summaryrefslogtreecommitdiffstats
path: root/src/VBox/ValidationKit/utils/cpu/cidet.h
blob: 2273b7b0a4e5c5764f9a6f5af7228885c210b26a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
/* $Id: cidet.h $ */
/** @file
 * CPU Instruction Decoding & Execution Tests - C/C++ Header.
 */

/*
 * Copyright (C) 2014-2023 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
 * in the VirtualBox distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 *
 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
 */

#ifndef VBOX_INCLUDED_SRC_cpu_cidet_h
#define VBOX_INCLUDED_SRC_cpu_cidet_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include <iprt/types.h>
#include <iprt/x86.h>


/** @name CIDET - Operand flags.
 * @{ */
#define CIDET_OF_FIXED_MASK     UINT32_C(0x0000001f) /**< Fixed register/whatever mask. */

#define CIDET_OF_Z_SHIFT        8                    /**< Size shift. */
#define CIDET_OF_Z_MASK         UINT32_C(0x00000f00) /**< Size mask. */
#define CIDET_OF_Z_NONE         UINT32_C(0x00000000) /**< Unused zero value. */
#define CIDET_OF_Z_BYTE         UINT32_C(0x00000100) /**< Byte size. */
#define CIDET_OF_Z_WORD         UINT32_C(0x00000200) /**< Word (2 bytes) size. */
#define CIDET_OF_Z_DWORD        UINT32_C(0x00000300) /**< Double word (4 bytes) size. */
#define CIDET_OF_Z_QWORD        UINT32_C(0x00000400) /**< Quad word (8 bytes) size. */
#define CIDET_OF_Z_TBYTE        UINT32_C(0x00000500) /**< Ten byte (10 bytes) size - aka TWORD. */
#define CIDET_OF_Z_OWORD        UINT32_C(0x00000600) /**< Octa word (16 bytes) size - aka DQWORD. */
#define CIDET_OF_Z_YWORD        UINT32_C(0x00000700) /**< Yxx sized, i.e. 32 bytes. */
#define CIDET_OF_Z_ZWORD        UINT32_C(0x00000800) /**< Zxx sized, i.e. 64 bytes. */
#define CIDET_OF_Z_VAR_WDQ      UINT32_C(0x00000900) /**< Variable size depending on size prefix (2, 4, or 8 bytes). */
#define CIDET_OF_Z_SPECIAL      UINT32_C(0x00000f00) /**< Special size, see instruction flags or smth. */

#define CIDET_OF_K_MASK         UINT32_C(0x0000f000) /**< Kind of operand. */
#define CIDET_OF_K_NONE         UINT32_C(0x00000000) /**< Unused zero value. */
#define CIDET_OF_K_GPR          UINT32_C(0x00001000) /**< General purpose register. Includes memory when used with CIDET_OF_M_RM. */
#define CIDET_OF_K_SREG         UINT32_C(0x00002000) /**< Segment register. */
#define CIDET_OF_K_CR           UINT32_C(0x00003000) /**< Control register. */
#define CIDET_OF_K_SSE          UINT32_C(0x00004000) /**< SSE register. */
#define CIDET_OF_K_AVX          UINT32_C(0x00005000) /**< AVX register. */
#define CIDET_OF_K_AVX512       UINT32_C(0x00006000) /**< AVX-512 register. */
#define CIDET_OF_K_AVXFUTURE    UINT32_C(0x00007000) /**< Reserved for future AVX register set. */
#define CIDET_OF_K_VRX_TST_MASK UINT32_C(0x0000c000) /**< Used for testing for VRX register kind, see CIDET_OF_K_IS_VRX. */
#define CIDET_OF_K_VRX_TST_RES  UINT32_C(0x00004000) /**< Used for testing for VRX register kind, see CIDET_OF_K_IS_VRX. */
#define CIDET_OF_K_FPU          UINT32_C(0x00008000) /**< FPU register. */
#define CIDET_OF_K_MMX          UINT32_C(0x00009000) /**< MMX register. */
#define CIDET_OF_K_TEST         UINT32_C(0x0000a000) /**< Test register. */
#define CIDET_OF_K_IMM          UINT32_C(0x0000d000) /**< Immediate. */
#define CIDET_OF_K_MEM          UINT32_C(0x0000e000) /**< Memory. */
#define CIDET_OF_K_SPECIAL      UINT32_C(0x0000f000) /**< Special. */
/** Check if @a a_fOp is a general purpose register. */
#define CIDET_OF_K_IS_GPR(a_fOp)    ( ((a_fOp) & CIDET_OF_K_MASK) == CIDET_OF_K_GPR )
/** Check if @a a_fOp is a XMM (SSE), YMM (AVX), ZMM (AVX-512) or similar register. */
#define CIDET_OF_K_IS_VRX(a_fOp)    ( ((a_fOp) & CIDET_OF_K_VRX_TST_MASK) == CIDET_OF_K_VRX_TST_RES )
/** Check if @a a_fOp1 and @a a_fOp2 specify the same kind of register,
 * treating SSE, AVX, AVX-512 and AVX-future as the same kind and ignoring the
 * special register kind. */
#define CIDET_OF_K_IS_SAME(a_fOp1, a_fOp2) \
    (   ((a_fOp1) & CIDET_OF_K_MASK) == ((a_fOp2) & CIDET_OF_K_MASK) \
     ?  ((a_fOp1) & CIDET_OF_K_MASK) != CIDET_OF_K_SPECIAL \
     :  (CIDET_OF_K_IS_VRX(a_fOp1) && CIDET_OF_K_IS_VRX(a_fOp2)) )

#define CIDET_OF_M_RM_ONLY_R    UINT32_C(0x00010000)
#define CIDET_OF_M_RM_ONLY_M    UINT32_C(0x00020000)
#define CIDET_OF_M_RM           (CIDET_OF_M_RM_ONLY_R | CIDET_OF_M_RM_ONLY_M)
#define CIDET_OF_M_REG          UINT32_C(0x00040000)

#define CIDET_OF_A_R            UINT32_C(0x00080000) /**< Read access. */
#define CIDET_OF_A_W            UINT32_C(0x00100000) /**< Write access. */
#define CIDET_OF_A_RW           UINT32_C(0x00180000) /**< Read & write access. */

/** The operand defaults to 64-bit width in 64-bit mode, making 32-bit width
 * inaccessible. */
#define CIDET_OF_DEFAULT_64BIT  UINT32_C(0x40000000)
/** Operand always uses the ES segment for memory accesses. */
#define CIDET_OF_ALWAYS_SEG_ES  UINT32_C(0x80000000)
/** @} */


/** @name CIDET - Instruction flags.
 * @{ */
#define CIDET_IF_MODRM          RT_BIT_64(0)    /**< ModR/M encoded. */
#define CIDET_IF_PRIVILEGED     RT_BIT_64(1)    /**< Privileged. */
/** @} */


/**
 * Callback function for setting up the input and expected output CPU contexts.
 *
 * @returns VBox status code.
 * @retval  VINF_EOF when static test data wraps (first entry is returned).
 * @retval  VERR_NO_DATA if @a fInvalid is set and there are no invalid operand
 *          values for this instruction.
 * @retval  VERR_NOT_SUPPORTED if something in the setup prevents us from
 *          comming up with working set of inputs and outputs.
 *
 * @param   pThis           The core CIDET state structure.  The InCtx
 *                          and ExpectedCtx members will be modified.
 * @param   fInvalid        When set, get the next invalid operands that will
 *                          cause exceptions/faults.
 */
typedef DECLCALLBACKTYPE(int, FNCIDETSETUPINOUT,(struct CIDETCORE *pThis, bool fInvalid));
/** Pointer to a FNCIDETSETUPINOUT function. */
typedef FNCIDETSETUPINOUT *PFNCIDETSETUPINOUT;


/**
 * Instruction test descriptor.
 */
typedef struct CIDETINSTR
{
    /** The mnemonic (kind of). */
    const char         *pszMnemonic;
    /** Setup input and outputs. */
    PFNCIDETSETUPINOUT  pfnSetupInOut;
    /** Number of opcode bytes. */
    uint8_t             cbOpcode;
    /** Opcode byte(s). */
    uint8_t             abOpcode[3];
    /** Mandatory prefix (zero if not applicable). */
    uint8_t             bMandatoryPrefix;
    /** Number of operands. */
    uint8_t             cOperands;
    /** Operand flags. */
    uint32_t            afOperands[4];
    /** Flags. */
    uint64_t            fFlags;
} CIDETINSTR;
/** Pointer to an instruction test descriptor. */
typedef CIDETINSTR const *PCCIDETINSTR;


/**
 * CPU Context with a few extra bits for expectations and results.
 */
typedef struct CIDETCPUCTX
{
    uint64_t            rip;
    uint64_t            rfl;
    uint64_t            aGRegs[16];
    uint16_t            aSRegs[6];

#ifndef CIDET_REDUCED_CTX
    uint16_t            tr;
    uint16_t            ldtr;
    uint64_t            cr0;
#else
    uint16_t            au16Padding[2];
#endif
    uint64_t            cr2;
#ifndef CIDET_REDUCED_CTX
    uint64_t            cr3;
    uint64_t            cr4;
    uint64_t            cr8;
    uint64_t            dr0;
    uint64_t            dr1;
    uint64_t            dr2;
    uint64_t            dr3;
    uint64_t            dr6;
    uint64_t            dr7;
#endif

    uint64_t            uErr;           /**< Exception error code.  UINT64_MAX if not applicable.  (Not for input context.) */
    uint32_t            uXcpt;          /**< Exception number.  UINT32_MAX if no exception.  (Not for input context.) */

    uint32_t            fIgnoredRFlags; /**< Only for expected result. */
    bool                fTrickyStack;   /**< Set if the stack might be bad.  May come at the cost of accurate flags (32-bit). */
} CIDETCPUCTX;
typedef CIDETCPUCTX *PCIDETCPUCTX;
typedef CIDETCPUCTX const *PCCIDETCPUCTX;

/** Number of bytes of CIDETCPUCTX that can be compared quickly using memcmp.
 * Anything following these bytes are not relevant to the compare.  */
#define CIDETCPUCTX_COMPARE_SIZE    RT_UOFFSETOF(CIDETCPUCTX, fIgnoredRFlags)


/** @name CPU mode + bits + environment.
 * @{ */
#define CIDETMODE_BIT_MASK      UINT8_C(0x0e) /**< The instruction bit count. Results in byte size when masked. */
#define CIDETMODE_BIT_16        UINT8_C(0x02) /**< 16-bit instructions. */
#define CIDETMODE_BIT_32        UINT8_C(0x04) /**< 32-bit instructions. */
#define CIDETMODE_BIT_64        UINT8_C(0x08) /**< 64-bit instructions. */
#define CIDETMODE_MODE_MASK     UINT8_C(0x70) /**< CPU mode mask. */
#define CIDETMODE_MODE_RM       UINT8_C(0x00) /**< Real mode. */
#define CIDETMODE_MODE_PE       UINT8_C(0x10) /**< Protected mode without paging. */
#define CIDETMODE_MODE_PP       UINT8_C(0x20) /**< Paged protected mode. */
#define CIDETMODE_MODE_PAE      UINT8_C(0x30) /**< PAE protected mode (paged). */
#define CIDETMODE_MODE_LM       UINT8_C(0x40) /**< Long mode (paged). */
#define CIDETMODE_ENV_MASK      UINT8_C(0x81) /**< Execution environment. */
#define CIDETMODE_ENV_NORMAL    UINT8_C(0x01) /**< Normal environment. */
#define CIDETMODE_ENV_V86       UINT8_C(0x80) /**< V8086 environment. */
#define CIDETMODE_RM            (CIDETMODE_MODE_RM  | CIDETMODE_BIT_16 | CIDETMODE_ENV_NORMAL)
#define CIDETMODE_PE_16         (CIDETMODE_MODE_PE  | CIDETMODE_BIT_16 | CIDETMODE_ENV_NORMAL)
#define CIDETMODE_PE_32         (CIDETMODE_MODE_PE  | CIDETMODE_BIT_32 | CIDETMODE_ENV_NORMAL)
#define CIDETMODE_PE_V86        (CIDETMODE_MODE_PE  | CIDETMODE_BIT_16 | CIDETMODE_ENV_V86)
#define CIDETMODE_PP_16         (CIDETMODE_MODE_PP  | CIDETMODE_BIT_16 | CIDETMODE_ENV_NORMAL)
#define CIDETMODE_PP_32         (CIDETMODE_MODE_PP  | CIDETMODE_BIT_32 | CIDETMODE_ENV_NORMAL)
#define CIDETMODE_PP_V86        (CIDETMODE_MODE_PP  | CIDETMODE_BIT_16 | CIDETMODE_ENV_V86)
#define CIDETMODE_PAE_16        (CIDETMODE_MODE_PAE | CIDETMODE_BIT_16 | CIDETMODE_ENV_NORMAL)
#define CIDETMODE_PAE_32        (CIDETMODE_MODE_PAE | CIDETMODE_BIT_32 | CIDETMODE_ENV_NORMAL)
#define CIDETMODE_PAE_V86       (CIDETMODE_MODE_PAE | CIDETMODE_BIT_16 | CIDETMODE_ENV_V86)
#define CIDETMODE_LM_16         (CIDETMODE_MODE_LM  | CIDETMODE_BIT_16 | CIDETMODE_ENV_NORMAL)
#define CIDETMODE_LM_32         (CIDETMODE_MODE_LM  | CIDETMODE_BIT_32 | CIDETMODE_ENV_NORMAL)
#define CIDETMODE_LM_64         (CIDETMODE_MODE_LM  | CIDETMODE_BIT_64 | CIDETMODE_ENV_NORMAL)
/** Test if @a a_bMode is a 16-bit mode. */
#define CIDETMODE_IS_16BIT(a_bMode) ( ((a_bMode) & CIDETMODE_BIT_MASK) == CIDETMODE_BIT_16 )
/** Test if @a a_bMode is a 32-bit mode. */
#define CIDETMODE_IS_32BIT(a_bMode) ( ((a_bMode) & CIDETMODE_BIT_MASK) == CIDETMODE_BIT_32 )
/** Test if @a a_bMode is a 64-bit mode. */
#define CIDETMODE_IS_64BIT(a_bMode) ( ((a_bMode) & CIDETMODE_BIT_MASK) == CIDETMODE_BIT_64 )
/** Get the instruction bit count. */
#define CIDETMODE_GET_BIT_COUNT(a_bMode) ( CIDETMODE_GET_BYTE_COUNT(a_bMode) * 8 )
/** Get the instruction byte count. */
#define CIDETMODE_GET_BYTE_COUNT(a_bMode) ( (a_bMode) & CIDETMODE_BIT_MASK )
/** Test if @a a_bMode long mode. */
#define CIDETMODE_IS_LM(a_bMode) ( ((a_bMode) & CIDETMODE_MODE_MASK) == CIDETMODE_MODE_LM )
/** Test if @a a_bMode some kind of protected mode. */
#define CIDETMODE_IS_PROT(a_bMode) ( ((a_bMode) & CIDETMODE_MODE_MASK) >= CIDETMODE_MODE_PE )

/** @} */


/** @name Test Configuration Flags.
 * @{ */
#define CIDET_TESTCFG_SEG_PRF_CS            UINT64_C(0x0000000000000001)
#define CIDET_TESTCFG_SEG_PRF_SS            UINT64_C(0x0000000000000002)
#define CIDET_TESTCFG_SEG_PRF_DS            UINT64_C(0x0000000000000004)
#define CIDET_TESTCFG_SEG_PRF_ES            UINT64_C(0x0000000000000008)
#define CIDET_TESTCFG_SEG_PRF_FS            UINT64_C(0x0000000000000010)
#define CIDET_TESTCFG_SEG_PRF_GS            UINT64_C(0x0000000000000020)
#define CIDET_TESTCFG_SEG_PRF_MASK          UINT64_C(0x000000000000003f)
/** @} */

/** */
typedef enum CIDETREG
{
    kCidetReg_Gpr_Invalid = 0,

    kCidetReg_Gpr_al,
    kCidetReg_Gpr_cl,
    kCidetReg_Gpr_dl,
    kCidetReg_Gpr_bl,
    kCidetReg_Gpr_spl,
    kCidetReg_Gpr_bpl,
    kCidetReg_Gpr_sil,
    kCidetReg_Gpr_dil,
    kCidetReg_Gpr_r8b,
    kCidetReg_Gpr_r9b,
    kCidetReg_Gpr_r10b,
    kCidetReg_Gpr_r11b,
    kCidetReg_Gpr_r12b,
    kCidetReg_Gpr_r13b,
    kCidetReg_Gpr_r14b,
    kCidetReg_Gpr_r15b,
    kCidetReg_Gpr_ah,
    kCidetReg_Gpr_ch,
    kCidetReg_Gpr_dh,
    kCidetReg_Gpr_bh,
#define kCidetReg_Gpr_Byte_First                    kCidetReg_Gpr_al
#define kCidetReg_Gpr_Byte_First_Upper              kCidetReg_Gpr_ah
#define kCidetReg_Gpr_Byte_Last                     kCidetReg_Gpr_bh

    kCidetReg_Gpr_ax,
    kCidetReg_Gpr_cx,
    kCidetReg_Gpr_dx,
    kCidetReg_Gpr_bx,
    kCidetReg_Gpr_sp,
    kCidetReg_Gpr_bp,
    kCidetReg_Gpr_si,
    kCidetReg_Gpr_di,
    kCidetReg_Gpr_r8w,
    kCidetReg_Gpr_r9w,
    kCidetReg_Gpr_r10w,
    kCidetReg_Gpr_r11w,
    kCidetReg_Gpr_r12w,
    kCidetReg_Gpr_r13w,
    kCidetReg_Gpr_r14w,
    kCidetReg_Gpr_r15w,
#define kCidetReg_Gpr_Word_First                    kCidetReg_Gpr_ax
#define kCidetReg_Gpr_Word_Last                     kCidetReg_Gpr_r15w

    kCidetReg_Gpr_eax,
    kCidetReg_Gpr_ecx,
    kCidetReg_Gpr_edx,
    kCidetReg_Gpr_ebx,
    kCidetReg_Gpr_esp,
    kCidetReg_Gpr_ebp,
    kCidetReg_Gpr_esi,
    kCidetReg_Gpr_edi,
    kCidetReg_Gpr_r8d,
    kCidetReg_Gpr_r9d,
    kCidetReg_Gpr_r10d,
    kCidetReg_Gpr_r11d,
    kCidetReg_Gpr_r12d,
    kCidetReg_Gpr_r13d,
    kCidetReg_Gpr_r14d,
    kCidetReg_Gpr_r15d,
#define kCidetReg_Gpr_DWord_First                    kCidetReg_Gpr_eax
#define kCidetReg_Gpr_DWord_Last                     kCidetReg_Gpr_r15d

    kCidetReg_Gpr_rax,
    kCidetReg_Gpr_rcx,
    kCidetReg_Gpr_rdx,
    kCidetReg_Gpr_rbx,
    kCidetReg_Gpr_rsp,
    kCidetReg_Gpr_rbp,
    kCidetReg_Gpr_rsi,
    kCidetReg_Gpr_rdi,
    kCidetReg_Gpr_r8,
    kCidetReg_Gpr_r9,
    kCidetReg_Gpr_r10,
    kCidetReg_Gpr_r11,
    kCidetReg_Gpr_r12,
    kCidetReg_Gpr_r13,
    kCidetReg_Gpr_r14,
    kCidetReg_Gpr_r15,
#define kCidetReg_Gpr_QWord_First                    kCidetReg_Gpr_rax
#define kCidetReg_Gpr_QWord_Last                     kCidetReg_Gpr_r15

    kCidetReg_Seg_es,
    kCidetReg_Seg_cs,
    kCidetReg_Seg_ss,
    kCidetReg_Seg_ds,
    kCidetReg_Seg_fs,
    kCidetReg_Seg_gs,
    kCidetReg_Seg_Inv6,
    kCidetReg_Seg_Inv7,
#define kCidetReg_Seg_First                         kCidetReg_Seg_es
#define kCidetReg_Seg_Last                          kCidetReg_Seg_gs
#define kCidetReg_Seg_Last_Inv                      kCidetReg_Seg_Inv7

    kCidetReg_Misc_ip,
    kCidetReg_Misc_eip,
    kCidetReg_Misc_rip,
    kCidetReg_Misc_flags,
    kCidetReg_Misc_eflags,
    kCidetReg_Misc_rflags,
    kCidetReg_Misc_tr,
    kCidetReg_Misc_ldtr,
    kCidetReg_Misc_gdtr,
    kCidetReg_Misc_idtr,

    kCidetReg_Ctrl_cr0,
    kCidetReg_Ctrl_cr1,
    kCidetReg_Ctrl_cr2,
    kCidetReg_Ctrl_cr3,
    kCidetReg_Ctrl_cr4,
    kCidetReg_Ctrl_cr5,
    kCidetReg_Ctrl_cr6,
    kCidetReg_Ctrl_cr7,
    kCidetReg_Ctrl_cr8,
    kCidetReg_Ctrl_cr9,
    kCidetReg_Ctrl_cr10,
    kCidetReg_Ctrl_cr11,
    kCidetReg_Ctrl_cr12,
    kCidetReg_Ctrl_cr13,
    kCidetReg_Ctrl_cr14,
    kCidetReg_Ctrl_cr15,
#define kCidetReg_Ctrl_First                        kCidetReg_Ctrl_cr0
#define kCidetReg_Ctrl_Last                         kCidetReg_Ctrl_cr15
#define CIDETREG_CTRL_IS_VALID(a_iReg) (   (a_iReg) == kCidetReg_Ctrl_cr0 \
                                        && (a_iReg) == kCidetReg_Ctrl_cr2 \
                                        && (a_iReg) == kCidetReg_Ctrl_cr3 \
                                        && (a_iReg) == kCidetReg_Ctrl_cr4 \
                                        && (a_iReg) == kCidetReg_Ctrl_cr8 )

    kCidetReg_Dbg_dr0,
    kCidetReg_Dbg_dr1,
    kCidetReg_Dbg_dr2,
    kCidetReg_Dbg_dr3,
    kCidetReg_Dbg_dr4,
    kCidetReg_Dbg_dr5,
    kCidetReg_Dbg_dr6,
    kCidetReg_Dbg_dr7,
    kCidetReg_Dbg_dr8,
    kCidetReg_Dbg_dr9,
    kCidetReg_Dbg_dr10,
    kCidetReg_Dbg_dr11,
    kCidetReg_Dbg_dr12,
    kCidetReg_Dbg_dr13,
    kCidetReg_Dbg_dr14,
    kCidetReg_Dbg_dr15,
#define kCidetReg_Dbg_First                         kCidetReg_Dbg_dr0
#define kCidetReg_Dbg_Last                          kCidetReg_Dbg_dr15
#define CIDETREG_DBG_IS_VALID(a_iReg) ((a_iReg) < kCidetReg_Dbg_dr8 && (a_iReg) >= kCidetReg_Dbg_First)

    kCidetReg_Test_tr0,
    kCidetReg_Test_tr1,
    kCidetReg_Test_tr2,
    kCidetReg_Test_tr3,
    kCidetReg_Test_tr4,
    kCidetReg_Test_tr5,
    kCidetReg_Test_tr6,
    kCidetReg_Test_tr7,
    kCidetReg_Test_tr8,
    kCidetReg_Test_tr9,
    kCidetReg_Test_tr10,
    kCidetReg_Test_tr11,
    kCidetReg_Test_tr12,
    kCidetReg_Test_tr13,
    kCidetReg_Test_tr14,
    kCidetReg_Test_tr15,
#define kCidetReg_Test_First                        kCidetReg_Test_tr0
#define kCidetReg_Test_Last                         kCidetReg_Test_tr15

    kCidetReg_Fpu_st0,
    kCidetReg_Fpu_st1,
    kCidetReg_Fpu_st2,
    kCidetReg_Fpu_st3,
    kCidetReg_Fpu_st4,
    kCidetReg_Fpu_st5,
    kCidetReg_Fpu_st6,
    kCidetReg_Fpu_st7,
#define kCidetReg_Fpu_First                         kCidetReg_Mmx_st0
#define kCidetReg_Fpu_Last                          kCidetReg_Mmx_st7

    kCidetReg_FpuMisc_cs,
    kCidetReg_FpuMisc_ip,
    kCidetReg_FpuMisc_ds,
    kCidetReg_FpuMisc_dp,
    kCidetReg_FpuMisc_fop,
    kCidetReg_FpuMisc_ftw,
    kCidetReg_FpuMisc_fsw,
    kCidetReg_FpuMisc_fcw,
    kCidetReg_FpuMisc_mxcsr_mask,
    kCidetReg_FpuMisc_mxcsr,

    kCidetReg_Mmx_mm0,
    kCidetReg_Mmx_mm1,
    kCidetReg_Mmx_mm2,
    kCidetReg_Mmx_mm3,
    kCidetReg_Mmx_mm4,
    kCidetReg_Mmx_mm5,
    kCidetReg_Mmx_mm6,
    kCidetReg_Mmx_mm7,
#define kCidetReg_Mmx_First                         kCidetReg_Mmx_mm0
#define kCidetReg_Mmx_Last                          kCidetReg_Mmx_mm7

    kCidetReg_Sse_xmm0,
    kCidetReg_Sse_xmm1,
    kCidetReg_Sse_xmm2,
    kCidetReg_Sse_xmm3,
    kCidetReg_Sse_xmm4,
    kCidetReg_Sse_xmm5,
    kCidetReg_Sse_xmm6,
    kCidetReg_Sse_xmm7,
    kCidetReg_Sse_xmm8,
    kCidetReg_Sse_xmm9,
    kCidetReg_Sse_xmm10,
    kCidetReg_Sse_xmm11,
    kCidetReg_Sse_xmm12,
    kCidetReg_Sse_xmm13,
    kCidetReg_Sse_xmm14,
    kCidetReg_Sse_xmm15,
    kCidetReg_Sse_xmm16,
    kCidetReg_Sse_xmm17,
    kCidetReg_Sse_xmm18,
    kCidetReg_Sse_xmm19,
    kCidetReg_Sse_xmm20,
    kCidetReg_Sse_xmm21,
    kCidetReg_Sse_xmm22,
    kCidetReg_Sse_xmm23,
    kCidetReg_Sse_xmm24,
    kCidetReg_Sse_xmm25,
    kCidetReg_Sse_xmm26,
    kCidetReg_Sse_xmm27,
    kCidetReg_Sse_xmm28,
    kCidetReg_Sse_xmm29,
    kCidetReg_Sse_xmm30,
    kCidetReg_Sse_xmm31,
