VirtualBox

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

Last change on this file since 36857 was 36857, checked in by vboxsync, 14 years ago

IEM: bsf, bsr, bt, btc, bts, btr and leave. Some cleaning up.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.6 KB
Line 
1; $Id: IEMAllAImpl.asm 36857 2011-04-27 14:54:49Z vboxsync $
2;; @file
3; IEM - Instruction Implementation in Assembly.
4;
5
6; Copyright (C) 2011 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 "VBox/x86.mac"
24
25
26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27; Defined Constants And Macros ;
28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29
30;
31; We employ some macro assembly here to hid the calling convention differences.
32;
33%ifdef RT_ARCH_AMD64
34 %macro PROLOGUE_1_ARGS 0
35 %endmacro
36 %macro EPILOGUE_1_ARGS 0
37 %endmacro
38 %macro PROLOGUE_2_ARGS 0
39 %endmacro
40 %macro EPILOGUE_2_ARGS 0
41 %endmacro
42 %macro PROLOGUE_3_ARGS 0
43 %endmacro
44 %macro EPILOGUE_3_ARGS 0
45 %endmacro
46 %macro PROLOGUE_4_ARGS 0
47 %endmacro
48 %macro EPILOGUE_4_ARGS 0
49 %endmacro
50
51 %ifdef ASM_CALL64_GCC
52 %define A0 rdi
53 %define A0_32 edi
54 %define A0_16 di
55 %define A0_8 dil
56
57 %define A1 rsi
58 %define A1_32 esi
59 %define A1_16 si
60 %define A1_8 sil
61
62 %define A2 rdx
63 %define A2_32 edx
64 %define A2_16 dx
65 %define A2_8 dl
66
67 %define A3 rcx
68 %define A3_32 ecx
69 %define A3_16 cx
70 %endif
71
72 %ifdef ASM_CALL64_MSC
73 %define A0 rcx
74 %define A0_32 ecx
75 %define A0_16 cx
76 %define A0_8 cl
77
78 %define A1 rdx
79 %define A1_32 edx
80 %define A1_16 dx
81 %define A1_8 dl
82
83 %define A2 r8
84 %define A2_32 r8d
85 %define A2_16 r8w
86 %define A2_8 r8b
87
88 %define A3 r9
89 %define A3_32 r9d
90 %define A3_16 r9w
91 %endif
92
93 %define T0 rax
94 %define T0_32 eax
95 %define T0_16 ax
96 %define T0_8 al
97
98 %define T1 r11
99 %define T1_32 r11d
100 %define T1_16 r11w
101 %define T1_8 r11b
102
103%else
104 ; x86
105 %macro PROLOGUE_1_ARGS 0
106 push edi
107 %endmacro
108 %macro EPILOGUE_1_ARGS 0
109 pop edi
110 %endmacro
111
112 %macro PROLOGUE_2_ARGS 0
113 push edi
114 %endmacro
115 %macro EPILOGUE_2_ARGS 0
116 pop edi
117 %endmacro
118
119 %macro PROLOGUE_3_ARGS 0
120 push ebx
121 mov ebx, [esp + 4 + 4]
122 push edi
123 %endmacro
124 %macro EPILOGUE_3_ARGS 0
125 pop edi
126 pop ebx
127 %endmacro
128
129 %macro PROLOGUE_4_ARGS 0
130 push ebx
131 push edi
132 push esi
133 mov ebx, [esp + 12 + 4 + 0]
134 mov esi, [esp + 12 + 4 + 4]
135 %endmacro
136 %macro EPILOGUE_4_ARGS 0
137 pop esi
138 pop edi
139 pop ebx
140 %endmacro
141
142 %define A0 ecx
143 %define A0_32 ecx
144 %define A0_16 cx
145 %define A0_8 cl
146
147 %define A1 edx
148 %define A1_32 edx
149 %define A1_16 dx
150 %define A1_8 dl
151
152 %define A2 ebx
153 %define A2_32 ebx
154 %define A2_16 bx
155 %define A2_8 bl
156
157 %define A3 esi
158 %define A3_32 esi
159 %define A3_16 si
160
161 %define T0 eax
162 %define T0_32 eax
163 %define T0_16 ax
164 %define T0_8 al
165
166 %define T1 edi
167 %define T1_32 edi
168 %define T1_16 di
169%endif
170
171
172;;
173; Load the relevant flags from [%1] if there are undefined flags (%3).
174;
175; @remarks Clobbers T0, stack. Changes EFLAGS.
176; @param A2 The register pointing to the flags.
177; @param 1 The parameter (A0..A3) pointing to the eflags.
178; @param 2 The set of modified flags.
179; @param 3 The set of undefined flags.
180;
181%macro IEM_MAYBE_LOAD_FLAGS 3
182 ;%if (%3) != 0
183 pushf ; store current flags
184 mov T0_32, [%1] ; load the guest flags
185 and dword [xSP], ~(%2 | %3) ; mask out the modified and undefined flags
186 and T0_32, (%2 | %3) ; select the modified and undefined flags.
187 or [xSP], T0 ; merge guest flags with host flags.
188 popf ; load the mixed flags.
189 ;%endif
190%endmacro
191
192;;
193; Update the flag.
194;
195; @remarks Clobbers T0, T1, stack.
196; @param 1 The register pointing to the EFLAGS.
197; @param 2 The mask of modified flags to save.
198; @param 3 The mask of undefined flags to (maybe) save.
199;
200%macro IEM_SAVE_FLAGS 3
201 %if (%2 | %3) != 0
202 pushf
203 pop T1
204 mov T0_32, [%1] ; flags
205 and T0_32, ~(%2 | %3) ; clear the modified & undefined flags.
206 and T1_32, (%2 | %3) ; select the modified and undefined flags.
207 or T0_32, T1_32 ; combine the flags.
208 mov [%1], T0_32 ; save the flags.
209 %endif
210%endmacro
211
212
213;;
214; Macro for implementing a binary operator.
215;
216; This will generate code for the 8, 16, 32 and 64 bit accesses with locked
217; variants, except on 32-bit system where the 64-bit accesses requires hand
218; coding.
219;
220; All the functions takes a pointer to the destination memory operand in A0,
221; the source register operand in A1 and a pointer to eflags in A2.
222;
223; @param 1 The instruction mnemonic.
224; @param 2 Non-zero if there should be a locked version.
225; @param 3 The modified flags.
226; @param 4 The undefined flags.
227;
228%macro IEMIMPL_BIN_OP 4
229BEGINPROC iemAImpl_ %+ %1 %+ _u8
230 PROLOGUE_3_ARGS
231 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
232 %1 byte [A0], A1_8
233 IEM_SAVE_FLAGS A2, %3, %4
234 EPILOGUE_3_ARGS
235 ret
236ENDPROC iemAImpl_ %+ %1 %+ _u8
237
238BEGINPROC iemAImpl_ %+ %1 %+ _u16
239 PROLOGUE_3_ARGS
240 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
241 %1 word [A0], A1_16
242 IEM_SAVE_FLAGS A2, %3, %4
243 EPILOGUE_3_ARGS
244 ret
245ENDPROC iemAImpl_ %+ %1 %+ _u16
246
247BEGINPROC iemAImpl_ %+ %1 %+ _u32
248 PROLOGUE_3_ARGS
249 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
250 %1 dword [A0], A1_32
251 IEM_SAVE_FLAGS A2, %3, %4
252 EPILOGUE_3_ARGS
253 ret
254ENDPROC iemAImpl_ %+ %1 %+ _u32
255
256 %ifdef RT_ARCH_AMD64
257BEGINPROC iemAImpl_ %+ %1 %+ _u64
258 PROLOGUE_3_ARGS
259 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
260 %1 qword [A0], A1
261 IEM_SAVE_FLAGS A2, %3, %4
262 EPILOGUE_3_ARGS
263 ret
264ENDPROC iemAImpl_ %+ %1 %+ _u64
265 %else ; stub it for now - later, replace with hand coded stuff.
266BEGINPROC iemAImpl_ %+ %1 %+ _u64
267 int3
268 ret
269ENDPROC iemAImpl_ %+ %1 %+ _u64
270 %endif ; !RT_ARCH_AMD64
271
272 %if %2 != 0 ; locked versions requested?
273
274BEGINPROC iemAImpl_ %+ %1 %+ _u8_locked
275 PROLOGUE_3_ARGS
276 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
277 lock %1 byte [A0], A1_8
278 IEM_SAVE_FLAGS A2, %3, %4
279 EPILOGUE_3_ARGS
280 ret
281ENDPROC iemAImpl_ %+ %1 %+ _u8_locked
282
283BEGINPROC iemAImpl_ %+ %1 %+ _u16_locked
284 PROLOGUE_3_ARGS
285 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
286 lock %1 word [A0], A1_16
287 IEM_SAVE_FLAGS A2, %3, %4
288 EPILOGUE_3_ARGS
289 ret
290ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
291
292BEGINPROC iemAImpl_ %+ %1 %+ _u32_locked
293 PROLOGUE_3_ARGS
294 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
295 lock %1 dword [A0], A1_32
296 IEM_SAVE_FLAGS A2, %3, %4
297 EPILOGUE_3_ARGS
298 ret
299ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
300
301 %ifdef RT_ARCH_AMD64
302BEGINPROC iemAImpl_ %+ %1 %+ _u64_locked
303 PROLOGUE_3_ARGS
304 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
305 lock %1 qword [A0], A1
306 IEM_SAVE_FLAGS A2, %3, %4
307 EPILOGUE_3_ARGS
308 ret
309ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
310 %else ; stub it for now - later, replace with hand coded stuff.
311BEGINPROC iemAImpl_ %+ %1 %+ _u64_locked
312 int3
313 ret
314ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
315 %endif ; !RT_ARCH_AMD64
316 %endif ; locked
317%endmacro
318
319; instr,lock,modified-flags.
320IEMIMPL_BIN_OP add, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
321IEMIMPL_BIN_OP adc, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
322IEMIMPL_BIN_OP sub, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
323IEMIMPL_BIN_OP sbb, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
324IEMIMPL_BIN_OP or, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
325IEMIMPL_BIN_OP xor, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
326IEMIMPL_BIN_OP and, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
327IEMIMPL_BIN_OP cmp, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
328IEMIMPL_BIN_OP test, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
329
330
331;;
332; Macro for implementing a bit operator.
333;
334; This will generate code for the 16, 32 and 64 bit accesses with locked
335; variants, except on 32-bit system where the 64-bit accesses requires hand
336; coding.
337;
338; All the functions takes a pointer to the destination memory operand in A0,
339; the source register operand in A1 and a pointer to eflags in A2.
340;
341; @param 1 The instruction mnemonic.
342; @param 2 Non-zero if there should be a locked version.
343; @param 3 The modified flags.
344; @param 4 The undefined flags.
345;
346%macro IEMIMPL_BIT_OP 4
347BEGINPROC iemAImpl_ %+ %1 %+ _u16
348 PROLOGUE_3_ARGS
349 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
350 %1 word [A0], A1_16
351 IEM_SAVE_FLAGS A2, %3, %4
352 EPILOGUE_3_ARGS
353 ret
354ENDPROC iemAImpl_ %+ %1 %+ _u16
355
356BEGINPROC iemAImpl_ %+ %1 %+ _u32
357 PROLOGUE_3_ARGS
358 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
359 %1 dword [A0], A1_32
360 IEM_SAVE_FLAGS A2, %3, %4
361 EPILOGUE_3_ARGS
362 ret
363ENDPROC iemAImpl_ %+ %1 %+ _u32
364
365 %ifdef RT_ARCH_AMD64
366BEGINPROC iemAImpl_ %+ %1 %+ _u64
367 PROLOGUE_3_ARGS
368 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
369 %1 qword [A0], A1
370 IEM_SAVE_FLAGS A2, %3, %4
371 EPILOGUE_3_ARGS
372 ret
373ENDPROC iemAImpl_ %+ %1 %+ _u64
374 %else ; stub it for now - later, replace with hand coded stuff.
375BEGINPROC iemAImpl_ %+ %1 %+ _u64
376 int3
377 ret
378ENDPROC iemAImpl_ %+ %1 %+ _u64
379 %endif ; !RT_ARCH_AMD64
380
381 %if %2 != 0 ; locked versions requested?
382
383BEGINPROC iemAImpl_ %+ %1 %+ _u16_locked
384 PROLOGUE_3_ARGS
385 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
386 lock %1 word [A0], A1_16
387 IEM_SAVE_FLAGS A2, %3, %4
388 EPILOGUE_3_ARGS
389 ret
390ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
391
392BEGINPROC iemAImpl_ %+ %1 %+ _u32_locked
393 PROLOGUE_3_ARGS
394 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
395 lock %1 dword [A0], A1_32
396 IEM_SAVE_FLAGS A2, %3, %4
397 EPILOGUE_3_ARGS
398 ret
399ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
400
401 %ifdef RT_ARCH_AMD64
402BEGINPROC iemAImpl_ %+ %1 %+ _u64_locked
403 PROLOGUE_3_ARGS
404 IEM_MAYBE_LOAD_FLAGS A2, %3, %4
405 lock %1 qword [A0], A1
406 IEM_SAVE_FLAGS A2, %3, %4
407 EPILOGUE_3_ARGS
408 ret
409ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
410 %else ; stub it for now - later, replace with hand coded stuff.
411BEGINPROC iemAImpl_ %+ %1 %+ _u64_locked
412 int3
413 ret
414ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
415 %endif ; !RT_ARCH_AMD64
416 %endif ; locked
417%endmacro
418IEMIMPL_BIT_OP bt, 0, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
419IEMIMPL_BIT_OP btc, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
420IEMIMPL_BIT_OP bts, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
421IEMIMPL_BIT_OP btr, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
422
423;;
424; Macro for implementing a bit search operator.
425;
426; This will generate code for the 16, 32 and 64 bit accesses, except on 32-bit
427; system where the 64-bit accesses requires hand coding.
428;
429; All the functions takes a pointer to the destination memory operand in A0,
430; the source register operand in A1 and a pointer to eflags in A2.
431;
432; @param 1 The instruction mnemonic.
433; @param 2 The modified flags.
434; @param 3 The undefined flags.
435;
436%macro IEMIMPL_BIT_OP 3
437BEGINPROC iemAImpl_ %+ %1 %+ _u16
438 PROLOGUE_3_ARGS
439 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
440 %1 T0_16, A1_16
441 mov [A0], T0_16
442 IEM_SAVE_FLAGS A2, %2, %3
443 EPILOGUE_3_ARGS
444 ret
445ENDPROC iemAImpl_ %+ %1 %+ _u16
446
447BEGINPROC iemAImpl_ %+ %1 %+ _u32
448 PROLOGUE_3_ARGS
449 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
450 %1 T0_32, A1_32
451 mov [A0], T0_32
452 IEM_SAVE_FLAGS A2, %2, %3
453 EPILOGUE_3_ARGS
454 ret
455ENDPROC iemAImpl_ %+ %1 %+ _u32
456
457 %ifdef RT_ARCH_AMD64
458BEGINPROC iemAImpl_ %+ %1 %+ _u64
459 PROLOGUE_3_ARGS
460 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
461 %1 T0, A1
462 mov [A0], T0
463 IEM_SAVE_FLAGS A2, %2, %3
464 EPILOGUE_3_ARGS
465 ret
466ENDPROC iemAImpl_ %+ %1 %+ _u64
467 %else ; stub it for now - later, replace with hand coded stuff.
468BEGINPROC iemAImpl_ %+ %1 %+ _u64
469 int3
470 ret
471ENDPROC iemAImpl_ %+ %1 %+ _u64
472 %endif ; !RT_ARCH_AMD64
473%endmacro
474IEMIMPL_BIT_OP bsf, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
475IEMIMPL_BIT_OP bsr, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
476
477
478;
479; IMUL is also a similar but yet different case (no lock, no mem dst).
480; The rDX:rAX variant of imul is handled together with mul further down.
481;
482BEGINPROC iemAImpl_imul_two_u16
483 PROLOGUE_3_ARGS
484 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
485 imul A1_16, word [A0]
486 mov [A0], A1_16
487 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
488 EPILOGUE_3_ARGS
489 ret
490ENDPROC iemAImpl_imul_two_u16
491
492BEGINPROC iemAImpl_imul_two_u32
493 PROLOGUE_3_ARGS
494 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
495 imul A1_32, dword [A0]
496 mov [A0], A1_32
497 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
498 EPILOGUE_3_ARGS
499 ret
500ENDPROC iemAImpl_imul_two_u32
501
502BEGINPROC iemAImpl_imul_two_u64
503 PROLOGUE_3_ARGS
504%ifdef RT_ARCH_AMD64
505 IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
506 imul A1, qword [A0]
507 mov [A0], A1
508 IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
509%else
510 int3 ;; @todo implement me
511%endif
512 EPILOGUE_3_ARGS
513 ret
514ENDPROC iemAImpl_imul_two_u64
515
516
517;
518; XCHG for memory operands. This implies locking. No flag changes.
519;
520; Each function takes two arguments, first the pointer to the memory,
521; then the pointer to the register. They all return void.
522;
523BEGINPROC iemAImpl_xchg_u8
524 PROLOGUE_2_ARGS
525 mov T0_8, [A1]
526 xchg [A0], T0_8
527 mov [A1], T0_8
528 EPILOGUE_2_ARGS
529 ret
530ENDPROC iemAImpl_xchg_u8
531
532BEGINPROC iemAImpl_xchg_u16
533 PROLOGUE_2_ARGS
534 mov T0_16, [A1]
535 xchg [A0], T0_16
536 mov [A1], T0_16
537 EPILOGUE_2_ARGS
538 ret
539ENDPROC iemAImpl_xchg_u16
540
541BEGINPROC iemAImpl_xchg_u32
542 PROLOGUE_2_ARGS
543 mov T0_32, [A1]
544 xchg [A0], T0_32
545 mov [A1], T0_32
546 EPILOGUE_2_ARGS
547 ret
548ENDPROC iemAImpl_xchg_u32
549
550BEGINPROC iemAImpl_xchg_u64
551%ifdef RT_ARCH_AMD64
552 PROLOGUE_2_ARGS
553 mov T0, [A1]
554 xchg [A0], T0
555 mov [A1], T0
556 EPILOGUE_2_ARGS
557 ret
558%else
559 int3
560%endif
561ENDPROC iemAImpl_xchg_u64
562
563
564;;
565; Macro for implementing a unary operator.
566;
567; This will generate code for the 8, 16, 32 and 64 bit accesses with locked
568; variants, except on 32-bit system where the 64-bit accesses requires hand
569; coding.
570;
571; All the functions takes a pointer to the destination memory operand in A0,
572; the source register operand in A1 and a pointer to eflags in A2.
573;
574; @param 1 The instruction mnemonic.
575; @param 2 The modified flags.
576; @param 3 The undefined flags.
577;
578%macro IEMIMPL_UNARY_OP 3
579BEGINPROC iemAImpl_ %+ %1 %+ _u8
580 PROLOGUE_2_ARGS
581 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
582 %1 byte [A0]
583 IEM_SAVE_FLAGS A1, %2, %3
584 EPILOGUE_2_ARGS
585 ret
586ENDPROC iemAImpl_ %+ %1 %+ _u8
587
588BEGINPROC iemAImpl_ %+ %1 %+ _u8_locked
589 PROLOGUE_2_ARGS
590 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
591 lock %1 byte [A0]
592 IEM_SAVE_FLAGS A1, %2, %3
593 EPILOGUE_2_ARGS
594 ret
595ENDPROC iemAImpl_ %+ %1 %+ _u8_locked
596
597BEGINPROC iemAImpl_ %+ %1 %+ _u16
598 PROLOGUE_2_ARGS
599 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
600 %1 word [A0]
601 IEM_SAVE_FLAGS A1, %2, %3
602 EPILOGUE_2_ARGS
603 ret
604ENDPROC iemAImpl_ %+ %1 %+ _u16
605
606BEGINPROC iemAImpl_ %+ %1 %+ _u16_locked
607 PROLOGUE_2_ARGS
608 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
609 lock %1 word [A0]
610 IEM_SAVE_FLAGS A1, %2, %3
611 EPILOGUE_2_ARGS
612 ret
613ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
614
615BEGINPROC iemAImpl_ %+ %1 %+ _u32
616 PROLOGUE_2_ARGS
617 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
618 %1 dword [A0]
619 IEM_SAVE_FLAGS A1, %2, %3
620 EPILOGUE_2_ARGS
621 ret
622ENDPROC iemAImpl_ %+ %1 %+ _u32
623
624BEGINPROC iemAImpl_ %+ %1 %+ _u32_locked
625 PROLOGUE_2_ARGS
626 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
627 lock %1 dword [A0]
628 IEM_SAVE_FLAGS A1, %2, %3
629 EPILOGUE_2_ARGS
630 ret
631ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
632
633 %ifdef RT_ARCH_AMD64
634BEGINPROC iemAImpl_ %+ %1 %+ _u64
635 PROLOGUE_2_ARGS
636 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
637 %1 qword [A0]
638 IEM_SAVE_FLAGS A1, %2, %3
639 EPILOGUE_2_ARGS
640 ret
641ENDPROC iemAImpl_ %+ %1 %+ _u64
642
643BEGINPROC iemAImpl_ %+ %1 %+ _u64_locked
644 PROLOGUE_2_ARGS
645 IEM_MAYBE_LOAD_FLAGS A1, %2, %3
646 lock %1 qword [A0]
647 IEM_SAVE_FLAGS A1, %2, %3
648 EPILOGUE_2_ARGS
649 ret
650ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
651 %else
652 ; stub them for now.
653BEGINPROC iemAImpl_ %+ %1 %+ _u64
654 int3
655 ret
656ENDPROC iemAImpl_ %+ %1 %+ _u64
657BEGINPROC iemAImpl_ %+ %1 %+ _u64_locked
658 int3
659 ret
660ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
661 %endif
662
663%endmacro
664
665IEMIMPL_UNARY_OP inc, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), 0
666IEMIMPL_UNARY_OP dec, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), 0
667IEMIMPL_UNARY_OP neg, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
668IEMIMPL_UNARY_OP not, 0, 0
669
670
671
672;;
673; Macro for implementing a shift operation.
674;
675; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
676; 32-bit system where the 64-bit accesses requires hand coding.
677;
678; All the functions takes a pointer to the destination memory operand in A0,
679; the shift count in A1 and a pointer to eflags in A2.
680;
681; @param 1 The instruction mnemonic.
682; @param 2 The modified flags.
683; @param 3 The undefined flags.
684;
685; Makes ASSUMPTIONS about A0, A1 and A2 assignments.
686;
687%macro IEMIMPL_SHIFT_OP 3
688BEGINPROC iemAImpl_ %+ %1 %+ _u8
689 PROLOGUE_3_ARGS
690 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
691 %ifdef ASM_CALL64_GCC
692 mov cl, A1_8
693 %1 byte [A0], cl
694 %else
695 xchg A1, A0
696 %1 byte [A1], cl
697 %endif
698 IEM_SAVE_FLAGS A2, %2, %3
699 EPILOGUE_3_ARGS
700 ret
701ENDPROC iemAImpl_ %+ %1 %+ _u8
702
703BEGINPROC iemAImpl_ %+ %1 %+ _u16
704 PROLOGUE_3_ARGS
705 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
706 %ifdef ASM_CALL64_GCC
707 mov cl, A1_8
708 %1 word [A0], cl
709 %else
710 xchg A1, A0
711 %1 word [A1], cl
712 %endif
713 IEM_SAVE_FLAGS A2, %2, %3
714 EPILOGUE_3_ARGS
715 ret
716ENDPROC iemAImpl_ %+ %1 %+ _u16
717
718BEGINPROC iemAImpl_ %+ %1 %+ _u32
719 PROLOGUE_3_ARGS
720 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
721 %ifdef ASM_CALL64_GCC
722 mov cl, A1_8
723 %1 dword [A0], cl
724 %else
725 xchg A1, A0
726 %1 dword [A1], cl
727 %endif
728 IEM_SAVE_FLAGS A2, %2, %3
729 EPILOGUE_3_ARGS
730 ret
731ENDPROC iemAImpl_ %+ %1 %+ _u32
732
733 %ifdef RT_ARCH_AMD64
734BEGINPROC iemAImpl_ %+ %1 %+ _u64
735 PROLOGUE_3_ARGS
736 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
737 %ifdef ASM_CALL64_GCC
738 mov cl, A1_8
739 %1 qword [A0], cl
740 %else
741 xchg A1, A0
742 %1 qword [A1], cl
743 %endif
744 IEM_SAVE_FLAGS A2, %2, %3
745 EPILOGUE_3_ARGS
746 ret
747ENDPROC iemAImpl_ %+ %1 %+ _u64
748 %else ; stub it for now - later, replace with hand coded stuff.
749BEGINPROC iemAImpl_ %+ %1 %+ _u64
750 int3
751 ret
752ENDPROC iemAImpl_ %+ %1 %+ _u64
753 %endif ; !RT_ARCH_AMD64
754
755%endmacro
756
757IEMIMPL_SHIFT_OP rol, (X86_EFL_OF | X86_EFL_CF), 0
758IEMIMPL_SHIFT_OP ror, (X86_EFL_OF | X86_EFL_CF), 0
759IEMIMPL_SHIFT_OP rcl, (X86_EFL_OF | X86_EFL_CF), 0
760IEMIMPL_SHIFT_OP rcr, (X86_EFL_OF | X86_EFL_CF), 0
761IEMIMPL_SHIFT_OP shl, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
762IEMIMPL_SHIFT_OP shr, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
763IEMIMPL_SHIFT_OP sar, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
764
765
766;;
767; Macro for implementing a doulbe precision shift operation.
768;
769; This will generate code for the 16, 32 and 64 bit accesses, except on
770; 32-bit system where the 64-bit accesses requires hand coding.
771;
772; The functions takes the destination operand (r/m) in A0, the source (reg) in
773; A1, the shift count in A2 and a pointer to the eflags variable/register in A3.
774;
775; @param 1 The instruction mnemonic.
776; @param 2 The modified flags.
777; @param 3 The undefined flags.
778;
779; Makes ASSUMPTIONS about A0, A1, A2 and A3 assignments.
780;
781%macro IEMIMPL_SHIFT_DBL_OP 3
782BEGINPROC iemAImpl_ %+ %1 %+ _u16
783 PROLOGUE_4_ARGS
784 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
785 %ifdef ASM_CALL64_GCC
786 xchg A3, A2
787 %1 [A0], A1_16, cl
788 xchg A3, A2
789 %else
790 xchg A0, A2
791 %1 [A2], A1_16, cl
792 %endif
793 IEM_SAVE_FLAGS A3, %2, %3
794 EPILOGUE_4_ARGS
795 ret
796ENDPROC iemAImpl_ %+ %1 %+ _u16
797
798BEGINPROC iemAImpl_ %+ %1 %+ _u32
799 PROLOGUE_4_ARGS
800 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
801 %ifdef ASM_CALL64_GCC
802 xchg A3, A2
803 %1 [A0], A1_32, cl
804 xchg A3, A2
805 %else
806 xchg A0, A2
807 %1 [A2], A1_32, cl
808 %endif
809 IEM_SAVE_FLAGS A3, %2, %3
810 EPILOGUE_4_ARGS
811 ret
812ENDPROC iemAImpl_ %+ %1 %+ _u32
813
814 %ifdef RT_ARCH_AMD64
815BEGINPROC iemAImpl_ %+ %1 %+ _u64
816 PROLOGUE_4_ARGS
817 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
818 %ifdef ASM_CALL64_GCC
819 xchg A3, A2
820 %1 [A0], A1, cl
821 xchg A3, A2
822 %else
823 xchg A0, A2
824 %1 [A2], A1, cl
825 %endif
826 IEM_SAVE_FLAGS A3, %2, %3
827 EPILOGUE_4_ARGS
828 ret
829ENDPROC iemAImpl_ %+ %1 %+ _u64
830 %else ; stub it for now - later, replace with hand coded stuff.
831BEGINPROC iemAImpl_ %+ %1 %+ _u64
832 int3
833 ret
834ENDPROC iemAImpl_ %+ %1 %+ _u64
835 %endif ; !RT_ARCH_AMD64
836
837%endmacro
838
839IEMIMPL_SHIFT_DBL_OP shld, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
840IEMIMPL_SHIFT_DBL_OP shrd, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
841
842
843;;
844; Macro for implementing a multiplication operations.
845;
846; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
847; 32-bit system where the 64-bit accesses requires hand coding.
848;
849; The 8-bit function only operates on AX, so it takes no DX pointer. The other
850; functions takes a pointer to rAX in A0, rDX in A1, the operand in A2 and a
851; pointer to eflags in A3.
852;
853; The functions all return 0 so the caller can be used for div/idiv as well as
854; for the mul/imul implementation.
855;
856; @param 1 The instruction mnemonic.
857; @param 2 The modified flags.
858; @param 3 The undefined flags.
859;
860; Makes ASSUMPTIONS about A0, A1, A2, A3, T0 and T1 assignments.
861;
862%macro IEMIMPL_MUL_OP 3
863BEGINPROC iemAImpl_ %+ %1 %+ _u8
864 PROLOGUE_3_ARGS
865 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
866 mov al, [A0]
867 %1 A1_8
868 mov [A0], ax
869 IEM_SAVE_FLAGS A2, %2, %3
870 EPILOGUE_3_ARGS
871 xor eax, eax
872 ret
873ENDPROC iemAImpl_ %+ %1 %+ _u8
874
875BEGINPROC iemAImpl_ %+ %1 %+ _u16
876 PROLOGUE_4_ARGS
877 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
878 mov ax, [A0]
879 %ifdef ASM_CALL64_GCC
880 %1 A2_16
881 mov [A0], ax
882 mov [A1], dx
883 %else
884 mov T1, A1
885 %1 A2_16
886 mov [A0], ax
887 mov [T1], dx
888 %endif
889 IEM_SAVE_FLAGS A3, %2, %3
890 EPILOGUE_4_ARGS
891 xor eax, eax
892 ret
893ENDPROC iemAImpl_ %+ %1 %+ _u16
894
895BEGINPROC iemAImpl_ %+ %1 %+ _u32
896 PROLOGUE_4_ARGS
897 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
898 mov eax, [A0]
899 %ifdef ASM_CALL64_GCC
900 %1 A2_32
901 mov [A0], eax
902 mov [A1], edx
903 %else
904 mov T1, A1
905 %1 A2_32
906 mov [A0], eax
907 mov [T1], edx
908 %endif
909 IEM_SAVE_FLAGS A3, %2, %3
910 EPILOGUE_4_ARGS
911 xor eax, eax
912 ret
913ENDPROC iemAImpl_ %+ %1 %+ _u32
914
915 %ifdef RT_ARCH_AMD64
916BEGINPROC iemAImpl_ %+ %1 %+ _u64
917 PROLOGUE_4_ARGS
918 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
919 mov rax, [A0]
920 %ifdef ASM_CALL64_GCC
921 %1 A2
922 mov [A0], rax
923 mov [A1], rdx
924 %else
925 mov T1, A1
926 %1 A2
927 mov [A0], rax
928 mov [T1], rdx
929 %endif
930 IEM_SAVE_FLAGS A3, %2, %3
931 EPILOGUE_4_ARGS
932 xor eax, eax
933 ret
934ENDPROC iemAImpl_ %+ %1 %+ _u64
935 %else ; stub it for now - later, replace with hand coded stuff.
936BEGINPROC iemAImpl_ %+ %1 %+ _u64
937 int3
938 ret
939ENDPROC iemAImpl_ %+ %1 %+ _u64
940 %endif ; !RT_ARCH_AMD64
941
942%endmacro
943
944IEMIMPL_MUL_OP mul, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
945IEMIMPL_MUL_OP imul, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
946
947
948;;
949; Macro for implementing a division operations.
950;
951; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
952; 32-bit system where the 64-bit accesses requires hand coding.
953;
954; The 8-bit function only operates on AX, so it takes no DX pointer. The other
955; functions takes a pointer to rAX in A0, rDX in A1, the operand in A2 and a
956; pointer to eflags in A3.
957;
958; The functions all return 0 on success and -1 if a divide error should be
959; raised by the caller.
960;
961; @param 1 The instruction mnemonic.
962; @param 2 The modified flags.
963; @param 3 The undefined flags.
964;
965; Makes ASSUMPTIONS about A0, A1, A2, A3, T0 and T1 assignments.
966;
967%macro IEMIMPL_DIV_OP 3
968BEGINPROC iemAImpl_ %+ %1 %+ _u8
969 PROLOGUE_3_ARGS
970
971 test A1_8, A1_8
972 jz .div_zero
973 ;; @todo test for overflow
974
975 IEM_MAYBE_LOAD_FLAGS A2, %2, %3
976 mov ax, [A0]
977 %1 A1_8
978 mov [A0], ax
979 IEM_SAVE_FLAGS A2, %2, %3
980 xor eax, eax
981
982.return:
983 EPILOGUE_3_ARGS
984 ret
985.div_zero:
986 mov eax, -1
987 jmp .return
988ENDPROC iemAImpl_ %+ %1 %+ _u8
989
990BEGINPROC iemAImpl_ %+ %1 %+ _u16
991 PROLOGUE_4_ARGS
992
993 test A1_16, A1_16
994 jz .div_zero
995 ;; @todo test for overflow
996
997 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
998 %ifdef ASM_CALL64_GCC
999 mov T1, A2
1000 mov ax, [A0]
1001 mov dx, [A1]
1002 %1 T1_16
1003 mov [A0], ax
1004 mov [A1], dx
1005 %else
1006 mov T1, A1
1007 mov ax, [A0]
1008 mov dx, [T1]
1009 %1 A2_16
1010 mov [A0], ax
1011 mov [T1], dx
1012 %endif
1013 IEM_SAVE_FLAGS A3, %2, %3
1014 xor eax, eax
1015
1016.return:
1017 EPILOGUE_4_ARGS
1018 ret
1019.div_zero:
1020 mov eax, -1
1021 jmp .return
1022ENDPROC iemAImpl_ %+ %1 %+ _u16
1023
1024BEGINPROC iemAImpl_ %+ %1 %+ _u32
1025 PROLOGUE_4_ARGS
1026
1027 test A1_32, A1_32
1028 jz .div_zero
1029 ;; @todo test for overflow
1030
1031 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1032 mov eax, [A0]
1033 %ifdef ASM_CALL64_GCC
1034 mov T1, A2
1035 mov eax, [A0]
1036 mov edx, [A1]
1037 %1 T1_32
1038 mov [A0], eax
1039 mov [A1], edx
1040 %else
1041 mov T1, A1
1042 mov eax, [A0]
1043 mov edx, [T1]
1044 %1 A2_32
1045 mov [A0], eax
1046 mov [T1], edx
1047 %endif
1048 IEM_SAVE_FLAGS A3, %2, %3
1049 xor eax, eax
1050
1051.return:
1052 EPILOGUE_4_ARGS
1053 ret
1054.div_zero:
1055 mov eax, -1
1056 jmp .return
1057ENDPROC iemAImpl_ %+ %1 %+ _u32
1058
1059 %ifdef RT_ARCH_AMD64
1060BEGINPROC iemAImpl_ %+ %1 %+ _u64
1061 PROLOGUE_4_ARGS
1062
1063 test A1, A1
1064 jz .div_zero
1065 ;; @todo test for overflow
1066
1067 IEM_MAYBE_LOAD_FLAGS A3, %2, %3
1068 mov rax, [A0]
1069 %ifdef ASM_CALL64_GCC
1070 mov T1, A2
1071 mov rax, [A0]
1072 mov rdx, [A1]
1073 %1 T1
1074 mov [A0], rax
1075 mov [A1], rdx
1076 %else
1077 mov T1, A1
1078 mov rax, [A0]
1079 mov rdx, [T1]
1080 %1 A2
1081 mov [A0], rax
1082 mov [T1], rdx
1083 %endif
1084 IEM_SAVE_FLAGS A3, %2, %3
1085 xor eax, eax
1086
1087.return:
1088 EPILOGUE_4_ARGS
1089 ret
1090.div_zero:
1091 mov eax, -1
1092 jmp .return
1093ENDPROC iemAImpl_ %+ %1 %+ _u64
1094 %else ; stub it for now - later, replace with hand coded stuff.
1095BEGINPROC iemAImpl_ %+ %1 %+ _u64
1096 int3
1097 ret
1098ENDPROC iemAImpl_ %+ %1 %+ _u64
1099 %endif ; !RT_ARCH_AMD64
1100
1101%endmacro
1102
1103IEMIMPL_DIV_OP div, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
1104IEMIMPL_DIV_OP idiv, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
1105
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