VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/IEMAllInstOneByte.cpp.h@ 103917

Last change on this file since 103917 was 103828, checked in by vboxsync, 9 months ago

VMM/IEM: Implemented simple (whole sale) status flag up update skipping for arithmetic operations with native emitter. bugref:10375

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 587.0 KB
Line 
1/* $Id: IEMAllInstOneByte.cpp.h 103828 2024-03-13 14:01:20Z vboxsync $ */
2/** @file
3 * IEM - Instruction Decoding and Emulation.
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
29/*******************************************************************************
30* Global Variables *
31*******************************************************************************/
32extern const PFNIEMOP g_apfnOneByteMap[256]; /* not static since we need to forward declare it. */
33
34/* Instruction group definitions: */
35
36/** @defgroup og_gen General
37 * @{ */
38 /** @defgroup og_gen_arith Arithmetic
39 * @{ */
40 /** @defgroup og_gen_arith_bin Binary numbers */
41 /** @defgroup og_gen_arith_dec Decimal numbers */
42 /** @} */
43/** @} */
44
45/** @defgroup og_stack Stack
46 * @{ */
47 /** @defgroup og_stack_sreg Segment registers */
48/** @} */
49
50/** @defgroup og_prefix Prefixes */
51/** @defgroup og_escapes Escape bytes */
52
53
54
55/** @name One byte opcodes.
56 * @{
57 */
58
59/**
60 * Special case body for bytes instruction like SUB and XOR that can be used
61 * to zero a register.
62 *
63 * This can be used both for the r8_rm and rm_r8 forms since it's working on the
64 * same register.
65 */
66#define IEMOP_BODY_BINARY_r8_SAME_REG_ZERO(a_bRm) \
67 if ( (a_bRm >> X86_MODRM_REG_SHIFT) == ((bRm & X86_MODRM_RM_MASK) | (X86_MOD_REG << X86_MODRM_REG_SHIFT)) \
68 && pVCpu->iem.s.uRexReg == pVCpu->iem.s.uRexB) \
69 { \
70 IEM_MC_BEGIN(0, 1, 0, 0); \
71 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
72 IEM_MC_STORE_GREG_U8_CONST(IEM_GET_MODRM_REG(pVCpu, a_bRm), 0); \
73 IEM_MC_LOCAL(uint32_t, fEFlags); \
74 IEM_MC_FETCH_EFLAGS(fEFlags); \
75 IEM_MC_AND_LOCAL_U32(fEFlags, ~(uint32_t)X86_EFL_STATUS_BITS); \
76 IEM_MC_OR_LOCAL_U32(fEFlags, X86_EFL_PF | X86_EFL_ZF); \
77 IEM_MC_COMMIT_EFLAGS(fEFlags); \
78 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
79 IEM_MC_END(); \
80 } ((void)0)
81
82/**
83 * Body for instructions like ADD, AND, OR, TEST, CMP, ++ with a byte
84 * memory/register as the destination.
85 */
86#define IEMOP_BODY_BINARY_rm_r8_RW(a_bRm, a_InsNm, a_fRegRegNativeArchs, a_fMemRegNativeArchs) \
87 /* \
88 * If rm is denoting a register, no more instruction bytes. \
89 */ \
90 if (IEM_IS_MODRM_REG_MODE(a_bRm)) \
91 { \
92 IEM_MC_BEGIN(3, 0, 0, 0); \
93 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
94 IEM_MC_ARG(uint8_t, u8Src, 1); \
95 IEM_MC_FETCH_GREG_U8(u8Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
96 IEM_MC_NATIVE_IF(a_fRegRegNativeArchs) { \
97 IEM_MC_LOCAL(uint8_t, u8Dst); \
98 IEM_MC_FETCH_GREG_U8(u8Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
99 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
100 IEM_MC_LOCAL(uint32_t, uEFlags); \
101 IEM_MC_FETCH_EFLAGS(uEFlags); \
102 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u8Dst, u8Src, uEFlags, 8); \
103 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_RM(pVCpu, a_bRm), u8Dst); \
104 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
105 } IEM_MC_NATIVE_ELSE() { \
106 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
107 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
108 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
109 IEM_MC_REF_EFLAGS(pEFlags); \
110 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
111 } IEM_MC_NATIVE_ENDIF(); \
112 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
113 IEM_MC_END(); \
114 } \
115 else \
116 { \
117 /* \
118 * We're accessing memory. \
119 * Note! We're putting the eflags on the stack here so we can commit them \
120 * after the memory. \
121 */ \
122 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
123 { \
124 IEM_MC_BEGIN(3, 3, 0, 0); \
125 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
126 IEM_MC_ARG(uint8_t, u8Src, 1); \
127 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
128 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
129 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
130 \
131 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
132 IEMOP_HLP_DONE_DECODING(); \
133 IEM_MC_MEM_MAP_U8_RW(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
134 IEM_MC_FETCH_GREG_U8(u8Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
135 IEM_MC_FETCH_EFLAGS(EFlags); \
136 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
137 \
138 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
139 IEM_MC_COMMIT_EFLAGS(EFlags); \
140 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
141 IEM_MC_END(); \
142 } \
143 else \
144 { \
145 IEM_MC_BEGIN(3, 3, 0, 0); \
146 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
147 IEM_MC_ARG(uint8_t, u8Src, 1); \
148 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
149 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
150 IEM_MC_LOCAL(uint8_t, bMapInfoDst); \
151 \
152 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
153 IEMOP_HLP_DONE_DECODING(); \
154 IEM_MC_MEM_MAP_U8_ATOMIC(pu8Dst, bMapInfoDst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
155 IEM_MC_FETCH_GREG_U8(u8Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
156 IEM_MC_FETCH_EFLAGS(EFlags); \
157 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8_locked), pu8Dst, u8Src, pEFlags); \
158 \
159 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bMapInfoDst); \
160 IEM_MC_COMMIT_EFLAGS(EFlags); \
161 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
162 IEM_MC_END(); \
163 } \
164 } \
165 (void)0
166
167/**
168 * Body for instructions like TEST & CMP with a byte memory/registers as
169 * operands.
170 */
171#define IEMOP_BODY_BINARY_rm_r8_RO(a_bRm, a_fnNormalU8, a_EmitterBasename, a_fNativeArchs) \
172 /* \
173 * If rm is denoting a register, no more instruction bytes. \
174 */ \
175 if (IEM_IS_MODRM_REG_MODE(a_bRm)) \
176 { \
177 IEM_MC_BEGIN(3, 0, 0, 0); \
178 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
179 IEM_MC_ARG(uint8_t, u8Src, 1); \
180 IEM_MC_FETCH_GREG_U8(u8Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
181 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
182 IEM_MC_LOCAL(uint8_t, u8Dst); \
183 IEM_MC_FETCH_GREG_U8(u8Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
184 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
185 IEM_MC_LOCAL(uint32_t, uEFlags); \
186 IEM_MC_FETCH_EFLAGS(uEFlags); \
187 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_EmitterBasename,_r_r_efl), u8Dst, u8Src, uEFlags, 8); \
188 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
189 } IEM_MC_NATIVE_ELSE() { \
190 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
191 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
192 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
193 IEM_MC_REF_EFLAGS(pEFlags); \
194 IEM_MC_CALL_VOID_AIMPL_3(a_fnNormalU8, pu8Dst, u8Src, pEFlags); \
195 } IEM_MC_NATIVE_ENDIF(); \
196 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
197 IEM_MC_END(); \
198 } \
199 else \
200 { \
201 /* \
202 * We're accessing memory. \
203 * Note! We're putting the eflags on the stack here so we can commit them \
204 * after the memory. \
205 */ \
206 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK)) \
207 { \
208 IEM_MC_BEGIN(3, 3, 0, 0); \
209 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
210 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
211 IEMOP_HLP_DONE_DECODING(); \
212 IEM_MC_NATIVE_IF(0) { \
213 IEM_MC_LOCAL(uint8_t, u8Dst); \
214 IEM_MC_FETCH_MEM_U8(u8Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
215 IEM_MC_LOCAL(uint8_t, u8SrcEmit); \
216 IEM_MC_FETCH_GREG_U8(u8SrcEmit, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
217 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
218 IEM_MC_LOCAL(uint32_t, uEFlags); \
219 IEM_MC_FETCH_EFLAGS(uEFlags); \
220 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_EmitterBasename,_r_r_efl), u8Dst, u8SrcEmit, uEFlags, 8); \
221 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
222 } IEM_MC_NATIVE_ELSE() { \
223 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
224 IEM_MC_ARG(uint8_t const *, pu8Dst, 0); \
225 IEM_MC_MEM_MAP_U8_RO(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
226 IEM_MC_ARG(uint8_t, u8Src, 1); \
227 IEM_MC_FETCH_GREG_U8(u8Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
228 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
229 IEM_MC_FETCH_EFLAGS(EFlags); \
230 IEM_MC_CALL_VOID_AIMPL_3(a_fnNormalU8, pu8Dst, u8Src, pEFlags); \
231 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
232 IEM_MC_COMMIT_EFLAGS(EFlags); \
233 } IEM_MC_NATIVE_ENDIF(); \
234 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
235 IEM_MC_END(); \
236 } \
237 else \
238 { \
239 /** @todo we should probably decode the address first. */ \
240 IEMOP_HLP_DONE_DECODING(); \
241 IEMOP_RAISE_INVALID_LOCK_PREFIX_RET(); \
242 } \
243 } \
244 (void)0
245
246/**
247 * Body for byte instructions like ADD, AND, OR, ++ with a register as the
248 * destination.
249 */
250#define IEMOP_BODY_BINARY_r8_rm(a_bRm, a_InsNm, a_fNativeArchs) \
251 /* \
252 * If rm is denoting a register, no more instruction bytes. \
253 */ \
254 if (IEM_IS_MODRM_REG_MODE(a_bRm)) \
255 { \
256 IEM_MC_BEGIN(3, 0, 0, 0); \
257 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
258 IEM_MC_ARG(uint8_t, u8Src, 1); \
259 IEM_MC_FETCH_GREG_U8(u8Src, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
260 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
261 IEM_MC_LOCAL(uint8_t, u8Dst); \
262 IEM_MC_FETCH_GREG_U8(u8Dst, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
263 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
264 IEM_MC_LOCAL(uint32_t, uEFlags); \
265 IEM_MC_FETCH_EFLAGS(uEFlags); \
266 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u8Dst, u8Src, uEFlags, 8); \
267 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_REG(pVCpu, a_bRm), u8Dst); \
268 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
269 } IEM_MC_NATIVE_ELSE() { \
270 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
271 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
272 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
273 IEM_MC_REF_EFLAGS(pEFlags); \
274 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
275 } IEM_MC_NATIVE_ENDIF(); \
276 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
277 IEM_MC_END(); \
278 } \
279 else \
280 { \
281 /* \
282 * We're accessing memory. \
283 */ \
284 IEM_MC_BEGIN(3, 1, 0, 0); \
285 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
286 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
287 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
288 IEM_MC_ARG(uint8_t, u8Src, 1); \
289 IEM_MC_FETCH_MEM_U8(u8Src, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
290 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
291 IEM_MC_LOCAL(uint8_t, u8Dst); \
292 IEM_MC_FETCH_GREG_U8(u8Dst, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
293 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
294 IEM_MC_LOCAL(uint32_t, uEFlags); \
295 IEM_MC_FETCH_EFLAGS(uEFlags); \
296 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u8Dst, u8Src, uEFlags, 8); \
297 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_REG(pVCpu, a_bRm), u8Dst); \
298 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
299 } IEM_MC_NATIVE_ELSE() { \
300 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
301 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
302 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
303 IEM_MC_REF_EFLAGS(pEFlags); \
304 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
305 } IEM_MC_NATIVE_ENDIF(); \
306 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
307 IEM_MC_END(); \
308 } \
309 (void)0
310
311/**
312 * Body for byte instruction CMP with a register as the destination.
313 */
314#define IEMOP_BODY_BINARY_r8_rm_RO(a_bRm, a_InsNm, a_fNativeArchs) \
315 /* \
316 * If rm is denoting a register, no more instruction bytes. \
317 */ \
318 if (IEM_IS_MODRM_REG_MODE(a_bRm)) \
319 { \
320 IEM_MC_BEGIN(3, 0, 0, 0); \
321 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
322 IEM_MC_ARG(uint8_t, u8Src, 1); \
323 IEM_MC_FETCH_GREG_U8(u8Src, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
324 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
325 IEM_MC_LOCAL(uint8_t, u8Dst); \
326 IEM_MC_FETCH_GREG_U8(u8Dst, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
327 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
328 IEM_MC_LOCAL(uint32_t, uEFlags); \
329 IEM_MC_FETCH_EFLAGS(uEFlags); \
330 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u8Dst, u8Src, uEFlags, 8); \
331 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
332 } IEM_MC_NATIVE_ELSE() { \
333 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
334 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
335 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
336 IEM_MC_REF_EFLAGS(pEFlags); \
337 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
338 } IEM_MC_NATIVE_ENDIF(); \
339 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
340 IEM_MC_END(); \
341 } \
342 else \
343 { \
344 /* \
345 * We're accessing memory. \
346 */ \
347 IEM_MC_BEGIN(3, 1, 0, 0); \
348 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
349 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
350 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
351 IEM_MC_ARG(uint8_t, u8Src, 1); \
352 IEM_MC_FETCH_MEM_U8(u8Src, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
353 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
354 IEM_MC_LOCAL(uint8_t, u8Dst); \
355 IEM_MC_FETCH_GREG_U8(u8Dst, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
356 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
357 IEM_MC_LOCAL(uint32_t, uEFlags); \
358 IEM_MC_FETCH_EFLAGS(uEFlags); \
359 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u8Dst, u8Src, uEFlags, 8); \
360 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
361 } IEM_MC_NATIVE_ELSE() { \
362 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
363 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
364 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
365 IEM_MC_REF_EFLAGS(pEFlags); \
366 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
367 } IEM_MC_NATIVE_ENDIF(); \
368 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
369 IEM_MC_END(); \
370 } \
371 (void)0
372
373
374/**
375 * Body for word/dword/qword instructions like ADD, AND, OR, ++ with
376 * memory/register as the destination.
377 */
378#define IEMOP_BODY_BINARY_rm_rv_RW(a_bRm, a_InsNm, a_fRegRegNativeArchs, a_fMemRegNativeArchs) \
379 /* \
380 * If rm is denoting a register, no more instruction bytes. \
381 */ \
382 if (IEM_IS_MODRM_REG_MODE(a_bRm)) \
383 { \
384 switch (pVCpu->iem.s.enmEffOpSize) \
385 { \
386 case IEMMODE_16BIT: \
387 IEM_MC_BEGIN(3, 0, 0, 0); \
388 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
389 IEM_MC_ARG(uint16_t, u16Src, 1); \
390 IEM_MC_FETCH_GREG_U16(u16Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
391 IEM_MC_NATIVE_IF(a_fRegRegNativeArchs) { \
392 IEM_MC_LOCAL(uint16_t, u16Dst); \
393 IEM_MC_FETCH_GREG_U16(u16Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
394 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
395 IEM_MC_LOCAL(uint32_t, uEFlags); \
396 IEM_MC_FETCH_EFLAGS(uEFlags); \
397 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u16Dst, u16Src, uEFlags, 16); \
398 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_RM(pVCpu, a_bRm), u16Dst); \
399 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
400 } IEM_MC_NATIVE_ELSE() { \
401 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
402 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
403 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
404 IEM_MC_REF_EFLAGS(pEFlags); \
405 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
406 } IEM_MC_NATIVE_ENDIF(); \
407 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
408 IEM_MC_END(); \
409 break; \
410 \
411 case IEMMODE_32BIT: \
412 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_386, 0); \
413 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
414 IEM_MC_ARG(uint32_t, u32Src, 1); \
415 IEM_MC_FETCH_GREG_U32(u32Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
416 IEM_MC_NATIVE_IF(a_fRegRegNativeArchs) { \
417 IEM_MC_LOCAL(uint32_t, u32Dst); \
418 IEM_MC_FETCH_GREG_U32(u32Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
419 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
420 IEM_MC_LOCAL(uint32_t, uEFlags); \
421 IEM_MC_FETCH_EFLAGS(uEFlags); \
422 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u32Dst, u32Src, uEFlags, 32); \
423 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_RM(pVCpu, a_bRm), u32Dst); \
424 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
425 } IEM_MC_NATIVE_ELSE() { \
426 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
427 IEM_MC_REF_GREG_U32(pu32Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
428 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
429 IEM_MC_REF_EFLAGS(pEFlags); \
430 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
431 IEM_MC_CLEAR_HIGH_GREG_U64(IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
432 } IEM_MC_NATIVE_ENDIF(); \
433 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
434 IEM_MC_END(); \
435 break; \
436 \
437 case IEMMODE_64BIT: \
438 IEM_MC_BEGIN(3, 0, IEM_MC_F_64BIT, 0); \
439 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
440 IEM_MC_ARG(uint64_t, u64Src, 1); \
441 IEM_MC_FETCH_GREG_U64(u64Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
442 IEM_MC_NATIVE_IF(a_fRegRegNativeArchs) { \
443 IEM_MC_LOCAL(uint64_t, u64Dst); \
444 IEM_MC_FETCH_GREG_U64(u64Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
445 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
446 IEM_MC_LOCAL(uint32_t, uEFlags); \
447 IEM_MC_FETCH_EFLAGS(uEFlags); \
448 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u64Dst, u64Src, uEFlags, 64); \
449 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_RM(pVCpu, a_bRm), u64Dst); \
450 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
451 } IEM_MC_NATIVE_ELSE() { \
452 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
453 IEM_MC_REF_GREG_U64(pu64Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
454 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
455 IEM_MC_REF_EFLAGS(pEFlags); \
456 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
457 } IEM_MC_NATIVE_ENDIF(); \
458 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
459 IEM_MC_END(); \
460 break; \
461 \
462 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
463 } \
464 } \
465 else \
466 { \
467 /* \
468 * We're accessing memory. \
469 * Note! We're putting the eflags on the stack here so we can commit them \
470 * after the memory. \
471 */ \
472 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
473 { \
474 switch (pVCpu->iem.s.enmEffOpSize) \
475 { \
476 case IEMMODE_16BIT: \
477 IEM_MC_BEGIN(3, 3, 0, 0); \
478 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
479 IEM_MC_ARG(uint16_t, u16Src, 1); \
480 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
481 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
482 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
483 \
484 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
485 IEMOP_HLP_DONE_DECODING(); \
486 IEM_MC_MEM_MAP_U16_RW(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
487 IEM_MC_FETCH_GREG_U16(u16Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
488 IEM_MC_FETCH_EFLAGS(EFlags); \
489 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
490 \
491 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
492 IEM_MC_COMMIT_EFLAGS(EFlags); \
493 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
494 IEM_MC_END(); \
495 break; \
496 \
497 case IEMMODE_32BIT: \
498 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
499 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
500 IEM_MC_ARG(uint32_t, u32Src, 1); \
501 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
502 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
503 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
504 \
505 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
506 IEMOP_HLP_DONE_DECODING(); \
507 IEM_MC_MEM_MAP_U32_RW(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
508 IEM_MC_FETCH_GREG_U32(u32Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
509 IEM_MC_FETCH_EFLAGS(EFlags); \
510 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
511 \
512 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
513 IEM_MC_COMMIT_EFLAGS(EFlags); \
514 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
515 IEM_MC_END(); \
516 break; \
517 \
518 case IEMMODE_64BIT: \
519 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
520 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
521 IEM_MC_ARG(uint64_t, u64Src, 1); \
522 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
523 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
524 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
525 \
526 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
527 IEMOP_HLP_DONE_DECODING(); \
528 IEM_MC_MEM_MAP_U64_RW(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
529 IEM_MC_FETCH_GREG_U64(u64Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
530 IEM_MC_FETCH_EFLAGS(EFlags); \
531 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
532 \
533 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
534 IEM_MC_COMMIT_EFLAGS(EFlags); \
535 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
536 IEM_MC_END(); \
537 break; \
538 \
539 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
540 } \
541 } \
542 else \
543 { \
544 (void)0
545/* Separate macro to work around parsing issue in IEMAllInstPython.py */
546#define IEMOP_BODY_BINARY_rm_rv_LOCKED(a_bRm, a_InsNm) \
547 switch (pVCpu->iem.s.enmEffOpSize) \
548 { \
549 case IEMMODE_16BIT: \
550 IEM_MC_BEGIN(3, 3, 0, 0); \
551 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
552 IEM_MC_ARG(uint16_t, u16Src, 1); \
553 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
554 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
555 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
556 \
557 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
558 IEMOP_HLP_DONE_DECODING(); \
559 IEM_MC_MEM_MAP_U16_ATOMIC(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
560 IEM_MC_FETCH_GREG_U16(u16Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
561 IEM_MC_FETCH_EFLAGS(EFlags); \
562 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16_locked), pu16Dst, u16Src, pEFlags); \
563 \
564 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
565 IEM_MC_COMMIT_EFLAGS(EFlags); \
566 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
567 IEM_MC_END(); \
568 break; \
569 \
570 case IEMMODE_32BIT: \
571 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
572 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
573 IEM_MC_ARG(uint32_t, u32Src, 1); \
574 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
575 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
576 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
577 \
578 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
579 IEMOP_HLP_DONE_DECODING(); \
580 IEM_MC_MEM_MAP_U32_ATOMIC(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
581 IEM_MC_FETCH_GREG_U32(u32Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
582 IEM_MC_FETCH_EFLAGS(EFlags); \
583 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32_locked), pu32Dst, u32Src, pEFlags); \
584 \
585 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo /* CMP,TEST */); \
586 IEM_MC_COMMIT_EFLAGS(EFlags); \
587 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
588 IEM_MC_END(); \
589 break; \
590 \
591 case IEMMODE_64BIT: \
592 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
593 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
594 IEM_MC_ARG(uint64_t, u64Src, 1); \
595 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
596 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
597 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
598 \
599 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
600 IEMOP_HLP_DONE_DECODING(); \
601 IEM_MC_MEM_MAP_U64_ATOMIC(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
602 IEM_MC_FETCH_GREG_U64(u64Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
603 IEM_MC_FETCH_EFLAGS(EFlags); \
604 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64_locked), pu64Dst, u64Src, pEFlags); \
605 \
606 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
607 IEM_MC_COMMIT_EFLAGS(EFlags); \
608 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
609 IEM_MC_END(); \
610 break; \
611 \
612 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
613 } \
614 } \
615 } \
616 (void)0
617
618/**
619 * Body for read-only word/dword/qword instructions like TEST and CMP with
620 * memory/register as the destination.
621 */
622#define IEMOP_BODY_BINARY_rm_rv_RO(a_bRm, a_InsNm, a_fNativeArchs) \
623 /* \
624 * If rm is denoting a register, no more instruction bytes. \
625 */ \
626 if (IEM_IS_MODRM_REG_MODE(a_bRm)) \
627 { \
628 switch (pVCpu->iem.s.enmEffOpSize) \
629 { \
630 case IEMMODE_16BIT: \
631 IEM_MC_BEGIN(3, 0, 0, 0); \
632 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
633 IEM_MC_ARG(uint16_t, u16Src, 1); \
634 IEM_MC_FETCH_GREG_U16(u16Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
635 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
636 IEM_MC_LOCAL(uint16_t, u16Dst); \
637 IEM_MC_FETCH_GREG_U16(u16Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
638 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
639 IEM_MC_LOCAL(uint32_t, uEFlags); \
640 IEM_MC_FETCH_EFLAGS(uEFlags); \
641 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u16Dst, u16Src, uEFlags, 16); \
642 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
643 } IEM_MC_NATIVE_ELSE() { \
644 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
645 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
646 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
647 IEM_MC_REF_EFLAGS(pEFlags); \
648 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
649 } IEM_MC_NATIVE_ENDIF(); \
650 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
651 IEM_MC_END(); \
652 break; \
653 \
654 case IEMMODE_32BIT: \
655 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_386, 0); \
656 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
657 IEM_MC_ARG(uint32_t, u32Src, 1); \
658 IEM_MC_FETCH_GREG_U32(u32Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
659 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
660 IEM_MC_LOCAL(uint32_t, u32Dst); \
661 IEM_MC_FETCH_GREG_U32(u32Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
662 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
663 IEM_MC_LOCAL(uint32_t, uEFlags); \
664 IEM_MC_FETCH_EFLAGS(uEFlags); \
665 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u32Dst, u32Src, uEFlags, 32); \
666 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
667 } IEM_MC_NATIVE_ELSE() { \
668 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
669 IEM_MC_REF_GREG_U32(pu32Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
670 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
671 IEM_MC_REF_EFLAGS(pEFlags); \
672 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
673 } IEM_MC_NATIVE_ENDIF(); \
674 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
675 IEM_MC_END(); \
676 break; \
677 \
678 case IEMMODE_64BIT: \
679 IEM_MC_BEGIN(3, 0, IEM_MC_F_64BIT, 0); \
680 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
681 IEM_MC_ARG(uint64_t, u64Src, 1); \
682 IEM_MC_FETCH_GREG_U64(u64Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
683 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
684 IEM_MC_LOCAL(uint64_t, u64Dst); \
685 IEM_MC_FETCH_GREG_U64(u64Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
686 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
687 IEM_MC_LOCAL(uint32_t, uEFlags); \
688 IEM_MC_FETCH_EFLAGS(uEFlags); \
689 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u64Dst, u64Src, uEFlags, 64); \
690 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
691 } IEM_MC_NATIVE_ELSE() { \
692 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
693 IEM_MC_REF_GREG_U64(pu64Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
694 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
695 IEM_MC_REF_EFLAGS(pEFlags); \
696 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
697 } IEM_MC_NATIVE_ENDIF(); \
698 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
699 IEM_MC_END(); \
700 break; \
701 \
702 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
703 } \
704 } \
705 else \
706 { \
707 /* \
708 * We're accessing memory. \
709 * Note! We're putting the eflags on the stack here so we can commit them \
710 * after the memory. \
711 */ \
712 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
713 { \
714 switch (pVCpu->iem.s.enmEffOpSize) \
715 { \
716 case IEMMODE_16BIT: \
717 IEM_MC_BEGIN(3, 3, 0, 0); \
718 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
719 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
720 IEMOP_HLP_DONE_DECODING(); \
721 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
722 IEM_MC_LOCAL(uint16_t, u16Dst); \
723 IEM_MC_FETCH_MEM_U16(u16Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
724 IEM_MC_LOCAL(uint16_t, u16SrcEmit); \
725 IEM_MC_FETCH_GREG_U16(u16SrcEmit, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
726 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
727 IEM_MC_LOCAL(uint32_t, uEFlags); \
728 IEM_MC_FETCH_EFLAGS(uEFlags); \
729 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u16Dst, u16SrcEmit, uEFlags, 16); \
730 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
731 } IEM_MC_NATIVE_ELSE() { \
732 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
733 IEM_MC_ARG(uint16_t const *, pu16Dst, 0); \
734 IEM_MC_MEM_MAP_U16_RO(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
735 IEM_MC_ARG(uint16_t, u16Src, 1); \
736 IEM_MC_FETCH_GREG_U16(u16Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
737 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
738 IEM_MC_FETCH_EFLAGS(EFlags); \
739 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
740 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
741 IEM_MC_COMMIT_EFLAGS(EFlags); \
742 } IEM_MC_NATIVE_ENDIF(); \
743 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
744 IEM_MC_END(); \
745 break; \
746 \
747 case IEMMODE_32BIT: \
748 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
749 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
750 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
751 IEMOP_HLP_DONE_DECODING(); \
752 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
753 IEM_MC_LOCAL(uint32_t, u32Dst); \
754 IEM_MC_FETCH_MEM_U32(u32Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
755 IEM_MC_LOCAL(uint32_t, u32SrcEmit); \
756 IEM_MC_FETCH_GREG_U32(u32SrcEmit, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
757 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
758 IEM_MC_LOCAL(uint32_t, uEFlags); \
759 IEM_MC_FETCH_EFLAGS(uEFlags); \
760 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u32Dst, u32SrcEmit, uEFlags, 32); \
761 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
762 } IEM_MC_NATIVE_ELSE() { \
763 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
764 IEM_MC_ARG(uint32_t const *, pu32Dst, 0); \
765 IEM_MC_MEM_MAP_U32_RO(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
766 IEM_MC_ARG(uint32_t, u32Src, 1); \
767 IEM_MC_FETCH_GREG_U32(u32Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
768 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
769 IEM_MC_FETCH_EFLAGS(EFlags); \
770 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
771 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
772 IEM_MC_COMMIT_EFLAGS(EFlags); \
773 } IEM_MC_NATIVE_ENDIF(); \
774 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
775 IEM_MC_END(); \
776 break; \
777 \
778 case IEMMODE_64BIT: \
779 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
780 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
781 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
782 IEMOP_HLP_DONE_DECODING(); \
783 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
784 IEM_MC_LOCAL(uint64_t, u64Dst); \
785 IEM_MC_FETCH_MEM_U64(u64Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
786 IEM_MC_LOCAL(uint64_t, u64SrcEmit); \
787 IEM_MC_FETCH_GREG_U64(u64SrcEmit, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
788 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */ \
789 IEM_MC_LOCAL(uint32_t, uEFlags); \
790 IEM_MC_FETCH_EFLAGS(uEFlags); \
791 IEM_MC_NATIVE_EMIT_4(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_r_efl), u64Dst, u64SrcEmit, uEFlags, 64); \
792 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
793 } IEM_MC_NATIVE_ELSE() { \
794 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
795 IEM_MC_ARG(uint64_t const *, pu64Dst, 0); \
796 IEM_MC_MEM_MAP_U64_RO(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
797 IEM_MC_ARG(uint64_t, u64Src, 1); \
798 IEM_MC_FETCH_GREG_U64(u64Src, IEM_GET_MODRM_REG(pVCpu, a_bRm)); \
799 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
800 IEM_MC_FETCH_EFLAGS(EFlags); \
801 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
802 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
803 IEM_MC_COMMIT_EFLAGS(EFlags); \
804 } IEM_MC_NATIVE_ENDIF(); \
805 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
806 IEM_MC_END(); \
807 break; \
808 \
809 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
810 } \
811 } \
812 else \
813 { \
814 IEMOP_HLP_DONE_DECODING(); \
815 IEMOP_RAISE_INVALID_LOCK_PREFIX_RET(); \
816 } \
817 } \
818 (void)0
819
820
821/**
822 * Body for instructions like ADD, AND, OR, ++ with working on AL with
823 * a byte immediate.
824 */
825#define IEMOP_BODY_BINARY_AL_Ib(a_InsNm, a_fNativeArchs) \
826 IEM_MC_BEGIN(3, 3, 0, 0); \
827 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
828 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
829 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
830 IEM_MC_LOCAL(uint8_t, u8Dst); \
831 IEM_MC_FETCH_GREG_U8(u8Dst, X86_GREG_xAX); \
832 IEM_MC_LOCAL(uint32_t, uEFlags); \
833 IEM_MC_FETCH_EFLAGS(uEFlags); \
834 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u8Dst, u8Imm, uEFlags, 8, 8); \
835 IEM_MC_STORE_GREG_U8(X86_GREG_xAX, u8Dst); \
836 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
837 } IEM_MC_NATIVE_ELSE() { \
838 IEM_MC_ARG_CONST(uint8_t, u8Src,/*=*/ u8Imm, 1); \
839 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
840 IEM_MC_REF_GREG_U8(pu8Dst, X86_GREG_xAX); \
841 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
842 IEM_MC_REF_EFLAGS(pEFlags); \
843 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
844 } IEM_MC_NATIVE_ENDIF(); \
845 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
846 IEM_MC_END()
847
848/**
849 * Body for instructions like ADD, AND, OR, ++ with working on
850 * AX/EAX/RAX with a word/dword immediate.
851 */
852#define IEMOP_BODY_BINARY_rAX_Iz_RW(a_InsNm, a_fNativeArchs) \
853 switch (pVCpu->iem.s.enmEffOpSize) \
854 { \
855 case IEMMODE_16BIT: \
856 { \
857 IEM_MC_BEGIN(3, 2, 0, 0); \
858 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm); \
859 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
860 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
861 IEM_MC_LOCAL(uint16_t, u16Dst); \
862 IEM_MC_FETCH_GREG_U16(u16Dst, X86_GREG_xAX); \
863 IEM_MC_LOCAL(uint32_t, uEFlags); \
864 IEM_MC_FETCH_EFLAGS(uEFlags); \
865 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u16Dst, u16Imm, uEFlags, 16, 16); \
866 IEM_MC_STORE_GREG_U16(X86_GREG_xAX, u16Dst); \
867 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
868 } IEM_MC_NATIVE_ELSE() { \
869 IEM_MC_ARG_CONST(uint16_t, u16Src,/*=*/ u16Imm, 1); \
870 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
871 IEM_MC_REF_GREG_U16(pu16Dst, X86_GREG_xAX); \
872 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
873 IEM_MC_REF_EFLAGS(pEFlags); \
874 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
875 } IEM_MC_NATIVE_ENDIF(); \
876 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
877 IEM_MC_END(); \
878 } \
879 \
880 case IEMMODE_32BIT: \
881 { \
882 IEM_MC_BEGIN(3, 2, IEM_MC_F_MIN_386, 0); \
883 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm); \
884 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
885 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
886 IEM_MC_LOCAL(uint32_t, u32Dst); \
887 IEM_MC_FETCH_GREG_U32(u32Dst, X86_GREG_xAX); \
888 IEM_MC_LOCAL(uint32_t, uEFlags); \
889 IEM_MC_FETCH_EFLAGS(uEFlags); \
890 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u32Dst, u32Imm, uEFlags, 32, 32); \
891 IEM_MC_STORE_GREG_U32(X86_GREG_xAX, u32Dst); \
892 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
893 } IEM_MC_NATIVE_ELSE() { \
894 IEM_MC_ARG_CONST(uint32_t, u32Src,/*=*/ u32Imm, 1); \
895 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
896 IEM_MC_REF_GREG_U32(pu32Dst, X86_GREG_xAX); \
897 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
898 IEM_MC_REF_EFLAGS(pEFlags); \
899 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
900 IEM_MC_CLEAR_HIGH_GREG_U64(X86_GREG_xAX); \
901 } IEM_MC_NATIVE_ENDIF(); \
902 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
903 IEM_MC_END(); \
904 } \
905 \
906 case IEMMODE_64BIT: \
907 { \
908 IEM_MC_BEGIN(3, 2, IEM_MC_F_64BIT, 0); \
909 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm); \
910 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
911 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
912 IEM_MC_LOCAL(uint64_t, u64Dst); \
913 IEM_MC_FETCH_GREG_U64(u64Dst, X86_GREG_xAX); \
914 IEM_MC_LOCAL(uint32_t, uEFlags); \
915 IEM_MC_FETCH_EFLAGS(uEFlags); \
916 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u64Dst, u64Imm, uEFlags, 64, 32); \
917 IEM_MC_STORE_GREG_U64(X86_GREG_xAX, u64Dst); \
918 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
919 } IEM_MC_NATIVE_ELSE() { \
920 IEM_MC_ARG_CONST(uint64_t, u64Src,/*=*/ u64Imm, 1); \
921 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
922 IEM_MC_REF_GREG_U64(pu64Dst, X86_GREG_xAX); \
923 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
924 IEM_MC_REF_EFLAGS(pEFlags); \
925 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
926 } IEM_MC_NATIVE_ENDIF(); \
927 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
928 IEM_MC_END(); \
929 } \
930 \
931 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
932 } \
933 (void)0
934
935/**
936 * Body for the instructions CMP and TEST working on AX/EAX/RAX with a
937 * word/dword immediate.
938 */
939#define IEMOP_BODY_BINARY_rAX_Iz_RO(a_InsNm, a_fNativeArchs) \
940 switch (pVCpu->iem.s.enmEffOpSize) \
941 { \
942 case IEMMODE_16BIT: \
943 { \
944 IEM_MC_BEGIN(3, 2, 0, 0); \
945 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm); \
946 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
947 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
948 IEM_MC_LOCAL(uint16_t, u16Dst); \
949 IEM_MC_FETCH_GREG_U16(u16Dst, X86_GREG_xAX); \
950 IEM_MC_LOCAL(uint32_t, uEFlags); \
951 IEM_MC_FETCH_EFLAGS(uEFlags); \
952 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u16Dst, u16Imm, uEFlags, 16, 16); \
953 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
954 } IEM_MC_NATIVE_ELSE() { \
955 IEM_MC_ARG_CONST(uint16_t, u16Src,/*=*/ u16Imm, 1); \
956 IEM_MC_ARG(uint16_t const *,pu16Dst, 0); \
957 IEM_MC_REF_GREG_U16_CONST(pu16Dst, X86_GREG_xAX); \
958 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
959 IEM_MC_REF_EFLAGS(pEFlags); \
960 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
961 } IEM_MC_NATIVE_ENDIF(); \
962 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
963 IEM_MC_END(); \
964 } \
965 \
966 case IEMMODE_32BIT: \
967 { \
968 IEM_MC_BEGIN(3, 2, IEM_MC_F_MIN_386, 0); \
969 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm); \
970 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
971 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
972 IEM_MC_LOCAL(uint32_t, u32Dst); \
973 IEM_MC_FETCH_GREG_U32(u32Dst, X86_GREG_xAX); \
974 IEM_MC_LOCAL(uint32_t, uEFlags); \
975 IEM_MC_FETCH_EFLAGS(uEFlags); \
976 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u32Dst, u32Imm, uEFlags, 32, 32); \
977 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
978 } IEM_MC_NATIVE_ELSE() { \
979 IEM_MC_ARG_CONST(uint32_t, u32Src,/*=*/ u32Imm, 1); \
980 IEM_MC_ARG(uint32_t const *,pu32Dst, 0); \
981 IEM_MC_REF_GREG_U32_CONST(pu32Dst, X86_GREG_xAX); \
982 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
983 IEM_MC_REF_EFLAGS(pEFlags); \
984 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
985 } IEM_MC_NATIVE_ENDIF(); \
986 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
987 IEM_MC_END(); \
988 } \
989 \
990 case IEMMODE_64BIT: \
991 { \
992 IEM_MC_BEGIN(3, 2, IEM_MC_F_64BIT, 0); \
993 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm); \
994 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
995 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
996 IEM_MC_LOCAL(uint64_t, u64Dst); \
997 IEM_MC_FETCH_GREG_U64(u64Dst, X86_GREG_xAX); \
998 IEM_MC_LOCAL(uint32_t, uEFlags); \
999 IEM_MC_FETCH_EFLAGS(uEFlags); \
1000 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u64Dst, u64Imm, uEFlags, 64, 32); \
1001 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
1002 } IEM_MC_NATIVE_ELSE() { \
1003 IEM_MC_ARG_CONST(uint64_t, u64Src,/*=*/ u64Imm, 1); \
1004 IEM_MC_ARG(uint64_t const *,pu64Dst, 0); \
1005 IEM_MC_REF_GREG_U64_CONST(pu64Dst, X86_GREG_xAX); \
1006 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
1007 IEM_MC_REF_EFLAGS(pEFlags); \
1008 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
1009 } IEM_MC_NATIVE_ENDIF(); \
1010 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
1011 IEM_MC_END(); \
1012 } \
1013 \
1014 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
1015 } \
1016 (void)0
1017
1018
1019
1020/* Instruction specification format - work in progress: */
1021
1022/**
1023 * @opcode 0x00
1024 * @opmnemonic add
1025 * @op1 rm:Eb
1026 * @op2 reg:Gb
1027 * @opmaps one
1028 * @openc ModR/M
1029 * @opflclass arithmetic
1030 * @ophints harmless ignores_op_sizes
1031 * @opstats add_Eb_Gb
1032 * @opgroup og_gen_arith_bin
1033 * @optest op1=1 op2=1 -> op1=2 efl&|=nc,pe,na,nz,pl,nv
1034 * @optest efl|=cf op1=1 op2=2 -> op1=3 efl&|=nc,po,na,nz,pl,nv
1035 * @optest op1=254 op2=1 -> op1=255 efl&|=nc,po,na,nz,ng,nv
1036 * @optest op1=128 op2=128 -> op1=0 efl&|=ov,pl,zf,na,po,cf
1037 */
1038FNIEMOP_DEF(iemOp_add_Eb_Gb)
1039{
1040 IEMOP_MNEMONIC2(MR, ADD, add, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
1041 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1042 IEMOP_BODY_BINARY_rm_r8_RW(bRm, add, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1043}
1044
1045
1046/**
1047 * @opcode 0x01
1048 * @opgroup og_gen_arith_bin
1049 * @opflclass arithmetic
1050 * @optest op1=1 op2=1 -> op1=2 efl&|=nc,pe,na,nz,pl,nv
1051 * @optest efl|=cf op1=2 op2=2 -> op1=4 efl&|=nc,pe,na,nz,pl,nv
1052 * @optest efl&~=cf op1=-1 op2=1 -> op1=0 efl&|=cf,po,af,zf,pl,nv
1053 * @optest op1=-1 op2=-1 -> op1=-2 efl&|=cf,pe,af,nz,ng,nv
1054 */
1055FNIEMOP_DEF(iemOp_add_Ev_Gv)
1056{
1057 IEMOP_MNEMONIC2(MR, ADD, add, Ev, Gv, DISOPTYPE_HARMLESS, IEMOPHINT_LOCK_ALLOWED);
1058 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1059 IEMOP_BODY_BINARY_rm_rv_RW( bRm, add, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1060 IEMOP_BODY_BINARY_rm_rv_LOCKED(bRm, add);
1061}
1062
1063
1064/**
1065 * @opcode 0x02
1066 * @opgroup og_gen_arith_bin
1067 * @opflclass arithmetic
1068 * @opcopytests iemOp_add_Eb_Gb
1069 */
1070FNIEMOP_DEF(iemOp_add_Gb_Eb)
1071{
1072 IEMOP_MNEMONIC2(RM, ADD, add, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1073 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1074 IEMOP_BODY_BINARY_r8_rm(bRm, add, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1075}
1076
1077
1078/**
1079 * @opcode 0x03
1080 * @opgroup og_gen_arith_bin
1081 * @opflclass arithmetic
1082 * @opcopytests iemOp_add_Ev_Gv
1083 */
1084FNIEMOP_DEF(iemOp_add_Gv_Ev)
1085{
1086 IEMOP_MNEMONIC2(RM, ADD, add, Gv, Ev, DISOPTYPE_HARMLESS, 0);
1087 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1088 IEMOP_BODY_BINARY_rv_rm(bRm, iemAImpl_add_u16, iemAImpl_add_u32, iemAImpl_add_u64, 0, add, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1089}
1090
1091
1092/**
1093 * @opcode 0x04
1094 * @opgroup og_gen_arith_bin
1095 * @opflclass arithmetic
1096 * @opcopytests iemOp_add_Eb_Gb
1097 */
1098FNIEMOP_DEF(iemOp_add_Al_Ib)
1099{
1100 IEMOP_MNEMONIC2(FIXED, ADD, add, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1101 IEMOP_BODY_BINARY_AL_Ib(add, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1102}
1103
1104
1105/**
1106 * @opcode 0x05
1107 * @opgroup og_gen_arith_bin
1108 * @opflclass arithmetic
1109 * @optest op1=1 op2=1 -> op1=2 efl&|=nv,pl,nz,na,pe
1110 * @optest efl|=cf op1=2 op2=2 -> op1=4 efl&|=nc,pe,na,nz,pl,nv
1111 * @optest efl&~=cf op1=-1 op2=1 -> op1=0 efl&|=cf,po,af,zf,pl,nv
1112 * @optest op1=-1 op2=-1 -> op1=-2 efl&|=cf,pe,af,nz,ng,nv
1113 */
1114FNIEMOP_DEF(iemOp_add_eAX_Iz)
1115{
1116 IEMOP_MNEMONIC2(FIXED, ADD, add, rAX, Iz, DISOPTYPE_HARMLESS, 0);
1117 IEMOP_BODY_BINARY_rAX_Iz_RW(add, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1118}
1119
1120
1121/**
1122 * @opcode 0x06
1123 * @opgroup og_stack_sreg
1124 */
1125FNIEMOP_DEF(iemOp_push_ES)
1126{
1127 IEMOP_MNEMONIC1(FIXED, PUSH, push, ES, DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64, 0);
1128 IEMOP_HLP_NO_64BIT();
1129 return FNIEMOP_CALL_1(iemOpCommonPushSReg, X86_SREG_ES);
1130}
1131
1132
1133/**
1134 * @opcode 0x07
1135 * @opgroup og_stack_sreg
1136 */
1137FNIEMOP_DEF(iemOp_pop_ES)
1138{
1139 IEMOP_MNEMONIC1(FIXED, POP, pop, ES, DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64, 0);
1140 IEMOP_HLP_NO_64BIT();
1141 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
1142 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_MODE,
1143 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
1144 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_ES)
1145 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_ES)
1146 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_ES)
1147 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_ES),
1148 iemCImpl_pop_Sreg, X86_SREG_ES, pVCpu->iem.s.enmEffOpSize);
1149}
1150
1151
1152/**
1153 * @opcode 0x08
1154 * @opgroup og_gen_arith_bin
1155 * @opflclass logical
1156 * @optest op1=7 op2=12 -> op1=15 efl&|=nc,po,na,nz,pl,nv
1157 * @optest efl|=of,cf op1=0 op2=0 -> op1=0 efl&|=nc,po,na,zf,pl,nv
1158 * @optest op1=0xee op2=0x11 -> op1=0xff efl&|=nc,po,na,nz,ng,nv
1159 * @optest op1=0xff op2=0xff -> op1=0xff efl&|=nc,po,na,nz,ng,nv
1160 */
1161FNIEMOP_DEF(iemOp_or_Eb_Gb)
1162{
1163 IEMOP_MNEMONIC2(MR, OR, or, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
1164 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1165 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1166 IEMOP_BODY_BINARY_rm_r8_RW(bRm, or, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1167}
1168
1169
1170/*
1171 * @opcode 0x09
1172 * @opgroup og_gen_arith_bin
1173 * @opflclass logical
1174 * @optest efl|=of,cf op1=12 op2=7 -> op1=15 efl&|=nc,po,na,nz,pl,nv
1175 * @optest efl|=of,cf op1=0 op2=0 -> op1=0 efl&|=nc,po,na,zf,pl,nv
1176 * @optest op1=-2 op2=1 -> op1=-1 efl&|=nc,po,na,nz,ng,nv
1177 * @optest o16 / op1=0x5a5a op2=0xa5a5 -> op1=-1 efl&|=nc,po,na,nz,ng,nv
1178 * @optest o32 / op1=0x5a5a5a5a op2=0xa5a5a5a5 -> op1=-1 efl&|=nc,po,na,nz,ng,nv
1179 * @optest o64 / op1=0x5a5a5a5a5a5a5a5a op2=0xa5a5a5a5a5a5a5a5 -> op1=-1 efl&|=nc,po,na,nz,ng,nv
1180 * @note AF is documented as undefined, but both modern AMD and Intel CPUs clears it.
1181 */
1182FNIEMOP_DEF(iemOp_or_Ev_Gv)
1183{
1184 IEMOP_MNEMONIC2(MR, OR, or, Ev, Gv, DISOPTYPE_HARMLESS, IEMOPHINT_LOCK_ALLOWED);
1185 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1186 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1187 IEMOP_BODY_BINARY_rm_rv_RW( bRm, or, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1188 IEMOP_BODY_BINARY_rm_rv_LOCKED(bRm, or);
1189}
1190
1191
1192/**
1193 * @opcode 0x0a
1194 * @opgroup og_gen_arith_bin
1195 * @opflclass logical
1196 * @opcopytests iemOp_or_Eb_Gb
1197 */
1198FNIEMOP_DEF(iemOp_or_Gb_Eb)
1199{
1200 IEMOP_MNEMONIC2(RM, OR, or, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
1201 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1202 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1203 IEMOP_BODY_BINARY_r8_rm(bRm, or, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1204}
1205
1206
1207/**
1208 * @opcode 0x0b
1209 * @opgroup og_gen_arith_bin
1210 * @opflclass logical
1211 * @opcopytests iemOp_or_Ev_Gv
1212 */
1213FNIEMOP_DEF(iemOp_or_Gv_Ev)
1214{
1215 IEMOP_MNEMONIC2(RM, OR, or, Gv, Ev, DISOPTYPE_HARMLESS, 0);
1216 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1217 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1218 IEMOP_BODY_BINARY_rv_rm(bRm, iemAImpl_or_u16, iemAImpl_or_u32, iemAImpl_or_u64, 0, or, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1219}
1220
1221
1222/**
1223 * @opcode 0x0c
1224 * @opgroup og_gen_arith_bin
1225 * @opflclass logical
1226 * @opcopytests iemOp_or_Eb_Gb
1227 */
1228FNIEMOP_DEF(iemOp_or_Al_Ib)
1229{
1230 IEMOP_MNEMONIC2(FIXED, OR, or, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1231 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1232 IEMOP_BODY_BINARY_AL_Ib(or, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1233}
1234
1235
1236/**
1237 * @opcode 0x0d
1238 * @opgroup og_gen_arith_bin
1239 * @opflclass logical
1240 * @optest efl|=of,cf op1=12 op2=7 -> op1=15 efl&|=nc,po,na,nz,pl,nv
1241 * @optest efl|=of,cf op1=0 op2=0 -> op1=0 efl&|=nc,po,na,zf,pl,nv
1242 * @optest op1=-2 op2=1 -> op1=-1 efl&|=nc,po,na,nz,ng,nv
1243 * @optest o16 / op1=0x5a5a op2=0xa5a5 -> op1=-1 efl&|=nc,po,na,nz,ng,nv
1244 * @optest o32 / op1=0x5a5a5a5a op2=0xa5a5a5a5 -> op1=-1 efl&|=nc,po,na,nz,ng,nv
1245 * @optest o64 / op1=0x5a5a5a5a5a5a5a5a op2=0xa5a5a5a5 -> op1=-1 efl&|=nc,po,na,nz,ng,nv
1246 * @optest o64 / op1=0x5a5a5a5aa5a5a5a5 op2=0x5a5a5a5a -> op1=0x5a5a5a5affffffff efl&|=nc,po,na,nz,pl,nv
1247 */
1248FNIEMOP_DEF(iemOp_or_eAX_Iz)
1249{
1250 IEMOP_MNEMONIC2(FIXED, OR, or, rAX, Iz, DISOPTYPE_HARMLESS, 0);
1251 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1252 IEMOP_BODY_BINARY_rAX_Iz_RW(or, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1253}
1254
1255
1256/**
1257 * @opcode 0x0e
1258 * @opgroup og_stack_sreg
1259 */
1260FNIEMOP_DEF(iemOp_push_CS)
1261{
1262 IEMOP_MNEMONIC1(FIXED, PUSH, push, CS, DISOPTYPE_HARMLESS | DISOPTYPE_POTENTIALLY_DANGEROUS | DISOPTYPE_X86_INVALID_64, 0);
1263 IEMOP_HLP_NO_64BIT();
1264 return FNIEMOP_CALL_1(iemOpCommonPushSReg, X86_SREG_CS);
1265}
1266
1267
1268/**
1269 * @opcode 0x0f
1270 * @opmnemonic EscTwo0f
1271 * @openc two0f
1272 * @opdisenum OP_2B_ESC
1273 * @ophints harmless
1274 * @opgroup og_escapes
1275 */
1276FNIEMOP_DEF(iemOp_2byteEscape)
1277{
1278#if 0 /// @todo def VBOX_STRICT
1279 /* Sanity check the table the first time around. */
1280 static bool s_fTested = false;
1281 if (RT_LIKELY(s_fTested)) { /* likely */ }
1282 else
1283 {
1284 s_fTested = true;
1285 Assert(g_apfnTwoByteMap[0xbc * 4 + 0] == iemOp_bsf_Gv_Ev);
1286 Assert(g_apfnTwoByteMap[0xbc * 4 + 1] == iemOp_bsf_Gv_Ev);
1287 Assert(g_apfnTwoByteMap[0xbc * 4 + 2] == iemOp_tzcnt_Gv_Ev);
1288 Assert(g_apfnTwoByteMap[0xbc * 4 + 3] == iemOp_bsf_Gv_Ev);
1289 }
1290#endif
1291
1292 if (RT_LIKELY(IEM_GET_TARGET_CPU(pVCpu) >= IEMTARGETCPU_286))
1293 {
1294 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
1295 IEMOP_HLP_MIN_286();
1296 return FNIEMOP_CALL(g_apfnTwoByteMap[(uintptr_t)b * 4 + pVCpu->iem.s.idxPrefix]);
1297 }
1298 /* @opdone */
1299
1300 /*
1301 * On the 8086 this is a POP CS instruction.
1302 * For the time being we don't specify this this.
1303 */
1304 IEMOP_MNEMONIC1(FIXED, POP, pop, CS, DISOPTYPE_HARMLESS | DISOPTYPE_POTENTIALLY_DANGEROUS | DISOPTYPE_X86_INVALID_64, IEMOPHINT_SKIP_PYTHON);
1305 IEMOP_HLP_NO_64BIT();
1306 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
1307 /** @todo eliminate END_TB here */
1308 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_END_TB,
1309 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
1310 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_CS),
1311 iemCImpl_pop_Sreg, X86_SREG_CS, pVCpu->iem.s.enmEffOpSize);
1312}
1313
1314/**
1315 * @opcode 0x10
1316 * @opgroup og_gen_arith_bin
1317 * @opflclass arithmetic_carry
1318 * @optest op1=1 op2=1 efl&~=cf -> op1=2 efl&|=nc,pe,na,nz,pl,nv
1319 * @optest op1=1 op2=1 efl|=cf -> op1=3 efl&|=nc,po,na,nz,pl,nv
1320 * @optest op1=0xff op2=0 efl|=cf -> op1=0 efl&|=cf,po,af,zf,pl,nv
1321 * @optest op1=0 op2=0 efl|=cf -> op1=1 efl&|=nc,pe,na,nz,pl,nv
1322 * @optest op1=0 op2=0 efl&~=cf -> op1=0 efl&|=nc,po,na,zf,pl,nv
1323 */
1324FNIEMOP_DEF(iemOp_adc_Eb_Gb)
1325{
1326 IEMOP_MNEMONIC2(MR, ADC, adc, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
1327 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1328 IEMOP_BODY_BINARY_rm_r8_RW(bRm, adc, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1329}
1330
1331
1332/**
1333 * @opcode 0x11
1334 * @opgroup og_gen_arith_bin
1335 * @opflclass arithmetic_carry
1336 * @optest op1=1 op2=1 efl&~=cf -> op1=2 efl&|=nc,pe,na,nz,pl,nv
1337 * @optest op1=1 op2=1 efl|=cf -> op1=3 efl&|=nc,po,na,nz,pl,nv
1338 * @optest op1=-1 op2=0 efl|=cf -> op1=0 efl&|=cf,po,af,zf,pl,nv
1339 * @optest op1=0 op2=0 efl|=cf -> op1=1 efl&|=nc,pe,na,nz,pl,nv
1340 * @optest op1=0 op2=0 efl&~=cf -> op1=0 efl&|=nc,po,na,zf,pl,nv
1341 */
1342FNIEMOP_DEF(iemOp_adc_Ev_Gv)
1343{
1344 IEMOP_MNEMONIC2(MR, ADC, adc, Ev, Gv, DISOPTYPE_HARMLESS, IEMOPHINT_LOCK_ALLOWED);
1345 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1346 IEMOP_BODY_BINARY_rm_rv_RW( bRm, adc, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1347 IEMOP_BODY_BINARY_rm_rv_LOCKED(bRm, adc);
1348}
1349
1350
1351/**
1352 * @opcode 0x12
1353 * @opgroup og_gen_arith_bin
1354 * @opflclass arithmetic_carry
1355 * @opcopytests iemOp_adc_Eb_Gb
1356 */
1357FNIEMOP_DEF(iemOp_adc_Gb_Eb)
1358{
1359 IEMOP_MNEMONIC2(RM, ADC, adc, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1360 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1361 IEMOP_BODY_BINARY_r8_rm(bRm, adc, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1362}
1363
1364
1365/**
1366 * @opcode 0x13
1367 * @opgroup og_gen_arith_bin
1368 * @opflclass arithmetic_carry
1369 * @opcopytests iemOp_adc_Ev_Gv
1370 */
1371FNIEMOP_DEF(iemOp_adc_Gv_Ev)
1372{
1373 IEMOP_MNEMONIC2(RM, ADC, adc, Gv, Ev, DISOPTYPE_HARMLESS, 0);
1374 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1375 IEMOP_BODY_BINARY_rv_rm(bRm, iemAImpl_adc_u16, iemAImpl_adc_u32, iemAImpl_adc_u64, 0, adc, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1376}
1377
1378
1379/**
1380 * @opcode 0x14
1381 * @opgroup og_gen_arith_bin
1382 * @opflclass arithmetic_carry
1383 * @opcopytests iemOp_adc_Eb_Gb
1384 */
1385FNIEMOP_DEF(iemOp_adc_Al_Ib)
1386{
1387 IEMOP_MNEMONIC2(FIXED, ADC, adc, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1388 IEMOP_BODY_BINARY_AL_Ib(adc, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1389}
1390
1391
1392/**
1393 * @opcode 0x15
1394 * @opgroup og_gen_arith_bin
1395 * @opflclass arithmetic_carry
1396 * @opcopytests iemOp_adc_Ev_Gv
1397 */
1398FNIEMOP_DEF(iemOp_adc_eAX_Iz)
1399{
1400 IEMOP_MNEMONIC2(FIXED, ADC, adc, rAX, Iz, DISOPTYPE_HARMLESS, 0);
1401 IEMOP_BODY_BINARY_rAX_Iz_RW(adc, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1402}
1403
1404
1405/**
1406 * @opcode 0x16
1407 */
1408FNIEMOP_DEF(iemOp_push_SS)
1409{
1410 IEMOP_MNEMONIC1(FIXED, PUSH, push, SS, DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64 | DISOPTYPE_RRM_DANGEROUS, 0);
1411 IEMOP_HLP_NO_64BIT();
1412 return FNIEMOP_CALL_1(iemOpCommonPushSReg, X86_SREG_SS);
1413}
1414
1415
1416/**
1417 * @opcode 0x17
1418 */
1419FNIEMOP_DEF(iemOp_pop_SS)
1420{
1421 IEMOP_MNEMONIC1(FIXED, POP, pop, SS, DISOPTYPE_HARMLESS | DISOPTYPE_INHIBIT_IRQS | DISOPTYPE_X86_INVALID_64 | DISOPTYPE_RRM_DANGEROUS , 0);
1422 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
1423 IEMOP_HLP_NO_64BIT();
1424 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_MODE | IEM_CIMPL_F_INHIBIT_SHADOW,
1425 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
1426 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_SS)
1427 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_SS)
1428 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_SS)
1429 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_SS),
1430 iemCImpl_pop_Sreg, X86_SREG_SS, pVCpu->iem.s.enmEffOpSize);
1431}
1432
1433
1434/**
1435 * @opcode 0x18
1436 * @opgroup og_gen_arith_bin
1437 * @opflclass arithmetic_carry
1438 */
1439FNIEMOP_DEF(iemOp_sbb_Eb_Gb)
1440{
1441 IEMOP_MNEMONIC2(MR, SBB, sbb, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
1442 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1443 IEMOP_BODY_BINARY_rm_r8_RW(bRm, sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1444}
1445
1446
1447/**
1448 * @opcode 0x19
1449 * @opgroup og_gen_arith_bin
1450 * @opflclass arithmetic_carry
1451 */
1452FNIEMOP_DEF(iemOp_sbb_Ev_Gv)
1453{
1454 IEMOP_MNEMONIC2(MR, SBB, sbb, Ev, Gv, DISOPTYPE_HARMLESS, IEMOPHINT_LOCK_ALLOWED);
1455 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1456 IEMOP_BODY_BINARY_rm_rv_RW( bRm, sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1457 IEMOP_BODY_BINARY_rm_rv_LOCKED(bRm, sbb);
1458}
1459
1460
1461/**
1462 * @opcode 0x1a
1463 * @opgroup og_gen_arith_bin
1464 * @opflclass arithmetic_carry
1465 */
1466FNIEMOP_DEF(iemOp_sbb_Gb_Eb)
1467{
1468 IEMOP_MNEMONIC2(RM, SBB, sbb, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1469 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1470 IEMOP_BODY_BINARY_r8_rm(bRm, sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1471}
1472
1473
1474/**
1475 * @opcode 0x1b
1476 * @opgroup og_gen_arith_bin
1477 * @opflclass arithmetic_carry
1478 */
1479FNIEMOP_DEF(iemOp_sbb_Gv_Ev)
1480{
1481 IEMOP_MNEMONIC2(RM, SBB, sbb, Gv, Ev, DISOPTYPE_HARMLESS, 0);
1482 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1483 IEMOP_BODY_BINARY_rv_rm(bRm, iemAImpl_sbb_u16, iemAImpl_sbb_u32, iemAImpl_sbb_u64, 0, sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1484}
1485
1486
1487/**
1488 * @opcode 0x1c
1489 * @opgroup og_gen_arith_bin
1490 * @opflclass arithmetic_carry
1491 */
1492FNIEMOP_DEF(iemOp_sbb_Al_Ib)
1493{
1494 IEMOP_MNEMONIC2(FIXED, SBB, sbb, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1495 IEMOP_BODY_BINARY_AL_Ib(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1496}
1497
1498
1499/**
1500 * @opcode 0x1d
1501 * @opgroup og_gen_arith_bin
1502 * @opflclass arithmetic_carry
1503 */
1504FNIEMOP_DEF(iemOp_sbb_eAX_Iz)
1505{
1506 IEMOP_MNEMONIC2(FIXED, SBB, sbb, rAX, Iz, DISOPTYPE_HARMLESS, 0);
1507 IEMOP_BODY_BINARY_rAX_Iz_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1508}
1509
1510
1511/**
1512 * @opcode 0x1e
1513 * @opgroup og_stack_sreg
1514 */
1515FNIEMOP_DEF(iemOp_push_DS)
1516{
1517 IEMOP_MNEMONIC1(FIXED, PUSH, push, DS, DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64, 0);
1518 IEMOP_HLP_NO_64BIT();
1519 return FNIEMOP_CALL_1(iemOpCommonPushSReg, X86_SREG_DS);
1520}
1521
1522
1523/**
1524 * @opcode 0x1f
1525 * @opgroup og_stack_sreg
1526 */
1527FNIEMOP_DEF(iemOp_pop_DS)
1528{
1529 IEMOP_MNEMONIC1(FIXED, POP, pop, DS, DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64 | DISOPTYPE_RRM_DANGEROUS, 0);
1530 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
1531 IEMOP_HLP_NO_64BIT();
1532 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_MODE,
1533 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
1534 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_DS)
1535 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_DS)
1536 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_DS)
1537 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_DS),
1538 iemCImpl_pop_Sreg, X86_SREG_DS, pVCpu->iem.s.enmEffOpSize);
1539}
1540
1541
1542/**
1543 * @opcode 0x20
1544 * @opgroup og_gen_arith_bin
1545 * @opflclass logical
1546 */
1547FNIEMOP_DEF(iemOp_and_Eb_Gb)
1548{
1549 IEMOP_MNEMONIC2(MR, AND, and, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
1550 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1551 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1552 IEMOP_BODY_BINARY_rm_r8_RW(bRm, and, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1553}
1554
1555
1556/**
1557 * @opcode 0x21
1558 * @opgroup og_gen_arith_bin
1559 * @opflclass logical
1560 */
1561FNIEMOP_DEF(iemOp_and_Ev_Gv)
1562{
1563 IEMOP_MNEMONIC2(MR, AND, and, Ev, Gv, DISOPTYPE_HARMLESS, IEMOPHINT_LOCK_ALLOWED);
1564 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1565 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1566 IEMOP_BODY_BINARY_rm_rv_RW( bRm, and, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1567 IEMOP_BODY_BINARY_rm_rv_LOCKED(bRm, and);
1568}
1569
1570
1571/**
1572 * @opcode 0x22
1573 * @opgroup og_gen_arith_bin
1574 * @opflclass logical
1575 */
1576FNIEMOP_DEF(iemOp_and_Gb_Eb)
1577{
1578 IEMOP_MNEMONIC2(RM, AND, and, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1579 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1580 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1581 IEMOP_BODY_BINARY_r8_rm(bRm, and, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1582}
1583
1584
1585/**
1586 * @opcode 0x23
1587 * @opgroup og_gen_arith_bin
1588 * @opflclass logical
1589 */
1590FNIEMOP_DEF(iemOp_and_Gv_Ev)
1591{
1592 IEMOP_MNEMONIC2(RM, AND, and, Gv, Ev, DISOPTYPE_HARMLESS, 0);
1593 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1594 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1595 IEMOP_BODY_BINARY_rv_rm(bRm, iemAImpl_and_u16, iemAImpl_and_u32, iemAImpl_and_u64, 0, and, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1596}
1597
1598
1599/**
1600 * @opcode 0x24
1601 * @opgroup og_gen_arith_bin
1602 * @opflclass logical
1603 */
1604FNIEMOP_DEF(iemOp_and_Al_Ib)
1605{
1606 IEMOP_MNEMONIC2(FIXED, AND, and, AL, Ib, DISOPTYPE_HARMLESS, 0);
1607 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1608 IEMOP_BODY_BINARY_AL_Ib(and, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1609}
1610
1611
1612/**
1613 * @opcode 0x25
1614 * @opgroup og_gen_arith_bin
1615 * @opflclass logical
1616 */
1617FNIEMOP_DEF(iemOp_and_eAX_Iz)
1618{
1619 IEMOP_MNEMONIC2(FIXED, AND, and, rAX, Iz, DISOPTYPE_HARMLESS, 0);
1620 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1621 IEMOP_BODY_BINARY_rAX_Iz_RW(and, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1622}
1623
1624
1625/**
1626 * @opcode 0x26
1627 * @opmnemonic SEG
1628 * @op1 ES
1629 * @opgroup og_prefix
1630 * @openc prefix
1631 * @opdisenum OP_SEG
1632 * @ophints harmless
1633 */
1634FNIEMOP_DEF(iemOp_seg_ES)
1635{
1636 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("seg es");
1637 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SEG_ES;
1638 pVCpu->iem.s.iEffSeg = X86_SREG_ES;
1639
1640 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
1641 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
1642}
1643
1644
1645/**
1646 * @opcode 0x27
1647 * @opfltest af,cf
1648 * @opflmodify cf,pf,af,zf,sf,of
1649 * @opflundef of
1650 */
1651FNIEMOP_DEF(iemOp_daa)
1652{
1653 IEMOP_MNEMONIC0(FIXED, DAA, daa, DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64, 0); /* express implicit AL register use */
1654 IEMOP_HLP_NO_64BIT();
1655 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
1656 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF);
1657 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_STATUS_FLAGS, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX), iemCImpl_daa);
1658}
1659
1660
1661/**
1662 * @opcode 0x28
1663 * @opgroup og_gen_arith_bin
1664 * @opflclass arithmetic
1665 */
1666FNIEMOP_DEF(iemOp_sub_Eb_Gb)
1667{
1668 IEMOP_MNEMONIC2(MR, SUB, sub, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
1669 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1670 IEMOP_BODY_BINARY_r8_SAME_REG_ZERO(bRm); /* Special case: sub samereg, samereg - zeros samereg and sets EFLAGS to know value */
1671 IEMOP_BODY_BINARY_rm_r8_RW(bRm, sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1672}
1673
1674
1675/**
1676 * @opcode 0x29
1677 * @opgroup og_gen_arith_bin
1678 * @opflclass arithmetic
1679 */
1680FNIEMOP_DEF(iemOp_sub_Ev_Gv)
1681{
1682 IEMOP_MNEMONIC2(MR, SUB, sub, Ev, Gv, DISOPTYPE_HARMLESS, IEMOPHINT_LOCK_ALLOWED);
1683 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1684 IEMOP_BODY_BINARY_rv_SAME_REG_ZERO(bRm); /* Special case: sub samereg, samereg - zeros samereg and sets EFLAGS to know value */
1685 IEMOP_BODY_BINARY_rm_rv_RW( bRm, sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1686 IEMOP_BODY_BINARY_rm_rv_LOCKED(bRm, sub);
1687}
1688
1689
1690/**
1691 * @opcode 0x2a
1692 * @opgroup og_gen_arith_bin
1693 * @opflclass arithmetic
1694 */
1695FNIEMOP_DEF(iemOp_sub_Gb_Eb)
1696{
1697 IEMOP_MNEMONIC2(RM, SUB, sub, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1698 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1699 IEMOP_BODY_BINARY_r8_SAME_REG_ZERO(bRm); /* Special case: sub samereg, samereg - zeros samereg and sets EFLAGS to know value */
1700 IEMOP_BODY_BINARY_r8_rm(bRm, sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1701}
1702
1703
1704/**
1705 * @opcode 0x2b
1706 * @opgroup og_gen_arith_bin
1707 * @opflclass arithmetic
1708 */
1709FNIEMOP_DEF(iemOp_sub_Gv_Ev)
1710{
1711 IEMOP_MNEMONIC2(RM, SUB, sub, Gv, Ev, DISOPTYPE_HARMLESS, 0);
1712 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1713 IEMOP_BODY_BINARY_rv_SAME_REG_ZERO(bRm); /* Special case: sub samereg, samereg - zeros samereg and sets EFLAGS to know value */
1714 IEMOP_BODY_BINARY_rv_rm(bRm, iemAImpl_sub_u16, iemAImpl_sub_u32, iemAImpl_sub_u64, 0, sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1715}
1716
1717
1718/**
1719 * @opcode 0x2c
1720 * @opgroup og_gen_arith_bin
1721 * @opflclass arithmetic
1722 */
1723FNIEMOP_DEF(iemOp_sub_Al_Ib)
1724{
1725 IEMOP_MNEMONIC2(FIXED, SUB, sub, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1726 IEMOP_BODY_BINARY_AL_Ib(sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1727}
1728
1729
1730/**
1731 * @opcode 0x2d
1732 * @opgroup og_gen_arith_bin
1733 * @opflclass arithmetic
1734 */
1735FNIEMOP_DEF(iemOp_sub_eAX_Iz)
1736{
1737 IEMOP_MNEMONIC2(FIXED, SUB, sub, rAX, Iz, DISOPTYPE_HARMLESS, 0);
1738 IEMOP_BODY_BINARY_rAX_Iz_RW(sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1739}
1740
1741
1742/**
1743 * @opcode 0x2e
1744 * @opmnemonic SEG
1745 * @op1 CS
1746 * @opgroup og_prefix
1747 * @openc prefix
1748 * @opdisenum OP_SEG
1749 * @ophints harmless
1750 */
1751FNIEMOP_DEF(iemOp_seg_CS)
1752{
1753 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("seg cs");
1754 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SEG_CS;
1755 pVCpu->iem.s.iEffSeg = X86_SREG_CS;
1756
1757 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
1758 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
1759}
1760
1761
1762/**
1763 * @opcode 0x2f
1764 * @opfltest af,cf
1765 * @opflmodify cf,pf,af,zf,sf,of
1766 * @opflundef of
1767 */
1768FNIEMOP_DEF(iemOp_das)
1769{
1770 IEMOP_MNEMONIC0(FIXED, DAS, das, DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64, 0); /* express implicit AL register use */
1771 IEMOP_HLP_NO_64BIT();
1772 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
1773 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF);
1774 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_STATUS_FLAGS, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX), iemCImpl_das);
1775}
1776
1777
1778/**
1779 * @opcode 0x30
1780 * @opgroup og_gen_arith_bin
1781 * @opflclass logical
1782 */
1783FNIEMOP_DEF(iemOp_xor_Eb_Gb)
1784{
1785 IEMOP_MNEMONIC2(MR, XOR, xor, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
1786 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1787 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1788 IEMOP_BODY_BINARY_r8_SAME_REG_ZERO(bRm); /* Special case: xor samereg, samereg - zeros samereg and sets EFLAGS to know value */
1789 IEMOP_BODY_BINARY_rm_r8_RW(bRm, xor, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1790}
1791
1792
1793/**
1794 * @opcode 0x31
1795 * @opgroup og_gen_arith_bin
1796 * @opflclass logical
1797 */
1798FNIEMOP_DEF(iemOp_xor_Ev_Gv)
1799{
1800 IEMOP_MNEMONIC2(MR, XOR, xor, Ev, Gv, DISOPTYPE_HARMLESS, IEMOPHINT_LOCK_ALLOWED);
1801 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1802 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1803 IEMOP_BODY_BINARY_rm_rv_RW( bRm, xor, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
1804 IEMOP_BODY_BINARY_rv_SAME_REG_ZERO(bRm); /* Special case: xor samereg, samereg - zeros samereg and sets EFLAGS to know value */
1805 IEMOP_BODY_BINARY_rm_rv_LOCKED( bRm, xor);
1806}
1807
1808
1809/**
1810 * @opcode 0x32
1811 * @opgroup og_gen_arith_bin
1812 * @opflclass logical
1813 */
1814FNIEMOP_DEF(iemOp_xor_Gb_Eb)
1815{
1816 IEMOP_MNEMONIC2(RM, XOR, xor, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1817 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1818 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1819 IEMOP_BODY_BINARY_r8_SAME_REG_ZERO(bRm); /* Special case: xor samereg, samereg - zeros samereg and sets EFLAGS to know value */
1820 IEMOP_BODY_BINARY_r8_rm(bRm, xor, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1821}
1822
1823
1824/**
1825 * @opcode 0x33
1826 * @opgroup og_gen_arith_bin
1827 * @opflclass logical
1828 */
1829FNIEMOP_DEF(iemOp_xor_Gv_Ev)
1830{
1831 IEMOP_MNEMONIC2(RM, XOR, xor, Gv, Ev, DISOPTYPE_HARMLESS, 0);
1832 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1833 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1834 IEMOP_BODY_BINARY_rv_SAME_REG_ZERO(bRm); /* Special case: xor samereg, samereg - zeros samereg and sets EFLAGS to know value */
1835 IEMOP_BODY_BINARY_rv_rm(bRm, iemAImpl_xor_u16, iemAImpl_xor_u32, iemAImpl_xor_u64, 0, xor, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1836}
1837
1838
1839/**
1840 * @opcode 0x34
1841 * @opgroup og_gen_arith_bin
1842 * @opflclass logical
1843 */
1844FNIEMOP_DEF(iemOp_xor_Al_Ib)
1845{
1846 IEMOP_MNEMONIC2(FIXED, XOR, xor, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1847 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1848 IEMOP_BODY_BINARY_AL_Ib(xor, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1849}
1850
1851
1852/**
1853 * @opcode 0x35
1854 * @opgroup og_gen_arith_bin
1855 * @opflclass logical
1856 */
1857FNIEMOP_DEF(iemOp_xor_eAX_Iz)
1858{
1859 IEMOP_MNEMONIC2(FIXED, XOR, xor, rAX, Iz, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
1860 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
1861 IEMOP_BODY_BINARY_rAX_Iz_RW(xor, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1862}
1863
1864
1865/**
1866 * @opcode 0x36
1867 * @opmnemonic SEG
1868 * @op1 SS
1869 * @opgroup og_prefix
1870 * @openc prefix
1871 * @opdisenum OP_SEG
1872 * @ophints harmless
1873 */
1874FNIEMOP_DEF(iemOp_seg_SS)
1875{
1876 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("seg ss");
1877 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SEG_SS;
1878 pVCpu->iem.s.iEffSeg = X86_SREG_SS;
1879
1880 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
1881 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
1882}
1883
1884
1885/**
1886 * @opcode 0x37
1887 * @opfltest af
1888 * @opflmodify cf,pf,af,zf,sf,of
1889 * @opflundef pf,zf,sf,of
1890 * @opgroup og_gen_arith_dec
1891 * @optest efl&~=af ax=9 -> efl&|=nc,po,na,nz,pl,nv
1892 * @optest efl&~=af ax=0 -> efl&|=nc,po,na,zf,pl,nv
1893 * @optest intel / efl&~=af ax=0x00f0 -> ax=0x0000 efl&|=nc,po,na,zf,pl,nv
1894 * @optest amd / efl&~=af ax=0x00f0 -> ax=0x0000 efl&|=nc,po,na,nz,pl,nv
1895 * @optest efl&~=af ax=0x00f9 -> ax=0x0009 efl&|=nc,po,na,nz,pl,nv
1896 * @optest efl|=af ax=0 -> ax=0x0106 efl&|=cf,po,af,nz,pl,nv
1897 * @optest efl|=af ax=0x0100 -> ax=0x0206 efl&|=cf,po,af,nz,pl,nv
1898 * @optest intel / efl|=af ax=0x000a -> ax=0x0100 efl&|=cf,po,af,zf,pl,nv
1899 * @optest amd / efl|=af ax=0x000a -> ax=0x0100 efl&|=cf,pe,af,nz,pl,nv
1900 * @optest intel / efl|=af ax=0x010a -> ax=0x0200 efl&|=cf,po,af,zf,pl,nv
1901 * @optest amd / efl|=af ax=0x010a -> ax=0x0200 efl&|=cf,pe,af,nz,pl,nv
1902 * @optest intel / efl|=af ax=0x0f0a -> ax=0x1000 efl&|=cf,po,af,zf,pl,nv
1903 * @optest amd / efl|=af ax=0x0f0a -> ax=0x1000 efl&|=cf,pe,af,nz,pl,nv
1904 * @optest intel / efl|=af ax=0x7f0a -> ax=0x8000 efl&|=cf,po,af,zf,pl,nv
1905 * @optest amd / efl|=af ax=0x7f0a -> ax=0x8000 efl&|=cf,pe,af,nz,ng,ov
1906 * @optest intel / efl|=af ax=0xff0a -> ax=0x0000 efl&|=cf,po,af,zf,pl,nv
1907 * @optest amd / efl|=af ax=0xff0a -> ax=0x0000 efl&|=cf,pe,af,nz,pl,nv
1908 * @optest intel / efl&~=af ax=0xff0a -> ax=0x0000 efl&|=cf,po,af,zf,pl,nv
1909 * @optest amd / efl&~=af ax=0xff0a -> ax=0x0000 efl&|=cf,pe,af,nz,pl,nv
1910 * @optest intel / efl&~=af ax=0x000b -> ax=0x0101 efl&|=cf,pe,af,nz,pl,nv
1911 * @optest amd / efl&~=af ax=0x000b -> ax=0x0101 efl&|=cf,po,af,nz,pl,nv
1912 * @optest intel / efl&~=af ax=0x000c -> ax=0x0102 efl&|=cf,pe,af,nz,pl,nv
1913 * @optest amd / efl&~=af ax=0x000c -> ax=0x0102 efl&|=cf,po,af,nz,pl,nv
1914 * @optest intel / efl&~=af ax=0x000d -> ax=0x0103 efl&|=cf,po,af,nz,pl,nv
1915 * @optest amd / efl&~=af ax=0x000d -> ax=0x0103 efl&|=cf,pe,af,nz,pl,nv
1916 * @optest intel / efl&~=af ax=0x000e -> ax=0x0104 efl&|=cf,pe,af,nz,pl,nv
1917 * @optest amd / efl&~=af ax=0x000e -> ax=0x0104 efl&|=cf,po,af,nz,pl,nv
1918 * @optest intel / efl&~=af ax=0x000f -> ax=0x0105 efl&|=cf,po,af,nz,pl,nv
1919 * @optest amd / efl&~=af ax=0x000f -> ax=0x0105 efl&|=cf,pe,af,nz,pl,nv
1920 * @optest intel / efl&~=af ax=0x020f -> ax=0x0305 efl&|=cf,po,af,nz,pl,nv
1921 * @optest amd / efl&~=af ax=0x020f -> ax=0x0305 efl&|=cf,pe,af,nz,pl,nv
1922 */
1923FNIEMOP_DEF(iemOp_aaa)
1924{
1925 IEMOP_MNEMONIC0(FIXED, AAA, aaa, DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64, 0); /* express implicit AL/AX register use */
1926 IEMOP_HLP_NO_64BIT();
1927 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
1928 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF);
1929
1930 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_STATUS_FLAGS, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX), iemCImpl_aaa);
1931}
1932
1933
1934/**
1935 * @opcode 0x38
1936 * @opflclass arithmetic
1937 */
1938FNIEMOP_DEF(iemOp_cmp_Eb_Gb)
1939{
1940 IEMOP_MNEMONIC(cmp_Eb_Gb, "cmp Eb,Gb");
1941 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1942 IEMOP_BODY_BINARY_rm_r8_RO(bRm, iemAImpl_cmp_u8, cmp, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1943}
1944
1945
1946/**
1947 * @opcode 0x39
1948 * @opflclass arithmetic
1949 */
1950FNIEMOP_DEF(iemOp_cmp_Ev_Gv)
1951{
1952 IEMOP_MNEMONIC(cmp_Ev_Gv, "cmp Ev,Gv");
1953 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1954 IEMOP_BODY_BINARY_rm_rv_RO(bRm, cmp, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1955}
1956
1957
1958/**
1959 * @opcode 0x3a
1960 * @opflclass arithmetic
1961 */
1962FNIEMOP_DEF(iemOp_cmp_Gb_Eb)
1963{
1964 IEMOP_MNEMONIC(cmp_Gb_Eb, "cmp Gb,Eb");
1965 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1966 IEMOP_BODY_BINARY_r8_rm_RO(bRm, cmp, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1967}
1968
1969
1970/**
1971 * @opcode 0x3b
1972 * @opflclass arithmetic
1973 */
1974FNIEMOP_DEF(iemOp_cmp_Gv_Ev)
1975{
1976 IEMOP_MNEMONIC(cmp_Gv_Ev, "cmp Gv,Ev");
1977 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
1978 IEMOP_BODY_BINARY_rv_rm_RO(bRm, cmp, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1979}
1980
1981
1982/**
1983 * @opcode 0x3c
1984 * @opflclass arithmetic
1985 */
1986FNIEMOP_DEF(iemOp_cmp_Al_Ib)
1987{
1988 IEMOP_MNEMONIC(cmp_al_Ib, "cmp al,Ib");
1989 IEMOP_BODY_BINARY_AL_Ib(cmp, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
1990}
1991
1992
1993/**
1994 * @opcode 0x3d
1995 * @opflclass arithmetic
1996 */
1997FNIEMOP_DEF(iemOp_cmp_eAX_Iz)
1998{
1999 IEMOP_MNEMONIC(cmp_rAX_Iz, "cmp rAX,Iz");
2000 IEMOP_BODY_BINARY_rAX_Iz_RO(cmp, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
2001}
2002
2003
2004/**
2005 * @opcode 0x3e
2006 */
2007FNIEMOP_DEF(iemOp_seg_DS)
2008{
2009 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("seg ds");
2010 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SEG_DS;
2011 pVCpu->iem.s.iEffSeg = X86_SREG_DS;
2012
2013 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2014 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2015}
2016
2017
2018/**
2019 * @opcode 0x3f
2020 * @opfltest af
2021 * @opflmodify cf,pf,af,zf,sf,of
2022 * @opflundef pf,zf,sf,of
2023 * @opgroup og_gen_arith_dec
2024 * @optest / efl&~=af ax=0x0009 -> efl&|=nc,po,na,nz,pl,nv
2025 * @optest / efl&~=af ax=0x0000 -> efl&|=nc,po,na,zf,pl,nv
2026 * @optest intel / efl&~=af ax=0x00f0 -> ax=0x0000 efl&|=nc,po,na,zf,pl,nv
2027 * @optest amd / efl&~=af ax=0x00f0 -> ax=0x0000 efl&|=nc,po,na,nz,pl,nv
2028 * @optest / efl&~=af ax=0x00f9 -> ax=0x0009 efl&|=nc,po,na,nz,pl,nv
2029 * @optest intel / efl|=af ax=0x0000 -> ax=0xfe0a efl&|=cf,po,af,nz,pl,nv
2030 * @optest amd / efl|=af ax=0x0000 -> ax=0xfe0a efl&|=cf,po,af,nz,ng,nv
2031 * @optest intel / efl|=af ax=0x0100 -> ax=0xff0a efl&|=cf,po,af,nz,pl,nv
2032 * @optest amd / efl|=af ax=0x0100 -> ax=0xff0a efl&|=cf,po,af,nz,ng,nv
2033 * @optest intel / efl|=af ax=0x000a -> ax=0xff04 efl&|=cf,pe,af,nz,pl,nv
2034 * @optest amd / efl|=af ax=0x000a -> ax=0xff04 efl&|=cf,pe,af,nz,ng,nv
2035 * @optest / efl|=af ax=0x010a -> ax=0x0004 efl&|=cf,pe,af,nz,pl,nv
2036 * @optest / efl|=af ax=0x020a -> ax=0x0104 efl&|=cf,pe,af,nz,pl,nv
2037 * @optest / efl|=af ax=0x0f0a -> ax=0x0e04 efl&|=cf,pe,af,nz,pl,nv
2038 * @optest / efl|=af ax=0x7f0a -> ax=0x7e04 efl&|=cf,pe,af,nz,pl,nv
2039 * @optest intel / efl|=af ax=0xff0a -> ax=0xfe04 efl&|=cf,pe,af,nz,pl,nv
2040 * @optest amd / efl|=af ax=0xff0a -> ax=0xfe04 efl&|=cf,pe,af,nz,ng,nv
2041 * @optest intel / efl&~=af ax=0xff0a -> ax=0xfe04 efl&|=cf,pe,af,nz,pl,nv
2042 * @optest amd / efl&~=af ax=0xff0a -> ax=0xfe04 efl&|=cf,pe,af,nz,ng,nv
2043 * @optest intel / efl&~=af ax=0xff09 -> ax=0xff09 efl&|=nc,po,na,nz,pl,nv
2044 * @optest amd / efl&~=af ax=0xff09 -> ax=0xff09 efl&|=nc,po,na,nz,ng,nv
2045 * @optest intel / efl&~=af ax=0x000b -> ax=0xff05 efl&|=cf,po,af,nz,pl,nv
2046 * @optest amd / efl&~=af ax=0x000b -> ax=0xff05 efl&|=cf,po,af,nz,ng,nv
2047 * @optest intel / efl&~=af ax=0x000c -> ax=0xff06 efl&|=cf,po,af,nz,pl,nv
2048 * @optest amd / efl&~=af ax=0x000c -> ax=0xff06 efl&|=cf,po,af,nz,ng,nv
2049 * @optest intel / efl&~=af ax=0x000d -> ax=0xff07 efl&|=cf,pe,af,nz,pl,nv
2050 * @optest amd / efl&~=af ax=0x000d -> ax=0xff07 efl&|=cf,pe,af,nz,ng,nv
2051 * @optest intel / efl&~=af ax=0x000e -> ax=0xff08 efl&|=cf,pe,af,nz,pl,nv
2052 * @optest amd / efl&~=af ax=0x000e -> ax=0xff08 efl&|=cf,pe,af,nz,ng,nv
2053 * @optest intel / efl&~=af ax=0x000f -> ax=0xff09 efl&|=cf,po,af,nz,pl,nv
2054 * @optest amd / efl&~=af ax=0x000f -> ax=0xff09 efl&|=cf,po,af,nz,ng,nv
2055 * @optest intel / efl&~=af ax=0x00fa -> ax=0xff04 efl&|=cf,pe,af,nz,pl,nv
2056 * @optest amd / efl&~=af ax=0x00fa -> ax=0xff04 efl&|=cf,pe,af,nz,ng,nv
2057 * @optest intel / efl&~=af ax=0xfffa -> ax=0xfe04 efl&|=cf,pe,af,nz,pl,nv
2058 * @optest amd / efl&~=af ax=0xfffa -> ax=0xfe04 efl&|=cf,pe,af,nz,ng,nv
2059 */
2060FNIEMOP_DEF(iemOp_aas)
2061{
2062 IEMOP_MNEMONIC0(FIXED, AAS, aas, DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64, 0); /* express implicit AL/AX register use */
2063 IEMOP_HLP_NO_64BIT();
2064 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2065 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF | X86_EFL_OF);
2066
2067 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_STATUS_FLAGS, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX), iemCImpl_aas);
2068}
2069
2070
2071/**
2072 * Common 'inc/dec register' helper.
2073 *
2074 * Not for 64-bit code, only for what became the rex prefixes.
2075 */
2076#define IEMOP_BODY_UNARY_GReg(a_fnNormalU16, a_fnNormalU32, a_iReg) \
2077 switch (pVCpu->iem.s.enmEffOpSize) \
2078 { \
2079 case IEMMODE_16BIT: \
2080 IEM_MC_BEGIN(2, 0, IEM_MC_F_NOT_64BIT, 0); \
2081 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
2082 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
2083 IEM_MC_ARG(uint32_t *, pEFlags, 1); \
2084 IEM_MC_REF_GREG_U16(pu16Dst, a_iReg); \
2085 IEM_MC_REF_EFLAGS(pEFlags); \
2086 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU16, pu16Dst, pEFlags); \
2087 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
2088 IEM_MC_END(); \
2089 break; \
2090 \
2091 case IEMMODE_32BIT: \
2092 IEM_MC_BEGIN(2, 0, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT, 0); \
2093 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
2094 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
2095 IEM_MC_ARG(uint32_t *, pEFlags, 1); \
2096 IEM_MC_REF_GREG_U32(pu32Dst, a_iReg); \
2097 IEM_MC_REF_EFLAGS(pEFlags); \
2098 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU32, pu32Dst, pEFlags); \
2099 IEM_MC_CLEAR_HIGH_GREG_U64(a_iReg); \
2100 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
2101 IEM_MC_END(); \
2102 break; \
2103 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
2104 } \
2105 (void)0
2106
2107/**
2108 * @opcode 0x40
2109 * @opflclass incdec
2110 */
2111FNIEMOP_DEF(iemOp_inc_eAX)
2112{
2113 /*
2114 * This is a REX prefix in 64-bit mode.
2115 */
2116 if (IEM_IS_64BIT_CODE(pVCpu))
2117 {
2118 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex");
2119 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX;
2120
2121 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2122 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2123 }
2124
2125 IEMOP_MNEMONIC(inc_eAX, "inc eAX");
2126 IEMOP_BODY_UNARY_GReg(iemAImpl_inc_u16, iemAImpl_inc_u32, X86_GREG_xAX);
2127}
2128
2129
2130/**
2131 * @opcode 0x41
2132 * @opflclass incdec
2133 */
2134FNIEMOP_DEF(iemOp_inc_eCX)
2135{
2136 /*
2137 * This is a REX prefix in 64-bit mode.
2138 */
2139 if (IEM_IS_64BIT_CODE(pVCpu))
2140 {
2141 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.b");
2142 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_B;
2143 pVCpu->iem.s.uRexB = 1 << 3;
2144
2145 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2146 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2147 }
2148
2149 IEMOP_MNEMONIC(inc_eCX, "inc eCX");
2150 IEMOP_BODY_UNARY_GReg(iemAImpl_inc_u16, iemAImpl_inc_u32, X86_GREG_xCX);
2151}
2152
2153
2154/**
2155 * @opcode 0x42
2156 * @opflclass incdec
2157 */
2158FNIEMOP_DEF(iemOp_inc_eDX)
2159{
2160 /*
2161 * This is a REX prefix in 64-bit mode.
2162 */
2163 if (IEM_IS_64BIT_CODE(pVCpu))
2164 {
2165 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.x");
2166 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_X;
2167 pVCpu->iem.s.uRexIndex = 1 << 3;
2168
2169 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2170 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2171 }
2172
2173 IEMOP_MNEMONIC(inc_eDX, "inc eDX");
2174 IEMOP_BODY_UNARY_GReg(iemAImpl_inc_u16, iemAImpl_inc_u32, X86_GREG_xDX);
2175}
2176
2177
2178
2179/**
2180 * @opcode 0x43
2181 * @opflclass incdec
2182 */
2183FNIEMOP_DEF(iemOp_inc_eBX)
2184{
2185 /*
2186 * This is a REX prefix in 64-bit mode.
2187 */
2188 if (IEM_IS_64BIT_CODE(pVCpu))
2189 {
2190 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.bx");
2191 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_B | IEM_OP_PRF_REX_X;
2192 pVCpu->iem.s.uRexB = 1 << 3;
2193 pVCpu->iem.s.uRexIndex = 1 << 3;
2194
2195 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2196 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2197 }
2198
2199 IEMOP_MNEMONIC(inc_eBX, "inc eBX");
2200 IEMOP_BODY_UNARY_GReg(iemAImpl_inc_u16, iemAImpl_inc_u32, X86_GREG_xBX);
2201}
2202
2203
2204/**
2205 * @opcode 0x44
2206 * @opflclass incdec
2207 */
2208FNIEMOP_DEF(iemOp_inc_eSP)
2209{
2210 /*
2211 * This is a REX prefix in 64-bit mode.
2212 */
2213 if (IEM_IS_64BIT_CODE(pVCpu))
2214 {
2215 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.r");
2216 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_R;
2217 pVCpu->iem.s.uRexReg = 1 << 3;
2218
2219 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2220 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2221 }
2222
2223 IEMOP_MNEMONIC(inc_eSP, "inc eSP");
2224 IEMOP_BODY_UNARY_GReg(iemAImpl_inc_u16, iemAImpl_inc_u32, X86_GREG_xSP);
2225}
2226
2227
2228/**
2229 * @opcode 0x45
2230 * @opflclass incdec
2231 */
2232FNIEMOP_DEF(iemOp_inc_eBP)
2233{
2234 /*
2235 * This is a REX prefix in 64-bit mode.
2236 */
2237 if (IEM_IS_64BIT_CODE(pVCpu))
2238 {
2239 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.rb");
2240 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_R | IEM_OP_PRF_REX_B;
2241 pVCpu->iem.s.uRexReg = 1 << 3;
2242 pVCpu->iem.s.uRexB = 1 << 3;
2243
2244 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2245 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2246 }
2247
2248 IEMOP_MNEMONIC(inc_eBP, "inc eBP");
2249 IEMOP_BODY_UNARY_GReg(iemAImpl_inc_u16, iemAImpl_inc_u32, X86_GREG_xBP);
2250}
2251
2252
2253/**
2254 * @opcode 0x46
2255 * @opflclass incdec
2256 */
2257FNIEMOP_DEF(iemOp_inc_eSI)
2258{
2259 /*
2260 * This is a REX prefix in 64-bit mode.
2261 */
2262 if (IEM_IS_64BIT_CODE(pVCpu))
2263 {
2264 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.rx");
2265 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_R | IEM_OP_PRF_REX_X;
2266 pVCpu->iem.s.uRexReg = 1 << 3;
2267 pVCpu->iem.s.uRexIndex = 1 << 3;
2268
2269 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2270 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2271 }
2272
2273 IEMOP_MNEMONIC(inc_eSI, "inc eSI");
2274 IEMOP_BODY_UNARY_GReg(iemAImpl_inc_u16, iemAImpl_inc_u32, X86_GREG_xSI);
2275}
2276
2277
2278/**
2279 * @opcode 0x47
2280 * @opflclass incdec
2281 */
2282FNIEMOP_DEF(iemOp_inc_eDI)
2283{
2284 /*
2285 * This is a REX prefix in 64-bit mode.
2286 */
2287 if (IEM_IS_64BIT_CODE(pVCpu))
2288 {
2289 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.rbx");
2290 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_R | IEM_OP_PRF_REX_B | IEM_OP_PRF_REX_X;
2291 pVCpu->iem.s.uRexReg = 1 << 3;
2292 pVCpu->iem.s.uRexB = 1 << 3;
2293 pVCpu->iem.s.uRexIndex = 1 << 3;
2294
2295 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2296 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2297 }
2298
2299 IEMOP_MNEMONIC(inc_eDI, "inc eDI");
2300 IEMOP_BODY_UNARY_GReg(iemAImpl_inc_u16, iemAImpl_inc_u32, X86_GREG_xDI);
2301}
2302
2303
2304/**
2305 * @opcode 0x48
2306 * @opflclass incdec
2307 */
2308FNIEMOP_DEF(iemOp_dec_eAX)
2309{
2310 /*
2311 * This is a REX prefix in 64-bit mode.
2312 */
2313 if (IEM_IS_64BIT_CODE(pVCpu))
2314 {
2315 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.w");
2316 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_SIZE_REX_W;
2317 iemRecalEffOpSize(pVCpu);
2318
2319 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2320 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2321 }
2322
2323 IEMOP_MNEMONIC(dec_eAX, "dec eAX");
2324 IEMOP_BODY_UNARY_GReg(iemAImpl_dec_u16, iemAImpl_dec_u32, X86_GREG_xAX);
2325}
2326
2327
2328/**
2329 * @opcode 0x49
2330 * @opflclass incdec
2331 */
2332FNIEMOP_DEF(iemOp_dec_eCX)
2333{
2334 /*
2335 * This is a REX prefix in 64-bit mode.
2336 */
2337 if (IEM_IS_64BIT_CODE(pVCpu))
2338 {
2339 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.bw");
2340 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_B | IEM_OP_PRF_SIZE_REX_W;
2341 pVCpu->iem.s.uRexB = 1 << 3;
2342 iemRecalEffOpSize(pVCpu);
2343
2344 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2345 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2346 }
2347
2348 IEMOP_MNEMONIC(dec_eCX, "dec eCX");
2349 IEMOP_BODY_UNARY_GReg(iemAImpl_dec_u16, iemAImpl_dec_u32, X86_GREG_xCX);
2350}
2351
2352
2353/**
2354 * @opcode 0x4a
2355 * @opflclass incdec
2356 */
2357FNIEMOP_DEF(iemOp_dec_eDX)
2358{
2359 /*
2360 * This is a REX prefix in 64-bit mode.
2361 */
2362 if (IEM_IS_64BIT_CODE(pVCpu))
2363 {
2364 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.xw");
2365 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_X | IEM_OP_PRF_SIZE_REX_W;
2366 pVCpu->iem.s.uRexIndex = 1 << 3;
2367 iemRecalEffOpSize(pVCpu);
2368
2369 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2370 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2371 }
2372
2373 IEMOP_MNEMONIC(dec_eDX, "dec eDX");
2374 IEMOP_BODY_UNARY_GReg(iemAImpl_dec_u16, iemAImpl_dec_u32, X86_GREG_xDX);
2375}
2376
2377
2378/**
2379 * @opcode 0x4b
2380 * @opflclass incdec
2381 */
2382FNIEMOP_DEF(iemOp_dec_eBX)
2383{
2384 /*
2385 * This is a REX prefix in 64-bit mode.
2386 */
2387 if (IEM_IS_64BIT_CODE(pVCpu))
2388 {
2389 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.bxw");
2390 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_B | IEM_OP_PRF_REX_X | IEM_OP_PRF_SIZE_REX_W;
2391 pVCpu->iem.s.uRexB = 1 << 3;
2392 pVCpu->iem.s.uRexIndex = 1 << 3;
2393 iemRecalEffOpSize(pVCpu);
2394
2395 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2396 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2397 }
2398
2399 IEMOP_MNEMONIC(dec_eBX, "dec eBX");
2400 IEMOP_BODY_UNARY_GReg(iemAImpl_dec_u16, iemAImpl_dec_u32, X86_GREG_xBX);
2401}
2402
2403
2404/**
2405 * @opcode 0x4c
2406 * @opflclass incdec
2407 */
2408FNIEMOP_DEF(iemOp_dec_eSP)
2409{
2410 /*
2411 * This is a REX prefix in 64-bit mode.
2412 */
2413 if (IEM_IS_64BIT_CODE(pVCpu))
2414 {
2415 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.rw");
2416 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_R | IEM_OP_PRF_SIZE_REX_W;
2417 pVCpu->iem.s.uRexReg = 1 << 3;
2418 iemRecalEffOpSize(pVCpu);
2419
2420 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2421 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2422 }
2423
2424 IEMOP_MNEMONIC(dec_eSP, "dec eSP");
2425 IEMOP_BODY_UNARY_GReg(iemAImpl_dec_u16, iemAImpl_dec_u32, X86_GREG_xSP);
2426}
2427
2428
2429/**
2430 * @opcode 0x4d
2431 * @opflclass incdec
2432 */
2433FNIEMOP_DEF(iemOp_dec_eBP)
2434{
2435 /*
2436 * This is a REX prefix in 64-bit mode.
2437 */
2438 if (IEM_IS_64BIT_CODE(pVCpu))
2439 {
2440 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.rbw");
2441 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_R | IEM_OP_PRF_REX_B | IEM_OP_PRF_SIZE_REX_W;
2442 pVCpu->iem.s.uRexReg = 1 << 3;
2443 pVCpu->iem.s.uRexB = 1 << 3;
2444 iemRecalEffOpSize(pVCpu);
2445
2446 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2447 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2448 }
2449
2450 IEMOP_MNEMONIC(dec_eBP, "dec eBP");
2451 IEMOP_BODY_UNARY_GReg(iemAImpl_dec_u16, iemAImpl_dec_u32, X86_GREG_xBP);
2452}
2453
2454
2455/**
2456 * @opcode 0x4e
2457 * @opflclass incdec
2458 */
2459FNIEMOP_DEF(iemOp_dec_eSI)
2460{
2461 /*
2462 * This is a REX prefix in 64-bit mode.
2463 */
2464 if (IEM_IS_64BIT_CODE(pVCpu))
2465 {
2466 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.rxw");
2467 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_R | IEM_OP_PRF_REX_X | IEM_OP_PRF_SIZE_REX_W;
2468 pVCpu->iem.s.uRexReg = 1 << 3;
2469 pVCpu->iem.s.uRexIndex = 1 << 3;
2470 iemRecalEffOpSize(pVCpu);
2471
2472 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2473 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2474 }
2475
2476 IEMOP_MNEMONIC(dec_eSI, "dec eSI");
2477 IEMOP_BODY_UNARY_GReg(iemAImpl_dec_u16, iemAImpl_dec_u32, X86_GREG_xSI);
2478}
2479
2480
2481/**
2482 * @opcode 0x4f
2483 * @opflclass incdec
2484 */
2485FNIEMOP_DEF(iemOp_dec_eDI)
2486{
2487 /*
2488 * This is a REX prefix in 64-bit mode.
2489 */
2490 if (IEM_IS_64BIT_CODE(pVCpu))
2491 {
2492 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("rex.rbxw");
2493 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REX | IEM_OP_PRF_REX_R | IEM_OP_PRF_REX_B | IEM_OP_PRF_REX_X | IEM_OP_PRF_SIZE_REX_W;
2494 pVCpu->iem.s.uRexReg = 1 << 3;
2495 pVCpu->iem.s.uRexB = 1 << 3;
2496 pVCpu->iem.s.uRexIndex = 1 << 3;
2497 iemRecalEffOpSize(pVCpu);
2498
2499 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
2500 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
2501 }
2502
2503 IEMOP_MNEMONIC(dec_eDI, "dec eDI");
2504 IEMOP_BODY_UNARY_GReg(iemAImpl_dec_u16, iemAImpl_dec_u32, X86_GREG_xDI);
2505}
2506
2507
2508/**
2509 * Common 'push register' helper.
2510 */
2511FNIEMOP_DEF_1(iemOpCommonPushGReg, uint8_t, iReg)
2512{
2513 if (IEM_IS_64BIT_CODE(pVCpu))
2514 {
2515 iReg |= pVCpu->iem.s.uRexB;
2516 pVCpu->iem.s.enmDefOpSize = IEMMODE_64BIT;
2517 pVCpu->iem.s.enmEffOpSize = !(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_OP) ? IEMMODE_64BIT : IEMMODE_16BIT;
2518 }
2519
2520 switch (pVCpu->iem.s.enmEffOpSize)
2521 {
2522 case IEMMODE_16BIT:
2523 IEM_MC_BEGIN(0, 1, 0, 0);
2524 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2525 IEM_MC_LOCAL(uint16_t, u16Value);
2526 IEM_MC_FETCH_GREG_U16(u16Value, iReg);
2527 IEM_MC_PUSH_U16(u16Value);
2528 IEM_MC_ADVANCE_RIP_AND_FINISH();
2529 IEM_MC_END();
2530 break;
2531
2532 case IEMMODE_32BIT:
2533 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT, 0);
2534 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2535 IEM_MC_LOCAL(uint32_t, u32Value);
2536 IEM_MC_FETCH_GREG_U32(u32Value, iReg);
2537 IEM_MC_PUSH_U32(u32Value);
2538 IEM_MC_ADVANCE_RIP_AND_FINISH();
2539 IEM_MC_END();
2540 break;
2541
2542 case IEMMODE_64BIT:
2543 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
2544 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2545 IEM_MC_LOCAL(uint64_t, u64Value);
2546 IEM_MC_FETCH_GREG_U64(u64Value, iReg);
2547 IEM_MC_PUSH_U64(u64Value);
2548 IEM_MC_ADVANCE_RIP_AND_FINISH();
2549 IEM_MC_END();
2550 break;
2551
2552 IEM_NOT_REACHED_DEFAULT_CASE_RET();
2553 }
2554}
2555
2556
2557/**
2558 * @opcode 0x50
2559 */
2560FNIEMOP_DEF(iemOp_push_eAX)
2561{
2562 IEMOP_MNEMONIC(push_rAX, "push rAX");
2563 return FNIEMOP_CALL_1(iemOpCommonPushGReg, X86_GREG_xAX);
2564}
2565
2566
2567/**
2568 * @opcode 0x51
2569 */
2570FNIEMOP_DEF(iemOp_push_eCX)
2571{
2572 IEMOP_MNEMONIC(push_rCX, "push rCX");
2573 return FNIEMOP_CALL_1(iemOpCommonPushGReg, X86_GREG_xCX);
2574}
2575
2576
2577/**
2578 * @opcode 0x52
2579 */
2580FNIEMOP_DEF(iemOp_push_eDX)
2581{
2582 IEMOP_MNEMONIC(push_rDX, "push rDX");
2583 return FNIEMOP_CALL_1(iemOpCommonPushGReg, X86_GREG_xDX);
2584}
2585
2586
2587/**
2588 * @opcode 0x53
2589 */
2590FNIEMOP_DEF(iemOp_push_eBX)
2591{
2592 IEMOP_MNEMONIC(push_rBX, "push rBX");
2593 return FNIEMOP_CALL_1(iemOpCommonPushGReg, X86_GREG_xBX);
2594}
2595
2596
2597/**
2598 * @opcode 0x54
2599 */
2600FNIEMOP_DEF(iemOp_push_eSP)
2601{
2602 IEMOP_MNEMONIC(push_rSP, "push rSP");
2603 if (IEM_GET_TARGET_CPU(pVCpu) != IEMTARGETCPU_8086)
2604 return FNIEMOP_CALL_1(iemOpCommonPushGReg, X86_GREG_xSP);
2605
2606 /* 8086 works differently wrt to 'push sp' compared to 80186 and later. */
2607 IEM_MC_BEGIN(0, 1, IEM_MC_F_ONLY_8086, 0);
2608 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2609 IEM_MC_LOCAL(uint16_t, u16Value);
2610 IEM_MC_FETCH_GREG_U16(u16Value, X86_GREG_xSP);
2611 IEM_MC_SUB_LOCAL_U16(u16Value, 2);
2612 IEM_MC_PUSH_U16(u16Value);
2613 IEM_MC_ADVANCE_RIP_AND_FINISH();
2614 IEM_MC_END();
2615}
2616
2617
2618/**
2619 * @opcode 0x55
2620 */
2621FNIEMOP_DEF(iemOp_push_eBP)
2622{
2623 IEMOP_MNEMONIC(push_rBP, "push rBP");
2624 return FNIEMOP_CALL_1(iemOpCommonPushGReg, X86_GREG_xBP);
2625}
2626
2627
2628/**
2629 * @opcode 0x56
2630 */
2631FNIEMOP_DEF(iemOp_push_eSI)
2632{
2633 IEMOP_MNEMONIC(push_rSI, "push rSI");
2634 return FNIEMOP_CALL_1(iemOpCommonPushGReg, X86_GREG_xSI);
2635}
2636
2637
2638/**
2639 * @opcode 0x57
2640 */
2641FNIEMOP_DEF(iemOp_push_eDI)
2642{
2643 IEMOP_MNEMONIC(push_rDI, "push rDI");
2644 return FNIEMOP_CALL_1(iemOpCommonPushGReg, X86_GREG_xDI);
2645}
2646
2647
2648/**
2649 * Common 'pop register' helper.
2650 */
2651FNIEMOP_DEF_1(iemOpCommonPopGReg, uint8_t, iReg)
2652{
2653 if (IEM_IS_64BIT_CODE(pVCpu))
2654 {
2655 iReg |= pVCpu->iem.s.uRexB;
2656 pVCpu->iem.s.enmDefOpSize = IEMMODE_64BIT;
2657 pVCpu->iem.s.enmEffOpSize = !(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_OP) ? IEMMODE_64BIT : IEMMODE_16BIT;
2658 }
2659
2660 switch (pVCpu->iem.s.enmEffOpSize)
2661 {
2662 case IEMMODE_16BIT:
2663 IEM_MC_BEGIN(0, 0, 0, 0);
2664 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2665 IEM_MC_POP_GREG_U16(iReg);
2666 IEM_MC_ADVANCE_RIP_AND_FINISH();
2667 IEM_MC_END();
2668 break;
2669
2670 case IEMMODE_32BIT:
2671 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT, 0);
2672 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2673 IEM_MC_POP_GREG_U32(iReg);
2674 IEM_MC_ADVANCE_RIP_AND_FINISH();
2675 IEM_MC_END();
2676 break;
2677
2678 case IEMMODE_64BIT:
2679 IEM_MC_BEGIN(0, 0, IEM_MC_F_64BIT, 0);
2680 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2681 IEM_MC_POP_GREG_U64(iReg);
2682 IEM_MC_ADVANCE_RIP_AND_FINISH();
2683 IEM_MC_END();
2684 break;
2685
2686 IEM_NOT_REACHED_DEFAULT_CASE_RET();
2687 }
2688}
2689
2690
2691/**
2692 * @opcode 0x58
2693 */
2694FNIEMOP_DEF(iemOp_pop_eAX)
2695{
2696 IEMOP_MNEMONIC(pop_rAX, "pop rAX");
2697 return FNIEMOP_CALL_1(iemOpCommonPopGReg, X86_GREG_xAX);
2698}
2699
2700
2701/**
2702 * @opcode 0x59
2703 */
2704FNIEMOP_DEF(iemOp_pop_eCX)
2705{
2706 IEMOP_MNEMONIC(pop_rCX, "pop rCX");
2707 return FNIEMOP_CALL_1(iemOpCommonPopGReg, X86_GREG_xCX);
2708}
2709
2710
2711/**
2712 * @opcode 0x5a
2713 */
2714FNIEMOP_DEF(iemOp_pop_eDX)
2715{
2716 IEMOP_MNEMONIC(pop_rDX, "pop rDX");
2717 return FNIEMOP_CALL_1(iemOpCommonPopGReg, X86_GREG_xDX);
2718}
2719
2720
2721/**
2722 * @opcode 0x5b
2723 */
2724FNIEMOP_DEF(iemOp_pop_eBX)
2725{
2726 IEMOP_MNEMONIC(pop_rBX, "pop rBX");
2727 return FNIEMOP_CALL_1(iemOpCommonPopGReg, X86_GREG_xBX);
2728}
2729
2730
2731/**
2732 * @opcode 0x5c
2733 */
2734FNIEMOP_DEF(iemOp_pop_eSP)
2735{
2736 IEMOP_MNEMONIC(pop_rSP, "pop rSP");
2737 return FNIEMOP_CALL_1(iemOpCommonPopGReg, X86_GREG_xSP);
2738}
2739
2740
2741/**
2742 * @opcode 0x5d
2743 */
2744FNIEMOP_DEF(iemOp_pop_eBP)
2745{
2746 IEMOP_MNEMONIC(pop_rBP, "pop rBP");
2747 return FNIEMOP_CALL_1(iemOpCommonPopGReg, X86_GREG_xBP);
2748}
2749
2750
2751/**
2752 * @opcode 0x5e
2753 */
2754FNIEMOP_DEF(iemOp_pop_eSI)
2755{
2756 IEMOP_MNEMONIC(pop_rSI, "pop rSI");
2757 return FNIEMOP_CALL_1(iemOpCommonPopGReg, X86_GREG_xSI);
2758}
2759
2760
2761/**
2762 * @opcode 0x5f
2763 */
2764FNIEMOP_DEF(iemOp_pop_eDI)
2765{
2766 IEMOP_MNEMONIC(pop_rDI, "pop rDI");
2767 return FNIEMOP_CALL_1(iemOpCommonPopGReg, X86_GREG_xDI);
2768}
2769
2770
2771/**
2772 * @opcode 0x60
2773 */
2774FNIEMOP_DEF(iemOp_pusha)
2775{
2776 IEMOP_MNEMONIC(pusha, "pusha");
2777 IEMOP_HLP_MIN_186();
2778 IEMOP_HLP_NO_64BIT();
2779 if (pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT)
2780 IEM_MC_DEFER_TO_CIMPL_0_RET(0, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_pusha_16);
2781 Assert(pVCpu->iem.s.enmEffOpSize == IEMMODE_32BIT);
2782 IEM_MC_DEFER_TO_CIMPL_0_RET(0, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_pusha_32);
2783}
2784
2785
2786/**
2787 * @opcode 0x61
2788 */
2789FNIEMOP_DEF(iemOp_popa__mvex)
2790{
2791 if (!IEM_IS_64BIT_CODE(pVCpu))
2792 {
2793 IEMOP_MNEMONIC(popa, "popa");
2794 IEMOP_HLP_MIN_186();
2795 IEMOP_HLP_NO_64BIT();
2796 if (pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT)
2797 IEM_MC_DEFER_TO_CIMPL_0_RET(0,
2798 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
2799 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX)
2800 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDX)
2801 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xBX)
2802 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
2803 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xBP)
2804 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
2805 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
2806 iemCImpl_popa_16);
2807 Assert(pVCpu->iem.s.enmEffOpSize == IEMMODE_32BIT);
2808 IEM_MC_DEFER_TO_CIMPL_0_RET(0,
2809 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
2810 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX)
2811 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDX)
2812 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xBX)
2813 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
2814 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xBP)
2815 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
2816 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
2817 iemCImpl_popa_32);
2818 }
2819 IEMOP_MNEMONIC(mvex, "mvex");
2820 Log(("mvex prefix is not supported!\n"));
2821 IEMOP_RAISE_INVALID_OPCODE_RET();
2822}
2823
2824
2825/**
2826 * @opcode 0x62
2827 * @opmnemonic bound
2828 * @op1 Gv_RO
2829 * @op2 Ma
2830 * @opmincpu 80186
2831 * @ophints harmless x86_invalid_64
2832 * @optest op1=0 op2=0 ->
2833 * @optest op1=1 op2=0 -> value.xcpt=5
2834 * @optest o16 / op1=0xffff op2=0x0000fffe ->
2835 * @optest o16 / op1=0xfffe op2=0x0000fffe ->
2836 * @optest o16 / op1=0x7fff op2=0x0000fffe -> value.xcpt=5
2837 * @optest o16 / op1=0x7fff op2=0x7ffffffe ->
2838 * @optest o16 / op1=0x7fff op2=0xfffe8000 -> value.xcpt=5
2839 * @optest o16 / op1=0x8000 op2=0xfffe8000 ->
2840 * @optest o16 / op1=0xffff op2=0xfffe8000 -> value.xcpt=5
2841 * @optest o16 / op1=0xfffe op2=0xfffe8000 ->
2842 * @optest o16 / op1=0xfffe op2=0x8000fffe -> value.xcpt=5
2843 * @optest o16 / op1=0x8000 op2=0x8000fffe -> value.xcpt=5
2844 * @optest o16 / op1=0x0000 op2=0x8000fffe -> value.xcpt=5
2845 * @optest o16 / op1=0x0001 op2=0x8000fffe -> value.xcpt=5
2846 * @optest o16 / op1=0xffff op2=0x0001000f -> value.xcpt=5
2847 * @optest o16 / op1=0x0000 op2=0x0001000f -> value.xcpt=5
2848 * @optest o16 / op1=0x0001 op2=0x0001000f -> value.xcpt=5
2849 * @optest o16 / op1=0x0002 op2=0x0001000f -> value.xcpt=5
2850 * @optest o16 / op1=0x0003 op2=0x0001000f -> value.xcpt=5
2851 * @optest o16 / op1=0x0004 op2=0x0001000f -> value.xcpt=5
2852 * @optest o16 / op1=0x000e op2=0x0001000f -> value.xcpt=5
2853 * @optest o16 / op1=0x000f op2=0x0001000f -> value.xcpt=5
2854 * @optest o16 / op1=0x0010 op2=0x0001000f -> value.xcpt=5
2855 * @optest o16 / op1=0x0011 op2=0x0001000f -> value.xcpt=5
2856 * @optest o32 / op1=0xffffffff op2=0x00000000fffffffe ->
2857 * @optest o32 / op1=0xfffffffe op2=0x00000000fffffffe ->
2858 * @optest o32 / op1=0x7fffffff op2=0x00000000fffffffe -> value.xcpt=5
2859 * @optest o32 / op1=0x7fffffff op2=0x7ffffffffffffffe ->
2860 * @optest o32 / op1=0x7fffffff op2=0xfffffffe80000000 -> value.xcpt=5
2861 * @optest o32 / op1=0x80000000 op2=0xfffffffe80000000 ->
2862 * @optest o32 / op1=0xffffffff op2=0xfffffffe80000000 -> value.xcpt=5
2863 * @optest o32 / op1=0xfffffffe op2=0xfffffffe80000000 ->
2864 * @optest o32 / op1=0xfffffffe op2=0x80000000fffffffe -> value.xcpt=5
2865 * @optest o32 / op1=0x80000000 op2=0x80000000fffffffe -> value.xcpt=5
2866 * @optest o32 / op1=0x00000000 op2=0x80000000fffffffe -> value.xcpt=5
2867 * @optest o32 / op1=0x00000002 op2=0x80000000fffffffe -> value.xcpt=5
2868 * @optest o32 / op1=0x00000001 op2=0x0000000100000003 -> value.xcpt=5
2869 * @optest o32 / op1=0x00000002 op2=0x0000000100000003 -> value.xcpt=5
2870 * @optest o32 / op1=0x00000003 op2=0x0000000100000003 -> value.xcpt=5
2871 * @optest o32 / op1=0x00000004 op2=0x0000000100000003 -> value.xcpt=5
2872 * @optest o32 / op1=0x00000005 op2=0x0000000100000003 -> value.xcpt=5
2873 * @optest o32 / op1=0x0000000e op2=0x0000000100000003 -> value.xcpt=5
2874 * @optest o32 / op1=0x0000000f op2=0x0000000100000003 -> value.xcpt=5
2875 * @optest o32 / op1=0x00000010 op2=0x0000000100000003 -> value.xcpt=5
2876 */
2877FNIEMOP_DEF(iemOp_bound_Gv_Ma__evex)
2878{
2879 /* The BOUND instruction is invalid 64-bit mode. In legacy and
2880 compatability mode it is invalid with MOD=3.
2881
2882 In 32-bit mode, the EVEX prefix works by having the top two bits (MOD)
2883 both be set. In the Intel EVEX documentation (sdm vol 2) these are simply
2884 given as R and X without an exact description, so we assume it builds on
2885 the VEX one and means they are inverted wrt REX.R and REX.X. Thus, just
2886 like with the 3-byte VEX, 32-bit code is restrict wrt addressable registers. */
2887 uint8_t bRm;
2888 if (!IEM_IS_64BIT_CODE(pVCpu))
2889 {
2890 IEMOP_MNEMONIC2(RM_MEM, BOUND, bound, Gv_RO, Ma, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
2891 IEMOP_HLP_MIN_186();
2892 IEM_OPCODE_GET_NEXT_U8(&bRm);
2893 if (IEM_IS_MODRM_MEM_MODE(bRm))
2894 {
2895 /** @todo testcase: check that there are two memory accesses involved. Check
2896 * whether they're both read before the \#BR triggers. */
2897 if (pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT)
2898 {
2899 IEM_MC_BEGIN(3, 1, IEM_MC_F_MIN_186 | IEM_MC_F_NOT_64BIT, 0);
2900 IEM_MC_ARG(uint16_t, u16Index, 0); /* Note! All operands are actually signed. Lazy unsigned bird. */
2901 IEM_MC_ARG(uint16_t, u16LowerBounds, 1);
2902 IEM_MC_ARG(uint16_t, u16UpperBounds, 2);
2903 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
2904
2905 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
2906 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2907
2908 IEM_MC_FETCH_GREG_U16(u16Index, IEM_GET_MODRM_REG_8(bRm));
2909 IEM_MC_FETCH_MEM_U16(u16LowerBounds, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
2910 IEM_MC_FETCH_MEM_U16_DISP(u16UpperBounds, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, 2);
2911
2912 IEM_MC_CALL_CIMPL_3(0, 0, iemCImpl_bound_16, u16Index, u16LowerBounds, u16UpperBounds); /* returns */
2913 IEM_MC_END();
2914 }
2915 else /* 32-bit operands */
2916 {
2917 IEM_MC_BEGIN(3, 1, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT, 0);
2918 IEM_MC_ARG(uint32_t, u32Index, 0); /* Note! All operands are actually signed. Lazy unsigned bird. */
2919 IEM_MC_ARG(uint32_t, u32LowerBounds, 1);
2920 IEM_MC_ARG(uint32_t, u32UpperBounds, 2);
2921 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
2922
2923 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
2924 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
2925
2926 IEM_MC_FETCH_GREG_U32(u32Index, IEM_GET_MODRM_REG_8(bRm));
2927 IEM_MC_FETCH_MEM_U32(u32LowerBounds, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
2928 IEM_MC_FETCH_MEM_U32_DISP(u32UpperBounds, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, 4);
2929
2930 IEM_MC_CALL_CIMPL_3(0, 0, iemCImpl_bound_32, u32Index, u32LowerBounds, u32UpperBounds); /* returns */
2931 IEM_MC_END();
2932 }
2933 }
2934
2935 /*
2936 * @opdone
2937 */
2938 if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fAvx512Foundation)
2939 {
2940 /* Note that there is no need for the CPU to fetch further bytes
2941 here because MODRM.MOD == 3. */
2942 Log(("evex not supported by the guest CPU!\n"));
2943 IEMOP_RAISE_INVALID_OPCODE_RET();
2944 }
2945 }
2946 else
2947 {
2948 /** @todo check how this is decoded in 64-bit mode w/o EVEX. Intel probably
2949 * does modr/m read, whereas AMD probably doesn't... */
2950 if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fAvx512Foundation)
2951 {
2952 Log(("evex not supported by the guest CPU!\n"));
2953 return FNIEMOP_CALL(iemOp_InvalidAllNeedRM);
2954 }
2955 IEM_OPCODE_GET_NEXT_U8(&bRm);
2956 }
2957
2958 IEMOP_MNEMONIC(evex, "evex");
2959 uint8_t bP2; IEM_OPCODE_GET_NEXT_U8(&bP2);
2960 uint8_t bP3; IEM_OPCODE_GET_NEXT_U8(&bP3);
2961 Log(("evex prefix is not implemented!\n"));
2962 return VERR_IEM_INSTR_NOT_IMPLEMENTED;
2963}
2964
2965
2966/**
2967 * @opcode 0x63
2968 * @opflmodify zf
2969 * @note non-64-bit modes.
2970 */
2971FNIEMOP_DEF(iemOp_arpl_Ew_Gw)
2972{
2973 IEMOP_MNEMONIC(arpl_Ew_Gw, "arpl Ew,Gw");
2974 IEMOP_HLP_MIN_286();
2975 IEMOP_HLP_NO_REAL_OR_V86_MODE();
2976 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
2977
2978 if (IEM_IS_MODRM_REG_MODE(bRm))
2979 {
2980 /* Register */
2981 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_286 | IEM_MC_F_NOT_64BIT, 0);
2982 IEMOP_HLP_DECODED_NL_2(OP_ARPL, IEMOPFORM_MR_REG, OP_PARM_Ew, OP_PARM_Gw, DISOPTYPE_HARMLESS);
2983 IEM_MC_ARG(uint16_t *, pu16Dst, 0);
2984 IEM_MC_ARG(uint16_t, u16Src, 1);
2985 IEM_MC_ARG(uint32_t *, pEFlags, 2);
2986
2987 IEM_MC_FETCH_GREG_U16(u16Src, IEM_GET_MODRM_REG_8(bRm));
2988 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_RM_8(bRm));
2989 IEM_MC_REF_EFLAGS(pEFlags);
2990 IEM_MC_CALL_VOID_AIMPL_3(iemAImpl_arpl, pu16Dst, u16Src, pEFlags);
2991
2992 IEM_MC_ADVANCE_RIP_AND_FINISH();
2993 IEM_MC_END();
2994 }
2995 else
2996 {
2997 /* Memory */
2998 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_286 | IEM_MC_F_NOT_64BIT, 0);
2999 IEM_MC_ARG(uint16_t *, pu16Dst, 0);
3000 IEM_MC_ARG(uint16_t, u16Src, 1);
3001 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2);
3002 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
3003 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
3004
3005 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
3006 IEMOP_HLP_DECODED_NL_2(OP_ARPL, IEMOPFORM_MR_REG, OP_PARM_Ew, OP_PARM_Gw, DISOPTYPE_HARMLESS);
3007 IEM_MC_MEM_MAP_U16_RW(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
3008 IEM_MC_FETCH_GREG_U16(u16Src, IEM_GET_MODRM_REG_8(bRm));
3009 IEM_MC_FETCH_EFLAGS(EFlags);
3010 IEM_MC_CALL_VOID_AIMPL_3(iemAImpl_arpl, pu16Dst, u16Src, pEFlags);
3011
3012 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo);
3013 IEM_MC_COMMIT_EFLAGS(EFlags);
3014 IEM_MC_ADVANCE_RIP_AND_FINISH();
3015 IEM_MC_END();
3016 }
3017}
3018
3019
3020/**
3021 * @opcode 0x63
3022 *
3023 * @note This is a weird one. It works like a regular move instruction if
3024 * REX.W isn't set, at least according to AMD docs (rev 3.15, 2009-11).
3025 * @todo This definitely needs a testcase to verify the odd cases. */
3026FNIEMOP_DEF(iemOp_movsxd_Gv_Ev)
3027{
3028 Assert(pVCpu->iem.s.enmEffOpSize == IEMMODE_64BIT); /* Caller branched already . */
3029
3030 IEMOP_MNEMONIC(movsxd_Gv_Ev, "movsxd Gv,Ev");
3031 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
3032
3033 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_REX_W)
3034 {
3035 if (IEM_IS_MODRM_REG_MODE(bRm))
3036 {
3037 /*
3038 * Register to register.
3039 */
3040 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
3041 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3042 IEM_MC_LOCAL(uint64_t, u64Value);
3043 IEM_MC_FETCH_GREG_U32_SX_U64(u64Value, IEM_GET_MODRM_RM(pVCpu, bRm));
3044 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), u64Value);
3045 IEM_MC_ADVANCE_RIP_AND_FINISH();
3046 IEM_MC_END();
3047 }
3048 else
3049 {
3050 /*
3051 * We're loading a register from memory.
3052 */
3053 IEM_MC_BEGIN(0, 2, IEM_MC_F_64BIT, 0);
3054 IEM_MC_LOCAL(uint64_t, u64Value);
3055 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
3056 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
3057 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3058 IEM_MC_FETCH_MEM_U32_SX_U64(u64Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
3059 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), u64Value);
3060 IEM_MC_ADVANCE_RIP_AND_FINISH();
3061 IEM_MC_END();
3062 }
3063 }
3064 else
3065 AssertFailedReturn(VERR_IEM_INSTR_NOT_IMPLEMENTED);
3066}
3067
3068
3069/**
3070 * @opcode 0x64
3071 * @opmnemonic segfs
3072 * @opmincpu 80386
3073 * @opgroup og_prefixes
3074 */
3075FNIEMOP_DEF(iemOp_seg_FS)
3076{
3077 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("seg fs");
3078 IEMOP_HLP_MIN_386();
3079
3080 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SEG_FS;
3081 pVCpu->iem.s.iEffSeg = X86_SREG_FS;
3082
3083 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
3084 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
3085}
3086
3087
3088/**
3089 * @opcode 0x65
3090 * @opmnemonic seggs
3091 * @opmincpu 80386
3092 * @opgroup og_prefixes
3093 */
3094FNIEMOP_DEF(iemOp_seg_GS)
3095{
3096 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("seg gs");
3097 IEMOP_HLP_MIN_386();
3098
3099 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SEG_GS;
3100 pVCpu->iem.s.iEffSeg = X86_SREG_GS;
3101
3102 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
3103 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
3104}
3105
3106
3107/**
3108 * @opcode 0x66
3109 * @opmnemonic opsize
3110 * @openc prefix
3111 * @opmincpu 80386
3112 * @ophints harmless
3113 * @opgroup og_prefixes
3114 */
3115FNIEMOP_DEF(iemOp_op_size)
3116{
3117 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("op size");
3118 IEMOP_HLP_MIN_386();
3119
3120 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SIZE_OP;
3121 iemRecalEffOpSize(pVCpu);
3122
3123 /* For the 4 entry opcode tables, the operand prefix doesn't not count
3124 when REPZ or REPNZ are present. */
3125 if (pVCpu->iem.s.idxPrefix == 0)
3126 pVCpu->iem.s.idxPrefix = 1;
3127
3128 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
3129 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
3130}
3131
3132
3133/**
3134 * @opcode 0x67
3135 * @opmnemonic addrsize
3136 * @openc prefix
3137 * @opmincpu 80386
3138 * @ophints harmless
3139 * @opgroup og_prefixes
3140 */
3141FNIEMOP_DEF(iemOp_addr_size)
3142{
3143 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("addr size");
3144 IEMOP_HLP_MIN_386();
3145
3146 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SIZE_ADDR;
3147 switch (pVCpu->iem.s.enmDefAddrMode)
3148 {
3149 case IEMMODE_16BIT: pVCpu->iem.s.enmEffAddrMode = IEMMODE_32BIT; break;
3150 case IEMMODE_32BIT: pVCpu->iem.s.enmEffAddrMode = IEMMODE_16BIT; break;
3151 case IEMMODE_64BIT: pVCpu->iem.s.enmEffAddrMode = IEMMODE_32BIT; break;
3152 default: AssertFailed();
3153 }
3154
3155 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
3156 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
3157}
3158
3159
3160/**
3161 * @opcode 0x68
3162 */
3163FNIEMOP_DEF(iemOp_push_Iz)
3164{
3165 IEMOP_MNEMONIC(push_Iz, "push Iz");
3166 IEMOP_HLP_MIN_186();
3167 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
3168 switch (pVCpu->iem.s.enmEffOpSize)
3169 {
3170 case IEMMODE_16BIT:
3171 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_186, 0);
3172 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm);
3173 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3174 IEM_MC_LOCAL_CONST(uint16_t, u16Value, u16Imm);
3175 IEM_MC_PUSH_U16(u16Value);
3176 IEM_MC_ADVANCE_RIP_AND_FINISH();
3177 IEM_MC_END();
3178 break;
3179
3180 case IEMMODE_32BIT:
3181 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT, 0);
3182 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm);
3183 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3184 IEM_MC_LOCAL_CONST(uint32_t, u32Value, u32Imm);
3185 IEM_MC_PUSH_U32(u32Value);
3186 IEM_MC_ADVANCE_RIP_AND_FINISH();
3187 IEM_MC_END();
3188 break;
3189
3190 case IEMMODE_64BIT:
3191 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
3192 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm);
3193 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3194 IEM_MC_LOCAL_CONST(uint64_t, u64Value, u64Imm);
3195 IEM_MC_PUSH_U64(u64Value);
3196 IEM_MC_ADVANCE_RIP_AND_FINISH();
3197 IEM_MC_END();
3198 break;
3199
3200 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3201 }
3202}
3203
3204
3205/**
3206 * @opcode 0x69
3207 * @opflclass multiply
3208 */
3209FNIEMOP_DEF(iemOp_imul_Gv_Ev_Iz)
3210{
3211 IEMOP_MNEMONIC(imul_Gv_Ev_Iz, "imul Gv,Ev,Iz"); /* Gv = Ev * Iz; */
3212 IEMOP_HLP_MIN_186();
3213 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
3214 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
3215
3216 switch (pVCpu->iem.s.enmEffOpSize)
3217 {
3218 case IEMMODE_16BIT:
3219 {
3220 PFNIEMAIMPLBINU16 const pfnAImplU16 = IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_imul_two_u16_eflags);
3221 if (IEM_IS_MODRM_REG_MODE(bRm))
3222 {
3223 /* register operand */
3224 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm);
3225 IEM_MC_BEGIN(3, 1, IEM_MC_F_MIN_186, 0);
3226 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3227 IEM_MC_LOCAL(uint16_t, u16Tmp);
3228 IEM_MC_FETCH_GREG_U16(u16Tmp, IEM_GET_MODRM_RM(pVCpu, bRm));
3229 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Dst, u16Tmp, 0);
3230 IEM_MC_ARG_CONST(uint16_t, u16Src,/*=*/ u16Imm, 1);
3231 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3232 IEM_MC_REF_EFLAGS(pEFlags);
3233 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU16, pu16Dst, u16Src, pEFlags);
3234 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_REG(pVCpu, bRm), u16Tmp);
3235
3236 IEM_MC_ADVANCE_RIP_AND_FINISH();
3237 IEM_MC_END();
3238 }
3239 else
3240 {
3241 /* memory operand */
3242 IEM_MC_BEGIN(3, 2, IEM_MC_F_MIN_186, 0);
3243 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
3244 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 2);
3245
3246 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm);
3247 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3248
3249 IEM_MC_LOCAL(uint16_t, u16Tmp);
3250 IEM_MC_FETCH_MEM_U16(u16Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
3251
3252 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Dst, u16Tmp, 0);
3253 IEM_MC_ARG_CONST(uint16_t, u16Src, u16Imm, 1);
3254 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3255 IEM_MC_REF_EFLAGS(pEFlags);
3256 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU16, pu16Dst, u16Src, pEFlags);
3257 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_REG(pVCpu, bRm), u16Tmp);
3258
3259 IEM_MC_ADVANCE_RIP_AND_FINISH();
3260 IEM_MC_END();
3261 }
3262 break;
3263 }
3264
3265 case IEMMODE_32BIT:
3266 {
3267 PFNIEMAIMPLBINU32 const pfnAImplU32 = IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_imul_two_u32_eflags);
3268 if (IEM_IS_MODRM_REG_MODE(bRm))
3269 {
3270 /* register operand */
3271 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm);
3272 IEM_MC_BEGIN(3, 1, IEM_MC_F_MIN_386, 0);
3273 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3274 IEM_MC_LOCAL(uint32_t, u32Tmp);
3275 IEM_MC_FETCH_GREG_U32(u32Tmp, IEM_GET_MODRM_RM(pVCpu, bRm));
3276
3277 IEM_MC_ARG_LOCAL_REF(uint32_t *, pu32Dst, u32Tmp, 0);
3278 IEM_MC_ARG_CONST(uint32_t, u32Src,/*=*/ u32Imm, 1);
3279 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3280 IEM_MC_REF_EFLAGS(pEFlags);
3281 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU32, pu32Dst, u32Src, pEFlags);
3282 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_REG(pVCpu, bRm), u32Tmp);
3283
3284 IEM_MC_ADVANCE_RIP_AND_FINISH();
3285 IEM_MC_END();
3286 }
3287 else
3288 {
3289 /* memory operand */
3290 IEM_MC_BEGIN(3, 2, IEM_MC_F_MIN_386, 0);
3291 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
3292 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4);
3293
3294 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm);
3295 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3296
3297 IEM_MC_LOCAL(uint32_t, u32Tmp);
3298 IEM_MC_FETCH_MEM_U32(u32Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
3299
3300 IEM_MC_ARG_LOCAL_REF(uint32_t *, pu32Dst, u32Tmp, 0);
3301 IEM_MC_ARG_CONST(uint32_t, u32Src, u32Imm, 1);
3302 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3303 IEM_MC_REF_EFLAGS(pEFlags);
3304 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU32, pu32Dst, u32Src, pEFlags);
3305 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_REG(pVCpu, bRm), u32Tmp);
3306
3307 IEM_MC_ADVANCE_RIP_AND_FINISH();
3308 IEM_MC_END();
3309 }
3310 break;
3311 }
3312
3313 case IEMMODE_64BIT:
3314 {
3315 PFNIEMAIMPLBINU64 const pfnAImplU64 = IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_imul_two_u64_eflags);
3316 if (IEM_IS_MODRM_REG_MODE(bRm))
3317 {
3318 /* register operand */
3319 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm);
3320 IEM_MC_BEGIN(3, 1, IEM_MC_F_64BIT, 0);
3321 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3322 IEM_MC_LOCAL(uint64_t, u64Tmp);
3323 IEM_MC_FETCH_GREG_U64(u64Tmp, IEM_GET_MODRM_RM(pVCpu, bRm));
3324
3325 IEM_MC_ARG_LOCAL_REF(uint64_t *, pu64Dst, u64Tmp, 0);
3326 IEM_MC_ARG_CONST(uint64_t, u64Src,/*=*/ u64Imm, 1);
3327 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3328 IEM_MC_REF_EFLAGS(pEFlags);
3329 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU64, pu64Dst, u64Src, pEFlags);
3330 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), u64Tmp);
3331
3332 IEM_MC_ADVANCE_RIP_AND_FINISH();
3333 IEM_MC_END();
3334 }
3335 else
3336 {
3337 /* memory operand */
3338 IEM_MC_BEGIN(3, 2, IEM_MC_F_64BIT, 0);
3339 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
3340 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4);
3341
3342 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm); /* Not using IEM_OPCODE_GET_NEXT_S32_SX_U64 to reduce the */
3343 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); /* parameter count for the threaded function for this block. */
3344
3345 IEM_MC_LOCAL(uint64_t, u64Tmp);
3346 IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
3347
3348 IEM_MC_ARG_LOCAL_REF(uint64_t *, pu64Dst, u64Tmp, 0);
3349 IEM_MC_ARG_CONST(uint64_t, u64Src, /*=*/ (int64_t)(int32_t)u32Imm, 1);
3350 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3351 IEM_MC_REF_EFLAGS(pEFlags);
3352 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU64, pu64Dst, u64Src, pEFlags);
3353 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), u64Tmp);
3354
3355 IEM_MC_ADVANCE_RIP_AND_FINISH();
3356 IEM_MC_END();
3357 }
3358 break;
3359 }
3360
3361 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3362 }
3363}
3364
3365
3366/**
3367 * @opcode 0x6a
3368 */
3369FNIEMOP_DEF(iemOp_push_Ib)
3370{
3371 IEMOP_MNEMONIC(push_Ib, "push Ib");
3372 IEMOP_HLP_MIN_186();
3373 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
3374 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
3375
3376 switch (pVCpu->iem.s.enmEffOpSize)
3377 {
3378 case IEMMODE_16BIT:
3379 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_186, 0);
3380 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3381 IEM_MC_LOCAL_CONST(uint16_t, uValue, (int16_t)i8Imm);
3382 IEM_MC_PUSH_U16(uValue);
3383 IEM_MC_ADVANCE_RIP_AND_FINISH();
3384 IEM_MC_END();
3385 break;
3386 case IEMMODE_32BIT:
3387 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT, 0);
3388 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3389 IEM_MC_LOCAL_CONST(uint32_t, uValue, (int32_t)i8Imm);
3390 IEM_MC_PUSH_U32(uValue);
3391 IEM_MC_ADVANCE_RIP_AND_FINISH();
3392 IEM_MC_END();
3393 break;
3394 case IEMMODE_64BIT:
3395 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
3396 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3397 IEM_MC_LOCAL_CONST(uint64_t, uValue, (int64_t)i8Imm);
3398 IEM_MC_PUSH_U64(uValue);
3399 IEM_MC_ADVANCE_RIP_AND_FINISH();
3400 IEM_MC_END();
3401 break;
3402 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3403 }
3404}
3405
3406
3407/**
3408 * @opcode 0x6b
3409 * @opflclass multiply
3410 */
3411FNIEMOP_DEF(iemOp_imul_Gv_Ev_Ib)
3412{
3413 IEMOP_MNEMONIC(imul_Gv_Ev_Ib, "imul Gv,Ev,Ib"); /* Gv = Ev * Iz; */
3414 IEMOP_HLP_MIN_186();
3415 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
3416 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
3417
3418 switch (pVCpu->iem.s.enmEffOpSize)
3419 {
3420 case IEMMODE_16BIT:
3421 {
3422 PFNIEMAIMPLBINU16 const pfnAImplU16 = IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_imul_two_u16_eflags);
3423 if (IEM_IS_MODRM_REG_MODE(bRm))
3424 {
3425 /* register operand */
3426 IEM_MC_BEGIN(3, 1, IEM_MC_F_MIN_186, 0);
3427 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
3428 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3429
3430 IEM_MC_LOCAL(uint16_t, u16Tmp);
3431 IEM_MC_FETCH_GREG_U16(u16Tmp, IEM_GET_MODRM_RM(pVCpu, bRm));
3432
3433 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Dst, u16Tmp, 0);
3434 IEM_MC_ARG_CONST(uint16_t, u16Src,/*=*/ (int8_t)u8Imm, 1);
3435 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3436 IEM_MC_REF_EFLAGS(pEFlags);
3437 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU16, pu16Dst, u16Src, pEFlags);
3438 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_REG(pVCpu, bRm), u16Tmp);
3439
3440 IEM_MC_ADVANCE_RIP_AND_FINISH();
3441 IEM_MC_END();
3442 }
3443 else
3444 {
3445 /* memory operand */
3446 IEM_MC_BEGIN(3, 2, IEM_MC_F_MIN_186, 0);
3447
3448 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
3449 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1);
3450
3451 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_S8_SX_U16(&u16Imm);
3452 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3453
3454 IEM_MC_LOCAL(uint16_t, u16Tmp);
3455 IEM_MC_FETCH_MEM_U16(u16Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
3456
3457 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Dst, u16Tmp, 0);
3458 IEM_MC_ARG_CONST(uint16_t, u16Src, u16Imm, 1);
3459 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3460 IEM_MC_REF_EFLAGS(pEFlags);
3461 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU16, pu16Dst, u16Src, pEFlags);
3462 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_REG(pVCpu, bRm), u16Tmp);
3463
3464 IEM_MC_ADVANCE_RIP_AND_FINISH();
3465 IEM_MC_END();
3466 }
3467 break;
3468 }
3469
3470 case IEMMODE_32BIT:
3471 {
3472 PFNIEMAIMPLBINU32 const pfnAImplU32 = IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_imul_two_u32_eflags);
3473 if (IEM_IS_MODRM_REG_MODE(bRm))
3474 {
3475 /* register operand */
3476 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
3477 IEM_MC_BEGIN(3, 1, IEM_MC_F_MIN_386, 0);
3478 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3479 IEM_MC_LOCAL(uint32_t, u32Tmp);
3480 IEM_MC_FETCH_GREG_U32(u32Tmp, IEM_GET_MODRM_RM(pVCpu, bRm));
3481
3482 IEM_MC_ARG_LOCAL_REF(uint32_t *, pu32Dst, u32Tmp, 0);
3483 IEM_MC_ARG_CONST(uint32_t, u32Src,/*=*/ (int8_t)u8Imm, 1);
3484 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3485 IEM_MC_REF_EFLAGS(pEFlags);
3486 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU32, pu32Dst, u32Src, pEFlags);
3487 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_REG(pVCpu, bRm), u32Tmp);
3488
3489 IEM_MC_ADVANCE_RIP_AND_FINISH();
3490 IEM_MC_END();
3491 }
3492 else
3493 {
3494 /* memory operand */
3495 IEM_MC_BEGIN(3, 2, IEM_MC_F_MIN_386, 0);
3496 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
3497 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1);
3498
3499 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_S8_SX_U32(&u32Imm);
3500 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3501
3502 IEM_MC_LOCAL(uint32_t, u32Tmp);
3503 IEM_MC_FETCH_MEM_U32(u32Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
3504
3505 IEM_MC_ARG_LOCAL_REF(uint32_t *, pu32Dst, u32Tmp, 0);
3506 IEM_MC_ARG_CONST(uint32_t, u32Src, u32Imm, 1);
3507 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3508 IEM_MC_REF_EFLAGS(pEFlags);
3509 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU32, pu32Dst, u32Src, pEFlags);
3510 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_REG(pVCpu, bRm), u32Tmp);
3511
3512 IEM_MC_ADVANCE_RIP_AND_FINISH();
3513 IEM_MC_END();
3514 }
3515 break;
3516 }
3517
3518 case IEMMODE_64BIT:
3519 {
3520 PFNIEMAIMPLBINU64 const pfnAImplU64 = IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_imul_two_u64_eflags);
3521 if (IEM_IS_MODRM_REG_MODE(bRm))
3522 {
3523 /* register operand */
3524 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
3525 IEM_MC_BEGIN(3, 1, IEM_MC_F_64BIT, 0);
3526 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3527 IEM_MC_LOCAL(uint64_t, u64Tmp);
3528 IEM_MC_FETCH_GREG_U64(u64Tmp, IEM_GET_MODRM_RM(pVCpu, bRm));
3529
3530 IEM_MC_ARG_LOCAL_REF(uint64_t *, pu64Dst, u64Tmp, 0);
3531 IEM_MC_ARG_CONST(uint64_t, u64Src, /*=*/ (int64_t)(int8_t)u8Imm, 1);
3532 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3533 IEM_MC_REF_EFLAGS(pEFlags);
3534 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU64, pu64Dst, u64Src, pEFlags);
3535 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), u64Tmp);
3536
3537 IEM_MC_ADVANCE_RIP_AND_FINISH();
3538 IEM_MC_END();
3539 }
3540 else
3541 {
3542 /* memory operand */
3543 IEM_MC_BEGIN(3, 2, IEM_MC_F_64BIT, 0);
3544 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
3545 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1);
3546
3547 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); /* Not using IEM_OPCODE_GET_NEXT_S8_SX_U64 to reduce the threaded parameter count. */
3548 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3549
3550 IEM_MC_LOCAL(uint64_t, u64Tmp);
3551 IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
3552
3553 IEM_MC_ARG_LOCAL_REF(uint64_t *, pu64Dst, u64Tmp, 0);
3554 IEM_MC_ARG_CONST(uint64_t, u64Src, /*=*/ (int64_t)(int8_t)u8Imm, 1);
3555 IEM_MC_ARG(uint32_t *, pEFlags, 2);
3556 IEM_MC_REF_EFLAGS(pEFlags);
3557 IEM_MC_CALL_VOID_AIMPL_3(pfnAImplU64, pu64Dst, u64Src, pEFlags);
3558 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), u64Tmp);
3559
3560 IEM_MC_ADVANCE_RIP_AND_FINISH();
3561 IEM_MC_END();
3562 }
3563 break;
3564 }
3565
3566 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3567 }
3568}
3569
3570
3571/**
3572 * @opcode 0x6c
3573 * @opfltest iopl,df
3574 */
3575FNIEMOP_DEF(iemOp_insb_Yb_DX)
3576{
3577 IEMOP_HLP_MIN_186();
3578 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3579 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
3580 {
3581 IEMOP_MNEMONIC(rep_insb_Yb_DX, "rep ins Yb,DX");
3582 switch (pVCpu->iem.s.enmEffAddrMode)
3583 {
3584 case IEMMODE_16BIT:
3585 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3586 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
3587 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3588 iemCImpl_rep_ins_op8_addr16, false);
3589 case IEMMODE_32BIT:
3590 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3591 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
3592 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3593 iemCImpl_rep_ins_op8_addr32, false);
3594 case IEMMODE_64BIT:
3595 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3596 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
3597 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3598 iemCImpl_rep_ins_op8_addr64, false);
3599 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3600 }
3601 }
3602 else
3603 {
3604 IEMOP_MNEMONIC(ins_Yb_DX, "ins Yb,DX");
3605 switch (pVCpu->iem.s.enmEffAddrMode)
3606 {
3607 case IEMMODE_16BIT:
3608 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3609 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
3610 iemCImpl_ins_op8_addr16, false);
3611 case IEMMODE_32BIT:
3612 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3613 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
3614 iemCImpl_ins_op8_addr32, false);
3615 case IEMMODE_64BIT:
3616 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3617 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
3618 iemCImpl_ins_op8_addr64, false);
3619 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3620 }
3621 }
3622}
3623
3624
3625/**
3626 * @opcode 0x6d
3627 * @opfltest iopl,df
3628 */
3629FNIEMOP_DEF(iemOp_inswd_Yv_DX)
3630{
3631 IEMOP_HLP_MIN_186();
3632 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3633 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPZ | IEM_OP_PRF_REPNZ))
3634 {
3635 IEMOP_MNEMONIC(rep_ins_Yv_DX, "rep ins Yv,DX");
3636 switch (pVCpu->iem.s.enmEffOpSize)
3637 {
3638 case IEMMODE_16BIT:
3639 switch (pVCpu->iem.s.enmEffAddrMode)
3640 {
3641 case IEMMODE_16BIT:
3642 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3643 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
3644 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3645 iemCImpl_rep_ins_op16_addr16, false);
3646 case IEMMODE_32BIT:
3647 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3648 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
3649 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3650 iemCImpl_rep_ins_op16_addr32, false);
3651 case IEMMODE_64BIT:
3652 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3653 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
3654 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3655 iemCImpl_rep_ins_op16_addr64, false);
3656 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3657 }
3658 break;
3659 case IEMMODE_64BIT:
3660 case IEMMODE_32BIT:
3661 switch (pVCpu->iem.s.enmEffAddrMode)
3662 {
3663 case IEMMODE_16BIT:
3664 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3665 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
3666 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3667 iemCImpl_rep_ins_op32_addr16, false);
3668 case IEMMODE_32BIT:
3669 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3670 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
3671 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3672 iemCImpl_rep_ins_op32_addr32, false);
3673 case IEMMODE_64BIT:
3674 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3675 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
3676 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3677 iemCImpl_rep_ins_op32_addr64, false);
3678 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3679 }
3680 break;
3681 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3682 }
3683 }
3684 else
3685 {
3686 IEMOP_MNEMONIC(ins_Yv_DX, "ins Yv,DX");
3687 switch (pVCpu->iem.s.enmEffOpSize)
3688 {
3689 case IEMMODE_16BIT:
3690 switch (pVCpu->iem.s.enmEffAddrMode)
3691 {
3692 case IEMMODE_16BIT:
3693 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3694 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
3695 iemCImpl_ins_op16_addr16, false);
3696 case IEMMODE_32BIT:
3697 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3698 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
3699 iemCImpl_ins_op16_addr32, false);
3700 case IEMMODE_64BIT:
3701 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3702 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
3703 iemCImpl_ins_op16_addr64, false);
3704 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3705 }
3706 break;
3707 case IEMMODE_64BIT:
3708 case IEMMODE_32BIT:
3709 switch (pVCpu->iem.s.enmEffAddrMode)
3710 {
3711 case IEMMODE_16BIT:
3712 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3713 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
3714 iemCImpl_ins_op32_addr16, false);
3715 case IEMMODE_32BIT:
3716 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3717 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
3718 iemCImpl_ins_op32_addr32, false);
3719 case IEMMODE_64BIT:
3720 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3721 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI),
3722 iemCImpl_ins_op32_addr64, false);
3723 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3724 }
3725 break;
3726 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3727 }
3728 }
3729}
3730
3731
3732/**
3733 * @opcode 0x6e
3734 * @opfltest iopl,df
3735 */
3736FNIEMOP_DEF(iemOp_outsb_Yb_DX)
3737{
3738 IEMOP_HLP_MIN_186();
3739 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3740 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
3741 {
3742 IEMOP_MNEMONIC(rep_outsb_DX_Yb, "rep outs DX,Yb");
3743 switch (pVCpu->iem.s.enmEffAddrMode)
3744 {
3745 case IEMMODE_16BIT:
3746 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3747 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
3748 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3749 iemCImpl_rep_outs_op8_addr16, pVCpu->iem.s.iEffSeg, false);
3750 case IEMMODE_32BIT:
3751 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3752 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
3753 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3754 iemCImpl_rep_outs_op8_addr32, pVCpu->iem.s.iEffSeg, false);
3755 case IEMMODE_64BIT:
3756 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3757 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
3758 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3759 iemCImpl_rep_outs_op8_addr64, pVCpu->iem.s.iEffSeg, false);
3760 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3761 }
3762 }
3763 else
3764 {
3765 IEMOP_MNEMONIC(outs_DX_Yb, "outs DX,Yb");
3766 switch (pVCpu->iem.s.enmEffAddrMode)
3767 {
3768 case IEMMODE_16BIT:
3769 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3770 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI),
3771 iemCImpl_outs_op8_addr16, pVCpu->iem.s.iEffSeg, false);
3772 case IEMMODE_32BIT:
3773 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3774 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI),
3775 iemCImpl_outs_op8_addr32, pVCpu->iem.s.iEffSeg, false);
3776 case IEMMODE_64BIT:
3777 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3778 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI),
3779 iemCImpl_outs_op8_addr64, pVCpu->iem.s.iEffSeg, false);
3780 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3781 }
3782 }
3783}
3784
3785
3786/**
3787 * @opcode 0x6f
3788 * @opfltest iopl,df
3789 */
3790FNIEMOP_DEF(iemOp_outswd_Yv_DX)
3791{
3792 IEMOP_HLP_MIN_186();
3793 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3794 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPZ | IEM_OP_PRF_REPNZ))
3795 {
3796 IEMOP_MNEMONIC(rep_outs_DX_Yv, "rep outs DX,Yv");
3797 switch (pVCpu->iem.s.enmEffOpSize)
3798 {
3799 case IEMMODE_16BIT:
3800 switch (pVCpu->iem.s.enmEffAddrMode)
3801 {
3802 case IEMMODE_16BIT:
3803 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3804 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
3805 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3806 iemCImpl_rep_outs_op16_addr16, pVCpu->iem.s.iEffSeg, false);
3807 case IEMMODE_32BIT:
3808 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3809 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
3810 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3811 iemCImpl_rep_outs_op16_addr32, pVCpu->iem.s.iEffSeg, false);
3812 case IEMMODE_64BIT:
3813 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3814 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
3815 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3816 iemCImpl_rep_outs_op16_addr64, pVCpu->iem.s.iEffSeg, false);
3817 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3818 }
3819 break;
3820 case IEMMODE_64BIT:
3821 case IEMMODE_32BIT:
3822 switch (pVCpu->iem.s.enmEffAddrMode)
3823 {
3824 case IEMMODE_16BIT:
3825 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3826 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
3827 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3828 iemCImpl_rep_outs_op32_addr16, pVCpu->iem.s.iEffSeg, false);
3829 case IEMMODE_32BIT:
3830 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3831 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
3832 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3833 iemCImpl_rep_outs_op32_addr32, pVCpu->iem.s.iEffSeg, false);
3834 case IEMMODE_64BIT:
3835 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3836 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
3837 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
3838 iemCImpl_rep_outs_op32_addr64, pVCpu->iem.s.iEffSeg, false);
3839 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3840 }
3841 break;
3842 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3843 }
3844 }
3845 else
3846 {
3847 IEMOP_MNEMONIC(outs_DX_Yv, "outs DX,Yv");
3848 switch (pVCpu->iem.s.enmEffOpSize)
3849 {
3850 case IEMMODE_16BIT:
3851 switch (pVCpu->iem.s.enmEffAddrMode)
3852 {
3853 case IEMMODE_16BIT:
3854 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3855 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI),
3856 iemCImpl_outs_op16_addr16, pVCpu->iem.s.iEffSeg, false);
3857 case IEMMODE_32BIT:
3858 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3859 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI),
3860 iemCImpl_outs_op16_addr32, pVCpu->iem.s.iEffSeg, false);
3861 case IEMMODE_64BIT:
3862 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3863 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI),
3864 iemCImpl_outs_op16_addr64, pVCpu->iem.s.iEffSeg, false);
3865 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3866 }
3867 break;
3868 case IEMMODE_64BIT:
3869 case IEMMODE_32BIT:
3870 switch (pVCpu->iem.s.enmEffAddrMode)
3871 {
3872 case IEMMODE_16BIT:
3873 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3874 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI),
3875 iemCImpl_outs_op32_addr16, pVCpu->iem.s.iEffSeg, false);
3876 case IEMMODE_32BIT:
3877 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3878 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI),
3879 iemCImpl_outs_op32_addr32, pVCpu->iem.s.iEffSeg, false);
3880 case IEMMODE_64BIT:
3881 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
3882 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI),
3883 iemCImpl_outs_op32_addr64, pVCpu->iem.s.iEffSeg, false);
3884 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3885 }
3886 break;
3887 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3888 }
3889 }
3890}
3891
3892
3893/**
3894 * @opcode 0x70
3895 * @opfltest of
3896 */
3897FNIEMOP_DEF(iemOp_jo_Jb)
3898{
3899 IEMOP_MNEMONIC(jo_Jb, "jo Jb");
3900 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
3901 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
3902
3903 IEM_MC_BEGIN(0, 0, 0, 0);
3904 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3905 IEM_MC_IF_EFL_BIT_SET(X86_EFL_OF) {
3906 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
3907 } IEM_MC_ELSE() {
3908 IEM_MC_ADVANCE_RIP_AND_FINISH();
3909 } IEM_MC_ENDIF();
3910 IEM_MC_END();
3911}
3912
3913
3914/**
3915 * @opcode 0x71
3916 * @opfltest of
3917 */
3918FNIEMOP_DEF(iemOp_jno_Jb)
3919{
3920 IEMOP_MNEMONIC(jno_Jb, "jno Jb");
3921 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
3922 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
3923
3924 IEM_MC_BEGIN(0, 0, 0, 0);
3925 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3926 IEM_MC_IF_EFL_BIT_SET(X86_EFL_OF) {
3927 IEM_MC_ADVANCE_RIP_AND_FINISH();
3928 } IEM_MC_ELSE() {
3929 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
3930 } IEM_MC_ENDIF();
3931 IEM_MC_END();
3932}
3933
3934/**
3935 * @opcode 0x72
3936 * @opfltest cf
3937 */
3938FNIEMOP_DEF(iemOp_jc_Jb)
3939{
3940 IEMOP_MNEMONIC(jc_Jb, "jc/jnae Jb");
3941 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
3942 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
3943
3944 IEM_MC_BEGIN(0, 0, 0, 0);
3945 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3946 IEM_MC_IF_EFL_BIT_SET(X86_EFL_CF) {
3947 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
3948 } IEM_MC_ELSE() {
3949 IEM_MC_ADVANCE_RIP_AND_FINISH();
3950 } IEM_MC_ENDIF();
3951 IEM_MC_END();
3952}
3953
3954
3955/**
3956 * @opcode 0x73
3957 * @opfltest cf
3958 */
3959FNIEMOP_DEF(iemOp_jnc_Jb)
3960{
3961 IEMOP_MNEMONIC(jnc_Jb, "jnc/jnb Jb");
3962 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
3963 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
3964
3965 IEM_MC_BEGIN(0, 0, 0, 0);
3966 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3967 IEM_MC_IF_EFL_BIT_SET(X86_EFL_CF) {
3968 IEM_MC_ADVANCE_RIP_AND_FINISH();
3969 } IEM_MC_ELSE() {
3970 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
3971 } IEM_MC_ENDIF();
3972 IEM_MC_END();
3973}
3974
3975
3976/**
3977 * @opcode 0x74
3978 * @opfltest zf
3979 */
3980FNIEMOP_DEF(iemOp_je_Jb)
3981{
3982 IEMOP_MNEMONIC(je_Jb, "je/jz Jb");
3983 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
3984 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
3985
3986 IEM_MC_BEGIN(0, 0, 0, 0);
3987 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
3988 IEM_MC_IF_EFL_BIT_SET(X86_EFL_ZF) {
3989 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
3990 } IEM_MC_ELSE() {
3991 IEM_MC_ADVANCE_RIP_AND_FINISH();
3992 } IEM_MC_ENDIF();
3993 IEM_MC_END();
3994}
3995
3996
3997/**
3998 * @opcode 0x75
3999 * @opfltest zf
4000 */
4001FNIEMOP_DEF(iemOp_jne_Jb)
4002{
4003 IEMOP_MNEMONIC(jne_Jb, "jne/jnz Jb");
4004 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4005 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4006
4007 IEM_MC_BEGIN(0, 0, 0, 0);
4008 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4009 IEM_MC_IF_EFL_BIT_SET(X86_EFL_ZF) {
4010 IEM_MC_ADVANCE_RIP_AND_FINISH();
4011 } IEM_MC_ELSE() {
4012 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4013 } IEM_MC_ENDIF();
4014 IEM_MC_END();
4015}
4016
4017
4018/**
4019 * @opcode 0x76
4020 * @opfltest cf,zf
4021 */
4022FNIEMOP_DEF(iemOp_jbe_Jb)
4023{
4024 IEMOP_MNEMONIC(jbe_Jb, "jbe/jna Jb");
4025 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4026 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4027
4028 IEM_MC_BEGIN(0, 0, 0, 0);
4029 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4030 IEM_MC_IF_EFL_ANY_BITS_SET(X86_EFL_CF | X86_EFL_ZF) {
4031 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4032 } IEM_MC_ELSE() {
4033 IEM_MC_ADVANCE_RIP_AND_FINISH();
4034 } IEM_MC_ENDIF();
4035 IEM_MC_END();
4036}
4037
4038
4039/**
4040 * @opcode 0x77
4041 * @opfltest cf,zf
4042 */
4043FNIEMOP_DEF(iemOp_jnbe_Jb)
4044{
4045 IEMOP_MNEMONIC(ja_Jb, "ja/jnbe Jb");
4046 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4047 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4048
4049 IEM_MC_BEGIN(0, 0, 0, 0);
4050 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4051 IEM_MC_IF_EFL_ANY_BITS_SET(X86_EFL_CF | X86_EFL_ZF) {
4052 IEM_MC_ADVANCE_RIP_AND_FINISH();
4053 } IEM_MC_ELSE() {
4054 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4055 } IEM_MC_ENDIF();
4056 IEM_MC_END();
4057}
4058
4059
4060/**
4061 * @opcode 0x78
4062 * @opfltest sf
4063 */
4064FNIEMOP_DEF(iemOp_js_Jb)
4065{
4066 IEMOP_MNEMONIC(js_Jb, "js Jb");
4067 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4068 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4069
4070 IEM_MC_BEGIN(0, 0, 0, 0);
4071 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4072 IEM_MC_IF_EFL_BIT_SET(X86_EFL_SF) {
4073 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4074 } IEM_MC_ELSE() {
4075 IEM_MC_ADVANCE_RIP_AND_FINISH();
4076 } IEM_MC_ENDIF();
4077 IEM_MC_END();
4078}
4079
4080
4081/**
4082 * @opcode 0x79
4083 * @opfltest sf
4084 */
4085FNIEMOP_DEF(iemOp_jns_Jb)
4086{
4087 IEMOP_MNEMONIC(jns_Jb, "jns Jb");
4088 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4089 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4090
4091 IEM_MC_BEGIN(0, 0, 0, 0);
4092 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4093 IEM_MC_IF_EFL_BIT_SET(X86_EFL_SF) {
4094 IEM_MC_ADVANCE_RIP_AND_FINISH();
4095 } IEM_MC_ELSE() {
4096 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4097 } IEM_MC_ENDIF();
4098 IEM_MC_END();
4099}
4100
4101
4102/**
4103 * @opcode 0x7a
4104 * @opfltest pf
4105 */
4106FNIEMOP_DEF(iemOp_jp_Jb)
4107{
4108 IEMOP_MNEMONIC(jp_Jb, "jp Jb");
4109 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4110 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4111
4112 IEM_MC_BEGIN(0, 0, 0, 0);
4113 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4114 IEM_MC_IF_EFL_BIT_SET(X86_EFL_PF) {
4115 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4116 } IEM_MC_ELSE() {
4117 IEM_MC_ADVANCE_RIP_AND_FINISH();
4118 } IEM_MC_ENDIF();
4119 IEM_MC_END();
4120}
4121
4122
4123/**
4124 * @opcode 0x7b
4125 * @opfltest pf
4126 */
4127FNIEMOP_DEF(iemOp_jnp_Jb)
4128{
4129 IEMOP_MNEMONIC(jnp_Jb, "jnp Jb");
4130 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4131 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4132
4133 IEM_MC_BEGIN(0, 0, 0, 0);
4134 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4135 IEM_MC_IF_EFL_BIT_SET(X86_EFL_PF) {
4136 IEM_MC_ADVANCE_RIP_AND_FINISH();
4137 } IEM_MC_ELSE() {
4138 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4139 } IEM_MC_ENDIF();
4140 IEM_MC_END();
4141}
4142
4143
4144/**
4145 * @opcode 0x7c
4146 * @opfltest sf,of
4147 */
4148FNIEMOP_DEF(iemOp_jl_Jb)
4149{
4150 IEMOP_MNEMONIC(jl_Jb, "jl/jnge Jb");
4151 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4152 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4153
4154 IEM_MC_BEGIN(0, 0, 0, 0);
4155 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4156 IEM_MC_IF_EFL_BITS_NE(X86_EFL_SF, X86_EFL_OF) {
4157 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4158 } IEM_MC_ELSE() {
4159 IEM_MC_ADVANCE_RIP_AND_FINISH();
4160 } IEM_MC_ENDIF();
4161 IEM_MC_END();
4162}
4163
4164
4165/**
4166 * @opcode 0x7d
4167 * @opfltest sf,of
4168 */
4169FNIEMOP_DEF(iemOp_jnl_Jb)
4170{
4171 IEMOP_MNEMONIC(jge_Jb, "jnl/jge Jb");
4172 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4173 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4174
4175 IEM_MC_BEGIN(0, 0, 0, 0);
4176 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4177 IEM_MC_IF_EFL_BITS_NE(X86_EFL_SF, X86_EFL_OF) {
4178 IEM_MC_ADVANCE_RIP_AND_FINISH();
4179 } IEM_MC_ELSE() {
4180 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4181 } IEM_MC_ENDIF();
4182 IEM_MC_END();
4183}
4184
4185
4186/**
4187 * @opcode 0x7e
4188 * @opfltest zf,sf,of
4189 */
4190FNIEMOP_DEF(iemOp_jle_Jb)
4191{
4192 IEMOP_MNEMONIC(jle_Jb, "jle/jng Jb");
4193 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4194 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4195
4196 IEM_MC_BEGIN(0, 0, 0, 0);
4197 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4198 IEM_MC_IF_EFL_BIT_SET_OR_BITS_NE(X86_EFL_ZF, X86_EFL_SF, X86_EFL_OF) {
4199 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4200 } IEM_MC_ELSE() {
4201 IEM_MC_ADVANCE_RIP_AND_FINISH();
4202 } IEM_MC_ENDIF();
4203 IEM_MC_END();
4204}
4205
4206
4207/**
4208 * @opcode 0x7f
4209 * @opfltest zf,sf,of
4210 */
4211FNIEMOP_DEF(iemOp_jnle_Jb)
4212{
4213 IEMOP_MNEMONIC(jg_Jb, "jnle/jg Jb");
4214 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
4215 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
4216
4217 IEM_MC_BEGIN(0, 0, 0, 0);
4218 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
4219 IEM_MC_IF_EFL_BIT_SET_OR_BITS_NE(X86_EFL_ZF, X86_EFL_SF, X86_EFL_OF) {
4220 IEM_MC_ADVANCE_RIP_AND_FINISH();
4221 } IEM_MC_ELSE() {
4222 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
4223 } IEM_MC_ENDIF();
4224 IEM_MC_END();
4225}
4226
4227
4228/**
4229 * Body for group 1 instruction (binary) w/ byte imm operand, dispatched via
4230 * iemOp_Grp1_Eb_Ib_80.
4231 */
4232#define IEMOP_BODY_BINARY_Eb_Ib_RW(a_InsNm, a_fRegNativeArchs, a_fMemNativeArchs) \
4233 if (IEM_IS_MODRM_REG_MODE(bRm)) \
4234 { \
4235 /* register target */ \
4236 IEM_MC_BEGIN(3, 2, 0, 0); \
4237 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
4238 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
4239 IEM_MC_NATIVE_IF(a_fRegNativeArchs) { \
4240 IEM_MC_LOCAL(uint8_t, u8Dst); \
4241 IEM_MC_FETCH_GREG_U8(u8Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4242 IEM_MC_LOCAL(uint32_t, uEFlags); \
4243 IEM_MC_FETCH_EFLAGS(uEFlags); \
4244 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u8Dst, u8Imm, uEFlags, 8, 8); \
4245 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_RM(pVCpu, bRm), u8Dst); \
4246 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4247 } IEM_MC_NATIVE_ELSE() { \
4248 IEM_MC_ARG_CONST(uint8_t, u8Src, /*=*/ u8Imm, 1); \
4249 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
4250 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4251 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
4252 IEM_MC_REF_EFLAGS(pEFlags); \
4253 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
4254 } IEM_MC_NATIVE_ENDIF(); \
4255 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4256 IEM_MC_END(); \
4257 } \
4258 else \
4259 { \
4260 /* memory target */ \
4261 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
4262 { \
4263 IEM_MC_BEGIN(3, 3, 0, 0); \
4264 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
4265 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4266 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4267 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4268 \
4269 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
4270 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
4271 IEM_MC_ARG_CONST(uint8_t, u8Src, /*=*/ u8Imm, 1); \
4272 IEMOP_HLP_DONE_DECODING(); \
4273 \
4274 IEM_MC_MEM_MAP_U8_RW(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4275 IEM_MC_FETCH_EFLAGS(EFlags); \
4276 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
4277 \
4278 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
4279 IEM_MC_COMMIT_EFLAGS(EFlags); \
4280 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4281 IEM_MC_END(); \
4282 } \
4283 else \
4284 { \
4285 IEM_MC_BEGIN(3, 3, 0, 0); \
4286 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
4287 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4288 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4289 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4290 \
4291 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
4292 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
4293 IEM_MC_ARG_CONST(uint8_t, u8Src, /*=*/ u8Imm, 1); \
4294 IEMOP_HLP_DONE_DECODING(); \
4295 \
4296 IEM_MC_MEM_MAP_U8_ATOMIC(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4297 IEM_MC_FETCH_EFLAGS(EFlags); \
4298 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8_locked), pu8Dst, u8Src, pEFlags); \
4299 \
4300 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
4301 IEM_MC_COMMIT_EFLAGS(EFlags); \
4302 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4303 IEM_MC_END(); \
4304 } \
4305 } \
4306 (void)0
4307
4308#define IEMOP_BODY_BINARY_Eb_Ib_RO(a_InsNm, a_fNativeArchs) \
4309 if (IEM_IS_MODRM_REG_MODE(bRm)) \
4310 { \
4311 /* register target */ \
4312 IEM_MC_BEGIN(3, 2, 0, 0); \
4313 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
4314 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
4315 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
4316 IEM_MC_LOCAL(uint8_t, u8Dst); \
4317 IEM_MC_FETCH_GREG_U8(u8Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4318 IEM_MC_LOCAL(uint32_t, uEFlags); \
4319 IEM_MC_FETCH_EFLAGS(uEFlags); \
4320 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u8Dst, u8Imm, uEFlags, 8, 8); \
4321 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4322 } IEM_MC_NATIVE_ELSE() { \
4323 IEM_MC_ARG_CONST(uint8_t, u8Src, /*=*/ u8Imm, 1); \
4324 IEM_MC_ARG(uint8_t const *, pu8Dst, 0); \
4325 IEM_MC_REF_GREG_U8_CONST(pu8Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4326 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
4327 IEM_MC_REF_EFLAGS(pEFlags); \
4328 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
4329 } IEM_MC_NATIVE_ENDIF(); \
4330 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4331 IEM_MC_END(); \
4332 } \
4333 else \
4334 { \
4335 /* memory target */ \
4336 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
4337 { \
4338 IEM_MC_BEGIN(3, 3, 0, 0); \
4339 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4340 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
4341 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
4342 IEMOP_HLP_DONE_DECODING(); \
4343 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
4344 IEM_MC_LOCAL(uint8_t, u8Dst); \
4345 IEM_MC_FETCH_MEM_U8(u8Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4346 IEM_MC_LOCAL(uint32_t, uEFlags); \
4347 IEM_MC_FETCH_EFLAGS(uEFlags); \
4348 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u8Dst, u8Imm, uEFlags, 8, 8); \
4349 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4350 } IEM_MC_NATIVE_ELSE() { \
4351 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4352 IEM_MC_ARG(uint8_t const *, pu8Dst, 0); \
4353 IEM_MC_MEM_MAP_U8_RO(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4354 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4355 IEM_MC_FETCH_EFLAGS(EFlags); \
4356 IEM_MC_ARG_CONST(uint8_t, u8Src, /*=*/ u8Imm, 1); \
4357 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u8), pu8Dst, u8Src, pEFlags); \
4358 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
4359 IEM_MC_COMMIT_EFLAGS(EFlags); \
4360 } IEM_MC_NATIVE_ENDIF(); \
4361 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4362 IEM_MC_END(); \
4363 } \
4364 else \
4365 { \
4366 IEMOP_HLP_DONE_DECODING(); \
4367 IEMOP_RAISE_INVALID_LOCK_PREFIX_RET(); \
4368 } \
4369 } \
4370 (void)0
4371
4372
4373
4374/**
4375 * @opmaps grp1_80,grp1_83
4376 * @opcode /0
4377 * @opflclass arithmetic
4378 */
4379FNIEMOP_DEF_1(iemOp_Grp1_add_Eb_Ib, uint8_t, bRm)
4380{
4381 IEMOP_MNEMONIC(add_Eb_Ib, "add Eb,Ib");
4382 IEMOP_BODY_BINARY_Eb_Ib_RW(add, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4383}
4384
4385
4386/**
4387 * @opmaps grp1_80,grp1_83
4388 * @opcode /1
4389 * @opflclass logical
4390 */
4391FNIEMOP_DEF_1(iemOp_Grp1_or_Eb_Ib, uint8_t, bRm)
4392{
4393 IEMOP_MNEMONIC(or_Eb_Ib, "or Eb,Ib");
4394 IEMOP_BODY_BINARY_Eb_Ib_RW(or, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4395}
4396
4397
4398/**
4399 * @opmaps grp1_80,grp1_83
4400 * @opcode /2
4401 * @opflclass arithmetic_carry
4402 */
4403FNIEMOP_DEF_1(iemOp_Grp1_adc_Eb_Ib, uint8_t, bRm)
4404{
4405 IEMOP_MNEMONIC(adc_Eb_Ib, "adc Eb,Ib");
4406 IEMOP_BODY_BINARY_Eb_Ib_RW(adc, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4407}
4408
4409
4410/**
4411 * @opmaps grp1_80,grp1_83
4412 * @opcode /3
4413 * @opflclass arithmetic_carry
4414 */
4415FNIEMOP_DEF_1(iemOp_Grp1_sbb_Eb_Ib, uint8_t, bRm)
4416{
4417 IEMOP_MNEMONIC(sbb_Eb_Ib, "sbb Eb,Ib");
4418 IEMOP_BODY_BINARY_Eb_Ib_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4419}
4420
4421
4422/**
4423 * @opmaps grp1_80,grp1_83
4424 * @opcode /4
4425 * @opflclass logical
4426 */
4427FNIEMOP_DEF_1(iemOp_Grp1_and_Eb_Ib, uint8_t, bRm)
4428{
4429 IEMOP_MNEMONIC(and_Eb_Ib, "and Eb,Ib");
4430 IEMOP_BODY_BINARY_Eb_Ib_RW(and, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4431}
4432
4433
4434/**
4435 * @opmaps grp1_80,grp1_83
4436 * @opcode /5
4437 * @opflclass arithmetic
4438 */
4439FNIEMOP_DEF_1(iemOp_Grp1_sub_Eb_Ib, uint8_t, bRm)
4440{
4441 IEMOP_MNEMONIC(sub_Eb_Ib, "sub Eb,Ib");
4442 IEMOP_BODY_BINARY_Eb_Ib_RW(sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4443}
4444
4445
4446/**
4447 * @opmaps grp1_80,grp1_83
4448 * @opcode /6
4449 * @opflclass logical
4450 */
4451FNIEMOP_DEF_1(iemOp_Grp1_xor_Eb_Ib, uint8_t, bRm)
4452{
4453 IEMOP_MNEMONIC(xor_Eb_Ib, "xor Eb,Ib");
4454 IEMOP_BODY_BINARY_Eb_Ib_RW(xor, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4455}
4456
4457
4458/**
4459 * @opmaps grp1_80,grp1_83
4460 * @opcode /7
4461 * @opflclass arithmetic
4462 */
4463FNIEMOP_DEF_1(iemOp_Grp1_cmp_Eb_Ib, uint8_t, bRm)
4464{
4465 IEMOP_MNEMONIC(cmp_Eb_Ib, "cmp Eb,Ib");
4466 IEMOP_BODY_BINARY_Eb_Ib_RO(cmp, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
4467}
4468
4469
4470/**
4471 * @opcode 0x80
4472 */
4473FNIEMOP_DEF(iemOp_Grp1_Eb_Ib_80)
4474{
4475 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
4476 switch (IEM_GET_MODRM_REG_8(bRm))
4477 {
4478 case 0: return FNIEMOP_CALL_1(iemOp_Grp1_add_Eb_Ib, bRm);
4479 case 1: return FNIEMOP_CALL_1(iemOp_Grp1_or_Eb_Ib, bRm);
4480 case 2: return FNIEMOP_CALL_1(iemOp_Grp1_adc_Eb_Ib, bRm);
4481 case 3: return FNIEMOP_CALL_1(iemOp_Grp1_sbb_Eb_Ib, bRm);
4482 case 4: return FNIEMOP_CALL_1(iemOp_Grp1_and_Eb_Ib, bRm);
4483 case 5: return FNIEMOP_CALL_1(iemOp_Grp1_sub_Eb_Ib, bRm);
4484 case 6: return FNIEMOP_CALL_1(iemOp_Grp1_xor_Eb_Ib, bRm);
4485 case 7: return FNIEMOP_CALL_1(iemOp_Grp1_cmp_Eb_Ib, bRm);
4486 IEM_NOT_REACHED_DEFAULT_CASE_RET();
4487 }
4488}
4489
4490
4491/**
4492 * Body for a group 1 binary operator.
4493 */
4494#define IEMOP_BODY_BINARY_Ev_Iz_RW(a_InsNm, a_fRegNativeArchs, a_fMemNativeArchs) \
4495 if (IEM_IS_MODRM_REG_MODE(bRm)) \
4496 { \
4497 /* register target */ \
4498 switch (pVCpu->iem.s.enmEffOpSize) \
4499 { \
4500 case IEMMODE_16BIT: \
4501 { \
4502 IEM_MC_BEGIN(3, 2, 0, 0); \
4503 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm); \
4504 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
4505 IEM_MC_NATIVE_IF(a_fRegNativeArchs) { \
4506 IEM_MC_LOCAL(uint16_t, u16Dst); \
4507 IEM_MC_FETCH_GREG_U16(u16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4508 IEM_MC_LOCAL(uint32_t, uEFlags); \
4509 IEM_MC_FETCH_EFLAGS(uEFlags); \
4510 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u16Dst, u16Imm, uEFlags, 16, 16); \
4511 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_RM(pVCpu, bRm), u16Dst); \
4512 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4513 } IEM_MC_NATIVE_ELSE() { \
4514 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
4515 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4516 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
4517 IEM_MC_REF_EFLAGS(pEFlags); \
4518 IEM_MC_ARG_CONST(uint16_t, u16Src, /*=*/ u16Imm, 1); \
4519 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
4520 } IEM_MC_NATIVE_ENDIF(); \
4521 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4522 IEM_MC_END(); \
4523 break; \
4524 } \
4525 \
4526 case IEMMODE_32BIT: \
4527 { \
4528 IEM_MC_BEGIN(3, 2, IEM_MC_F_MIN_386, 0); \
4529 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm); \
4530 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
4531 IEM_MC_NATIVE_IF(a_fRegNativeArchs) { \
4532 IEM_MC_LOCAL(uint32_t, u32Dst); \
4533 IEM_MC_FETCH_GREG_U32(u32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4534 IEM_MC_LOCAL(uint32_t, uEFlags); \
4535 IEM_MC_FETCH_EFLAGS(uEFlags); \
4536 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u32Dst, u32Imm, uEFlags, 32, 32); \
4537 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_RM(pVCpu, bRm), u32Dst); \
4538 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4539 } IEM_MC_NATIVE_ELSE() { \
4540 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
4541 IEM_MC_REF_GREG_U32(pu32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4542 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
4543 IEM_MC_REF_EFLAGS(pEFlags); \
4544 IEM_MC_ARG_CONST(uint32_t, u32Src, /*=*/ u32Imm, 1); \
4545 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
4546 IEM_MC_CLEAR_HIGH_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm)); \
4547 } IEM_MC_NATIVE_ENDIF(); \
4548 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4549 IEM_MC_END(); \
4550 break; \
4551 } \
4552 \
4553 case IEMMODE_64BIT: \
4554 { \
4555 IEM_MC_BEGIN(3, 2, IEM_MC_F_64BIT, 0); \
4556 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm); \
4557 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
4558 IEM_MC_NATIVE_IF(a_fRegNativeArchs) { \
4559 IEM_MC_LOCAL(uint64_t, u64Dst); \
4560 IEM_MC_FETCH_GREG_U64(u64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4561 IEM_MC_LOCAL(uint32_t, uEFlags); \
4562 IEM_MC_FETCH_EFLAGS(uEFlags); \
4563 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u64Dst, u64Imm, uEFlags, 64, 32); \
4564 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm), u64Dst); \
4565 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4566 } IEM_MC_NATIVE_ELSE() { \
4567 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
4568 IEM_MC_REF_GREG_U64(pu64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4569 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
4570 IEM_MC_REF_EFLAGS(pEFlags); \
4571 IEM_MC_ARG_CONST(uint64_t, u64Src, /*=*/ u64Imm, 1); \
4572 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
4573 } IEM_MC_NATIVE_ENDIF(); \
4574 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4575 IEM_MC_END(); \
4576 break; \
4577 } \
4578 \
4579 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
4580 } \
4581 } \
4582 else \
4583 { \
4584 /* memory target */ \
4585 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
4586 { \
4587 switch (pVCpu->iem.s.enmEffOpSize) \
4588 { \
4589 case IEMMODE_16BIT: \
4590 { \
4591 IEM_MC_BEGIN(3, 3, 0, 0); \
4592 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4593 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 2); \
4594 \
4595 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm); \
4596 IEMOP_HLP_DONE_DECODING(); \
4597 \
4598 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4599 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
4600 IEM_MC_MEM_MAP_U16_RW(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4601 \
4602 IEM_MC_ARG_CONST(uint16_t, u16Src, u16Imm, 1); \
4603 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4604 IEM_MC_FETCH_EFLAGS(EFlags); \
4605 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
4606 \
4607 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
4608 IEM_MC_COMMIT_EFLAGS(EFlags); \
4609 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4610 IEM_MC_END(); \
4611 break; \
4612 } \
4613 \
4614 case IEMMODE_32BIT: \
4615 { \
4616 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
4617 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4618 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4); \
4619 \
4620 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm); \
4621 IEMOP_HLP_DONE_DECODING(); \
4622 \
4623 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4624 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
4625 IEM_MC_MEM_MAP_U32_RW(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4626 \
4627 IEM_MC_ARG_CONST(uint32_t, u32Src, u32Imm, 1); \
4628 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4629 IEM_MC_FETCH_EFLAGS(EFlags); \
4630 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
4631 \
4632 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
4633 IEM_MC_COMMIT_EFLAGS(EFlags); \
4634 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4635 IEM_MC_END(); \
4636 break; \
4637 } \
4638 \
4639 case IEMMODE_64BIT: \
4640 { \
4641 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
4642 \
4643 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4644 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4); \
4645 \
4646 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm); \
4647 IEMOP_HLP_DONE_DECODING(); \
4648 \
4649 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4650 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
4651 IEM_MC_MEM_MAP_U64_RW(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4652 \
4653 IEM_MC_ARG_CONST(uint64_t, u64Src, u64Imm, 1); \
4654 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4655 IEM_MC_FETCH_EFLAGS(EFlags); \
4656 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
4657 \
4658 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
4659 IEM_MC_COMMIT_EFLAGS(EFlags); \
4660 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4661 IEM_MC_END(); \
4662 break; \
4663 } \
4664 \
4665 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
4666 } \
4667 } \
4668 else \
4669 { \
4670 switch (pVCpu->iem.s.enmEffOpSize) \
4671 { \
4672 case IEMMODE_16BIT: \
4673 { \
4674 IEM_MC_BEGIN(3, 3, 0, 0); \
4675 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4676 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 2); \
4677 \
4678 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm); \
4679 IEMOP_HLP_DONE_DECODING(); \
4680 \
4681 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4682 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
4683 IEM_MC_MEM_MAP_U16_ATOMIC(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4684 \
4685 IEM_MC_ARG_CONST(uint16_t, u16Src, u16Imm, 1); \
4686 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4687 IEM_MC_FETCH_EFLAGS(EFlags); \
4688 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16_locked), pu16Dst, u16Src, pEFlags); \
4689 \
4690 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
4691 IEM_MC_COMMIT_EFLAGS(EFlags); \
4692 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4693 IEM_MC_END(); \
4694 break; \
4695 } \
4696 \
4697 case IEMMODE_32BIT: \
4698 { \
4699 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
4700 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4701 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4); \
4702 \
4703 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm); \
4704 IEMOP_HLP_DONE_DECODING(); \
4705 \
4706 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4707 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
4708 IEM_MC_MEM_MAP_U32_ATOMIC(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4709 \
4710 IEM_MC_ARG_CONST(uint32_t, u32Src, u32Imm, 1); \
4711 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4712 IEM_MC_FETCH_EFLAGS(EFlags); \
4713 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32_locked), pu32Dst, u32Src, pEFlags); \
4714 \
4715 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
4716 IEM_MC_COMMIT_EFLAGS(EFlags); \
4717 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4718 IEM_MC_END(); \
4719 break; \
4720 } \
4721 \
4722 case IEMMODE_64BIT: \
4723 { \
4724 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
4725 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4726 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4); \
4727 \
4728 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm); \
4729 IEMOP_HLP_DONE_DECODING(); \
4730 \
4731 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4732 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
4733 IEM_MC_MEM_MAP_U64_ATOMIC(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4734 \
4735 IEM_MC_ARG_CONST(uint64_t, u64Src, u64Imm, 1); \
4736 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4737 IEM_MC_FETCH_EFLAGS(EFlags); \
4738 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64_locked), pu64Dst, u64Src, pEFlags); \
4739 \
4740 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
4741 IEM_MC_COMMIT_EFLAGS(EFlags); \
4742 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4743 IEM_MC_END(); \
4744 break; \
4745 } \
4746 \
4747 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
4748 } \
4749 } \
4750 } \
4751 (void)0
4752
4753/* read-only version */
4754#define IEMOP_BODY_BINARY_Ev_Iz_RO(a_InsNm, a_fNativeArchs) \
4755 if (IEM_IS_MODRM_REG_MODE(bRm)) \
4756 { \
4757 /* register target */ \
4758 switch (pVCpu->iem.s.enmEffOpSize) \
4759 { \
4760 case IEMMODE_16BIT: \
4761 { \
4762 IEM_MC_BEGIN(3, 2, 0, 0); \
4763 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm); \
4764 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
4765 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
4766 IEM_MC_LOCAL(uint16_t, u16Dst); \
4767 IEM_MC_FETCH_GREG_U16(u16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4768 IEM_MC_LOCAL(uint32_t, uEFlags); \
4769 IEM_MC_FETCH_EFLAGS(uEFlags); \
4770 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u16Dst, u16Imm, uEFlags, 16, 16); \
4771 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4772 } IEM_MC_NATIVE_ELSE() { \
4773 IEM_MC_ARG(uint16_t const *,pu16Dst, 0); \
4774 IEM_MC_REF_GREG_U16_CONST(pu16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4775 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
4776 IEM_MC_REF_EFLAGS(pEFlags); \
4777 IEM_MC_ARG_CONST(uint16_t, u16Src, /*=*/ u16Imm, 1); \
4778 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
4779 } IEM_MC_NATIVE_ENDIF(); \
4780 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4781 IEM_MC_END(); \
4782 break; \
4783 } \
4784 \
4785 case IEMMODE_32BIT: \
4786 { \
4787 IEM_MC_BEGIN(3, 2, IEM_MC_F_MIN_386, 0); \
4788 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm); \
4789 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
4790 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
4791 IEM_MC_LOCAL(uint32_t, u32Dst); \
4792 IEM_MC_FETCH_GREG_U32(u32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4793 IEM_MC_LOCAL(uint32_t, uEFlags); \
4794 IEM_MC_FETCH_EFLAGS(uEFlags); \
4795 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u32Dst, u32Imm, uEFlags, 32, 32); \
4796 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4797 } IEM_MC_NATIVE_ELSE() { \
4798 IEM_MC_ARG(uint32_t const *,pu32Dst, 0); \
4799 IEM_MC_REF_GREG_U32_CONST (pu32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4800 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
4801 IEM_MC_REF_EFLAGS(pEFlags); \
4802 IEM_MC_ARG_CONST(uint32_t, u32Src, /*=*/ u32Imm, 1); \
4803 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
4804 } IEM_MC_NATIVE_ENDIF(); \
4805 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4806 IEM_MC_END(); \
4807 break; \
4808 } \
4809 \
4810 case IEMMODE_64BIT: \
4811 { \
4812 IEM_MC_BEGIN(3, 2, IEM_MC_F_64BIT, 0); \
4813 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm); \
4814 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
4815 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
4816 IEM_MC_LOCAL(uint64_t, u64Dst); \
4817 IEM_MC_FETCH_GREG_U64(u64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4818 IEM_MC_LOCAL(uint32_t, uEFlags); \
4819 IEM_MC_FETCH_EFLAGS(uEFlags); \
4820 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u64Dst, u64Imm, uEFlags, 64, 32); \
4821 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4822 } IEM_MC_NATIVE_ELSE() { \
4823 IEM_MC_ARG(uint64_t const *,pu64Dst, 0); \
4824 IEM_MC_REF_GREG_U64_CONST(pu64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
4825 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
4826 IEM_MC_REF_EFLAGS(pEFlags); \
4827 IEM_MC_ARG_CONST(uint64_t, u64Src, /*=*/ u64Imm, 1); \
4828 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
4829 } IEM_MC_NATIVE_ENDIF(); \
4830 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4831 IEM_MC_END(); \
4832 break; \
4833 } \
4834 \
4835 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
4836 } \
4837 } \
4838 else \
4839 { \
4840 /* memory target */ \
4841 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
4842 { \
4843 switch (pVCpu->iem.s.enmEffOpSize) \
4844 { \
4845 case IEMMODE_16BIT: \
4846 { \
4847 IEM_MC_BEGIN(3, 3, 0, 0); \
4848 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4849 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 2); \
4850 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm); \
4851 IEMOP_HLP_DONE_DECODING(); \
4852 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
4853 IEM_MC_LOCAL(uint16_t, u16Dst); \
4854 IEM_MC_FETCH_MEM_U16(u16Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4855 IEM_MC_LOCAL(uint32_t, uEFlags); \
4856 IEM_MC_FETCH_EFLAGS(uEFlags); \
4857 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u16Dst, u16Imm, uEFlags, 16, 16); \
4858 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4859 } IEM_MC_NATIVE_ELSE() { \
4860 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4861 IEM_MC_ARG(uint16_t const *, pu16Dst, 0); \
4862 IEM_MC_MEM_MAP_U16_RO(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4863 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4864 IEM_MC_FETCH_EFLAGS(EFlags); \
4865 IEM_MC_ARG_CONST(uint16_t, u16Src, u16Imm, 1); \
4866 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
4867 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
4868 IEM_MC_COMMIT_EFLAGS(EFlags); \
4869 } IEM_MC_NATIVE_ENDIF(); \
4870 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4871 IEM_MC_END(); \
4872 break; \
4873 } \
4874 \
4875 case IEMMODE_32BIT: \
4876 { \
4877 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
4878 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4879 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4); \
4880 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm); \
4881 IEMOP_HLP_DONE_DECODING(); \
4882 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
4883 IEM_MC_LOCAL(uint32_t, u32Dst); \
4884 IEM_MC_FETCH_MEM_U32(u32Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4885 IEM_MC_LOCAL(uint32_t, uEFlags); \
4886 IEM_MC_FETCH_EFLAGS(uEFlags); \
4887 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u32Dst, u32Imm, uEFlags, 32, 32); \
4888 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4889 } IEM_MC_NATIVE_ELSE() { \
4890 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4891 IEM_MC_ARG(uint32_t const *, pu32Dst, 0); \
4892 IEM_MC_MEM_MAP_U32_RO(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4893 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4894 IEM_MC_FETCH_EFLAGS(EFlags); \
4895 IEM_MC_ARG_CONST(uint32_t, u32Src, u32Imm, 1); \
4896 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
4897 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
4898 IEM_MC_COMMIT_EFLAGS(EFlags); \
4899 } IEM_MC_NATIVE_ENDIF(); \
4900 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4901 IEM_MC_END(); \
4902 break; \
4903 } \
4904 \
4905 case IEMMODE_64BIT: \
4906 { \
4907 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
4908 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
4909 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4); \
4910 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm); \
4911 IEMOP_HLP_DONE_DECODING(); \
4912 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
4913 IEM_MC_LOCAL(uint64_t, u64Dst); \
4914 IEM_MC_FETCH_MEM_U64(u64Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4915 IEM_MC_LOCAL(uint32_t, uEFlags); \
4916 IEM_MC_FETCH_EFLAGS(uEFlags); \
4917 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u64Dst, u64Imm, uEFlags, 64, 32); \
4918 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
4919 } IEM_MC_NATIVE_ELSE() { \
4920 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
4921 IEM_MC_ARG(uint64_t const *, pu64Dst, 0); \
4922 IEM_MC_MEM_MAP_U64_RO(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
4923 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
4924 IEM_MC_FETCH_EFLAGS(EFlags); \
4925 IEM_MC_ARG_CONST(uint64_t, u64Src, u64Imm, 1); \
4926 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
4927 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
4928 IEM_MC_COMMIT_EFLAGS(EFlags); \
4929 } IEM_MC_NATIVE_ENDIF(); \
4930 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
4931 IEM_MC_END(); \
4932 break; \
4933 } \
4934 \
4935 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
4936 } \
4937 } \
4938 else \
4939 { \
4940 IEMOP_HLP_DONE_DECODING(); \
4941 IEMOP_RAISE_INVALID_LOCK_PREFIX_RET(); \
4942 } \
4943 } \
4944 (void)0
4945
4946
4947/**
4948 * @opmaps grp1_81
4949 * @opcode /0
4950 * @opflclass arithmetic
4951 */
4952FNIEMOP_DEF_1(iemOp_Grp1_add_Ev_Iz, uint8_t, bRm)
4953{
4954 IEMOP_MNEMONIC(add_Ev_Iz, "add Ev,Iz");
4955 IEMOP_BODY_BINARY_Ev_Iz_RW(add, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4956}
4957
4958
4959/**
4960 * @opmaps grp1_81
4961 * @opcode /1
4962 * @opflclass logical
4963 */
4964FNIEMOP_DEF_1(iemOp_Grp1_or_Ev_Iz, uint8_t, bRm)
4965{
4966 IEMOP_MNEMONIC(or_Ev_Iz, "or Ev,Iz");
4967 IEMOP_BODY_BINARY_Ev_Iz_RW(or, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4968}
4969
4970
4971/**
4972 * @opmaps grp1_81
4973 * @opcode /2
4974 * @opflclass arithmetic_carry
4975 */
4976FNIEMOP_DEF_1(iemOp_Grp1_adc_Ev_Iz, uint8_t, bRm)
4977{
4978 IEMOP_MNEMONIC(adc_Ev_Iz, "adc Ev,Iz");
4979 IEMOP_BODY_BINARY_Ev_Iz_RW(adc, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4980}
4981
4982
4983/**
4984 * @opmaps grp1_81
4985 * @opcode /3
4986 * @opflclass arithmetic_carry
4987 */
4988FNIEMOP_DEF_1(iemOp_Grp1_sbb_Ev_Iz, uint8_t, bRm)
4989{
4990 IEMOP_MNEMONIC(sbb_Ev_Iz, "sbb Ev,Iz");
4991 IEMOP_BODY_BINARY_Ev_Iz_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
4992}
4993
4994
4995/**
4996 * @opmaps grp1_81
4997 * @opcode /4
4998 * @opflclass logical
4999 */
5000FNIEMOP_DEF_1(iemOp_Grp1_and_Ev_Iz, uint8_t, bRm)
5001{
5002 IEMOP_MNEMONIC(and_Ev_Iz, "and Ev,Iz");
5003 IEMOP_BODY_BINARY_Ev_Iz_RW(and, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5004}
5005
5006
5007/**
5008 * @opmaps grp1_81
5009 * @opcode /5
5010 * @opflclass arithmetic
5011 */
5012FNIEMOP_DEF_1(iemOp_Grp1_sub_Ev_Iz, uint8_t, bRm)
5013{
5014 IEMOP_MNEMONIC(sub_Ev_Iz, "sub Ev,Iz");
5015 IEMOP_BODY_BINARY_Ev_Iz_RW(sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5016}
5017
5018
5019/**
5020 * @opmaps grp1_81
5021 * @opcode /6
5022 * @opflclass logical
5023 */
5024FNIEMOP_DEF_1(iemOp_Grp1_xor_Ev_Iz, uint8_t, bRm)
5025{
5026 IEMOP_MNEMONIC(xor_Ev_Iz, "xor Ev,Iz");
5027 IEMOP_BODY_BINARY_Ev_Iz_RW(xor, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5028}
5029
5030
5031/**
5032 * @opmaps grp1_81
5033 * @opcode /7
5034 * @opflclass arithmetic
5035 */
5036FNIEMOP_DEF_1(iemOp_Grp1_cmp_Ev_Iz, uint8_t, bRm)
5037{
5038 IEMOP_MNEMONIC(cmp_Ev_Iz, "cmp Ev,Iz");
5039 IEMOP_BODY_BINARY_Ev_Iz_RO(cmp, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
5040}
5041
5042
5043/**
5044 * @opcode 0x81
5045 */
5046FNIEMOP_DEF(iemOp_Grp1_Ev_Iz)
5047{
5048 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
5049 switch (IEM_GET_MODRM_REG_8(bRm))
5050 {
5051 case 0: return FNIEMOP_CALL_1(iemOp_Grp1_add_Ev_Iz, bRm);
5052 case 1: return FNIEMOP_CALL_1(iemOp_Grp1_or_Ev_Iz, bRm);
5053 case 2: return FNIEMOP_CALL_1(iemOp_Grp1_adc_Ev_Iz, bRm);
5054 case 3: return FNIEMOP_CALL_1(iemOp_Grp1_sbb_Ev_Iz, bRm);
5055 case 4: return FNIEMOP_CALL_1(iemOp_Grp1_and_Ev_Iz, bRm);
5056 case 5: return FNIEMOP_CALL_1(iemOp_Grp1_sub_Ev_Iz, bRm);
5057 case 6: return FNIEMOP_CALL_1(iemOp_Grp1_xor_Ev_Iz, bRm);
5058 case 7: return FNIEMOP_CALL_1(iemOp_Grp1_cmp_Ev_Iz, bRm);
5059 IEM_NOT_REACHED_DEFAULT_CASE_RET();
5060 }
5061}
5062
5063
5064/**
5065 * @opcode 0x82
5066 * @opmnemonic grp1_82
5067 * @opgroup og_groups
5068 */
5069FNIEMOP_DEF(iemOp_Grp1_Eb_Ib_82)
5070{
5071 IEMOP_HLP_NO_64BIT(); /** @todo do we need to decode the whole instruction or is this ok? */
5072 return FNIEMOP_CALL(iemOp_Grp1_Eb_Ib_80);
5073}
5074
5075
5076/**
5077 * Body for group 1 instruction (binary) w/ byte imm operand, dispatched via
5078 * iemOp_Grp1_Ev_Ib.
5079 */
5080#define IEMOP_BODY_BINARY_Ev_Ib_RW(a_InsNm, a_fRegNativeArchs, a_fMemNativeArchs) \
5081 if (IEM_IS_MODRM_REG_MODE(bRm)) \
5082 { \
5083 /* \
5084 * Register target \
5085 */ \
5086 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); /* Not sign extending it here saves threaded function param space. */ \
5087 switch (pVCpu->iem.s.enmEffOpSize) \
5088 { \
5089 case IEMMODE_16BIT: \
5090 IEM_MC_BEGIN(3, 0, 0, 0); \
5091 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
5092 IEM_MC_NATIVE_IF(a_fRegNativeArchs) { \
5093 IEM_MC_LOCAL(uint16_t, u16Dst); \
5094 IEM_MC_FETCH_GREG_U16(u16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5095 IEM_MC_LOCAL(uint32_t, uEFlags); \
5096 IEM_MC_FETCH_EFLAGS(uEFlags); \
5097 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u16Dst, (uint16_t)(int16_t)(int8_t)u8Imm, uEFlags, 16, 8); \
5098 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_RM(pVCpu, bRm), u16Dst); \
5099 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
5100 } IEM_MC_NATIVE_ELSE() { \
5101 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
5102 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5103 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
5104 IEM_MC_REF_EFLAGS(pEFlags); \
5105 IEM_MC_ARG_CONST(uint16_t, u16Src, /*=*/ (uint16_t)(int16_t)(int8_t)u8Imm, 1); \
5106 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
5107 } IEM_MC_NATIVE_ENDIF(); \
5108 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5109 IEM_MC_END(); \
5110 break; \
5111 \
5112 case IEMMODE_32BIT: \
5113 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_386, 0); \
5114 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
5115 IEM_MC_NATIVE_IF(a_fRegNativeArchs) { \
5116 IEM_MC_LOCAL(uint32_t, u32Dst); \
5117 IEM_MC_FETCH_GREG_U32(u32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5118 IEM_MC_LOCAL(uint32_t, uEFlags); \
5119 IEM_MC_FETCH_EFLAGS(uEFlags); \
5120 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u32Dst, (uint32_t)(int32_t)(int8_t)u8Imm, uEFlags, 32, 8); \
5121 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_RM(pVCpu, bRm), u32Dst); \
5122 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
5123 } IEM_MC_NATIVE_ELSE() { \
5124 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
5125 IEM_MC_REF_GREG_U32(pu32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5126 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
5127 IEM_MC_REF_EFLAGS(pEFlags); \
5128 IEM_MC_ARG_CONST(uint32_t, u32Src, /*=*/ (uint32_t)(int32_t)(int8_t)u8Imm, 1); \
5129 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
5130 IEM_MC_CLEAR_HIGH_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm)); \
5131 } IEM_MC_NATIVE_ENDIF(); \
5132 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5133 IEM_MC_END(); \
5134 break; \
5135 \
5136 case IEMMODE_64BIT: \
5137 IEM_MC_BEGIN(3, 0, IEM_MC_F_64BIT, 0); \
5138 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
5139 IEM_MC_NATIVE_IF(a_fRegNativeArchs) { \
5140 IEM_MC_LOCAL(uint64_t, u64Dst); \
5141 IEM_MC_FETCH_GREG_U64(u64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5142 IEM_MC_LOCAL(uint32_t, uEFlags); \
5143 IEM_MC_FETCH_EFLAGS(uEFlags); \
5144 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u64Dst, (uint64_t)(int64_t)(int8_t)u8Imm, uEFlags, 64, 8); \
5145 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm), u64Dst); \
5146 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
5147 } IEM_MC_NATIVE_ELSE() { \
5148 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
5149 IEM_MC_REF_GREG_U64(pu64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5150 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
5151 IEM_MC_REF_EFLAGS(pEFlags); \
5152 IEM_MC_ARG_CONST(uint64_t, u64Src, /*=*/ (uint64_t)(int64_t)(int8_t)u8Imm, 1); \
5153 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
5154 } IEM_MC_NATIVE_ENDIF(); \
5155 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5156 IEM_MC_END(); \
5157 break; \
5158 \
5159 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
5160 } \
5161 } \
5162 else \
5163 { \
5164 /* \
5165 * Memory target. \
5166 */ \
5167 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
5168 { \
5169 switch (pVCpu->iem.s.enmEffOpSize) \
5170 { \
5171 case IEMMODE_16BIT: \
5172 IEM_MC_BEGIN(3, 3, 0, 0); \
5173 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5174 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
5175 \
5176 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
5177 IEMOP_HLP_DONE_DECODING(); \
5178 \
5179 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5180 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
5181 IEM_MC_MEM_MAP_U16_RW(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5182 \
5183 IEM_MC_ARG_CONST(uint16_t, u16Src, (uint16_t)(int16_t)(int8_t)u8Imm, 1); \
5184 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
5185 IEM_MC_FETCH_EFLAGS(EFlags); \
5186 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
5187 \
5188 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
5189 IEM_MC_COMMIT_EFLAGS(EFlags); \
5190 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5191 IEM_MC_END(); \
5192 break; \
5193 \
5194 case IEMMODE_32BIT: \
5195 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
5196 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5197 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
5198 \
5199 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
5200 IEMOP_HLP_DONE_DECODING(); \
5201 \
5202 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5203 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
5204 IEM_MC_MEM_MAP_U32_RW(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5205 \
5206 IEM_MC_ARG_CONST(uint32_t, u32Src, (uint32_t)(int32_t)(int8_t)u8Imm, 1); \
5207 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
5208 IEM_MC_FETCH_EFLAGS(EFlags); \
5209 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
5210 \
5211 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
5212 IEM_MC_COMMIT_EFLAGS(EFlags); \
5213 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5214 IEM_MC_END(); \
5215 break; \
5216 \
5217 case IEMMODE_64BIT: \
5218 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
5219 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5220 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
5221 \
5222 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
5223 IEMOP_HLP_DONE_DECODING(); \
5224 \
5225 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5226 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
5227 IEM_MC_MEM_MAP_U64_RW(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5228 \
5229 IEM_MC_ARG_CONST(uint64_t, u64Src, (uint64_t)(int64_t)(int8_t)u8Imm, 1); \
5230 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
5231 IEM_MC_FETCH_EFLAGS(EFlags); \
5232 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
5233 \
5234 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
5235 IEM_MC_COMMIT_EFLAGS(EFlags); \
5236 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5237 IEM_MC_END(); \
5238 break; \
5239 \
5240 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
5241 } \
5242 } \
5243 else \
5244 { \
5245 switch (pVCpu->iem.s.enmEffOpSize) \
5246 { \
5247 case IEMMODE_16BIT: \
5248 IEM_MC_BEGIN(3, 3, 0, 0); \
5249 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5250 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
5251 \
5252 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
5253 IEMOP_HLP_DONE_DECODING(); \
5254 \
5255 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5256 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
5257 IEM_MC_MEM_MAP_U16_ATOMIC(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5258 \
5259 IEM_MC_ARG_CONST(uint16_t, u16Src, (uint16_t)(int16_t)(int8_t)u8Imm, 1); \
5260 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
5261 IEM_MC_FETCH_EFLAGS(EFlags); \
5262 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16_locked), pu16Dst, u16Src, pEFlags); \
5263 \
5264 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
5265 IEM_MC_COMMIT_EFLAGS(EFlags); \
5266 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5267 IEM_MC_END(); \
5268 break; \
5269 \
5270 case IEMMODE_32BIT: \
5271 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
5272 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5273 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
5274 \
5275 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
5276 IEMOP_HLP_DONE_DECODING(); \
5277 \
5278 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5279 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
5280 IEM_MC_MEM_MAP_U32_ATOMIC(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5281 \
5282 IEM_MC_ARG_CONST(uint32_t, u32Src, (uint32_t)(int32_t)(int8_t)u8Imm, 1); \
5283 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
5284 IEM_MC_FETCH_EFLAGS(EFlags); \
5285 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32_locked), pu32Dst, u32Src, pEFlags); \
5286 \
5287 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
5288 IEM_MC_COMMIT_EFLAGS(EFlags); \
5289 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5290 IEM_MC_END(); \
5291 break; \
5292 \
5293 case IEMMODE_64BIT: \
5294 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
5295 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5296 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
5297 \
5298 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
5299 IEMOP_HLP_DONE_DECODING(); \
5300 \
5301 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5302 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
5303 IEM_MC_MEM_MAP_U64_ATOMIC(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5304 \
5305 IEM_MC_ARG_CONST(uint64_t, u64Src, (uint64_t)(int64_t)(int8_t)u8Imm, 1); \
5306 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
5307 IEM_MC_FETCH_EFLAGS(EFlags); \
5308 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64_locked), pu64Dst, u64Src, pEFlags); \
5309 \
5310 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
5311 IEM_MC_COMMIT_EFLAGS(EFlags); \
5312 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5313 IEM_MC_END(); \
5314 break; \
5315 \
5316 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
5317 } \
5318 } \
5319 } \
5320 (void)0
5321
5322/* read-only variant */
5323#define IEMOP_BODY_BINARY_Ev_Ib_RO(a_InsNm, a_fNativeArchs) \
5324 if (IEM_IS_MODRM_REG_MODE(bRm)) \
5325 { \
5326 /* \
5327 * Register target \
5328 */ \
5329 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); /* Not sign extending it here saves threaded function param space. */ \
5330 switch (pVCpu->iem.s.enmEffOpSize) \
5331 { \
5332 case IEMMODE_16BIT: \
5333 IEM_MC_BEGIN(3, 0, 0, 0); \
5334 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
5335 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
5336 IEM_MC_LOCAL(uint16_t, u16Dst); \
5337 IEM_MC_FETCH_GREG_U16(u16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5338 IEM_MC_LOCAL(uint32_t, uEFlags); \
5339 IEM_MC_FETCH_EFLAGS(uEFlags); \
5340 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u16Dst, (uint16_t)(int16_t)(int8_t)u8Imm, uEFlags, 16, 8); \
5341 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
5342 } IEM_MC_NATIVE_ELSE() { \
5343 IEM_MC_ARG(uint16_t const *, pu16Dst, 0); \
5344 IEM_MC_REF_GREG_U16_CONST(pu16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5345 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
5346 IEM_MC_ARG_CONST(uint16_t, u16Src, /*=*/ (uint16_t)(int16_t)(int8_t)u8Imm, 1); \
5347 IEM_MC_REF_EFLAGS(pEFlags); \
5348 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
5349 } IEM_MC_NATIVE_ENDIF(); \
5350 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5351 IEM_MC_END(); \
5352 break; \
5353 \
5354 case IEMMODE_32BIT: \
5355 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_386, 0); \
5356 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
5357 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
5358 IEM_MC_LOCAL(uint32_t, u32Dst); \
5359 IEM_MC_FETCH_GREG_U32(u32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5360 IEM_MC_LOCAL(uint32_t, uEFlags); \
5361 IEM_MC_FETCH_EFLAGS(uEFlags); \
5362 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u32Dst, (uint32_t)(int32_t)(int8_t)u8Imm, uEFlags, 32, 8); \
5363 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
5364 } IEM_MC_NATIVE_ELSE() { \
5365 IEM_MC_ARG(uint32_t const *, pu32Dst, 0); \
5366 IEM_MC_REF_GREG_U32_CONST(pu32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5367 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
5368 IEM_MC_REF_EFLAGS(pEFlags); \
5369 IEM_MC_ARG_CONST(uint32_t, u32Src, /*=*/ (uint32_t)(int32_t)(int8_t)u8Imm, 1); \
5370 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
5371 } IEM_MC_NATIVE_ENDIF(); \
5372 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5373 IEM_MC_END(); \
5374 break; \
5375 \
5376 case IEMMODE_64BIT: \
5377 IEM_MC_BEGIN(3, 0, IEM_MC_F_64BIT, 0); \
5378 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
5379 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
5380 IEM_MC_LOCAL(uint64_t, u64Dst); \
5381 IEM_MC_FETCH_GREG_U64(u64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5382 IEM_MC_LOCAL(uint32_t, uEFlags); \
5383 IEM_MC_FETCH_EFLAGS(uEFlags); \
5384 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u64Dst, (uint64_t)(int64_t)(int8_t)u8Imm, uEFlags, 64, 8); \
5385 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
5386 } IEM_MC_NATIVE_ELSE() { \
5387 IEM_MC_ARG(uint64_t const *, pu64Dst, 0); \
5388 IEM_MC_REF_GREG_U64_CONST(pu64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
5389 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
5390 IEM_MC_REF_EFLAGS(pEFlags); \
5391 IEM_MC_ARG_CONST(uint64_t, u64Src, /*=*/ (uint64_t)(int64_t)(int8_t)u8Imm, 1); \
5392 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
5393 } IEM_MC_NATIVE_ENDIF(); \
5394 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5395 IEM_MC_END(); \
5396 break; \
5397 \
5398 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
5399 } \
5400 } \
5401 else \
5402 { \
5403 /* \
5404 * Memory target. \
5405 */ \
5406 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
5407 { \
5408 switch (pVCpu->iem.s.enmEffOpSize) \
5409 { \
5410 case IEMMODE_16BIT: \
5411 IEM_MC_BEGIN(3, 3, 0, 0); \
5412 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5413 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
5414 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
5415 IEMOP_HLP_DONE_DECODING(); \
5416 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
5417 IEM_MC_LOCAL(uint16_t, u16Dst); \
5418 IEM_MC_FETCH_MEM_U16(u16Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5419 IEM_MC_LOCAL(uint32_t, uEFlags); \
5420 IEM_MC_FETCH_EFLAGS(uEFlags); \
5421 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u16Dst, (uint16_t)(int16_t)(int8_t)u8Imm, uEFlags, 16, 8); \
5422 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
5423 } IEM_MC_NATIVE_ELSE() { \
5424 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5425 IEM_MC_ARG(uint16_t const *, pu16Dst, 0); \
5426 IEM_MC_MEM_MAP_U16_RO(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5427 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
5428 IEM_MC_FETCH_EFLAGS(EFlags); \
5429 IEM_MC_ARG_CONST(uint16_t, u16Src, (uint16_t)(int16_t)(int8_t)u8Imm, 1); \
5430 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u16), pu16Dst, u16Src, pEFlags); \
5431 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
5432 IEM_MC_COMMIT_EFLAGS(EFlags); \
5433 } IEM_MC_NATIVE_ENDIF(); \
5434 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5435 IEM_MC_END(); \
5436 break; \
5437 \
5438 case IEMMODE_32BIT: \
5439 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
5440 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5441 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
5442 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
5443 IEMOP_HLP_DONE_DECODING(); \
5444 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
5445 IEM_MC_LOCAL(uint32_t, u32Dst); \
5446 IEM_MC_FETCH_MEM_U32(u32Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5447 IEM_MC_LOCAL(uint32_t, uEFlags); \
5448 IEM_MC_FETCH_EFLAGS(uEFlags); \
5449 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u32Dst, (uint32_t)(int32_t)(int8_t)u8Imm, uEFlags, 32, 8); \
5450 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
5451 } IEM_MC_NATIVE_ELSE() { \
5452 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5453 IEM_MC_ARG(uint32_t const *, pu32Dst, 0); \
5454 IEM_MC_MEM_MAP_U32_RO(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5455 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
5456 IEM_MC_FETCH_EFLAGS(EFlags); \
5457 IEM_MC_ARG_CONST(uint32_t, u32Src, (uint32_t)(int32_t)(int8_t)u8Imm, 1); \
5458 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u32), pu32Dst, u32Src, pEFlags); \
5459 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
5460 IEM_MC_COMMIT_EFLAGS(EFlags); \
5461 } IEM_MC_NATIVE_ENDIF(); \
5462 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5463 IEM_MC_END(); \
5464 break; \
5465 \
5466 case IEMMODE_64BIT: \
5467 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
5468 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5469 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
5470 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm); \
5471 IEMOP_HLP_DONE_DECODING(); \
5472 IEM_MC_NATIVE_IF(a_fNativeArchs) { \
5473 IEM_MC_LOCAL(uint64_t, u64Dst); \
5474 IEM_MC_FETCH_MEM_U64(u64Dst, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5475 IEM_MC_LOCAL(uint32_t, uEFlags); \
5476 IEM_MC_FETCH_EFLAGS(uEFlags); \
5477 IEM_MC_NATIVE_EMIT_5(RT_CONCAT3(iemNativeEmit_,a_InsNm,_r_i_efl), u64Dst, (uint64_t)(int64_t)(int8_t)u8Imm, uEFlags, 64, 8); \
5478 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags); \
5479 } IEM_MC_NATIVE_ELSE() { \
5480 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5481 IEM_MC_ARG(uint64_t const *, pu64Dst, 0); \
5482 IEM_MC_MEM_MAP_U64_RO(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5483 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
5484 IEM_MC_FETCH_EFLAGS(EFlags); \
5485 IEM_MC_ARG_CONST(uint64_t, u64Src, (uint64_t)(int64_t)(int8_t)u8Imm, 1); \
5486 IEM_MC_CALL_VOID_AIMPL_3(RT_CONCAT3(iemAImpl_,a_InsNm,_u64), pu64Dst, u64Src, pEFlags); \
5487 IEM_MC_MEM_COMMIT_AND_UNMAP_RO(bUnmapInfo); \
5488 IEM_MC_COMMIT_EFLAGS(EFlags); \
5489 } IEM_MC_NATIVE_ENDIF(); \
5490 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5491 IEM_MC_END(); \
5492 break; \
5493 \
5494 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
5495 } \
5496 } \
5497 else \
5498 { \
5499 IEMOP_HLP_DONE_DECODING(); \
5500 IEMOP_RAISE_INVALID_LOCK_PREFIX_RET(); \
5501 } \
5502 } \
5503 (void)0
5504
5505/**
5506 * @opmaps grp1_83
5507 * @opcode /0
5508 * @opflclass arithmetic
5509 */
5510FNIEMOP_DEF_1(iemOp_Grp1_add_Ev_Ib, uint8_t, bRm)
5511{
5512 IEMOP_MNEMONIC(add_Ev_Ib, "add Ev,Ib");
5513 IEMOP_BODY_BINARY_Ev_Ib_RW(add, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5514}
5515
5516
5517/**
5518 * @opmaps grp1_83
5519 * @opcode /1
5520 * @opflclass logical
5521 */
5522FNIEMOP_DEF_1(iemOp_Grp1_or_Ev_Ib, uint8_t, bRm)
5523{
5524 IEMOP_MNEMONIC(or_Ev_Ib, "or Ev,Ib");
5525 IEMOP_BODY_BINARY_Ev_Ib_RW(or, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5526}
5527
5528
5529/**
5530 * @opmaps grp1_83
5531 * @opcode /2
5532 * @opflclass arithmetic_carry
5533 */
5534FNIEMOP_DEF_1(iemOp_Grp1_adc_Ev_Ib, uint8_t, bRm)
5535{
5536 IEMOP_MNEMONIC(adc_Ev_Ib, "adc Ev,Ib");
5537 IEMOP_BODY_BINARY_Ev_Ib_RW(adc, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5538}
5539
5540
5541/**
5542 * @opmaps grp1_83
5543 * @opcode /3
5544 * @opflclass arithmetic_carry
5545 */
5546FNIEMOP_DEF_1(iemOp_Grp1_sbb_Ev_Ib, uint8_t, bRm)
5547{
5548 IEMOP_MNEMONIC(sbb_Ev_Ib, "sbb Ev,Ib");
5549 IEMOP_BODY_BINARY_Ev_Ib_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5550}
5551
5552
5553/**
5554 * @opmaps grp1_83
5555 * @opcode /4
5556 * @opflclass logical
5557 */
5558FNIEMOP_DEF_1(iemOp_Grp1_and_Ev_Ib, uint8_t, bRm)
5559{
5560 IEMOP_MNEMONIC(and_Ev_Ib, "and Ev,Ib");
5561 IEMOP_BODY_BINARY_Ev_Ib_RW(and, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5562}
5563
5564
5565/**
5566 * @opmaps grp1_83
5567 * @opcode /5
5568 * @opflclass arithmetic
5569 */
5570FNIEMOP_DEF_1(iemOp_Grp1_sub_Ev_Ib, uint8_t, bRm)
5571{
5572 IEMOP_MNEMONIC(sub_Ev_Ib, "sub Ev,Ib");
5573 IEMOP_BODY_BINARY_Ev_Ib_RW(sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5574}
5575
5576
5577/**
5578 * @opmaps grp1_83
5579 * @opcode /6
5580 * @opflclass logical
5581 */
5582FNIEMOP_DEF_1(iemOp_Grp1_xor_Ev_Ib, uint8_t, bRm)
5583{
5584 IEMOP_MNEMONIC(xor_Ev_Ib, "xor Ev,Ib");
5585 IEMOP_BODY_BINARY_Ev_Ib_RW(xor, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
5586}
5587
5588
5589/**
5590 * @opmaps grp1_83
5591 * @opcode /7
5592 * @opflclass arithmetic
5593 */
5594FNIEMOP_DEF_1(iemOp_Grp1_cmp_Ev_Ib, uint8_t, bRm)
5595{
5596 IEMOP_MNEMONIC(cmp_Ev_Ib, "cmp Ev,Ib");
5597 IEMOP_BODY_BINARY_Ev_Ib_RO(cmp, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
5598}
5599
5600
5601/**
5602 * @opcode 0x83
5603 */
5604FNIEMOP_DEF(iemOp_Grp1_Ev_Ib)
5605{
5606 /* Note! Seems the OR, AND, and XOR instructions are present on CPUs prior
5607 to the 386 even if absent in the intel reference manuals and some
5608 3rd party opcode listings. */
5609 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
5610 switch (IEM_GET_MODRM_REG_8(bRm))
5611 {
5612 case 0: return FNIEMOP_CALL_1(iemOp_Grp1_add_Ev_Ib, bRm);
5613 case 1: return FNIEMOP_CALL_1(iemOp_Grp1_or_Ev_Ib, bRm);
5614 case 2: return FNIEMOP_CALL_1(iemOp_Grp1_adc_Ev_Ib, bRm);
5615 case 3: return FNIEMOP_CALL_1(iemOp_Grp1_sbb_Ev_Ib, bRm);
5616 case 4: return FNIEMOP_CALL_1(iemOp_Grp1_and_Ev_Ib, bRm);
5617 case 5: return FNIEMOP_CALL_1(iemOp_Grp1_sub_Ev_Ib, bRm);
5618 case 6: return FNIEMOP_CALL_1(iemOp_Grp1_xor_Ev_Ib, bRm);
5619 case 7: return FNIEMOP_CALL_1(iemOp_Grp1_cmp_Ev_Ib, bRm);
5620 IEM_NOT_REACHED_DEFAULT_CASE_RET();
5621 }
5622}
5623
5624
5625/**
5626 * @opcode 0x84
5627 * @opflclass logical
5628 */
5629FNIEMOP_DEF(iemOp_test_Eb_Gb)
5630{
5631 IEMOP_MNEMONIC(test_Eb_Gb, "test Eb,Gb");
5632 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
5633
5634 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
5635
5636 /*
5637 * Deal with special case of 'test rN, rN' which is frequently used for testing for zero/non-zero registers.
5638 * This block only makes a differences when emitting native code, where we'll save a register fetch.
5639 */
5640 if ( (bRm >> X86_MODRM_REG_SHIFT) == ((bRm & X86_MODRM_RM_MASK) | (X86_MOD_REG << X86_MODRM_REG_SHIFT))
5641 && pVCpu->iem.s.uRexReg == pVCpu->iem.s.uRexB)
5642 {
5643 IEM_MC_BEGIN(3, 0, 0, 0);
5644 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
5645 IEM_MC_ARG(uint8_t, u8Src, 1);
5646 IEM_MC_FETCH_GREG_U8(u8Src, IEM_GET_MODRM_REG(pVCpu, bRm));
5647 IEM_MC_NATIVE_IF(RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64) {
5648 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */
5649 IEM_MC_LOCAL(uint32_t, uEFlags);
5650 IEM_MC_FETCH_EFLAGS(uEFlags);
5651 IEM_MC_NATIVE_EMIT_4(iemNativeEmit_test_r_r_efl, u8Src, u8Src, uEFlags, 8);
5652 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags);
5653 } IEM_MC_NATIVE_ELSE() {
5654 IEM_MC_ARG(uint8_t *, pu8Dst, 0);
5655 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_REG(pVCpu, bRm)); /* == IEM_GET_MODRM_RM(pVCpu, bRm) */
5656 IEM_MC_ARG(uint32_t *, pEFlags, 2);
5657 IEM_MC_REF_EFLAGS(pEFlags);
5658 IEM_MC_CALL_VOID_AIMPL_3(iemAImpl_test_u8, pu8Dst, u8Src, pEFlags);
5659 } IEM_MC_NATIVE_ENDIF();
5660 IEM_MC_ADVANCE_RIP_AND_FINISH();
5661 IEM_MC_END();
5662 }
5663
5664 IEMOP_BODY_BINARY_rm_r8_RO(bRm, iemAImpl_test_u8, test, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
5665}
5666
5667
5668/**
5669 * @opcode 0x85
5670 * @opflclass logical
5671 */
5672FNIEMOP_DEF(iemOp_test_Ev_Gv)
5673{
5674 IEMOP_MNEMONIC(test_Ev_Gv, "test Ev,Gv");
5675 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
5676
5677 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
5678
5679 /*
5680 * Deal with special case of 'test rN, rN' which is frequently used for testing for zero/non-zero registers.
5681 * This block only makes a differences when emitting native code, where we'll save a register fetch.
5682 */
5683 if ( (bRm >> X86_MODRM_REG_SHIFT) == ((bRm & X86_MODRM_RM_MASK) | (X86_MOD_REG << X86_MODRM_REG_SHIFT))
5684 && pVCpu->iem.s.uRexReg == pVCpu->iem.s.uRexB)
5685 {
5686 switch (pVCpu->iem.s.enmEffOpSize)
5687 {
5688 case IEMMODE_16BIT:
5689 IEM_MC_BEGIN(3, 0, 0, 0);
5690 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
5691 IEM_MC_ARG(uint16_t, u16Src, 1);
5692 IEM_MC_FETCH_GREG_U16(u16Src, IEM_GET_MODRM_REG(pVCpu, bRm));
5693 IEM_MC_NATIVE_IF(RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64) {
5694 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */
5695 IEM_MC_LOCAL(uint32_t, uEFlags);
5696 IEM_MC_FETCH_EFLAGS(uEFlags);
5697 IEM_MC_NATIVE_EMIT_4(iemNativeEmit_test_r_r_efl, u16Src, u16Src, uEFlags, 16);
5698 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags);
5699 } IEM_MC_NATIVE_ELSE() {
5700 IEM_MC_ARG(uint16_t *, pu16Dst, 0);
5701 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_REG(pVCpu, bRm)); /* == IEM_GET_MODRM_RM(pVCpu, bRm) */
5702 IEM_MC_ARG(uint32_t *, pEFlags, 2);
5703 IEM_MC_REF_EFLAGS(pEFlags);
5704 IEM_MC_CALL_VOID_AIMPL_3(iemAImpl_test_u16, pu16Dst, u16Src, pEFlags);
5705 } IEM_MC_NATIVE_ENDIF();
5706 IEM_MC_ADVANCE_RIP_AND_FINISH();
5707 IEM_MC_END();
5708 break;
5709
5710 case IEMMODE_32BIT:
5711 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_386, 0);
5712 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
5713 IEM_MC_ARG(uint32_t, u32Src, 1);
5714 IEM_MC_FETCH_GREG_U32(u32Src, IEM_GET_MODRM_REG(pVCpu, bRm));
5715 IEM_MC_NATIVE_IF(RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64) {
5716 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */
5717 IEM_MC_LOCAL(uint32_t, uEFlags);
5718 IEM_MC_FETCH_EFLAGS(uEFlags);
5719 IEM_MC_NATIVE_EMIT_4(iemNativeEmit_test_r_r_efl, u32Src, u32Src, uEFlags, 32);
5720 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags);
5721 } IEM_MC_NATIVE_ELSE() {
5722 IEM_MC_ARG(uint32_t *, pu32Dst, 0);
5723 IEM_MC_REF_GREG_U32(pu32Dst, IEM_GET_MODRM_REG(pVCpu, bRm)); /* == IEM_GET_MODRM_RM(pVCpu, bRm) */
5724 IEM_MC_ARG(uint32_t *, pEFlags, 2);
5725 IEM_MC_REF_EFLAGS(pEFlags);
5726 IEM_MC_CALL_VOID_AIMPL_3(iemAImpl_test_u32, pu32Dst, u32Src, pEFlags);
5727 } IEM_MC_NATIVE_ENDIF();
5728 IEM_MC_ADVANCE_RIP_AND_FINISH();
5729 IEM_MC_END();
5730 break;
5731
5732 case IEMMODE_64BIT:
5733 IEM_MC_BEGIN(3, 0, IEM_MC_F_64BIT, 0);
5734 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
5735 IEM_MC_ARG(uint64_t, u64Src, 1);
5736 IEM_MC_FETCH_GREG_U64(u64Src, IEM_GET_MODRM_REG(pVCpu, bRm));
5737 IEM_MC_NATIVE_IF(RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64) {
5738 /** @todo IEM_MC_LOCAL_EFLAGS(uEFlags); */
5739 IEM_MC_LOCAL(uint32_t, uEFlags);
5740 IEM_MC_FETCH_EFLAGS(uEFlags);
5741 IEM_MC_NATIVE_EMIT_4(iemNativeEmit_test_r_r_efl, u64Src, u64Src, uEFlags, 64);
5742 IEM_MC_COMMIT_EFLAGS_OPT(uEFlags);
5743 } IEM_MC_NATIVE_ELSE() {
5744 IEM_MC_ARG(uint64_t *, pu64Dst, 0);
5745 IEM_MC_REF_GREG_U64(pu64Dst, IEM_GET_MODRM_REG(pVCpu, bRm)); /* == IEM_GET_MODRM_RM(pVCpu, bRm) */
5746 IEM_MC_ARG(uint32_t *, pEFlags, 2);
5747 IEM_MC_REF_EFLAGS(pEFlags);
5748 IEM_MC_CALL_VOID_AIMPL_3(iemAImpl_test_u64, pu64Dst, u64Src, pEFlags);
5749 } IEM_MC_NATIVE_ENDIF();
5750 IEM_MC_ADVANCE_RIP_AND_FINISH();
5751 IEM_MC_END();
5752 break;
5753
5754 IEM_NOT_REACHED_DEFAULT_CASE_RET();
5755 }
5756 }
5757
5758 IEMOP_BODY_BINARY_rm_rv_RO(bRm, test, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
5759}
5760
5761
5762/**
5763 * @opcode 0x86
5764 */
5765FNIEMOP_DEF(iemOp_xchg_Eb_Gb)
5766{
5767 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
5768 IEMOP_MNEMONIC(xchg_Eb_Gb, "xchg Eb,Gb");
5769
5770 /*
5771 * If rm is denoting a register, no more instruction bytes.
5772 */
5773 if (IEM_IS_MODRM_REG_MODE(bRm))
5774 {
5775 IEM_MC_BEGIN(0, 2, 0, 0);
5776 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
5777 IEM_MC_LOCAL(uint8_t, uTmp1);
5778 IEM_MC_LOCAL(uint8_t, uTmp2);
5779
5780 IEM_MC_FETCH_GREG_U8(uTmp1, IEM_GET_MODRM_REG(pVCpu, bRm));
5781 IEM_MC_FETCH_GREG_U8(uTmp2, IEM_GET_MODRM_RM(pVCpu, bRm));
5782 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_RM(pVCpu, bRm), uTmp1);
5783 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_REG(pVCpu, bRm), uTmp2);
5784
5785 IEM_MC_ADVANCE_RIP_AND_FINISH();
5786 IEM_MC_END();
5787 }
5788 else
5789 {
5790 /*
5791 * We're accessing memory.
5792 */
5793#define IEMOP_XCHG_BYTE(a_fnWorker, a_Style) \
5794 IEM_MC_BEGIN(2, 4, 0, 0); \
5795 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5796 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5797 IEM_MC_LOCAL(uint8_t, uTmpReg); \
5798 IEM_MC_ARG(uint8_t *, pu8Mem, 0); \
5799 IEM_MC_ARG_LOCAL_REF(uint8_t *, pu8Reg, uTmpReg, 1); \
5800 \
5801 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
5802 IEMOP_HLP_DONE_DECODING(); /** @todo testcase: lock xchg */ \
5803 IEM_MC_MEM_MAP_U8_##a_Style(pu8Mem, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5804 IEM_MC_FETCH_GREG_U8(uTmpReg, IEM_GET_MODRM_REG(pVCpu, bRm)); \
5805 IEM_MC_CALL_VOID_AIMPL_2(a_fnWorker, pu8Mem, pu8Reg); \
5806 IEM_MC_MEM_COMMIT_AND_UNMAP_##a_Style(bUnmapInfo); \
5807 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_REG(pVCpu, bRm), uTmpReg); \
5808 \
5809 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5810 IEM_MC_END()
5811
5812 if (!(pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK))
5813 {
5814 IEMOP_XCHG_BYTE(iemAImpl_xchg_u8_locked,ATOMIC);
5815 }
5816 else
5817 {
5818 IEMOP_XCHG_BYTE(iemAImpl_xchg_u8_unlocked,RW);
5819 }
5820 }
5821}
5822
5823
5824/**
5825 * @opcode 0x87
5826 */
5827FNIEMOP_DEF(iemOp_xchg_Ev_Gv)
5828{
5829 IEMOP_MNEMONIC(xchg_Ev_Gv, "xchg Ev,Gv");
5830 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
5831
5832 /*
5833 * If rm is denoting a register, no more instruction bytes.
5834 */
5835 if (IEM_IS_MODRM_REG_MODE(bRm))
5836 {
5837 switch (pVCpu->iem.s.enmEffOpSize)
5838 {
5839 case IEMMODE_16BIT:
5840 IEM_MC_BEGIN(0, 2, 0, 0);
5841 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
5842 IEM_MC_LOCAL(uint16_t, uTmp1);
5843 IEM_MC_LOCAL(uint16_t, uTmp2);
5844
5845 IEM_MC_FETCH_GREG_U16(uTmp1, IEM_GET_MODRM_REG(pVCpu, bRm));
5846 IEM_MC_FETCH_GREG_U16(uTmp2, IEM_GET_MODRM_RM(pVCpu, bRm));
5847 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_RM(pVCpu, bRm), uTmp1);
5848 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_REG(pVCpu, bRm), uTmp2);
5849
5850 IEM_MC_ADVANCE_RIP_AND_FINISH();
5851 IEM_MC_END();
5852 break;
5853
5854 case IEMMODE_32BIT:
5855 IEM_MC_BEGIN(0, 2, IEM_MC_F_MIN_386, 0);
5856 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
5857 IEM_MC_LOCAL(uint32_t, uTmp1);
5858 IEM_MC_LOCAL(uint32_t, uTmp2);
5859
5860 IEM_MC_FETCH_GREG_U32(uTmp1, IEM_GET_MODRM_REG(pVCpu, bRm));
5861 IEM_MC_FETCH_GREG_U32(uTmp2, IEM_GET_MODRM_RM(pVCpu, bRm));
5862 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_RM(pVCpu, bRm), uTmp1);
5863 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_REG(pVCpu, bRm), uTmp2);
5864
5865 IEM_MC_ADVANCE_RIP_AND_FINISH();
5866 IEM_MC_END();
5867 break;
5868
5869 case IEMMODE_64BIT:
5870 IEM_MC_BEGIN(0, 2, IEM_MC_F_64BIT, 0);
5871 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
5872 IEM_MC_LOCAL(uint64_t, uTmp1);
5873 IEM_MC_LOCAL(uint64_t, uTmp2);
5874
5875 IEM_MC_FETCH_GREG_U64(uTmp1, IEM_GET_MODRM_REG(pVCpu, bRm));
5876 IEM_MC_FETCH_GREG_U64(uTmp2, IEM_GET_MODRM_RM(pVCpu, bRm));
5877 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm), uTmp1);
5878 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), uTmp2);
5879
5880 IEM_MC_ADVANCE_RIP_AND_FINISH();
5881 IEM_MC_END();
5882 break;
5883
5884 IEM_NOT_REACHED_DEFAULT_CASE_RET();
5885 }
5886 }
5887 else
5888 {
5889 /*
5890 * We're accessing memory.
5891 */
5892#define IEMOP_XCHG_EV_GV(a_fnWorker16, a_fnWorker32, a_fnWorker64, a_Type) \
5893 do { \
5894 switch (pVCpu->iem.s.enmEffOpSize) \
5895 { \
5896 case IEMMODE_16BIT: \
5897 IEM_MC_BEGIN(2, 4, 0, 0); \
5898 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5899 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5900 IEM_MC_LOCAL(uint16_t, uTmpReg); \
5901 IEM_MC_ARG(uint16_t *, pu16Mem, 0); \
5902 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Reg, uTmpReg, 1); \
5903 \
5904 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
5905 IEMOP_HLP_DONE_DECODING(); /** @todo testcase: lock xchg */ \
5906 IEM_MC_MEM_MAP_U16_##a_Type(pu16Mem, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5907 IEM_MC_FETCH_GREG_U16(uTmpReg, IEM_GET_MODRM_REG(pVCpu, bRm)); \
5908 IEM_MC_CALL_VOID_AIMPL_2(a_fnWorker16, pu16Mem, pu16Reg); \
5909 IEM_MC_MEM_COMMIT_AND_UNMAP_##a_Type(bUnmapInfo); \
5910 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_REG(pVCpu, bRm), uTmpReg); \
5911 \
5912 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5913 IEM_MC_END(); \
5914 break; \
5915 \
5916 case IEMMODE_32BIT: \
5917 IEM_MC_BEGIN(2, 4, IEM_MC_F_MIN_386, 0); \
5918 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5919 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5920 IEM_MC_LOCAL(uint32_t, uTmpReg); \
5921 IEM_MC_ARG(uint32_t *, pu32Mem, 0); \
5922 IEM_MC_ARG_LOCAL_REF(uint32_t *, pu32Reg, uTmpReg, 1); \
5923 \
5924 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
5925 IEMOP_HLP_DONE_DECODING(); \
5926 IEM_MC_MEM_MAP_U32_##a_Type(pu32Mem, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5927 IEM_MC_FETCH_GREG_U32(uTmpReg, IEM_GET_MODRM_REG(pVCpu, bRm)); \
5928 IEM_MC_CALL_VOID_AIMPL_2(a_fnWorker32, pu32Mem, pu32Reg); \
5929 IEM_MC_MEM_COMMIT_AND_UNMAP_##a_Type(bUnmapInfo); \
5930 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_REG(pVCpu, bRm), uTmpReg); \
5931 \
5932 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5933 IEM_MC_END(); \
5934 break; \
5935 \
5936 case IEMMODE_64BIT: \
5937 IEM_MC_BEGIN(2, 4, IEM_MC_F_64BIT, 0); \
5938 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
5939 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
5940 IEM_MC_LOCAL(uint64_t, uTmpReg); \
5941 IEM_MC_ARG(uint64_t *, pu64Mem, 0); \
5942 IEM_MC_ARG_LOCAL_REF(uint64_t *, pu64Reg, uTmpReg, 1); \
5943 \
5944 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
5945 IEMOP_HLP_DONE_DECODING(); \
5946 IEM_MC_MEM_MAP_U64_##a_Type(pu64Mem, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
5947 IEM_MC_FETCH_GREG_U64(uTmpReg, IEM_GET_MODRM_REG(pVCpu, bRm)); \
5948 IEM_MC_CALL_VOID_AIMPL_2(a_fnWorker64, pu64Mem, pu64Reg); \
5949 IEM_MC_MEM_COMMIT_AND_UNMAP_##a_Type(bUnmapInfo); \
5950 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), uTmpReg); \
5951 \
5952 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
5953 IEM_MC_END(); \
5954 break; \
5955 \
5956 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
5957 } \
5958 } while (0)
5959 if (!(pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK))
5960 {
5961 IEMOP_XCHG_EV_GV(iemAImpl_xchg_u16_locked, iemAImpl_xchg_u32_locked, iemAImpl_xchg_u64_locked,ATOMIC);
5962 }
5963 else
5964 {
5965 IEMOP_XCHG_EV_GV(iemAImpl_xchg_u16_unlocked, iemAImpl_xchg_u32_unlocked, iemAImpl_xchg_u64_unlocked,RW);
5966 }
5967 }
5968}
5969
5970
5971/**
5972 * @opcode 0x88
5973 */
5974FNIEMOP_DEF(iemOp_mov_Eb_Gb)
5975{
5976 IEMOP_MNEMONIC(mov_Eb_Gb, "mov Eb,Gb");
5977
5978 uint8_t bRm;
5979 IEM_OPCODE_GET_NEXT_U8(&bRm);
5980
5981 /*
5982 * If rm is denoting a register, no more instruction bytes.
5983 */
5984 if (IEM_IS_MODRM_REG_MODE(bRm))
5985 {
5986 IEM_MC_BEGIN(0, 1, 0, 0);
5987 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
5988 IEM_MC_LOCAL(uint8_t, u8Value);
5989 IEM_MC_FETCH_GREG_U8(u8Value, IEM_GET_MODRM_REG(pVCpu, bRm));
5990 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_RM(pVCpu, bRm), u8Value);
5991 IEM_MC_ADVANCE_RIP_AND_FINISH();
5992 IEM_MC_END();
5993 }
5994 else
5995 {
5996 /*
5997 * We're writing a register to memory.
5998 */
5999 IEM_MC_BEGIN(0, 2, 0, 0);
6000 IEM_MC_LOCAL(uint8_t, u8Value);
6001 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
6002 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
6003 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6004 IEM_MC_FETCH_GREG_U8(u8Value, IEM_GET_MODRM_REG(pVCpu, bRm));
6005 IEM_MC_STORE_MEM_U8(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u8Value);
6006 IEM_MC_ADVANCE_RIP_AND_FINISH();
6007 IEM_MC_END();
6008 }
6009}
6010
6011
6012/**
6013 * @opcode 0x89
6014 */
6015FNIEMOP_DEF(iemOp_mov_Ev_Gv)
6016{
6017 IEMOP_MNEMONIC(mov_Ev_Gv, "mov Ev,Gv");
6018
6019 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
6020
6021 /*
6022 * If rm is denoting a register, no more instruction bytes.
6023 */
6024 if (IEM_IS_MODRM_REG_MODE(bRm))
6025 {
6026 switch (pVCpu->iem.s.enmEffOpSize)
6027 {
6028 case IEMMODE_16BIT:
6029 IEM_MC_BEGIN(0, 1, 0, 0);
6030 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6031 IEM_MC_LOCAL(uint16_t, u16Value);
6032 IEM_MC_FETCH_GREG_U16(u16Value, IEM_GET_MODRM_REG(pVCpu, bRm));
6033 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_RM(pVCpu, bRm), u16Value);
6034 IEM_MC_ADVANCE_RIP_AND_FINISH();
6035 IEM_MC_END();
6036 break;
6037
6038 case IEMMODE_32BIT:
6039 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_386, 0);
6040 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6041 IEM_MC_LOCAL(uint32_t, u32Value);
6042 IEM_MC_FETCH_GREG_U32(u32Value, IEM_GET_MODRM_REG(pVCpu, bRm));
6043 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_RM(pVCpu, bRm), u32Value);
6044 IEM_MC_ADVANCE_RIP_AND_FINISH();
6045 IEM_MC_END();
6046 break;
6047
6048 case IEMMODE_64BIT:
6049 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
6050 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6051 IEM_MC_LOCAL(uint64_t, u64Value);
6052 IEM_MC_FETCH_GREG_U64(u64Value, IEM_GET_MODRM_REG(pVCpu, bRm));
6053 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm), u64Value);
6054 IEM_MC_ADVANCE_RIP_AND_FINISH();
6055 IEM_MC_END();
6056 break;
6057
6058 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6059 }
6060 }
6061 else
6062 {
6063 /*
6064 * We're writing a register to memory.
6065 */
6066 switch (pVCpu->iem.s.enmEffOpSize)
6067 {
6068 case IEMMODE_16BIT:
6069 IEM_MC_BEGIN(0, 2, 0, 0);
6070 IEM_MC_LOCAL(uint16_t, u16Value);
6071 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
6072 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
6073 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6074 IEM_MC_FETCH_GREG_U16(u16Value, IEM_GET_MODRM_REG(pVCpu, bRm));
6075 IEM_MC_STORE_MEM_U16(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u16Value);
6076 IEM_MC_ADVANCE_RIP_AND_FINISH();
6077 IEM_MC_END();
6078 break;
6079
6080 case IEMMODE_32BIT:
6081 IEM_MC_BEGIN(0, 2, IEM_MC_F_MIN_386, 0);
6082 IEM_MC_LOCAL(uint32_t, u32Value);
6083 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
6084 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
6085 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6086 IEM_MC_FETCH_GREG_U32(u32Value, IEM_GET_MODRM_REG(pVCpu, bRm));
6087 IEM_MC_STORE_MEM_U32(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u32Value);
6088 IEM_MC_ADVANCE_RIP_AND_FINISH();
6089 IEM_MC_END();
6090 break;
6091
6092 case IEMMODE_64BIT:
6093 IEM_MC_BEGIN(0, 2, IEM_MC_F_64BIT, 0);
6094 IEM_MC_LOCAL(uint64_t, u64Value);
6095 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
6096 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
6097 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6098 IEM_MC_FETCH_GREG_U64(u64Value, IEM_GET_MODRM_REG(pVCpu, bRm));
6099 IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u64Value);
6100 IEM_MC_ADVANCE_RIP_AND_FINISH();
6101 IEM_MC_END();
6102 break;
6103
6104 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6105 }
6106 }
6107}
6108
6109
6110/**
6111 * @opcode 0x8a
6112 */
6113FNIEMOP_DEF(iemOp_mov_Gb_Eb)
6114{
6115 IEMOP_MNEMONIC(mov_Gb_Eb, "mov Gb,Eb");
6116
6117 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
6118
6119 /*
6120 * If rm is denoting a register, no more instruction bytes.
6121 */
6122 if (IEM_IS_MODRM_REG_MODE(bRm))
6123 {
6124 IEM_MC_BEGIN(0, 1, 0, 0);
6125 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6126 IEM_MC_LOCAL(uint8_t, u8Value);
6127 IEM_MC_FETCH_GREG_U8(u8Value, IEM_GET_MODRM_RM(pVCpu, bRm));
6128 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_REG(pVCpu, bRm), u8Value);
6129 IEM_MC_ADVANCE_RIP_AND_FINISH();
6130 IEM_MC_END();
6131 }
6132 else
6133 {
6134 /*
6135 * We're loading a register from memory.
6136 */
6137 IEM_MC_BEGIN(0, 2, 0, 0);
6138 IEM_MC_LOCAL(uint8_t, u8Value);
6139 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
6140 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
6141 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6142 IEM_MC_FETCH_MEM_U8(u8Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
6143 IEM_MC_STORE_GREG_U8(IEM_GET_MODRM_REG(pVCpu, bRm), u8Value);
6144 IEM_MC_ADVANCE_RIP_AND_FINISH();
6145 IEM_MC_END();
6146 }
6147}
6148
6149
6150/**
6151 * @opcode 0x8b
6152 */
6153FNIEMOP_DEF(iemOp_mov_Gv_Ev)
6154{
6155 IEMOP_MNEMONIC(mov_Gv_Ev, "mov Gv,Ev");
6156
6157 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
6158
6159 /*
6160 * If rm is denoting a register, no more instruction bytes.
6161 */
6162 if (IEM_IS_MODRM_REG_MODE(bRm))
6163 {
6164 switch (pVCpu->iem.s.enmEffOpSize)
6165 {
6166 case IEMMODE_16BIT:
6167 IEM_MC_BEGIN(0, 1, 0, 0);
6168 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6169 IEM_MC_LOCAL(uint16_t, u16Value);
6170 IEM_MC_FETCH_GREG_U16(u16Value, IEM_GET_MODRM_RM(pVCpu, bRm));
6171 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_REG(pVCpu, bRm), u16Value);
6172 IEM_MC_ADVANCE_RIP_AND_FINISH();
6173 IEM_MC_END();
6174 break;
6175
6176 case IEMMODE_32BIT:
6177 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_386, 0);
6178 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6179 IEM_MC_LOCAL(uint32_t, u32Value);
6180 IEM_MC_FETCH_GREG_U32(u32Value, IEM_GET_MODRM_RM(pVCpu, bRm));
6181 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_REG(pVCpu, bRm), u32Value);
6182 IEM_MC_ADVANCE_RIP_AND_FINISH();
6183 IEM_MC_END();
6184 break;
6185
6186 case IEMMODE_64BIT:
6187 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
6188 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6189 IEM_MC_LOCAL(uint64_t, u64Value);
6190 IEM_MC_FETCH_GREG_U64(u64Value, IEM_GET_MODRM_RM(pVCpu, bRm));
6191 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), u64Value);
6192 IEM_MC_ADVANCE_RIP_AND_FINISH();
6193 IEM_MC_END();
6194 break;
6195
6196 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6197 }
6198 }
6199 else
6200 {
6201 /*
6202 * We're loading a register from memory.
6203 */
6204 switch (pVCpu->iem.s.enmEffOpSize)
6205 {
6206 case IEMMODE_16BIT:
6207 IEM_MC_BEGIN(0, 2, 0, 0);
6208 IEM_MC_LOCAL(uint16_t, u16Value);
6209 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
6210 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
6211 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6212 IEM_MC_FETCH_MEM_U16(u16Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
6213 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_REG(pVCpu, bRm), u16Value);
6214 IEM_MC_ADVANCE_RIP_AND_FINISH();
6215 IEM_MC_END();
6216 break;
6217
6218 case IEMMODE_32BIT:
6219 IEM_MC_BEGIN(0, 2, IEM_MC_F_MIN_386, 0);
6220 IEM_MC_LOCAL(uint32_t, u32Value);
6221 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
6222 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
6223 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6224 IEM_MC_FETCH_MEM_U32(u32Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
6225 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_REG(pVCpu, bRm), u32Value);
6226 IEM_MC_ADVANCE_RIP_AND_FINISH();
6227 IEM_MC_END();
6228 break;
6229
6230 case IEMMODE_64BIT:
6231 IEM_MC_BEGIN(0, 2, IEM_MC_F_64BIT, 0);
6232 IEM_MC_LOCAL(uint64_t, u64Value);
6233 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
6234 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
6235 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6236 IEM_MC_FETCH_MEM_U64(u64Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
6237 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), u64Value);
6238 IEM_MC_ADVANCE_RIP_AND_FINISH();
6239 IEM_MC_END();
6240 break;
6241
6242 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6243 }
6244 }
6245}
6246
6247
6248/**
6249 * opcode 0x63
6250 * @todo Table fixme
6251 */
6252FNIEMOP_DEF(iemOp_arpl_Ew_Gw_movsx_Gv_Ev)
6253{
6254 if (!IEM_IS_64BIT_CODE(pVCpu))
6255 return FNIEMOP_CALL(iemOp_arpl_Ew_Gw);
6256 if (pVCpu->iem.s.enmEffOpSize != IEMMODE_64BIT)
6257 return FNIEMOP_CALL(iemOp_mov_Gv_Ev);
6258 return FNIEMOP_CALL(iemOp_movsxd_Gv_Ev);
6259}
6260
6261
6262/**
6263 * @opcode 0x8c
6264 */
6265FNIEMOP_DEF(iemOp_mov_Ev_Sw)
6266{
6267 IEMOP_MNEMONIC(mov_Ev_Sw, "mov Ev,Sw");
6268
6269 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
6270
6271 /*
6272 * Check that the destination register exists. The REX.R prefix is ignored.
6273 */
6274 uint8_t const iSegReg = IEM_GET_MODRM_REG_8(bRm);
6275 if (iSegReg > X86_SREG_GS)
6276 IEMOP_RAISE_INVALID_OPCODE_RET(); /** @todo should probably not be raised until we've fetched all the opcode bytes? */
6277
6278 /*
6279 * If rm is denoting a register, no more instruction bytes.
6280 * In that case, the operand size is respected and the upper bits are
6281 * cleared (starting with some pentium).
6282 */
6283 if (IEM_IS_MODRM_REG_MODE(bRm))
6284 {
6285 switch (pVCpu->iem.s.enmEffOpSize)
6286 {
6287 case IEMMODE_16BIT:
6288 IEM_MC_BEGIN(0, 1, 0, 0);
6289 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6290 IEM_MC_LOCAL(uint16_t, u16Value);
6291 IEM_MC_FETCH_SREG_U16(u16Value, iSegReg);
6292 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_RM(pVCpu, bRm), u16Value);
6293 IEM_MC_ADVANCE_RIP_AND_FINISH();
6294 IEM_MC_END();
6295 break;
6296
6297 case IEMMODE_32BIT:
6298 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_386, 0);
6299 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6300 IEM_MC_LOCAL(uint32_t, u32Value);
6301 IEM_MC_FETCH_SREG_ZX_U32(u32Value, iSegReg);
6302 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_RM(pVCpu, bRm), u32Value);
6303 IEM_MC_ADVANCE_RIP_AND_FINISH();
6304 IEM_MC_END();
6305 break;
6306
6307 case IEMMODE_64BIT:
6308 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
6309 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6310 IEM_MC_LOCAL(uint64_t, u64Value);
6311 IEM_MC_FETCH_SREG_ZX_U64(u64Value, iSegReg);
6312 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm), u64Value);
6313 IEM_MC_ADVANCE_RIP_AND_FINISH();
6314 IEM_MC_END();
6315 break;
6316
6317 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6318 }
6319 }
6320 else
6321 {
6322 /*
6323 * We're saving the register to memory. The access is word sized
6324 * regardless of operand size prefixes.
6325 */
6326#if 0 /* not necessary */
6327 pVCpu->iem.s.enmEffOpSize = pVCpu->iem.s.enmDefOpSize = IEMMODE_16BIT;
6328#endif
6329 IEM_MC_BEGIN(0, 2, 0, 0);
6330 IEM_MC_LOCAL(uint16_t, u16Value);
6331 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
6332 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
6333 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6334 IEM_MC_FETCH_SREG_U16(u16Value, iSegReg);
6335 IEM_MC_STORE_MEM_U16(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u16Value);
6336 IEM_MC_ADVANCE_RIP_AND_FINISH();
6337 IEM_MC_END();
6338 }
6339}
6340
6341
6342
6343
6344/**
6345 * @opcode 0x8d
6346 */
6347FNIEMOP_DEF(iemOp_lea_Gv_M)
6348{
6349 IEMOP_MNEMONIC(lea_Gv_M, "lea Gv,M");
6350 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
6351 if (IEM_IS_MODRM_REG_MODE(bRm))
6352 IEMOP_RAISE_INVALID_OPCODE_RET(); /* no register form */
6353
6354 switch (pVCpu->iem.s.enmEffOpSize)
6355 {
6356 case IEMMODE_16BIT:
6357 IEM_MC_BEGIN(0, 2, 0, 0);
6358 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
6359 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
6360 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6361 /** @todo optimize: This value casting/masking can be skipped if addr-size ==
6362 * operand-size, which is usually the case. It'll save an instruction
6363 * and a register. */
6364 IEM_MC_LOCAL(uint16_t, u16Cast);
6365 IEM_MC_ASSIGN_TO_SMALLER(u16Cast, GCPtrEffSrc);
6366 IEM_MC_STORE_GREG_U16(IEM_GET_MODRM_REG(pVCpu, bRm), u16Cast);
6367 IEM_MC_ADVANCE_RIP_AND_FINISH();
6368 IEM_MC_END();
6369 break;
6370
6371 case IEMMODE_32BIT:
6372 IEM_MC_BEGIN(0, 2, IEM_MC_F_MIN_386, 0);
6373 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
6374 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
6375 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6376 /** @todo optimize: This value casting/masking can be skipped if addr-size ==
6377 * operand-size, which is usually the case. It'll save an instruction
6378 * and a register. */
6379 IEM_MC_LOCAL(uint32_t, u32Cast);
6380 IEM_MC_ASSIGN_TO_SMALLER(u32Cast, GCPtrEffSrc);
6381 IEM_MC_STORE_GREG_U32(IEM_GET_MODRM_REG(pVCpu, bRm), u32Cast);
6382 IEM_MC_ADVANCE_RIP_AND_FINISH();
6383 IEM_MC_END();
6384 break;
6385
6386 case IEMMODE_64BIT:
6387 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
6388 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
6389 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
6390 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6391 IEM_MC_STORE_GREG_U64(IEM_GET_MODRM_REG(pVCpu, bRm), GCPtrEffSrc);
6392 IEM_MC_ADVANCE_RIP_AND_FINISH();
6393 IEM_MC_END();
6394 break;
6395
6396 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6397 }
6398}
6399
6400
6401/**
6402 * @opcode 0x8e
6403 */
6404FNIEMOP_DEF(iemOp_mov_Sw_Ev)
6405{
6406 IEMOP_MNEMONIC(mov_Sw_Ev, "mov Sw,Ev");
6407
6408 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
6409
6410 /*
6411 * The practical operand size is 16-bit.
6412 */
6413#if 0 /* not necessary */
6414 pVCpu->iem.s.enmEffOpSize = pVCpu->iem.s.enmDefOpSize = IEMMODE_16BIT;
6415#endif
6416
6417 /*
6418 * Check that the destination register exists and can be used with this
6419 * instruction. The REX.R prefix is ignored.
6420 */
6421 uint8_t const iSegReg = IEM_GET_MODRM_REG_8(bRm);
6422 /** @todo r=bird: What does 8086 do here wrt CS? */
6423 if ( iSegReg == X86_SREG_CS
6424 || iSegReg > X86_SREG_GS)
6425 IEMOP_RAISE_INVALID_OPCODE_RET(); /** @todo should probably not be raised until we've fetched all the opcode bytes? */
6426
6427 /*
6428 * If rm is denoting a register, no more instruction bytes.
6429 *
6430 * Note! Using IEMOP_MOV_SW_EV_REG_BODY here to specify different
6431 * IEM_CIMPL_F_XXX values depending on the CPU mode and target
6432 * register. This is a restriction of the current recompiler
6433 * approach.
6434 */
6435 if (IEM_IS_MODRM_REG_MODE(bRm))
6436 {
6437#define IEMOP_MOV_SW_EV_REG_BODY(a_fCImplFlags) \
6438 IEM_MC_BEGIN(2, 0, 0, a_fCImplFlags); \
6439 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
6440 IEM_MC_ARG_CONST(uint8_t, iSRegArg, iSegReg, 0); \
6441 IEM_MC_ARG(uint16_t, u16Value, 1); \
6442 IEM_MC_FETCH_GREG_U16(u16Value, IEM_GET_MODRM_RM(pVCpu, bRm)); \
6443 IEM_MC_CALL_CIMPL_2(a_fCImplFlags, \
6444 RT_BIT_64(kIemNativeGstReg_SegSelFirst + iSegReg) \
6445 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + iSegReg) \
6446 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + iSegReg) \
6447 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + iSegReg), \
6448 iemCImpl_load_SReg, iSRegArg, u16Value); \
6449 IEM_MC_END()
6450
6451 if (iSegReg == X86_SREG_SS)
6452 {
6453 if (IEM_IS_32BIT_CODE(pVCpu))
6454 {
6455 IEMOP_MOV_SW_EV_REG_BODY(IEM_CIMPL_F_INHIBIT_SHADOW | IEM_CIMPL_F_MODE);
6456 }
6457 else
6458 {
6459 IEMOP_MOV_SW_EV_REG_BODY(IEM_CIMPL_F_INHIBIT_SHADOW);
6460 }
6461 }
6462 else if (iSegReg >= X86_SREG_FS || !IEM_IS_32BIT_CODE(pVCpu))
6463 {
6464 IEMOP_MOV_SW_EV_REG_BODY(0);
6465 }
6466 else
6467 {
6468 IEMOP_MOV_SW_EV_REG_BODY(IEM_CIMPL_F_MODE);
6469 }
6470#undef IEMOP_MOV_SW_EV_REG_BODY
6471 }
6472 else
6473 {
6474 /*
6475 * We're loading the register from memory. The access is word sized
6476 * regardless of operand size prefixes.
6477 */
6478#define IEMOP_MOV_SW_EV_MEM_BODY(a_fCImplFlags) \
6479 IEM_MC_BEGIN(2, 1, 0, a_fCImplFlags); \
6480 IEM_MC_ARG_CONST(uint8_t, iSRegArg, iSegReg, 0); \
6481 IEM_MC_ARG(uint16_t, u16Value, 1); \
6482 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
6483 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
6484 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
6485 IEM_MC_FETCH_MEM_U16(u16Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
6486 IEM_MC_CALL_CIMPL_2(a_fCImplFlags, \
6487 RT_BIT_64(kIemNativeGstReg_SegSelFirst + iSegReg) \
6488 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + iSegReg) \
6489 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + iSegReg) \
6490 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + iSegReg), \
6491 iemCImpl_load_SReg, iSRegArg, u16Value); \
6492 IEM_MC_END()
6493
6494 if (iSegReg == X86_SREG_SS)
6495 {
6496 if (IEM_IS_32BIT_CODE(pVCpu))
6497 {
6498 IEMOP_MOV_SW_EV_MEM_BODY(IEM_CIMPL_F_INHIBIT_SHADOW | IEM_CIMPL_F_MODE);
6499 }
6500 else
6501 {
6502 IEMOP_MOV_SW_EV_MEM_BODY(IEM_CIMPL_F_INHIBIT_SHADOW);
6503 }
6504 }
6505 else if (iSegReg >= X86_SREG_FS || !IEM_IS_32BIT_CODE(pVCpu))
6506 {
6507 IEMOP_MOV_SW_EV_MEM_BODY(0);
6508 }
6509 else
6510 {
6511 IEMOP_MOV_SW_EV_MEM_BODY(IEM_CIMPL_F_MODE);
6512 }
6513#undef IEMOP_MOV_SW_EV_MEM_BODY
6514 }
6515}
6516
6517
6518/** Opcode 0x8f /0. */
6519FNIEMOP_DEF_1(iemOp_pop_Ev, uint8_t, bRm)
6520{
6521 /* This bugger is rather annoying as it requires rSP to be updated before
6522 doing the effective address calculations. Will eventually require a
6523 split between the R/M+SIB decoding and the effective address
6524 calculation - which is something that is required for any attempt at
6525 reusing this code for a recompiler. It may also be good to have if we
6526 need to delay #UD exception caused by invalid lock prefixes.
6527
6528 For now, we'll do a mostly safe interpreter-only implementation here. */
6529 /** @todo What's the deal with the 'reg' field and pop Ev? Ignorning it for
6530 * now until tests show it's checked.. */
6531 IEMOP_MNEMONIC(pop_Ev, "pop Ev");
6532
6533 /* Register access is relatively easy and can share code. */
6534 if (IEM_IS_MODRM_REG_MODE(bRm))
6535 return FNIEMOP_CALL_1(iemOpCommonPopGReg, IEM_GET_MODRM_RM(pVCpu, bRm));
6536
6537 /*
6538 * Memory target.
6539 *
6540 * Intel says that RSP is incremented before it's used in any effective
6541 * address calcuations. This means some serious extra annoyance here since
6542 * we decode and calculate the effective address in one step and like to
6543 * delay committing registers till everything is done.
6544 *
6545 * So, we'll decode and calculate the effective address twice. This will
6546 * require some recoding if turned into a recompiler.
6547 */
6548 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE(); /* The common code does this differently. */
6549
6550#if 1 /* This can be compiled, optimize later if needed. */
6551 switch (pVCpu->iem.s.enmEffOpSize)
6552 {
6553 case IEMMODE_16BIT:
6554 IEM_MC_BEGIN(2, 0, 0, 0);
6555 IEM_MC_ARG(RTGCPTR, GCPtrEffDst, 1);
6556 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 2 << 8);
6557 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6558 IEM_MC_ARG_CONST(uint8_t, iEffSeg, pVCpu->iem.s.iEffSeg, 0);
6559 IEM_MC_CALL_CIMPL_2(0, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_pop_mem16, iEffSeg, GCPtrEffDst);
6560 IEM_MC_END();
6561 break;
6562
6563 case IEMMODE_32BIT:
6564 IEM_MC_BEGIN(2, 0, IEM_MC_F_MIN_386, 0);
6565 IEM_MC_ARG(RTGCPTR, GCPtrEffDst, 1);
6566 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4 << 8);
6567 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6568 IEM_MC_ARG_CONST(uint8_t, iEffSeg, pVCpu->iem.s.iEffSeg, 0);
6569 IEM_MC_CALL_CIMPL_2(0, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_pop_mem32, iEffSeg, GCPtrEffDst);
6570 IEM_MC_END();
6571 break;
6572
6573 case IEMMODE_64BIT:
6574 IEM_MC_BEGIN(2, 0, IEM_MC_F_64BIT, 0);
6575 IEM_MC_ARG(RTGCPTR, GCPtrEffDst, 1);
6576 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 8 << 8);
6577 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6578 IEM_MC_ARG_CONST(uint8_t, iEffSeg, pVCpu->iem.s.iEffSeg, 0);
6579 IEM_MC_CALL_CIMPL_2(0, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_pop_mem64, iEffSeg, GCPtrEffDst);
6580 IEM_MC_END();
6581 break;
6582
6583 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6584 }
6585
6586#else
6587# ifndef TST_IEM_CHECK_MC
6588 /* Calc effective address with modified ESP. */
6589/** @todo testcase */
6590 RTGCPTR GCPtrEff;
6591 VBOXSTRICTRC rcStrict;
6592 switch (pVCpu->iem.s.enmEffOpSize)
6593 {
6594 case IEMMODE_16BIT: rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 2 << 8, &GCPtrEff); break;
6595 case IEMMODE_32BIT: rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 4 << 8, &GCPtrEff); break;
6596 case IEMMODE_64BIT: rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 8 << 8, &GCPtrEff); break;
6597 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6598 }
6599 if (rcStrict != VINF_SUCCESS)
6600 return rcStrict;
6601 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6602
6603 /* Perform the operation - this should be CImpl. */
6604 RTUINT64U TmpRsp;
6605 TmpRsp.u = pVCpu->cpum.GstCtx.rsp;
6606 switch (pVCpu->iem.s.enmEffOpSize)
6607 {
6608 case IEMMODE_16BIT:
6609 {
6610 uint16_t u16Value;
6611 rcStrict = iemMemStackPopU16Ex(pVCpu, &u16Value, &TmpRsp);
6612 if (rcStrict == VINF_SUCCESS)
6613 rcStrict = iemMemStoreDataU16(pVCpu, pVCpu->iem.s.iEffSeg, GCPtrEff, u16Value);
6614 break;
6615 }
6616
6617 case IEMMODE_32BIT:
6618 {
6619 uint32_t u32Value;
6620 rcStrict = iemMemStackPopU32Ex(pVCpu, &u32Value, &TmpRsp);
6621 if (rcStrict == VINF_SUCCESS)
6622 rcStrict = iemMemStoreDataU32(pVCpu, pVCpu->iem.s.iEffSeg, GCPtrEff, u32Value);
6623 break;
6624 }
6625
6626 case IEMMODE_64BIT:
6627 {
6628 uint64_t u64Value;
6629 rcStrict = iemMemStackPopU64Ex(pVCpu, &u64Value, &TmpRsp);
6630 if (rcStrict == VINF_SUCCESS)
6631 rcStrict = iemMemStoreDataU64(pVCpu, pVCpu->iem.s.iEffSeg, GCPtrEff, u64Value);
6632 break;
6633 }
6634
6635 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6636 }
6637 if (rcStrict == VINF_SUCCESS)
6638 {
6639 pVCpu->cpum.GstCtx.rsp = TmpRsp.u;
6640 return iemRegUpdateRipAndFinishClearingRF(pVCpu);
6641 }
6642 return rcStrict;
6643
6644# else
6645 return VERR_IEM_IPE_2;
6646# endif
6647#endif
6648}
6649
6650
6651/**
6652 * @opcode 0x8f
6653 */
6654FNIEMOP_DEF(iemOp_Grp1A__xop)
6655{
6656 /*
6657 * AMD has defined /1 thru /7 as XOP prefix. The prefix is similar to the
6658 * three byte VEX prefix, except that the mmmmm field cannot have the values
6659 * 0 thru 7, because it would then be confused with pop Ev (modrm.reg == 0).
6660 */
6661 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
6662 if ((bRm & X86_MODRM_REG_MASK) == (0 << X86_MODRM_REG_SHIFT)) /* /0 */
6663 return FNIEMOP_CALL_1(iemOp_pop_Ev, bRm);
6664
6665 IEMOP_MNEMONIC(xop, "xop");
6666 if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fXop)
6667 {
6668 /** @todo Test when exctly the XOP conformance checks kick in during
6669 * instruction decoding and fetching (using \#PF). */
6670 uint8_t bXop2; IEM_OPCODE_GET_NEXT_U8(&bXop2);
6671 uint8_t bOpcode; IEM_OPCODE_GET_NEXT_U8(&bOpcode);
6672 if ( ( pVCpu->iem.s.fPrefixes
6673 & (IEM_OP_PRF_SIZE_OP | IEM_OP_PRF_REPZ | IEM_OP_PRF_REPNZ | IEM_OP_PRF_LOCK | IEM_OP_PRF_REX))
6674 == 0)
6675 {
6676 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_XOP;
6677 if ((bXop2 & 0x80 /* XOP.W */) && IEM_IS_64BIT_CODE(pVCpu))
6678 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SIZE_REX_W;
6679 pVCpu->iem.s.uRexReg = (~bRm >> (7 - 3)) & 0x8;
6680 pVCpu->iem.s.uRexIndex = (~bRm >> (6 - 3)) & 0x8;
6681 pVCpu->iem.s.uRexB = (~bRm >> (5 - 3)) & 0x8;
6682 pVCpu->iem.s.uVex3rdReg = (~bXop2 >> 3) & 0xf;
6683 pVCpu->iem.s.uVexLength = (bXop2 >> 2) & 1;
6684 pVCpu->iem.s.idxPrefix = bXop2 & 0x3;
6685
6686 /** @todo XOP: Just use new tables and decoders. */
6687 switch (bRm & 0x1f)
6688 {
6689 case 8: /* xop opcode map 8. */
6690 IEMOP_BITCH_ABOUT_STUB();
6691 return VERR_IEM_INSTR_NOT_IMPLEMENTED;
6692
6693 case 9: /* xop opcode map 9. */
6694 IEMOP_BITCH_ABOUT_STUB();
6695 return VERR_IEM_INSTR_NOT_IMPLEMENTED;
6696
6697 case 10: /* xop opcode map 10. */
6698 IEMOP_BITCH_ABOUT_STUB();
6699 return VERR_IEM_INSTR_NOT_IMPLEMENTED;
6700
6701 default:
6702 Log(("XOP: Invalid vvvv value: %#x!\n", bRm & 0x1f));
6703 IEMOP_RAISE_INVALID_OPCODE_RET();
6704 }
6705 }
6706 else
6707 Log(("XOP: Invalid prefix mix!\n"));
6708 }
6709 else
6710 Log(("XOP: XOP support disabled!\n"));
6711 IEMOP_RAISE_INVALID_OPCODE_RET();
6712}
6713
6714
6715/**
6716 * Common 'xchg reg,rAX' helper.
6717 */
6718FNIEMOP_DEF_1(iemOpCommonXchgGRegRax, uint8_t, iReg)
6719{
6720 iReg |= pVCpu->iem.s.uRexB;
6721 switch (pVCpu->iem.s.enmEffOpSize)
6722 {
6723 case IEMMODE_16BIT:
6724 IEM_MC_BEGIN(0, 2, 0, 0);
6725 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6726 IEM_MC_LOCAL(uint16_t, u16Tmp1);
6727 IEM_MC_LOCAL(uint16_t, u16Tmp2);
6728 IEM_MC_FETCH_GREG_U16(u16Tmp1, iReg);
6729 IEM_MC_FETCH_GREG_U16(u16Tmp2, X86_GREG_xAX);
6730 IEM_MC_STORE_GREG_U16(X86_GREG_xAX, u16Tmp1);
6731 IEM_MC_STORE_GREG_U16(iReg, u16Tmp2);
6732 IEM_MC_ADVANCE_RIP_AND_FINISH();
6733 IEM_MC_END();
6734 break;
6735
6736 case IEMMODE_32BIT:
6737 IEM_MC_BEGIN(0, 2, IEM_MC_F_MIN_386, 0);
6738 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6739 IEM_MC_LOCAL(uint32_t, u32Tmp1);
6740 IEM_MC_LOCAL(uint32_t, u32Tmp2);
6741 IEM_MC_FETCH_GREG_U32(u32Tmp1, iReg);
6742 IEM_MC_FETCH_GREG_U32(u32Tmp2, X86_GREG_xAX);
6743 IEM_MC_STORE_GREG_U32(X86_GREG_xAX, u32Tmp1);
6744 IEM_MC_STORE_GREG_U32(iReg, u32Tmp2);
6745 IEM_MC_ADVANCE_RIP_AND_FINISH();
6746 IEM_MC_END();
6747 break;
6748
6749 case IEMMODE_64BIT:
6750 IEM_MC_BEGIN(0, 2, IEM_MC_F_64BIT, 0);
6751 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6752 IEM_MC_LOCAL(uint64_t, u64Tmp1);
6753 IEM_MC_LOCAL(uint64_t, u64Tmp2);
6754 IEM_MC_FETCH_GREG_U64(u64Tmp1, iReg);
6755 IEM_MC_FETCH_GREG_U64(u64Tmp2, X86_GREG_xAX);
6756 IEM_MC_STORE_GREG_U64(X86_GREG_xAX, u64Tmp1);
6757 IEM_MC_STORE_GREG_U64(iReg, u64Tmp2);
6758 IEM_MC_ADVANCE_RIP_AND_FINISH();
6759 IEM_MC_END();
6760 break;
6761
6762 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6763 }
6764}
6765
6766
6767/**
6768 * @opcode 0x90
6769 */
6770FNIEMOP_DEF(iemOp_nop)
6771{
6772 /* R8/R8D and RAX/EAX can be exchanged. */
6773 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_REX_B)
6774 {
6775 IEMOP_MNEMONIC(xchg_r8_rAX, "xchg r8,rAX");
6776 return FNIEMOP_CALL_1(iemOpCommonXchgGRegRax, X86_GREG_xAX);
6777 }
6778
6779 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK)
6780 {
6781 IEMOP_MNEMONIC(pause, "pause");
6782 /* ASSUMING that we keep the IEM_F_X86_CTX_IN_GUEST, IEM_F_X86_CTX_VMX
6783 and IEM_F_X86_CTX_SVM in the TB key, we can safely do the following: */
6784 if (!IEM_IS_IN_GUEST(pVCpu))
6785 { /* probable */ }
6786#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
6787 else if (pVCpu->iem.s.fExec & IEM_F_X86_CTX_VMX)
6788 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_VMEXIT, 0, iemCImpl_vmx_pause);
6789#endif
6790#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
6791 else if (pVCpu->iem.s.fExec & IEM_F_X86_CTX_SVM)
6792 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_VMEXIT, 0, iemCImpl_svm_pause);
6793#endif
6794 }
6795 else
6796 IEMOP_MNEMONIC(nop, "nop");
6797 /** @todo testcase: lock nop; lock pause */
6798 IEM_MC_BEGIN(0, 0, 0, 0);
6799 IEMOP_HLP_DONE_DECODING();
6800 IEM_MC_ADVANCE_RIP_AND_FINISH();
6801 IEM_MC_END();
6802}
6803
6804
6805/**
6806 * @opcode 0x91
6807 */
6808FNIEMOP_DEF(iemOp_xchg_eCX_eAX)
6809{
6810 IEMOP_MNEMONIC(xchg_rCX_rAX, "xchg rCX,rAX");
6811 return FNIEMOP_CALL_1(iemOpCommonXchgGRegRax, X86_GREG_xCX);
6812}
6813
6814
6815/**
6816 * @opcode 0x92
6817 */
6818FNIEMOP_DEF(iemOp_xchg_eDX_eAX)
6819{
6820 IEMOP_MNEMONIC(xchg_rDX_rAX, "xchg rDX,rAX");
6821 return FNIEMOP_CALL_1(iemOpCommonXchgGRegRax, X86_GREG_xDX);
6822}
6823
6824
6825/**
6826 * @opcode 0x93
6827 */
6828FNIEMOP_DEF(iemOp_xchg_eBX_eAX)
6829{
6830 IEMOP_MNEMONIC(xchg_rBX_rAX, "xchg rBX,rAX");
6831 return FNIEMOP_CALL_1(iemOpCommonXchgGRegRax, X86_GREG_xBX);
6832}
6833
6834
6835/**
6836 * @opcode 0x94
6837 */
6838FNIEMOP_DEF(iemOp_xchg_eSP_eAX)
6839{
6840 IEMOP_MNEMONIC(xchg_rSX_rAX, "xchg rSX,rAX");
6841 return FNIEMOP_CALL_1(iemOpCommonXchgGRegRax, X86_GREG_xSP);
6842}
6843
6844
6845/**
6846 * @opcode 0x95
6847 */
6848FNIEMOP_DEF(iemOp_xchg_eBP_eAX)
6849{
6850 IEMOP_MNEMONIC(xchg_rBP_rAX, "xchg rBP,rAX");
6851 return FNIEMOP_CALL_1(iemOpCommonXchgGRegRax, X86_GREG_xBP);
6852}
6853
6854
6855/**
6856 * @opcode 0x96
6857 */
6858FNIEMOP_DEF(iemOp_xchg_eSI_eAX)
6859{
6860 IEMOP_MNEMONIC(xchg_rSI_rAX, "xchg rSI,rAX");
6861 return FNIEMOP_CALL_1(iemOpCommonXchgGRegRax, X86_GREG_xSI);
6862}
6863
6864
6865/**
6866 * @opcode 0x97
6867 */
6868FNIEMOP_DEF(iemOp_xchg_eDI_eAX)
6869{
6870 IEMOP_MNEMONIC(xchg_rDI_rAX, "xchg rDI,rAX");
6871 return FNIEMOP_CALL_1(iemOpCommonXchgGRegRax, X86_GREG_xDI);
6872}
6873
6874
6875/**
6876 * @opcode 0x98
6877 */
6878FNIEMOP_DEF(iemOp_cbw)
6879{
6880 switch (pVCpu->iem.s.enmEffOpSize)
6881 {
6882 case IEMMODE_16BIT:
6883 IEMOP_MNEMONIC(cbw, "cbw");
6884 IEM_MC_BEGIN(0, 1, 0, 0);
6885 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6886 IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 7) {
6887 IEM_MC_OR_GREG_U16(X86_GREG_xAX, UINT16_C(0xff00));
6888 } IEM_MC_ELSE() {
6889 IEM_MC_AND_GREG_U16(X86_GREG_xAX, UINT16_C(0x00ff));
6890 } IEM_MC_ENDIF();
6891 IEM_MC_ADVANCE_RIP_AND_FINISH();
6892 IEM_MC_END();
6893 break;
6894
6895 case IEMMODE_32BIT:
6896 IEMOP_MNEMONIC(cwde, "cwde");
6897 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_386, 0);
6898 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6899 IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 15) {
6900 IEM_MC_OR_GREG_U32(X86_GREG_xAX, UINT32_C(0xffff0000));
6901 } IEM_MC_ELSE() {
6902 IEM_MC_AND_GREG_U32(X86_GREG_xAX, UINT32_C(0x0000ffff));
6903 } IEM_MC_ENDIF();
6904 IEM_MC_ADVANCE_RIP_AND_FINISH();
6905 IEM_MC_END();
6906 break;
6907
6908 case IEMMODE_64BIT:
6909 IEMOP_MNEMONIC(cdqe, "cdqe");
6910 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
6911 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6912 IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 31) {
6913 IEM_MC_OR_GREG_U64(X86_GREG_xAX, UINT64_C(0xffffffff00000000));
6914 } IEM_MC_ELSE() {
6915 IEM_MC_AND_GREG_U64(X86_GREG_xAX, UINT64_C(0x00000000ffffffff));
6916 } IEM_MC_ENDIF();
6917 IEM_MC_ADVANCE_RIP_AND_FINISH();
6918 IEM_MC_END();
6919 break;
6920
6921 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6922 }
6923}
6924
6925
6926/**
6927 * @opcode 0x99
6928 */
6929FNIEMOP_DEF(iemOp_cwd)
6930{
6931 switch (pVCpu->iem.s.enmEffOpSize)
6932 {
6933 case IEMMODE_16BIT:
6934 IEMOP_MNEMONIC(cwd, "cwd");
6935 IEM_MC_BEGIN(0, 1, 0, 0);
6936 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6937 IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 15) {
6938 IEM_MC_STORE_GREG_U16_CONST(X86_GREG_xDX, UINT16_C(0xffff));
6939 } IEM_MC_ELSE() {
6940 IEM_MC_STORE_GREG_U16_CONST(X86_GREG_xDX, 0);
6941 } IEM_MC_ENDIF();
6942 IEM_MC_ADVANCE_RIP_AND_FINISH();
6943 IEM_MC_END();
6944 break;
6945
6946 case IEMMODE_32BIT:
6947 IEMOP_MNEMONIC(cdq, "cdq");
6948 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_386, 0);
6949 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6950 IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 31) {
6951 IEM_MC_STORE_GREG_U32_CONST(X86_GREG_xDX, UINT32_C(0xffffffff));
6952 } IEM_MC_ELSE() {
6953 IEM_MC_STORE_GREG_U32_CONST(X86_GREG_xDX, 0);
6954 } IEM_MC_ENDIF();
6955 IEM_MC_ADVANCE_RIP_AND_FINISH();
6956 IEM_MC_END();
6957 break;
6958
6959 case IEMMODE_64BIT:
6960 IEMOP_MNEMONIC(cqo, "cqo");
6961 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
6962 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6963 IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 63) {
6964 IEM_MC_STORE_GREG_U64_CONST(X86_GREG_xDX, UINT64_C(0xffffffffffffffff));
6965 } IEM_MC_ELSE() {
6966 IEM_MC_STORE_GREG_U64_CONST(X86_GREG_xDX, 0);
6967 } IEM_MC_ENDIF();
6968 IEM_MC_ADVANCE_RIP_AND_FINISH();
6969 IEM_MC_END();
6970 break;
6971
6972 IEM_NOT_REACHED_DEFAULT_CASE_RET();
6973 }
6974}
6975
6976
6977/**
6978 * @opcode 0x9a
6979 */
6980FNIEMOP_DEF(iemOp_call_Ap)
6981{
6982 IEMOP_MNEMONIC(call_Ap, "call Ap");
6983 IEMOP_HLP_NO_64BIT();
6984
6985 /* Decode the far pointer address and pass it on to the far call C implementation. */
6986 uint32_t off32Seg;
6987 if (pVCpu->iem.s.enmEffOpSize != IEMMODE_16BIT)
6988 IEM_OPCODE_GET_NEXT_U32(&off32Seg);
6989 else
6990 IEM_OPCODE_GET_NEXT_U16_ZX_U32(&off32Seg);
6991 uint16_t u16Sel; IEM_OPCODE_GET_NEXT_U16(&u16Sel);
6992 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
6993 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_BRANCH_DIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_STACK
6994 | IEM_CIMPL_F_MODE | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_VMEXIT, UINT64_MAX,
6995 iemCImpl_callf, u16Sel, off32Seg, pVCpu->iem.s.enmEffOpSize);
6996 /** @todo make task-switches, ring-switches, ++ return non-zero status */
6997}
6998
6999
7000/** Opcode 0x9b. (aka fwait) */
7001FNIEMOP_DEF(iemOp_wait)
7002{
7003 IEMOP_MNEMONIC(wait, "wait");
7004 IEM_MC_BEGIN(0, 0, 0, 0);
7005 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7006 IEM_MC_MAYBE_RAISE_WAIT_DEVICE_NOT_AVAILABLE();
7007 IEM_MC_MAYBE_RAISE_FPU_XCPT();
7008 IEM_MC_ADVANCE_RIP_AND_FINISH();
7009 IEM_MC_END();
7010}
7011
7012
7013/**
7014 * @opcode 0x9c
7015 */
7016FNIEMOP_DEF(iemOp_pushf_Fv)
7017{
7018 IEMOP_MNEMONIC(pushf_Fv, "pushf Fv");
7019 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7020 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
7021 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP),
7022 iemCImpl_pushf, pVCpu->iem.s.enmEffOpSize);
7023}
7024
7025
7026/**
7027 * @opcode 0x9d
7028 */
7029FNIEMOP_DEF(iemOp_popf_Fv)
7030{
7031 IEMOP_MNEMONIC(popf_Fv, "popf Fv");
7032 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7033 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
7034 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_CHECK_IRQ_BEFORE_AND_AFTER,
7035 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP),
7036 iemCImpl_popf, pVCpu->iem.s.enmEffOpSize);
7037}
7038
7039
7040/**
7041 * @opcode 0x9e
7042 * @opflmodify cf,pf,af,zf,sf
7043 */
7044FNIEMOP_DEF(iemOp_sahf)
7045{
7046 IEMOP_MNEMONIC(sahf, "sahf");
7047 if ( IEM_IS_64BIT_CODE(pVCpu)
7048 && !IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fLahfSahf)
7049 IEMOP_RAISE_INVALID_OPCODE_RET();
7050 IEM_MC_BEGIN(0, 2, 0, 0);
7051 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7052 IEM_MC_LOCAL(uint32_t, u32Flags);
7053 IEM_MC_LOCAL(uint32_t, EFlags);
7054 IEM_MC_FETCH_EFLAGS(EFlags);
7055 IEM_MC_FETCH_GREG_U8_ZX_U32(u32Flags, X86_GREG_xSP/*=AH*/);
7056 IEM_MC_AND_LOCAL_U32(u32Flags, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF);
7057 IEM_MC_AND_LOCAL_U32(EFlags, UINT32_C(0xffffff00));
7058 IEM_MC_OR_LOCAL_U32(u32Flags, X86_EFL_1);
7059 IEM_MC_OR_2LOCS_U32(EFlags, u32Flags);
7060 IEM_MC_COMMIT_EFLAGS(EFlags);
7061 IEM_MC_ADVANCE_RIP_AND_FINISH();
7062 IEM_MC_END();
7063}
7064
7065
7066/**
7067 * @opcode 0x9f
7068 * @opfltest cf,pf,af,zf,sf
7069 */
7070FNIEMOP_DEF(iemOp_lahf)
7071{
7072 IEMOP_MNEMONIC(lahf, "lahf");
7073 if ( IEM_IS_64BIT_CODE(pVCpu)
7074 && !IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fLahfSahf)
7075 IEMOP_RAISE_INVALID_OPCODE_RET();
7076 IEM_MC_BEGIN(0, 1, 0, 0);
7077 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7078 IEM_MC_LOCAL(uint8_t, u8Flags);
7079 IEM_MC_FETCH_EFLAGS_U8(u8Flags);
7080 IEM_MC_STORE_GREG_U8(X86_GREG_xSP/*=AH*/, u8Flags);
7081 IEM_MC_ADVANCE_RIP_AND_FINISH();
7082 IEM_MC_END();
7083}
7084
7085
7086/**
7087 * Macro used by iemOp_mov_AL_Ob, iemOp_mov_rAX_Ov, iemOp_mov_Ob_AL and
7088 * iemOp_mov_Ov_rAX to fetch the moffsXX bit of the opcode.
7089 * Will return/throw on failures.
7090 * @param a_GCPtrMemOff The variable to store the offset in.
7091 */
7092#define IEMOP_FETCH_MOFFS_XX(a_GCPtrMemOff) \
7093 do \
7094 { \
7095 switch (pVCpu->iem.s.enmEffAddrMode) \
7096 { \
7097 case IEMMODE_16BIT: \
7098 IEM_OPCODE_GET_NEXT_U16_ZX_U64(&(a_GCPtrMemOff)); \
7099 break; \
7100 case IEMMODE_32BIT: \
7101 IEM_OPCODE_GET_NEXT_U32_ZX_U64(&(a_GCPtrMemOff)); \
7102 break; \
7103 case IEMMODE_64BIT: \
7104 IEM_OPCODE_GET_NEXT_U64(&(a_GCPtrMemOff)); \
7105 break; \
7106 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
7107 } \
7108 } while (0)
7109
7110/**
7111 * @opcode 0xa0
7112 */
7113FNIEMOP_DEF(iemOp_mov_AL_Ob)
7114{
7115 /*
7116 * Get the offset.
7117 */
7118 IEMOP_MNEMONIC(mov_AL_Ob, "mov AL,Ob");
7119 RTGCPTR GCPtrMemOffDecode;
7120 IEMOP_FETCH_MOFFS_XX(GCPtrMemOffDecode);
7121
7122 /*
7123 * Fetch AL.
7124 */
7125 IEM_MC_BEGIN(0, 2, 0, 0);
7126 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7127 IEM_MC_LOCAL(uint8_t, u8Tmp);
7128 IEM_MC_LOCAL_CONST(RTGCPTR, GCPtrMemOff, GCPtrMemOffDecode);
7129 IEM_MC_FETCH_MEM_U8(u8Tmp, pVCpu->iem.s.iEffSeg, GCPtrMemOff);
7130 IEM_MC_STORE_GREG_U8(X86_GREG_xAX, u8Tmp);
7131 IEM_MC_ADVANCE_RIP_AND_FINISH();
7132 IEM_MC_END();
7133}
7134
7135
7136/**
7137 * @opcode 0xa1
7138 */
7139FNIEMOP_DEF(iemOp_mov_rAX_Ov)
7140{
7141 /*
7142 * Get the offset.
7143 */
7144 IEMOP_MNEMONIC(mov_rAX_Ov, "mov rAX,Ov");
7145 RTGCPTR GCPtrMemOffDecode;
7146 IEMOP_FETCH_MOFFS_XX(GCPtrMemOffDecode);
7147
7148 /*
7149 * Fetch rAX.
7150 */
7151 switch (pVCpu->iem.s.enmEffOpSize)
7152 {
7153 case IEMMODE_16BIT:
7154 IEM_MC_BEGIN(0, 2, 0, 0);
7155 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7156 IEM_MC_LOCAL(uint16_t, u16Tmp);
7157 IEM_MC_LOCAL_CONST(RTGCPTR, GCPtrMemOff, GCPtrMemOffDecode);
7158 IEM_MC_FETCH_MEM_U16(u16Tmp, pVCpu->iem.s.iEffSeg, GCPtrMemOff);
7159 IEM_MC_STORE_GREG_U16(X86_GREG_xAX, u16Tmp);
7160 IEM_MC_ADVANCE_RIP_AND_FINISH();
7161 IEM_MC_END();
7162 break;
7163
7164 case IEMMODE_32BIT:
7165 IEM_MC_BEGIN(0, 2, IEM_MC_F_MIN_386, 0);
7166 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7167 IEM_MC_LOCAL(uint32_t, u32Tmp);
7168 IEM_MC_LOCAL_CONST(RTGCPTR, GCPtrMemOff, GCPtrMemOffDecode);
7169 IEM_MC_FETCH_MEM_U32(u32Tmp, pVCpu->iem.s.iEffSeg, GCPtrMemOff);
7170 IEM_MC_STORE_GREG_U32(X86_GREG_xAX, u32Tmp);
7171 IEM_MC_ADVANCE_RIP_AND_FINISH();
7172 IEM_MC_END();
7173 break;
7174
7175 case IEMMODE_64BIT:
7176 IEM_MC_BEGIN(0, 2, IEM_MC_F_64BIT, 0);
7177 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7178 IEM_MC_LOCAL(uint64_t, u64Tmp);
7179 IEM_MC_LOCAL_CONST(RTGCPTR, GCPtrMemOff, GCPtrMemOffDecode);
7180 IEM_MC_FETCH_MEM_U64(u64Tmp, pVCpu->iem.s.iEffSeg, GCPtrMemOff);
7181 IEM_MC_STORE_GREG_U64(X86_GREG_xAX, u64Tmp);
7182 IEM_MC_ADVANCE_RIP_AND_FINISH();
7183 IEM_MC_END();
7184 break;
7185
7186 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7187 }
7188}
7189
7190
7191/**
7192 * @opcode 0xa2
7193 */
7194FNIEMOP_DEF(iemOp_mov_Ob_AL)
7195{
7196 /*
7197 * Get the offset.
7198 */
7199 IEMOP_MNEMONIC(mov_Ob_AL, "mov Ob,AL");
7200 RTGCPTR GCPtrMemOffDecode;
7201 IEMOP_FETCH_MOFFS_XX(GCPtrMemOffDecode);
7202
7203 /*
7204 * Store AL.
7205 */
7206 IEM_MC_BEGIN(0, 2, 0, 0);
7207 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7208 IEM_MC_LOCAL(uint8_t, u8Tmp);
7209 IEM_MC_FETCH_GREG_U8(u8Tmp, X86_GREG_xAX);
7210 IEM_MC_LOCAL_CONST(RTGCPTR, GCPtrMemOff, GCPtrMemOffDecode);
7211 IEM_MC_STORE_MEM_U8(pVCpu->iem.s.iEffSeg, GCPtrMemOff, u8Tmp);
7212 IEM_MC_ADVANCE_RIP_AND_FINISH();
7213 IEM_MC_END();
7214}
7215
7216
7217/**
7218 * @opcode 0xa3
7219 */
7220FNIEMOP_DEF(iemOp_mov_Ov_rAX)
7221{
7222 /*
7223 * Get the offset.
7224 */
7225 IEMOP_MNEMONIC(mov_Ov_rAX, "mov Ov,rAX");
7226 RTGCPTR GCPtrMemOffDecode;
7227 IEMOP_FETCH_MOFFS_XX(GCPtrMemOffDecode);
7228
7229 /*
7230 * Store rAX.
7231 */
7232 switch (pVCpu->iem.s.enmEffOpSize)
7233 {
7234 case IEMMODE_16BIT:
7235 IEM_MC_BEGIN(0, 2, 0, 0);
7236 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7237 IEM_MC_LOCAL(uint16_t, u16Tmp);
7238 IEM_MC_FETCH_GREG_U16(u16Tmp, X86_GREG_xAX);
7239 IEM_MC_LOCAL_CONST(RTGCPTR, GCPtrMemOff, GCPtrMemOffDecode);
7240 IEM_MC_STORE_MEM_U16(pVCpu->iem.s.iEffSeg, GCPtrMemOff, u16Tmp);
7241 IEM_MC_ADVANCE_RIP_AND_FINISH();
7242 IEM_MC_END();
7243 break;
7244
7245 case IEMMODE_32BIT:
7246 IEM_MC_BEGIN(0, 2, IEM_MC_F_MIN_386, 0);
7247 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7248 IEM_MC_LOCAL(uint32_t, u32Tmp);
7249 IEM_MC_FETCH_GREG_U32(u32Tmp, X86_GREG_xAX);
7250 IEM_MC_LOCAL_CONST(RTGCPTR, GCPtrMemOff, GCPtrMemOffDecode);
7251 IEM_MC_STORE_MEM_U32(pVCpu->iem.s.iEffSeg, GCPtrMemOff, u32Tmp);
7252 IEM_MC_ADVANCE_RIP_AND_FINISH();
7253 IEM_MC_END();
7254 break;
7255
7256 case IEMMODE_64BIT:
7257 IEM_MC_BEGIN(0, 2, IEM_MC_F_64BIT, 0);
7258 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7259 IEM_MC_LOCAL(uint64_t, u64Tmp);
7260 IEM_MC_FETCH_GREG_U64(u64Tmp, X86_GREG_xAX);
7261 IEM_MC_LOCAL_CONST(RTGCPTR, GCPtrMemOff, GCPtrMemOffDecode);
7262 IEM_MC_STORE_MEM_U64(pVCpu->iem.s.iEffSeg, GCPtrMemOff, u64Tmp);
7263 IEM_MC_ADVANCE_RIP_AND_FINISH();
7264 IEM_MC_END();
7265 break;
7266
7267 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7268 }
7269}
7270
7271/** Macro used by iemOp_movsb_Xb_Yb and iemOp_movswd_Xv_Yv */
7272#define IEM_MOVS_CASE(ValBits, AddrBits, a_fMcFlags) \
7273 IEM_MC_BEGIN(0, 2, a_fMcFlags, 0); \
7274 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
7275 IEM_MC_LOCAL(uint##ValBits##_t, uValue); \
7276 IEM_MC_LOCAL(RTGCPTR, uAddr); \
7277 IEM_MC_FETCH_GREG_U##AddrBits##_ZX_U64(uAddr, X86_GREG_xSI); \
7278 IEM_MC_FETCH_MEM_U##ValBits(uValue, pVCpu->iem.s.iEffSeg, uAddr); \
7279 IEM_MC_FETCH_GREG_U##AddrBits##_ZX_U64(uAddr, X86_GREG_xDI); \
7280 IEM_MC_STORE_MEM_U##ValBits(X86_SREG_ES, uAddr, uValue); \
7281 IEM_MC_IF_EFL_BIT_SET(X86_EFL_DF) { \
7282 IEM_MC_SUB_GREG_U##AddrBits(X86_GREG_xDI, ValBits / 8); \
7283 IEM_MC_SUB_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \
7284 } IEM_MC_ELSE() { \
7285 IEM_MC_ADD_GREG_U##AddrBits(X86_GREG_xDI, ValBits / 8); \
7286 IEM_MC_ADD_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \
7287 } IEM_MC_ENDIF(); \
7288 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
7289 IEM_MC_END() \
7290
7291/**
7292 * @opcode 0xa4
7293 * @opfltest df
7294 */
7295FNIEMOP_DEF(iemOp_movsb_Xb_Yb)
7296{
7297 /*
7298 * Use the C implementation if a repeat prefix is encountered.
7299 */
7300 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
7301 {
7302 IEMOP_MNEMONIC(rep_movsb_Xb_Yb, "rep movsb Xb,Yb");
7303 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7304 switch (pVCpu->iem.s.enmEffAddrMode)
7305 {
7306 case IEMMODE_16BIT:
7307 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7308 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7309 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7310 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7311 iemCImpl_rep_movs_op8_addr16, pVCpu->iem.s.iEffSeg);
7312 case IEMMODE_32BIT:
7313 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7314 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7315 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7316 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7317 iemCImpl_rep_movs_op8_addr32, pVCpu->iem.s.iEffSeg);
7318 case IEMMODE_64BIT:
7319 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7320 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7321 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7322 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7323 iemCImpl_rep_movs_op8_addr64, pVCpu->iem.s.iEffSeg);
7324 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7325 }
7326 }
7327
7328 /*
7329 * Sharing case implementation with movs[wdq] below.
7330 */
7331 IEMOP_MNEMONIC(movsb_Xb_Yb, "movsb Xb,Yb");
7332 switch (pVCpu->iem.s.enmEffAddrMode)
7333 {
7334 case IEMMODE_16BIT: IEM_MOVS_CASE(8, 16, IEM_MC_F_NOT_64BIT); break;
7335 case IEMMODE_32BIT: IEM_MOVS_CASE(8, 32, IEM_MC_F_MIN_386); break;
7336 case IEMMODE_64BIT: IEM_MOVS_CASE(8, 64, IEM_MC_F_64BIT); break;
7337 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7338 }
7339}
7340
7341
7342/**
7343 * @opcode 0xa5
7344 * @opfltest df
7345 */
7346FNIEMOP_DEF(iemOp_movswd_Xv_Yv)
7347{
7348
7349 /*
7350 * Use the C implementation if a repeat prefix is encountered.
7351 */
7352 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
7353 {
7354 IEMOP_MNEMONIC(rep_movs_Xv_Yv, "rep movs Xv,Yv");
7355 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7356 switch (pVCpu->iem.s.enmEffOpSize)
7357 {
7358 case IEMMODE_16BIT:
7359 switch (pVCpu->iem.s.enmEffAddrMode)
7360 {
7361 case IEMMODE_16BIT:
7362 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7363 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7364 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7365 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7366 iemCImpl_rep_movs_op16_addr16, pVCpu->iem.s.iEffSeg);
7367 case IEMMODE_32BIT:
7368 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7369 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7370 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7371 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7372 iemCImpl_rep_movs_op16_addr32, pVCpu->iem.s.iEffSeg);
7373 case IEMMODE_64BIT:
7374 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7375 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7376 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7377 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7378 iemCImpl_rep_movs_op16_addr64, pVCpu->iem.s.iEffSeg);
7379 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7380 }
7381 break;
7382 case IEMMODE_32BIT:
7383 switch (pVCpu->iem.s.enmEffAddrMode)
7384 {
7385 case IEMMODE_16BIT:
7386 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7387 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7388 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7389 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7390 iemCImpl_rep_movs_op32_addr16, pVCpu->iem.s.iEffSeg);
7391 case IEMMODE_32BIT:
7392 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7393 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7394 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7395 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7396 iemCImpl_rep_movs_op32_addr32, pVCpu->iem.s.iEffSeg);
7397 case IEMMODE_64BIT:
7398 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7399 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7400 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7401 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7402 iemCImpl_rep_movs_op32_addr64, pVCpu->iem.s.iEffSeg);
7403 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7404 }
7405 case IEMMODE_64BIT:
7406 switch (pVCpu->iem.s.enmEffAddrMode)
7407 {
7408 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_6);
7409 case IEMMODE_32BIT:
7410 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7411 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7412 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7413 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7414 iemCImpl_rep_movs_op64_addr32, pVCpu->iem.s.iEffSeg);
7415 case IEMMODE_64BIT:
7416 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
7417 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7418 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7419 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7420 iemCImpl_rep_movs_op64_addr64, pVCpu->iem.s.iEffSeg);
7421 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7422 }
7423 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7424 }
7425 }
7426
7427 /*
7428 * Annoying double switch here.
7429 * Using ugly macro for implementing the cases, sharing it with movsb.
7430 */
7431 IEMOP_MNEMONIC(movs_Xv_Yv, "movs Xv,Yv");
7432 switch (pVCpu->iem.s.enmEffOpSize)
7433 {
7434 case IEMMODE_16BIT:
7435 switch (pVCpu->iem.s.enmEffAddrMode)
7436 {
7437 case IEMMODE_16BIT: IEM_MOVS_CASE(16, 16, IEM_MC_F_NOT_64BIT); break;
7438 case IEMMODE_32BIT: IEM_MOVS_CASE(16, 32, IEM_MC_F_MIN_386); break;
7439 case IEMMODE_64BIT: IEM_MOVS_CASE(16, 64, IEM_MC_F_64BIT); break;
7440 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7441 }
7442 break;
7443
7444 case IEMMODE_32BIT:
7445 switch (pVCpu->iem.s.enmEffAddrMode)
7446 {
7447 case IEMMODE_16BIT: IEM_MOVS_CASE(32, 16, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT); break;
7448 case IEMMODE_32BIT: IEM_MOVS_CASE(32, 32, IEM_MC_F_MIN_386); break;
7449 case IEMMODE_64BIT: IEM_MOVS_CASE(32, 64, IEM_MC_F_64BIT); break;
7450 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7451 }
7452 break;
7453
7454 case IEMMODE_64BIT:
7455 switch (pVCpu->iem.s.enmEffAddrMode)
7456 {
7457 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_1); /* cannot be encoded */ break;
7458 case IEMMODE_32BIT: IEM_MOVS_CASE(64, 32, IEM_MC_F_64BIT); break;
7459 case IEMMODE_64BIT: IEM_MOVS_CASE(64, 64, IEM_MC_F_64BIT); break;
7460 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7461 }
7462 break;
7463 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7464 }
7465}
7466
7467#undef IEM_MOVS_CASE
7468
7469/** Macro used by iemOp_cmpsb_Xb_Yb and iemOp_cmpswd_Xv_Yv */
7470#define IEM_CMPS_CASE(ValBits, AddrBits, a_fMcFlags) \
7471 IEM_MC_BEGIN(3, 3, a_fMcFlags, 0); \
7472 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
7473 \
7474 IEM_MC_LOCAL(RTGCPTR, uAddr1); \
7475 IEM_MC_FETCH_GREG_U##AddrBits##_ZX_U64(uAddr1, X86_GREG_xSI); \
7476 IEM_MC_LOCAL(uint##ValBits##_t, uValue1); \
7477 IEM_MC_FETCH_MEM_U##ValBits(uValue1, pVCpu->iem.s.iEffSeg, uAddr1); \
7478 \
7479 IEM_MC_LOCAL(RTGCPTR, uAddr2); \
7480 IEM_MC_FETCH_GREG_U##AddrBits##_ZX_U64(uAddr2, X86_GREG_xDI); \
7481 IEM_MC_ARG(uint##ValBits##_t, uValue2, 1); \
7482 IEM_MC_FETCH_MEM_U##ValBits(uValue2, X86_SREG_ES, uAddr2); \
7483 \
7484 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
7485 IEM_MC_REF_EFLAGS(pEFlags); \
7486 IEM_MC_ARG_LOCAL_REF(uint##ValBits##_t *, puValue1, uValue1, 0); \
7487 IEM_MC_CALL_VOID_AIMPL_3(iemAImpl_cmp_u##ValBits, puValue1, uValue2, pEFlags); \
7488 \
7489 IEM_MC_IF_EFL_BIT_SET(X86_EFL_DF) { \
7490 IEM_MC_SUB_GREG_U##AddrBits(X86_GREG_xDI, ValBits / 8); \
7491 IEM_MC_SUB_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \
7492 } IEM_MC_ELSE() { \
7493 IEM_MC_ADD_GREG_U##AddrBits(X86_GREG_xDI, ValBits / 8); \
7494 IEM_MC_ADD_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \
7495 } IEM_MC_ENDIF(); \
7496 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
7497 IEM_MC_END() \
7498
7499/**
7500 * @opcode 0xa6
7501 * @opflclass arithmetic
7502 * @opfltest df
7503 */
7504FNIEMOP_DEF(iemOp_cmpsb_Xb_Yb)
7505{
7506
7507 /*
7508 * Use the C implementation if a repeat prefix is encountered.
7509 */
7510 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_REPZ)
7511 {
7512 IEMOP_MNEMONIC(repz_cmps_Xb_Yb, "repz cmps Xb,Yb");
7513 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7514 switch (pVCpu->iem.s.enmEffAddrMode)
7515 {
7516 case IEMMODE_16BIT:
7517 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7518 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7519 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7520 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7521 iemCImpl_repe_cmps_op8_addr16, pVCpu->iem.s.iEffSeg);
7522 case IEMMODE_32BIT:
7523 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7524 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7525 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7526 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7527 iemCImpl_repe_cmps_op8_addr32, pVCpu->iem.s.iEffSeg);
7528 case IEMMODE_64BIT:
7529 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7530 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7531 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7532 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7533 iemCImpl_repe_cmps_op8_addr64, pVCpu->iem.s.iEffSeg);
7534 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7535 }
7536 }
7537 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_REPNZ)
7538 {
7539 IEMOP_MNEMONIC(repnz_cmps_Xb_Yb, "repnz cmps Xb,Yb");
7540 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7541 switch (pVCpu->iem.s.enmEffAddrMode)
7542 {
7543 case IEMMODE_16BIT:
7544 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7545 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7546 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7547 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7548 iemCImpl_repne_cmps_op8_addr16, pVCpu->iem.s.iEffSeg);
7549 case IEMMODE_32BIT:
7550 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7551 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7552 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7553 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7554 iemCImpl_repne_cmps_op8_addr32, pVCpu->iem.s.iEffSeg);
7555 case IEMMODE_64BIT:
7556 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7557 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7558 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7559 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7560 iemCImpl_repne_cmps_op8_addr64, pVCpu->iem.s.iEffSeg);
7561 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7562 }
7563 }
7564
7565 /*
7566 * Sharing case implementation with cmps[wdq] below.
7567 */
7568 IEMOP_MNEMONIC(cmps_Xb_Yb, "cmps Xb,Yb");
7569 switch (pVCpu->iem.s.enmEffAddrMode)
7570 {
7571 case IEMMODE_16BIT: IEM_CMPS_CASE(8, 16, IEM_MC_F_NOT_64BIT); break;
7572 case IEMMODE_32BIT: IEM_CMPS_CASE(8, 32, IEM_MC_F_MIN_386); break;
7573 case IEMMODE_64BIT: IEM_CMPS_CASE(8, 64, IEM_MC_F_64BIT); break;
7574 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7575 }
7576}
7577
7578
7579/**
7580 * @opcode 0xa7
7581 * @opflclass arithmetic
7582 * @opfltest df
7583 */
7584FNIEMOP_DEF(iemOp_cmpswd_Xv_Yv)
7585{
7586 /*
7587 * Use the C implementation if a repeat prefix is encountered.
7588 */
7589 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_REPZ)
7590 {
7591 IEMOP_MNEMONIC(repe_cmps_Xv_Yv, "repe cmps Xv,Yv");
7592 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7593 switch (pVCpu->iem.s.enmEffOpSize)
7594 {
7595 case IEMMODE_16BIT:
7596 switch (pVCpu->iem.s.enmEffAddrMode)
7597 {
7598 case IEMMODE_16BIT:
7599 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7600 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7601 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7602 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7603 iemCImpl_repe_cmps_op16_addr16, pVCpu->iem.s.iEffSeg);
7604 case IEMMODE_32BIT:
7605 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7606 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7607 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7608 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7609 iemCImpl_repe_cmps_op16_addr32, pVCpu->iem.s.iEffSeg);
7610 case IEMMODE_64BIT:
7611 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7612 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7613 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7614 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7615 iemCImpl_repe_cmps_op16_addr64, pVCpu->iem.s.iEffSeg);
7616 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7617 }
7618 break;
7619 case IEMMODE_32BIT:
7620 switch (pVCpu->iem.s.enmEffAddrMode)
7621 {
7622 case IEMMODE_16BIT:
7623 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7624 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7625 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7626 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7627 iemCImpl_repe_cmps_op32_addr16, pVCpu->iem.s.iEffSeg);
7628 case IEMMODE_32BIT:
7629 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7630 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7631 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7632 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7633 iemCImpl_repe_cmps_op32_addr32, pVCpu->iem.s.iEffSeg);
7634 case IEMMODE_64BIT:
7635 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7636 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7637 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7638 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7639 iemCImpl_repe_cmps_op32_addr64, pVCpu->iem.s.iEffSeg);
7640 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7641 }
7642 case IEMMODE_64BIT:
7643 switch (pVCpu->iem.s.enmEffAddrMode)
7644 {
7645 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_4);
7646 case IEMMODE_32BIT:
7647 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7648 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7649 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7650 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7651 iemCImpl_repe_cmps_op64_addr32, pVCpu->iem.s.iEffSeg);
7652 case IEMMODE_64BIT:
7653 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7654 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7655 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7656 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7657 iemCImpl_repe_cmps_op64_addr64, pVCpu->iem.s.iEffSeg);
7658 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7659 }
7660 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7661 }
7662 }
7663
7664 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_REPNZ)
7665 {
7666 IEMOP_MNEMONIC(repne_cmps_Xv_Yv, "repne cmps Xv,Yv");
7667 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7668 switch (pVCpu->iem.s.enmEffOpSize)
7669 {
7670 case IEMMODE_16BIT:
7671 switch (pVCpu->iem.s.enmEffAddrMode)
7672 {
7673 case IEMMODE_16BIT:
7674 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7675 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7676 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7677 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7678 iemCImpl_repne_cmps_op16_addr16, pVCpu->iem.s.iEffSeg);
7679 case IEMMODE_32BIT:
7680 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7681 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7682 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7683 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7684 iemCImpl_repne_cmps_op16_addr32, pVCpu->iem.s.iEffSeg);
7685 case IEMMODE_64BIT:
7686 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7687 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7688 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7689 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7690 iemCImpl_repne_cmps_op16_addr64, pVCpu->iem.s.iEffSeg);
7691 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7692 }
7693 break;
7694 case IEMMODE_32BIT:
7695 switch (pVCpu->iem.s.enmEffAddrMode)
7696 {
7697 case IEMMODE_16BIT:
7698 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7699 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7700 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7701 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7702 iemCImpl_repne_cmps_op32_addr16, pVCpu->iem.s.iEffSeg);
7703 case IEMMODE_32BIT:
7704 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7705 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7706 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7707 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7708 iemCImpl_repne_cmps_op32_addr32, pVCpu->iem.s.iEffSeg);
7709 case IEMMODE_64BIT:
7710 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7711 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7712 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7713 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7714 iemCImpl_repne_cmps_op32_addr64, pVCpu->iem.s.iEffSeg);
7715 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7716 }
7717 case IEMMODE_64BIT:
7718 switch (pVCpu->iem.s.enmEffAddrMode)
7719 {
7720 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_2);
7721 case IEMMODE_32BIT:
7722 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7723 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7724 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7725 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7726 iemCImpl_repne_cmps_op64_addr32, pVCpu->iem.s.iEffSeg);
7727 case IEMMODE_64BIT:
7728 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
7729 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
7730 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7731 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7732 iemCImpl_repne_cmps_op64_addr64, pVCpu->iem.s.iEffSeg);
7733 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7734 }
7735 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7736 }
7737 }
7738
7739 /*
7740 * Annoying double switch here.
7741 * Using ugly macro for implementing the cases, sharing it with cmpsb.
7742 */
7743 IEMOP_MNEMONIC(cmps_Xv_Yv, "cmps Xv,Yv");
7744 switch (pVCpu->iem.s.enmEffOpSize)
7745 {
7746 case IEMMODE_16BIT:
7747 switch (pVCpu->iem.s.enmEffAddrMode)
7748 {
7749 case IEMMODE_16BIT: IEM_CMPS_CASE(16, 16, IEM_MC_F_NOT_64BIT); break;
7750 case IEMMODE_32BIT: IEM_CMPS_CASE(16, 32, IEM_MC_F_MIN_386); break;
7751 case IEMMODE_64BIT: IEM_CMPS_CASE(16, 64, IEM_MC_F_64BIT); break;
7752 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7753 }
7754 break;
7755
7756 case IEMMODE_32BIT:
7757 switch (pVCpu->iem.s.enmEffAddrMode)
7758 {
7759 case IEMMODE_16BIT: IEM_CMPS_CASE(32, 16, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT); break;
7760 case IEMMODE_32BIT: IEM_CMPS_CASE(32, 32, IEM_MC_F_MIN_386); break;
7761 case IEMMODE_64BIT: IEM_CMPS_CASE(32, 64, IEM_MC_F_64BIT); break;
7762 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7763 }
7764 break;
7765
7766 case IEMMODE_64BIT:
7767 switch (pVCpu->iem.s.enmEffAddrMode)
7768 {
7769 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_1); /* cannot be encoded */ break;
7770 case IEMMODE_32BIT: IEM_CMPS_CASE(64, 32, IEM_MC_F_MIN_386); break;
7771 case IEMMODE_64BIT: IEM_CMPS_CASE(64, 64, IEM_MC_F_64BIT); break;
7772 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7773 }
7774 break;
7775 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7776 }
7777}
7778
7779#undef IEM_CMPS_CASE
7780
7781/**
7782 * @opcode 0xa8
7783 * @opflclass logical
7784 */
7785FNIEMOP_DEF(iemOp_test_AL_Ib)
7786{
7787 IEMOP_MNEMONIC(test_al_Ib, "test al,Ib");
7788 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
7789 IEMOP_BODY_BINARY_AL_Ib(test, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
7790}
7791
7792
7793/**
7794 * @opcode 0xa9
7795 * @opflclass logical
7796 */
7797FNIEMOP_DEF(iemOp_test_eAX_Iz)
7798{
7799 IEMOP_MNEMONIC(test_rAX_Iz, "test rAX,Iz");
7800 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
7801 IEMOP_BODY_BINARY_rAX_Iz_RO(test, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
7802}
7803
7804
7805/** Macro used by iemOp_stosb_Yb_AL and iemOp_stoswd_Yv_eAX */
7806#define IEM_STOS_CASE(ValBits, AddrBits, a_fMcFlags) \
7807 IEM_MC_BEGIN(0, 2, a_fMcFlags, 0); \
7808 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
7809 IEM_MC_LOCAL(uint##ValBits##_t, uValue); \
7810 IEM_MC_LOCAL(RTGCPTR, uAddr); \
7811 IEM_MC_FETCH_GREG_U##ValBits(uValue, X86_GREG_xAX); \
7812 IEM_MC_FETCH_GREG_U##AddrBits##_ZX_U64(uAddr, X86_GREG_xDI); \
7813 IEM_MC_STORE_MEM_U##ValBits(X86_SREG_ES, uAddr, uValue); \
7814 IEM_MC_IF_EFL_BIT_SET(X86_EFL_DF) { \
7815 IEM_MC_SUB_GREG_U##AddrBits(X86_GREG_xDI, ValBits / 8); \
7816 } IEM_MC_ELSE() { \
7817 IEM_MC_ADD_GREG_U##AddrBits(X86_GREG_xDI, ValBits / 8); \
7818 } IEM_MC_ENDIF(); \
7819 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
7820 IEM_MC_END() \
7821
7822/**
7823 * @opcode 0xaa
7824 */
7825FNIEMOP_DEF(iemOp_stosb_Yb_AL)
7826{
7827 /*
7828 * Use the C implementation if a repeat prefix is encountered.
7829 */
7830 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
7831 {
7832 IEMOP_MNEMONIC(rep_stos_Yb_al, "rep stos Yb,al");
7833 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7834 switch (pVCpu->iem.s.enmEffAddrMode)
7835 {
7836 case IEMMODE_16BIT:
7837 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP,
7838 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7839 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7840 iemCImpl_stos_al_m16);
7841 case IEMMODE_32BIT:
7842 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP,
7843 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7844 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7845 iemCImpl_stos_al_m32);
7846 case IEMMODE_64BIT:
7847 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP,
7848 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7849 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7850 iemCImpl_stos_al_m64);
7851 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7852 }
7853 }
7854
7855 /*
7856 * Sharing case implementation with stos[wdq] below.
7857 */
7858 IEMOP_MNEMONIC(stos_Yb_al, "stos Yb,al");
7859 switch (pVCpu->iem.s.enmEffAddrMode)
7860 {
7861 case IEMMODE_16BIT: IEM_STOS_CASE(8, 16, IEM_MC_F_NOT_64BIT); break;
7862 case IEMMODE_32BIT: IEM_STOS_CASE(8, 32, IEM_MC_F_MIN_386); break;
7863 case IEMMODE_64BIT: IEM_STOS_CASE(8, 64, IEM_MC_F_64BIT); break;
7864 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7865 }
7866}
7867
7868
7869/**
7870 * @opcode 0xab
7871 */
7872FNIEMOP_DEF(iemOp_stoswd_Yv_eAX)
7873{
7874 /*
7875 * Use the C implementation if a repeat prefix is encountered.
7876 */
7877 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
7878 {
7879 IEMOP_MNEMONIC(rep_stos_Yv_rAX, "rep stos Yv,rAX");
7880 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
7881 switch (pVCpu->iem.s.enmEffOpSize)
7882 {
7883 case IEMMODE_16BIT:
7884 switch (pVCpu->iem.s.enmEffAddrMode)
7885 {
7886 case IEMMODE_16BIT:
7887 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_REP,
7888 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7889 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7890 iemCImpl_stos_ax_m16);
7891 case IEMMODE_32BIT:
7892 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_REP,
7893 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7894 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7895 iemCImpl_stos_ax_m32);
7896 case IEMMODE_64BIT:
7897 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_REP,
7898 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7899 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7900 iemCImpl_stos_ax_m64);
7901 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7902 }
7903 break;
7904 case IEMMODE_32BIT:
7905 switch (pVCpu->iem.s.enmEffAddrMode)
7906 {
7907 case IEMMODE_16BIT:
7908 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_REP,
7909 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7910 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7911 iemCImpl_stos_eax_m16);
7912 case IEMMODE_32BIT:
7913 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_REP,
7914 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7915 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7916 iemCImpl_stos_eax_m32);
7917 case IEMMODE_64BIT:
7918 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_REP,
7919 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7920 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7921 iemCImpl_stos_eax_m64);
7922 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7923 }
7924 case IEMMODE_64BIT:
7925 switch (pVCpu->iem.s.enmEffAddrMode)
7926 {
7927 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_9);
7928 case IEMMODE_32BIT:
7929 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_REP,
7930 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7931 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7932 iemCImpl_stos_rax_m32);
7933 case IEMMODE_64BIT:
7934 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_REP,
7935 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
7936 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
7937 iemCImpl_stos_rax_m64);
7938 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7939 }
7940 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7941 }
7942 }
7943
7944 /*
7945 * Annoying double switch here.
7946 * Using ugly macro for implementing the cases, sharing it with stosb.
7947 */
7948 IEMOP_MNEMONIC(stos_Yv_rAX, "stos Yv,rAX");
7949 switch (pVCpu->iem.s.enmEffOpSize)
7950 {
7951 case IEMMODE_16BIT:
7952 switch (pVCpu->iem.s.enmEffAddrMode)
7953 {
7954 case IEMMODE_16BIT: IEM_STOS_CASE(16, 16, IEM_MC_F_NOT_64BIT); break;
7955 case IEMMODE_32BIT: IEM_STOS_CASE(16, 32, IEM_MC_F_MIN_386); break;
7956 case IEMMODE_64BIT: IEM_STOS_CASE(16, 64, IEM_MC_F_64BIT); break;
7957 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7958 }
7959 break;
7960
7961 case IEMMODE_32BIT:
7962 switch (pVCpu->iem.s.enmEffAddrMode)
7963 {
7964 case IEMMODE_16BIT: IEM_STOS_CASE(32, 16, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT); break;
7965 case IEMMODE_32BIT: IEM_STOS_CASE(32, 32, IEM_MC_F_MIN_386); break;
7966 case IEMMODE_64BIT: IEM_STOS_CASE(32, 64, IEM_MC_F_64BIT); break;
7967 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7968 }
7969 break;
7970
7971 case IEMMODE_64BIT:
7972 switch (pVCpu->iem.s.enmEffAddrMode)
7973 {
7974 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_1); /* cannot be encoded */ break;
7975 case IEMMODE_32BIT: IEM_STOS_CASE(64, 32, IEM_MC_F_64BIT); break;
7976 case IEMMODE_64BIT: IEM_STOS_CASE(64, 64, IEM_MC_F_64BIT); break;
7977 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7978 }
7979 break;
7980 IEM_NOT_REACHED_DEFAULT_CASE_RET();
7981 }
7982}
7983
7984#undef IEM_STOS_CASE
7985
7986/** Macro used by iemOp_lodsb_AL_Xb and iemOp_lodswd_eAX_Xv */
7987#define IEM_LODS_CASE(ValBits, AddrBits, a_fMcFlags) \
7988 IEM_MC_BEGIN(0, 2, a_fMcFlags, 0); \
7989 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
7990 IEM_MC_LOCAL(uint##ValBits##_t, uValue); \
7991 IEM_MC_LOCAL(RTGCPTR, uAddr); \
7992 IEM_MC_FETCH_GREG_U##AddrBits##_ZX_U64(uAddr, X86_GREG_xSI); \
7993 IEM_MC_FETCH_MEM_U##ValBits(uValue, pVCpu->iem.s.iEffSeg, uAddr); \
7994 IEM_MC_STORE_GREG_U##ValBits(X86_GREG_xAX, uValue); \
7995 IEM_MC_IF_EFL_BIT_SET(X86_EFL_DF) { \
7996 IEM_MC_SUB_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \
7997 } IEM_MC_ELSE() { \
7998 IEM_MC_ADD_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \
7999 } IEM_MC_ENDIF(); \
8000 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8001 IEM_MC_END() \
8002
8003/**
8004 * @opcode 0xac
8005 * @opfltest df
8006 */
8007FNIEMOP_DEF(iemOp_lodsb_AL_Xb)
8008{
8009 /*
8010 * Use the C implementation if a repeat prefix is encountered.
8011 */
8012 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
8013 {
8014 IEMOP_MNEMONIC(rep_lodsb_AL_Xb, "rep lodsb AL,Xb");
8015 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8016 switch (pVCpu->iem.s.enmEffAddrMode)
8017 {
8018 case IEMMODE_16BIT:
8019 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8020 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8021 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8022 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8023 iemCImpl_lods_al_m16, pVCpu->iem.s.iEffSeg);
8024 case IEMMODE_32BIT:
8025 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8026 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8027 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8028 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8029 iemCImpl_lods_al_m32, pVCpu->iem.s.iEffSeg);
8030 case IEMMODE_64BIT:
8031 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8032 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8033 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8034 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8035 iemCImpl_lods_al_m64, pVCpu->iem.s.iEffSeg);
8036 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8037 }
8038 }
8039
8040 /*
8041 * Sharing case implementation with stos[wdq] below.
8042 */
8043 IEMOP_MNEMONIC(lodsb_AL_Xb, "lodsb AL,Xb");
8044 switch (pVCpu->iem.s.enmEffAddrMode)
8045 {
8046 case IEMMODE_16BIT: IEM_LODS_CASE(8, 16, IEM_MC_F_NOT_64BIT); break;
8047 case IEMMODE_32BIT: IEM_LODS_CASE(8, 32, IEM_MC_F_MIN_386); break;
8048 case IEMMODE_64BIT: IEM_LODS_CASE(8, 64, IEM_MC_F_64BIT); break;
8049 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8050 }
8051}
8052
8053
8054/**
8055 * @opcode 0xad
8056 * @opfltest df
8057 */
8058FNIEMOP_DEF(iemOp_lodswd_eAX_Xv)
8059{
8060 /*
8061 * Use the C implementation if a repeat prefix is encountered.
8062 */
8063 if (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
8064 {
8065 IEMOP_MNEMONIC(rep_lods_rAX_Xv, "rep lods rAX,Xv");
8066 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8067 switch (pVCpu->iem.s.enmEffOpSize)
8068 {
8069 case IEMMODE_16BIT:
8070 switch (pVCpu->iem.s.enmEffAddrMode)
8071 {
8072 case IEMMODE_16BIT:
8073 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8074 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8075 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8076 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8077 iemCImpl_lods_ax_m16, pVCpu->iem.s.iEffSeg);
8078 case IEMMODE_32BIT:
8079 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8080 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8081 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8082 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8083 iemCImpl_lods_ax_m32, pVCpu->iem.s.iEffSeg);
8084 case IEMMODE_64BIT:
8085 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8086 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8087 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8088 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8089 iemCImpl_lods_ax_m64, pVCpu->iem.s.iEffSeg);
8090 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8091 }
8092 break;
8093 case IEMMODE_32BIT:
8094 switch (pVCpu->iem.s.enmEffAddrMode)
8095 {
8096 case IEMMODE_16BIT:
8097 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8098 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8099 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8100 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8101 iemCImpl_lods_eax_m16, pVCpu->iem.s.iEffSeg);
8102 case IEMMODE_32BIT:
8103 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8104 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8105 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8106 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8107 iemCImpl_lods_eax_m32, pVCpu->iem.s.iEffSeg);
8108 case IEMMODE_64BIT:
8109 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8110 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8111 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8112 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8113 iemCImpl_lods_eax_m64, pVCpu->iem.s.iEffSeg);
8114 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8115 }
8116 case IEMMODE_64BIT:
8117 switch (pVCpu->iem.s.enmEffAddrMode)
8118 {
8119 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_7);
8120 case IEMMODE_32BIT:
8121 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8122 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8123 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8124 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8125 iemCImpl_lods_rax_m32, pVCpu->iem.s.iEffSeg);
8126 case IEMMODE_64BIT:
8127 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_REP,
8128 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX)
8129 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSI)
8130 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8131 iemCImpl_lods_rax_m64, pVCpu->iem.s.iEffSeg);
8132 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8133 }
8134 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8135 }
8136 }
8137
8138 /*
8139 * Annoying double switch here.
8140 * Using ugly macro for implementing the cases, sharing it with lodsb.
8141 */
8142 IEMOP_MNEMONIC(lods_rAX_Xv, "lods rAX,Xv");
8143 switch (pVCpu->iem.s.enmEffOpSize)
8144 {
8145 case IEMMODE_16BIT:
8146 switch (pVCpu->iem.s.enmEffAddrMode)
8147 {
8148 case IEMMODE_16BIT: IEM_LODS_CASE(16, 16, IEM_MC_F_NOT_64BIT); break;
8149 case IEMMODE_32BIT: IEM_LODS_CASE(16, 32, IEM_MC_F_MIN_386); break;
8150 case IEMMODE_64BIT: IEM_LODS_CASE(16, 64, IEM_MC_F_64BIT); break;
8151 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8152 }
8153 break;
8154
8155 case IEMMODE_32BIT:
8156 switch (pVCpu->iem.s.enmEffAddrMode)
8157 {
8158 case IEMMODE_16BIT: IEM_LODS_CASE(32, 16, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT); break;
8159 case IEMMODE_32BIT: IEM_LODS_CASE(32, 32, IEM_MC_F_MIN_386); break;
8160 case IEMMODE_64BIT: IEM_LODS_CASE(32, 64, IEM_MC_F_64BIT); break;
8161 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8162 }
8163 break;
8164
8165 case IEMMODE_64BIT:
8166 switch (pVCpu->iem.s.enmEffAddrMode)
8167 {
8168 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_1); /* cannot be encoded */ break;
8169 case IEMMODE_32BIT: IEM_LODS_CASE(64, 32, IEM_MC_F_64BIT); break;
8170 case IEMMODE_64BIT: IEM_LODS_CASE(64, 64, IEM_MC_F_64BIT); break;
8171 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8172 }
8173 break;
8174 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8175 }
8176}
8177
8178#undef IEM_LODS_CASE
8179
8180/** Macro used by iemOp_scasb_AL_Xb and iemOp_scaswd_eAX_Xv */
8181#define IEM_SCAS_CASE(ValBits, AddrBits, a_fMcFlags) \
8182 IEM_MC_BEGIN(3, 2, a_fMcFlags, 0); \
8183 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
8184 IEM_MC_ARG(uint##ValBits##_t *, puRax, 0); \
8185 IEM_MC_ARG(uint##ValBits##_t, uValue, 1); \
8186 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
8187 IEM_MC_LOCAL(RTGCPTR, uAddr); \
8188 \
8189 IEM_MC_FETCH_GREG_U##AddrBits##_ZX_U64(uAddr, X86_GREG_xDI); \
8190 IEM_MC_FETCH_MEM_U##ValBits(uValue, X86_SREG_ES, uAddr); \
8191 IEM_MC_REF_GREG_U##ValBits(puRax, X86_GREG_xAX); \
8192 IEM_MC_REF_EFLAGS(pEFlags); \
8193 IEM_MC_CALL_VOID_AIMPL_3(iemAImpl_cmp_u##ValBits, puRax, uValue, pEFlags); \
8194 \
8195 IEM_MC_IF_EFL_BIT_SET(X86_EFL_DF) { \
8196 IEM_MC_SUB_GREG_U##AddrBits(X86_GREG_xDI, ValBits / 8); \
8197 } IEM_MC_ELSE() { \
8198 IEM_MC_ADD_GREG_U##AddrBits(X86_GREG_xDI, ValBits / 8); \
8199 } IEM_MC_ENDIF(); \
8200 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8201 IEM_MC_END();
8202
8203/**
8204 * @opcode 0xae
8205 * @opflclass arithmetic
8206 * @opfltest df
8207 */
8208FNIEMOP_DEF(iemOp_scasb_AL_Xb)
8209{
8210 /*
8211 * Use the C implementation if a repeat prefix is encountered.
8212 */
8213 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_REPZ)
8214 {
8215 IEMOP_MNEMONIC(repe_scasb_AL_Xb, "repe scasb AL,Xb");
8216 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8217 switch (pVCpu->iem.s.enmEffAddrMode)
8218 {
8219 case IEMMODE_16BIT:
8220 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8221 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8222 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8223 iemCImpl_repe_scas_al_m16);
8224 case IEMMODE_32BIT:
8225 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8226 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8227 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8228 iemCImpl_repe_scas_al_m32);
8229 case IEMMODE_64BIT:
8230 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8231 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8232 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8233 iemCImpl_repe_scas_al_m64);
8234 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8235 }
8236 }
8237 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_REPNZ)
8238 {
8239 IEMOP_MNEMONIC(repone_scasb_AL_Xb, "repne scasb AL,Xb");
8240 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8241 switch (pVCpu->iem.s.enmEffAddrMode)
8242 {
8243 case IEMMODE_16BIT:
8244 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8245 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8246 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8247 iemCImpl_repne_scas_al_m16);
8248 case IEMMODE_32BIT:
8249 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8250 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8251 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8252 iemCImpl_repne_scas_al_m32);
8253 case IEMMODE_64BIT:
8254 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8255 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8256 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8257 iemCImpl_repne_scas_al_m64);
8258 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8259 }
8260 }
8261
8262 /*
8263 * Sharing case implementation with stos[wdq] below.
8264 */
8265 IEMOP_MNEMONIC(scasb_AL_Xb, "scasb AL,Xb");
8266 switch (pVCpu->iem.s.enmEffAddrMode)
8267 {
8268 case IEMMODE_16BIT: IEM_SCAS_CASE(8, 16, IEM_MC_F_NOT_64BIT); break;
8269 case IEMMODE_32BIT: IEM_SCAS_CASE(8, 32, IEM_MC_F_MIN_386); break;
8270 case IEMMODE_64BIT: IEM_SCAS_CASE(8, 64, IEM_MC_F_64BIT); break;
8271 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8272 }
8273}
8274
8275
8276/**
8277 * @opcode 0xaf
8278 * @opflclass arithmetic
8279 * @opfltest df
8280 */
8281FNIEMOP_DEF(iemOp_scaswd_eAX_Xv)
8282{
8283 /*
8284 * Use the C implementation if a repeat prefix is encountered.
8285 */
8286 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_REPZ)
8287 {
8288 IEMOP_MNEMONIC(repe_scas_rAX_Xv, "repe scas rAX,Xv");
8289 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8290 switch (pVCpu->iem.s.enmEffOpSize)
8291 {
8292 case IEMMODE_16BIT:
8293 switch (pVCpu->iem.s.enmEffAddrMode)
8294 {
8295 case IEMMODE_16BIT:
8296 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8297 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8298 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8299 iemCImpl_repe_scas_ax_m16);
8300 case IEMMODE_32BIT:
8301 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8302 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8303 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8304 iemCImpl_repe_scas_ax_m32);
8305 case IEMMODE_64BIT:
8306 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8307 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8308 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8309 iemCImpl_repe_scas_ax_m64);
8310 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8311 }
8312 break;
8313 case IEMMODE_32BIT:
8314 switch (pVCpu->iem.s.enmEffAddrMode)
8315 {
8316 case IEMMODE_16BIT:
8317 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8318 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8319 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8320 iemCImpl_repe_scas_eax_m16);
8321 case IEMMODE_32BIT:
8322 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8323 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8324 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8325 iemCImpl_repe_scas_eax_m32);
8326 case IEMMODE_64BIT:
8327 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8328 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8329 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8330 iemCImpl_repe_scas_eax_m64);
8331 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8332 }
8333 case IEMMODE_64BIT:
8334 switch (pVCpu->iem.s.enmEffAddrMode)
8335 {
8336 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_6); /** @todo It's this wrong, we can do 16-bit addressing in 64-bit mode, but not 32-bit. right? */
8337 case IEMMODE_32BIT:
8338 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8339 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8340 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8341 iemCImpl_repe_scas_rax_m32);
8342 case IEMMODE_64BIT:
8343 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8344 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8345 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8346 iemCImpl_repe_scas_rax_m64);
8347 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8348 }
8349 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8350 }
8351 }
8352 if (pVCpu->iem.s.fPrefixes & IEM_OP_PRF_REPNZ)
8353 {
8354 IEMOP_MNEMONIC(repne_scas_rAX_Xv, "repne scas rAX,Xv");
8355 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8356 switch (pVCpu->iem.s.enmEffOpSize)
8357 {
8358 case IEMMODE_16BIT:
8359 switch (pVCpu->iem.s.enmEffAddrMode)
8360 {
8361 case IEMMODE_16BIT:
8362 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8363 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8364 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8365 iemCImpl_repne_scas_ax_m16);
8366 case IEMMODE_32BIT:
8367 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8368 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8369 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8370 iemCImpl_repne_scas_ax_m32);
8371 case IEMMODE_64BIT:
8372 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8373 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8374 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8375 iemCImpl_repne_scas_ax_m64);
8376 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8377 }
8378 break;
8379 case IEMMODE_32BIT:
8380 switch (pVCpu->iem.s.enmEffAddrMode)
8381 {
8382 case IEMMODE_16BIT:
8383 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8384 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8385 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8386 iemCImpl_repne_scas_eax_m16);
8387 case IEMMODE_32BIT:
8388 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8389 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8390 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8391 iemCImpl_repne_scas_eax_m32);
8392 case IEMMODE_64BIT:
8393 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8394 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8395 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8396 iemCImpl_repne_scas_eax_m64);
8397 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8398 }
8399 case IEMMODE_64BIT:
8400 switch (pVCpu->iem.s.enmEffAddrMode)
8401 {
8402 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_5);
8403 case IEMMODE_32BIT:
8404 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8405 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8406 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8407 iemCImpl_repne_scas_rax_m32);
8408 case IEMMODE_64BIT:
8409 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_REP | IEM_CIMPL_F_STATUS_FLAGS,
8410 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xDI)
8411 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xCX),
8412 iemCImpl_repne_scas_rax_m64);
8413 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8414 }
8415 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8416 }
8417 }
8418
8419 /*
8420 * Annoying double switch here.
8421 * Using ugly macro for implementing the cases, sharing it with scasb.
8422 */
8423 IEMOP_MNEMONIC(scas_rAX_Xv, "scas rAX,Xv");
8424 switch (pVCpu->iem.s.enmEffOpSize)
8425 {
8426 case IEMMODE_16BIT:
8427 switch (pVCpu->iem.s.enmEffAddrMode)
8428 {
8429 case IEMMODE_16BIT: IEM_SCAS_CASE(16, 16, IEM_MC_F_NOT_64BIT); break;
8430 case IEMMODE_32BIT: IEM_SCAS_CASE(16, 32, IEM_MC_F_MIN_386); break;
8431 case IEMMODE_64BIT: IEM_SCAS_CASE(16, 64, IEM_MC_F_64BIT); break;
8432 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8433 }
8434 break;
8435
8436 case IEMMODE_32BIT:
8437 switch (pVCpu->iem.s.enmEffAddrMode)
8438 {
8439 case IEMMODE_16BIT: IEM_SCAS_CASE(32, 16, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT); break;
8440 case IEMMODE_32BIT: IEM_SCAS_CASE(32, 32, IEM_MC_F_MIN_386); break;
8441 case IEMMODE_64BIT: IEM_SCAS_CASE(32, 64, IEM_MC_F_64BIT); break;
8442 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8443 }
8444 break;
8445
8446 case IEMMODE_64BIT:
8447 switch (pVCpu->iem.s.enmEffAddrMode)
8448 {
8449 case IEMMODE_16BIT: AssertFailedReturn(VERR_IEM_IPE_1); /* cannot be encoded */ break;
8450 case IEMMODE_32BIT: IEM_SCAS_CASE(64, 32, IEM_MC_F_64BIT); break;
8451 case IEMMODE_64BIT: IEM_SCAS_CASE(64, 64, IEM_MC_F_64BIT); break;
8452 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8453 }
8454 break;
8455 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8456 }
8457}
8458
8459#undef IEM_SCAS_CASE
8460
8461/**
8462 * Common 'mov r8, imm8' helper.
8463 */
8464FNIEMOP_DEF_1(iemOpCommonMov_r8_Ib, uint8_t, iFixedReg)
8465{
8466 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
8467 IEM_MC_BEGIN(0, 0, 0, 0);
8468 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8469 IEM_MC_STORE_GREG_U8_CONST(iFixedReg, u8Imm);
8470 IEM_MC_ADVANCE_RIP_AND_FINISH();
8471 IEM_MC_END();
8472}
8473
8474
8475/**
8476 * @opcode 0xb0
8477 */
8478FNIEMOP_DEF(iemOp_mov_AL_Ib)
8479{
8480 IEMOP_MNEMONIC(mov_AL_Ib, "mov AL,Ib");
8481 return FNIEMOP_CALL_1(iemOpCommonMov_r8_Ib, X86_GREG_xAX | pVCpu->iem.s.uRexB);
8482}
8483
8484
8485/**
8486 * @opcode 0xb1
8487 */
8488FNIEMOP_DEF(iemOp_CL_Ib)
8489{
8490 IEMOP_MNEMONIC(mov_CL_Ib, "mov CL,Ib");
8491 return FNIEMOP_CALL_1(iemOpCommonMov_r8_Ib, X86_GREG_xCX | pVCpu->iem.s.uRexB);
8492}
8493
8494
8495/**
8496 * @opcode 0xb2
8497 */
8498FNIEMOP_DEF(iemOp_DL_Ib)
8499{
8500 IEMOP_MNEMONIC(mov_DL_Ib, "mov DL,Ib");
8501 return FNIEMOP_CALL_1(iemOpCommonMov_r8_Ib, X86_GREG_xDX | pVCpu->iem.s.uRexB);
8502}
8503
8504
8505/**
8506 * @opcode 0xb3
8507 */
8508FNIEMOP_DEF(iemOp_BL_Ib)
8509{
8510 IEMOP_MNEMONIC(mov_BL_Ib, "mov BL,Ib");
8511 return FNIEMOP_CALL_1(iemOpCommonMov_r8_Ib, X86_GREG_xBX | pVCpu->iem.s.uRexB);
8512}
8513
8514
8515/**
8516 * @opcode 0xb4
8517 */
8518FNIEMOP_DEF(iemOp_mov_AH_Ib)
8519{
8520 IEMOP_MNEMONIC(mov_AH_Ib, "mov AH,Ib");
8521 return FNIEMOP_CALL_1(iemOpCommonMov_r8_Ib, X86_GREG_xSP | pVCpu->iem.s.uRexB);
8522}
8523
8524
8525/**
8526 * @opcode 0xb5
8527 */
8528FNIEMOP_DEF(iemOp_CH_Ib)
8529{
8530 IEMOP_MNEMONIC(mov_CH_Ib, "mov CH,Ib");
8531 return FNIEMOP_CALL_1(iemOpCommonMov_r8_Ib, X86_GREG_xBP | pVCpu->iem.s.uRexB);
8532}
8533
8534
8535/**
8536 * @opcode 0xb6
8537 */
8538FNIEMOP_DEF(iemOp_DH_Ib)
8539{
8540 IEMOP_MNEMONIC(mov_DH_Ib, "mov DH,Ib");
8541 return FNIEMOP_CALL_1(iemOpCommonMov_r8_Ib, X86_GREG_xSI | pVCpu->iem.s.uRexB);
8542}
8543
8544
8545/**
8546 * @opcode 0xb7
8547 */
8548FNIEMOP_DEF(iemOp_BH_Ib)
8549{
8550 IEMOP_MNEMONIC(mov_BH_Ib, "mov BH,Ib");
8551 return FNIEMOP_CALL_1(iemOpCommonMov_r8_Ib, X86_GREG_xDI | pVCpu->iem.s.uRexB);
8552}
8553
8554
8555/**
8556 * Common 'mov regX,immX' helper.
8557 */
8558FNIEMOP_DEF_1(iemOpCommonMov_Rv_Iv, uint8_t, iFixedReg)
8559{
8560 switch (pVCpu->iem.s.enmEffOpSize)
8561 {
8562 case IEMMODE_16BIT:
8563 IEM_MC_BEGIN(0, 0, 0, 0);
8564 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm);
8565 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8566 IEM_MC_STORE_GREG_U16_CONST(iFixedReg, u16Imm);
8567 IEM_MC_ADVANCE_RIP_AND_FINISH();
8568 IEM_MC_END();
8569 break;
8570
8571 case IEMMODE_32BIT:
8572 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386, 0);
8573 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm);
8574 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8575 IEM_MC_STORE_GREG_U32_CONST(iFixedReg, u32Imm);
8576 IEM_MC_ADVANCE_RIP_AND_FINISH();
8577 IEM_MC_END();
8578 break;
8579
8580 case IEMMODE_64BIT:
8581 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
8582 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_U64(&u64Imm); /* 64-bit immediate! */
8583 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
8584 IEM_MC_STORE_GREG_U64_CONST(iFixedReg, u64Imm);
8585 IEM_MC_ADVANCE_RIP_AND_FINISH();
8586 IEM_MC_END();
8587 break;
8588 IEM_NOT_REACHED_DEFAULT_CASE_RET();
8589 }
8590}
8591
8592
8593/**
8594 * @opcode 0xb8
8595 */
8596FNIEMOP_DEF(iemOp_eAX_Iv)
8597{
8598 IEMOP_MNEMONIC(mov_rAX_IV, "mov rAX,IV");
8599 return FNIEMOP_CALL_1(iemOpCommonMov_Rv_Iv, X86_GREG_xAX | pVCpu->iem.s.uRexB);
8600}
8601
8602
8603/**
8604 * @opcode 0xb9
8605 */
8606FNIEMOP_DEF(iemOp_eCX_Iv)
8607{
8608 IEMOP_MNEMONIC(mov_rCX_IV, "mov rCX,IV");
8609 return FNIEMOP_CALL_1(iemOpCommonMov_Rv_Iv, X86_GREG_xCX | pVCpu->iem.s.uRexB);
8610}
8611
8612
8613/**
8614 * @opcode 0xba
8615 */
8616FNIEMOP_DEF(iemOp_eDX_Iv)
8617{
8618 IEMOP_MNEMONIC(mov_rDX_IV, "mov rDX,IV");
8619 return FNIEMOP_CALL_1(iemOpCommonMov_Rv_Iv, X86_GREG_xDX | pVCpu->iem.s.uRexB);
8620}
8621
8622
8623/**
8624 * @opcode 0xbb
8625 */
8626FNIEMOP_DEF(iemOp_eBX_Iv)
8627{
8628 IEMOP_MNEMONIC(mov_rBX_IV, "mov rBX,IV");
8629 return FNIEMOP_CALL_1(iemOpCommonMov_Rv_Iv, X86_GREG_xBX | pVCpu->iem.s.uRexB);
8630}
8631
8632
8633/**
8634 * @opcode 0xbc
8635 */
8636FNIEMOP_DEF(iemOp_eSP_Iv)
8637{
8638 IEMOP_MNEMONIC(mov_rSP_IV, "mov rSP,IV");
8639 return FNIEMOP_CALL_1(iemOpCommonMov_Rv_Iv, X86_GREG_xSP | pVCpu->iem.s.uRexB);
8640}
8641
8642
8643/**
8644 * @opcode 0xbd
8645 */
8646FNIEMOP_DEF(iemOp_eBP_Iv)
8647{
8648 IEMOP_MNEMONIC(mov_rBP_IV, "mov rBP,IV");
8649 return FNIEMOP_CALL_1(iemOpCommonMov_Rv_Iv, X86_GREG_xBP | pVCpu->iem.s.uRexB);
8650}
8651
8652
8653/**
8654 * @opcode 0xbe
8655 */
8656FNIEMOP_DEF(iemOp_eSI_Iv)
8657{
8658 IEMOP_MNEMONIC(mov_rSI_IV, "mov rSI,IV");
8659 return FNIEMOP_CALL_1(iemOpCommonMov_Rv_Iv, X86_GREG_xSI | pVCpu->iem.s.uRexB);
8660}
8661
8662
8663/**
8664 * @opcode 0xbf
8665 */
8666FNIEMOP_DEF(iemOp_eDI_Iv)
8667{
8668 IEMOP_MNEMONIC(mov_rDI_IV, "mov rDI,IV");
8669 return FNIEMOP_CALL_1(iemOpCommonMov_Rv_Iv, X86_GREG_xDI | pVCpu->iem.s.uRexB);
8670}
8671
8672
8673/**
8674 * @opcode 0xc0
8675 */
8676FNIEMOP_DEF(iemOp_Grp2_Eb_Ib)
8677{
8678 IEMOP_HLP_MIN_186();
8679 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
8680
8681 /* Need to use a body macro here since the EFLAGS behaviour differs between
8682 the shifts, rotates and rotate w/ carry. Sigh. */
8683#define GRP2_BODY_Eb_Ib(a_pImplExpr) \
8684 PCIEMOPSHIFTSIZES const pImpl = (a_pImplExpr); \
8685 if (IEM_IS_MODRM_REG_MODE(bRm)) \
8686 { \
8687 /* register */ \
8688 uint8_t cShift; IEM_OPCODE_GET_NEXT_U8(&cShift); \
8689 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_186, 0); \
8690 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
8691 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
8692 IEM_MC_ARG_CONST(uint8_t, cShiftArg, cShift, 1); \
8693 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
8694 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
8695 IEM_MC_REF_EFLAGS(pEFlags); \
8696 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU8, pu8Dst, cShiftArg, pEFlags); \
8697 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8698 IEM_MC_END(); \
8699 } \
8700 else \
8701 { \
8702 /* memory */ \
8703 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_186, 0); \
8704 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
8705 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
8706 \
8707 uint8_t cShift; IEM_OPCODE_GET_NEXT_U8(&cShift); \
8708 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
8709 \
8710 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
8711 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
8712 IEM_MC_MEM_MAP_U8_RW(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
8713 \
8714 IEM_MC_ARG_CONST(uint8_t, cShiftArg, cShift, 1); \
8715 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
8716 IEM_MC_FETCH_EFLAGS(EFlags); \
8717 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU8, pu8Dst, cShiftArg, pEFlags); \
8718 \
8719 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
8720 IEM_MC_COMMIT_EFLAGS(EFlags); \
8721 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8722 IEM_MC_END(); \
8723 } (void)0
8724
8725 switch (IEM_GET_MODRM_REG_8(bRm))
8726 {
8727 /**
8728 * @opdone
8729 * @opmaps grp2_c0
8730 * @opcode /0
8731 * @opflclass rotate_count
8732 */
8733 case 0:
8734 {
8735 IEMOP_MNEMONIC2(MI, ROL, rol, Eb, Ib, DISOPTYPE_HARMLESS, 0);
8736 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF);
8737 GRP2_BODY_Eb_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rol_eflags));
8738 break;
8739 }
8740 /**
8741 * @opdone
8742 * @opmaps grp2_c0
8743 * @opcode /1
8744 * @opflclass rotate_count
8745 */
8746 case 1:
8747 {
8748 IEMOP_MNEMONIC2(MI, ROR, ror, Eb, Ib, DISOPTYPE_HARMLESS, 0);
8749 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF);
8750 GRP2_BODY_Eb_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_ror_eflags));
8751 break;
8752 }
8753 /**
8754 * @opdone
8755 * @opmaps grp2_c0
8756 * @opcode /2
8757 * @opflclass rotate_carry_count
8758 */
8759 case 2:
8760 {
8761 IEMOP_MNEMONIC2(MI, RCL, rcl, Eb, Ib, DISOPTYPE_HARMLESS, 0);
8762 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF);
8763 GRP2_BODY_Eb_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcl_eflags));
8764 break;
8765 }
8766 /**
8767 * @opdone
8768 * @opmaps grp2_c0
8769 * @opcode /3
8770 * @opflclass rotate_carry_count
8771 */
8772 case 3:
8773 {
8774 IEMOP_MNEMONIC2(MI, RCR, rcr, Eb, Ib, DISOPTYPE_HARMLESS, 0);
8775 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF);
8776 GRP2_BODY_Eb_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcr_eflags));
8777 break;
8778 }
8779 /**
8780 * @opdone
8781 * @opmaps grp2_c0
8782 * @opcode /4
8783 * @opflclass shift_count
8784 */
8785 case 4:
8786 {
8787 IEMOP_MNEMONIC2(MI, SHL, shl, Eb, Ib, DISOPTYPE_HARMLESS, 0);
8788 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF | X86_EFL_AF);
8789 GRP2_BODY_Eb_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shl_eflags));
8790 break;
8791 }
8792 /**
8793 * @opdone
8794 * @opmaps grp2_c0
8795 * @opcode /5
8796 * @opflclass shift_count
8797 */
8798 case 5:
8799 {
8800 IEMOP_MNEMONIC2(MI, SHR, shr, Eb, Ib, DISOPTYPE_HARMLESS, 0);
8801 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF | X86_EFL_AF);
8802 GRP2_BODY_Eb_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shr_eflags));
8803 break;
8804 }
8805 /**
8806 * @opdone
8807 * @opmaps grp2_c0
8808 * @opcode /7
8809 * @opflclass shift_count
8810 */
8811 case 7:
8812 {
8813 IEMOP_MNEMONIC2(MI, SAR, sar, Eb, Ib, DISOPTYPE_HARMLESS, 0);
8814 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF | X86_EFL_AF);
8815 GRP2_BODY_Eb_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_sar_eflags));
8816 break;
8817 }
8818
8819 /** @opdone */
8820 case 6: IEMOP_RAISE_INVALID_OPCODE_RET();
8821 IEM_NOT_REACHED_DEFAULT_CASE_RET(); /* gcc maybe stupid */
8822 }
8823#undef GRP2_BODY_Eb_Ib
8824}
8825
8826
8827/* Need to use a body macro here since the EFLAGS behaviour differs between
8828 the shifts, rotates and rotate w/ carry. Sigh. */
8829#define GRP2_BODY_Ev_Ib(a_pImplExpr) \
8830 PCIEMOPSHIFTSIZES const pImpl = (a_pImplExpr); \
8831 if (IEM_IS_MODRM_REG_MODE(bRm)) \
8832 { \
8833 /* register */ \
8834 uint8_t cShift; IEM_OPCODE_GET_NEXT_U8(&cShift); \
8835 switch (pVCpu->iem.s.enmEffOpSize) \
8836 { \
8837 case IEMMODE_16BIT: \
8838 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_186, 0); \
8839 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
8840 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
8841 IEM_MC_ARG_CONST(uint8_t, cShiftArg, cShift, 1); \
8842 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
8843 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
8844 IEM_MC_REF_EFLAGS(pEFlags); \
8845 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU16, pu16Dst, cShiftArg, pEFlags); \
8846 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8847 IEM_MC_END(); \
8848 break; \
8849 \
8850 case IEMMODE_32BIT: \
8851 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_386, 0); \
8852 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
8853 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
8854 IEM_MC_ARG_CONST(uint8_t, cShiftArg, cShift, 1); \
8855 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
8856 IEM_MC_REF_GREG_U32(pu32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
8857 IEM_MC_REF_EFLAGS(pEFlags); \
8858 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU32, pu32Dst, cShiftArg, pEFlags); \
8859 IEM_MC_CLEAR_HIGH_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm)); \
8860 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8861 IEM_MC_END(); \
8862 break; \
8863 \
8864 case IEMMODE_64BIT: \
8865 IEM_MC_BEGIN(3, 0, IEM_MC_F_64BIT, 0); \
8866 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
8867 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
8868 IEM_MC_ARG_CONST(uint8_t, cShiftArg, cShift, 1); \
8869 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
8870 IEM_MC_REF_GREG_U64(pu64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
8871 IEM_MC_REF_EFLAGS(pEFlags); \
8872 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU64, pu64Dst, cShiftArg, pEFlags); \
8873 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8874 IEM_MC_END(); \
8875 break; \
8876 \
8877 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
8878 } \
8879 } \
8880 else \
8881 { \
8882 /* memory */ \
8883 switch (pVCpu->iem.s.enmEffOpSize) \
8884 { \
8885 case IEMMODE_16BIT: \
8886 IEM_MC_BEGIN(3, 3, 0, 0); \
8887 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
8888 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
8889 \
8890 uint8_t cShift; IEM_OPCODE_GET_NEXT_U8(&cShift); \
8891 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
8892 \
8893 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
8894 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
8895 IEM_MC_MEM_MAP_U16_RW(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
8896 \
8897 IEM_MC_ARG_CONST(uint8_t, cShiftArg, cShift, 1); \
8898 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
8899 IEM_MC_FETCH_EFLAGS(EFlags); \
8900 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU16, pu16Dst, cShiftArg, pEFlags); \
8901 \
8902 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
8903 IEM_MC_COMMIT_EFLAGS(EFlags); \
8904 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8905 IEM_MC_END(); \
8906 break; \
8907 \
8908 case IEMMODE_32BIT: \
8909 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
8910 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
8911 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
8912 \
8913 uint8_t cShift; IEM_OPCODE_GET_NEXT_U8(&cShift); \
8914 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
8915 \
8916 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
8917 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
8918 IEM_MC_MEM_MAP_U32_RW(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
8919 \
8920 IEM_MC_ARG_CONST(uint8_t, cShiftArg, cShift, 1); \
8921 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
8922 IEM_MC_FETCH_EFLAGS(EFlags); \
8923 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU32, pu32Dst, cShiftArg, pEFlags); \
8924 \
8925 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
8926 IEM_MC_COMMIT_EFLAGS(EFlags); \
8927 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8928 IEM_MC_END(); \
8929 break; \
8930 \
8931 case IEMMODE_64BIT: \
8932 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
8933 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
8934 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1); \
8935 \
8936 uint8_t cShift; IEM_OPCODE_GET_NEXT_U8(&cShift); \
8937 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
8938 \
8939 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
8940 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
8941 IEM_MC_MEM_MAP_U64_RW(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
8942 \
8943 IEM_MC_ARG_CONST(uint8_t, cShiftArg, cShift, 1); \
8944 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 2); \
8945 IEM_MC_FETCH_EFLAGS(EFlags); \
8946 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU64, pu64Dst, cShiftArg, pEFlags); \
8947 \
8948 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
8949 IEM_MC_COMMIT_EFLAGS(EFlags); \
8950 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
8951 IEM_MC_END(); \
8952 break; \
8953 \
8954 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
8955 } \
8956 } (void)0
8957
8958/**
8959 * @opmaps grp2_c1
8960 * @opcode /0
8961 * @opflclass rotate_count
8962 */
8963FNIEMOP_DEF_1(iemOp_grp2_rol_Ev_Ib, uint8_t, bRm)
8964{
8965 IEMOP_MNEMONIC2(MI, ROL, rol, Ev, Ib, DISOPTYPE_HARMLESS, 0);
8966 GRP2_BODY_Ev_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rol_eflags));
8967}
8968
8969
8970/**
8971 * @opmaps grp2_c1
8972 * @opcode /1
8973 * @opflclass rotate_count
8974 */
8975FNIEMOP_DEF_1(iemOp_grp2_ror_Ev_Ib, uint8_t, bRm)
8976{
8977 IEMOP_MNEMONIC2(MI, ROR, ror, Ev, Ib, DISOPTYPE_HARMLESS, 0);
8978 GRP2_BODY_Ev_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_ror_eflags));
8979}
8980
8981
8982/**
8983 * @opmaps grp2_c1
8984 * @opcode /2
8985 * @opflclass rotate_carry_count
8986 */
8987FNIEMOP_DEF_1(iemOp_grp2_rcl_Ev_Ib, uint8_t, bRm)
8988{
8989 IEMOP_MNEMONIC2(MI, RCL, rcl, Ev, Ib, DISOPTYPE_HARMLESS, 0);
8990 GRP2_BODY_Ev_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcl_eflags));
8991}
8992
8993
8994/**
8995 * @opmaps grp2_c1
8996 * @opcode /3
8997 * @opflclass rotate_carry_count
8998 */
8999FNIEMOP_DEF_1(iemOp_grp2_rcr_Ev_Ib, uint8_t, bRm)
9000{
9001 IEMOP_MNEMONIC2(MI, RCR, rcr, Ev, Ib, DISOPTYPE_HARMLESS, 0);
9002 GRP2_BODY_Ev_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcr_eflags));
9003}
9004
9005
9006/**
9007 * @opmaps grp2_c1
9008 * @opcode /4
9009 * @opflclass shift_count
9010 */
9011FNIEMOP_DEF_1(iemOp_grp2_shl_Ev_Ib, uint8_t, bRm)
9012{
9013 IEMOP_MNEMONIC2(MI, SHL, shl, Ev, Ib, DISOPTYPE_HARMLESS, 0);
9014 GRP2_BODY_Ev_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shl_eflags));
9015}
9016
9017
9018/**
9019 * @opmaps grp2_c1
9020 * @opcode /5
9021 * @opflclass shift_count
9022 */
9023FNIEMOP_DEF_1(iemOp_grp2_shr_Ev_Ib, uint8_t, bRm)
9024{
9025 IEMOP_MNEMONIC2(MI, SHR, shr, Ev, Ib, DISOPTYPE_HARMLESS, 0);
9026 GRP2_BODY_Ev_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shr_eflags));
9027}
9028
9029
9030/**
9031 * @opmaps grp2_c1
9032 * @opcode /7
9033 * @opflclass shift_count
9034 */
9035FNIEMOP_DEF_1(iemOp_grp2_sar_Ev_Ib, uint8_t, bRm)
9036{
9037 IEMOP_MNEMONIC2(MI, SAR, sar, Ev, Ib, DISOPTYPE_HARMLESS, 0);
9038 GRP2_BODY_Ev_Ib(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_sar_eflags));
9039}
9040
9041#undef GRP2_BODY_Ev_Ib
9042
9043/**
9044 * @opcode 0xc1
9045 */
9046FNIEMOP_DEF(iemOp_Grp2_Ev_Ib)
9047{
9048 IEMOP_HLP_MIN_186();
9049 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
9050
9051 switch (IEM_GET_MODRM_REG_8(bRm))
9052 {
9053 case 0: return FNIEMOP_CALL_1(iemOp_grp2_rol_Ev_Ib, bRm);
9054 case 1: return FNIEMOP_CALL_1(iemOp_grp2_ror_Ev_Ib, bRm);
9055 case 2: return FNIEMOP_CALL_1(iemOp_grp2_rcl_Ev_Ib, bRm);
9056 case 3: return FNIEMOP_CALL_1(iemOp_grp2_rcr_Ev_Ib, bRm);
9057 case 4: return FNIEMOP_CALL_1(iemOp_grp2_shl_Ev_Ib, bRm);
9058 case 5: return FNIEMOP_CALL_1(iemOp_grp2_shr_Ev_Ib, bRm);
9059 case 7: return FNIEMOP_CALL_1(iemOp_grp2_sar_Ev_Ib, bRm);
9060 case 6: IEMOP_RAISE_INVALID_OPCODE_RET();
9061 IEM_NOT_REACHED_DEFAULT_CASE_RET(); /* gcc maybe stupid */
9062 }
9063}
9064
9065
9066/**
9067 * @opcode 0xc2
9068 */
9069FNIEMOP_DEF(iemOp_retn_Iw)
9070{
9071 IEMOP_MNEMONIC(retn_Iw, "retn Iw");
9072 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm);
9073 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
9074 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9075 switch (pVCpu->iem.s.enmEffOpSize)
9076 {
9077 case IEMMODE_16BIT:
9078 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK,
9079 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_retn_iw_16, u16Imm);
9080 case IEMMODE_32BIT:
9081 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK,
9082 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_retn_iw_32, u16Imm);
9083 case IEMMODE_64BIT:
9084 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK,
9085 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_retn_iw_64, u16Imm);
9086 IEM_NOT_REACHED_DEFAULT_CASE_RET();
9087 }
9088}
9089
9090
9091/**
9092 * @opcode 0xc3
9093 */
9094FNIEMOP_DEF(iemOp_retn)
9095{
9096 IEMOP_MNEMONIC(retn, "retn");
9097 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
9098 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9099 switch (pVCpu->iem.s.enmEffOpSize)
9100 {
9101 case IEMMODE_16BIT:
9102 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK,
9103 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_retn_16);
9104 case IEMMODE_32BIT:
9105 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK,
9106 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_retn_32);
9107 case IEMMODE_64BIT:
9108 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK,
9109 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP), iemCImpl_retn_64);
9110 IEM_NOT_REACHED_DEFAULT_CASE_RET();
9111 }
9112}
9113
9114
9115/**
9116 * @opcode 0xc4
9117 */
9118FNIEMOP_DEF(iemOp_les_Gv_Mp__vex3)
9119{
9120 /* The LDS instruction is invalid 64-bit mode. In legacy and
9121 compatability mode it is invalid with MOD=3.
9122 The use as a VEX prefix is made possible by assigning the inverted
9123 REX.R and REX.X to the two MOD bits, since the REX bits are ignored
9124 outside of 64-bit mode. VEX is not available in real or v86 mode. */
9125 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
9126 if ( IEM_IS_64BIT_CODE(pVCpu)
9127 || IEM_IS_MODRM_REG_MODE(bRm) )
9128 {
9129 IEMOP_MNEMONIC(vex3_prefix, "vex3");
9130 if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVex)
9131 {
9132 /* Note! The real mode, v8086 mode and invalid prefix checks are done once
9133 the instruction is fully decoded. Even when XCR0=3 and CR4.OSXSAVE=0. */
9134 uint8_t bVex2; IEM_OPCODE_GET_NEXT_U8(&bVex2);
9135 uint8_t bOpcode; IEM_OPCODE_GET_NEXT_U8(&bOpcode);
9136 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_VEX;
9137#if 1
9138 AssertCompile(IEM_OP_PRF_SIZE_REX_W == RT_BIT_32(9));
9139 pVCpu->iem.s.fPrefixes |= (uint32_t)(bVex2 & 0x80) << (9 - 7);
9140#else
9141 if (bVex2 & 0x80 /* VEX.W */)
9142 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SIZE_REX_W;
9143#endif
9144 if (IEM_IS_64BIT_CODE(pVCpu))
9145 {
9146#if 1
9147 AssertCompile(IEM_OP_PRF_REX_B == RT_BIT_32(25) && IEM_OP_PRF_REX_X == RT_BIT_32(26) && IEM_OP_PRF_REX_R == RT_BIT_32(27));
9148 pVCpu->iem.s.fPrefixes |= (uint32_t)(~bRm & 0xe0) << (25 - 5);
9149#else
9150 if (~bRm & 0x20 /* VEX.~B */)
9151 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SIZE_REX_B;
9152 if (~bRm & 0x40 /* VEX.~X */)
9153 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SIZE_REX_X;
9154 if (~bRm & 0x80 /* VEX.~R */)
9155 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_SIZE_REX_R;
9156#endif
9157 pVCpu->iem.s.uRexReg = (~bRm >> (7 - 3)) & 0x8;
9158 pVCpu->iem.s.uRexIndex = (~bRm >> (6 - 3)) & 0x8;
9159 pVCpu->iem.s.uRexB = (~bRm >> (5 - 3)) & 0x8;
9160 pVCpu->iem.s.uVex3rdReg = (~bVex2 >> 3) & 0xf;
9161 }
9162 else
9163 {
9164 pVCpu->iem.s.uRexReg = 0;
9165 pVCpu->iem.s.uRexIndex = 0;
9166 pVCpu->iem.s.uRexB = 0;
9167 /** @todo testcase: Will attemps to access registers 8 thru 15 from 16&32 bit
9168 * code raise \#UD or just be ignored? We're ignoring for now... */
9169 pVCpu->iem.s.uVex3rdReg = (~bVex2 >> 3) & 0x7;
9170 }
9171 pVCpu->iem.s.uVexLength = (bVex2 >> 2) & 1;
9172 pVCpu->iem.s.idxPrefix = bVex2 & 0x3;
9173
9174 switch (bRm & 0x1f)
9175 {
9176 case 1: /* 0x0f lead opcode byte. */
9177#ifdef IEM_WITH_VEX
9178 return FNIEMOP_CALL(g_apfnVexMap1[(uintptr_t)bOpcode * 4 + pVCpu->iem.s.idxPrefix]);
9179#else
9180 IEMOP_BITCH_ABOUT_STUB();
9181 return VERR_IEM_INSTR_NOT_IMPLEMENTED;
9182#endif
9183
9184 case 2: /* 0x0f 0x38 lead opcode bytes. */
9185#ifdef IEM_WITH_VEX
9186 return FNIEMOP_CALL(g_apfnVexMap2[(uintptr_t)bOpcode * 4 + pVCpu->iem.s.idxPrefix]);
9187#else
9188 IEMOP_BITCH_ABOUT_STUB();
9189 return VERR_IEM_INSTR_NOT_IMPLEMENTED;
9190#endif
9191
9192 case 3: /* 0x0f 0x3a lead opcode bytes. */
9193#ifdef IEM_WITH_VEX
9194 return FNIEMOP_CALL(g_apfnVexMap3[(uintptr_t)bOpcode * 4 + pVCpu->iem.s.idxPrefix]);
9195#else
9196 IEMOP_BITCH_ABOUT_STUB();
9197 return VERR_IEM_INSTR_NOT_IMPLEMENTED;
9198#endif
9199
9200 default:
9201 Log(("VEX3: Invalid vvvv value: %#x!\n", bRm & 0x1f));
9202 IEMOP_RAISE_INVALID_OPCODE_RET();
9203 }
9204 }
9205 Log(("VEX3: VEX support disabled!\n"));
9206 IEMOP_RAISE_INVALID_OPCODE_RET();
9207 }
9208
9209 IEMOP_MNEMONIC(les_Gv_Mp, "les Gv,Mp");
9210 return FNIEMOP_CALL_2(iemOpCommonLoadSRegAndGreg, X86_SREG_ES, bRm);
9211}
9212
9213
9214/**
9215 * @opcode 0xc5
9216 */
9217FNIEMOP_DEF(iemOp_lds_Gv_Mp__vex2)
9218{
9219 /* The LES instruction is invalid 64-bit mode. In legacy and
9220 compatability mode it is invalid with MOD=3.
9221 The use as a VEX prefix is made possible by assigning the inverted
9222 REX.R to the top MOD bit, and the top bit in the inverted register
9223 specifier to the bottom MOD bit, thereby effectively limiting 32-bit
9224 to accessing registers 0..7 in this VEX form. */
9225 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
9226 if ( IEM_IS_64BIT_CODE(pVCpu)
9227 || IEM_IS_MODRM_REG_MODE(bRm))
9228 {
9229 IEMOP_MNEMONIC(vex2_prefix, "vex2");
9230 if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVex)
9231 {
9232 /* Note! The real mode, v8086 mode and invalid prefix checks are done once
9233 the instruction is fully decoded. Even when XCR0=3 and CR4.OSXSAVE=0. */
9234 uint8_t bOpcode; IEM_OPCODE_GET_NEXT_U8(&bOpcode);
9235 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_VEX;
9236 AssertCompile(IEM_OP_PRF_REX_R == RT_BIT_32(27));
9237 pVCpu->iem.s.fPrefixes |= (uint32_t)(~bRm & 0x80) << (27 - 7);
9238 pVCpu->iem.s.uRexReg = (~bRm >> (7 - 3)) & 0x8;
9239 pVCpu->iem.s.uVex3rdReg = (~bRm >> 3) & 0xf;
9240 pVCpu->iem.s.uVexLength = (bRm >> 2) & 1;
9241 pVCpu->iem.s.idxPrefix = bRm & 0x3;
9242
9243#ifdef IEM_WITH_VEX
9244 return FNIEMOP_CALL(g_apfnVexMap1[(uintptr_t)bOpcode * 4 + pVCpu->iem.s.idxPrefix]);
9245#else
9246 IEMOP_BITCH_ABOUT_STUB();
9247 return VERR_IEM_INSTR_NOT_IMPLEMENTED;
9248#endif
9249 }
9250
9251 /** @todo does intel completely decode the sequence with SIB/disp before \#UD? */
9252 Log(("VEX2: VEX support disabled!\n"));
9253 IEMOP_RAISE_INVALID_OPCODE_RET();
9254 }
9255
9256 IEMOP_MNEMONIC(lds_Gv_Mp, "lds Gv,Mp");
9257 return FNIEMOP_CALL_2(iemOpCommonLoadSRegAndGreg, X86_SREG_DS, bRm);
9258}
9259
9260
9261/**
9262 * @opcode 0xc6
9263 */
9264FNIEMOP_DEF(iemOp_Grp11_Eb_Ib)
9265{
9266 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
9267 if ((bRm & X86_MODRM_REG_MASK) != (0 << X86_MODRM_REG_SHIFT)) /* only mov Eb,Ib in this group. */
9268 IEMOP_RAISE_INVALID_OPCODE_RET();
9269 IEMOP_MNEMONIC(mov_Eb_Ib, "mov Eb,Ib");
9270
9271 if (IEM_IS_MODRM_REG_MODE(bRm))
9272 {
9273 /* register access */
9274 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
9275 IEM_MC_BEGIN(0, 0, 0, 0);
9276 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9277 IEM_MC_STORE_GREG_U8_CONST(IEM_GET_MODRM_RM(pVCpu, bRm), u8Imm);
9278 IEM_MC_ADVANCE_RIP_AND_FINISH();
9279 IEM_MC_END();
9280 }
9281 else
9282 {
9283 /* memory access. */
9284 IEM_MC_BEGIN(0, 1, 0, 0);
9285 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
9286 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 1);
9287 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
9288 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9289 IEM_MC_STORE_MEM_U8_CONST(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u8Imm);
9290 IEM_MC_ADVANCE_RIP_AND_FINISH();
9291 IEM_MC_END();
9292 }
9293}
9294
9295
9296/**
9297 * @opcode 0xc7
9298 */
9299FNIEMOP_DEF(iemOp_Grp11_Ev_Iz)
9300{
9301 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
9302 if ((bRm & X86_MODRM_REG_MASK) != (0 << X86_MODRM_REG_SHIFT)) /* only mov Eb,Iz in this group. */
9303 IEMOP_RAISE_INVALID_OPCODE_RET();
9304 IEMOP_MNEMONIC(mov_Ev_Iz, "mov Ev,Iz");
9305
9306 if (IEM_IS_MODRM_REG_MODE(bRm))
9307 {
9308 /* register access */
9309 switch (pVCpu->iem.s.enmEffOpSize)
9310 {
9311 case IEMMODE_16BIT:
9312 IEM_MC_BEGIN(0, 0, 0, 0);
9313 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm);
9314 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9315 IEM_MC_STORE_GREG_U16_CONST(IEM_GET_MODRM_RM(pVCpu, bRm), u16Imm);
9316 IEM_MC_ADVANCE_RIP_AND_FINISH();
9317 IEM_MC_END();
9318 break;
9319
9320 case IEMMODE_32BIT:
9321 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386, 0);
9322 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm);
9323 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9324 IEM_MC_STORE_GREG_U32_CONST(IEM_GET_MODRM_RM(pVCpu, bRm), u32Imm);
9325 IEM_MC_ADVANCE_RIP_AND_FINISH();
9326 IEM_MC_END();
9327 break;
9328
9329 case IEMMODE_64BIT:
9330 IEM_MC_BEGIN(0, 0, IEM_MC_F_64BIT, 0);
9331 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm);
9332 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9333 IEM_MC_STORE_GREG_U64_CONST(IEM_GET_MODRM_RM(pVCpu, bRm), u64Imm);
9334 IEM_MC_ADVANCE_RIP_AND_FINISH();
9335 IEM_MC_END();
9336 break;
9337
9338 IEM_NOT_REACHED_DEFAULT_CASE_RET();
9339 }
9340 }
9341 else
9342 {
9343 /* memory access. */
9344 switch (pVCpu->iem.s.enmEffOpSize)
9345 {
9346 case IEMMODE_16BIT:
9347 IEM_MC_BEGIN(0, 1, 0, 0);
9348 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
9349 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 2);
9350 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm);
9351 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9352 IEM_MC_STORE_MEM_U16_CONST(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u16Imm);
9353 IEM_MC_ADVANCE_RIP_AND_FINISH();
9354 IEM_MC_END();
9355 break;
9356
9357 case IEMMODE_32BIT:
9358 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_386, 0);
9359 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
9360 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4);
9361 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm);
9362 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9363 IEM_MC_STORE_MEM_U32_CONST(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u32Imm);
9364 IEM_MC_ADVANCE_RIP_AND_FINISH();
9365 IEM_MC_END();
9366 break;
9367
9368 case IEMMODE_64BIT:
9369 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
9370 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
9371 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4);
9372 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm);
9373 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9374 IEM_MC_STORE_MEM_U64_CONST(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u64Imm);
9375 IEM_MC_ADVANCE_RIP_AND_FINISH();
9376 IEM_MC_END();
9377 break;
9378
9379 IEM_NOT_REACHED_DEFAULT_CASE_RET();
9380 }
9381 }
9382}
9383
9384
9385
9386
9387/**
9388 * @opcode 0xc8
9389 */
9390FNIEMOP_DEF(iemOp_enter_Iw_Ib)
9391{
9392 IEMOP_MNEMONIC(enter_Iw_Ib, "enter Iw,Ib");
9393 IEMOP_HLP_MIN_186();
9394 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
9395 uint16_t cbFrame; IEM_OPCODE_GET_NEXT_U16(&cbFrame);
9396 uint8_t u8NestingLevel; IEM_OPCODE_GET_NEXT_U8(&u8NestingLevel);
9397 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9398 IEM_MC_DEFER_TO_CIMPL_3_RET(0,
9399 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
9400 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xBP),
9401 iemCImpl_enter, pVCpu->iem.s.enmEffOpSize, cbFrame, u8NestingLevel);
9402}
9403
9404
9405/**
9406 * @opcode 0xc9
9407 */
9408FNIEMOP_DEF(iemOp_leave)
9409{
9410 IEMOP_MNEMONIC(leave, "leave");
9411 IEMOP_HLP_MIN_186();
9412 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
9413 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9414 IEM_MC_DEFER_TO_CIMPL_1_RET(0,
9415 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
9416 | RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xBP),
9417 iemCImpl_leave, pVCpu->iem.s.enmEffOpSize);
9418}
9419
9420
9421/**
9422 * @opcode 0xca
9423 */
9424FNIEMOP_DEF(iemOp_retf_Iw)
9425{
9426 IEMOP_MNEMONIC(retf_Iw, "retf Iw");
9427 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm);
9428 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9429 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_STACK
9430 | IEM_CIMPL_F_MODE,
9431 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
9432 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_DS)
9433 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_ES)
9434 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_FS)
9435 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_GS)
9436 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_DS)
9437 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_ES)
9438 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_FS)
9439 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_GS)
9440 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_DS)
9441 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_ES)
9442 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_FS)
9443 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_GS)
9444 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_DS)
9445 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_ES)
9446 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_FS)
9447 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_GS),
9448 iemCImpl_retf, pVCpu->iem.s.enmEffOpSize, u16Imm);
9449}
9450
9451
9452/**
9453 * @opcode 0xcb
9454 */
9455FNIEMOP_DEF(iemOp_retf)
9456{
9457 IEMOP_MNEMONIC(retf, "retf");
9458 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9459 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_STACK
9460 | IEM_CIMPL_F_MODE,
9461 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
9462 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_DS)
9463 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_ES)
9464 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_FS)
9465 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_GS)
9466 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_DS)
9467 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_ES)
9468 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_FS)
9469 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_GS)
9470 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_DS)
9471 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_ES)
9472 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_FS)
9473 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_GS)
9474 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_DS)
9475 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_ES)
9476 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_FS)
9477 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_GS),
9478 iemCImpl_retf, pVCpu->iem.s.enmEffOpSize, 0);
9479}
9480
9481
9482/**
9483 * @opcode 0xcc
9484 */
9485FNIEMOP_DEF(iemOp_int3)
9486{
9487 IEMOP_MNEMONIC(int3, "int3");
9488 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9489 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_STACK_FAR
9490 | IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_END_TB, 0,
9491 iemCImpl_int, X86_XCPT_BP, IEMINT_INT3);
9492}
9493
9494
9495/**
9496 * @opcode 0xcd
9497 */
9498FNIEMOP_DEF(iemOp_int_Ib)
9499{
9500 IEMOP_MNEMONIC(int_Ib, "int Ib");
9501 uint8_t u8Int; IEM_OPCODE_GET_NEXT_U8(&u8Int);
9502 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9503 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_STACK_FAR
9504 | IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_RFLAGS, UINT64_MAX,
9505 iemCImpl_int, u8Int, IEMINT_INTN);
9506 /** @todo make task-switches, ring-switches, ++ return non-zero status */
9507}
9508
9509
9510/**
9511 * @opcode 0xce
9512 */
9513FNIEMOP_DEF(iemOp_into)
9514{
9515 IEMOP_MNEMONIC(into, "into");
9516 IEMOP_HLP_NO_64BIT();
9517 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_STACK_FAR
9518 | IEM_CIMPL_F_BRANCH_CONDITIONAL | IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_RFLAGS,
9519 UINT64_MAX,
9520 iemCImpl_int, X86_XCPT_OF, IEMINT_INTO);
9521 /** @todo make task-switches, ring-switches, ++ return non-zero status */
9522}
9523
9524
9525/**
9526 * @opcode 0xcf
9527 */
9528FNIEMOP_DEF(iemOp_iret)
9529{
9530 IEMOP_MNEMONIC(iret, "iret");
9531 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
9532 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_STACK_FAR
9533 | IEM_CIMPL_F_MODE | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_CHECK_IRQ_BEFORE | IEM_CIMPL_F_VMEXIT,
9534 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xSP)
9535 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_DS)
9536 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_DS)
9537 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_DS)
9538 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_DS)
9539 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_ES)
9540 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_ES)
9541 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_ES)
9542 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_ES)
9543 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_FS)
9544 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_FS)
9545 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_FS)
9546 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_FS)
9547 | RT_BIT_64(kIemNativeGstReg_SegSelFirst + X86_SREG_GS)
9548 | RT_BIT_64(kIemNativeGstReg_SegBaseFirst + X86_SREG_GS)
9549 | RT_BIT_64(kIemNativeGstReg_SegLimitFirst + X86_SREG_GS)
9550 | RT_BIT_64(kIemNativeGstReg_SegAttribFirst + X86_SREG_GS),
9551 iemCImpl_iret, pVCpu->iem.s.enmEffOpSize);
9552 /* Segment registers are sanitized when returning to an outer ring, or fully
9553 reloaded when returning to v86 mode. Thus the large flush list above. */
9554}
9555
9556
9557/**
9558 * @opcode 0xd0
9559 */
9560FNIEMOP_DEF(iemOp_Grp2_Eb_1)
9561{
9562 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
9563
9564 /* Need to use a body macro here since the EFLAGS behaviour differs between
9565 the shifts, rotates and rotate w/ carry. Sigh. */
9566#define GRP2_BODY_Eb_1(a_pImplExpr) \
9567 PCIEMOPSHIFTSIZES const pImpl = (a_pImplExpr); \
9568 if (IEM_IS_MODRM_REG_MODE(bRm)) \
9569 { \
9570 /* register */ \
9571 IEM_MC_BEGIN(3, 0, 0, 0); \
9572 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9573 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
9574 IEM_MC_ARG_CONST(uint8_t, cShiftArg,/*=*/1, 1); \
9575 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
9576 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
9577 IEM_MC_REF_EFLAGS(pEFlags); \
9578 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU8, pu8Dst, cShiftArg, pEFlags); \
9579 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9580 IEM_MC_END(); \
9581 } \
9582 else \
9583 { \
9584 /* memory */ \
9585 IEM_MC_BEGIN(3, 3, 0, 0); \
9586 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
9587 IEM_MC_ARG_CONST(uint8_t, cShiftArg,/*=*/1, 1); \
9588 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
9589 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
9590 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
9591 \
9592 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
9593 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9594 IEM_MC_MEM_MAP_U8_RW(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
9595 IEM_MC_FETCH_EFLAGS(EFlags); \
9596 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU8, pu8Dst, cShiftArg, pEFlags); \
9597 \
9598 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
9599 IEM_MC_COMMIT_EFLAGS(EFlags); \
9600 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9601 IEM_MC_END(); \
9602 } (void)0
9603
9604 switch (IEM_GET_MODRM_REG_8(bRm))
9605 {
9606 /**
9607 * @opdone
9608 * @opmaps grp2_d0
9609 * @opcode /0
9610 * @opflclass rotate_1
9611 */
9612 case 0:
9613 {
9614 IEMOP_MNEMONIC2(M1, ROL, rol, Eb, 1, DISOPTYPE_HARMLESS, 0);
9615 GRP2_BODY_Eb_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rol_eflags));
9616 break;
9617 }
9618 /**
9619 * @opdone
9620 * @opmaps grp2_d0
9621 * @opcode /1
9622 * @opflclass rotate_1
9623 */
9624 case 1:
9625 {
9626 IEMOP_MNEMONIC2(M1, ROR, ror, Eb, 1, DISOPTYPE_HARMLESS, 0);
9627 GRP2_BODY_Eb_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_ror_eflags));
9628 break;
9629 }
9630 /**
9631 * @opdone
9632 * @opmaps grp2_d0
9633 * @opcode /2
9634 * @opflclass rotate_carry_1
9635 */
9636 case 2:
9637 {
9638 IEMOP_MNEMONIC2(M1, RCL, rcl, Eb, 1, DISOPTYPE_HARMLESS, 0);
9639 GRP2_BODY_Eb_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcl_eflags));
9640 break;
9641 }
9642 /**
9643 * @opdone
9644 * @opmaps grp2_d0
9645 * @opcode /3
9646 * @opflclass rotate_carry_1
9647 */
9648 case 3:
9649 {
9650 IEMOP_MNEMONIC2(M1, RCR, rcr, Eb, 1, DISOPTYPE_HARMLESS, 0);
9651 GRP2_BODY_Eb_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcr_eflags));
9652 break;
9653 }
9654 /**
9655 * @opdone
9656 * @opmaps grp2_d0
9657 * @opcode /4
9658 * @opflclass shift_1
9659 */
9660 case 4:
9661 {
9662 IEMOP_MNEMONIC2(M1, SHL, shl, Eb, 1, DISOPTYPE_HARMLESS, 0);
9663 GRP2_BODY_Eb_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shl_eflags));
9664 break;
9665 }
9666 /**
9667 * @opdone
9668 * @opmaps grp2_d0
9669 * @opcode /5
9670 * @opflclass shift_1
9671 */
9672 case 5:
9673 {
9674 IEMOP_MNEMONIC2(M1, SHR, shr, Eb, 1, DISOPTYPE_HARMLESS, 0);
9675 GRP2_BODY_Eb_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shr_eflags));
9676 break;
9677 }
9678 /**
9679 * @opdone
9680 * @opmaps grp2_d0
9681 * @opcode /7
9682 * @opflclass shift_1
9683 */
9684 case 7:
9685 {
9686 IEMOP_MNEMONIC2(M1, SAR, sar, Eb, 1, DISOPTYPE_HARMLESS, 0);
9687 GRP2_BODY_Eb_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_sar_eflags));
9688 break;
9689 }
9690 /** @opdone */
9691 case 6: IEMOP_RAISE_INVALID_OPCODE_RET();
9692 IEM_NOT_REACHED_DEFAULT_CASE_RET(); /* gcc maybe, well... */
9693 }
9694#undef GRP2_BODY_Eb_1
9695}
9696
9697
9698/* Need to use a body macro here since the EFLAGS behaviour differs between
9699 the shifts, rotates and rotate w/ carry. Sigh. */
9700#define GRP2_BODY_Ev_1(a_pImplExpr) \
9701 PCIEMOPSHIFTSIZES const pImpl = (a_pImplExpr); \
9702 if (IEM_IS_MODRM_REG_MODE(bRm)) \
9703 { \
9704 /* register */ \
9705 switch (pVCpu->iem.s.enmEffOpSize) \
9706 { \
9707 case IEMMODE_16BIT: \
9708 IEM_MC_BEGIN(3, 0, 0, 0); \
9709 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9710 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
9711 IEM_MC_ARG_CONST(uint8_t, cShiftArg,/*=1*/1, 1); \
9712 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
9713 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
9714 IEM_MC_REF_EFLAGS(pEFlags); \
9715 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU16, pu16Dst, cShiftArg, pEFlags); \
9716 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9717 IEM_MC_END(); \
9718 break; \
9719 \
9720 case IEMMODE_32BIT: \
9721 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_386, 0); \
9722 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9723 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
9724 IEM_MC_ARG_CONST(uint8_t, cShiftArg,/*=1*/1, 1); \
9725 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
9726 IEM_MC_REF_GREG_U32(pu32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
9727 IEM_MC_REF_EFLAGS(pEFlags); \
9728 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU32, pu32Dst, cShiftArg, pEFlags); \
9729 IEM_MC_CLEAR_HIGH_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm)); \
9730 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9731 IEM_MC_END(); \
9732 break; \
9733 \
9734 case IEMMODE_64BIT: \
9735 IEM_MC_BEGIN(3, 0, IEM_MC_F_64BIT, 0); \
9736 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9737 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
9738 IEM_MC_ARG_CONST(uint8_t, cShiftArg,/*=1*/1, 1); \
9739 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
9740 IEM_MC_REF_GREG_U64(pu64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
9741 IEM_MC_REF_EFLAGS(pEFlags); \
9742 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU64, pu64Dst, cShiftArg, pEFlags); \
9743 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9744 IEM_MC_END(); \
9745 break; \
9746 \
9747 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
9748 } \
9749 } \
9750 else \
9751 { \
9752 /* memory */ \
9753 switch (pVCpu->iem.s.enmEffOpSize) \
9754 { \
9755 case IEMMODE_16BIT: \
9756 IEM_MC_BEGIN(3, 3, 0, 0); \
9757 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
9758 IEM_MC_ARG_CONST(uint8_t, cShiftArg,/*=1*/1, 1); \
9759 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
9760 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
9761 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
9762 \
9763 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
9764 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9765 IEM_MC_MEM_MAP_U16_RW(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
9766 IEM_MC_FETCH_EFLAGS(EFlags); \
9767 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU16, pu16Dst, cShiftArg, pEFlags); \
9768 \
9769 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
9770 IEM_MC_COMMIT_EFLAGS(EFlags); \
9771 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9772 IEM_MC_END(); \
9773 break; \
9774 \
9775 case IEMMODE_32BIT: \
9776 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
9777 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
9778 IEM_MC_ARG_CONST(uint8_t, cShiftArg,/*=1*/1, 1); \
9779 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
9780 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
9781 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
9782 \
9783 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
9784 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9785 IEM_MC_MEM_MAP_U32_RW(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
9786 IEM_MC_FETCH_EFLAGS(EFlags); \
9787 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU32, pu32Dst, cShiftArg, pEFlags); \
9788 \
9789 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
9790 IEM_MC_COMMIT_EFLAGS(EFlags); \
9791 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9792 IEM_MC_END(); \
9793 break; \
9794 \
9795 case IEMMODE_64BIT: \
9796 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
9797 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
9798 IEM_MC_ARG_CONST(uint8_t, cShiftArg,/*=1*/1, 1); \
9799 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
9800 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
9801 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
9802 \
9803 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
9804 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9805 IEM_MC_MEM_MAP_U64_RW(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
9806 IEM_MC_FETCH_EFLAGS(EFlags); \
9807 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU64, pu64Dst, cShiftArg, pEFlags); \
9808 \
9809 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
9810 IEM_MC_COMMIT_EFLAGS(EFlags); \
9811 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9812 IEM_MC_END(); \
9813 break; \
9814 \
9815 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
9816 } \
9817 } (void)0
9818
9819/**
9820 * @opmaps grp2_d1
9821 * @opcode /0
9822 * @opflclass rotate_1
9823 */
9824FNIEMOP_DEF_1(iemOp_grp2_rol_Ev_1, uint8_t, bRm)
9825{
9826 IEMOP_MNEMONIC2(M1, ROL, rol, Ev, 1, DISOPTYPE_HARMLESS, 0);
9827 GRP2_BODY_Ev_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rol_eflags));
9828}
9829
9830
9831/**
9832 * @opmaps grp2_d1
9833 * @opcode /1
9834 * @opflclass rotate_1
9835 */
9836FNIEMOP_DEF_1(iemOp_grp2_ror_Ev_1, uint8_t, bRm)
9837{
9838 IEMOP_MNEMONIC2(M1, ROR, ror, Ev, 1, DISOPTYPE_HARMLESS, 0);
9839 GRP2_BODY_Ev_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_ror_eflags));
9840}
9841
9842
9843/**
9844 * @opmaps grp2_d1
9845 * @opcode /2
9846 * @opflclass rotate_carry_1
9847 */
9848FNIEMOP_DEF_1(iemOp_grp2_rcl_Ev_1, uint8_t, bRm)
9849{
9850 IEMOP_MNEMONIC2(M1, RCL, rcl, Ev, 1, DISOPTYPE_HARMLESS, 0);
9851 GRP2_BODY_Ev_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcl_eflags));
9852}
9853
9854
9855/**
9856 * @opmaps grp2_d1
9857 * @opcode /3
9858 * @opflclass rotate_carry_1
9859 */
9860FNIEMOP_DEF_1(iemOp_grp2_rcr_Ev_1, uint8_t, bRm)
9861{
9862 IEMOP_MNEMONIC2(M1, RCR, rcr, Ev, 1, DISOPTYPE_HARMLESS, 0);
9863 GRP2_BODY_Ev_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcr_eflags));
9864}
9865
9866
9867/**
9868 * @opmaps grp2_d1
9869 * @opcode /4
9870 * @opflclass shift_1
9871 */
9872FNIEMOP_DEF_1(iemOp_grp2_shl_Ev_1, uint8_t, bRm)
9873{
9874 IEMOP_MNEMONIC2(M1, SHL, shl, Ev, 1, DISOPTYPE_HARMLESS, 0);
9875 GRP2_BODY_Ev_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shl_eflags));
9876}
9877
9878
9879/**
9880 * @opmaps grp2_d1
9881 * @opcode /5
9882 * @opflclass shift_1
9883 */
9884FNIEMOP_DEF_1(iemOp_grp2_shr_Ev_1, uint8_t, bRm)
9885{
9886 IEMOP_MNEMONIC2(M1, SHR, shr, Ev, 1, DISOPTYPE_HARMLESS, 0);
9887 GRP2_BODY_Ev_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shr_eflags));
9888}
9889
9890
9891/**
9892 * @opmaps grp2_d1
9893 * @opcode /7
9894 * @opflclass shift_1
9895 */
9896FNIEMOP_DEF_1(iemOp_grp2_sar_Ev_1, uint8_t, bRm)
9897{
9898 IEMOP_MNEMONIC2(M1, SAR, sar, Ev, 1, DISOPTYPE_HARMLESS, 0);
9899 GRP2_BODY_Ev_1(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_sar_eflags));
9900}
9901
9902#undef GRP2_BODY_Ev_1
9903
9904/**
9905 * @opcode 0xd1
9906 */
9907FNIEMOP_DEF(iemOp_Grp2_Ev_1)
9908{
9909 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
9910 switch (IEM_GET_MODRM_REG_8(bRm))
9911 {
9912 case 0: return FNIEMOP_CALL_1(iemOp_grp2_rol_Ev_1, bRm);
9913 case 1: return FNIEMOP_CALL_1(iemOp_grp2_ror_Ev_1, bRm);
9914 case 2: return FNIEMOP_CALL_1(iemOp_grp2_rcl_Ev_1, bRm);
9915 case 3: return FNIEMOP_CALL_1(iemOp_grp2_rcr_Ev_1, bRm);
9916 case 4: return FNIEMOP_CALL_1(iemOp_grp2_shl_Ev_1, bRm);
9917 case 5: return FNIEMOP_CALL_1(iemOp_grp2_shr_Ev_1, bRm);
9918 case 7: return FNIEMOP_CALL_1(iemOp_grp2_sar_Ev_1, bRm);
9919 case 6: IEMOP_RAISE_INVALID_OPCODE_RET();
9920 IEM_NOT_REACHED_DEFAULT_CASE_RET(); /* gcc maybe, well... */
9921 }
9922}
9923
9924
9925/**
9926 * @opcode 0xd2
9927 */
9928FNIEMOP_DEF(iemOp_Grp2_Eb_CL)
9929{
9930 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
9931
9932 /* Need to use a body macro here since the EFLAGS behaviour differs between
9933 the shifts, rotates and rotate w/ carry. Sigh. */
9934#define GRP2_BODY_Eb_CL(a_pImplExpr) \
9935 PCIEMOPSHIFTSIZES const pImpl = (a_pImplExpr); \
9936 if (IEM_IS_MODRM_REG_MODE(bRm)) \
9937 { \
9938 /* register */ \
9939 IEM_MC_BEGIN(3, 0, 0, 0); \
9940 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9941 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
9942 IEM_MC_ARG(uint8_t, cShiftArg, 1); \
9943 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
9944 IEM_MC_FETCH_GREG_U8(cShiftArg, X86_GREG_xCX); \
9945 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
9946 IEM_MC_REF_EFLAGS(pEFlags); \
9947 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU8, pu8Dst, cShiftArg, pEFlags); \
9948 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9949 IEM_MC_END(); \
9950 } \
9951 else \
9952 { \
9953 /* memory */ \
9954 IEM_MC_BEGIN(3, 3, 0, 0); \
9955 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
9956 IEM_MC_ARG(uint8_t, cShiftArg, 1); \
9957 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
9958 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
9959 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
9960 \
9961 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
9962 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
9963 IEM_MC_FETCH_GREG_U8(cShiftArg, X86_GREG_xCX); \
9964 IEM_MC_MEM_MAP_U8_RW(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
9965 IEM_MC_FETCH_EFLAGS(EFlags); \
9966 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU8, pu8Dst, cShiftArg, pEFlags); \
9967 \
9968 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
9969 IEM_MC_COMMIT_EFLAGS(EFlags); \
9970 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
9971 IEM_MC_END(); \
9972 } (void)0
9973
9974 switch (IEM_GET_MODRM_REG_8(bRm))
9975 {
9976 /**
9977 * @opdone
9978 * @opmaps grp2_d0
9979 * @opcode /0
9980 * @opflclass rotate_count
9981 */
9982 case 0:
9983 {
9984 IEMOP_MNEMONIC2EX(rol_Eb_CL, "rol Eb,CL", M_CL, ROL, rol, Eb, REG_CL, DISOPTYPE_HARMLESS, 0);
9985 GRP2_BODY_Eb_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rol_eflags));
9986 break;
9987 }
9988 /**
9989 * @opdone
9990 * @opmaps grp2_d0
9991 * @opcode /1
9992 * @opflclass rotate_count
9993 */
9994 case 1:
9995 {
9996 IEMOP_MNEMONIC2EX(ror_Eb_CL, "ror Eb,CL", M_CL, ROR, ror, Eb, REG_CL, DISOPTYPE_HARMLESS, 0);
9997 GRP2_BODY_Eb_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_ror_eflags));
9998 break;
9999 }
10000 /**
10001 * @opdone
10002 * @opmaps grp2_d0
10003 * @opcode /2
10004 * @opflclass rotate_carry_count
10005 */
10006 case 2:
10007 {
10008 IEMOP_MNEMONIC2EX(rcl_Eb_CL, "rcl Eb,CL", M_CL, RCL, rcl, Eb, REG_CL, DISOPTYPE_HARMLESS, 0);
10009 GRP2_BODY_Eb_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcl_eflags));
10010 break;
10011 }
10012 /**
10013 * @opdone
10014 * @opmaps grp2_d0
10015 * @opcode /3
10016 * @opflclass rotate_carry_count
10017 */
10018 case 3:
10019 {
10020 IEMOP_MNEMONIC2EX(rcr_Eb_CL, "rcr Eb,CL", M_CL, RCR, rcr, Eb, REG_CL, DISOPTYPE_HARMLESS, 0);
10021 GRP2_BODY_Eb_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcr_eflags));
10022 break;
10023 }
10024 /**
10025 * @opdone
10026 * @opmaps grp2_d0
10027 * @opcode /4
10028 * @opflclass shift_count
10029 */
10030 case 4:
10031 {
10032 IEMOP_MNEMONIC2EX(shl_Eb_CL, "shl Eb,CL", M_CL, SHL, shl, Eb, REG_CL, DISOPTYPE_HARMLESS, 0);
10033 GRP2_BODY_Eb_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shl_eflags));
10034 break;
10035 }
10036 /**
10037 * @opdone
10038 * @opmaps grp2_d0
10039 * @opcode /5
10040 * @opflclass shift_count
10041 */
10042 case 5:
10043 {
10044 IEMOP_MNEMONIC2EX(shr_Eb_CL, "shr Eb,CL", M_CL, SHR, shr, Eb, REG_CL, DISOPTYPE_HARMLESS, 0);
10045 GRP2_BODY_Eb_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shr_eflags));
10046 break;
10047 }
10048 /**
10049 * @opdone
10050 * @opmaps grp2_d0
10051 * @opcode /7
10052 * @opflclass shift_count
10053 */
10054 case 7:
10055 {
10056 IEMOP_MNEMONIC2EX(sar_Eb_CL, "sar Eb,CL", M_CL, SAR, sar, Eb, REG_CL, DISOPTYPE_HARMLESS, 0);
10057 GRP2_BODY_Eb_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_sar_eflags));
10058 break;
10059 }
10060 /** @opdone */
10061 case 6: IEMOP_RAISE_INVALID_OPCODE_RET();
10062 IEM_NOT_REACHED_DEFAULT_CASE_RET(); /* gcc maybe, well... */
10063 }
10064#undef GRP2_BODY_Eb_CL
10065}
10066
10067
10068/* Need to use a body macro here since the EFLAGS behaviour differs between
10069 the shifts, rotates and rotate w/ carry. Sigh. */
10070#define GRP2_BODY_Ev_CL(a_pImplExpr) \
10071 PCIEMOPSHIFTSIZES const pImpl = (a_pImplExpr); \
10072 if (IEM_IS_MODRM_REG_MODE(bRm)) \
10073 { \
10074 /* register */ \
10075 switch (pVCpu->iem.s.enmEffOpSize) \
10076 { \
10077 case IEMMODE_16BIT: \
10078 IEM_MC_BEGIN(3, 0, 0, 0); \
10079 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
10080 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
10081 IEM_MC_ARG(uint8_t, cShiftArg, 1); \
10082 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
10083 IEM_MC_FETCH_GREG_U8(cShiftArg, X86_GREG_xCX); \
10084 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
10085 IEM_MC_REF_EFLAGS(pEFlags); \
10086 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU16, pu16Dst, cShiftArg, pEFlags); \
10087 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
10088 IEM_MC_END(); \
10089 break; \
10090 \
10091 case IEMMODE_32BIT: \
10092 IEM_MC_BEGIN(3, 0, IEM_MC_F_MIN_386, 0); \
10093 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
10094 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
10095 IEM_MC_ARG(uint8_t, cShiftArg, 1); \
10096 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
10097 IEM_MC_FETCH_GREG_U8(cShiftArg, X86_GREG_xCX); \
10098 IEM_MC_REF_GREG_U32(pu32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
10099 IEM_MC_REF_EFLAGS(pEFlags); \
10100 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU32, pu32Dst, cShiftArg, pEFlags); \
10101 IEM_MC_CLEAR_HIGH_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm)); \
10102 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
10103 IEM_MC_END(); \
10104 break; \
10105 \
10106 case IEMMODE_64BIT: \
10107 IEM_MC_BEGIN(3, 0, IEM_MC_F_64BIT, 0); \
10108 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
10109 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
10110 IEM_MC_ARG(uint8_t, cShiftArg, 1); \
10111 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
10112 IEM_MC_FETCH_GREG_U8(cShiftArg, X86_GREG_xCX); \
10113 IEM_MC_REF_GREG_U64(pu64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
10114 IEM_MC_REF_EFLAGS(pEFlags); \
10115 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU64, pu64Dst, cShiftArg, pEFlags); \
10116 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
10117 IEM_MC_END(); \
10118 break; \
10119 \
10120 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
10121 } \
10122 } \
10123 else \
10124 { \
10125 /* memory */ \
10126 switch (pVCpu->iem.s.enmEffOpSize) \
10127 { \
10128 case IEMMODE_16BIT: \
10129 IEM_MC_BEGIN(3, 3, 0, 0); \
10130 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
10131 IEM_MC_ARG(uint8_t, cShiftArg, 1); \
10132 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
10133 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
10134 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
10135 \
10136 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
10137 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
10138 IEM_MC_FETCH_GREG_U8(cShiftArg, X86_GREG_xCX); \
10139 IEM_MC_MEM_MAP_U16_RW(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
10140 IEM_MC_FETCH_EFLAGS(EFlags); \
10141 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU16, pu16Dst, cShiftArg, pEFlags); \
10142 \
10143 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
10144 IEM_MC_COMMIT_EFLAGS(EFlags); \
10145 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
10146 IEM_MC_END(); \
10147 break; \
10148 \
10149 case IEMMODE_32BIT: \
10150 IEM_MC_BEGIN(3, 3, IEM_MC_F_MIN_386, 0); \
10151 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
10152 IEM_MC_ARG(uint8_t, cShiftArg, 1); \
10153 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
10154 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
10155 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
10156 \
10157 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
10158 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
10159 IEM_MC_FETCH_GREG_U8(cShiftArg, X86_GREG_xCX); \
10160 IEM_MC_MEM_MAP_U32_RW(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
10161 IEM_MC_FETCH_EFLAGS(EFlags); \
10162 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU32, pu32Dst, cShiftArg, pEFlags); \
10163 \
10164 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
10165 IEM_MC_COMMIT_EFLAGS(EFlags); \
10166 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
10167 IEM_MC_END(); \
10168 break; \
10169 \
10170 case IEMMODE_64BIT: \
10171 IEM_MC_BEGIN(3, 3, IEM_MC_F_64BIT, 0); \
10172 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
10173 IEM_MC_ARG(uint8_t, cShiftArg, 1); \
10174 IEM_MC_ARG_LOCAL_EFLAGS(pEFlags, EFlags, 2); \
10175 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
10176 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
10177 \
10178 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
10179 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
10180 IEM_MC_FETCH_GREG_U8(cShiftArg, X86_GREG_xCX); \
10181 IEM_MC_MEM_MAP_U64_RW(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
10182 IEM_MC_FETCH_EFLAGS(EFlags); \
10183 IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU64, pu64Dst, cShiftArg, pEFlags); \
10184 \
10185 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
10186 IEM_MC_COMMIT_EFLAGS(EFlags); \
10187 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
10188 IEM_MC_END(); \
10189 break; \
10190 \
10191 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
10192 } \
10193 } (void)0
10194
10195
10196/**
10197 * @opmaps grp2_d0
10198 * @opcode /0
10199 * @opflclass rotate_count
10200 */
10201FNIEMOP_DEF_1(iemOp_grp2_rol_Ev_CL, uint8_t, bRm)
10202{
10203 IEMOP_MNEMONIC2EX(rol_Ev_CL, "rol Ev,CL", M_CL, ROL, rol, Ev, REG_CL, DISOPTYPE_HARMLESS, 0);
10204 GRP2_BODY_Ev_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rol_eflags));
10205}
10206
10207
10208/**
10209 * @opmaps grp2_d0
10210 * @opcode /1
10211 * @opflclass rotate_count
10212 */
10213FNIEMOP_DEF_1(iemOp_grp2_ror_Ev_CL, uint8_t, bRm)
10214{
10215 IEMOP_MNEMONIC2EX(ror_Ev_CL, "ror Ev,CL", M_CL, ROR, ror, Ev, REG_CL, DISOPTYPE_HARMLESS, 0);
10216 GRP2_BODY_Ev_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_ror_eflags));
10217}
10218
10219
10220/**
10221 * @opmaps grp2_d0
10222 * @opcode /2
10223 * @opflclass rotate_carry_count
10224 */
10225FNIEMOP_DEF_1(iemOp_grp2_rcl_Ev_CL, uint8_t, bRm)
10226{
10227 IEMOP_MNEMONIC2EX(rcl_Ev_CL, "rcl Ev,CL", M_CL, RCL, rcl, Ev, REG_CL, DISOPTYPE_HARMLESS, 0);
10228 GRP2_BODY_Ev_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcl_eflags));
10229}
10230
10231
10232/**
10233 * @opmaps grp2_d0
10234 * @opcode /3
10235 * @opflclass rotate_carry_count
10236 */
10237FNIEMOP_DEF_1(iemOp_grp2_rcr_Ev_CL, uint8_t, bRm)
10238{
10239 IEMOP_MNEMONIC2EX(rcr_Ev_CL, "rcr Ev,CL", M_CL, RCR, rcr, Ev, REG_CL, DISOPTYPE_HARMLESS, 0);
10240 GRP2_BODY_Ev_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_rcr_eflags));
10241}
10242
10243
10244/**
10245 * @opmaps grp2_d0
10246 * @opcode /4
10247 * @opflclass shift_count
10248 */
10249FNIEMOP_DEF_1(iemOp_grp2_shl_Ev_CL, uint8_t, bRm)
10250{
10251 IEMOP_MNEMONIC2EX(shl_Ev_CL, "shl Ev,CL", M_CL, SHL, shl, Ev, REG_CL, DISOPTYPE_HARMLESS, 0);
10252 GRP2_BODY_Ev_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shl_eflags));
10253}
10254
10255
10256/**
10257 * @opmaps grp2_d0
10258 * @opcode /5
10259 * @opflclass shift_count
10260 */
10261FNIEMOP_DEF_1(iemOp_grp2_shr_Ev_CL, uint8_t, bRm)
10262{
10263 IEMOP_MNEMONIC2EX(shr_Ev_CL, "shr Ev,CL", M_CL, SHR, shr, Ev, REG_CL, DISOPTYPE_HARMLESS, 0);
10264 GRP2_BODY_Ev_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shr_eflags));
10265}
10266
10267
10268/**
10269 * @opmaps grp2_d0
10270 * @opcode /7
10271 * @opflclass shift_count
10272 */
10273FNIEMOP_DEF_1(iemOp_grp2_sar_Ev_CL, uint8_t, bRm)
10274{
10275 IEMOP_MNEMONIC2EX(sar_Ev_CL, "sar Ev,CL", M_CL, SAR, sar, Ev, REG_CL, DISOPTYPE_HARMLESS, 0);
10276 GRP2_BODY_Ev_CL(IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_sar_eflags));
10277}
10278
10279#undef GRP2_BODY_Ev_CL
10280
10281/**
10282 * @opcode 0xd3
10283 */
10284FNIEMOP_DEF(iemOp_Grp2_Ev_CL)
10285{
10286 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
10287 switch (IEM_GET_MODRM_REG_8(bRm))
10288 {
10289 case 0: return FNIEMOP_CALL_1(iemOp_grp2_rol_Ev_CL, bRm);
10290 case 1: return FNIEMOP_CALL_1(iemOp_grp2_ror_Ev_CL, bRm);
10291 case 2: return FNIEMOP_CALL_1(iemOp_grp2_rcl_Ev_CL, bRm);
10292 case 3: return FNIEMOP_CALL_1(iemOp_grp2_rcr_Ev_CL, bRm);
10293 case 4: return FNIEMOP_CALL_1(iemOp_grp2_shl_Ev_CL, bRm);
10294 case 5: return FNIEMOP_CALL_1(iemOp_grp2_shr_Ev_CL, bRm);
10295 case 7: return FNIEMOP_CALL_1(iemOp_grp2_sar_Ev_CL, bRm);
10296 case 6: IEMOP_RAISE_INVALID_OPCODE_RET();
10297 IEM_NOT_REACHED_DEFAULT_CASE_RET(); /* gcc maybe, well... */
10298 }
10299}
10300
10301
10302/**
10303 * @opcode 0xd4
10304 * @opflmodify cf,pf,af,zf,sf,of
10305 * @opflundef cf,af,of
10306 */
10307FNIEMOP_DEF(iemOp_aam_Ib)
10308{
10309/** @todo testcase: aam */
10310 IEMOP_MNEMONIC(aam_Ib, "aam Ib");
10311 uint8_t bImm; IEM_OPCODE_GET_NEXT_U8(&bImm);
10312 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10313 IEMOP_HLP_NO_64BIT();
10314 if (!bImm)
10315 IEMOP_RAISE_DIVIDE_ERROR_RET();
10316 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_STATUS_FLAGS, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX), iemCImpl_aam, bImm);
10317}
10318
10319
10320/**
10321 * @opcode 0xd5
10322 * @opflmodify cf,pf,af,zf,sf,of
10323 * @opflundef cf,af,of
10324 */
10325FNIEMOP_DEF(iemOp_aad_Ib)
10326{
10327/** @todo testcase: aad? */
10328 IEMOP_MNEMONIC(aad_Ib, "aad Ib");
10329 uint8_t bImm; IEM_OPCODE_GET_NEXT_U8(&bImm);
10330 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10331 IEMOP_HLP_NO_64BIT();
10332 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_STATUS_FLAGS, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX), iemCImpl_aad, bImm);
10333}
10334
10335
10336/**
10337 * @opcode 0xd6
10338 */
10339FNIEMOP_DEF(iemOp_salc)
10340{
10341 IEMOP_MNEMONIC(salc, "salc");
10342 IEMOP_HLP_NO_64BIT();
10343
10344 IEM_MC_BEGIN(0, 0, 0, 0);
10345 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10346 IEM_MC_IF_EFL_BIT_SET(X86_EFL_CF) {
10347 IEM_MC_STORE_GREG_U8_CONST(X86_GREG_xAX, 0xff);
10348 } IEM_MC_ELSE() {
10349 IEM_MC_STORE_GREG_U8_CONST(X86_GREG_xAX, 0x00);
10350 } IEM_MC_ENDIF();
10351 IEM_MC_ADVANCE_RIP_AND_FINISH();
10352 IEM_MC_END();
10353}
10354
10355
10356/**
10357 * @opcode 0xd7
10358 */
10359FNIEMOP_DEF(iemOp_xlat)
10360{
10361 IEMOP_MNEMONIC(xlat, "xlat");
10362 switch (pVCpu->iem.s.enmEffAddrMode)
10363 {
10364 case IEMMODE_16BIT:
10365 IEM_MC_BEGIN(2, 0, 0, 0);
10366 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10367 IEM_MC_LOCAL(uint8_t, u8Tmp);
10368 IEM_MC_LOCAL(uint16_t, u16Addr);
10369 IEM_MC_FETCH_GREG_U8_ZX_U16(u16Addr, X86_GREG_xAX);
10370 IEM_MC_ADD_GREG_U16_TO_LOCAL(u16Addr, X86_GREG_xBX);
10371 IEM_MC_FETCH_MEM16_U8(u8Tmp, pVCpu->iem.s.iEffSeg, u16Addr);
10372 IEM_MC_STORE_GREG_U8(X86_GREG_xAX, u8Tmp);
10373 IEM_MC_ADVANCE_RIP_AND_FINISH();
10374 IEM_MC_END();
10375 break;
10376
10377 case IEMMODE_32BIT:
10378 IEM_MC_BEGIN(2, 0, IEM_MC_F_MIN_386, 0);
10379 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10380 IEM_MC_LOCAL(uint8_t, u8Tmp);
10381 IEM_MC_LOCAL(uint32_t, u32Addr);
10382 IEM_MC_FETCH_GREG_U8_ZX_U32(u32Addr, X86_GREG_xAX);
10383 IEM_MC_ADD_GREG_U32_TO_LOCAL(u32Addr, X86_GREG_xBX);
10384 IEM_MC_FETCH_MEM32_U8(u8Tmp, pVCpu->iem.s.iEffSeg, u32Addr);
10385 IEM_MC_STORE_GREG_U8(X86_GREG_xAX, u8Tmp);
10386 IEM_MC_ADVANCE_RIP_AND_FINISH();
10387 IEM_MC_END();
10388 break;
10389
10390 case IEMMODE_64BIT:
10391 IEM_MC_BEGIN(2, 0, IEM_MC_F_64BIT, 0);
10392 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10393 IEM_MC_LOCAL(uint8_t, u8Tmp);
10394 IEM_MC_LOCAL(uint64_t, u64Addr);
10395 IEM_MC_FETCH_GREG_U8_ZX_U64(u64Addr, X86_GREG_xAX);
10396 IEM_MC_ADD_GREG_U64_TO_LOCAL(u64Addr, X86_GREG_xBX);
10397 IEM_MC_FETCH_MEM_U8(u8Tmp, pVCpu->iem.s.iEffSeg, u64Addr);
10398 IEM_MC_STORE_GREG_U8(X86_GREG_xAX, u8Tmp);
10399 IEM_MC_ADVANCE_RIP_AND_FINISH();
10400 IEM_MC_END();
10401 break;
10402
10403 IEM_NOT_REACHED_DEFAULT_CASE_RET();
10404 }
10405}
10406
10407
10408/**
10409 * Common worker for FPU instructions working on ST0 and STn, and storing the
10410 * result in ST0.
10411 *
10412 * @param bRm Mod R/M byte.
10413 * @param pfnAImpl Pointer to the instruction implementation (assembly).
10414 */
10415FNIEMOP_DEF_2(iemOpHlpFpu_st0_stN, uint8_t, bRm, PFNIEMAIMPLFPUR80, pfnAImpl)
10416{
10417 IEM_MC_BEGIN(3, 1, 0, 0);
10418 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10419 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
10420 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
10421 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
10422 IEM_MC_ARG(PCRTFLOAT80U, pr80Value2, 2);
10423
10424 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10425 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10426 IEM_MC_PREPARE_FPU_USAGE();
10427 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, 0, pr80Value2, IEM_GET_MODRM_RM_8(bRm)) {
10428 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pr80Value2);
10429 IEM_MC_STORE_FPU_RESULT(FpuRes, 0, pVCpu->iem.s.uFpuOpcode);
10430 } IEM_MC_ELSE() {
10431 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
10432 } IEM_MC_ENDIF();
10433 IEM_MC_ADVANCE_RIP_AND_FINISH();
10434
10435 IEM_MC_END();
10436}
10437
10438
10439/**
10440 * Common worker for FPU instructions working on ST0 and STn, and only affecting
10441 * flags.
10442 *
10443 * @param bRm Mod R/M byte.
10444 * @param pfnAImpl Pointer to the instruction implementation (assembly).
10445 */
10446FNIEMOP_DEF_2(iemOpHlpFpuNoStore_st0_stN, uint8_t, bRm, PFNIEMAIMPLFPUR80FSW, pfnAImpl)
10447{
10448 IEM_MC_BEGIN(3, 1, 0, 0);
10449 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10450 IEM_MC_LOCAL(uint16_t, u16Fsw);
10451 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
10452 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
10453 IEM_MC_ARG(PCRTFLOAT80U, pr80Value2, 2);
10454
10455 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10456 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10457 IEM_MC_PREPARE_FPU_USAGE();
10458 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, 0, pr80Value2, IEM_GET_MODRM_RM_8(bRm)) {
10459 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pu16Fsw, pr80Value1, pr80Value2);
10460 IEM_MC_UPDATE_FSW(u16Fsw, pVCpu->iem.s.uFpuOpcode);
10461 } IEM_MC_ELSE() {
10462 IEM_MC_FPU_STACK_UNDERFLOW(UINT8_MAX, pVCpu->iem.s.uFpuOpcode);
10463 } IEM_MC_ENDIF();
10464 IEM_MC_ADVANCE_RIP_AND_FINISH();
10465
10466 IEM_MC_END();
10467}
10468
10469
10470/**
10471 * Common worker for FPU instructions working on ST0 and STn, only affecting
10472 * flags, and popping when done.
10473 *
10474 * @param bRm Mod R/M byte.
10475 * @param pfnAImpl Pointer to the instruction implementation (assembly).
10476 */
10477FNIEMOP_DEF_2(iemOpHlpFpuNoStore_st0_stN_pop, uint8_t, bRm, PFNIEMAIMPLFPUR80FSW, pfnAImpl)
10478{
10479 IEM_MC_BEGIN(3, 1, 0, 0);
10480 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10481 IEM_MC_LOCAL(uint16_t, u16Fsw);
10482 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
10483 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
10484 IEM_MC_ARG(PCRTFLOAT80U, pr80Value2, 2);
10485
10486 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10487 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10488 IEM_MC_PREPARE_FPU_USAGE();
10489 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, 0, pr80Value2, IEM_GET_MODRM_RM_8(bRm)) {
10490 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pu16Fsw, pr80Value1, pr80Value2);
10491 IEM_MC_UPDATE_FSW_THEN_POP(u16Fsw, pVCpu->iem.s.uFpuOpcode);
10492 } IEM_MC_ELSE() {
10493 IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(UINT8_MAX, pVCpu->iem.s.uFpuOpcode);
10494 } IEM_MC_ENDIF();
10495 IEM_MC_ADVANCE_RIP_AND_FINISH();
10496
10497 IEM_MC_END();
10498}
10499
10500
10501/** Opcode 0xd8 11/0. */
10502FNIEMOP_DEF_1(iemOp_fadd_stN, uint8_t, bRm)
10503{
10504 IEMOP_MNEMONIC(fadd_st0_stN, "fadd st0,stN");
10505 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fadd_r80_by_r80);
10506}
10507
10508
10509/** Opcode 0xd8 11/1. */
10510FNIEMOP_DEF_1(iemOp_fmul_stN, uint8_t, bRm)
10511{
10512 IEMOP_MNEMONIC(fmul_st0_stN, "fmul st0,stN");
10513 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fmul_r80_by_r80);
10514}
10515
10516
10517/** Opcode 0xd8 11/2. */
10518FNIEMOP_DEF_1(iemOp_fcom_stN, uint8_t, bRm)
10519{
10520 IEMOP_MNEMONIC(fcom_st0_stN, "fcom st0,stN");
10521 return FNIEMOP_CALL_2(iemOpHlpFpuNoStore_st0_stN, bRm, iemAImpl_fcom_r80_by_r80);
10522}
10523
10524
10525/** Opcode 0xd8 11/3. */
10526FNIEMOP_DEF_1(iemOp_fcomp_stN, uint8_t, bRm)
10527{
10528 IEMOP_MNEMONIC(fcomp_st0_stN, "fcomp st0,stN");
10529 return FNIEMOP_CALL_2(iemOpHlpFpuNoStore_st0_stN_pop, bRm, iemAImpl_fcom_r80_by_r80);
10530}
10531
10532
10533/** Opcode 0xd8 11/4. */
10534FNIEMOP_DEF_1(iemOp_fsub_stN, uint8_t, bRm)
10535{
10536 IEMOP_MNEMONIC(fsub_st0_stN, "fsub st0,stN");
10537 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fsub_r80_by_r80);
10538}
10539
10540
10541/** Opcode 0xd8 11/5. */
10542FNIEMOP_DEF_1(iemOp_fsubr_stN, uint8_t, bRm)
10543{
10544 IEMOP_MNEMONIC(fsubr_st0_stN, "fsubr st0,stN");
10545 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fsubr_r80_by_r80);
10546}
10547
10548
10549/** Opcode 0xd8 11/6. */
10550FNIEMOP_DEF_1(iemOp_fdiv_stN, uint8_t, bRm)
10551{
10552 IEMOP_MNEMONIC(fdiv_st0_stN, "fdiv st0,stN");
10553 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fdiv_r80_by_r80);
10554}
10555
10556
10557/** Opcode 0xd8 11/7. */
10558FNIEMOP_DEF_1(iemOp_fdivr_stN, uint8_t, bRm)
10559{
10560 IEMOP_MNEMONIC(fdivr_st0_stN, "fdivr st0,stN");
10561 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fdivr_r80_by_r80);
10562}
10563
10564
10565/**
10566 * Common worker for FPU instructions working on ST0 and an m32r, and storing
10567 * the result in ST0.
10568 *
10569 * @param bRm Mod R/M byte.
10570 * @param pfnAImpl Pointer to the instruction implementation (assembly).
10571 */
10572FNIEMOP_DEF_2(iemOpHlpFpu_st0_m32r, uint8_t, bRm, PFNIEMAIMPLFPUR32, pfnAImpl)
10573{
10574 IEM_MC_BEGIN(3, 3, 0, 0);
10575 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
10576 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
10577 IEM_MC_LOCAL(RTFLOAT32U, r32Val2);
10578 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
10579 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
10580 IEM_MC_ARG_LOCAL_REF(PCRTFLOAT32U, pr32Val2, r32Val2, 2);
10581
10582 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
10583 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10584
10585 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10586 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10587 IEM_MC_FETCH_MEM_R32(r32Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
10588
10589 IEM_MC_PREPARE_FPU_USAGE();
10590 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
10591 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pr32Val2);
10592 IEM_MC_STORE_FPU_RESULT(FpuRes, 0, pVCpu->iem.s.uFpuOpcode);
10593 } IEM_MC_ELSE() {
10594 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
10595 } IEM_MC_ENDIF();
10596 IEM_MC_ADVANCE_RIP_AND_FINISH();
10597
10598 IEM_MC_END();
10599}
10600
10601
10602/** Opcode 0xd8 !11/0. */
10603FNIEMOP_DEF_1(iemOp_fadd_m32r, uint8_t, bRm)
10604{
10605 IEMOP_MNEMONIC(fadd_st0_m32r, "fadd st0,m32r");
10606 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32r, bRm, iemAImpl_fadd_r80_by_r32);
10607}
10608
10609
10610/** Opcode 0xd8 !11/1. */
10611FNIEMOP_DEF_1(iemOp_fmul_m32r, uint8_t, bRm)
10612{
10613 IEMOP_MNEMONIC(fmul_st0_m32r, "fmul st0,m32r");
10614 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32r, bRm, iemAImpl_fmul_r80_by_r32);
10615}
10616
10617
10618/** Opcode 0xd8 !11/2. */
10619FNIEMOP_DEF_1(iemOp_fcom_m32r, uint8_t, bRm)
10620{
10621 IEMOP_MNEMONIC(fcom_st0_m32r, "fcom st0,m32r");
10622
10623 IEM_MC_BEGIN(3, 3, 0, 0);
10624 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
10625 IEM_MC_LOCAL(uint16_t, u16Fsw);
10626 IEM_MC_LOCAL(RTFLOAT32U, r32Val2);
10627 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
10628 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
10629 IEM_MC_ARG_LOCAL_REF(PCRTFLOAT32U, pr32Val2, r32Val2, 2);
10630
10631 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
10632 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10633
10634 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10635 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10636 IEM_MC_FETCH_MEM_R32(r32Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
10637
10638 IEM_MC_PREPARE_FPU_USAGE();
10639 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
10640 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fcom_r80_by_r32, pu16Fsw, pr80Value1, pr32Val2);
10641 IEM_MC_UPDATE_FSW_WITH_MEM_OP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
10642 } IEM_MC_ELSE() {
10643 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
10644 } IEM_MC_ENDIF();
10645 IEM_MC_ADVANCE_RIP_AND_FINISH();
10646
10647 IEM_MC_END();
10648}
10649
10650
10651/** Opcode 0xd8 !11/3. */
10652FNIEMOP_DEF_1(iemOp_fcomp_m32r, uint8_t, bRm)
10653{
10654 IEMOP_MNEMONIC(fcomp_st0_m32r, "fcomp st0,m32r");
10655
10656 IEM_MC_BEGIN(3, 3, 0, 0);
10657 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
10658 IEM_MC_LOCAL(uint16_t, u16Fsw);
10659 IEM_MC_LOCAL(RTFLOAT32U, r32Val2);
10660 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
10661 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
10662 IEM_MC_ARG_LOCAL_REF(PCRTFLOAT32U, pr32Val2, r32Val2, 2);
10663
10664 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
10665 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10666
10667 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10668 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10669 IEM_MC_FETCH_MEM_R32(r32Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
10670
10671 IEM_MC_PREPARE_FPU_USAGE();
10672 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
10673 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fcom_r80_by_r32, pu16Fsw, pr80Value1, pr32Val2);
10674 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
10675 } IEM_MC_ELSE() {
10676 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
10677 } IEM_MC_ENDIF();
10678 IEM_MC_ADVANCE_RIP_AND_FINISH();
10679
10680 IEM_MC_END();
10681}
10682
10683
10684/** Opcode 0xd8 !11/4. */
10685FNIEMOP_DEF_1(iemOp_fsub_m32r, uint8_t, bRm)
10686{
10687 IEMOP_MNEMONIC(fsub_st0_m32r, "fsub st0,m32r");
10688 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32r, bRm, iemAImpl_fsub_r80_by_r32);
10689}
10690
10691
10692/** Opcode 0xd8 !11/5. */
10693FNIEMOP_DEF_1(iemOp_fsubr_m32r, uint8_t, bRm)
10694{
10695 IEMOP_MNEMONIC(fsubr_st0_m32r, "fsubr st0,m32r");
10696 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32r, bRm, iemAImpl_fsubr_r80_by_r32);
10697}
10698
10699
10700/** Opcode 0xd8 !11/6. */
10701FNIEMOP_DEF_1(iemOp_fdiv_m32r, uint8_t, bRm)
10702{
10703 IEMOP_MNEMONIC(fdiv_st0_m32r, "fdiv st0,m32r");
10704 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32r, bRm, iemAImpl_fdiv_r80_by_r32);
10705}
10706
10707
10708/** Opcode 0xd8 !11/7. */
10709FNIEMOP_DEF_1(iemOp_fdivr_m32r, uint8_t, bRm)
10710{
10711 IEMOP_MNEMONIC(fdivr_st0_m32r, "fdivr st0,m32r");
10712 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32r, bRm, iemAImpl_fdivr_r80_by_r32);
10713}
10714
10715
10716/**
10717 * @opcode 0xd8
10718 */
10719FNIEMOP_DEF(iemOp_EscF0)
10720{
10721 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
10722 pVCpu->iem.s.uFpuOpcode = RT_MAKE_U16(bRm, 0xd8 & 0x7);
10723
10724 if (IEM_IS_MODRM_REG_MODE(bRm))
10725 {
10726 switch (IEM_GET_MODRM_REG_8(bRm))
10727 {
10728 case 0: return FNIEMOP_CALL_1(iemOp_fadd_stN, bRm);
10729 case 1: return FNIEMOP_CALL_1(iemOp_fmul_stN, bRm);
10730 case 2: return FNIEMOP_CALL_1(iemOp_fcom_stN, bRm);
10731 case 3: return FNIEMOP_CALL_1(iemOp_fcomp_stN, bRm);
10732 case 4: return FNIEMOP_CALL_1(iemOp_fsub_stN, bRm);
10733 case 5: return FNIEMOP_CALL_1(iemOp_fsubr_stN, bRm);
10734 case 6: return FNIEMOP_CALL_1(iemOp_fdiv_stN, bRm);
10735 case 7: return FNIEMOP_CALL_1(iemOp_fdivr_stN, bRm);
10736 IEM_NOT_REACHED_DEFAULT_CASE_RET();
10737 }
10738 }
10739 else
10740 {
10741 switch (IEM_GET_MODRM_REG_8(bRm))
10742 {
10743 case 0: return FNIEMOP_CALL_1(iemOp_fadd_m32r, bRm);
10744 case 1: return FNIEMOP_CALL_1(iemOp_fmul_m32r, bRm);
10745 case 2: return FNIEMOP_CALL_1(iemOp_fcom_m32r, bRm);
10746 case 3: return FNIEMOP_CALL_1(iemOp_fcomp_m32r, bRm);
10747 case 4: return FNIEMOP_CALL_1(iemOp_fsub_m32r, bRm);
10748 case 5: return FNIEMOP_CALL_1(iemOp_fsubr_m32r, bRm);
10749 case 6: return FNIEMOP_CALL_1(iemOp_fdiv_m32r, bRm);
10750 case 7: return FNIEMOP_CALL_1(iemOp_fdivr_m32r, bRm);
10751 IEM_NOT_REACHED_DEFAULT_CASE_RET();
10752 }
10753 }
10754}
10755
10756
10757/** Opcode 0xd9 /0 mem32real
10758 * @sa iemOp_fld_m64r */
10759FNIEMOP_DEF_1(iemOp_fld_m32r, uint8_t, bRm)
10760{
10761 IEMOP_MNEMONIC(fld_m32r, "fld m32r");
10762
10763 IEM_MC_BEGIN(2, 3, 0, 0);
10764 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
10765 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
10766 IEM_MC_LOCAL(RTFLOAT32U, r32Val);
10767 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
10768 IEM_MC_ARG_LOCAL_REF(PCRTFLOAT32U, pr32Val, r32Val, 1);
10769
10770 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
10771 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10772
10773 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10774 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10775 IEM_MC_FETCH_MEM_R32(r32Val, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
10776 IEM_MC_PREPARE_FPU_USAGE();
10777 IEM_MC_IF_FPUREG_IS_EMPTY(7) {
10778 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fld_r80_from_r32, pFpuRes, pr32Val);
10779 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
10780 } IEM_MC_ELSE() {
10781 IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
10782 } IEM_MC_ENDIF();
10783 IEM_MC_ADVANCE_RIP_AND_FINISH();
10784
10785 IEM_MC_END();
10786}
10787
10788
10789/** Opcode 0xd9 !11/2 mem32real */
10790FNIEMOP_DEF_1(iemOp_fst_m32r, uint8_t, bRm)
10791{
10792 IEMOP_MNEMONIC(fst_m32r, "fst m32r");
10793 IEM_MC_BEGIN(3, 3, 0, 0);
10794 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
10795 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
10796
10797 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10798 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10799 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10800 IEM_MC_PREPARE_FPU_USAGE();
10801
10802 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
10803 IEM_MC_ARG(PRTFLOAT32U, pr32Dst, 1);
10804 IEM_MC_MEM_MAP_R32_WO(pr32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
10805
10806 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
10807 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
10808 IEM_MC_LOCAL(uint16_t, u16Fsw);
10809 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
10810 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fst_r80_to_r32, pu16Fsw, pr32Dst, pr80Value);
10811 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
10812 IEM_MC_UPDATE_FSW_WITH_MEM_OP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
10813 } IEM_MC_ELSE() {
10814 IEM_MC_IF_FCW_IM() {
10815 IEM_MC_STORE_MEM_NEG_QNAN_R32_BY_REF(pr32Dst);
10816 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
10817 } IEM_MC_ELSE() {
10818 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
10819 } IEM_MC_ENDIF();
10820 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
10821 } IEM_MC_ENDIF();
10822 IEM_MC_ADVANCE_RIP_AND_FINISH();
10823
10824 IEM_MC_END();
10825}
10826
10827
10828/** Opcode 0xd9 !11/3 */
10829FNIEMOP_DEF_1(iemOp_fstp_m32r, uint8_t, bRm)
10830{
10831 IEMOP_MNEMONIC(fstp_m32r, "fstp m32r");
10832 IEM_MC_BEGIN(3, 3, 0, 0);
10833 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
10834 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
10835
10836 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10837 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10838 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10839 IEM_MC_PREPARE_FPU_USAGE();
10840
10841 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
10842 IEM_MC_ARG(PRTFLOAT32U, pr32Dst, 1);
10843 IEM_MC_MEM_MAP_R32_WO(pr32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
10844
10845 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
10846 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
10847 IEM_MC_LOCAL(uint16_t, u16Fsw);
10848 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
10849 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fst_r80_to_r32, pu16Fsw, pr32Dst, pr80Value);
10850 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
10851 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
10852 } IEM_MC_ELSE() {
10853 IEM_MC_IF_FCW_IM() {
10854 IEM_MC_STORE_MEM_NEG_QNAN_R32_BY_REF(pr32Dst);
10855 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
10856 } IEM_MC_ELSE() {
10857 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
10858 } IEM_MC_ENDIF();
10859 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
10860 } IEM_MC_ENDIF();
10861 IEM_MC_ADVANCE_RIP_AND_FINISH();
10862
10863 IEM_MC_END();
10864}
10865
10866
10867/** Opcode 0xd9 !11/4 */
10868FNIEMOP_DEF_1(iemOp_fldenv, uint8_t, bRm)
10869{
10870 IEMOP_MNEMONIC(fldenv, "fldenv m14/28byte");
10871 IEM_MC_BEGIN(3, 0, 0, 0);
10872 IEM_MC_ARG(RTGCPTR, GCPtrEffSrc, 2);
10873 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
10874
10875 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10876 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10877 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
10878
10879 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize, /*=*/ pVCpu->iem.s.enmEffOpSize, 0);
10880 IEM_MC_ARG_CONST(uint8_t, iEffSeg, /*=*/ pVCpu->iem.s.iEffSeg, 1);
10881 IEM_MC_CALL_CIMPL_3(IEM_CIMPL_F_FPU, RT_BIT_64(kIemNativeGstReg_FpuFcw),
10882 iemCImpl_fldenv, enmEffOpSize, iEffSeg, GCPtrEffSrc);
10883 IEM_MC_END();
10884}
10885
10886
10887/** Opcode 0xd9 !11/5 */
10888FNIEMOP_DEF_1(iemOp_fldcw, uint8_t, bRm)
10889{
10890 IEMOP_MNEMONIC(fldcw_m2byte, "fldcw m2byte");
10891 IEM_MC_BEGIN(1, 1, 0, 0);
10892 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
10893 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
10894
10895 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10896 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10897 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
10898
10899 IEM_MC_ARG(uint16_t, u16Fsw, 0);
10900 IEM_MC_FETCH_MEM_U16(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
10901
10902 IEM_MC_CALL_CIMPL_1(IEM_CIMPL_F_FPU, RT_BIT_64(kIemNativeGstReg_FpuFcw),
10903 iemCImpl_fldcw, u16Fsw);
10904 IEM_MC_END();
10905}
10906
10907
10908/** Opcode 0xd9 !11/6 */
10909FNIEMOP_DEF_1(iemOp_fnstenv, uint8_t, bRm)
10910{
10911 IEMOP_MNEMONIC(fstenv, "fstenv m14/m28byte");
10912 IEM_MC_BEGIN(3, 0, 0, 0);
10913 IEM_MC_ARG(RTGCPTR, GCPtrEffDst, 2);
10914 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
10915
10916 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10917 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10918 IEM_MC_ACTUALIZE_FPU_STATE_FOR_READ();
10919
10920 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize, /*=*/ pVCpu->iem.s.enmEffOpSize, 0);
10921 IEM_MC_ARG_CONST(uint8_t, iEffSeg, /*=*/ pVCpu->iem.s.iEffSeg, 1);
10922 IEM_MC_CALL_CIMPL_3(IEM_CIMPL_F_FPU, RT_BIT_64(kIemNativeGstReg_FpuFcw) | RT_BIT_64(kIemNativeGstReg_FpuFsw),
10923 iemCImpl_fnstenv, enmEffOpSize, iEffSeg, GCPtrEffDst);
10924 IEM_MC_END();
10925}
10926
10927
10928/** Opcode 0xd9 !11/7 */
10929FNIEMOP_DEF_1(iemOp_fnstcw, uint8_t, bRm)
10930{
10931 IEMOP_MNEMONIC(fnstcw_m2byte, "fnstcw m2byte");
10932 IEM_MC_BEGIN(2, 0, 0, 0);
10933 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
10934 IEM_MC_LOCAL(uint16_t, u16Fcw);
10935 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
10936 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10937 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10938 IEM_MC_ACTUALIZE_FPU_STATE_FOR_READ();
10939 IEM_MC_FETCH_FCW(u16Fcw);
10940 IEM_MC_STORE_MEM_U16(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u16Fcw);
10941 IEM_MC_ADVANCE_RIP_AND_FINISH(); /* C0-C3 are documented as undefined, we leave them unmodified. */
10942 IEM_MC_END();
10943}
10944
10945
10946/** Opcode 0xd9 0xd0, 0xd9 0xd8-0xdf, ++?. */
10947FNIEMOP_DEF(iemOp_fnop)
10948{
10949 IEMOP_MNEMONIC(fnop, "fnop");
10950 IEM_MC_BEGIN(0, 0, 0, 0);
10951 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10952 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10953 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10954 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
10955 /** @todo Testcase: looks like FNOP leaves FOP alone but updates FPUIP. Could be
10956 * intel optimizations. Investigate. */
10957 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
10958 IEM_MC_ADVANCE_RIP_AND_FINISH(); /* C0-C3 are documented as undefined, we leave them unmodified. */
10959 IEM_MC_END();
10960}
10961
10962
10963/** Opcode 0xd9 11/0 stN */
10964FNIEMOP_DEF_1(iemOp_fld_stN, uint8_t, bRm)
10965{
10966 IEMOP_MNEMONIC(fld_stN, "fld stN");
10967 /** @todo Testcase: Check if this raises \#MF? Intel mentioned it not. AMD
10968 * indicates that it does. */
10969 IEM_MC_BEGIN(0, 2, 0, 0);
10970 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10971 IEM_MC_LOCAL(PCRTFLOAT80U, pr80Value);
10972 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
10973 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
10974 IEM_MC_MAYBE_RAISE_FPU_XCPT();
10975
10976 IEM_MC_PREPARE_FPU_USAGE();
10977 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, IEM_GET_MODRM_RM_8(bRm)) {
10978 IEM_MC_SET_FPU_RESULT(FpuRes, 0 /*FSW*/, pr80Value);
10979 IEM_MC_PUSH_FPU_RESULT(FpuRes, pVCpu->iem.s.uFpuOpcode);
10980 } IEM_MC_ELSE() {
10981 IEM_MC_FPU_STACK_PUSH_UNDERFLOW(pVCpu->iem.s.uFpuOpcode);
10982 } IEM_MC_ENDIF();
10983
10984 IEM_MC_ADVANCE_RIP_AND_FINISH();
10985 IEM_MC_END();
10986}
10987
10988
10989/** Opcode 0xd9 11/3 stN */
10990FNIEMOP_DEF_1(iemOp_fxch_stN, uint8_t, bRm)
10991{
10992 IEMOP_MNEMONIC(fxch_stN, "fxch stN");
10993 /** @todo Testcase: Check if this raises \#MF? Intel mentioned it not. AMD
10994 * indicates that it does. */
10995 IEM_MC_BEGIN(2, 3, 0, 0);
10996 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
10997 IEM_MC_LOCAL(PCRTFLOAT80U, pr80Value1);
10998 IEM_MC_LOCAL(PCRTFLOAT80U, pr80Value2);
10999 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
11000 IEM_MC_ARG_CONST(uint8_t, iStReg, /*=*/ IEM_GET_MODRM_RM_8(bRm), 0);
11001 IEM_MC_ARG_CONST(uint16_t, uFpuOpcode, /*=*/ pVCpu->iem.s.uFpuOpcode, 1);
11002 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11003 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11004
11005 IEM_MC_PREPARE_FPU_USAGE();
11006 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, 0, pr80Value2, IEM_GET_MODRM_RM_8(bRm)) {
11007 IEM_MC_SET_FPU_RESULT(FpuRes, X86_FSW_C1, pr80Value2);
11008 IEM_MC_STORE_FPUREG_R80_SRC_REF(IEM_GET_MODRM_RM_8(bRm), pr80Value1);
11009 IEM_MC_STORE_FPU_RESULT(FpuRes, 0, pVCpu->iem.s.uFpuOpcode);
11010 } IEM_MC_ELSE() {
11011 IEM_MC_CALL_CIMPL_2(IEM_CIMPL_F_FPU, 0, iemCImpl_fxch_underflow, iStReg, uFpuOpcode);
11012 } IEM_MC_ENDIF();
11013
11014 IEM_MC_ADVANCE_RIP_AND_FINISH();
11015 IEM_MC_END();
11016}
11017
11018
11019/** Opcode 0xd9 11/4, 0xdd 11/2. */
11020FNIEMOP_DEF_1(iemOp_fstp_stN, uint8_t, bRm)
11021{
11022 IEMOP_MNEMONIC(fstp_st0_stN, "fstp st0,stN");
11023
11024 /* fstp st0, st0 is frequently used as an official 'ffreep st0' sequence. */
11025 uint8_t const iDstReg = IEM_GET_MODRM_RM_8(bRm);
11026 if (!iDstReg)
11027 {
11028 IEM_MC_BEGIN(0, 1, 0, 0);
11029 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11030 IEM_MC_LOCAL_CONST(uint16_t, u16Fsw, /*=*/ 0);
11031 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11032 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11033
11034 IEM_MC_PREPARE_FPU_USAGE();
11035 IEM_MC_IF_FPUREG_NOT_EMPTY(0) {
11036 IEM_MC_UPDATE_FSW_THEN_POP(u16Fsw, pVCpu->iem.s.uFpuOpcode);
11037 } IEM_MC_ELSE() {
11038 IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(0, pVCpu->iem.s.uFpuOpcode);
11039 } IEM_MC_ENDIF();
11040
11041 IEM_MC_ADVANCE_RIP_AND_FINISH();
11042 IEM_MC_END();
11043 }
11044 else
11045 {
11046 IEM_MC_BEGIN(0, 2, 0, 0);
11047 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11048 IEM_MC_LOCAL(PCRTFLOAT80U, pr80Value);
11049 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
11050 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11051 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11052
11053 IEM_MC_PREPARE_FPU_USAGE();
11054 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
11055 IEM_MC_SET_FPU_RESULT(FpuRes, 0 /*FSW*/, pr80Value);
11056 IEM_MC_STORE_FPU_RESULT_THEN_POP(FpuRes, iDstReg, pVCpu->iem.s.uFpuOpcode);
11057 } IEM_MC_ELSE() {
11058 IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(iDstReg, pVCpu->iem.s.uFpuOpcode);
11059 } IEM_MC_ENDIF();
11060
11061 IEM_MC_ADVANCE_RIP_AND_FINISH();
11062 IEM_MC_END();
11063 }
11064}
11065
11066
11067/**
11068 * Common worker for FPU instructions working on ST0 and replaces it with the
11069 * result, i.e. unary operators.
11070 *
11071 * @param pfnAImpl Pointer to the instruction implementation (assembly).
11072 */
11073FNIEMOP_DEF_1(iemOpHlpFpu_st0, PFNIEMAIMPLFPUR80UNARY, pfnAImpl)
11074{
11075 IEM_MC_BEGIN(2, 1, 0, 0);
11076 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11077 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
11078 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
11079 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 1);
11080
11081 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11082 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11083 IEM_MC_PREPARE_FPU_USAGE();
11084 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
11085 IEM_MC_CALL_FPU_AIMPL_2(pfnAImpl, pFpuRes, pr80Value);
11086 IEM_MC_STORE_FPU_RESULT(FpuRes, 0, pVCpu->iem.s.uFpuOpcode);
11087 } IEM_MC_ELSE() {
11088 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
11089 } IEM_MC_ENDIF();
11090 IEM_MC_ADVANCE_RIP_AND_FINISH();
11091
11092 IEM_MC_END();
11093}
11094
11095
11096/** Opcode 0xd9 0xe0. */
11097FNIEMOP_DEF(iemOp_fchs)
11098{
11099 IEMOP_MNEMONIC(fchs_st0, "fchs st0");
11100 return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_fchs_r80);
11101}
11102
11103
11104/** Opcode 0xd9 0xe1. */
11105FNIEMOP_DEF(iemOp_fabs)
11106{
11107 IEMOP_MNEMONIC(fabs_st0, "fabs st0");
11108 return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_fabs_r80);
11109}
11110
11111
11112/** Opcode 0xd9 0xe4. */
11113FNIEMOP_DEF(iemOp_ftst)
11114{
11115 IEMOP_MNEMONIC(ftst_st0, "ftst st0");
11116 IEM_MC_BEGIN(2, 1, 0, 0);
11117 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11118 IEM_MC_LOCAL(uint16_t, u16Fsw);
11119 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
11120 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 1);
11121
11122 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11123 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11124 IEM_MC_PREPARE_FPU_USAGE();
11125 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
11126 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_ftst_r80, pu16Fsw, pr80Value);
11127 IEM_MC_UPDATE_FSW(u16Fsw, pVCpu->iem.s.uFpuOpcode);
11128 } IEM_MC_ELSE() {
11129 IEM_MC_FPU_STACK_UNDERFLOW(UINT8_MAX, pVCpu->iem.s.uFpuOpcode);
11130 } IEM_MC_ENDIF();
11131 IEM_MC_ADVANCE_RIP_AND_FINISH();
11132
11133 IEM_MC_END();
11134}
11135
11136
11137/** Opcode 0xd9 0xe5. */
11138FNIEMOP_DEF(iemOp_fxam)
11139{
11140 IEMOP_MNEMONIC(fxam_st0, "fxam st0");
11141 IEM_MC_BEGIN(2, 1, 0, 0);
11142 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11143 IEM_MC_LOCAL(uint16_t, u16Fsw);
11144 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
11145 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 1);
11146
11147 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11148 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11149 IEM_MC_PREPARE_FPU_USAGE();
11150 IEM_MC_REF_FPUREG(pr80Value, 0);
11151 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fxam_r80, pu16Fsw, pr80Value);
11152 IEM_MC_UPDATE_FSW(u16Fsw, pVCpu->iem.s.uFpuOpcode);
11153 IEM_MC_ADVANCE_RIP_AND_FINISH();
11154
11155 IEM_MC_END();
11156}
11157
11158
11159/**
11160 * Common worker for FPU instructions pushing a constant onto the FPU stack.
11161 *
11162 * @param pfnAImpl Pointer to the instruction implementation (assembly).
11163 */
11164FNIEMOP_DEF_1(iemOpHlpFpuPushConstant, PFNIEMAIMPLFPUR80LDCONST, pfnAImpl)
11165{
11166 IEM_MC_BEGIN(1, 1, 0, 0);
11167 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11168 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
11169 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
11170
11171 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11172 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11173 IEM_MC_PREPARE_FPU_USAGE();
11174 IEM_MC_IF_FPUREG_IS_EMPTY(7) {
11175 IEM_MC_CALL_FPU_AIMPL_1(pfnAImpl, pFpuRes);
11176 IEM_MC_PUSH_FPU_RESULT(FpuRes, pVCpu->iem.s.uFpuOpcode);
11177 } IEM_MC_ELSE() {
11178 IEM_MC_FPU_STACK_PUSH_OVERFLOW(pVCpu->iem.s.uFpuOpcode);
11179 } IEM_MC_ENDIF();
11180 IEM_MC_ADVANCE_RIP_AND_FINISH();
11181
11182 IEM_MC_END();
11183}
11184
11185
11186/** Opcode 0xd9 0xe8. */
11187FNIEMOP_DEF(iemOp_fld1)
11188{
11189 IEMOP_MNEMONIC(fld1, "fld1");
11190 return FNIEMOP_CALL_1(iemOpHlpFpuPushConstant, iemAImpl_fld1);
11191}
11192
11193
11194/** Opcode 0xd9 0xe9. */
11195FNIEMOP_DEF(iemOp_fldl2t)
11196{
11197 IEMOP_MNEMONIC(fldl2t, "fldl2t");
11198 return FNIEMOP_CALL_1(iemOpHlpFpuPushConstant, iemAImpl_fldl2t);
11199}
11200
11201
11202/** Opcode 0xd9 0xea. */
11203FNIEMOP_DEF(iemOp_fldl2e)
11204{
11205 IEMOP_MNEMONIC(fldl2e, "fldl2e");
11206 return FNIEMOP_CALL_1(iemOpHlpFpuPushConstant, iemAImpl_fldl2e);
11207}
11208
11209/** Opcode 0xd9 0xeb. */
11210FNIEMOP_DEF(iemOp_fldpi)
11211{
11212 IEMOP_MNEMONIC(fldpi, "fldpi");
11213 return FNIEMOP_CALL_1(iemOpHlpFpuPushConstant, iemAImpl_fldpi);
11214}
11215
11216
11217/** Opcode 0xd9 0xec. */
11218FNIEMOP_DEF(iemOp_fldlg2)
11219{
11220 IEMOP_MNEMONIC(fldlg2, "fldlg2");
11221 return FNIEMOP_CALL_1(iemOpHlpFpuPushConstant, iemAImpl_fldlg2);
11222}
11223
11224/** Opcode 0xd9 0xed. */
11225FNIEMOP_DEF(iemOp_fldln2)
11226{
11227 IEMOP_MNEMONIC(fldln2, "fldln2");
11228 return FNIEMOP_CALL_1(iemOpHlpFpuPushConstant, iemAImpl_fldln2);
11229}
11230
11231
11232/** Opcode 0xd9 0xee. */
11233FNIEMOP_DEF(iemOp_fldz)
11234{
11235 IEMOP_MNEMONIC(fldz, "fldz");
11236 return FNIEMOP_CALL_1(iemOpHlpFpuPushConstant, iemAImpl_fldz);
11237}
11238
11239
11240/** Opcode 0xd9 0xf0.
11241 *
11242 * The f2xm1 instruction works on values +1.0 thru -1.0, currently (the range on
11243 * 287 & 8087 was +0.5 thru 0.0 according to docs). In addition is does appear
11244 * to produce proper results for +Inf and -Inf.
11245 *
11246 * This is probably usful in the implementation pow() and similar.
11247 */
11248FNIEMOP_DEF(iemOp_f2xm1)
11249{
11250 IEMOP_MNEMONIC(f2xm1_st0, "f2xm1 st0");
11251 return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_f2xm1_r80);
11252}
11253
11254
11255/**
11256 * Common worker for FPU instructions working on STn and ST0, storing the result
11257 * in STn, and popping the stack unless IE, DE or ZE was raised.
11258 *
11259 * @param bRm Mod R/M byte.
11260 * @param pfnAImpl Pointer to the instruction implementation (assembly).
11261 */
11262FNIEMOP_DEF_2(iemOpHlpFpu_stN_st0_pop, uint8_t, bRm, PFNIEMAIMPLFPUR80, pfnAImpl)
11263{
11264 IEM_MC_BEGIN(3, 1, 0, 0);
11265 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11266 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
11267 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
11268 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
11269 IEM_MC_ARG(PCRTFLOAT80U, pr80Value2, 2);
11270
11271 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11272 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11273
11274 IEM_MC_PREPARE_FPU_USAGE();
11275 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, IEM_GET_MODRM_RM_8(bRm), pr80Value2, 0) {
11276 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pr80Value2);
11277 IEM_MC_STORE_FPU_RESULT_THEN_POP(FpuRes, IEM_GET_MODRM_RM_8(bRm), pVCpu->iem.s.uFpuOpcode);
11278 } IEM_MC_ELSE() {
11279 IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(IEM_GET_MODRM_RM_8(bRm), pVCpu->iem.s.uFpuOpcode);
11280 } IEM_MC_ENDIF();
11281 IEM_MC_ADVANCE_RIP_AND_FINISH();
11282
11283 IEM_MC_END();
11284}
11285
11286
11287/** Opcode 0xd9 0xf1. */
11288FNIEMOP_DEF(iemOp_fyl2x)
11289{
11290 IEMOP_MNEMONIC(fyl2x_st0, "fyl2x st1,st0");
11291 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, 1, iemAImpl_fyl2x_r80_by_r80);
11292}
11293
11294
11295/**
11296 * Common worker for FPU instructions working on ST0 and having two outputs, one
11297 * replacing ST0 and one pushed onto the stack.
11298 *
11299 * @param pfnAImpl Pointer to the instruction implementation (assembly).
11300 */
11301FNIEMOP_DEF_1(iemOpHlpFpuReplace_st0_push, PFNIEMAIMPLFPUR80UNARYTWO, pfnAImpl)
11302{
11303 IEM_MC_BEGIN(2, 1, 0, 0);
11304 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11305 IEM_MC_LOCAL(IEMFPURESULTTWO, FpuResTwo);
11306 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULTTWO, pFpuResTwo, FpuResTwo, 0);
11307 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 1);
11308
11309 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11310 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11311 IEM_MC_PREPARE_FPU_USAGE();
11312 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
11313 IEM_MC_CALL_FPU_AIMPL_2(pfnAImpl, pFpuResTwo, pr80Value);
11314 IEM_MC_PUSH_FPU_RESULT_TWO(FpuResTwo, pVCpu->iem.s.uFpuOpcode);
11315 } IEM_MC_ELSE() {
11316 IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO(pVCpu->iem.s.uFpuOpcode);
11317 } IEM_MC_ENDIF();
11318 IEM_MC_ADVANCE_RIP_AND_FINISH();
11319
11320 IEM_MC_END();
11321}
11322
11323
11324/** Opcode 0xd9 0xf2. */
11325FNIEMOP_DEF(iemOp_fptan)
11326{
11327 IEMOP_MNEMONIC(fptan_st0, "fptan st0");
11328 return FNIEMOP_CALL_1(iemOpHlpFpuReplace_st0_push, iemAImpl_fptan_r80_r80);
11329}
11330
11331
11332/** Opcode 0xd9 0xf3. */
11333FNIEMOP_DEF(iemOp_fpatan)
11334{
11335 IEMOP_MNEMONIC(fpatan_st1_st0, "fpatan st1,st0");
11336 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, 1, iemAImpl_fpatan_r80_by_r80);
11337}
11338
11339
11340/** Opcode 0xd9 0xf4. */
11341FNIEMOP_DEF(iemOp_fxtract)
11342{
11343 IEMOP_MNEMONIC(fxtract_st0, "fxtract st0");
11344 return FNIEMOP_CALL_1(iemOpHlpFpuReplace_st0_push, iemAImpl_fxtract_r80_r80);
11345}
11346
11347
11348/** Opcode 0xd9 0xf5. */
11349FNIEMOP_DEF(iemOp_fprem1)
11350{
11351 IEMOP_MNEMONIC(fprem1_st0_st1, "fprem1 st0,st1");
11352 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, 1, iemAImpl_fprem1_r80_by_r80);
11353}
11354
11355
11356/** Opcode 0xd9 0xf6. */
11357FNIEMOP_DEF(iemOp_fdecstp)
11358{
11359 IEMOP_MNEMONIC(fdecstp, "fdecstp");
11360 /* Note! C0, C2 and C3 are documented as undefined, we clear them. */
11361 /** @todo Testcase: Check whether FOP, FPUIP and FPUCS are affected by
11362 * FINCSTP and FDECSTP. */
11363 IEM_MC_BEGIN(0, 0, 0, 0);
11364 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11365
11366 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11367 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11368
11369 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
11370 IEM_MC_FPU_STACK_DEC_TOP();
11371 IEM_MC_UPDATE_FSW_CONST(0, pVCpu->iem.s.uFpuOpcode);
11372
11373 IEM_MC_ADVANCE_RIP_AND_FINISH();
11374 IEM_MC_END();
11375}
11376
11377
11378/** Opcode 0xd9 0xf7. */
11379FNIEMOP_DEF(iemOp_fincstp)
11380{
11381 IEMOP_MNEMONIC(fincstp, "fincstp");
11382 /* Note! C0, C2 and C3 are documented as undefined, we clear them. */
11383 /** @todo Testcase: Check whether FOP, FPUIP and FPUCS are affected by
11384 * FINCSTP and FDECSTP. */
11385 IEM_MC_BEGIN(0, 0, 0, 0);
11386 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11387
11388 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11389 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11390
11391 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
11392 IEM_MC_FPU_STACK_INC_TOP();
11393 IEM_MC_UPDATE_FSW_CONST(0, pVCpu->iem.s.uFpuOpcode);
11394
11395 IEM_MC_ADVANCE_RIP_AND_FINISH();
11396 IEM_MC_END();
11397}
11398
11399
11400/** Opcode 0xd9 0xf8. */
11401FNIEMOP_DEF(iemOp_fprem)
11402{
11403 IEMOP_MNEMONIC(fprem_st0_st1, "fprem st0,st1");
11404 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, 1, iemAImpl_fprem_r80_by_r80);
11405}
11406
11407
11408/** Opcode 0xd9 0xf9. */
11409FNIEMOP_DEF(iemOp_fyl2xp1)
11410{
11411 IEMOP_MNEMONIC(fyl2xp1_st1_st0, "fyl2xp1 st1,st0");
11412 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, 1, iemAImpl_fyl2xp1_r80_by_r80);
11413}
11414
11415
11416/** Opcode 0xd9 0xfa. */
11417FNIEMOP_DEF(iemOp_fsqrt)
11418{
11419 IEMOP_MNEMONIC(fsqrt_st0, "fsqrt st0");
11420 return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_fsqrt_r80);
11421}
11422
11423
11424/** Opcode 0xd9 0xfb. */
11425FNIEMOP_DEF(iemOp_fsincos)
11426{
11427 IEMOP_MNEMONIC(fsincos_st0, "fsincos st0");
11428 return FNIEMOP_CALL_1(iemOpHlpFpuReplace_st0_push, iemAImpl_fsincos_r80_r80);
11429}
11430
11431
11432/** Opcode 0xd9 0xfc. */
11433FNIEMOP_DEF(iemOp_frndint)
11434{
11435 IEMOP_MNEMONIC(frndint_st0, "frndint st0");
11436 return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_frndint_r80);
11437}
11438
11439
11440/** Opcode 0xd9 0xfd. */
11441FNIEMOP_DEF(iemOp_fscale)
11442{
11443 IEMOP_MNEMONIC(fscale_st0_st1, "fscale st0,st1");
11444 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, 1, iemAImpl_fscale_r80_by_r80);
11445}
11446
11447
11448/** Opcode 0xd9 0xfe. */
11449FNIEMOP_DEF(iemOp_fsin)
11450{
11451 IEMOP_MNEMONIC(fsin_st0, "fsin st0");
11452 return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_fsin_r80);
11453}
11454
11455
11456/** Opcode 0xd9 0xff. */
11457FNIEMOP_DEF(iemOp_fcos)
11458{
11459 IEMOP_MNEMONIC(fcos_st0, "fcos st0");
11460 return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_fcos_r80);
11461}
11462
11463
11464/** Used by iemOp_EscF1. */
11465IEM_STATIC const PFNIEMOP g_apfnEscF1_E0toFF[32] =
11466{
11467 /* 0xe0 */ iemOp_fchs,
11468 /* 0xe1 */ iemOp_fabs,
11469 /* 0xe2 */ iemOp_Invalid,
11470 /* 0xe3 */ iemOp_Invalid,
11471 /* 0xe4 */ iemOp_ftst,
11472 /* 0xe5 */ iemOp_fxam,
11473 /* 0xe6 */ iemOp_Invalid,
11474 /* 0xe7 */ iemOp_Invalid,
11475 /* 0xe8 */ iemOp_fld1,
11476 /* 0xe9 */ iemOp_fldl2t,
11477 /* 0xea */ iemOp_fldl2e,
11478 /* 0xeb */ iemOp_fldpi,
11479 /* 0xec */ iemOp_fldlg2,
11480 /* 0xed */ iemOp_fldln2,
11481 /* 0xee */ iemOp_fldz,
11482 /* 0xef */ iemOp_Invalid,
11483 /* 0xf0 */ iemOp_f2xm1,
11484 /* 0xf1 */ iemOp_fyl2x,
11485 /* 0xf2 */ iemOp_fptan,
11486 /* 0xf3 */ iemOp_fpatan,
11487 /* 0xf4 */ iemOp_fxtract,
11488 /* 0xf5 */ iemOp_fprem1,
11489 /* 0xf6 */ iemOp_fdecstp,
11490 /* 0xf7 */ iemOp_fincstp,
11491 /* 0xf8 */ iemOp_fprem,
11492 /* 0xf9 */ iemOp_fyl2xp1,
11493 /* 0xfa */ iemOp_fsqrt,
11494 /* 0xfb */ iemOp_fsincos,
11495 /* 0xfc */ iemOp_frndint,
11496 /* 0xfd */ iemOp_fscale,
11497 /* 0xfe */ iemOp_fsin,
11498 /* 0xff */ iemOp_fcos
11499};
11500
11501
11502/**
11503 * @opcode 0xd9
11504 */
11505FNIEMOP_DEF(iemOp_EscF1)
11506{
11507 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
11508 pVCpu->iem.s.uFpuOpcode = RT_MAKE_U16(bRm, 0xd9 & 0x7);
11509
11510 if (IEM_IS_MODRM_REG_MODE(bRm))
11511 {
11512 switch (IEM_GET_MODRM_REG_8(bRm))
11513 {
11514 case 0: return FNIEMOP_CALL_1(iemOp_fld_stN, bRm);
11515 case 1: return FNIEMOP_CALL_1(iemOp_fxch_stN, bRm);
11516 case 2:
11517 if (bRm == 0xd0)
11518 return FNIEMOP_CALL(iemOp_fnop);
11519 IEMOP_RAISE_INVALID_OPCODE_RET();
11520 case 3: return FNIEMOP_CALL_1(iemOp_fstp_stN, bRm); /* Reserved. Intel behavior seems to be FSTP ST(i) though. */
11521 case 4:
11522 case 5:
11523 case 6:
11524 case 7:
11525 Assert((unsigned)bRm - 0xe0U < RT_ELEMENTS(g_apfnEscF1_E0toFF));
11526 return FNIEMOP_CALL(g_apfnEscF1_E0toFF[bRm - 0xe0]);
11527 IEM_NOT_REACHED_DEFAULT_CASE_RET();
11528 }
11529 }
11530 else
11531 {
11532 switch (IEM_GET_MODRM_REG_8(bRm))
11533 {
11534 case 0: return FNIEMOP_CALL_1(iemOp_fld_m32r, bRm);
11535 case 1: IEMOP_RAISE_INVALID_OPCODE_RET();
11536 case 2: return FNIEMOP_CALL_1(iemOp_fst_m32r, bRm);
11537 case 3: return FNIEMOP_CALL_1(iemOp_fstp_m32r, bRm);
11538 case 4: return FNIEMOP_CALL_1(iemOp_fldenv, bRm);
11539 case 5: return FNIEMOP_CALL_1(iemOp_fldcw, bRm);
11540 case 6: return FNIEMOP_CALL_1(iemOp_fnstenv, bRm);
11541 case 7: return FNIEMOP_CALL_1(iemOp_fnstcw, bRm);
11542 IEM_NOT_REACHED_DEFAULT_CASE_RET();
11543 }
11544 }
11545}
11546
11547
11548/** Opcode 0xda 11/0. */
11549FNIEMOP_DEF_1(iemOp_fcmovb_stN, uint8_t, bRm)
11550{
11551 IEMOP_MNEMONIC(fcmovb_st0_stN, "fcmovb st0,stN");
11552 IEM_MC_BEGIN(0, 1, 0, 0);
11553 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11554 IEM_MC_LOCAL(PCRTFLOAT80U, pr80ValueN);
11555
11556 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11557 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11558
11559 IEM_MC_PREPARE_FPU_USAGE();
11560 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80_FIRST(pr80ValueN, IEM_GET_MODRM_RM_8(bRm), 0) {
11561 IEM_MC_IF_EFL_BIT_SET(X86_EFL_CF) {
11562 IEM_MC_STORE_FPUREG_R80_SRC_REF(0, pr80ValueN);
11563 } IEM_MC_ENDIF();
11564 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
11565 } IEM_MC_ELSE() {
11566 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
11567 } IEM_MC_ENDIF();
11568 IEM_MC_ADVANCE_RIP_AND_FINISH();
11569
11570 IEM_MC_END();
11571}
11572
11573
11574/** Opcode 0xda 11/1. */
11575FNIEMOP_DEF_1(iemOp_fcmove_stN, uint8_t, bRm)
11576{
11577 IEMOP_MNEMONIC(fcmove_st0_stN, "fcmove st0,stN");
11578 IEM_MC_BEGIN(0, 1, 0, 0);
11579 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11580 IEM_MC_LOCAL(PCRTFLOAT80U, pr80ValueN);
11581
11582 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11583 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11584
11585 IEM_MC_PREPARE_FPU_USAGE();
11586 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80_FIRST(pr80ValueN, IEM_GET_MODRM_RM_8(bRm), 0) {
11587 IEM_MC_IF_EFL_BIT_SET(X86_EFL_ZF) {
11588 IEM_MC_STORE_FPUREG_R80_SRC_REF(0, pr80ValueN);
11589 } IEM_MC_ENDIF();
11590 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
11591 } IEM_MC_ELSE() {
11592 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
11593 } IEM_MC_ENDIF();
11594 IEM_MC_ADVANCE_RIP_AND_FINISH();
11595
11596 IEM_MC_END();
11597}
11598
11599
11600/** Opcode 0xda 11/2. */
11601FNIEMOP_DEF_1(iemOp_fcmovbe_stN, uint8_t, bRm)
11602{
11603 IEMOP_MNEMONIC(fcmovbe_st0_stN, "fcmovbe st0,stN");
11604 IEM_MC_BEGIN(0, 1, 0, 0);
11605 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11606 IEM_MC_LOCAL(PCRTFLOAT80U, pr80ValueN);
11607
11608 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11609 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11610
11611 IEM_MC_PREPARE_FPU_USAGE();
11612 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80_FIRST(pr80ValueN, IEM_GET_MODRM_RM_8(bRm), 0) {
11613 IEM_MC_IF_EFL_ANY_BITS_SET(X86_EFL_CF | X86_EFL_ZF) {
11614 IEM_MC_STORE_FPUREG_R80_SRC_REF(0, pr80ValueN);
11615 } IEM_MC_ENDIF();
11616 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
11617 } IEM_MC_ELSE() {
11618 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
11619 } IEM_MC_ENDIF();
11620 IEM_MC_ADVANCE_RIP_AND_FINISH();
11621
11622 IEM_MC_END();
11623}
11624
11625
11626/** Opcode 0xda 11/3. */
11627FNIEMOP_DEF_1(iemOp_fcmovu_stN, uint8_t, bRm)
11628{
11629 IEMOP_MNEMONIC(fcmovu_st0_stN, "fcmovu st0,stN");
11630 IEM_MC_BEGIN(0, 1, 0, 0);
11631 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11632 IEM_MC_LOCAL(PCRTFLOAT80U, pr80ValueN);
11633
11634 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11635 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11636
11637 IEM_MC_PREPARE_FPU_USAGE();
11638 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80_FIRST(pr80ValueN, IEM_GET_MODRM_RM_8(bRm), 0) {
11639 IEM_MC_IF_EFL_BIT_SET(X86_EFL_PF) {
11640 IEM_MC_STORE_FPUREG_R80_SRC_REF(0, pr80ValueN);
11641 } IEM_MC_ENDIF();
11642 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
11643 } IEM_MC_ELSE() {
11644 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
11645 } IEM_MC_ENDIF();
11646 IEM_MC_ADVANCE_RIP_AND_FINISH();
11647
11648 IEM_MC_END();
11649}
11650
11651
11652/**
11653 * Common worker for FPU instructions working on ST0 and ST1, only affecting
11654 * flags, and popping twice when done.
11655 *
11656 * @param pfnAImpl Pointer to the instruction implementation (assembly).
11657 */
11658FNIEMOP_DEF_1(iemOpHlpFpuNoStore_st0_st1_pop_pop, PFNIEMAIMPLFPUR80FSW, pfnAImpl)
11659{
11660 IEM_MC_BEGIN(3, 1, 0, 0);
11661 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11662 IEM_MC_LOCAL(uint16_t, u16Fsw);
11663 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
11664 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
11665 IEM_MC_ARG(PCRTFLOAT80U, pr80Value2, 2);
11666
11667 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11668 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11669
11670 IEM_MC_PREPARE_FPU_USAGE();
11671 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, 0, pr80Value2, 1) {
11672 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pu16Fsw, pr80Value1, pr80Value2);
11673 IEM_MC_UPDATE_FSW_THEN_POP_POP(u16Fsw, pVCpu->iem.s.uFpuOpcode);
11674 } IEM_MC_ELSE() {
11675 IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP_POP(pVCpu->iem.s.uFpuOpcode);
11676 } IEM_MC_ENDIF();
11677 IEM_MC_ADVANCE_RIP_AND_FINISH();
11678
11679 IEM_MC_END();
11680}
11681
11682
11683/** Opcode 0xda 0xe9. */
11684FNIEMOP_DEF(iemOp_fucompp)
11685{
11686 IEMOP_MNEMONIC(fucompp, "fucompp");
11687 return FNIEMOP_CALL_1(iemOpHlpFpuNoStore_st0_st1_pop_pop, iemAImpl_fucom_r80_by_r80);
11688}
11689
11690
11691/**
11692 * Common worker for FPU instructions working on ST0 and an m32i, and storing
11693 * the result in ST0.
11694 *
11695 * @param bRm Mod R/M byte.
11696 * @param pfnAImpl Pointer to the instruction implementation (assembly).
11697 */
11698FNIEMOP_DEF_2(iemOpHlpFpu_st0_m32i, uint8_t, bRm, PFNIEMAIMPLFPUI32, pfnAImpl)
11699{
11700 IEM_MC_BEGIN(3, 3, 0, 0);
11701 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
11702 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
11703 IEM_MC_LOCAL(int32_t, i32Val2);
11704 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
11705 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
11706 IEM_MC_ARG_LOCAL_REF(int32_t const *, pi32Val2, i32Val2, 2);
11707
11708 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
11709 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11710
11711 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11712 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11713 IEM_MC_FETCH_MEM_I32(i32Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
11714
11715 IEM_MC_PREPARE_FPU_USAGE();
11716 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
11717 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pi32Val2);
11718 IEM_MC_STORE_FPU_RESULT(FpuRes, 0, pVCpu->iem.s.uFpuOpcode);
11719 } IEM_MC_ELSE() {
11720 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
11721 } IEM_MC_ENDIF();
11722 IEM_MC_ADVANCE_RIP_AND_FINISH();
11723
11724 IEM_MC_END();
11725}
11726
11727
11728/** Opcode 0xda !11/0. */
11729FNIEMOP_DEF_1(iemOp_fiadd_m32i, uint8_t, bRm)
11730{
11731 IEMOP_MNEMONIC(fiadd_m32i, "fiadd m32i");
11732 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32i, bRm, iemAImpl_fiadd_r80_by_i32);
11733}
11734
11735
11736/** Opcode 0xda !11/1. */
11737FNIEMOP_DEF_1(iemOp_fimul_m32i, uint8_t, bRm)
11738{
11739 IEMOP_MNEMONIC(fimul_m32i, "fimul m32i");
11740 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32i, bRm, iemAImpl_fimul_r80_by_i32);
11741}
11742
11743
11744/** Opcode 0xda !11/2. */
11745FNIEMOP_DEF_1(iemOp_ficom_m32i, uint8_t, bRm)
11746{
11747 IEMOP_MNEMONIC(ficom_st0_m32i, "ficom st0,m32i");
11748
11749 IEM_MC_BEGIN(3, 3, 0, 0);
11750 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
11751 IEM_MC_LOCAL(uint16_t, u16Fsw);
11752 IEM_MC_LOCAL(int32_t, i32Val2);
11753 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
11754 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
11755 IEM_MC_ARG_LOCAL_REF(int32_t const *, pi32Val2, i32Val2, 2);
11756
11757 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
11758 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11759
11760 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11761 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11762 IEM_MC_FETCH_MEM_I32(i32Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
11763
11764 IEM_MC_PREPARE_FPU_USAGE();
11765 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
11766 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_ficom_r80_by_i32, pu16Fsw, pr80Value1, pi32Val2);
11767 IEM_MC_UPDATE_FSW_WITH_MEM_OP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
11768 } IEM_MC_ELSE() {
11769 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
11770 } IEM_MC_ENDIF();
11771 IEM_MC_ADVANCE_RIP_AND_FINISH();
11772
11773 IEM_MC_END();
11774}
11775
11776
11777/** Opcode 0xda !11/3. */
11778FNIEMOP_DEF_1(iemOp_ficomp_m32i, uint8_t, bRm)
11779{
11780 IEMOP_MNEMONIC(ficomp_st0_m32i, "ficomp st0,m32i");
11781
11782 IEM_MC_BEGIN(3, 3, 0, 0);
11783 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
11784 IEM_MC_LOCAL(uint16_t, u16Fsw);
11785 IEM_MC_LOCAL(int32_t, i32Val2);
11786 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
11787 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
11788 IEM_MC_ARG_LOCAL_REF(int32_t const *, pi32Val2, i32Val2, 2);
11789
11790 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
11791 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11792
11793 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11794 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11795 IEM_MC_FETCH_MEM_I32(i32Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
11796
11797 IEM_MC_PREPARE_FPU_USAGE();
11798 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
11799 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_ficom_r80_by_i32, pu16Fsw, pr80Value1, pi32Val2);
11800 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
11801 } IEM_MC_ELSE() {
11802 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
11803 } IEM_MC_ENDIF();
11804 IEM_MC_ADVANCE_RIP_AND_FINISH();
11805
11806 IEM_MC_END();
11807}
11808
11809
11810/** Opcode 0xda !11/4. */
11811FNIEMOP_DEF_1(iemOp_fisub_m32i, uint8_t, bRm)
11812{
11813 IEMOP_MNEMONIC(fisub_m32i, "fisub m32i");
11814 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32i, bRm, iemAImpl_fisub_r80_by_i32);
11815}
11816
11817
11818/** Opcode 0xda !11/5. */
11819FNIEMOP_DEF_1(iemOp_fisubr_m32i, uint8_t, bRm)
11820{
11821 IEMOP_MNEMONIC(fisubr_m32i, "fisubr m32i");
11822 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32i, bRm, iemAImpl_fisubr_r80_by_i32);
11823}
11824
11825
11826/** Opcode 0xda !11/6. */
11827FNIEMOP_DEF_1(iemOp_fidiv_m32i, uint8_t, bRm)
11828{
11829 IEMOP_MNEMONIC(fidiv_m32i, "fidiv m32i");
11830 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32i, bRm, iemAImpl_fidiv_r80_by_i32);
11831}
11832
11833
11834/** Opcode 0xda !11/7. */
11835FNIEMOP_DEF_1(iemOp_fidivr_m32i, uint8_t, bRm)
11836{
11837 IEMOP_MNEMONIC(fidivr_m32i, "fidivr m32i");
11838 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m32i, bRm, iemAImpl_fidivr_r80_by_i32);
11839}
11840
11841
11842/**
11843 * @opcode 0xda
11844 */
11845FNIEMOP_DEF(iemOp_EscF2)
11846{
11847 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
11848 pVCpu->iem.s.uFpuOpcode = RT_MAKE_U16(bRm, 0xda & 0x7);
11849 if (IEM_IS_MODRM_REG_MODE(bRm))
11850 {
11851 switch (IEM_GET_MODRM_REG_8(bRm))
11852 {
11853 case 0: return FNIEMOP_CALL_1(iemOp_fcmovb_stN, bRm);
11854 case 1: return FNIEMOP_CALL_1(iemOp_fcmove_stN, bRm);
11855 case 2: return FNIEMOP_CALL_1(iemOp_fcmovbe_stN, bRm);
11856 case 3: return FNIEMOP_CALL_1(iemOp_fcmovu_stN, bRm);
11857 case 4: IEMOP_RAISE_INVALID_OPCODE_RET();
11858 case 5:
11859 if (bRm == 0xe9)
11860 return FNIEMOP_CALL(iemOp_fucompp);
11861 IEMOP_RAISE_INVALID_OPCODE_RET();
11862 case 6: IEMOP_RAISE_INVALID_OPCODE_RET();
11863 case 7: IEMOP_RAISE_INVALID_OPCODE_RET();
11864 IEM_NOT_REACHED_DEFAULT_CASE_RET();
11865 }
11866 }
11867 else
11868 {
11869 switch (IEM_GET_MODRM_REG_8(bRm))
11870 {
11871 case 0: return FNIEMOP_CALL_1(iemOp_fiadd_m32i, bRm);
11872 case 1: return FNIEMOP_CALL_1(iemOp_fimul_m32i, bRm);
11873 case 2: return FNIEMOP_CALL_1(iemOp_ficom_m32i, bRm);
11874 case 3: return FNIEMOP_CALL_1(iemOp_ficomp_m32i, bRm);
11875 case 4: return FNIEMOP_CALL_1(iemOp_fisub_m32i, bRm);
11876 case 5: return FNIEMOP_CALL_1(iemOp_fisubr_m32i, bRm);
11877 case 6: return FNIEMOP_CALL_1(iemOp_fidiv_m32i, bRm);
11878 case 7: return FNIEMOP_CALL_1(iemOp_fidivr_m32i, bRm);
11879 IEM_NOT_REACHED_DEFAULT_CASE_RET();
11880 }
11881 }
11882}
11883
11884
11885/** Opcode 0xdb !11/0. */
11886FNIEMOP_DEF_1(iemOp_fild_m32i, uint8_t, bRm)
11887{
11888 IEMOP_MNEMONIC(fild_m32i, "fild m32i");
11889
11890 IEM_MC_BEGIN(2, 3, 0, 0);
11891 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
11892 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
11893 IEM_MC_LOCAL(int32_t, i32Val);
11894 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
11895 IEM_MC_ARG_LOCAL_REF(int32_t const *, pi32Val, i32Val, 1);
11896
11897 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
11898 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11899
11900 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11901 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11902 IEM_MC_FETCH_MEM_I32(i32Val, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
11903
11904 IEM_MC_PREPARE_FPU_USAGE();
11905 IEM_MC_IF_FPUREG_IS_EMPTY(7) {
11906 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fild_r80_from_i32, pFpuRes, pi32Val);
11907 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
11908 } IEM_MC_ELSE() {
11909 IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
11910 } IEM_MC_ENDIF();
11911 IEM_MC_ADVANCE_RIP_AND_FINISH();
11912
11913 IEM_MC_END();
11914}
11915
11916
11917/** Opcode 0xdb !11/1. */
11918FNIEMOP_DEF_1(iemOp_fisttp_m32i, uint8_t, bRm)
11919{
11920 IEMOP_MNEMONIC(fisttp_m32i, "fisttp m32i");
11921 IEM_MC_BEGIN(3, 3, 0, 0);
11922 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
11923 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
11924
11925 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11926 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11927 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11928 IEM_MC_PREPARE_FPU_USAGE();
11929
11930 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
11931 IEM_MC_ARG(int32_t *, pi32Dst, 1);
11932 IEM_MC_MEM_MAP_I32_WO(pi32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
11933
11934 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
11935 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
11936 IEM_MC_LOCAL(uint16_t, u16Fsw);
11937 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
11938 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fistt_r80_to_i32, pu16Fsw, pi32Dst, pr80Value);
11939 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
11940 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
11941 } IEM_MC_ELSE() {
11942 IEM_MC_IF_FCW_IM() {
11943 IEM_MC_STORE_MEM_I32_CONST_BY_REF(pi32Dst, INT32_MIN /* (integer indefinite) */);
11944 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
11945 } IEM_MC_ELSE() {
11946 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
11947 } IEM_MC_ENDIF();
11948 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
11949 } IEM_MC_ENDIF();
11950 IEM_MC_ADVANCE_RIP_AND_FINISH();
11951
11952 IEM_MC_END();
11953}
11954
11955
11956/** Opcode 0xdb !11/2. */
11957FNIEMOP_DEF_1(iemOp_fist_m32i, uint8_t, bRm)
11958{
11959 IEMOP_MNEMONIC(fist_m32i, "fist m32i");
11960 IEM_MC_BEGIN(3, 3, 0, 0);
11961 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
11962 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
11963
11964 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
11965 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
11966 IEM_MC_MAYBE_RAISE_FPU_XCPT();
11967 IEM_MC_PREPARE_FPU_USAGE();
11968
11969 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
11970 IEM_MC_ARG(int32_t *, pi32Dst, 1);
11971 IEM_MC_MEM_MAP_I32_WO(pi32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
11972
11973 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
11974 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
11975 IEM_MC_LOCAL(uint16_t, u16Fsw);
11976 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
11977 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fist_r80_to_i32, pu16Fsw, pi32Dst, pr80Value);
11978 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
11979 IEM_MC_UPDATE_FSW_WITH_MEM_OP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
11980 } IEM_MC_ELSE() {
11981 IEM_MC_IF_FCW_IM() {
11982 IEM_MC_STORE_MEM_I32_CONST_BY_REF(pi32Dst, INT32_MIN /* (integer indefinite) */);
11983 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
11984 } IEM_MC_ELSE() {
11985 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
11986 } IEM_MC_ENDIF();
11987 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
11988 } IEM_MC_ENDIF();
11989 IEM_MC_ADVANCE_RIP_AND_FINISH();
11990
11991 IEM_MC_END();
11992}
11993
11994
11995/** Opcode 0xdb !11/3. */
11996FNIEMOP_DEF_1(iemOp_fistp_m32i, uint8_t, bRm)
11997{
11998 IEMOP_MNEMONIC(fistp_m32i, "fistp m32i");
11999 IEM_MC_BEGIN(3, 2, 0, 0);
12000 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
12001 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
12002
12003 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12004 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12005 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12006 IEM_MC_PREPARE_FPU_USAGE();
12007
12008 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
12009 IEM_MC_ARG(int32_t *, pi32Dst, 1);
12010 IEM_MC_MEM_MAP_I32_WO(pi32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
12011
12012 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
12013 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
12014 IEM_MC_LOCAL(uint16_t, u16Fsw);
12015 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
12016 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fist_r80_to_i32, pu16Fsw, pi32Dst, pr80Value);
12017 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
12018 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12019 } IEM_MC_ELSE() {
12020 IEM_MC_IF_FCW_IM() {
12021 IEM_MC_STORE_MEM_I32_CONST_BY_REF(pi32Dst, INT32_MIN /* (integer indefinite) */);
12022 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
12023 } IEM_MC_ELSE() {
12024 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
12025 } IEM_MC_ENDIF();
12026 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12027 } IEM_MC_ENDIF();
12028 IEM_MC_ADVANCE_RIP_AND_FINISH();
12029
12030 IEM_MC_END();
12031}
12032
12033
12034/** Opcode 0xdb !11/5. */
12035FNIEMOP_DEF_1(iemOp_fld_m80r, uint8_t, bRm)
12036{
12037 IEMOP_MNEMONIC(fld_m80r, "fld m80r");
12038
12039 IEM_MC_BEGIN(2, 3, 0, 0);
12040 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
12041 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
12042 IEM_MC_LOCAL(RTFLOAT80U, r80Val);
12043 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
12044 IEM_MC_ARG_LOCAL_REF(PCRTFLOAT80U, pr80Val, r80Val, 1);
12045
12046 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
12047 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12048
12049 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12050 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12051 IEM_MC_FETCH_MEM_R80(r80Val, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
12052
12053 IEM_MC_PREPARE_FPU_USAGE();
12054 IEM_MC_IF_FPUREG_IS_EMPTY(7) {
12055 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fld_r80_from_r80, pFpuRes, pr80Val);
12056 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12057 } IEM_MC_ELSE() {
12058 IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12059 } IEM_MC_ENDIF();
12060 IEM_MC_ADVANCE_RIP_AND_FINISH();
12061
12062 IEM_MC_END();
12063}
12064
12065
12066/** Opcode 0xdb !11/7. */
12067FNIEMOP_DEF_1(iemOp_fstp_m80r, uint8_t, bRm)
12068{
12069 IEMOP_MNEMONIC(fstp_m80r, "fstp m80r");
12070 IEM_MC_BEGIN(3, 3, 0, 0);
12071 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
12072 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
12073
12074 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12075 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12076 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12077 IEM_MC_PREPARE_FPU_USAGE();
12078
12079 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
12080 IEM_MC_ARG(PRTFLOAT80U, pr80Dst, 1);
12081 IEM_MC_MEM_MAP_R80_WO(pr80Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
12082
12083 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
12084 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
12085 IEM_MC_LOCAL(uint16_t, u16Fsw);
12086 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
12087 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fst_r80_to_r80, pu16Fsw, pr80Dst, pr80Value);
12088 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
12089 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12090 } IEM_MC_ELSE() {
12091 IEM_MC_IF_FCW_IM() {
12092 IEM_MC_STORE_MEM_NEG_QNAN_R80_BY_REF(pr80Dst);
12093 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
12094 } IEM_MC_ELSE() {
12095 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
12096 } IEM_MC_ENDIF();
12097 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12098 } IEM_MC_ENDIF();
12099 IEM_MC_ADVANCE_RIP_AND_FINISH();
12100
12101 IEM_MC_END();
12102}
12103
12104
12105/** Opcode 0xdb 11/0. */
12106FNIEMOP_DEF_1(iemOp_fcmovnb_stN, uint8_t, bRm)
12107{
12108 IEMOP_MNEMONIC(fcmovnb_st0_stN, "fcmovnb st0,stN");
12109 IEM_MC_BEGIN(0, 1, 0, 0);
12110 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12111 IEM_MC_LOCAL(PCRTFLOAT80U, pr80ValueN);
12112
12113 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12114 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12115
12116 IEM_MC_PREPARE_FPU_USAGE();
12117 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80_FIRST(pr80ValueN, IEM_GET_MODRM_RM_8(bRm), 0) {
12118 IEM_MC_IF_EFL_BIT_NOT_SET(X86_EFL_CF) {
12119 IEM_MC_STORE_FPUREG_R80_SRC_REF(0, pr80ValueN);
12120 } IEM_MC_ENDIF();
12121 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
12122 } IEM_MC_ELSE() {
12123 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
12124 } IEM_MC_ENDIF();
12125 IEM_MC_ADVANCE_RIP_AND_FINISH();
12126
12127 IEM_MC_END();
12128}
12129
12130
12131/** Opcode 0xdb 11/1. */
12132FNIEMOP_DEF_1(iemOp_fcmovne_stN, uint8_t, bRm)
12133{
12134 IEMOP_MNEMONIC(fcmovne_st0_stN, "fcmovne st0,stN");
12135 IEM_MC_BEGIN(0, 1, 0, 0);
12136 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12137 IEM_MC_LOCAL(PCRTFLOAT80U, pr80ValueN);
12138
12139 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12140 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12141
12142 IEM_MC_PREPARE_FPU_USAGE();
12143 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80_FIRST(pr80ValueN, IEM_GET_MODRM_RM_8(bRm), 0) {
12144 IEM_MC_IF_EFL_BIT_NOT_SET(X86_EFL_ZF) {
12145 IEM_MC_STORE_FPUREG_R80_SRC_REF(0, pr80ValueN);
12146 } IEM_MC_ENDIF();
12147 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
12148 } IEM_MC_ELSE() {
12149 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
12150 } IEM_MC_ENDIF();
12151 IEM_MC_ADVANCE_RIP_AND_FINISH();
12152
12153 IEM_MC_END();
12154}
12155
12156
12157/** Opcode 0xdb 11/2. */
12158FNIEMOP_DEF_1(iemOp_fcmovnbe_stN, uint8_t, bRm)
12159{
12160 IEMOP_MNEMONIC(fcmovnbe_st0_stN, "fcmovnbe st0,stN");
12161 IEM_MC_BEGIN(0, 1, 0, 0);
12162 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12163 IEM_MC_LOCAL(PCRTFLOAT80U, pr80ValueN);
12164
12165 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12166 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12167
12168 IEM_MC_PREPARE_FPU_USAGE();
12169 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80_FIRST(pr80ValueN, IEM_GET_MODRM_RM_8(bRm), 0) {
12170 IEM_MC_IF_EFL_NO_BITS_SET(X86_EFL_CF | X86_EFL_ZF) {
12171 IEM_MC_STORE_FPUREG_R80_SRC_REF(0, pr80ValueN);
12172 } IEM_MC_ENDIF();
12173 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
12174 } IEM_MC_ELSE() {
12175 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
12176 } IEM_MC_ENDIF();
12177 IEM_MC_ADVANCE_RIP_AND_FINISH();
12178
12179 IEM_MC_END();
12180}
12181
12182
12183/** Opcode 0xdb 11/3. */
12184FNIEMOP_DEF_1(iemOp_fcmovnnu_stN, uint8_t, bRm)
12185{
12186 IEMOP_MNEMONIC(fcmovnnu_st0_stN, "fcmovnnu st0,stN");
12187 IEM_MC_BEGIN(0, 1, 0, 0);
12188 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12189 IEM_MC_LOCAL(PCRTFLOAT80U, pr80ValueN);
12190
12191 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12192 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12193
12194 IEM_MC_PREPARE_FPU_USAGE();
12195 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80_FIRST(pr80ValueN, IEM_GET_MODRM_RM_8(bRm), 0) {
12196 IEM_MC_IF_EFL_BIT_NOT_SET(X86_EFL_PF) {
12197 IEM_MC_STORE_FPUREG_R80_SRC_REF(0, pr80ValueN);
12198 } IEM_MC_ENDIF();
12199 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
12200 } IEM_MC_ELSE() {
12201 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
12202 } IEM_MC_ENDIF();
12203 IEM_MC_ADVANCE_RIP_AND_FINISH();
12204
12205 IEM_MC_END();
12206}
12207
12208
12209/** Opcode 0xdb 0xe0. */
12210FNIEMOP_DEF(iemOp_fneni)
12211{
12212 IEMOP_MNEMONIC(fneni, "fneni (8087/ign)");
12213 IEM_MC_BEGIN(0, 0, 0, 0);
12214 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12215 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12216 IEM_MC_ADVANCE_RIP_AND_FINISH();
12217 IEM_MC_END();
12218}
12219
12220
12221/** Opcode 0xdb 0xe1. */
12222FNIEMOP_DEF(iemOp_fndisi)
12223{
12224 IEMOP_MNEMONIC(fndisi, "fndisi (8087/ign)");
12225 IEM_MC_BEGIN(0, 0, 0, 0);
12226 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12227 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12228 IEM_MC_ADVANCE_RIP_AND_FINISH();
12229 IEM_MC_END();
12230}
12231
12232
12233/** Opcode 0xdb 0xe2. */
12234FNIEMOP_DEF(iemOp_fnclex)
12235{
12236 IEMOP_MNEMONIC(fnclex, "fnclex");
12237 IEM_MC_BEGIN(0, 0, 0, 0);
12238 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12239 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12240 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
12241 IEM_MC_CLEAR_FSW_EX();
12242 IEM_MC_ADVANCE_RIP_AND_FINISH();
12243 IEM_MC_END();
12244}
12245
12246
12247/** Opcode 0xdb 0xe3. */
12248FNIEMOP_DEF(iemOp_fninit)
12249{
12250 IEMOP_MNEMONIC(fninit, "fninit");
12251 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12252 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_FPU, RT_BIT_64(kIemNativeGstReg_FpuFcw) | RT_BIT_64(kIemNativeGstReg_FpuFsw),
12253 iemCImpl_finit, false /*fCheckXcpts*/);
12254}
12255
12256
12257/** Opcode 0xdb 0xe4. */
12258FNIEMOP_DEF(iemOp_fnsetpm)
12259{
12260 IEMOP_MNEMONIC(fnsetpm, "fnsetpm (80287/ign)"); /* set protected mode on fpu. */
12261 IEM_MC_BEGIN(0, 0, 0, 0);
12262 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12263 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12264 IEM_MC_ADVANCE_RIP_AND_FINISH();
12265 IEM_MC_END();
12266}
12267
12268
12269/** Opcode 0xdb 0xe5. */
12270FNIEMOP_DEF(iemOp_frstpm)
12271{
12272 IEMOP_MNEMONIC(frstpm, "frstpm (80287XL/ign)"); /* reset pm, back to real mode. */
12273#if 0 /* #UDs on newer CPUs */
12274 IEM_MC_BEGIN(0, 0, 0, 0);
12275 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12276 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12277 IEM_MC_ADVANCE_RIP_AND_FINISH();
12278 IEM_MC_END();
12279 return VINF_SUCCESS;
12280#else
12281 IEMOP_RAISE_INVALID_OPCODE_RET();
12282#endif
12283}
12284
12285
12286/** Opcode 0xdb 11/5. */
12287FNIEMOP_DEF_1(iemOp_fucomi_stN, uint8_t, bRm)
12288{
12289 IEMOP_MNEMONIC(fucomi_st0_stN, "fucomi st0,stN");
12290 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS, 0,
12291 iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), true /*fUCmp*/,
12292 0 /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
12293}
12294
12295
12296/** Opcode 0xdb 11/6. */
12297FNIEMOP_DEF_1(iemOp_fcomi_stN, uint8_t, bRm)
12298{
12299 IEMOP_MNEMONIC(fcomi_st0_stN, "fcomi st0,stN");
12300 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS, 0,
12301 iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), false /*fUCmp*/,
12302 false /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
12303}
12304
12305
12306/**
12307 * @opcode 0xdb
12308 */
12309FNIEMOP_DEF(iemOp_EscF3)
12310{
12311 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
12312 pVCpu->iem.s.uFpuOpcode = RT_MAKE_U16(bRm, 0xdb & 0x7);
12313 if (IEM_IS_MODRM_REG_MODE(bRm))
12314 {
12315 switch (IEM_GET_MODRM_REG_8(bRm))
12316 {
12317 case 0: return FNIEMOP_CALL_1(iemOp_fcmovnb_stN, bRm);
12318 case 1: return FNIEMOP_CALL_1(iemOp_fcmovne_stN, bRm);
12319 case 2: return FNIEMOP_CALL_1(iemOp_fcmovnbe_stN, bRm);
12320 case 3: return FNIEMOP_CALL_1(iemOp_fcmovnnu_stN, bRm);
12321 case 4:
12322 switch (bRm)
12323 {
12324 case 0xe0: return FNIEMOP_CALL(iemOp_fneni);
12325 case 0xe1: return FNIEMOP_CALL(iemOp_fndisi);
12326 case 0xe2: return FNIEMOP_CALL(iemOp_fnclex);
12327 case 0xe3: return FNIEMOP_CALL(iemOp_fninit);
12328 case 0xe4: return FNIEMOP_CALL(iemOp_fnsetpm);
12329 case 0xe5: return FNIEMOP_CALL(iemOp_frstpm);
12330 case 0xe6: IEMOP_RAISE_INVALID_OPCODE_RET();
12331 case 0xe7: IEMOP_RAISE_INVALID_OPCODE_RET();
12332 IEM_NOT_REACHED_DEFAULT_CASE_RET();
12333 }
12334 break;
12335 case 5: return FNIEMOP_CALL_1(iemOp_fucomi_stN, bRm);
12336 case 6: return FNIEMOP_CALL_1(iemOp_fcomi_stN, bRm);
12337 case 7: IEMOP_RAISE_INVALID_OPCODE_RET();
12338 IEM_NOT_REACHED_DEFAULT_CASE_RET();
12339 }
12340 }
12341 else
12342 {
12343 switch (IEM_GET_MODRM_REG_8(bRm))
12344 {
12345 case 0: return FNIEMOP_CALL_1(iemOp_fild_m32i, bRm);
12346 case 1: return FNIEMOP_CALL_1(iemOp_fisttp_m32i,bRm);
12347 case 2: return FNIEMOP_CALL_1(iemOp_fist_m32i, bRm);
12348 case 3: return FNIEMOP_CALL_1(iemOp_fistp_m32i, bRm);
12349 case 4: IEMOP_RAISE_INVALID_OPCODE_RET();
12350 case 5: return FNIEMOP_CALL_1(iemOp_fld_m80r, bRm);
12351 case 6: IEMOP_RAISE_INVALID_OPCODE_RET();
12352 case 7: return FNIEMOP_CALL_1(iemOp_fstp_m80r, bRm);
12353 IEM_NOT_REACHED_DEFAULT_CASE_RET();
12354 }
12355 }
12356}
12357
12358
12359/**
12360 * Common worker for FPU instructions working on STn and ST0, and storing the
12361 * result in STn unless IE, DE or ZE was raised.
12362 *
12363 * @param bRm Mod R/M byte.
12364 * @param pfnAImpl Pointer to the instruction implementation (assembly).
12365 */
12366FNIEMOP_DEF_2(iemOpHlpFpu_stN_st0, uint8_t, bRm, PFNIEMAIMPLFPUR80, pfnAImpl)
12367{
12368 IEM_MC_BEGIN(3, 1, 0, 0);
12369 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12370 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
12371 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
12372 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
12373 IEM_MC_ARG(PCRTFLOAT80U, pr80Value2, 2);
12374
12375 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12376 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12377
12378 IEM_MC_PREPARE_FPU_USAGE();
12379 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, IEM_GET_MODRM_RM_8(bRm), pr80Value2, 0) {
12380 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pr80Value2);
12381 IEM_MC_STORE_FPU_RESULT(FpuRes, IEM_GET_MODRM_RM_8(bRm), pVCpu->iem.s.uFpuOpcode);
12382 } IEM_MC_ELSE() {
12383 IEM_MC_FPU_STACK_UNDERFLOW(IEM_GET_MODRM_RM_8(bRm), pVCpu->iem.s.uFpuOpcode);
12384 } IEM_MC_ENDIF();
12385 IEM_MC_ADVANCE_RIP_AND_FINISH();
12386
12387 IEM_MC_END();
12388}
12389
12390
12391/** Opcode 0xdc 11/0. */
12392FNIEMOP_DEF_1(iemOp_fadd_stN_st0, uint8_t, bRm)
12393{
12394 IEMOP_MNEMONIC(fadd_stN_st0, "fadd stN,st0");
12395 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0, bRm, iemAImpl_fadd_r80_by_r80);
12396}
12397
12398
12399/** Opcode 0xdc 11/1. */
12400FNIEMOP_DEF_1(iemOp_fmul_stN_st0, uint8_t, bRm)
12401{
12402 IEMOP_MNEMONIC(fmul_stN_st0, "fmul stN,st0");
12403 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0, bRm, iemAImpl_fmul_r80_by_r80);
12404}
12405
12406
12407/** Opcode 0xdc 11/4. */
12408FNIEMOP_DEF_1(iemOp_fsubr_stN_st0, uint8_t, bRm)
12409{
12410 IEMOP_MNEMONIC(fsubr_stN_st0, "fsubr stN,st0");
12411 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0, bRm, iemAImpl_fsubr_r80_by_r80);
12412}
12413
12414
12415/** Opcode 0xdc 11/5. */
12416FNIEMOP_DEF_1(iemOp_fsub_stN_st0, uint8_t, bRm)
12417{
12418 IEMOP_MNEMONIC(fsub_stN_st0, "fsub stN,st0");
12419 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0, bRm, iemAImpl_fsub_r80_by_r80);
12420}
12421
12422
12423/** Opcode 0xdc 11/6. */
12424FNIEMOP_DEF_1(iemOp_fdivr_stN_st0, uint8_t, bRm)
12425{
12426 IEMOP_MNEMONIC(fdivr_stN_st0, "fdivr stN,st0");
12427 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0, bRm, iemAImpl_fdivr_r80_by_r80);
12428}
12429
12430
12431/** Opcode 0xdc 11/7. */
12432FNIEMOP_DEF_1(iemOp_fdiv_stN_st0, uint8_t, bRm)
12433{
12434 IEMOP_MNEMONIC(fdiv_stN_st0, "fdiv stN,st0");
12435 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0, bRm, iemAImpl_fdiv_r80_by_r80);
12436}
12437
12438
12439/**
12440 * Common worker for FPU instructions working on ST0 and a 64-bit floating point
12441 * memory operand, and storing the result in ST0.
12442 *
12443 * @param bRm Mod R/M byte.
12444 * @param pfnImpl Pointer to the instruction implementation (assembly).
12445 */
12446FNIEMOP_DEF_2(iemOpHlpFpu_ST0_m64r, uint8_t, bRm, PFNIEMAIMPLFPUR64, pfnImpl)
12447{
12448 IEM_MC_BEGIN(3, 3, 0, 0);
12449 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
12450 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
12451 IEM_MC_LOCAL(RTFLOAT64U, r64Factor2);
12452 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
12453 IEM_MC_ARG(PCRTFLOAT80U, pr80Factor1, 1);
12454 IEM_MC_ARG_LOCAL_REF(PRTFLOAT64U, pr64Factor2, r64Factor2, 2);
12455
12456 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
12457 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12458 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12459 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12460
12461 IEM_MC_FETCH_MEM_R64(r64Factor2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
12462 IEM_MC_PREPARE_FPU_USAGE();
12463 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Factor1, 0) {
12464 IEM_MC_CALL_FPU_AIMPL_3(pfnImpl, pFpuRes, pr80Factor1, pr64Factor2);
12465 IEM_MC_STORE_FPU_RESULT_MEM_OP(FpuRes, 0, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12466 } IEM_MC_ELSE() {
12467 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(0, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12468 } IEM_MC_ENDIF();
12469 IEM_MC_ADVANCE_RIP_AND_FINISH();
12470
12471 IEM_MC_END();
12472}
12473
12474
12475/** Opcode 0xdc !11/0. */
12476FNIEMOP_DEF_1(iemOp_fadd_m64r, uint8_t, bRm)
12477{
12478 IEMOP_MNEMONIC(fadd_m64r, "fadd m64r");
12479 return FNIEMOP_CALL_2(iemOpHlpFpu_ST0_m64r, bRm, iemAImpl_fadd_r80_by_r64);
12480}
12481
12482
12483/** Opcode 0xdc !11/1. */
12484FNIEMOP_DEF_1(iemOp_fmul_m64r, uint8_t, bRm)
12485{
12486 IEMOP_MNEMONIC(fmul_m64r, "fmul m64r");
12487 return FNIEMOP_CALL_2(iemOpHlpFpu_ST0_m64r, bRm, iemAImpl_fmul_r80_by_r64);
12488}
12489
12490
12491/** Opcode 0xdc !11/2. */
12492FNIEMOP_DEF_1(iemOp_fcom_m64r, uint8_t, bRm)
12493{
12494 IEMOP_MNEMONIC(fcom_st0_m64r, "fcom st0,m64r");
12495
12496 IEM_MC_BEGIN(3, 3, 0, 0);
12497 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
12498 IEM_MC_LOCAL(uint16_t, u16Fsw);
12499 IEM_MC_LOCAL(RTFLOAT64U, r64Val2);
12500 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
12501 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
12502 IEM_MC_ARG_LOCAL_REF(PCRTFLOAT64U, pr64Val2, r64Val2, 2);
12503
12504 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
12505 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12506
12507 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12508 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12509 IEM_MC_FETCH_MEM_R64(r64Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
12510
12511 IEM_MC_PREPARE_FPU_USAGE();
12512 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
12513 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fcom_r80_by_r64, pu16Fsw, pr80Value1, pr64Val2);
12514 IEM_MC_UPDATE_FSW_WITH_MEM_OP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12515 } IEM_MC_ELSE() {
12516 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12517 } IEM_MC_ENDIF();
12518 IEM_MC_ADVANCE_RIP_AND_FINISH();
12519
12520 IEM_MC_END();
12521}
12522
12523
12524/** Opcode 0xdc !11/3. */
12525FNIEMOP_DEF_1(iemOp_fcomp_m64r, uint8_t, bRm)
12526{
12527 IEMOP_MNEMONIC(fcomp_st0_m64r, "fcomp st0,m64r");
12528
12529 IEM_MC_BEGIN(3, 3, 0, 0);
12530 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
12531 IEM_MC_LOCAL(uint16_t, u16Fsw);
12532 IEM_MC_LOCAL(RTFLOAT64U, r64Val2);
12533 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
12534 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
12535 IEM_MC_ARG_LOCAL_REF(PCRTFLOAT64U, pr64Val2, r64Val2, 2);
12536
12537 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
12538 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12539
12540 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12541 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12542 IEM_MC_FETCH_MEM_R64(r64Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
12543
12544 IEM_MC_PREPARE_FPU_USAGE();
12545 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
12546 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fcom_r80_by_r64, pu16Fsw, pr80Value1, pr64Val2);
12547 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12548 } IEM_MC_ELSE() {
12549 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12550 } IEM_MC_ENDIF();
12551 IEM_MC_ADVANCE_RIP_AND_FINISH();
12552
12553 IEM_MC_END();
12554}
12555
12556
12557/** Opcode 0xdc !11/4. */
12558FNIEMOP_DEF_1(iemOp_fsub_m64r, uint8_t, bRm)
12559{
12560 IEMOP_MNEMONIC(fsub_m64r, "fsub m64r");
12561 return FNIEMOP_CALL_2(iemOpHlpFpu_ST0_m64r, bRm, iemAImpl_fsub_r80_by_r64);
12562}
12563
12564
12565/** Opcode 0xdc !11/5. */
12566FNIEMOP_DEF_1(iemOp_fsubr_m64r, uint8_t, bRm)
12567{
12568 IEMOP_MNEMONIC(fsubr_m64r, "fsubr m64r");
12569 return FNIEMOP_CALL_2(iemOpHlpFpu_ST0_m64r, bRm, iemAImpl_fsubr_r80_by_r64);
12570}
12571
12572
12573/** Opcode 0xdc !11/6. */
12574FNIEMOP_DEF_1(iemOp_fdiv_m64r, uint8_t, bRm)
12575{
12576 IEMOP_MNEMONIC(fdiv_m64r, "fdiv m64r");
12577 return FNIEMOP_CALL_2(iemOpHlpFpu_ST0_m64r, bRm, iemAImpl_fdiv_r80_by_r64);
12578}
12579
12580
12581/** Opcode 0xdc !11/7. */
12582FNIEMOP_DEF_1(iemOp_fdivr_m64r, uint8_t, bRm)
12583{
12584 IEMOP_MNEMONIC(fdivr_m64r, "fdivr m64r");
12585 return FNIEMOP_CALL_2(iemOpHlpFpu_ST0_m64r, bRm, iemAImpl_fdivr_r80_by_r64);
12586}
12587
12588
12589/**
12590 * @opcode 0xdc
12591 */
12592FNIEMOP_DEF(iemOp_EscF4)
12593{
12594 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
12595 pVCpu->iem.s.uFpuOpcode = RT_MAKE_U16(bRm, 0xdc & 0x7);
12596 if (IEM_IS_MODRM_REG_MODE(bRm))
12597 {
12598 switch (IEM_GET_MODRM_REG_8(bRm))
12599 {
12600 case 0: return FNIEMOP_CALL_1(iemOp_fadd_stN_st0, bRm);
12601 case 1: return FNIEMOP_CALL_1(iemOp_fmul_stN_st0, bRm);
12602 case 2: return FNIEMOP_CALL_1(iemOp_fcom_stN, bRm); /* Marked reserved, intel behavior is that of FCOM ST(i). */
12603 case 3: return FNIEMOP_CALL_1(iemOp_fcomp_stN, bRm); /* Marked reserved, intel behavior is that of FCOMP ST(i). */
12604 case 4: return FNIEMOP_CALL_1(iemOp_fsubr_stN_st0, bRm);
12605 case 5: return FNIEMOP_CALL_1(iemOp_fsub_stN_st0, bRm);
12606 case 6: return FNIEMOP_CALL_1(iemOp_fdivr_stN_st0, bRm);
12607 case 7: return FNIEMOP_CALL_1(iemOp_fdiv_stN_st0, bRm);
12608 IEM_NOT_REACHED_DEFAULT_CASE_RET();
12609 }
12610 }
12611 else
12612 {
12613 switch (IEM_GET_MODRM_REG_8(bRm))
12614 {
12615 case 0: return FNIEMOP_CALL_1(iemOp_fadd_m64r, bRm);
12616 case 1: return FNIEMOP_CALL_1(iemOp_fmul_m64r, bRm);
12617 case 2: return FNIEMOP_CALL_1(iemOp_fcom_m64r, bRm);
12618 case 3: return FNIEMOP_CALL_1(iemOp_fcomp_m64r, bRm);
12619 case 4: return FNIEMOP_CALL_1(iemOp_fsub_m64r, bRm);
12620 case 5: return FNIEMOP_CALL_1(iemOp_fsubr_m64r, bRm);
12621 case 6: return FNIEMOP_CALL_1(iemOp_fdiv_m64r, bRm);
12622 case 7: return FNIEMOP_CALL_1(iemOp_fdivr_m64r, bRm);
12623 IEM_NOT_REACHED_DEFAULT_CASE_RET();
12624 }
12625 }
12626}
12627
12628
12629/** Opcode 0xdd !11/0.
12630 * @sa iemOp_fld_m32r */
12631FNIEMOP_DEF_1(iemOp_fld_m64r, uint8_t, bRm)
12632{
12633 IEMOP_MNEMONIC(fld_m64r, "fld m64r");
12634
12635 IEM_MC_BEGIN(2, 3, 0, 0);
12636 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
12637 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
12638 IEM_MC_LOCAL(RTFLOAT64U, r64Val);
12639 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
12640 IEM_MC_ARG_LOCAL_REF(PCRTFLOAT64U, pr64Val, r64Val, 1);
12641
12642 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
12643 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12644 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12645 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12646
12647 IEM_MC_FETCH_MEM_R64(r64Val, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
12648 IEM_MC_PREPARE_FPU_USAGE();
12649 IEM_MC_IF_FPUREG_IS_EMPTY(7) {
12650 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fld_r80_from_r64, pFpuRes, pr64Val);
12651 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12652 } IEM_MC_ELSE() {
12653 IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
12654 } IEM_MC_ENDIF();
12655 IEM_MC_ADVANCE_RIP_AND_FINISH();
12656
12657 IEM_MC_END();
12658}
12659
12660
12661/** Opcode 0xdd !11/0. */
12662FNIEMOP_DEF_1(iemOp_fisttp_m64i, uint8_t, bRm)
12663{
12664 IEMOP_MNEMONIC(fisttp_m64i, "fisttp m64i");
12665 IEM_MC_BEGIN(3, 3, 0, 0);
12666 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
12667 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
12668
12669 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12670 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12671 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12672 IEM_MC_PREPARE_FPU_USAGE();
12673
12674 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
12675 IEM_MC_ARG(int64_t *, pi64Dst, 1);
12676 IEM_MC_MEM_MAP_I64_WO(pi64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
12677
12678 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
12679 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
12680 IEM_MC_LOCAL(uint16_t, u16Fsw);
12681 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
12682 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fistt_r80_to_i64, pu16Fsw, pi64Dst, pr80Value);
12683 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
12684 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12685 } IEM_MC_ELSE() {
12686 IEM_MC_IF_FCW_IM() {
12687 IEM_MC_STORE_MEM_I64_CONST_BY_REF(pi64Dst, INT64_MIN /* (integer indefinite) */);
12688 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
12689 } IEM_MC_ELSE() {
12690 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
12691 } IEM_MC_ENDIF();
12692 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12693 } IEM_MC_ENDIF();
12694 IEM_MC_ADVANCE_RIP_AND_FINISH();
12695
12696 IEM_MC_END();
12697}
12698
12699
12700/** Opcode 0xdd !11/0. */
12701FNIEMOP_DEF_1(iemOp_fst_m64r, uint8_t, bRm)
12702{
12703 IEMOP_MNEMONIC(fst_m64r, "fst m64r");
12704 IEM_MC_BEGIN(3, 3, 0, 0);
12705 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
12706 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
12707
12708 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12709 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12710 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12711 IEM_MC_PREPARE_FPU_USAGE();
12712
12713 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
12714 IEM_MC_ARG(PRTFLOAT64U, pr64Dst, 1);
12715 IEM_MC_MEM_MAP_R64_WO(pr64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
12716
12717 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
12718 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
12719 IEM_MC_LOCAL(uint16_t, u16Fsw);
12720 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
12721 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fst_r80_to_r64, pu16Fsw, pr64Dst, pr80Value);
12722 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
12723 IEM_MC_UPDATE_FSW_WITH_MEM_OP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12724 } IEM_MC_ELSE() {
12725 IEM_MC_IF_FCW_IM() {
12726 IEM_MC_STORE_MEM_NEG_QNAN_R64_BY_REF(pr64Dst);
12727 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
12728 } IEM_MC_ELSE() {
12729 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
12730 } IEM_MC_ENDIF();
12731 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12732 } IEM_MC_ENDIF();
12733 IEM_MC_ADVANCE_RIP_AND_FINISH();
12734
12735 IEM_MC_END();
12736}
12737
12738
12739
12740
12741/** Opcode 0xdd !11/0. */
12742FNIEMOP_DEF_1(iemOp_fstp_m64r, uint8_t, bRm)
12743{
12744 IEMOP_MNEMONIC(fstp_m64r, "fstp m64r");
12745 IEM_MC_BEGIN(3, 3, 0, 0);
12746 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
12747 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
12748
12749 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12750 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12751 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12752 IEM_MC_PREPARE_FPU_USAGE();
12753
12754 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
12755 IEM_MC_ARG(PRTFLOAT64U, pr64Dst, 1);
12756 IEM_MC_MEM_MAP_R64_WO(pr64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
12757
12758 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
12759 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
12760 IEM_MC_LOCAL(uint16_t, u16Fsw);
12761 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
12762 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fst_r80_to_r64, pu16Fsw, pr64Dst, pr80Value);
12763 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
12764 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12765 } IEM_MC_ELSE() {
12766 IEM_MC_IF_FCW_IM() {
12767 IEM_MC_STORE_MEM_NEG_QNAN_R64_BY_REF(pr64Dst);
12768 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
12769 } IEM_MC_ELSE() {
12770 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
12771 } IEM_MC_ENDIF();
12772 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
12773 } IEM_MC_ENDIF();
12774 IEM_MC_ADVANCE_RIP_AND_FINISH();
12775
12776 IEM_MC_END();
12777}
12778
12779
12780/** Opcode 0xdd !11/0. */
12781FNIEMOP_DEF_1(iemOp_frstor, uint8_t, bRm)
12782{
12783 IEMOP_MNEMONIC(frstor, "frstor m94/108byte");
12784 IEM_MC_BEGIN(3, 0, 0, 0);
12785 IEM_MC_ARG(RTGCPTR, GCPtrEffSrc, 2);
12786 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
12787
12788 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12789 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12790 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
12791
12792 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize, /*=*/ pVCpu->iem.s.enmEffOpSize, 0);
12793 IEM_MC_ARG_CONST(uint8_t, iEffSeg, /*=*/ pVCpu->iem.s.iEffSeg, 1);
12794 IEM_MC_CALL_CIMPL_3(IEM_CIMPL_F_FPU, RT_BIT_64(kIemNativeGstReg_FpuFcw) | RT_BIT_64(kIemNativeGstReg_FpuFsw),
12795 iemCImpl_frstor, enmEffOpSize, iEffSeg, GCPtrEffSrc);
12796 IEM_MC_END();
12797}
12798
12799
12800/** Opcode 0xdd !11/0. */
12801FNIEMOP_DEF_1(iemOp_fnsave, uint8_t, bRm)
12802{
12803 IEMOP_MNEMONIC(fnsave, "fnsave m94/108byte");
12804 IEM_MC_BEGIN(3, 0, 0, 0);
12805 IEM_MC_ARG(RTGCPTR, GCPtrEffDst, 2);
12806 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
12807
12808 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12809 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12810 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE(); /* Note! Implicit fninit after the save, do not use FOR_READ here! */
12811
12812 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize, /*=*/ pVCpu->iem.s.enmEffOpSize, 0);
12813 IEM_MC_ARG_CONST(uint8_t, iEffSeg, /*=*/ pVCpu->iem.s.iEffSeg, 1);
12814 IEM_MC_CALL_CIMPL_3(IEM_CIMPL_F_FPU, RT_BIT_64(kIemNativeGstReg_FpuFcw) | RT_BIT_64(kIemNativeGstReg_FpuFsw),
12815 iemCImpl_fnsave, enmEffOpSize, iEffSeg, GCPtrEffDst);
12816 IEM_MC_END();
12817}
12818
12819/** Opcode 0xdd !11/0. */
12820FNIEMOP_DEF_1(iemOp_fnstsw, uint8_t, bRm)
12821{
12822 IEMOP_MNEMONIC(fnstsw_m16, "fnstsw m16");
12823
12824 IEM_MC_BEGIN(0, 2, 0, 0);
12825 IEM_MC_LOCAL(uint16_t, u16Tmp);
12826 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
12827
12828 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
12829 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12830 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12831
12832 IEM_MC_ACTUALIZE_FPU_STATE_FOR_READ();
12833 IEM_MC_FETCH_FSW(u16Tmp);
12834 IEM_MC_STORE_MEM_U16(pVCpu->iem.s.iEffSeg, GCPtrEffDst, u16Tmp);
12835 IEM_MC_ADVANCE_RIP_AND_FINISH();
12836
12837/** @todo Debug / drop a hint to the verifier that things may differ
12838 * from REM. Seen 0x4020 (iem) vs 0x4000 (rem) at 0008:801c6b88 booting
12839 * NT4SP1. (X86_FSW_PE) */
12840 IEM_MC_END();
12841}
12842
12843
12844/** Opcode 0xdd 11/0. */
12845FNIEMOP_DEF_1(iemOp_ffree_stN, uint8_t, bRm)
12846{
12847 IEMOP_MNEMONIC(ffree_stN, "ffree stN");
12848 /* Note! C0, C1, C2 and C3 are documented as undefined, we leave the
12849 unmodified. */
12850 IEM_MC_BEGIN(0, 0, 0, 0);
12851 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12852
12853 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12854 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12855
12856 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
12857 IEM_MC_FPU_STACK_FREE(IEM_GET_MODRM_RM_8(bRm));
12858 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
12859
12860 IEM_MC_ADVANCE_RIP_AND_FINISH();
12861 IEM_MC_END();
12862}
12863
12864
12865/** Opcode 0xdd 11/1. */
12866FNIEMOP_DEF_1(iemOp_fst_stN, uint8_t, bRm)
12867{
12868 IEMOP_MNEMONIC(fst_st0_stN, "fst st0,stN");
12869 IEM_MC_BEGIN(0, 2, 0, 0);
12870 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
12871 IEM_MC_LOCAL(PCRTFLOAT80U, pr80Value);
12872 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
12873 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
12874 IEM_MC_MAYBE_RAISE_FPU_XCPT();
12875
12876 IEM_MC_PREPARE_FPU_USAGE();
12877 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
12878 IEM_MC_SET_FPU_RESULT(FpuRes, 0 /*FSW*/, pr80Value);
12879 IEM_MC_STORE_FPU_RESULT(FpuRes, IEM_GET_MODRM_RM_8(bRm), pVCpu->iem.s.uFpuOpcode);
12880 } IEM_MC_ELSE() {
12881 IEM_MC_FPU_STACK_UNDERFLOW(IEM_GET_MODRM_RM_8(bRm), pVCpu->iem.s.uFpuOpcode);
12882 } IEM_MC_ENDIF();
12883
12884 IEM_MC_ADVANCE_RIP_AND_FINISH();
12885 IEM_MC_END();
12886}
12887
12888
12889/** Opcode 0xdd 11/3. */
12890FNIEMOP_DEF_1(iemOp_fucom_stN_st0, uint8_t, bRm)
12891{
12892 IEMOP_MNEMONIC(fucom_st0_stN, "fucom st0,stN");
12893 return FNIEMOP_CALL_2(iemOpHlpFpuNoStore_st0_stN, bRm, iemAImpl_fucom_r80_by_r80);
12894}
12895
12896
12897/** Opcode 0xdd 11/4. */
12898FNIEMOP_DEF_1(iemOp_fucomp_stN, uint8_t, bRm)
12899{
12900 IEMOP_MNEMONIC(fucomp_st0_stN, "fucomp st0,stN");
12901 return FNIEMOP_CALL_2(iemOpHlpFpuNoStore_st0_stN_pop, bRm, iemAImpl_fucom_r80_by_r80);
12902}
12903
12904
12905/**
12906 * @opcode 0xdd
12907 */
12908FNIEMOP_DEF(iemOp_EscF5)
12909{
12910 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
12911 pVCpu->iem.s.uFpuOpcode = RT_MAKE_U16(bRm, 0xdd & 0x7);
12912 if (IEM_IS_MODRM_REG_MODE(bRm))
12913 {
12914 switch (IEM_GET_MODRM_REG_8(bRm))
12915 {
12916 case 0: return FNIEMOP_CALL_1(iemOp_ffree_stN, bRm);
12917 case 1: return FNIEMOP_CALL_1(iemOp_fxch_stN, bRm); /* Reserved, intel behavior is that of XCHG ST(i). */
12918 case 2: return FNIEMOP_CALL_1(iemOp_fst_stN, bRm);
12919 case 3: return FNIEMOP_CALL_1(iemOp_fstp_stN, bRm);
12920 case 4: return FNIEMOP_CALL_1(iemOp_fucom_stN_st0,bRm);
12921 case 5: return FNIEMOP_CALL_1(iemOp_fucomp_stN, bRm);
12922 case 6: IEMOP_RAISE_INVALID_OPCODE_RET();
12923 case 7: IEMOP_RAISE_INVALID_OPCODE_RET();
12924 IEM_NOT_REACHED_DEFAULT_CASE_RET();
12925 }
12926 }
12927 else
12928 {
12929 switch (IEM_GET_MODRM_REG_8(bRm))
12930 {
12931 case 0: return FNIEMOP_CALL_1(iemOp_fld_m64r, bRm);
12932 case 1: return FNIEMOP_CALL_1(iemOp_fisttp_m64i, bRm);
12933 case 2: return FNIEMOP_CALL_1(iemOp_fst_m64r, bRm);
12934 case 3: return FNIEMOP_CALL_1(iemOp_fstp_m64r, bRm);
12935 case 4: return FNIEMOP_CALL_1(iemOp_frstor, bRm);
12936 case 5: IEMOP_RAISE_INVALID_OPCODE_RET();
12937 case 6: return FNIEMOP_CALL_1(iemOp_fnsave, bRm);
12938 case 7: return FNIEMOP_CALL_1(iemOp_fnstsw, bRm);
12939 IEM_NOT_REACHED_DEFAULT_CASE_RET();
12940 }
12941 }
12942}
12943
12944
12945/** Opcode 0xde 11/0. */
12946FNIEMOP_DEF_1(iemOp_faddp_stN_st0, uint8_t, bRm)
12947{
12948 IEMOP_MNEMONIC(faddp_stN_st0, "faddp stN,st0");
12949 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fadd_r80_by_r80);
12950}
12951
12952
12953/** Opcode 0xde 11/0. */
12954FNIEMOP_DEF_1(iemOp_fmulp_stN_st0, uint8_t, bRm)
12955{
12956 IEMOP_MNEMONIC(fmulp_stN_st0, "fmulp stN,st0");
12957 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fmul_r80_by_r80);
12958}
12959
12960
12961/** Opcode 0xde 0xd9. */
12962FNIEMOP_DEF(iemOp_fcompp)
12963{
12964 IEMOP_MNEMONIC(fcompp, "fcompp");
12965 return FNIEMOP_CALL_1(iemOpHlpFpuNoStore_st0_st1_pop_pop, iemAImpl_fcom_r80_by_r80);
12966}
12967
12968
12969/** Opcode 0xde 11/4. */
12970FNIEMOP_DEF_1(iemOp_fsubrp_stN_st0, uint8_t, bRm)
12971{
12972 IEMOP_MNEMONIC(fsubrp_stN_st0, "fsubrp stN,st0");
12973 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fsubr_r80_by_r80);
12974}
12975
12976
12977/** Opcode 0xde 11/5. */
12978FNIEMOP_DEF_1(iemOp_fsubp_stN_st0, uint8_t, bRm)
12979{
12980 IEMOP_MNEMONIC(fsubp_stN_st0, "fsubp stN,st0");
12981 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fsub_r80_by_r80);
12982}
12983
12984
12985/** Opcode 0xde 11/6. */
12986FNIEMOP_DEF_1(iemOp_fdivrp_stN_st0, uint8_t, bRm)
12987{
12988 IEMOP_MNEMONIC(fdivrp_stN_st0, "fdivrp stN,st0");
12989 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fdivr_r80_by_r80);
12990}
12991
12992
12993/** Opcode 0xde 11/7. */
12994FNIEMOP_DEF_1(iemOp_fdivp_stN_st0, uint8_t, bRm)
12995{
12996 IEMOP_MNEMONIC(fdivp_stN_st0, "fdivp stN,st0");
12997 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fdiv_r80_by_r80);
12998}
12999
13000
13001/**
13002 * Common worker for FPU instructions working on ST0 and an m16i, and storing
13003 * the result in ST0.
13004 *
13005 * @param bRm Mod R/M byte.
13006 * @param pfnAImpl Pointer to the instruction implementation (assembly).
13007 */
13008FNIEMOP_DEF_2(iemOpHlpFpu_st0_m16i, uint8_t, bRm, PFNIEMAIMPLFPUI16, pfnAImpl)
13009{
13010 IEM_MC_BEGIN(3, 3, 0, 0);
13011 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
13012 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
13013 IEM_MC_LOCAL(int16_t, i16Val2);
13014 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
13015 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
13016 IEM_MC_ARG_LOCAL_REF(int16_t const *, pi16Val2, i16Val2, 2);
13017
13018 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
13019 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13020
13021 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13022 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13023 IEM_MC_FETCH_MEM_I16(i16Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
13024
13025 IEM_MC_PREPARE_FPU_USAGE();
13026 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
13027 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pi16Val2);
13028 IEM_MC_STORE_FPU_RESULT(FpuRes, 0, pVCpu->iem.s.uFpuOpcode);
13029 } IEM_MC_ELSE() {
13030 IEM_MC_FPU_STACK_UNDERFLOW(0, pVCpu->iem.s.uFpuOpcode);
13031 } IEM_MC_ENDIF();
13032 IEM_MC_ADVANCE_RIP_AND_FINISH();
13033
13034 IEM_MC_END();
13035}
13036
13037
13038/** Opcode 0xde !11/0. */
13039FNIEMOP_DEF_1(iemOp_fiadd_m16i, uint8_t, bRm)
13040{
13041 IEMOP_MNEMONIC(fiadd_m16i, "fiadd m16i");
13042 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m16i, bRm, iemAImpl_fiadd_r80_by_i16);
13043}
13044
13045
13046/** Opcode 0xde !11/1. */
13047FNIEMOP_DEF_1(iemOp_fimul_m16i, uint8_t, bRm)
13048{
13049 IEMOP_MNEMONIC(fimul_m16i, "fimul m16i");
13050 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m16i, bRm, iemAImpl_fimul_r80_by_i16);
13051}
13052
13053
13054/** Opcode 0xde !11/2. */
13055FNIEMOP_DEF_1(iemOp_ficom_m16i, uint8_t, bRm)
13056{
13057 IEMOP_MNEMONIC(ficom_st0_m16i, "ficom st0,m16i");
13058
13059 IEM_MC_BEGIN(3, 3, 0, 0);
13060 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
13061 IEM_MC_LOCAL(uint16_t, u16Fsw);
13062 IEM_MC_LOCAL(int16_t, i16Val2);
13063 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
13064 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
13065 IEM_MC_ARG_LOCAL_REF(int16_t const *, pi16Val2, i16Val2, 2);
13066
13067 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
13068 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13069
13070 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13071 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13072 IEM_MC_FETCH_MEM_I16(i16Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
13073
13074 IEM_MC_PREPARE_FPU_USAGE();
13075 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
13076 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_ficom_r80_by_i16, pu16Fsw, pr80Value1, pi16Val2);
13077 IEM_MC_UPDATE_FSW_WITH_MEM_OP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13078 } IEM_MC_ELSE() {
13079 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13080 } IEM_MC_ENDIF();
13081 IEM_MC_ADVANCE_RIP_AND_FINISH();
13082
13083 IEM_MC_END();
13084}
13085
13086
13087/** Opcode 0xde !11/3. */
13088FNIEMOP_DEF_1(iemOp_ficomp_m16i, uint8_t, bRm)
13089{
13090 IEMOP_MNEMONIC(ficomp_st0_m16i, "ficomp st0,m16i");
13091
13092 IEM_MC_BEGIN(3, 3, 0, 0);
13093 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
13094 IEM_MC_LOCAL(uint16_t, u16Fsw);
13095 IEM_MC_LOCAL(int16_t, i16Val2);
13096 IEM_MC_ARG_LOCAL_REF(uint16_t *, pu16Fsw, u16Fsw, 0);
13097 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1);
13098 IEM_MC_ARG_LOCAL_REF(int16_t const *, pi16Val2, i16Val2, 2);
13099
13100 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
13101 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13102
13103 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13104 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13105 IEM_MC_FETCH_MEM_I16(i16Val2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
13106
13107 IEM_MC_PREPARE_FPU_USAGE();
13108 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value1, 0) {
13109 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_ficom_r80_by_i16, pu16Fsw, pr80Value1, pi16Val2);
13110 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13111 } IEM_MC_ELSE() {
13112 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13113 } IEM_MC_ENDIF();
13114 IEM_MC_ADVANCE_RIP_AND_FINISH();
13115
13116 IEM_MC_END();
13117}
13118
13119
13120/** Opcode 0xde !11/4. */
13121FNIEMOP_DEF_1(iemOp_fisub_m16i, uint8_t, bRm)
13122{
13123 IEMOP_MNEMONIC(fisub_m16i, "fisub m16i");
13124 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m16i, bRm, iemAImpl_fisub_r80_by_i16);
13125}
13126
13127
13128/** Opcode 0xde !11/5. */
13129FNIEMOP_DEF_1(iemOp_fisubr_m16i, uint8_t, bRm)
13130{
13131 IEMOP_MNEMONIC(fisubr_m16i, "fisubr m16i");
13132 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m16i, bRm, iemAImpl_fisubr_r80_by_i16);
13133}
13134
13135
13136/** Opcode 0xde !11/6. */
13137FNIEMOP_DEF_1(iemOp_fidiv_m16i, uint8_t, bRm)
13138{
13139 IEMOP_MNEMONIC(fidiv_m16i, "fidiv m16i");
13140 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m16i, bRm, iemAImpl_fidiv_r80_by_i16);
13141}
13142
13143
13144/** Opcode 0xde !11/7. */
13145FNIEMOP_DEF_1(iemOp_fidivr_m16i, uint8_t, bRm)
13146{
13147 IEMOP_MNEMONIC(fidivr_m16i, "fidivr m16i");
13148 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_m16i, bRm, iemAImpl_fidivr_r80_by_i16);
13149}
13150
13151
13152/**
13153 * @opcode 0xde
13154 */
13155FNIEMOP_DEF(iemOp_EscF6)
13156{
13157 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
13158 pVCpu->iem.s.uFpuOpcode = RT_MAKE_U16(bRm, 0xde & 0x7);
13159 if (IEM_IS_MODRM_REG_MODE(bRm))
13160 {
13161 switch (IEM_GET_MODRM_REG_8(bRm))
13162 {
13163 case 0: return FNIEMOP_CALL_1(iemOp_faddp_stN_st0, bRm);
13164 case 1: return FNIEMOP_CALL_1(iemOp_fmulp_stN_st0, bRm);
13165 case 2: return FNIEMOP_CALL_1(iemOp_fcomp_stN, bRm);
13166 case 3: if (bRm == 0xd9)
13167 return FNIEMOP_CALL(iemOp_fcompp);
13168 IEMOP_RAISE_INVALID_OPCODE_RET();
13169 case 4: return FNIEMOP_CALL_1(iemOp_fsubrp_stN_st0, bRm);
13170 case 5: return FNIEMOP_CALL_1(iemOp_fsubp_stN_st0, bRm);
13171 case 6: return FNIEMOP_CALL_1(iemOp_fdivrp_stN_st0, bRm);
13172 case 7: return FNIEMOP_CALL_1(iemOp_fdivp_stN_st0, bRm);
13173 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13174 }
13175 }
13176 else
13177 {
13178 switch (IEM_GET_MODRM_REG_8(bRm))
13179 {
13180 case 0: return FNIEMOP_CALL_1(iemOp_fiadd_m16i, bRm);
13181 case 1: return FNIEMOP_CALL_1(iemOp_fimul_m16i, bRm);
13182 case 2: return FNIEMOP_CALL_1(iemOp_ficom_m16i, bRm);
13183 case 3: return FNIEMOP_CALL_1(iemOp_ficomp_m16i, bRm);
13184 case 4: return FNIEMOP_CALL_1(iemOp_fisub_m16i, bRm);
13185 case 5: return FNIEMOP_CALL_1(iemOp_fisubr_m16i, bRm);
13186 case 6: return FNIEMOP_CALL_1(iemOp_fidiv_m16i, bRm);
13187 case 7: return FNIEMOP_CALL_1(iemOp_fidivr_m16i, bRm);
13188 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13189 }
13190 }
13191}
13192
13193
13194/** Opcode 0xdf 11/0.
13195 * Undocument instruction, assumed to work like ffree + fincstp. */
13196FNIEMOP_DEF_1(iemOp_ffreep_stN, uint8_t, bRm)
13197{
13198 IEMOP_MNEMONIC(ffreep_stN, "ffreep stN");
13199 IEM_MC_BEGIN(0, 0, 0, 0);
13200 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13201
13202 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13203 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13204
13205 IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE();
13206 IEM_MC_FPU_STACK_FREE(IEM_GET_MODRM_RM_8(bRm));
13207 IEM_MC_FPU_STACK_INC_TOP();
13208 IEM_MC_UPDATE_FPU_OPCODE_IP(pVCpu->iem.s.uFpuOpcode);
13209
13210 IEM_MC_ADVANCE_RIP_AND_FINISH();
13211 IEM_MC_END();
13212}
13213
13214
13215/** Opcode 0xdf 0xe0. */
13216FNIEMOP_DEF(iemOp_fnstsw_ax)
13217{
13218 IEMOP_MNEMONIC(fnstsw_ax, "fnstsw ax");
13219 IEM_MC_BEGIN(0, 1, 0, 0);
13220 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13221 IEM_MC_LOCAL(uint16_t, u16Tmp);
13222 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13223 IEM_MC_ACTUALIZE_FPU_STATE_FOR_READ();
13224 IEM_MC_FETCH_FSW(u16Tmp);
13225 IEM_MC_STORE_GREG_U16(X86_GREG_xAX, u16Tmp);
13226 IEM_MC_ADVANCE_RIP_AND_FINISH();
13227 IEM_MC_END();
13228}
13229
13230
13231/** Opcode 0xdf 11/5. */
13232FNIEMOP_DEF_1(iemOp_fucomip_st0_stN, uint8_t, bRm)
13233{
13234 IEMOP_MNEMONIC(fucomip_st0_stN, "fucomip st0,stN");
13235 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS, 0,
13236 iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), false /*fUCmp*/,
13237 RT_BIT_32(31) /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
13238}
13239
13240
13241/** Opcode 0xdf 11/6. */
13242FNIEMOP_DEF_1(iemOp_fcomip_st0_stN, uint8_t, bRm)
13243{
13244 IEMOP_MNEMONIC(fcomip_st0_stN, "fcomip st0,stN");
13245 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS, 0,
13246 iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), false /*fUCmp*/,
13247 RT_BIT_32(31) /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
13248}
13249
13250
13251/** Opcode 0xdf !11/0. */
13252FNIEMOP_DEF_1(iemOp_fild_m16i, uint8_t, bRm)
13253{
13254 IEMOP_MNEMONIC(fild_m16i, "fild m16i");
13255
13256 IEM_MC_BEGIN(2, 3, 0, 0);
13257 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
13258 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
13259 IEM_MC_LOCAL(int16_t, i16Val);
13260 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
13261 IEM_MC_ARG_LOCAL_REF(int16_t const *, pi16Val, i16Val, 1);
13262
13263 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
13264 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13265
13266 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13267 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13268 IEM_MC_FETCH_MEM_I16(i16Val, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
13269
13270 IEM_MC_PREPARE_FPU_USAGE();
13271 IEM_MC_IF_FPUREG_IS_EMPTY(7) {
13272 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fild_r80_from_i16, pFpuRes, pi16Val);
13273 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13274 } IEM_MC_ELSE() {
13275 IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13276 } IEM_MC_ENDIF();
13277 IEM_MC_ADVANCE_RIP_AND_FINISH();
13278
13279 IEM_MC_END();
13280}
13281
13282
13283/** Opcode 0xdf !11/1. */
13284FNIEMOP_DEF_1(iemOp_fisttp_m16i, uint8_t, bRm)
13285{
13286 IEMOP_MNEMONIC(fisttp_m16i, "fisttp m16i");
13287 IEM_MC_BEGIN(3, 3, 0, 0);
13288 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
13289 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
13290
13291 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13292 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13293 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13294 IEM_MC_PREPARE_FPU_USAGE();
13295
13296 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
13297 IEM_MC_ARG(int16_t *, pi16Dst, 1);
13298 IEM_MC_MEM_MAP_I16_WO(pi16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
13299
13300 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
13301 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
13302 IEM_MC_LOCAL(uint16_t, u16Fsw);
13303 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
13304 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fistt_r80_to_i16, pu16Fsw, pi16Dst, pr80Value);
13305 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
13306 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13307 } IEM_MC_ELSE() {
13308 IEM_MC_IF_FCW_IM() {
13309 IEM_MC_STORE_MEM_I16_CONST_BY_REF(pi16Dst, INT16_MIN /* (integer indefinite) */);
13310 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
13311 } IEM_MC_ELSE() {
13312 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
13313 } IEM_MC_ENDIF();
13314 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13315 } IEM_MC_ENDIF();
13316 IEM_MC_ADVANCE_RIP_AND_FINISH();
13317
13318 IEM_MC_END();
13319}
13320
13321
13322/** Opcode 0xdf !11/2. */
13323FNIEMOP_DEF_1(iemOp_fist_m16i, uint8_t, bRm)
13324{
13325 IEMOP_MNEMONIC(fist_m16i, "fist m16i");
13326 IEM_MC_BEGIN(3, 3, 0, 0);
13327 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
13328 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
13329
13330 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13331 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13332 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13333 IEM_MC_PREPARE_FPU_USAGE();
13334
13335 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
13336 IEM_MC_ARG(int16_t *, pi16Dst, 1);
13337 IEM_MC_MEM_MAP_I16_WO(pi16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
13338
13339 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
13340 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
13341 IEM_MC_LOCAL(uint16_t, u16Fsw);
13342 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
13343 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fist_r80_to_i16, pu16Fsw, pi16Dst, pr80Value);
13344 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
13345 IEM_MC_UPDATE_FSW_WITH_MEM_OP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13346 } IEM_MC_ELSE() {
13347 IEM_MC_IF_FCW_IM() {
13348 IEM_MC_STORE_MEM_I16_CONST_BY_REF(pi16Dst, INT16_MIN /* (integer indefinite) */);
13349 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
13350 } IEM_MC_ELSE() {
13351 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
13352 } IEM_MC_ENDIF();
13353 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13354 } IEM_MC_ENDIF();
13355 IEM_MC_ADVANCE_RIP_AND_FINISH();
13356
13357 IEM_MC_END();
13358}
13359
13360
13361/** Opcode 0xdf !11/3. */
13362FNIEMOP_DEF_1(iemOp_fistp_m16i, uint8_t, bRm)
13363{
13364 IEMOP_MNEMONIC(fistp_m16i, "fistp m16i");
13365 IEM_MC_BEGIN(3, 3, 0, 0);
13366 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
13367 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
13368
13369 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13370 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13371 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13372 IEM_MC_PREPARE_FPU_USAGE();
13373
13374 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
13375 IEM_MC_ARG(int16_t *, pi16Dst, 1);
13376 IEM_MC_MEM_MAP_I16_WO(pi16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
13377
13378 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
13379 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
13380 IEM_MC_LOCAL(uint16_t, u16Fsw);
13381 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
13382 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fist_r80_to_i16, pu16Fsw, pi16Dst, pr80Value);
13383 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
13384 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13385 } IEM_MC_ELSE() {
13386 IEM_MC_IF_FCW_IM() {
13387 IEM_MC_STORE_MEM_I16_CONST_BY_REF(pi16Dst, INT16_MIN /* (integer indefinite) */);
13388 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
13389 } IEM_MC_ELSE() {
13390 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
13391 } IEM_MC_ENDIF();
13392 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13393 } IEM_MC_ENDIF();
13394 IEM_MC_ADVANCE_RIP_AND_FINISH();
13395
13396 IEM_MC_END();
13397}
13398
13399
13400/** Opcode 0xdf !11/4. */
13401FNIEMOP_DEF_1(iemOp_fbld_m80d, uint8_t, bRm)
13402{
13403 IEMOP_MNEMONIC(fbld_m80d, "fbld m80d");
13404
13405 IEM_MC_BEGIN(2, 3, 0, 0);
13406 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
13407 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
13408 IEM_MC_LOCAL(RTPBCD80U, d80Val);
13409 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
13410 IEM_MC_ARG_LOCAL_REF(PCRTPBCD80U, pd80Val, d80Val, 1);
13411
13412 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
13413 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13414
13415 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13416 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13417 IEM_MC_FETCH_MEM_D80(d80Val, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
13418
13419 IEM_MC_PREPARE_FPU_USAGE();
13420 IEM_MC_IF_FPUREG_IS_EMPTY(7) {
13421 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fld_r80_from_d80, pFpuRes, pd80Val);
13422 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13423 } IEM_MC_ELSE() {
13424 IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13425 } IEM_MC_ENDIF();
13426 IEM_MC_ADVANCE_RIP_AND_FINISH();
13427
13428 IEM_MC_END();
13429}
13430
13431
13432/** Opcode 0xdf !11/5. */
13433FNIEMOP_DEF_1(iemOp_fild_m64i, uint8_t, bRm)
13434{
13435 IEMOP_MNEMONIC(fild_m64i, "fild m64i");
13436
13437 IEM_MC_BEGIN(2, 3, 0, 0);
13438 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
13439 IEM_MC_LOCAL(IEMFPURESULT, FpuRes);
13440 IEM_MC_LOCAL(int64_t, i64Val);
13441 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0);
13442 IEM_MC_ARG_LOCAL_REF(int64_t const *, pi64Val, i64Val, 1);
13443
13444 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
13445 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13446
13447 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13448 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13449 IEM_MC_FETCH_MEM_I64(i64Val, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
13450
13451 IEM_MC_PREPARE_FPU_USAGE();
13452 IEM_MC_IF_FPUREG_IS_EMPTY(7) {
13453 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fild_r80_from_i64, pFpuRes, pi64Val);
13454 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13455 } IEM_MC_ELSE() {
13456 IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(pVCpu->iem.s.iEffSeg, GCPtrEffSrc, pVCpu->iem.s.uFpuOpcode);
13457 } IEM_MC_ENDIF();
13458 IEM_MC_ADVANCE_RIP_AND_FINISH();
13459
13460 IEM_MC_END();
13461}
13462
13463
13464/** Opcode 0xdf !11/6. */
13465FNIEMOP_DEF_1(iemOp_fbstp_m80d, uint8_t, bRm)
13466{
13467 IEMOP_MNEMONIC(fbstp_m80d, "fbstp m80d");
13468 IEM_MC_BEGIN(3, 3, 0, 0);
13469 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
13470 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
13471
13472 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13473 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13474 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13475 IEM_MC_PREPARE_FPU_USAGE();
13476
13477 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
13478 IEM_MC_ARG(PRTPBCD80U, pd80Dst, 1);
13479 IEM_MC_MEM_MAP_D80_WO(pd80Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
13480
13481 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
13482 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
13483 IEM_MC_LOCAL(uint16_t, u16Fsw);
13484 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
13485 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fst_r80_to_d80, pu16Fsw, pd80Dst, pr80Value);
13486 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
13487 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13488 } IEM_MC_ELSE() {
13489 IEM_MC_IF_FCW_IM() {
13490 IEM_MC_STORE_MEM_INDEF_D80_BY_REF(pd80Dst);
13491 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
13492 } IEM_MC_ELSE() {
13493 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
13494 } IEM_MC_ENDIF();
13495 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13496 } IEM_MC_ENDIF();
13497 IEM_MC_ADVANCE_RIP_AND_FINISH();
13498
13499 IEM_MC_END();
13500}
13501
13502
13503/** Opcode 0xdf !11/7. */
13504FNIEMOP_DEF_1(iemOp_fistp_m64i, uint8_t, bRm)
13505{
13506 IEMOP_MNEMONIC(fistp_m64i, "fistp m64i");
13507 IEM_MC_BEGIN(3, 3, 0, 0);
13508 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst);
13509 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
13510
13511 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13512 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
13513 IEM_MC_MAYBE_RAISE_FPU_XCPT();
13514 IEM_MC_PREPARE_FPU_USAGE();
13515
13516 IEM_MC_LOCAL(uint8_t, bUnmapInfo);
13517 IEM_MC_ARG(int64_t *, pi64Dst, 1);
13518 IEM_MC_MEM_MAP_I64_WO(pi64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
13519
13520 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 2);
13521 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) {
13522 IEM_MC_LOCAL(uint16_t, u16Fsw);
13523 IEM_MC_ARG_LOCAL_REF(uint16_t *,pu16Fsw, u16Fsw, 0);
13524 IEM_MC_CALL_FPU_AIMPL_3(iemAImpl_fist_r80_to_i64, pu16Fsw, pi64Dst, pr80Value);
13525 IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO(bUnmapInfo, u16Fsw);
13526 IEM_MC_UPDATE_FSW_WITH_MEM_OP_THEN_POP(u16Fsw, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13527 } IEM_MC_ELSE() {
13528 IEM_MC_IF_FCW_IM() {
13529 IEM_MC_STORE_MEM_I64_CONST_BY_REF(pi64Dst, INT64_MIN /* (integer indefinite) */);
13530 IEM_MC_MEM_COMMIT_AND_UNMAP_WO(bUnmapInfo);
13531 } IEM_MC_ELSE() {
13532 IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO(bUnmapInfo);
13533 } IEM_MC_ENDIF();
13534 IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(UINT8_MAX, pVCpu->iem.s.iEffSeg, GCPtrEffDst, pVCpu->iem.s.uFpuOpcode);
13535 } IEM_MC_ENDIF();
13536 IEM_MC_ADVANCE_RIP_AND_FINISH();
13537
13538 IEM_MC_END();
13539}
13540
13541
13542/**
13543 * @opcode 0xdf
13544 */
13545FNIEMOP_DEF(iemOp_EscF7)
13546{
13547 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
13548 pVCpu->iem.s.uFpuOpcode = RT_MAKE_U16(bRm, 0xdf & 0x7);
13549 if (IEM_IS_MODRM_REG_MODE(bRm))
13550 {
13551 switch (IEM_GET_MODRM_REG_8(bRm))
13552 {
13553 case 0: return FNIEMOP_CALL_1(iemOp_ffreep_stN, bRm); /* ffree + pop afterwards, since forever according to AMD. */
13554 case 1: return FNIEMOP_CALL_1(iemOp_fxch_stN, bRm); /* Reserved, behaves like FXCH ST(i) on intel. */
13555 case 2: return FNIEMOP_CALL_1(iemOp_fstp_stN, bRm); /* Reserved, behaves like FSTP ST(i) on intel. */
13556 case 3: return FNIEMOP_CALL_1(iemOp_fstp_stN, bRm); /* Reserved, behaves like FSTP ST(i) on intel. */
13557 case 4: if (bRm == 0xe0)
13558 return FNIEMOP_CALL(iemOp_fnstsw_ax);
13559 IEMOP_RAISE_INVALID_OPCODE_RET();
13560 case 5: return FNIEMOP_CALL_1(iemOp_fucomip_st0_stN, bRm);
13561 case 6: return FNIEMOP_CALL_1(iemOp_fcomip_st0_stN, bRm);
13562 case 7: IEMOP_RAISE_INVALID_OPCODE_RET();
13563 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13564 }
13565 }
13566 else
13567 {
13568 switch (IEM_GET_MODRM_REG_8(bRm))
13569 {
13570 case 0: return FNIEMOP_CALL_1(iemOp_fild_m16i, bRm);
13571 case 1: return FNIEMOP_CALL_1(iemOp_fisttp_m16i, bRm);
13572 case 2: return FNIEMOP_CALL_1(iemOp_fist_m16i, bRm);
13573 case 3: return FNIEMOP_CALL_1(iemOp_fistp_m16i, bRm);
13574 case 4: return FNIEMOP_CALL_1(iemOp_fbld_m80d, bRm);
13575 case 5: return FNIEMOP_CALL_1(iemOp_fild_m64i, bRm);
13576 case 6: return FNIEMOP_CALL_1(iemOp_fbstp_m80d, bRm);
13577 case 7: return FNIEMOP_CALL_1(iemOp_fistp_m64i, bRm);
13578 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13579 }
13580 }
13581}
13582
13583
13584/**
13585 * @opcode 0xe0
13586 * @opfltest zf
13587 */
13588FNIEMOP_DEF(iemOp_loopne_Jb)
13589{
13590 IEMOP_MNEMONIC(loopne_Jb, "loopne Jb");
13591 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
13592 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
13593
13594 switch (pVCpu->iem.s.enmEffAddrMode)
13595 {
13596 case IEMMODE_16BIT:
13597 IEM_MC_BEGIN(0, 0, IEM_MC_F_NOT_64BIT, 0);
13598 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13599 IEM_MC_IF_CX_IS_NOT_ONE_AND_EFL_BIT_NOT_SET(X86_EFL_ZF) {
13600 IEM_MC_SUB_GREG_U16(X86_GREG_xCX, 1);
13601 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13602 } IEM_MC_ELSE() {
13603 IEM_MC_SUB_GREG_U16(X86_GREG_xCX, 1);
13604 IEM_MC_ADVANCE_RIP_AND_FINISH();
13605 } IEM_MC_ENDIF();
13606 IEM_MC_END();
13607 break;
13608
13609 case IEMMODE_32BIT:
13610 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386, 0);
13611 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13612 IEM_MC_IF_ECX_IS_NOT_ONE_AND_EFL_BIT_NOT_SET(X86_EFL_ZF) {
13613 IEM_MC_SUB_GREG_U32(X86_GREG_xCX, 1);
13614 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13615 } IEM_MC_ELSE() {
13616 IEM_MC_SUB_GREG_U32(X86_GREG_xCX, 1);
13617 IEM_MC_ADVANCE_RIP_AND_FINISH();
13618 } IEM_MC_ENDIF();
13619 IEM_MC_END();
13620 break;
13621
13622 case IEMMODE_64BIT:
13623 IEM_MC_BEGIN(0, 0, IEM_MC_F_64BIT, 0);
13624 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13625 IEM_MC_IF_RCX_IS_NOT_ONE_AND_EFL_BIT_NOT_SET(X86_EFL_ZF) {
13626 IEM_MC_SUB_GREG_U64(X86_GREG_xCX, 1);
13627 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13628 } IEM_MC_ELSE() {
13629 IEM_MC_SUB_GREG_U64(X86_GREG_xCX, 1);
13630 IEM_MC_ADVANCE_RIP_AND_FINISH();
13631 } IEM_MC_ENDIF();
13632 IEM_MC_END();
13633 break;
13634
13635 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13636 }
13637}
13638
13639
13640/**
13641 * @opcode 0xe1
13642 * @opfltest zf
13643 */
13644FNIEMOP_DEF(iemOp_loope_Jb)
13645{
13646 IEMOP_MNEMONIC(loope_Jb, "loope Jb");
13647 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
13648 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
13649
13650 switch (pVCpu->iem.s.enmEffAddrMode)
13651 {
13652 case IEMMODE_16BIT:
13653 IEM_MC_BEGIN(0, 0, IEM_MC_F_NOT_64BIT, 0);
13654 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13655 IEM_MC_IF_CX_IS_NOT_ONE_AND_EFL_BIT_SET(X86_EFL_ZF) {
13656 IEM_MC_SUB_GREG_U16(X86_GREG_xCX, 1);
13657 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13658 } IEM_MC_ELSE() {
13659 IEM_MC_SUB_GREG_U16(X86_GREG_xCX, 1);
13660 IEM_MC_ADVANCE_RIP_AND_FINISH();
13661 } IEM_MC_ENDIF();
13662 IEM_MC_END();
13663 break;
13664
13665 case IEMMODE_32BIT:
13666 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386, 0);
13667 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13668 IEM_MC_IF_ECX_IS_NOT_ONE_AND_EFL_BIT_SET(X86_EFL_ZF) {
13669 IEM_MC_SUB_GREG_U32(X86_GREG_xCX, 1);
13670 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13671 } IEM_MC_ELSE() {
13672 IEM_MC_SUB_GREG_U32(X86_GREG_xCX, 1);
13673 IEM_MC_ADVANCE_RIP_AND_FINISH();
13674 } IEM_MC_ENDIF();
13675 IEM_MC_END();
13676 break;
13677
13678 case IEMMODE_64BIT:
13679 IEM_MC_BEGIN(0, 0, IEM_MC_F_64BIT, 0);
13680 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13681 IEM_MC_IF_RCX_IS_NOT_ONE_AND_EFL_BIT_SET(X86_EFL_ZF) {
13682 IEM_MC_SUB_GREG_U64(X86_GREG_xCX, 1);
13683 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13684 } IEM_MC_ELSE() {
13685 IEM_MC_SUB_GREG_U64(X86_GREG_xCX, 1);
13686 IEM_MC_ADVANCE_RIP_AND_FINISH();
13687 } IEM_MC_ENDIF();
13688 IEM_MC_END();
13689 break;
13690
13691 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13692 }
13693}
13694
13695
13696/**
13697 * @opcode 0xe2
13698 */
13699FNIEMOP_DEF(iemOp_loop_Jb)
13700{
13701 IEMOP_MNEMONIC(loop_Jb, "loop Jb");
13702 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
13703 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
13704
13705 /** @todo Check out the \#GP case if EIP < CS.Base or EIP > CS.Limit when
13706 * using the 32-bit operand size override. How can that be restarted? See
13707 * weird pseudo code in intel manual. */
13708
13709 /* NB: At least Windows for Workgroups 3.11 (NDIS.386) and Windows 95 (NDIS.VXD, IOS)
13710 * use LOOP $-2 to implement NdisStallExecution and other CPU stall APIs. Shortcutting
13711 * the loop causes guest crashes, but when logging it's nice to skip a few million
13712 * lines of useless output. */
13713#if defined(LOG_ENABLED)
13714 if ((LogIs3Enabled() || LogIs4Enabled()) && -(int8_t)IEM_GET_INSTR_LEN(pVCpu) == i8Imm)
13715 switch (pVCpu->iem.s.enmEffAddrMode)
13716 {
13717 case IEMMODE_16BIT:
13718 IEM_MC_BEGIN(0, 0, IEM_MC_F_NOT_64BIT, 0);
13719 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13720 IEM_MC_STORE_GREG_U16_CONST(X86_GREG_xCX, 0);
13721 IEM_MC_ADVANCE_RIP_AND_FINISH();
13722 IEM_MC_END();
13723 break;
13724
13725 case IEMMODE_32BIT:
13726 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386, 0);
13727 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13728 IEM_MC_STORE_GREG_U32_CONST(X86_GREG_xCX, 0);
13729 IEM_MC_ADVANCE_RIP_AND_FINISH();
13730 IEM_MC_END();
13731 break;
13732
13733 case IEMMODE_64BIT:
13734 IEM_MC_BEGIN(0, 0, IEM_MC_F_64BIT, 0);
13735 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13736 IEM_MC_STORE_GREG_U64_CONST(X86_GREG_xCX, 0);
13737 IEM_MC_ADVANCE_RIP_AND_FINISH();
13738 IEM_MC_END();
13739 break;
13740
13741 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13742 }
13743#endif
13744
13745 switch (pVCpu->iem.s.enmEffAddrMode)
13746 {
13747 case IEMMODE_16BIT:
13748 IEM_MC_BEGIN(0, 0, IEM_MC_F_NOT_64BIT, 0);
13749 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13750 IEM_MC_IF_CX_IS_NOT_ONE() {
13751 IEM_MC_SUB_GREG_U16(X86_GREG_xCX, 1);
13752 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13753 } IEM_MC_ELSE() {
13754 IEM_MC_STORE_GREG_U16_CONST(X86_GREG_xCX, 0);
13755 IEM_MC_ADVANCE_RIP_AND_FINISH();
13756 } IEM_MC_ENDIF();
13757 IEM_MC_END();
13758 break;
13759
13760 case IEMMODE_32BIT:
13761 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386, 0);
13762 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13763 IEM_MC_IF_ECX_IS_NOT_ONE() {
13764 IEM_MC_SUB_GREG_U32(X86_GREG_xCX, 1);
13765 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13766 } IEM_MC_ELSE() {
13767 IEM_MC_STORE_GREG_U32_CONST(X86_GREG_xCX, 0);
13768 IEM_MC_ADVANCE_RIP_AND_FINISH();
13769 } IEM_MC_ENDIF();
13770 IEM_MC_END();
13771 break;
13772
13773 case IEMMODE_64BIT:
13774 IEM_MC_BEGIN(0, 0, IEM_MC_F_64BIT, 0);
13775 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13776 IEM_MC_IF_RCX_IS_NOT_ONE() {
13777 IEM_MC_SUB_GREG_U64(X86_GREG_xCX, 1);
13778 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13779 } IEM_MC_ELSE() {
13780 IEM_MC_STORE_GREG_U64_CONST(X86_GREG_xCX, 0);
13781 IEM_MC_ADVANCE_RIP_AND_FINISH();
13782 } IEM_MC_ENDIF();
13783 IEM_MC_END();
13784 break;
13785
13786 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13787 }
13788}
13789
13790
13791/**
13792 * @opcode 0xe3
13793 */
13794FNIEMOP_DEF(iemOp_jecxz_Jb)
13795{
13796 IEMOP_MNEMONIC(jecxz_Jb, "jecxz Jb");
13797 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
13798 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
13799
13800 switch (pVCpu->iem.s.enmEffAddrMode)
13801 {
13802 case IEMMODE_16BIT:
13803 IEM_MC_BEGIN(0, 0, IEM_MC_F_NOT_64BIT, 0);
13804 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13805 IEM_MC_IF_CX_IS_NZ() {
13806 IEM_MC_ADVANCE_RIP_AND_FINISH();
13807 } IEM_MC_ELSE() {
13808 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13809 } IEM_MC_ENDIF();
13810 IEM_MC_END();
13811 break;
13812
13813 case IEMMODE_32BIT:
13814 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386, 0);
13815 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13816 IEM_MC_IF_ECX_IS_NZ() {
13817 IEM_MC_ADVANCE_RIP_AND_FINISH();
13818 } IEM_MC_ELSE() {
13819 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13820 } IEM_MC_ENDIF();
13821 IEM_MC_END();
13822 break;
13823
13824 case IEMMODE_64BIT:
13825 IEM_MC_BEGIN(0, 0, IEM_MC_F_64BIT, 0);
13826 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13827 IEM_MC_IF_RCX_IS_NZ() {
13828 IEM_MC_ADVANCE_RIP_AND_FINISH();
13829 } IEM_MC_ELSE() {
13830 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13831 } IEM_MC_ENDIF();
13832 IEM_MC_END();
13833 break;
13834
13835 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13836 }
13837}
13838
13839
13840/**
13841 * @opcode 0xe4
13842 * @opfltest iopl
13843 */
13844FNIEMOP_DEF(iemOp_in_AL_Ib)
13845{
13846 IEMOP_MNEMONIC(in_AL_Ib, "in AL,Ib");
13847 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
13848 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13849 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX),
13850 iemCImpl_in, u8Imm, 1, 0x80 /* fImm */ | pVCpu->iem.s.enmEffAddrMode);
13851}
13852
13853
13854/**
13855 * @opcode 0xe5
13856 * @opfltest iopl
13857 */
13858FNIEMOP_DEF(iemOp_in_eAX_Ib)
13859{
13860 IEMOP_MNEMONIC(in_eAX_Ib, "in eAX,Ib");
13861 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
13862 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13863 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO, RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX),
13864 iemCImpl_in, u8Imm, pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT ? 2 : 4,
13865 0x80 /* fImm */ | pVCpu->iem.s.enmEffAddrMode);
13866}
13867
13868
13869/**
13870 * @opcode 0xe6
13871 * @opfltest iopl
13872 */
13873FNIEMOP_DEF(iemOp_out_Ib_AL)
13874{
13875 IEMOP_MNEMONIC(out_Ib_AL, "out Ib,AL");
13876 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
13877 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13878 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO, 0,
13879 iemCImpl_out, u8Imm, 1, 0x80 /* fImm */ | pVCpu->iem.s.enmEffAddrMode);
13880}
13881
13882
13883/**
13884 * @opcode 0xe7
13885 * @opfltest iopl
13886 */
13887FNIEMOP_DEF(iemOp_out_Ib_eAX)
13888{
13889 IEMOP_MNEMONIC(out_Ib_eAX, "out Ib,eAX");
13890 uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
13891 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13892 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO, 0,
13893 iemCImpl_out, u8Imm, pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT ? 2 : 4,
13894 0x80 /* fImm */ | pVCpu->iem.s.enmEffAddrMode);
13895}
13896
13897
13898/**
13899 * @opcode 0xe8
13900 */
13901FNIEMOP_DEF(iemOp_call_Jv)
13902{
13903 IEMOP_MNEMONIC(call_Jv, "call Jv");
13904 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
13905 switch (pVCpu->iem.s.enmEffOpSize)
13906 {
13907 case IEMMODE_16BIT:
13908 {
13909 uint16_t u16Imm; IEM_OPCODE_GET_NEXT_U16(&u16Imm);
13910 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_BRANCH_RELATIVE | IEM_CIMPL_F_BRANCH_STACK, 0,
13911 iemCImpl_call_rel_16, (int16_t)u16Imm);
13912 }
13913
13914 case IEMMODE_32BIT:
13915 {
13916 uint32_t u32Imm; IEM_OPCODE_GET_NEXT_U32(&u32Imm);
13917 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_BRANCH_RELATIVE | IEM_CIMPL_F_BRANCH_STACK, 0,
13918 iemCImpl_call_rel_32, (int32_t)u32Imm);
13919 }
13920
13921 case IEMMODE_64BIT:
13922 {
13923 uint64_t u64Imm; IEM_OPCODE_GET_NEXT_S32_SX_U64(&u64Imm);
13924 IEM_MC_DEFER_TO_CIMPL_1_RET(IEM_CIMPL_F_BRANCH_RELATIVE | IEM_CIMPL_F_BRANCH_STACK, 0,
13925 iemCImpl_call_rel_64, u64Imm);
13926 }
13927
13928 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13929 }
13930}
13931
13932
13933/**
13934 * @opcode 0xe9
13935 */
13936FNIEMOP_DEF(iemOp_jmp_Jv)
13937{
13938 IEMOP_MNEMONIC(jmp_Jv, "jmp Jv");
13939 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
13940 switch (pVCpu->iem.s.enmEffOpSize)
13941 {
13942 case IEMMODE_16BIT:
13943 IEM_MC_BEGIN(0, 0, 0, 0);
13944 int16_t i16Imm; IEM_OPCODE_GET_NEXT_S16(&i16Imm);
13945 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13946 IEM_MC_REL_JMP_S16_AND_FINISH(i16Imm);
13947 IEM_MC_END();
13948 break;
13949
13950 case IEMMODE_64BIT:
13951 case IEMMODE_32BIT:
13952 IEM_MC_BEGIN(0, 0, IEM_MC_F_MIN_386, 0);
13953 int32_t i32Imm; IEM_OPCODE_GET_NEXT_S32(&i32Imm);
13954 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13955 IEM_MC_REL_JMP_S32_AND_FINISH(i32Imm);
13956 IEM_MC_END();
13957 break;
13958
13959 IEM_NOT_REACHED_DEFAULT_CASE_RET();
13960 }
13961}
13962
13963
13964/**
13965 * @opcode 0xea
13966 */
13967FNIEMOP_DEF(iemOp_jmp_Ap)
13968{
13969 IEMOP_MNEMONIC(jmp_Ap, "jmp Ap");
13970 IEMOP_HLP_NO_64BIT();
13971
13972 /* Decode the far pointer address and pass it on to the far call C implementation. */
13973 uint32_t off32Seg;
13974 if (pVCpu->iem.s.enmEffOpSize != IEMMODE_16BIT)
13975 IEM_OPCODE_GET_NEXT_U32(&off32Seg);
13976 else
13977 IEM_OPCODE_GET_NEXT_U16_ZX_U32(&off32Seg);
13978 uint16_t u16Sel; IEM_OPCODE_GET_NEXT_U16(&u16Sel);
13979 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13980 IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_BRANCH_DIRECT | IEM_CIMPL_F_BRANCH_FAR
13981 | IEM_CIMPL_F_MODE | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_VMEXIT, UINT64_MAX,
13982 iemCImpl_FarJmp, u16Sel, off32Seg, pVCpu->iem.s.enmEffOpSize);
13983 /** @todo make task-switches, ring-switches, ++ return non-zero status */
13984}
13985
13986
13987/**
13988 * @opcode 0xeb
13989 */
13990FNIEMOP_DEF(iemOp_jmp_Jb)
13991{
13992 IEMOP_MNEMONIC(jmp_Jb, "jmp Jb");
13993 int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
13994 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
13995
13996 IEM_MC_BEGIN(0, 0, 0, 0);
13997 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
13998 IEM_MC_REL_JMP_S8_AND_FINISH(i8Imm);
13999 IEM_MC_END();
14000}
14001
14002
14003/**
14004 * @opcode 0xec
14005 * @opfltest iopl
14006 */
14007FNIEMOP_DEF(iemOp_in_AL_DX)
14008{
14009 IEMOP_MNEMONIC(in_AL_DX, "in AL,DX");
14010 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14011 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
14012 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX),
14013 iemCImpl_in_eAX_DX, 1, pVCpu->iem.s.enmEffAddrMode);
14014}
14015
14016
14017/**
14018 * @opcode 0xed
14019 * @opfltest iopl
14020 */
14021FNIEMOP_DEF(iemOp_in_eAX_DX)
14022{
14023 IEMOP_MNEMONIC(in_eAX_DX, "in eAX,DX");
14024 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14025 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO,
14026 RT_BIT_64(kIemNativeGstReg_GprFirst + X86_GREG_xAX),
14027 iemCImpl_in_eAX_DX, pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT ? 2 : 4,
14028 pVCpu->iem.s.enmEffAddrMode);
14029}
14030
14031
14032/**
14033 * @opcode 0xee
14034 * @opfltest iopl
14035 */
14036FNIEMOP_DEF(iemOp_out_DX_AL)
14037{
14038 IEMOP_MNEMONIC(out_DX_AL, "out DX,AL");
14039 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14040 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO, 0,
14041 iemCImpl_out_DX_eAX, 1, pVCpu->iem.s.enmEffAddrMode);
14042}
14043
14044
14045/**
14046 * @opcode 0xef
14047 * @opfltest iopl
14048 */
14049FNIEMOP_DEF(iemOp_out_DX_eAX)
14050{
14051 IEMOP_MNEMONIC(out_DX_eAX, "out DX,eAX");
14052 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14053 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_IO, 0,
14054 iemCImpl_out_DX_eAX, pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT ? 2 : 4,
14055 pVCpu->iem.s.enmEffAddrMode);
14056}
14057
14058
14059/**
14060 * @opcode 0xf0
14061 */
14062FNIEMOP_DEF(iemOp_lock)
14063{
14064 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("lock");
14065 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_LOCK;
14066
14067 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
14068 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
14069}
14070
14071
14072/**
14073 * @opcode 0xf1
14074 */
14075FNIEMOP_DEF(iemOp_int1)
14076{
14077 IEMOP_MNEMONIC(int1, "int1"); /* icebp */
14078 /** @todo Does not generate \#UD on 286, or so they say... Was allegedly a
14079 * prefix byte on 8086 and/or/maybe 80286 without meaning according to the 286
14080 * LOADALL memo. Needs some testing. */
14081 IEMOP_HLP_MIN_386();
14082 /** @todo testcase! */
14083 IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_STACK_FAR
14084 | IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_END_TB, 0,
14085 iemCImpl_int, X86_XCPT_DB, IEMINT_INT1);
14086}
14087
14088
14089/**
14090 * @opcode 0xf2
14091 */
14092FNIEMOP_DEF(iemOp_repne)
14093{
14094 /* This overrides any previous REPE prefix. */
14095 pVCpu->iem.s.fPrefixes &= ~IEM_OP_PRF_REPZ;
14096 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("repne");
14097 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REPNZ;
14098
14099 /* For the 4 entry opcode tables, REPNZ overrides any previous
14100 REPZ and operand size prefixes. */
14101 pVCpu->iem.s.idxPrefix = 3;
14102
14103 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
14104 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
14105}
14106
14107
14108/**
14109 * @opcode 0xf3
14110 */
14111FNIEMOP_DEF(iemOp_repe)
14112{
14113 /* This overrides any previous REPNE prefix. */
14114 pVCpu->iem.s.fPrefixes &= ~IEM_OP_PRF_REPNZ;
14115 IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("repe");
14116 pVCpu->iem.s.fPrefixes |= IEM_OP_PRF_REPZ;
14117
14118 /* For the 4 entry opcode tables, REPNZ overrides any previous
14119 REPNZ and operand size prefixes. */
14120 pVCpu->iem.s.idxPrefix = 2;
14121
14122 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
14123 return FNIEMOP_CALL(g_apfnOneByteMap[b]);
14124}
14125
14126
14127/**
14128 * @opcode 0xf4
14129 */
14130FNIEMOP_DEF(iemOp_hlt)
14131{
14132 IEMOP_MNEMONIC(hlt, "hlt");
14133 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14134 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_END_TB | IEM_CIMPL_F_VMEXIT, 0, iemCImpl_hlt);
14135}
14136
14137
14138/**
14139 * @opcode 0xf5
14140 * @opflmodify cf
14141 */
14142FNIEMOP_DEF(iemOp_cmc)
14143{
14144 IEMOP_MNEMONIC(cmc, "cmc");
14145 IEM_MC_BEGIN(0, 0, 0, 0);
14146 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14147 IEM_MC_FLIP_EFL_BIT(X86_EFL_CF);
14148 IEM_MC_ADVANCE_RIP_AND_FINISH();
14149 IEM_MC_END();
14150}
14151
14152
14153/**
14154 * Body for of 'inc/dec/not/neg Eb'.
14155 */
14156#define IEMOP_BODY_UNARY_Eb(a_bRm, a_fnNormalU8, a_fnLockedU8) \
14157 if (IEM_IS_MODRM_REG_MODE(a_bRm)) \
14158 { \
14159 /* register access */ \
14160 IEM_MC_BEGIN(2, 0, 0, 0); \
14161 IEMOP_HLP_DONE_DECODING(); \
14162 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
14163 IEM_MC_ARG(uint32_t *, pEFlags, 1); \
14164 IEM_MC_REF_GREG_U8(pu8Dst, IEM_GET_MODRM_RM(pVCpu, a_bRm)); \
14165 IEM_MC_REF_EFLAGS(pEFlags); \
14166 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU8, pu8Dst, pEFlags); \
14167 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14168 IEM_MC_END(); \
14169 } \
14170 else \
14171 { \
14172 /* memory access. */ \
14173 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
14174 { \
14175 IEM_MC_BEGIN(2, 2, 0, 0); \
14176 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
14177 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 1); \
14178 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14179 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
14180 \
14181 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
14182 IEMOP_HLP_DONE_DECODING(); \
14183 IEM_MC_MEM_MAP_U8_RW(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14184 IEM_MC_FETCH_EFLAGS(EFlags); \
14185 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU8, pu8Dst, pEFlags); \
14186 \
14187 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
14188 IEM_MC_COMMIT_EFLAGS(EFlags); \
14189 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14190 IEM_MC_END(); \
14191 } \
14192 else \
14193 { \
14194 IEM_MC_BEGIN(2, 2, 0, 0); \
14195 IEM_MC_ARG(uint8_t *, pu8Dst, 0); \
14196 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 1); \
14197 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14198 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
14199 \
14200 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, a_bRm, 0); \
14201 IEMOP_HLP_DONE_DECODING(); \
14202 IEM_MC_MEM_MAP_U8_ATOMIC(pu8Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14203 IEM_MC_FETCH_EFLAGS(EFlags); \
14204 IEM_MC_CALL_VOID_AIMPL_2(a_fnLockedU8, pu8Dst, pEFlags); \
14205 \
14206 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
14207 IEM_MC_COMMIT_EFLAGS(EFlags); \
14208 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14209 IEM_MC_END(); \
14210 } \
14211 } \
14212 (void)0
14213
14214
14215/**
14216 * Body for 'inc/dec/not/neg Ev' (groups 3 and 5).
14217 */
14218#define IEMOP_BODY_UNARY_Ev(a_fnNormalU16, a_fnNormalU32, a_fnNormalU64) \
14219 if (IEM_IS_MODRM_REG_MODE(bRm)) \
14220 { \
14221 /* \
14222 * Register target \
14223 */ \
14224 switch (pVCpu->iem.s.enmEffOpSize) \
14225 { \
14226 case IEMMODE_16BIT: \
14227 IEM_MC_BEGIN(2, 0, 0, 0); \
14228 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14229 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
14230 IEM_MC_ARG(uint32_t *, pEFlags, 1); \
14231 IEM_MC_REF_GREG_U16(pu16Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
14232 IEM_MC_REF_EFLAGS(pEFlags); \
14233 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU16, pu16Dst, pEFlags); \
14234 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14235 IEM_MC_END(); \
14236 break; \
14237 \
14238 case IEMMODE_32BIT: \
14239 IEM_MC_BEGIN(2, 0, IEM_MC_F_MIN_386, 0); \
14240 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14241 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
14242 IEM_MC_ARG(uint32_t *, pEFlags, 1); \
14243 IEM_MC_REF_GREG_U32(pu32Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
14244 IEM_MC_REF_EFLAGS(pEFlags); \
14245 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU32, pu32Dst, pEFlags); \
14246 IEM_MC_CLEAR_HIGH_GREG_U64(IEM_GET_MODRM_RM(pVCpu, bRm)); \
14247 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14248 IEM_MC_END(); \
14249 break; \
14250 \
14251 case IEMMODE_64BIT: \
14252 IEM_MC_BEGIN(2, 0, IEM_MC_F_64BIT, 0); \
14253 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14254 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
14255 IEM_MC_ARG(uint32_t *, pEFlags, 1); \
14256 IEM_MC_REF_GREG_U64(pu64Dst, IEM_GET_MODRM_RM(pVCpu, bRm)); \
14257 IEM_MC_REF_EFLAGS(pEFlags); \
14258 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU64, pu64Dst, pEFlags); \
14259 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14260 IEM_MC_END(); \
14261 break; \
14262 \
14263 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
14264 } \
14265 } \
14266 else \
14267 { \
14268 /* \
14269 * Memory target. \
14270 */ \
14271 if (!(pVCpu->iem.s.fPrefixes & IEM_OP_PRF_LOCK) || (pVCpu->iem.s.fExec & IEM_F_X86_DISREGARD_LOCK)) \
14272 { \
14273 switch (pVCpu->iem.s.enmEffOpSize) \
14274 { \
14275 case IEMMODE_16BIT: \
14276 IEM_MC_BEGIN(2, 3, 0, 0); \
14277 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
14278 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 1); \
14279 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14280 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
14281 \
14282 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14283 IEMOP_HLP_DONE_DECODING(); \
14284 IEM_MC_MEM_MAP_U16_RW(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14285 IEM_MC_FETCH_EFLAGS(EFlags); \
14286 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU16, pu16Dst, pEFlags); \
14287 \
14288 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
14289 IEM_MC_COMMIT_EFLAGS(EFlags); \
14290 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14291 IEM_MC_END(); \
14292 break; \
14293 \
14294 case IEMMODE_32BIT: \
14295 IEM_MC_BEGIN(2, 3, IEM_MC_F_MIN_386, 0); \
14296 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
14297 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 1); \
14298 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14299 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
14300 \
14301 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14302 IEMOP_HLP_DONE_DECODING(); \
14303 IEM_MC_MEM_MAP_U32_RW(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14304 IEM_MC_FETCH_EFLAGS(EFlags); \
14305 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU32, pu32Dst, pEFlags); \
14306 \
14307 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
14308 IEM_MC_COMMIT_EFLAGS(EFlags); \
14309 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14310 IEM_MC_END(); \
14311 break; \
14312 \
14313 case IEMMODE_64BIT: \
14314 IEM_MC_BEGIN(2, 3, IEM_MC_F_64BIT, 0); \
14315 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
14316 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 1); \
14317 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14318 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
14319 \
14320 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14321 IEMOP_HLP_DONE_DECODING(); \
14322 IEM_MC_MEM_MAP_U64_RW(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14323 IEM_MC_FETCH_EFLAGS(EFlags); \
14324 IEM_MC_CALL_VOID_AIMPL_2(a_fnNormalU64, pu64Dst, pEFlags); \
14325 \
14326 IEM_MC_MEM_COMMIT_AND_UNMAP_RW(bUnmapInfo); \
14327 IEM_MC_COMMIT_EFLAGS(EFlags); \
14328 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14329 IEM_MC_END(); \
14330 break; \
14331 \
14332 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
14333 } \
14334 } \
14335 else \
14336 { \
14337 (void)0
14338
14339#define IEMOP_BODY_UNARY_Ev_LOCKED(a_fnLockedU16, a_fnLockedU32, a_fnLockedU64) \
14340 switch (pVCpu->iem.s.enmEffOpSize) \
14341 { \
14342 case IEMMODE_16BIT: \
14343 IEM_MC_BEGIN(2, 3, 0, 0); \
14344 IEM_MC_ARG(uint16_t *, pu16Dst, 0); \
14345 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 1); \
14346 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14347 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
14348 \
14349 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14350 IEMOP_HLP_DONE_DECODING(); \
14351 IEM_MC_MEM_MAP_U16_ATOMIC(pu16Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14352 IEM_MC_FETCH_EFLAGS(EFlags); \
14353 IEM_MC_CALL_VOID_AIMPL_2(a_fnLockedU16, pu16Dst, pEFlags); \
14354 \
14355 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
14356 IEM_MC_COMMIT_EFLAGS(EFlags); \
14357 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14358 IEM_MC_END(); \
14359 break; \
14360 \
14361 case IEMMODE_32BIT: \
14362 IEM_MC_BEGIN(2, 3, IEM_MC_F_MIN_386, 0); \
14363 IEM_MC_ARG(uint32_t *, pu32Dst, 0); \
14364 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 1); \
14365 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14366 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
14367 \
14368 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14369 IEMOP_HLP_DONE_DECODING(); \
14370 IEM_MC_MEM_MAP_U32_ATOMIC(pu32Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14371 IEM_MC_FETCH_EFLAGS(EFlags); \
14372 IEM_MC_CALL_VOID_AIMPL_2(a_fnLockedU32, pu32Dst, pEFlags); \
14373 \
14374 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
14375 IEM_MC_COMMIT_EFLAGS(EFlags); \
14376 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14377 IEM_MC_END(); \
14378 break; \
14379 \
14380 case IEMMODE_64BIT: \
14381 IEM_MC_BEGIN(2, 3, IEM_MC_F_64BIT, 0); \
14382 IEM_MC_ARG(uint64_t *, pu64Dst, 0); \
14383 IEM_MC_ARG_LOCAL_EFLAGS( pEFlags, EFlags, 1); \
14384 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14385 IEM_MC_LOCAL(uint8_t, bUnmapInfo); \
14386 \
14387 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14388 IEMOP_HLP_DONE_DECODING(); \
14389 IEM_MC_MEM_MAP_U64_ATOMIC(pu64Dst, bUnmapInfo, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14390 IEM_MC_FETCH_EFLAGS(EFlags); \
14391 IEM_MC_CALL_VOID_AIMPL_2(a_fnLockedU64, pu64Dst, pEFlags); \
14392 \
14393 IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC(bUnmapInfo); \
14394 IEM_MC_COMMIT_EFLAGS(EFlags); \
14395 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14396 IEM_MC_END(); \
14397 break; \
14398 \
14399 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
14400 } \
14401 } \
14402 } \
14403 (void)0
14404
14405
14406/**
14407 * @opmaps grp3_f6
14408 * @opcode /0
14409 * @opflclass logical
14410 * @todo also /1
14411 */
14412FNIEMOP_DEF_1(iemOp_grp3_test_Eb_Ib, uint8_t, bRm)
14413{
14414 IEMOP_MNEMONIC(test_Eb_Ib, "test Eb,Ib");
14415 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
14416 IEMOP_BODY_BINARY_Eb_Ib_RO(test, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
14417}
14418
14419
14420/* Body for opcode 0xf6 variations /4, /5, /6 and /7. */
14421#define IEMOP_GRP3_MUL_DIV_EB(bRm, a_pfnU8Expr) \
14422 PFNIEMAIMPLMULDIVU8 const pfnU8 = (a_pfnU8Expr); \
14423 if (IEM_IS_MODRM_REG_MODE(bRm)) \
14424 { \
14425 /* register access */ \
14426 IEM_MC_BEGIN(3, 1, 0, 0); \
14427 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14428 IEM_MC_ARG(uint16_t *, pu16AX, 0); \
14429 IEM_MC_ARG(uint8_t, u8Value, 1); \
14430 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
14431 IEM_MC_LOCAL(int32_t, rc); \
14432 \
14433 IEM_MC_FETCH_GREG_U8(u8Value, IEM_GET_MODRM_RM(pVCpu, bRm)); \
14434 IEM_MC_REF_GREG_U16(pu16AX, X86_GREG_xAX); \
14435 IEM_MC_REF_EFLAGS(pEFlags); \
14436 IEM_MC_CALL_AIMPL_3(rc, pfnU8, pu16AX, u8Value, pEFlags); \
14437 IEM_MC_IF_LOCAL_IS_Z(rc) { \
14438 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14439 } IEM_MC_ELSE() { \
14440 IEM_MC_RAISE_DIVIDE_ERROR(); \
14441 } IEM_MC_ENDIF(); \
14442 \
14443 IEM_MC_END(); \
14444 } \
14445 else \
14446 { \
14447 /* memory access. */ \
14448 IEM_MC_BEGIN(3, 2, 0, 0); \
14449 IEM_MC_ARG(uint16_t *, pu16AX, 0); \
14450 IEM_MC_ARG(uint8_t, u8Value, 1); \
14451 IEM_MC_ARG(uint32_t *, pEFlags, 2); \
14452 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14453 IEM_MC_LOCAL(int32_t, rc); \
14454 \
14455 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14456 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14457 IEM_MC_FETCH_MEM_U8(u8Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14458 IEM_MC_REF_GREG_U16(pu16AX, X86_GREG_xAX); \
14459 IEM_MC_REF_EFLAGS(pEFlags); \
14460 IEM_MC_CALL_AIMPL_3(rc, pfnU8, pu16AX, u8Value, pEFlags); \
14461 IEM_MC_IF_LOCAL_IS_Z(rc) { \
14462 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14463 } IEM_MC_ELSE() { \
14464 IEM_MC_RAISE_DIVIDE_ERROR(); \
14465 } IEM_MC_ENDIF(); \
14466 \
14467 IEM_MC_END(); \
14468 } (void)0
14469
14470
14471/* Body for opcode 0xf7 variant /4, /5, /6 and /7. */
14472#define IEMOP_BODY_GRP3_MUL_DIV_EV(bRm, a_pImplExpr) \
14473 PCIEMOPMULDIVSIZES const pImpl = (a_pImplExpr); \
14474 if (IEM_IS_MODRM_REG_MODE(bRm)) \
14475 { \
14476 /* register access */ \
14477 switch (pVCpu->iem.s.enmEffOpSize) \
14478 { \
14479 case IEMMODE_16BIT: \
14480 IEM_MC_BEGIN(4, 1, 0, 0); \
14481 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14482 IEM_MC_ARG(uint16_t *, pu16AX, 0); \
14483 IEM_MC_ARG(uint16_t *, pu16DX, 1); \
14484 IEM_MC_ARG(uint16_t, u16Value, 2); \
14485 IEM_MC_ARG(uint32_t *, pEFlags, 3); \
14486 IEM_MC_LOCAL(int32_t, rc); \
14487 \
14488 IEM_MC_FETCH_GREG_U16(u16Value, IEM_GET_MODRM_RM(pVCpu, bRm)); \
14489 IEM_MC_REF_GREG_U16(pu16AX, X86_GREG_xAX); \
14490 IEM_MC_REF_GREG_U16(pu16DX, X86_GREG_xDX); \
14491 IEM_MC_REF_EFLAGS(pEFlags); \
14492 IEM_MC_CALL_AIMPL_4(rc, pImpl->pfnU16, pu16AX, pu16DX, u16Value, pEFlags); \
14493 IEM_MC_IF_LOCAL_IS_Z(rc) { \
14494 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14495 } IEM_MC_ELSE() { \
14496 IEM_MC_RAISE_DIVIDE_ERROR(); \
14497 } IEM_MC_ENDIF(); \
14498 \
14499 IEM_MC_END(); \
14500 break; \
14501 \
14502 case IEMMODE_32BIT: \
14503 IEM_MC_BEGIN(4, 1, IEM_MC_F_MIN_386, 0); \
14504 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14505 IEM_MC_ARG(uint32_t *, pu32AX, 0); \
14506 IEM_MC_ARG(uint32_t *, pu32DX, 1); \
14507 IEM_MC_ARG(uint32_t, u32Value, 2); \
14508 IEM_MC_ARG(uint32_t *, pEFlags, 3); \
14509 IEM_MC_LOCAL(int32_t, rc); \
14510 \
14511 IEM_MC_FETCH_GREG_U32(u32Value, IEM_GET_MODRM_RM(pVCpu, bRm)); \
14512 IEM_MC_REF_GREG_U32(pu32AX, X86_GREG_xAX); \
14513 IEM_MC_REF_GREG_U32(pu32DX, X86_GREG_xDX); \
14514 IEM_MC_REF_EFLAGS(pEFlags); \
14515 IEM_MC_CALL_AIMPL_4(rc, pImpl->pfnU32, pu32AX, pu32DX, u32Value, pEFlags); \
14516 IEM_MC_IF_LOCAL_IS_Z(rc) { \
14517 IEM_MC_CLEAR_HIGH_GREG_U64(X86_GREG_xAX); \
14518 IEM_MC_CLEAR_HIGH_GREG_U64(X86_GREG_xDX); \
14519 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14520 } IEM_MC_ELSE() { \
14521 IEM_MC_RAISE_DIVIDE_ERROR(); \
14522 } IEM_MC_ENDIF(); \
14523 \
14524 IEM_MC_END(); \
14525 break; \
14526 \
14527 case IEMMODE_64BIT: \
14528 IEM_MC_BEGIN(4, 1, IEM_MC_F_64BIT, 0); \
14529 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14530 IEM_MC_ARG(uint64_t *, pu64AX, 0); \
14531 IEM_MC_ARG(uint64_t *, pu64DX, 1); \
14532 IEM_MC_ARG(uint64_t, u64Value, 2); \
14533 IEM_MC_ARG(uint32_t *, pEFlags, 3); \
14534 IEM_MC_LOCAL(int32_t, rc); \
14535 \
14536 IEM_MC_FETCH_GREG_U64(u64Value, IEM_GET_MODRM_RM(pVCpu, bRm)); \
14537 IEM_MC_REF_GREG_U64(pu64AX, X86_GREG_xAX); \
14538 IEM_MC_REF_GREG_U64(pu64DX, X86_GREG_xDX); \
14539 IEM_MC_REF_EFLAGS(pEFlags); \
14540 IEM_MC_CALL_AIMPL_4(rc, pImpl->pfnU64, pu64AX, pu64DX, u64Value, pEFlags); \
14541 IEM_MC_IF_LOCAL_IS_Z(rc) { \
14542 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14543 } IEM_MC_ELSE() { \
14544 IEM_MC_RAISE_DIVIDE_ERROR(); \
14545 } IEM_MC_ENDIF(); \
14546 \
14547 IEM_MC_END(); \
14548 break; \
14549 \
14550 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
14551 } \
14552 } \
14553 else \
14554 { \
14555 /* memory access. */ \
14556 switch (pVCpu->iem.s.enmEffOpSize) \
14557 { \
14558 case IEMMODE_16BIT: \
14559 IEM_MC_BEGIN(4, 2, 0, 0); \
14560 IEM_MC_ARG(uint16_t *, pu16AX, 0); \
14561 IEM_MC_ARG(uint16_t *, pu16DX, 1); \
14562 IEM_MC_ARG(uint16_t, u16Value, 2); \
14563 IEM_MC_ARG(uint32_t *, pEFlags, 3); \
14564 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14565 IEM_MC_LOCAL(int32_t, rc); \
14566 \
14567 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14568 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14569 IEM_MC_FETCH_MEM_U16(u16Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14570 IEM_MC_REF_GREG_U16(pu16AX, X86_GREG_xAX); \
14571 IEM_MC_REF_GREG_U16(pu16DX, X86_GREG_xDX); \
14572 IEM_MC_REF_EFLAGS(pEFlags); \
14573 IEM_MC_CALL_AIMPL_4(rc, pImpl->pfnU16, pu16AX, pu16DX, u16Value, pEFlags); \
14574 IEM_MC_IF_LOCAL_IS_Z(rc) { \
14575 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14576 } IEM_MC_ELSE() { \
14577 IEM_MC_RAISE_DIVIDE_ERROR(); \
14578 } IEM_MC_ENDIF(); \
14579 \
14580 IEM_MC_END(); \
14581 break; \
14582 \
14583 case IEMMODE_32BIT: \
14584 IEM_MC_BEGIN(4, 2, IEM_MC_F_MIN_386, 0); \
14585 IEM_MC_ARG(uint32_t *, pu32AX, 0); \
14586 IEM_MC_ARG(uint32_t *, pu32DX, 1); \
14587 IEM_MC_ARG(uint32_t, u32Value, 2); \
14588 IEM_MC_ARG(uint32_t *, pEFlags, 3); \
14589 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14590 IEM_MC_LOCAL(int32_t, rc); \
14591 \
14592 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14593 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14594 IEM_MC_FETCH_MEM_U32(u32Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14595 IEM_MC_REF_GREG_U32(pu32AX, X86_GREG_xAX); \
14596 IEM_MC_REF_GREG_U32(pu32DX, X86_GREG_xDX); \
14597 IEM_MC_REF_EFLAGS(pEFlags); \
14598 IEM_MC_CALL_AIMPL_4(rc, pImpl->pfnU32, pu32AX, pu32DX, u32Value, pEFlags); \
14599 IEM_MC_IF_LOCAL_IS_Z(rc) { \
14600 IEM_MC_CLEAR_HIGH_GREG_U64(X86_GREG_xAX); \
14601 IEM_MC_CLEAR_HIGH_GREG_U64(X86_GREG_xDX); \
14602 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14603 } IEM_MC_ELSE() { \
14604 IEM_MC_RAISE_DIVIDE_ERROR(); \
14605 } IEM_MC_ENDIF(); \
14606 \
14607 IEM_MC_END(); \
14608 break; \
14609 \
14610 case IEMMODE_64BIT: \
14611 IEM_MC_BEGIN(4, 2, IEM_MC_F_64BIT, 0); \
14612 IEM_MC_ARG(uint64_t *, pu64AX, 0); \
14613 IEM_MC_ARG(uint64_t *, pu64DX, 1); \
14614 IEM_MC_ARG(uint64_t, u64Value, 2); \
14615 IEM_MC_ARG(uint32_t *, pEFlags, 3); \
14616 IEM_MC_LOCAL(RTGCPTR, GCPtrEffDst); \
14617 IEM_MC_LOCAL(int32_t, rc); \
14618 \
14619 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0); \
14620 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
14621 IEM_MC_FETCH_MEM_U64(u64Value, pVCpu->iem.s.iEffSeg, GCPtrEffDst); \
14622 IEM_MC_REF_GREG_U64(pu64AX, X86_GREG_xAX); \
14623 IEM_MC_REF_GREG_U64(pu64DX, X86_GREG_xDX); \
14624 IEM_MC_REF_EFLAGS(pEFlags); \
14625 IEM_MC_CALL_AIMPL_4(rc, pImpl->pfnU64, pu64AX, pu64DX, u64Value, pEFlags); \
14626 IEM_MC_IF_LOCAL_IS_Z(rc) { \
14627 IEM_MC_ADVANCE_RIP_AND_FINISH(); \
14628 } IEM_MC_ELSE() { \
14629 IEM_MC_RAISE_DIVIDE_ERROR(); \
14630 } IEM_MC_ENDIF(); \
14631 \
14632 IEM_MC_END(); \
14633 break; \
14634 \
14635 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
14636 } \
14637 } (void)0
14638
14639
14640/**
14641 * @opmaps grp3_f6
14642 * @opcode /2
14643 * @opflclass unchanged
14644 */
14645FNIEMOP_DEF_1(iemOp_grp3_not_Eb, uint8_t, bRm)
14646{
14647/** @todo does not modify EFLAGS. */
14648 IEMOP_MNEMONIC(not_Eb, "not Eb");
14649 IEMOP_BODY_UNARY_Eb(bRm, iemAImpl_not_u8, iemAImpl_not_u8_locked);
14650}
14651
14652
14653/**
14654 * @opmaps grp3_f6
14655 * @opcode /3
14656 * @opflclass arithmetic
14657 */
14658FNIEMOP_DEF_1(iemOp_grp3_neg_Eb, uint8_t, bRm)
14659{
14660 IEMOP_MNEMONIC(net_Eb, "neg Eb");
14661 IEMOP_BODY_UNARY_Eb(bRm, iemAImpl_neg_u8, iemAImpl_neg_u8_locked);
14662}
14663
14664
14665/**
14666 * @opcode 0xf6
14667 */
14668FNIEMOP_DEF(iemOp_Grp3_Eb)
14669{
14670 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
14671 switch (IEM_GET_MODRM_REG_8(bRm))
14672 {
14673 case 0:
14674 return FNIEMOP_CALL_1(iemOp_grp3_test_Eb_Ib, bRm);
14675 case 1:
14676 return FNIEMOP_CALL_1(iemOp_grp3_test_Eb_Ib, bRm);
14677 case 2:
14678 return FNIEMOP_CALL_1(iemOp_grp3_not_Eb, bRm);
14679 case 3:
14680 return FNIEMOP_CALL_1(iemOp_grp3_neg_Eb, bRm);
14681 case 4:
14682 {
14683 /**
14684 * @opdone
14685 * @opmaps grp3_f6
14686 * @opcode /4
14687 * @opflclass multiply
14688 */
14689 IEMOP_MNEMONIC(mul_Eb, "mul Eb");
14690 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
14691 IEMOP_GRP3_MUL_DIV_EB(bRm, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_mul_u8_eflags));
14692 break;
14693 }
14694 case 5:
14695 {
14696 /**
14697 * @opdone
14698 * @opmaps grp3_f6
14699 * @opcode /5
14700 * @opflclass multiply
14701 */
14702 IEMOP_MNEMONIC(imul_Eb, "imul Eb");
14703 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
14704 IEMOP_GRP3_MUL_DIV_EB(bRm, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_imul_u8_eflags));
14705 break;
14706 }
14707 case 6:
14708 {
14709 /**
14710 * @opdone
14711 * @opmaps grp3_f6
14712 * @opcode /6
14713 * @opflclass division
14714 */
14715 IEMOP_MNEMONIC(div_Eb, "div Eb");
14716 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_OF | X86_EFL_CF);
14717 IEMOP_GRP3_MUL_DIV_EB(bRm, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_div_u8_eflags));
14718 break;
14719 }
14720 case 7:
14721 {
14722 /**
14723 * @opdone
14724 * @opmaps grp3_f6
14725 * @opcode /7
14726 * @opflclass division
14727 */
14728 IEMOP_MNEMONIC(idiv_Eb, "idiv Eb");
14729 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_OF | X86_EFL_CF);
14730 IEMOP_GRP3_MUL_DIV_EB(bRm, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_idiv_u8_eflags));
14731 break;
14732 }
14733 IEM_NOT_REACHED_DEFAULT_CASE_RET();
14734 }
14735}
14736
14737
14738/**
14739 * @opmaps grp3_f7
14740 * @opcode /0
14741 * @opflclass logical
14742 */
14743FNIEMOP_DEF_1(iemOp_grp3_test_Ev_Iz, uint8_t, bRm)
14744{
14745 IEMOP_MNEMONIC(test_Ev_Iv, "test Ev,Iv");
14746 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_AF);
14747 IEMOP_BODY_BINARY_Ev_Iz_RO(test, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
14748}
14749
14750
14751/**
14752 * @opmaps grp3_f7
14753 * @opcode /2
14754 * @opflclass unchanged
14755 */
14756FNIEMOP_DEF_1(iemOp_grp3_not_Ev, uint8_t, bRm)
14757{
14758/** @todo does not modify EFLAGS */
14759 IEMOP_MNEMONIC(not_Ev, "not Ev");
14760 IEMOP_BODY_UNARY_Ev( iemAImpl_not_u16, iemAImpl_not_u32, iemAImpl_not_u64);
14761 IEMOP_BODY_UNARY_Ev_LOCKED(iemAImpl_not_u16_locked, iemAImpl_not_u32_locked, iemAImpl_not_u64_locked);
14762}
14763
14764
14765/**
14766 * @opmaps grp3_f7
14767 * @opcode /3
14768 * @opflclass arithmetic
14769 */
14770FNIEMOP_DEF_1(iemOp_grp3_neg_Ev, uint8_t, bRm)
14771{
14772 IEMOP_MNEMONIC(neg_Ev, "neg Ev");
14773 IEMOP_BODY_UNARY_Ev( iemAImpl_neg_u16, iemAImpl_neg_u32, iemAImpl_neg_u64);
14774 IEMOP_BODY_UNARY_Ev_LOCKED(iemAImpl_neg_u16_locked, iemAImpl_neg_u32_locked, iemAImpl_neg_u64_locked);
14775}
14776
14777
14778/**
14779 * @opmaps grp3_f7
14780 * @opcode /4
14781 * @opflclass multiply
14782 */
14783FNIEMOP_DEF_1(iemOp_grp3_mul_Ev, uint8_t, bRm)
14784{
14785 IEMOP_MNEMONIC(mul_Ev, "mul Ev");
14786 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
14787 IEMOP_BODY_GRP3_MUL_DIV_EV(bRm, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_mul_eflags));
14788}
14789
14790
14791/**
14792 * @opmaps grp3_f7
14793 * @opcode /5
14794 * @opflclass multiply
14795 */
14796FNIEMOP_DEF_1(iemOp_grp3_imul_Ev, uint8_t, bRm)
14797{
14798 IEMOP_MNEMONIC(imul_Ev, "imul Ev");
14799 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
14800 IEMOP_BODY_GRP3_MUL_DIV_EV(bRm, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_imul_eflags));
14801}
14802
14803
14804/**
14805 * @opmaps grp3_f7
14806 * @opcode /6
14807 * @opflclass division
14808 */
14809FNIEMOP_DEF_1(iemOp_grp3_div_Ev, uint8_t, bRm)
14810{
14811 IEMOP_MNEMONIC(div_Ev, "div Ev");
14812 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_OF | X86_EFL_CF);
14813 IEMOP_BODY_GRP3_MUL_DIV_EV(bRm, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_div_eflags));
14814}
14815
14816
14817/**
14818 * @opmaps grp3_f7
14819 * @opcode /7
14820 * @opflclass division
14821 */
14822FNIEMOP_DEF_1(iemOp_grp3_idiv_Ev, uint8_t, bRm)
14823{
14824 IEMOP_MNEMONIC(idiv_Ev, "idiv Ev");
14825 IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_OF | X86_EFL_CF);
14826 IEMOP_BODY_GRP3_MUL_DIV_EV(bRm, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_idiv_eflags));
14827}
14828
14829
14830/**
14831 * @opcode 0xf7
14832 */
14833FNIEMOP_DEF(iemOp_Grp3_Ev)
14834{
14835 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
14836 switch (IEM_GET_MODRM_REG_8(bRm))
14837 {
14838 case 0: return FNIEMOP_CALL_1(iemOp_grp3_test_Ev_Iz, bRm);
14839 case 1: return FNIEMOP_CALL_1(iemOp_grp3_test_Ev_Iz, bRm);
14840 case 2: return FNIEMOP_CALL_1(iemOp_grp3_not_Ev, bRm);
14841 case 3: return FNIEMOP_CALL_1(iemOp_grp3_neg_Ev, bRm);
14842 case 4: return FNIEMOP_CALL_1(iemOp_grp3_mul_Ev, bRm);
14843 case 5: return FNIEMOP_CALL_1(iemOp_grp3_imul_Ev, bRm);
14844 case 6: return FNIEMOP_CALL_1(iemOp_grp3_div_Ev, bRm);
14845 case 7: return FNIEMOP_CALL_1(iemOp_grp3_idiv_Ev, bRm);
14846 IEM_NOT_REACHED_DEFAULT_CASE_RET();
14847 }
14848}
14849
14850
14851/**
14852 * @opcode 0xf8
14853 * @opflmodify cf
14854 * @opflclear cf
14855 */
14856FNIEMOP_DEF(iemOp_clc)
14857{
14858 IEMOP_MNEMONIC(clc, "clc");
14859 IEM_MC_BEGIN(0, 0, 0, 0);
14860 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14861 IEM_MC_CLEAR_EFL_BIT(X86_EFL_CF);
14862 IEM_MC_ADVANCE_RIP_AND_FINISH();
14863 IEM_MC_END();
14864}
14865
14866
14867/**
14868 * @opcode 0xf9
14869 * @opflmodify cf
14870 * @opflset cf
14871 */
14872FNIEMOP_DEF(iemOp_stc)
14873{
14874 IEMOP_MNEMONIC(stc, "stc");
14875 IEM_MC_BEGIN(0, 0, 0, 0);
14876 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14877 IEM_MC_SET_EFL_BIT(X86_EFL_CF);
14878 IEM_MC_ADVANCE_RIP_AND_FINISH();
14879 IEM_MC_END();
14880}
14881
14882
14883/**
14884 * @opcode 0xfa
14885 * @opfltest iopl,vm
14886 * @opflmodify if,vif
14887 */
14888FNIEMOP_DEF(iemOp_cli)
14889{
14890 IEMOP_MNEMONIC(cli, "cli");
14891 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14892 IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_CHECK_IRQ_BEFORE, 0, iemCImpl_cli);
14893}
14894
14895
14896/**
14897 * @opcode 0xfb
14898 * @opfltest iopl,vm
14899 * @opflmodify if,vif
14900 */
14901FNIEMOP_DEF(iemOp_sti)
14902{
14903 IEMOP_MNEMONIC(sti, "sti");
14904 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14905 IEM_MC_DEFER_TO_CIMPL_0_RET( IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_CHECK_IRQ_AFTER
14906 | IEM_CIMPL_F_VMEXIT | IEM_CIMPL_F_INHIBIT_SHADOW, 0, iemCImpl_sti);
14907}
14908
14909
14910/**
14911 * @opcode 0xfc
14912 * @opflmodify df
14913 * @opflclear df
14914 */
14915FNIEMOP_DEF(iemOp_cld)
14916{
14917 IEMOP_MNEMONIC(cld, "cld");
14918 IEM_MC_BEGIN(0, 0, 0, 0);
14919 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14920 IEM_MC_CLEAR_EFL_BIT(X86_EFL_DF);
14921 IEM_MC_ADVANCE_RIP_AND_FINISH();
14922 IEM_MC_END();
14923}
14924
14925
14926/**
14927 * @opcode 0xfd
14928 * @opflmodify df
14929 * @opflset df
14930 */
14931FNIEMOP_DEF(iemOp_std)
14932{
14933 IEMOP_MNEMONIC(std, "std");
14934 IEM_MC_BEGIN(0, 0, 0, 0);
14935 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
14936 IEM_MC_SET_EFL_BIT(X86_EFL_DF);
14937 IEM_MC_ADVANCE_RIP_AND_FINISH();
14938 IEM_MC_END();
14939}
14940
14941
14942/**
14943 * @opmaps grp4
14944 * @opcode /0
14945 * @opflclass incdec
14946 */
14947FNIEMOP_DEF_1(iemOp_Grp4_inc_Eb, uint8_t, bRm)
14948{
14949 IEMOP_MNEMONIC(inc_Eb, "inc Eb");
14950 IEMOP_BODY_UNARY_Eb(bRm, iemAImpl_inc_u8, iemAImpl_inc_u8_locked);
14951}
14952
14953
14954/**
14955 * @opmaps grp4
14956 * @opcode /1
14957 * @opflclass incdec
14958 */
14959FNIEMOP_DEF_1(iemOp_Grp4_dec_Eb, uint8_t, bRm)
14960{
14961 IEMOP_MNEMONIC(dec_Eb, "dec Eb");
14962 IEMOP_BODY_UNARY_Eb(bRm, iemAImpl_dec_u8, iemAImpl_dec_u8_locked);
14963}
14964
14965
14966/**
14967 * @opcode 0xfe
14968 */
14969FNIEMOP_DEF(iemOp_Grp4)
14970{
14971 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
14972 switch (IEM_GET_MODRM_REG_8(bRm))
14973 {
14974 case 0: return FNIEMOP_CALL_1(iemOp_Grp4_inc_Eb, bRm);
14975 case 1: return FNIEMOP_CALL_1(iemOp_Grp4_dec_Eb, bRm);
14976 default:
14977 /** @todo is the eff-addr decoded? */
14978 IEMOP_MNEMONIC(grp4_ud, "grp4-ud");
14979 IEMOP_RAISE_INVALID_OPCODE_RET();
14980 }
14981}
14982
14983/**
14984 * @opmaps grp5
14985 * @opcode /0
14986 * @opflclass incdec
14987 */
14988FNIEMOP_DEF_1(iemOp_Grp5_inc_Ev, uint8_t, bRm)
14989{
14990 IEMOP_MNEMONIC(inc_Ev, "inc Ev");
14991 IEMOP_BODY_UNARY_Ev( iemAImpl_inc_u16, iemAImpl_inc_u32, iemAImpl_inc_u64);
14992 IEMOP_BODY_UNARY_Ev_LOCKED(iemAImpl_inc_u16_locked, iemAImpl_inc_u32_locked, iemAImpl_inc_u64_locked);
14993}
14994
14995
14996/**
14997 * @opmaps grp5
14998 * @opcode /1
14999 * @opflclass incdec
15000 */
15001FNIEMOP_DEF_1(iemOp_Grp5_dec_Ev, uint8_t, bRm)
15002{
15003 IEMOP_MNEMONIC(dec_Ev, "dec Ev");
15004 IEMOP_BODY_UNARY_Ev( iemAImpl_dec_u16, iemAImpl_dec_u32, iemAImpl_dec_u64);
15005 IEMOP_BODY_UNARY_Ev_LOCKED(iemAImpl_dec_u16_locked, iemAImpl_dec_u32_locked, iemAImpl_dec_u64_locked);
15006}
15007
15008
15009/**
15010 * Opcode 0xff /2.
15011 * @param bRm The RM byte.
15012 */
15013FNIEMOP_DEF_1(iemOp_Grp5_calln_Ev, uint8_t, bRm)
15014{
15015 IEMOP_MNEMONIC(calln_Ev, "calln Ev");
15016 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
15017
15018 if (IEM_IS_MODRM_REG_MODE(bRm))
15019 {
15020 /* The new RIP is taken from a register. */
15021 switch (pVCpu->iem.s.enmEffOpSize)
15022 {
15023 case IEMMODE_16BIT:
15024 IEM_MC_BEGIN(1, 0, 0, 0);
15025 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15026 IEM_MC_ARG(uint16_t, u16Target, 0);
15027 IEM_MC_FETCH_GREG_U16(u16Target, IEM_GET_MODRM_RM(pVCpu, bRm));
15028 IEM_MC_CALL_CIMPL_1(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK, 0, iemCImpl_call_16, u16Target);
15029 IEM_MC_END();
15030 break;
15031
15032 case IEMMODE_32BIT:
15033 IEM_MC_BEGIN(1, 0, IEM_MC_F_MIN_386, 0);
15034 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15035 IEM_MC_ARG(uint32_t, u32Target, 0);
15036 IEM_MC_FETCH_GREG_U32(u32Target, IEM_GET_MODRM_RM(pVCpu, bRm));
15037 IEM_MC_CALL_CIMPL_1(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK, 0, iemCImpl_call_32, u32Target);
15038 IEM_MC_END();
15039 break;
15040
15041 case IEMMODE_64BIT:
15042 IEM_MC_BEGIN(1, 0, IEM_MC_F_64BIT, 0);
15043 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15044 IEM_MC_ARG(uint64_t, u64Target, 0);
15045 IEM_MC_FETCH_GREG_U64(u64Target, IEM_GET_MODRM_RM(pVCpu, bRm));
15046 IEM_MC_CALL_CIMPL_1(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK, 0, iemCImpl_call_64, u64Target);
15047 IEM_MC_END();
15048 break;
15049
15050 IEM_NOT_REACHED_DEFAULT_CASE_RET();
15051 }
15052 }
15053 else
15054 {
15055 /* The new RIP is taken from a register. */
15056 switch (pVCpu->iem.s.enmEffOpSize)
15057 {
15058 case IEMMODE_16BIT:
15059 IEM_MC_BEGIN(1, 1, 0, 0);
15060 IEM_MC_ARG(uint16_t, u16Target, 0);
15061 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
15062 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
15063 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15064 IEM_MC_FETCH_MEM_U16(u16Target, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
15065 IEM_MC_CALL_CIMPL_1(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK, 0, iemCImpl_call_16, u16Target);
15066 IEM_MC_END();
15067 break;
15068
15069 case IEMMODE_32BIT:
15070 IEM_MC_BEGIN(1, 1, IEM_MC_F_MIN_386, 0);
15071 IEM_MC_ARG(uint32_t, u32Target, 0);
15072 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
15073 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
15074 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15075 IEM_MC_FETCH_MEM_U32(u32Target, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
15076 IEM_MC_CALL_CIMPL_1(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK, 0, iemCImpl_call_32, u32Target);
15077 IEM_MC_END();
15078 break;
15079
15080 case IEMMODE_64BIT:
15081 IEM_MC_BEGIN(1, 1, IEM_MC_F_64BIT, 0);
15082 IEM_MC_ARG(uint64_t, u64Target, 0);
15083 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
15084 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
15085 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15086 IEM_MC_FETCH_MEM_U64(u64Target, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
15087 IEM_MC_CALL_CIMPL_1(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_STACK, 0, iemCImpl_call_64, u64Target);
15088 IEM_MC_END();
15089 break;
15090
15091 IEM_NOT_REACHED_DEFAULT_CASE_RET();
15092 }
15093 }
15094}
15095
15096#define IEMOP_BODY_GRP5_FAR_EP(a_bRm, a_fnCImpl, a_fCImplExtra) \
15097 /* Registers? How?? */ \
15098 if (RT_LIKELY(IEM_IS_MODRM_MEM_MODE(a_bRm))) \
15099 { /* likely */ } \
15100 else \
15101 IEMOP_RAISE_INVALID_OPCODE_RET(); /* callf eax is not legal */ \
15102 \
15103 /* 64-bit mode: Default is 32-bit, but only intel respects a REX.W prefix. */ \
15104 /** @todo what does VIA do? */ \
15105 if (!IEM_IS_64BIT_CODE(pVCpu) || pVCpu->iem.s.enmEffOpSize != IEMMODE_64BIT || IEM_IS_GUEST_CPU_INTEL(pVCpu)) \
15106 { /* likely */ } \
15107 else \
15108 pVCpu->iem.s.enmEffOpSize = IEMMODE_32BIT; \
15109 \
15110 /* Far pointer loaded from memory. */ \
15111 switch (pVCpu->iem.s.enmEffOpSize) \
15112 { \
15113 case IEMMODE_16BIT: \
15114 IEM_MC_BEGIN(3, 1, 0, 0); \
15115 IEM_MC_ARG(uint16_t, u16Sel, 0); \
15116 IEM_MC_ARG(uint16_t, offSeg, 1); \
15117 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize, IEMMODE_16BIT, 2); \
15118 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc); \
15119 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, a_bRm, 0); \
15120 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
15121 IEM_MC_FETCH_MEM_U16(offSeg, pVCpu->iem.s.iEffSeg, GCPtrEffSrc); \
15122 IEM_MC_FETCH_MEM_U16_DISP(u16Sel, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, 2); \
15123 IEM_MC_CALL_CIMPL_3(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | (a_fCImplExtra) \
15124 | IEM_CIMPL_F_MODE | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_VMEXIT, 0, \
15125 a_fnCImpl, u16Sel, offSeg, enmEffOpSize); \
15126 IEM_MC_END(); \
15127 break; \
15128 \
15129 case IEMMODE_32BIT: \
15130 IEM_MC_BEGIN(3, 1, IEM_MC_F_MIN_386, 0); \
15131 IEM_MC_ARG(uint16_t, u16Sel, 0); \
15132 IEM_MC_ARG(uint32_t, offSeg, 1); \
15133 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize, IEMMODE_32BIT, 2); \
15134 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc); \
15135 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, a_bRm, 0); \
15136 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
15137 IEM_MC_FETCH_MEM_U32(offSeg, pVCpu->iem.s.iEffSeg, GCPtrEffSrc); \
15138 IEM_MC_FETCH_MEM_U16_DISP(u16Sel, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, 4); \
15139 IEM_MC_CALL_CIMPL_3(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | (a_fCImplExtra) \
15140 | IEM_CIMPL_F_MODE | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_VMEXIT, 0, \
15141 a_fnCImpl, u16Sel, offSeg, enmEffOpSize); \
15142 IEM_MC_END(); \
15143 break; \
15144 \
15145 case IEMMODE_64BIT: \
15146 Assert(!IEM_IS_GUEST_CPU_AMD(pVCpu)); \
15147 IEM_MC_BEGIN(3, 1, IEM_MC_F_64BIT, 0); \
15148 IEM_MC_ARG(uint16_t, u16Sel, 0); \
15149 IEM_MC_ARG(uint64_t, offSeg, 1); \
15150 IEM_MC_ARG_CONST(IEMMODE, enmEffOpSize, IEMMODE_64BIT, 2); \
15151 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc); \
15152 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, a_bRm, 0); \
15153 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); \
15154 IEM_MC_FETCH_MEM_U64(offSeg, pVCpu->iem.s.iEffSeg, GCPtrEffSrc); \
15155 IEM_MC_FETCH_MEM_U16_DISP(u16Sel, pVCpu->iem.s.iEffSeg, GCPtrEffSrc, 8); \
15156 IEM_MC_CALL_CIMPL_3(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | (a_fCImplExtra) \
15157 | IEM_CIMPL_F_MODE /* no gates */, 0, \
15158 a_fnCImpl, u16Sel, offSeg, enmEffOpSize); \
15159 IEM_MC_END(); \
15160 break; \
15161 \
15162 IEM_NOT_REACHED_DEFAULT_CASE_RET(); \
15163 } do {} while (0)
15164
15165
15166/**
15167 * Opcode 0xff /3.
15168 * @param bRm The RM byte.
15169 */
15170FNIEMOP_DEF_1(iemOp_Grp5_callf_Ep, uint8_t, bRm)
15171{
15172 IEMOP_MNEMONIC(callf_Ep, "callf Ep");
15173 IEMOP_BODY_GRP5_FAR_EP(bRm, iemCImpl_callf, IEM_CIMPL_F_BRANCH_STACK);
15174}
15175
15176
15177/**
15178 * Opcode 0xff /4.
15179 * @param bRm The RM byte.
15180 */
15181FNIEMOP_DEF_1(iemOp_Grp5_jmpn_Ev, uint8_t, bRm)
15182{
15183 IEMOP_MNEMONIC(jmpn_Ev, "jmpn Ev");
15184 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE_AND_INTEL_IGNORES_OP_SIZE_PREFIX();
15185
15186 if (IEM_IS_MODRM_REG_MODE(bRm))
15187 {
15188 /* The new RIP is taken from a register. */
15189 switch (pVCpu->iem.s.enmEffOpSize)
15190 {
15191 case IEMMODE_16BIT:
15192 IEM_MC_BEGIN(0, 1, 0, 0);
15193 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15194 IEM_MC_LOCAL(uint16_t, u16Target);
15195 IEM_MC_FETCH_GREG_U16(u16Target, IEM_GET_MODRM_RM(pVCpu, bRm));
15196 IEM_MC_SET_RIP_U16_AND_FINISH(u16Target);
15197 IEM_MC_END();
15198 break;
15199
15200 case IEMMODE_32BIT:
15201 IEM_MC_BEGIN(0, 1, IEM_MC_F_MIN_386, 0);
15202 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15203 IEM_MC_LOCAL(uint32_t, u32Target);
15204 IEM_MC_FETCH_GREG_U32(u32Target, IEM_GET_MODRM_RM(pVCpu, bRm));
15205 IEM_MC_SET_RIP_U32_AND_FINISH(u32Target);
15206 IEM_MC_END();
15207 break;
15208
15209 case IEMMODE_64BIT:
15210 IEM_MC_BEGIN(0, 1, IEM_MC_F_64BIT, 0);
15211 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15212 IEM_MC_LOCAL(uint64_t, u64Target);
15213 IEM_MC_FETCH_GREG_U64(u64Target, IEM_GET_MODRM_RM(pVCpu, bRm));
15214 IEM_MC_SET_RIP_U64_AND_FINISH(u64Target);
15215 IEM_MC_END();
15216 break;
15217
15218 IEM_NOT_REACHED_DEFAULT_CASE_RET();
15219 }
15220 }
15221 else
15222 {
15223 /* The new RIP is taken from a memory location. */
15224 switch (pVCpu->iem.s.enmEffOpSize)
15225 {
15226 case IEMMODE_16BIT:
15227 IEM_MC_BEGIN(0, 2, 0, 0);
15228 IEM_MC_LOCAL(uint16_t, u16Target);
15229 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
15230 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
15231 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15232 IEM_MC_FETCH_MEM_U16(u16Target, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
15233 IEM_MC_SET_RIP_U16_AND_FINISH(u16Target);
15234 IEM_MC_END();
15235 break;
15236
15237 case IEMMODE_32BIT:
15238 IEM_MC_BEGIN(0, 2, IEM_MC_F_MIN_386, 0);
15239 IEM_MC_LOCAL(uint32_t, u32Target);
15240 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
15241 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
15242 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15243 IEM_MC_FETCH_MEM_U32(u32Target, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
15244 IEM_MC_SET_RIP_U32_AND_FINISH(u32Target);
15245 IEM_MC_END();
15246 break;
15247
15248 case IEMMODE_64BIT:
15249 IEM_MC_BEGIN(0, 2, IEM_MC_F_64BIT, 0);
15250 IEM_MC_LOCAL(uint64_t, u64Target);
15251 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
15252 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
15253 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15254 IEM_MC_FETCH_MEM_U64(u64Target, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
15255 IEM_MC_SET_RIP_U64_AND_FINISH(u64Target);
15256 IEM_MC_END();
15257 break;
15258
15259 IEM_NOT_REACHED_DEFAULT_CASE_RET();
15260 }
15261 }
15262}
15263
15264
15265/**
15266 * Opcode 0xff /5.
15267 * @param bRm The RM byte.
15268 */
15269FNIEMOP_DEF_1(iemOp_Grp5_jmpf_Ep, uint8_t, bRm)
15270{
15271 IEMOP_MNEMONIC(jmpf_Ep, "jmpf Ep");
15272 IEMOP_BODY_GRP5_FAR_EP(bRm, iemCImpl_FarJmp, 0);
15273}
15274
15275
15276/**
15277 * Opcode 0xff /6.
15278 * @param bRm The RM byte.
15279 */
15280FNIEMOP_DEF_1(iemOp_Grp5_push_Ev, uint8_t, bRm)
15281{
15282 IEMOP_MNEMONIC(push_Ev, "push Ev");
15283
15284 /* Registers are handled by a common worker. */
15285 if (IEM_IS_MODRM_REG_MODE(bRm))
15286 return FNIEMOP_CALL_1(iemOpCommonPushGReg, IEM_GET_MODRM_RM(pVCpu, bRm));
15287
15288 /* Memory we do here. */
15289 IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
15290 switch (pVCpu->iem.s.enmEffOpSize)
15291 {
15292 case IEMMODE_16BIT:
15293 IEM_MC_BEGIN(0, 2, 0, 0);
15294 IEM_MC_LOCAL(uint16_t, u16Src);
15295 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
15296 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
15297 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15298 IEM_MC_FETCH_MEM_U16(u16Src, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
15299 IEM_MC_PUSH_U16(u16Src);
15300 IEM_MC_ADVANCE_RIP_AND_FINISH();
15301 IEM_MC_END();
15302 break;
15303
15304 case IEMMODE_32BIT:
15305 IEM_MC_BEGIN(0, 2, IEM_MC_F_MIN_386 | IEM_MC_F_NOT_64BIT, 0);
15306 IEM_MC_LOCAL(uint32_t, u32Src);
15307 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
15308 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
15309 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15310 IEM_MC_FETCH_MEM_U32(u32Src, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
15311 IEM_MC_PUSH_U32(u32Src);
15312 IEM_MC_ADVANCE_RIP_AND_FINISH();
15313 IEM_MC_END();
15314 break;
15315
15316 case IEMMODE_64BIT:
15317 IEM_MC_BEGIN(0, 2, IEM_MC_F_64BIT, 0);
15318 IEM_MC_LOCAL(uint64_t, u64Src);
15319 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
15320 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
15321 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
15322 IEM_MC_FETCH_MEM_U64(u64Src, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
15323 IEM_MC_PUSH_U64(u64Src);
15324 IEM_MC_ADVANCE_RIP_AND_FINISH();
15325 IEM_MC_END();
15326 break;
15327
15328 IEM_NOT_REACHED_DEFAULT_CASE_RET();
15329 }
15330}
15331
15332
15333/**
15334 * @opcode 0xff
15335 */
15336FNIEMOP_DEF(iemOp_Grp5)
15337{
15338 uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
15339 switch (IEM_GET_MODRM_REG_8(bRm))
15340 {
15341 case 0:
15342 return FNIEMOP_CALL_1(iemOp_Grp5_inc_Ev, bRm);
15343 case 1:
15344 return FNIEMOP_CALL_1(iemOp_Grp5_dec_Ev, bRm);
15345 case 2:
15346 return FNIEMOP_CALL_1(iemOp_Grp5_calln_Ev, bRm);
15347 case 3:
15348 return FNIEMOP_CALL_1(iemOp_Grp5_callf_Ep, bRm);
15349 case 4:
15350 return FNIEMOP_CALL_1(iemOp_Grp5_jmpn_Ev, bRm);
15351 case 5:
15352 return FNIEMOP_CALL_1(iemOp_Grp5_jmpf_Ep, bRm);
15353 case 6:
15354 return FNIEMOP_CALL_1(iemOp_Grp5_push_Ev, bRm);
15355 case 7:
15356 IEMOP_MNEMONIC(grp5_ud, "grp5-ud");
15357 IEMOP_RAISE_INVALID_OPCODE_RET();
15358 }
15359 AssertFailedReturn(VERR_IEM_IPE_3);
15360}
15361
15362
15363
15364const PFNIEMOP g_apfnOneByteMap[256] =
15365{
15366 /* 0x00 */ iemOp_add_Eb_Gb, iemOp_add_Ev_Gv, iemOp_add_Gb_Eb, iemOp_add_Gv_Ev,
15367 /* 0x04 */ iemOp_add_Al_Ib, iemOp_add_eAX_Iz, iemOp_push_ES, iemOp_pop_ES,
15368 /* 0x08 */ iemOp_or_Eb_Gb, iemOp_or_Ev_Gv, iemOp_or_Gb_Eb, iemOp_or_Gv_Ev,
15369 /* 0x0c */ iemOp_or_Al_Ib, iemOp_or_eAX_Iz, iemOp_push_CS, iemOp_2byteEscape,
15370 /* 0x10 */ iemOp_adc_Eb_Gb, iemOp_adc_Ev_Gv, iemOp_adc_Gb_Eb, iemOp_adc_Gv_Ev,
15371 /* 0x14 */ iemOp_adc_Al_Ib, iemOp_adc_eAX_Iz, iemOp_push_SS, iemOp_pop_SS,
15372 /* 0x18 */ iemOp_sbb_Eb_Gb, iemOp_sbb_Ev_Gv, iemOp_sbb_Gb_Eb, iemOp_sbb_Gv_Ev,
15373 /* 0x1c */ iemOp_sbb_Al_Ib, iemOp_sbb_eAX_Iz, iemOp_push_DS, iemOp_pop_DS,
15374 /* 0x20 */ iemOp_and_Eb_Gb, iemOp_and_Ev_Gv, iemOp_and_Gb_Eb, iemOp_and_Gv_Ev,
15375 /* 0x24 */ iemOp_and_Al_Ib, iemOp_and_eAX_Iz, iemOp_seg_ES, iemOp_daa,
15376 /* 0x28 */ iemOp_sub_Eb_Gb, iemOp_sub_Ev_Gv, iemOp_sub_Gb_Eb, iemOp_sub_Gv_Ev,
15377 /* 0x2c */ iemOp_sub_Al_Ib, iemOp_sub_eAX_Iz, iemOp_seg_CS, iemOp_das,
15378 /* 0x30 */ iemOp_xor_Eb_Gb, iemOp_xor_Ev_Gv, iemOp_xor_Gb_Eb, iemOp_xor_Gv_Ev,
15379 /* 0x34 */ iemOp_xor_Al_Ib, iemOp_xor_eAX_Iz, iemOp_seg_SS, iemOp_aaa,
15380 /* 0x38 */ iemOp_cmp_Eb_Gb, iemOp_cmp_Ev_Gv, iemOp_cmp_Gb_Eb, iemOp_cmp_Gv_Ev,
15381 /* 0x3c */ iemOp_cmp_Al_Ib, iemOp_cmp_eAX_Iz, iemOp_seg_DS, iemOp_aas,
15382 /* 0x40 */ iemOp_inc_eAX, iemOp_inc_eCX, iemOp_inc_eDX, iemOp_inc_eBX,
15383 /* 0x44 */ iemOp_inc_eSP, iemOp_inc_eBP, iemOp_inc_eSI, iemOp_inc_eDI,
15384 /* 0x48 */ iemOp_dec_eAX, iemOp_dec_eCX, iemOp_dec_eDX, iemOp_dec_eBX,
15385 /* 0x4c */ iemOp_dec_eSP, iemOp_dec_eBP, iemOp_dec_eSI, iemOp_dec_eDI,
15386 /* 0x50 */ iemOp_push_eAX, iemOp_push_eCX, iemOp_push_eDX, iemOp_push_eBX,
15387 /* 0x54 */ iemOp_push_eSP, iemOp_push_eBP, iemOp_push_eSI, iemOp_push_eDI,
15388 /* 0x58 */ iemOp_pop_eAX, iemOp_pop_eCX, iemOp_pop_eDX, iemOp_pop_eBX,
15389 /* 0x5c */ iemOp_pop_eSP, iemOp_pop_eBP, iemOp_pop_eSI, iemOp_pop_eDI,
15390 /* 0x60 */ iemOp_pusha, iemOp_popa__mvex, iemOp_bound_Gv_Ma__evex, iemOp_arpl_Ew_Gw_movsx_Gv_Ev,
15391 /* 0x64 */ iemOp_seg_FS, iemOp_seg_GS, iemOp_op_size, iemOp_addr_size,
15392 /* 0x68 */ iemOp_push_Iz, iemOp_imul_Gv_Ev_Iz, iemOp_push_Ib, iemOp_imul_Gv_Ev_Ib,
15393 /* 0x6c */ iemOp_insb_Yb_DX, iemOp_inswd_Yv_DX, iemOp_outsb_Yb_DX, iemOp_outswd_Yv_DX,
15394 /* 0x70 */ iemOp_jo_Jb, iemOp_jno_Jb, iemOp_jc_Jb, iemOp_jnc_Jb,
15395 /* 0x74 */ iemOp_je_Jb, iemOp_jne_Jb, iemOp_jbe_Jb, iemOp_jnbe_Jb,
15396 /* 0x78 */ iemOp_js_Jb, iemOp_jns_Jb, iemOp_jp_Jb, iemOp_jnp_Jb,
15397 /* 0x7c */ iemOp_jl_Jb, iemOp_jnl_Jb, iemOp_jle_Jb, iemOp_jnle_Jb,
15398 /* 0x80 */ iemOp_Grp1_Eb_Ib_80, iemOp_Grp1_Ev_Iz, iemOp_Grp1_Eb_Ib_82, iemOp_Grp1_Ev_Ib,
15399 /* 0x84 */ iemOp_test_Eb_Gb, iemOp_test_Ev_Gv, iemOp_xchg_Eb_Gb, iemOp_xchg_Ev_Gv,
15400 /* 0x88 */ iemOp_mov_Eb_Gb, iemOp_mov_Ev_Gv, iemOp_mov_Gb_Eb, iemOp_mov_Gv_Ev,
15401 /* 0x8c */ iemOp_mov_Ev_Sw, iemOp_lea_Gv_M, iemOp_mov_Sw_Ev, iemOp_Grp1A__xop,
15402 /* 0x90 */ iemOp_nop, iemOp_xchg_eCX_eAX, iemOp_xchg_eDX_eAX, iemOp_xchg_eBX_eAX,
15403 /* 0x94 */ iemOp_xchg_eSP_eAX, iemOp_xchg_eBP_eAX, iemOp_xchg_eSI_eAX, iemOp_xchg_eDI_eAX,
15404 /* 0x98 */ iemOp_cbw, iemOp_cwd, iemOp_call_Ap, iemOp_wait,
15405 /* 0x9c */ iemOp_pushf_Fv, iemOp_popf_Fv, iemOp_sahf, iemOp_lahf,
15406 /* 0xa0 */ iemOp_mov_AL_Ob, iemOp_mov_rAX_Ov, iemOp_mov_Ob_AL, iemOp_mov_Ov_rAX,
15407 /* 0xa4 */ iemOp_movsb_Xb_Yb, iemOp_movswd_Xv_Yv, iemOp_cmpsb_Xb_Yb, iemOp_cmpswd_Xv_Yv,
15408 /* 0xa8 */ iemOp_test_AL_Ib, iemOp_test_eAX_Iz, iemOp_stosb_Yb_AL, iemOp_stoswd_Yv_eAX,
15409 /* 0xac */ iemOp_lodsb_AL_Xb, iemOp_lodswd_eAX_Xv, iemOp_scasb_AL_Xb, iemOp_scaswd_eAX_Xv,
15410 /* 0xb0 */ iemOp_mov_AL_Ib, iemOp_CL_Ib, iemOp_DL_Ib, iemOp_BL_Ib,
15411 /* 0xb4 */ iemOp_mov_AH_Ib, iemOp_CH_Ib, iemOp_DH_Ib, iemOp_BH_Ib,
15412 /* 0xb8 */ iemOp_eAX_Iv, iemOp_eCX_Iv, iemOp_eDX_Iv, iemOp_eBX_Iv,
15413 /* 0xbc */ iemOp_eSP_Iv, iemOp_eBP_Iv, iemOp_eSI_Iv, iemOp_eDI_Iv,
15414 /* 0xc0 */ iemOp_Grp2_Eb_Ib, iemOp_Grp2_Ev_Ib, iemOp_retn_Iw, iemOp_retn,
15415 /* 0xc4 */ iemOp_les_Gv_Mp__vex3, iemOp_lds_Gv_Mp__vex2, iemOp_Grp11_Eb_Ib, iemOp_Grp11_Ev_Iz,
15416 /* 0xc8 */ iemOp_enter_Iw_Ib, iemOp_leave, iemOp_retf_Iw, iemOp_retf,
15417 /* 0xcc */ iemOp_int3, iemOp_int_Ib, iemOp_into, iemOp_iret,
15418 /* 0xd0 */ iemOp_Grp2_Eb_1, iemOp_Grp2_Ev_1, iemOp_Grp2_Eb_CL, iemOp_Grp2_Ev_CL,
15419 /* 0xd4 */ iemOp_aam_Ib, iemOp_aad_Ib, iemOp_salc, iemOp_xlat,
15420 /* 0xd8 */ iemOp_EscF0, iemOp_EscF1, iemOp_EscF2, iemOp_EscF3,
15421 /* 0xdc */ iemOp_EscF4, iemOp_EscF5, iemOp_EscF6, iemOp_EscF7,
15422 /* 0xe0 */ iemOp_loopne_Jb, iemOp_loope_Jb, iemOp_loop_Jb, iemOp_jecxz_Jb,
15423 /* 0xe4 */ iemOp_in_AL_Ib, iemOp_in_eAX_Ib, iemOp_out_Ib_AL, iemOp_out_Ib_eAX,
15424 /* 0xe8 */ iemOp_call_Jv, iemOp_jmp_Jv, iemOp_jmp_Ap, iemOp_jmp_Jb,
15425 /* 0xec */ iemOp_in_AL_DX, iemOp_in_eAX_DX, iemOp_out_DX_AL, iemOp_out_DX_eAX,
15426 /* 0xf0 */ iemOp_lock, iemOp_int1, iemOp_repne, iemOp_repe,
15427 /* 0xf4 */ iemOp_hlt, iemOp_cmc, iemOp_Grp3_Eb, iemOp_Grp3_Ev,
15428 /* 0xf8 */ iemOp_clc, iemOp_stc, iemOp_cli, iemOp_sti,
15429 /* 0xfc */ iemOp_cld, iemOp_std, iemOp_Grp4, iemOp_Grp5,
15430};
15431
15432
15433/** @} */
15434
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