#define kCidetReg_Sse_First                         kCidetReg_Mmx_Xmm0
#define kCidetReg_Sse_Last                          kCidetReg_Mmx_Xmm15
#define kCidetReg_Sse_Last_Avx512                   kCidetReg_Mmx_Xmm31

    kCidetReg_Avx_Ymm0,
    kCidetReg_Avx_Ymm1,
    kCidetReg_Avx_Ymm2,
    kCidetReg_Avx_Ymm3,
    kCidetReg_Avx_Ymm4,
    kCidetReg_Avx_Ymm5,
    kCidetReg_Avx_Ymm6,
    kCidetReg_Avx_Ymm7,
    kCidetReg_Avx_Ymm8,
    kCidetReg_Avx_Ymm9,
    kCidetReg_Avx_Ymm10,
    kCidetReg_Avx_Ymm11,
    kCidetReg_Avx_Ymm12,
    kCidetReg_Avx_Ymm13,
    kCidetReg_Avx_Ymm14,
    kCidetReg_Avx_Ymm15,
    kCidetReg_Avx_Ymm16,
    kCidetReg_Avx_Ymm17,
    kCidetReg_Avx_Ymm18,
    kCidetReg_Avx_Ymm19,
    kCidetReg_Avx_Ymm20,
    kCidetReg_Avx_Ymm21,
    kCidetReg_Avx_Ymm22,
    kCidetReg_Avx_Ymm23,
    kCidetReg_Avx_Ymm24,
    kCidetReg_Avx_Ymm25,
    kCidetReg_Avx_Ymm26,
    kCidetReg_Avx_Ymm27,
    kCidetReg_Avx_Ymm28,
    kCidetReg_Avx_Ymm29,
    kCidetReg_Avx_Ymm30,
    kCidetReg_Avx_Ymm31,
#define kCidetReg_Avx_First                         kCidetReg_Avx_Ymm0
#define kCidetReg_Avx_Last                          kCidetReg_Avx_Ymm15
#define kCidetReg_Avx_Last_Avx512                   kCidetReg_Avx_Ymm31

    kCidetReg_Avx512_Zmm0,
    kCidetReg_Avx512_Zmm1,
    kCidetReg_Avx512_Zmm2,
    kCidetReg_Avx512_Zmm3,
    kCidetReg_Avx512_Zmm4,
    kCidetReg_Avx512_Zmm5,
    kCidetReg_Avx512_Zmm6,
    kCidetReg_Avx512_Zmm7,
    kCidetReg_Avx512_Zmm8,
    kCidetReg_Avx512_Zmm9,
    kCidetReg_Avx512_Zmm10,
    kCidetReg_Avx512_Zmm11,
    kCidetReg_Avx512_Zmm12,
    kCidetReg_Avx512_Zmm13,
    kCidetReg_Avx512_Zmm14,
    kCidetReg_Avx512_Zmm15,
    kCidetReg_Avx512_Zmm16,
    kCidetReg_Avx512_Zmm17,
    kCidetReg_Avx512_Zmm18,
    kCidetReg_Avx512_Zmm19,
    kCidetReg_Avx512_Zmm20,
    kCidetReg_Avx512_Zmm21,
    kCidetReg_Avx512_Zmm22,
    kCidetReg_Avx512_Zmm23,
    kCidetReg_Avx512_Zmm24,
    kCidetReg_Avx512_Zmm25,
    kCidetReg_Avx512_Zmm26,
    kCidetReg_Avx512_Zmm27,
    kCidetReg_Avx512_Zmm28,
    kCidetReg_Avx512_Zmm29,
    kCidetReg_Avx512_Zmm30,
    kCidetReg_Avx512_Zmm31,
#define kCidetReg_Avx512_First                      kCidetReg_Avx512_Zmm0
#define kCidetReg_Avx512_Last                       kCidetReg_Avx512_Zmm31

    kCidetReg_End
} CIDETREG;


/** @name CIDETBUF_XXX - buffer flags.
 * @{ */
#define CIDETBUF_PROT_MASK          UINT32_C(0x0000000f) /**< Page protection mask. */
#define CIDETBUF_PROT_RWX           UINT32_C(0x00000001) /**< Read + write + execute. */
#define CIDETBUF_PROT_RWNX          UINT32_C(0x00000002) /**< Read + write + no execute. */
#define CIDETBUF_PROT_RX            UINT32_C(0x00000003) /**< Read + execute. */
#define CIDETBUF_PROT_RNX           UINT32_C(0x00000004) /**< Read + no execute. */
#define CIDETBUF_PROT_RWX_1NP       UINT32_C(0x00000005) /**< Read + write + execute; 1 page not present. */
#define CIDETBUF_PROT_RWX_1RWNX     UINT32_C(0x00000006) /**< Read + write + execute; 1 page read + write + no execute. */
#define CIDETBUF_PROT_RWX_1RNX      UINT32_C(0x00000007) /**< Read + write + execute; 1 page read + no execute. */
#define CIDETBUF_PROT_RWX_1RWXS     UINT32_C(0x00000008) /**< Read + write + execute; 1 page read + execute + supervisor. */

#define CIDETBUF_LOC_MASK           UINT32_C(0x000000f0) /**< Location mask. */
/** Buffer located at top and start of the 32-bit address space. */
#define CIDETBUF_LOC_32BIT_WRAP     UINT32_C(0x00000010)
/** Buffer located at the low canonical boundrary (AMD64).   */
#define CIDETBUF_LOC_CANON_LO       UINT32_C(0x00000020)
/** Buffer located at the high canonical boundrary (AMD64).   */
#define CIDETBUF_LOC_CANON_HI       UINT32_C(0x00000030)

/** Segment protection mask. */
#define CIDETBUF_SEG_MASK           UINT32_C(0x00000f00)
#define CIDETBUF_SEG_EO             UINT32_C(0x00000100) /**< Execute only */
#define CIDETBUF_SEG_ER             UINT32_C(0x00000200) /**< Execute + read */
#define CIDETBUF_SEG_EO_CONF        UINT32_C(0x00000300) /**< Execute only + conforming. */
#define CIDETBUF_SEG_ER_CONF        UINT32_C(0x00000400) /**< Execute + read + conforming. */
#define CIDETBUF_SEG_RO             UINT32_C(0x00000500) /**< Read only. */
#define CIDETBUF_SEG_RW             UINT32_C(0x00000600) /**< Read + write. */
#define CIDETBUF_SEG_RO_DOWN        UINT32_C(0x00000700) /**< Read only + expand down. */
#define CIDETBUF_SEG_RW_DOWN        UINT32_C(0x00000800) /**< Read + write + expand down. */

#define CIDETBUF_DPL_MASK           UINT32_C(0x00003000) /**< DPL mask. */
#define CIDETBUF_DPL_0              UINT32_C(0x00000000) /**< DPL=0. */
#define CIDETBUF_DPL_1              UINT32_C(0x00001000) /**< DPL=1. */
#define CIDETBUF_DPL_2              UINT32_C(0x00002000) /**< DPL=2. */
#define CIDETBUF_DPL_3              UINT32_C(0x00003000) /**< DPL=3. */
#define CIDETBUF_DPL_SAME           UINT32_C(0x00004000) /**< Same DPL as the execution environment. */

#define CIDETBUF_SEG_LIMIT_BASE_CAP UINT32_C(0x00008000) /**< Capability to change segment limit and base. */

