VirtualBox

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

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

IEM: More r80 by m64r instructions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.3 KB
Line 
1; $Id: IEMAllAImpl.asm 40163 2012-02-16 20:28:18Z 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%macro FPU_SAFE_INIT 1
1281 fninit
1282 movzx T0, word [%1 + X86FXSTATE.FCW]
1283 and T0, X86_FCW_MASK_ALL | X86_FCW_PC_MASK | X86_FCW_RC_MASK
1284 or T0, X86_FCW_MASK_ALL
1285 mov [xSP], T0
1286 fldcw [xSP]
1287%endmacro
1288
1289;;
1290; Initialize the FPU for the actual instruction being emulated, this means
1291; loading parts of the guest's control word and status word.
1292;
1293; @uses 24 bytes of stack.
1294; @param 1 Expression giving the address of the FXSTATE of the guest.
1295;
1296%macro FPU_LD_FXSTATE_FCW_AND_SAFE_FSW 1
1297 fnstenv [xSP]
1298
1299 ; FCW - for exception, precision and rounding control.
1300 movzx T0, word [%1 + X86FXSTATE.FCW]
1301 and T0, X86_FCW_MASK_ALL | X86_FCW_PC_MASK | X86_FCW_RC_MASK
1302 mov [xSP + X86FSTENV32P.FCW], T0_16
1303
1304 ; FSW - for undefined C0, C1, C2, and C3.
1305 movzx T1, word [%1 + X86FXSTATE.FSW]
1306 and T1, X86_FSW_C_MASK
1307 movzx T0, word [xSP + X86FSTENV32P.FSW]
1308 and T0, X86_FSW_TOP_MASK
1309 or T0, T1
1310 mov [xSP + X86FSTENV32P.FSW], T0_16
1311
1312 fldenv [xSP]
1313%endmacro
1314
1315
1316;;
1317; Need to move this as well somewhere better?
1318;
1319struc IEMFPURESULT
1320 .r80Result resw 5
1321 .FSW resw 1
1322endstruc
1323
1324
1325;;
1326; Converts a 32-bit floating point value to a 80-bit one (fpu register).
1327;
1328; @param A0 FPU context (fxsave).
1329; @param A1 Pointer to a IEMFPURESULT for the output.
1330; @param A2 The 32-bit floating point value to convert.
1331;
1332BEGINPROC_FASTCALL iemAImpl_fpu_r32_to_r80, 12
1333 PROLOGUE_3_ARGS
1334 sub xSP, 20h
1335
1336 FPU_SAFE_INIT A0
1337 mov [xSP], A2
1338 fld dword [xSP]
1339
1340 fnstsw word [A1 + IEMFPURESULT.FSW]
1341 fstp tword [A1 + IEMFPURESULT.r80Result]
1342
1343 add xSP, 20h
1344 EPILOGUE_3_ARGS 0
1345ENDPROC iemAImpl_fpu_r32_to_r80
1346
1347
1348;;
1349; Converts a 64-bit floating point value to a 80-bit one (fpu register).
1350;
1351; @param A0 FPU context (fxsave).
1352; @param A1 Pointer to a IEMFPURESULT for the output.
1353; @param A2 Pointer to the 64-bit floating point value to convert.
1354;
1355BEGINPROC_FASTCALL iemAImpl_fpu_r64_to_r80, 12
1356 PROLOGUE_3_ARGS
1357 sub xSP, 20h
1358
1359 FPU_SAFE_INIT A0
1360 fld qword [A2]
1361
1362 fnstsw word [A1 + IEMFPURESULT.FSW]
1363 fstp tword [A1 + IEMFPURESULT.r80Result]
1364
1365 add xSP, 20h
1366 EPILOGUE_3_ARGS 0
1367ENDPROC iemAImpl_fpu_r64_to_r80
1368
1369
1370;;
1371; FPU instruction working on one 80-bit and one 64-bit floating point value.
1372;
1373; @param 1 The instruction
1374;
1375; @param A0 FPU context (fxsave).
1376; @param A1 Pointer to a IEMFPURESULT for the output.
1377; @param A2 Pointer to the 80-bit dividend.
1378; @param A3 Pointer to the 64-bit divisor.
1379;
1380%macro IEMIMPL_FPU_R80_BY_R64 1
1381BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r64, 16
1382 PROLOGUE_4_ARGS
1383 sub xSP, 20h
1384
1385 fninit
1386 fld tword [A2]
1387 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
1388 %1 qword [A3]
1389
1390 fnstsw word [A1 + IEMFPURESULT.FSW]
1391 fnclex
1392 fstp tword [A1 + IEMFPURESULT.r80Result]
1393
1394 add xSP, 20h
1395 EPILOGUE_4_ARGS 8
1396ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r64
1397%endmacro
1398
1399IEMIMPL_FPU_R80_BY_R64 fadd
1400IEMIMPL_FPU_R80_BY_R64 fmul
1401IEMIMPL_FPU_R80_BY_R64 fcom
1402IEMIMPL_FPU_R80_BY_R64 fsub
1403IEMIMPL_FPU_R80_BY_R64 fsubr
1404IEMIMPL_FPU_R80_BY_R64 fdiv
1405IEMIMPL_FPU_R80_BY_R64 fdivr
1406
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