VirtualBox

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

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

IEM: fdiv work. Added x86extra.mac for non-automatic x86.h bits.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 78.0 KB
Line 
1; $Id: tstX86-1A.asm 40138 2012-02-15 16:40:03Z 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%ifdef RT_ARCH_AMD64
36 %define arch_fxsave o64 fxsave
37 %define arch_fxrstor o64 fxrstor
38%else
39 %define arch_fxsave fxsave
40 %define arch_fxrstor fxrstor
41%endif
42
43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
44; Global Variables ;
45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
46BEGINDATA
47extern NAME(g_pbEfPage)
48extern NAME(g_pbEfExecPage)
49
50GLOBALNAME g_szAlpha
51 db "abcdefghijklmnopqrstuvwxyz", 0
52g_szAlpha_end:
53%define g_cchAlpha (g_szAlpha_end - NAME(g_szAlpha))
54 db 0, 0, 0,
55
56;; @name Floating point constants.
57; @{
58g_r32_0dot1: dd 0.1
59g_r32_3dot2: dd 3.2
60g_r32_Zero: dd 0.0
61g_r32_One: dd 1.0
62g_r32_Two: dd 2.0
63g_r32_Three: dd 3.0
64g_r32_Ten: dd 10.0
65g_r32_Eleven: dd 11.0
66g_r32_ThirtyTwo:dd 32.0
67g_r32_Min: dd 000800000h
68g_r32_Max: dd 07f7fffffh
69g_r32_Inf: dd 07f800000h
70g_r32_SNaN: dd 07f800001h
71g_r32_SNaNMax: dd 07fbfffffh
72g_r32_QNaN: dd 07fc00000h
73g_r32_QNaNMax: dd 07fffffffh
74
75g_r64_0dot1: dq 0.1
76g_r64_6dot9: dq 6.9
77g_r64_Zero: dq 0.0
78g_r64_One: dq 1.0
79g_r64_Two: dq 2.0
80g_r64_Three: dq 3.0
81g_r64_Ten: dq 10.0
82g_r64_Eleven: dq 11.0
83g_r64_ThirtyTwo:dq 32.0
84g_r64_Min: dq 00010000000000000h
85g_r64_Max: dq 07fefffffffffffffh
86g_r64_Inf: dq 07ff0000000000000h
87g_r64_SNaN: dq 07ff0000000000001h
88g_r64_SNaNMax: dq 07ff7ffffffffffffh
89g_r64_QNaN: dq 07ff8000000000000h
90g_r64_QNaNMax: dq 07fffffffffffffffh
91g_r64_DnMin: dq 00000000000000001h
92g_r64_DnMax: dq 0000fffffffffffffh
93
94
95g_r80_0dot1: dt 0.1
96g_r80_3dot2: dt 3.2
97g_r80_Zero: dt 0.0
98g_r80_One: dt 1.0
99g_r80_Two: dt 2.0
100g_r80_Three: dt 3.0
101g_r80_Ten: dt 10.0
102g_r80_Eleven: dt 11.0
103g_r80_ThirtyTwo:dt 32.0
104g_r80_Min: dt 000018000000000000000h
105g_r80_Max: dt 07ffeffffffffffffffffh
106g_r80_Inf: dt 07fff8000000000000000h
107
108g_r32V1: dd 3.2
109g_r32V2: dd -1.9
110g_r64V1: dq 6.4
111g_r80V1: dt 8.0
112
113; Denormal numbers.
114g_r32D0: dd 000200000h
115;; @}
116
117;; @name Upconverted Floating point constants
118; @{
119;g_r80_r32_0dot1: dt 0.1
120g_r80_r32_3dot2: dt 04000cccccd0000000000h
121;g_r80_r32_Zero: dt 0.0
122;g_r80_r32_One: dt 1.0
123;g_r80_r32_Two: dt 2.0
124;g_r80_r32_Three: dt 3.0
125;g_r80_r32_Ten: dt 10.0
126;g_r80_r32_Eleven: dt 11.0
127;g_r80_r32_ThirtyTwo: dt 32.0
128;; @}
129
130;; @name Decimal constants.
131; @{
132g_u64Zero: dd 0
133g_u32Zero: dw 0
134g_u64Two: dd 2
135g_u32Two: dw 2
136;; @}
137
138
139;;
140; The last global data item. We build this as we write the code.
141GLOBALNAME g_aTrapInfo
142
143
144;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
145; Defined Constants And Macros ;
146;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
147%define X86_XCPT_UD 6
148%define X86_XCPT_GP 13
149%define X86_XCPT_PF 14
150%define X86_XCPT_MF 16
151
152%define PAGE_SIZE 0x1000
153
154;; Reference a variable
155%ifdef RT_ARCH_AMD64
156 %define REF(a_Name) a_Name wrt rip
157%else
158 %define REF(a_Name) a_Name
159%endif
160
161;; Reference a global variable
162%ifdef RT_ARCH_AMD64
163 %define REF_EXTERN(a_Name) NAME(a_Name) wrt rip
164%else
165 %define REF_EXTERN(a_Name) NAME(a_Name)
166%endif
167
168;;
169; Macro for recording a trapping instruction (simple).
170;
171; @param 1 The trap number.
172; @param 2+ The instruction which should trap.
173%macro ShouldTrap 2+
174%%trap:
175 %2
176%%trap_end:
177 mov eax, __LINE__
178 jmp .return
179BEGINDATA
180%%trapinfo: istruc TRAPINFO
181 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
182 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
183 at TRAPINFO.u8TrapNo, db %1
184 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
185iend
186BEGINCODE
187%%resume:
188%endmacro
189
190
191;;
192; Macro for recording a FPU instruction trapping on a following fwait.
193;
194; Uses stack.
195;
196; @param 1 The status flags that are expected to be set afterwards.
197; @param 2 C0..C3 to mask out in case undefined.
198; @param 3+ The instruction which should trap.
199; @uses eax
200;
201%macro FpuShouldTrap 3+
202 fnclex
203 %3
204%%trap:
205 fwait
206%%trap_end:
207 mov eax, __LINE__
208 jmp .return
209BEGINDATA
210%%trapinfo: istruc TRAPINFO
211 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
212 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
213 at TRAPINFO.u8TrapNo, db X86_XCPT_MF
214 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
215iend
216BEGINCODE
217%%resume:
218 FpuCheckFSW ((%1) | X86_FSW_ES | X86_FSW_B), %2
219 fnclex
220%endmacro
221
222;;
223; Macro for recording checking the FSW value.
224;
225; Uses stack.
226;
227; @param 1 The status flags that are expected to be set afterwards.
228; @param 2 C0..C3 to mask out in case undefined.
229; @uses eax
230;
231%macro FpuCheckFSW 2
232%%resume:
233 fnstsw ax
234 and eax, ~X86_FSW_TOP_MASK & ~(%2)
235 cmp eax, (%1)
236 je %%ok
237 ;int3
238 lea eax, [eax + __LINE__ * 100000]
239 jmp .return
240%%ok:
241%endmacro
242
243
244;;
245; Checks that ST0 has a certain value
246;
247; @uses tword at [xSP]
248;
249%macro CheckSt0Value 3
250 fstp tword [xSP]
251 fld tword [xSP]
252 cmp dword [xSP], %1
253 je %%ok1
254%%bad:
255 mov eax, __LINE__
256 jmp .return
257%%ok1:
258 cmp dword [xSP + 4], %2
259 jne %%bad
260 cmp word [xSP + 8], %3
261 jne %%bad
262%endmacro
263
264;; Checks that ST0 contains QNaN.
265%define CheckSt0Value_QNaN CheckSt0Value 0x00000000, 0xc0000000, 0xffff
266;; Checks that ST0 contains +Inf.
267%define CheckSt0Value_PlusInf CheckSt0Value 0x00000000, 0x80000000, 0x7fff
268;; Checks that ST0 contains 3 & 1/3.
269%define CheckSt0Value_3_and_a_3rd CheckSt0Value 0x55555555, 0xd5555555, 0x4000
270;; Checks that ST0 contains 3 & 1/3.
271%define CheckSt0Value_3_and_two_3rds CheckSt0Value 0xaaaaaaab, 0xeaaaaaaa, 0x4000
272
273
274;;
275; Macro for recording checking the FSW value of a FXSAVE image.
276;
277; Uses stack.
278;
279; @param 1 Address expression for the FXSAVE image.
280; @param 2 The status flags that are expected to be set afterwards.
281; @param 3 C0..C3 to mask out in case undefined.
282; @uses eax
283; @sa FpuCheckFSW
284;
285%macro FxSaveCheckFSW 3
286%%resume:
287 movzx eax, word [%1 + X86FXSTATE.FSW]
288 and eax, ~X86_FSW_TOP_MASK & ~(%3)
289 cmp eax, (%2)
290 je %%ok
291 mov eax, 10000000 + __LINE__
292 jmp .return
293%%ok:
294%endmacro
295
296
297;;
298; Checks that ST0 is empty in an FXSAVE image.
299;
300; @uses eax
301; @param 1 Address expression for the FXSAVE image.
302;
303%macro FxSaveCheckSt0Empty 1
304 movzx eax, word [%1 + X86FXSTATE.FSW]
305 and eax, X86_FSW_TOP_MASK
306 shr eax, X86_FSW_TOP_SHIFT
307 bt [%1 + X86FXSTATE.FTW], eax
308 jnc %%ok
309 mov eax, 20000000 + __LINE__
310 jmp .return
311%%ok:
312%endmacro
313
314
315;;
316; Checks that ST0 is not-empty in an FXSAVE image.
317;
318; @uses eax
319; @param 1 Address expression for the FXSAVE image.
320;
321%macro FxSaveCheckSt0NonEmpty 1
322 movzx eax, word [%1 + X86FXSTATE.FSW]
323 and eax, X86_FSW_TOP_MASK
324 shr eax, X86_FSW_TOP_SHIFT
325 bt [%1 + X86FXSTATE.FTW], eax
326 jc %%ok
327 mov eax, 30000000 + __LINE__
328 jmp .return
329%%ok:
330%endmacro
331
332;;
333; Checks that ST0 in a FXSAVE image has a certain value (empty or not
334; is ignored).
335;
336; @uses eax
337; @param 1 Address expression for the FXSAVE image.
338; @param 2 First dword of value.
339; @param 3 Second dword of value.
340; @param 4 Final word of value.
341;
342%macro FxSaveCheckSt0ValueEx 4
343 cmp dword [%1 + X86FXSTATE.st0], %2
344 je %%ok1
345%%bad:
346 mov eax, 40000000 + __LINE__
347 jmp .return
348%%ok1:
349 cmp dword [%1 + X86FXSTATE.st0 + 4], %3
350 jne %%bad
351 cmp word [%1 + X86FXSTATE.st0 + 8], %4
352 jne %%bad
353%endmacro
354
355
356;;
357; Checks if ST0 in a FXSAVE image has the same value as the specified
358; floating point (80-bit) constant.
359;
360; @uses eax, xDX
361; @param 1 Address expression for the FXSAVE image.
362; @param 2 The address expression of the constant.
363;
364%macro FxSaveCheckSt0ValueConstEx 2
365 mov eax, [%2]
366 cmp dword [%1 + X86FXSTATE.st0], eax
367 je %%ok1
368%%bad:
369 mov eax, 40000000 + __LINE__
370 jmp .return
371%%ok1:
372 mov eax, [4 + %2]
373 cmp dword [%1 + X86FXSTATE.st0 + 4], eax
374 jne %%bad
375 mov ax, [8 + %2]
376 cmp word [%1 + X86FXSTATE.st0 + 8], ax
377 jne %%bad
378%endmacro
379
380
381;;
382; Checks that ST0 in a FXSAVE image has a certain value.
383;
384; @uses eax
385; @param 1 Address expression for the FXSAVE image.
386; @param 2 First dword of value.
387; @param 3 Second dword of value.
388; @param 4 Final word of value.
389;
390%macro FxSaveCheckSt0Value 4
391 FxSaveCheckSt0NonEmpty %1
392 FxSaveCheckSt0ValueEx %1, %2, %3, %4
393%endmacro
394
395
396;;
397; Checks that ST0 in a FXSAVE image is empty and that the value stored is the
398; init value set by FpuInitWithCW.
399;
400; @uses eax
401; @param 1 Address expression for the FXSAVE image.
402;
403%macro FxSaveCheckSt0EmptyInitValue 1
404 FxSaveCheckSt0Empty %1
405 FxSaveCheckSt0ValueEx %1, 0x40404040, 0x40404040, 0xffff
406%endmacro
407
408;;
409; Checks that ST0 in a FXSAVE image is non-empty and has the same value as the
410; specified constant (80-bit).
411;
412; @uses eax, xDX
413; @param 1 Address expression for the FXSAVE image.
414; @param 2 The address expression of the constant.
415%macro FxSaveCheckSt0ValueConst 2
416 FxSaveCheckSt0NonEmpty %1
417 FxSaveCheckSt0ValueConstEx %1, %2
418%endmacro
419
420;; Checks that ST0 contains QNaN.
421%define FxSaveCheckSt0Value_QNaN(p) FxSaveCheckSt0Value p, 0x00000000, 0xc0000000, 0xffff
422;; Checks that ST0 contains +Inf.
423%define FxSaveCheckSt0Value_PlusInf(p) FxSaveCheckSt0Value p, 0x00000000, 0x80000000, 0x7fff
424;; Checks that ST0 contains 3 & 1/3.
425%define FxSaveCheckSt0Value_3_and_a_3rd(p) FxSaveCheckSt0Value p, 0x55555555, 0xd5555555, 0x4000
426;; Checks that ST0 contains 3 & 1/3.
427%define FxSaveCheckSt0Value_3_and_two_3rds(p) FxSaveCheckSt0Value p, 0xaaaaaaab, 0xeaaaaaaa, 0x4000
428
429
430;;
431; Function prologue saving all registers except EAX and aligns the stack
432; on a 16-byte boundrary.
433;
434%macro SAVE_ALL_PROLOGUE 0
435 push xBP
436 mov xBP, xSP
437 pushf
438 push xBX
439 push xCX
440 push xDX
441 push xSI
442 push xDI
443%ifdef RT_ARCH_AMD64
444 push r8
445 push r9
446 push r10
447 push r11
448 push r12
449 push r13
450 push r14
451 push r15
452%endif
453 and xSP, ~0fh;
454%endmacro
455
456
457;;
458; Function epilogue restoring all regisers except EAX.
459;
460%macro SAVE_ALL_EPILOGUE 0
461%ifdef RT_ARCH_AMD64
462 lea rsp, [rbp - 14 * 8]
463 pop r15
464 pop r14
465 pop r13
466 pop r12
467 pop r11
468 pop r10
469 pop r9
470 pop r8
471%else
472 lea esp, [ebp - 6 * 4]
473%endif
474 pop xDI
475 pop xSI
476 pop xDX
477 pop xCX
478 pop xBX
479 popf
480 leave
481%endmacro
482
483
484
485
486BEGINCODE
487
488;;
489; Loads all general registers except xBP and xSP with unique values.
490;
491x861_LoadUniqueRegValues:
492%ifdef RT_ARCH_AMD64
493 mov rax, 00000000000000000h
494 mov rcx, 01111111111111111h
495 mov rdx, 02222222222222222h
496 mov rbx, 03333333333333333h
497 mov rsi, 06666666666666666h
498 mov rdi, 07777777777777777h
499 mov r8, 08888888888888888h
500 mov r9, 09999999999999999h
501 mov r10, 0aaaaaaaaaaaaaaaah
502 mov r11, 0bbbbbbbbbbbbbbbbh
503 mov r12, 0cccccccccccccccch
504 mov r13, 0ddddddddddddddddh
505 mov r14, 0eeeeeeeeeeeeeeeeh
506 mov r15, 0ffffffffffffffffh
507%else
508 mov eax, 000000000h
509 mov ecx, 011111111h
510 mov edx, 022222222h
511 mov ebx, 033333333h
512 mov esi, 066666666h
513 mov edi, 077777777h
514%endif
515 ret
516; end x861_LoadUniqueRegValues
517
518
519;;
520; Clears all general registers except xBP and xSP.
521;
522x861_ClearRegisters:
523 xor eax, eax
524 xor ebx, ebx
525 xor ecx, ecx
526 xor edx, edx
527 xor esi, esi
528 xor edi, edi
529%ifdef RT_ARCH_AMD64
530 xor r8, r8
531 xor r9, r9
532 xor r10, r10
533 xor r11, r11
534 xor r12, r12
535 xor r13, r13
536 xor r14, r14
537 xor r15, r15
538%endif
539 ret
540; x861_ClearRegisters
541
542
543;;
544; Loads all general, MMX and SSE registers except xBP and xSP with unique values.
545;
546x861_LoadUniqueRegValuesSSE:
547 fninit
548 movq mm0, [REF(._mm0)]
549 movq mm1, [REF(._mm1)]
550 movq mm2, [REF(._mm2)]
551 movq mm3, [REF(._mm3)]
552 movq mm4, [REF(._mm4)]
553 movq mm5, [REF(._mm5)]
554 movq mm6, [REF(._mm6)]
555 movq mm7, [REF(._mm7)]
556 movdqu xmm0, [REF(._xmm0)]
557 movdqu xmm1, [REF(._xmm1)]
558 movdqu xmm2, [REF(._xmm2)]
559 movdqu xmm3, [REF(._xmm3)]
560 movdqu xmm4, [REF(._xmm4)]
561 movdqu xmm5, [REF(._xmm5)]
562 movdqu xmm6, [REF(._xmm6)]
563 movdqu xmm7, [REF(._xmm7)]
564%ifdef RT_ARCH_AMD64
565 movdqu xmm8, [REF(._xmm8)]
566 movdqu xmm9, [REF(._xmm9)]
567 movdqu xmm10, [REF(._xmm10)]
568 movdqu xmm11, [REF(._xmm11)]
569 movdqu xmm12, [REF(._xmm12)]
570 movdqu xmm13, [REF(._xmm13)]
571 movdqu xmm14, [REF(._xmm14)]
572 movdqu xmm15, [REF(._xmm15)]
573%endif
574 call x861_LoadUniqueRegValues
575 ret
576._mm0: times 8 db 040h
577._mm1: times 8 db 041h
578._mm2: times 8 db 042h
579._mm3: times 8 db 043h
580._mm4: times 8 db 044h
581._mm5: times 8 db 045h
582._mm6: times 8 db 046h
583._mm7: times 8 db 047h
584._xmm0: times 16 db 080h
585._xmm1: times 16 db 081h
586._xmm2: times 16 db 082h
587._xmm3: times 16 db 083h
588._xmm4: times 16 db 084h
589._xmm5: times 16 db 085h
590._xmm6: times 16 db 086h
591._xmm7: times 16 db 087h
592%ifdef RT_ARCH_AMD64
593._xmm8: times 16 db 088h
594._xmm9: times 16 db 089h
595._xmm10: times 16 db 08ah
596._xmm11: times 16 db 08bh
597._xmm12: times 16 db 08ch
598._xmm13: times 16 db 08dh
599._xmm14: times 16 db 08eh
600._xmm15: times 16 db 08fh
601%endif
602; end x861_LoadUniqueRegValuesSSE
603
604
605;;
606; Clears all MMX and SSE registers.
607;
608x861_ClearRegistersSSE:
609 fninit
610 movq mm0, [REF(.zero)]
611 movq mm1, [REF(.zero)]
612 movq mm2, [REF(.zero)]
613 movq mm3, [REF(.zero)]
614 movq mm4, [REF(.zero)]
615 movq mm5, [REF(.zero)]
616 movq mm6, [REF(.zero)]
617 movq mm7, [REF(.zero)]
618 movdqu xmm0, [REF(.zero)]
619 movdqu xmm1, [REF(.zero)]
620 movdqu xmm2, [REF(.zero)]
621 movdqu xmm3, [REF(.zero)]
622 movdqu xmm4, [REF(.zero)]
623 movdqu xmm5, [REF(.zero)]
624 movdqu xmm6, [REF(.zero)]
625 movdqu xmm7, [REF(.zero)]
626%ifdef RT_ARCH_AMD64
627 movdqu xmm8, [REF(.zero)]
628 movdqu xmm9, [REF(.zero)]
629 movdqu xmm10, [REF(.zero)]
630 movdqu xmm11, [REF(.zero)]
631 movdqu xmm12, [REF(.zero)]
632 movdqu xmm13, [REF(.zero)]
633 movdqu xmm14, [REF(.zero)]
634 movdqu xmm15, [REF(.zero)]
635%endif
636 ret
637
638 ret
639.zero times 16 db 000h
640; x861_ClearRegistersSSE
641
642
643;;
644; Loads all general, MMX and SSE registers except xBP and xSP with unique values.
645;
646x861_LoadUniqueRegValuesSSEAndGRegs:
647 call x861_LoadUniqueRegValuesSSE
648 call x861_LoadUniqueRegValues
649 ret
650
651;;
652; Clears all general, MMX and SSE registers except xBP and xSP.
653;
654x861_ClearRegistersSSEAndGRegs:
655 call x861_ClearRegistersSSE
656 call x861_ClearRegisters
657 ret
658
659BEGINPROC x861_Test1
660 push xBP
661 mov xBP, xSP
662 pushf
663 push xBX
664 push xCX
665 push xDX
666 push xSI
667 push xDI
668%ifdef RT_ARCH_AMD64
669 push r8
670 push r9
671 push r10
672 push r11
673 push r12
674 push r13
675 push r14
676 push r15
677%endif
678
679 ;
680 ; Odd push behavior
681 ;
682%if 0 ; Seems to be so on AMD only
683%ifdef RT_ARCH_X86
684 ; upper word of a 'push cs' is cleared.
685 mov eax, __LINE__
686 mov dword [esp - 4], 0f0f0f0fh
687 push cs
688 pop ecx
689 mov bx, cs
690 and ebx, 0000ffffh
691 cmp ecx, ebx
692 jne .failed
693
694 ; upper word of a 'push ds' is cleared.
695 mov eax, __LINE__
696 mov dword [esp - 4], 0f0f0f0fh
697 push ds
698 pop ecx
699 mov bx, ds
700 and ebx, 0000ffffh
701 cmp ecx, ebx
702 jne .failed
703
704 ; upper word of a 'push es' is cleared.
705 mov eax, __LINE__
706 mov dword [esp - 4], 0f0f0f0fh
707 push es
708 pop ecx
709 mov bx, es
710 and ebx, 0000ffffh
711 cmp ecx, ebx
712 jne .failed
713%endif ; RT_ARCH_X86
714
715 ; The upper part of a 'push fs' is cleared.
716 mov eax, __LINE__
717 xor ecx, ecx
718 not xCX
719 push xCX
720 pop xCX
721 push fs
722 pop xCX
723 mov bx, fs
724 and ebx, 0000ffffh
725 cmp xCX, xBX
726 jne .failed
727
728 ; The upper part of a 'push gs' is cleared.
729 mov eax, __LINE__
730 xor ecx, ecx
731 not xCX
732 push xCX
733 pop xCX
734 push gs
735 pop xCX
736 mov bx, gs
737 and ebx, 0000ffffh
738 cmp xCX, xBX
739 jne .failed
740%endif
741
742%ifdef RT_ARCH_AMD64
743 ; REX.B works with 'push r64'.
744 call x861_LoadUniqueRegValues
745 mov eax, __LINE__
746 push rcx
747 pop rdx
748 cmp rdx, rcx
749 jne .failed
750
751 call x861_LoadUniqueRegValues
752 mov eax, __LINE__
753 db 041h ; REX.B
754 push rcx
755 pop rdx
756 cmp rdx, r9
757 jne .failed
758
759 call x861_LoadUniqueRegValues
760 mov eax, __LINE__
761 db 042h ; REX.X
762 push rcx
763 pop rdx
764 cmp rdx, rcx
765 jne .failed
766
767 call x861_LoadUniqueRegValues
768 mov eax, __LINE__
769 db 044h ; REX.R
770 push rcx
771 pop rdx
772 cmp rdx, rcx
773 jne .failed
774
775 call x861_LoadUniqueRegValues
776 mov eax, __LINE__
777 db 048h ; REX.W
778 push rcx
779 pop rdx
780 cmp rdx, rcx
781 jne .failed
782
783 call x861_LoadUniqueRegValues
784 mov eax, __LINE__
785 db 04fh ; REX.*
786 push rcx
787 pop rdx
788 cmp rdx, r9
789 jne .failed
790%endif
791
792 ;
793 ; Zero extening when moving from a segreg as well as memory access sizes.
794 ;
795 call x861_LoadUniqueRegValues
796 mov eax, __LINE__
797 mov ecx, ds
798 shr xCX, 16
799 cmp xCX, 0
800 jnz .failed
801
802%ifdef RT_ARCH_AMD64
803 call x861_LoadUniqueRegValues
804 mov eax, __LINE__
805 mov rcx, ds
806 shr rcx, 16
807 cmp rcx, 0
808 jnz .failed
809%endif
810
811 call x861_LoadUniqueRegValues
812 mov eax, __LINE__
813 mov xDX, xCX
814 mov cx, ds
815 shr xCX, 16
816 shr xDX, 16
817 cmp xCX, xDX
818 jnz .failed
819
820 ; Loading is always a word access.
821 mov eax, __LINE__
822 mov xDI, [REF_EXTERN(g_pbEfPage)]
823 lea xDI, [xDI + 0x1000 - 2]
824 mov xDX, es
825 mov [xDI], dx
826 mov es, [xDI] ; should not crash
827
828 ; Saving is always a word access.
829 mov eax, __LINE__
830 mov xDI, [REF_EXTERN(g_pbEfPage)]
831 mov dword [xDI + 0x1000 - 4], -1
832 mov [xDI + 0x1000 - 2], ss ; Should not crash.
833 mov bx, ss
834 mov cx, [xDI + 0x1000 - 2]
835 cmp cx, bx
836 jne .failed
837
838%ifdef RT_ARCH_AMD64
839 ; Check that the rex.R and rex.W bits don't have any influence over a memory write.
840 call x861_ClearRegisters
841 mov eax, __LINE__
842 mov xDI, [REF_EXTERN(g_pbEfPage)]
843 mov dword [xDI + 0x1000 - 4], -1
844 db 04ah
845 mov [xDI + 0x1000 - 2], ss ; Should not crash.
846 mov bx, ss
847 mov cx, [xDI + 0x1000 - 2]
848 cmp cx, bx
849 jne .failed
850%endif
851
852
853 ;
854 ; Check what happens when both string prefixes are used.
855 ;
856 cld
857 mov dx, ds
858 mov es, dx
859
860 ; check that repne scasb (al=0) behaves like expected.
861 lea xDI, [REF(g_szAlpha)]
862 xor eax, eax ; find the end
863 mov ecx, g_cchAlpha + 1
864 repne scasb
865 cmp ecx, 1
866 mov eax, __LINE__
867 jne .failed
868
869 ; check that repe scasb (al=0) behaves like expected.
870 lea xDI, [REF(g_szAlpha)]
871 xor eax, eax ; find the end
872 mov ecx, g_cchAlpha + 1
873 repe scasb
874 cmp ecx, g_cchAlpha
875 mov eax, __LINE__
876 jne .failed
877
878 ; repne is last, it wins.
879 lea xDI, [REF(g_szAlpha)]
880 xor eax, eax ; find the end
881 mov ecx, g_cchAlpha + 1
882 db 0f3h ; repe - ignored
883 db 0f2h ; repne
884 scasb
885 cmp ecx, 1
886 mov eax, __LINE__
887 jne .failed
888
889 ; repe is last, it wins.
890 lea xDI, [REF(g_szAlpha)]
891 xor eax, eax ; find the end
892 mov ecx, g_cchAlpha + 1
893 db 0f2h ; repne - ignored
894 db 0f3h ; repe
895 scasb
896 cmp ecx, g_cchAlpha
897 mov eax, __LINE__
898 jne .failed
899
900 ;
901 ; Check if stosb works with both prefixes.
902 ;
903 cld
904 mov dx, ds
905 mov es, dx
906 mov xDI, [REF_EXTERN(g_pbEfPage)]
907 xor eax, eax
908 mov ecx, 01000h
909 rep stosb
910
911 mov xDI, [REF_EXTERN(g_pbEfPage)]
912 mov ecx, 4
913 mov eax, 0ffh
914 db 0f2h ; repne
915 stosb
916 mov eax, __LINE__
917 cmp ecx, 0
918 jne .failed
919 mov eax, __LINE__
920 mov xDI, [REF_EXTERN(g_pbEfPage)]
921 cmp dword [xDI], 0ffffffffh
922 jne .failed
923 cmp dword [xDI+4], 0
924 jne .failed
925
926 mov xDI, [REF_EXTERN(g_pbEfPage)]
927 mov ecx, 4
928 mov eax, 0feh
929 db 0f3h ; repe
930 stosb
931 mov eax, __LINE__
932 cmp ecx, 0
933 jne .failed
934 mov eax, __LINE__
935 mov xDI, [REF_EXTERN(g_pbEfPage)]
936 cmp dword [xDI], 0fefefefeh
937 jne .failed
938 cmp dword [xDI+4], 0
939 jne .failed
940
941 ;
942 ; String operations shouldn't crash because of an invalid address if rCX is 0.
943 ;
944 mov eax, __LINE__
945 cld
946 mov dx, ds
947 mov es, dx
948 mov xDI, [REF_EXTERN(g_pbEfPage)]
949 xor xCX, xCX
950 rep stosb ; no trap
951
952 ;
953 ; INS/OUTS will trap in ring-3 even when rCX is 0. (ASSUMES IOPL < 3)
954 ;
955 mov eax, __LINE__
956 cld
957 mov dx, ss
958 mov ss, dx
959 mov xDI, xSP
960 xor xCX, xCX
961 ShouldTrap X86_XCPT_GP, rep insb
962
963 ;
964 ; SMSW can get to the whole of CR0.
965 ;
966 mov eax, __LINE__
967 xor xBX, xBX
968 smsw xBX
969 test ebx, X86_CR0_PG
970 jz .failed
971 test ebx, X86_CR0_PE
972 jz .failed
973
974 ;
975 ; Will the CPU decode the whole r/m+sib stuff before signalling a lock
976 ; prefix error? Use the EF exec page and a LOCK ADD CL,[rDI + disp32]
977 ; instruction at the very end of it.
978 ;
979 mov eax, __LINE__
980 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
981 add xDI, 1000h - 8h
982 mov byte [xDI+0], 0f0h
983 mov byte [xDI+1], 002h
984 mov byte [xDI+2], 08fh
985 mov dword [xDI+3], 000000000h
986 mov byte [xDI+7], 0cch
987 ShouldTrap X86_XCPT_UD, call xDI
988
989 mov eax, __LINE__
990 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
991 add xDI, 1000h - 7h
992 mov byte [xDI+0], 0f0h
993 mov byte [xDI+1], 002h
994 mov byte [xDI+2], 08Fh
995 mov dword [xDI+3], 000000000h
996 ShouldTrap X86_XCPT_UD, call xDI
997
998 mov eax, __LINE__
999 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1000 add xDI, 1000h - 4h
1001 mov byte [xDI+0], 0f0h
1002 mov byte [xDI+1], 002h
1003 mov byte [xDI+2], 08Fh
1004 mov byte [xDI+3], 000h
1005 ShouldTrap X86_XCPT_PF, call xDI
1006
1007 mov eax, __LINE__
1008 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1009 add xDI, 1000h - 6h
1010 mov byte [xDI+0], 0f0h
1011 mov byte [xDI+1], 002h
1012 mov byte [xDI+2], 08Fh
1013 mov byte [xDI+3], 00h
1014 mov byte [xDI+4], 00h
1015 mov byte [xDI+5], 00h
1016 ShouldTrap X86_XCPT_PF, call xDI
1017
1018 mov eax, __LINE__
1019 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1020 add xDI, 1000h - 5h
1021 mov byte [xDI+0], 0f0h
1022 mov byte [xDI+1], 002h
1023 mov byte [xDI+2], 08Fh
1024 mov byte [xDI+3], 00h
1025 mov byte [xDI+4], 00h
1026 ShouldTrap X86_XCPT_PF, call xDI
1027
1028 mov eax, __LINE__
1029 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1030 add xDI, 1000h - 4h
1031 mov byte [xDI+0], 0f0h
1032 mov byte [xDI+1], 002h
1033 mov byte [xDI+2], 08Fh
1034 mov byte [xDI+3], 00h
1035 ShouldTrap X86_XCPT_PF, call xDI
1036
1037 mov eax, __LINE__
1038 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1039 add xDI, 1000h - 3h
1040 mov byte [xDI+0], 0f0h
1041 mov byte [xDI+1], 002h
1042 mov byte [xDI+2], 08Fh
1043 ShouldTrap X86_XCPT_PF, call xDI
1044
1045 mov eax, __LINE__
1046 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1047 add xDI, 1000h - 2h
1048 mov byte [xDI+0], 0f0h
1049 mov byte [xDI+1], 002h
1050 ShouldTrap X86_XCPT_PF, call xDI
1051
1052 mov eax, __LINE__
1053 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1054 add xDI, 1000h - 1h
1055 mov byte [xDI+0], 0f0h
1056 ShouldTrap X86_XCPT_PF, call xDI
1057
1058
1059
1060.success:
1061 xor eax, eax
1062.return:
1063%ifdef RT_ARCH_AMD64
1064 pop r15
1065 pop r14
1066 pop r13
1067 pop r12
1068 pop r11
1069 pop r10
1070 pop r9
1071 pop r8
1072%endif
1073 pop xDI
1074 pop xSI
1075 pop xDX
1076 pop xCX
1077 pop xBX
1078 popf
1079 leave
1080 ret
1081
1082.failed2:
1083 mov eax, -1
1084.failed:
1085 jmp .return
1086ENDPROC x861_Test1
1087
1088
1089
1090;;
1091; Tests the effect of prefix order in group 14.
1092;
1093BEGINPROC x861_Test2
1094 SAVE_ALL_PROLOGUE
1095
1096 ; Check testcase preconditions.
1097 call x861_LoadUniqueRegValuesSSEAndGRegs
1098 mov eax, __LINE__
1099 db 00Fh, 073h, 0D0h, 080h ; psrlq mm0, 128
1100 call .check_mm0_zero_and_xmm0_nz
1101
1102 call x861_LoadUniqueRegValuesSSEAndGRegs
1103 mov eax, __LINE__
1104 db 066h, 00Fh, 073h, 0D0h, 080h ; psrlq xmm0, 128
1105 call .check_xmm0_zero_and_mm0_nz
1106
1107
1108 ;
1109 ; Real test - Inject other prefixes before the 066h and see what
1110 ; happens.
1111 ;
1112
1113 ; General checks that order does not matter, etc.
1114 call x861_LoadUniqueRegValuesSSEAndGRegs
1115 mov eax, __LINE__
1116 db 026h, 066h, 00Fh, 073h, 0D0h, 080h
1117 call .check_xmm0_zero_and_mm0_nz
1118
1119 call x861_LoadUniqueRegValuesSSEAndGRegs
1120 mov eax, __LINE__
1121 db 066h, 026h, 00Fh, 073h, 0D0h, 080h
1122 call .check_xmm0_zero_and_mm0_nz
1123
1124 call x861_LoadUniqueRegValuesSSEAndGRegs
1125 mov eax, __LINE__
1126 db 066h, 067h, 00Fh, 073h, 0D0h, 080h
1127 call .check_xmm0_zero_and_mm0_nz
1128
1129 call x861_LoadUniqueRegValuesSSEAndGRegs
1130 mov eax, __LINE__
1131 db 067h, 066h, 00Fh, 073h, 0D0h, 080h
1132 call .check_xmm0_zero_and_mm0_nz
1133
1134 call x861_LoadUniqueRegValuesSSEAndGRegs
1135 mov eax, __LINE__
1136 db 067h, 066h, 065h, 00Fh, 073h, 0D0h, 080h
1137 call .check_xmm0_zero_and_mm0_nz
1138
1139%ifdef RT_ARCH_AMD64
1140 call x861_LoadUniqueRegValuesSSEAndGRegs
1141 mov eax, __LINE__
1142 db 048h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.W
1143 call .check_xmm0_zero_and_mm0_nz
1144
1145 call x861_LoadUniqueRegValuesSSEAndGRegs
1146 mov eax, __LINE__
1147 db 044h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.R
1148 call .check_xmm0_zero_and_mm0_nz
1149
1150 call x861_LoadUniqueRegValuesSSEAndGRegs
1151 mov eax, __LINE__
1152 db 042h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.X
1153 call .check_xmm0_zero_and_mm0_nz
1154
1155 ; Actually for REX, order does matter if the prefix is used.
1156 call x861_LoadUniqueRegValuesSSEAndGRegs
1157 mov eax, __LINE__
1158 db 041h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.B
1159 call .check_xmm0_zero_and_mm0_nz
1160
1161 call x861_LoadUniqueRegValuesSSEAndGRegs
1162 mov eax, __LINE__
1163 db 066h, 041h, 00Fh, 073h, 0D0h, 080h ; REX.B
1164 call .check_xmm8_zero_and_xmm0_nz
1165%endif
1166
1167 ; Check all ignored prefixes (repeates some of the above).
1168 call x861_LoadUniqueRegValuesSSEAndGRegs
1169 mov eax, __LINE__
1170 db 066h, 026h, 00Fh, 073h, 0D0h, 080h ; es
1171 call .check_xmm0_zero_and_mm0_nz
1172
1173 call x861_LoadUniqueRegValuesSSEAndGRegs
1174 mov eax, __LINE__
1175 db 066h, 065h, 00Fh, 073h, 0D0h, 080h ; gs
1176 call .check_xmm0_zero_and_mm0_nz
1177
1178 call x861_LoadUniqueRegValuesSSEAndGRegs
1179 mov eax, __LINE__
1180 db 066h, 064h, 00Fh, 073h, 0D0h, 080h ; fs
1181 call .check_xmm0_zero_and_mm0_nz
1182
1183 call x861_LoadUniqueRegValuesSSEAndGRegs
1184 mov eax, __LINE__
1185 db 066h, 02eh, 00Fh, 073h, 0D0h, 080h ; cs
1186 call .check_xmm0_zero_and_mm0_nz
1187
1188 call x861_LoadUniqueRegValuesSSEAndGRegs
1189 mov eax, __LINE__
1190 db 066h, 036h, 00Fh, 073h, 0D0h, 080h ; ss
1191 call .check_xmm0_zero_and_mm0_nz
1192
1193 call x861_LoadUniqueRegValuesSSEAndGRegs
1194 mov eax, __LINE__
1195 db 066h, 03eh, 00Fh, 073h, 0D0h, 080h ; ds
1196 call .check_xmm0_zero_and_mm0_nz
1197
1198 call x861_LoadUniqueRegValuesSSEAndGRegs
1199 mov eax, __LINE__
1200 db 066h, 067h, 00Fh, 073h, 0D0h, 080h ; addr size
1201 call .check_xmm0_zero_and_mm0_nz
1202
1203%ifdef RT_ARCH_AMD64
1204 call x861_LoadUniqueRegValuesSSEAndGRegs
1205 mov eax, __LINE__
1206 db 066h, 048h, 00Fh, 073h, 0D0h, 080h ; REX.W
1207 call .check_xmm0_zero_and_mm0_nz
1208
1209 call x861_LoadUniqueRegValuesSSEAndGRegs
1210 mov eax, __LINE__
1211 db 066h, 044h, 00Fh, 073h, 0D0h, 080h ; REX.R
1212 call .check_xmm0_zero_and_mm0_nz
1213
1214 call x861_LoadUniqueRegValuesSSEAndGRegs
1215 mov eax, __LINE__
1216 db 066h, 042h, 00Fh, 073h, 0D0h, 080h ; REX.X
1217 call .check_xmm0_zero_and_mm0_nz
1218
1219 call x861_LoadUniqueRegValuesSSEAndGRegs
1220 mov eax, __LINE__
1221 db 066h, 041h, 00Fh, 073h, 0D0h, 080h ; REX.B - has actual effect on the instruction.
1222 call .check_xmm8_zero_and_xmm0_nz
1223%endif
1224
1225 ; Repeated prefix until we hit the max opcode limit.
1226 call x861_LoadUniqueRegValuesSSEAndGRegs
1227 mov eax, __LINE__
1228 db 066h, 066h, 00Fh, 073h, 0D0h, 080h
1229 call .check_xmm0_zero_and_mm0_nz
1230
1231 call x861_LoadUniqueRegValuesSSEAndGRegs
1232 mov eax, __LINE__
1233 db 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
1234 call .check_xmm0_zero_and_mm0_nz
1235
1236 call x861_LoadUniqueRegValuesSSEAndGRegs
1237 mov eax, __LINE__
1238 db 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
1239 call .check_xmm0_zero_and_mm0_nz
1240
1241 call x861_LoadUniqueRegValuesSSEAndGRegs
1242 mov eax, __LINE__
1243 db 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
1244 call .check_xmm0_zero_and_mm0_nz
1245
1246 ShouldTrap X86_XCPT_GP, db 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
1247
1248%ifdef RT_ARCH_AMD64
1249 ; Repeated REX is parsed, but only the last byte matters.
1250 call x861_LoadUniqueRegValuesSSEAndGRegs
1251 mov eax, __LINE__
1252 db 066h, 041h, 048h, 00Fh, 073h, 0D0h, 080h ; REX.B, REX.W
1253 call .check_xmm0_zero_and_mm0_nz
1254
1255 call x861_LoadUniqueRegValuesSSEAndGRegs
1256 mov eax, __LINE__
1257 db 066h, 048h, 041h, 00Fh, 073h, 0D0h, 080h ; REX.B, REX.W
1258 call .check_xmm8_zero_and_xmm0_nz
1259
1260 call x861_LoadUniqueRegValuesSSEAndGRegs
1261 mov eax, __LINE__
1262 db 066h, 048h, 044h, 042h, 048h, 044h, 042h, 048h, 044h, 042h, 041h, 00Fh, 073h, 0D0h, 080h
1263 call .check_xmm8_zero_and_xmm0_nz
1264
1265 call x861_LoadUniqueRegValuesSSEAndGRegs
1266 mov eax, __LINE__
1267 db 066h, 041h, 041h, 041h, 041h, 041h, 041h, 041h, 041h, 041h, 04eh, 00Fh, 073h, 0D0h, 080h
1268 call .check_xmm0_zero_and_mm0_nz
1269%endif
1270
1271 ; Undefined sequences with prefixes that counts.
1272 ShouldTrap X86_XCPT_UD, db 0f0h, 066h, 00Fh, 073h, 0D0h, 080h ; LOCK
1273 ShouldTrap X86_XCPT_UD, db 0f2h, 066h, 00Fh, 073h, 0D0h, 080h ; REPNZ
1274 ShouldTrap X86_XCPT_UD, db 0f3h, 066h, 00Fh, 073h, 0D0h, 080h ; REPZ
1275 ShouldTrap X86_XCPT_UD, db 066h, 0f2h, 00Fh, 073h, 0D0h, 080h
1276 ShouldTrap X86_XCPT_UD, db 066h, 0f3h, 00Fh, 073h, 0D0h, 080h
1277 ShouldTrap X86_XCPT_UD, db 066h, 0f3h, 0f2h, 00Fh, 073h, 0D0h, 080h
1278 ShouldTrap X86_XCPT_UD, db 066h, 0f2h, 0f3h, 00Fh, 073h, 0D0h, 080h
1279 ShouldTrap X86_XCPT_UD, db 0f2h, 066h, 0f3h, 00Fh, 073h, 0D0h, 080h
1280 ShouldTrap X86_XCPT_UD, db 0f3h, 066h, 0f2h, 00Fh, 073h, 0D0h, 080h
1281 ShouldTrap X86_XCPT_UD, db 0f3h, 0f2h, 066h, 00Fh, 073h, 0D0h, 080h
1282 ShouldTrap X86_XCPT_UD, db 0f2h, 0f3h, 066h, 00Fh, 073h, 0D0h, 080h
1283 ShouldTrap X86_XCPT_UD, db 0f0h, 0f2h, 066h, 0f3h, 00Fh, 073h, 0D0h, 080h
1284 ShouldTrap X86_XCPT_UD, db 0f0h, 0f3h, 066h, 0f2h, 00Fh, 073h, 0D0h, 080h
1285 ShouldTrap X86_XCPT_UD, db 0f0h, 0f3h, 0f2h, 066h, 00Fh, 073h, 0D0h, 080h
1286 ShouldTrap X86_XCPT_UD, db 0f0h, 0f2h, 0f3h, 066h, 00Fh, 073h, 0D0h, 080h
1287
1288.success:
1289 xor eax, eax
1290.return:
1291 SAVE_ALL_EPILOGUE
1292 ret
1293
1294.check_xmm0_zero_and_mm0_nz:
1295 sub xSP, 20h
1296 movdqu [xSP], xmm0
1297 cmp dword [xSP], 0
1298 jne .failed3
1299 cmp dword [xSP + 4], 0
1300 jne .failed3
1301 cmp dword [xSP + 8], 0
1302 jne .failed3
1303 cmp dword [xSP + 12], 0
1304 jne .failed3
1305 movq [xSP], mm0
1306 cmp dword [xSP], 0
1307 je .failed3
1308 cmp dword [xSP + 4], 0
1309 je .failed3
1310 add xSP, 20h
1311 ret
1312
1313.check_mm0_zero_and_xmm0_nz:
1314 sub xSP, 20h
1315 movq [xSP], mm0
1316 cmp dword [xSP], 0
1317 jne .failed3
1318 cmp dword [xSP + 4], 0
1319 jne .failed3
1320 movdqu [xSP], xmm0
1321 cmp dword [xSP], 0
1322 je .failed3
1323 cmp dword [xSP + 4], 0
1324 je .failed3
1325 cmp dword [xSP + 8], 0
1326 je .failed3
1327 cmp dword [xSP + 12], 0
1328 je .failed3
1329 add xSP, 20h
1330 ret
1331
1332%ifdef RT_ARCH_AMD64
1333.check_xmm8_zero_and_xmm0_nz:
1334 sub xSP, 20h
1335 movdqu [xSP], xmm8
1336 cmp dword [xSP], 0
1337 jne .failed3
1338 cmp dword [xSP + 4], 0
1339 jne .failed3
1340 cmp dword [xSP + 8], 0
1341 jne .failed3
1342 cmp dword [xSP + 12], 0
1343 jne .failed3
1344 movdqu [xSP], xmm0
1345 cmp dword [xSP], 0
1346 je .failed3
1347 cmp dword [xSP + 4], 0
1348 je .failed3
1349 cmp dword [xSP + 8], 0
1350 je .failed3
1351 cmp dword [xSP + 12], 0
1352 je .failed3
1353 add xSP, 20h
1354 ret
1355%endif
1356
1357.failed3:
1358 add xSP, 20h + xS
1359 jmp .return
1360
1361
1362ENDPROC x861_Test2
1363
1364
1365;;
1366; Tests how much fxsave and fxrstor actually accesses of their 512 memory
1367; operand.
1368;
1369BEGINPROC x861_Test3
1370 SAVE_ALL_PROLOGUE
1371 call x861_LoadUniqueRegValuesSSEAndGRegs
1372 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1373
1374 ; Check testcase preconditions.
1375 fxsave [xDI]
1376 fxrstor [xDI]
1377
1378 add xDI, PAGE_SIZE - 512
1379 mov xSI, xDI
1380 fxsave [xDI]
1381 fxrstor [xDI]
1382
1383 ; 464:511 are available to software use. Check that they are left
1384 ; untouched by fxsave.
1385 mov eax, 0aabbccddh
1386 mov ecx, 512 / 4
1387 cld
1388 rep stosd
1389 mov xDI, xSI
1390 fxsave [xDI]
1391
1392 mov ebx, 512
1393.chech_software_area_loop:
1394 cmp [xDI + xBX - 4], eax
1395 jne .chech_software_area_done
1396 sub ebx, 4
1397 jmp .chech_software_area_loop
1398.chech_software_area_done:
1399 cmp ebx, 464
1400 mov eax, __LINE__
1401 ja .return
1402
1403 ; Check that a save + restore + save cycle yield the same results.
1404 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
1405 mov xDI, xBX
1406 mov eax, 066778899h
1407 mov ecx, 512 * 2 / 4
1408 cld
1409 rep stosd
1410 fxsave [xBX]
1411
1412 call x861_ClearRegistersSSEAndGRegs
1413 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
1414 fxrstor [xBX]
1415
1416 fxsave [xBX + 512]
1417 mov xSI, xBX
1418 lea xDI, [xBX + 512]
1419 mov ecx, 512
1420 cld
1421 repe cmpsb
1422 mov eax, __LINE__
1423 jnz .return
1424
1425
1426 ; 464:511 are available to software use. Let see how carefully access
1427 ; to the full 512 bytes are checked...
1428 call x861_LoadUniqueRegValuesSSEAndGRegs
1429 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1430 add xDI, PAGE_SIZE - 512
1431 ShouldTrap X86_XCPT_PF, fxsave [xDI + 16]
1432 ShouldTrap X86_XCPT_PF, fxsave [xDI + 32]
1433 ShouldTrap X86_XCPT_PF, fxsave [xDI + 48]
1434 ShouldTrap X86_XCPT_PF, fxsave [xDI + 64]
1435 ShouldTrap X86_XCPT_PF, fxsave [xDI + 80]
1436 ShouldTrap X86_XCPT_PF, fxsave [xDI + 96]
1437 ShouldTrap X86_XCPT_PF, fxsave [xDI + 128]
1438 ShouldTrap X86_XCPT_PF, fxsave [xDI + 144]
1439 ShouldTrap X86_XCPT_PF, fxsave [xDI + 160]
1440 ShouldTrap X86_XCPT_PF, fxsave [xDI + 176]
1441 ShouldTrap X86_XCPT_PF, fxsave [xDI + 192]
1442 ShouldTrap X86_XCPT_PF, fxsave [xDI + 208]
1443 ShouldTrap X86_XCPT_PF, fxsave [xDI + 224]
1444 ShouldTrap X86_XCPT_PF, fxsave [xDI + 240]
1445 ShouldTrap X86_XCPT_PF, fxsave [xDI + 256]
1446 ShouldTrap X86_XCPT_PF, fxsave [xDI + 384]
1447 ShouldTrap X86_XCPT_PF, fxsave [xDI + 432]
1448 ShouldTrap X86_XCPT_PF, fxsave [xDI + 496]
1449
1450 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 16]
1451 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 32]
1452 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 48]
1453 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 64]
1454 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 80]
1455 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 96]
1456 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 128]
1457 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 144]
1458 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 160]
1459 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 176]
1460 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 192]
1461 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 208]
1462 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 224]
1463 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 240]
1464 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 256]
1465 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 384]
1466 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 432]
1467 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 496]
1468
1469 ; Unaligned accesses will cause #GP(0). This takes precedence over #PF.
1470 ShouldTrap X86_XCPT_GP, fxsave [xDI + 1]
1471 ShouldTrap X86_XCPT_GP, fxsave [xDI + 2]
1472 ShouldTrap X86_XCPT_GP, fxsave [xDI + 3]
1473 ShouldTrap X86_XCPT_GP, fxsave [xDI + 4]
1474 ShouldTrap X86_XCPT_GP, fxsave [xDI + 5]
1475 ShouldTrap X86_XCPT_GP, fxsave [xDI + 6]
1476 ShouldTrap X86_XCPT_GP, fxsave [xDI + 7]
1477 ShouldTrap X86_XCPT_GP, fxsave [xDI + 8]
1478 ShouldTrap X86_XCPT_GP, fxsave [xDI + 9]
1479 ShouldTrap X86_XCPT_GP, fxsave [xDI + 10]
1480 ShouldTrap X86_XCPT_GP, fxsave [xDI + 11]
1481 ShouldTrap X86_XCPT_GP, fxsave [xDI + 12]
1482 ShouldTrap X86_XCPT_GP, fxsave [xDI + 13]
1483 ShouldTrap X86_XCPT_GP, fxsave [xDI + 14]
1484 ShouldTrap X86_XCPT_GP, fxsave [xDI + 15]
1485
1486 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 1]
1487 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 2]
1488 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 3]
1489 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 4]
1490 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 5]
1491 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 6]
1492 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 7]
1493 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 8]
1494 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 9]
1495 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 10]
1496 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 11]
1497 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 12]
1498 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 13]
1499 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 14]
1500 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 15]
1501
1502 ; Lets check what a FP in fxsave changes ... nothing on intel.
1503 mov ebx, 16
1504.fxsave_pf_effect_loop:
1505 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1506 add xDI, PAGE_SIZE - 512 * 2
1507 mov xSI, xDI
1508 mov eax, 066778899h
1509 mov ecx, 512 * 2 / 4
1510 cld
1511 rep stosd
1512
1513 ShouldTrap X86_XCPT_PF, fxsave [xSI + PAGE_SIZE - 512 + xBX]
1514
1515 mov ecx, 512 / 4
1516 lea xDI, [xSI + 512]
1517 cld
1518 repz cmpsd
1519 lea xAX, [xBX + 20000]
1520 jnz .return
1521
1522 add ebx, 16
1523 cmp ebx, 512
1524 jbe .fxsave_pf_effect_loop
1525
1526 ; Lets check that a FP in fxrstor does not have any effect on the FPU or SSE state.
1527 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1528 mov ecx, PAGE_SIZE / 4
1529 mov eax, 0ffaa33cch
1530 cld
1531 rep stosd
1532
1533 call x861_LoadUniqueRegValuesSSEAndGRegs
1534 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1535 fxsave [xDI]
1536
1537 call x861_ClearRegistersSSEAndGRegs
1538 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1539 fxsave [xDI + 512]
1540
1541 mov ebx, 16
1542.fxrstor_pf_effect_loop:
1543 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1544 mov xSI, xDI
1545 lea xDI, [xDI + PAGE_SIZE - 512 + xBX]
1546 mov ecx, 512
1547 sub ecx, ebx
1548 cld
1549 rep movsb ; copy unique state to end of page.
1550
1551 push xBX
1552 call x861_ClearRegistersSSEAndGRegs
1553 pop xBX
1554 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1555 ShouldTrap X86_XCPT_PF, fxrstor [xDI + PAGE_SIZE - 512 + xBX] ; try load unique state
1556
1557 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1558 lea xSI, [xDI + 512] ; point it to the clean state, which is what we expect.
1559 lea xDI, [xDI + 1024]
1560 fxsave [xDI] ; save whatever the fpu state currently is.
1561 mov ecx, 512 / 4
1562 cld
1563 repe cmpsd
1564 lea xAX, [xBX + 40000]
1565 jnz .return ; it shouldn't be modified by faulting fxrstor, i.e. a clean state.
1566
1567 add ebx, 16
1568 cmp ebx, 512
1569 jbe .fxrstor_pf_effect_loop
1570
1571.success:
1572 xor eax, eax
1573.return:
1574 SAVE_ALL_EPILOGUE
1575 ret
1576ENDPROC x861_Test3
1577
1578
1579;;
1580; Tests various multibyte NOP sequences.
1581;
1582BEGINPROC x861_Test4
1583 SAVE_ALL_PROLOGUE
1584 call x861_ClearRegisters
1585
1586 ; Intel recommended sequences.
1587 nop
1588 db 066h, 090h
1589 db 00fh, 01fh, 000h
1590 db 00fh, 01fh, 040h, 000h
1591 db 00fh, 01fh, 044h, 000h, 000h
1592 db 066h, 00fh, 01fh, 044h, 000h, 000h
1593 db 00fh, 01fh, 080h, 000h, 000h, 000h, 000h
1594 db 00fh, 01fh, 084h, 000h, 000h, 000h, 000h, 000h
1595 db 066h, 00fh, 01fh, 084h, 000h, 000h, 000h, 000h, 000h
1596
1597 ; Check that the NOPs are allergic to lock prefixing.
1598 ShouldTrap X86_XCPT_UD, db 0f0h, 090h ; lock prefixed NOP.
1599 ShouldTrap X86_XCPT_UD, db 0f0h, 066h, 090h ; lock prefixed two byte NOP.
1600 ShouldTrap X86_XCPT_UD, db 0f0h, 00fh, 01fh, 000h ; lock prefixed three byte NOP.
1601
1602 ; Check the range of instructions that AMD marks as NOPs.
1603%macro TST_NOP 1
1604 db 00fh, %1, 000h
1605 db 00fh, %1, 040h, 000h
1606 db 00fh, %1, 044h, 000h, 000h
1607 db 066h, 00fh, %1, 044h, 000h, 000h
1608 db 00fh, %1, 080h, 000h, 000h, 000h, 000h
1609 db 00fh, %1, 084h, 000h, 000h, 000h, 000h, 000h
1610 db 066h, 00fh, %1, 084h, 000h, 000h, 000h, 000h, 000h
1611 ShouldTrap X86_XCPT_UD, db 0f0h, 00fh, %1, 000h
1612%endmacro
1613 TST_NOP 019h
1614 TST_NOP 01ah
1615 TST_NOP 01bh
1616 TST_NOP 01ch
1617 TST_NOP 01dh
1618 TST_NOP 01eh
1619 TST_NOP 01fh
1620
1621 ; The AMD P group, intel marks this as a NOP.
1622 TST_NOP 00dh
1623
1624.success:
1625 xor eax, eax
1626.return:
1627 SAVE_ALL_EPILOGUE
1628 ret
1629ENDPROC x861_Test4
1630
1631
1632;;
1633; Tests an reserved FPU encoding, checking that it does not affect the FPU or
1634; CPU state in any way.
1635;
1636; @uses stack
1637%macro FpuNopEncoding 1+
1638 fnclex
1639 call SetFSW_C0_thru_C3
1640
1641 push xBP
1642 mov xBP, xSP
1643 sub xSP, 1024
1644 and xSP, ~0fh
1645 call SaveFPUAndGRegsToStack
1646 %1
1647 call CompareFPUAndGRegsOnStack
1648 leave
1649
1650 jz %%ok
1651 add eax, __LINE__
1652 jmp .return
1653%%ok:
1654%endmacro
1655
1656;;
1657; Used for marking encodings which has a meaning other than FNOP and
1658; needs investigating.
1659%macro FpuReservedEncoding 2
1660 fnclex
1661 call SetFSW_C0_thru_C3
1662
1663 push xBP
1664 mov xBP, xSP
1665 sub xSP, 2048
1666 and xSP, ~0fh
1667 arch_fxsave [xSP + 1024]
1668 %1
1669 call SaveFPUAndGRegsToStack
1670
1671 arch_fxrstor [xSP + 1024]
1672 %2
1673 call CompareFPUAndGRegsOnStack
1674 ;arch_fxrstor [xSP + 1024]
1675 leave
1676
1677 jz %%ok
1678 add eax, __LINE__
1679 jmp .return
1680%%ok:
1681%endmacro
1682
1683
1684;;
1685; Saves the FPU and general registers to the stack area right next to the
1686; return address.
1687;
1688; The required area size is 512 + 80h = 640.
1689;
1690; @uses Nothing, except stack.
1691;
1692SaveFPUAndGRegsToStack:
1693 ; Must clear the FXSAVE area.
1694 pushf
1695 push xCX
1696 push xAX
1697 push xDI
1698
1699 lea xDI, [xSP + xS * 5]
1700 mov xCX, 512 / 4
1701 mov eax, 0cccccccch
1702 cld
1703 rep stosd
1704
1705 pop xDI
1706 pop xAX
1707 pop xCX
1708 popf
1709
1710 ; Save the FPU state.
1711 arch_fxsave [xSP + xS]
1712
1713 ; Save GRegs (80h bytes).
1714%ifdef RT_ARCH_AMD64
1715 mov [xSP + 512 + xS + 000h], xAX
1716 mov [xSP + 512 + xS + 008h], xBX
1717 mov [xSP + 512 + xS + 010h], xCX
1718 mov [xSP + 512 + xS + 018h], xDX
1719 mov [xSP + 512 + xS + 020h], xDI
1720 mov [xSP + 512 + xS + 028h], xSI
1721 mov [xSP + 512 + xS + 030h], xBP
1722 mov [xSP + 512 + xS + 038h], r8
1723 mov [xSP + 512 + xS + 040h], r9
1724 mov [xSP + 512 + xS + 048h], r10
1725 mov [xSP + 512 + xS + 050h], r11
1726 mov [xSP + 512 + xS + 058h], r12
1727 mov [xSP + 512 + xS + 060h], r13
1728 mov [xSP + 512 + xS + 068h], r14
1729 mov [xSP + 512 + xS + 070h], r15
1730 pushf
1731 pop rax
1732 mov [xSP + 512 + xS + 078h], rax
1733 mov rax, [xSP + 512 + xS + 000h]
1734%else
1735 mov [xSP + 512 + xS + 000h], eax
1736 mov [xSP + 512 + xS + 004h], eax
1737 mov [xSP + 512 + xS + 008h], ebx
1738 mov [xSP + 512 + xS + 00ch], ebx
1739 mov [xSP + 512 + xS + 010h], ecx
1740 mov [xSP + 512 + xS + 014h], ecx
1741 mov [xSP + 512 + xS + 018h], edx
1742 mov [xSP + 512 + xS + 01ch], edx
1743 mov [xSP + 512 + xS + 020h], edi
1744 mov [xSP + 512 + xS + 024h], edi
1745 mov [xSP + 512 + xS + 028h], esi
1746 mov [xSP + 512 + xS + 02ch], esi
1747 mov [xSP + 512 + xS + 030h], ebp
1748 mov [xSP + 512 + xS + 034h], ebp
1749 mov [xSP + 512 + xS + 038h], eax
1750 mov [xSP + 512 + xS + 03ch], eax
1751 mov [xSP + 512 + xS + 040h], eax
1752 mov [xSP + 512 + xS + 044h], eax
1753 mov [xSP + 512 + xS + 048h], eax
1754 mov [xSP + 512 + xS + 04ch], eax
1755 mov [xSP + 512 + xS + 050h], eax
1756 mov [xSP + 512 + xS + 054h], eax
1757 mov [xSP + 512 + xS + 058h], eax
1758 mov [xSP + 512 + xS + 05ch], eax
1759 mov [xSP + 512 + xS + 060h], eax
1760 mov [xSP + 512 + xS + 064h], eax
1761 mov [xSP + 512 + xS + 068h], eax
1762 mov [xSP + 512 + xS + 06ch], eax
1763 mov [xSP + 512 + xS + 070h], eax
1764 mov [xSP + 512 + xS + 074h], eax
1765 pushf
1766 pop eax
1767 mov [xSP + 512 + xS + 078h], eax
1768 mov [xSP + 512 + xS + 07ch], eax
1769 mov eax, [xSP + 512 + xS + 000h]
1770%endif
1771 ret
1772
1773;;
1774; Compares the current FPU and general registers to that found in the stack
1775; area prior to the return address.
1776;
1777; @uses Stack, flags and eax/rax.
1778; @returns eax is zero on success, eax is 1000000 * offset on failure.
1779; ZF reflects the eax value to save a couple of instructions...
1780;
1781CompareFPUAndGRegsOnStack:
1782 lea xSP, [xSP - (1024 - xS)]
1783 call SaveFPUAndGRegsToStack
1784
1785 push xSI
1786 push xDI
1787 push xCX
1788
1789 mov xCX, 640
1790 lea xSI, [xSP + xS*3]
1791 lea xDI, [xSI + 1024]
1792
1793 mov word [xSI + X86FXSTATE.FOP], 0 ; ignore
1794 mov dword [xSI + X86FXSTATE.FPUIP], 0 ; ignore
1795 mov dword [xDI + X86FXSTATE.FPUDP], 0 ; ignore
1796
1797 cld
1798 repe cmpsb
1799 je .ok
1800
1801 ;int3
1802 lea xAX, [xSP + xS*3]
1803 xchg xAX, xSI
1804 sub xAX, xSI
1805
1806 push xDX
1807 mov xDX, 1000000
1808 mul xDX
1809 pop xDX
1810 jmp .return
1811.ok:
1812 xor eax, eax
1813.return:
1814 pop xCX
1815 pop xDI
1816 pop xSI
1817 lea xSP, [xSP + (1024 - xS)]
1818 or eax, eax
1819 ret
1820
1821
1822SetFSW_C0_thru_C3:
1823 sub xSP, 20h
1824 fstenv [xSP]
1825 or word [xSP + 4], X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3
1826 fldenv [xSP]
1827 add xSP, 20h
1828 ret
1829
1830
1831;;
1832; Tests some odd floating point instruction encodings.
1833;
1834BEGINPROC x861_Test5
1835 SAVE_ALL_PROLOGUE
1836
1837 ; standard stuff...
1838 fld dword [REF(g_r32V1)]
1839 fld qword [REF(g_r64V1)]
1840 fld tword [REF(g_r80V1)]
1841 fld qword [REF(g_r64V1)]
1842 fld dword [REF(g_r32V2)]
1843 fld dword [REF(g_r32V1)]
1844
1845 ; Test the nop check.
1846 FpuNopEncoding fnop
1847
1848
1849 ; the 0xd9 block
1850 ShouldTrap X86_XCPT_UD, db 0d9h, 008h
1851 ShouldTrap X86_XCPT_UD, db 0d9h, 009h
1852 ShouldTrap X86_XCPT_UD, db 0d9h, 00ah
1853 ShouldTrap X86_XCPT_UD, db 0d9h, 00bh
1854 ShouldTrap X86_XCPT_UD, db 0d9h, 00ch
1855 ShouldTrap X86_XCPT_UD, db 0d9h, 00dh
1856 ShouldTrap X86_XCPT_UD, db 0d9h, 00eh
1857 ShouldTrap X86_XCPT_UD, db 0d9h, 00fh
1858
1859 ShouldTrap X86_XCPT_UD, db 0d9h, 0d1h
1860 ShouldTrap X86_XCPT_UD, db 0d9h, 0d2h
1861 ShouldTrap X86_XCPT_UD, db 0d9h, 0d3h
1862 ShouldTrap X86_XCPT_UD, db 0d9h, 0d4h
1863 ShouldTrap X86_XCPT_UD, db 0d9h, 0d5h
1864 ShouldTrap X86_XCPT_UD, db 0d9h, 0d6h
1865 ShouldTrap X86_XCPT_UD, db 0d9h, 0d7h
1866 FpuReservedEncoding {db 0d9h, 0d8h}, { fstp st0 }
1867 FpuReservedEncoding {db 0d9h, 0d9h}, { fstp st1 }
1868 FpuReservedEncoding {db 0d9h, 0dah}, { fstp st2 }
1869 FpuReservedEncoding {db 0d9h, 0dbh}, { fstp st3 }
1870 FpuReservedEncoding {db 0d9h, 0dch}, { fstp st4 }
1871 FpuReservedEncoding {db 0d9h, 0ddh}, { fstp st5 }
1872 FpuReservedEncoding {db 0d9h, 0deh}, { fstp st6 }
1873 ;FpuReservedEncoding {db 0d9h, 0dfh}, { fstp st7 } ; This variant seems to ignore empty ST(0) values!
1874 ShouldTrap X86_XCPT_UD, db 0d9h, 0e2h
1875 ShouldTrap X86_XCPT_UD, db 0d9h, 0e3h
1876 ShouldTrap X86_XCPT_UD, db 0d9h, 0e6h
1877 ShouldTrap X86_XCPT_UD, db 0d9h, 0e7h
1878 ShouldTrap X86_XCPT_UD, db 0d9h, 0efh
1879 ShouldTrap X86_XCPT_UD, db 0d9h, 008h
1880 ShouldTrap X86_XCPT_UD, db 0d9h, 00fh
1881
1882 ; the 0xda block
1883 ShouldTrap X86_XCPT_UD, db 0dah, 0e0h
1884 ShouldTrap X86_XCPT_UD, db 0dah, 0e1h
1885 ShouldTrap X86_XCPT_UD, db 0dah, 0e2h
1886 ShouldTrap X86_XCPT_UD, db 0dah, 0e3h
1887 ShouldTrap X86_XCPT_UD, db 0dah, 0e4h
1888 ShouldTrap X86_XCPT_UD, db 0dah, 0e5h
1889 ShouldTrap X86_XCPT_UD, db 0dah, 0e6h
1890 ShouldTrap X86_XCPT_UD, db 0dah, 0e7h
1891 ShouldTrap X86_XCPT_UD, db 0dah, 0e8h
1892 ShouldTrap X86_XCPT_UD, db 0dah, 0eah
1893 ShouldTrap X86_XCPT_UD, db 0dah, 0ebh
1894 ShouldTrap X86_XCPT_UD, db 0dah, 0ech
1895 ShouldTrap X86_XCPT_UD, db 0dah, 0edh
1896 ShouldTrap X86_XCPT_UD, db 0dah, 0eeh
1897 ShouldTrap X86_XCPT_UD, db 0dah, 0efh
1898 ShouldTrap X86_XCPT_UD, db 0dah, 0f0h
1899 ShouldTrap X86_XCPT_UD, db 0dah, 0f1h
1900 ShouldTrap X86_XCPT_UD, db 0dah, 0f2h
1901 ShouldTrap X86_XCPT_UD, db 0dah, 0f3h
1902 ShouldTrap X86_XCPT_UD, db 0dah, 0f4h
1903 ShouldTrap X86_XCPT_UD, db 0dah, 0f5h
1904 ShouldTrap X86_XCPT_UD, db 0dah, 0f6h
1905 ShouldTrap X86_XCPT_UD, db 0dah, 0f7h
1906 ShouldTrap X86_XCPT_UD, db 0dah, 0f8h
1907 ShouldTrap X86_XCPT_UD, db 0dah, 0f9h
1908 ShouldTrap X86_XCPT_UD, db 0dah, 0fah
1909 ShouldTrap X86_XCPT_UD, db 0dah, 0fbh
1910 ShouldTrap X86_XCPT_UD, db 0dah, 0fch
1911 ShouldTrap X86_XCPT_UD, db 0dah, 0fdh
1912 ShouldTrap X86_XCPT_UD, db 0dah, 0feh
1913 ShouldTrap X86_XCPT_UD, db 0dah, 0ffh
1914
1915 ; the 0xdb block
1916 FpuNopEncoding db 0dbh, 0e0h ; fneni
1917 FpuNopEncoding db 0dbh, 0e1h ; fndisi
1918 FpuNopEncoding db 0dbh, 0e4h ; fnsetpm
1919 ShouldTrap X86_XCPT_UD, db 0dbh, 0e5h
1920 ShouldTrap X86_XCPT_UD, db 0dbh, 0e6h
1921 ShouldTrap X86_XCPT_UD, db 0dbh, 0e7h
1922 ShouldTrap X86_XCPT_UD, db 0dbh, 0f8h
1923 ShouldTrap X86_XCPT_UD, db 0dbh, 0f9h
1924 ShouldTrap X86_XCPT_UD, db 0dbh, 0fah
1925 ShouldTrap X86_XCPT_UD, db 0dbh, 0fbh
1926 ShouldTrap X86_XCPT_UD, db 0dbh, 0fch
1927 ShouldTrap X86_XCPT_UD, db 0dbh, 0fdh
1928 ShouldTrap X86_XCPT_UD, db 0dbh, 0feh
1929 ShouldTrap X86_XCPT_UD, db 0dbh, 0ffh
1930 ShouldTrap X86_XCPT_UD, db 0dbh, 020h
1931 ShouldTrap X86_XCPT_UD, db 0dbh, 023h
1932 ShouldTrap X86_XCPT_UD, db 0dbh, 030h
1933 ShouldTrap X86_XCPT_UD, db 0dbh, 032h
1934
1935 ; the 0xdc block
1936 FpuReservedEncoding {db 0dch, 0d0h}, { fcom st0 }
1937 FpuReservedEncoding {db 0dch, 0d1h}, { fcom st1 }
1938 FpuReservedEncoding {db 0dch, 0d2h}, { fcom st2 }
1939 FpuReservedEncoding {db 0dch, 0d3h}, { fcom st3 }
1940 FpuReservedEncoding {db 0dch, 0d4h}, { fcom st4 }
1941 FpuReservedEncoding {db 0dch, 0d5h}, { fcom st5 }
1942 FpuReservedEncoding {db 0dch, 0d6h}, { fcom st6 }
1943 FpuReservedEncoding {db 0dch, 0d7h}, { fcom st7 }
1944 FpuReservedEncoding {db 0dch, 0d8h}, { fcomp st0 }
1945 FpuReservedEncoding {db 0dch, 0d9h}, { fcomp st1 }
1946 FpuReservedEncoding {db 0dch, 0dah}, { fcomp st2 }
1947 FpuReservedEncoding {db 0dch, 0dbh}, { fcomp st3 }
1948 FpuReservedEncoding {db 0dch, 0dch}, { fcomp st4 }
1949 FpuReservedEncoding {db 0dch, 0ddh}, { fcomp st5 }
1950 FpuReservedEncoding {db 0dch, 0deh}, { fcomp st6 }
1951 FpuReservedEncoding {db 0dch, 0dfh}, { fcomp st7 }
1952
1953 ; the 0xdd block
1954 FpuReservedEncoding {db 0ddh, 0c8h}, { fxch st0 }
1955 FpuReservedEncoding {db 0ddh, 0c9h}, { fxch st1 }
1956 FpuReservedEncoding {db 0ddh, 0cah}, { fxch st2 }
1957 FpuReservedEncoding {db 0ddh, 0cbh}, { fxch st3 }
1958 FpuReservedEncoding {db 0ddh, 0cch}, { fxch st4 }
1959 FpuReservedEncoding {db 0ddh, 0cdh}, { fxch st5 }
1960 FpuReservedEncoding {db 0ddh, 0ceh}, { fxch st6 }
1961 FpuReservedEncoding {db 0ddh, 0cfh}, { fxch st7 }
1962 ShouldTrap X86_XCPT_UD, db 0ddh, 0f0h
1963 ShouldTrap X86_XCPT_UD, db 0ddh, 0f1h
1964 ShouldTrap X86_XCPT_UD, db 0ddh, 0f2h
1965 ShouldTrap X86_XCPT_UD, db 0ddh, 0f3h
1966 ShouldTrap X86_XCPT_UD, db 0ddh, 0f4h
1967 ShouldTrap X86_XCPT_UD, db 0ddh, 0f5h
1968 ShouldTrap X86_XCPT_UD, db 0ddh, 0f6h
1969 ShouldTrap X86_XCPT_UD, db 0ddh, 0f7h
1970 ShouldTrap X86_XCPT_UD, db 0ddh, 0f8h
1971 ShouldTrap X86_XCPT_UD, db 0ddh, 0f9h
1972 ShouldTrap X86_XCPT_UD, db 0ddh, 0fah
1973 ShouldTrap X86_XCPT_UD, db 0ddh, 0fbh
1974 ShouldTrap X86_XCPT_UD, db 0ddh, 0fch
1975 ShouldTrap X86_XCPT_UD, db 0ddh, 0fdh
1976 ShouldTrap X86_XCPT_UD, db 0ddh, 0feh
1977 ShouldTrap X86_XCPT_UD, db 0ddh, 0ffh
1978 ShouldTrap X86_XCPT_UD, db 0ddh, 028h
1979 ShouldTrap X86_XCPT_UD, db 0ddh, 02fh
1980
1981 ; the 0xde block
1982 FpuReservedEncoding {db 0deh, 0d0h}, { fcomp st0 }
1983 FpuReservedEncoding {db 0deh, 0d1h}, { fcomp st1 }
1984 FpuReservedEncoding {db 0deh, 0d2h}, { fcomp st2 }
1985 FpuReservedEncoding {db 0deh, 0d3h}, { fcomp st3 }
1986 FpuReservedEncoding {db 0deh, 0d4h}, { fcomp st4 }
1987 FpuReservedEncoding {db 0deh, 0d5h}, { fcomp st5 }
1988 FpuReservedEncoding {db 0deh, 0d6h}, { fcomp st6 }
1989 FpuReservedEncoding {db 0deh, 0d7h}, { fcomp st7 }
1990 ShouldTrap X86_XCPT_UD, db 0deh, 0d8h
1991 ShouldTrap X86_XCPT_UD, db 0deh, 0dah
1992 ShouldTrap X86_XCPT_UD, db 0deh, 0dbh
1993 ShouldTrap X86_XCPT_UD, db 0deh, 0dch
1994 ShouldTrap X86_XCPT_UD, db 0deh, 0ddh
1995 ShouldTrap X86_XCPT_UD, db 0deh, 0deh
1996 ShouldTrap X86_XCPT_UD, db 0deh, 0dfh
1997
1998 ; the 0xdf block
1999 FpuReservedEncoding {db 0dfh, 0c8h}, { fxch st0 }
2000 FpuReservedEncoding {db 0dfh, 0c9h}, { fxch st1 }
2001 FpuReservedEncoding {db 0dfh, 0cah}, { fxch st2 }
2002 FpuReservedEncoding {db 0dfh, 0cbh}, { fxch st3 }
2003 FpuReservedEncoding {db 0dfh, 0cch}, { fxch st4 }
2004 FpuReservedEncoding {db 0dfh, 0cdh}, { fxch st5 }
2005 FpuReservedEncoding {db 0dfh, 0ceh}, { fxch st6 }
2006 FpuReservedEncoding {db 0dfh, 0cfh}, { fxch st7 }
2007 FpuReservedEncoding {db 0dfh, 0d0h}, { fstp st0 }
2008 FpuReservedEncoding {db 0dfh, 0d1h}, { fstp st1 }
2009 FpuReservedEncoding {db 0dfh, 0d2h}, { fstp st2 }
2010 FpuReservedEncoding {db 0dfh, 0d3h}, { fstp st3 }
2011 FpuReservedEncoding {db 0dfh, 0d4h}, { fstp st4 }
2012 FpuReservedEncoding {db 0dfh, 0d5h}, { fstp st5 }
2013 FpuReservedEncoding {db 0dfh, 0d6h}, { fstp st6 }
2014 FpuReservedEncoding {db 0dfh, 0d7h}, { fstp st7 }
2015 FpuReservedEncoding {db 0dfh, 0d8h}, { fstp st0 }
2016 FpuReservedEncoding {db 0dfh, 0d9h}, { fstp st1 }
2017 FpuReservedEncoding {db 0dfh, 0dah}, { fstp st2 }
2018 FpuReservedEncoding {db 0dfh, 0dbh}, { fstp st3 }
2019 FpuReservedEncoding {db 0dfh, 0dch}, { fstp st4 }
2020 FpuReservedEncoding {db 0dfh, 0ddh}, { fstp st5 }
2021 FpuReservedEncoding {db 0dfh, 0deh}, { fstp st6 }
2022 FpuReservedEncoding {db 0dfh, 0dfh}, { fstp st7 }
2023 ShouldTrap X86_XCPT_UD, db 0dfh, 0e1h
2024 ShouldTrap X86_XCPT_UD, db 0dfh, 0e2h
2025 ShouldTrap X86_XCPT_UD, db 0dfh, 0e3h
2026 ShouldTrap X86_XCPT_UD, db 0dfh, 0e4h
2027 ShouldTrap X86_XCPT_UD, db 0dfh, 0e5h
2028 ShouldTrap X86_XCPT_UD, db 0dfh, 0e6h
2029 ShouldTrap X86_XCPT_UD, db 0dfh, 0e7h
2030 ShouldTrap X86_XCPT_UD, db 0dfh, 0f8h
2031 ShouldTrap X86_XCPT_UD, db 0dfh, 0f9h
2032 ShouldTrap X86_XCPT_UD, db 0dfh, 0fah
2033 ShouldTrap X86_XCPT_UD, db 0dfh, 0fbh
2034 ShouldTrap X86_XCPT_UD, db 0dfh, 0fch
2035 ShouldTrap X86_XCPT_UD, db 0dfh, 0fdh
2036 ShouldTrap X86_XCPT_UD, db 0dfh, 0feh
2037 ShouldTrap X86_XCPT_UD, db 0dfh, 0ffh
2038
2039
2040.success:
2041 xor eax, eax
2042.return:
2043 SAVE_ALL_EPILOGUE
2044 ret
2045
2046ENDPROC x861_Test5
2047
2048
2049;;
2050; Tests some floating point exceptions and such.
2051;
2052;
2053;
2054BEGINPROC x861_Test6
2055 SAVE_ALL_PROLOGUE
2056 sub xSP, 2048
2057
2058 ; Load some pointers.
2059 lea xSI, [REF(g_r32V1)]
2060 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
2061 add xDI, PAGE_SIZE ; invalid page.
2062
2063 ;
2064 ; Check denormal numbers.
2065 ; Turns out the number is loaded onto the stack even if an exception is triggered.
2066 ;
2067 fninit
2068 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2069 fldcw [xSP]
2070 FpuShouldTrap X86_FSW_DE, 0, fld dword [REF(g_r32D0)]
2071 CheckSt0Value 0x00000000, 0x80000000, 0x3f7f
2072
2073 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_DM
2074 fldcw [xSP]
2075 fld dword [REF(g_r32D0)]
2076 fwait
2077 FpuCheckFSW X86_FSW_DE, 0
2078 CheckSt0Value 0x00000000, 0x80000000, 0x3f7f
2079
2080 ;
2081 ; stack overflow
2082 ;
2083 fninit
2084 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2085 fldcw [xSP]
2086 fld qword [REF(g_r64V1)]
2087 fld dword [xSI]
2088 fld dword [xSI]
2089 fld dword [xSI]
2090 fld dword [xSI]
2091 fld dword [xSI]
2092 fld dword [xSI]
2093 fld tword [REF(g_r80V1)]
2094 fwait
2095
2096 FpuShouldTrap X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3, \
2097 fld dword [xSI]
2098 CheckSt0Value 0x00000000, 0x80000000, 0x4002
2099
2100 FpuShouldTrap X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3, \
2101 fld dword [xSI]
2102 CheckSt0Value 0x00000000, 0x80000000, 0x4002
2103
2104 ; stack overflow vs #PF.
2105 ShouldTrap X86_XCPT_PF, fld dword [xDI]
2106 fwait
2107
2108 ; stack overflow vs denormal number
2109 FpuShouldTrap X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3, \
2110 fld dword [xSI]
2111 CheckSt0Value 0x00000000, 0x80000000, 0x4002
2112
2113 ;
2114 ; Mask the overflow exception. We should get QNaN now regardless of
2115 ; what we try to push (provided the memory is valid).
2116 ;
2117 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_IM
2118 fldcw [xSP]
2119
2120 fld dword [xSI]
2121 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2122 fnclex
2123 CheckSt0Value 0x00000000, 0xc0000000, 0xffff
2124
2125 fld qword [REF(g_r64V1)]
2126 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2127 fnclex
2128 CheckSt0Value 0x00000000, 0xc0000000, 0xffff
2129
2130 ; This is includes denormal values.
2131 fld dword [REF(g_r32D0)]
2132 fwait
2133 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2134 CheckSt0Value 0x00000000, 0xc0000000, 0xffff
2135 fnclex
2136
2137 ;
2138 ; #PF vs previous stack overflow. I.e. whether pending FPU exception
2139 ; is checked before fetching memory operands.
2140 ;
2141 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2142 fldcw [xSP]
2143 fld qword [REF(g_r64V1)]
2144 ShouldTrap X86_XCPT_MF, fld dword [xDI]
2145 fnclex
2146
2147 ;
2148 ; What happens when we unmask an exception and fwait?
2149 ;
2150 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_IM
2151 fldcw [xSP]
2152 fld dword [xSI]
2153 fwait
2154 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2155 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2156 fldcw [xSP]
2157 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
2158
2159 ShouldTrap X86_XCPT_MF, fwait
2160 ShouldTrap X86_XCPT_MF, fwait
2161 ShouldTrap X86_XCPT_MF, fwait
2162 fnclex
2163
2164
2165.success:
2166 xor eax, eax
2167.return:
2168 add xSP, 2048
2169 SAVE_ALL_EPILOGUE
2170 ret
2171ENDPROC x861_Test6
2172
2173
2174extern NAME(RTTestISub)
2175
2176;;
2177; Sets the current subtest.
2178%macro SetSubTest 1
2179%ifdef RT_ARCH_AMD64
2180 %ifdef ASM_CALL64_GCC
2181 lea rdi, [%%s_szName wrt rip]
2182 %else
2183 lea rcx, [%%s_szName wrt rip]
2184 %endif
2185 call NAME(RTTestISub)
2186%else
2187 push %%s_szName
2188 call NAME(RTTestISub)
2189 add esp, 4
2190%endif
2191 jmp %%done
2192%%s_szName:
2193 db %1, 0
2194%%done:
2195%endmacro
2196
2197
2198;;
2199; Checks the opcode and CS:IP FPU.
2200;
2201; @returns ZF=1 on success, ZF=0 on failure.
2202; @param xSP + xS fxsave image followed by fnstenv.
2203; @param xCX Opcode address (no prefixes).
2204;
2205CheckOpcodeCsIp:
2206 push xBP
2207 mov xBP, xSP
2208 push xAX
2209
2210 ; Check the IP.
2211%ifdef RT_ARCH_AMD64
2212 cmp rcx, [xBP + xS*2 + X86FXSTATE.FPUIP]
2213%else
2214 cmp ecx, [xBP + xS*2 + X86FXSTATE.FPUIP]
2215%endif
2216 jne .failure1
2217
2218 mov ax, cs
2219 cmp ax, [xBP + xS*2 + 512 + X86FSTENV32P.FPUCS]
2220 jne .failure2
2221
2222 ; Check the opcode. This may be disabled.
2223 cmp word [xBP + xS*2 + X86FXSTATE.FOP], 0
2224 je .success
2225
2226 mov ah, [xCX]
2227 mov al, [xCX + 1]
2228 and ax, 07ffh
2229 cmp ax, [xBP + xS*2 + X86FXSTATE.FOP]
2230 jne .failure3
2231
2232.success:
2233 xor eax, eax ; clear Z
2234.return:
2235 pop xAX
2236 leave
2237 ret
2238
2239.failure1:
2240 mov eax, 10000000
2241 jmp .failure
2242.failure2:
2243 mov eax, 20000000
2244 jmp .failure
2245.failure3:
2246 mov eax, 30000000
2247 jmp .failure
2248.failure:
2249 or eax, eax
2250 leave
2251 ret
2252
2253
2254
2255
2256
2257;;
2258; Checks the opcode, CS:IP and DS:DP of the FPU.
2259;
2260; @returns ZF=1 on success, ZF=0+EAX on failure.
2261; @param xSP + xS fxsave image followed by fnstenv.
2262; @param xCX Opcode address (no prefixes).
2263; @param xDX Memory address (DS relative).
2264;
2265CheckOpcodeCsIpDsDp:
2266 push xBP
2267 mov xBP, xSP
2268 push xAX
2269
2270 ; Check the memory operand.
2271%ifdef RT_ARCH_AMD64
2272 cmp rdx, [xBP + xS*2 + X86FXSTATE.FPUDP]
2273%else
2274 cmp edx, [xBP + xS*2 + X86FXSTATE.FPUDP]
2275%endif
2276 jne .failure1
2277
2278 mov ax, ds
2279 cmp ax, [xBP + xS*2 + 512 + X86FSTENV32P.FPUDS]
2280 jne .failure2
2281
2282.success:
2283 pop xAX
2284 leave
2285 ; Let CheckOpcodeCsIp to the rest.
2286 jmp CheckOpcodeCsIp
2287
2288.failure1:
2289 mov eax, 60000000
2290 jmp .failure
2291.failure2:
2292 mov eax, 80000000
2293.failure:
2294 or eax, eax
2295 leave
2296 ret
2297
2298
2299;;
2300; Checks a FPU instruction taking a memory operand.
2301;
2302; @uses xCX, xDX, xAX, Stack.
2303;
2304%macro FpuCheckOpcodeCsIpDsDp 2
2305%%instruction:
2306 %1
2307 arch_fxsave [xSP]
2308 fnstenv [xSP + 512] ; for the selectors (64-bit)
2309 arch_fxrstor [xSP] ; fnstenv screws up the ES bit.
2310 lea xDX, %2
2311 lea xCX, [REF(%%instruction)]
2312 call CheckOpcodeCsIpDsDp
2313 jz %%ok
2314 or eax, __LINE__
2315 jmp .return
2316%%ok:
2317%endmacro
2318
2319
2320;;
2321; Checks a trapping FPU instruction taking a memory operand.
2322;
2323; Upon return, there is are two FXSAVE image on the stack at xSP.
2324;
2325; @uses xCX, xDX, xAX, Stack.
2326;
2327; @param %1 The instruction.
2328; @param %2 Operand memory address (DS relative).
2329;
2330%macro FpuTrapOpcodeCsIpDsDp 2
2331%%instruction:
2332 %1
2333 fxsave [xSP + 1024 +512] ; FPUDS and FPUCS for 64-bit hosts.
2334 ; WEIRD: When saved after FWAIT they are ZEROed! (64-bit Intel)
2335%%trap:
2336 fwait
2337%%trap_end:
2338 mov eax, __LINE__
2339 jmp .return
2340BEGINDATA
2341%%trapinfo: istruc TRAPINFO
2342 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
2343 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
2344 at TRAPINFO.u8TrapNo, db X86_XCPT_MF
2345 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
2346iend
2347BEGINCODE
2348%%resume:
2349 arch_fxsave [xSP]
2350 lea xDX, %2
2351 lea xCX, [REF(%%instruction)]
2352 call CheckOpcodeCsIpDsDp
2353 jz %%ok
2354 or eax, __LINE__
2355 jmp .return
2356%%ok:
2357%endmacro
2358
2359
2360;;
2361; Initialize the FPU and set CW to %1.
2362;
2363; @uses dword at [xSP].
2364;
2365%macro FpuInitWithCW 1
2366 call x861_LoadUniqueRegValuesSSE
2367 fninit
2368 mov dword [xSP], %1
2369 fldcw [xSP]
2370%endmacro
2371
2372
2373;;
2374; First bunch of FPU instruction tests.
2375;
2376;
2377BEGINPROC x861_TestFPUInstr1
2378 SAVE_ALL_PROLOGUE
2379 sub xSP, 2048
2380
2381 ; Make xBX (preserved accross calls) point to the invalid page.
2382 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
2383 add xBX, PAGE_SIZE
2384
2385 ;
2386 ; FDIV with 64-bit floating point memory operand.
2387 ;
2388 SetSubTest "FDIV m64r"
2389
2390 ; ## Normal operation. ##
2391 fninit
2392 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2393 CheckSt0Value 0x00000000, 0xcccccd00, 0x4000
2394 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_One)] }, [REF(g_r64_One)]
2395 FpuCheckFSW 0, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2396 CheckSt0Value 0x00000000, 0xcccccd00, 0x4000
2397
2398
2399 ; ## Masked exceptions. ##
2400 ; Masked stack underflow.
2401 fninit
2402 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_One)] }, [REF(g_r64_One)]
2403 FpuCheckFSW X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2404 CheckSt0Value_QNaN
2405
2406 ; Masked zero divide.
2407 fninit
2408 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2409 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2410 FpuCheckFSW X86_FSW_ZE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2411 CheckSt0Value_PlusInf
2412
2413 ; Masked Inf/Inf.
2414 fninit
2415 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Inf)] }, [REF(g_r32_Inf)]
2416 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Inf)] }, [REF(g_r64_Inf)]
2417 FpuCheckFSW X86_FSW_IE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2418 CheckSt0Value_QNaN
2419
2420 ; Masked 0/0.
2421 fninit
2422 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Zero)] }, [REF(g_r32_Zero)]
2423 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2424 FpuCheckFSW X86_FSW_IE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2425 CheckSt0Value_QNaN
2426
2427 ; Masked precision exception, rounded down.
2428 fninit
2429 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Ten)] }, [REF(g_r32_Ten)]
2430 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2431 FpuCheckFSW X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2432 CheckSt0Value_3_and_a_3rd
2433
2434 ; Masked precision exception, rounded up.
2435 fninit
2436 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Eleven)] }, [REF(g_r32_Eleven)]
2437 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2438 FpuCheckFSW X86_FSW_PE | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2439 CheckSt0Value_3_and_two_3rds
2440
2441 ; Masked overflow exception.
2442 fninit
2443 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Max)] }, [REF(g_r80_Max)]
2444 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_0dot1)] }, [REF(g_r64_0dot1)]
2445 FpuCheckFSW X86_FSW_PE | X86_FSW_OE | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2446 CheckSt0Value_PlusInf
2447
2448 ; Masked underflow exception.
2449 fninit
2450 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Min)] }, [REF(g_r80_Min)]
2451 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Ten)] }, [REF(g_r64_Ten)]
2452 FpuCheckFSW X86_FSW_PE | X86_FSW_UE | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2453 CheckSt0Value 0xcccccccd, 0x0ccccccc, 0x0000
2454
2455 ; Denormal operand.
2456 fninit
2457 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_One)] }, [REF(g_r80_One)]
2458 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_DnMax)] }, [REF(g_r64_DnMax)]
2459 FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2460 FxSaveCheckSt0Value xSP, 0x00000800, 0x80000000, 0x43fd
2461
2462 ; ## Unmasked exceptions. ##
2463%if 1
2464 ; Stack underflow - TOP and ST0 unmodified.
2465 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2466 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_One)] }, [REF(g_r64_One)]
2467 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_B | X86_FSW_ES, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2468 FxSaveCheckSt0EmptyInitValue xSP
2469
2470 ; Zero divide - Unmodified ST0.
2471 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2472 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2473 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2474 FxSaveCheckFSW xSP, X86_FSW_ZE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2475 FxSaveCheckSt0ValueConst xSP, REF(g_r80_r32_3dot2)
2476
2477 ; Invalid Operand (Inf/Inf) - Unmodified ST0.
2478 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2479 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Inf)] }, [REF(g_r32_Inf)]
2480 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Inf)] }, [REF(g_r64_Inf)]
2481 FpuCheckFSW X86_FSW_IE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2482 FxSaveCheckSt0ValueConst xSP, REF(g_r80_Inf)
2483
2484 ; Invalid Operand (0/0) - Unmodified ST0.
2485 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2486 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Zero)] }, [REF(g_r32_Zero)]
2487 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2488 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2489 FxSaveCheckSt0ValueConst xSP, REF(g_r80_Zero)
2490
2491 ; Precision exception, rounded down.
2492 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2493 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Ten)] }, [REF(g_r32_Ten)]
2494 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2495 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2496 FxSaveCheckSt0Value_3_and_a_3rd(xSP)
2497
2498 ; Precision exception, rounded up.
2499 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2500 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Eleven)] }, [REF(g_r32_Eleven)]
2501 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2502 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_C1 | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2503 FxSaveCheckSt0Value_3_and_two_3rds(xSP)
2504
2505 ; Overflow exception.
2506 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2507 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Max)] }, [REF(g_r80_Max)]
2508 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_0dot1)] }, [REF(g_r64_0dot1)]
2509 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_OE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2510 FxSaveCheckSt0Value xSP, 0xfffffd7f, 0x9fffffff, 0x2002
2511
2512 ; Underflow exception.
2513 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2514 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Min)] }, [REF(g_r80_Min)]
2515 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Ten)] }, [REF(g_r64_Ten)]
2516 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_UE | X86_FSW_C1 | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2517 FxSaveCheckSt0Value xSP, 0xcccccccd, 0xcccccccc, 0x5ffd
2518
2519 ; Denormal operand - Unmodified ST0.
2520 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2521 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_One)] }, [REF(g_r80_One)]
2522 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_DnMax)] }, [REF(g_r64_DnMax)]
2523 FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2524 FxSaveCheckSt0ValueConst xSP, REF(g_r80_One)
2525%endif
2526
2527
2528 ; ## A couple of variations on the #PF theme. ##
2529
2530.success:
2531 xor eax, eax
2532.return:
2533 add xSP, 2048
2534 SAVE_ALL_EPILOGUE
2535 ret
2536
2537ENDPROC x861_TestFPUInstr1
2538
2539
2540
2541
2542;;
2543; Terminate the trap info array with a NIL entry.
2544BEGINDATA
2545GLOBALNAME g_aTrapInfoEnd
2546istruc TRAPINFO
2547 at TRAPINFO.uTrapPC, RTCCPTR_DEF 0
2548 at TRAPINFO.uResumePC, RTCCPTR_DEF 0
2549 at TRAPINFO.u8TrapNo, db 0
2550 at TRAPINFO.cbInstr, db 0
2551iend
2552
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