VirtualBox

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

Last change on this file since 58591 was 56287, checked in by vboxsync, 10 years ago

VMM: Updated (C) year.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 108.8 KB
Line 
1; $Id: tstX86-1A.asm 56287 2015-06-09 11:15:22Z vboxsync $
2;; @file
3; X86 instruction set exploration/testcase #1.
4;
5
6;
7; Copyright (C) 2011-2015 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17
18
19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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 + xCB
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 + xCB * 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 + xCB + X86FXSTATE.FPUIP], 0
1957 mov dword [xSP + xCB + X86FXSTATE.FPUCS], 0
1958 mov dword [xSP + xCB + X86FXSTATE.FPUDP], 0
1959 mov dword [xSP + xCB + X86FXSTATE.FPUDS], 0
1960 arch_fxsave [xSP + xCB]
1961
1962 ; Save GRegs (80h bytes).
1963%ifdef RT_ARCH_AMD64
1964 mov [xSP + 512 + xCB + 000h], xAX
1965 mov [xSP + 512 + xCB + 008h], xBX
1966 mov [xSP + 512 + xCB + 010h], xCX
1967 mov [xSP + 512 + xCB + 018h], xDX
1968 mov [xSP + 512 + xCB + 020h], xDI
1969 mov [xSP + 512 + xCB + 028h], xSI
1970 mov [xSP + 512 + xCB + 030h], xBP
1971 mov [xSP + 512 + xCB + 038h], r8
1972 mov [xSP + 512 + xCB + 040h], r9
1973 mov [xSP + 512 + xCB + 048h], r10
1974 mov [xSP + 512 + xCB + 050h], r11
1975 mov [xSP + 512 + xCB + 058h], r12
1976 mov [xSP + 512 + xCB + 060h], r13
1977 mov [xSP + 512 + xCB + 068h], r14
1978 mov [xSP + 512 + xCB + 070h], r15
1979 pushf
1980 pop rax
1981 mov [xSP + 512 + xCB + 078h], rax
1982 mov rax, [xSP + 512 + xCB + 000h]
1983%else
1984 mov [xSP + 512 + xCB + 000h], eax
1985 mov [xSP + 512 + xCB + 004h], eax
1986 mov [xSP + 512 + xCB + 008h], ebx
1987 mov [xSP + 512 + xCB + 00ch], ebx
1988 mov [xSP + 512 + xCB + 010h], ecx
1989 mov [xSP + 512 + xCB + 014h], ecx
1990 mov [xSP + 512 + xCB + 018h], edx
1991 mov [xSP + 512 + xCB + 01ch], edx
1992 mov [xSP + 512 + xCB + 020h], edi
1993 mov [xSP + 512 + xCB + 024h], edi
1994 mov [xSP + 512 + xCB + 028h], esi
1995 mov [xSP + 512 + xCB + 02ch], esi
1996 mov [xSP + 512 + xCB + 030h], ebp
1997 mov [xSP + 512 + xCB + 034h], ebp
1998 mov [xSP + 512 + xCB + 038h], eax
1999 mov [xSP + 512 + xCB + 03ch], eax
2000 mov [xSP + 512 + xCB + 040h], eax
2001 mov [xSP + 512 + xCB + 044h], eax
2002 mov [xSP + 512 + xCB + 048h], eax
2003 mov [xSP + 512 + xCB + 04ch], eax
2004 mov [xSP + 512 + xCB + 050h], eax
2005 mov [xSP + 512 + xCB + 054h], eax
2006 mov [xSP + 512 + xCB + 058h], eax
2007 mov [xSP + 512 + xCB + 05ch], eax
2008 mov [xSP + 512 + xCB + 060h], eax
2009 mov [xSP + 512 + xCB + 064h], eax
2010 mov [xSP + 512 + xCB + 068h], eax
2011 mov [xSP + 512 + xCB + 06ch], eax
2012 mov [xSP + 512 + xCB + 070h], eax
2013 mov [xSP + 512 + xCB + 074h], eax
2014 pushf
2015 pop eax
2016 mov [xSP + 512 + xCB + 078h], eax
2017 mov [xSP + 512 + xCB + 07ch], eax
2018 mov eax, [xSP + 512 + xCB + 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 - xCB)]
2032 call SaveFPUAndGRegsToStack
2033
2034 push xSI
2035 push xDI
2036 push xCX
2037
2038 mov xCX, 640
2039 lea xSI, [xSP + xCB*3]
2040 lea xDI, [xSI + 1024]
2041
2042 cld
2043 repe cmpsb
2044 je .ok
2045
2046 ;int3
2047 lea xAX, [xSP + xCB*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 - xCB)]
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 - xCB)]
2076 call SaveFPUAndGRegsToStack
2077
2078 push xSI
2079 push xDI
2080 push xCX
2081
2082 mov xCX, 640
2083 lea xSI, [xSP + xCB*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 + xCB*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 - xCB)]
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 %ifdef RT_OS_DARWIN
2482 sub esp, 12
2483 push %%s_szName
2484 call NAME(RTTestISub)
2485 add esp, 16
2486 %else
2487 push %%s_szName
2488 call NAME(RTTestISub)
2489 add esp, 4
2490 %endif
2491%endif
2492 jmp %%done
2493%%s_szName:
2494 db %1, 0
2495%%done:
2496%endmacro
2497
2498
2499;;
2500; Checks the opcode and CS:IP FPU.
2501;
2502; @returns ZF=1 on success, ZF=0 on failure.
2503; @param xSP + xCB fxsave image followed by fnstenv.
2504; @param xCX Opcode address (no prefixes).
2505;
2506CheckOpcodeCsIp:
2507 push xBP
2508 mov xBP, xSP
2509 push xAX
2510
2511 ; Check the IP.
2512%ifdef RT_ARCH_AMD64
2513 cmp rcx, [xBP + xCB*2 + X86FXSTATE.FPUIP]
2514%else
2515 cmp ecx, [xBP + xCB*2 + X86FXSTATE.FPUIP]
2516%endif
2517 jne .failure1
2518
2519.check_fpucs:
2520 mov ax, cs
2521 cmp ax, [xBP + xCB*2 + 512 + X86FSTENV32P.FPUCS]
2522 jne .failure2
2523
2524 ; Check the opcode. This may be disabled.
2525 mov ah, [xCX]
2526 mov al, [xCX + 1]
2527 and ax, 07ffh
2528
2529 cmp ax, [xBP + xCB*2 + X86FXSTATE.FOP]
2530 je .success
2531 cmp ax, [xBP + xCB*2 + 512 + X86FSTENV32P.FOP]
2532 je .success
2533
2534; xor ax, ax
2535; cmp ax, [xBP + xCB*2 + X86FXSTATE.FOP]
2536; jne .failure3
2537
2538.success:
2539 xor eax, eax ; clear Z
2540.return:
2541 pop xAX
2542 leave
2543 ret
2544
2545.failure1:
2546 ; AMD64 doesn't seem to store anything at IP and DP, so use the
2547 ; fnstenv image instead even if that only contains the lower 32-bit.
2548 xor eax, eax
2549 cmp xAX, [xBP + xCB*2 + X86FXSTATE.FPUIP]
2550 jne .failure1_for_real
2551 cmp xAX, [xBP + xCB*2 + X86FXSTATE.FPUDP]
2552 jne .failure1_for_real
2553 cmp ecx, [xBP + xCB*2 + 512 + X86FSTENV32P.FPUIP]
2554 je .check_fpucs
2555.failure1_for_real:
2556 mov eax, 10000000
2557 jmp .failure
2558.failure2:
2559 mov eax, 20000000
2560 jmp .failure
2561.failure3:
2562 mov eax, 30000000
2563 jmp .failure
2564.failure:
2565 or eax, eax
2566 leave
2567 ret
2568
2569;;
2570; Checks a FPU instruction, no memory operand.
2571;
2572; @uses xCX, xAX, Stack.
2573;
2574%macro FpuCheckOpcodeCsIp 1
2575 mov dword [xSP + X86FXSTATE.FPUIP], 0
2576 mov dword [xSP + X86FXSTATE.FPUCS], 0
2577 mov dword [xSP + X86FXSTATE.FPUDP], 0
2578 mov dword [xSP + X86FXSTATE.FPUDS], 0
2579%%instruction:
2580 %1
2581 arch_fxsave [xSP]
2582 fnstenv [xSP + 512] ; for the selectors (64-bit)
2583 arch_fxrstor [xSP] ; fnstenv screws up the ES bit.
2584 lea xCX, [REF(%%instruction)]
2585 call CheckOpcodeCsIp
2586 jz %%ok
2587 lea xAX, [xAX + __LINE__]
2588 jmp .return
2589%%ok:
2590%endmacro
2591
2592
2593;;
2594; Checks a trapping FPU instruction, no memory operand.
2595;
2596; Upon return, there is are two FXSAVE image on the stack at xSP.
2597;
2598; @uses xCX, xAX, Stack.
2599;
2600; @param %1 The instruction.
2601;
2602%macro FpuTrapOpcodeCsIp 1
2603 mov dword [xSP + 1024 + 512 + X86FXSTATE.FPUIP], 0
2604 mov dword [xSP + 1024 + 512 + X86FXSTATE.FPUCS], 0
2605 mov dword [xSP + 1024 + 512 + X86FXSTATE.FPUDP], 0
2606 mov dword [xSP + 1024 + 512 + X86FXSTATE.FPUDS], 0
2607 mov dword [xSP + X86FXSTATE.FPUIP], 0
2608 mov dword [xSP + X86FXSTATE.FPUCS], 0
2609 mov dword [xSP + X86FXSTATE.FPUDP], 0
2610 mov dword [xSP + X86FXSTATE.FPUDS], 0
2611%%instruction:
2612 %1
2613 fxsave [xSP + 1024 +512] ; FPUDS and FPUCS for 64-bit hosts.
2614 ; WEIRD: When saved after FWAIT they are ZEROed! (64-bit Intel)
2615 arch_fxsave [xSP]
2616 fnstenv [xSP + 512]
2617 arch_fxrstor [xSP]
2618%%trap:
2619 fwait
2620%%trap_end:
2621 mov eax, __LINE__
2622 jmp .return
2623BEGINDATA
2624%%trapinfo: istruc TRAPINFO
2625 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
2626 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
2627 at TRAPINFO.u8TrapNo, db X86_XCPT_MF
2628 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
2629iend
2630BEGINCODE
2631%%resume:
2632 lea xCX, [REF(%%instruction)]
2633 call CheckOpcodeCsIp
2634 jz %%ok
2635 lea xAX, [xAX + __LINE__]
2636 jmp .return
2637%%ok:
2638%endmacro
2639
2640
2641
2642
2643;;
2644; Checks the opcode, CS:IP and DS:DP of the FPU.
2645;
2646; @returns ZF=1 on success, ZF=0+EAX on failure.
2647; @param xSP + xCB fxsave image followed by fnstenv.
2648; @param xCX Opcode address (no prefixes).
2649; @param xDX Memory address (DS relative).
2650;
2651CheckOpcodeCsIpDsDp:
2652 push xBP
2653 mov xBP, xSP
2654 push xAX
2655
2656 ; Check the memory operand.
2657%ifdef RT_ARCH_AMD64
2658 cmp rdx, [xBP + xCB*2 + X86FXSTATE.FPUDP]
2659%else
2660 cmp edx, [xBP + xCB*2 + X86FXSTATE.FPUDP]
2661%endif
2662 jne .failure1
2663
2664.check_fpuds:
2665 mov ax, ds
2666 cmp ax, [xBP + xCB*2 + 512 + X86FSTENV32P.FPUDS]
2667 jne .failure2
2668
2669.success:
2670 pop xAX
2671 leave
2672 ; Let CheckOpcodeCsIp to the rest.
2673 jmp CheckOpcodeCsIp
2674
2675.failure1:
2676 ; AMD may leave all fields as ZERO in the FXSAVE image - figure
2677 ; if there is a flag controlling this anywhere...
2678 xor eax, eax
2679 cmp xAX, [xBP + xCB*2 + X86FXSTATE.FPUDP]
2680 jne .failure1_for_real
2681 cmp xAX, [xBP + xCB*2 + X86FXSTATE.FPUIP]
2682 jne .failure1_for_real
2683 cmp edx, [xBP + xCB*2 + 512 + X86FSTENV32P.FPUDP]
2684 je .check_fpuds
2685.failure1_for_real:
2686 mov eax, 60000000
2687 jmp .failure
2688.failure2:
2689 mov eax, 80000000
2690.failure:
2691 or eax, eax
2692 leave
2693 ret
2694
2695
2696;;
2697; Checks a FPU instruction taking a memory operand.
2698;
2699; @uses xCX, xDX, xAX, Stack.
2700;
2701%macro FpuCheckOpcodeCsIpDsDp 2
2702 mov dword [xSP + X86FXSTATE.FPUIP], 0
2703 mov dword [xSP + X86FXSTATE.FPUCS], 0
2704 mov dword [xSP + X86FXSTATE.FPUDP], 0
2705 mov dword [xSP + X86FXSTATE.FPUDS], 0
2706%%instruction:
2707 %1
2708 arch_fxsave [xSP]
2709 fnstenv [xSP + 512] ; for the selectors (64-bit)
2710 arch_fxrstor [xSP] ; fnstenv screws up the ES bit.
2711 lea xDX, %2
2712 lea xCX, [REF(%%instruction)]
2713 call CheckOpcodeCsIpDsDp
2714 jz %%ok
2715 lea xAX, [xAX + __LINE__]
2716 jmp .return
2717%%ok:
2718%endmacro
2719
2720
2721;;
2722; Checks a trapping FPU instruction taking a memory operand.
2723;
2724; Upon return, there is are two FXSAVE image on the stack at xSP.
2725;
2726; @uses xCX, xDX, xAX, Stack.
2727;
2728; @param %1 The instruction.
2729; @param %2 Operand memory address (DS relative).
2730;
2731%macro FpuTrapOpcodeCsIpDsDp 2
2732 mov dword [xSP + X86FXSTATE.FPUIP], 0
2733 mov dword [xSP + X86FXSTATE.FPUCS], 0
2734 mov dword [xSP + X86FXSTATE.FPUDP], 0
2735 mov dword [xSP + X86FXSTATE.FPUDS], 0
2736%%instruction:
2737 %1
2738 fxsave [xSP + 1024 +512] ; FPUDS and FPUCS for 64-bit hosts.
2739 ; WEIRD: When saved after FWAIT they are ZEROed! (64-bit Intel)
2740 arch_fxsave [xSP]
2741 fnstenv [xSP + 512]
2742 arch_fxrstor [xSP]
2743%%trap:
2744 fwait
2745%%trap_end:
2746 mov eax, __LINE__
2747 jmp .return
2748BEGINDATA
2749%%trapinfo: istruc TRAPINFO
2750 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap
2751 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume
2752 at TRAPINFO.u8TrapNo, db X86_XCPT_MF
2753 at TRAPINFO.cbInstr, db (%%trap_end - %%trap)
2754iend
2755BEGINCODE
2756%%resume:
2757 lea xDX, %2
2758 lea xCX, [REF(%%instruction)]
2759 call CheckOpcodeCsIpDsDp
2760 jz %%ok
2761 lea xAX, [xAX + __LINE__]
2762 jmp .return
2763%%ok:
2764%endmacro
2765
2766
2767;;
2768; Checks that the FPU and GReg state is completely unchanged after an instruction
2769; resulting in a CPU trap.
2770;
2771; @param 1 The trap number.
2772; @param 2+ The instruction which should trap.
2773;
2774%macro FpuCheckCpuTrapUnchangedState 2+
2775 call SaveFPUAndGRegsToStack
2776 ShouldTrap %1, %2
2777 call CompareFPUAndGRegsOnStack
2778 jz %%ok
2779 lea xAX, [xAX + __LINE__]
2780 jmp .return
2781%%ok:
2782%endmacro
2783
2784
2785;;
2786; Initialize the FPU and set CW to %1.
2787;
2788; @uses dword at [xSP].
2789;
2790%macro FpuInitWithCW 1
2791 call x861_LoadUniqueRegValuesSSE
2792 fninit
2793 mov dword [xSP], %1
2794 fldcw [xSP]
2795%endmacro
2796
2797
2798;;
2799; First bunch of FPU instruction tests.
2800;
2801;
2802BEGINPROC x861_TestFPUInstr1
2803 SAVE_ALL_PROLOGUE
2804 sub xSP, 2048
2805%if 0
2806 ;
2807 ; FDIV with 64-bit floating point memory operand.
2808 ;
2809 SetSubTest "FDIV m64r"
2810
2811 ; ## Normal operation. ##
2812
2813 fninit
2814 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2815 CheckSt0Value 0x00000000, 0xcccccd00, 0x4000
2816 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_One)] }, [REF(g_r64_One)]
2817 FpuCheckFSW 0, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2818 CheckSt0Value 0x00000000, 0xcccccd00, 0x4000
2819
2820
2821 ; ## Masked exceptions. ##
2822
2823 ; Masked stack underflow.
2824 fninit
2825 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_One)] }, [REF(g_r64_One)]
2826 FpuCheckFSW X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2827 CheckSt0Value_QNaN
2828
2829 ; Masked zero divide.
2830 fninit
2831 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2832 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2833 FpuCheckFSW X86_FSW_ZE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2834 CheckSt0Value_PlusInf
2835
2836 ; Masked Inf/Inf.
2837 fninit
2838 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Inf)] }, [REF(g_r32_Inf)]
2839 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Inf)] }, [REF(g_r64_Inf)]
2840 FpuCheckFSW X86_FSW_IE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2841 CheckSt0Value_QNaN
2842
2843 ; Masked 0/0.
2844 fninit
2845 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Zero)] }, [REF(g_r32_Zero)]
2846 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2847 FpuCheckFSW X86_FSW_IE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2848 CheckSt0Value_QNaN
2849
2850 ; Masked precision exception, rounded down.
2851 fninit
2852 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Ten)] }, [REF(g_r32_Ten)]
2853 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2854 FpuCheckFSW X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2855 CheckSt0Value_3_and_a_3rd
2856
2857 ; Masked precision exception, rounded up.
2858 fninit
2859 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Eleven)] }, [REF(g_r32_Eleven)]
2860 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2861 FpuCheckFSW X86_FSW_PE | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2862 CheckSt0Value_3_and_two_3rds
2863
2864 ; Masked overflow exception.
2865 fninit
2866 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Max)] }, [REF(g_r80_Max)]
2867 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_0dot1)] }, [REF(g_r64_0dot1)]
2868 FpuCheckFSW X86_FSW_PE | X86_FSW_OE | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2869 CheckSt0Value_PlusInf
2870
2871 ; Masked underflow exception.
2872 fninit
2873 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Min)] }, [REF(g_r80_Min)]
2874 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Ten)] }, [REF(g_r64_Ten)]
2875 FpuCheckFSW X86_FSW_PE | X86_FSW_UE | X86_FSW_C1, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2876 CheckSt0Value 0xcccccccd, 0x0ccccccc, 0x0000
2877
2878 ; Denormal operand.
2879 fninit
2880 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_One)] }, [REF(g_r80_One)]
2881 FpuCheckOpcodeCsIpDsDp { fdiv qword [REF(g_r64_DnMax)] }, [REF(g_r64_DnMax)]
2882 FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2883 FxSaveCheckSt0Value xSP, 0x00000800, 0x80000000, 0x43fd
2884
2885 ; ## Unmasked exceptions. ##
2886
2887 ; Stack underflow - TOP and ST0 unmodified.
2888 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2889 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_One)] }, [REF(g_r64_One)]
2890 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_B | X86_FSW_ES, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2891 FxSaveCheckSt0EmptyInitValue xSP
2892
2893 ; Zero divide - Unmodified ST0.
2894 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2895 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2896 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2897 FxSaveCheckFSW xSP, X86_FSW_ZE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2898 FxSaveCheckSt0ValueConst xSP, REF(g_r80_r32_3dot2)
2899
2900 ; Invalid Operand (Inf/Inf) - Unmodified ST0.
2901 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2902 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Inf)] }, [REF(g_r32_Inf)]
2903 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Inf)] }, [REF(g_r64_Inf)]
2904 FpuCheckFSW X86_FSW_IE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2905 FxSaveCheckSt0ValueConst xSP, REF(g_r80_Inf)
2906
2907 ; Invalid Operand (0/0) - Unmodified ST0.
2908 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2909 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Zero)] }, [REF(g_r32_Zero)]
2910 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Zero)] }, [REF(g_r64_Zero)]
2911 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2912 FxSaveCheckSt0ValueConst xSP, REF(g_r80_Zero)
2913
2914 ; Precision exception, rounded down.
2915 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2916 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Ten)] }, [REF(g_r32_Ten)]
2917 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2918 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2919 FxSaveCheckSt0Value_3_and_a_3rd(xSP)
2920
2921 ; Precision exception, rounded up.
2922 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2923 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_Eleven)] }, [REF(g_r32_Eleven)]
2924 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Three)] }, [REF(g_r64_Three)]
2925 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_C1 | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2926 FxSaveCheckSt0Value_3_and_two_3rds(xSP)
2927
2928 ; Overflow exception.
2929 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2930 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Max)] }, [REF(g_r80_Max)]
2931 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_0dot1)] }, [REF(g_r64_0dot1)]
2932 FxSaveCheckFSW xSP, X86_FSW_PE | X86_FSW_OE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2933 FxSaveCheckSt0Value xSP, 0xfffffd7f, 0x9fffffff, 0x2002
2934
2935 ; Underflow exception.
2936 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2937 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_Min)] }, [REF(g_r80_Min)]
2938 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_Ten)] }, [REF(g_r64_Ten)]
2939 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
2940 FxSaveCheckSt0Value xSP, 0xcccccccd, 0xcccccccc, 0x5ffd
2941
2942 ; Denormal operand - Unmodified ST0.
2943 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2944 FpuCheckOpcodeCsIpDsDp { fld tword [REF(g_r80_One)] }, [REF(g_r80_One)]
2945 FpuTrapOpcodeCsIpDsDp { fdiv qword [REF(g_r64_DnMax)] }, [REF(g_r64_DnMax)]
2946 FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2947 FxSaveCheckSt0ValueConst xSP, REF(g_r80_One)
2948
2949 ;;; @todo exception priority checks.
2950
2951
2952
2953 ; ## A couple of variations on the #PF theme. ##
2954
2955 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
2956 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
2957 FpuCheckCpuTrapUnchangedState X86_XCPT_PF, fdiv qword [xBX + PAGE_SIZE]
2958
2959 ; Check that a pending FPU exception takes precedence over a #PF.
2960 fninit
2961 fdiv qword [REF(g_r64_One)]
2962 fstcw [xSP]
2963 and word [xSP], ~(X86_FCW_IM)
2964 fldcw [xSP]
2965 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
2966 ShouldTrap X86_XCPT_MF, fdiv qword [xBX + PAGE_SIZE]
2967
2968 ;
2969 ; FSUBRP STn, ST0
2970 ;
2971 SetSubTest "FSUBRP STn, ST0"
2972
2973 ; ## Normal operation. ##
2974 fninit
2975 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2976 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2977 FpuCheckOpcodeCsIp { fsubrp st1, st0 }
2978 FxSaveCheckFSW xSP, 0, 0
2979 FxSaveCheckSt0ValueConst xSP, REF(g_r80_Zero)
2980
2981 ; ## Masked exceptions. ##
2982
2983 ; Masked stack underflow, both operands.
2984 fninit
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 ; Masked stack underflow, one operand.
2990 fninit
2991 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
2992 FpuCheckOpcodeCsIp { fsubrp st1, st0 }
2993 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
2994 FxSaveCheckSt0Value_QNaN(xSP)
2995
2996 ; Denormal operand.
2997 fninit
2998 fld tword [REF(g_r80_DnMax)]
2999 fld tword [REF(g_r80_DnMin)]
3000 FpuCheckOpcodeCsIp { fsubrp st1, st0 }
3001 FxSaveCheckFSW xSP, X86_FSW_DE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3002 FxSaveCheckSt0Value xSP, 0xfffffffe, 0x7fffffff, 0x8000
3003
3004 ; ## Unmasked exceptions. ##
3005
3006 ; Stack underflow, both operands - no pop or change.
3007 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
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 FxSaveCheckSt0EmptyInitValue xSP
3011
3012 ; Stack underflow, one operand - no pop or change.
3013 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3014 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)]
3015 FpuTrapOpcodeCsIp { fsubrp st1, st0 }
3016 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3017 FxSaveCheckSt0ValueConst xSP, REF(g_r80_r32_3dot2)
3018
3019 ; Denormal operand - no pop.
3020 fninit
3021 fld tword [REF(g_r80_DnMax)]
3022 fld tword [REF(g_r80_DnMin)]
3023 fnclex
3024 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3025 fldcw [xSP]
3026 FpuTrapOpcodeCsIp { fsubrp st1, st0 }
3027 FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3028 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_DnMax)
3029 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_DnMin)
3030
3031 ;
3032 ; FSTP ST0, STn
3033 ;
3034 SetSubTest "FSTP ST0, STn"
3035
3036 ; ## Normal operation. ##
3037 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3038 fld tword [REF(g_r80_0dot1)]
3039 fld tword [REF(g_r80_3dot2)]
3040 FpuCheckOpcodeCsIp { fstp st2 }
3041 FxSaveCheckFSW xSP, 0, 0
3042 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_0dot1)
3043 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
3044
3045 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3046 fld tword [REF(g_r80_Max)]
3047 fld tword [REF(g_r80_Inf)]
3048 FpuCheckOpcodeCsIp { fstp st3 }
3049 FxSaveCheckFSW xSP, 0, 0
3050 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_Max)
3051 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_Inf)
3052
3053 ; Denormal register values doesn't matter get reasserted.
3054 fninit
3055 fld tword [REF(g_r80_DnMin)]
3056 fld tword [REF(g_r80_DnMax)]
3057 fnclex
3058 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3059 fldcw [xSP]
3060 FpuCheckOpcodeCsIp { fstp st2 }
3061 FxSaveCheckFSW xSP, 0, 0
3062 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_DnMin)
3063 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_DnMax)
3064
3065 ; Signaled NaN doesn't matter.
3066 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3067 fld tword [REF(g_r80_SNaN)]
3068 fld tword [REF(g_r80_SNaN)]
3069 fnclex
3070 FpuCheckOpcodeCsIp { fstp st3 }
3071 FxSaveCheckFSW xSP, 0, 0
3072 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_SNaN)
3073 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_SNaN)
3074
3075 ; Quiet NaN doesn't matter either
3076 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3077 fld tword [REF(g_r80_QNaN)]
3078 fld tword [REF(g_r80_QNaN)]
3079 fnclex
3080 FpuCheckOpcodeCsIp { fstp st4 }
3081 FxSaveCheckFSW xSP, 0, 0
3082 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_QNaN)
3083 FxSaveCheckStNValueConst xSP, 3, REF(g_r80_QNaN)
3084
3085 ; There is no overflow signalled.
3086 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3087 fld tword [REF(g_r80_SNaNMax)]
3088 fld tword [REF(g_r80_SNaNMax)]
3089 fnclex
3090 FpuCheckOpcodeCsIp { fstp st1 }
3091 FxSaveCheckFSW xSP, 0, 0
3092 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_SNaNMax)
3093
3094 ; ## Masked exceptions. ##
3095
3096 ; Masked stack underflow.
3097 fninit
3098 FpuCheckOpcodeCsIp { fstp st1 }
3099 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3100 FxSaveCheckSt0Value_QNaN(xSP)
3101
3102 fninit
3103 FpuCheckOpcodeCsIp { fstp st0 }
3104 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3105 FxSaveCheckSt0Empty xSP
3106
3107 ; ## Unmasked exceptions. ##
3108
3109 ; Stack underflow - no pop or change.
3110 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3111 fld tword [REF(g_r80_0dot1)]
3112 fld tword [REF(g_r80_3dot2)]
3113 fld tword [REF(g_r80_Ten)]
3114 ffree st0
3115 FpuTrapOpcodeCsIp { fstp st1 }
3116 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3117 FxSaveCheckSt0Empty xSP
3118 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
3119 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
3120%endif
3121
3122 ;
3123 ; FSTP M32R, ST0
3124 ;
3125 SetSubTest "FSTP M32R, ST0"
3126
3127 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
3128 lea xBX, [xBX + PAGE_SIZE - 4]
3129
3130 ; ## Normal operation. ##
3131 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3132 fld dword [REF(g_r32_Ten)]
3133 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3134 FxSaveCheckFSW xSP, 0, 0
3135 FxSaveCheckSt0Empty xSP
3136 CheckMemoryR32ValueConst xBX, REF(g_r32_Ten)
3137
3138 ; ## Masked exceptions. ##
3139
3140 ; Masked stack underflow.
3141 fninit
3142 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3143 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3144 CheckMemoryR32ValueConst xBX, REF(g_r32_NegQNaN)
3145
3146 fninit
3147 fld tword [REF(g_r80_0dot1)]
3148 fld tword [REF(g_r80_3dot2)]
3149 fld tword [REF(g_r80_Ten)]
3150 ffree st0
3151 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3152 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3153 CheckMemoryR32ValueConst xBX, REF(g_r32_NegQNaN)
3154 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_3dot2)
3155 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_0dot1)
3156
3157 ; Masked #IA caused by SNaN.
3158 fninit
3159 fld tword [REF(g_r80_SNaN)]
3160 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3161 FxSaveCheckFSW xSP, X86_FSW_IE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3162 CheckMemoryR32ValueConst xBX, REF(g_r32_QNaN)
3163
3164 ; Masked #U caused by a denormal value.
3165 fninit
3166 fld tword [REF(g_r80_DnMin)]
3167 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3168 FxSaveCheckFSW xSP, X86_FSW_UE | X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3169 CheckMemoryR32ValueConst xBX, REF(g_r32_Zero)
3170
3171 ; Masked #P caused by a decimal value.
3172 fninit
3173 fld tword [REF(g_r80_3dot2)]
3174 FpuCheckOpcodeCsIp { fstp dword [xBX] }
3175 FxSaveCheckFSW xSP, X86_FSW_C1 | X86_FSW_PE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3176 CheckMemoryR32ValueConst xBX, REF(g_r32_3dot2)
3177
3178 ; ## Unmasked exceptions. ##
3179
3180 ; Stack underflow - nothing stored or popped.
3181 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3182 mov dword [xBX], 0xffeeddcc
3183 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3184 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3185 CheckMemoryValue dword, xBX, 0xffeeddcc
3186
3187 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3188 fld tword [REF(g_r80_0dot1)]
3189 fld tword [REF(g_r80_3dot2)]
3190 fld tword [REF(g_r80_Ten)]
3191 ffree st0
3192 mov dword [xBX], 0xffeeddcc
3193 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3194 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3195 CheckMemoryValue dword, xBX, 0xffeeddcc
3196 FxSaveCheckStNEmpty xSP, 0
3197 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
3198 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
3199
3200 ; #IA caused by SNaN.
3201 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3202 fld tword [REF(g_r80_SNaN)]
3203 mov dword [xBX], 0xffeeddcc
3204 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3205 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3206 CheckMemoryValue dword, xBX, 0xffeeddcc
3207
3208 ; #U caused by a denormal value - nothing written
3209 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3210 fld tword [REF(g_r80_DnMin)]
3211 mov dword [xBX], 0xffeeddcc
3212 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3213 FxSaveCheckFSW xSP, X86_FSW_UE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3214 CheckMemoryValue dword, xBX, 0xffeeddcc
3215
3216 ; #U caused by a small value - nothing written
3217 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3218 fld tword [REF(g_r80_Min)]
3219 mov dword [xBX], 0xffeeddcc
3220 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3221 FxSaveCheckFSW xSP, X86_FSW_UE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3222 CheckMemoryValue dword, xBX, 0xffeeddcc
3223
3224 ; #O caused by a small value - nothing written
3225 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3226 fld tword [REF(g_r80_Max)]
3227 mov dword [xBX], 0xffeeddcc
3228 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3229 FxSaveCheckFSW xSP, X86_FSW_OE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3230 CheckMemoryValue dword, xBX, 0xffeeddcc
3231
3232 ; #P caused by a decimal value - rounded value is written just like if it was masked.
3233 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3234 fld tword [REF(g_r80_3dot2)]
3235 mov dword [xBX], 0xffeeddcc
3236 FpuTrapOpcodeCsIp { fstp dword [xBX] }
3237 FxSaveCheckFSW xSP, X86_FSW_C1 | X86_FSW_PE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3238 CheckMemoryR32ValueConst xBX, REF(g_r32_3dot2)
3239
3240%if 0 ;; @todo implement me
3241 ;
3242 ; FISTP M32I, ST0
3243 ;
3244 SetSubTest "FISTP M32I, ST0"
3245
3246 mov xBX, [REF_EXTERN(g_pbEfExecPage)]
3247 lea xBX, [xBX + PAGE_SIZE - 4]
3248
3249 ; ## Normal operation. ##
3250 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3251 fld tword [REF(g_r80_Ten)]
3252 FpuCheckOpcodeCsIp { fistp dword [xBX] }
3253 FxSaveCheckFSW xSP, 0, 0
3254 FxSaveCheckSt0Empty xSP
3255 CheckMemoryValue dword, xBX, 10
3256
3257 ; ## Masked exceptions. ##
3258
3259 ; Masked stack underflow.
3260 fninit
3261 FpuCheckOpcodeCsIp { fistp dword [xBX] }
3262 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3263 CheckMemoryValue dword, xBX, 0x80000000
3264
3265 fninit
3266 fld tword [REF(g_r80_0dot1)]
3267 fld tword [REF(g_r80_3dot2)]
3268 fld tword [REF(g_r80_Ten)]
3269 ffree st0
3270 FpuCheckOpcodeCsIp { fistp dword [xBX] }
3271 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3272 CheckMemoryValue dword, xBX, 0x80000000
3273 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_3dot2)
3274 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_0dot1)
3275
3276 ; ## Unmasked exceptions. ##
3277
3278 ; Stack underflow - no pop or change.
3279 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
3280 fld tword [REF(g_r80_0dot1)]
3281 fld tword [REF(g_r80_3dot2)]
3282 fld tword [REF(g_r80_Ten)]
3283 ffree st0
3284 mov dword [xBX], 0xffeeddcc
3285 FpuTrapOpcodeCsIp { fistp dword [xBX] }
3286 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3287 FxSaveCheckSt0Empty xSP
3288 CheckMemoryValue dword, xBX, 0xffeeddcc
3289 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
3290 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
3291%endif
3292%if 0
3293 ;
3294 ; FPTAN - calc, store ST0, push 1.0.
3295 ;
3296 SetSubTest "FPTAN"
3297
3298 ; ## Normal operation. ##
3299 fninit
3300 fldpi
3301 FpuCheckOpcodeCsIp { fptan }
3302 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_One)
3303 FxSaveCheckStNValue xSP, 1, 0x00000000, 0x80000000, 0x3fbf ; should be zero, so, this might fail due to precision later.
3304
3305 ; Masked stack underflow - two QNaNs.
3306 fninit
3307 FpuCheckOpcodeCsIp { fptan }
3308 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN)
3309 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN)
3310
3311 ; Masked stack overflow - two QNaNs
3312 fninit
3313 fldpi
3314 fldpi
3315 fldpi
3316 fldpi
3317 fldpi
3318 fldpi
3319 fldpi
3320 fldpi
3321 FpuCheckOpcodeCsIp { fptan }
3322 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN)
3323 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN)
3324
3325 ;; @todo Finish FPTAN testcase.
3326
3327 ;
3328 ; FCMOVB - move if CF=1.
3329 ;
3330 SetSubTest "FCMOVB ST0,STn"
3331
3332 ; ## Normal operation. ##
3333 fninit
3334 fldz
3335 fldpi
3336 call SetFSW_C0_thru_C3
3337 stc
3338 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3339 FxSaveCheckFSW xSP, X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3, 0 ; seems to be preserved...
3340 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_Zero)
3341 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_Zero)
3342
3343 fninit
3344 fldz
3345 fld1
3346 call SetFSW_C0_thru_C3
3347 clc
3348 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3349 FxSaveCheckFSW xSP, X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3, 0 ; seems to be preserved...
3350 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_One)
3351 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_Zero)
3352
3353 ; ## Masked exceptions. ##
3354
3355 ; Masked stack underflow - both.
3356 ; Note! #IE triggers regardless of the test result!
3357 fninit
3358 stc
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 fninit
3365 clc
3366 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3367 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3368 FxSaveCheckStNValue_QNaN(xSP, 0)
3369 FxSaveCheckStNEmpty xSP, 1
3370
3371 ; Masked stack underflow - source.
3372 fninit
3373 fldz
3374 stc
3375 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3376 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3377 FxSaveCheckStNValue_QNaN(xSP, 0)
3378 FxSaveCheckStNEmpty xSP, 1
3379
3380 fninit
3381 fldz
3382 stc
3383 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3384 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3385 FxSaveCheckStNValue_QNaN(xSP, 0)
3386 FxSaveCheckStNEmpty xSP, 1
3387
3388 ; Masked stack underflow - destination.
3389 fninit
3390 fldz
3391 fldpi
3392 ffree st0
3393 stc
3394 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3395 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3396 FxSaveCheckStNValue_QNaN(xSP, 0)
3397 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_Zero)
3398
3399 fninit
3400 fldz
3401 fldpi
3402 ffree st0
3403 clc
3404 FpuCheckOpcodeCsIp { fcmovb st0,st1 }
3405 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
3406 FxSaveCheckStNValue_QNaN(xSP, 0)
3407 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_Zero)
3408
3409 ;; @todo Finish FCMOVB testcase.
3410%endif
3411
3412
3413.success:
3414 xor eax, eax
3415.return:
3416 add xSP, 2048
3417 SAVE_ALL_EPILOGUE
3418 ret
3419
3420ENDPROC x861_TestFPUInstr1
3421
3422
3423
3424
3425;;
3426; Terminate the trap info array with a NIL entry.
3427BEGINDATA
3428GLOBALNAME g_aTrapInfoExecPage
3429istruc TRAPINFO
3430 at TRAPINFO.uTrapPC, RTCCPTR_DEF 1
3431 at TRAPINFO.uResumePC, RTCCPTR_DEF 1
3432 at TRAPINFO.u8TrapNo, db 16
3433 at TRAPINFO.cbInstr, db 3
3434iend
3435GLOBALNAME g_aTrapInfoEnd
3436istruc TRAPINFO
3437 at TRAPINFO.uTrapPC, RTCCPTR_DEF 0
3438 at TRAPINFO.uResumePC, RTCCPTR_DEF 0
3439 at TRAPINFO.u8TrapNo, db 0
3440 at TRAPINFO.cbInstr, db 0
3441iend
3442
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