#define CIDETBUF_KIND_DATA          UINT32_C(0x00000000) /**< Data buffer. */
#define CIDETBUF_KIND_CODE          UINT32_C(0x80000000) /**< Code buffer. */
/** Checks if @a a_fFlags describes a code buffer. */
#define CIDETBUF_IS_CODE(a_fFlags)  (((a_fFlags) & CIDETBUF_KIND_CODE) != 0)
/** Checks if @a a_fFlags describes a data buffer. */
#define CIDETBUF_IS_DATA(a_fFlags)  (((a_fFlags) & CIDETBUF_KIND_CODE) == 0)
/** @} */

/** Code buffer size.  (At least two pages.) */
#define CIDET_CODE_BUF_SIZE         (PAGE_SIZE * 2)
/** Data buffer size.  (At least two pages.) */
#define CIDET_DATA_BUF_SIZE         (PAGE_SIZE * 3)


/**
 * Detailed expected exception.
 *
 * This is used to internally in the core to calculate the expected exception
 * considering all the things that may cause exceptions.
 */
typedef enum CIDETEXPECTXCPT
{
    kCidetExpectXcpt_Invalid = 0,
    /** No exception expected.   */
    kCidetExpectXcpt_None,

    /** Page not present. */
    kCidetExpectXcpt_PageNotPresent,
    /** Write access to a non-writable page. */
    kCidetExpectXcpt_PageNotWritable,
    /** Executable access to a non-executable page. */
    kCidetExpectXcpt_PageNotExecutable,
    /** Access to supervisor page from user mode code. */
    kCidetExpectXcpt_PagePrivileged,
#define kCidetExpectXcpt_First_PageFault                kCidetExpectXcpt_PageNotPresent
#define kCidetExpectXcpt_Last_PageFault                 kCidetExpectXcpt_PagePrivileged

    /** Read or write access to an execute only segment. */
    kCidetExpectXcpt_SegExecuteOnly,
    /** Write to a read only or execute+read segment. */
    kCidetExpectXcpt_SegNotWritable,
    /** Exceeded the limit of a non-stack access. */
    kCidetExpectXcpt_SegExceededLimit,
    /** Non-canonical address via any segment other than the stack. */
    kCidetExpectXcpt_AddrNotCanonical,
    /** Misaligned 16 or 32 byte SSE or AVX operand. */
    kCidetExpectXcpt_MisalignedSseAvx,
    /** Privileged instruction. */
    kCidetExpectXcpt_PrivilegedInstruction,
#define kCidetExpectXcpt_First_GeneralProtectionFault   kCidetExpectXcpt_SegExecuteOnly
#define kCidetExpectXcpt_Last_GeneralProtectionFault    kCidetExpectXcpt_PrivilegedInstruction

    /** Exceeded the limit of a stack access. */
    kCidetExpectXcpt_StackExceededLimit,
    /** Non-canonical stack address. */
    kCidetExpectXcpt_StackAddrNotCanonical,
#define kCidetExpectXcpt_First_StackFault               kCidetExpectXcpt_StackExceededLimit
#define kCidetExpectXcpt_Last_StackFault                kCidetExpectXcpt_StackAddrNotCanonical

    /** Misaligned memory operand (and alignment checking is in effect) if AC is
     * enabled (executing in ring-3). */
    kCidetExpectXcpt_MisalignedIfAcEnabled,
    /** Misaligned 16 byte memory operand resulting in \#AC if ring-3 and
     *  enable, otherwise \#GP(0). */
    kCidetExpectXcpt_Misaligned16ByteAcEnabledOrGp,
#define kCidetExpectXcpt_First_AlignmentCheckFault      kCidetExpectXcpt_MisalignedIfAcEnabled
#define kCidetExpectXcpt_Last_AlignmentCheckFault       kCidetExpectXcpt_Misaligned16ByteAcEnabledOrGp

    kCidetExpectXcpt_End
} CIDETEXPECTXCPT;


/**
 * Buffer configuration.
 */
typedef struct CIDETBUFCFG
{
    /** The name of this buffer configuration. */
    const char *pszName;
    /** The buffer flags (CIDETBUF_XXX) */
    uint32_t    fFlags;
} CIDETBUFCFG;
/** Pointer to a constant buffer configuration. */
typedef CIDETBUFCFG const *PCCIDETBUFCFG;


/**
 * CIDET buffer for code or data.
 *
 * ASSUMES page aligned buffers.
 */
typedef struct CIDETBUF
{
    /** @name Owned & modified by the front end.
     * @{ */
    /** Effective buffer address. */
    uint64_t        uEffBufAddr;
    /** The segment base address. */
    uint64_t        uSegBase;
    /** The active segment limit (see also cbSegLimit). UINT64_MAX if flat. */
    uint64_t        cbActiveSegLimit;
    /** This specifies the selector to use if a non-flat segment limit or special
     * segment flags was requested via pfnSetupBuf.  UINT32_MAX if any segment is
     * selector works. */
    uint32_t        uSeg;
    /** The off value at the last pfnReinitBuf call.  */
    uint16_t        offActive;
    /** The cb value at the last pfnReinitBuf call.  */
    uint16_t        cbActive;
    /** Prologue (or front fence) size. */
    uint16_t        cbPrologue;
    /** Epilogue (or tail fence) size. */
    uint16_t        cbEpilogue;
    /** @} */

    /** @name Set by the core before pfnReinitBuf call.
     * @{ */
    /** Pointer to the buffer config. */
    PCCIDETBUFCFG   pCfg;
    /** The configuration index. */
    uint32_t        idxCfg;
    /** The offset into the buffer of the data / code. */
    uint16_t        off;
    /** The number of bytes of data / code. */
    uint16_t        cb;
    /** The segment limit relative to the start of the buffer (last byte included
     *  in count). UINT16_MAX if maximum segment size should be used. */
    uint16_t        cbSegLimit;
    /** Desired segment base offset.
     * This is for checking where the alignment checks are performed. */
    uint8_t         offSegBase;

    /** Set if this buffer is actively being used. */
    bool            fActive : 1;
    /** The operand index (if data), 7 if not active. */
    uint8_t         idxOp : 3;
    /** Code: Set if the expected exception is supposed to occur on the
     * following insturction, not the instruction unter test. */
    bool            fXcptAfterInstruction : 1;
    /** Set if the instruction will read from the buffer. */
    bool            fRead : 1;
    /** Set if the instruction will write to the buffer. */
    bool            fWrite : 1;
    /** The expected exception. */
    CIDETEXPECTXCPT enmExpectXcpt;
    /** @} */
} CIDETBUF;
/** Pointer to a CIDET buffer for code or data. */
typedef CIDETBUF *PCIDETBUF;


/**
 * CPU Instruction Decoding & Execution Testing (CIDET) state.
 */
