VirtualBox

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

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

IEM: Implemented missing FPU instructions starting with 0xd8 and adjusted fld m32r and fld m64r.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette