VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bootsector2-cpu-instr-1-template.mac@ 97613

Last change on this file since 97613 was 97116, checked in by vboxsync, 2 years ago

ValKit: Also test what CMPXCHG8B does to RAX/RDX.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.8 KB
Line 
1; $Id: bootsector2-cpu-instr-1-template.mac 97116 2022-10-12 15:07:25Z vboxsync $
2;; @file
3; Bootsector test for misc instruction - multi mode template.
4;
5
6;
7; Copyright (C) 2007-2022 Oracle and/or its affiliates.
8;
9; This file is part of VirtualBox base platform packages, as
10; available from https://www.virtualbox.org.
11;
12; This program is free software; you can redistribute it and/or
13; modify it under the terms of the GNU General Public License
14; as published by the Free Software Foundation, in version 3 of the
15; License.
16;
17; This program is distributed in the hope that it will be useful, but
18; WITHOUT ANY WARRANTY; without even the implied warranty of
19; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20; General Public License for more details.
21;
22; You should have received a copy of the GNU General Public License
23; along with this program; if not, see <https://www.gnu.org/licenses>.
24;
25; The contents of this file may alternatively be used under the terms
26; of the Common Development and Distribution License Version 1.0
27; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28; in the VirtualBox distribution, in which case the provisions of the
29; CDDL are applicable instead of those of the GPL.
30;
31; You may elect to license modified versions of this file under the
32; terms and conditions of either the GPL or the CDDL or both.
33;
34; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35;
36
37
38%include "bootsector2-template-header.mac"
39
40
41
42;;
43; Memory fence instructions (SSE2).
44;
45; @uses No registers, but BS2_SEL_SPARE0 is trashed.
46;
47BEGINPROC TMPL_NM(TestMemFences)
48 push xBP
49 mov xBP, xSP
50 push sAX
51 push xBX
52 push xCX
53 push xDX
54 push xDI
55 push xSI
56 sub xSP, 80h ; iret stack frame space.
57 mov xSI, xSP ; Save the stack register.
58
59 mov xAX, .s_szSubTestName
60 call TMPL_NM_CMN(TestSub)
61
62 ;
63 ; SSE2 supported?
64 ;
65 mov eax, 1
66 xor ecx, ecx
67 cpuid
68 test edx, X86_CPUID_FEATURE_EDX_SSE2
69 jz .skip
70
71 ;
72 ; Check that the standard instruction encodings work.
73 ;
74 mov xBX, [xSP + 10h]
75 mov [xSP], xAX
76 mfence
77 mov [xSP], xCX
78 mov xBX, [xSP + 08h]
79 sfence
80 mov [xSP], xDX
81 mov xBX, [xSP]
82 lfence
83 mov bx, [xSP + 04h]
84
85
86 ;
87 ; The instruction encodings in the intel manual may open the RM as well
88 ; as prefixes open to interpretation. AMD sets RM=0 in their docs.
89 ;
90 ; lfence = 0f,ea,e8
91 ; mfence = 0f,ea,f0
92 ; sfence = 0f,ea,f8
93 ; (RM is the lower 3 bits of the last byte.)
94
95%assign MY_RM 0xe8
96%rep 18h
97 db 0fh, 0aeh, MY_RM
98 db X86_OP_PRF_CS, 0fh, 0aeh, MY_RM
99 db X86_OP_PRF_DS, 0fh, 0aeh, MY_RM
100 db X86_OP_PRF_ES, 0fh, 0aeh, MY_RM
101 db X86_OP_PRF_FS, 0fh, 0aeh, MY_RM
102 db X86_OP_PRF_GS, 0fh, 0aeh, MY_RM
103 db X86_OP_PRF_SS, 0fh, 0aeh, MY_RM
104 db X86_OP_PRF_SIZE_ADDR, 0fh, 0aeh, MY_RM
105 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_SIZE_OP, 0fh, 0aeh, MY_RM ; (used in group)
106 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_LOCK, 0fh, 0aeh, MY_RM ; (used in group)
107 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_REPNZ, 0fh, 0aeh, MY_RM ; (used in group)
108 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_REPZ, 0fh, 0aeh, MY_RM ; (used in group)
109%ifdef TMPL_64BIT
110 %assign MY_REX 0x40
111 %rep 10h
112 ; Rex prefixes doesn't change anything.
113 db MY_REX, 0fh, 0aeh, MY_RM
114 db X86_OP_PRF_CS, MY_REX, 0fh, 0aeh, MY_RM
115 db X86_OP_PRF_DS, MY_REX, 0fh, 0aeh, MY_RM
116 db X86_OP_PRF_ES, MY_REX, 0fh, 0aeh, MY_RM
117 db X86_OP_PRF_FS, MY_REX, 0fh, 0aeh, MY_RM
118 db X86_OP_PRF_GS, MY_REX, 0fh, 0aeh, MY_RM
119 db X86_OP_PRF_SS, MY_REX, 0fh, 0aeh, MY_RM
120 db X86_OP_PRF_SIZE_ADDR, MY_REX, 0fh, 0aeh, MY_RM
121 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_SIZE_OP, MY_REX, 0fh, 0aeh, MY_RM ; (used in group)
122 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_LOCK, MY_REX, 0fh, 0aeh, MY_RM ; (used in group)
123 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_REPNZ, MY_REX, 0fh, 0aeh, MY_RM ; (used in group)
124 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_REPZ, MY_REX, 0fh, 0aeh, MY_RM ; (used in group)
125 %assign MY_REX (MY_REX + 1)
126 %endrep
127%endif
128 %assign MY_RM (MY_RM + 1)
129%endrep
130
131 ;
132 ; Done.
133 ;
134 call TMPL_NM_CMN(TestSubDone)
135.done:
136 mov xSP, xSI
137 add xSP, 80h
138 pop xSI
139 pop xDI
140 pop xDX
141 pop xCX
142 pop xBX
143 pop sAX
144 leave
145 ret
146
147.skip:
148 mov xAX, .s_szSse2Missing
149 call TMPL_NM_CMN(TestSubDone)
150 jmp .done
151
152.s_szSubTestName:
153 db TMPL_MODE_STR, ', mfence et al.', 0
154.s_szSse2Missing:
155 db 'SSE2 is missing', 0
156ENDPROC TMPL_NM(TestMemFences)
157
158
159;;
160; Floating-point to integer conversion (SSE/SSE2).
161; Neither Intel nor AMD explicitly document what happens for the 32-bit forms
162; of CVTxx2SI in 64-bit mode with regard to the high dword of a 64-bit
163; destination register.
164;
165; @uses XMM0, and BS2_SEL_SPARE0 is trashed.
166;
167BEGINPROC TMPL_NM(TestCvtSize)
168 push xBP
169 mov xBP, xSP
170 push sAX
171 push xBX
172 push xCX
173 push xDX
174 push xDI
175 push xSI
176 sub xSP, 80h ; iret stack frame space.
177 mov xSI, xSP ; Save the stack register.
178
179 mov xAX, .s_szSubTestName
180 call TMPL_NM_CMN(TestSub)
181
182 ;
183 ; SSE2 supported?
184 ;
185 mov eax, 1
186 xor ecx, ecx
187 cpuid
188 test edx, X86_CPUID_FEATURE_EDX_SSE2
189 jz .skip
190
191%ifdef TMPL_64BIT
192
193 ;
194 ; Have to enable OSFXSR for SSE instructions to work.
195 ;
196 mov rcx,cr4
197 mov rsi,rcx
198 or rcx,200h
199 mov cr4,rcx
200
201 ;
202 ; Load 32-bit float -2.75 into XMM0
203 ;
204 mov eax, 0C0300000h
205 movd xmm0, eax
206 mov rbx, -1 ; make sure high dword is not zero
207 cvtss2si ebx, xmm0 ; result is -3
208 mov eax, -3 ; high dword of rax zeroed
209 TEST_ASSERT_SIMPLE rbx, rax, jz, "CVTSS2SI EBX"
210
211 mov eax, 0C0300000h
212 movd xmm0, eax
213 mov rbx, -1
214 cvttss2si ebx, xmm0 ; result is -2
215 mov eax, -2
216 TEST_ASSERT_SIMPLE rbx, rax, jz, "CVTTSS2SI EBX"
217
218 ;
219 ; Load 64-bit double -2.75 into XMM0
220 ;
221 mov rax, 0C006000000000000h
222 movd xmm0, rax
223 mov rbx, -1
224 cvtsd2si ebx, xmm0
225 mov eax, -3
226 TEST_ASSERT_SIMPLE rbx, rax, jz, "CVTSD2SI EBX"
227
228 mov rax, 0C006000000000000h
229 mov rbx, -1
230 movd xmm0, rax
231 cvttsd2si ebx, xmm0
232 mov eax,-2
233 TEST_ASSERT_SIMPLE rbx, rax, jz, "CVTTSD2SI EBX"
234
235 ;
236 ; Restore prior CR4 value
237 ;
238 mov cr4,rsi
239%endif
240
241 ;
242 ; Done.
243 ;
244 call TMPL_NM_CMN(TestSubDone)
245.done:
246 mov xSP, xSI
247 add xSP, 80h
248 pop xSI
249 pop xDI
250 pop xDX
251 pop xCX
252 pop xBX
253 pop sAX
254 leave
255 ret
256
257.skip:
258 mov xAX, .s_szSse2Missing
259 call TMPL_NM_CMN(TestSubDone)
260 jmp .done
261
262.s_szSubTestName:
263 db TMPL_MODE_STR, ', cvtss2si et al.', 0
264.s_szSse2Missing:
265 db 'SSE2 is missing', 0
266ENDPROC TMPL_NM(TestCvtSize)
267
268
269;;
270; Test what CMPXCHG with 32-bit operand size does to 64-bit registers,
271; as this is not particularly well documented by either Intel or AMD.
272;
273; @uses No registers, but BS2_SEL_SPARE0 is trashed.
274;
275BEGINPROC TMPL_NM(TestCmpxchg32)
276 push xBP
277 mov xBP, xSP
278 push sAX
279 push xBX
280 push xCX
281 push xDX
282 push xDI
283 push xSI
284 sub xSP, 80h ; iret stack frame space.
285 mov xSI, xSP ; Save the stack register.
286
287 mov xAX, .s_szSubTestName
288 call TMPL_NM_CMN(TestSub)
289
290%ifdef TMPL_64BIT
291
292 ;
293 ; CMPXCHG reg, reg - values not equal, eax written
294 ;
295 mov rax, -1 ; Load registers with 64-bit values
296 mov rbx, -2
297 mov rcx, -3
298 cmpxchg ebx, ecx ; Not equal, writes ebx to eax
299 mov edx, -2 ; Clears high dword
300 TEST_ASSERT_SIMPLE rax, rdx, jz, "CMPXCHG reg, unequal, rax set"
301 mov rdx, -2 ; All ones still in high dword
302 TEST_ASSERT_SIMPLE rbx, rdx, jz, "CMPXCHG reg, unequal, rbx not set"
303
304 ;
305 ; CMPXCHG reg, reg - values equal, first operand written
306 ;
307 mov rax, -4 ; Load registers with 64-bit values
308 mov rbx, -4
309 mov rcx, -5
310 cmpxchg ebx, ecx ; Equal, writes ecx to ebx
311 mov edx, -5 ; Clears high dword
312 TEST_ASSERT_SIMPLE rbx, rdx, jz, "CMPXCHG reg, equal, rbx set"
313 mov rdx, -4 ; All ones still in high dword
314 TEST_ASSERT_SIMPLE rax, rdx, jz, "CMPXCHG reg, equal, rax not set"
315
316 ;
317 ; CMPXCHG mem, reg - values not equal, eax written
318 ;
319 mov rax, -1 ; Load registers with 64-bit values
320 mov rbx, -2
321 push rbx
322 mov rcx, -3
323 cmpxchg [rsp], ecx ; Not equal, writes eax
324 mov edx, -2 ; Clears high dword
325 TEST_ASSERT_SIMPLE rax, rdx, jz, "CMPXCHG mem, unequal, rax set"
326 pop rbx
327
328 ;
329 ; CMPXCHG mem, reg - values equal, first operand written
330 ;
331 mov rax, -4 ; Load registers with 64-bit values
332 mov rbx, -4
333 push rbx
334 mov rcx, -5
335 cmpxchg [rsp], ecx ; Equal, writes ecx to memory
336 mov rdx, -4 ; All ones in high dword
337 TEST_ASSERT_SIMPLE rax, rdx, jz, "CMPXCHG mem, equal, rax not set"
338 pop rbx
339
340 ;
341 ; CMPXCHG8B mem, reg - values equal, memory written
342 ; compares edx:eax with mem64
343 ;
344 mov rdx, -1 ; Load registers with 64-bit values
345 mov rax, -4
346 mov rcx, -1
347 mov rbx, -5
348 mov rsi, -4
349 push rsi
350 cmpxchg8b [rsp] ; Equal, writes ecx:ebx to memory
351 mov rsi, -4 ; All ones in high dword
352 TEST_ASSERT_SIMPLE rax, rsi, jz, "CMPXCHG8B mem, equal, rax not set"
353 mov rsi, -1 ; All ones in high dword
354 TEST_ASSERT_SIMPLE rdx, rsi, jz, "CMPXCHG8B mem, equal, rdx not set"
355 pop rsi
356
357 ;
358 ; CMPXCHG8B mem, reg - values unequal, edx:eax written
359 ; compares edx:eax with mem64
360 ;
361 mov rdx, -1 ; Load registers with 64-bit values
362 mov rax, -2
363 mov rcx, -1
364 mov rbx, -4
365 mov rsi, -3
366 push rsi
367 cmpxchg8b [rsp] ; Not equal, writes memory to edx:eax
368 mov esi, -3 ; Clears high dword
369 TEST_ASSERT_SIMPLE rax, rsi, jz, "CMPXCHG8B mem, unequal, rax set"
370 mov esi, -1 ; Clears high dword
371 TEST_ASSERT_SIMPLE rdx, rsi, jz, "CMPXCHG8B mem, unequal, rdx set"
372 pop rsi
373
374%endif
375
376 ;
377 ; Done.
378 ;
379 call TMPL_NM_CMN(TestSubDone)
380.done:
381 mov xSP, xSI
382 add xSP, 80h
383 pop xSI
384 pop xDI
385 pop xDX
386 pop xCX
387 pop xBX
388 pop sAX
389 leave
390 ret
391
392.s_szSubTestName:
393 db TMPL_MODE_STR, ', 32-bit CMPXCHG in 64-bit mode', 0
394ENDPROC TMPL_NM(TestCmpxchg32)
395
396
397;;
398; Proving intel manual wrong about using REX.X for BSWAP R8-R15 on 64-bit.
399; Checking the 'undefined' 16-bit bswap behavior.
400;
401; @uses No registers, but BS2_SEL_SPARE0 is trashed.
402;
403BEGINPROC TMPL_NM(TestBSwap)
404 push xBP
405 mov xBP, xSP
406 push sAX
407 push xBX
408 push xCX
409 push xDX
410 push xDI
411 push xSI
412 sub xSP, 80h ; iret stack frame space.
413 mov xSI, xSP ; Save the stack register.
414
415 mov xAX, .s_szSubTestName
416 call TMPL_NM_CMN(TestSub)
417
418 ;
419 ; Assert sanity.
420 ;
421 mov eax, 11223344h
422 bswap eax
423 TEST_ASSERT_SIMPLE eax, 44332211h, jz, "32-bit BSWAP EAX"
424
425 ;
426 ; Buggy manual (325383-041US, December 2011).
427 ;
428%ifdef TMPL_64BIT
429 push r8
430
431 mov r8d, 55667788h
432 mov eax, 55667788h
433 db X86_OP_REX_X
434 bswap eax ; does it access r8 or eax?
435 TEST_ASSERT_SIMPLE eax, 88776655h, jz, "REX.X BSWAP EAX - Wrong EAX."
436 TEST_ASSERT_SIMPLE r8, 55667788h, jz, "REX.X BSWAP EAX - Wrong R8."
437
438 mov r8d, 55667788h
439 mov eax, 55667788h
440 db X86_OP_REX_R
441 bswap eax ; does it access r8 or eax?
442 TEST_ASSERT_SIMPLE eax, 88776655h, jz, "REX.R BSWAP EAX - Wrong EAX."
443 TEST_ASSERT_SIMPLE r8, 55667788h, jz, "REX.R BSWAP EAX - Wrong R8."
444
445 mov r8d, 55667788h
446 mov eax, 55667788h
447 db X86_OP_REX_B
448 bswap eax ; does it access r8 or eax?
449 TEST_ASSERT_SIMPLE rax, 55667788h, jz, "REX.B BSWAP R8D - Wrong RAX."
450 TEST_ASSERT_SIMPLE r8d, 88776655h, jz, "REX.B BSWAP R8D - Wrong R8D."
451
452 pop r8
453%endif
454
455 ;
456 ; 'Undefined' 16-bit behavior.
457 ;
458 ; Zeroing of the lower 16-bits has been observed on:
459 ; - Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz
460 ;
461%ifndef TestBSwap16_defined
462 %define TestBSwap16_defined
463 %macro TestBSwap16 3,
464 mov %3, %2 ; save the primary register.
465 %ifdef TMPL_64BIT
466 mov %2, 0ffffffff98765432h ; Set the upper bit as well.
467 %else
468 mov %2, 98765432h
469 %endif
470 %ifndef TMPL_16BIT
471 db X86_OP_PRF_SIZE_OP
472 %endif
473 bswap %1
474 xchg %2, %3 ; Restore and save the result (xSP).
475 TEST_ASSERT_SIMPLE %3, 98760000h, jz, "Unexpected 16-bit BSWAP error."
476 %endmacro
477%endif
478
479 TestBSwap16 eax, sAX, sSI
480 TestBSwap16 ebx, sBX, sSI
481 TestBSwap16 ecx, sCX, sSI
482 TestBSwap16 edx, sDX, sSI
483 TestBSwap16 esp, sSP, sSI
484 TestBSwap16 ebp, sBP, sSI
485 TestBSwap16 edi, sDI, sSI
486 TestBSwap16 esi, sSI, sDI
487%ifdef TMPL_64BIT
488 TestBSwap16 r8d, r8, rax
489 TestBSwap16 r9d, r9, rax
490 TestBSwap16 r10d, r10, rax
491 TestBSwap16 r11d, r11, rax
492 TestBSwap16 r12d, r12, rax
493 TestBSwap16 r13d, r13, rax
494 TestBSwap16 r14d, r14, rax
495 TestBSwap16 r15d, r15, rax
496%endif
497
498 ;
499 ; Done.
500 ;
501 call TMPL_NM_CMN(TestSubDone)
502.done:
503 mov xSP, xSI
504 add xSP, 80h
505 pop xSI
506 pop xDI
507 pop xDX
508 pop xCX
509 pop xBX
510 pop sAX
511 leave
512 ret
513
514.s_szSubTestName:
515 db TMPL_MODE_STR, ', bswap', 0
516ENDPROC TMPL_NM(TestBSwap)
517
518
519;;
520; Do the tests for this mode.
521;
522; @uses nothing
523;
524BEGINCODELOW
525BITS 16
526BEGINPROC TMPL_NM(DoTestsForMode_rm)
527 push bp
528 mov bp, sp
529 push ax
530
531 ;
532 ; Check if the mode and NX is supported, do the switch.
533 ;
534 call TMPL_NM(Bs2IsModeSupported_rm)
535 jz .done
536 call TMPL_NM(Bs2EnterMode_rm)
537BITS TMPL_BITS
538
539 ;
540 ; Test exception handler basics using INT3 and #BP.
541 ;
542
543 call TMPL_NM(TestMemFences)
544 call TMPL_NM(TestBSwap)
545%ifdef TMPL_64BIT
546 ; Specifically tests 64-bit behavior.
547 call TMPL_NM(TestCvtSize)
548 call TMPL_NM(TestCmpxchg32)
549%endif
550
551 ;
552 ; Back to real mode.
553 ;
554 call TMPL_NM(Bs2ExitMode)
555BITS 16
556 call Bs2DisableNX_r86
557
558.done:
559 pop ax
560 leave
561 ret
562ENDPROC TMPL_NM(DoTestsForMode_rm)
563TMPL_BEGINCODE
564BITS TMPL_BITS
565
566%include "bootsector2-template-footer.mac"
567
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