VirtualBox

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

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

checked out some todos.

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