VirtualBox

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

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

IEM: Conditional FPU move instructions (FCMOV*).

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

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