VirtualBox

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

Last change on this file since 67018 was 62478, checked in by vboxsync, 8 years ago

(C) 2016

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