VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm@ 46992

Last change on this file since 46992 was 46992, checked in by vboxsync, 11 years ago

8-bit idiv overflow checks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 70.3 KB
Line 
1; $Id: IEMAllAImpl.asm 46992 2013-07-05 08:00:06Z vboxsync $
2;; @file
3; IEM - Instruction Implementation in Assembly.
4;
5
6; Copyright (C) 2011-2012 Oracle Corporation
7;
8; This file is part of VirtualBox Open Source Edition (OSE), as
9; available from http://www.virtualbox.org. This file is free software;
10; you can redistribute it and/or modify it under the terms of the GNU
11; General Public License (GPL) as published by the Free Software
12; Foundation, in version 2 as it comes in the "COPYING" file of the
13; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15;
16
17
18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19; Header Files ;
20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
21%include "VBox/asmdefs.mac"
22%include "VBox/err.mac"
23%include "iprt/x86.mac"
24
25
26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27; Defined Constants And Macros ;
28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29
30;;
31; RET XX / RET wrapper for fastcall.
32;
33%macro RET_FASTCALL 1
34%ifdef RT_ARCH_X86
35 %ifdef RT_OS_WINDOWS
36 ret %1
37 %else
38 ret
39 %endif
40%else
41 ret
42%endif
43%endmacro
44
45;;
46; NAME for fastcall functions.
47;
48;; @todo 'global @fastcall@12' is still broken in yasm and requires dollar
49; escaping (or whatever the dollar is good for here). Thus the ugly
50; prefix argument.
51;
52%define NAME_FASTCALL(a_Name, a_cbArgs, a_Prefix) NAME(a_Name)
53%ifdef RT_ARCH_X86
54 %ifdef RT_OS_WINDOWS
55 %undef NAME_FASTCALL
56 %define NAME_FASTCALL(a_Name, a_cbArgs, a_Prefix) a_Prefix %+ a_Name %+ @ %+ a_cbArgs
57 %endif
58%endif
59
60;;
61; BEGINPROC for fastcall functions.
62;
63; @param 1 The function name (C).
64; @param 2 The argument size on x86.
65;
66%macro BEGINPROC_FASTCALL 2
67 %ifdef ASM_FORMAT_PE
68 export %1=NAME_FASTCALL(%1,%2,$@)
69 %endif
70 %ifdef __NASM__
71 %ifdef ASM_FORMAT_OMF
72 export NAME(%1) NAME_FASTCALL(%1,%2,$@)
73 %endif
74 %endif
75 %ifndef ASM_FORMAT_BIN
76 global NAME_FASTCALL(%1,%2,$@)
77 %endif
78NAME_FASTCALL(%1,%2,@):
79%endmacro
80
81
82;
83; We employ some macro assembly here to hid the calling convention differences.
84;
85%ifdef RT_ARCH_AMD64
86 %macro PROLOGUE_1_ARGS 0
87 %endmacro
88 %macro EPILOGUE_1_ARGS 0
89 ret
90 %endmacro
91 %macro EPILOGUE_1_ARGS_EX 0
92 ret
93 %endmacro
94
95 %macro PROLOGUE_2_ARGS 0
96 %endmacro
97 %macro EPILOGUE_2_ARGS 0
98 ret
99 %endmacro
100 %macro EPILOGUE_2_ARGS_EX 1
101 ret
102 %endmacro
103
104 %macro PROLOGUE_3_ARGS 0
105 %endmacro
106 %macro EPILOGUE_3_ARGS 0
107 ret
108 %endmacro
109 %macro EPILOGUE_3_ARGS_EX 1
110 ret
111 %endmacro
112
113 %macro PROLOGUE_4_ARGS 0
114 %endmacro
115 %macro EPILOGUE_4_ARGS 0
116 ret
117 %endmacro
118 %macro EPILOGUE_4_ARGS_EX 1
119 ret
120 %endmacro
121
122 %ifdef ASM_CALL64_GCC
123 %define A0 rdi
124 %define A0_32 edi
125 %define A0_16 di
126 %define A0_8 dil
127
128 %define A1 rsi
129 %define A1_32 esi
130 %define A1_16 si
131 %define A1_8 sil
132
133 %define A2 rdx
134 %define A2_32 edx
135 %define A2_16 dx
136 %define A2_8 dl
137
138 %define A3 rcx
139 %define A3_32 ecx
140 %define A3_16 cx
141 %endif
142
143 %ifdef ASM_CALL64_MSC
144 %define A0 rcx
145 %define A0_32 ecx
146 %define A0_16 cx
147 %define A0_8 cl
148
149 %define A1 rdx
150 %define A1_32 edx
151 %define A1_16 dx
152 %define A1_8 dl
153
154 %define A2 r8
155 %define A2_32 r8d
156 %define A2_16 r8w
157 %define A2_8 r8b
158
159 %define A3 r9
160 %define A3_32 r9d
161 %define A3_16 r9w
162 %endif
163
164 %define T0 rax
165 %define T0_32 eax
166 %define T0_16 ax
167 %define T0_8 al
168
169 %define T1 r11
170 %define T1_32 r11d
171 %define T1_16 r11w
172 %define T1_8 r11b
173
174%else
175 ; x86
176 %macro PROLOGUE_1_ARGS 0
177 push edi
178 %endmacro
179 %macro EPILOGUE_1_ARGS 0
180 pop edi
181 ret 0
182 %endmacro
183 %macro EPILOGUE_1_ARGS_EX 1
184 pop edi
185 ret %1
186 %endmacro
187
188 %macro PROLOGUE_2_ARGS 0
189 push edi
190 %endmacro
191 %macro EPILOGUE_2_ARGS 0
192 pop edi
193 ret 0
194 %endmacro
195 %macro EPILOGUE_2_ARGS_EX 1
196 pop edi
197 ret %1
198 %endmacro
199
200 %macro PROLOGUE_3_ARGS 0
201 push ebx
202 mov ebx, [esp + 4 + 4]
203 push edi
204 %endmacro
205 %macro EPILOGUE_3_ARGS_EX 1
206 %if (%1) < 4
207 %error "With three args, at least 4 bytes must be remove from the stack upon return (32-bit)."
208 %endif
209 pop edi
210 pop ebx
211 ret %1
212 %endmacro
213 %macro EPILOGUE_3_ARGS 0
214 EPILOGUE_3_ARGS_EX 4
215 %endmacro
216
217 %macro PROLOGUE_4_ARGS 0
218 push ebx
219 push edi
220 push esi
221 mov ebx, [esp + 12 + 4 + 0]
222 mov esi, [esp + 12 + 4 + 4]
223 %endmacro
224 %macro EPILOGUE_4_ARGS_EX 1
225 %if (%1) < 8
226 %error "With four args, at least 8 bytes must be remove from the stack upon return (32-bit)."
227 %endif
228 pop esi
229 pop edi
230 pop ebx
231 ret %1
232 %endmacro
233 %macro EPILOGUE_4_ARGS 0
234 EPILOGUE_4_ARGS_EX 8
235 %endmacro
236
237 %define A0 ecx
238 %define A0_32 ecx
239 %define A0_16 cx
240 %define A0_8 cl
241
242 %define A1 edx
243 %define A1_32 edx
244 %define A1_16 dx
245 %define A1_8 dl
246
247 %define A2 ebx
248 %define A2_32 ebx
249 %define A2_16 bx
250 %define A2_8 bl
251
252 %define A3 esi
253 %define A3_32 esi
254 %define A3_16 si
255
256 %define T0 eax
257 %define T0_32 eax
258 %define T0_16 ax
259 %define T0_8 al
260
261 %define T1 edi
262 %define T1_32 edi
263 %define T1_16 di
264%endif
265
266
267;;
268; Load the relevant flags from [%1] if there are undefined flags (%3).
269;
270; @remarks Clobbers T0, stack. Changes EFLAGS.
271; @param A2 The register pointing to the flags.
272; @param 1 The parameter (A0..A3) pointing to the eflags.
273; @param 2 The set of modified flags.
274; @param 3 The set of undefined flags.
275;
276%macro IEM_MAYBE_LOAD_FLAGS 3
277 ;%if (%3) != 0
278 pushf ; store current flags
279 mov T0_32, [%1] ; load the guest flags
280 and dword [xSP], ~(%2 | %3) ; mask out the modified and undefined flags
281 and T0_32, (%2 | %3) ; select the modified and undefined flags.
282 or [xSP], T0 ; merge guest flags with host flags.
283 popf ; load the mixed flags.
284 ;%endif
285%endmacro
286
287;;
288; Update the flag.
289;
290; @remarks Clobbers T0, T1, stack.
291; @param 1 The register pointing to the EFLAGS.
292; @param 2 The mask of modified flags to save.
293; @param 3 The mask of undefined flags to (maybe) save.
294;
295%macro IEM_SAVE_FLAGS 3
296 %if (%2 | %3) != 0
297 pushf
298 pop T1
299 mov T0_32, [%1] ; flags
300 and T0_32, ~(%2 | %3) ; clear the modified & undefined flags.
301 and T1_32, (%2 | %3) ; select the modified and undefined flags.
302 or T0_32, T1_32 ; combine the flags.
303 mov [%1], T0_32 ; save the flags.
304 %endif
305%endmacro
306
307
308;;
309; Macro for implementing a binary operator.
310;
311; This will generate code for the 8, 16, 32 and 64 bit accesses with locked
312; variants, except on 32-bit system where the 64-bit accesses requires hand
313; coding.
314;
315; All the functions takes a pointer to the destination memory operand in A0,
316; the source register operand in A1 and a pointer to eflags in A2.
317;
318; @param 1 The instruction mnemonic.
319; @param 2 Non-zero if there should be a locked version.
320; @param 3 The modified flags.
321; @param 4 The undefined flags.
322;
323%macro IEMIMPL_BIN_OP 4
324BEGINCODE
325BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
326 PROLOGUE_3_ARGS
327 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
328 %1 byte [A0], A1_8
329 IEM_SAVE_FLAGS A2, %3, %4
330 EPILOGUE_3_ARGS
331ENDPROC iemAImpl_ %+ %1 %+ _u8
332
333BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
334 PROLOGUE_3_ARGS
335 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
336 %1 word [A0], A1_16
337 IEM_SAVE_FLAGS A2, %3, %4
338 EPILOGUE_3_ARGS
339ENDPROC iemAImpl_ %+ %1 %+ _u16
340
341BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
342 PROLOGUE_3_ARGS
343 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
344 %1 dword [A0], A1_32
345 IEM_SAVE_FLAGS A2, %3, %4
346 EPILOGUE_3_ARGS
347ENDPROC iemAImpl_ %+ %1 %+ _u32
348
349 %ifdef RT_ARCH_AMD64
350BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
351 PROLOGUE_3_ARGS
352 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
353 %1 qword [A0], A1
354 IEM_SAVE_FLAGS A2, %3, %4
355 EPILOGUE_3_ARGS_EX 8
356ENDPROC iemAImpl_ %+ %1 %+ _u64
357 %else ; stub it for now - later, replace with hand coded stuff.
358BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
359 int3
360 ret
361ENDPROC iemAImpl_ %+ %1 %+ _u64
362 %endif ; !RT_ARCH_AMD64
363
364 %if %2 != 0 ; locked versions requested?
365
366BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8_locked, 12
367 PROLOGUE_3_ARGS
368 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
369 lock %1 byte [A0], A1_8
370 IEM_SAVE_FLAGS A2, %3, %4
371 EPILOGUE_3_ARGS
372ENDPROC iemAImpl_ %+ %1 %+ _u8_locked
373
374BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 12
375 PROLOGUE_3_ARGS
376 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
377 lock %1 word [A0], A1_16
378 IEM_SAVE_FLAGS A2, %3, %4
379 EPILOGUE_3_ARGS
380ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
381
382BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 12
383 PROLOGUE_3_ARGS
384 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
385 lock %1 dword [A0], A1_32
386 IEM_SAVE_FLAGS A2, %3, %4
387 EPILOGUE_3_ARGS
388ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
389
390 %ifdef RT_ARCH_AMD64
391BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
392 PROLOGUE_3_ARGS
393 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
394 lock %1 qword [A0], A1
395 IEM_SAVE_FLAGS A2, %3, %4
396 EPILOGUE_3_ARGS_EX 8
397ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
398 %else ; stub it for now - later, replace with hand coded stuff.
399BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
400 int3
401 ret 8
402ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
403 %endif ; !RT_ARCH_AMD64
404 %endif ; locked
405%endmacro
406
407; instr,lock,modified-flags.
408IEMIMPL_BIN_OP add, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
409IEMIMPL_BIN_OP adc, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
410IEMIMPL_BIN_OP sub, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
411IEMIMPL_BIN_OP sbb, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
412IEMIMPL_BIN_OP or, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
413IEMIMPL_BIN_OP xor, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
414IEMIMPL_BIN_OP and, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
415IEMIMPL_BIN_OP cmp, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
416IEMIMPL_BIN_OP test, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
417
418
419;;
420; Macro for implementing a bit operator.
421;
422; This will generate code for the 16, 32 and 64 bit accesses with locked
423; variants, except on 32-bit system where the 64-bit accesses requires hand
424; coding.
425;
426; All the functions takes a pointer to the destination memory operand in A0,
427; the source register operand in A1 and a pointer to eflags in A2.
428;
429; @param 1 The instruction mnemonic.
430; @param 2 Non-zero if there should be a locked version.
431; @param 3 The modified flags.
432; @param 4 The undefined flags.
433;
434%macro IEMIMPL_BIT_OP 4
435BEGINCODE
436BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
437 PROLOGUE_3_ARGS
438 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
439 %1 word [A0], A1_16
440 IEM_SAVE_FLAGS A2, %3, %4
441 EPILOGUE_3_ARGS
442ENDPROC iemAImpl_ %+ %1 %+ _u16
443
444BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
445 PROLOGUE_3_ARGS
446 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
447 %1 dword [A0], A1_32
448 IEM_SAVE_FLAGS A2, %3, %4
449 EPILOGUE_3_ARGS
450ENDPROC iemAImpl_ %+ %1 %+ _u32
451
452 %ifdef RT_ARCH_AMD64
453BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
454 PROLOGUE_3_ARGS
455 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
456 %1 qword [A0], A1
457 IEM_SAVE_FLAGS A2, %3, %4
458 EPILOGUE_3_ARGS_EX 8
459ENDPROC iemAImpl_ %+ %1 %+ _u64
460 %else ; stub it for now - later, replace with hand coded stuff.
461BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
462 int3
463 ret 8
464ENDPROC iemAImpl_ %+ %1 %+ _u64
465 %endif ; !RT_ARCH_AMD64
466
467 %if %2 != 0 ; locked versions requested?
468
469BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 12
470 PROLOGUE_3_ARGS
471 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
472 lock %1 word [A0], A1_16
473 IEM_SAVE_FLAGS A2, %3, %4
474 EPILOGUE_3_ARGS
475ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
476
477BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 12
478 PROLOGUE_3_ARGS
479 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
480 lock %1 dword [A0], A1_32
481 IEM_SAVE_FLAGS A2, %3, %4
482 EPILOGUE_3_ARGS
483ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
484
485 %ifdef RT_ARCH_AMD64
486BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
487 PROLOGUE_3_ARGS
488 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
489 lock %1 qword [A0], A1
490 IEM_SAVE_FLAGS A2, %3, %4
491 EPILOGUE_3_ARGS_EX 8
492ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
493 %else ; stub it for now - later, replace with hand coded stuff.
494BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
495 int3
496 ret 8
497ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
498 %endif ; !RT_ARCH_AMD64
499 %endif ; locked
500%endmacro
501IEMIMPL_BIT_OP bt, 0, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
502IEMIMPL_BIT_OP btc, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
503IEMIMPL_BIT_OP bts, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
504IEMIMPL_BIT_OP btr, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
505
506;;
507; Macro for implementing a bit search operator.
508;
509; This will generate code for the 16, 32 and 64 bit accesses, except on 32-bit
510; system where the 64-bit accesses requires hand coding.
511;
512; All the functions takes a pointer to the destination memory operand in A0,
513; the source register operand in A1 and a pointer to eflags in A2.
514;
515; @param 1 The instruction mnemonic.
516; @param 2 The modified flags.
517; @param 3 The undefined flags.
518;
519%macro IEMIMPL_BIT_OP 3
520BEGINCODE
521BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
522 PROLOGUE_3_ARGS
523 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
524 %1 T0_16, A1_16
525 jz .unchanged_dst
526 mov [A0], T0_16
527.unchanged_dst:
528 IEM_SAVE_FLAGS A2, %2, %3
529 EPILOGUE_3_ARGS
530ENDPROC iemAImpl_ %+ %1 %+ _u16
531
532BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
533 PROLOGUE_3_ARGS
534 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
535 %1 T0_32, A1_32
536 jz .unchanged_dst
537 mov [A0], T0_32
538.unchanged_dst:
539 IEM_SAVE_FLAGS A2, %2, %3
540 EPILOGUE_3_ARGS
541ENDPROC iemAImpl_ %+ %1 %+ _u32
542
543 %ifdef RT_ARCH_AMD64
544BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
545 PROLOGUE_3_ARGS
546 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
547 %1 T0, A1
548 jz .unchanged_dst
549 mov [A0], T0
550.unchanged_dst:
551 IEM_SAVE_FLAGS A2, %2, %3
552 EPILOGUE_3_ARGS_EX 8
553ENDPROC iemAImpl_ %+ %1 %+ _u64
554 %else ; stub it for now - later, replace with hand coded stuff.
555BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
556 int3
557 ret 8
558ENDPROC iemAImpl_ %+ %1 %+ _u64
559 %endif ; !RT_ARCH_AMD64
560%endmacro
561IEMIMPL_BIT_OP bsf, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
562IEMIMPL_BIT_OP bsr, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
563
564
565;
566; IMUL is also a similar but yet different case (no lock, no mem dst).
567; The rDX:rAX variant of imul is handled together with mul further down.
568;
569BEGINCODE
570BEGINPROC_FASTCALL iemAImpl_imul_two_u16, 12
571 PROLOGUE_3_ARGS
572 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
573 imul A1_16, word [A0]
574 mov [A0], A1_16
575 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
576 EPILOGUE_3_ARGS
577ENDPROC iemAImpl_imul_two_u16
578
579BEGINPROC_FASTCALL iemAImpl_imul_two_u32, 12
580 PROLOGUE_3_ARGS
581 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
582 imul A1_32, dword [A0]
583 mov [A0], A1_32
584 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
585 EPILOGUE_3_ARGS
586ENDPROC iemAImpl_imul_two_u32
587
588BEGINPROC_FASTCALL iemAImpl_imul_two_u64, 16
589 PROLOGUE_3_ARGS
590%ifdef RT_ARCH_AMD64
591 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
592 imul A1, qword [A0]
593 mov [A0], A1
594 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
595%else
596 int3 ;; @todo implement me
597%endif
598 EPILOGUE_3_ARGS_EX 8
599ENDPROC iemAImpl_imul_two_u64
600
601
602;
603; XCHG for memory operands. This implies locking. No flag changes.
604;
605; Each function takes two arguments, first the pointer to the memory,
606; then the pointer to the register. They all return void.
607;
608BEGINCODE
609BEGINPROC_FASTCALL iemAImpl_xchg_u8, 8
610 PROLOGUE_2_ARGS
611 mov T0_8, [A1]
612 xchg [A0], T0_8
613 mov [A1], T0_8
614 EPILOGUE_2_ARGS
615ENDPROC iemAImpl_xchg_u8
616
617BEGINPROC_FASTCALL iemAImpl_xchg_u16, 8
618 PROLOGUE_2_ARGS
619 mov T0_16, [A1]
620 xchg [A0], T0_16
621 mov [A1], T0_16
622 EPILOGUE_2_ARGS
623ENDPROC iemAImpl_xchg_u16
624
625BEGINPROC_FASTCALL iemAImpl_xchg_u32, 8
626 PROLOGUE_2_ARGS
627 mov T0_32, [A1]
628 xchg [A0], T0_32
629 mov [A1], T0_32
630 EPILOGUE_2_ARGS
631ENDPROC iemAImpl_xchg_u32
632
633BEGINPROC_FASTCALL iemAImpl_xchg_u64, 8
634%ifdef RT_ARCH_AMD64
635 PROLOGUE_2_ARGS
636 mov T0, [A1]
637 xchg [A0], T0
638 mov [A1], T0
639 EPILOGUE_2_ARGS
640%else
641 int3
642 ret 0
643%endif
644ENDPROC iemAImpl_xchg_u64
645
646
647;
648; XADD for memory operands.
649;
650; Each function takes three arguments, first the pointer to the
651; memory/register, then the pointer to the register, and finally a pointer to
652; eflags. They all return void.
653;
654BEGINCODE
655BEGINPROC_FASTCALL iemAImpl_xadd_u8, 12
656 PROLOGUE_3_ARGS
657 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
658 mov T0_8, [A1]
659 xadd [A0], T0_8
660 mov [A1], T0_8
661 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
662 EPILOGUE_3_ARGS
663ENDPROC iemAImpl_xadd_u8
664
665BEGINPROC_FASTCALL iemAImpl_xadd_u16, 12
666 PROLOGUE_3_ARGS
667 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
668 mov T0_16, [A1]
669 xadd [A0], T0_16
670 mov [A1], T0_16
671 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
672 EPILOGUE_3_ARGS
673ENDPROC iemAImpl_xadd_u16
674
675BEGINPROC_FASTCALL iemAImpl_xadd_u32, 12
676 PROLOGUE_3_ARGS
677 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
678 mov T0_32, [A1]
679 xadd [A0], T0_32
680 mov [A1], T0_32
681 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
682 EPILOGUE_3_ARGS
683ENDPROC iemAImpl_xadd_u32
684
685BEGINPROC_FASTCALL iemAImpl_xadd_u64, 12
686%ifdef RT_ARCH_AMD64
687 PROLOGUE_3_ARGS
688 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
689 mov T0, [A1]
690 xadd [A0], T0
691 mov [A1], T0
692 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
693 EPILOGUE_3_ARGS
694%else
695 int3
696 ret 4
697%endif
698ENDPROC iemAImpl_xadd_u64
699
700BEGINPROC_FASTCALL iemAImpl_xadd_u8_locked, 12
701 PROLOGUE_3_ARGS
702 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
703 mov T0_8, [A1]
704 lock xadd [A0], T0_8
705 mov [A1], T0_8
706 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
707 EPILOGUE_3_ARGS
708ENDPROC iemAImpl_xadd_u8_locked
709
710BEGINPROC_FASTCALL iemAImpl_xadd_u16_locked, 12
711 PROLOGUE_3_ARGS
712 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
713 mov T0_16, [A1]
714 lock xadd [A0], T0_16
715 mov [A1], T0_16
716 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
717 EPILOGUE_3_ARGS
718ENDPROC iemAImpl_xadd_u16_locked
719
720BEGINPROC_FASTCALL iemAImpl_xadd_u32_locked, 12
721 PROLOGUE_3_ARGS
722 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
723 mov T0_32, [A1]
724 lock xadd [A0], T0_32
725 mov [A1], T0_32
726 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
727 EPILOGUE_3_ARGS
728ENDPROC iemAImpl_xadd_u32_locked
729
730BEGINPROC_FASTCALL iemAImpl_xadd_u64_locked, 12
731%ifdef RT_ARCH_AMD64
732 PROLOGUE_3_ARGS
733 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
734 mov T0, [A1]
735 lock xadd [A0], T0
736 mov [A1], T0
737 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
738 EPILOGUE_3_ARGS
739%else
740 int3
741 ret 4
742%endif
743ENDPROC iemAImpl_xadd_u64_locked
744
745
746;
747; CMPXCHG8B.
748;
749; These are tricky register wise, so the code is duplicated for each calling
750; convention.
751;
752; WARNING! This code make ASSUMPTIONS about which registers T1 and T0 are mapped to!
753;
754; C-proto:
755; IEM_DECL_IMPL_DEF(void, iemAImpl_cmpxchg8b,(uint64_t *pu64Dst, PRTUINT64U pu64EaxEdx, PRTUINT64U pu64EbxEcx,
756; uint32_t *pEFlags));
757;
758BEGINCODE
759BEGINPROC_FASTCALL iemAImpl_cmpxchg8b, 16
760%ifdef RT_ARCH_AMD64
761 %ifdef ASM_CALL64_MSC
762 push rbx
763
764 mov r11, rdx ; pu64EaxEdx (is also T1)
765 mov r10, rcx ; pu64Dst
766
767 mov ebx, [r8]
768 mov ecx, [r8 + 4]
769 IEM_MAYBE_LOAD_FLAGS r9, (X86_EFL_ZF), 0 ; clobbers T0 (eax)
770 mov eax, [r11]
771 mov edx, [r11 + 4]
772
773 lock cmpxchg8b [r10]
774
775 mov [r11], eax
776 mov [r11 + 4], edx
777 IEM_SAVE_FLAGS r9, (X86_EFL_ZF), 0 ; clobbers T0+T1 (eax, r11)
778
779 pop rbx
780 ret
781 %else
782 push rbx
783
784 mov r10, rcx ; pEFlags
785 mov r11, rdx ; pu64EbxEcx (is also T1)
786
787 mov ebx, [r11]
788 mov ecx, [r11 + 4]
789 IEM_MAYBE_LOAD_FLAGS r10, (X86_EFL_ZF), 0 ; clobbers T0 (eax)
790 mov eax, [rsi]
791 mov edx, [rsi + 4]
792
793 lock cmpxchg8b [rdi]
794
795 mov [rsi], eax
796 mov [rsi + 4], edx
797 IEM_SAVE_FLAGS r10, (X86_EFL_ZF), 0 ; clobbers T0+T1 (eax, r11)
798
799 pop rbx
800 ret
801
802 %endif
803%else
804 push esi
805 push edi
806 push ebx
807 push ebp
808
809 mov edi, ecx ; pu64Dst
810 mov esi, edx ; pu64EaxEdx
811 mov ecx, [esp + 16 + 4 + 0] ; pu64EbxEcx
812 mov ebp, [esp + 16 + 4 + 4] ; pEFlags
813
814 mov ebx, [ecx]
815 mov ecx, [ecx + 4]
816 IEM_MAYBE_LOAD_FLAGS ebp, (X86_EFL_ZF), 0 ; clobbers T0 (eax)
817 mov eax, [esi]
818 mov edx, [esi + 4]
819
820 lock cmpxchg8b [edi]
821
822 mov [esi], eax
823 mov [esi + 4], edx
824 IEM_SAVE_FLAGS ebp, (X86_EFL_ZF), 0 ; clobbers T0+T1 (eax, edi)
825
826 pop ebp
827 pop ebx
828 pop edi
829 pop esi
830 ret 8
831%endif
832ENDPROC iemAImpl_cmpxchg8b
833
834BEGINPROC_FASTCALL iemAImpl_cmpxchg8b_locked, 16
835 ; Lazy bird always lock prefixes cmpxchg8b.
836 jmp NAME_FASTCALL(iemAImpl_cmpxchg8b,16,$@)
837ENDPROC iemAImpl_cmpxchg8b_locked
838
839
840
841;
842; CMPXCHG.
843;
844; WARNING! This code make ASSUMPTIONS about which registers T1 and T0 are mapped to!
845;
846; C-proto:
847; IEM_DECL_IMPL_DEF(void, iemAImpl_cmpxchg,(uintX_t *puXDst, uintX_t puEax, uintX_t uReg, uint32_t *pEFlags));
848;
849BEGINCODE
850%macro IEMIMPL_CMPXCHG 2
851BEGINPROC_FASTCALL iemAImpl_cmpxchg_u8 %+ %2, 16
852 PROLOGUE_4_ARGS
853 IEM_MAYBE_LOAD_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
854 mov al, [A1]
855 %1 cmpxchg [A0], A2_8
856 mov [A1], al
857 IEM_SAVE_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, r11/edi)
858 EPILOGUE_4_ARGS
859ENDPROC iemAImpl_cmpxchg_u8 %+ %2
860
861BEGINPROC_FASTCALL iemAImpl_cmpxchg_u16 %+ %2, 16
862 PROLOGUE_4_ARGS
863 IEM_MAYBE_LOAD_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
864 mov ax, [A1]
865 %1 cmpxchg [A0], A2_16
866 mov [A1], ax
867 IEM_SAVE_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, r11/edi)
868 EPILOGUE_4_ARGS
869ENDPROC iemAImpl_cmpxchg_u16 %+ %2
870
871BEGINPROC_FASTCALL iemAImpl_cmpxchg_u32 %+ %2, 16
872 PROLOGUE_4_ARGS
873 IEM_MAYBE_LOAD_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
874 mov eax, [A1]
875 %1 cmpxchg [A0], A2_32
876 mov [A1], eax
877 IEM_SAVE_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, r11/edi)
878 EPILOGUE_4_ARGS
879ENDPROC iemAImpl_cmpxchg_u32 %+ %2
880
881BEGINPROC_FASTCALL iemAImpl_cmpxchg_u64 %+ %2, 16
882%ifdef RT_ARCH_AMD64
883 PROLOGUE_4_ARGS
884 IEM_MAYBE_LOAD_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
885 mov ax, [A1]
886 %1 cmpxchg [A0], A2
887 mov [A1], ax
888 IEM_SAVE_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, r11/edi)
889 EPILOGUE_4_ARGS
890%else
891 ;
892 ; Must use cmpxchg8b here. See also iemAImpl_cmpxchg8b.
893 ;
894 push esi
895 push edi
896 push ebx
897 push ebp
898
899 mov edi, ecx ; pu64Dst
900 mov esi, edx ; pu64Rax
901 mov ecx, [esp + 16 + 4 + 0] ; pu64Reg - Note! Pointer on 32-bit hosts!
902 mov ebp, [esp + 16 + 4 + 4] ; pEFlags
903
904 mov ebx, [ecx]
905 mov ecx, [ecx + 4]
906 IEM_MAYBE_LOAD_FLAGS ebp, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
907 mov eax, [esi]
908 mov edx, [esi + 4]
909
910 lock cmpxchg8b [edi]
911
912 ; cmpxchg8b doesn't set CF, PF, AF, SF and OF, so we have to do that.
913 jz .cmpxchg8b_not_equal
914 cmp eax, eax ; just set the other flags.
915.store:
916 mov [esi], eax
917 mov [esi + 4], edx
918 IEM_SAVE_FLAGS ebp, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, edi)
919
920 pop ebp
921 pop ebx
922 pop edi
923 pop esi
924 ret 8
925
926.cmpxchg8b_not_equal:
927 cmp [esi + 4], edx ;; @todo FIXME - verify 64-bit compare implementation
928 jne .store
929 cmp [esi], eax
930 jmp .store
931
932%endif
933ENDPROC iemAImpl_cmpxchg_u64 %+ %2
934%endmacro ; IEMIMPL_CMPXCHG
935
936IEMIMPL_CMPXCHG , ,
937IEMIMPL_CMPXCHG lock, _locked
938
939;;
940; Macro for implementing a unary operator.
941;
942; This will generate code for the 8, 16, 32 and 64 bit accesses with locked
943; variants, except on 32-bit system where the 64-bit accesses requires hand
944; coding.
945;
946; All the functions takes a pointer to the destination memory operand in A0,
947; the source register operand in A1 and a pointer to eflags in A2.
948;
949; @param 1 The instruction mnemonic.
950; @param 2 The modified flags.
951; @param 3 The undefined flags.
952;
953%macro IEMIMPL_UNARY_OP 3
954BEGINCODE
955BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 8
956 PROLOGUE_2_ARGS
957 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
958 %1 byte [A0]
959 IEM_SAVE_FLAGS A1, %2, %3
960 EPILOGUE_2_ARGS
961ENDPROC iemAImpl_ %+ %1 %+ _u8
962
963BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8_locked, 8
964 PROLOGUE_2_ARGS
965 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
966 lock %1 byte [A0]
967 IEM_SAVE_FLAGS A1, %2, %3
968 EPILOGUE_2_ARGS
969ENDPROC iemAImpl_ %+ %1 %+ _u8_locked
970
971BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 8
972 PROLOGUE_2_ARGS
973 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
974 %1 word [A0]
975 IEM_SAVE_FLAGS A1, %2, %3
976 EPILOGUE_2_ARGS
977ENDPROC iemAImpl_ %+ %1 %+ _u16
978
979BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 8
980 PROLOGUE_2_ARGS
981 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
982 lock %1 word [A0]
983 IEM_SAVE_FLAGS A1, %2, %3
984 EPILOGUE_2_ARGS
985ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
986
987BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 8
988 PROLOGUE_2_ARGS
989 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
990 %1 dword [A0]
991 IEM_SAVE_FLAGS A1, %2, %3
992 EPILOGUE_2_ARGS
993ENDPROC iemAImpl_ %+ %1 %+ _u32
994
995BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 8
996 PROLOGUE_2_ARGS
997 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
998 lock %1 dword [A0]
999 IEM_SAVE_FLAGS A1, %2, %3
1000 EPILOGUE_2_ARGS
1001ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
1002
1003 %ifdef RT_ARCH_AMD64
1004BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 8
1005 PROLOGUE_2_ARGS
1006 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
1007 %1 qword [A0]
1008 IEM_SAVE_FLAGS A1, %2, %3
1009 EPILOGUE_2_ARGS
1010ENDPROC iemAImpl_ %+ %1 %+ _u64
1011
1012BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 8
1013 PROLOGUE_2_ARGS
1014 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
1015 lock %1 qword [A0]
1016 IEM_SAVE_FLAGS A1, %2, %3
1017 EPILOGUE_2_ARGS
1018ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
1019 %else
1020 ; stub them for now.
1021BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 8
1022 int3
1023 ret 0
1024ENDPROC iemAImpl_ %+ %1 %+ _u64
1025BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 8
1026 int3
1027 ret 0
1028ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
1029 %endif
1030
1031%endmacro
1032
1033IEMIMPL_UNARY_OP inc, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), 0
1034IEMIMPL_UNARY_OP dec, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), 0
1035IEMIMPL_UNARY_OP neg, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
1036IEMIMPL_UNARY_OP not, 0, 0
1037
1038
1039
1040;;
1041; Macro for implementing a shift operation.
1042;
1043; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
1044; 32-bit system where the 64-bit accesses requires hand coding.
1045;
1046; All the functions takes a pointer to the destination memory operand in A0,
1047; the shift count in A1 and a pointer to eflags in A2.
1048;
1049; @param 1 The instruction mnemonic.
1050; @param 2 The modified flags.
1051; @param 3 The undefined flags.
1052;
1053; Makes ASSUMPTIONS about A0, A1 and A2 assignments.
1054;
1055%macro IEMIMPL_SHIFT_OP 3
1056BEGINCODE
1057BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
1058 PROLOGUE_3_ARGS
1059 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
1060 %ifdef ASM_CALL64_GCC
1061 mov cl, A1_8
1062 %1 byte [A0], cl
1063 %else
1064 xchg A1, A0
1065 %1 byte [A1], cl
1066 %endif
1067 IEM_SAVE_FLAGS A2, %2, %3
1068 EPILOGUE_3_ARGS
1069ENDPROC iemAImpl_ %+ %1 %+ _u8
1070
1071BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
1072 PROLOGUE_3_ARGS
1073 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
1074 %ifdef ASM_CALL64_GCC
1075 mov cl, A1_8
1076 %1 word [A0], cl
1077 %else
1078 xchg A1, A0
1079 %1 word [A1], cl
1080 %endif
1081 IEM_SAVE_FLAGS A2, %2, %3
1082 EPILOGUE_3_ARGS
1083ENDPROC iemAImpl_ %+ %1 %+ _u16
1084
1085BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
1086 PROLOGUE_3_ARGS
1087 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
1088 %ifdef ASM_CALL64_GCC
1089 mov cl, A1_8
1090 %1 dword [A0], cl
1091 %else
1092 xchg A1, A0
1093 %1 dword [A1], cl
1094 %endif
1095 IEM_SAVE_FLAGS A2, %2, %3
1096 EPILOGUE_3_ARGS
1097ENDPROC iemAImpl_ %+ %1 %+ _u32
1098
1099 %ifdef RT_ARCH_AMD64
1100BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 12
1101 PROLOGUE_3_ARGS
1102 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
1103 %ifdef ASM_CALL64_GCC
1104 mov cl, A1_8
1105 %1 qword [A0], cl
1106 %else
1107 xchg A1, A0
1108 %1 qword [A1], cl
1109 %endif
1110 IEM_SAVE_FLAGS A2, %2, %3
1111 EPILOGUE_3_ARGS
1112ENDPROC iemAImpl_ %+ %1 %+ _u64
1113 %else ; stub it for now - later, replace with hand coded stuff.
1114BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 12
1115 int3
1116 ret 4
1117ENDPROC iemAImpl_ %+ %1 %+ _u64
1118 %endif ; !RT_ARCH_AMD64
1119
1120%endmacro
1121
1122IEMIMPL_SHIFT_OP rol, (X86_EFL_OF | X86_EFL_CF), 0
1123IEMIMPL_SHIFT_OP ror, (X86_EFL_OF | X86_EFL_CF), 0
1124IEMIMPL_SHIFT_OP rcl, (X86_EFL_OF | X86_EFL_CF), 0
1125IEMIMPL_SHIFT_OP rcr, (X86_EFL_OF | X86_EFL_CF), 0
1126IEMIMPL_SHIFT_OP shl, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
1127IEMIMPL_SHIFT_OP shr, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
1128IEMIMPL_SHIFT_OP sar, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
1129
1130
1131;;
1132; Macro for implementing a double precision shift operation.
1133;
1134; This will generate code for the 16, 32 and 64 bit accesses, except on
1135; 32-bit system where the 64-bit accesses requires hand coding.
1136;
1137; The functions takes the destination operand (r/m) in A0, the source (reg) in
1138; A1, the shift count in A2 and a pointer to the eflags variable/register in A3.
1139;
1140; @param 1 The instruction mnemonic.
1141; @param 2 The modified flags.
1142; @param 3 The undefined flags.
1143;
1144; Makes ASSUMPTIONS about A0, A1, A2 and A3 assignments.
1145;
1146%macro IEMIMPL_SHIFT_DBL_OP 3
1147BEGINCODE
1148BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
1149 PROLOGUE_4_ARGS
1150 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1151 %ifdef ASM_CALL64_GCC
1152 xchg A3, A2
1153 %1 [A0], A1_16, cl
1154 xchg A3, A2
1155 %else
1156 xchg A0, A2
1157 %1 [A2], A1_16, cl
1158 %endif
1159 IEM_SAVE_FLAGS A3, %2, %3
1160 EPILOGUE_4_ARGS
1161ENDPROC iemAImpl_ %+ %1 %+ _u16
1162
1163BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
1164 PROLOGUE_4_ARGS
1165 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1166 %ifdef ASM_CALL64_GCC
1167 xchg A3, A2
1168 %1 [A0], A1_32, cl
1169 xchg A3, A2
1170 %else
1171 xchg A0, A2
1172 %1 [A2], A1_32, cl
1173 %endif
1174 IEM_SAVE_FLAGS A3, %2, %3
1175 EPILOGUE_4_ARGS
1176ENDPROC iemAImpl_ %+ %1 %+ _u32
1177
1178 %ifdef RT_ARCH_AMD64
1179BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1180 PROLOGUE_4_ARGS
1181 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1182 %ifdef ASM_CALL64_GCC
1183 xchg A3, A2
1184 %1 [A0], A1, cl
1185 xchg A3, A2
1186 %else
1187 xchg A0, A2
1188 %1 [A2], A1, cl
1189 %endif
1190 IEM_SAVE_FLAGS A3, %2, %3
1191 EPILOGUE_4_ARGS_EX 12
1192ENDPROC iemAImpl_ %+ %1 %+ _u64
1193 %else ; stub it for now - later, replace with hand coded stuff.
1194BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1195 int3
1196 ret 12
1197ENDPROC iemAImpl_ %+ %1 %+ _u64
1198 %endif ; !RT_ARCH_AMD64
1199
1200%endmacro
1201
1202IEMIMPL_SHIFT_DBL_OP shld, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
1203IEMIMPL_SHIFT_DBL_OP shrd, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
1204
1205
1206;;
1207; Macro for implementing a multiplication operations.
1208;
1209; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
1210; 32-bit system where the 64-bit accesses requires hand coding.
1211;
1212; The 8-bit function only operates on AX, so it takes no DX pointer. The other
1213; functions takes a pointer to rAX in A0, rDX in A1, the operand in A2 and a
1214; pointer to eflags in A3.
1215;
1216; The functions all return 0 so the caller can be used for div/idiv as well as
1217; for the mul/imul implementation.
1218;
1219; @param 1 The instruction mnemonic.
1220; @param 2 The modified flags.
1221; @param 3 The undefined flags.
1222;
1223; Makes ASSUMPTIONS about A0, A1, A2, A3, T0 and T1 assignments.
1224;
1225%macro IEMIMPL_MUL_OP 3
1226BEGINCODE
1227BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
1228 PROLOGUE_3_ARGS
1229 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
1230 mov al, [A0]
1231 %1 A1_8
1232 mov [A0], ax
1233 IEM_SAVE_FLAGS A2, %2, %3
1234 xor eax, eax
1235 EPILOGUE_3_ARGS
1236ENDPROC iemAImpl_ %+ %1 %+ _u8
1237
1238BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
1239 PROLOGUE_4_ARGS
1240 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1241 mov ax, [A0]
1242 %ifdef ASM_CALL64_GCC
1243 %1 A2_16
1244 mov [A0], ax
1245 mov [A1], dx
1246 %else
1247 mov T1, A1
1248 %1 A2_16
1249 mov [A0], ax
1250 mov [T1], dx
1251 %endif
1252 IEM_SAVE_FLAGS A3, %2, %3
1253 xor eax, eax
1254 EPILOGUE_4_ARGS
1255ENDPROC iemAImpl_ %+ %1 %+ _u16
1256
1257BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
1258 PROLOGUE_4_ARGS
1259 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1260 mov eax, [A0]
1261 %ifdef ASM_CALL64_GCC
1262 %1 A2_32
1263 mov [A0], eax
1264 mov [A1], edx
1265 %else
1266 mov T1, A1
1267 %1 A2_32
1268 mov [A0], eax
1269 mov [T1], edx
1270 %endif
1271 IEM_SAVE_FLAGS A3, %2, %3
1272 xor eax, eax
1273 EPILOGUE_4_ARGS
1274ENDPROC iemAImpl_ %+ %1 %+ _u32
1275
1276 %ifdef RT_ARCH_AMD64
1277BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1278 PROLOGUE_4_ARGS
1279 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1280 mov rax, [A0]
1281 %ifdef ASM_CALL64_GCC
1282 %1 A2
1283 mov [A0], rax
1284 mov [A1], rdx
1285 %else
1286 mov T1, A1
1287 %1 A2
1288 mov [A0], rax
1289 mov [T1], rdx
1290 %endif
1291 IEM_SAVE_FLAGS A3, %2, %3
1292 xor eax, eax
1293 EPILOGUE_4_ARGS_EX 12
1294ENDPROC iemAImpl_ %+ %1 %+ _u64
1295 %else ; stub it for now - later, replace with hand coded stuff.
1296BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1297 int3
1298 ret 12
1299ENDPROC iemAImpl_ %+ %1 %+ _u64
1300 %endif ; !RT_ARCH_AMD64
1301
1302%endmacro
1303
1304IEMIMPL_MUL_OP mul, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
1305IEMIMPL_MUL_OP imul, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
1306
1307
1308;;
1309; Macro for implementing a division operations.
1310;
1311; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
1312; 32-bit system where the 64-bit accesses requires hand coding.
1313;
1314; The 8-bit function only operates on AX, so it takes no DX pointer. The other
1315; functions takes a pointer to rAX in A0, rDX in A1, the operand in A2 and a
1316; pointer to eflags in A3.
1317;
1318; The functions all return 0 on success and -1 if a divide error should be
1319; raised by the caller.
1320;
1321; @param 1 The instruction mnemonic.
1322; @param 2 The modified flags.
1323; @param 3 The undefined flags.
1324; @param 4 1 if signed, 0 if unsigned.
1325;
1326; Makes ASSUMPTIONS about A0, A1, A2, A3, T0 and T1 assignments.
1327;
1328%macro IEMIMPL_DIV_OP 4
1329BEGINCODE
1330BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
1331 PROLOGUE_3_ARGS
1332
1333 ; div by chainsaw check.
1334 test A1_8, A1_8
1335 jz .div_zero
1336
1337 ; Overflow check - unsigned division is simple to verify, haven't
1338 ; found a simple way to check signed division yet unfortunately.
1339 %if %4 == 0
1340 cmp [A0 + 1], A1_8
1341 jae .div_overflow
1342 %else
1343 mov T0_16, [A0] ; T0 = dividend
1344 mov T1_8, A1_8 ; T1 = divisor
1345 test T1_16, T1_16
1346 js .divisor_negative
1347 test T0_16, T0_16
1348 jns .both_positive
1349 neg T0_16
1350.one_of_each: ; OK range is 2^(result-with - 1) + (divisor - 1).
1351 push T0 ; Start off like unsigned below.
1352 shr T0_16, 7
1353 cmp T0_8, T1_8
1354 pop T0
1355 jb .div_no_overflow
1356 ja .div_overflow
1357 and T0_8, 0x7f ; Special case for covering (divisor - 1).
1358 cmp T0_8, T1_8
1359 jae .div_overflow
1360 jmp .div_no_overflow
1361
1362.divisor_negative:
1363 neg T1_8
1364 test T0_16, T0_16
1365 jns .one_of_each
1366 neg T0_16
1367.both_positive: ; Same as unsigned shifted by sign indicator bit.
1368 shr T0_16, 7
1369 cmp T0_8, T1_8
1370 jae .div_overflow
1371.div_no_overflow:
1372 %endif
1373
1374 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
1375 mov ax, [A0]
1376 %1 A1_8
1377 mov [A0], ax
1378 IEM_SAVE_FLAGS A2, %2, %3
1379 xor eax, eax
1380
1381.return:
1382 EPILOGUE_3_ARGS
1383
1384.div_zero:
1385.div_overflow:
1386 mov eax, -1
1387 jmp .return
1388ENDPROC iemAImpl_ %+ %1 %+ _u8
1389
1390BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
1391 PROLOGUE_4_ARGS
1392
1393 test A2_16, A2_16
1394 jz .div_zero
1395 %if %4 == 0
1396 cmp [A1], A2_16
1397 jae .div_overflow
1398 %else
1399 ;; @todo idiv overflow checking.
1400 %endif
1401
1402 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1403 %ifdef ASM_CALL64_GCC
1404 mov T1, A2
1405 mov ax, [A0]
1406 mov dx, [A1]
1407 %1 T1_16
1408 mov [A0], ax
1409 mov [A1], dx
1410 %else
1411 mov T1, A1
1412 mov ax, [A0]
1413 mov dx, [T1]
1414 %1 A2_16
1415 mov [A0], ax
1416 mov [T1], dx
1417 %endif
1418 IEM_SAVE_FLAGS A3, %2, %3
1419 xor eax, eax
1420
1421.return:
1422 EPILOGUE_4_ARGS
1423
1424.div_zero:
1425.div_overflow:
1426 mov eax, -1
1427 jmp .return
1428ENDPROC iemAImpl_ %+ %1 %+ _u16
1429
1430BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
1431 PROLOGUE_4_ARGS
1432
1433 test A2_32, A2_32
1434 jz .div_zero
1435 %if %4 == 0
1436 cmp [A1], A2_32
1437 jae .div_overflow
1438 %else
1439 ;; @todo idiv overflow checking.
1440 %endif
1441
1442 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1443 mov eax, [A0]
1444 %ifdef ASM_CALL64_GCC
1445 mov T1, A2
1446 mov eax, [A0]
1447 mov edx, [A1]
1448 %1 T1_32
1449 mov [A0], eax
1450 mov [A1], edx
1451 %else
1452 mov T1, A1
1453 mov eax, [A0]
1454 mov edx, [T1]
1455 %1 A2_32
1456 mov [A0], eax
1457 mov [T1], edx
1458 %endif
1459 IEM_SAVE_FLAGS A3, %2, %3
1460 xor eax, eax
1461
1462.return:
1463 EPILOGUE_4_ARGS
1464
1465.div_zero:
1466.div_overflow:
1467 mov eax, -1
1468 jmp .return
1469ENDPROC iemAImpl_ %+ %1 %+ _u32
1470
1471 %ifdef RT_ARCH_AMD64
1472BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1473 PROLOGUE_4_ARGS
1474
1475 test A2, A2
1476 jz .div_zero
1477 %if %4 == 0
1478 cmp [A1], A2
1479 jae .div_overflow
1480 %else
1481 ;; @todo idiv overflow checking.
1482 %endif
1483
1484 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1485 mov rax, [A0]
1486 %ifdef ASM_CALL64_GCC
1487 mov T1, A2
1488 mov rax, [A0]
1489 mov rdx, [A1]
1490 %1 T1
1491 mov [A0], rax
1492 mov [A1], rdx
1493 %else
1494 mov T1, A1
1495 mov rax, [A0]
1496 mov rdx, [T1]
1497 %1 A2
1498 mov [A0], rax
1499 mov [T1], rdx
1500 %endif
1501 IEM_SAVE_FLAGS A3, %2, %3
1502 xor eax, eax
1503
1504.return:
1505 EPILOGUE_4_ARGS_EX 12
1506
1507.div_zero:
1508.div_overflow:
1509 mov eax, -1
1510 jmp .return
1511ENDPROC iemAImpl_ %+ %1 %+ _u64
1512 %else ; stub it for now - later, replace with hand coded stuff.
1513BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1514 int3
1515 ret
1516ENDPROC iemAImpl_ %+ %1 %+ _u64
1517 %endif ; !RT_ARCH_AMD64
1518
1519%endmacro
1520
1521IEMIMPL_DIV_OP div, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
1522IEMIMPL_DIV_OP idiv, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 1
1523
1524
1525;
1526; BSWAP. No flag changes.
1527;
1528; Each function takes one argument, pointer to the value to bswap
1529; (input/output). They all return void.
1530;
1531BEGINPROC_FASTCALL iemAImpl_bswap_u16, 4
1532 PROLOGUE_1_ARGS
1533 mov T0_32, [A0] ; just in case any of the upper bits are used.
1534 db 66h
1535 bswap T0_32
1536 mov [A0], T0_32
1537 EPILOGUE_1_ARGS
1538ENDPROC iemAImpl_bswap_u16
1539
1540BEGINPROC_FASTCALL iemAImpl_bswap_u32, 4
1541 PROLOGUE_1_ARGS
1542 mov T0_32, [A0]
1543 bswap T0_32
1544 mov [A0], T0_32
1545 EPILOGUE_1_ARGS
1546ENDPROC iemAImpl_bswap_u32
1547
1548BEGINPROC_FASTCALL iemAImpl_bswap_u64, 4
1549%ifdef RT_ARCH_AMD64
1550 PROLOGUE_1_ARGS
1551 mov T0, [A0]
1552 bswap T0
1553 mov [A0], T0
1554 EPILOGUE_1_ARGS
1555%else
1556 PROLOGUE_1_ARGS
1557 mov T0, [A0]
1558 mov T1, [A0 + 4]
1559 bswap T0
1560 bswap T1
1561 mov [A0 + 4], T0
1562 mov [A0], T1
1563 EPILOGUE_1_ARGS
1564%endif
1565ENDPROC iemAImpl_bswap_u64
1566
1567
1568;;
1569; Initialize the FPU for the actual instruction being emulated, this means
1570; loading parts of the guest's control word and status word.
1571;
1572; @uses 24 bytes of stack.
1573; @param 1 Expression giving the address of the FXSTATE of the guest.
1574;
1575%macro FPU_LD_FXSTATE_FCW_AND_SAFE_FSW 1
1576 fnstenv [xSP]
1577
1578 ; FCW - for exception, precision and rounding control.
1579 movzx T0, word [%1 + X86FXSTATE.FCW]
1580 and T0, X86_FCW_MASK_ALL | X86_FCW_PC_MASK | X86_FCW_RC_MASK
1581 mov [xSP + X86FSTENV32P.FCW], T0_16
1582
1583 ; FSW - for undefined C0, C1, C2, and C3.
1584 movzx T1, word [%1 + X86FXSTATE.FSW]
1585 and T1, X86_FSW_C_MASK
1586 movzx T0, word [xSP + X86FSTENV32P.FSW]
1587 and T0, X86_FSW_TOP_MASK
1588 or T0, T1
1589 mov [xSP + X86FSTENV32P.FSW], T0_16
1590
1591 fldenv [xSP]
1592%endmacro
1593
1594
1595;;
1596; Need to move this as well somewhere better?
1597;
1598struc IEMFPURESULT
1599 .r80Result resw 5
1600 .FSW resw 1
1601endstruc
1602
1603
1604;;
1605; Need to move this as well somewhere better?
1606;
1607struc IEMFPURESULTTWO
1608 .r80Result1 resw 5
1609 .FSW resw 1
1610 .r80Result2 resw 5
1611endstruc
1612
1613
1614;
1615;---------------------- 16-bit signed integer operations ----------------------
1616;
1617
1618
1619;;
1620; Converts a 16-bit floating point value to a 80-bit one (fpu register).
1621;
1622; @param A0 FPU context (fxsave).
1623; @param A1 Pointer to a IEMFPURESULT for the output.
1624; @param A2 Pointer to the 16-bit floating point value to convert.
1625;
1626BEGINPROC_FASTCALL iemAImpl_fild_i16_to_r80, 12
1627 PROLOGUE_3_ARGS
1628 sub xSP, 20h
1629
1630 fninit
1631 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1632 fild word [A2]
1633
1634 fnstsw word [A1 + IEMFPURESULT.FSW]
1635 fnclex
1636 fstp tword [A1 + IEMFPURESULT.r80Result]
1637
1638 fninit
1639 add xSP, 20h
1640 EPILOGUE_3_ARGS
1641ENDPROC iemAImpl_fild_i16_to_r80
1642
1643
1644;;
1645; Store a 80-bit floating point value (register) as a 16-bit signed integer (memory).
1646;
1647; @param A0 FPU context (fxsave).
1648; @param A1 Where to return the output FSW.
1649; @param A2 Where to store the 16-bit signed integer value.
1650; @param A3 Pointer to the 80-bit value.
1651;
1652BEGINPROC_FASTCALL iemAImpl_fist_r80_to_i16, 16
1653 PROLOGUE_4_ARGS
1654 sub xSP, 20h
1655
1656 fninit
1657 fld tword [A3]
1658 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1659 fistp word [A2]
1660
1661 fnstsw word [A1]
1662
1663 fninit
1664 add xSP, 20h
1665 EPILOGUE_4_ARGS
1666ENDPROC iemAImpl_fist_r80_to_i16
1667
1668
1669;;
1670; Store a 80-bit floating point value (register) as a 16-bit signed integer
1671; (memory) with truncation.
1672;
1673; @param A0 FPU context (fxsave).
1674; @param A1 Where to return the output FSW.
1675; @param A2 Where to store the 16-bit signed integer value.
1676; @param A3 Pointer to the 80-bit value.
1677;
1678BEGINPROC_FASTCALL iemAImpl_fistt_r80_to_i16, 16
1679 PROLOGUE_4_ARGS
1680 sub xSP, 20h
1681
1682 fninit
1683 fld tword [A3]
1684 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1685 fisttp dword [A2]
1686
1687 fnstsw word [A1]
1688
1689 fninit
1690 add xSP, 20h
1691 EPILOGUE_4_ARGS
1692ENDPROC iemAImpl_fistt_r80_to_i16
1693
1694
1695;;
1696; FPU instruction working on one 80-bit and one 16-bit signed integer value.
1697;
1698; @param 1 The instruction
1699;
1700; @param A0 FPU context (fxsave).
1701; @param A1 Pointer to a IEMFPURESULT for the output.
1702; @param A2 Pointer to the 80-bit value.
1703; @param A3 Pointer to the 16-bit value.
1704;
1705%macro IEMIMPL_FPU_R80_BY_I16 1
1706BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_i16, 16
1707 PROLOGUE_4_ARGS
1708 sub xSP, 20h
1709
1710 fninit
1711 fld tword [A2]
1712 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1713 %1 word [A3]
1714
1715 fnstsw word [A1 + IEMFPURESULT.FSW]
1716 fnclex
1717 fstp tword [A1 + IEMFPURESULT.r80Result]
1718
1719 fninit
1720 add xSP, 20h
1721 EPILOGUE_4_ARGS
1722ENDPROC iemAImpl_ %+ %1 %+ _r80_by_i16
1723%endmacro
1724
1725IEMIMPL_FPU_R80_BY_I16 fiadd
1726IEMIMPL_FPU_R80_BY_I16 fimul
1727IEMIMPL_FPU_R80_BY_I16 fisub
1728IEMIMPL_FPU_R80_BY_I16 fisubr
1729IEMIMPL_FPU_R80_BY_I16 fidiv
1730IEMIMPL_FPU_R80_BY_I16 fidivr
1731
1732
1733;;
1734; FPU instruction working on one 80-bit and one 16-bit signed integer value,
1735; only returning FSW.
1736;
1737; @param 1 The instruction
1738;
1739; @param A0 FPU context (fxsave).
1740; @param A1 Where to store the output FSW.
1741; @param A2 Pointer to the 80-bit value.
1742; @param A3 Pointer to the 64-bit value.
1743;
1744%macro IEMIMPL_FPU_R80_BY_I16_FSW 1
1745BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_i16, 16
1746 PROLOGUE_4_ARGS
1747 sub xSP, 20h
1748
1749 fninit
1750 fld tword [A2]
1751 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1752 %1 word [A3]
1753
1754 fnstsw word [A1]
1755
1756 fninit
1757 add xSP, 20h
1758 EPILOGUE_4_ARGS
1759ENDPROC iemAImpl_ %+ %1 %+ _r80_by_i16
1760%endmacro
1761
1762IEMIMPL_FPU_R80_BY_I16_FSW ficom
1763
1764
1765
1766;
1767;---------------------- 32-bit signed integer operations ----------------------
1768;
1769
1770
1771;;
1772; Converts a 32-bit floating point value to a 80-bit one (fpu register).
1773;
1774; @param A0 FPU context (fxsave).
1775; @param A1 Pointer to a IEMFPURESULT for the output.
1776; @param A2 Pointer to the 32-bit floating point value to convert.
1777;
1778BEGINPROC_FASTCALL iemAImpl_fild_i32_to_r80, 12
1779 PROLOGUE_3_ARGS
1780 sub xSP, 20h
1781
1782 fninit
1783 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1784 fild dword [A2]
1785
1786 fnstsw word [A1 + IEMFPURESULT.FSW]
1787 fnclex
1788 fstp tword [A1 + IEMFPURESULT.r80Result]
1789
1790 fninit
1791 add xSP, 20h
1792 EPILOGUE_3_ARGS
1793ENDPROC iemAImpl_fild_i32_to_r80
1794
1795
1796;;
1797; Store a 80-bit floating point value (register) as a 32-bit signed integer (memory).
1798;
1799; @param A0 FPU context (fxsave).
1800; @param A1 Where to return the output FSW.
1801; @param A2 Where to store the 32-bit signed integer value.
1802; @param A3 Pointer to the 80-bit value.
1803;
1804BEGINPROC_FASTCALL iemAImpl_fist_r80_to_i32, 16
1805 PROLOGUE_4_ARGS
1806 sub xSP, 20h
1807
1808 fninit
1809 fld tword [A3]
1810 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1811 fistp dword [A2]
1812
1813 fnstsw word [A1]
1814
1815 fninit
1816 add xSP, 20h
1817 EPILOGUE_4_ARGS
1818ENDPROC iemAImpl_fist_r80_to_i32
1819
1820
1821;;
1822; Store a 80-bit floating point value (register) as a 32-bit signed integer
1823; (memory) with truncation.
1824;
1825; @param A0 FPU context (fxsave).
1826; @param A1 Where to return the output FSW.
1827; @param A2 Where to store the 32-bit signed integer value.
1828; @param A3 Pointer to the 80-bit value.
1829;
1830BEGINPROC_FASTCALL iemAImpl_fistt_r80_to_i32, 16
1831 PROLOGUE_4_ARGS
1832 sub xSP, 20h
1833
1834 fninit
1835 fld tword [A3]
1836 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1837 fisttp dword [A2]
1838
1839 fnstsw word [A1]
1840
1841 fninit
1842 add xSP, 20h
1843 EPILOGUE_4_ARGS
1844ENDPROC iemAImpl_fistt_r80_to_i32
1845
1846
1847;;
1848; FPU instruction working on one 80-bit and one 32-bit signed integer value.
1849;
1850; @param 1 The instruction
1851;
1852; @param A0 FPU context (fxsave).
1853; @param A1 Pointer to a IEMFPURESULT for the output.
1854; @param A2 Pointer to the 80-bit value.
1855; @param A3 Pointer to the 32-bit value.
1856;
1857%macro IEMIMPL_FPU_R80_BY_I32 1
1858BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_i32, 16
1859 PROLOGUE_4_ARGS
1860 sub xSP, 20h
1861
1862 fninit
1863 fld tword [A2]
1864 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1865 %1 dword [A3]
1866
1867 fnstsw word [A1 + IEMFPURESULT.FSW]
1868 fnclex
1869 fstp tword [A1 + IEMFPURESULT.r80Result]
1870
1871 fninit
1872 add xSP, 20h
1873 EPILOGUE_4_ARGS
1874ENDPROC iemAImpl_ %+ %1 %+ _r80_by_i32
1875%endmacro
1876
1877IEMIMPL_FPU_R80_BY_I32 fiadd
1878IEMIMPL_FPU_R80_BY_I32 fimul
1879IEMIMPL_FPU_R80_BY_I32 fisub
1880IEMIMPL_FPU_R80_BY_I32 fisubr
1881IEMIMPL_FPU_R80_BY_I32 fidiv
1882IEMIMPL_FPU_R80_BY_I32 fidivr
1883
1884
1885;;
1886; FPU instruction working on one 80-bit and one 32-bit signed integer value,
1887; only returning FSW.
1888;
1889; @param 1 The instruction
1890;
1891; @param A0 FPU context (fxsave).
1892; @param A1 Where to store the output FSW.
1893; @param A2 Pointer to the 80-bit value.
1894; @param A3 Pointer to the 64-bit value.
1895;
1896%macro IEMIMPL_FPU_R80_BY_I32_FSW 1
1897BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_i32, 16
1898 PROLOGUE_4_ARGS
1899 sub xSP, 20h
1900
1901 fninit
1902 fld tword [A2]
1903 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1904 %1 dword [A3]
1905
1906 fnstsw word [A1]
1907
1908 fninit
1909 add xSP, 20h
1910 EPILOGUE_4_ARGS
1911ENDPROC iemAImpl_ %+ %1 %+ _r80_by_i32
1912%endmacro
1913
1914IEMIMPL_FPU_R80_BY_I32_FSW ficom
1915
1916
1917
1918;
1919;---------------------- 64-bit signed integer operations ----------------------
1920;
1921
1922
1923;;
1924; Converts a 64-bit floating point value to a 80-bit one (fpu register).
1925;
1926; @param A0 FPU context (fxsave).
1927; @param A1 Pointer to a IEMFPURESULT for the output.
1928; @param A2 Pointer to the 64-bit floating point value to convert.
1929;
1930BEGINPROC_FASTCALL iemAImpl_fild_i64_to_r80, 12
1931 PROLOGUE_3_ARGS
1932 sub xSP, 20h
1933
1934 fninit
1935 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1936 fild qword [A2]
1937
1938 fnstsw word [A1 + IEMFPURESULT.FSW]
1939 fnclex
1940 fstp tword [A1 + IEMFPURESULT.r80Result]
1941
1942 fninit
1943 add xSP, 20h
1944 EPILOGUE_3_ARGS
1945ENDPROC iemAImpl_fild_i64_to_r80
1946
1947
1948;;
1949; Store a 80-bit floating point value (register) as a 64-bit signed integer (memory).
1950;
1951; @param A0 FPU context (fxsave).
1952; @param A1 Where to return the output FSW.
1953; @param A2 Where to store the 64-bit signed integer value.
1954; @param A3 Pointer to the 80-bit value.
1955;
1956BEGINPROC_FASTCALL iemAImpl_fist_r80_to_i64, 16
1957 PROLOGUE_4_ARGS
1958 sub xSP, 20h
1959
1960 fninit
1961 fld tword [A3]
1962 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1963 fistp qword [A2]
1964
1965 fnstsw word [A1]
1966
1967 fninit
1968 add xSP, 20h
1969 EPILOGUE_4_ARGS
1970ENDPROC iemAImpl_fist_r80_to_i64
1971
1972
1973;;
1974; Store a 80-bit floating point value (register) as a 64-bit signed integer
1975; (memory) with truncation.
1976;
1977; @param A0 FPU context (fxsave).
1978; @param A1 Where to return the output FSW.
1979; @param A2 Where to store the 64-bit signed integer value.
1980; @param A3 Pointer to the 80-bit value.
1981;
1982BEGINPROC_FASTCALL iemAImpl_fistt_r80_to_i64, 16
1983 PROLOGUE_4_ARGS
1984 sub xSP, 20h
1985
1986 fninit
1987 fld tword [A3]
1988 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1989 fisttp qword [A2]
1990
1991 fnstsw word [A1]
1992
1993 fninit
1994 add xSP, 20h
1995 EPILOGUE_4_ARGS
1996ENDPROC iemAImpl_fistt_r80_to_i64
1997
1998
1999
2000;
2001;---------------------- 32-bit floating point operations ----------------------
2002;
2003
2004;;
2005; Converts a 32-bit floating point value to a 80-bit one (fpu register).
2006;
2007; @param A0 FPU context (fxsave).
2008; @param A1 Pointer to a IEMFPURESULT for the output.
2009; @param A2 Pointer to the 32-bit floating point value to convert.
2010;
2011BEGINPROC_FASTCALL iemAImpl_fld_r32_to_r80, 12
2012 PROLOGUE_3_ARGS
2013 sub xSP, 20h
2014
2015 fninit
2016 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2017 fld dword [A2]
2018
2019 fnstsw word [A1 + IEMFPURESULT.FSW]
2020 fnclex
2021 fstp tword [A1 + IEMFPURESULT.r80Result]
2022
2023 fninit
2024 add xSP, 20h
2025 EPILOGUE_3_ARGS
2026ENDPROC iemAImpl_fld_r32_to_r80
2027
2028
2029;;
2030; Store a 80-bit floating point value (register) as a 32-bit one (memory).
2031;
2032; @param A0 FPU context (fxsave).
2033; @param A1 Where to return the output FSW.
2034; @param A2 Where to store the 32-bit value.
2035; @param A3 Pointer to the 80-bit value.
2036;
2037BEGINPROC_FASTCALL iemAImpl_fst_r80_to_r32, 16
2038 PROLOGUE_4_ARGS
2039 sub xSP, 20h
2040
2041 fninit
2042 fld tword [A3]
2043 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2044 fst dword [A2]
2045
2046 fnstsw word [A1]
2047
2048 fninit
2049 add xSP, 20h
2050 EPILOGUE_4_ARGS
2051ENDPROC iemAImpl_fst_r80_to_r32
2052
2053
2054;;
2055; FPU instruction working on one 80-bit and one 32-bit floating point value.
2056;
2057; @param 1 The instruction
2058;
2059; @param A0 FPU context (fxsave).
2060; @param A1 Pointer to a IEMFPURESULT for the output.
2061; @param A2 Pointer to the 80-bit value.
2062; @param A3 Pointer to the 32-bit value.
2063;
2064%macro IEMIMPL_FPU_R80_BY_R32 1
2065BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r32, 16
2066 PROLOGUE_4_ARGS
2067 sub xSP, 20h
2068
2069 fninit
2070 fld tword [A2]
2071 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2072 %1 dword [A3]
2073
2074 fnstsw word [A1 + IEMFPURESULT.FSW]
2075 fnclex
2076 fstp tword [A1 + IEMFPURESULT.r80Result]
2077
2078 fninit
2079 add xSP, 20h
2080 EPILOGUE_4_ARGS
2081ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r32
2082%endmacro
2083
2084IEMIMPL_FPU_R80_BY_R32 fadd
2085IEMIMPL_FPU_R80_BY_R32 fmul
2086IEMIMPL_FPU_R80_BY_R32 fsub
2087IEMIMPL_FPU_R80_BY_R32 fsubr
2088IEMIMPL_FPU_R80_BY_R32 fdiv
2089IEMIMPL_FPU_R80_BY_R32 fdivr
2090
2091
2092;;
2093; FPU instruction working on one 80-bit and one 32-bit floating point value,
2094; only returning FSW.
2095;
2096; @param 1 The instruction
2097;
2098; @param A0 FPU context (fxsave).
2099; @param A1 Where to store the output FSW.
2100; @param A2 Pointer to the 80-bit value.
2101; @param A3 Pointer to the 64-bit value.
2102;
2103%macro IEMIMPL_FPU_R80_BY_R32_FSW 1
2104BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r32, 16
2105 PROLOGUE_4_ARGS
2106 sub xSP, 20h
2107
2108 fninit
2109 fld tword [A2]
2110 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2111 %1 dword [A3]
2112
2113 fnstsw word [A1]
2114
2115 fninit
2116 add xSP, 20h
2117 EPILOGUE_4_ARGS
2118ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r32
2119%endmacro
2120
2121IEMIMPL_FPU_R80_BY_R32_FSW fcom
2122
2123
2124
2125;
2126;---------------------- 64-bit floating point operations ----------------------
2127;
2128
2129;;
2130; Converts a 64-bit floating point value to a 80-bit one (fpu register).
2131;
2132; @param A0 FPU context (fxsave).
2133; @param A1 Pointer to a IEMFPURESULT for the output.
2134; @param A2 Pointer to the 64-bit floating point value to convert.
2135;
2136BEGINPROC_FASTCALL iemAImpl_fld_r64_to_r80, 12
2137 PROLOGUE_3_ARGS
2138 sub xSP, 20h
2139
2140 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2141 fld qword [A2]
2142
2143 fnstsw word [A1 + IEMFPURESULT.FSW]
2144 fnclex
2145 fstp tword [A1 + IEMFPURESULT.r80Result]
2146
2147 fninit
2148 add xSP, 20h
2149 EPILOGUE_3_ARGS
2150ENDPROC iemAImpl_fld_r64_to_r80
2151
2152
2153;;
2154; Store a 80-bit floating point value (register) as a 64-bit one (memory).
2155;
2156; @param A0 FPU context (fxsave).
2157; @param A1 Where to return the output FSW.
2158; @param A2 Where to store the 64-bit value.
2159; @param A3 Pointer to the 80-bit value.
2160;
2161BEGINPROC_FASTCALL iemAImpl_fst_r80_to_r64, 16
2162 PROLOGUE_4_ARGS
2163 sub xSP, 20h
2164
2165 fninit
2166 fld tword [A3]
2167 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2168 fst qword [A2]
2169
2170 fnstsw word [A1]
2171
2172 fninit
2173 add xSP, 20h
2174 EPILOGUE_4_ARGS
2175ENDPROC iemAImpl_fst_r80_to_r64
2176
2177
2178;;
2179; FPU instruction working on one 80-bit and one 64-bit floating point value.
2180;
2181; @param 1 The instruction
2182;
2183; @param A0 FPU context (fxsave).
2184; @param A1 Pointer to a IEMFPURESULT for the output.
2185; @param A2 Pointer to the 80-bit value.
2186; @param A3 Pointer to the 64-bit value.
2187;
2188%macro IEMIMPL_FPU_R80_BY_R64 1
2189BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r64, 16
2190 PROLOGUE_4_ARGS
2191 sub xSP, 20h
2192
2193 fninit
2194 fld tword [A2]
2195 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2196 %1 qword [A3]
2197
2198 fnstsw word [A1 + IEMFPURESULT.FSW]
2199 fnclex
2200 fstp tword [A1 + IEMFPURESULT.r80Result]
2201
2202 fninit
2203 add xSP, 20h
2204 EPILOGUE_4_ARGS
2205ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r64
2206%endmacro
2207
2208IEMIMPL_FPU_R80_BY_R64 fadd
2209IEMIMPL_FPU_R80_BY_R64 fmul
2210IEMIMPL_FPU_R80_BY_R64 fsub
2211IEMIMPL_FPU_R80_BY_R64 fsubr
2212IEMIMPL_FPU_R80_BY_R64 fdiv
2213IEMIMPL_FPU_R80_BY_R64 fdivr
2214
2215;;
2216; FPU instruction working on one 80-bit and one 64-bit floating point value,
2217; only returning FSW.
2218;
2219; @param 1 The instruction
2220;
2221; @param A0 FPU context (fxsave).
2222; @param A1 Where to store the output FSW.
2223; @param A2 Pointer to the 80-bit value.
2224; @param A3 Pointer to the 64-bit value.
2225;
2226%macro IEMIMPL_FPU_R80_BY_R64_FSW 1
2227BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r64, 16
2228 PROLOGUE_4_ARGS
2229 sub xSP, 20h
2230
2231 fninit
2232 fld tword [A2]
2233 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2234 %1 qword [A3]
2235
2236 fnstsw word [A1]
2237
2238 fninit
2239 add xSP, 20h
2240 EPILOGUE_4_ARGS
2241ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r64
2242%endmacro
2243
2244IEMIMPL_FPU_R80_BY_R64_FSW fcom
2245
2246
2247
2248;
2249;---------------------- 80-bit floating point operations ----------------------
2250;
2251
2252;;
2253; Loads a 80-bit floating point register value from memory.
2254;
2255; @param A0 FPU context (fxsave).
2256; @param A1 Pointer to a IEMFPURESULT for the output.
2257; @param A2 Pointer to the 80-bit floating point value to load.
2258;
2259BEGINPROC_FASTCALL iemAImpl_fld_r80_from_r80, 12
2260 PROLOGUE_3_ARGS
2261 sub xSP, 20h
2262
2263 fninit
2264 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2265 fld tword [A2]
2266
2267 fnstsw word [A1 + IEMFPURESULT.FSW]
2268 fnclex
2269 fstp tword [A1 + IEMFPURESULT.r80Result]
2270
2271 fninit
2272 add xSP, 20h
2273 EPILOGUE_3_ARGS
2274ENDPROC iemAImpl_fld_r80_from_r80
2275
2276
2277;;
2278; Store a 80-bit floating point register to memory
2279;
2280; @param A0 FPU context (fxsave).
2281; @param A1 Where to return the output FSW.
2282; @param A2 Where to store the 80-bit value.
2283; @param A3 Pointer to the 80-bit register value.
2284;
2285BEGINPROC_FASTCALL iemAImpl_fst_r80_to_r80, 16
2286 PROLOGUE_4_ARGS
2287 sub xSP, 20h
2288
2289 fninit
2290 fld tword [A3]
2291 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2292 fstp tword [A2]
2293
2294 fnstsw word [A1]
2295
2296 fninit
2297 add xSP, 20h
2298 EPILOGUE_4_ARGS
2299ENDPROC iemAImpl_fst_r80_to_r80
2300
2301
2302;;
2303; FPU instruction working on two 80-bit floating point values.
2304;
2305; @param 1 The instruction
2306;
2307; @param A0 FPU context (fxsave).
2308; @param A1 Pointer to a IEMFPURESULT for the output.
2309; @param A2 Pointer to the first 80-bit value (ST0)
2310; @param A3 Pointer to the second 80-bit value (STn).
2311;
2312%macro IEMIMPL_FPU_R80_BY_R80 2
2313BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
2314 PROLOGUE_4_ARGS
2315 sub xSP, 20h
2316
2317 fninit
2318 fld tword [A3]
2319 fld tword [A2]
2320 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2321 %1 %2
2322
2323 fnstsw word [A1 + IEMFPURESULT.FSW]
2324 fnclex
2325 fstp tword [A1 + IEMFPURESULT.r80Result]
2326
2327 fninit
2328 add xSP, 20h
2329 EPILOGUE_4_ARGS
2330ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
2331%endmacro
2332
2333IEMIMPL_FPU_R80_BY_R80 fadd, {st0, st1}
2334IEMIMPL_FPU_R80_BY_R80 fmul, {st0, st1}
2335IEMIMPL_FPU_R80_BY_R80 fsub, {st0, st1}
2336IEMIMPL_FPU_R80_BY_R80 fsubr, {st0, st1}
2337IEMIMPL_FPU_R80_BY_R80 fdiv, {st0, st1}
2338IEMIMPL_FPU_R80_BY_R80 fdivr, {st0, st1}
2339IEMIMPL_FPU_R80_BY_R80 fprem, {}
2340IEMIMPL_FPU_R80_BY_R80 fprem1, {}
2341IEMIMPL_FPU_R80_BY_R80 fscale, {}
2342
2343
2344;;
2345; FPU instruction working on two 80-bit floating point values, ST1 and ST0,
2346; storing the result in ST1 and popping the stack.
2347;
2348; @param 1 The instruction
2349;
2350; @param A0 FPU context (fxsave).
2351; @param A1 Pointer to a IEMFPURESULT for the output.
2352; @param A2 Pointer to the first 80-bit value (ST1).
2353; @param A3 Pointer to the second 80-bit value (ST0).
2354;
2355%macro IEMIMPL_FPU_R80_BY_R80_ST1_ST0_POP 1
2356BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
2357 PROLOGUE_4_ARGS
2358 sub xSP, 20h
2359
2360 fninit
2361 fld tword [A2]
2362 fld tword [A3]
2363 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2364 %1
2365
2366 fnstsw word [A1 + IEMFPURESULT.FSW]
2367 fnclex
2368 fstp tword [A1 + IEMFPURESULT.r80Result]
2369
2370 fninit
2371 add xSP, 20h
2372 EPILOGUE_4_ARGS
2373ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
2374%endmacro
2375
2376IEMIMPL_FPU_R80_BY_R80_ST1_ST0_POP fpatan
2377IEMIMPL_FPU_R80_BY_R80_ST1_ST0_POP fyl2xp1
2378
2379
2380;;
2381; FPU instruction working on two 80-bit floating point values, only
2382; returning FSW.
2383;
2384; @param 1 The instruction
2385;
2386; @param A0 FPU context (fxsave).
2387; @param A1 Pointer to a uint16_t for the resulting FSW.
2388; @param A2 Pointer to the first 80-bit value.
2389; @param A3 Pointer to the second 80-bit value.
2390;
2391%macro IEMIMPL_FPU_R80_BY_R80_FSW 1
2392BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
2393 PROLOGUE_4_ARGS
2394 sub xSP, 20h
2395
2396 fninit
2397 fld tword [A3]
2398 fld tword [A2]
2399 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2400 %1 st0, st1
2401
2402 fnstsw word [A1]
2403
2404 fninit
2405 add xSP, 20h
2406 EPILOGUE_4_ARGS
2407ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
2408%endmacro
2409
2410IEMIMPL_FPU_R80_BY_R80_FSW fcom
2411IEMIMPL_FPU_R80_BY_R80_FSW fucom
2412
2413
2414;;
2415; FPU instruction working on two 80-bit floating point values,
2416; returning FSW and EFLAGS (eax).
2417;
2418; @param 1 The instruction
2419;
2420; @returns EFLAGS in EAX.
2421; @param A0 FPU context (fxsave).
2422; @param A1 Pointer to a uint16_t for the resulting FSW.
2423; @param A2 Pointer to the first 80-bit value.
2424; @param A3 Pointer to the second 80-bit value.
2425;
2426%macro IEMIMPL_FPU_R80_BY_R80_EFL 1
2427BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
2428 PROLOGUE_4_ARGS
2429 sub xSP, 20h
2430
2431 fninit
2432 fld tword [A3]
2433 fld tword [A2]
2434 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2435 %1 st1
2436
2437 fnstsw word [A1]
2438 pushf
2439 pop xAX
2440
2441 fninit
2442 add xSP, 20h
2443 EPILOGUE_4_ARGS
2444ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
2445%endmacro
2446
2447IEMIMPL_FPU_R80_BY_R80_EFL fcomi
2448IEMIMPL_FPU_R80_BY_R80_EFL fucomi
2449
2450
2451;;
2452; FPU instruction working on one 80-bit floating point value.
2453;
2454; @param 1 The instruction
2455;
2456; @param A0 FPU context (fxsave).
2457; @param A1 Pointer to a IEMFPURESULT for the output.
2458; @param A2 Pointer to the 80-bit value.
2459;
2460%macro IEMIMPL_FPU_R80 1
2461BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80, 12
2462 PROLOGUE_3_ARGS
2463 sub xSP, 20h
2464
2465 fninit
2466 fld tword [A2]
2467 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2468 %1
2469
2470 fnstsw word [A1 + IEMFPURESULT.FSW]
2471 fnclex
2472 fstp tword [A1 + IEMFPURESULT.r80Result]
2473
2474 fninit
2475 add xSP, 20h
2476 EPILOGUE_3_ARGS
2477ENDPROC iemAImpl_ %+ %1 %+ _r80
2478%endmacro
2479
2480IEMIMPL_FPU_R80 fchs
2481IEMIMPL_FPU_R80 fabs
2482IEMIMPL_FPU_R80 f2xm1
2483IEMIMPL_FPU_R80 fyl2x
2484IEMIMPL_FPU_R80 fsqrt
2485IEMIMPL_FPU_R80 frndint
2486IEMIMPL_FPU_R80 fsin
2487IEMIMPL_FPU_R80 fcos
2488
2489
2490;;
2491; FPU instruction working on one 80-bit floating point value, only
2492; returning FSW.
2493;
2494; @param 1 The instruction
2495;
2496; @param A0 FPU context (fxsave).
2497; @param A1 Pointer to a uint16_t for the resulting FSW.
2498; @param A2 Pointer to the 80-bit value.
2499;
2500%macro IEMIMPL_FPU_R80_FSW 1
2501BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80, 12
2502 PROLOGUE_3_ARGS
2503 sub xSP, 20h
2504
2505 fninit
2506 fld tword [A2]
2507 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2508 %1
2509
2510 fnstsw word [A1]
2511
2512 fninit
2513 add xSP, 20h
2514 EPILOGUE_3_ARGS
2515ENDPROC iemAImpl_ %+ %1 %+ _r80
2516%endmacro
2517
2518IEMIMPL_FPU_R80_FSW ftst
2519IEMIMPL_FPU_R80_FSW fxam
2520
2521
2522
2523;;
2524; FPU instruction loading a 80-bit floating point constant.
2525;
2526; @param 1 The instruction
2527;
2528; @param A0 FPU context (fxsave).
2529; @param A1 Pointer to a IEMFPURESULT for the output.
2530;
2531%macro IEMIMPL_FPU_R80_CONST 1
2532BEGINPROC_FASTCALL iemAImpl_ %+ %1, 8
2533 PROLOGUE_2_ARGS
2534 sub xSP, 20h
2535
2536 fninit
2537 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2538 %1
2539
2540 fnstsw word [A1 + IEMFPURESULT.FSW]
2541 fnclex
2542 fstp tword [A1 + IEMFPURESULT.r80Result]
2543
2544 fninit
2545 add xSP, 20h
2546 EPILOGUE_2_ARGS
2547ENDPROC iemAImpl_ %+ %1 %+
2548%endmacro
2549
2550IEMIMPL_FPU_R80_CONST fld1
2551IEMIMPL_FPU_R80_CONST fldl2t
2552IEMIMPL_FPU_R80_CONST fldl2e
2553IEMIMPL_FPU_R80_CONST fldpi
2554IEMIMPL_FPU_R80_CONST fldlg2
2555IEMIMPL_FPU_R80_CONST fldln2
2556IEMIMPL_FPU_R80_CONST fldz
2557
2558
2559;;
2560; FPU instruction working on one 80-bit floating point value, outputing two.
2561;
2562; @param 1 The instruction
2563;
2564; @param A0 FPU context (fxsave).
2565; @param A1 Pointer to a IEMFPURESULTTWO for the output.
2566; @param A2 Pointer to the 80-bit value.
2567;
2568%macro IEMIMPL_FPU_R80_R80 1
2569BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_r80, 12
2570 PROLOGUE_3_ARGS
2571 sub xSP, 20h
2572
2573 fninit
2574 fld tword [A2]
2575 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
2576 %1
2577
2578 fnstsw word [A1 + IEMFPURESULTTWO.FSW]
2579 fnclex
2580 fstp tword [A1 + IEMFPURESULTTWO.r80Result2]
2581 fnclex
2582 fstp tword [A1 + IEMFPURESULTTWO.r80Result1]
2583
2584 fninit
2585 add xSP, 20h
2586 EPILOGUE_3_ARGS
2587ENDPROC iemAImpl_ %+ %1 %+ _r80_r80
2588%endmacro
2589
2590IEMIMPL_FPU_R80_R80 fptan
2591IEMIMPL_FPU_R80_R80 fxtract
2592IEMIMPL_FPU_R80_R80 fsincos
2593
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