typedef struct CIDETCORE
{
    /** Magic number (CIDETCORE_MAGIC).  */
    uint32_t            u32Magic;

    /** The target CPU mode / environment. */
    uint8_t             bMode;
    /** The target ring. */
    uint8_t             iRing;
    /** Unused padding bytes.  */
    uint8_t             abPadding1[2];

    /** Test configuration. */
    uint64_t            fTestCfg;

    /** Code buffer configurations to test.
     * The first buffer must be a normal buffer that does not cause any problems. */
    PCCIDETBUFCFG       paCodeBufConfigs;
    /** The number of code buffer configurations to test (pafCodeBufConfigs). */
    uint32_t            cCodeBufConfigs;
    /** The number of data buffer configurations to test (pafDataBufConfigs). */
    uint32_t            cDataBufConfigs;
    /** Data buffer configurations to test.
     * The first buffer must be a normal buffer that does not cause any problems. */
    PCCIDETBUFCFG       paDataBufConfigs;

    /** The instruction currently under testing. */
    PCCIDETINSTR        pCurInstr;

    /** Primary data buffer. */
    CIDETBUF            DataBuf;
    /** Secondary data buffer. */
    CIDETBUF            DataBuf2;

    /** Handle to the random number source. */
    RTRAND              hRand;

    /**
     * Re-initializes one of the data buffers.
     *
     * @returns true on succes, false if the request cannot be satisfied.
     * @param   pThis           The core state.
     * @param   pBuf            Pointer to the buffer structure.
     */
    DECLCALLBACKMEMBER(bool, pfnReInitDataBuf,(struct CIDETCORE *pThis, PCIDETBUF pBuf));

    /**
     * Copies bytes into the data buffer and sets it up for execution.
     *
     * @returns true on succes, false if the request cannot be satisfied.
     * @param   pThis           The core state.
     * @param   pBuf            Pointer to the buffer structure.
     * @param   pvSrc           The source bytes (size and destination offset
     *                          given in pfnReinitBuf call).
     */
    DECLCALLBACKMEMBER(bool, pfnSetupDataBuf,(struct CIDETCORE *pThis, PCIDETBUF pBuf, void const *pvSrc));

    /**
     * Compares buffer content after test execution.
     *
     * This also checks any fill bytes in the buffer that the front end may
     * have put up.  The front end will double buffer the content of supposedly
     * inaccessible pages as well as non-existing pages to simplify things for
     * the core code.
     *
     * @returns true if equal, false if not.
     * @param   pThis           The core state.
     * @param   pBuf            Pointer to the buffer structure.
     * @param   pvExpected      Pointer to the expected source bytes (size and
     *                          buffer offset given in pfnReinitBuf call).
     */
    DECLCALLBACKMEMBER(bool, pfnIsBufEqual,(struct CIDETCORE *pThis, struct CIDETBUF *pBuf, void const *pvExpected));

    /**
     * Re-initializes the code buffer.
     *
     * @returns true on succes, false if the request cannot be satisfied.
     * @param   pThis           The core state.
     * @param   pBuf            Pointer to the CodeBuf member.  The off and cb
     *                          members represent what the core wants to
     *                          execute.
     */
    DECLCALLBACKMEMBER(bool, pfnReInitCodeBuf,(struct CIDETCORE *pThis, PCIDETBUF pBuf));

    /**
     * Emit code into the code buffer, making everything ready for pfnExecute.
     *
     * @returns VBox status code.
     * @param   pThis           Pointer to the core structure.
     * @param   pBuf            Pointer to the CodeBuf member.
     * @param   pvInstr         Pointer to the encoded instruction bytes.
     */
    DECLCALLBACKMEMBER(bool, pfnSetupCodeBuf,(struct CIDETCORE *pThis, PCIDETBUF pBuf, void const *pvInstr));

    /**
     * Executes the code indicated by InCtx, returning the result in ActualCtx.
     *
     * @returns true if execute, false if skipped.
     * @param   pThis           Pointer to the core structure.
     */
    DECLCALLBACKMEMBER(bool, pfnExecute,(struct CIDETCORE *pThis));

    /**
     * Report a test failure.
     *
     * @param   pThis           Pointer to the core structure.
     * @param   pszFormat       Format string containing failure details.
     * @param   va              Arguments referenced in @a pszFormat.
     */
    DECLCALLBACKMEMBER(void, pfnFailure,(struct CIDETCORE *pThis, const char *pszFormat, va_list va));

    /** Array of indexes for use by FNCIDETSETUPINOUT.
     * Reset when changing instruction or switching between valid and invalid
     * inputs. */
    uint32_t            aiInOut[4];

    /** @name Copyied and extracted instruction information.
     * @{ */
    /** The flags (CIDET_OF_XXX) for the MODRM.REG operand, 0 if not applicable. */
    uint32_t            fMrmRegOp;
    /** The flags (CIDET_OF_XXX) for the MODRM.RM operand, 0 if not applicable. */
    uint32_t            fMrmRmOp;
    /** Instruction flags (CIDETINSTR::fFlags). */
    uint64_t            fInstrFlags;
    /** Number of operands (CIDETINSTR::cOperands). */
    uint8_t             cOperands;
    /** Number of memory operands (set by CidetCoreSetupFirstMemoryOperandConfig). */
    uint8_t             cMemoryOperands : 3;
    /** Set if we're working on a MOD R/M byte. */
    bool                fUsesModRm : 1;
    /** The index of the MODRM.REG operand, 7 if not applicable. */
    uint8_t             idxMrmRegOp : 3;
    /** The index of the MODRM.RM operand, 7 if not applicable. */
    uint8_t             idxMrmRmOp : 3;
    /** Set if the SIB byte uses VEX registers for indexing. */
    bool                fUsesVexIndexRegs : 1;
    /** @}  */

    /** @name Basic encoding knobs, wheels and indicators.
     * @{ */
    /** Set if we're working on a SIB byte. */
    bool                fSib : 1;
    /** Required segment prefix (X86_SREG_XXX), X86_SREG_COUNT if not. */
    uint8_t             uSegPrf : 3;
    /** The address size prefix. */
    bool                fAddrSizePrf : 1;
    /** The operand size prefix. */
    bool                fOpSizePrf : 1;
    /** The REX.W prefix value. */
    bool                fRexW : 1;
    /** The REX.R prefix value. */
    bool                fRexR : 1;
    /** The REX.X prefix value. */
    bool                fRexX : 1;
    /** The REX.B prefix value. */
    bool                fRexB : 1;
    /** Set if a REX prefix is required with or without flags (for byte regs). */
    bool                fRex : 1;
    /** Use VEX encoding. */
    bool                fVex : 1;
    /** Use EVEX encoding. */
    bool                fEvex : 1;
    /** Indicator: Effective addressing mode in bytes (2, 4, 8). */
    uint8_t             cbAddrMode : 4;
    /** Indicator: Set if there is an operand accessing memory. */
    bool                fHasMemoryOperand : 1;
    /** Indicator: Set if a register is used in two or more operands, and one of
     * them being for addressing. */
    bool                fHasRegCollisionMem : 1;
    /** Indicator: Helper indicator for tracking SIB.BASE collision. */
    bool                fHasRegCollisionMemBase : 1;
    /** Indicator: Helper indicator for tracking SIB.INDEX collision. */
    bool                fHasRegCollisionMemIndex : 1;
    /** Indicator: Set if a register is used directly in more than one operand. */
    bool                fHasRegCollisionDirect : 1;

    /** Indicator: Set if MODRM.REG is the stack register. */
    bool                fHasStackRegInMrmReg : 1;
    /** Indicator: Set if MODRM.RM or SIB.BASE is the stack register. */
    bool                fHasStackRegInMrmRmBase: 1;

    /** Indicator: High byte-register specified by MODRM.REG. */
    bool                fHasHighByteRegInMrmReg : 1;
    /** Indicator: High byte-register specified by MODRM.RM. */
    bool                fHasHighByteRegInMrmRm : 1;
    /** Indicator: Set if REX prefixes are incompatible with the byte-register
     * specified by MODRM.REG. */
    bool                fNoRexPrefixMrmReg : 1;
    /** Indicator: Set if REX prefixes are incompatible with the byte-register
     * specified by MODRM.RM. */
    bool                fNoRexPrefixMrmRm : 1;
    /** Indicator: fNoRexPrefixMrmReg || fNoRexPrefixMrmMr. */
    bool                fNoRexPrefix : 1;
    /** The MOD R/M byte we're working on (if fUsesModRm is set). */
    uint8_t             bModRm;
    /** The SIB/VSIB byte we're working on (if fSib is set). */
    uint8_t             bSib;
    /** @} */

    /** The effective instruction address.  (See InCtx.rip and InCtx.cs for the
     * rest of the instruction addressing stuff.) */
    uint64_t            uInstrEffAddr;

    /** Operand information, mainly for the FNCIDETSETUPINOUT and similar. */
    struct
    {
        /** The operand flags copied from (CIDETINSTR::afOperands).   */
        uint32_t        fFlags;
        /** The encoded register number, if register, UINT8_MAX if not.  */
        uint8_t         iReg;
        /** The actual operand size (encoded). */
        uint8_t         cb;
        /** Set if immediate value. */
        bool            fIsImmediate : 1;
        /** Set if memory access. */
        bool            fIsMem : 1;
        /** Set if addressing is relative to RIP. */
        bool            fIsRipRelative : 1;
        /** Set if it's a high byte register. */
        bool            fIsHighByteRegister : 1;
        /** Size of the disposition, 0 if none. */
        uint8_t         cbMemDisp;
        /** Base register, UINT8_MAX if not applicable. */
        uint8_t         iMemBaseReg;
        /** Index register, UINT8_MAX if not applicable. */
        uint8_t         iMemIndexReg;
        /** Index register, 1 if not applicable. */
        uint8_t         uMemScale;
        /** Effective segment register, UINT8_MAX if not memory access. */
        uint8_t         iEffSeg;
        /** Segment offset if memory access.  Undefined if not memory access. */
        uint64_t        offSeg;
        /** The effective address if memory access. */
        uint64_t        uEffAddr;
        /** Immediate or displacement value. */
        uint64_t        uImmDispValue;
        /** Base register value, undefined if irrelevant. */
        uint64_t        uMemBaseRegValue;
        /** Index register value, undefined if irrelevant. */
        uint64_t        uMemIndexRegValue;
        /** Points to where the input data for this operand should be placed,
         * when possible.  In the fIsMem = true case, it either points directly
         * to the input buffer or to a temporary one.  While in the other case,
         * it'll point into InCtx when possible. */
        RTPTRUNION      In;
        /** Points to where the expected output data for this operand should be
         * stored, when possible.  In the fIsMem = false case, it'll point into
         * ExpectedCtx when possible. */
        RTPTRUNION      Expected;
        /** Pointer to the data buffer for this operand. */
        PCIDETBUF       pDataBuf;
    }                   aOperands[4];

    /** Buffer where we assemble the instruction. */
    uint8_t             abInstr[45];
    /** The size of the instruction in abInstr. */
    uint8_t             cbInstr;
    /** Offset of the instruction into the buffer. */
    uint16_t            offInstr;
    /** Current code buffer. */
    CIDETBUF            CodeBuf;

    /** The input context.  Initalized by driver and FNCIDETSETUPINOUT. */
    CIDETCPUCTX         InCtx;
    /** The expected output context. */
    CIDETCPUCTX         ExpectedCtx;
    /** The actual output context. */
    CIDETCPUCTX         ActualCtx;
    /** Template input context, initialized when setting the mode. */
    CIDETCPUCTX         InTemplateCtx;

    /** Input and expected output temporary memory buffers. */
    uint8_t             abBuf[0x2000];


    /** Number of skipped tests because of pfnSetupInOut failures. */
    uint32_t            cSkippedSetupInOut;
    /** Number of skipped tests because of pfnReInitDataBuf failures. */
    uint32_t            cSkippedReInitDataBuf;
    /** Number of skipped tests because of pfnSetupDataBuf failures. */
    uint32_t            cSkippedSetupDataBuf;
    /** Number of skipped tests because RIP relative addressing constraints. */
    uint32_t            cSkippedDataBufWrtRip;
    /** Number of skipped tests because of assemble failures. */
    uint32_t            cSkippedAssemble;
    /** Number of skipped tests because of pfnReInitCodeBuf failures. */
    uint32_t            cSkippedReInitCodeBuf;
    /** Number of skipped tests because of pfnSetupCodeBuf failures. */
    uint32_t            cSkippedSetupCodeBuf;
    /** Number of skipped tests because the base and index registers are the same
     * one and there was a remainder when trying to point to the data buffer. */
    uint32_t            cSkippedSameBaseIndexRemainder;
    /** Number of skipped tests because index-only addressing left a remainder. */
    uint32_t            cSkippedOnlyIndexRemainder;
    /** Number of skipped tests because of direct addressing overflowed. */
    uint32_t            cSkippedDirectAddressingOverflow;


} CIDETCORE;
/** Pointer to the CIDET core state. */
typedef CIDETCORE *PCIDETCORE;

/** Magic number for CIDETCORE (Lee Konitz). */
#define CIDETCORE_MAGIC     UINT32_C(0x19271013)


int     CidetCoreInit(PCIDETCORE pThis, RTRAND hRand);
void    CidetCoreDelete(PCIDETCORE pThis);
int     CidetCoreSetTargetMode(PCIDETCORE pThis, uint8_t bMode);
uint32_t CidetCoreGetOperandSize(PCIDETCORE pThis, uint8_t iOp);
bool    CidetCoreTestInstruction(PCIDETCORE pThis, PCCIDETINSTR pInstr);


extern const CIDETINSTR g_aCidetInstructions1[];
extern const uint32_t   g_cCidetInstructions1;

#endif /* !VBOX_INCLUDED_SRC_cpu_cidet_h */