VirtualBox

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

Last change on this file since 23794 was 20641, checked in by vboxsync, 15 years ago

Fixed lock and/or/xor result store in amd64 gcc case.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 46.1 KB
Line 
1; $Id: EMAllA.asm 20641 2009-06-16 16:14:33Z 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 LOCK AND instruction.
215; VMMDECL(int) EMEmulateLockAnd(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
216;
217; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
218; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
219; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value.
220; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Size of the operation - 1, 2, 4 or 8 bytes.
221; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Where to store the eflags on success.
222; only arithmetic flags are valid.
223align 16
224BEGINPROC EMEmulateLockAnd
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 r9, rcx ; r9 = eflags result ptr
230 mov rax, rdx ; rax = size of parameters
231 mov rcx, rdi ; rcx = first parameter
232 mov rdx, rsi ; rdx = second parameter
233%endif ; !RT_OS_WINDOWS
234%else ; !RT_ARCH_AMD64
235 mov eax, [esp + 10h] ; eax = size of parameters
236 mov ecx, [esp + 04h] ; ecx = first parameter (MY_PTR_REG)
237 mov edx, [esp + 08h] ; edx = second parameter
238%endif
239
240 ; switch on size
241%ifdef CAN_DO_8_BYTE_OP
242 cmp al, 8
243 je short .do_qword ; 8 bytes variant
244%endif
245 cmp al, 4
246 je short .do_dword ; 4 bytes variant
247 cmp al, 2
248 je short .do_word ; 2 byte variant
249 cmp al, 1
250 je short .do_byte ; 1 bytes variant
251 int3
252
253 ; workers
254%ifdef RT_ARCH_AMD64
255.do_qword:
256 lock and [MY_PTR_REG], rdx ; do 8 bytes OR
257 jmp short .done
258%endif
259
260.do_dword:
261 lock and [MY_PTR_REG], edx ; do 4 bytes OR
262 jmp short .done
263
264.do_word:
265 lock and [MY_PTR_REG], dx ; do 2 bytes OR
266 jmp short .done
267
268.do_byte:
269 lock and [MY_PTR_REG], dl ; do 1 byte OR
270
271 ; collect flags and return.
272.done:
273 pushf
274%ifdef RT_ARCH_AMD64
275 pop rax
276 mov [r9], eax
277%else ; !RT_ARCH_AMD64
278 mov eax, [esp + 14h + 4]
279 pop dword [eax]
280%endif
281 mov eax, VINF_SUCCESS
282 retn
283
284%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
285.do_qword:
286 db 0xea ; jmp far .sixtyfourbit_mode
287 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
288BITS 64
289.sixtyfourbit_mode:
290 and esp, 0ffffffffh
291 and MY_PTR_REG, 0ffffffffh
292 mov rdx, qword [rsp + 08h] ; rdx = second parameter
293 lock and [MY_PTR_REG64], rdx ; do 8 bytes OR
294 jmp far [.fpret wrt rip]
295.fpret: ; 16:32 Pointer to .done.
296 dd .done, NAME(SUPR0AbsKernelCS)
297BITS 32
298%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
299
300
301%ifdef IN_RC
302; #PF resume point.
303GLOBALNAME EMEmulateLockAnd_Error
304 mov eax, VERR_ACCESS_DENIED
305 ret
306%endif
307
308ENDPROC EMEmulateLockAnd
309
310;;
311; Emulate OR instruction, CDECL calling conv.
312; VMMDECL(uint32_t) EMEmulateOr(void *pvParam1, uint64_t u64Param2, size_t cb);
313;
314; @returns EFLAGS after the operation, only arithmetic flags are valid.
315; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
316; @param [esp + 08h] Param 2 - Second parameter.
317; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
318; @uses eax, ecx, edx
319;
320align 16
321BEGINPROC EMEmulateOr
322%ifdef RT_ARCH_AMD64
323%ifdef RT_OS_WINDOWS
324 mov rax, r8 ; eax = size of parameters
325%else ; !RT_OS_WINDOWS
326 mov rax, rdx ; rax = size of parameters
327 mov rcx, rdi ; rcx = first parameter
328 mov rdx, rsi ; rdx = second parameter
329%endif ; !RT_OS_WINDOWS
330%else ; !RT_ARCH_AMD64
331 mov eax, [esp + 10h] ; eax = size of parameters
332 mov ecx, [esp + 04h] ; ecx = first parameter
333 mov edx, [esp + 08h] ; edx = second parameter
334%endif
335
336 ; switch on size
337%ifdef CAN_DO_8_BYTE_OP
338 cmp al, 8
339 je short .do_qword ; 8 bytes variant
340%endif
341 cmp al, 4
342 je short .do_dword ; 4 bytes variant
343 cmp al, 2
344 je short .do_word ; 2 byte variant
345 cmp al, 1
346 je short .do_byte ; 1 bytes variant
347 int3
348
349 ; workers
350%ifdef RT_ARCH_AMD64
351.do_qword:
352 or [MY_PTR_REG], rdx ; do 8 bytes OR
353 jmp short .done
354%endif
355
356.do_dword:
357 or [MY_PTR_REG], edx ; do 4 bytes OR
358 jmp short .done
359
360.do_word:
361 or [MY_PTR_REG], dx ; do 2 bytes OR
362 jmp short .done
363
364.do_byte:
365 or [MY_PTR_REG], dl ; do 1 byte OR
366
367 ; collect flags and return.
368.done:
369 pushf
370 pop MY_RET_REG
371 retn
372
373%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
374.do_qword:
375 db 0xea ; jmp far .sixtyfourbit_mode
376 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
377BITS 64
378.sixtyfourbit_mode:
379 and esp, 0ffffffffh
380 and MY_PTR_REG, 0ffffffffh
381 mov rdx, qword [rsp + 08h] ; rdx = second parameter
382 or [MY_PTR_REG64], rdx ; do 8 bytes OR
383 jmp far [.fpret wrt rip]
384.fpret: ; 16:32 Pointer to .done.
385 dd .done, NAME(SUPR0AbsKernelCS)
386BITS 32
387%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
388ENDPROC EMEmulateOr
389
390
391;;
392; Emulate LOCK OR instruction.
393; VMMDECL(int) EMEmulateLockOr(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
394;
395; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
396; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
397; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value.
398; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Size of the operation - 1, 2, 4 or 8 bytes.
399; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Where to store the eflags on success.
400; only arithmetic flags are valid.
401align 16
402BEGINPROC EMEmulateLockOr
403%ifdef RT_ARCH_AMD64
404%ifdef RT_OS_WINDOWS
405 mov rax, r8 ; eax = size of parameters
406%else ; !RT_OS_WINDOWS
407 mov r9, rcx ; r9 = eflags result ptr
408 mov rax, rdx ; rax = size of parameters
409 mov rcx, rdi ; rcx = first parameter
410 mov rdx, rsi ; rdx = second parameter
411%endif ; !RT_OS_WINDOWS
412%else ; !RT_ARCH_AMD64
413 mov eax, [esp + 10h] ; eax = size of parameters
414 mov ecx, [esp + 04h] ; ecx = first parameter (MY_PTR_REG)
415 mov edx, [esp + 08h] ; edx = second parameter
416%endif
417
418 ; switch on size
419%ifdef CAN_DO_8_BYTE_OP
420 cmp al, 8
421 je short .do_qword ; 8 bytes variant
422%endif
423 cmp al, 4
424 je short .do_dword ; 4 bytes variant
425 cmp al, 2
426 je short .do_word ; 2 byte variant
427 cmp al, 1
428 je short .do_byte ; 1 bytes variant
429 int3
430
431 ; workers
432%ifdef RT_ARCH_AMD64
433.do_qword:
434 lock or [MY_PTR_REG], rdx ; do 8 bytes OR
435 jmp short .done
436%endif
437
438.do_dword:
439 lock or [MY_PTR_REG], edx ; do 4 bytes OR
440 jmp short .done
441
442.do_word:
443 lock or [MY_PTR_REG], dx ; do 2 bytes OR
444 jmp short .done
445
446.do_byte:
447 lock or [MY_PTR_REG], dl ; do 1 byte OR
448
449 ; collect flags and return.
450.done:
451 pushf
452%ifdef RT_ARCH_AMD64
453 pop rax
454 mov [r9], eax
455%else ; !RT_ARCH_AMD64
456 mov eax, [esp + 14h + 4]
457 pop dword [eax]
458%endif
459 mov eax, VINF_SUCCESS
460 retn
461
462%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
463.do_qword:
464 db 0xea ; jmp far .sixtyfourbit_mode
465 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
466BITS 64
467.sixtyfourbit_mode:
468 and esp, 0ffffffffh
469 and MY_PTR_REG, 0ffffffffh
470 mov rdx, qword [rsp + 08h] ; rdx = second parameter
471 lock or [MY_PTR_REG64], rdx ; do 8 bytes OR
472 jmp far [.fpret wrt rip]
473.fpret: ; 16:32 Pointer to .done.
474 dd .done, NAME(SUPR0AbsKernelCS)
475BITS 32
476%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
477
478
479%ifdef IN_RC
480; #PF resume point.
481GLOBALNAME EMEmulateLockOr_Error
482 mov eax, VERR_ACCESS_DENIED
483 ret
484%endif
485
486ENDPROC EMEmulateLockOr
487
488
489;;
490; Emulate XOR instruction, CDECL calling conv.
491; VMMDECL(uint32_t) EMEmulateXor(void *pvParam1, uint64_t u64Param2, size_t cb);
492;
493; @returns EFLAGS after the operation, only arithmetic flags are valid.
494; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
495; @param [esp + 08h] Param 2 - Second parameter.
496; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
497; @uses eax, ecx, edx
498;
499align 16
500BEGINPROC EMEmulateXor
501%ifdef RT_ARCH_AMD64
502%ifdef RT_OS_WINDOWS
503 mov rax, r8 ; eax = size of parameters
504%else ; !RT_OS_WINDOWS
505 mov rax, rdx ; rax = size of parameters
506 mov rcx, rdi ; rcx = first parameter
507 mov rdx, rsi ; rdx = second parameter
508%endif ; !RT_OS_WINDOWS
509%else ; !RT_ARCH_AMD64
510 mov eax, [esp + 10h] ; eax = size of parameters
511 mov ecx, [esp + 04h] ; ecx = first parameter
512 mov edx, [esp + 08h] ; edx = second parameter
513%endif
514
515 ; switch on size
516%ifdef CAN_DO_8_BYTE_OP
517 cmp al, 8
518 je short .do_qword ; 8 bytes variant
519%endif
520 cmp al, 4
521 je short .do_dword ; 4 bytes variant
522 cmp al, 2
523 je short .do_word ; 2 byte variant
524 cmp al, 1
525 je short .do_byte ; 1 bytes variant
526 int3
527
528 ; workers
529%ifdef RT_ARCH_AMD64
530.do_qword:
531 xor [MY_PTR_REG], rdx ; do 8 bytes XOR
532 jmp short .done
533%endif
534
535.do_dword:
536 xor [MY_PTR_REG], edx ; do 4 bytes XOR
537 jmp short .done
538
539.do_word:
540 xor [MY_PTR_REG], dx ; do 2 bytes XOR
541 jmp short .done
542
543.do_byte:
544 xor [MY_PTR_REG], dl ; do 1 byte XOR
545
546 ; collect flags and return.
547.done:
548 pushf
549 pop MY_RET_REG
550 retn
551
552%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
553.do_qword:
554 db 0xea ; jmp far .sixtyfourbit_mode
555 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
556BITS 64
557.sixtyfourbit_mode:
558 and esp, 0ffffffffh
559 and MY_PTR_REG, 0ffffffffh
560 mov rdx, qword [rsp + 08h] ; rdx = second parameter
561 xor [MY_PTR_REG64], rdx ; do 8 bytes XOR
562 jmp far [.fpret wrt rip]
563.fpret: ; 16:32 Pointer to .done.
564 dd .done, NAME(SUPR0AbsKernelCS)
565BITS 32
566%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
567ENDPROC EMEmulateXor
568
569;;
570; Emulate LOCK XOR instruction.
571; VMMDECL(int) EMEmulateLockXor(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
572;
573; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
574; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
575; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value.
576; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Size of the operation - 1, 2, 4 or 8 bytes.
577; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Where to store the eflags on success.
578; only arithmetic flags are valid.
579align 16
580BEGINPROC EMEmulateLockXor
581%ifdef RT_ARCH_AMD64
582%ifdef RT_OS_WINDOWS
583 mov rax, r8 ; eax = size of parameters
584%else ; !RT_OS_WINDOWS
585 mov r9, rcx ; r9 = eflags result ptr
586 mov rax, rdx ; rax = size of parameters
587 mov rcx, rdi ; rcx = first parameter
588 mov rdx, rsi ; rdx = second parameter
589%endif ; !RT_OS_WINDOWS
590%else ; !RT_ARCH_AMD64
591 mov eax, [esp + 10h] ; eax = size of parameters
592 mov ecx, [esp + 04h] ; ecx = first parameter (MY_PTR_REG)
593 mov edx, [esp + 08h] ; edx = second parameter
594%endif
595
596 ; switch on size
597%ifdef CAN_DO_8_BYTE_OP
598 cmp al, 8
599 je short .do_qword ; 8 bytes variant
600%endif
601 cmp al, 4
602 je short .do_dword ; 4 bytes variant
603 cmp al, 2
604 je short .do_word ; 2 byte variant
605 cmp al, 1
606 je short .do_byte ; 1 bytes variant
607 int3
608
609 ; workers
610%ifdef RT_ARCH_AMD64
611.do_qword:
612 lock xor [MY_PTR_REG], rdx ; do 8 bytes OR
613 jmp short .done
614%endif
615
616.do_dword:
617 lock xor [MY_PTR_REG], edx ; do 4 bytes OR
618 jmp short .done
619
620.do_word:
621 lock xor [MY_PTR_REG], dx ; do 2 bytes OR
622 jmp short .done
623
624.do_byte:
625 lock xor [MY_PTR_REG], dl ; do 1 byte OR
626
627 ; collect flags and return.
628.done:
629 pushf
630%ifdef RT_ARCH_AMD64
631 pop rax
632 mov [r9], eax
633%else ; !RT_ARCH_AMD64
634 mov eax, [esp + 14h + 4]
635 pop dword [eax]
636%endif
637 mov eax, VINF_SUCCESS
638 retn
639
640%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
641.do_qword:
642 db 0xea ; jmp far .sixtyfourbit_mode
643 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
644BITS 64
645.sixtyfourbit_mode:
646 and esp, 0ffffffffh
647 and MY_PTR_REG, 0ffffffffh
648 mov rdx, qword [rsp + 08h] ; rdx = second parameter
649 lock xor [MY_PTR_REG64], rdx ; do 8 bytes OR
650 jmp far [.fpret wrt rip]
651.fpret: ; 16:32 Pointer to .done.
652 dd .done, NAME(SUPR0AbsKernelCS)
653BITS 32
654%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
655
656
657%ifdef IN_RC
658; #PF resume point.
659GLOBALNAME EMEmulateLockXor_Error
660 mov eax, VERR_ACCESS_DENIED
661 ret
662%endif
663
664ENDPROC EMEmulateLockXor
665
666;;
667; Emulate INC instruction, CDECL calling conv.
668; VMMDECL(uint32_t) EMEmulateInc(void *pvParam1, size_t cb);
669;
670; @returns EFLAGS after the operation, only arithmetic flags are valid.
671; @param [esp + 04h] rdi rcx Param 1 - First parameter - pointer to data item.
672; @param [esp + 08h] rsi rdx Param 2 - Size of parameters, only 1/2/4 is valid.
673; @uses eax, ecx, edx
674;
675align 16
676BEGINPROC EMEmulateInc
677%ifdef RT_ARCH_AMD64
678%ifdef RT_OS_WINDOWS
679 mov rax, rdx ; eax = size of parameters
680%else ; !RT_OS_WINDOWS
681 mov rax, rsi ; eax = size of parameters
682 mov rcx, rdi ; rcx = first parameter
683%endif ; !RT_OS_WINDOWS
684%else ; !RT_ARCH_AMD64
685 mov eax, [esp + 08h] ; eax = size of parameters
686 mov ecx, [esp + 04h] ; ecx = first parameter
687%endif
688
689 ; switch on size
690%ifdef RT_ARCH_AMD64
691 cmp al, 8
692 je short .do_qword ; 8 bytes variant
693%endif
694 cmp al, 4
695 je short .do_dword ; 4 bytes variant
696 cmp al, 2
697 je short .do_word ; 2 byte variant
698 cmp al, 1
699 je short .do_byte ; 1 bytes variant
700 int3
701
702 ; workers
703%ifdef RT_ARCH_AMD64
704.do_qword:
705 inc qword [MY_PTR_REG] ; do 8 bytes INC
706 jmp short .done
707%endif
708
709.do_dword:
710 inc dword [MY_PTR_REG] ; do 4 bytes INC
711 jmp short .done
712
713.do_word:
714 inc word [MY_PTR_REG] ; do 2 bytes INC
715 jmp short .done
716
717.do_byte:
718 inc byte [MY_PTR_REG] ; do 1 byte INC
719 jmp short .done
720
721 ; collect flags and return.
722.done:
723 pushf
724 pop MY_RET_REG
725 retn
726ENDPROC EMEmulateInc
727
728
729;;
730; Emulate DEC instruction, CDECL calling conv.
731; VMMDECL(uint32_t) EMEmulateDec(void *pvParam1, size_t cb);
732;
733; @returns EFLAGS after the operation, only arithmetic flags are valid.
734; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
735; @param [esp + 08h] Param 2 - Size of parameters, only 1/2/4 is valid.
736; @uses eax, ecx, edx
737;
738align 16
739BEGINPROC EMEmulateDec
740%ifdef RT_ARCH_AMD64
741%ifdef RT_OS_WINDOWS
742 mov rax, rdx ; eax = size of parameters
743%else ; !RT_OS_WINDOWS
744 mov rax, rsi ; eax = size of parameters
745 mov rcx, rdi ; rcx = first parameter
746%endif ; !RT_OS_WINDOWS
747%else ; !RT_ARCH_AMD64
748 mov eax, [esp + 08h] ; eax = size of parameters
749 mov ecx, [esp + 04h] ; ecx = first parameter
750%endif
751
752 ; switch on size
753%ifdef RT_ARCH_AMD64
754 cmp al, 8
755 je short .do_qword ; 8 bytes variant
756%endif
757 cmp al, 4
758 je short .do_dword ; 4 bytes variant
759 cmp al, 2
760 je short .do_word ; 2 byte variant
761 cmp al, 1
762 je short .do_byte ; 1 bytes variant
763 int3
764
765 ; workers
766%ifdef RT_ARCH_AMD64
767.do_qword:
768 dec qword [MY_PTR_REG] ; do 8 bytes DEC
769 jmp short .done
770%endif
771
772.do_dword:
773 dec dword [MY_PTR_REG] ; do 4 bytes DEC
774 jmp short .done
775
776.do_word:
777 dec word [MY_PTR_REG] ; do 2 bytes DEC
778 jmp short .done
779
780.do_byte:
781 dec byte [MY_PTR_REG] ; do 1 byte DEC
782 jmp short .done
783
784 ; collect flags and return.
785.done:
786 pushf
787 pop MY_RET_REG
788 retn
789ENDPROC EMEmulateDec
790
791
792;;
793; Emulate ADD instruction, CDECL calling conv.
794; VMMDECL(uint32_t) EMEmulateAdd(void *pvParam1, uint64_t u64Param2, size_t cb);
795;
796; @returns EFLAGS after the operation, only arithmetic flags are valid.
797; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
798; @param [esp + 08h] Param 2 - Second parameter.
799; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
800; @uses eax, ecx, edx
801;
802align 16
803BEGINPROC EMEmulateAdd
804%ifdef RT_ARCH_AMD64
805%ifdef RT_OS_WINDOWS
806 mov rax, r8 ; eax = size of parameters
807%else ; !RT_OS_WINDOWS
808 mov rax, rdx ; rax = size of parameters
809 mov rcx, rdi ; rcx = first parameter
810 mov rdx, rsi ; rdx = second parameter
811%endif ; !RT_OS_WINDOWS
812%else ; !RT_ARCH_AMD64
813 mov eax, [esp + 10h] ; eax = size of parameters
814 mov ecx, [esp + 04h] ; ecx = first parameter
815 mov edx, [esp + 08h] ; edx = second parameter
816%endif
817
818 ; switch on size
819%ifdef CAN_DO_8_BYTE_OP
820 cmp al, 8
821 je short .do_qword ; 8 bytes variant
822%endif
823 cmp al, 4
824 je short .do_dword ; 4 bytes variant
825 cmp al, 2
826 je short .do_word ; 2 byte variant
827 cmp al, 1
828 je short .do_byte ; 1 bytes variant
829 int3
830
831 ; workers
832%ifdef RT_ARCH_AMD64
833.do_qword:
834 add [MY_PTR_REG], rdx ; do 8 bytes ADD
835 jmp short .done
836%endif
837
838.do_dword:
839 add [MY_PTR_REG], edx ; do 4 bytes ADD
840 jmp short .done
841
842.do_word:
843 add [MY_PTR_REG], dx ; do 2 bytes ADD
844 jmp short .done
845
846.do_byte:
847 add [MY_PTR_REG], dl ; do 1 byte ADD
848
849 ; collect flags and return.
850.done:
851 pushf
852 pop MY_RET_REG
853 retn
854
855%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
856.do_qword:
857 db 0xea ; jmp far .sixtyfourbit_mode
858 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
859BITS 64
860.sixtyfourbit_mode:
861 and esp, 0ffffffffh
862 and MY_PTR_REG, 0ffffffffh
863 mov rdx, qword [rsp + 08h] ; rdx = second parameter
864 add [MY_PTR_REG64], rdx ; do 8 bytes ADD
865 jmp far [.fpret wrt rip]
866.fpret: ; 16:32 Pointer to .done.
867 dd .done, NAME(SUPR0AbsKernelCS)
868BITS 32
869%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
870ENDPROC EMEmulateAdd
871
872
873;;
874; Emulate ADC instruction, CDECL calling conv.
875; VMMDECL(uint32_t) EMEmulateAdcWithCarrySet(void *pvParam1, uint64_t u64Param2, size_t cb);
876;
877; @returns EFLAGS after the operation, only arithmetic flags are valid.
878; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
879; @param [esp + 08h] Param 2 - Second parameter.
880; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
881; @uses eax, ecx, edx
882;
883align 16
884BEGINPROC EMEmulateAdcWithCarrySet
885%ifdef RT_ARCH_AMD64
886%ifdef RT_OS_WINDOWS
887 mov rax, r8 ; eax = size of parameters
888%else ; !RT_OS_WINDOWS
889 mov rax, rdx ; rax = size of parameters
890 mov rcx, rdi ; rcx = first parameter
891 mov rdx, rsi ; rdx = second parameter
892%endif ; !RT_OS_WINDOWS
893%else ; !RT_ARCH_AMD64
894 mov eax, [esp + 10h] ; eax = size of parameters
895 mov ecx, [esp + 04h] ; ecx = first parameter
896 mov edx, [esp + 08h] ; edx = second parameter
897%endif
898
899 ; switch on size
900%ifdef CAN_DO_8_BYTE_OP
901 cmp al, 8
902 je short .do_qword ; 8 bytes variant
903%endif
904 cmp al, 4
905 je short .do_dword ; 4 bytes variant
906 cmp al, 2
907 je short .do_word ; 2 byte variant
908 cmp al, 1
909 je short .do_byte ; 1 bytes variant
910 int3
911
912 ; workers
913%ifdef RT_ARCH_AMD64
914.do_qword:
915 stc ; set carry flag
916 adc [MY_PTR_REG], rdx ; do 8 bytes ADC
917 jmp short .done
918%endif
919
920.do_dword:
921 stc ; set carry flag
922 adc [MY_PTR_REG], edx ; do 4 bytes ADC
923 jmp short .done
924
925.do_word:
926 stc ; set carry flag
927 adc [MY_PTR_REG], dx ; do 2 bytes ADC
928 jmp short .done
929
930.do_byte:
931 stc ; set carry flag
932 adc [MY_PTR_REG], dl ; do 1 byte ADC
933
934 ; collect flags and return.
935.done:
936 pushf
937 pop MY_RET_REG
938 retn
939
940%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
941.do_qword:
942 db 0xea ; jmp far .sixtyfourbit_mode
943 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
944BITS 64
945.sixtyfourbit_mode:
946 and esp, 0ffffffffh
947 and MY_PTR_REG, 0ffffffffh
948 mov rdx, qword [rsp + 08h] ; rdx = second parameter
949 stc ; set carry flag
950 adc [MY_PTR_REG64], rdx ; do 8 bytes ADC
951 jmp far [.fpret wrt rip]
952.fpret: ; 16:32 Pointer to .done.
953 dd .done, NAME(SUPR0AbsKernelCS)
954BITS 32
955%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
956ENDPROC EMEmulateAdcWithCarrySet
957
958
959;;
960; Emulate SUB instruction, CDECL calling conv.
961; VMMDECL(uint32_t) EMEmulateSub(void *pvParam1, uint64_t u64Param2, size_t cb);
962;
963; @returns EFLAGS after the operation, only arithmetic flags are valid.
964; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
965; @param [esp + 08h] Param 2 - Second parameter.
966; @param [esp + 10h] Param 3 - Size of parameters, only 1/2/4/8 (64 bits host only) is valid.
967; @uses eax, ecx, edx
968;
969align 16
970BEGINPROC EMEmulateSub
971%ifdef RT_ARCH_AMD64
972%ifdef RT_OS_WINDOWS
973 mov rax, r8 ; eax = size of parameters
974%else ; !RT_OS_WINDOWS
975 mov rax, rdx ; rax = size of parameters
976 mov rcx, rdi ; rcx = first parameter
977 mov rdx, rsi ; rdx = second parameter
978%endif ; !RT_OS_WINDOWS
979%else ; !RT_ARCH_AMD64
980 mov eax, [esp + 10h] ; eax = size of parameters
981 mov ecx, [esp + 04h] ; ecx = first parameter
982 mov edx, [esp + 08h] ; edx = second parameter
983%endif
984
985 ; switch on size
986%ifdef CAN_DO_8_BYTE_OP
987 cmp al, 8
988 je short .do_qword ; 8 bytes variant
989%endif
990 cmp al, 4
991 je short .do_dword ; 4 bytes variant
992 cmp al, 2
993 je short .do_word ; 2 byte variant
994 cmp al, 1
995 je short .do_byte ; 1 bytes variant
996 int3
997
998 ; workers
999%ifdef RT_ARCH_AMD64
1000.do_qword:
1001 sub [MY_PTR_REG], rdx ; do 8 bytes SUB
1002 jmp short .done
1003%endif
1004
1005.do_dword:
1006 sub [MY_PTR_REG], edx ; do 4 bytes SUB
1007 jmp short .done
1008
1009.do_word:
1010 sub [MY_PTR_REG], dx ; do 2 bytes SUB
1011 jmp short .done
1012
1013.do_byte:
1014 sub [MY_PTR_REG], dl ; do 1 byte SUB
1015
1016 ; collect flags and return.
1017.done:
1018 pushf
1019 pop MY_RET_REG
1020 retn
1021
1022%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1023.do_qword:
1024 db 0xea ; jmp far .sixtyfourbit_mode
1025 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1026BITS 64
1027.sixtyfourbit_mode:
1028 and esp, 0ffffffffh
1029 and MY_PTR_REG, 0ffffffffh
1030 mov rdx, qword [rsp + 08h] ; rdx = second parameter
1031 sub [MY_PTR_REG64], rdx ; do 8 bytes SUB
1032 jmp far [.fpret wrt rip]
1033.fpret: ; 16:32 Pointer to .done.
1034 dd .done, NAME(SUPR0AbsKernelCS)
1035BITS 32
1036%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1037ENDPROC EMEmulateSub
1038
1039
1040;;
1041; Emulate BTR instruction, CDECL calling conv.
1042; VMMDECL(uint32_t) EMEmulateBtr(void *pvParam1, uint64_t u64Param2);
1043;
1044; @returns EFLAGS after the operation, only arithmetic flags are valid.
1045; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
1046; @param [esp + 08h] Param 2 - Second parameter.
1047; @uses eax, ecx, edx
1048;
1049align 16
1050BEGINPROC EMEmulateBtr
1051%ifdef RT_ARCH_AMD64
1052%ifndef RT_OS_WINDOWS
1053 mov rcx, rdi ; rcx = first parameter
1054 mov rdx, rsi ; rdx = second parameter
1055%endif ; !RT_OS_WINDOWS
1056%else ; !RT_ARCH_AMD64
1057 mov ecx, [esp + 04h] ; ecx = first parameter
1058 mov edx, [esp + 08h] ; edx = second parameter
1059%endif
1060
1061 and edx, 7
1062 btr [MY_PTR_REG], edx
1063
1064 ; collect flags and return.
1065 pushf
1066 pop MY_RET_REG
1067 retn
1068ENDPROC EMEmulateBtr
1069
1070;;
1071; Emulate LOCK BTR instruction.
1072; VMMDECL(int) EMEmulateLockBtr(void *pvParam1, uint64_t u64Param2, RTGCUINTREG32 *pf);
1073;
1074; @returns VINF_SUCCESS on success, VERR_ACCESS_DENIED on \#PF (GC only).
1075; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to data item (the real stuff).
1076; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Second parameter- the immediate / register value. (really an 8 byte value)
1077; @param [esp + 10h] gcc:rdx msc:r8 Param 3 - Where to store the eflags on success.
1078;
1079align 16
1080BEGINPROC EMEmulateLockBtr
1081%ifdef RT_ARCH_AMD64
1082 %ifdef RT_OS_WINDOWS
1083 mov rax, r8 ; rax = third parameter
1084 %else ; !RT_OS_WINDOWS
1085 mov rcx, rdi ; rcx = first parameter
1086 mov rax, rdx ; rax = third parameter
1087 mov rdx, rsi ; rdx = second parameter
1088 %endif ; !RT_OS_WINDOWS
1089%else ; !RT_ARCH_AMD64
1090 mov ecx, [esp + 04h] ; ecx = first parameter
1091 mov edx, [esp + 08h] ; edx = second parameter
1092 mov eax, [esp + 10h] ; eax = third parameter
1093%endif
1094
1095 lock btr [MY_PTR_REG], edx
1096
1097 ; collect flags and return.
1098 pushf
1099 pop xDX
1100 mov [xAX], edx
1101 mov eax, VINF_SUCCESS
1102 retn
1103
1104%ifdef IN_RC
1105; #PF resume point.
1106GLOBALNAME EMEmulateLockBtr_Error
1107 mov eax, VERR_ACCESS_DENIED
1108 ret
1109%endif
1110
1111ENDPROC EMEmulateLockBtr
1112
1113
1114;;
1115; Emulate BTC instruction, CDECL calling conv.
1116; VMMDECL(uint32_t) EMEmulateBtc(void *pvParam1, uint64_t u64Param2);
1117;
1118; @returns EFLAGS after the operation, only arithmetic flags are valid.
1119; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
1120; @param [esp + 08h] Param 2 - Second parameter.
1121; @uses eax, ecx, edx
1122;
1123align 16
1124BEGINPROC EMEmulateBtc
1125%ifdef RT_ARCH_AMD64
1126%ifndef RT_OS_WINDOWS
1127 mov rcx, rdi ; rcx = first parameter
1128 mov rdx, rsi ; rdx = second parameter
1129%endif ; !RT_OS_WINDOWS
1130%else ; !RT_ARCH_AMD64
1131 mov ecx, [esp + 04h] ; ecx = first parameter
1132 mov edx, [esp + 08h] ; edx = second parameter
1133%endif
1134
1135 and edx, 7
1136 btc [MY_PTR_REG], edx
1137
1138 ; collect flags and return.
1139 pushf
1140 pop MY_RET_REG
1141 retn
1142ENDPROC EMEmulateBtc
1143
1144
1145;;
1146; Emulate BTS instruction, CDECL calling conv.
1147; VMMDECL(uint32_t) EMEmulateBts(void *pvParam1, uint64_t u64Param2);
1148;
1149; @returns EFLAGS after the operation, only arithmetic flags are valid.
1150; @param [esp + 04h] Param 1 - First parameter - pointer to data item.
1151; @param [esp + 08h] Param 2 - Second parameter.
1152; @uses eax, ecx, edx
1153;
1154align 16
1155BEGINPROC EMEmulateBts
1156%ifdef RT_ARCH_AMD64
1157%ifndef RT_OS_WINDOWS
1158 mov rcx, rdi ; rcx = first parameter
1159 mov rdx, rsi ; rdx = second parameter
1160%endif ; !RT_OS_WINDOWS
1161%else ; !RT_ARCH_AMD64
1162 mov ecx, [esp + 04h] ; ecx = first parameter
1163 mov edx, [esp + 08h] ; edx = second parameter
1164%endif
1165
1166 and edx, 7
1167 bts [MY_PTR_REG], edx
1168
1169 ; collect flags and return.
1170 pushf
1171 pop MY_RET_REG
1172 retn
1173ENDPROC EMEmulateBts
1174
1175
1176;;
1177; Emulate LOCK CMPXCHG instruction, CDECL calling conv.
1178; VMMDECL(uint32_t) EMEmulateLockCmpXchg(void *pvParam1, uint64_t *pu64Param2, uint64_t u64Param3, size_t cbSize);
1179;
1180; @returns EFLAGS after the operation, only arithmetic flags are valid.
1181; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1182; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - pointer to second parameter (eax)
1183; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - third parameter
1184; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Size of parameters, only 1/2/4/8 is valid
1185; @uses eax, ecx, edx
1186;
1187align 16
1188BEGINPROC EMEmulateLockCmpXchg
1189 push xBX
1190%ifdef RT_ARCH_AMD64
1191%ifdef RT_OS_WINDOWS
1192 ; rcx contains the first parameter already
1193 mov rbx, rdx ; rdx = 2nd parameter
1194 mov rdx, r8 ; r8 = 3rd parameter
1195 mov rax, r9 ; r9 = size of parameters
1196%else
1197 mov rax, rcx ; rcx = size of parameters (4th)
1198 mov rcx, rdi ; rdi = 1st parameter
1199 mov rbx, rsi ; rsi = second parameter
1200 ;rdx contains the 3rd parameter already
1201%endif ; !RT_OS_WINDOWS
1202%else ; !RT_ARCH_AMD64
1203 mov ecx, [esp + 04h + 4] ; ecx = first parameter
1204 mov ebx, [esp + 08h + 4] ; ebx = 2nd parameter (eax)
1205 mov edx, [esp + 0ch + 4] ; edx = third parameter
1206 mov eax, [esp + 14h + 4] ; eax = size of parameters
1207%endif
1208
1209%ifdef CAN_DO_8_BYTE_OP
1210 cmp al, 8
1211 je short .do_qword ; 8 bytes variant
1212%endif
1213 cmp al, 4
1214 je short .do_dword ; 4 bytes variant
1215 cmp al, 2
1216 je short .do_word ; 2 byte variant
1217 cmp al, 1
1218 je short .do_byte ; 1 bytes variant
1219 int3
1220
1221%ifdef RT_ARCH_AMD64
1222.do_qword:
1223 ; load 2nd parameter's value
1224 mov rax, qword [rbx]
1225
1226 lock cmpxchg qword [rcx], rdx ; do 8 bytes CMPXCHG
1227 mov qword [rbx], rax
1228 jmp short .done
1229%endif
1230
1231.do_dword:
1232 ; load 2nd parameter's value
1233 mov eax, dword [xBX]
1234
1235 lock cmpxchg dword [xCX], edx ; do 4 bytes CMPXCHG
1236 mov dword [xBX], eax
1237 jmp short .done
1238
1239.do_word:
1240 ; load 2nd parameter's value
1241 mov eax, dword [xBX]
1242
1243 lock cmpxchg word [xCX], dx ; do 2 bytes CMPXCHG
1244 mov word [xBX], ax
1245 jmp short .done
1246
1247.do_byte:
1248 ; load 2nd parameter's value
1249 mov eax, dword [xBX]
1250
1251 lock cmpxchg byte [xCX], dl ; do 1 byte CMPXCHG
1252 mov byte [xBX], al
1253
1254.done:
1255 ; collect flags and return.
1256 pushf
1257 pop MY_RET_REG
1258
1259 pop xBX
1260 retn
1261
1262%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1263.do_qword:
1264 db 0xea ; jmp far .sixtyfourbit_mode
1265 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1266BITS 64
1267.sixtyfourbit_mode:
1268 and ebx, 0ffffffffh
1269 and esp, 0ffffffffh
1270 and ecx, 0ffffffffh
1271 mov rax, qword [rbx] ; load 2nd parameter's value
1272 mov rdx, qword [rsp + 0ch + 4] ; rdx = third parameter
1273
1274 lock cmpxchg qword [rcx], rdx ; do 8 byte CMPXCHG
1275 mov qword [rbx], rax
1276 jmp far [.fpret wrt rip]
1277.fpret: ; 16:32 Pointer to .done.
1278 dd .done, NAME(SUPR0AbsKernelCS)
1279BITS 32
1280%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1281ENDPROC EMEmulateLockCmpXchg
1282
1283
1284;;
1285; Emulate CMPXCHG instruction, CDECL calling conv.
1286; VMMDECL(uint32_t) EMEmulateCmpXchg(void *pvParam1, uint64_t *pu32Param2, uint64_t u32Param3, size_t cbSize);
1287;
1288; @returns EFLAGS after the operation, only arithmetic flags are valid.
1289; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1290; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - pointer to second parameter (eax)
1291; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - third parameter
1292; @param [esp + 14h] gcc:rcx msc:r9 Param 4 - Size of parameters, only 1/2/4 is valid.
1293; @uses eax, ecx, edx
1294;
1295align 16
1296BEGINPROC EMEmulateCmpXchg
1297 push xBX
1298%ifdef RT_ARCH_AMD64
1299%ifdef RT_OS_WINDOWS
1300 ; rcx contains the first parameter already
1301 mov rbx, rdx ; rdx = 2nd parameter
1302 mov rdx, r8 ; r8 = 3rd parameter
1303 mov rax, r9 ; r9 = size of parameters
1304%else
1305 mov rax, rcx ; rcx = size of parameters (4th)
1306 mov rcx, rdi ; rdi = 1st parameter
1307 mov rbx, rsi ; rsi = second parameter
1308 ;rdx contains the 3rd parameter already
1309%endif ; !RT_OS_WINDOWS
1310%else ; !RT_ARCH_AMD64
1311 mov ecx, [esp + 04h + 4] ; ecx = first parameter
1312 mov ebx, [esp + 08h + 4] ; ebx = 2nd parameter (eax)
1313 mov edx, [esp + 0ch + 4] ; edx = third parameter
1314 mov eax, [esp + 14h + 4] ; eax = size of parameters
1315%endif
1316
1317%ifdef CAN_DO_8_BYTE_OP
1318 cmp al, 8
1319 je short .do_qword ; 8 bytes variant
1320%endif
1321 cmp al, 4
1322 je short .do_dword ; 4 bytes variant
1323 cmp al, 2
1324 je short .do_word ; 2 byte variant
1325 cmp al, 1
1326 je short .do_byte ; 1 bytes variant
1327 int3
1328
1329%ifdef RT_ARCH_AMD64
1330.do_qword:
1331 ; load 2nd parameter's value
1332 mov rax, qword [rbx]
1333
1334 cmpxchg qword [rcx], rdx ; do 8 bytes CMPXCHG
1335 mov qword [rbx], rax
1336 jmp short .done
1337%endif
1338
1339.do_dword:
1340 ; load 2nd parameter's value
1341 mov eax, dword [xBX]
1342
1343 cmpxchg dword [xCX], edx ; do 4 bytes CMPXCHG
1344 mov dword [xBX], eax
1345 jmp short .done
1346
1347.do_word:
1348 ; load 2nd parameter's value
1349 mov eax, dword [xBX]
1350
1351 cmpxchg word [xCX], dx ; do 2 bytes CMPXCHG
1352 mov word [xBX], ax
1353 jmp short .done
1354
1355.do_byte:
1356 ; load 2nd parameter's value
1357 mov eax, dword [xBX]
1358
1359 cmpxchg byte [xCX], dl ; do 1 byte CMPXCHG
1360 mov byte [xBX], al
1361
1362.done:
1363 ; collect flags and return.
1364 pushf
1365 pop MY_RET_REG
1366
1367 pop xBX
1368 retn
1369
1370%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1371.do_qword:
1372 db 0xea ; jmp far .sixtyfourbit_mode
1373 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1374BITS 64
1375.sixtyfourbit_mode:
1376 and ebx, 0ffffffffh
1377 and esp, 0ffffffffh
1378 and ecx, 0ffffffffh
1379 mov rax, qword [rbx] ; load 2nd parameter's value
1380 mov rdx, qword [rsp + 0ch + 4] ; rdx = third parameter
1381
1382 cmpxchg qword [rcx], rdx ; do 8 byte CMPXCHG
1383 mov qword [rbx], rax
1384 jmp far [.fpret wrt rip]
1385.fpret: ; 16:32 Pointer to .done.
1386 dd .done, NAME(SUPR0AbsKernelCS)
1387BITS 32
1388%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
1389ENDPROC EMEmulateCmpXchg
1390
1391
1392;;
1393; Emulate LOCK CMPXCHG8B instruction, CDECL calling conv.
1394; VMMDECL(uint32_t) EMEmulateLockCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);
1395;
1396; @returns EFLAGS after the operation, only the ZF flag is valid.
1397; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1398; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Address of the eax register
1399; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Address of the edx register
1400; @param [esp + 10h] gcc:rcx msc:r9 Param 4 - EBX
1401; @param [esp + 14h] gcc:r8 msc:[rsp + 8] Param 5 - ECX
1402; @uses eax, ecx, edx
1403;
1404align 16
1405BEGINPROC EMEmulateLockCmpXchg8b
1406 push xBP
1407 push xBX
1408%ifdef RT_ARCH_AMD64
1409 %ifdef RT_OS_WINDOWS
1410 mov rbp, rcx
1411 mov r10, rdx
1412 mov eax, dword [rdx]
1413 mov edx, dword [r8]
1414 mov rbx, r9
1415 mov ecx, [rsp + 28h + 16]
1416 %else
1417 mov rbp, rdi
1418 mov r10, rdx
1419 mov eax, dword [rsi]
1420 mov edx, dword [rdx]
1421 mov rbx, rcx
1422 mov rcx, r8
1423 %endif
1424%else
1425 mov ebp, [esp + 04h + 8] ; ebp = first parameter
1426 mov eax, [esp + 08h + 8] ; &EAX
1427 mov eax, dword [eax]
1428 mov edx, [esp + 0ch + 8] ; &EDX
1429 mov edx, dword [edx]
1430 mov ebx, [esp + 10h + 8] ; EBX
1431 mov ecx, [esp + 14h + 8] ; ECX
1432%endif
1433
1434%ifdef RT_OS_OS2
1435 lock cmpxchg8b [xBP] ; do CMPXCHG8B
1436%else
1437 lock cmpxchg8b qword [xBP] ; do CMPXCHG8B
1438%endif
1439
1440%ifdef RT_ARCH_AMD64
1441 %ifdef RT_OS_WINDOWS
1442 mov dword [r10], eax
1443 mov dword [r8], edx
1444 %else
1445 mov dword [rsi], eax
1446 mov dword [r10], edx
1447 %endif
1448%else
1449 mov ebx, dword [esp + 08h + 8]
1450 mov dword [ebx], eax
1451 mov ebx, dword [esp + 0ch + 8]
1452 mov dword [ebx], edx
1453%endif
1454 ; collect flags and return.
1455 pushf
1456 pop MY_RET_REG
1457
1458 pop xBX
1459 pop xBP
1460 retn
1461ENDPROC EMEmulateLockCmpXchg8b
1462
1463;;
1464; Emulate CMPXCHG8B instruction, CDECL calling conv.
1465; VMMDECL(uint32_t) EMEmulateCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);
1466;
1467; @returns EFLAGS after the operation, only arithmetic flags are valid.
1468; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter
1469; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Address of the eax register
1470; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Address of the edx register
1471; @param [esp + 10h] gcc:rcx msc:r9 Param 4 - EBX
1472; @param [esp + 14h] gcc:r8 msc:[rsp + 8] Param 5 - ECX
1473; @uses eax, ecx, edx
1474;
1475align 16
1476BEGINPROC EMEmulateCmpXchg8b
1477 push xBP
1478 push xBX
1479%ifdef RT_ARCH_AMD64
1480 %ifdef RT_OS_WINDOWS
1481 mov rbp, rcx
1482 mov r10, rdx
1483 mov eax, dword [rdx]
1484 mov edx, dword [r8]
1485 mov rbx, r9
1486 mov ecx, [rsp + 28h + 16]
1487 %else
1488 mov rbp, rdi
1489 mov r10, rdx
1490 mov eax, dword [rsi]
1491 mov edx, dword [rdx]
1492 mov rbx, rcx
1493 mov rcx, r8
1494 %endif
1495%else
1496 mov ebp, [esp + 04h + 8] ; ebp = first parameter
1497 mov eax, [esp + 08h + 8] ; &EAX
1498 mov eax, dword [eax]
1499 mov edx, [esp + 0ch + 8] ; &EDX
1500 mov edx, dword [edx]
1501 mov ebx, [esp + 10h + 8] ; EBX
1502 mov ecx, [esp + 14h + 8] ; ECX
1503%endif
1504
1505%ifdef RT_OS_OS2
1506 cmpxchg8b [xBP] ; do CMPXCHG8B
1507%else
1508 cmpxchg8b qword [xBP] ; do CMPXCHG8B
1509%endif
1510
1511%ifdef RT_ARCH_AMD64
1512 %ifdef RT_OS_WINDOWS
1513 mov dword [r10], eax
1514 mov dword [r8], edx
1515 %else
1516 mov dword [rsi], eax
1517 mov dword [r10], edx
1518 %endif
1519%else
1520 mov ebx, dword [esp + 08h + 8]
1521 mov dword [ebx], eax
1522 mov ebx, dword [esp + 0ch + 8]
1523 mov dword [ebx], edx
1524%endif
1525
1526 ; collect flags and return.
1527 pushf
1528 pop MY_RET_REG
1529
1530 pop xBX
1531 pop xBP
1532 retn
1533ENDPROC EMEmulateCmpXchg8b
1534
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