VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/EMAllA.asm@ 18215

Last change on this file since 18215 was 15420, checked in by vboxsync, 16 years ago

EMAll: ADD, ADC and SUB - the first is used a bit by windows.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 40.0 KB
Line 
1; $Id: EMAllA.asm 15420 2008-12-13 07:21:55Z vboxsync $
2;; @file
3; EM Assembly Routines.
4;
5
6;
7; Copyright (C) 2006-2007 Sun Microsystems, Inc.
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18; Clara, CA 95054 USA or visit http://www.sun.com if you need
19; additional information or have any questions.
20;
21
22;*******************************************************************************
23;* Header Files *
24;*******************************************************************************
25%include "VBox/asmdefs.mac"
26%include "VBox/err.mac"
27%include "VBox/x86.mac"
28
29;; @def MY_PTR_REG
30; The register we use for value pointers (And,Or,Dec,Inc).
31%ifdef RT_ARCH_AMD64
32 %define MY_PTR_REG rcx
33%else
34 %define MY_PTR_REG ecx
35%endif
36
37;; @def MY_RET_REG
38; The register we return the result in.
39%ifdef RT_ARCH_AMD64
40 %define MY_RET_REG rax
41%else
42 %define MY_RET_REG eax
43%endif
44
45;; @def RT_ARCH_AMD64
46; Indicator for whether we can deal with 8 byte operatands. (Darwin fun again.)
47%ifdef RT_ARCH_AMD64
48 %define CAN_DO_8_BYTE_OP 1
49%endif
50%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
51 %define CAN_DO_8_BYTE_OP 1
52 %define MY_PTR_REG64 rcx
53%endif
54
55
56;*******************************************************************************
57;* External Symbols *
58;*******************************************************************************
59%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
60extern NAME(SUPR0Abs64bitKernelCS)
61extern NAME(SUPR0AbsKernelCS)
62%endif
63
64
65BEGINCODE
66
67
68;;
69; Emulate CMP instruction, CDECL calling conv.
70; VMMDECL(uint32_t) EMEmulateCmp(uint32_t u32Param1, uint64_t u64Param2, size_t cb);
71;
72; @returns EFLAGS after the operation, only arithmetic flags are valid.
73; @param [esp + 04h] rdi rcx Param 1 - First parameter (Dst).
74; @param [esp + 08h] rsi edx Param 2 - Second parameter (Src).
75; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
76;
77align 16
78BEGINPROC EMEmulateCmp
79%ifdef RT_ARCH_AMD64
80%ifdef RT_OS_WINDOWS
81 mov rax, r8 ; eax = size of parameters
82%else ; !RT_OS_WINDOWS
83 mov rax, rdx ; rax = size of parameters
84 mov rcx, rdi ; rcx = first parameter
85 mov rdx, rsi ; rdx = second parameter
86%endif ; !RT_OS_WINDOWS
87%else ; !RT_ARCH_AMD64
88 mov eax, [esp + 10h] ; eax = size of parameters
89 mov ecx, [esp + 04h] ; ecx = first parameter
90 mov edx, [esp + 08h] ; edx = second parameter
91%endif
92
93 ; switch on size
94%ifdef RT_ARCH_AMD64
95 cmp al, 8
96 je short .do_qword ; 8 bytes variant
97%endif
98 cmp al, 4
99 je short .do_dword ; 4 bytes variant
100 cmp al, 2
101 je short .do_word ; 2 byte variant
102 cmp al, 1
103 je short .do_byte ; 1 bytes variant
104 int3
105
106 ; workers
107%ifdef RT_ARCH_AMD64
108.do_qword:
109 cmp rcx, rdx ; do 8 bytes CMP
110 jmp short .done
111%endif
112
113.do_dword:
114 cmp ecx, edx ; do 4 bytes CMP
115 jmp short .done
116
117.do_word:
118 cmp cx, dx ; do 2 bytes CMP
119 jmp short .done
120
121.do_byte:
122 cmp cl, dl ; do 1 byte CMP
123
124 ; collect flags and return.
125.done:
126 pushf
127 pop MY_RET_REG
128 retn
129ENDPROC EMEmulateCmp
130
131
132;;
133; Emulate AND instruction, CDECL calling conv.
134; VMMDECL(uint32_t) EMEmulateAnd(void *pvParam1, uint64_t u64Param2, size_t cb);
135;
136; @returns EFLAGS after the operation, only arithmetic flags are valid.
137; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
138; @param [esp + 08h] Param 2 - Second parameter.
139; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
140; @uses eax, ecx, edx
141;
142align 16
143BEGINPROC EMEmulateAnd
144%ifdef RT_ARCH_AMD64
145%ifdef RT_OS_WINDOWS
146 mov rax, r8 ; eax = size of parameters
147%else ; !RT_OS_WINDOWS
148 mov rax, rdx ; rax = size of parameters
149 mov rcx, rdi ; rcx = first parameter
150 mov rdx, rsi ; rdx = second parameter
151%endif ; !RT_OS_WINDOWS
152%else ; !RT_ARCH_AMD64
153 mov eax, [esp + 10h] ; eax = size of parameters
154 mov ecx, [esp + 04h] ; ecx = first parameter
155 mov edx, [esp + 08h] ; edx = second parameter
156%endif
157
158 ; switch on size
159%ifdef CAN_DO_8_BYTE_OP
160 cmp al, 8
161 je short .do_qword ; 8 bytes variant
162%endif
163 cmp al, 4
164 je short .do_dword ; 4 bytes variant
165 cmp al, 2
166 je short .do_word ; 2 byte variant
167 cmp al, 1
168 je short .do_byte ; 1 bytes variant
169 int3
170
171 ; workers
172%ifdef RT_ARCH_AMD64
173.do_qword:
174 and [MY_PTR_REG], rdx ; do 8 bytes AND
175 jmp short .done
176%endif
177
178.do_dword:
179 and [MY_PTR_REG], edx ; do 4 bytes AND
180 jmp short .done
181
182.do_word:
183 and [MY_PTR_REG], dx ; do 2 bytes AND
184 jmp short .done
185
186.do_byte:
187 and [MY_PTR_REG], dl ; do 1 byte AND
188
189 ; collect flags and return.
190.done:
191 pushf
192 pop MY_RET_REG
193 retn
194
195%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
196.do_qword:
197 db 0xea ; jmp far .sixtyfourbit_mode
198 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
199BITS 64
200.sixtyfourbit_mode:
201 and esp, 0ffffffffh
202 and MY_PTR_REG, 0ffffffffh
203 mov rdx, qword [rsp + 08h] ; rdx = second parameter
204 and [MY_PTR_REG64], rdx ; do 8 bytes AND
205 jmp far [.fpret wrt rip]
206.fpret: ; 16:32 Pointer to .done.
207 dd .done, NAME(SUPR0AbsKernelCS)
208BITS 32
209%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
210ENDPROC EMEmulateAnd
211
212
213;;
214; Emulate OR instruction, CDECL calling conv.
215; VMMDECL(uint32_t) EMEmulateOr(void *pvParam1, uint64_t u64Param2, size_t cb);
216;
217; @returns EFLAGS after the operation, only arithmetic flags are valid.
218; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
219; @param [esp + 08h] Param 2 - Second parameter.
220; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
221; @uses eax, ecx, edx
222;
223align 16
224BEGINPROC EMEmulateOr
225%ifdef RT_ARCH_AMD64
226%ifdef RT_OS_WINDOWS
227 mov rax, r8 ; eax = size of parameters
228%else ; !RT_OS_WINDOWS
229 mov rax, rdx ; rax = size of parameters
230 mov rcx, rdi ; rcx = first parameter
231 mov rdx, rsi ; rdx = second parameter
232%endif ; !RT_OS_WINDOWS
233%else ; !RT_ARCH_AMD64
234 mov eax, [esp + 10h] ; eax = size of parameters
235 mov ecx, [esp + 04h] ; ecx = first parameter
236 mov edx, [esp + 08h] ; edx = second parameter
237%endif
238
239 ; switch on size
240%ifdef CAN_DO_8_BYTE_OP
241 cmp al, 8
242 je short .do_qword ; 8 bytes variant
243%endif
244 cmp al, 4
245 je short .do_dword ; 4 bytes variant
246 cmp al, 2
247 je short .do_word ; 2 byte variant
248 cmp al, 1
249 je short .do_byte ; 1 bytes variant
250 int3
251
252 ; workers
253%ifdef RT_ARCH_AMD64
254.do_qword:
255 or [MY_PTR_REG], rdx ; do 8 bytes OR
256 jmp short .done
257%endif
258
259.do_dword:
260 or [MY_PTR_REG], edx ; do 4 bytes OR
261 jmp short .done
262
263.do_word:
264 or [MY_PTR_REG], dx ; do 2 bytes OR
265 jmp short .done
266
267.do_byte:
268 or [MY_PTR_REG], dl ; do 1 byte OR
269
270 ; collect flags and return.
271.done:
272 pushf
273 pop MY_RET_REG
274 retn
275
276%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
277.do_qword:
278 db 0xea ; jmp far .sixtyfourbit_mode
279 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
280BITS 64
281.sixtyfourbit_mode:
282 and esp, 0ffffffffh
283 and MY_PTR_REG, 0ffffffffh
284 mov rdx, qword [rsp + 08h] ; rdx = second parameter
285 or [MY_PTR_REG64], rdx ; do 8 bytes OR
286 jmp far [.fpret wrt rip]
287.fpret: ; 16:32 Pointer to .done.
288 dd .done, NAME(SUPR0AbsKernelCS)
289BITS 32
290%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
291ENDPROC EMEmulateOr
292
293
294;;
295; Emulate LOCK OR instruction.
296; VMMDECL(int) EMEmulateLockOr(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
297;
298; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
299; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
300; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value.
301; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Size of the operation - 1, 2, 4 or 8 bytes.
302; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Where to store the eflags on success.
303; only arithmetic flags are valid.
304align 16
305BEGINPROC EMEmulateLockOr
306%ifdef RT_ARCH_AMD64
307%ifdef RT_OS_WINDOWS
308 mov rax, r8 ; eax = size of parameters
309%else ; !RT_OS_WINDOWS
310 mov rax, rdx ; rax = size of parameters
311 mov rcx, rdi ; rcx = first parameter
312 mov rdx, rsi ; rdx = second parameter
313%endif ; !RT_OS_WINDOWS
314%else ; !RT_ARCH_AMD64
315 mov eax, [esp + 10h] ; eax = size of parameters
316 mov ecx, [esp + 04h] ; ecx = first parameter (MY_PTR_REG)
317 mov edx, [esp + 08h] ; edx = second parameter
318%endif
319
320 ; switch on size
321%ifdef CAN_DO_8_BYTE_OP
322 cmp al, 8
323 je short .do_qword ; 8 bytes variant
324%endif
325 cmp al, 4
326 je short .do_dword ; 4 bytes variant
327 cmp al, 2
328 je short .do_word ; 2 byte variant
329 cmp al, 1
330 je short .do_byte ; 1 bytes variant
331 int3
332
333 ; workers
334%ifdef RT_ARCH_AMD64
335.do_qword:
336 lock or [MY_PTR_REG], rdx ; do 8 bytes OR
337 jmp short .done
338%endif
339
340.do_dword:
341 lock or [MY_PTR_REG], edx ; do 4 bytes OR
342 jmp short .done
343
344.do_word:
345 lock or [MY_PTR_REG], dx ; do 2 bytes OR
346 jmp short .done
347
348.do_byte:
349 lock or [MY_PTR_REG], dl ; do 1 byte OR
350
351 ; collect flags and return.
352.done:
353 pushf
354%ifdef RT_ARCH_AMD64
355 pop rax
356 %ifdef RT_OS_WINDOWS
357 mov [r9], eax
358 %else ; !RT_OS_WINDOWS
359 mov [rcx], eax
360 %endif ; !RT_OS_WINDOWS
361%else ; !RT_ARCH_AMD64
362 mov eax, [esp + 14h + 4]
363 pop dword [eax]
364%endif
365 mov eax, VINF_SUCCESS
366 retn
367
368%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
369.do_qword:
370 db 0xea ; jmp far .sixtyfourbit_mode
371 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
372BITS 64
373.sixtyfourbit_mode:
374 and esp, 0ffffffffh
375 and MY_PTR_REG, 0ffffffffh
376 mov rdx, qword [rsp + 08h] ; rdx = second parameter
377 lock or [MY_PTR_REG64], rdx ; do 8 bytes OR
378 jmp far [.fpret wrt rip]
379.fpret: ; 16:32 Pointer to .done.
380 dd .done, NAME(SUPR0AbsKernelCS)
381BITS 32
382%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
383
384
385%ifdef IN_RC
386; #PF resume point.
387GLOBALNAME EMEmulateLockOr_Error
388 mov eax, VERR_ACCESS_DENIED
389 ret
390%endif
391
392ENDPROC EMEmulateLockOr
393
394
395;;
396; Emulate XOR instruction, CDECL calling conv.
397; VMMDECL(uint32_t) EMEmulateXor(void *pvParam1, uint64_t u64Param2, size_t cb);
398;
399; @returns EFLAGS after the operation, only arithmetic flags are valid.
400; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
401; @param [esp + 08h] Param 2 - Second parameter.
402; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
403; @uses eax, ecx, edx
404;
405align 16
406BEGINPROC EMEmulateXor
407%ifdef RT_ARCH_AMD64
408%ifdef RT_OS_WINDOWS
409 mov rax, r8 ; eax = size of parameters
410%else ; !RT_OS_WINDOWS
411 mov rax, rdx ; rax = size of parameters
412 mov rcx, rdi ; rcx = first parameter
413 mov rdx, rsi ; rdx = second parameter
414%endif ; !RT_OS_WINDOWS
415%else ; !RT_ARCH_AMD64
416 mov eax, [esp + 10h] ; eax = size of parameters
417 mov ecx, [esp + 04h] ; ecx = first parameter
418 mov edx, [esp + 08h] ; edx = second parameter
419%endif
420
421 ; switch on size
422%ifdef CAN_DO_8_BYTE_OP
423 cmp al, 8
424 je short .do_qword ; 8 bytes variant
425%endif
426 cmp al, 4
427 je short .do_dword ; 4 bytes variant
428 cmp al, 2
429 je short .do_word ; 2 byte variant
430 cmp al, 1
431 je short .do_byte ; 1 bytes variant
432 int3
433
434 ; workers
435%ifdef RT_ARCH_AMD64
436.do_qword:
437 xor [MY_PTR_REG], rdx ; do 8 bytes XOR
438 jmp short .done
439%endif
440
441.do_dword:
442 xor [MY_PTR_REG], edx ; do 4 bytes XOR
443 jmp short .done
444
445.do_word:
446 xor [MY_PTR_REG], dx ; do 2 bytes XOR
447 jmp short .done
448
449.do_byte:
450 xor [MY_PTR_REG], dl ; do 1 byte XOR
451
452 ; collect flags and return.
453.done:
454 pushf
455 pop MY_RET_REG
456 retn
457
458%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
459.do_qword:
460 db 0xea ; jmp far .sixtyfourbit_mode
461 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
462BITS 64
463.sixtyfourbit_mode:
464 and esp, 0ffffffffh
465 and MY_PTR_REG, 0ffffffffh
466 mov rdx, qword [rsp + 08h] ; rdx = second parameter
467 xor [MY_PTR_REG64], rdx ; do 8 bytes XOR
468 jmp far [.fpret wrt rip]
469.fpret: ; 16:32 Pointer to .done.
470 dd .done, NAME(SUPR0AbsKernelCS)
471BITS 32
472%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
473ENDPROC EMEmulateXor
474
475
476;;
477; Emulate INC instruction, CDECL calling conv.
478; VMMDECL(uint32_t) EMEmulateInc(void *pvParam1, size_t cb);
479;
480; @returns EFLAGS after the operation, only arithmetic flags are valid.
481; @param [esp + 04h] rdi rcx Param 1 - First parameter - pointer to data item.
482; @param [esp + 08h] rsi rdx Param 2 - Size of parameters, only 1/2/4 is valid.
483; @uses eax, ecx, edx
484;
485align 16
486BEGINPROC EMEmulateInc
487%ifdef RT_ARCH_AMD64
488%ifdef RT_OS_WINDOWS
489 mov rax, rdx ; eax = size of parameters
490%else ; !RT_OS_WINDOWS
491 mov rax, rsi ; eax = size of parameters
492 mov rcx, rdi ; rcx = first parameter
493%endif ; !RT_OS_WINDOWS
494%else ; !RT_ARCH_AMD64
495 mov eax, [esp + 08h] ; eax = size of parameters
496 mov ecx, [esp + 04h] ; ecx = first parameter
497%endif
498
499 ; switch on size
500%ifdef RT_ARCH_AMD64
501 cmp al, 8
502 je short .do_qword ; 8 bytes variant
503%endif
504 cmp al, 4
505 je short .do_dword ; 4 bytes variant
506 cmp al, 2
507 je short .do_word ; 2 byte variant
508 cmp al, 1
509 je short .do_byte ; 1 bytes variant
510 int3
511
512 ; workers
513%ifdef RT_ARCH_AMD64
514.do_qword:
515 inc qword [MY_PTR_REG] ; do 8 bytes INC
516 jmp short .done
517%endif
518
519.do_dword:
520 inc dword [MY_PTR_REG] ; do 4 bytes INC
521 jmp short .done
522
523.do_word:
524 inc word [MY_PTR_REG] ; do 2 bytes INC
525 jmp short .done
526
527.do_byte:
528 inc byte [MY_PTR_REG] ; do 1 byte INC
529 jmp short .done
530
531 ; collect flags and return.
532.done:
533 pushf
534 pop MY_RET_REG
535 retn
536ENDPROC EMEmulateInc
537
538
539;;
540; Emulate DEC instruction, CDECL calling conv.
541; VMMDECL(uint32_t) EMEmulateDec(void *pvParam1, size_t cb);
542;
543; @returns EFLAGS after the operation, only arithmetic flags are valid.
544; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
545; @param [esp + 08h] Param 2 - Size of parameters, only 1/2/4 is valid.
546; @uses eax, ecx, edx
547;
548align 16
549BEGINPROC EMEmulateDec
550%ifdef RT_ARCH_AMD64
551%ifdef RT_OS_WINDOWS
552 mov rax, rdx ; eax = size of parameters
553%else ; !RT_OS_WINDOWS
554 mov rax, rsi ; eax = size of parameters
555 mov rcx, rdi ; rcx = first parameter
556%endif ; !RT_OS_WINDOWS
557%else ; !RT_ARCH_AMD64
558 mov eax, [esp + 08h] ; eax = size of parameters
559 mov ecx, [esp + 04h] ; ecx = first parameter
560%endif
561
562 ; switch on size
563%ifdef RT_ARCH_AMD64
564 cmp al, 8
565 je short .do_qword ; 8 bytes variant
566%endif
567 cmp al, 4
568 je short .do_dword ; 4 bytes variant
569 cmp al, 2
570 je short .do_word ; 2 byte variant
571 cmp al, 1
572 je short .do_byte ; 1 bytes variant
573 int3
574
575 ; workers
576%ifdef RT_ARCH_AMD64
577.do_qword:
578 dec qword [MY_PTR_REG] ; do 8 bytes DEC
579 jmp short .done
580%endif
581
582.do_dword:
583 dec dword [MY_PTR_REG] ; do 4 bytes DEC
584 jmp short .done
585
586.do_word:
587 dec word [MY_PTR_REG] ; do 2 bytes DEC
588 jmp short .done
589
590.do_byte:
591 dec byte [MY_PTR_REG] ; do 1 byte DEC
592 jmp short .done
593
594 ; collect flags and return.
595.done:
596 pushf
597 pop MY_RET_REG
598 retn
599ENDPROC EMEmulateDec
600
601
602;;
603; Emulate ADD instruction, CDECL calling conv.
604; VMMDECL(uint32_t) EMEmulateAdd(void *pvParam1, uint64_t u64Param2, size_t cb);
605;
606; @returns EFLAGS after the operation, only arithmetic flags are valid.
607; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
608; @param [esp + 08h] Param 2 - Second parameter.
609; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
610; @uses eax, ecx, edx
611;
612align 16
613BEGINPROC EMEmulateAdd
614%ifdef RT_ARCH_AMD64
615%ifdef RT_OS_WINDOWS
616 mov rax, r8 ; eax = size of parameters
617%else ; !RT_OS_WINDOWS
618 mov rax, rdx ; rax = size of parameters
619 mov rcx, rdi ; rcx = first parameter
620 mov rdx, rsi ; rdx = second parameter
621%endif ; !RT_OS_WINDOWS
622%else ; !RT_ARCH_AMD64
623 mov eax, [esp + 10h] ; eax = size of parameters
624 mov ecx, [esp + 04h] ; ecx = first parameter
625 mov edx, [esp + 08h] ; edx = second parameter
626%endif
627
628 ; switch on size
629%ifdef CAN_DO_8_BYTE_OP
630 cmp al, 8
631 je short .do_qword ; 8 bytes variant
632%endif
633 cmp al, 4
634 je short .do_dword ; 4 bytes variant
635 cmp al, 2
636 je short .do_word ; 2 byte variant
637 cmp al, 1
638 je short .do_byte ; 1 bytes variant
639 int3
640
641 ; workers
642%ifdef RT_ARCH_AMD64
643.do_qword:
644 add [MY_PTR_REG], rdx ; do 8 bytes ADD
645 jmp short .done
646%endif
647
648.do_dword:
649 add [MY_PTR_REG], edx ; do 4 bytes ADD
650 jmp short .done
651
652.do_word:
653 add [MY_PTR_REG], dx ; do 2 bytes ADD
654 jmp short .done
655
656.do_byte:
657 add [MY_PTR_REG], dl ; do 1 byte ADD
658
659 ; collect flags and return.
660.done:
661 pushf
662 pop MY_RET_REG
663 retn
664
665%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
666.do_qword:
667 db 0xea ; jmp far .sixtyfourbit_mode
668 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
669BITS 64
670.sixtyfourbit_mode:
671 and esp, 0ffffffffh
672 and MY_PTR_REG, 0ffffffffh
673 mov rdx, qword [rsp + 08h] ; rdx = second parameter
674 add [MY_PTR_REG64], rdx ; do 8 bytes ADD
675 jmp far [.fpret wrt rip]
676.fpret: ; 16:32 Pointer to .done.
677 dd .done, NAME(SUPR0AbsKernelCS)
678BITS 32
679%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
680ENDPROC EMEmulateAdd
681
682
683;;
684; Emulate ADC instruction, CDECL calling conv.
685; VMMDECL(uint32_t) EMEmulateAdcWithCarrySet(void *pvParam1, uint64_t u64Param2, size_t cb);
686;
687; @returns EFLAGS after the operation, only arithmetic flags are valid.
688; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
689; @param [esp + 08h] Param 2 - Second parameter.
690; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
691; @uses eax, ecx, edx
692;
693align 16
694BEGINPROC EMEmulateAdcWithCarrySet
695%ifdef RT_ARCH_AMD64
696%ifdef RT_OS_WINDOWS
697 mov rax, r8 ; eax = size of parameters
698%else ; !RT_OS_WINDOWS
699 mov rax, rdx ; rax = size of parameters
700 mov rcx, rdi ; rcx = first parameter
701 mov rdx, rsi ; rdx = second parameter
702%endif ; !RT_OS_WINDOWS
703%else ; !RT_ARCH_AMD64
704 mov eax, [esp + 10h] ; eax = size of parameters
705 mov ecx, [esp + 04h] ; ecx = first parameter
706 mov edx, [esp + 08h] ; edx = second parameter
707%endif
708
709 ; switch on size
710%ifdef CAN_DO_8_BYTE_OP
711 cmp al, 8
712 je short .do_qword ; 8 bytes variant
713%endif
714 cmp al, 4
715 je short .do_dword ; 4 bytes variant
716 cmp al, 2
717 je short .do_word ; 2 byte variant
718 cmp al, 1
719 je short .do_byte ; 1 bytes variant
720 int3
721
722 ; workers
723%ifdef RT_ARCH_AMD64
724.do_qword:
725 stc ; set carry flag
726 adc [MY_PTR_REG], rdx ; do 8 bytes ADC
727 jmp short .done
728%endif
729
730.do_dword:
731 stc ; set carry flag
732 adc [MY_PTR_REG], edx ; do 4 bytes ADC
733 jmp short .done
734
735.do_word:
736 stc ; set carry flag
737 adc [MY_PTR_REG], dx ; do 2 bytes ADC
738 jmp short .done
739
740.do_byte:
741 stc ; set carry flag
742 adc [MY_PTR_REG], dl ; do 1 byte ADC
743
744 ; collect flags and return.
745.done:
746 pushf
747 pop MY_RET_REG
748 retn
749
750%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
751.do_qword:
752 db 0xea ; jmp far .sixtyfourbit_mode
753 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
754BITS 64
755.sixtyfourbit_mode:
756 and esp, 0ffffffffh
757 and MY_PTR_REG, 0ffffffffh
758 mov rdx, qword [rsp + 08h] ; rdx = second parameter
759 stc ; set carry flag
760 adc [MY_PTR_REG64], rdx ; do 8 bytes ADC
761 jmp far [.fpret wrt rip]
762.fpret: ; 16:32 Pointer to .done.
763 dd .done, NAME(SUPR0AbsKernelCS)
764BITS 32
765%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
766ENDPROC EMEmulateAdcWithCarrySet
767
768
769;;
770; Emulate SUB instruction, CDECL calling conv.
771; VMMDECL(uint32_t) EMEmulateSub(void *pvParam1, uint64_t u64Param2, size_t cb);
772;
773; @returns EFLAGS after the operation, only arithmetic flags are valid.
774; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
775; @param [esp + 08h] Param 2 - Second parameter.
776; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
777; @uses eax, ecx, edx
778;
779align 16
780BEGINPROC EMEmulateSub
781%ifdef RT_ARCH_AMD64
782%ifdef RT_OS_WINDOWS
783 mov rax, r8 ; eax = size of parameters
784%else ; !RT_OS_WINDOWS
785 mov rax, rdx ; rax = size of parameters
786 mov rcx, rdi ; rcx = first parameter
787 mov rdx, rsi ; rdx = second parameter
788%endif ; !RT_OS_WINDOWS
789%else ; !RT_ARCH_AMD64
790 mov eax, [esp + 10h] ; eax = size of parameters
791 mov ecx, [esp + 04h] ; ecx = first parameter
792 mov edx, [esp + 08h] ; edx = second parameter
793%endif
794
795 ; switch on size
796%ifdef CAN_DO_8_BYTE_OP
797 cmp al, 8
798 je short .do_qword ; 8 bytes variant
799%endif
800 cmp al, 4
801 je short .do_dword ; 4 bytes variant
802 cmp al, 2
803 je short .do_word ; 2 byte variant
804 cmp al, 1
805 je short .do_byte ; 1 bytes variant
806 int3
807
808 ; workers
809%ifdef RT_ARCH_AMD64
810.do_qword:
811 sub [MY_PTR_REG], rdx ; do 8 bytes SUB
812 jmp short .done
813%endif
814
815.do_dword:
816 sub [MY_PTR_REG], edx ; do 4 bytes SUB
817 jmp short .done
818
819.do_word:
820 sub [MY_PTR_REG], dx ; do 2 bytes SUB
821 jmp short .done
822
823.do_byte:
824 sub [MY_PTR_REG], dl ; do 1 byte SUB
825
826 ; collect flags and return.
827.done:
828 pushf
829 pop MY_RET_REG
830 retn
831
832%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
833.do_qword:
834 db 0xea ; jmp far .sixtyfourbit_mode
835 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
836BITS 64
837.sixtyfourbit_mode:
838 and esp, 0ffffffffh
839 and MY_PTR_REG, 0ffffffffh
840 mov rdx, qword [rsp + 08h] ; rdx = second parameter
841 sub [MY_PTR_REG64], rdx ; do 8 bytes SUB
842 jmp far [.fpret wrt rip]
843.fpret: ; 16:32 Pointer to .done.
844 dd .done, NAME(SUPR0AbsKernelCS)
845BITS 32
846%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
847ENDPROC EMEmulateSub
848
849
850;;
851; Emulate BTR instruction, CDECL calling conv.
852; VMMDECL(uint32_t) EMEmulateBtr(void *pvParam1, uint64_t u64Param2);
853;
854; @returns EFLAGS after the operation, only arithmetic flags are valid.
855; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
856; @param [esp + 08h] Param 2 - Second parameter.
857; @uses eax, ecx, edx
858;
859align 16
860BEGINPROC EMEmulateBtr
861%ifdef RT_ARCH_AMD64
862%ifndef RT_OS_WINDOWS
863 mov rcx, rdi ; rcx = first parameter
864 mov rdx, rsi ; rdx = second parameter
865%endif ; !RT_OS_WINDOWS
866%else ; !RT_ARCH_AMD64
867 mov ecx, [esp + 04h] ; ecx = first parameter
868 mov edx, [esp + 08h] ; edx = second parameter
869%endif
870
871 and edx, 7
872 btr [MY_PTR_REG], edx
873
874 ; collect flags and return.
875 pushf
876 pop MY_RET_REG
877 retn
878ENDPROC EMEmulateBtr
879
880;;
881; Emulate LOCK BTR instruction.
882; VMMDECL(int) EMEmulateLockBtr(void *pvParam1, uint64_t u64Param2, RTGCUINTREG32 *pf);
883;
884; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
885; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
886; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value. (really an 8 byte value)
887; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Where to store the eflags on success.
888;
889align 16
890BEGINPROC EMEmulateLockBtr
891%ifdef RT_ARCH_AMD64
892 %ifdef RT_OS_WINDOWS
893 mov rax, r8 ; rax = third parameter
894 %else ; !RT_OS_WINDOWS
895 mov rcx, rdi ; rcx = first parameter
896 mov rax, rdx ; rax = third parameter
897 mov rdx, rsi ; rdx = second parameter
898 %endif ; !RT_OS_WINDOWS
899%else ; !RT_ARCH_AMD64
900 mov ecx, [esp + 04h] ; ecx = first parameter
901 mov edx, [esp + 08h] ; edx = second parameter
902 mov eax, [esp + 10h] ; eax = third parameter
903%endif
904
905 lock btr [MY_PTR_REG], edx
906
907 ; collect flags and return.
908 pushf
909 pop xDX
910 mov [xAX], edx
911 mov eax, VINF_SUCCESS
912 retn
913
914%ifdef IN_RC
915; #PF resume point.
916GLOBALNAME EMEmulateLockBtr_Error
917 mov eax, VERR_ACCESS_DENIED
918 ret
919%endif
920
921ENDPROC EMEmulateLockBtr
922
923
924;;
925; Emulate BTC instruction, CDECL calling conv.
926; VMMDECL(uint32_t) EMEmulateBtc(void *pvParam1, uint64_t u64Param2);
927;
928; @returns EFLAGS after the operation, only arithmetic flags are valid.
929; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
930; @param [esp + 08h] Param 2 - Second parameter.
931; @uses eax, ecx, edx
932;
933align 16
934BEGINPROC EMEmulateBtc
935%ifdef RT_ARCH_AMD64
936%ifndef RT_OS_WINDOWS
937 mov rcx, rdi ; rcx = first parameter
938 mov rdx, rsi ; rdx = second parameter
939%endif ; !RT_OS_WINDOWS
940%else ; !RT_ARCH_AMD64
941 mov ecx, [esp + 04h] ; ecx = first parameter
942 mov edx, [esp + 08h] ; edx = second parameter
943%endif
944
945 and edx, 7
946 btc [MY_PTR_REG], edx
947
948 ; collect flags and return.
949 pushf
950 pop MY_RET_REG
951 retn
952ENDPROC EMEmulateBtc
953
954
955;;
956; Emulate BTS instruction, CDECL calling conv.
957; VMMDECL(uint32_t) EMEmulateBts(void *pvParam1, uint64_t u64Param2);
958;
959; @returns EFLAGS after the operation, only arithmetic flags are valid.
960; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
961; @param [esp + 08h] Param 2 - Second parameter.
962; @uses eax, ecx, edx
963;
964align 16
965BEGINPROC EMEmulateBts
966%ifdef RT_ARCH_AMD64
967%ifndef RT_OS_WINDOWS
968 mov rcx, rdi ; rcx = first parameter
969 mov rdx, rsi ; rdx = second parameter
970%endif ; !RT_OS_WINDOWS
971%else ; !RT_ARCH_AMD64
972 mov ecx, [esp + 04h] ; ecx = first parameter
973 mov edx, [esp + 08h] ; edx = second parameter
974%endif
975
976 and edx, 7
977 bts [MY_PTR_REG], edx
978
979 ; collect flags and return.
980 pushf
981 pop MY_RET_REG
982 retn
983ENDPROC EMEmulateBts
984
985
986;;
987; Emulate LOCK CMPXCHG instruction, CDECL calling conv.
988; VMMDECL(uint32_t) EMEmulateLockCmpXchg(void *pvParam1, uint64_t *pu64Param2, uint64_t u64Param3, size_t cbSize);
989;
990; @returns EFLAGS after the operation, only arithmetic flags are valid.
991; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
992; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - pointer to second parameter (eax)
993; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - third parameter
994; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Size of parameters, only 1/2/4/8 is valid
995; @uses eax, ecx, edx
996;
997align 16
998BEGINPROC EMEmulateLockCmpXchg
999 push xBX
1000%ifdef RT_ARCH_AMD64
1001%ifdef RT_OS_WINDOWS
1002 ; rcx contains the first parameter already
1003 mov rbx, rdx ; rdx = 2nd parameter
1004 mov rdx, r8 ; r8 = 3rd parameter
1005 mov rax, r9 ; r9 = size of parameters
1006%else
1007 mov rax, rcx ; rcx = size of parameters (4th)
1008 mov rcx, rdi ; rdi = 1st parameter
1009 mov rbx, rsi ; rsi = second parameter
1010 ;rdx contains the 3rd parameter already
1011%endif ; !RT_OS_WINDOWS
1012%else ; !RT_ARCH_AMD64
1013 mov ecx, [esp + 04h + 4] ; ecx = first parameter
1014 mov ebx, [esp + 08h + 4] ; ebx = 2nd parameter (eax)
1015 mov edx, [esp + 0ch + 4] ; edx = third parameter
1016 mov eax, [esp + 14h + 4] ; eax = size of parameters
1017%endif
1018
1019%ifdef CAN_DO_8_BYTE_OP
1020 cmp al, 8
1021 je short .do_qword ; 8 bytes variant
1022%endif
1023 cmp al, 4
1024 je short .do_dword ; 4 bytes variant
1025 cmp al, 2
1026 je short .do_word ; 2 byte variant
1027 cmp al, 1
1028 je short .do_byte ; 1 bytes variant
1029 int3
1030
1031%ifdef RT_ARCH_AMD64
1032.do_qword:
1033 ; load 2nd parameter's value
1034 mov rax, qword [rbx]
1035
1036 lock cmpxchg qword [rcx], rdx ; do 8 bytes CMPXCHG
1037 mov qword [rbx], rax
1038 jmp short .done
1039%endif
1040
1041.do_dword:
1042 ; load 2nd parameter's value
1043 mov eax, dword [xBX]
1044
1045 lock cmpxchg dword [xCX], edx ; do 4 bytes CMPXCHG
1046 mov dword [xBX], eax
1047 jmp short .done
1048
1049.do_word:
1050 ; load 2nd parameter's value
1051 mov eax, dword [xBX]
1052
1053 lock cmpxchg word [xCX], dx ; do 2 bytes CMPXCHG
1054 mov word [xBX], ax
1055 jmp short .done
1056
1057.do_byte:
1058 ; load 2nd parameter's value
1059 mov eax, dword [xBX]
1060
1061 lock cmpxchg byte [xCX], dl ; do 1 byte CMPXCHG
1062 mov byte [xBX], al
1063
1064.done:
1065 ; collect flags and return.
1066 pushf
1067 pop MY_RET_REG
1068
1069 pop xBX
1070 retn
1071
1072%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1073.do_qword:
1074 db 0xea ; jmp far .sixtyfourbit_mode
1075 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1076BITS 64
1077.sixtyfourbit_mode:
1078 and ebx, 0ffffffffh
1079 and esp, 0ffffffffh
1080 and ecx, 0ffffffffh
1081 mov rax, qword [rbx] ; load 2nd parameter's value
1082 mov rdx, qword [rsp + 0ch + 4] ; rdx = third parameter
1083
1084 lock cmpxchg qword [rcx], rdx ; do 8 byte CMPXCHG
1085 mov qword [rbx], rax
1086 jmp far [.fpret wrt rip]
1087.fpret: ; 16:32 Pointer to .done.
1088 dd .done, NAME(SUPR0AbsKernelCS)
1089BITS 32
1090%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1091ENDPROC EMEmulateLockCmpXchg
1092
1093
1094;;
1095; Emulate CMPXCHG instruction, CDECL calling conv.
1096; VMMDECL(uint32_t) EMEmulateCmpXchg(void *pvParam1, uint64_t *pu32Param2, uint64_t u32Param3, size_t cbSize);
1097;
1098; @returns EFLAGS after the operation, only arithmetic flags are valid.
1099; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1100; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - pointer to second parameter (eax)
1101; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - third parameter
1102; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Size of parameters, only 1/2/4 is valid.
1103; @uses eax, ecx, edx
1104;
1105align 16
1106BEGINPROC EMEmulateCmpXchg
1107 push xBX
1108%ifdef RT_ARCH_AMD64
1109%ifdef RT_OS_WINDOWS
1110 ; rcx contains the first parameter already
1111 mov rbx, rdx ; rdx = 2nd parameter
1112 mov rdx, r8 ; r8 = 3rd parameter
1113 mov rax, r9 ; r9 = size of parameters
1114%else
1115 mov rax, rcx ; rcx = size of parameters (4th)
1116 mov rcx, rdi ; rdi = 1st parameter
1117 mov rbx, rsi ; rsi = second parameter
1118 ;rdx contains the 3rd parameter already
1119%endif ; !RT_OS_WINDOWS
1120%else ; !RT_ARCH_AMD64
1121 mov ecx, [esp + 04h + 4] ; ecx = first parameter
1122 mov ebx, [esp + 08h + 4] ; ebx = 2nd parameter (eax)
1123 mov edx, [esp + 0ch + 4] ; edx = third parameter
1124 mov eax, [esp + 14h + 4] ; eax = size of parameters
1125%endif
1126
1127%ifdef CAN_DO_8_BYTE_OP
1128 cmp al, 8
1129 je short .do_qword ; 8 bytes variant
1130%endif
1131 cmp al, 4
1132 je short .do_dword ; 4 bytes variant
1133 cmp al, 2
1134 je short .do_word ; 2 byte variant
1135 cmp al, 1
1136 je short .do_byte ; 1 bytes variant
1137 int3
1138
1139%ifdef RT_ARCH_AMD64
1140.do_qword:
1141 ; load 2nd parameter's value
1142 mov rax, qword [rbx]
1143
1144 cmpxchg qword [rcx], rdx ; do 8 bytes CMPXCHG
1145 mov qword [rbx], rax
1146 jmp short .done
1147%endif
1148
1149.do_dword:
1150 ; load 2nd parameter's value
1151 mov eax, dword [xBX]
1152
1153 cmpxchg dword [xCX], edx ; do 4 bytes CMPXCHG
1154 mov dword [xBX], eax
1155 jmp short .done
1156
1157.do_word:
1158 ; load 2nd parameter's value
1159 mov eax, dword [xBX]
1160
1161 cmpxchg word [xCX], dx ; do 2 bytes CMPXCHG
1162 mov word [xBX], ax
1163 jmp short .done
1164
1165.do_byte:
1166 ; load 2nd parameter's value
1167 mov eax, dword [xBX]
1168
1169 cmpxchg byte [xCX], dl ; do 1 byte CMPXCHG
1170 mov byte [xBX], al
1171
1172.done:
1173 ; collect flags and return.
1174 pushf
1175 pop MY_RET_REG
1176
1177 pop xBX
1178 retn
1179
1180%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1181.do_qword:
1182 db 0xea ; jmp far .sixtyfourbit_mode
1183 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1184BITS 64
1185.sixtyfourbit_mode:
1186 and ebx, 0ffffffffh
1187 and esp, 0ffffffffh
1188 and ecx, 0ffffffffh
1189 mov rax, qword [rbx] ; load 2nd parameter's value
1190 mov rdx, qword [rsp + 0ch + 4] ; rdx = third parameter
1191
1192 cmpxchg qword [rcx], rdx ; do 8 byte CMPXCHG
1193 mov qword [rbx], rax
1194 jmp far [.fpret wrt rip]
1195.fpret: ; 16:32 Pointer to .done.
1196 dd .done, NAME(SUPR0AbsKernelCS)
1197BITS 32
1198%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1199ENDPROC EMEmulateCmpXchg
1200
1201
1202;;
1203; Emulate LOCK CMPXCHG8B instruction, CDECL calling conv.
1204; VMMDECL(uint32_t) EMEmulateLockCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);
1205;
1206; @returns EFLAGS after the operation, only the ZF flag is valid.
1207; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1208; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Address of the eax register
1209; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Address of the edx register
1210; @param [esp + 10h] gcc:rcx msc:r9 Param 4 - EBX
1211; @param [esp + 14h] gcc:r8 msc:[rsp + 8] Param 5 - ECX
1212; @uses eax, ecx, edx
1213;
1214align 16
1215BEGINPROC EMEmulateLockCmpXchg8b
1216 push xBP
1217 push xBX
1218%ifdef RT_ARCH_AMD64
1219 %ifdef RT_OS_WINDOWS
1220 mov rbp, rcx
1221 mov r10, rdx
1222 mov eax, dword [rdx]
1223 mov edx, dword [r8]
1224 mov rbx, r9
1225 mov ecx, [rsp + 28h + 16]
1226 %else
1227 mov rbp, rdi
1228 mov r10, rdx
1229 mov eax, dword [rsi]
1230 mov edx, dword [rdx]
1231 mov rbx, rcx
1232 mov rcx, r8
1233 %endif
1234%else
1235 mov ebp, [esp + 04h + 8] ; ebp = first parameter
1236 mov eax, [esp + 08h + 8] ; &EAX
1237 mov eax, dword [eax]
1238 mov edx, [esp + 0ch + 8] ; &EDX
1239 mov edx, dword [edx]
1240 mov ebx, [esp + 10h + 8] ; EBX
1241 mov ecx, [esp + 14h + 8] ; ECX
1242%endif
1243
1244%ifdef RT_OS_OS2
1245 lock cmpxchg8b [xBP] ; do CMPXCHG8B
1246%else
1247 lock cmpxchg8b qword [xBP] ; do CMPXCHG8B
1248%endif
1249
1250%ifdef RT_ARCH_AMD64
1251 %ifdef RT_OS_WINDOWS
1252 mov dword [r10], eax
1253 mov dword [r8], edx
1254 %else
1255 mov dword [rsi], eax
1256 mov dword [r10], edx
1257 %endif
1258%else
1259 mov ebx, dword [esp + 08h + 8]
1260 mov dword [ebx], eax
1261 mov ebx, dword [esp + 0ch + 8]
1262 mov dword [ebx], edx
1263%endif
1264 ; collect flags and return.
1265 pushf
1266 pop MY_RET_REG
1267
1268 pop xBX
1269 pop xBP
1270 retn
1271ENDPROC EMEmulateLockCmpXchg8b
1272
1273;;
1274; Emulate CMPXCHG8B instruction, CDECL calling conv.
1275; VMMDECL(uint32_t) EMEmulateCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);
1276;
1277; @returns EFLAGS after the operation, only arithmetic flags are valid.
1278; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1279; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Address of the eax register
1280; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Address of the edx register
1281; @param [esp + 10h] gcc:rcx msc:r9 Param 4 - EBX
1282; @param [esp + 14h] gcc:r8 msc:[rsp + 8] Param 5 - ECX
1283; @uses eax, ecx, edx
1284;
1285align 16
1286BEGINPROC EMEmulateCmpXchg8b
1287 push xBP
1288 push xBX
1289%ifdef RT_ARCH_AMD64
1290 %ifdef RT_OS_WINDOWS
1291 mov rbp, rcx
1292 mov r10, rdx
1293 mov eax, dword [rdx]
1294 mov edx, dword [r8]
1295 mov rbx, r9
1296 mov ecx, [rsp + 28h + 16]
1297 %else
1298 mov rbp, rdi
1299 mov r10, rdx
1300 mov eax, dword [rsi]
1301 mov edx, dword [rdx]
1302 mov rbx, rcx
1303 mov rcx, r8
1304 %endif
1305%else
1306 mov ebp, [esp + 04h + 8] ; ebp = first parameter
1307 mov eax, [esp + 08h + 8] ; &EAX
1308 mov eax, dword [eax]
1309 mov edx, [esp + 0ch + 8] ; &EDX
1310 mov edx, dword [edx]
1311 mov ebx, [esp + 10h + 8] ; EBX
1312 mov ecx, [esp + 14h + 8] ; ECX
1313%endif
1314
1315%ifdef RT_OS_OS2
1316 cmpxchg8b [xBP] ; do CMPXCHG8B
1317%else
1318 cmpxchg8b qword [xBP] ; do CMPXCHG8B
1319%endif
1320
1321%ifdef RT_ARCH_AMD64
1322 %ifdef RT_OS_WINDOWS
1323 mov dword [r10], eax
1324 mov dword [r8], edx
1325 %else
1326 mov dword [rsi], eax
1327 mov dword [r10], edx
1328 %endif
1329%else
1330 mov ebx, dword [esp + 08h + 8]
1331 mov dword [ebx], eax
1332 mov ebx, dword [esp + 0ch + 8]
1333 mov dword [ebx], edx
1334%endif
1335
1336 ; collect flags and return.
1337 pushf
1338 pop MY_RET_REG
1339
1340 pop xBX
1341 pop xBP
1342 retn
1343ENDPROC EMEmulateCmpXchg8b
1344
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