VirtualBox

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

Last change on this file since 100764 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

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