VirtualBox

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

Last change on this file since 40244 was 40244, checked in by vboxsync, 13 years ago

IEM: Implemented FPU instructions 0xd9 0xf3 thru 0xd9 0xff, completing the 0xd9 prefixed instructions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 51.0 KB
Line 
1; $Id: IEMAllAImpl.asm 40244 2012-02-24 00:48:47Z 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_Dollar) 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 1
89 ret
90 %endmacro
91
92 %macro PROLOGUE_2_ARGS 0
93 %endmacro
94 %macro EPILOGUE_2_ARGS 1
95 ret
96 %endmacro
97
98 %macro PROLOGUE_3_ARGS 0
99 %endmacro
100 %macro EPILOGUE_3_ARGS 1
101 ret
102 %endmacro
103
104 %macro PROLOGUE_4_ARGS 0
105 %endmacro
106 %macro EPILOGUE_4_ARGS 1
107 ret
108 %endmacro
109
110 %ifdef ASM_CALL64_GCC
111 %define A0 rdi
112 %define A0_32 edi
113 %define A0_16 di
114 %define A0_8 dil
115
116 %define A1 rsi
117 %define A1_32 esi
118 %define A1_16 si
119 %define A1_8 sil
120
121 %define A2 rdx
122 %define A2_32 edx
123 %define A2_16 dx
124 %define A2_8 dl
125
126 %define A3 rcx
127 %define A3_32 ecx
128 %define A3_16 cx
129 %endif
130
131 %ifdef ASM_CALL64_MSC
132 %define A0 rcx
133 %define A0_32 ecx
134 %define A0_16 cx
135 %define A0_8 cl
136
137 %define A1 rdx
138 %define A1_32 edx
139 %define A1_16 dx
140 %define A1_8 dl
141
142 %define A2 r8
143 %define A2_32 r8d
144 %define A2_16 r8w
145 %define A2_8 r8b
146
147 %define A3 r9
148 %define A3_32 r9d
149 %define A3_16 r9w
150 %endif
151
152 %define T0 rax
153 %define T0_32 eax
154 %define T0_16 ax
155 %define T0_8 al
156
157 %define T1 r11
158 %define T1_32 r11d
159 %define T1_16 r11w
160 %define T1_8 r11b
161
162%else
163 ; x86
164 %macro PROLOGUE_1_ARGS 0
165 push edi
166 %endmacro
167 %macro EPILOGUE_1_ARGS 1
168 pop edi
169 ret %1
170 %endmacro
171
172 %macro PROLOGUE_2_ARGS 0
173 push edi
174 %endmacro
175 %macro EPILOGUE_2_ARGS 1
176 pop edi
177 ret %1
178 %endmacro
179
180 %macro PROLOGUE_3_ARGS 0
181 push ebx
182 mov ebx, [esp + 4 + 4]
183 push edi
184 %endmacro
185 %macro EPILOGUE_3_ARGS 1
186 pop edi
187 pop ebx
188 ret %1
189 %endmacro
190
191 %macro PROLOGUE_4_ARGS 0
192 push ebx
193 push edi
194 push esi
195 mov ebx, [esp + 12 + 4 + 0]
196 mov esi, [esp + 12 + 4 + 4]
197 %endmacro
198 %macro EPILOGUE_4_ARGS 1
199 pop esi
200 pop edi
201 pop ebx
202 ret %1
203 %endmacro
204
205 %define A0 ecx
206 %define A0_32 ecx
207 %define A0_16 cx
208 %define A0_8 cl
209
210 %define A1 edx
211 %define A1_32 edx
212 %define A1_16 dx
213 %define A1_8 dl
214
215 %define A2 ebx
216 %define A2_32 ebx
217 %define A2_16 bx
218 %define A2_8 bl
219
220 %define A3 esi
221 %define A3_32 esi
222 %define A3_16 si
223
224 %define T0 eax
225 %define T0_32 eax
226 %define T0_16 ax
227 %define T0_8 al
228
229 %define T1 edi
230 %define T1_32 edi
231 %define T1_16 di
232%endif
233
234
235;;
236; Load the relevant flags from [%1] if there are undefined flags (%3).
237;
238; @remarks Clobbers T0, stack. Changes EFLAGS.
239; @param A2 The register pointing to the flags.
240; @param 1 The parameter (A0..A3) pointing to the eflags.
241; @param 2 The set of modified flags.
242; @param 3 The set of undefined flags.
243;
244%macro IEM_MAYBE_LOAD_FLAGS 3
245 ;%if (%3) != 0
246 pushf ; store current flags
247 mov T0_32, [%1] ; load the guest flags
248 and dword [xSP], ~(%2 | %3) ; mask out the modified and undefined flags
249 and T0_32, (%2 | %3) ; select the modified and undefined flags.
250 or [xSP], T0 ; merge guest flags with host flags.
251 popf ; load the mixed flags.
252 ;%endif
253%endmacro
254
255;;
256; Update the flag.
257;
258; @remarks Clobbers T0, T1, stack.
259; @param 1 The register pointing to the EFLAGS.
260; @param 2 The mask of modified flags to save.
261; @param 3 The mask of undefined flags to (maybe) save.
262;
263%macro IEM_SAVE_FLAGS 3
264 %if (%2 | %3) != 0
265 pushf
266 pop T1
267 mov T0_32, [%1] ; flags
268 and T0_32, ~(%2 | %3) ; clear the modified & undefined flags.
269 and T1_32, (%2 | %3) ; select the modified and undefined flags.
270 or T0_32, T1_32 ; combine the flags.
271 mov [%1], T0_32 ; save the flags.
272 %endif
273%endmacro
274
275
276;;
277; Macro for implementing a binary operator.
278;
279; This will generate code for the 8, 16, 32 and 64 bit accesses with locked
280; variants, except on 32-bit system where the 64-bit accesses requires hand
281; coding.
282;
283; All the functions takes a pointer to the destination memory operand in A0,
284; the source register operand in A1 and a pointer to eflags in A2.
285;
286; @param 1 The instruction mnemonic.
287; @param 2 Non-zero if there should be a locked version.
288; @param 3 The modified flags.
289; @param 4 The undefined flags.
290;
291%macro IEMIMPL_BIN_OP 4
292BEGINCODE
293BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
294 PROLOGUE_3_ARGS
295 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
296 %1 byte [A0], A1_8
297 IEM_SAVE_FLAGS A2, %3, %4
298 EPILOGUE_3_ARGS 4
299ENDPROC iemAImpl_ %+ %1 %+ _u8
300
301BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
302 PROLOGUE_3_ARGS
303 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
304 %1 word [A0], A1_16
305 IEM_SAVE_FLAGS A2, %3, %4
306 EPILOGUE_3_ARGS 4
307ENDPROC iemAImpl_ %+ %1 %+ _u16
308
309BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
310 PROLOGUE_3_ARGS
311 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
312 %1 dword [A0], A1_32
313 IEM_SAVE_FLAGS A2, %3, %4
314 EPILOGUE_3_ARGS 4
315ENDPROC iemAImpl_ %+ %1 %+ _u32
316
317 %ifdef RT_ARCH_AMD64
318BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
319 PROLOGUE_3_ARGS
320 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
321 %1 qword [A0], A1
322 IEM_SAVE_FLAGS A2, %3, %4
323 EPILOGUE_3_ARGS 8
324ENDPROC iemAImpl_ %+ %1 %+ _u64
325 %else ; stub it for now - later, replace with hand coded stuff.
326BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
327 int3
328 ret
329ENDPROC iemAImpl_ %+ %1 %+ _u64
330 %endif ; !RT_ARCH_AMD64
331
332 %if %2 != 0 ; locked versions requested?
333
334BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8_locked, 12
335 PROLOGUE_3_ARGS
336 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
337 lock %1 byte [A0], A1_8
338 IEM_SAVE_FLAGS A2, %3, %4
339 EPILOGUE_3_ARGS 4
340ENDPROC iemAImpl_ %+ %1 %+ _u8_locked
341
342BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 12
343 PROLOGUE_3_ARGS
344 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
345 lock %1 word [A0], A1_16
346 IEM_SAVE_FLAGS A2, %3, %4
347 EPILOGUE_3_ARGS 4
348ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
349
350BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 12
351 PROLOGUE_3_ARGS
352 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
353 lock %1 dword [A0], A1_32
354 IEM_SAVE_FLAGS A2, %3, %4
355 EPILOGUE_3_ARGS 4
356ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
357
358 %ifdef RT_ARCH_AMD64
359BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
360 PROLOGUE_3_ARGS
361 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
362 lock %1 qword [A0], A1
363 IEM_SAVE_FLAGS A2, %3, %4
364 EPILOGUE_3_ARGS 8
365ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
366 %else ; stub it for now - later, replace with hand coded stuff.
367BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
368 int3
369 ret 8
370ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
371 %endif ; !RT_ARCH_AMD64
372 %endif ; locked
373%endmacro
374
375; instr,lock,modified-flags.
376IEMIMPL_BIN_OP add, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
377IEMIMPL_BIN_OP adc, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
378IEMIMPL_BIN_OP sub, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
379IEMIMPL_BIN_OP sbb, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
380IEMIMPL_BIN_OP or, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
381IEMIMPL_BIN_OP xor, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
382IEMIMPL_BIN_OP and, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
383IEMIMPL_BIN_OP cmp, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
384IEMIMPL_BIN_OP test, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
385
386
387;;
388; Macro for implementing a bit operator.
389;
390; This will generate code for the 16, 32 and 64 bit accesses with locked
391; variants, except on 32-bit system where the 64-bit accesses requires hand
392; coding.
393;
394; All the functions takes a pointer to the destination memory operand in A0,
395; the source register operand in A1 and a pointer to eflags in A2.
396;
397; @param 1 The instruction mnemonic.
398; @param 2 Non-zero if there should be a locked version.
399; @param 3 The modified flags.
400; @param 4 The undefined flags.
401;
402%macro IEMIMPL_BIT_OP 4
403BEGINCODE
404BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
405 PROLOGUE_3_ARGS
406 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
407 %1 word [A0], A1_16
408 IEM_SAVE_FLAGS A2, %3, %4
409 EPILOGUE_3_ARGS 4
410ENDPROC iemAImpl_ %+ %1 %+ _u16
411
412BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
413 PROLOGUE_3_ARGS
414 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
415 %1 dword [A0], A1_32
416 IEM_SAVE_FLAGS A2, %3, %4
417 EPILOGUE_3_ARGS 4
418ENDPROC iemAImpl_ %+ %1 %+ _u32
419
420 %ifdef RT_ARCH_AMD64
421BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
422 PROLOGUE_3_ARGS
423 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
424 %1 qword [A0], A1
425 IEM_SAVE_FLAGS A2, %3, %4
426 EPILOGUE_3_ARGS 8
427ENDPROC iemAImpl_ %+ %1 %+ _u64
428 %else ; stub it for now - later, replace with hand coded stuff.
429BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
430 int3
431 ret 8
432ENDPROC iemAImpl_ %+ %1 %+ _u64
433 %endif ; !RT_ARCH_AMD64
434
435 %if %2 != 0 ; locked versions requested?
436
437BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 12
438 PROLOGUE_3_ARGS
439 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
440 lock %1 word [A0], A1_16
441 IEM_SAVE_FLAGS A2, %3, %4
442 EPILOGUE_3_ARGS 4
443ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
444
445BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 12
446 PROLOGUE_3_ARGS
447 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
448 lock %1 dword [A0], A1_32
449 IEM_SAVE_FLAGS A2, %3, %4
450 EPILOGUE_3_ARGS 4
451ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
452
453 %ifdef RT_ARCH_AMD64
454BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
455 PROLOGUE_3_ARGS
456 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
457 lock %1 qword [A0], A1
458 IEM_SAVE_FLAGS A2, %3, %4
459 EPILOGUE_3_ARGS 8
460ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
461 %else ; stub it for now - later, replace with hand coded stuff.
462BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
463 int3
464 ret 8
465ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
466 %endif ; !RT_ARCH_AMD64
467 %endif ; locked
468%endmacro
469IEMIMPL_BIT_OP bt, 0, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
470IEMIMPL_BIT_OP btc, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
471IEMIMPL_BIT_OP bts, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
472IEMIMPL_BIT_OP btr, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
473
474;;
475; Macro for implementing a bit search operator.
476;
477; This will generate code for the 16, 32 and 64 bit accesses, except on 32-bit
478; system where the 64-bit accesses requires hand coding.
479;
480; All the functions takes a pointer to the destination memory operand in A0,
481; the source register operand in A1 and a pointer to eflags in A2.
482;
483; @param 1 The instruction mnemonic.
484; @param 2 The modified flags.
485; @param 3 The undefined flags.
486;
487%macro IEMIMPL_BIT_OP 3
488BEGINCODE
489BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
490 PROLOGUE_3_ARGS
491 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
492 %1 T0_16, A1_16
493 mov [A0], T0_16
494 IEM_SAVE_FLAGS A2, %2, %3
495 EPILOGUE_3_ARGS 4
496ENDPROC iemAImpl_ %+ %1 %+ _u16
497
498BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
499 PROLOGUE_3_ARGS
500 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
501 %1 T0_32, A1_32
502 mov [A0], T0_32
503 IEM_SAVE_FLAGS A2, %2, %3
504 EPILOGUE_3_ARGS 4
505ENDPROC iemAImpl_ %+ %1 %+ _u32
506
507 %ifdef RT_ARCH_AMD64
508BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
509 PROLOGUE_3_ARGS
510 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
511 %1 T0, A1
512 mov [A0], T0
513 IEM_SAVE_FLAGS A2, %2, %3
514 EPILOGUE_3_ARGS 8
515ENDPROC iemAImpl_ %+ %1 %+ _u64
516 %else ; stub it for now - later, replace with hand coded stuff.
517BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
518 int3
519 ret 8
520ENDPROC iemAImpl_ %+ %1 %+ _u64
521 %endif ; !RT_ARCH_AMD64
522%endmacro
523IEMIMPL_BIT_OP bsf, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
524IEMIMPL_BIT_OP bsr, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
525
526
527;
528; IMUL is also a similar but yet different case (no lock, no mem dst).
529; The rDX:rAX variant of imul is handled together with mul further down.
530;
531BEGINCODE
532BEGINPROC_FASTCALL iemAImpl_imul_two_u16, 12
533 PROLOGUE_3_ARGS
534 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
535 imul A1_16, word [A0]
536 mov [A0], A1_16
537 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
538 EPILOGUE_3_ARGS 4
539ENDPROC iemAImpl_imul_two_u16
540
541BEGINPROC_FASTCALL iemAImpl_imul_two_u32, 12
542 PROLOGUE_3_ARGS
543 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
544 imul A1_32, dword [A0]
545 mov [A0], A1_32
546 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
547 EPILOGUE_3_ARGS 4
548ENDPROC iemAImpl_imul_two_u32
549
550BEGINPROC_FASTCALL iemAImpl_imul_two_u64, 16
551 PROLOGUE_3_ARGS
552%ifdef RT_ARCH_AMD64
553 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
554 imul A1, qword [A0]
555 mov [A0], A1
556 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
557%else
558 int3 ;; @todo implement me
559%endif
560 EPILOGUE_3_ARGS 8
561ENDPROC iemAImpl_imul_two_u64
562
563
564;
565; XCHG for memory operands. This implies locking. No flag changes.
566;
567; Each function takes two arguments, first the pointer to the memory,
568; then the pointer to the register. They all return void.
569;
570BEGINCODE
571BEGINPROC_FASTCALL iemAImpl_xchg_u8, 8
572 PROLOGUE_2_ARGS
573 mov T0_8, [A1]
574 xchg [A0], T0_8
575 mov [A1], T0_8
576 EPILOGUE_2_ARGS 0
577ENDPROC iemAImpl_xchg_u8
578
579BEGINPROC_FASTCALL iemAImpl_xchg_u16, 8
580 PROLOGUE_2_ARGS
581 mov T0_16, [A1]
582 xchg [A0], T0_16
583 mov [A1], T0_16
584 EPILOGUE_2_ARGS 0
585ENDPROC iemAImpl_xchg_u16
586
587BEGINPROC_FASTCALL iemAImpl_xchg_u32, 8
588 PROLOGUE_2_ARGS
589 mov T0_32, [A1]
590 xchg [A0], T0_32
591 mov [A1], T0_32
592 EPILOGUE_2_ARGS 0
593ENDPROC iemAImpl_xchg_u32
594
595BEGINPROC_FASTCALL iemAImpl_xchg_u64, 8
596%ifdef RT_ARCH_AMD64
597 PROLOGUE_2_ARGS
598 mov T0, [A1]
599 xchg [A0], T0
600 mov [A1], T0
601 EPILOGUE_2_ARGS 0
602%else
603 int3
604 ret 0
605%endif
606ENDPROC iemAImpl_xchg_u64
607
608
609;
610; XADD for memory operands.
611;
612; Each function takes three arguments, first the pointer to the
613; memory/register, then the pointer to the register, and finally a pointer to
614; eflags. They all return void.
615;
616BEGINCODE
617BEGINPROC_FASTCALL iemAImpl_xadd_u8, 12
618 PROLOGUE_3_ARGS
619 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
620 mov T0_8, [A1]
621 xadd [A0], T0_8
622 mov [A1], T0_8
623 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
624 EPILOGUE_3_ARGS 4
625ENDPROC iemAImpl_xadd_u8
626
627BEGINPROC_FASTCALL iemAImpl_xadd_u16, 12
628 PROLOGUE_3_ARGS
629 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
630 mov T0_16, [A1]
631 xadd [A0], T0_16
632 mov [A1], T0_16
633 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
634 EPILOGUE_3_ARGS 4
635ENDPROC iemAImpl_xadd_u16
636
637BEGINPROC_FASTCALL iemAImpl_xadd_u32, 12
638 PROLOGUE_3_ARGS
639 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
640 mov T0_32, [A1]
641 xadd [A0], T0_32
642 mov [A1], T0_32
643 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
644 EPILOGUE_3_ARGS 4
645ENDPROC iemAImpl_xadd_u32
646
647BEGINPROC_FASTCALL iemAImpl_xadd_u64, 12
648%ifdef RT_ARCH_AMD64
649 PROLOGUE_3_ARGS
650 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
651 mov T0, [A1]
652 xadd [A0], T0
653 mov [A1], T0
654 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
655 EPILOGUE_3_ARGS 4
656%else
657 int3
658 ret 4
659%endif
660ENDPROC iemAImpl_xadd_u64
661
662BEGINPROC_FASTCALL iemAImpl_xadd_u8_locked, 12
663 PROLOGUE_3_ARGS
664 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
665 mov T0_8, [A1]
666 lock xadd [A0], T0_8
667 mov [A1], T0_8
668 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
669 EPILOGUE_3_ARGS 4
670ENDPROC iemAImpl_xadd_u8_locked
671
672BEGINPROC_FASTCALL iemAImpl_xadd_u16_locked, 12
673 PROLOGUE_3_ARGS
674 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
675 mov T0_16, [A1]
676 lock xadd [A0], T0_16
677 mov [A1], T0_16
678 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
679 EPILOGUE_3_ARGS 4
680ENDPROC iemAImpl_xadd_u16_locked
681
682BEGINPROC_FASTCALL iemAImpl_xadd_u32_locked, 12
683 PROLOGUE_3_ARGS
684 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
685 mov T0_32, [A1]
686 lock xadd [A0], T0_32
687 mov [A1], T0_32
688 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
689 EPILOGUE_3_ARGS 4
690ENDPROC iemAImpl_xadd_u32_locked
691
692BEGINPROC_FASTCALL iemAImpl_xadd_u64_locked, 12
693%ifdef RT_ARCH_AMD64
694 PROLOGUE_3_ARGS
695 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
696 mov T0, [A1]
697 lock xadd [A0], T0
698 mov [A1], T0
699 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
700 EPILOGUE_3_ARGS 4
701%else
702 int3
703 ret 4
704%endif
705ENDPROC iemAImpl_xadd_u64_locked
706
707
708;;
709; Macro for implementing a unary operator.
710;
711; This will generate code for the 8, 16, 32 and 64 bit accesses with locked
712; variants, except on 32-bit system where the 64-bit accesses requires hand
713; coding.
714;
715; All the functions takes a pointer to the destination memory operand in A0,
716; the source register operand in A1 and a pointer to eflags in A2.
717;
718; @param 1 The instruction mnemonic.
719; @param 2 The modified flags.
720; @param 3 The undefined flags.
721;
722%macro IEMIMPL_UNARY_OP 3
723BEGINCODE
724BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 8
725 PROLOGUE_2_ARGS
726 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
727 %1 byte [A0]
728 IEM_SAVE_FLAGS A1, %2, %3
729 EPILOGUE_2_ARGS 0
730ENDPROC iemAImpl_ %+ %1 %+ _u8
731
732BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8_locked, 8
733 PROLOGUE_2_ARGS
734 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
735 lock %1 byte [A0]
736 IEM_SAVE_FLAGS A1, %2, %3
737 EPILOGUE_2_ARGS 0
738ENDPROC iemAImpl_ %+ %1 %+ _u8_locked
739
740BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 8
741 PROLOGUE_2_ARGS
742 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
743 %1 word [A0]
744 IEM_SAVE_FLAGS A1, %2, %3
745 EPILOGUE_2_ARGS 0
746ENDPROC iemAImpl_ %+ %1 %+ _u16
747
748BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 8
749 PROLOGUE_2_ARGS
750 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
751 lock %1 word [A0]
752 IEM_SAVE_FLAGS A1, %2, %3
753 EPILOGUE_2_ARGS 0
754ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
755
756BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 8
757 PROLOGUE_2_ARGS
758 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
759 %1 dword [A0]
760 IEM_SAVE_FLAGS A1, %2, %3
761 EPILOGUE_2_ARGS 0
762ENDPROC iemAImpl_ %+ %1 %+ _u32
763
764BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 8
765 PROLOGUE_2_ARGS
766 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
767 lock %1 dword [A0]
768 IEM_SAVE_FLAGS A1, %2, %3
769 EPILOGUE_2_ARGS 0
770ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
771
772 %ifdef RT_ARCH_AMD64
773BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 8
774 PROLOGUE_2_ARGS
775 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
776 %1 qword [A0]
777 IEM_SAVE_FLAGS A1, %2, %3
778 EPILOGUE_2_ARGS 0
779ENDPROC iemAImpl_ %+ %1 %+ _u64
780
781BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 8
782 PROLOGUE_2_ARGS
783 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
784 lock %1 qword [A0]
785 IEM_SAVE_FLAGS A1, %2, %3
786 EPILOGUE_2_ARGS 0
787ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
788 %else
789 ; stub them for now.
790BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 8
791 int3
792 ret 0
793ENDPROC iemAImpl_ %+ %1 %+ _u64
794BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 8
795 int3
796 ret 0
797ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
798 %endif
799
800%endmacro
801
802IEMIMPL_UNARY_OP inc, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), 0
803IEMIMPL_UNARY_OP dec, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), 0
804IEMIMPL_UNARY_OP neg, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
805IEMIMPL_UNARY_OP not, 0, 0
806
807
808
809;;
810; Macro for implementing a shift operation.
811;
812; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
813; 32-bit system where the 64-bit accesses requires hand coding.
814;
815; All the functions takes a pointer to the destination memory operand in A0,
816; the shift count in A1 and a pointer to eflags in A2.
817;
818; @param 1 The instruction mnemonic.
819; @param 2 The modified flags.
820; @param 3 The undefined flags.
821;
822; Makes ASSUMPTIONS about A0, A1 and A2 assignments.
823;
824%macro IEMIMPL_SHIFT_OP 3
825BEGINCODE
826BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
827 PROLOGUE_3_ARGS
828 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
829 %ifdef ASM_CALL64_GCC
830 mov cl, A1_8
831 %1 byte [A0], cl
832 %else
833 xchg A1, A0
834 %1 byte [A1], cl
835 %endif
836 IEM_SAVE_FLAGS A2, %2, %3
837 EPILOGUE_3_ARGS 4
838ENDPROC iemAImpl_ %+ %1 %+ _u8
839
840BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
841 PROLOGUE_3_ARGS
842 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
843 %ifdef ASM_CALL64_GCC
844 mov cl, A1_8
845 %1 word [A0], cl
846 %else
847 xchg A1, A0
848 %1 word [A1], cl
849 %endif
850 IEM_SAVE_FLAGS A2, %2, %3
851 EPILOGUE_3_ARGS 4
852ENDPROC iemAImpl_ %+ %1 %+ _u16
853
854BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
855 PROLOGUE_3_ARGS
856 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
857 %ifdef ASM_CALL64_GCC
858 mov cl, A1_8
859 %1 dword [A0], cl
860 %else
861 xchg A1, A0
862 %1 dword [A1], cl
863 %endif
864 IEM_SAVE_FLAGS A2, %2, %3
865 EPILOGUE_3_ARGS 4
866ENDPROC iemAImpl_ %+ %1 %+ _u32
867
868 %ifdef RT_ARCH_AMD64
869BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 12
870 PROLOGUE_3_ARGS
871 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
872 %ifdef ASM_CALL64_GCC
873 mov cl, A1_8
874 %1 qword [A0], cl
875 %else
876 xchg A1, A0
877 %1 qword [A1], cl
878 %endif
879 IEM_SAVE_FLAGS A2, %2, %3
880 EPILOGUE_3_ARGS 4
881ENDPROC iemAImpl_ %+ %1 %+ _u64
882 %else ; stub it for now - later, replace with hand coded stuff.
883BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 12
884 int3
885 ret 4
886ENDPROC iemAImpl_ %+ %1 %+ _u64
887 %endif ; !RT_ARCH_AMD64
888
889%endmacro
890
891IEMIMPL_SHIFT_OP rol, (X86_EFL_OF | X86_EFL_CF), 0
892IEMIMPL_SHIFT_OP ror, (X86_EFL_OF | X86_EFL_CF), 0
893IEMIMPL_SHIFT_OP rcl, (X86_EFL_OF | X86_EFL_CF), 0
894IEMIMPL_SHIFT_OP rcr, (X86_EFL_OF | X86_EFL_CF), 0
895IEMIMPL_SHIFT_OP shl, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
896IEMIMPL_SHIFT_OP shr, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
897IEMIMPL_SHIFT_OP sar, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
898
899
900;;
901; Macro for implementing a double precision shift operation.
902;
903; This will generate code for the 16, 32 and 64 bit accesses, except on
904; 32-bit system where the 64-bit accesses requires hand coding.
905;
906; The functions takes the destination operand (r/m) in A0, the source (reg) in
907; A1, the shift count in A2 and a pointer to the eflags variable/register in A3.
908;
909; @param 1 The instruction mnemonic.
910; @param 2 The modified flags.
911; @param 3 The undefined flags.
912;
913; Makes ASSUMPTIONS about A0, A1, A2 and A3 assignments.
914;
915%macro IEMIMPL_SHIFT_DBL_OP 3
916BEGINCODE
917BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
918 PROLOGUE_4_ARGS
919 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
920 %ifdef ASM_CALL64_GCC
921 xchg A3, A2
922 %1 [A0], A1_16, cl
923 xchg A3, A2
924 %else
925 xchg A0, A2
926 %1 [A2], A1_16, cl
927 %endif
928 IEM_SAVE_FLAGS A3, %2, %3
929 EPILOGUE_4_ARGS 8
930ENDPROC iemAImpl_ %+ %1 %+ _u16
931
932BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
933 PROLOGUE_4_ARGS
934 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
935 %ifdef ASM_CALL64_GCC
936 xchg A3, A2
937 %1 [A0], A1_32, cl
938 xchg A3, A2
939 %else
940 xchg A0, A2
941 %1 [A2], A1_32, cl
942 %endif
943 IEM_SAVE_FLAGS A3, %2, %3
944 EPILOGUE_4_ARGS 8
945ENDPROC iemAImpl_ %+ %1 %+ _u32
946
947 %ifdef RT_ARCH_AMD64
948BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
949 PROLOGUE_4_ARGS
950 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
951 %ifdef ASM_CALL64_GCC
952 xchg A3, A2
953 %1 [A0], A1, cl
954 xchg A3, A2
955 %else
956 xchg A0, A2
957 %1 [A2], A1, cl
958 %endif
959 IEM_SAVE_FLAGS A3, %2, %3
960 EPILOGUE_4_ARGS 12
961ENDPROC iemAImpl_ %+ %1 %+ _u64
962 %else ; stub it for now - later, replace with hand coded stuff.
963BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
964 int3
965 ret 12
966ENDPROC iemAImpl_ %+ %1 %+ _u64
967 %endif ; !RT_ARCH_AMD64
968
969%endmacro
970
971IEMIMPL_SHIFT_DBL_OP shld, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
972IEMIMPL_SHIFT_DBL_OP shrd, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
973
974
975;;
976; Macro for implementing a multiplication operations.
977;
978; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
979; 32-bit system where the 64-bit accesses requires hand coding.
980;
981; The 8-bit function only operates on AX, so it takes no DX pointer. The other
982; functions takes a pointer to rAX in A0, rDX in A1, the operand in A2 and a
983; pointer to eflags in A3.
984;
985; The functions all return 0 so the caller can be used for div/idiv as well as
986; for the mul/imul implementation.
987;
988; @param 1 The instruction mnemonic.
989; @param 2 The modified flags.
990; @param 3 The undefined flags.
991;
992; Makes ASSUMPTIONS about A0, A1, A2, A3, T0 and T1 assignments.
993;
994%macro IEMIMPL_MUL_OP 3
995BEGINCODE
996BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
997 PROLOGUE_3_ARGS
998 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
999 mov al, [A0]
1000 %1 A1_8
1001 mov [A0], ax
1002 IEM_SAVE_FLAGS A2, %2, %3
1003 xor eax, eax
1004 EPILOGUE_3_ARGS 4
1005ENDPROC iemAImpl_ %+ %1 %+ _u8
1006
1007BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
1008 PROLOGUE_4_ARGS
1009 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1010 mov ax, [A0]
1011 %ifdef ASM_CALL64_GCC
1012 %1 A2_16
1013 mov [A0], ax
1014 mov [A1], dx
1015 %else
1016 mov T1, A1
1017 %1 A2_16
1018 mov [A0], ax
1019 mov [T1], dx
1020 %endif
1021 IEM_SAVE_FLAGS A3, %2, %3
1022 xor eax, eax
1023 EPILOGUE_4_ARGS 8
1024ENDPROC iemAImpl_ %+ %1 %+ _u16
1025
1026BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
1027 PROLOGUE_4_ARGS
1028 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1029 mov eax, [A0]
1030 %ifdef ASM_CALL64_GCC
1031 %1 A2_32
1032 mov [A0], eax
1033 mov [A1], edx
1034 %else
1035 mov T1, A1
1036 %1 A2_32
1037 mov [A0], eax
1038 mov [T1], edx
1039 %endif
1040 IEM_SAVE_FLAGS A3, %2, %3
1041 xor eax, eax
1042 EPILOGUE_4_ARGS 8
1043ENDPROC iemAImpl_ %+ %1 %+ _u32
1044
1045 %ifdef RT_ARCH_AMD64
1046BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1047 PROLOGUE_4_ARGS
1048 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1049 mov rax, [A0]
1050 %ifdef ASM_CALL64_GCC
1051 %1 A2
1052 mov [A0], rax
1053 mov [A1], rdx
1054 %else
1055 mov T1, A1
1056 %1 A2
1057 mov [A0], rax
1058 mov [T1], rdx
1059 %endif
1060 IEM_SAVE_FLAGS A3, %2, %3
1061 xor eax, eax
1062 EPILOGUE_4_ARGS 12
1063ENDPROC iemAImpl_ %+ %1 %+ _u64
1064 %else ; stub it for now - later, replace with hand coded stuff.
1065BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1066 int3
1067 ret 12
1068ENDPROC iemAImpl_ %+ %1 %+ _u64
1069 %endif ; !RT_ARCH_AMD64
1070
1071%endmacro
1072
1073IEMIMPL_MUL_OP mul, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
1074IEMIMPL_MUL_OP imul, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
1075
1076
1077;;
1078; Macro for implementing a division operations.
1079;
1080; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
1081; 32-bit system where the 64-bit accesses requires hand coding.
1082;
1083; The 8-bit function only operates on AX, so it takes no DX pointer. The other
1084; functions takes a pointer to rAX in A0, rDX in A1, the operand in A2 and a
1085; pointer to eflags in A3.
1086;
1087; The functions all return 0 on success and -1 if a divide error should be
1088; raised by the caller.
1089;
1090; @param 1 The instruction mnemonic.
1091; @param 2 The modified flags.
1092; @param 3 The undefined flags.
1093;
1094; Makes ASSUMPTIONS about A0, A1, A2, A3, T0 and T1 assignments.
1095;
1096%macro IEMIMPL_DIV_OP 3
1097BEGINCODE
1098BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
1099 PROLOGUE_3_ARGS
1100
1101 test A1_8, A1_8
1102 jz .div_zero
1103 ;; @todo test for overflow
1104
1105 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
1106 mov ax, [A0]
1107 %1 A1_8
1108 mov [A0], ax
1109 IEM_SAVE_FLAGS A2, %2, %3
1110 xor eax, eax
1111
1112.return:
1113 EPILOGUE_3_ARGS 4
1114
1115.div_zero:
1116 mov eax, -1
1117 jmp .return
1118ENDPROC iemAImpl_ %+ %1 %+ _u8
1119
1120BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
1121 PROLOGUE_4_ARGS
1122
1123 test A1_16, A1_16
1124 jz .div_zero
1125 ;; @todo test for overflow
1126
1127 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1128 %ifdef ASM_CALL64_GCC
1129 mov T1, A2
1130 mov ax, [A0]
1131 mov dx, [A1]
1132 %1 T1_16
1133 mov [A0], ax
1134 mov [A1], dx
1135 %else
1136 mov T1, A1
1137 mov ax, [A0]
1138 mov dx, [T1]
1139 %1 A2_16
1140 mov [A0], ax
1141 mov [T1], dx
1142 %endif
1143 IEM_SAVE_FLAGS A3, %2, %3
1144 xor eax, eax
1145
1146.return:
1147 EPILOGUE_4_ARGS 8
1148
1149.div_zero:
1150 mov eax, -1
1151 jmp .return
1152ENDPROC iemAImpl_ %+ %1 %+ _u16
1153
1154BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
1155 PROLOGUE_4_ARGS
1156
1157 test A1_32, A1_32
1158 jz .div_zero
1159 ;; @todo test for overflow
1160
1161 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1162 mov eax, [A0]
1163 %ifdef ASM_CALL64_GCC
1164 mov T1, A2
1165 mov eax, [A0]
1166 mov edx, [A1]
1167 %1 T1_32
1168 mov [A0], eax
1169 mov [A1], edx
1170 %else
1171 mov T1, A1
1172 mov eax, [A0]
1173 mov edx, [T1]
1174 %1 A2_32
1175 mov [A0], eax
1176 mov [T1], edx
1177 %endif
1178 IEM_SAVE_FLAGS A3, %2, %3
1179 xor eax, eax
1180
1181.return:
1182 EPILOGUE_4_ARGS 8
1183
1184.div_zero:
1185 mov eax, -1
1186 jmp .return
1187ENDPROC iemAImpl_ %+ %1 %+ _u32
1188
1189 %ifdef RT_ARCH_AMD64
1190BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1191 PROLOGUE_4_ARGS
1192
1193 test A1, A1
1194 jz .div_zero
1195 ;; @todo test for overflow
1196
1197 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1198 mov rax, [A0]
1199 %ifdef ASM_CALL64_GCC
1200 mov T1, A2
1201 mov rax, [A0]
1202 mov rdx, [A1]
1203 %1 T1
1204 mov [A0], rax
1205 mov [A1], rdx
1206 %else
1207 mov T1, A1
1208 mov rax, [A0]
1209 mov rdx, [T1]
1210 %1 A2
1211 mov [A0], rax
1212 mov [T1], rdx
1213 %endif
1214 IEM_SAVE_FLAGS A3, %2, %3
1215 xor eax, eax
1216
1217.return:
1218 EPILOGUE_4_ARGS 12
1219
1220.div_zero:
1221 mov eax, -1
1222 jmp .return
1223ENDPROC iemAImpl_ %+ %1 %+ _u64
1224 %else ; stub it for now - later, replace with hand coded stuff.
1225BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
1226 int3
1227 ret
1228ENDPROC iemAImpl_ %+ %1 %+ _u64
1229 %endif ; !RT_ARCH_AMD64
1230
1231%endmacro
1232
1233IEMIMPL_DIV_OP div, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
1234IEMIMPL_DIV_OP idiv, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
1235
1236
1237;
1238; BSWAP. No flag changes.
1239;
1240; Each function takes one argument, pointer to the value to bswap
1241; (input/output). They all return void.
1242;
1243BEGINPROC_FASTCALL iemAImpl_bswap_u16, 4
1244 PROLOGUE_1_ARGS
1245 mov T0_32, [A0] ; just in case any of the upper bits are used.
1246 db 66h
1247 bswap T0_32
1248 mov [A0], T0_32
1249 EPILOGUE_1_ARGS 0
1250ENDPROC iemAImpl_bswap_u16
1251
1252BEGINPROC_FASTCALL iemAImpl_bswap_u32, 4
1253 PROLOGUE_1_ARGS
1254 mov T0_32, [A0]
1255 bswap T0_32
1256 mov [A0], T0_32
1257 EPILOGUE_1_ARGS 0
1258ENDPROC iemAImpl_bswap_u32
1259
1260BEGINPROC_FASTCALL iemAImpl_bswap_u64, 4
1261%ifdef RT_ARCH_AMD64
1262 PROLOGUE_1_ARGS
1263 mov T0, [A0]
1264 bswap T0
1265 mov [A0], T0
1266 EPILOGUE_1_ARGS 0
1267%else
1268 PROLOGUE_1_ARGS
1269 mov T0, [A0]
1270 mov T1, [A0 + 4]
1271 bswap T0
1272 bswap T1
1273 mov [A0 + 4], T0
1274 mov [A0], T1
1275 EPILOGUE_1_ARGS 0
1276%endif
1277ENDPROC iemAImpl_bswap_u64
1278
1279
1280;;
1281; Initialize the FPU for the actual instruction being emulated, this means
1282; loading parts of the guest's control word and status word.
1283;
1284; @uses 24 bytes of stack.
1285; @param 1 Expression giving the address of the FXSTATE of the guest.
1286;
1287%macro FPU_LD_FXSTATE_FCW_AND_SAFE_FSW 1
1288 fnstenv [xSP]
1289
1290 ; FCW - for exception, precision and rounding control.
1291 movzx T0, word [%1 + X86FXSTATE.FCW]
1292 and T0, X86_FCW_MASK_ALL | X86_FCW_PC_MASK | X86_FCW_RC_MASK
1293 mov [xSP + X86FSTENV32P.FCW], T0_16
1294
1295 ; FSW - for undefined C0, C1, C2, and C3.
1296 movzx T1, word [%1 + X86FXSTATE.FSW]
1297 and T1, X86_FSW_C_MASK
1298 movzx T0, word [xSP + X86FSTENV32P.FSW]
1299 and T0, X86_FSW_TOP_MASK
1300 or T0, T1
1301 mov [xSP + X86FSTENV32P.FSW], T0_16
1302
1303 fldenv [xSP]
1304%endmacro
1305
1306
1307;;
1308; Need to move this as well somewhere better?
1309;
1310struc IEMFPURESULT
1311 .r80Result resw 5
1312 .FSW resw 1
1313endstruc
1314
1315
1316;;
1317; Need to move this as well somewhere better?
1318;
1319struc IEMFPURESULTTWO
1320 .r80Result1 resw 5
1321 .FSW resw 1
1322 .r80Result2 resw 5
1323endstruc
1324
1325
1326;;
1327; Converts a 80-bit floating point value to a 32-bit signed integer.
1328;
1329; @param A0 FPU context (fxsave).
1330; @param A1 Pointer to a 16-bit FSW output variable.
1331; @param A2 Pointer to the 32-bit signed integer output variable.
1332; @param A3 Pointer to the 80-bit floating point value to convert.
1333;
1334BEGINPROC_FASTCALL iemAImpl_fpu_r80_to_i32, 12
1335 PROLOGUE_4_ARGS
1336 sub xSP, 20h
1337
1338 fninit
1339 fld tword [A3]
1340 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1341 fistp dword [A2]
1342
1343 fnstsw word [A1]
1344 fnclex
1345
1346 add xSP, 20h
1347 EPILOGUE_4_ARGS 0
1348ENDPROC iemAImpl_fpu_r80_to_i32
1349
1350
1351
1352;
1353;---------------------- 32-bit floating point operations ----------------------
1354;
1355
1356;;
1357; Converts a 32-bit floating point value to a 80-bit one (fpu register).
1358;
1359; @param A0 FPU context (fxsave).
1360; @param A1 Pointer to a IEMFPURESULT for the output.
1361; @param A2 Pointer to the 32-bit floating point value to convert.
1362;
1363BEGINPROC_FASTCALL iemAImpl_fld_r32_to_r80, 12
1364 PROLOGUE_3_ARGS
1365 sub xSP, 20h
1366
1367 fninit
1368 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1369 fld dword [A2]
1370
1371 fnstsw word [A1 + IEMFPURESULT.FSW]
1372 fnclex
1373 fstp tword [A1 + IEMFPURESULT.r80Result]
1374
1375 fninit
1376 add xSP, 20h
1377 EPILOGUE_3_ARGS 0
1378ENDPROC iemAImpl_fld_r32_to_r80
1379
1380
1381;;
1382; Store a 80-bit floating point value (register) as a 32-bit one (memory).
1383;
1384; @param A0 FPU context (fxsave).
1385; @param A1 Where to return the output FSW.
1386; @param A2 Where to store the 32-bit value.
1387; @param A3 Pointer to the 80-bit value.
1388;
1389BEGINPROC_FASTCALL iemAImpl_fst_r80_to_r32, 12
1390 PROLOGUE_3_ARGS
1391 sub xSP, 20h
1392
1393 fninit
1394 fld tword [A3]
1395 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1396 fst dword [A2]
1397
1398 fnstsw word [A1]
1399
1400 fninit
1401 add xSP, 20h
1402 EPILOGUE_3_ARGS 0
1403ENDPROC iemAImpl_fst_r80_to_r32
1404
1405
1406;;
1407; FPU instruction working on one 80-bit and one 32-bit floating point value.
1408;
1409; @param 1 The instruction
1410;
1411; @param A0 FPU context (fxsave).
1412; @param A1 Pointer to a IEMFPURESULT for the output.
1413; @param A2 Pointer to the 80-bit value.
1414; @param A3 Pointer to the 32-bit value.
1415;
1416%macro IEMIMPL_FPU_R80_BY_R32 1
1417BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r32, 16
1418 PROLOGUE_4_ARGS
1419 sub xSP, 20h
1420
1421 fninit
1422 fld tword [A2]
1423 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1424 %1 dword [A3]
1425
1426 fnstsw word [A1 + IEMFPURESULT.FSW]
1427 fnclex
1428 fstp tword [A1 + IEMFPURESULT.r80Result]
1429
1430 fninit
1431 add xSP, 20h
1432 EPILOGUE_4_ARGS 8
1433ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r32
1434%endmacro
1435
1436IEMIMPL_FPU_R80_BY_R32 fadd
1437IEMIMPL_FPU_R80_BY_R32 fmul
1438IEMIMPL_FPU_R80_BY_R32 fsub
1439IEMIMPL_FPU_R80_BY_R32 fsubr
1440IEMIMPL_FPU_R80_BY_R32 fdiv
1441IEMIMPL_FPU_R80_BY_R32 fdivr
1442
1443
1444;;
1445; FPU instruction working on one 80-bit and one 64-bit floating point value,
1446; only returning FSW.
1447;
1448; @param 1 The instruction
1449;
1450; @param A0 FPU context (fxsave).
1451; @param A1 Where to store the output FSW.
1452; @param A2 Pointer to the 80-bit value.
1453; @param A3 Pointer to the 64-bit value.
1454;
1455%macro IEMIMPL_FPU_R80_BY_R32_FSW 1
1456BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r32, 16
1457 PROLOGUE_4_ARGS
1458 sub xSP, 20h
1459
1460 fninit
1461 fld tword [A2]
1462 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1463 %1 dword [A3]
1464
1465 fnstsw word [A1]
1466
1467 fninit
1468 add xSP, 20h
1469 EPILOGUE_4_ARGS 8
1470ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r32
1471%endmacro
1472
1473IEMIMPL_FPU_R80_BY_R32_FSW fcom
1474
1475
1476
1477;
1478;---------------------- 64-bit floating point operations ----------------------
1479;
1480
1481;;
1482; Converts a 64-bit floating point value to a 80-bit one (fpu register).
1483;
1484; @param A0 FPU context (fxsave).
1485; @param A1 Pointer to a IEMFPURESULT for the output.
1486; @param A2 Pointer to the 64-bit floating point value to convert.
1487;
1488BEGINPROC_FASTCALL iemAImpl_fld_r64_to_r80, 12
1489 PROLOGUE_3_ARGS
1490 sub xSP, 20h
1491
1492 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1493 fld qword [A2]
1494
1495 fnstsw word [A1 + IEMFPURESULT.FSW]
1496 fnclex
1497 fstp tword [A1 + IEMFPURESULT.r80Result]
1498
1499 fninit
1500 add xSP, 20h
1501 EPILOGUE_3_ARGS 0
1502ENDPROC iemAImpl_fld_r64_to_r80
1503
1504
1505;;
1506; Store a 80-bit floating point value (register) as a 64-bit one (memory).
1507;
1508; @param A0 FPU context (fxsave).
1509; @param A1 Where to return the output FSW.
1510; @param A2 Where to store the 64-bit value.
1511; @param A3 Pointer to the 80-bit value.
1512;
1513BEGINPROC_FASTCALL iemAImpl_fst_r80_to_r64, 12
1514 PROLOGUE_3_ARGS
1515 sub xSP, 20h
1516
1517 fninit
1518 fld tword [A3]
1519 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1520 fst qword [A2]
1521
1522 fnstsw word [A1]
1523
1524 fninit
1525 add xSP, 20h
1526 EPILOGUE_3_ARGS 0
1527ENDPROC iemAImpl_fst_r80_to_r64
1528
1529
1530;;
1531; FPU instruction working on one 80-bit and one 64-bit floating point value.
1532;
1533; @param 1 The instruction
1534;
1535; @param A0 FPU context (fxsave).
1536; @param A1 Pointer to a IEMFPURESULT for the output.
1537; @param A2 Pointer to the 80-bit value.
1538; @param A3 Pointer to the 64-bit value.
1539;
1540%macro IEMIMPL_FPU_R80_BY_R64 1
1541BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r64, 16
1542 PROLOGUE_4_ARGS
1543 sub xSP, 20h
1544
1545 fninit
1546 fld tword [A2]
1547 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1548 %1 qword [A3]
1549
1550 fnstsw word [A1 + IEMFPURESULT.FSW]
1551 fnclex
1552 fstp tword [A1 + IEMFPURESULT.r80Result]
1553
1554 fninit
1555 add xSP, 20h
1556 EPILOGUE_4_ARGS 8
1557ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r64
1558%endmacro
1559
1560IEMIMPL_FPU_R80_BY_R64 fadd
1561IEMIMPL_FPU_R80_BY_R64 fmul
1562IEMIMPL_FPU_R80_BY_R64 fsub
1563IEMIMPL_FPU_R80_BY_R64 fsubr
1564IEMIMPL_FPU_R80_BY_R64 fdiv
1565IEMIMPL_FPU_R80_BY_R64 fdivr
1566
1567;;
1568; FPU instruction working on one 80-bit and one 64-bit floating point value,
1569; only returning FSW.
1570;
1571; @param 1 The instruction
1572;
1573; @param A0 FPU context (fxsave).
1574; @param A1 Where to store the output FSW.
1575; @param A2 Pointer to the 80-bit value.
1576; @param A3 Pointer to the 64-bit value.
1577;
1578%macro IEMIMPL_FPU_R80_BY_R64_FSW 1
1579BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r64, 16
1580 PROLOGUE_4_ARGS
1581 sub xSP, 20h
1582
1583 fninit
1584 fld tword [A2]
1585 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1586 %1 qword [A3]
1587
1588 fnstsw word [A1]
1589
1590 fninit
1591 add xSP, 20h
1592 EPILOGUE_4_ARGS 8
1593ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r64
1594%endmacro
1595
1596IEMIMPL_FPU_R80_BY_R64_FSW fcom
1597
1598
1599
1600;
1601;---------------------- 80-bit floating point operations ----------------------
1602;
1603
1604;;
1605; FPU instruction working on two 80-bit floating point values.
1606;
1607; @param 1 The instruction
1608;
1609; @param A0 FPU context (fxsave).
1610; @param A1 Pointer to a IEMFPURESULT for the output.
1611; @param A2 Pointer to the first 80-bit value (ST0)
1612; @param A3 Pointer to the second 80-bit value (STn).
1613;
1614%macro IEMIMPL_FPU_R80_BY_R80 2
1615BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
1616 PROLOGUE_4_ARGS
1617 sub xSP, 20h
1618
1619 fninit
1620 fld tword [A3]
1621 fld tword [A2]
1622 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1623 %1 %2
1624
1625 fnstsw word [A1 + IEMFPURESULT.FSW]
1626 fnclex
1627 fstp tword [A1 + IEMFPURESULT.r80Result]
1628
1629 fninit
1630 add xSP, 20h
1631 EPILOGUE_4_ARGS 8
1632ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
1633%endmacro
1634
1635IEMIMPL_FPU_R80_BY_R80 fadd, {st0, st1}
1636IEMIMPL_FPU_R80_BY_R80 fmul, {st0, st1}
1637IEMIMPL_FPU_R80_BY_R80 fsub, {st0, st1}
1638IEMIMPL_FPU_R80_BY_R80 fsubr, {st0, st1}
1639IEMIMPL_FPU_R80_BY_R80 fdiv, {st0, st1}
1640IEMIMPL_FPU_R80_BY_R80 fdivr, {st0, st1}
1641IEMIMPL_FPU_R80_BY_R80 fprem, {}
1642IEMIMPL_FPU_R80_BY_R80 fprem1, {}
1643IEMIMPL_FPU_R80_BY_R80 fscale, {}
1644
1645
1646;;
1647; FPU instruction working on two 80-bit floating point values, ST1 and ST0,
1648; storing the result in ST1 and popping the stack.
1649;
1650; @param 1 The instruction
1651;
1652; @param A0 FPU context (fxsave).
1653; @param A1 Pointer to a IEMFPURESULT for the output.
1654; @param A2 Pointer to the first 80-bit value (ST1).
1655; @param A3 Pointer to the second 80-bit value (ST0).
1656;
1657%macro IEMIMPL_FPU_R80_BY_R80_ST1_ST0_POP 1
1658BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
1659 PROLOGUE_4_ARGS
1660 sub xSP, 20h
1661
1662 fninit
1663 fld tword [A2]
1664 fld tword [A3]
1665 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1666 %1
1667
1668 fnstsw word [A1 + IEMFPURESULT.FSW]
1669 fnclex
1670 fstp tword [A1 + IEMFPURESULT.r80Result]
1671
1672 fninit
1673 add xSP, 20h
1674 EPILOGUE_4_ARGS 8
1675ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
1676%endmacro
1677
1678IEMIMPL_FPU_R80_BY_R80_ST1_ST0_POP fpatan
1679IEMIMPL_FPU_R80_BY_R80_ST1_ST0_POP fyl2xp1
1680
1681
1682;;
1683; FPU instruction working on two 80-bit floating point values, only
1684; returning FSW.
1685;
1686; @param 1 The instruction
1687;
1688; @param A0 FPU context (fxsave).
1689; @param A1 Pointer to a uint16_t for the resulting FSW.
1690; @param A2 Pointer to the first 80-bit value.
1691; @param A3 Pointer to the second 80-bit value.
1692;
1693%macro IEMIMPL_FPU_R80_BY_R80_FSW 1
1694BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
1695 PROLOGUE_4_ARGS
1696 sub xSP, 20h
1697
1698 fninit
1699 fld tword [A3]
1700 fld tword [A2]
1701 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1702 %1 st0, st1
1703
1704 fnstsw word [A1]
1705
1706 fninit
1707 add xSP, 20h
1708 EPILOGUE_4_ARGS 8
1709ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
1710%endmacro
1711
1712IEMIMPL_FPU_R80_BY_R80_FSW fcom
1713IEMIMPL_FPU_R80_BY_R80_FSW fucom
1714
1715
1716;;
1717; FPU instruction working on one 80-bit floating point value.
1718;
1719; @param 1 The instruction
1720;
1721; @param A0 FPU context (fxsave).
1722; @param A1 Pointer to a IEMFPURESULT for the output.
1723; @param A2 Pointer to the 80-bit value.
1724;
1725%macro IEMIMPL_FPU_R80 1
1726BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80, 12
1727 PROLOGUE_3_ARGS
1728 sub xSP, 20h
1729
1730 fninit
1731 fld tword [A2]
1732 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1733 %1
1734
1735 fnstsw word [A1 + IEMFPURESULT.FSW]
1736 fnclex
1737 fstp tword [A1 + IEMFPURESULT.r80Result]
1738
1739 fninit
1740 add xSP, 20h
1741 EPILOGUE_3_ARGS 4
1742ENDPROC iemAImpl_ %+ %1 %+ _r80
1743%endmacro
1744
1745IEMIMPL_FPU_R80 fchs
1746IEMIMPL_FPU_R80 fabs
1747IEMIMPL_FPU_R80 f2xm1
1748IEMIMPL_FPU_R80 fyl2x
1749IEMIMPL_FPU_R80 fsqrt
1750IEMIMPL_FPU_R80 frndint
1751IEMIMPL_FPU_R80 fsin
1752IEMIMPL_FPU_R80 fcos
1753
1754
1755;;
1756; FPU instruction working on one 80-bit floating point value, only
1757; returning FSW.
1758;
1759; @param 1 The instruction
1760;
1761; @param A0 FPU context (fxsave).
1762; @param A1 Pointer to a uint16_t for the resulting FSW.
1763; @param A2 Pointer to the 80-bit value.
1764;
1765%macro IEMIMPL_FPU_R80_FSW 1
1766BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80, 12
1767 PROLOGUE_3_ARGS
1768 sub xSP, 20h
1769
1770 fninit
1771 fld tword [A2]
1772 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1773 %1
1774
1775 fnstsw word [A1]
1776
1777 fninit
1778 add xSP, 20h
1779 EPILOGUE_3_ARGS 4
1780ENDPROC iemAImpl_ %+ %1 %+ _r80
1781%endmacro
1782
1783IEMIMPL_FPU_R80_FSW ftst
1784IEMIMPL_FPU_R80_FSW fxam
1785
1786
1787
1788;;
1789; FPU instruction loading a 80-bit floating point constant.
1790;
1791; @param 1 The instruction
1792;
1793; @param A0 FPU context (fxsave).
1794; @param A1 Pointer to a IEMFPURESULT for the output.
1795;
1796%macro IEMIMPL_FPU_R80_CONST 1
1797BEGINPROC_FASTCALL iemAImpl_ %+ %1, 8
1798 PROLOGUE_2_ARGS
1799 sub xSP, 20h
1800
1801 fninit
1802 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1803 %1
1804
1805 fnstsw word [A1 + IEMFPURESULT.FSW]
1806 fnclex
1807 fstp tword [A1 + IEMFPURESULT.r80Result]
1808
1809 fninit
1810 add xSP, 20h
1811 EPILOGUE_2_ARGS 0
1812ENDPROC iemAImpl_ %+ %1 %+
1813%endmacro
1814
1815IEMIMPL_FPU_R80_CONST fld1
1816IEMIMPL_FPU_R80_CONST fldl2t
1817IEMIMPL_FPU_R80_CONST fldl2e
1818IEMIMPL_FPU_R80_CONST fldpi
1819IEMIMPL_FPU_R80_CONST fldlg2
1820IEMIMPL_FPU_R80_CONST fldln2
1821IEMIMPL_FPU_R80_CONST fldz
1822
1823
1824;;
1825; FPU instruction working on one 80-bit floating point value, outputing two.
1826;
1827; @param 1 The instruction
1828;
1829; @param A0 FPU context (fxsave).
1830; @param A1 Pointer to a IEMFPURESULTTWO for the output.
1831; @param A2 Pointer to the 80-bit value.
1832;
1833%macro IEMIMPL_FPU_R80_R80 1
1834BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_r80, 12
1835 PROLOGUE_3_ARGS
1836 sub xSP, 20h
1837
1838 fninit
1839 fld tword [A2]
1840 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1841 %1
1842
1843 fnstsw word [A1 + IEMFPURESULTTWO.FSW]
1844 fnclex
1845 fstp tword [A1 + IEMFPURESULTTWO.r80Result2]
1846 fnclex
1847 fstp tword [A1 + IEMFPURESULTTWO.r80Result1]
1848
1849 fninit
1850 add xSP, 20h
1851 EPILOGUE_3_ARGS 4
1852ENDPROC iemAImpl_ %+ %1 %+ _r80_r80
1853%endmacro
1854
1855IEMIMPL_FPU_R80_R80 fptan
1856IEMIMPL_FPU_R80_R80 fxtract
1857IEMIMPL_FPU_R80_R80 fsincos
1858
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