VirtualBox

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

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

IEM: fst[p], fist[p] and fisttp implementations and fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 108.6 KB
Line 
1; $Id: tstX86-1A.asm 40248 2012-02-24 16:12:05Z 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
74g_r32_NegQNaN: dd 0ffc00000h
75
76g_r64_0dot1: dq 0.1
77g_r64_6dot9: dq 6.9
78g_r64_Zero: dq 0.0
79g_r64_One: dq 1.0
80g_r64_Two: dq 2.0
81g_r64_Three: dq 3.0
82g_r64_Ten: dq 10.0
83g_r64_Eleven: dq 11.0
84g_r64_ThirtyTwo:dq 32.0
85g_r64_Min: dq 00010000000000000h
86g_r64_Max: dq 07fefffffffffffffh
87g_r64_Inf: dq 07ff0000000000000h
88g_r64_SNaN: dq 07ff0000000000001h
89g_r64_SNaNMax: dq 07ff7ffffffffffffh
90g_r64_NegQNaN: dq 0fff8000000000000h
91g_r64_QNaN: dq 07ff8000000000000h
92g_r64_QNaNMax: dq 07fffffffffffffffh
93g_r64_DnMin: dq 00000000000000001h
94g_r64_DnMax: dq 0000fffffffffffffh
95
96
97g_r80_0dot1: dt 0.1
98g_r80_3dot2: dt 3.2
99g_r80_Zero: dt 0.0
100g_r80_One: dt 1.0
101g_r80_Two: dt 2.0
102g_r80_Three: dt 3.0
103g_r80_Ten: dt 10.0
104g_r80_Eleven: dt 11.0
105g_r80_ThirtyTwo:dt 32.0
106g_r80_Min: dt 000018000000000000000h
107g_r80_Max: dt 07ffeffffffffffffffffh
108g_r80_Inf: dt 07fff8000000000000000h
109g_r80_QNaN: dt 07fffc000000000000000h
110g_r80_QNaNMax: dt 07fffffffffffffffffffh
111g_r80_NegQNaN: dt 0ffffc000000000000000h
112g_r80_SNaN: dt 07fff8000000000000001h
113g_r80_SNaNMax: dt 07fffbfffffffffffffffh
114g_r80_DnMin: dt 000000000000000000001h
115g_r80_DnMax: dt 000007fffffffffffffffh
116
117g_r32V1: dd 3.2
118g_r32V2: dd -1.9
119g_r64V1: dq 6.4
120g_r80V1: dt 8.0
121
122; Denormal numbers.
123g_r32D0: dd 000200000h
124;; @}
125
126;; @name Upconverted Floating point constants
127; @{
128;g_r80_r32_0dot1: dt 0.1
129g_r80_r32_3dot2: dt 04000cccccd0000000000h
130;g_r80_r32_Zero: dt 0.0
131;g_r80_r32_One: dt 1.0
132;g_r80_r32_Two: dt 2.0
133;g_r80_r32_Three: dt 3.0
134;g_r80_r32_Ten: dt 10.0
135;g_r80_r32_Eleven: dt 11.0
136;g_r80_r32_ThirtyTwo: dt 32.0
137;; @}
138
139;; @name Decimal constants.
140; @{
141g_u64Zero: dd 0
142g_u32Zero: dw 0
143g_u64Two: dd 2
144g_u32Two: dw 2
145;; @}
146
147
148;;
149; The last global data item. We build this as we write the code.
150GLOBALNAME g_aTrapInfo
151
152
153;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
154; Defined Constants And Macros ;
155;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
156;; Reference a variable
157%ifdef RT_ARCH_AMD64
158 %define REF(a_Name) a_Name wrt rip
159%else
160 %define REF(a_Name) a_Name
161%endif
162
163;; Reference a global variable
164%ifdef RT_ARCH_AMD64
165 %define REF_EXTERN(a_Name) NAME(a_Name) wrt rip
166%else
167 %define REF_EXTERN(a_Name) NAME(a_Name)
168%endif
169
170
171;;
172; Macro for checking a memory value.
173;
174; @param 1 The size (byte, word, dword, etc)
175; @param 2 The memory address expression.
176; @param 3 The valued expected at the location.
177%macro CheckMemoryValue 3
178 cmp %1 [%2], %3
179 je %%ok
180 mov eax, __LINE__
181 jmp .return
182%%ok:
183%endmacro
184
185
186;;
187; Checks if a 32-bit floating point memory value is the same as the specified
188; constant (also memory).
189;
190; @uses eax
191; @param 1 Address expression for the 32-bit floating point value
192; to be checked.
193; @param 2 The address expression of the constant.
194;
195%macro CheckMemoryR32ValueConst 2
196 mov eax, [%2]
197 cmp dword [%1], eax
198 je %%ok
199%%bad:
200 mov eax, 90000000 + __LINE__
201 jmp .return
202%%ok:
203%endmacro
204
205
206;;
207; Checks if a 80-bit floating point memory value is the same as the specified
208; constant (also memory).
209;
210; @uses eax
211; @param 1 Address expression for the FXSAVE image.
212; @param 2 The address expression of the constant.
213;
214%macro CheckMemoryR80ValueConst 2
215 mov eax, [%2]
216 cmp dword [%1], eax
217 je %%ok1
218%%bad:
219 mov eax, 92000000 + __LINE__
220 jmp .return
221%%ok1:
222 mov eax, [4 + %2]
223 cmp dword [%1 + 4], eax
224 jne %%bad
225 mov ax, [8 + %2]
226 cmp word [%1 + 8], ax
227 jne %%bad
228%endmacro
229
230
231;;
232; Macro for recording a trapping instruction (simple).
233;
234; @param 1 The trap number.
235; @param 2+ The instruction which should trap.
236%macro ShouldTrap 2+
237%%trap:
238 %2
239%%trap_end:
240 mov eax, __LINE__
241 jmp .return
242BEGINDATA
243%%trapinfo: istruc TRAPINFO
244 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
245 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
246 at TRAPINFO.u8TrapNo, db %1
247 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
248iend
249BEGINCODE
250%%resume:
251%endmacro
252
253;;
254; Macro for recording a trapping instruction in the exec page.
255;
256; @uses xAX, xDX
257; @param 1 The trap number.
258; @param 2 The offset into the exec page.
259%macro ShouldTrapExecPage 2
260 lea xDX, [REF(NAME(g_aTrapInfoExecPage))]
261 lea xAX, [REF(%%resume)]
262 mov byte [xDX + TRAPINFO.cbInstr], PAGE_SIZE - (%2)
263 mov byte [xDX + TRAPINFO.u8TrapNo], %1
264 mov [xDX + TRAPINFO.uResumePC], xAX
265 mov xAX, [REF_EXTERN(g_pbEfExecPage)]
266 lea xAX, [xAX + (%2)]
267 mov [xDX + TRAPINFO.uTrapPC], xAX
268 jmp xAX
269%%resume:
270%endmacro
271
272
273;;
274; Macro for recording a FPU instruction trapping on a following fwait.
275;
276; Uses stack.
277;
278; @param 1 The status flags that are expected to be set afterwards.
279; @param 2 C0..C3 to mask out in case undefined.
280; @param 3+ The instruction which should trap.
281; @uses eax
282;
283%macro FpuShouldTrap 3+
284 fnclex
285 %3
286%%trap:
287 fwait
288%%trap_end:
289 mov eax, __LINE__
290 jmp .return
291BEGINDATA
292%%trapinfo: istruc TRAPINFO
293 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
294 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
295 at TRAPINFO.u8TrapNo, db X86_XCPT_MF
296 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
297iend
298BEGINCODE
299%%resume:
300 FpuCheckFSW ((%1) | X86_FSW_ES | X86_FSW_B), %2
301 fnclex
302%endmacro
303
304;;
305; Macro for recording checking the FSW value.
306;
307; Uses stack.
308;
309; @param 1 The status flags that are expected to be set afterwards.
310; @param 2 C0..C3 to mask out in case undefined.
311; @uses eax
312;
313%macro FpuCheckFSW 2
314%%resume:
315 fnstsw ax
316 and eax, ~X86_FSW_TOP_MASK & ~(%2)
317 cmp eax, (%1)
318 je %%ok
319 ;int3
320 lea eax, [eax + __LINE__ * 100000]
321 jmp .return
322%%ok:
323%endmacro
324
325
326;;
327; Checks that ST0 has a certain value
328;
329; @uses tword at [xSP]
330;
331%macro CheckSt0Value 3
332 fstp tword [xSP]
333 fld tword [xSP]
334 cmp dword [xSP], %1
335 je %%ok1
336%%bad:
337 mov eax, __LINE__
338 jmp .return
339%%ok1:
340 cmp dword [xSP + 4], %2
341 jne %%bad
342 cmp word [xSP + 8], %3
343 jne %%bad
344%endmacro
345
346;; Checks that ST0 contains QNaN.
347%define CheckSt0Value_QNaN CheckSt0Value 0x00000000, 0xc0000000, 0xffff
348;; Checks that ST0 contains +Inf.
349%define CheckSt0Value_PlusInf CheckSt0Value 0x00000000, 0x80000000, 0x7fff
350;; Checks that ST0 contains 3 & 1/3.
351%define CheckSt0Value_3_and_a_3rd CheckSt0Value 0x55555555, 0xd5555555, 0x4000
352;; Checks that ST0 contains 3 & 1/3.
353%define CheckSt0Value_3_and_two_3rds CheckSt0Value 0xaaaaaaab, 0xeaaaaaaa, 0x4000
354;; Checks that ST0 contains 8.0.
355%define CheckSt0Value_Eight CheckSt0Value 0x00000000, 0x80000000, 0x4002
356
357
358;;
359; Macro for recording checking the FSW value of a FXSAVE image.
360;
361; Uses stack.
362;
363; @param 1 Address expression for the FXSAVE image.
364; @param 2 The status flags that are expected to be set afterwards.
365; @param 3 C0..C3 to mask out in case undefined.
366; @uses eax
367; @sa FpuCheckFSW
368;
369%macro FxSaveCheckFSW 3
370%%resume:
371 movzx eax, word [%1 + X86FXSTATE.FSW]
372 and eax, ~X86_FSW_TOP_MASK & ~(%3)
373 cmp eax, (%2)
374 je %%ok
375 mov eax, 100000000 + __LINE__
376 jmp .return
377%%ok:
378%endmacro
379
380
381;;
382; Checks that ST0 is empty in an FXSAVE image.
383;
384; @uses eax
385; @param 1 Address expression for the FXSAVE image.
386;
387%macro FxSaveCheckSt0Empty 1
388 movzx eax, word [%1 + X86FXSTATE.FSW]
389 and eax, X86_FSW_TOP_MASK
390 shr eax, X86_FSW_TOP_SHIFT
391 bt [%1 + X86FXSTATE.FTW], eax
392 jnc %%ok
393 mov eax, 200000000 + __LINE__
394 jmp .return
395%%ok:
396%endmacro
397
398
399;;
400; Checks that ST0 is not-empty in an FXSAVE image.
401;
402; @uses eax
403; @param 1 Address expression for the FXSAVE image.
404;
405%macro FxSaveCheckSt0NonEmpty 1
406 movzx eax, word [%1 + X86FXSTATE.FSW]
407 and eax, X86_FSW_TOP_MASK
408 shr eax, X86_FSW_TOP_SHIFT
409 bt [%1 + X86FXSTATE.FTW], eax
410 jc %%ok
411 mov eax, 30000000 + __LINE__
412 jmp .return
413%%ok:
414%endmacro
415
416;;
417; Checks that STn in a FXSAVE image has a certain value (empty or not
418; is ignored).
419;
420; @uses eax
421; @param 1 Address expression for the FXSAVE image.
422; @param 2 The register number.
423; @param 3 First dword of value.
424; @param 4 Second dword of value.
425; @param 5 Final word of value.
426;
427%macro FxSaveCheckStNValueEx 5
428 cmp dword [%1 + X86FXSTATE.st0 + %2 * 16], %3
429 je %%ok1
430%%bad:
431 mov eax, 40000000 + __LINE__
432 jmp .return
433%%ok1:
434 cmp dword [%1 + X86FXSTATE.st0 + %2 * 16 + 4], %4
435 jne %%bad
436 cmp word [%1 + X86FXSTATE.st0 + %2 * 16 + 8], %5
437 jne %%bad
438%endmacro
439
440
441;;
442; Checks if STn in a FXSAVE image has the same value as the specified
443; floating point (80-bit) constant.
444;
445; @uses eax, xDX
446; @param 1 Address expression for the FXSAVE image.
447; @param 2 The register number.
448; @param 3 The address expression of the constant.
449;
450%macro FxSaveCheckStNValueConstEx 3
451 mov eax, [%3]
452 cmp dword [%1 + X86FXSTATE.st0 + %2 * 16], eax
453 je %%ok1
454%%bad:
455 mov eax, 40000000 + __LINE__
456 jmp .return
457%%ok1:
458 mov eax, [4 + %3]
459 cmp dword [%1 + X86FXSTATE.st0 + %2 * 16 + 4], eax
460 jne %%bad
461 mov ax, [8 + %3]
462 cmp word [%1 + X86FXSTATE.st0 + %2 * 16 + 8], ax
463 jne %%bad
464%endmacro
465
466
467;;
468; Checks that ST0 in a FXSAVE image has a certain value.
469;
470; @uses eax
471; @param 1 Address expression for the FXSAVE image.
472; @param 2 First dword of value.
473; @param 3 Second dword of value.
474; @param 4 Final word of value.
475;
476%macro FxSaveCheckSt0Value 4
477 FxSaveCheckSt0NonEmpty %1
478 FxSaveCheckStNValueEx %1, 0, %2, %3, %4
479%endmacro
480
481
482;;
483; Checks that ST0 in a FXSAVE image is empty and that the value stored is the
484; init value set by FpuInitWithCW.
485;
486; @uses eax
487; @param 1 Address expression for the FXSAVE image.
488;
489%macro FxSaveCheckSt0EmptyInitValue 1
490 FxSaveCheckSt0Empty %1
491 FxSaveCheckStNValueEx %1, 0, 0x40404040, 0x40404040, 0xffff
492%endmacro
493
494;;
495; Checks that ST0 in a FXSAVE image is non-empty and has the same value as the
496; specified constant (80-bit).
497;
498; @uses eax, xDX
499; @param 1 Address expression for the FXSAVE image.
500; @param 2 The address expression of the constant.
501%macro FxSaveCheckSt0ValueConst 2
502 FxSaveCheckSt0NonEmpty %1
503 FxSaveCheckStNValueConstEx %1, 0, %2
504%endmacro
505
506;; Checks that ST0 contains QNaN.
507%define FxSaveCheckSt0Value_QNaN(p) FxSaveCheckSt0Value p, 0x00000000, 0xc0000000, 0xffff
508;; Checks that ST0 contains +Inf.
509%define FxSaveCheckSt0Value_PlusInf(p) FxSaveCheckSt0Value p, 0x00000000, 0x80000000, 0x7fff
510;; Checks that ST0 contains 3 & 1/3.
511%define FxSaveCheckSt0Value_3_and_a_3rd(p) FxSaveCheckSt0Value p, 0x55555555, 0xd5555555, 0x4000
512;; Checks that ST0 contains 3 & 1/3.
513%define FxSaveCheckSt0Value_3_and_two_3rds(p) FxSaveCheckSt0Value p, 0xaaaaaaab, 0xeaaaaaaa, 0x4000
514
515
516
517;;
518; Checks that STn is empty in an FXSAVE image.
519;
520; @uses eax
521; @param 1 Address expression for the FXSAVE image.
522; @param 2 The register number.
523;
524%macro FxSaveCheckStNEmpty 2
525 movzx eax, word [%1 + X86FXSTATE.FSW]
526 and eax, X86_FSW_TOP_MASK
527 shr eax, X86_FSW_TOP_SHIFT
528 add eax, %2
529 and eax, X86_FSW_TOP_SMASK
530 bt [%1 + X86FXSTATE.FTW], eax
531 jnc %%ok
532 mov eax, 20000000 + __LINE__
533 jmp .return
534%%ok:
535%endmacro
536
537
538;;
539; Checks that STn is not-empty in an FXSAVE image.
540;
541; @uses eax
542; @param 1 Address expression for the FXSAVE image.
543; @param 2 The register number.
544;
545%macro FxSaveCheckStNNonEmpty 2
546 movzx eax, word [%1 + X86FXSTATE.FSW]
547 and eax, X86_FSW_TOP_MASK
548 shr eax, X86_FSW_TOP_SHIFT
549 add eax, %2
550 and eax, X86_FSW_TOP_SMASK
551 bt [%1 + X86FXSTATE.FTW], eax
552 jc %%ok
553 mov eax, 30000000 + __LINE__
554 jmp .return
555%%ok:
556%endmacro
557
558
559;;
560; Checks that STn in a FXSAVE image has a certain value.
561;
562; @uses eax
563; @param 1 Address expression for the FXSAVE image.
564; @param 2 The register number.
565; @param 3 First dword of value.
566; @param 4 Second dword of value.
567; @param 5 Final word of value.
568;
569%macro FxSaveCheckStNValue 5
570 FxSaveCheckStNNonEmpty %1, %2
571 FxSaveCheckStNValueEx %1, %2, %3, %4, %5
572%endmacro
573
574;;
575; Checks that ST0 in a FXSAVE image is non-empty and has the same value as the
576; specified constant (80-bit).
577;
578; @uses eax, xDX
579; @param 1 Address expression for the FXSAVE image.
580; @param 2 The register number.
581; @param 3 The address expression of the constant.
582%macro FxSaveCheckStNValueConst 3
583 FxSaveCheckStNNonEmpty %1, %2
584 FxSaveCheckStNValueConstEx %1, %2, %3
585%endmacro
586
587;; Checks that ST0 contains QNaN.
588%define FxSaveCheckStNValue_QNaN(p, iSt) FxSaveCheckStNValue p, iSt, 0x00000000, 0xc0000000, 0xffff
589;; Checks that ST0 contains +Inf.
590%define FxSaveCheckStNValue_PlusInf(p, iSt) FxSaveCheckStNValue p, iSt, 0x00000000, 0x80000000, 0x7fff
591;; Checks that ST0 contains 3 & 1/3.
592%define FxSaveCheckStNValue_3_and_a_3rd(p, iSt) FxSaveCheckStNValue p, iSt, 0x55555555, 0xd5555555, 0x4000
593;; Checks that ST0 contains 3 & 1/3.
594%define FxSaveCheckStNValue_3_and_two_3rds(p, iSt) FxSaveCheckStNValue p, iSt, 0xaaaaaaab, 0xeaaaaaaa, 0x4000
595
596
597;;
598; Function prologue saving all registers except EAX and aligns the stack
599; on a 16-byte boundrary.
600;
601%macro SAVE_ALL_PROLOGUE 0
602 push xBP
603 mov xBP, xSP
604 pushf
605 push xBX
606 push xCX
607 push xDX
608 push xSI
609 push xDI
610%ifdef RT_ARCH_AMD64
611 push r8
612 push r9
613 push r10
614 push r11
615 push r12
616 push r13
617 push r14
618 push r15
619%endif
620 and xSP, ~0fh;
621%endmacro
622
623
624;;
625; Function epilogue restoring all regisers except EAX.
626;
627%macro SAVE_ALL_EPILOGUE 0
628%ifdef RT_ARCH_AMD64
629 lea rsp, [rbp - 14 * 8]
630 pop r15
631 pop r14
632 pop r13
633 pop r12
634 pop r11
635 pop r10
636 pop r9
637 pop r8
638%else
639 lea esp, [ebp - 6 * 4]
640%endif
641 pop xDI
642 pop xSI
643 pop xDX
644 pop xCX
645 pop xBX
646 popf
647 leave
648%endmacro
649
650
651
652
653BEGINCODE
654
655;;
656; Loads all general registers except xBP and xSP with unique values.
657;
658x861_LoadUniqueRegValues:
659%ifdef RT_ARCH_AMD64
660 mov rax, 00000000000000000h
661 mov rcx, 01111111111111111h
662 mov rdx, 02222222222222222h
663 mov rbx, 03333333333333333h
664 mov rsi, 06666666666666666h
665 mov rdi, 07777777777777777h
666 mov r8, 08888888888888888h
667 mov r9, 09999999999999999h
668 mov r10, 0aaaaaaaaaaaaaaaah
669 mov r11, 0bbbbbbbbbbbbbbbbh
670 mov r12, 0cccccccccccccccch
671 mov r13, 0ddddddddddddddddh
672 mov r14, 0eeeeeeeeeeeeeeeeh
673 mov r15, 0ffffffffffffffffh
674%else
675 mov eax, 000000000h
676 mov ecx, 011111111h
677 mov edx, 022222222h
678 mov ebx, 033333333h
679 mov esi, 066666666h
680 mov edi, 077777777h
681%endif
682 ret
683; end x861_LoadUniqueRegValues
684
685
686;;
687; Clears all general registers except xBP and xSP.
688;
689x861_ClearRegisters:
690 xor eax, eax
691 xor ebx, ebx
692 xor ecx, ecx
693 xor edx, edx
694 xor esi, esi
695 xor edi, edi
696%ifdef RT_ARCH_AMD64
697 xor r8, r8
698 xor r9, r9
699 xor r10, r10
700 xor r11, r11
701 xor r12, r12
702 xor r13, r13
703 xor r14, r14
704 xor r15, r15
705%endif
706 ret
707; x861_ClearRegisters
708
709
710;;
711; Loads all MMX and SSE registers except xBP and xSP with unique values.
712;
713x861_LoadUniqueRegValuesSSE:
714 fninit
715 movq mm0, [REF(._mm0)]
716 movq mm1, [REF(._mm1)]
717 movq mm2, [REF(._mm2)]
718 movq mm3, [REF(._mm3)]
719 movq mm4, [REF(._mm4)]
720 movq mm5, [REF(._mm5)]
721 movq mm6, [REF(._mm6)]
722 movq mm7, [REF(._mm7)]
723 movdqu xmm0, [REF(._xmm0)]
724 movdqu xmm1, [REF(._xmm1)]
725 movdqu xmm2, [REF(._xmm2)]
726 movdqu xmm3, [REF(._xmm3)]
727 movdqu xmm4, [REF(._xmm4)]
728 movdqu xmm5, [REF(._xmm5)]
729 movdqu xmm6, [REF(._xmm6)]
730 movdqu xmm7, [REF(._xmm7)]
731%ifdef RT_ARCH_AMD64
732 movdqu xmm8, [REF(._xmm8)]
733 movdqu xmm9, [REF(._xmm9)]
734 movdqu xmm10, [REF(._xmm10)]
735 movdqu xmm11, [REF(._xmm11)]
736 movdqu xmm12, [REF(._xmm12)]
737 movdqu xmm13, [REF(._xmm13)]
738 movdqu xmm14, [REF(._xmm14)]
739 movdqu xmm15, [REF(._xmm15)]
740%endif
741 ret
742._mm0: times 8 db 040h
743._mm1: times 8 db 041h
744._mm2: times 8 db 042h
745._mm3: times 8 db 043h
746._mm4: times 8 db 044h
747._mm5: times 8 db 045h
748._mm6: times 8 db 046h
749._mm7: times 8 db 047h
750._xmm0: times 16 db 080h
751._xmm1: times 16 db 081h
752._xmm2: times 16 db 082h
753._xmm3: times 16 db 083h
754._xmm4: times 16 db 084h
755._xmm5: times 16 db 085h
756._xmm6: times 16 db 086h
757._xmm7: times 16 db 087h
758%ifdef RT_ARCH_AMD64
759._xmm8: times 16 db 088h
760._xmm9: times 16 db 089h
761._xmm10: times 16 db 08ah
762._xmm11: times 16 db 08bh
763._xmm12: times 16 db 08ch
764._xmm13: times 16 db 08dh
765._xmm14: times 16 db 08eh
766._xmm15: times 16 db 08fh
767%endif
768; end x861_LoadUniqueRegValuesSSE
769
770
771;;
772; Clears all MMX and SSE registers.
773;
774x861_ClearRegistersSSE:
775 fninit
776 movq mm0, [REF(.zero)]
777 movq mm1, [REF(.zero)]
778 movq mm2, [REF(.zero)]
779 movq mm3, [REF(.zero)]
780 movq mm4, [REF(.zero)]
781 movq mm5, [REF(.zero)]
782 movq mm6, [REF(.zero)]
783 movq mm7, [REF(.zero)]
784 movdqu xmm0, [REF(.zero)]
785 movdqu xmm1, [REF(.zero)]
786 movdqu xmm2, [REF(.zero)]
787 movdqu xmm3, [REF(.zero)]
788 movdqu xmm4, [REF(.zero)]
789 movdqu xmm5, [REF(.zero)]
790 movdqu xmm6, [REF(.zero)]
791 movdqu xmm7, [REF(.zero)]
792%ifdef RT_ARCH_AMD64
793 movdqu xmm8, [REF(.zero)]
794 movdqu xmm9, [REF(.zero)]
795 movdqu xmm10, [REF(.zero)]
796 movdqu xmm11, [REF(.zero)]
797 movdqu xmm12, [REF(.zero)]
798 movdqu xmm13, [REF(.zero)]
799 movdqu xmm14, [REF(.zero)]
800 movdqu xmm15, [REF(.zero)]
801%endif
802 ret
803
804 ret
805.zero times 16 db 000h
806; x861_ClearRegistersSSE
807
808
809;;
810; Loads all general, MMX and SSE registers except xBP and xSP with unique values.
811;
812x861_LoadUniqueRegValuesSSEAndGRegs:
813 call x861_LoadUniqueRegValuesSSE
814 call x861_LoadUniqueRegValues
815 ret
816
817;;
818; Clears all general, MMX and SSE registers except xBP and xSP.
819;
820x861_ClearRegistersSSEAndGRegs:
821 call x861_ClearRegistersSSE
822 call x861_ClearRegisters
823 ret
824
825BEGINPROC x861_Test1
826 push xBP
827 mov xBP, xSP
828 pushf
829 push xBX
830 push xCX
831 push xDX
832 push xSI
833 push xDI
834%ifdef RT_ARCH_AMD64
835 push r8
836 push r9
837 push r10
838 push r11
839 push r12
840 push r13
841 push r14
842 push r15
843%endif
844
845 ;
846 ; Odd push behavior
847 ;
848%if 0 ; Seems to be so on AMD only
849%ifdef RT_ARCH_X86
850 ; upper word of a 'push cs' is cleared.
851 mov eax, __LINE__
852 mov dword [esp - 4], 0f0f0f0fh
853 push cs
854 pop ecx
855 mov bx, cs
856 and ebx, 0000ffffh
857 cmp ecx, ebx
858 jne .failed
859
860 ; upper word of a 'push ds' is cleared.
861 mov eax, __LINE__
862 mov dword [esp - 4], 0f0f0f0fh
863 push ds
864 pop ecx
865 mov bx, ds
866 and ebx, 0000ffffh
867 cmp ecx, ebx
868 jne .failed
869
870 ; upper word of a 'push es' is cleared.
871 mov eax, __LINE__
872 mov dword [esp - 4], 0f0f0f0fh
873 push es
874 pop ecx
875 mov bx, es
876 and ebx, 0000ffffh
877 cmp ecx, ebx
878 jne .failed
879%endif ; RT_ARCH_X86
880
881 ; The upper part of a 'push fs' is cleared.
882 mov eax, __LINE__
883 xor ecx, ecx
884 not xCX
885 push xCX
886 pop xCX
887 push fs
888 pop xCX
889 mov bx, fs
890 and ebx, 0000ffffh
891 cmp xCX, xBX
892 jne .failed
893
894 ; The upper part of a 'push gs' is cleared.
895 mov eax, __LINE__
896 xor ecx, ecx
897 not xCX
898 push xCX
899 pop xCX
900 push gs
901 pop xCX
902 mov bx, gs
903 and ebx, 0000ffffh
904 cmp xCX, xBX
905 jne .failed
906%endif
907
908%ifdef RT_ARCH_AMD64
909 ; REX.B works with 'push r64'.
910 call x861_LoadUniqueRegValues
911 mov eax, __LINE__
912 push rcx
913 pop rdx
914 cmp rdx, rcx
915 jne .failed
916
917 call x861_LoadUniqueRegValues
918 mov eax, __LINE__
919 db 041h ; REX.B
920 push rcx
921 pop rdx
922 cmp rdx, r9
923 jne .failed
924
925 call x861_LoadUniqueRegValues
926 mov eax, __LINE__
927 db 042h ; REX.X
928 push rcx
929 pop rdx
930 cmp rdx, rcx
931 jne .failed
932
933 call x861_LoadUniqueRegValues
934 mov eax, __LINE__
935 db 044h ; REX.R
936 push rcx
937 pop rdx
938 cmp rdx, rcx
939 jne .failed
940
941 call x861_LoadUniqueRegValues
942 mov eax, __LINE__
943 db 048h ; REX.W
944 push rcx
945 pop rdx
946 cmp rdx, rcx
947 jne .failed
948
949 call x861_LoadUniqueRegValues
950 mov eax, __LINE__
951 db 04fh ; REX.*
952 push rcx
953 pop rdx
954 cmp rdx, r9
955 jne .failed
956%endif
957
958 ;
959 ; Zero extening when moving from a segreg as well as memory access sizes.
960 ;
961 call x861_LoadUniqueRegValues
962 mov eax, __LINE__
963 mov ecx, ds
964 shr xCX, 16
965 cmp xCX, 0
966 jnz .failed
967
968%ifdef RT_ARCH_AMD64
969 call x861_LoadUniqueRegValues
970 mov eax, __LINE__
971 mov rcx, ds
972 shr rcx, 16
973 cmp rcx, 0
974 jnz .failed
975%endif
976
977 call x861_LoadUniqueRegValues
978 mov eax, __LINE__
979 mov xDX, xCX
980 mov cx, ds
981 shr xCX, 16
982 shr xDX, 16
983 cmp xCX, xDX
984 jnz .failed
985
986 ; Loading is always a word access.
987 mov eax, __LINE__
988 mov xDI, [REF_EXTERN(g_pbEfPage)]
989 lea xDI, [xDI + 0x1000 - 2]
990 mov xDX, es
991 mov [xDI], dx
992 mov es, [xDI] ; should not crash
993
994 ; Saving is always a word access.
995 mov eax, __LINE__
996 mov xDI, [REF_EXTERN(g_pbEfPage)]
997 mov dword [xDI + 0x1000 - 4], -1
998 mov [xDI + 0x1000 - 2], ss ; Should not crash.
999 mov bx, ss
1000 mov cx, [xDI + 0x1000 - 2]
1001 cmp cx, bx
1002 jne .failed
1003
1004%ifdef RT_ARCH_AMD64
1005 ; Check that the rex.R and rex.W bits don't have any influence over a memory write.
1006 call x861_ClearRegisters
1007 mov eax, __LINE__
1008 mov xDI, [REF_EXTERN(g_pbEfPage)]
1009 mov dword [xDI + 0x1000 - 4], -1
1010 db 04ah
1011 mov [xDI + 0x1000 - 2], ss ; Should not crash.
1012 mov bx, ss
1013 mov cx, [xDI + 0x1000 - 2]
1014 cmp cx, bx
1015 jne .failed
1016%endif
1017
1018
1019 ;
1020 ; Check what happens when both string prefixes are used.
1021 ;
1022 cld
1023 mov dx, ds
1024 mov es, dx
1025
1026 ; check that repne scasb (al=0) behaves like expected.
1027 lea xDI, [REF(NAME(g_szAlpha))]
1028 xor eax, eax ; find the end
1029 mov ecx, g_cchAlpha + 1
1030 repne scasb
1031 cmp ecx, 1
1032 mov eax, __LINE__
1033 jne .failed
1034
1035 ; check that repe scasb (al=0) behaves like expected.
1036 lea xDI, [REF(NAME(g_szAlpha))]
1037 xor eax, eax ; find the end
1038 mov ecx, g_cchAlpha + 1
1039 repe scasb
1040 cmp ecx, g_cchAlpha
1041 mov eax, __LINE__
1042 jne .failed
1043
1044 ; repne is last, it wins.
1045 lea xDI, [REF(NAME(g_szAlpha))]
1046 xor eax, eax ; find the end
1047 mov ecx, g_cchAlpha + 1
1048 db 0f3h ; repe - ignored
1049 db 0f2h ; repne
1050 scasb
1051 cmp ecx, 1
1052 mov eax, __LINE__
1053 jne .failed
1054
1055 ; repe is last, it wins.
1056 lea xDI, [REF(NAME(g_szAlpha))]
1057 xor eax, eax ; find the end
1058 mov ecx, g_cchAlpha + 1
1059 db 0f2h ; repne - ignored
1060 db 0f3h ; repe
1061 scasb
1062 cmp ecx, g_cchAlpha
1063 mov eax, __LINE__
1064 jne .failed
1065
1066 ;
1067 ; Check if stosb works with both prefixes.
1068 ;
1069 cld
1070 mov dx, ds
1071 mov es, dx
1072 mov xDI, [REF_EXTERN(g_pbEfPage)]
1073 xor eax, eax
1074 mov ecx, 01000h
1075 rep stosb
1076
1077 mov xDI, [REF_EXTERN(g_pbEfPage)]
1078 mov ecx, 4
1079 mov eax, 0ffh
1080 db 0f2h ; repne
1081 stosb
1082 mov eax, __LINE__
1083 cmp ecx, 0
1084 jne .failed
1085 mov eax, __LINE__
1086 mov xDI, [REF_EXTERN(g_pbEfPage)]
1087 cmp dword [xDI], 0ffffffffh
1088 jne .failed
1089 cmp dword [xDI+4], 0
1090 jne .failed
1091
1092 mov xDI, [REF_EXTERN(g_pbEfPage)]
1093 mov ecx, 4
1094 mov eax, 0feh
1095 db 0f3h ; repe
1096 stosb
1097 mov eax, __LINE__
1098 cmp ecx, 0
1099 jne .failed
1100 mov eax, __LINE__
1101 mov xDI, [REF_EXTERN(g_pbEfPage)]
1102 cmp dword [xDI], 0fefefefeh
1103 jne .failed
1104 cmp dword [xDI+4], 0
1105 jne .failed
1106
1107 ;
1108 ; String operations shouldn't crash because of an invalid address if rCX is 0.
1109 ;
1110 mov eax, __LINE__
1111 cld
1112 mov dx, ds
1113 mov es, dx
1114 mov xDI, [REF_EXTERN(g_pbEfPage)]
1115 xor xCX, xCX
1116 rep stosb ; no trap
1117
1118 ;
1119 ; INS/OUTS will trap in ring-3 even when rCX is 0. (ASSUMES IOPL < 3)
1120 ;
1121 mov eax, __LINE__
1122 cld
1123 mov dx, ss
1124 mov ss, dx
1125 mov xDI, xSP
1126 xor xCX, xCX
1127 ShouldTrap X86_XCPT_GP, rep insb
1128
1129 ;
1130 ; SMSW can get to the whole of CR0.
1131 ;
1132 mov eax, __LINE__
1133 xor xBX, xBX
1134 smsw xBX
1135 test ebx, X86_CR0_PG
1136 jz .failed
1137 test ebx, X86_CR0_PE
1138 jz .failed
1139
1140 ;
1141 ; Will the CPU decode the whole r/m+sib stuff before signalling a lock
1142 ; prefix error? Use the EF exec page and a LOCK ADD CL,[rDI + disp32]
1143 ; instruction at the very end of it.
1144 ;
1145 mov eax, __LINE__
1146 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1147 add xDI, 1000h - 8h
1148 mov byte [xDI+0], 0f0h
1149 mov byte [xDI+1], 002h
1150 mov byte [xDI+2], 08fh
1151 mov dword [xDI+3], 000000000h
1152 mov byte [xDI+7], 0cch
1153 ShouldTrap X86_XCPT_UD, call xDI
1154
1155 mov eax, __LINE__
1156 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1157 add xDI, 1000h - 7h
1158 mov byte [xDI+0], 0f0h
1159 mov byte [xDI+1], 002h
1160 mov byte [xDI+2], 08Fh
1161 mov dword [xDI+3], 000000000h
1162 ShouldTrap X86_XCPT_UD, call xDI
1163
1164 mov eax, __LINE__
1165 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1166 add xDI, 1000h - 4h
1167 mov byte [xDI+0], 0f0h
1168 mov byte [xDI+1], 002h
1169 mov byte [xDI+2], 08Fh
1170 mov byte [xDI+3], 000h
1171 ShouldTrap X86_XCPT_PF, call xDI
1172
1173 mov eax, __LINE__
1174 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1175 add xDI, 1000h - 6h
1176 mov byte [xDI+0], 0f0h
1177 mov byte [xDI+1], 002h
1178 mov byte [xDI+2], 08Fh
1179 mov byte [xDI+3], 00h
1180 mov byte [xDI+4], 00h
1181 mov byte [xDI+5], 00h
1182 ShouldTrap X86_XCPT_PF, call xDI
1183
1184 mov eax, __LINE__
1185 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1186 add xDI, 1000h - 5h
1187 mov byte [xDI+0], 0f0h
1188 mov byte [xDI+1], 002h
1189 mov byte [xDI+2], 08Fh
1190 mov byte [xDI+3], 00h
1191 mov byte [xDI+4], 00h
1192 ShouldTrap X86_XCPT_PF, call xDI
1193
1194 mov eax, __LINE__
1195 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1196 add xDI, 1000h - 4h
1197 mov byte [xDI+0], 0f0h
1198 mov byte [xDI+1], 002h
1199 mov byte [xDI+2], 08Fh
1200 mov byte [xDI+3], 00h
1201 ShouldTrap X86_XCPT_PF, call xDI
1202
1203 mov eax, __LINE__
1204 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1205 add xDI, 1000h - 3h
1206 mov byte [xDI+0], 0f0h
1207 mov byte [xDI+1], 002h
1208 mov byte [xDI+2], 08Fh
1209 ShouldTrap X86_XCPT_PF, call xDI
1210
1211 mov eax, __LINE__
1212 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1213 add xDI, 1000h - 2h
1214 mov byte [xDI+0], 0f0h
1215 mov byte [xDI+1], 002h
1216 ShouldTrap X86_XCPT_PF, call xDI
1217
1218 mov eax, __LINE__
1219 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1220 add xDI, 1000h - 1h
1221 mov byte [xDI+0], 0f0h
1222 ShouldTrap X86_XCPT_PF, call xDI
1223
1224
1225
1226.success:
1227 xor eax, eax
1228.return:
1229%ifdef RT_ARCH_AMD64
1230 pop r15
1231 pop r14
1232 pop r13
1233 pop r12
1234 pop r11
1235 pop r10
1236 pop r9
1237 pop r8
1238%endif
1239 pop xDI
1240 pop xSI
1241 pop xDX
1242 pop xCX
1243 pop xBX
1244 popf
1245 leave
1246 ret
1247
1248.failed2:
1249 mov eax, -1
1250.failed:
1251 jmp .return
1252ENDPROC x861_Test1
1253
1254
1255
1256;;
1257; Tests the effect of prefix order in group 14.
1258;
1259BEGINPROC x861_Test2
1260 SAVE_ALL_PROLOGUE
1261
1262 ; Check testcase preconditions.
1263 call x861_LoadUniqueRegValuesSSEAndGRegs
1264 mov eax, __LINE__
1265 db 00Fh, 073h, 0D0h, 080h ; psrlq mm0, 128
1266 call .check_mm0_zero_and_xmm0_nz
1267
1268 call x861_LoadUniqueRegValuesSSEAndGRegs
1269 mov eax, __LINE__
1270 db 066h, 00Fh, 073h, 0D0h, 080h ; psrlq xmm0, 128
1271 call .check_xmm0_zero_and_mm0_nz
1272
1273
1274 ;
1275 ; Real test - Inject other prefixes before the 066h and see what
1276 ; happens.
1277 ;
1278
1279 ; General checks that order does not matter, etc.
1280 call x861_LoadUniqueRegValuesSSEAndGRegs
1281 mov eax, __LINE__
1282 db 026h, 066h, 00Fh, 073h, 0D0h, 080h
1283 call .check_xmm0_zero_and_mm0_nz
1284
1285 call x861_LoadUniqueRegValuesSSEAndGRegs
1286 mov eax, __LINE__
1287 db 066h, 026h, 00Fh, 073h, 0D0h, 080h
1288 call .check_xmm0_zero_and_mm0_nz
1289
1290 call x861_LoadUniqueRegValuesSSEAndGRegs
1291 mov eax, __LINE__
1292 db 066h, 067h, 00Fh, 073h, 0D0h, 080h
1293 call .check_xmm0_zero_and_mm0_nz
1294
1295 call x861_LoadUniqueRegValuesSSEAndGRegs
1296 mov eax, __LINE__
1297 db 067h, 066h, 00Fh, 073h, 0D0h, 080h
1298 call .check_xmm0_zero_and_mm0_nz
1299
1300 call x861_LoadUniqueRegValuesSSEAndGRegs
1301 mov eax, __LINE__
1302 db 067h, 066h, 065h, 00Fh, 073h, 0D0h, 080h
1303 call .check_xmm0_zero_and_mm0_nz
1304
1305%ifdef RT_ARCH_AMD64
1306 call x861_LoadUniqueRegValuesSSEAndGRegs
1307 mov eax, __LINE__
1308 db 048h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.W
1309 call .check_xmm0_zero_and_mm0_nz
1310
1311 call x861_LoadUniqueRegValuesSSEAndGRegs
1312 mov eax, __LINE__
1313 db 044h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.R
1314 call .check_xmm0_zero_and_mm0_nz
1315
1316 call x861_LoadUniqueRegValuesSSEAndGRegs
1317 mov eax, __LINE__
1318 db 042h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.X
1319 call .check_xmm0_zero_and_mm0_nz
1320
1321 ; Actually for REX, order does matter if the prefix is used.
1322 call x861_LoadUniqueRegValuesSSEAndGRegs
1323 mov eax, __LINE__
1324 db 041h, 066h, 00Fh, 073h, 0D0h, 080h ; REX.B
1325 call .check_xmm0_zero_and_mm0_nz
1326
1327 call x861_LoadUniqueRegValuesSSEAndGRegs
1328 mov eax, __LINE__
1329 db 066h, 041h, 00Fh, 073h, 0D0h, 080h ; REX.B
1330 call .check_xmm8_zero_and_xmm0_nz
1331%endif
1332
1333 ; Check all ignored prefixes (repeates some of the above).
1334 call x861_LoadUniqueRegValuesSSEAndGRegs
1335 mov eax, __LINE__
1336 db 066h, 026h, 00Fh, 073h, 0D0h, 080h ; es
1337 call .check_xmm0_zero_and_mm0_nz
1338
1339 call x861_LoadUniqueRegValuesSSEAndGRegs
1340 mov eax, __LINE__
1341 db 066h, 065h, 00Fh, 073h, 0D0h, 080h ; gs
1342 call .check_xmm0_zero_and_mm0_nz
1343
1344 call x861_LoadUniqueRegValuesSSEAndGRegs
1345 mov eax, __LINE__
1346 db 066h, 064h, 00Fh, 073h, 0D0h, 080h ; fs
1347 call .check_xmm0_zero_and_mm0_nz
1348
1349 call x861_LoadUniqueRegValuesSSEAndGRegs
1350 mov eax, __LINE__
1351 db 066h, 02eh, 00Fh, 073h, 0D0h, 080h ; cs
1352 call .check_xmm0_zero_and_mm0_nz
1353
1354 call x861_LoadUniqueRegValuesSSEAndGRegs
1355 mov eax, __LINE__
1356 db 066h, 036h, 00Fh, 073h, 0D0h, 080h ; ss
1357 call .check_xmm0_zero_and_mm0_nz
1358
1359 call x861_LoadUniqueRegValuesSSEAndGRegs
1360 mov eax, __LINE__
1361 db 066h, 03eh, 00Fh, 073h, 0D0h, 080h ; ds
1362 call .check_xmm0_zero_and_mm0_nz
1363
1364 call x861_LoadUniqueRegValuesSSEAndGRegs
1365 mov eax, __LINE__
1366 db 066h, 067h, 00Fh, 073h, 0D0h, 080h ; addr size
1367 call .check_xmm0_zero_and_mm0_nz
1368
1369%ifdef RT_ARCH_AMD64
1370 call x861_LoadUniqueRegValuesSSEAndGRegs
1371 mov eax, __LINE__
1372 db 066h, 048h, 00Fh, 073h, 0D0h, 080h ; REX.W
1373 call .check_xmm0_zero_and_mm0_nz
1374
1375 call x861_LoadUniqueRegValuesSSEAndGRegs
1376 mov eax, __LINE__
1377 db 066h, 044h, 00Fh, 073h, 0D0h, 080h ; REX.R
1378 call .check_xmm0_zero_and_mm0_nz
1379
1380 call x861_LoadUniqueRegValuesSSEAndGRegs
1381 mov eax, __LINE__
1382 db 066h, 042h, 00Fh, 073h, 0D0h, 080h ; REX.X
1383 call .check_xmm0_zero_and_mm0_nz
1384
1385 call x861_LoadUniqueRegValuesSSEAndGRegs
1386 mov eax, __LINE__
1387 db 066h, 041h, 00Fh, 073h, 0D0h, 080h ; REX.B - has actual effect on the instruction.
1388 call .check_xmm8_zero_and_xmm0_nz
1389%endif
1390
1391 ; Repeated prefix until we hit the max opcode limit.
1392 call x861_LoadUniqueRegValuesSSEAndGRegs
1393 mov eax, __LINE__
1394 db 066h, 066h, 00Fh, 073h, 0D0h, 080h
1395 call .check_xmm0_zero_and_mm0_nz
1396
1397 call x861_LoadUniqueRegValuesSSEAndGRegs
1398 mov eax, __LINE__
1399 db 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
1400 call .check_xmm0_zero_and_mm0_nz
1401
1402 call x861_LoadUniqueRegValuesSSEAndGRegs
1403 mov eax, __LINE__
1404 db 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
1405 call .check_xmm0_zero_and_mm0_nz
1406
1407 call x861_LoadUniqueRegValuesSSEAndGRegs
1408 mov eax, __LINE__
1409 db 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
1410 call .check_xmm0_zero_and_mm0_nz
1411
1412 ShouldTrap X86_XCPT_GP, db 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 066h, 00Fh, 073h, 0D0h, 080h
1413
1414%ifdef RT_ARCH_AMD64
1415 ; Repeated REX is parsed, but only the last byte matters.
1416 call x861_LoadUniqueRegValuesSSEAndGRegs
1417 mov eax, __LINE__
1418 db 066h, 041h, 048h, 00Fh, 073h, 0D0h, 080h ; REX.B, REX.W
1419 call .check_xmm0_zero_and_mm0_nz
1420
1421 call x861_LoadUniqueRegValuesSSEAndGRegs
1422 mov eax, __LINE__
1423 db 066h, 048h, 041h, 00Fh, 073h, 0D0h, 080h ; REX.B, REX.W
1424 call .check_xmm8_zero_and_xmm0_nz
1425
1426 call x861_LoadUniqueRegValuesSSEAndGRegs
1427 mov eax, __LINE__
1428 db 066h, 048h, 044h, 042h, 048h, 044h, 042h, 048h, 044h, 042h, 041h, 00Fh, 073h, 0D0h, 080h
1429 call .check_xmm8_zero_and_xmm0_nz
1430
1431 call x861_LoadUniqueRegValuesSSEAndGRegs
1432 mov eax, __LINE__
1433 db 066h, 041h, 041h, 041h, 041h, 041h, 041h, 041h, 041h, 041h, 04eh, 00Fh, 073h, 0D0h, 080h
1434 call .check_xmm0_zero_and_mm0_nz
1435%endif
1436
1437 ; Undefined sequences with prefixes that counts.
1438 ShouldTrap X86_XCPT_UD, db 0f0h, 066h, 00Fh, 073h, 0D0h, 080h ; LOCK
1439 ShouldTrap X86_XCPT_UD, db 0f2h, 066h, 00Fh, 073h, 0D0h, 080h ; REPNZ
1440 ShouldTrap X86_XCPT_UD, db 0f3h, 066h, 00Fh, 073h, 0D0h, 080h ; REPZ
1441 ShouldTrap X86_XCPT_UD, db 066h, 0f2h, 00Fh, 073h, 0D0h, 080h
1442 ShouldTrap X86_XCPT_UD, db 066h, 0f3h, 00Fh, 073h, 0D0h, 080h
1443 ShouldTrap X86_XCPT_UD, db 066h, 0f3h, 0f2h, 00Fh, 073h, 0D0h, 080h
1444 ShouldTrap X86_XCPT_UD, db 066h, 0f2h, 0f3h, 00Fh, 073h, 0D0h, 080h
1445 ShouldTrap X86_XCPT_UD, db 0f2h, 066h, 0f3h, 00Fh, 073h, 0D0h, 080h
1446 ShouldTrap X86_XCPT_UD, db 0f3h, 066h, 0f2h, 00Fh, 073h, 0D0h, 080h
1447 ShouldTrap X86_XCPT_UD, db 0f3h, 0f2h, 066h, 00Fh, 073h, 0D0h, 080h
1448 ShouldTrap X86_XCPT_UD, db 0f2h, 0f3h, 066h, 00Fh, 073h, 0D0h, 080h
1449 ShouldTrap X86_XCPT_UD, db 0f0h, 0f2h, 066h, 0f3h, 00Fh, 073h, 0D0h, 080h
1450 ShouldTrap X86_XCPT_UD, db 0f0h, 0f3h, 066h, 0f2h, 00Fh, 073h, 0D0h, 080h
1451 ShouldTrap X86_XCPT_UD, db 0f0h, 0f3h, 0f2h, 066h, 00Fh, 073h, 0D0h, 080h
1452 ShouldTrap X86_XCPT_UD, db 0f0h, 0f2h, 0f3h, 066h, 00Fh, 073h, 0D0h, 080h
1453
1454.success:
1455 xor eax, eax
1456.return:
1457 SAVE_ALL_EPILOGUE
1458 ret
1459
1460.check_xmm0_zero_and_mm0_nz:
1461 sub xSP, 20h
1462 movdqu [xSP], xmm0
1463 cmp dword [xSP], 0
1464 jne .failed3
1465 cmp dword [xSP + 4], 0
1466 jne .failed3
1467 cmp dword [xSP + 8], 0
1468 jne .failed3
1469 cmp dword [xSP + 12], 0
1470 jne .failed3
1471 movq [xSP], mm0
1472 cmp dword [xSP], 0
1473 je .failed3
1474 cmp dword [xSP + 4], 0
1475 je .failed3
1476 add xSP, 20h
1477 ret
1478
1479.check_mm0_zero_and_xmm0_nz:
1480 sub xSP, 20h
1481 movq [xSP], mm0
1482 cmp dword [xSP], 0
1483 jne .failed3
1484 cmp dword [xSP + 4], 0
1485 jne .failed3
1486 movdqu [xSP], xmm0
1487 cmp dword [xSP], 0
1488 je .failed3
1489 cmp dword [xSP + 4], 0
1490 je .failed3
1491 cmp dword [xSP + 8], 0
1492 je .failed3
1493 cmp dword [xSP + 12], 0
1494 je .failed3
1495 add xSP, 20h
1496 ret
1497
1498%ifdef RT_ARCH_AMD64
1499.check_xmm8_zero_and_xmm0_nz:
1500 sub xSP, 20h
1501 movdqu [xSP], xmm8
1502 cmp dword [xSP], 0
1503 jne .failed3
1504 cmp dword [xSP + 4], 0
1505 jne .failed3
1506 cmp dword [xSP + 8], 0
1507 jne .failed3
1508 cmp dword [xSP + 12], 0
1509 jne .failed3
1510 movdqu [xSP], xmm0
1511 cmp dword [xSP], 0
1512 je .failed3
1513 cmp dword [xSP + 4], 0
1514 je .failed3
1515 cmp dword [xSP + 8], 0
1516 je .failed3
1517 cmp dword [xSP + 12], 0
1518 je .failed3
1519 add xSP, 20h
1520 ret
1521%endif
1522
1523.failed3:
1524 add xSP, 20h + xS
1525 jmp .return
1526
1527
1528ENDPROC x861_Test2
1529
1530
1531;;
1532; Tests how much fxsave and fxrstor actually accesses of their 512 memory
1533; operand.
1534;
1535BEGINPROC x861_Test3
1536 SAVE_ALL_PROLOGUE
1537 call x861_LoadUniqueRegValuesSSEAndGRegs
1538 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1539
1540 ; Check testcase preconditions.
1541 fxsave [xDI]
1542 fxrstor [xDI]
1543
1544 add xDI, PAGE_SIZE - 512
1545 mov xSI, xDI
1546 fxsave [xDI]
1547 fxrstor [xDI]
1548
1549 ; 464:511 are available to software use. Check that they are left
1550 ; untouched by fxsave.
1551 mov eax, 0aabbccddh
1552 mov ecx, 512 / 4
1553 cld
1554 rep stosd
1555 mov xDI, xSI
1556 fxsave [xDI]
1557
1558 mov ebx, 512
1559.chech_software_area_loop:
1560 cmp [xDI + xBX - 4], eax
1561 jne .chech_software_area_done
1562 sub ebx, 4
1563 jmp .chech_software_area_loop
1564.chech_software_area_done:
1565 cmp ebx, 464
1566 mov eax, __LINE__
1567 ja .return
1568
1569 ; Check that a save + restore + save cycle yield the same results.
1570 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
1571 mov xDI, xBX
1572 mov eax, 066778899h
1573 mov ecx, 512 * 2 / 4
1574 cld
1575 rep stosd
1576 fxsave [xBX]
1577
1578 call x861_ClearRegistersSSEAndGRegs
1579 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
1580 fxrstor [xBX]
1581
1582 fxsave [xBX + 512]
1583 mov xSI, xBX
1584 lea xDI, [xBX + 512]
1585 mov ecx, 512
1586 cld
1587 repe cmpsb
1588 mov eax, __LINE__
1589 jnz .return
1590
1591
1592 ; 464:511 are available to software use. Let see how carefully access
1593 ; to the full 512 bytes are checked...
1594 call x861_LoadUniqueRegValuesSSEAndGRegs
1595 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1596 add xDI, PAGE_SIZE - 512
1597 ShouldTrap X86_XCPT_PF, fxsave [xDI + 16]
1598 ShouldTrap X86_XCPT_PF, fxsave [xDI + 32]
1599 ShouldTrap X86_XCPT_PF, fxsave [xDI + 48]
1600 ShouldTrap X86_XCPT_PF, fxsave [xDI + 64]
1601 ShouldTrap X86_XCPT_PF, fxsave [xDI + 80]
1602 ShouldTrap X86_XCPT_PF, fxsave [xDI + 96]
1603 ShouldTrap X86_XCPT_PF, fxsave [xDI + 128]
1604 ShouldTrap X86_XCPT_PF, fxsave [xDI + 144]
1605 ShouldTrap X86_XCPT_PF, fxsave [xDI + 160]
1606 ShouldTrap X86_XCPT_PF, fxsave [xDI + 176]
1607 ShouldTrap X86_XCPT_PF, fxsave [xDI + 192]
1608 ShouldTrap X86_XCPT_PF, fxsave [xDI + 208]
1609 ShouldTrap X86_XCPT_PF, fxsave [xDI + 224]
1610 ShouldTrap X86_XCPT_PF, fxsave [xDI + 240]
1611 ShouldTrap X86_XCPT_PF, fxsave [xDI + 256]
1612 ShouldTrap X86_XCPT_PF, fxsave [xDI + 384]
1613 ShouldTrap X86_XCPT_PF, fxsave [xDI + 432]
1614 ShouldTrap X86_XCPT_PF, fxsave [xDI + 496]
1615
1616 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 16]
1617 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 32]
1618 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 48]
1619 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 64]
1620 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 80]
1621 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 96]
1622 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 128]
1623 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 144]
1624 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 160]
1625 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 176]
1626 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 192]
1627 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 208]
1628 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 224]
1629 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 240]
1630 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 256]
1631 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 384]
1632 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 432]
1633 ShouldTrap X86_XCPT_PF, fxrstor [xDI + 496]
1634
1635 ; Unaligned accesses will cause #GP(0). This takes precedence over #PF.
1636 ShouldTrap X86_XCPT_GP, fxsave [xDI + 1]
1637 ShouldTrap X86_XCPT_GP, fxsave [xDI + 2]
1638 ShouldTrap X86_XCPT_GP, fxsave [xDI + 3]
1639 ShouldTrap X86_XCPT_GP, fxsave [xDI + 4]
1640 ShouldTrap X86_XCPT_GP, fxsave [xDI + 5]
1641 ShouldTrap X86_XCPT_GP, fxsave [xDI + 6]
1642 ShouldTrap X86_XCPT_GP, fxsave [xDI + 7]
1643 ShouldTrap X86_XCPT_GP, fxsave [xDI + 8]
1644 ShouldTrap X86_XCPT_GP, fxsave [xDI + 9]
1645 ShouldTrap X86_XCPT_GP, fxsave [xDI + 10]
1646 ShouldTrap X86_XCPT_GP, fxsave [xDI + 11]
1647 ShouldTrap X86_XCPT_GP, fxsave [xDI + 12]
1648 ShouldTrap X86_XCPT_GP, fxsave [xDI + 13]
1649 ShouldTrap X86_XCPT_GP, fxsave [xDI + 14]
1650 ShouldTrap X86_XCPT_GP, fxsave [xDI + 15]
1651
1652 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 1]
1653 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 2]
1654 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 3]
1655 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 4]
1656 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 5]
1657 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 6]
1658 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 7]
1659 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 8]
1660 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 9]
1661 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 10]
1662 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 11]
1663 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 12]
1664 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 13]
1665 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 14]
1666 ShouldTrap X86_XCPT_GP, fxrstor [xDI + 15]
1667
1668 ; Lets check what a FP in fxsave changes ... nothing on intel.
1669 mov ebx, 16
1670.fxsave_pf_effect_loop:
1671 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1672 add xDI, PAGE_SIZE - 512 * 2
1673 mov xSI, xDI
1674 mov eax, 066778899h
1675 mov ecx, 512 * 2 / 4
1676 cld
1677 rep stosd
1678
1679 ShouldTrap X86_XCPT_PF, fxsave [xSI + PAGE_SIZE - 512 + xBX]
1680
1681 mov ecx, 512 / 4
1682 lea xDI, [xSI + 512]
1683 cld
1684 repz cmpsd
1685 lea xAX, [xBX + 20000]
1686 jnz .return
1687
1688 add ebx, 16
1689 cmp ebx, 512
1690 jbe .fxsave_pf_effect_loop
1691
1692 ; Lets check that a FP in fxrstor does not have any effect on the FPU or SSE state.
1693 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1694 mov ecx, PAGE_SIZE / 4
1695 mov eax, 0ffaa33cch
1696 cld
1697 rep stosd
1698
1699 call x861_LoadUniqueRegValuesSSEAndGRegs
1700 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1701 fxsave [xDI]
1702
1703 call x861_ClearRegistersSSEAndGRegs
1704 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1705 fxsave [xDI + 512]
1706
1707 mov ebx, 16
1708.fxrstor_pf_effect_loop:
1709 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1710 mov xSI, xDI
1711 lea xDI, [xDI + PAGE_SIZE - 512 + xBX]
1712 mov ecx, 512
1713 sub ecx, ebx
1714 cld
1715 rep movsb ; copy unique state to end of page.
1716
1717 push xBX
1718 call x861_ClearRegistersSSEAndGRegs
1719 pop xBX
1720 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1721 ShouldTrap X86_XCPT_PF, fxrstor [xDI + PAGE_SIZE - 512 + xBX] ; try load unique state
1722
1723 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
1724 lea xSI, [xDI + 512] ; point it to the clean state, which is what we expect.
1725 lea xDI, [xDI + 1024]
1726 fxsave [xDI] ; save whatever the fpu state currently is.
1727 mov ecx, 512 / 4
1728 cld
1729 repe cmpsd
1730 lea xAX, [xBX + 40000]
1731 jnz .return ; it shouldn't be modified by faulting fxrstor, i.e. a clean state.
1732
1733 add ebx, 16
1734 cmp ebx, 512
1735 jbe .fxrstor_pf_effect_loop
1736
1737.success:
1738 xor eax, eax
1739.return:
1740 SAVE_ALL_EPILOGUE
1741 ret
1742ENDPROC x861_Test3
1743
1744
1745;;
1746; Tests various multibyte NOP sequences.
1747;
1748BEGINPROC x861_Test4
1749 SAVE_ALL_PROLOGUE
1750 call x861_ClearRegisters
1751
1752 ; Intel recommended sequences.
1753 nop
1754 db 066h, 090h
1755 db 00fh, 01fh, 000h
1756 db 00fh, 01fh, 040h, 000h
1757 db 00fh, 01fh, 044h, 000h, 000h
1758 db 066h, 00fh, 01fh, 044h, 000h, 000h
1759 db 00fh, 01fh, 080h, 000h, 000h, 000h, 000h
1760 db 00fh, 01fh, 084h, 000h, 000h, 000h, 000h, 000h
1761 db 066h, 00fh, 01fh, 084h, 000h, 000h, 000h, 000h, 000h
1762
1763 ; Check that the NOPs are allergic to lock prefixing.
1764 ShouldTrap X86_XCPT_UD, db 0f0h, 090h ; lock prefixed NOP.
1765 ShouldTrap X86_XCPT_UD, db 0f0h, 066h, 090h ; lock prefixed two byte NOP.
1766 ShouldTrap X86_XCPT_UD, db 0f0h, 00fh, 01fh, 000h ; lock prefixed three byte NOP.
1767
1768 ; Check the range of instructions that AMD marks as NOPs.
1769%macro TST_NOP 1
1770 db 00fh, %1, 000h
1771 db 00fh, %1, 040h, 000h
1772 db 00fh, %1, 044h, 000h, 000h
1773 db 066h, 00fh, %1, 044h, 000h, 000h
1774 db 00fh, %1, 080h, 000h, 000h, 000h, 000h
1775 db 00fh, %1, 084h, 000h, 000h, 000h, 000h, 000h
1776 db 066h, 00fh, %1, 084h, 000h, 000h, 000h, 000h, 000h
1777 ShouldTrap X86_XCPT_UD, db 0f0h, 00fh, %1, 000h
1778%endmacro
1779 TST_NOP 019h
1780 TST_NOP 01ah
1781 TST_NOP 01bh
1782 TST_NOP 01ch
1783 TST_NOP 01dh
1784 TST_NOP 01eh
1785 TST_NOP 01fh
1786
1787 ; The AMD P group, intel marks this as a NOP.
1788 TST_NOP 00dh
1789
1790.success:
1791 xor eax, eax
1792.return:
1793 SAVE_ALL_EPILOGUE
1794 ret
1795ENDPROC x861_Test4
1796
1797
1798;;
1799; Tests various odd/weird/bad encodings.
1800;
1801BEGINPROC x861_Test5
1802 SAVE_ALL_PROLOGUE
1803 call x861_ClearRegisters
1804
1805%if 0
1806 ; callf eax...
1807 ShouldTrap X86_XCPT_UD, db 0xff, 11011000b
1808 ShouldTrap X86_XCPT_UD, db 0xff, 11011001b
1809 ShouldTrap X86_XCPT_UD, db 0xff, 11011010b
1810 ShouldTrap X86_XCPT_UD, db 0xff, 11011011b
1811 ShouldTrap X86_XCPT_UD, db 0xff, 11011100b
1812 ShouldTrap X86_XCPT_UD, db 0xff, 11011101b
1813 ShouldTrap X86_XCPT_UD, db 0xff, 11011110b
1814 ShouldTrap X86_XCPT_UD, db 0xff, 11011111b
1815
1816 ; jmpf eax...
1817 ShouldTrap X86_XCPT_UD, db 0xff, 11101000b
1818 ShouldTrap X86_XCPT_UD, db 0xff, 11101001b
1819 ShouldTrap X86_XCPT_UD, db 0xff, 11101010b
1820 ShouldTrap X86_XCPT_UD, db 0xff, 11101011b
1821 ShouldTrap X86_XCPT_UD, db 0xff, 11101100b
1822 ShouldTrap X86_XCPT_UD, db 0xff, 11101101b
1823 ShouldTrap X86_XCPT_UD, db 0xff, 11101110b
1824 ShouldTrap X86_XCPT_UD, db 0xff, 11101111b
1825
1826 ; #GP(0) vs #UD.
1827 ShouldTrap X86_XCPT_GP, mov xAX, cr0
1828 ShouldTrap X86_XCPT_UD, lock mov xAX, cr0
1829 ShouldTrap X86_XCPT_GP, mov cr0, xAX
1830 ShouldTrap X86_XCPT_UD, lock mov cr0, xAX
1831 ShouldTrap X86_XCPT_UD, db 0x0f, 0x20,11001000b ; mov xAX, cr1
1832 ShouldTrap X86_XCPT_UD, db 0x0f, 0x20,11101000b ; mov xAX, cr5
1833 ShouldTrap X86_XCPT_UD, db 0x0f, 0x20,11110000b ; mov xAX, cr6
1834 ShouldTrap X86_XCPT_UD, db 0x0f, 0x20,11111000b ; mov xAX, cr7
1835 ShouldTrap X86_XCPT_GP, mov xAX, dr7
1836 ShouldTrap X86_XCPT_UD, lock mov xAX, dr7
1837
1838 ; The MOD is ignored by MOV CRx,GReg and MOV GReg,CRx
1839 ShouldTrap X86_XCPT_GP, db 0x0f, 0x20,00000000b ; mov xAX, cr0
1840 ShouldTrap X86_XCPT_GP, db 0x0f, 0x20,01000000b ; mov xAX, cr0
1841 ShouldTrap X86_XCPT_GP, db 0x0f, 0x20,10000000b ; mov xAX, cr0
1842 ShouldTrap X86_XCPT_GP, db 0x0f, 0x20,11000000b ; mov xAX, cr0
1843 ShouldTrap X86_XCPT_GP, db 0x0f, 0x22,00000000b ; mov cr0, xAX
1844 ShouldTrap X86_XCPT_GP, db 0x0f, 0x22,01000000b ; mov cr0, xAX
1845 ShouldTrap X86_XCPT_GP, db 0x0f, 0x22,10000000b ; mov cr0, xAX
1846 ShouldTrap X86_XCPT_GP, db 0x0f, 0x22,11000000b ; mov cr0, xAX
1847%endif
1848
1849 ; mov eax, tr0, 0x0f 0x24
1850 ShouldTrap X86_XCPT_UD, db 0x0f, 0x24, 0xc0 ; mov xAX, tr1
1851
1852 mov xAX, [REF_EXTERN(g_pbEfExecPage)]
1853 add xAX, PAGE_SIZE - 3
1854 mov byte [xAX ], 0x0f
1855 mov byte [xAX + 1], 0x24
1856 mov byte [xAX + 2], 0xc0
1857 ShouldTrapExecPage X86_XCPT_UD, PAGE_SIZE - 3
1858
1859 mov xAX, [REF_EXTERN(g_pbEfExecPage)]
1860 add xAX, PAGE_SIZE - 2
1861 mov byte [xAX ], 0x0f
1862 mov byte [xAX + 1], 0x24
1863 ShouldTrapExecPage X86_XCPT_UD, PAGE_SIZE - 2
1864
1865.success:
1866 xor eax, eax
1867.return:
1868 SAVE_ALL_EPILOGUE
1869 ret
1870ENDPROC x861_Test5
1871
1872
1873;;
1874; Tests an reserved FPU encoding, checking that it does not affect the FPU or
1875; CPU state in any way.
1876;
1877; @uses stack
1878%macro FpuNopEncoding 1+
1879 fnclex
1880 call SetFSW_C0_thru_C3
1881
1882 push xBP
1883 mov xBP, xSP
1884 sub xSP, 1024
1885 and xSP, ~0fh
1886 call SaveFPUAndGRegsToStack
1887 %1
1888 call CompareFPUAndGRegsOnStackIgnoreOpAndIp
1889 leave
1890
1891 jz %%ok
1892 add eax, __LINE__
1893 jmp .return
1894%%ok:
1895%endmacro
1896
1897;;
1898; Used for marking encodings which has a meaning other than FNOP and
1899; needs investigating.
1900%macro FpuReservedEncoding 2
1901 fnclex
1902 call SetFSW_C0_thru_C3
1903
1904 push xBP
1905 mov xBP, xSP
1906 sub xSP, 2048
1907 and xSP, ~0fh
1908 mov dword [xSP + 1024 + X86FXSTATE.FPUIP], 0
1909 mov dword [xSP + 1024 + X86FXSTATE.FPUCS], 0
1910 mov dword [xSP + 1024 + X86FXSTATE.FPUDP], 0
1911 mov dword [xSP + 1024 + X86FXSTATE.FPUDS], 0
1912 arch_fxsave [xSP + 1024]
1913 %1
1914 call SaveFPUAndGRegsToStack
1915
1916 arch_fxrstor [xSP + 1024]
1917 %2
1918 call CompareFPUAndGRegsOnStackIgnoreOpAndIp
1919 ;arch_fxrstor [xSP + 1024]
1920 leave
1921
1922 jz %%ok
1923 add eax, __LINE__
1924 jmp .return
1925%%ok:
1926%endmacro
1927
1928
1929;;
1930; Saves the FPU and general registers to the stack area right next to the
1931; return address.
1932;
1933; The required area size is 512 + 80h = 640.
1934;
1935; @uses Nothing, except stack.
1936;
1937SaveFPUAndGRegsToStack:
1938 ; Must clear the FXSAVE area.
1939 pushf
1940 push xCX
1941 push xAX
1942 push xDI
1943
1944 lea xDI, [xSP + xS * 5]
1945 mov xCX, 512 / 4
1946 mov eax, 0cccccccch
1947 cld
1948 rep stosd
1949
1950 pop xDI
1951 pop xAX
1952 pop xCX
1953 popf
1954
1955 ; Save the FPU state.
1956 mov dword [xSP + xS + X86FXSTATE.FPUIP], 0
1957 mov dword [xSP + xS + X86FXSTATE.FPUCS], 0
1958 mov dword [xSP + xS + X86FXSTATE.FPUDP], 0
1959 mov dword [xSP + xS + X86FXSTATE.FPUDS], 0
1960 arch_fxsave [xSP + xS]
1961
1962 ; Save GRegs (80h bytes).
1963%ifdef RT_ARCH_AMD64
1964 mov [xSP + 512 + xS + 000h], xAX
1965 mov [xSP + 512 + xS + 008h], xBX
1966 mov [xSP + 512 + xS + 010h], xCX
1967 mov [xSP + 512 + xS + 018h], xDX
1968 mov [xSP + 512 + xS + 020h], xDI
1969 mov [xSP + 512 + xS + 028h], xSI
1970 mov [xSP + 512 + xS + 030h], xBP
1971 mov [xSP + 512 + xS + 038h], r8
1972 mov [xSP + 512 + xS + 040h], r9
1973 mov [xSP + 512 + xS + 048h], r10
1974 mov [xSP + 512 + xS + 050h], r11
1975 mov [xSP + 512 + xS + 058h], r12
1976 mov [xSP + 512 + xS + 060h], r13
1977 mov [xSP + 512 + xS + 068h], r14
1978 mov [xSP + 512 + xS + 070h], r15
1979 pushf
1980 pop rax
1981 mov [xSP + 512 + xS + 078h], rax
1982 mov rax, [xSP + 512 + xS + 000h]
1983%else
1984 mov [xSP + 512 + xS + 000h], eax
1985 mov [xSP + 512 + xS + 004h], eax
1986 mov [xSP + 512 + xS + 008h], ebx
1987 mov [xSP + 512 + xS + 00ch], ebx
1988 mov [xSP + 512 + xS + 010h], ecx
1989 mov [xSP + 512 + xS + 014h], ecx
1990 mov [xSP + 512 + xS + 018h], edx
1991 mov [xSP + 512 + xS + 01ch], edx
1992 mov [xSP + 512 + xS + 020h], edi
1993 mov [xSP + 512 + xS + 024h], edi
1994 mov [xSP + 512 + xS + 028h], esi
1995 mov [xSP + 512 + xS + 02ch], esi
1996 mov [xSP + 512 + xS + 030h], ebp
1997 mov [xSP + 512 + xS + 034h], ebp
1998 mov [xSP + 512 + xS + 038h], eax
1999 mov [xSP + 512 + xS + 03ch], eax
2000 mov [xSP + 512 + xS + 040h], eax
2001 mov [xSP + 512 + xS + 044h], eax
2002 mov [xSP + 512 + xS + 048h], eax
2003 mov [xSP + 512 + xS + 04ch], eax
2004 mov [xSP + 512 + xS + 050h], eax
2005 mov [xSP + 512 + xS + 054h], eax
2006 mov [xSP + 512 + xS + 058h], eax
2007 mov [xSP + 512 + xS + 05ch], eax
2008 mov [xSP + 512 + xS + 060h], eax
2009 mov [xSP + 512 + xS + 064h], eax
2010 mov [xSP + 512 + xS + 068h], eax
2011 mov [xSP + 512 + xS + 06ch], eax
2012 mov [xSP + 512 + xS + 070h], eax
2013 mov [xSP + 512 + xS + 074h], eax
2014 pushf
2015 pop eax
2016 mov [xSP + 512 + xS + 078h], eax
2017 mov [xSP + 512 + xS + 07ch], eax
2018 mov eax, [xSP + 512 + xS + 000h]
2019%endif
2020 ret
2021
2022;;
2023; Compares the current FPU and general registers to that found in the stack
2024; area prior to the return address.
2025;
2026; @uses Stack, flags and eax/rax.
2027; @returns eax is zero on success, eax is 1000000 * offset on failure.
2028; ZF reflects the eax value to save a couple of instructions...
2029;
2030CompareFPUAndGRegsOnStack:
2031 lea xSP, [xSP - (1024 - xS)]
2032 call SaveFPUAndGRegsToStack
2033
2034 push xSI
2035 push xDI
2036 push xCX
2037
2038 mov xCX, 640
2039 lea xSI, [xSP + xS*3]
2040 lea xDI, [xSI + 1024]
2041
2042 cld
2043 repe cmpsb
2044 je .ok
2045
2046 ;int3
2047 lea xAX, [xSP + xS*3]
2048 xchg xAX, xSI
2049 sub xAX, xSI
2050
2051 push xDX
2052 mov xDX, 1000000
2053 mul xDX
2054 pop xDX
2055 jmp .return
2056.ok:
2057 xor eax, eax
2058.return:
2059 pop xCX
2060 pop xDI
2061 pop xSI
2062 lea xSP, [xSP + (1024 - xS)]
2063 or eax, eax
2064 ret
2065
2066;;
2067; Same as CompareFPUAndGRegsOnStack, except that it ignores the FOP and FPUIP
2068; registers.
2069;
2070; @uses Stack, flags and eax/rax.
2071; @returns eax is zero on success, eax is 1000000 * offset on failure.
2072; ZF reflects the eax value to save a couple of instructions...
2073;
2074CompareFPUAndGRegsOnStackIgnoreOpAndIp:
2075 lea xSP, [xSP - (1024 - xS)]
2076 call SaveFPUAndGRegsToStack
2077
2078 push xSI
2079 push xDI
2080 push xCX
2081
2082 mov xCX, 640
2083 lea xSI, [xSP + xS*3]
2084 lea xDI, [xSI + 1024]
2085
2086 mov word [xSI + X86FXSTATE.FOP], 0 ; ignore
2087 mov word [xDI + X86FXSTATE.FOP], 0 ; ignore
2088 mov dword [xSI + X86FXSTATE.FPUIP], 0 ; ignore
2089 mov dword [xDI + X86FXSTATE.FPUIP], 0 ; ignore
2090
2091 cld
2092 repe cmpsb
2093 je .ok
2094
2095 ;int3
2096 lea xAX, [xSP + xS*3]
2097 xchg xAX, xSI
2098 sub xAX, xSI
2099
2100 push xDX
2101 mov xDX, 1000000
2102 mul xDX
2103 pop xDX
2104 jmp .return
2105.ok:
2106 xor eax, eax
2107.return:
2108 pop xCX
2109 pop xDI
2110 pop xSI
2111 lea xSP, [xSP + (1024 - xS)]
2112 or eax, eax
2113 ret
2114
2115
2116SetFSW_C0_thru_C3:
2117 sub xSP, 20h
2118 fstenv [xSP]
2119 or word [xSP + 4], X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3
2120 fldenv [xSP]
2121 add xSP, 20h
2122 ret
2123
2124
2125;;
2126; Tests some odd floating point instruction encodings.
2127;
2128BEGINPROC x861_Test6
2129 SAVE_ALL_PROLOGUE
2130
2131 ; standard stuff...
2132 fld dword [REF(g_r32V1)]
2133 fld qword [REF(g_r64V1)]
2134 fld tword [REF(g_r80V1)]
2135 fld qword [REF(g_r64V1)]
2136 fld dword [REF(g_r32V2)]
2137 fld dword [REF(g_r32V1)]
2138
2139 ; Test the nop check.
2140 FpuNopEncoding fnop
2141
2142
2143 ; the 0xd9 block
2144 ShouldTrap X86_XCPT_UD, db 0d9h, 008h
2145 ShouldTrap X86_XCPT_UD, db 0d9h, 009h
2146 ShouldTrap X86_XCPT_UD, db 0d9h, 00ah
2147 ShouldTrap X86_XCPT_UD, db 0d9h, 00bh
2148 ShouldTrap X86_XCPT_UD, db 0d9h, 00ch
2149 ShouldTrap X86_XCPT_UD, db 0d9h, 00dh
2150 ShouldTrap X86_XCPT_UD, db 0d9h, 00eh
2151 ShouldTrap X86_XCPT_UD, db 0d9h, 00fh
2152
2153 ShouldTrap X86_XCPT_UD, db 0d9h, 0d1h
2154 ShouldTrap X86_XCPT_UD, db 0d9h, 0d2h
2155 ShouldTrap X86_XCPT_UD, db 0d9h, 0d3h
2156 ShouldTrap X86_XCPT_UD, db 0d9h, 0d4h
2157 ShouldTrap X86_XCPT_UD, db 0d9h, 0d5h
2158 ShouldTrap X86_XCPT_UD, db 0d9h, 0d6h
2159 ShouldTrap X86_XCPT_UD, db 0d9h, 0d7h
2160 FpuReservedEncoding {db 0d9h, 0d8h}, { fstp st0 }
2161 FpuReservedEncoding {db 0d9h, 0d9h}, { fstp st1 }
2162 FpuReservedEncoding {db 0d9h, 0dah}, { fstp st2 }
2163 FpuReservedEncoding {db 0d9h, 0dbh}, { fstp st3 }
2164 FpuReservedEncoding {db 0d9h, 0dch}, { fstp st4 }
2165 FpuReservedEncoding {db 0d9h, 0ddh}, { fstp st5 }
2166 FpuReservedEncoding {db 0d9h, 0deh}, { fstp st6 }
2167 ;FpuReservedEncoding {db 0d9h, 0dfh}, { fstp st7 } ; This variant seems to ignore empty ST(0) values!
2168 ShouldTrap X86_XCPT_UD, db 0d9h, 0e2h
2169 ShouldTrap X86_XCPT_UD, db 0d9h, 0e3h
2170 ShouldTrap X86_XCPT_UD, db 0d9h, 0e6h
2171 ShouldTrap X86_XCPT_UD, db 0d9h, 0e7h
2172 ShouldTrap X86_XCPT_UD, db 0d9h, 0efh
2173 ShouldTrap X86_XCPT_UD, db 0d9h, 008h
2174 ShouldTrap X86_XCPT_UD, db 0d9h, 00fh
2175
2176 ; the 0xda block
2177 ShouldTrap X86_XCPT_UD, db 0dah, 0e0h
2178 ShouldTrap X86_XCPT_UD, db 0dah, 0e1h
2179 ShouldTrap X86_XCPT_UD, db 0dah, 0e2h
2180 ShouldTrap X86_XCPT_UD, db 0dah, 0e3h
2181 ShouldTrap X86_XCPT_UD, db 0dah, 0e4h
2182 ShouldTrap X86_XCPT_UD, db 0dah, 0e5h
2183 ShouldTrap X86_XCPT_UD, db 0dah, 0e6h
2184 ShouldTrap X86_XCPT_UD, db 0dah, 0e7h
2185 ShouldTrap X86_XCPT_UD, db 0dah, 0e8h
2186 ShouldTrap X86_XCPT_UD, db 0dah, 0eah
2187 ShouldTrap X86_XCPT_UD, db 0dah, 0ebh
2188 ShouldTrap X86_XCPT_UD, db 0dah, 0ech
2189 ShouldTrap X86_XCPT_UD, db 0dah, 0edh
2190 ShouldTrap X86_XCPT_UD, db 0dah, 0eeh
2191 ShouldTrap X86_XCPT_UD, db 0dah, 0efh
2192 ShouldTrap X86_XCPT_UD, db 0dah, 0f0h
2193 ShouldTrap X86_XCPT_UD, db 0dah, 0f1h
2194 ShouldTrap X86_XCPT_UD, db 0dah, 0f2h
2195 ShouldTrap X86_XCPT_UD, db 0dah, 0f3h
2196 ShouldTrap X86_XCPT_UD, db 0dah, 0f4h
2197 ShouldTrap X86_XCPT_UD, db 0dah, 0f5h
2198 ShouldTrap X86_XCPT_UD, db 0dah, 0f6h
2199 ShouldTrap X86_XCPT_UD, db 0dah, 0f7h
2200 ShouldTrap X86_XCPT_UD, db 0dah, 0f8h
2201 ShouldTrap X86_XCPT_UD, db 0dah, 0f9h
2202 ShouldTrap X86_XCPT_UD, db 0dah, 0fah
2203 ShouldTrap X86_XCPT_UD, db 0dah, 0fbh
2204 ShouldTrap X86_XCPT_UD, db 0dah, 0fch
2205 ShouldTrap X86_XCPT_UD, db 0dah, 0fdh
2206 ShouldTrap X86_XCPT_UD, db 0dah, 0feh
2207 ShouldTrap X86_XCPT_UD, db 0dah, 0ffh
2208
2209 ; the 0xdb block
2210 FpuNopEncoding db 0dbh, 0e0h ; fneni
2211 FpuNopEncoding db 0dbh, 0e1h ; fndisi
2212 FpuNopEncoding db 0dbh, 0e4h ; fnsetpm
2213 ShouldTrap X86_XCPT_UD, db 0dbh, 0e5h
2214 ShouldTrap X86_XCPT_UD, db 0dbh, 0e6h
2215 ShouldTrap X86_XCPT_UD, db 0dbh, 0e7h
2216 ShouldTrap X86_XCPT_UD, db 0dbh, 0f8h
2217 ShouldTrap X86_XCPT_UD, db 0dbh, 0f9h
2218 ShouldTrap X86_XCPT_UD, db 0dbh, 0fah
2219 ShouldTrap X86_XCPT_UD, db 0dbh, 0fbh
2220 ShouldTrap X86_XCPT_UD, db 0dbh, 0fch
2221 ShouldTrap X86_XCPT_UD, db 0dbh, 0fdh
2222 ShouldTrap X86_XCPT_UD, db 0dbh, 0feh
2223 ShouldTrap X86_XCPT_UD, db 0dbh, 0ffh
2224 ShouldTrap X86_XCPT_UD, db 0dbh, 020h
2225 ShouldTrap X86_XCPT_UD, db 0dbh, 023h
2226 ShouldTrap X86_XCPT_UD, db 0dbh, 030h
2227 ShouldTrap X86_XCPT_UD, db 0dbh, 032h
2228
2229 ; the 0xdc block
2230 FpuReservedEncoding {db 0dch, 0d0h}, { fcom st0 }
2231 FpuReservedEncoding {db 0dch, 0d1h}, { fcom st1 }
2232 FpuReservedEncoding {db 0dch, 0d2h}, { fcom st2 }
2233 FpuReservedEncoding {db 0dch, 0d3h}, { fcom st3 }
2234 FpuReservedEncoding {db 0dch, 0d4h}, { fcom st4 }
2235 FpuReservedEncoding {db 0dch, 0d5h}, { fcom st5 }
2236 FpuReservedEncoding {db 0dch, 0d6h}, { fcom st6 }
2237 FpuReservedEncoding {db 0dch, 0d7h}, { fcom st7 }
2238 FpuReservedEncoding {db 0dch, 0d8h}, { fcomp st0 }
2239 FpuReservedEncoding {db 0dch, 0d9h}, { fcomp st1 }
2240 FpuReservedEncoding {db 0dch, 0dah}, { fcomp st2 }
2241 FpuReservedEncoding {db 0dch, 0dbh}, { fcomp st3 }
2242 FpuReservedEncoding {db 0dch, 0dch}, { fcomp st4 }
2243 FpuReservedEncoding {db 0dch, 0ddh}, { fcomp st5 }
2244 FpuReservedEncoding {db 0dch, 0deh}, { fcomp st6 }
2245 FpuReservedEncoding {db 0dch, 0dfh}, { fcomp st7 }
2246
2247 ; the 0xdd block
2248 FpuReservedEncoding {db 0ddh, 0c8h}, { fxch st0 }
2249 FpuReservedEncoding {db 0ddh, 0c9h}, { fxch st1 }
2250 FpuReservedEncoding {db 0ddh, 0cah}, { fxch st2 }
2251 FpuReservedEncoding {db 0ddh, 0cbh}, { fxch st3 }
2252 FpuReservedEncoding {db 0ddh, 0cch}, { fxch st4 }
2253 FpuReservedEncoding {db 0ddh, 0cdh}, { fxch st5 }
2254 FpuReservedEncoding {db 0ddh, 0ceh}, { fxch st6 }
2255 FpuReservedEncoding {db 0ddh, 0cfh}, { fxch st7 }
2256 ShouldTrap X86_XCPT_UD, db 0ddh, 0f0h
2257 ShouldTrap X86_XCPT_UD, db 0ddh, 0f1h
2258 ShouldTrap X86_XCPT_UD, db 0ddh, 0f2h
2259 ShouldTrap X86_XCPT_UD, db 0ddh, 0f3h
2260 ShouldTrap X86_XCPT_UD, db 0ddh, 0f4h
2261 ShouldTrap X86_XCPT_UD, db 0ddh, 0f5h
2262 ShouldTrap X86_XCPT_UD, db 0ddh, 0f6h
2263 ShouldTrap X86_XCPT_UD, db 0ddh, 0f7h
2264 ShouldTrap X86_XCPT_UD, db 0ddh, 0f8h
2265 ShouldTrap X86_XCPT_UD, db 0ddh, 0f9h
2266 ShouldTrap X86_XCPT_UD, db 0ddh, 0fah
2267 ShouldTrap X86_XCPT_UD, db 0ddh, 0fbh
2268 ShouldTrap X86_XCPT_UD, db 0ddh, 0fch
2269 ShouldTrap X86_XCPT_UD, db 0ddh, 0fdh
2270 ShouldTrap X86_XCPT_UD, db 0ddh, 0feh
2271 ShouldTrap X86_XCPT_UD, db 0ddh, 0ffh
2272 ShouldTrap X86_XCPT_UD, db 0ddh, 028h
2273 ShouldTrap X86_XCPT_UD, db 0ddh, 02fh
2274
2275 ; the 0xde block
2276 FpuReservedEncoding {db 0deh, 0d0h}, { fcomp st0 }
2277 FpuReservedEncoding {db 0deh, 0d1h}, { fcomp st1 }
2278 FpuReservedEncoding {db 0deh, 0d2h}, { fcomp st2 }
2279 FpuReservedEncoding {db 0deh, 0d3h}, { fcomp st3 }
2280 FpuReservedEncoding {db 0deh, 0d4h}, { fcomp st4 }
2281 FpuReservedEncoding {db 0deh, 0d5h}, { fcomp st5 }
2282 FpuReservedEncoding {db 0deh, 0d6h}, { fcomp st6 }
2283 FpuReservedEncoding {db 0deh, 0d7h}, { fcomp st7 }
2284 ShouldTrap X86_XCPT_UD, db 0deh, 0d8h
2285 ShouldTrap X86_XCPT_UD, db 0deh, 0dah
2286 ShouldTrap X86_XCPT_UD, db 0deh, 0dbh
2287 ShouldTrap X86_XCPT_UD, db 0deh, 0dch
2288 ShouldTrap X86_XCPT_UD, db 0deh, 0ddh
2289 ShouldTrap X86_XCPT_UD, db 0deh, 0deh
2290 ShouldTrap X86_XCPT_UD, db 0deh, 0dfh
2291
2292 ; the 0xdf block
2293 FpuReservedEncoding {db 0dfh, 0c8h}, { fxch st0 }
2294 FpuReservedEncoding {db 0dfh, 0c9h}, { fxch st1 }
2295 FpuReservedEncoding {db 0dfh, 0cah}, { fxch st2 }
2296 FpuReservedEncoding {db 0dfh, 0cbh}, { fxch st3 }
2297 FpuReservedEncoding {db 0dfh, 0cch}, { fxch st4 }
2298 FpuReservedEncoding {db 0dfh, 0cdh}, { fxch st5 }
2299 FpuReservedEncoding {db 0dfh, 0ceh}, { fxch st6 }
2300 FpuReservedEncoding {db 0dfh, 0cfh}, { fxch st7 }
2301 FpuReservedEncoding {db 0dfh, 0d0h}, { fstp st0 }
2302 FpuReservedEncoding {db 0dfh, 0d1h}, { fstp st1 }
2303 FpuReservedEncoding {db 0dfh, 0d2h}, { fstp st2 }
2304 FpuReservedEncoding {db 0dfh, 0d3h}, { fstp st3 }
2305 FpuReservedEncoding {db 0dfh, 0d4h}, { fstp st4 }
2306 FpuReservedEncoding {db 0dfh, 0d5h}, { fstp st5 }
2307 FpuReservedEncoding {db 0dfh, 0d6h}, { fstp st6 }
2308 FpuReservedEncoding {db 0dfh, 0d7h}, { fstp st7 }
2309 FpuReservedEncoding {db 0dfh, 0d8h}, { fstp st0 }
2310 FpuReservedEncoding {db 0dfh, 0d9h}, { fstp st1 }
2311 FpuReservedEncoding {db 0dfh, 0dah}, { fstp st2 }
2312 FpuReservedEncoding {db 0dfh, 0dbh}, { fstp st3 }
2313 FpuReservedEncoding {db 0dfh, 0dch}, { fstp st4 }
2314 FpuReservedEncoding {db 0dfh, 0ddh}, { fstp st5 }
2315 FpuReservedEncoding {db 0dfh, 0deh}, { fstp st6 }
2316 FpuReservedEncoding {db 0dfh, 0dfh}, { fstp st7 }
2317 ShouldTrap X86_XCPT_UD, db 0dfh, 0e1h
2318 ShouldTrap X86_XCPT_UD, db 0dfh, 0e2h
2319 ShouldTrap X86_XCPT_UD, db 0dfh, 0e3h
2320 ShouldTrap X86_XCPT_UD, db 0dfh, 0e4h
2321 ShouldTrap X86_XCPT_UD, db 0dfh, 0e5h
2322 ShouldTrap X86_XCPT_UD, db 0dfh, 0e6h
2323 ShouldTrap X86_XCPT_UD, db 0dfh, 0e7h
2324 ShouldTrap X86_XCPT_UD, db 0dfh, 0f8h
2325 ShouldTrap X86_XCPT_UD, db 0dfh, 0f9h
2326 ShouldTrap X86_XCPT_UD, db 0dfh, 0fah
2327 ShouldTrap X86_XCPT_UD, db 0dfh, 0fbh
2328 ShouldTrap X86_XCPT_UD, db 0dfh, 0fch
2329 ShouldTrap X86_XCPT_UD, db 0dfh, 0fdh
2330 ShouldTrap X86_XCPT_UD, db 0dfh, 0feh
2331 ShouldTrap X86_XCPT_UD, db 0dfh, 0ffh
2332
2333
2334.success:
2335 xor eax, eax
2336.return:
2337 SAVE_ALL_EPILOGUE
2338 ret
2339
2340ENDPROC x861_Test6
2341
2342
2343;;
2344; Tests some floating point exceptions and such.
2345;
2346;
2347;
2348BEGINPROC x861_Test7
2349 SAVE_ALL_PROLOGUE
2350 sub xSP, 2048
2351
2352 ; Load some pointers.
2353 lea xSI, [REF(g_r32V1)]
2354 mov xDI, [REF_EXTERN(g_pbEfExecPage)]
2355 add xDI, PAGE_SIZE ; invalid page.
2356
2357 ;
2358 ; Check denormal numbers.
2359 ; Turns out the number is loaded onto the stack even if an exception is triggered.
2360 ;
2361 fninit
2362 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2363 fldcw [xSP]
2364 FpuShouldTrap X86_FSW_DE, 0, fld dword [REF(g_r32D0)]
2365 CheckSt0Value 0x00000000, 0x80000000, 0x3f7f
2366
2367 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_DM
2368 fldcw [xSP]
2369 fld dword [REF(g_r32D0)]
2370 fwait
2371 FpuCheckFSW X86_FSW_DE, 0
2372 CheckSt0Value 0x00000000, 0x80000000, 0x3f7f
2373
2374 ;
2375 ; stack overflow
2376 ;
2377 fninit
2378 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2379 fldcw [xSP]
2380 fld qword [REF(g_r64V1)]
2381 fld dword [xSI]
2382 fld dword [xSI]
2383 fld dword [xSI]
2384 fld dword [xSI]
2385 fld dword [xSI]
2386 fld dword [xSI]
2387 fld tword [REF(g_r80V1)]
2388 fwait
2389
2390 FpuShouldTrap X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3, \
2391 fld dword [xSI]
2392 CheckSt0Value_Eight
2393
2394 FpuShouldTrap X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3, \
2395 fld dword [xSI]
2396 CheckSt0Value_Eight
2397
2398 ; stack overflow vs #PF.
2399 ShouldTrap X86_XCPT_PF, fld dword [xDI]
2400 fwait
2401
2402 ; stack overflow vs denormal number
2403 FpuShouldTrap X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3, \
2404 fld dword [xSI]
2405 CheckSt0Value_Eight
2406
2407 ;
2408 ; Mask the overflow exception. We should get QNaN now regardless of
2409 ; what we try to push (provided the memory is valid).
2410 ;
2411 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_IM
2412 fldcw [xSP]
2413
2414 fld dword [xSI]
2415 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2416 fnclex
2417 CheckSt0Value 0x00000000, 0xc0000000, 0xffff
2418
2419 fld qword [REF(g_r64V1)]
2420 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2421 fnclex
2422 CheckSt0Value 0x00000000, 0xc0000000, 0xffff
2423
2424 ; This is includes denormal values.
2425 fld dword [REF(g_r32D0)]
2426 fwait
2427 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2428 CheckSt0Value 0x00000000, 0xc0000000, 0xffff
2429 fnclex
2430
2431 ;
2432 ; #PF vs previous stack overflow. I.e. whether pending FPU exception
2433 ; is checked before fetching memory operands.
2434 ;
2435 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2436 fldcw [xSP]
2437 fld qword [REF(g_r64V1)]
2438 ShouldTrap X86_XCPT_MF, fld dword [xDI]
2439 fnclex
2440
2441 ;
2442 ; What happens when we unmask an exception and fwait?
2443 ;
2444 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_IM
2445 fldcw [xSP]
2446 fld dword [xSI]
2447 fwait
2448 FpuCheckFSW X86_FSW_IE | X86_FSW_SF | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2449 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2450 fldcw [xSP]
2451 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
2452
2453 ShouldTrap X86_XCPT_MF, fwait
2454 ShouldTrap X86_XCPT_MF, fwait
2455 ShouldTrap X86_XCPT_MF, fwait
2456 fnclex
2457
2458
2459.success:
2460 xor eax, eax
2461.return:
2462 add xSP, 2048
2463 SAVE_ALL_EPILOGUE
2464 ret
2465ENDPROC x861_Test7
2466
2467
2468extern NAME(RTTestISub)
2469
2470;;
2471; Sets the current subtest.
2472%macro SetSubTest 1
2473%ifdef RT_ARCH_AMD64
2474 %ifdef ASM_CALL64_GCC
2475 lea rdi, [%%s_szName wrt rip]
2476 %else
2477 lea rcx, [%%s_szName wrt rip]
2478 %endif
2479 call NAME(RTTestISub)
2480%else
2481 push %%s_szName
2482 call NAME(RTTestISub)
2483 add esp, 4
2484%endif
2485 jmp %%done
2486%%s_szName:
2487 db %1, 0
2488%%done:
2489%endmacro
2490
2491
2492;;
2493; Checks the opcode and CS:IP FPU.
2494;
2495; @returns ZF=1 on success, ZF=0 on failure.
2496; @param xSP + xS fxsave image followed by fnstenv.
2497; @param xCX Opcode address (no prefixes).
2498;
2499CheckOpcodeCsIp:
2500 push xBP
2501 mov xBP, xSP
2502 push xAX
2503
2504 ; Check the IP.
2505%ifdef RT_ARCH_AMD64
2506 cmp rcx, [xBP + xS*2 + X86FXSTATE.FPUIP]
2507%else
2508 cmp ecx, [xBP + xS*2 + X86FXSTATE.FPUIP]
2509%endif
2510 jne .failure1
2511
2512.check_fpucs:
2513 mov ax, cs
2514 cmp ax, [xBP + xS*2 + 512 + X86FSTENV32P.FPUCS]
2515 jne .failure2
2516
2517 ; Check the opcode. This may be disabled.
2518 mov ah, [xCX]
2519 mov al, [xCX + 1]
2520 and ax, 07ffh
2521
2522 cmp ax, [xBP + xS*2 + X86FXSTATE.FOP]
2523 je .success
2524 cmp ax, [xBP + xS*2 + 512 + X86FSTENV32P.FOP]
2525 je .success
2526
2527; xor ax, ax
2528; cmp ax, [xBP + xS*2 + X86FXSTATE.FOP]
2529; jne .failure3
2530
2531.success:
2532 xor eax, eax ; clear Z
2533.return:
2534 pop xAX
2535 leave
2536 ret
2537
2538.failure1:
2539 ; AMD64 doesn't seem to store anything at IP and DP, so use the
2540 ; fnstenv image instead even if that only contains the lower 32-bit.
2541 xor eax, eax
2542 cmp xAX, [xBP + xS*2 + X86FXSTATE.FPUIP]
2543 jne .failure1_for_real
2544 cmp xAX, [xBP + xS*2 + X86FXSTATE.FPUDP]
2545 jne .failure1_for_real
2546 cmp ecx, [xBP + xS*2 + 512 + X86FSTENV32P.FPUIP]
2547 je .check_fpucs
2548.failure1_for_real:
2549 mov eax, 10000000
2550 jmp .failure
2551.failure2:
2552 mov eax, 20000000
2553 jmp .failure
2554.failure3:
2555 mov eax, 30000000
2556 jmp .failure
2557.failure:
2558 or eax, eax
2559 leave
2560 ret
2561
2562;;
2563; Checks a FPU instruction, no memory operand.
2564;
2565; @uses xCX, xAX, Stack.
2566;
2567%macro FpuCheckOpcodeCsIp 1
2568 mov dword [xSP + X86FXSTATE.FPUIP], 0
2569 mov dword [xSP + X86FXSTATE.FPUCS], 0
2570 mov dword [xSP + X86FXSTATE.FPUDP], 0
2571 mov dword [xSP + X86FXSTATE.FPUDS], 0
2572%%instruction:
2573 %1
2574 arch_fxsave [xSP]
2575 fnstenv [xSP + 512] ; for the selectors (64-bit)
2576 arch_fxrstor [xSP] ; fnstenv screws up the ES bit.
2577 lea xCX, [REF(%%instruction)]
2578 call CheckOpcodeCsIp
2579 jz %%ok
2580 lea xAX, [xAX + __LINE__]
2581 jmp .return
2582%%ok:
2583%endmacro
2584
2585
2586;;
2587; Checks a trapping FPU instruction, no memory operand.
2588;
2589; Upon return, there is are two FXSAVE image on the stack at xSP.
2590;
2591; @uses xCX, xAX, Stack.
2592;
2593; @param %1 The instruction.
2594;
2595%macro FpuTrapOpcodeCsIp 1
2596 mov dword [xSP + 1024 + 512 + X86FXSTATE.FPUIP], 0
2597 mov dword [xSP + 1024 + 512 + X86FXSTATE.FPUCS], 0
2598 mov dword [xSP + 1024 + 512 + X86FXSTATE.FPUDP], 0
2599 mov dword [xSP + 1024 + 512 + X86FXSTATE.FPUDS], 0
2600 mov dword [xSP + X86FXSTATE.FPUIP], 0
2601 mov dword [xSP + X86FXSTATE.FPUCS], 0
2602 mov dword [xSP + X86FXSTATE.FPUDP], 0
2603 mov dword [xSP + X86FXSTATE.FPUDS], 0
2604%%instruction:
2605 %1
2606 fxsave [xSP + 1024 +512] ; FPUDS and FPUCS for 64-bit hosts.
2607 ; WEIRD: When saved after FWAIT they are ZEROed! (64-bit Intel)
2608 arch_fxsave [xSP]
2609 fnstenv [xSP + 512]
2610 arch_fxrstor [xSP]
2611%%trap:
2612 fwait
2613%%trap_end:
2614 mov eax, __LINE__
2615 jmp .return
2616BEGINDATA
2617%%trapinfo: istruc TRAPINFO
2618 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
2619 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
2620 at TRAPINFO.u8TrapNo, db X86_XCPT_MF
2621 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
2622iend
2623BEGINCODE
2624%%resume:
2625 lea xCX, [REF(%%instruction)]
2626 call CheckOpcodeCsIp
2627 jz %%ok
2628 lea xAX, [xAX + __LINE__]
2629 jmp .return
2630%%ok:
2631%endmacro
2632
2633
2634
2635
2636;;
2637; Checks the opcode, CS:IP and DS:DP of the FPU.
2638;
2639; @returns ZF=1 on success, ZF=0+EAX on failure.
2640; @param xSP + xS fxsave image followed by fnstenv.
2641; @param xCX Opcode address (no prefixes).
2642; @param xDX Memory address (DS relative).
2643;
2644CheckOpcodeCsIpDsDp:
2645 push xBP
2646 mov xBP, xSP
2647 push xAX
2648
2649 ; Check the memory operand.
2650%ifdef RT_ARCH_AMD64
2651 cmp rdx, [xBP + xS*2 + X86FXSTATE.FPUDP]
2652%else
2653 cmp edx, [xBP + xS*2 + X86FXSTATE.FPUDP]
2654%endif
2655 jne .failure1
2656
2657.check_fpuds:
2658 mov ax, ds
2659 cmp ax, [xBP + xS*2 + 512 + X86FSTENV32P.FPUDS]
2660 jne .failure2
2661
2662.success:
2663 pop xAX
2664 leave
2665 ; Let CheckOpcodeCsIp to the rest.
2666 jmp CheckOpcodeCsIp
2667
2668.failure1:
2669 ; AMD may leave all fields as ZERO in the FXSAVE image - figure
2670 ; if there is a flag controlling this anywhere...
2671 xor eax, eax
2672 cmp xAX, [xBP + xS*2 + X86FXSTATE.FPUDP]
2673 jne .failure1_for_real
2674 cmp xAX, [xBP + xS*2 + X86FXSTATE.FPUIP]
2675 jne .failure1_for_real
2676 cmp edx, [xBP + xS*2 + 512 + X86FSTENV32P.FPUDP]
2677 je .check_fpuds
2678.failure1_for_real:
2679 mov eax, 60000000
2680 jmp .failure
2681.failure2:
2682 mov eax, 80000000
2683.failure:
2684 or eax, eax
2685 leave
2686 ret
2687
2688
2689;;
2690; Checks a FPU instruction taking a memory operand.
2691;
2692; @uses xCX, xDX, xAX, Stack.
2693;
2694%macro FpuCheckOpcodeCsIpDsDp 2
2695 mov dword [xSP + X86FXSTATE.FPUIP], 0
2696 mov dword [xSP + X86FXSTATE.FPUCS], 0
2697 mov dword [xSP + X86FXSTATE.FPUDP], 0
2698 mov dword [xSP + X86FXSTATE.FPUDS], 0
2699%%instruction:
2700 %1
2701 arch_fxsave [xSP]
2702 fnstenv [xSP + 512] ; for the selectors (64-bit)
2703 arch_fxrstor [xSP] ; fnstenv screws up the ES bit.
2704 lea xDX, %2
2705 lea xCX, [REF(%%instruction)]
2706 call CheckOpcodeCsIpDsDp
2707 jz %%ok
2708 lea xAX, [xAX + __LINE__]
2709 jmp .return
2710%%ok:
2711%endmacro
2712
2713
2714;;
2715; Checks a trapping FPU instruction taking a memory operand.
2716;
2717; Upon return, there is are two FXSAVE image on the stack at xSP.
2718;
2719; @uses xCX, xDX, xAX, Stack.
2720;
2721; @param %1 The instruction.
2722; @param %2 Operand memory address (DS relative).
2723;
2724%macro FpuTrapOpcodeCsIpDsDp 2
2725 mov dword [xSP + X86FXSTATE.FPUIP], 0
2726 mov dword [xSP + X86FXSTATE.FPUCS], 0
2727 mov dword [xSP + X86FXSTATE.FPUDP], 0
2728 mov dword [xSP + X86FXSTATE.FPUDS], 0
2729%%instruction:
2730 %1
2731 fxsave [xSP + 1024 +512] ; FPUDS and FPUCS for 64-bit hosts.
2732 ; WEIRD: When saved after FWAIT they are ZEROed! (64-bit Intel)
2733 arch_fxsave [xSP]
2734 fnstenv [xSP + 512]
2735 arch_fxrstor [xSP]
2736%%trap:
2737 fwait
2738%%trap_end:
2739 mov eax, __LINE__
2740 jmp .return
2741BEGINDATA
2742%%trapinfo: istruc TRAPINFO
2743 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
2744 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
2745 at TRAPINFO.u8TrapNo, db X86_XCPT_MF
2746 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
2747iend
2748BEGINCODE
2749%%resume:
2750 lea xDX, %2
2751 lea xCX, [REF(%%instruction)]
2752 call CheckOpcodeCsIpDsDp
2753 jz %%ok
2754 lea xAX, [xAX + __LINE__]
2755 jmp .return
2756%%ok:
2757%endmacro
2758
2759
2760;;
2761; Checks that the FPU and GReg state is completely unchanged after an instruction
2762; resulting in a CPU trap.
2763;
2764; @param 1 The trap number.
2765; @param 2+ The instruction which should trap.
2766;
2767%macro FpuCheckCpuTrapUnchangedState 2+
2768 call SaveFPUAndGRegsToStack
2769 ShouldTrap %1, %2
2770 call CompareFPUAndGRegsOnStack
2771 jz %%ok
2772 lea xAX, [xAX + __LINE__]
2773 jmp .return
2774%%ok:
2775%endmacro
2776
2777
2778;;
2779; Initialize the FPU and set CW to %1.
2780;
2781; @uses dword at [xSP].
2782;
2783%macro FpuInitWithCW 1
2784 call x861_LoadUniqueRegValuesSSE
2785 fninit
2786 mov dword [xSP], %1
2787 fldcw [xSP]
2788%endmacro
2789
2790
2791;;
2792; First bunch of FPU instruction tests.
2793;
2794;
2795BEGINPROC x861_TestFPUInstr1
2796 SAVE_ALL_PROLOGUE
2797 sub xSP, 2048
2798%if 0
2799 ;
2800 ; FDIV with 64-bit floating point memory operand.
2801 ;
2802 SetSubTest "FDIV m64r"
2803
2804 ; ## Normal operation. ##
2805
2806 fninit
2807 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2808 CheckSt0Value 0x00000000, 0xcccccd00, 0x4000
2809 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_One)] }, [REF(g_r64_One)]
2810 FpuCheckFSW 0, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2811 CheckSt0Value 0x00000000, 0xcccccd00, 0x4000
2812
2813
2814 ; ## Masked exceptions. ##
2815
2816 ; Masked stack underflow.
2817 fninit
2818 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_One)] }, [REF(g_r64_One)]
2819 FpuCheckFSW X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2820 CheckSt0Value_QNaN
2821
2822 ; Masked zero divide.
2823 fninit
2824 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2825 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2826 FpuCheckFSW X86_FSW_ZE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2827 CheckSt0Value_PlusInf
2828
2829 ; Masked Inf/Inf.
2830 fninit
2831 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Inf)] }, [REF(g_r32_Inf)]
2832 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Inf)] }, [REF(g_r64_Inf)]
2833 FpuCheckFSW X86_FSW_IE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2834 CheckSt0Value_QNaN
2835
2836 ; Masked 0/0.
2837 fninit
2838 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Zero)] }, [REF(g_r32_Zero)]
2839 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2840 FpuCheckFSW X86_FSW_IE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2841 CheckSt0Value_QNaN
2842
2843 ; Masked precision exception, rounded down.
2844 fninit
2845 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Ten)] }, [REF(g_r32_Ten)]
2846 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2847 FpuCheckFSW X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2848 CheckSt0Value_3_and_a_3rd
2849
2850 ; Masked precision exception, rounded up.
2851 fninit
2852 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Eleven)] }, [REF(g_r32_Eleven)]
2853 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2854 FpuCheckFSW X86_FSW_PE | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2855 CheckSt0Value_3_and_two_3rds
2856
2857 ; Masked overflow exception.
2858 fninit
2859 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Max)] }, [REF(g_r80_Max)]
2860 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_0dot1)] }, [REF(g_r64_0dot1)]
2861 FpuCheckFSW X86_FSW_PE | X86_FSW_OE | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2862 CheckSt0Value_PlusInf
2863
2864 ; Masked underflow exception.
2865 fninit
2866 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Min)] }, [REF(g_r80_Min)]
2867 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Ten)] }, [REF(g_r64_Ten)]
2868 FpuCheckFSW X86_FSW_PE | X86_FSW_UE | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2869 CheckSt0Value 0xcccccccd, 0x0ccccccc, 0x0000
2870
2871 ; Denormal operand.
2872 fninit
2873 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_One)] }, [REF(g_r80_One)]
2874 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_DnMax)] }, [REF(g_r64_DnMax)]
2875 FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2876 FxSaveCheckSt0Value xSP, 0x00000800, 0x80000000, 0x43fd
2877
2878 ; ## Unmasked exceptions. ##
2879
2880 ; Stack underflow - TOP and ST0 unmodified.
2881 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2882 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_One)] }, [REF(g_r64_One)]
2883 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_B | X86_FSW_ES, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2884 FxSaveCheckSt0EmptyInitValue xSP
2885
2886 ; Zero divide - Unmodified ST0.
2887 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2888 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2889 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2890 FxSaveCheckFSW xSP, X86_FSW_ZE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2891 FxSaveCheckSt0ValueConst xSP, REF(g_r80_r32_3dot2)
2892
2893 ; Invalid Operand (Inf/Inf) - Unmodified ST0.
2894 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2895 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Inf)] }, [REF(g_r32_Inf)]
2896 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Inf)] }, [REF(g_r64_Inf)]
2897 FpuCheckFSW X86_FSW_IE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2898 FxSaveCheckSt0ValueConst xSP, REF(g_r80_Inf)
2899
2900 ; Invalid Operand (0/0) - Unmodified ST0.
2901 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2902 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Zero)] }, [REF(g_r32_Zero)]
2903 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2904 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2905 FxSaveCheckSt0ValueConst xSP, REF(g_r80_Zero)
2906
2907 ; Precision exception, rounded down.
2908 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2909 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Ten)] }, [REF(g_r32_Ten)]
2910 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2911 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2912 FxSaveCheckSt0Value_3_and_a_3rd(xSP)
2913
2914 ; Precision exception, rounded up.
2915 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2916 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Eleven)] }, [REF(g_r32_Eleven)]
2917 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2918 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_C1 | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2919 FxSaveCheckSt0Value_3_and_two_3rds(xSP)
2920
2921 ; Overflow exception.
2922 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2923 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Max)] }, [REF(g_r80_Max)]
2924 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_0dot1)] }, [REF(g_r64_0dot1)]
2925 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_OE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2926 FxSaveCheckSt0Value xSP, 0xfffffd7f, 0x9fffffff, 0x2002
2927
2928 ; Underflow exception.
2929 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2930 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Min)] }, [REF(g_r80_Min)]
2931 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Ten)] }, [REF(g_r64_Ten)]
2932 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
2933 FxSaveCheckSt0Value xSP, 0xcccccccd, 0xcccccccc, 0x5ffd
2934
2935 ; Denormal operand - Unmodified ST0.
2936 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2937 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_One)] }, [REF(g_r80_One)]
2938 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_DnMax)] }, [REF(g_r64_DnMax)]
2939 FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2940 FxSaveCheckSt0ValueConst xSP, REF(g_r80_One)
2941
2942 ;;; @todo exception priority checks.
2943
2944
2945
2946 ; ## A couple of variations on the #PF theme. ##
2947
2948 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2949 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
2950 FpuCheckCpuTrapUnchangedState X86_XCPT_PF, fdiv qword [xBX + PAGE_SIZE]
2951
2952 ; Check that a pending FPU exception takes precedence over a #PF.
2953 fninit
2954 fdiv qword [REF(g_r64_One)]
2955 fstcw [xSP]
2956 and word [xSP], ~(X86_FCW_IM)
2957 fldcw [xSP]
2958 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
2959 ShouldTrap X86_XCPT_MF, fdiv qword [xBX + PAGE_SIZE]
2960
2961 ;
2962 ; FSUBRP STn, ST0
2963 ;
2964 SetSubTest "FSUBRP STn, ST0"
2965
2966 ; ## Normal operation. ##
2967 fninit
2968 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2969 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2970 FpuCheckOpcodeCsIp { fsubrp st1, st0 }
2971 FxSaveCheckFSW xSP, 0, 0
2972 FxSaveCheckSt0ValueConst xSP, REF(g_r80_Zero)
2973
2974 ; ## Masked exceptions. ##
2975
2976 ; Masked stack underflow, both operands.
2977 fninit
2978 FpuCheckOpcodeCsIp { fsubrp st1, st0 }
2979 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2980 FxSaveCheckSt0Value_QNaN(xSP)
2981
2982 ; Masked stack underflow, one operand.
2983 fninit
2984 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2985 FpuCheckOpcodeCsIp { fsubrp st1, st0 }
2986 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2987 FxSaveCheckSt0Value_QNaN(xSP)
2988
2989 ; Denormal operand.
2990 fninit
2991 fld tword [REF(g_r80_DnMax)]
2992 fld tword [REF(g_r80_DnMin)]
2993 FpuCheckOpcodeCsIp { fsubrp st1, st0 }
2994 FxSaveCheckFSW xSP, X86_FSW_DE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2995 FxSaveCheckSt0Value xSP, 0xfffffffe, 0x7fffffff, 0x8000
2996
2997 ; ## Unmasked exceptions. ##
2998
2999 ; Stack underflow, both operands - no pop or change.
3000 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3001 FpuTrapOpcodeCsIp { fsubrp st1, st0 }
3002 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3003 FxSaveCheckSt0EmptyInitValue xSP
3004
3005 ; Stack underflow, one operand - no pop or change.
3006 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3007 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
3008 FpuTrapOpcodeCsIp { fsubrp st1, st0 }
3009 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3010 FxSaveCheckSt0ValueConst xSP, REF(g_r80_r32_3dot2)
3011
3012 ; Denormal operand - no pop.
3013 fninit
3014 fld tword [REF(g_r80_DnMax)]
3015 fld tword [REF(g_r80_DnMin)]
3016 fnclex
3017 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3018 fldcw [xSP]
3019 FpuTrapOpcodeCsIp { fsubrp st1, st0 }
3020 FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3021 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_DnMax)
3022 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_DnMin)
3023
3024 ;
3025 ; FSTP ST0, STn
3026 ;
3027 SetSubTest "FSTP ST0, STn"
3028
3029 ; ## Normal operation. ##
3030 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3031 fld tword [REF(g_r80_0dot1)]
3032 fld tword [REF(g_r80_3dot2)]
3033 FpuCheckOpcodeCsIp { fstp st2 }
3034 FxSaveCheckFSW xSP, 0, 0
3035 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_0dot1)
3036 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
3037
3038 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3039 fld tword [REF(g_r80_Max)]
3040 fld tword [REF(g_r80_Inf)]
3041 FpuCheckOpcodeCsIp { fstp st3 }
3042 FxSaveCheckFSW xSP, 0, 0
3043 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_Max)
3044 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_Inf)
3045
3046 ; Denormal register values doesn't matter get reasserted.
3047 fninit
3048 fld tword [REF(g_r80_DnMin)]
3049 fld tword [REF(g_r80_DnMax)]
3050 fnclex
3051 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3052 fldcw [xSP]
3053 FpuCheckOpcodeCsIp { fstp st2 }
3054 FxSaveCheckFSW xSP, 0, 0
3055 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_DnMin)
3056 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_DnMax)
3057
3058 ; Signaled NaN doesn't matter.
3059 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3060 fld tword [REF(g_r80_SNaN)]
3061 fld tword [REF(g_r80_SNaN)]
3062 fnclex
3063 FpuCheckOpcodeCsIp { fstp st3 }
3064 FxSaveCheckFSW xSP, 0, 0
3065 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_SNaN)
3066 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_SNaN)
3067
3068 ; Quiet NaN doesn't matter either
3069 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3070 fld tword [REF(g_r80_QNaN)]
3071 fld tword [REF(g_r80_QNaN)]
3072 fnclex
3073 FpuCheckOpcodeCsIp { fstp st4 }
3074 FxSaveCheckFSW xSP, 0, 0
3075 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_QNaN)
3076 FxSaveCheckStNValueConst xSP, 3, REF(g_r80_QNaN)
3077
3078 ; There is no overflow signalled.
3079 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3080 fld tword [REF(g_r80_SNaNMax)]
3081 fld tword [REF(g_r80_SNaNMax)]
3082 fnclex
3083 FpuCheckOpcodeCsIp { fstp st1 }
3084 FxSaveCheckFSW xSP, 0, 0
3085 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_SNaNMax)
3086
3087 ; ## Masked exceptions. ##
3088
3089 ; Masked stack underflow.
3090 fninit
3091 FpuCheckOpcodeCsIp { fstp st1 }
3092 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3093 FxSaveCheckSt0Value_QNaN(xSP)
3094
3095 fninit
3096 FpuCheckOpcodeCsIp { fstp st0 }
3097 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3098 FxSaveCheckSt0Empty xSP
3099
3100 ; ## Unmasked exceptions. ##
3101
3102 ; Stack underflow - no pop or change.
3103 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3104 fld tword [REF(g_r80_0dot1)]
3105 fld tword [REF(g_r80_3dot2)]
3106 fld tword [REF(g_r80_Ten)]
3107 ffree st0
3108 FpuTrapOpcodeCsIp { fstp st1 }
3109 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3110 FxSaveCheckSt0Empty xSP
3111 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
3112 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
3113%endif
3114
3115 ;
3116 ; FSTP M32R, ST0
3117 ;
3118 SetSubTest "FSTP M32R, ST0"
3119
3120 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
3121 lea xBX, [xBX + PAGE_SIZE - 4]
3122
3123 ; ## Normal operation. ##
3124 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3125 fld dword [REF(g_r32_Ten)]
3126 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3127 FxSaveCheckFSW xSP, 0, 0
3128 FxSaveCheckSt0Empty xSP
3129 CheckMemoryR32ValueConst xBX, REF(g_r32_Ten)
3130
3131 ; ## Masked exceptions. ##
3132
3133 ; Masked stack underflow.
3134 fninit
3135 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3136 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3137 CheckMemoryR32ValueConst xBX, REF(g_r32_NegQNaN)
3138
3139 fninit
3140 fld tword [REF(g_r80_0dot1)]
3141 fld tword [REF(g_r80_3dot2)]
3142 fld tword [REF(g_r80_Ten)]
3143 ffree st0
3144 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3145 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3146 CheckMemoryR32ValueConst xBX, REF(g_r32_NegQNaN)
3147 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_3dot2)
3148 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_0dot1)
3149
3150 ; Masked #IA caused by SNaN.
3151 fninit
3152 fld tword [REF(g_r80_SNaN)]
3153 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3154 FxSaveCheckFSW xSP, X86_FSW_IE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3155 CheckMemoryR32ValueConst xBX, REF(g_r32_QNaN)
3156
3157 ; Masked #U caused by a denormal value.
3158 fninit
3159 fld tword [REF(g_r80_DnMin)]
3160 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3161 FxSaveCheckFSW xSP, X86_FSW_UE | X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3162 CheckMemoryR32ValueConst xBX, REF(g_r32_Zero)
3163
3164 ; Masked #P caused by a decimal value.
3165 fninit
3166 fld tword [REF(g_r80_3dot2)]
3167 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3168 FxSaveCheckFSW xSP, X86_FSW_C1 | X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3169 CheckMemoryR32ValueConst xBX, REF(g_r32_3dot2)
3170
3171 ; ## Unmasked exceptions. ##
3172
3173 ; Stack underflow - nothing stored or popped.
3174 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3175 mov dword [xBX], 0xffeeddcc
3176 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3177 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3178 CheckMemoryValue dword, xBX, 0xffeeddcc
3179
3180 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3181 fld tword [REF(g_r80_0dot1)]
3182 fld tword [REF(g_r80_3dot2)]
3183 fld tword [REF(g_r80_Ten)]
3184 ffree st0
3185 mov dword [xBX], 0xffeeddcc
3186 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3187 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3188 CheckMemoryValue dword, xBX, 0xffeeddcc
3189 FxSaveCheckStNEmpty xSP, 0
3190 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
3191 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
3192
3193 ; #IA caused by SNaN.
3194 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3195 fld tword [REF(g_r80_SNaN)]
3196 mov dword [xBX], 0xffeeddcc
3197 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3198 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3199 CheckMemoryValue dword, xBX, 0xffeeddcc
3200
3201 ; #U caused by a denormal value - nothing written
3202 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3203 fld tword [REF(g_r80_DnMin)]
3204 mov dword [xBX], 0xffeeddcc
3205 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3206 FxSaveCheckFSW xSP, X86_FSW_UE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3207 CheckMemoryValue dword, xBX, 0xffeeddcc
3208
3209 ; #U caused by a small value - nothing written
3210 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3211 fld tword [REF(g_r80_Min)]
3212 mov dword [xBX], 0xffeeddcc
3213 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3214 FxSaveCheckFSW xSP, X86_FSW_UE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3215 CheckMemoryValue dword, xBX, 0xffeeddcc
3216
3217 ; #O caused by a small value - nothing written
3218 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3219 fld tword [REF(g_r80_Max)]
3220 mov dword [xBX], 0xffeeddcc
3221 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3222 FxSaveCheckFSW xSP, X86_FSW_OE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3223 CheckMemoryValue dword, xBX, 0xffeeddcc
3224
3225 ; #P caused by a decimal value - rounded value is written just like if it was masked.
3226 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3227 fld tword [REF(g_r80_3dot2)]
3228 mov dword [xBX], 0xffeeddcc
3229 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3230 FxSaveCheckFSW xSP, X86_FSW_C1 | X86_FSW_PE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3231 CheckMemoryR32ValueConst xBX, REF(g_r32_3dot2)
3232
3233%if 0 ;; @todo implement me
3234 ;
3235 ; FISTP M32I, ST0
3236 ;
3237 SetSubTest "FISTP M32I, ST0"
3238
3239 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
3240 lea xBX, [xBX + PAGE_SIZE - 4]
3241
3242 ; ## Normal operation. ##
3243 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3244 fld tword [REF(g_r80_Ten)]
3245 FpuCheckOpcodeCsIp { fistp dword [xBX] }
3246 FxSaveCheckFSW xSP, 0, 0
3247 FxSaveCheckSt0Empty xSP
3248 CheckMemoryValue dword, xBX, 10
3249
3250 ; ## Masked exceptions. ##
3251
3252 ; Masked stack underflow.
3253 fninit
3254 FpuCheckOpcodeCsIp { fistp dword [xBX] }
3255 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3256 CheckMemoryValue dword, xBX, 0x80000000
3257
3258 fninit
3259 fld tword [REF(g_r80_0dot1)]
3260 fld tword [REF(g_r80_3dot2)]
3261 fld tword [REF(g_r80_Ten)]
3262 ffree st0
3263 FpuCheckOpcodeCsIp { fistp dword [xBX] }
3264 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3265 CheckMemoryValue dword, xBX, 0x80000000
3266 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_3dot2)
3267 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_0dot1)
3268
3269 ; ## Unmasked exceptions. ##
3270
3271 ; Stack underflow - no pop or change.
3272 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3273 fld tword [REF(g_r80_0dot1)]
3274 fld tword [REF(g_r80_3dot2)]
3275 fld tword [REF(g_r80_Ten)]
3276 ffree st0
3277 mov dword [xBX], 0xffeeddcc
3278 FpuTrapOpcodeCsIp { fistp dword [xBX] }
3279 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3280 FxSaveCheckSt0Empty xSP
3281 CheckMemoryValue dword, xBX, 0xffeeddcc
3282 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
3283 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
3284%endif
3285%if 0
3286 ;
3287 ; FPTAN - calc, store ST0, push 1.0.
3288 ;
3289 SetSubTest "FPTAN"
3290
3291 ; ## Normal operation. ##
3292 fninit
3293 fldpi
3294 FpuCheckOpcodeCsIp { fptan }
3295 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_One)
3296 FxSaveCheckStNValue xSP, 1, 0x00000000, 0x80000000, 0x3fbf ; should be zero, so, this might fail due to precision later.
3297
3298 ; Masked stack underflow - two QNaNs.
3299 fninit
3300 FpuCheckOpcodeCsIp { fptan }
3301 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN)
3302 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN)
3303
3304 ; Masked stack overflow - two QNaNs
3305 fninit
3306 fldpi
3307 fldpi
3308 fldpi
3309 fldpi
3310 fldpi
3311 fldpi
3312 fldpi
3313 fldpi
3314 FpuCheckOpcodeCsIp { fptan }
3315 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN)
3316 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN)
3317
3318 ;; @todo Finish FPTAN testcase.
3319
3320 ;
3321 ; FCMOVB - move if CF=1.
3322 ;
3323 SetSubTest "FCMOVB ST0,STn"
3324
3325 ; ## Normal operation. ##
3326 fninit
3327 fldz
3328 fldpi
3329 call SetFSW_C0_thru_C3
3330 stc
3331 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3332 FxSaveCheckFSW xSP, X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3, 0 ; seems to be preserved...
3333 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_Zero)
3334 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_Zero)
3335
3336 fninit
3337 fldz
3338 fld1
3339 call SetFSW_C0_thru_C3
3340 clc
3341 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3342 FxSaveCheckFSW xSP, X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3, 0 ; seems to be preserved...
3343 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_One)
3344 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_Zero)
3345
3346 ; ## Masked exceptions. ##
3347
3348 ; Masked stack underflow - both.
3349 ; Note! #IE triggers regardless of the test result!
3350 fninit
3351 stc
3352 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3353 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3354 FxSaveCheckStNValue_QNaN(xSP, 0)
3355 FxSaveCheckStNEmpty xSP, 1
3356
3357 fninit
3358 clc
3359 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3360 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3361 FxSaveCheckStNValue_QNaN(xSP, 0)
3362 FxSaveCheckStNEmpty xSP, 1
3363
3364 ; Masked stack underflow - source.
3365 fninit
3366 fldz
3367 stc
3368 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3369 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3370 FxSaveCheckStNValue_QNaN(xSP, 0)
3371 FxSaveCheckStNEmpty xSP, 1
3372
3373 fninit
3374 fldz
3375 stc
3376 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3377 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3378 FxSaveCheckStNValue_QNaN(xSP, 0)
3379 FxSaveCheckStNEmpty xSP, 1
3380
3381 ; Masked stack underflow - destination.
3382 fninit
3383 fldz
3384 fldpi
3385 ffree st0
3386 stc
3387 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3388 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3389 FxSaveCheckStNValue_QNaN(xSP, 0)
3390 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_Zero)
3391
3392 fninit
3393 fldz
3394 fldpi
3395 ffree st0
3396 clc
3397 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3398 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3399 FxSaveCheckStNValue_QNaN(xSP, 0)
3400 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_Zero)
3401
3402 ;; @todo Finish FCMOVB testcase.
3403%endif
3404
3405
3406.success:
3407 xor eax, eax
3408.return:
3409 add xSP, 2048
3410 SAVE_ALL_EPILOGUE
3411 ret
3412
3413ENDPROC x861_TestFPUInstr1
3414
3415
3416
3417
3418;;
3419; Terminate the trap info array with a NIL entry.
3420BEGINDATA
3421GLOBALNAME g_aTrapInfoExecPage
3422istruc TRAPINFO
3423 at TRAPINFO.uTrapPC, RTCCPTR_DEF 1
3424 at TRAPINFO.uResumePC, RTCCPTR_DEF 1
3425 at TRAPINFO.u8TrapNo, db 16
3426 at TRAPINFO.cbInstr, db 3
3427iend
3428GLOBALNAME g_aTrapInfoEnd
3429istruc TRAPINFO
3430 at TRAPINFO.uTrapPC, RTCCPTR_DEF 0
3431 at TRAPINFO.uResumePC, RTCCPTR_DEF 0
3432 at TRAPINFO.u8TrapNo, db 0
3433 at TRAPINFO.cbInstr, db 0
3434iend
3435
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