VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstX86-1A.asm@ 40070

Last change on this file since 40070 was 40070, checked in by vboxsync, 13 years ago

More experiments / tests.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.9 KB
Line 
1; $Id: tstX86-1A.asm 40070 2012-02-10 19:47:10Z vboxsync $
2;; @file
3; X86 instruction set exploration/testcase #1.
4;
5
6;
7; Copyright (C) 2011-2012 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20; Header Files ;
21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22%include "iprt/asmdefs.mac"
23%include "iprt/x86.mac"
24
25;; @todo Move this to a header?
26struc TRAPINFO
27 .uTrapPC RTCCPTR_RES 1
28 .uResumePC RTCCPTR_RES 1
29 .u8TrapNo resb 1
30 .cbInstr resb 1
31 .au8Padding resb (RTCCPTR_CB*2 - 2)
32endstruc
33
34
35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36; Global Variables ;
37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
38BEGINDATA
39extern NAME(g_pbEfPage)
40extern NAME(g_pbEfExecPage)
41
42GLOBALNAME g_szAlpha
43 db "abcdefghijklmnopqrstuvwxyz", 0
44g_szAlpha_end:
45%define g_cchAlpha (g_szAlpha_end - NAME(g_szAlpha))
46 db 0, 0, 0,
47
48;;
49; The last global data item. We build this as we write the code.
50GLOBALNAME g_aTrapInfo
51
52
53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
54; Defined Constants And Macros ;
55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56%define X86_XCPT_UD 6
57%define X86_XCPT_GP 13
58%define X86_XCPT_PF 14
59%define X86_XCPT_MF 16
60
61%define PAGE_SIZE 0x1000
62
63;; Reference a variable
64%ifdef RT_ARCH_AMD64
65 %define REF(a_Name) [a_Name wrt rip]
66%else
67 %define REF(a_Name) [a_Name]
68%endif
69
70;; Reference a global variable
71%ifdef RT_ARCH_AMD64
72 %define REF_GLOBAL(a_Name) [NAME(a_Name) wrt rip]
73%else
74 %define REF_GLOBAL(a_Name) [NAME(a_Name)]
75%endif
76
77;;
78; Macro for recording a trapping instruction (simple).
79;
80; @param 1 The trap number.
81; @param 2+ The instruction which should trap.
82%macro ShouldTrap 2+
83%%trap:
84 %2
85%%trap_end:
86 mov eax, __LINE__
87 jmp .return
88BEGINDATA
89%%trapinfo: istruc TRAPINFO
90 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
91 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
92 at TRAPINFO.u8TrapNo, db %1
93 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
94iend
95BEGINCODE
96%%resume:
97%endmacro
98
99
100;;
101; Macro for recording a FPU instruction trapping on a following fwait.
102;
103; Uses stack.
104;
105; @param 1 The status flags that are expected to be set afterwards.
106; @param 2 C0..C3 to mask out in case undefined.
107; @param 3+ The instruction which should trap.
108; @uses eax
109;
110%macro FpuShouldTrap 3+
111 fnclex
112 %3
113%%trap:
114 fwait
115%%trap_end:
116 mov eax, __LINE__
117 jmp .return
118BEGINDATA
119%%trapinfo: istruc TRAPINFO
120 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
121 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
122 at TRAPINFO.u8TrapNo, db X86_XCPT_MF
123 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
124iend
125BEGINCODE
126%%resume:
127 FpuCheckFSW ((%1) | X86_FSW_B | X86_FSW_ES), %2
128 fnclex
129%endmacro
130
131;;
132; Macro for recording a FPU instruction trapping on a following fwait.
133;
134; Uses stack.
135;
136; @param 1 The status flags that are expected to be set afterwards.
137; @param 2 C0..C3 to mask out in case undefined.
138; @uses eax
139;
140%macro FpuCheckFSW 2
141%%resume:
142 fnstsw ax
143 and eax, ~X86_FSW_TOP_MASK & ~(%2)
144 cmp eax, (%1)
145 je %%ok
146 ;int3
147 lea eax, [eax + __LINE__ * 100000]
148 jmp .return
149%%ok:
150 fnstsw ax
151%endmacro
152
153
154;;
155; Checks that ST0 has a certain value
156;
157; @uses tword at [xSP]
158;
159%macro CheckSt0Value 3
160 fstp tword [xSP]
161 fld tword [xSP]
162 cmp dword [xSP], %1
163 je %%ok1
164%%bad:
165 mov eax, __LINE__
166 jmp .return
167%%ok1:
168 cmp dword [xSP + 4], %2
169 jne %%bad
170 cmp word [xSP + 8], %3
171 jne %%bad
172%endmacro
173
174
175;;
176; Function prologue saving all registers except EAX.
177;
178%macro SAVE_ALL_PROLOGUE 0
179 push xBP
180 mov xBP, xSP
181 pushf
182 push xBX
183 push xCX
184 push xDX
185 push xSI
186 push xDI
187%ifdef RT_ARCH_AMD64
188 push r8
189 push r9
190 push r10
191 push r11
192 push r12
193 push r13
194 push r14
195 push r15
196%endif
197%endmacro
198
199
200;;
201; Function epilogue restoring all regisers except EAX.
202;
203%macro SAVE_ALL_EPILOGUE 0
204%ifdef RT_ARCH_AMD64
205 pop r15
206 pop r14
207 pop r13
208 pop r12
209 pop r11
210 pop r10
211 pop r9
212 pop r8
213%endif
214 pop xDI
215 pop xSI
216 pop xDX
217 pop xCX
218 pop xBX
219 popf
220 leave
221%endmacro
222
223
224
225
226BEGINCODE
227
228;;
229; Loads all general registers except xBP and xSP with unique values.
230;
231x861_LoadUniqueRegValues:
232%ifdef RT_ARCH_AMD64
233 mov rax, 00000000000000000h
234 mov rcx, 01111111111111111h
235 mov rdx, 02222222222222222h
236 mov rbx, 03333333333333333h
237 mov rsi, 06666666666666666h
238 mov rdi, 07777777777777777h
239 mov r8, 08888888888888888h
240 mov r9, 09999999999999999h
241 mov r10, 0aaaaaaaaaaaaaaaah
242 mov r11, 0bbbbbbbbbbbbbbbbh
243 mov r12, 0cccccccccccccccch
244 mov r13, 0ddddddddddddddddh
245 mov r14, 0eeeeeeeeeeeeeeeeh
246 mov r15, 0ffffffffffffffffh
247%else
248 mov eax, 000000000h
249 mov ecx, 011111111h
250 mov edx, 022222222h
251 mov ebx, 033333333h
252 mov esi, 066666666h
253 mov edi, 077777777h
254%endif
255 ret
256; end x861_LoadUniqueRegValues
257
258
259;;
260; Clears all general registers except xBP and xSP.
261;
262x861_ClearRegisters:
263 xor eax, eax
264 xor ebx, ebx
265 xor ecx, ecx
266 xor edx, edx
267 xor esi, esi
268 xor edi, edi
269%ifdef RT_ARCH_AMD64
270 xor r8, r8
271 xor r9, r9
272 xor r10, r10
273 xor r11, r11
274 xor r12, r12
275 xor r13, r13
276 xor r14, r14
277 xor r15, r15
278%endif
279 ret
280; x861_ClearRegisters
281
282
283;;
284; Loads all general, MMX and SSE registers except xBP and xSP with unique values.
285;
286x861_LoadUniqueRegValuesSSE:
287 movq mm0, REF(._mm0)
288 movq mm1, REF(._mm1)
289 movq mm2, REF(._mm2)
290 movq mm3, REF(._mm3)
291 movq mm4, REF(._mm4)
292 movq mm5, REF(._mm5)
293 movq mm6, REF(._mm6)
294 movq mm7, REF(._mm7)
295 movdqu xmm0, REF(._xmm0)
296 movdqu xmm1, REF(._xmm1)
297 movdqu xmm2, REF(._xmm2)
298 movdqu xmm3, REF(._xmm3)
299 movdqu xmm4, REF(._xmm4)
300 movdqu xmm5, REF(._xmm5)
301 movdqu xmm6, REF(._xmm6)
302 movdqu xmm7, REF(._xmm7)
303%ifdef RT_ARCH_AMD64
304 movdqu xmm8, REF(._xmm8)
305 movdqu xmm9, REF(._xmm9)
306 movdqu xmm10, REF(._xmm10)
307 movdqu xmm11, REF(._xmm11)
308 movdqu xmm12, REF(._xmm12)
309 movdqu xmm13, REF(._xmm13)
310 movdqu xmm14, REF(._xmm14)
311 movdqu xmm15, REF(._xmm15)
312%endif
313 call x861_LoadUniqueRegValues
314 ret
315._mm0: times 8 db 040h
316._mm1: times 8 db 041h
317._mm2: times 8 db 042h
318._mm3: times 8 db 043h
319._mm4: times 8 db 044h
320._mm5: times 8 db 045h
321._mm6: times 8 db 046h
322._mm7: times 8 db 047h
323._xmm0: times 16 db 080h
324._xmm1: times 16 db 081h
325._xmm2: times 16 db 082h
326._xmm3: times 16 db 083h
327._xmm4: times 16 db 084h
328._xmm5: times 16 db 085h
329._xmm6: times 16 db 086h
330._xmm7: times 16 db 087h
331%ifdef RT_ARCH_AMD64
332._xmm8: times 16 db 088h
333._xmm9: times 16 db 089h
334._xmm10: times 16 db 08ah
335._xmm11: times 16 db 08bh
336._xmm12: times 16 db 08ch
337._xmm13: times 16 db 08dh
338._xmm14: times 16 db 08eh
339._xmm15: times 16 db 08fh
340%endif
341; end x861_LoadUniqueRegValuesSSE
342
343
344;;
345; Clears all general, MMX and SSE registers except xBP and xSP.
346;
347x861_ClearRegistersSSE:
348 call x861_ClearRegisters
349 movq mm0, REF(.zero)
350 movq mm1, REF(.zero)
351 movq mm2, REF(.zero)
352 movq mm3, REF(.zero)
353 movq mm4, REF(.zero)
354 movq mm5, REF(.zero)
355 movq mm6, REF(.zero)
356 movq mm7, REF(.zero)
357 movdqu xmm0, REF(.zero)
358 movdqu xmm1, REF(.zero)
359 movdqu xmm2, REF(.zero)
360 movdqu xmm3, REF(.zero)
361 movdqu xmm4, REF(.zero)
362 movdqu xmm5, REF(.zero)
363 movdqu xmm6, REF(.zero)
364 movdqu xmm7, REF(.zero)
365%ifdef RT_ARCH_AMD64
366 movdqu xmm8, REF(.zero)
367 movdqu xmm9, REF(.zero)
368 movdqu xmm10, REF(.zero)
369 movdqu xmm11, REF(.zero)
370 movdqu xmm12, REF(.zero)
371 movdqu xmm13, REF(.zero)
372 movdqu xmm14, REF(.zero)
373 movdqu xmm15, REF(.zero)
374%endif
375 call x861_LoadUniqueRegValues
376 ret
377
378 ret
379.zero times 16 db 000h
380; x861_ClearRegistersSSE
381
382
383BEGINPROC x861_Test1
384 push xBP
385 mov xBP, xSP
386 pushf
387 push xBX
388 push xCX
389 push xDX
390 push xSI
391 push xDI
392%ifdef RT_ARCH_AMD64
393 push r8
394 push r9
395 push r10
396 push r11
397 push r12
398 push r13
399 push r14
400 push r15
401%endif
402
403 ;
404 ; Odd push behavior
405 ;
406%if 0 ; Seems to be so on AMD only
407%ifdef RT_ARCH_X86
408 ; upper word of a 'push cs' is cleared.
409 mov eax, __LINE__
410 mov dword [esp - 4], 0f0f0f0fh
411 push cs
412 pop ecx
413 mov bx, cs
414 and ebx, 0000ffffh
415 cmp ecx, ebx
416 jne .failed
417
418 ; upper word of a 'push ds' is cleared.
419 mov eax, __LINE__
420 mov dword [esp - 4], 0f0f0f0fh
421 push ds
422 pop ecx
423 mov bx, ds
424 and ebx, 0000ffffh
425 cmp ecx, ebx
426 jne .failed
427
428 ; upper word of a 'push es' is cleared.
429 mov eax, __LINE__
430 mov dword [esp - 4], 0f0f0f0fh
431 push es
432 pop ecx
433 mov bx, es
434 and ebx, 0000ffffh
435 cmp ecx, ebx
436 jne .failed
437%endif ; RT_ARCH_X86
438
439 ; The upper part of a 'push fs' is cleared.
440 mov eax, __LINE__
441 xor ecx, ecx
442 not xCX
443 push xCX
444 pop xCX
445 push fs
446 pop xCX
447 mov bx, fs
448 and ebx, 0000ffffh
449 cmp xCX, xBX
450 jne .failed
451
452 ; The upper part of a 'push gs' is cleared.
453 mov eax, __LINE__
454 xor ecx, ecx
455 not xCX
456 push xCX
457 pop xCX
458 push gs
459 pop xCX
460 mov bx, gs
461 and ebx, 0000ffffh
462 cmp xCX, xBX
463 jne .failed
464%endif
465
466%ifdef RT_ARCH_AMD64
467 ; REX.B works with 'push r64'.
468 call x861_LoadUniqueRegValues
469 mov eax, __LINE__
470 push rcx
471 pop rdx
472 cmp rdx, rcx
473 jne .failed
474
475 call x861_LoadUniqueRegValues
476 mov eax, __LINE__
477 db 041h ; REX.B
478 push rcx
479 pop rdx
480 cmp rdx, r9
481 jne .failed
482
483 call x861_LoadUniqueRegValues
484 mov eax, __LINE__
485 db 042h ; REX.X
486 push rcx
487 pop rdx
488 cmp rdx, rcx
489 jne .failed
490
491 call x861_LoadUniqueRegValues
492 mov eax, __LINE__
493 db 044h ; REX.R
494 push rcx
495 pop rdx
496 cmp rdx, rcx
497 jne .failed
498
499 call x861_LoadUniqueRegValues
500 mov eax, __LINE__
501 db 048h ; REX.W
502 push rcx
503 pop rdx
504 cmp rdx, rcx
505 jne .failed
506
507 call x861_LoadUniqueRegValues
508 mov eax, __LINE__
509 db 04fh ; REX.*
510 push rcx
511 pop rdx
512 cmp rdx, r9
513 jne .failed
514%endif
515
516 ;
517 ; Zero extening when moving from a segreg as well as memory access sizes.
518 ;
519 call x861_LoadUniqueRegValues
520 mov eax, __LINE__
521 mov ecx, ds
522 shr xCX, 16
523 cmp xCX, 0
524 jnz .failed
525
526%ifdef RT_ARCH_AMD64
527 call x861_LoadUniqueRegValues
528 mov eax, __LINE__
529 mov rcx, ds
530 shr rcx, 16
531 cmp rcx, 0
532 jnz .failed
533%endif
534
535 call x861_LoadUniqueRegValues
536 mov eax, __LINE__
537 mov xDX, xCX
538 mov cx, ds
539 shr xCX, 16
540 shr xDX, 16
541 cmp xCX, xDX
542 jnz .failed
543
544 ; Loading is always a word access.
545 mov eax, __LINE__
546 mov xDI, REF_GLOBAL(g_pbEfPage)
547 lea xDI, [xDI + 0x1000 - 2]
548 mov xDX, es
549 mov [xDI], dx
550 mov es, [xDI] ; should not crash
551
552 ; Saving is always a word access.
553 mov eax, __LINE__
554 mov xDI, REF_GLOBAL(g_pbEfPage)
555 mov dword [xDI + 0x1000 - 4], -1
556 mov [xDI + 0x1000 - 2], ss ; Should not crash.
557 mov bx, ss
558 mov cx, [xDI + 0x1000 - 2]
559 cmp cx, bx
560 jne .failed
561
562%ifdef RT_ARCH_AMD64
563 ; Check that the rex.R and rex.W bits don't have any influence over a memory write.
564 call x861_ClearRegisters
565 mov eax, __LINE__
566 mov xDI, REF_GLOBAL(g_pbEfPage)
567 mov dword [xDI + 0x1000 - 4], -1
568 db 04ah
569 mov [xDI + 0x1000 - 2], ss ; Should not crash.
570 mov bx, ss
571 mov cx, [xDI + 0x1000 - 2]
572 cmp cx, bx
573 jne .failed
574%endif
575
576
577 ;
578 ; Check what happens when both string prefixes are used.
579 ;
580 cld
581 mov dx, ds
582 mov es, dx
583
584 ; check that repne scasb (al=0) behaves like expected.
585 lea xDI, REF_GLOBAL(g_szAlpha)
586 xor eax, eax ; find the end
587 mov ecx, g_cchAlpha + 1
588 repne scasb
589 cmp ecx, 1
590 mov eax, __LINE__
591 jne .failed
592
593 ; check that repe scasb (al=0) behaves like expected.
594 lea xDI, REF_GLOBAL(g_szAlpha)
595 xor eax, eax ; find the end
596 mov ecx, g_cchAlpha + 1
597 repe scasb
598 cmp ecx, g_cchAlpha
599 mov eax, __LINE__
600 jne .failed
601
602 ; repne is last, it wins.
603 lea xDI, REF_GLOBAL(g_szAlpha)
604 xor eax, eax ; find the end
605 mov ecx, g_cchAlpha + 1
606 db 0f3h ; repe - ignored
607 db 0f2h ; repne
608 scasb
609 cmp ecx, 1
610 mov eax, __LINE__
611 jne .failed
612
613 ; repe is last, it wins.
614 lea xDI, REF_GLOBAL(g_szAlpha)
615 xor eax, eax ; find the end
616 mov ecx, g_cchAlpha + 1
617 db 0f2h ; repne - ignored
618 db 0f3h ; repe
619 scasb
620 cmp ecx, g_cchAlpha
621 mov eax, __LINE__
622 jne .failed
623
624 ;
625 ; Check if stosb works with both prefixes.
626 ;
627 cld
628 mov dx, ds
629 mov es, dx
630 mov xDI, REF_GLOBAL(g_pbEfPage)
631 xor eax, eax
632 mov ecx, 01000h
633 rep stosb
634
635 mov xDI, REF_GLOBAL(g_pbEfPage)
636 mov ecx, 4
637 mov eax, 0ffh
638 db 0f2h ; repne
639 stosb
640 mov eax, __LINE__
641 cmp ecx, 0
642 jne .failed
643 mov eax, __LINE__
644 mov xDI, REF_GLOBAL(g_pbEfPage)
645 cmp dword [xDI], 0ffffffffh
646 jne .failed
647 cmp dword [xDI+4], 0
648 jne .failed
649
650 mov xDI, REF_GLOBAL(g_pbEfPage)
651 mov ecx, 4
652 mov eax, 0feh
653 db 0f3h ; repe
654 stosb
655 mov eax, __LINE__
656 cmp ecx, 0
657 jne .failed
658 mov eax, __LINE__
659 mov xDI, REF_GLOBAL(g_pbEfPage)
660 cmp dword [xDI], 0fefefefeh
661 jne .failed
662 cmp dword [xDI+4], 0
663 jne .failed
664
665 ;
666 ; String operations shouldn't crash because of an invalid address if rCX is 0.
667 ;
668 mov eax, __LINE__
669 cld
670 mov dx, ds
671 mov es, dx
672 mov xDI, REF_GLOBAL(g_pbEfPage)
673 xor xCX, xCX
674 rep stosb ; no trap
675
676 ;
677 ; INS/OUTS will trap in ring-3 even when rCX is 0. (ASSUMES IOPL < 3)
678 ;
679 mov eax, __LINE__
680 cld
681 mov dx, ss
682 mov ss, dx
683 mov xDI, xSP
684 xor xCX, xCX
685 ShouldTrap X86_XCPT_GP, rep insb
686
687 ;
688 ; SMSW can get to the whole of CR0.
689 ;
690 mov eax, __LINE__
691 xor xBX, xBX
692 smsw xBX
693 test ebx, X86_CR0_PG
694 jz .failed
695 test ebx, X86_CR0_PE
696 jz .failed
697
698 ;
699 ; Will the CPU decode the whole r/m+sib stuff before signalling a lock
700 ; prefix error? Use the EF exec page and a LOCK ADD CL,[rDI + disp32]
701 ; instruction at the very end of it.
702 ;
703 mov eax, __LINE__
704 mov xDI, REF_GLOBAL(g_pbEfExecPage)
705 add xDI, 1000h - 8h
706 mov byte [xDI+0], 0f0h
707 mov byte [xDI+1], 002h
708 mov byte [xDI+2], 08fh
709 mov dword [xDI+3], 000000000h
710 mov byte [xDI+7], 0cch
711 ShouldTrap X86_XCPT_UD, call xDI
712
713 mov eax, __LINE__
714 mov xDI, REF_GLOBAL(g_pbEfExecPage)
715 add xDI, 1000h - 7h
716 mov byte [xDI+0], 0f0h
717 mov byte [xDI+1], 002h
718 mov byte [xDI+2], 08Fh
719 mov dword [xDI+3], 000000000h
720 ShouldTrap X86_XCPT_UD, call xDI
721
722 mov eax, __LINE__
723 mov xDI, REF_GLOBAL(g_pbEfExecPage)
724 add xDI, 1000h - 4h
725 mov byte [xDI+0], 0f0h
726 mov byte [xDI+1], 002h
727 mov byte [xDI+2], 08Fh
728 mov byte [xDI+3], 000h
729 ShouldTrap X86_XCPT_PF, call xDI
730
731 mov eax, __LINE__
732 mov xDI, REF_GLOBAL(g_pbEfExecPage)
733 add xDI, 1000h - 6h
734 mov byte [xDI+0], 0f0h
735 mov byte [xDI+1], 002h
736 mov byte [xDI+2], 08Fh
737 mov byte [xDI+3], 00h
738 mov byte [xDI+4], 00h
739 mov byte [xDI+5], 00h
740 ShouldTrap X86_XCPT_PF, call xDI
741
742 mov eax, __LINE__
743 mov xDI, REF_GLOBAL(g_pbEfExecPage)
744 add xDI, 1000h - 5h
745 mov byte [xDI+0], 0f0h
746 mov byte [xDI+1], 002h
747 mov byte [xDI+2], 08Fh
748 mov byte [xDI+3], 00h
749 mov byte [xDI+4], 00h
750 ShouldTrap X86_XCPT_PF, call xDI
751
752 mov eax, __LINE__
753 mov xDI, REF_GLOBAL(g_pbEfExecPage)
754 add xDI, 1000h - 4h
755 mov byte [xDI+0], 0f0h
756 mov byte [xDI+1], 002h
757 mov byte [xDI+2], 08Fh
758 mov byte [xDI+3], 00h
759 ShouldTrap X86_XCPT_PF, call xDI
760
761 mov eax, __LINE__
762 mov xDI, REF_GLOBAL(g_pbEfExecPage)
763 add xDI, 1000h - 3h
764 mov byte [xDI+0], 0f0h
765 mov byte [xDI+1], 002h
766 mov byte [xDI+2], 08Fh
767 ShouldTrap X86_XCPT_PF, call xDI
768
769 mov eax, __LINE__
770 mov xDI, REF_GLOBAL(g_pbEfExecPage)
771 add xDI, 1000h - 2h
772 mov byte [xDI+0], 0f0h
773 mov byte [xDI+1], 002h
774 ShouldTrap X86_XCPT_PF, call xDI
775
776 mov eax, __LINE__
777 mov xDI, REF_GLOBAL(g_pbEfExecPage)
778 add xDI, 1000h - 1h
779 mov byte [xDI+0], 0f0h
780 ShouldTrap X86_XCPT_PF, call xDI
781
782
783
784.success:
785 xor eax, eax
786.return:
787%ifdef RT_ARCH_AMD64
788 pop r15
789 pop r14
790 pop r13
791 pop r12
792 pop r11
793 pop r10
794 pop r9
795 pop r8
796%endif
797 pop xDI
798 pop xSI
799 pop xDX
800 pop xCX
801 pop xBX
802 popf
803 leave
804 ret
805
806.failed2:
807 mov eax, -1
808.failed:
809 jmp .return
810ENDPROC x861_Test1
811
812
813
814;;
815; Tests the effect of prefix order in group 14.
816;
817BEGINPROC x861_Test2
818 SAVE_ALL_PROLOGUE
819
820 ; Check testcase preconditions.
821 call x861_LoadUniqueRegValuesSSE
822 mov eax, __LINE__
823 db 00Fh, 073h, 0D0h, 080h ; psrlq mm0, 128
824 call .check_mm0_zero_and_xmm0_nz
825
826 call x861_LoadUniqueRegValuesSSE
827 mov eax, __LINE__
828 db 066h, 00Fh, 073h, 0D0h, 080h ; psrlq xmm0, 128
829 call .check_xmm0_zero_and_mm0_nz
830
831
832 ;
833 ; Real test - Inject other prefixes before the 066h and see what
834 ; happens.
835 ;
836
837 ; General checks that order does not matter, etc.
838 call x861_LoadUniqueRegValuesSSE
839 mov eax, __LINE__
840 db 026h, 066h, 00Fh, 073h, 0D0h, 080h
841 call .check_xmm0_zero_and_mm0_nz
842
843 call x861_LoadUniqueRegValuesSSE
844 mov eax, __LINE__
845 db 066h, 026h, 00Fh, 073h, 0D0h, 080h
846 call .check_xmm0_zero_and_mm0_nz
847
848 call x861_LoadUniqueRegValuesSSE
849 mov eax, __LINE__
850 db 066h, 067h, 00Fh, 073h, 0D0h, 080h
851 call .check_xmm0_zero_and_mm0_nz
852
853 call x861_LoadUniqueRegValuesSSE
854 mov eax, __LINE__
855 db 067h, 066h, 00Fh, 073h, 0D0h, 080h
856 call .check_xmm0_zero_and_mm0_nz
857
858 call x861_LoadUniqueRegValuesSSE
859 mov eax, __LINE__
860 db 067h, 066h, 065h, 00Fh, 073h, 0D0h, 080h
861 call .check_xmm0_zero_and_mm0_nz
862
863%ifdef RT_ARCH_AMD64
864 call x861_LoadUniqueRegValuesSSE
865 mov eax, __LINE__
866 db 048h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.W
867 call .check_xmm0_zero_and_mm0_nz
868
869 call x861_LoadUniqueRegValuesSSE
870 mov eax, __LINE__
871 db 044h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.R
872 call .check_xmm0_zero_and_mm0_nz
873
874 call x861_LoadUniqueRegValuesSSE
875 mov eax, __LINE__
876 db 042h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.X
877 call .check_xmm0_zero_and_mm0_nz
878
879 ; Actually for REX, order does matter if the prefix is used.
880 call x861_LoadUniqueRegValuesSSE
881 mov eax, __LINE__
882 db 041h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.B
883 call .check_xmm0_zero_and_mm0_nz
884
885 call x861_LoadUniqueRegValuesSSE
886 mov eax, __LINE__
887 db 066h, 041h, 00Fh, 073h, 0D0h, 080h ; REX.B
888 call .check_xmm8_zero_and_xmm0_nz
889%endif
890
891 ; Check all ignored prefixes (repeates some of the above).
892 call x861_LoadUniqueRegValuesSSE
893 mov eax, __LINE__
894 db 066h, 026h, 00Fh, 073h, 0D0h, 080h ; es
895 call .check_xmm0_zero_and_mm0_nz
896
897 call x861_LoadUniqueRegValuesSSE
898 mov eax, __LINE__
899 db 066h, 065h, 00Fh, 073h, 0D0h, 080h ; gs
900 call .check_xmm0_zero_and_mm0_nz
901
902 call x861_LoadUniqueRegValuesSSE
903 mov eax, __LINE__
904 db 066h, 064h, 00Fh, 073h, 0D0h, 080h ; fs
905 call .check_xmm0_zero_and_mm0_nz
906
907 call x861_LoadUniqueRegValuesSSE
908 mov eax, __LINE__
909 db 066h, 02eh, 00Fh, 073h, 0D0h, 080h ; cs
910 call .check_xmm0_zero_and_mm0_nz
911
912 call x861_LoadUniqueRegValuesSSE
913 mov eax, __LINE__
914 db 066h, 036h, 00Fh, 073h, 0D0h, 080h ; ss
915 call .check_xmm0_zero_and_mm0_nz
916
917 call x861_LoadUniqueRegValuesSSE
918 mov eax, __LINE__
919 db 066h, 03eh, 00Fh, 073h, 0D0h, 080h ; ds
920 call .check_xmm0_zero_and_mm0_nz
921
922 call x861_LoadUniqueRegValuesSSE
923 mov eax, __LINE__
924 db 066h, 067h, 00Fh, 073h, 0D0h, 080h ; addr size
925 call .check_xmm0_zero_and_mm0_nz
926
927%ifdef RT_ARCH_AMD64
928 call x861_LoadUniqueRegValuesSSE
929 mov eax, __LINE__
930 db 066h, 048h, 00Fh, 073h, 0D0h, 080h ; REX.W
931 call .check_xmm0_zero_and_mm0_nz
932
933 call x861_LoadUniqueRegValuesSSE
934 mov eax, __LINE__
935 db 066h, 044h, 00Fh, 073h, 0D0h, 080h ; REX.R
936 call .check_xmm0_zero_and_mm0_nz
937
938 call x861_LoadUniqueRegValuesSSE
939 mov eax, __LINE__
940 db 066h, 042h, 00Fh, 073h, 0D0h, 080h ; REX.X
941 call .check_xmm0_zero_and_mm0_nz
942
943 call x861_LoadUniqueRegValuesSSE
944 mov eax, __LINE__
945 db 066h, 041h, 00Fh, 073h, 0D0h, 080h ; REX.B - has actual effect on the instruction.
946 call .check_xmm8_zero_and_xmm0_nz
947%endif
948
949 ; Repeated prefix until we hit the max opcode limit.
950 call x861_LoadUniqueRegValuesSSE
951 mov eax, __LINE__
952 db 066h, 066h, 00Fh, 073h, 0D0h, 080h
953 call .check_xmm0_zero_and_mm0_nz
954
955 call x861_LoadUniqueRegValuesSSE
956 mov eax, __LINE__
957 db 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
958 call .check_xmm0_zero_and_mm0_nz
959
960 call x861_LoadUniqueRegValuesSSE
961 mov eax, __LINE__
962 db 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
963 call .check_xmm0_zero_and_mm0_nz
964
965 call x861_LoadUniqueRegValuesSSE
966 mov eax, __LINE__
967 db 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
968 call .check_xmm0_zero_and_mm0_nz
969
970 ShouldTrap X86_XCPT_GP, db 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
971
972%ifdef RT_ARCH_AMD64
973 ; Repeated REX is parsed, but only the last byte matters.
974 call x861_LoadUniqueRegValuesSSE
975 mov eax, __LINE__
976 db 066h, 041h, 048h, 00Fh, 073h, 0D0h, 080h ; REX.B, REX.W
977 call .check_xmm0_zero_and_mm0_nz
978
979 call x861_LoadUniqueRegValuesSSE
980 mov eax, __LINE__
981 db 066h, 048h, 041h, 00Fh, 073h, 0D0h, 080h ; REX.B, REX.W
982 call .check_xmm8_zero_and_xmm0_nz
983
984 call x861_LoadUniqueRegValuesSSE
985 mov eax, __LINE__
986 db 066h, 048h, 044h, 042h, 048h, 044h, 042h, 048h, 044h, 042h, 041h, 00Fh, 073h, 0D0h, 080h
987 call .check_xmm8_zero_and_xmm0_nz
988
989 call x861_LoadUniqueRegValuesSSE
990 mov eax, __LINE__
991 db 066h, 041h, 041h, 041h, 041h, 041h, 041h, 041h, 041h, 041h, 04eh, 00Fh, 073h, 0D0h, 080h
992 call .check_xmm0_zero_and_mm0_nz
993%endif
994
995 ; Undefined sequences with prefixes that counts.
996 ShouldTrap X86_XCPT_UD, db 0f0h, 066h, 00Fh, 073h, 0D0h, 080h ; LOCK
997 ShouldTrap X86_XCPT_UD, db 0f2h, 066h, 00Fh, 073h, 0D0h, 080h ; REPNZ
998 ShouldTrap X86_XCPT_UD, db 0f3h, 066h, 00Fh, 073h, 0D0h, 080h ; REPZ
999 ShouldTrap X86_XCPT_UD, db 066h, 0f2h, 00Fh, 073h, 0D0h, 080h
1000 ShouldTrap X86_XCPT_UD, db 066h, 0f3h, 00Fh, 073h, 0D0h, 080h
1001 ShouldTrap X86_XCPT_UD, db 066h, 0f3h, 0f2h, 00Fh, 073h, 0D0h, 080h
1002 ShouldTrap X86_XCPT_UD, db 066h, 0f2h, 0f3h, 00Fh, 073h, 0D0h, 080h
1003 ShouldTrap X86_XCPT_UD, db 0f2h, 066h, 0f3h, 00Fh, 073h, 0D0h, 080h
1004 ShouldTrap X86_XCPT_UD, db 0f3h, 066h, 0f2h, 00Fh, 073h, 0D0h, 080h
1005 ShouldTrap X86_XCPT_UD, db 0f3h, 0f2h, 066h, 00Fh, 073h, 0D0h, 080h
1006 ShouldTrap X86_XCPT_UD, db 0f2h, 0f3h, 066h, 00Fh, 073h, 0D0h, 080h
1007 ShouldTrap X86_XCPT_UD, db 0f0h, 0f2h, 066h, 0f3h, 00Fh, 073h, 0D0h, 080h
1008 ShouldTrap X86_XCPT_UD, db 0f0h, 0f3h, 066h, 0f2h, 00Fh, 073h, 0D0h, 080h
1009 ShouldTrap X86_XCPT_UD, db 0f0h, 0f3h, 0f2h, 066h, 00Fh, 073h, 0D0h, 080h
1010 ShouldTrap X86_XCPT_UD, db 0f0h, 0f2h, 0f3h, 066h, 00Fh, 073h, 0D0h, 080h
1011
1012.success:
1013 xor eax, eax
1014.return:
1015 SAVE_ALL_EPILOGUE
1016 ret
1017
1018.check_xmm0_zero_and_mm0_nz:
1019 sub xSP, 20h
1020 movdqu [xSP], xmm0
1021 cmp dword [xSP], 0
1022 jne .failed3
1023 cmp dword [xSP + 4], 0
1024 jne .failed3
1025 cmp dword [xSP + 8], 0
1026 jne .failed3
1027 cmp dword [xSP + 12], 0
1028 jne .failed3
1029 movq [xSP], mm0
1030 cmp dword [xSP], 0
1031 je .failed3
1032 cmp dword [xSP + 4], 0
1033 je .failed3
1034 add xSP, 20h
1035 ret
1036
1037.check_mm0_zero_and_xmm0_nz:
1038 sub xSP, 20h
1039 movq [xSP], mm0
1040 cmp dword [xSP], 0
1041 jne .failed3
1042 cmp dword [xSP + 4], 0
1043 jne .failed3
1044 movdqu [xSP], xmm0
1045 cmp dword [xSP], 0
1046 je .failed3
1047 cmp dword [xSP + 4], 0
1048 je .failed3
1049 cmp dword [xSP + 8], 0
1050 je .failed3
1051 cmp dword [xSP + 12], 0
1052 je .failed3
1053 add xSP, 20h
1054 ret
1055
1056%ifdef RT_ARCH_AMD64
1057.check_xmm8_zero_and_xmm0_nz:
1058 sub xSP, 20h
1059 movdqu [xSP], xmm8
1060 cmp dword [xSP], 0
1061 jne .failed3
1062 cmp dword [xSP + 4], 0
1063 jne .failed3
1064 cmp dword [xSP + 8], 0
1065 jne .failed3
1066 cmp dword [xSP + 12], 0
1067 jne .failed3
1068 movdqu [xSP], xmm0
1069 cmp dword [xSP], 0
1070 je .failed3
1071 cmp dword [xSP + 4], 0
1072 je .failed3
1073 cmp dword [xSP + 8], 0
1074 je .failed3
1075 cmp dword [xSP + 12], 0
1076 je .failed3
1077 add xSP, 20h
1078 ret
1079%endif
1080
1081.failed3:
1082 add xSP, 20h + xS
1083 jmp .return
1084
1085
1086ENDPROC x861_Test2
1087
1088
1089;;
1090; Tests how much fxsave and fxrstor actually accesses of their 512 memory
1091; operand.
1092;
1093BEGINPROC x861_Test3
1094 SAVE_ALL_PROLOGUE
1095 call x861_LoadUniqueRegValuesSSE
1096 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1097
1098 ; Check testcase preconditions.
1099 fxsave [xDI]
1100 fxrstor [xDI]
1101
1102 add xDI, PAGE_SIZE - 512
1103 mov xSI, xDI
1104 fxsave [xDI]
1105 fxrstor [xDI]
1106
1107 ; 464:511 are available to software use. Check that they are left
1108 ; untouched by fxsave.
1109 mov eax, 0aabbccddh
1110 mov ecx, 512 / 4
1111 cld
1112 rep stosd
1113 mov xDI, xSI
1114 fxsave [xDI]
1115
1116 mov ebx, 512
1117.chech_software_area_loop:
1118 cmp [xDI + xBX - 4], eax
1119 jne .chech_software_area_done
1120 sub ebx, 4
1121 jmp .chech_software_area_loop
1122.chech_software_area_done:
1123 cmp ebx, 464
1124 mov eax, __LINE__
1125 ja .return
1126
1127 ; Check that a save + restore + save cycle yield the same results.
1128 mov xBX, REF_GLOBAL(g_pbEfExecPage)
1129 mov xDI, xBX
1130 mov eax, 066778899h
1131 mov ecx, 512 * 2 / 4
1132 cld
1133 rep stosd
1134 fxsave [xBX]
1135
1136 call x861_ClearRegistersSSE
1137 mov xBX, REF_GLOBAL(g_pbEfExecPage)
1138 fxrstor [xBX]
1139
1140 fxsave [xBX + 512]
1141 mov xSI, xBX
1142 lea xDI, [xBX + 512]
1143 mov ecx, 512
1144 cld
1145 repe cmpsb
1146 mov eax, __LINE__
1147 jnz .return
1148
1149
1150 ; 464:511 are available to software use. Let see how carefully access
1151 ; to the full 512 bytes are checked...
1152 call x861_LoadUniqueRegValuesSSE
1153 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1154 add xDI, PAGE_SIZE - 512
1155 ShouldTrap X86_XCPT_PF, fxsave [xDI + 16]
1156 ShouldTrap X86_XCPT_PF, fxsave [xDI + 32]
1157 ShouldTrap X86_XCPT_PF, fxsave [xDI + 48]
1158 ShouldTrap X86_XCPT_PF, fxsave [xDI + 64]
1159 ShouldTrap X86_XCPT_PF, fxsave [xDI + 80]
1160 ShouldTrap X86_XCPT_PF, fxsave [xDI + 96]
1161 ShouldTrap X86_XCPT_PF, fxsave [xDI + 128]
1162 ShouldTrap X86_XCPT_PF, fxsave [xDI + 144]
1163 ShouldTrap X86_XCPT_PF, fxsave [xDI + 160]
1164 ShouldTrap X86_XCPT_PF, fxsave [xDI + 176]
1165 ShouldTrap X86_XCPT_PF, fxsave [xDI + 192]
1166 ShouldTrap X86_XCPT_PF, fxsave [xDI + 208]
1167 ShouldTrap X86_XCPT_PF, fxsave [xDI + 224]
1168 ShouldTrap X86_XCPT_PF, fxsave [xDI + 240]
1169 ShouldTrap X86_XCPT_PF, fxsave [xDI + 256]
1170 ShouldTrap X86_XCPT_PF, fxsave [xDI + 384]
1171 ShouldTrap X86_XCPT_PF, fxsave [xDI + 432]
1172 ShouldTrap X86_XCPT_PF, fxsave [xDI + 496]
1173
1174 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 16]
1175 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 32]
1176 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 48]
1177 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 64]
1178 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 80]
1179 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 96]
1180 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 128]
1181 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 144]
1182 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 160]
1183 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 176]
1184 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 192]
1185 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 208]
1186 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 224]
1187 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 240]
1188 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 256]
1189 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 384]
1190 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 432]
1191 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 496]
1192
1193 ; Unaligned accesses will cause #GP(0). This takes precedence over #PF.
1194 ShouldTrap X86_XCPT_GP, fxsave [xDI + 1]
1195 ShouldTrap X86_XCPT_GP, fxsave [xDI + 2]
1196 ShouldTrap X86_XCPT_GP, fxsave [xDI + 3]
1197 ShouldTrap X86_XCPT_GP, fxsave [xDI + 4]
1198 ShouldTrap X86_XCPT_GP, fxsave [xDI + 5]
1199 ShouldTrap X86_XCPT_GP, fxsave [xDI + 6]
1200 ShouldTrap X86_XCPT_GP, fxsave [xDI + 7]
1201 ShouldTrap X86_XCPT_GP, fxsave [xDI + 8]
1202 ShouldTrap X86_XCPT_GP, fxsave [xDI + 9]
1203 ShouldTrap X86_XCPT_GP, fxsave [xDI + 10]
1204 ShouldTrap X86_XCPT_GP, fxsave [xDI + 11]
1205 ShouldTrap X86_XCPT_GP, fxsave [xDI + 12]
1206 ShouldTrap X86_XCPT_GP, fxsave [xDI + 13]
1207 ShouldTrap X86_XCPT_GP, fxsave [xDI + 14]
1208 ShouldTrap X86_XCPT_GP, fxsave [xDI + 15]
1209
1210 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 1]
1211 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 2]
1212 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 3]
1213 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 4]
1214 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 5]
1215 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 6]
1216 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 7]
1217 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 8]
1218 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 9]
1219 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 10]
1220 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 11]
1221 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 12]
1222 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 13]
1223 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 14]
1224 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 15]
1225
1226 ; Lets check what a FP in fxsave changes ... nothing on intel.
1227 mov ebx, 16
1228.fxsave_pf_effect_loop:
1229 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1230 add xDI, PAGE_SIZE - 512 * 2
1231 mov xSI, xDI
1232 mov eax, 066778899h
1233 mov ecx, 512 * 2 / 4
1234 cld
1235 rep stosd
1236
1237 ShouldTrap X86_XCPT_PF, fxsave [xSI + PAGE_SIZE - 512 + xBX]
1238
1239 mov ecx, 512 / 4
1240 lea xDI, [xSI + 512]
1241 cld
1242 repz cmpsd
1243 lea xAX, [xBX + 20000]
1244 jnz .return
1245
1246 add ebx, 16
1247 cmp ebx, 512
1248 jbe .fxsave_pf_effect_loop
1249
1250 ; Lets check that a FP in fxrstor does not have any effect on the FPU or SSE state.
1251 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1252 mov ecx, PAGE_SIZE / 4
1253 mov eax, 0ffaa33cch
1254 cld
1255 rep stosd
1256
1257 call x861_LoadUniqueRegValuesSSE
1258 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1259 fxsave [xDI]
1260
1261 call x861_ClearRegistersSSE
1262 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1263 fxsave [xDI + 512]
1264
1265 mov ebx, 16
1266.fxrstor_pf_effect_loop:
1267 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1268 mov xSI, xDI
1269 lea xDI, [xDI + PAGE_SIZE - 512 + xBX]
1270 mov ecx, 512
1271 sub ecx, ebx
1272 cld
1273 rep movsb ; copy unique state to end of page.
1274
1275 push xBX
1276 call x861_ClearRegistersSSE
1277 pop xBX
1278 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1279 ShouldTrap X86_XCPT_PF, fxrstor [xDI + PAGE_SIZE - 512 + xBX] ; try load unique state
1280
1281 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1282 lea xSI, [xDI + 512] ; point it to the clean state, which is what we expect.
1283 lea xDI, [xDI + 1024]
1284 fxsave [xDI] ; save whatever the fpu state currently is.
1285 mov ecx, 512 / 4
1286 cld
1287 repe cmpsd
1288 lea xAX, [xBX + 40000]
1289 jnz .return ; it shouldn't be modified by faulting fxrstor, i.e. a clean state.
1290
1291 add ebx, 16
1292 cmp ebx, 512
1293 jbe .fxrstor_pf_effect_loop
1294
1295.success:
1296 xor eax, eax
1297.return:
1298 SAVE_ALL_EPILOGUE
1299 ret
1300ENDPROC x861_Test3
1301
1302
1303;;
1304; Tests various multibyte NOP sequences.
1305;
1306BEGINPROC x861_Test4
1307 SAVE_ALL_PROLOGUE
1308 call x861_ClearRegisters
1309
1310 ; Intel recommended sequences.
1311 nop
1312 db 066h, 090h
1313 db 00fh, 01fh, 000h
1314 db 00fh, 01fh, 040h, 000h
1315 db 00fh, 01fh, 044h, 000h, 000h
1316 db 066h, 00fh, 01fh, 044h, 000h, 000h
1317 db 00fh, 01fh, 080h, 000h, 000h, 000h, 000h
1318 db 00fh, 01fh, 084h, 000h, 000h, 000h, 000h, 000h
1319 db 066h, 00fh, 01fh, 084h, 000h, 000h, 000h, 000h, 000h
1320
1321 ; Check that the NOPs are allergic to lock prefixing.
1322 ShouldTrap X86_XCPT_UD, db 0f0h, 090h ; lock prefixed NOP.
1323 ShouldTrap X86_XCPT_UD, db 0f0h, 066h, 090h ; lock prefixed two byte NOP.
1324 ShouldTrap X86_XCPT_UD, db 0f0h, 00fh, 01fh, 000h ; lock prefixed three byte NOP.
1325
1326 ; Check the range of instructions that AMD marks as NOPs.
1327%macro TST_NOP 1
1328 db 00fh, %1, 000h
1329 db 00fh, %1, 040h, 000h
1330 db 00fh, %1, 044h, 000h, 000h
1331 db 066h, 00fh, %1, 044h, 000h, 000h
1332 db 00fh, %1, 080h, 000h, 000h, 000h, 000h
1333 db 00fh, %1, 084h, 000h, 000h, 000h, 000h, 000h
1334 db 066h, 00fh, %1, 084h, 000h, 000h, 000h, 000h, 000h
1335 ShouldTrap X86_XCPT_UD, db 0f0h, 00fh, %1, 000h
1336%endmacro
1337 TST_NOP 019h
1338 TST_NOP 01ah
1339 TST_NOP 01bh
1340 TST_NOP 01ch
1341 TST_NOP 01dh
1342 TST_NOP 01eh
1343 TST_NOP 01fh
1344
1345 ; The AMD P group, intel marks this as a NOP.
1346 TST_NOP 00dh
1347
1348.success:
1349 xor eax, eax
1350.return:
1351 SAVE_ALL_EPILOGUE
1352 ret
1353ENDPROC x861_Test4
1354
1355
1356
1357;;
1358; Tests some odd floating point instruction encodings.
1359;
1360BEGINPROC x861_Test5
1361 SAVE_ALL_PROLOGUE
1362
1363 ; standard stuff...
1364 fld dword REF(.r32V1)
1365 fld qword REF(.r64V1)
1366 fld tword REF(.r80V1)
1367
1368 ShouldTrap X86_XCPT_UD, db 0d9h, 008h
1369 ShouldTrap X86_XCPT_UD, db 0d9h, 009h
1370 ShouldTrap X86_XCPT_UD, db 0d9h, 00ah
1371 ShouldTrap X86_XCPT_UD, db 0d9h, 00bh
1372 ShouldTrap X86_XCPT_UD, db 0d9h, 00ch
1373 ShouldTrap X86_XCPT_UD, db 0d9h, 00dh
1374 ShouldTrap X86_XCPT_UD, db 0d9h, 00eh
1375 ShouldTrap X86_XCPT_UD, db 0d9h, 00fh
1376
1377 ShouldTrap X86_XCPT_UD, db 0d9h, 0d1h
1378 ShouldTrap X86_XCPT_UD, db 0d9h, 0d2h
1379 ShouldTrap X86_XCPT_UD, db 0d9h, 0d3h
1380 ShouldTrap X86_XCPT_UD, db 0d9h, 0d4h
1381 ShouldTrap X86_XCPT_UD, db 0d9h, 0d5h
1382 ShouldTrap X86_XCPT_UD, db 0d9h, 0d6h
1383 ShouldTrap X86_XCPT_UD, db 0d9h, 0d7h
1384 db 0d9h, 0d8h ; fnop?
1385 db 0d9h, 0d9h ; fnop?
1386 db 0d9h, 0dah ; fnop?
1387 db 0d9h, 0dbh ; fnop?
1388 db 0d9h, 0dch ; fnop?
1389 db 0d9h, 0ddh ; fnop?
1390 db 0d9h, 0deh ; fnop?
1391 db 0d9h, 0dfh ; fnop?
1392 ShouldTrap X86_XCPT_UD, db 0d9h, 0e2h
1393 ShouldTrap X86_XCPT_UD, db 0d9h, 0e3h
1394 ShouldTrap X86_XCPT_UD, db 0d9h, 0e6h
1395 ShouldTrap X86_XCPT_UD, db 0d9h, 0e7h
1396 ShouldTrap X86_XCPT_UD, db 0d9h, 0efh
1397
1398
1399.success:
1400 xor eax, eax
1401.return:
1402 SAVE_ALL_EPILOGUE
1403 ret
1404
1405.r32V1: dd 3.2
1406.r64V1: dq 6.4
1407.r80V1: dt 8.0
1408
1409ENDPROC x861_Test5
1410
1411
1412;;
1413; Tests some floating point exceptions and such.
1414;
1415;
1416;
1417BEGINPROC x861_Test6
1418 SAVE_ALL_PROLOGUE
1419 sub xSP, 2048
1420
1421 ; Load some pointers.
1422 lea xSI, REF(.r32V1)
1423 mov xDI, REF_GLOBAL(g_pbEfExecPage)
1424 add xDI, PAGE_SIZE ; invalid page.
1425
1426 ;
1427 ; Check denormal numbers.
1428 ; Turns out the number is loaded onto the stack even if an exception is triggered.
1429 ;
1430 fninit
1431 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
1432 fldcw [xSP]
1433 FpuShouldTrap X86_FSW_DE, 0, fld dword REF(.r32D0)
1434 CheckSt0Value 0x00000000, 0x80000000, 0x3f7f
1435
1436 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_DM
1437 fldcw [xSP]
1438 fld dword REF(.r32D0)
1439 fwait
1440 FpuCheckFSW X86_FSW_DE, 0
1441 CheckSt0Value 0x00000000, 0x80000000, 0x3f7f
1442
1443 ;
1444 ; stack overflow
1445 ;
1446 fninit
1447 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
1448 fldcw [xSP]
1449 fld qword REF(.r64V1)
1450 fld dword [xSI]
1451 fld dword [xSI]
1452 fld dword [xSI]
1453 fld dword [xSI]
1454 fld dword [xSI]
1455 fld dword [xSI]
1456 fld tword REF(.r80V1)
1457 fwait
1458
1459 FpuShouldTrap X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3, \
1460 fld dword [xSI]
1461 CheckSt0Value 0x00000000, 0x80000000, 0x4002
1462
1463 FpuShouldTrap X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3, \
1464 fld dword [xSI]
1465 CheckSt0Value 0x00000000, 0x80000000, 0x4002
1466
1467 ; stack overflow vs #PF.
1468 ShouldTrap X86_XCPT_PF, fld dword [xDI]
1469 fwait
1470
1471 ; stack overflow vs denormal number
1472 FpuShouldTrap X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3, \
1473 fld dword [xSI]
1474 CheckSt0Value 0x00000000, 0x80000000, 0x4002
1475
1476 ;
1477 ; Mask the overflow exception. We should get QNaN now regardless of
1478 ; what we try to push (provided the memory is valid).
1479 ;
1480 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_IM
1481 fldcw [xSP]
1482
1483 fld dword [xSI]
1484 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
1485 fnclex
1486 CheckSt0Value 0x00000000, 0xc0000000, 0xffff
1487
1488 fld qword REF(.r64V1)
1489 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
1490 fnclex
1491 CheckSt0Value 0x00000000, 0xc0000000, 0xffff
1492
1493 ; This is includes denormal values.
1494 fld dword REF(.r32D0)
1495 fwait
1496 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
1497 CheckSt0Value 0x00000000, 0xc0000000, 0xffff
1498 fnclex
1499
1500 ;
1501 ; #PF vs previous stack overflow. I.e. whether pending FPU exception
1502 ; is checked before fetching memory operands.
1503 ;
1504 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
1505 fldcw [xSP]
1506 fld qword REF(.r64V1)
1507 ShouldTrap X86_XCPT_MF, fld dword [xDI]
1508 fnclex
1509
1510 ;
1511 ; What happens when we unmask an exception and fwait?
1512 ;
1513 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_IM
1514 fldcw [xSP]
1515 fld dword [xSI]
1516 fwait
1517 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
1518 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
1519 fldcw [xSP]
1520 FpuCheckFSW X86_FSW_ES | X86_FSW_B | X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
1521
1522 ShouldTrap X86_XCPT_MF, fwait
1523 ShouldTrap X86_XCPT_MF, fwait
1524 ShouldTrap X86_XCPT_MF, fwait
1525 fnclex
1526
1527
1528.success:
1529 xor eax, eax
1530.return:
1531 add xSP, 2048
1532 SAVE_ALL_EPILOGUE
1533 ret
1534
1535.r32V1: dd 3.2
1536.r64V1: dq 6.4
1537.r80V1: dt 8.0
1538
1539; Denormal numbers.
1540.r32D0: dd 0200000h
1541
1542ENDPROC x861_Test6
1543
1544
1545;;
1546; Terminate the trap info array with a NIL entry.
1547BEGINDATA
1548GLOBALNAME g_aTrapInfoEnd
1549istruc TRAPINFO
1550 at TRAPINFO.uTrapPC, RTCCPTR_DEF 0
1551 at TRAPINFO.uResumePC, RTCCPTR_DEF 0
1552 at TRAPINFO.u8TrapNo, db 0
1553 at TRAPINFO.cbInstr, db 0
1554iend
1555
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