VirtualBox

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

Last change on this file since 58591 was 57446, checked in by vboxsync, 9 years ago

VMM: Removing VBOX_WITH_HYBRID_32BIT_KERNEL and other 32-bit darwin fun.

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