VirtualBox

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

Last change on this file since 45620 was 44528, checked in by vboxsync, 12 years ago

header (C) fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 51.2 KB
Line 
1; $Id: EMAllA.asm 44528 2013-02-04 14:27:54Z vboxsync $
2;; @file
3; EM Assembly Routines.
4;
5
6;
7; Copyright (C) 2006-2011 Oracle Corporation
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
18;*******************************************************************************
19;* Header Files *
20;*******************************************************************************
21%include "VBox/asmdefs.mac"
22%include "VBox/err.mac"
23%include "iprt/x86.mac"
24
25;; @def MY_PTR_REG
26; The register we use for value pointers (And,Or,Dec,Inc,XAdd).
27%ifdef RT_ARCH_AMD64
28 %define MY_PTR_REG rcx
29%else
30 %define MY_PTR_REG ecx
31%endif
32
33;; @def MY_RET_REG
34; The register we return the result in.
35%ifdef RT_ARCH_AMD64
36 %define MY_RET_REG rax
37%else
38 %define MY_RET_REG eax
39%endif
40
41;; @def RT_ARCH_AMD64
42; Indicator for whether we can deal with 8 byte operands. (Darwin fun again.)
43%ifdef RT_ARCH_AMD64
44 %define CAN_DO_8_BYTE_OP 1
45%endif
46%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
47 %define CAN_DO_8_BYTE_OP 1
48 %define MY_PTR_REG64 rcx
49%endif
50
51
52;*******************************************************************************
53;* External Symbols *
54;*******************************************************************************
55%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
56extern NAME(SUPR0Abs64bitKernelCS)
57extern NAME(SUPR0AbsKernelCS)
58%endif
59
60
61BEGINCODE
62
63
64;;
65; Emulate CMP instruction, CDECL calling conv.
66; VMMDECL(uint32_t) EMEmulateCmp(uint32_t u32Param1, uint64_t u64Param2, size_t cb);
67;
68; @returns EFLAGS after the operation, only arithmetic flags are valid.
69; @param [esp + 04h] rdi rcx Param 1 - First parameter (Dst).
70; @param [esp + 08h] rsi edx Param 2 - Second parameter (Src).
71; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
72;
73align 16
74BEGINPROC EMEmulateCmp
75%ifdef RT_ARCH_AMD64
76%ifdef RT_OS_WINDOWS
77 mov rax, r8 ; eax = size of parameters
78%else ; !RT_OS_WINDOWS
79 mov rax, rdx ; rax = size of parameters
80 mov rcx, rdi ; rcx = first parameter
81 mov rdx, rsi ; rdx = second parameter
82%endif ; !RT_OS_WINDOWS
83%else ; !RT_ARCH_AMD64
84 mov eax, [esp + 10h] ; eax = size of parameters
85 mov ecx, [esp + 04h] ; ecx = first parameter
86 mov edx, [esp + 08h] ; edx = second parameter
87%endif
88
89 ; switch on size
90%ifdef RT_ARCH_AMD64
91 cmp al, 8
92 je short .do_qword ; 8 bytes variant
93%endif
94 cmp al, 4
95 je short .do_dword ; 4 bytes variant
96 cmp al, 2
97 je short .do_word ; 2 byte variant
98 cmp al, 1
99 je short .do_byte ; 1 bytes variant
100 int3
101
102 ; workers
103%ifdef RT_ARCH_AMD64
104.do_qword:
105 cmp rcx, rdx ; do 8 bytes CMP
106 jmp short .done
107%endif
108
109.do_dword:
110 cmp ecx, edx ; do 4 bytes CMP
111 jmp short .done
112
113.do_word:
114 cmp cx, dx ; do 2 bytes CMP
115 jmp short .done
116
117.do_byte:
118 cmp cl, dl ; do 1 byte CMP
119
120 ; collect flags and return.
121.done:
122 pushf
123 pop MY_RET_REG
124 retn
125ENDPROC EMEmulateCmp
126
127
128;;
129; Emulate AND instruction, CDECL calling conv.
130; VMMDECL(uint32_t) EMEmulateAnd(void *pvParam1, uint64_t u64Param2, size_t cb);
131;
132; @returns EFLAGS after the operation, only arithmetic flags are valid.
133; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
134; @param [esp + 08h] Param 2 - Second parameter.
135; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
136; @uses eax, ecx, edx
137;
138align 16
139BEGINPROC EMEmulateAnd
140%ifdef RT_ARCH_AMD64
141%ifdef RT_OS_WINDOWS
142 mov rax, r8 ; eax = size of parameters
143%else ; !RT_OS_WINDOWS
144 mov rax, rdx ; rax = size of parameters
145 mov rcx, rdi ; rcx = first parameter
146 mov rdx, rsi ; rdx = second parameter
147%endif ; !RT_OS_WINDOWS
148%else ; !RT_ARCH_AMD64
149 mov eax, [esp + 10h] ; eax = size of parameters
150 mov ecx, [esp + 04h] ; ecx = first parameter
151 mov edx, [esp + 08h] ; edx = second parameter
152%endif
153
154 ; switch on size
155%ifdef CAN_DO_8_BYTE_OP
156 cmp al, 8
157 je short .do_qword ; 8 bytes variant
158%endif
159 cmp al, 4
160 je short .do_dword ; 4 bytes variant
161 cmp al, 2
162 je short .do_word ; 2 byte variant
163 cmp al, 1
164 je short .do_byte ; 1 bytes variant
165 int3
166
167 ; workers
168%ifdef RT_ARCH_AMD64
169.do_qword:
170 and [MY_PTR_REG], rdx ; do 8 bytes AND
171 jmp short .done
172%endif
173
174.do_dword:
175 and [MY_PTR_REG], edx ; do 4 bytes AND
176 jmp short .done
177
178.do_word:
179 and [MY_PTR_REG], dx ; do 2 bytes AND
180 jmp short .done
181
182.do_byte:
183 and [MY_PTR_REG], dl ; do 1 byte AND
184
185 ; collect flags and return.
186.done:
187 pushf
188 pop MY_RET_REG
189 retn
190
191%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
192.do_qword:
193 db 0xea ; jmp far .sixtyfourbit_mode
194 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
195BITS 64
196.sixtyfourbit_mode:
197 and esp, 0ffffffffh
198 and MY_PTR_REG, 0ffffffffh
199 mov rdx, qword [rsp + 08h] ; rdx = second parameter
200 and [MY_PTR_REG64], rdx ; do 8 bytes AND
201 jmp far [.fpret wrt rip]
202.fpret: ; 16:32 Pointer to .done.
203 dd .done, NAME(SUPR0AbsKernelCS)
204BITS 32
205%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
206ENDPROC EMEmulateAnd
207
208
209;;
210; Emulate LOCK AND instruction.
211; VMMDECL(int) EMEmulateLockAnd(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
212;
213; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
214; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
215; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value.
216; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Size of the operation - 1, 2, 4 or 8 bytes.
217; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Where to store the eflags on success.
218; only arithmetic flags are valid.
219align 16
220BEGINPROC EMEmulateLockAnd
221%ifdef RT_ARCH_AMD64
222%ifdef RT_OS_WINDOWS
223 mov rax, r8 ; eax = size of parameters
224%else ; !RT_OS_WINDOWS
225 mov r9, rcx ; r9 = eflags result ptr
226 mov rax, rdx ; rax = size of parameters
227 mov rcx, rdi ; rcx = first parameter
228 mov rdx, rsi ; rdx = second parameter
229%endif ; !RT_OS_WINDOWS
230%else ; !RT_ARCH_AMD64
231 mov eax, [esp + 10h] ; eax = size of parameters
232 mov ecx, [esp + 04h] ; ecx = first parameter (MY_PTR_REG)
233 mov edx, [esp + 08h] ; edx = second parameter
234%endif
235
236 ; switch on size
237%ifdef CAN_DO_8_BYTE_OP
238 cmp al, 8
239 je short .do_qword ; 8 bytes variant
240%endif
241 cmp al, 4
242 je short .do_dword ; 4 bytes variant
243 cmp al, 2
244 je short .do_word ; 2 byte variant
245 cmp al, 1
246 je short .do_byte ; 1 bytes variant
247 int3
248
249 ; workers
250%ifdef RT_ARCH_AMD64
251.do_qword:
252 lock and [MY_PTR_REG], rdx ; do 8 bytes OR
253 jmp short .done
254%endif
255
256.do_dword:
257 lock and [MY_PTR_REG], edx ; do 4 bytes OR
258 jmp short .done
259
260.do_word:
261 lock and [MY_PTR_REG], dx ; do 2 bytes OR
262 jmp short .done
263
264.do_byte:
265 lock and [MY_PTR_REG], dl ; do 1 byte OR
266
267 ; collect flags and return.
268.done:
269 pushf
270%ifdef RT_ARCH_AMD64
271 pop rax
272 mov [r9], eax
273%else ; !RT_ARCH_AMD64
274 mov eax, [esp + 14h + 4]
275 pop dword [eax]
276%endif
277 mov eax, VINF_SUCCESS
278 retn
279
280%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
281.do_qword:
282 db 0xea ; jmp far .sixtyfourbit_mode
283 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
284BITS 64
285.sixtyfourbit_mode:
286 and esp, 0ffffffffh
287 and MY_PTR_REG, 0ffffffffh
288 mov rdx, qword [rsp + 08h] ; rdx = second parameter
289 lock and [MY_PTR_REG64], rdx ; do 8 bytes OR
290 jmp far [.fpret wrt rip]
291.fpret: ; 16:32 Pointer to .done.
292 dd .done, NAME(SUPR0AbsKernelCS)
293BITS 32
294%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
295ENDPROC EMEmulateLockAnd
296
297;;
298; Emulate OR instruction, CDECL calling conv.
299; VMMDECL(uint32_t) EMEmulateOr(void *pvParam1, uint64_t u64Param2, size_t cb);
300;
301; @returns EFLAGS after the operation, only arithmetic flags are valid.
302; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
303; @param [esp + 08h] Param 2 - Second parameter.
304; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
305; @uses eax, ecx, edx
306;
307align 16
308BEGINPROC EMEmulateOr
309%ifdef RT_ARCH_AMD64
310%ifdef RT_OS_WINDOWS
311 mov rax, r8 ; eax = size of parameters
312%else ; !RT_OS_WINDOWS
313 mov rax, rdx ; rax = size of parameters
314 mov rcx, rdi ; rcx = first parameter
315 mov rdx, rsi ; rdx = second parameter
316%endif ; !RT_OS_WINDOWS
317%else ; !RT_ARCH_AMD64
318 mov eax, [esp + 10h] ; eax = size of parameters
319 mov ecx, [esp + 04h] ; ecx = first parameter
320 mov edx, [esp + 08h] ; edx = second parameter
321%endif
322
323 ; switch on size
324%ifdef CAN_DO_8_BYTE_OP
325 cmp al, 8
326 je short .do_qword ; 8 bytes variant
327%endif
328 cmp al, 4
329 je short .do_dword ; 4 bytes variant
330 cmp al, 2
331 je short .do_word ; 2 byte variant
332 cmp al, 1
333 je short .do_byte ; 1 bytes variant
334 int3
335
336 ; workers
337%ifdef RT_ARCH_AMD64
338.do_qword:
339 or [MY_PTR_REG], rdx ; do 8 bytes OR
340 jmp short .done
341%endif
342
343.do_dword:
344 or [MY_PTR_REG], edx ; do 4 bytes OR
345 jmp short .done
346
347.do_word:
348 or [MY_PTR_REG], dx ; do 2 bytes OR
349 jmp short .done
350
351.do_byte:
352 or [MY_PTR_REG], dl ; do 1 byte OR
353
354 ; collect flags and return.
355.done:
356 pushf
357 pop MY_RET_REG
358 retn
359
360%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
361.do_qword:
362 db 0xea ; jmp far .sixtyfourbit_mode
363 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
364BITS 64
365.sixtyfourbit_mode:
366 and esp, 0ffffffffh
367 and MY_PTR_REG, 0ffffffffh
368 mov rdx, qword [rsp + 08h] ; rdx = second parameter
369 or [MY_PTR_REG64], rdx ; do 8 bytes OR
370 jmp far [.fpret wrt rip]
371.fpret: ; 16:32 Pointer to .done.
372 dd .done, NAME(SUPR0AbsKernelCS)
373BITS 32
374%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
375ENDPROC EMEmulateOr
376
377
378;;
379; Emulate LOCK OR instruction.
380; VMMDECL(int) EMEmulateLockOr(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
381;
382; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
383; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
384; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value.
385; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Size of the operation - 1, 2, 4 or 8 bytes.
386; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Where to store the eflags on success.
387; only arithmetic flags are valid.
388align 16
389BEGINPROC EMEmulateLockOr
390%ifdef RT_ARCH_AMD64
391%ifdef RT_OS_WINDOWS
392 mov rax, r8 ; eax = size of parameters
393%else ; !RT_OS_WINDOWS
394 mov r9, rcx ; r9 = eflags result ptr
395 mov rax, rdx ; rax = size of parameters
396 mov rcx, rdi ; rcx = first parameter
397 mov rdx, rsi ; rdx = second parameter
398%endif ; !RT_OS_WINDOWS
399%else ; !RT_ARCH_AMD64
400 mov eax, [esp + 10h] ; eax = size of parameters
401 mov ecx, [esp + 04h] ; ecx = first parameter (MY_PTR_REG)
402 mov edx, [esp + 08h] ; edx = second parameter
403%endif
404
405 ; switch on size
406%ifdef CAN_DO_8_BYTE_OP
407 cmp al, 8
408 je short .do_qword ; 8 bytes variant
409%endif
410 cmp al, 4
411 je short .do_dword ; 4 bytes variant
412 cmp al, 2
413 je short .do_word ; 2 byte variant
414 cmp al, 1
415 je short .do_byte ; 1 bytes variant
416 int3
417
418 ; workers
419%ifdef RT_ARCH_AMD64
420.do_qword:
421 lock or [MY_PTR_REG], rdx ; do 8 bytes OR
422 jmp short .done
423%endif
424
425.do_dword:
426 lock or [MY_PTR_REG], edx ; do 4 bytes OR
427 jmp short .done
428
429.do_word:
430 lock or [MY_PTR_REG], dx ; do 2 bytes OR
431 jmp short .done
432
433.do_byte:
434 lock or [MY_PTR_REG], dl ; do 1 byte OR
435
436 ; collect flags and return.
437.done:
438 pushf
439%ifdef RT_ARCH_AMD64
440 pop rax
441 mov [r9], eax
442%else ; !RT_ARCH_AMD64
443 mov eax, [esp + 14h + 4]
444 pop dword [eax]
445%endif
446 mov eax, VINF_SUCCESS
447 retn
448
449%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
450.do_qword:
451 db 0xea ; jmp far .sixtyfourbit_mode
452 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
453BITS 64
454.sixtyfourbit_mode:
455 and esp, 0ffffffffh
456 and MY_PTR_REG, 0ffffffffh
457 mov rdx, qword [rsp + 08h] ; rdx = second parameter
458 lock or [MY_PTR_REG64], rdx ; do 8 bytes OR
459 jmp far [.fpret wrt rip]
460.fpret: ; 16:32 Pointer to .done.
461 dd .done, NAME(SUPR0AbsKernelCS)
462BITS 32
463%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
464ENDPROC EMEmulateLockOr
465
466
467;;
468; Emulate XOR instruction, CDECL calling conv.
469; VMMDECL(uint32_t) EMEmulateXor(void *pvParam1, uint64_t u64Param2, size_t cb);
470;
471; @returns EFLAGS after the operation, only arithmetic flags are valid.
472; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
473; @param [esp + 08h] Param 2 - Second parameter.
474; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
475; @uses eax, ecx, edx
476;
477align 16
478BEGINPROC EMEmulateXor
479%ifdef RT_ARCH_AMD64
480%ifdef RT_OS_WINDOWS
481 mov rax, r8 ; eax = size of parameters
482%else ; !RT_OS_WINDOWS
483 mov rax, rdx ; rax = size of parameters
484 mov rcx, rdi ; rcx = first parameter
485 mov rdx, rsi ; rdx = second parameter
486%endif ; !RT_OS_WINDOWS
487%else ; !RT_ARCH_AMD64
488 mov eax, [esp + 10h] ; eax = size of parameters
489 mov ecx, [esp + 04h] ; ecx = first parameter
490 mov edx, [esp + 08h] ; edx = second parameter
491%endif
492
493 ; switch on size
494%ifdef CAN_DO_8_BYTE_OP
495 cmp al, 8
496 je short .do_qword ; 8 bytes variant
497%endif
498 cmp al, 4
499 je short .do_dword ; 4 bytes variant
500 cmp al, 2
501 je short .do_word ; 2 byte variant
502 cmp al, 1
503 je short .do_byte ; 1 bytes variant
504 int3
505
506 ; workers
507%ifdef RT_ARCH_AMD64
508.do_qword:
509 xor [MY_PTR_REG], rdx ; do 8 bytes XOR
510 jmp short .done
511%endif
512
513.do_dword:
514 xor [MY_PTR_REG], edx ; do 4 bytes XOR
515 jmp short .done
516
517.do_word:
518 xor [MY_PTR_REG], dx ; do 2 bytes XOR
519 jmp short .done
520
521.do_byte:
522 xor [MY_PTR_REG], dl ; do 1 byte XOR
523
524 ; collect flags and return.
525.done:
526 pushf
527 pop MY_RET_REG
528 retn
529
530%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
531.do_qword:
532 db 0xea ; jmp far .sixtyfourbit_mode
533 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
534BITS 64
535.sixtyfourbit_mode:
536 and esp, 0ffffffffh
537 and MY_PTR_REG, 0ffffffffh
538 mov rdx, qword [rsp + 08h] ; rdx = second parameter
539 xor [MY_PTR_REG64], rdx ; do 8 bytes XOR
540 jmp far [.fpret wrt rip]
541.fpret: ; 16:32 Pointer to .done.
542 dd .done, NAME(SUPR0AbsKernelCS)
543BITS 32
544%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
545ENDPROC EMEmulateXor
546
547;;
548; Emulate LOCK XOR instruction.
549; VMMDECL(int) EMEmulateLockXor(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
550;
551; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
552; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
553; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value.
554; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Size of the operation - 1, 2, 4 or 8 bytes.
555; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Where to store the eflags on success.
556; only arithmetic flags are valid.
557align 16
558BEGINPROC EMEmulateLockXor
559%ifdef RT_ARCH_AMD64
560%ifdef RT_OS_WINDOWS
561 mov rax, r8 ; eax = size of parameters
562%else ; !RT_OS_WINDOWS
563 mov r9, rcx ; r9 = eflags result ptr
564 mov rax, rdx ; rax = size of parameters
565 mov rcx, rdi ; rcx = first parameter
566 mov rdx, rsi ; rdx = second parameter
567%endif ; !RT_OS_WINDOWS
568%else ; !RT_ARCH_AMD64
569 mov eax, [esp + 10h] ; eax = size of parameters
570 mov ecx, [esp + 04h] ; ecx = first parameter (MY_PTR_REG)
571 mov edx, [esp + 08h] ; edx = second parameter
572%endif
573
574 ; switch on size
575%ifdef CAN_DO_8_BYTE_OP
576 cmp al, 8
577 je short .do_qword ; 8 bytes variant
578%endif
579 cmp al, 4
580 je short .do_dword ; 4 bytes variant
581 cmp al, 2
582 je short .do_word ; 2 byte variant
583 cmp al, 1
584 je short .do_byte ; 1 bytes variant
585 int3
586
587 ; workers
588%ifdef RT_ARCH_AMD64
589.do_qword:
590 lock xor [MY_PTR_REG], rdx ; do 8 bytes OR
591 jmp short .done
592%endif
593
594.do_dword:
595 lock xor [MY_PTR_REG], edx ; do 4 bytes OR
596 jmp short .done
597
598.do_word:
599 lock xor [MY_PTR_REG], dx ; do 2 bytes OR
600 jmp short .done
601
602.do_byte:
603 lock xor [MY_PTR_REG], dl ; do 1 byte OR
604
605 ; collect flags and return.
606.done:
607 pushf
608%ifdef RT_ARCH_AMD64
609 pop rax
610 mov [r9], eax
611%else ; !RT_ARCH_AMD64
612 mov eax, [esp + 14h + 4]
613 pop dword [eax]
614%endif
615 mov eax, VINF_SUCCESS
616 retn
617
618%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
619.do_qword:
620 db 0xea ; jmp far .sixtyfourbit_mode
621 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
622BITS 64
623.sixtyfourbit_mode:
624 and esp, 0ffffffffh
625 and MY_PTR_REG, 0ffffffffh
626 mov rdx, qword [rsp + 08h] ; rdx = second parameter
627 lock xor [MY_PTR_REG64], rdx ; do 8 bytes OR
628 jmp far [.fpret wrt rip]
629.fpret: ; 16:32 Pointer to .done.
630 dd .done, NAME(SUPR0AbsKernelCS)
631BITS 32
632%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
633ENDPROC EMEmulateLockXor
634
635;;
636; Emulate INC instruction, CDECL calling conv.
637; VMMDECL(uint32_t) EMEmulateInc(void *pvParam1, size_t cb);
638;
639; @returns EFLAGS after the operation, only arithmetic flags are valid.
640; @param [esp + 04h] rdi rcx Param 1 - First parameter - pointer to data item.
641; @param [esp + 08h] rsi rdx Param 2 - Size of parameters, only 1/2/4 is valid.
642; @uses eax, ecx, edx
643;
644align 16
645BEGINPROC EMEmulateInc
646%ifdef RT_ARCH_AMD64
647%ifdef RT_OS_WINDOWS
648 mov rax, rdx ; eax = size of parameters
649%else ; !RT_OS_WINDOWS
650 mov rax, rsi ; eax = size of parameters
651 mov rcx, rdi ; rcx = first parameter
652%endif ; !RT_OS_WINDOWS
653%else ; !RT_ARCH_AMD64
654 mov eax, [esp + 08h] ; eax = size of parameters
655 mov ecx, [esp + 04h] ; ecx = first parameter
656%endif
657
658 ; switch on size
659%ifdef RT_ARCH_AMD64
660 cmp al, 8
661 je short .do_qword ; 8 bytes variant
662%endif
663 cmp al, 4
664 je short .do_dword ; 4 bytes variant
665 cmp al, 2
666 je short .do_word ; 2 byte variant
667 cmp al, 1
668 je short .do_byte ; 1 bytes variant
669 int3
670
671 ; workers
672%ifdef RT_ARCH_AMD64
673.do_qword:
674 inc qword [MY_PTR_REG] ; do 8 bytes INC
675 jmp short .done
676%endif
677
678.do_dword:
679 inc dword [MY_PTR_REG] ; do 4 bytes INC
680 jmp short .done
681
682.do_word:
683 inc word [MY_PTR_REG] ; do 2 bytes INC
684 jmp short .done
685
686.do_byte:
687 inc byte [MY_PTR_REG] ; do 1 byte INC
688 jmp short .done
689
690 ; collect flags and return.
691.done:
692 pushf
693 pop MY_RET_REG
694 retn
695ENDPROC EMEmulateInc
696
697
698;;
699; Emulate DEC instruction, CDECL calling conv.
700; VMMDECL(uint32_t) EMEmulateDec(void *pvParam1, size_t cb);
701;
702; @returns EFLAGS after the operation, only arithmetic flags are valid.
703; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
704; @param [esp + 08h] Param 2 - Size of parameters, only 1/2/4 is valid.
705; @uses eax, ecx, edx
706;
707align 16
708BEGINPROC EMEmulateDec
709%ifdef RT_ARCH_AMD64
710%ifdef RT_OS_WINDOWS
711 mov rax, rdx ; eax = size of parameters
712%else ; !RT_OS_WINDOWS
713 mov rax, rsi ; eax = size of parameters
714 mov rcx, rdi ; rcx = first parameter
715%endif ; !RT_OS_WINDOWS
716%else ; !RT_ARCH_AMD64
717 mov eax, [esp + 08h] ; eax = size of parameters
718 mov ecx, [esp + 04h] ; ecx = first parameter
719%endif
720
721 ; switch on size
722%ifdef RT_ARCH_AMD64
723 cmp al, 8
724 je short .do_qword ; 8 bytes variant
725%endif
726 cmp al, 4
727 je short .do_dword ; 4 bytes variant
728 cmp al, 2
729 je short .do_word ; 2 byte variant
730 cmp al, 1
731 je short .do_byte ; 1 bytes variant
732 int3
733
734 ; workers
735%ifdef RT_ARCH_AMD64
736.do_qword:
737 dec qword [MY_PTR_REG] ; do 8 bytes DEC
738 jmp short .done
739%endif
740
741.do_dword:
742 dec dword [MY_PTR_REG] ; do 4 bytes DEC
743 jmp short .done
744
745.do_word:
746 dec word [MY_PTR_REG] ; do 2 bytes DEC
747 jmp short .done
748
749.do_byte:
750 dec byte [MY_PTR_REG] ; do 1 byte DEC
751 jmp short .done
752
753 ; collect flags and return.
754.done:
755 pushf
756 pop MY_RET_REG
757 retn
758ENDPROC EMEmulateDec
759
760
761;;
762; Emulate ADD instruction, CDECL calling conv.
763; VMMDECL(uint32_t) EMEmulateAdd(void *pvParam1, uint64_t u64Param2, size_t cb);
764;
765; @returns EFLAGS after the operation, only arithmetic flags are valid.
766; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
767; @param [esp + 08h] Param 2 - Second parameter.
768; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
769; @uses eax, ecx, edx
770;
771align 16
772BEGINPROC EMEmulateAdd
773%ifdef RT_ARCH_AMD64
774%ifdef RT_OS_WINDOWS
775 mov rax, r8 ; eax = size of parameters
776%else ; !RT_OS_WINDOWS
777 mov rax, rdx ; rax = size of parameters
778 mov rcx, rdi ; rcx = first parameter
779 mov rdx, rsi ; rdx = second parameter
780%endif ; !RT_OS_WINDOWS
781%else ; !RT_ARCH_AMD64
782 mov eax, [esp + 10h] ; eax = size of parameters
783 mov ecx, [esp + 04h] ; ecx = first parameter
784 mov edx, [esp + 08h] ; edx = second parameter
785%endif
786
787 ; switch on size
788%ifdef CAN_DO_8_BYTE_OP
789 cmp al, 8
790 je short .do_qword ; 8 bytes variant
791%endif
792 cmp al, 4
793 je short .do_dword ; 4 bytes variant
794 cmp al, 2
795 je short .do_word ; 2 byte variant
796 cmp al, 1
797 je short .do_byte ; 1 bytes variant
798 int3
799
800 ; workers
801%ifdef RT_ARCH_AMD64
802.do_qword:
803 add [MY_PTR_REG], rdx ; do 8 bytes ADD
804 jmp short .done
805%endif
806
807.do_dword:
808 add [MY_PTR_REG], edx ; do 4 bytes ADD
809 jmp short .done
810
811.do_word:
812 add [MY_PTR_REG], dx ; do 2 bytes ADD
813 jmp short .done
814
815.do_byte:
816 add [MY_PTR_REG], dl ; do 1 byte ADD
817
818 ; collect flags and return.
819.done:
820 pushf
821 pop MY_RET_REG
822 retn
823
824%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
825.do_qword:
826 db 0xea ; jmp far .sixtyfourbit_mode
827 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
828BITS 64
829.sixtyfourbit_mode:
830 and esp, 0ffffffffh
831 and MY_PTR_REG, 0ffffffffh
832 mov rdx, qword [rsp + 08h] ; rdx = second parameter
833 add [MY_PTR_REG64], rdx ; do 8 bytes ADD
834 jmp far [.fpret wrt rip]
835.fpret: ; 16:32 Pointer to .done.
836 dd .done, NAME(SUPR0AbsKernelCS)
837BITS 32
838%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
839ENDPROC EMEmulateAdd
840
841
842;;
843; Emulate ADC instruction, CDECL calling conv.
844; VMMDECL(uint32_t) EMEmulateAdcWithCarrySet(void *pvParam1, uint64_t u64Param2, size_t cb);
845;
846; @returns EFLAGS after the operation, only arithmetic flags are valid.
847; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
848; @param [esp + 08h] Param 2 - Second parameter.
849; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
850; @uses eax, ecx, edx
851;
852align 16
853BEGINPROC EMEmulateAdcWithCarrySet
854%ifdef RT_ARCH_AMD64
855%ifdef RT_OS_WINDOWS
856 mov rax, r8 ; eax = size of parameters
857%else ; !RT_OS_WINDOWS
858 mov rax, rdx ; rax = size of parameters
859 mov rcx, rdi ; rcx = first parameter
860 mov rdx, rsi ; rdx = second parameter
861%endif ; !RT_OS_WINDOWS
862%else ; !RT_ARCH_AMD64
863 mov eax, [esp + 10h] ; eax = size of parameters
864 mov ecx, [esp + 04h] ; ecx = first parameter
865 mov edx, [esp + 08h] ; edx = second parameter
866%endif
867
868 ; switch on size
869%ifdef CAN_DO_8_BYTE_OP
870 cmp al, 8
871 je short .do_qword ; 8 bytes variant
872%endif
873 cmp al, 4
874 je short .do_dword ; 4 bytes variant
875 cmp al, 2
876 je short .do_word ; 2 byte variant
877 cmp al, 1
878 je short .do_byte ; 1 bytes variant
879 int3
880
881 ; workers
882%ifdef RT_ARCH_AMD64
883.do_qword:
884 stc ; set carry flag
885 adc [MY_PTR_REG], rdx ; do 8 bytes ADC
886 jmp short .done
887%endif
888
889.do_dword:
890 stc ; set carry flag
891 adc [MY_PTR_REG], edx ; do 4 bytes ADC
892 jmp short .done
893
894.do_word:
895 stc ; set carry flag
896 adc [MY_PTR_REG], dx ; do 2 bytes ADC
897 jmp short .done
898
899.do_byte:
900 stc ; set carry flag
901 adc [MY_PTR_REG], dl ; do 1 byte ADC
902
903 ; collect flags and return.
904.done:
905 pushf
906 pop MY_RET_REG
907 retn
908
909%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
910.do_qword:
911 db 0xea ; jmp far .sixtyfourbit_mode
912 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
913BITS 64
914.sixtyfourbit_mode:
915 and esp, 0ffffffffh
916 and MY_PTR_REG, 0ffffffffh
917 mov rdx, qword [rsp + 08h] ; rdx = second parameter
918 stc ; set carry flag
919 adc [MY_PTR_REG64], rdx ; do 8 bytes ADC
920 jmp far [.fpret wrt rip]
921.fpret: ; 16:32 Pointer to .done.
922 dd .done, NAME(SUPR0AbsKernelCS)
923BITS 32
924%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
925ENDPROC EMEmulateAdcWithCarrySet
926
927
928;;
929; Emulate SUB instruction, CDECL calling conv.
930; VMMDECL(uint32_t) EMEmulateSub(void *pvParam1, uint64_t u64Param2, size_t cb);
931;
932; @returns EFLAGS after the operation, only arithmetic flags are valid.
933; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
934; @param [esp + 08h] Param 2 - Second parameter.
935; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
936; @uses eax, ecx, edx
937;
938align 16
939BEGINPROC EMEmulateSub
940%ifdef RT_ARCH_AMD64
941%ifdef RT_OS_WINDOWS
942 mov rax, r8 ; eax = size of parameters
943%else ; !RT_OS_WINDOWS
944 mov rax, rdx ; rax = size of parameters
945 mov rcx, rdi ; rcx = first parameter
946 mov rdx, rsi ; rdx = second parameter
947%endif ; !RT_OS_WINDOWS
948%else ; !RT_ARCH_AMD64
949 mov eax, [esp + 10h] ; eax = size of parameters
950 mov ecx, [esp + 04h] ; ecx = first parameter
951 mov edx, [esp + 08h] ; edx = second parameter
952%endif
953
954 ; switch on size
955%ifdef CAN_DO_8_BYTE_OP
956 cmp al, 8
957 je short .do_qword ; 8 bytes variant
958%endif
959 cmp al, 4
960 je short .do_dword ; 4 bytes variant
961 cmp al, 2
962 je short .do_word ; 2 byte variant
963 cmp al, 1
964 je short .do_byte ; 1 bytes variant
965 int3
966
967 ; workers
968%ifdef RT_ARCH_AMD64
969.do_qword:
970 sub [MY_PTR_REG], rdx ; do 8 bytes SUB
971 jmp short .done
972%endif
973
974.do_dword:
975 sub [MY_PTR_REG], edx ; do 4 bytes SUB
976 jmp short .done
977
978.do_word:
979 sub [MY_PTR_REG], dx ; do 2 bytes SUB
980 jmp short .done
981
982.do_byte:
983 sub [MY_PTR_REG], dl ; do 1 byte SUB
984
985 ; collect flags and return.
986.done:
987 pushf
988 pop MY_RET_REG
989 retn
990
991%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
992.do_qword:
993 db 0xea ; jmp far .sixtyfourbit_mode
994 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
995BITS 64
996.sixtyfourbit_mode:
997 and esp, 0ffffffffh
998 and MY_PTR_REG, 0ffffffffh
999 mov rdx, qword [rsp + 08h] ; rdx = second parameter
1000 sub [MY_PTR_REG64], rdx ; do 8 bytes SUB
1001 jmp far [.fpret wrt rip]
1002.fpret: ; 16:32 Pointer to .done.
1003 dd .done, NAME(SUPR0AbsKernelCS)
1004BITS 32
1005%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1006ENDPROC EMEmulateSub
1007
1008
1009;;
1010; Emulate BTR instruction, CDECL calling conv.
1011; VMMDECL(uint32_t) EMEmulateBtr(void *pvParam1, uint64_t u64Param2);
1012;
1013; @returns EFLAGS after the operation, only arithmetic flags are valid.
1014; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
1015; @param [esp + 08h] Param 2 - Second parameter.
1016; @uses eax, ecx, edx
1017;
1018align 16
1019BEGINPROC EMEmulateBtr
1020%ifdef RT_ARCH_AMD64
1021%ifndef RT_OS_WINDOWS
1022 mov rcx, rdi ; rcx = first parameter
1023 mov rdx, rsi ; rdx = second parameter
1024%endif ; !RT_OS_WINDOWS
1025%else ; !RT_ARCH_AMD64
1026 mov ecx, [esp + 04h] ; ecx = first parameter
1027 mov edx, [esp + 08h] ; edx = second parameter
1028%endif
1029
1030 and edx, 7
1031 btr [MY_PTR_REG], edx
1032
1033 ; collect flags and return.
1034 pushf
1035 pop MY_RET_REG
1036 retn
1037ENDPROC EMEmulateBtr
1038
1039;;
1040; Emulate LOCK BTR instruction.
1041; VMMDECL(int) EMEmulateLockBtr(void *pvParam1, uint64_t u64Param2, RTGCUINTREG32 *pf);
1042;
1043; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
1044; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
1045; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value. (really an 8 byte value)
1046; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Where to store the eflags on success.
1047;
1048align 16
1049BEGINPROC EMEmulateLockBtr
1050%ifdef RT_ARCH_AMD64
1051 %ifdef RT_OS_WINDOWS
1052 mov rax, r8 ; rax = third parameter
1053 %else ; !RT_OS_WINDOWS
1054 mov rcx, rdi ; rcx = first parameter
1055 mov rax, rdx ; rax = third parameter
1056 mov rdx, rsi ; rdx = second parameter
1057 %endif ; !RT_OS_WINDOWS
1058%else ; !RT_ARCH_AMD64
1059 mov ecx, [esp + 04h] ; ecx = first parameter
1060 mov edx, [esp + 08h] ; edx = second parameter
1061 mov eax, [esp + 10h] ; eax = third parameter
1062%endif
1063
1064 lock btr [MY_PTR_REG], edx
1065
1066 ; collect flags and return.
1067 pushf
1068 pop xDX
1069 mov [xAX], edx
1070 mov eax, VINF_SUCCESS
1071 retn
1072ENDPROC EMEmulateLockBtr
1073
1074
1075;;
1076; Emulate BTC instruction, CDECL calling conv.
1077; VMMDECL(uint32_t) EMEmulateBtc(void *pvParam1, uint64_t u64Param2);
1078;
1079; @returns EFLAGS after the operation, only arithmetic flags are valid.
1080; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
1081; @param [esp + 08h] Param 2 - Second parameter.
1082; @uses eax, ecx, edx
1083;
1084align 16
1085BEGINPROC EMEmulateBtc
1086%ifdef RT_ARCH_AMD64
1087%ifndef RT_OS_WINDOWS
1088 mov rcx, rdi ; rcx = first parameter
1089 mov rdx, rsi ; rdx = second parameter
1090%endif ; !RT_OS_WINDOWS
1091%else ; !RT_ARCH_AMD64
1092 mov ecx, [esp + 04h] ; ecx = first parameter
1093 mov edx, [esp + 08h] ; edx = second parameter
1094%endif
1095
1096 and edx, 7
1097 btc [MY_PTR_REG], edx
1098
1099 ; collect flags and return.
1100 pushf
1101 pop MY_RET_REG
1102 retn
1103ENDPROC EMEmulateBtc
1104
1105
1106;;
1107; Emulate BTS instruction, CDECL calling conv.
1108; VMMDECL(uint32_t) EMEmulateBts(void *pvParam1, uint64_t u64Param2);
1109;
1110; @returns EFLAGS after the operation, only arithmetic flags are valid.
1111; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
1112; @param [esp + 08h] Param 2 - Second parameter.
1113; @uses eax, ecx, edx
1114;
1115align 16
1116BEGINPROC EMEmulateBts
1117%ifdef RT_ARCH_AMD64
1118%ifndef RT_OS_WINDOWS
1119 mov rcx, rdi ; rcx = first parameter
1120 mov rdx, rsi ; rdx = second parameter
1121%endif ; !RT_OS_WINDOWS
1122%else ; !RT_ARCH_AMD64
1123 mov ecx, [esp + 04h] ; ecx = first parameter
1124 mov edx, [esp + 08h] ; edx = second parameter
1125%endif
1126
1127 and edx, 7
1128 bts [MY_PTR_REG], edx
1129
1130 ; collect flags and return.
1131 pushf
1132 pop MY_RET_REG
1133 retn
1134ENDPROC EMEmulateBts
1135
1136
1137;;
1138; Emulate LOCK CMPXCHG instruction, CDECL calling conv.
1139; VMMDECL(uint32_t) EMEmulateLockCmpXchg(void *pvParam1, uint64_t *pu64Param2, uint64_t u64Param3, size_t cbSize);
1140;
1141; @returns EFLAGS after the operation, only arithmetic flags are valid.
1142; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1143; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - pointer to second parameter (eax)
1144; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - third parameter
1145; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Size of parameters, only 1/2/4/8 is valid
1146; @uses eax, ecx, edx
1147;
1148align 16
1149BEGINPROC EMEmulateLockCmpXchg
1150 push xBX
1151%ifdef RT_ARCH_AMD64
1152%ifdef RT_OS_WINDOWS
1153 ; rcx contains the first parameter already
1154 mov rbx, rdx ; rdx = 2nd parameter
1155 mov rdx, r8 ; r8 = 3rd parameter
1156 mov rax, r9 ; r9 = size of parameters
1157%else
1158 mov rax, rcx ; rcx = size of parameters (4th)
1159 mov rcx, rdi ; rdi = 1st parameter
1160 mov rbx, rsi ; rsi = second parameter
1161 ;rdx contains the 3rd parameter already
1162%endif ; !RT_OS_WINDOWS
1163%else ; !RT_ARCH_AMD64
1164 mov ecx, [esp + 04h + 4] ; ecx = first parameter
1165 mov ebx, [esp + 08h + 4] ; ebx = 2nd parameter (eax)
1166 mov edx, [esp + 0ch + 4] ; edx = third parameter
1167 mov eax, [esp + 14h + 4] ; eax = size of parameters
1168%endif
1169
1170%ifdef CAN_DO_8_BYTE_OP
1171 cmp al, 8
1172 je short .do_qword ; 8 bytes variant
1173%endif
1174 cmp al, 4
1175 je short .do_dword ; 4 bytes variant
1176 cmp al, 2
1177 je short .do_word ; 2 byte variant
1178 cmp al, 1
1179 je short .do_byte ; 1 bytes variant
1180 int3
1181
1182%ifdef RT_ARCH_AMD64
1183.do_qword:
1184 ; load 2nd parameter's value
1185 mov rax, qword [rbx]
1186
1187 lock cmpxchg qword [rcx], rdx ; do 8 bytes CMPXCHG
1188 mov qword [rbx], rax
1189 jmp short .done
1190%endif
1191
1192.do_dword:
1193 ; load 2nd parameter's value
1194 mov eax, dword [xBX]
1195
1196 lock cmpxchg dword [xCX], edx ; do 4 bytes CMPXCHG
1197 mov dword [xBX], eax
1198 jmp short .done
1199
1200.do_word:
1201 ; load 2nd parameter's value
1202 mov eax, dword [xBX]
1203
1204 lock cmpxchg word [xCX], dx ; do 2 bytes CMPXCHG
1205 mov word [xBX], ax
1206 jmp short .done
1207
1208.do_byte:
1209 ; load 2nd parameter's value
1210 mov eax, dword [xBX]
1211
1212 lock cmpxchg byte [xCX], dl ; do 1 byte CMPXCHG
1213 mov byte [xBX], al
1214
1215.done:
1216 ; collect flags and return.
1217 pushf
1218 pop MY_RET_REG
1219
1220 pop xBX
1221 retn
1222
1223%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1224.do_qword:
1225 db 0xea ; jmp far .sixtyfourbit_mode
1226 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1227BITS 64
1228.sixtyfourbit_mode:
1229 and ebx, 0ffffffffh
1230 and esp, 0ffffffffh
1231 and ecx, 0ffffffffh
1232 mov rax, qword [rbx] ; load 2nd parameter's value
1233 mov rdx, qword [rsp + 0ch + 4] ; rdx = third parameter
1234
1235 lock cmpxchg qword [rcx], rdx ; do 8 byte CMPXCHG
1236 mov qword [rbx], rax
1237 jmp far [.fpret wrt rip]
1238.fpret: ; 16:32 Pointer to .done.
1239 dd .done, NAME(SUPR0AbsKernelCS)
1240BITS 32
1241%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1242ENDPROC EMEmulateLockCmpXchg
1243
1244
1245;;
1246; Emulate CMPXCHG instruction, CDECL calling conv.
1247; VMMDECL(uint32_t) EMEmulateCmpXchg(void *pvParam1, uint64_t *pu32Param2, uint64_t u32Param3, size_t cbSize);
1248;
1249; @returns EFLAGS after the operation, only arithmetic flags are valid.
1250; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1251; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - pointer to second parameter (eax)
1252; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - third parameter
1253; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Size of parameters, only 1/2/4 is valid.
1254; @uses eax, ecx, edx
1255;
1256align 16
1257BEGINPROC EMEmulateCmpXchg
1258 push xBX
1259%ifdef RT_ARCH_AMD64
1260%ifdef RT_OS_WINDOWS
1261 ; rcx contains the first parameter already
1262 mov rbx, rdx ; rdx = 2nd parameter
1263 mov rdx, r8 ; r8 = 3rd parameter
1264 mov rax, r9 ; r9 = size of parameters
1265%else
1266 mov rax, rcx ; rcx = size of parameters (4th)
1267 mov rcx, rdi ; rdi = 1st parameter
1268 mov rbx, rsi ; rsi = second parameter
1269 ;rdx contains the 3rd parameter already
1270%endif ; !RT_OS_WINDOWS
1271%else ; !RT_ARCH_AMD64
1272 mov ecx, [esp + 04h + 4] ; ecx = first parameter
1273 mov ebx, [esp + 08h + 4] ; ebx = 2nd parameter (eax)
1274 mov edx, [esp + 0ch + 4] ; edx = third parameter
1275 mov eax, [esp + 14h + 4] ; eax = size of parameters
1276%endif
1277
1278%ifdef CAN_DO_8_BYTE_OP
1279 cmp al, 8
1280 je short .do_qword ; 8 bytes variant
1281%endif
1282 cmp al, 4
1283 je short .do_dword ; 4 bytes variant
1284 cmp al, 2
1285 je short .do_word ; 2 byte variant
1286 cmp al, 1
1287 je short .do_byte ; 1 bytes variant
1288 int3
1289
1290%ifdef RT_ARCH_AMD64
1291.do_qword:
1292 ; load 2nd parameter's value
1293 mov rax, qword [rbx]
1294
1295 cmpxchg qword [rcx], rdx ; do 8 bytes CMPXCHG
1296 mov qword [rbx], rax
1297 jmp short .done
1298%endif
1299
1300.do_dword:
1301 ; load 2nd parameter's value
1302 mov eax, dword [xBX]
1303
1304 cmpxchg dword [xCX], edx ; do 4 bytes CMPXCHG
1305 mov dword [xBX], eax
1306 jmp short .done
1307
1308.do_word:
1309 ; load 2nd parameter's value
1310 mov eax, dword [xBX]
1311
1312 cmpxchg word [xCX], dx ; do 2 bytes CMPXCHG
1313 mov word [xBX], ax
1314 jmp short .done
1315
1316.do_byte:
1317 ; load 2nd parameter's value
1318 mov eax, dword [xBX]
1319
1320 cmpxchg byte [xCX], dl ; do 1 byte CMPXCHG
1321 mov byte [xBX], al
1322
1323.done:
1324 ; collect flags and return.
1325 pushf
1326 pop MY_RET_REG
1327
1328 pop xBX
1329 retn
1330
1331%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1332.do_qword:
1333 db 0xea ; jmp far .sixtyfourbit_mode
1334 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1335BITS 64
1336.sixtyfourbit_mode:
1337 and ebx, 0ffffffffh
1338 and esp, 0ffffffffh
1339 and ecx, 0ffffffffh
1340 mov rax, qword [rbx] ; load 2nd parameter's value
1341 mov rdx, qword [rsp + 0ch + 4] ; rdx = third parameter
1342
1343 cmpxchg qword [rcx], rdx ; do 8 byte CMPXCHG
1344 mov qword [rbx], rax
1345 jmp far [.fpret wrt rip]
1346.fpret: ; 16:32 Pointer to .done.
1347 dd .done, NAME(SUPR0AbsKernelCS)
1348BITS 32
1349%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1350ENDPROC EMEmulateCmpXchg
1351
1352
1353;;
1354; Emulate LOCK CMPXCHG8B instruction, CDECL calling conv.
1355; VMMDECL(uint32_t) EMEmulateLockCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);
1356;
1357; @returns EFLAGS after the operation, only the ZF flag is valid.
1358; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1359; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Address of the eax register
1360; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Address of the edx register
1361; @param [esp + 10h] gcc:rcx msc:r9 Param 4 - EBX
1362; @param [esp + 14h] gcc:r8 msc:[rsp + 8] Param 5 - ECX
1363; @uses eax, ecx, edx
1364;
1365align 16
1366BEGINPROC EMEmulateLockCmpXchg8b
1367 push xBP
1368 push xBX
1369%ifdef RT_ARCH_AMD64
1370 %ifdef RT_OS_WINDOWS
1371 mov rbp, rcx
1372 mov r10, rdx
1373 mov eax, dword [rdx]
1374 mov edx, dword [r8]
1375 mov rbx, r9
1376 mov ecx, [rsp + 28h + 16]
1377 %else
1378 mov rbp, rdi
1379 mov r10, rdx
1380 mov eax, dword [rsi]
1381 mov edx, dword [rdx]
1382 mov rbx, rcx
1383 mov rcx, r8
1384 %endif
1385%else
1386 mov ebp, [esp + 04h + 8] ; ebp = first parameter
1387 mov eax, [esp + 08h + 8] ; &EAX
1388 mov eax, dword [eax]
1389 mov edx, [esp + 0ch + 8] ; &EDX
1390 mov edx, dword [edx]
1391 mov ebx, [esp + 10h + 8] ; EBX
1392 mov ecx, [esp + 14h + 8] ; ECX
1393%endif
1394
1395%ifdef RT_OS_OS2
1396 lock cmpxchg8b [xBP] ; do CMPXCHG8B
1397%else
1398 lock cmpxchg8b qword [xBP] ; do CMPXCHG8B
1399%endif
1400
1401%ifdef RT_ARCH_AMD64
1402 %ifdef RT_OS_WINDOWS
1403 mov dword [r10], eax
1404 mov dword [r8], edx
1405 %else
1406 mov dword [rsi], eax
1407 mov dword [r10], edx
1408 %endif
1409%else
1410 mov ebx, dword [esp + 08h + 8]
1411 mov dword [ebx], eax
1412 mov ebx, dword [esp + 0ch + 8]
1413 mov dword [ebx], edx
1414%endif
1415 ; collect flags and return.
1416 pushf
1417 pop MY_RET_REG
1418
1419 pop xBX
1420 pop xBP
1421 retn
1422ENDPROC EMEmulateLockCmpXchg8b
1423
1424;;
1425; Emulate CMPXCHG8B instruction, CDECL calling conv.
1426; VMMDECL(uint32_t) EMEmulateCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);
1427;
1428; @returns EFLAGS after the operation, only arithmetic flags are valid.
1429; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1430; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Address of the eax register
1431; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Address of the edx register
1432; @param [esp + 10h] gcc:rcx msc:r9 Param 4 - EBX
1433; @param [esp + 14h] gcc:r8 msc:[rsp + 8] Param 5 - ECX
1434; @uses eax, ecx, edx
1435;
1436align 16
1437BEGINPROC EMEmulateCmpXchg8b
1438 push xBP
1439 push xBX
1440%ifdef RT_ARCH_AMD64
1441 %ifdef RT_OS_WINDOWS
1442 mov rbp, rcx
1443 mov r10, rdx
1444 mov eax, dword [rdx]
1445 mov edx, dword [r8]
1446 mov rbx, r9
1447 mov ecx, [rsp + 28h + 16]
1448 %else
1449 mov rbp, rdi
1450 mov r10, rdx
1451 mov eax, dword [rsi]
1452 mov edx, dword [rdx]
1453 mov rbx, rcx
1454 mov rcx, r8
1455 %endif
1456%else
1457 mov ebp, [esp + 04h + 8] ; ebp = first parameter
1458 mov eax, [esp + 08h + 8] ; &EAX
1459 mov eax, dword [eax]
1460 mov edx, [esp + 0ch + 8] ; &EDX
1461 mov edx, dword [edx]
1462 mov ebx, [esp + 10h + 8] ; EBX
1463 mov ecx, [esp + 14h + 8] ; ECX
1464%endif
1465
1466%ifdef RT_OS_OS2
1467 cmpxchg8b [xBP] ; do CMPXCHG8B
1468%else
1469 cmpxchg8b qword [xBP] ; do CMPXCHG8B
1470%endif
1471
1472%ifdef RT_ARCH_AMD64
1473 %ifdef RT_OS_WINDOWS
1474 mov dword [r10], eax
1475 mov dword [r8], edx
1476 %else
1477 mov dword [rsi], eax
1478 mov dword [r10], edx
1479 %endif
1480%else
1481 mov ebx, dword [esp + 08h + 8]
1482 mov dword [ebx], eax
1483 mov ebx, dword [esp + 0ch + 8]
1484 mov dword [ebx], edx
1485%endif
1486
1487 ; collect flags and return.
1488 pushf
1489 pop MY_RET_REG
1490
1491 pop xBX
1492 pop xBP
1493 retn
1494ENDPROC EMEmulateCmpXchg8b
1495
1496
1497;;
1498; Emulate LOCK XADD instruction.
1499; VMMDECL(uint32_t) EMEmulateLockXAdd(void *pvParam1, void *pvParam2, size_t cbOp);
1500;
1501; @returns (eax=)eflags
1502; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item.
1503; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter - pointer to second parameter (general register)
1504; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Size of parameters - {1,2,4,8}.
1505;
1506align 16
1507BEGINPROC EMEmulateLockXAdd
1508%ifdef RT_ARCH_AMD64
1509 %ifdef RT_OS_WINDOWS
1510 mov rax, r8 ; eax = size of parameters
1511 %else ; !RT_OS_WINDOWS
1512 mov rax, rdx ; rax = size of parameters
1513 mov rcx, rdi ; rcx = first parameter
1514 mov rdx, rsi ; rdx = second parameter
1515 %endif ; !RT_OS_WINDOWS
1516%else ; !RT_ARCH_AMD64
1517 mov eax, [esp + 0ch] ; eax = size of parameters
1518 mov ecx, [esp + 04h] ; ecx = first parameter
1519 mov edx, [esp + 08h] ; edx = second parameter
1520%endif
1521
1522 ; switch on size
1523%ifdef CAN_DO_8_BYTE_OP
1524 cmp al, 8
1525 je short .do_qword ; 8 bytes variant
1526%endif
1527 cmp al, 4
1528 je short .do_dword ; 4 bytes variant
1529 cmp al, 2
1530 je short .do_word ; 2 byte variant
1531 cmp al, 1
1532 je short .do_byte ; 1 bytes variant
1533 int3
1534
1535 ; workers
1536%ifdef RT_ARCH_AMD64
1537.do_qword:
1538 mov rax, qword [xDX] ; load 2nd parameter's value
1539 lock xadd qword [MY_PTR_REG], rax ; do 8 bytes XADD
1540 mov qword [xDX], rax
1541 jmp short .done
1542%endif
1543
1544.do_dword:
1545 mov eax, dword [xDX] ; load 2nd parameter's value
1546 lock xadd dword [MY_PTR_REG], eax ; do 4 bytes XADD
1547 mov dword [xDX], eax
1548 jmp short .done
1549
1550.do_word:
1551 mov eax, dword [xDX] ; load 2nd parameter's value
1552 lock xadd word [MY_PTR_REG], ax ; do 2 bytes XADD
1553 mov word [xDX], ax
1554 jmp short .done
1555
1556.do_byte:
1557 mov eax, dword [xDX] ; load 2nd parameter's value
1558 lock xadd byte [MY_PTR_REG], al ; do 1 bytes XADD
1559 mov byte [xDX], al
1560
1561.done:
1562 ; collect flags and return.
1563 pushf
1564 pop MY_RET_REG
1565
1566 retn
1567
1568%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1569.do_qword:
1570 db 0xea ; jmp far .sixtyfourbit_mode
1571 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1572BITS 64
1573.sixtyfourbit_mode:
1574 and esp, 0ffffffffh
1575 and edx, 0ffffffffh
1576 and MY_PTR_REG, 0ffffffffh
1577 mov rax, qword [rdx] ; load 2nd parameter's value
1578 and [MY_PTR_REG64], rax ; do 8 bytes XADD
1579 jmp far [.fpret wrt rip]
1580.fpret: ; 16:32 Pointer to .done.
1581 dd .done, NAME(SUPR0AbsKernelCS)
1582BITS 32
1583%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1584ENDPROC EMEmulateLockXAdd
1585
1586
1587;;
1588; Emulate XADD instruction.
1589; VMMDECL(uint32_t) EMEmulateXAdd(void *pvParam1, void *pvParam2, size_t cbOp);
1590;
1591; @returns eax=eflags
1592; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item.
1593; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter - pointer to second parameter (general register)
1594; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Size of parameters - {1,2,4,8}.
1595align 16
1596BEGINPROC EMEmulateXAdd
1597%ifdef RT_ARCH_AMD64
1598%ifdef RT_OS_WINDOWS
1599 mov rax, r8 ; eax = size of parameters
1600%else ; !RT_OS_WINDOWS
1601 mov rax, rdx ; rax = size of parameters
1602 mov rcx, rdi ; rcx = first parameter
1603 mov rdx, rsi ; rdx = second parameter
1604%endif ; !RT_OS_WINDOWS
1605%else ; !RT_ARCH_AMD64
1606 mov eax, [esp + 0ch] ; eax = size of parameters
1607 mov ecx, [esp + 04h] ; ecx = first parameter
1608 mov edx, [esp + 08h] ; edx = second parameter
1609%endif
1610
1611 ; switch on size
1612%ifdef CAN_DO_8_BYTE_OP
1613 cmp al, 8
1614 je short .do_qword ; 8 bytes variant
1615%endif
1616 cmp al, 4
1617 je short .do_dword ; 4 bytes variant
1618 cmp al, 2
1619 je short .do_word ; 2 byte variant
1620 cmp al, 1
1621 je short .do_byte ; 1 bytes variant
1622 int3
1623
1624 ; workers
1625%ifdef RT_ARCH_AMD64
1626.do_qword:
1627 mov rax, qword [xDX] ; load 2nd parameter's value
1628 xadd qword [MY_PTR_REG], rax ; do 8 bytes XADD
1629 mov qword [xDX], rax
1630 jmp short .done
1631%endif
1632
1633.do_dword:
1634 mov eax, dword [xDX] ; load 2nd parameter's value
1635 xadd dword [MY_PTR_REG], eax ; do 4 bytes XADD
1636 mov dword [xDX], eax
1637 jmp short .done
1638
1639.do_word:
1640 mov eax, dword [xDX] ; load 2nd parameter's value
1641 xadd word [MY_PTR_REG], ax ; do 2 bytes XADD
1642 mov word [xDX], ax
1643 jmp short .done
1644
1645.do_byte:
1646 mov eax, dword [xDX] ; load 2nd parameter's value
1647 xadd byte [MY_PTR_REG], al ; do 1 bytes XADD
1648 mov byte [xDX], al
1649
1650.done:
1651 ; collect flags and return.
1652 pushf
1653 pop MY_RET_REG
1654
1655 retn
1656
1657%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1658.do_qword:
1659 db 0xea ; jmp far .sixtyfourbit_mode
1660 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1661BITS 64
1662.sixtyfourbit_mode:
1663 and esp, 0ffffffffh
1664 and edx, 0ffffffffh
1665 and MY_PTR_REG, 0ffffffffh
1666 mov rax, qword [rdx] ; load 2nd parameter's value
1667 and [MY_PTR_REG64], rax ; do 8 bytes XADD
1668 jmp far [.fpret wrt rip]
1669.fpret: ; 16:32 Pointer to .done.
1670 dd .done, NAME(SUPR0AbsKernelCS)
1671BITS 32
1672%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1673ENDPROC EMEmulateXAdd
1674
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