OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [bochs486/] [cpu/] [generic_cpuid.cc] - Blame information for rev 4

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/////////////////////////////////////////////////////////////////////////
2
// $Id: generic_cpuid.cc 11688 2013-05-20 18:18:52Z sshwarts $
3
/////////////////////////////////////////////////////////////////////////
4
//
5
//   Copyright (c) 2011-2012 Stanislav Shwartsman
6
//          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7
//
8
//  This library is free software; you can redistribute it and/or
9
//  modify it under the terms of the GNU Lesser General Public
10
//  License as published by the Free Software Foundation; either
11
//  version 2 of the License, or (at your option) any later version.
12
//
13
//  This library is distributed in the hope that it will be useful,
14
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
//  Lesser General Public License for more details.
17
//
18
//  You should have received a copy of the GNU Lesser General Public
19
//  License along with this library; if not, write to the Free Software
20
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
21
//
22
/////////////////////////////////////////////////////////////////////////
23
 
24
#include "bochs.h"
25
#include "cpu.h"
26
#include "param_names.h"
27
#include "generic_cpuid.h"
28
 
29
#define LOG_THIS cpu->
30
 
31
#undef BX_CPUID_SUPPORT_ISA_EXTENSION
32
 
33
#define BX_CPUID_SUPPORT_ISA_EXTENSION(feature) \
34
   (this->isa_extensions_bitmask & (feature))
35
 
36
#undef BX_CPUID_SUPPORT_CPU_EXTENSION
37
 
38
#define BX_CPUID_SUPPORT_CPU_EXTENSION(feature) \
39
   (this->cpu_extensions_bitmask & (feature))
40
 
41
bx_cpuid_t::bx_cpuid_t(BX_CPU_C *_cpu): cpu(_cpu)
42
{
43
#if BX_SUPPORT_SMP
44
  nthreads = SIM->get_param_num(BXPN_CPU_NTHREADS)->get();
45
  ncores = SIM->get_param_num(BXPN_CPU_NCORES)->get();
46
  nprocessors = SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get();
47
#else
48
  nthreads = 1;
49
  ncores = 1;
50
  nprocessors = 1;
51
#endif
52
}
53
 
54
#if BX_CPU_LEVEL >= 4
55
 
56
bx_generic_cpuid_t::bx_generic_cpuid_t(BX_CPU_C *cpu): bx_cpuid_t(cpu)
57
{
58
  init_isa_extensions_bitmask();
59
  init_cpu_extensions_bitmask();
60
#if BX_SUPPORT_VMX
61
  init_vmx_extensions_bitmask();
62
#endif
63
#if BX_SUPPORT_SVM
64
  init_svm_extensions_bitmask();
65
#endif
66
 
67
#if BX_CPU_LEVEL <= 5
68
  // 486 and Pentium processors
69
  max_std_leaf = 1;
70
#else
71
  // for Pentium Pro, Pentium II, Pentium 4 processors
72
  max_std_leaf = 2;
73
 
74
  // do not report CPUID functions above 0x3 if cpuid_limit_winnt is set
75
  // to workaround WinNT issue.
76
  static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get();
77
  if (! cpuid_limit_winnt) {
78
    if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MONITOR_MWAIT))
79
      max_std_leaf = 0x5;
80
    if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_X2APIC))
81
      max_std_leaf = 0xB;
82
    if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVE))
83
      max_std_leaf = 0xD;
84
  }
85
#endif
86
 
87
#if BX_CPU_LEVEL <= 5
88
  max_ext_leaf = 0;
89
#else
90
  max_ext_leaf = 0x80000008;
91
 
92
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SVM))
93
    max_ext_leaf = 0x8000000A;
94
#endif
95
}
96
 
97
void bx_generic_cpuid_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const
98
{
99
  static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get();
100
  if (cpuid_limit_winnt)
101
    if (function > 2 && function < 0x80000000) function = 2;
102
 
103
//AO#if BX_CPU_LEVEL >= 6
104
  if (function >= 0x80000000 && function > max_ext_leaf)
105
    function = max_std_leaf;
106
//AO#endif
107
  if (function <  0x80000000 && function > max_std_leaf)
108
    function = max_std_leaf;
109
 
110
  switch(function) {
111
#if BX_CPU_LEVEL >= 6
112
  case 0x80000000:
113
    get_ext_cpuid_leaf_0(leaf);
114
    return;
115
  case 0x80000001:
116
    get_ext_cpuid_leaf_1(leaf);
117
    return;
118
  case 0x80000002:
119
  case 0x80000003:
120
  case 0x80000004:
121
    get_ext_cpuid_brand_string_leaf(function, leaf);
122
    return;
123
  case 0x80000005:
124
    get_ext_cpuid_leaf_5(leaf);
125
    return;
126
  case 0x80000006:
127
    get_ext_cpuid_leaf_6(leaf);
128
    return;
129
  case 0x80000007:
130
    get_ext_cpuid_leaf_7(leaf);
131
    return;
132
  case 0x80000008:
133
    get_ext_cpuid_leaf_8(leaf);
134
    return;
135
#if BX_SUPPORT_SVM
136
  case 0x8000000A:
137
    get_ext_cpuid_leaf_A(leaf);
138
    return;
139
#endif
140
#endif
141
  case 0x00000000:
142
    get_std_cpuid_leaf_0(leaf);
143
    return;
144
  case 0x00000001:
145
    get_std_cpuid_leaf_1(leaf);
146
    return;
147
#if BX_CPU_LEVEL >= 6
148
  case 0x00000002:
149
    get_std_cpuid_leaf_2(leaf);
150
    return;
151
  case 0x00000003:
152
    get_reserved_leaf(leaf);
153
    return;
154
  case 0x00000004:
155
    get_std_cpuid_leaf_4(subfunction, leaf);
156
    return;
157
  case 0x00000005:
158
    get_std_cpuid_leaf_5(leaf);
159
    return;
160
  case 0x00000006:
161
    get_std_cpuid_leaf_6(leaf);
162
    return;
163
  case 0x00000007:
164
    get_std_cpuid_leaf_7(subfunction, leaf);
165
    return;
166
  case 0x00000008:
167
  case 0x00000009:
168
    get_reserved_leaf(leaf);
169
    return;
170
  case 0x0000000A:
171
    get_std_cpuid_leaf_A(leaf);
172
    return;
173
  case 0x0000000B:
174
    get_std_cpuid_extended_topology_leaf(subfunction, leaf);
175
    return;
176
  case 0x0000000C:
177
    get_reserved_leaf(leaf);
178
    return;
179
  case 0x0000000D:
180
  default:
181
    get_std_cpuid_xsave_leaf(subfunction, leaf);
182
    return;
183
#endif
184
  }
185
}
186
 
187
// leaf 0x00000000 //
188
void bx_generic_cpuid_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const
189
{
190
  static Bit8u *vendor_string = (Bit8u *)SIM->get_param_string(BXPN_VENDOR_STRING)->getptr();
191
 
192
  // EAX: highest std function understood by CPUID
193
  // EBX: vendor ID string
194
  // EDX: vendor ID string
195
  // ECX: vendor ID string
196
  leaf->eax = max_std_leaf;
197
 
198
  // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...)
199
  memcpy(&(leaf->ebx), vendor_string,     4);
200
  memcpy(&(leaf->edx), vendor_string + 4, 4);
201
  memcpy(&(leaf->ecx), vendor_string + 8, 4);
202
#ifdef BX_BIG_ENDIAN
203
  leaf->ebx = bx_bswap32(leaf->ebx);
204
  leaf->ecx = bx_bswap32(leaf->ecx);
205
  leaf->edx = bx_bswap32(leaf->edx);
206
#endif
207
}
208
 
209
// leaf 0x00000001 //
210
void bx_generic_cpuid_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const
211
{
212
  // EAX:       CPU Version Information
213
  //   [3:0]   Stepping ID
214
  //   [7:4]   Model: starts at 1
215
  //   [11:8]  Family: 4=486, 5=Pentium, 6=PPro, ...
216
  //   [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved
217
  //   [19:16] Extended Model
218
  //   [27:20] Extended Family
219
  leaf->eax = get_cpu_version_information();
220
 
221
  // EBX:
222
  //   [7:0]   Brand ID
223
  //   [15:8]  CLFLUSH cache line size (value*8 = cache line size in bytes)
224
  //   [23:16] Number of logical processors in one physical processor
225
  //   [31:24] Local Apic ID
226
  leaf->ebx = 0;
227
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CLFLUSH)) {
228
    leaf->ebx |= (CACHE_LINE_SIZE / 8) << 8;
229
  }
230
  unsigned n_logical_processors = ncores*nthreads;
231
  leaf->ebx |= (n_logical_processors << 16);
232
#if BX_SUPPORT_APIC
233
  leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24);
234
#endif
235
 
236
  // ECX: Extended Feature Flags
237
#if BX_CPU_LEVEL >= 6
238
  leaf->ecx = get_extended_cpuid_features();
239
#else
240
  leaf->ecx = 0;
241
#endif
242
 
243
  // EDX: Standard Feature Flags
244
  leaf->edx = get_std_cpuid_features();
245
}
246
 
247
#if BX_CPU_LEVEL >= 6
248
 
249
// leaf 0x00000002 //
250
void bx_generic_cpuid_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const
251
{
252
  // CPUID function 0x00000002 - Cache and TLB Descriptors
253
#if BX_CPU_VENDOR_INTEL
254
  leaf->eax = 0x00410601;  // for Pentium Pro compatibility
255
  leaf->ebx = 0;
256
  leaf->ecx = 0;
257
  leaf->edx = 0;
258
#else
259
  leaf->eax = 0;           // ignore for AMD
260
  leaf->ebx = 0;
261
  leaf->ecx = 0;
262
  leaf->edx = 0;
263
#endif
264
}
265
 
266
// leaf 0x00000003 - Processor Serial Number (not supported) //
267
 
268
// leaf 0x00000004 //
269
void bx_generic_cpuid_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const
270
{
271
  // CPUID function 0x00000004 - Deterministic Cache Parameters
272
  leaf->eax = 0;
273
  leaf->ebx = 0;
274
  leaf->ecx = 0;
275
  leaf->edx = 0;
276
}
277
 
278
// leaf 0x00000005 //
279
void bx_generic_cpuid_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const
280
{
281
  // CPUID function 0x00000005 - MONITOR/MWAIT Leaf
282
#if BX_SUPPORT_MONITOR_MWAIT
283
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MONITOR_MWAIT))
284
  {
285
    // EAX - Smallest monitor-line size in bytes
286
    // EBX - Largest  monitor-line size in bytes
287
    // ECX -
288
    //   [31:2] - reserved
289
    //    [1:1] - exit MWAIT even with EFLAGS.IF = 0
290
    //    [0:0] - MONITOR/MWAIT extensions are supported
291
    // EDX -
292
    //  [03-00] - number of C0 sub C-states supported using MWAIT
293
    //  [07-04] - number of C1 sub C-states supported using MWAIT
294
    //  [11-08] - number of C2 sub C-states supported using MWAIT
295
    //  [15-12] - number of C3 sub C-states supported using MWAIT
296
    //  [19-16] - number of C4 sub C-states supported using MWAIT
297
    //  [31-20] - reserved (MBZ)
298
    leaf->eax = CACHE_LINE_SIZE;
299
    leaf->ebx = CACHE_LINE_SIZE;
300
    leaf->ecx = 3;
301
    leaf->edx = 0x00000020;
302
  }
303
  else
304
#endif
305
  {
306
    leaf->eax = 0;
307
    leaf->ebx = 0;
308
    leaf->ecx = 0;
309
    leaf->edx = 0;
310
  }
311
}
312
 
313
// leaf 0x00000006 //
314
void bx_generic_cpuid_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const
315
{
316
  // CPUID function 0x00000006 - Thermal and Power Management Leaf
317
  leaf->eax = 0;
318
  leaf->ebx = 0;
319
  leaf->ecx = 0;
320
  leaf->edx = 0;
321
}
322
 
323
// leaf 0x00000007 //
324
void bx_generic_cpuid_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const
325
{
326
  leaf->eax = 0; /* report max sub-leaf that supported in leaf 7 */
327
  leaf->ebx = get_ext3_cpuid_features();
328
  leaf->ecx = 0;
329
  leaf->edx = 0;
330
}
331
 
332
// leaf 0x00000008 reserved                          //
333
// leaf 0x00000009 direct cache access not supported //
334
 
335
// leaf 0x0000000A //
336
void bx_generic_cpuid_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf) const
337
{
338
  // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf
339
  leaf->eax = 0;
340
  leaf->ebx = 0;
341
  leaf->ecx = 0;
342
  leaf->edx = 0;
343
}
344
 
345
BX_CPP_INLINE static Bit32u ilog2(Bit32u x)
346
{
347
  Bit32u count = 0;
348
  while(x>>=1) count++;
349
  return count;
350
}
351
 
352
// leaf 0x0000000B //
353
void bx_generic_cpuid_t::get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const
354
{
355
  // CPUID function 0x0000000B - Extended Topology Leaf
356
  leaf->eax = 0;
357
  leaf->ebx = 0;
358
  leaf->ecx = subfunction;
359
  leaf->edx = cpu->get_apic_id();
360
 
361
#if BX_SUPPORT_SMP
362
  switch(subfunction) {
363
  case 0:
364
     if (nthreads > 1) {
365
        leaf->eax = ilog2(nthreads-1)+1;
366
        leaf->ebx = nthreads;
367
        leaf->ecx |= (1<<8);
368
     }
369
     else if (ncores > 1) {
370
        leaf->eax = ilog2(ncores-1)+1;
371
        leaf->ebx = ncores;
372
        leaf->ecx |= (2<<8);
373
     }
374
     else if (nprocessors > 1) {
375
        leaf->eax = ilog2(nprocessors-1)+1;
376
        leaf->ebx = nprocessors;
377
     }
378
     else {
379
        leaf->eax = 1;
380
        leaf->ebx = 1; // number of logical CPUs at this level
381
     }
382
     break;
383
 
384
  case 1:
385
     if (nthreads > 1) {
386
        if (ncores > 1) {
387
           leaf->eax = ilog2(ncores-1)+1;
388
           leaf->ebx = ncores;
389
           leaf->ecx |= (2<<8);
390
        }
391
        else if (nprocessors > 1) {
392
           leaf->eax = ilog2(nprocessors-1)+1;
393
           leaf->ebx = nprocessors;
394
        }
395
     }
396
     else if (ncores > 1) {
397
        if (nprocessors > 1) {
398
           leaf->eax = ilog2(nprocessors-1)+1;
399
           leaf->ebx = nprocessors;
400
        }
401
     }
402
     break;
403
 
404
  case 2:
405
     if (nthreads > 1) {
406
        if (nprocessors > 1) {
407
           leaf->eax = ilog2(nprocessors-1)+1;
408
           leaf->ebx = nprocessors;
409
        }
410
     }
411
     break;
412
 
413
  default:
414
     break;
415
  }
416
#endif
417
}
418
 
419
// leaf 0x0000000C - reserved //
420
 
421
// leaf 0x0000000D //
422
void bx_generic_cpuid_t::get_std_cpuid_xsave_leaf(Bit32u subfunction, cpuid_function_t *leaf) const
423
{
424
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVE))
425
  {
426
    switch(subfunction) {
427
    case 0:
428
      // EAX - valid bits of XCR0 (lower part)
429
      // EBX - Maximum size (in bytes) required by enabled features
430
      // ECX - Maximum size (in bytes) required by CPU supported features
431
      // EDX - valid bits of XCR0 (upper part)
432
      leaf->eax = cpu->xcr0_suppmask;
433
      leaf->ebx = 512+64;
434
#if BX_SUPPORT_AVX
435
      if (cpu->xcr0.get_AVX())
436
        leaf->ebx += 256;
437
#endif
438
      leaf->ecx = 512+64;
439
#if BX_SUPPORT_AVX
440
      if (cpu->xcr0_suppmask & BX_XCR0_AVX_MASK)
441
        leaf->ecx += 256;
442
#endif
443
      leaf->edx = 0;
444
      return;
445
 
446
    case 1:
447
      leaf->eax = BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVEOPT);
448
      leaf->ebx = 0;
449
      leaf->ecx = 0;
450
      leaf->edx = 0;
451
      return;
452
 
453
#if BX_SUPPORT_AVX
454
    case 2: // AVX leaf
455
      if (cpu->xcr0_suppmask & BX_XCR0_AVX_MASK) {
456
        leaf->eax = 256;
457
        leaf->ebx = 576;
458
        leaf->ecx = 0;
459
        leaf->edx = 0;
460
        break;
461
      }
462
      // else fall through
463
#endif
464
 
465
    default:
466
      leaf->eax = 0; // reserved
467
      leaf->ebx = 0; // reserved
468
      leaf->ecx = 0; // reserved
469
      leaf->edx = 0; // reserved
470
      break;
471
    }
472
  }
473
}
474
 
475
// leaf 0x80000000 //
476
void bx_generic_cpuid_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const
477
{
478
  // EAX: highest extended function understood by CPUID
479
  // EBX: vendor ID string
480
  // EDX: vendor ID string
481
  // ECX: vendor ID string
482
  leaf->eax = max_ext_leaf;
483
#if BX_CPU_VENDOR_INTEL
484
  leaf->ebx = 0;
485
  leaf->edx = 0;          // Reserved for Intel
486
  leaf->ecx = 0;
487
#else
488
  static Bit8u *vendor_string = (Bit8u *)SIM->get_param_string(BXPN_VENDOR_STRING)->getptr();
489
 
490
  memcpy(&(leaf->ebx), vendor_string,     4);
491
  memcpy(&(leaf->edx), vendor_string + 4, 4);
492
  memcpy(&(leaf->ecx), vendor_string + 8, 4);
493
#endif
494
 
495
#ifdef BX_BIG_ENDIAN
496
  leaf->ebx = bx_bswap32(leaf->ebx);
497
  leaf->ecx = bx_bswap32(leaf->ecx);
498
  leaf->edx = bx_bswap32(leaf->edx);
499
#endif
500
}
501
 
502
// leaf 0x80000001 //
503
void bx_generic_cpuid_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const
504
{
505
  // EAX:       CPU Version Information
506
  leaf->eax = BX_CPU_VENDOR_INTEL ? 0 : get_cpu_version_information();
507
 
508
  // EBX:       Brand ID
509
  leaf->ebx = 0;
510
 
511
  // ECX:
512
  leaf->ecx = get_ext2_cpuid_features();
513
 
514
  // EDX:
515
  // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD
516
  // [*] [0:0]   FPU on chip
517
  // [*] [1:1]   VME: Virtual-8086 Mode enhancements
518
  // [*] [2:2]   DE: Debug Extensions (I/O breakpoints)
519
  // [*] [3:3]   PSE: Page Size Extensions
520
  // [*] [4:4]   TSC: Time Stamp Counter
521
  // [*] [5:5]   MSR: RDMSR and WRMSR support
522
  // [*] [6:6]   PAE: Physical Address Extensions
523
  // [*] [7:7]   MCE: Machine Check Exception
524
  // [*] [8:8]   CXS: CMPXCHG8B instruction
525
  // [*] [9:9]   APIC: APIC on Chip
526
  //     [10:10] Reserved
527
  //     [11:11] SYSCALL/SYSRET support
528
  // [*] [12:12] MTRR: Memory Type Range Reg
529
  // [*] [13:13] PGE/PTE Global Bit
530
  // [*] [14:14] MCA: Machine Check Architecture
531
  // [*] [15:15] CMOV: Cond Mov/Cmp Instructions
532
  // [*] [16:16] PAT: Page Attribute Table
533
  // [*] [17:17] PSE-36: Physical Address Extensions
534
  //     [18:19] Reserved
535
  //     [20:20] No-Execute page protection
536
  //     [21:21] Reserved
537
  //     [22:22] AMD MMX Extensions
538
  // [*] [23:23] MMX Technology
539
  // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
540
  //     [25:25] Fast FXSAVE/FXRSTOR mode support
541
  //     [26:26] 1G paging support
542
  //     [27:27] Support RDTSCP Instruction
543
  //     [28:28] Reserved
544
  //     [29:29] Long Mode
545
  //     [30:30] AMD 3DNow! Extensions
546
  //     [31:31] AMD 3DNow! Instructions
547
  leaf->edx = get_std2_cpuid_features();
548
}
549
 
550
// leaf 0x80000002 //
551
// leaf 0x80000003 //
552
// leaf 0x80000004 //
553
void bx_generic_cpuid_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const
554
{
555
  // CPUID function 0x800000002-0x800000004 - Processor Name String Identifier
556
  static Bit8u *brand_string = (Bit8u *)SIM->get_param_string(BXPN_BRAND_STRING)->getptr();
557
 
558
  switch(function) {
559
  case 0x80000002:
560
    memcpy(&(leaf->eax), brand_string     , 4);
561
    memcpy(&(leaf->ebx), brand_string +  4, 4);
562
    memcpy(&(leaf->ecx), brand_string +  8, 4);
563
    memcpy(&(leaf->edx), brand_string + 12, 4);
564
    break;
565
  case 0x80000003:
566
    memcpy(&(leaf->eax), brand_string + 16, 4);
567
    memcpy(&(leaf->ebx), brand_string + 20, 4);
568
    memcpy(&(leaf->ecx), brand_string + 24, 4);
569
    memcpy(&(leaf->edx), brand_string + 28, 4);
570
    break;
571
  case 0x80000004:
572
    memcpy(&(leaf->eax), brand_string + 32, 4);
573
    memcpy(&(leaf->ebx), brand_string + 36, 4);
574
    memcpy(&(leaf->ecx), brand_string + 40, 4);
575
    memcpy(&(leaf->edx), brand_string + 44, 4);
576
    break;
577
  default:
578
    break;
579
  }
580
 
581
#ifdef BX_BIG_ENDIAN
582
  leaf->eax = bx_bswap32(leaf->eax);
583
  leaf->ebx = bx_bswap32(leaf->ebx);
584
  leaf->ecx = bx_bswap32(leaf->ecx);
585
  leaf->edx = bx_bswap32(leaf->edx);
586
#endif
587
}
588
 
589
// leaf 0x80000005 //
590
void bx_generic_cpuid_t::get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const
591
{
592
  // CPUID function 0x800000005 - L1 Cache and TLB Identifiers
593
  leaf->eax = 0x01ff01ff;
594
  leaf->ebx = 0x01ff01ff;
595
  leaf->ecx = 0x40020140;
596
  leaf->edx = 0x40020140;
597
}
598
 
599
// leaf 0x80000006 //
600
void bx_generic_cpuid_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const
601
{
602
  // CPUID function 0x800000006 - L2 Cache and TLB Identifiers
603
  leaf->eax = 0;
604
  leaf->ebx = 0x42004200;
605
  leaf->ecx = 0x02008140;
606
  leaf->edx = 0;
607
}
608
 
609
// leaf 0x80000007 //
610
void bx_generic_cpuid_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const
611
{
612
  // CPUID function 0x800000007 - Advanced Power Management
613
  leaf->eax = 0;
614
  leaf->ebx = 0;
615
  leaf->ecx = 0;
616
  leaf->edx = 0;
617
}
618
 
619
// leaf 0x80000008 //
620
void bx_generic_cpuid_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const
621
{
622
  // virtual & phys address size in low 2 bytes.
623
  leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8);
624
  leaf->ebx = 0;
625
  leaf->ecx = 0; // Reserved, undefined
626
  leaf->edx = 0;
627
}
628
 
629
#if BX_SUPPORT_SVM
630
 
631
// leaf 0x8000000A //
632
void bx_generic_cpuid_t::get_ext_cpuid_leaf_A(cpuid_function_t *leaf) const
633
{
634
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SVM))
635
  {
636
    leaf->eax = BX_SVM_REVISION;
637
    leaf->ebx = 0x40; /* number of ASIDs */
638
    leaf->ecx = 0;
639
 
640
    // * [0:0]   NP - Nested paging support
641
    //   [1:1]   LBR virtualization
642
    //   [2:2]   SVM Lock
643
    // * [3:3]   NRIPS - Next RIP save on VMEXIT
644
    //   [4:4]   TscRate - MSR based TSC ratio control
645
    //   [5:5]   VMCB Clean bits support
646
    //   [6:6]   Flush by ASID support
647
    //   [7:7]   Decode assists support
648
    //   [9:8]   Reserved
649
    //   [10:10] Pause filter support
650
    //   [11:11] Reserved
651
    //   [12:12] Pause filter threshold support
652
    //   [31:13] Reserved
653
 
654
    leaf->edx = BX_CPUID_SVM_NESTED_PAGING | BX_CPUID_SVM_NRIP_SAVE;
655
  }
656
  else {
657
    leaf->eax = 0;
658
    leaf->ebx = 0;
659
    leaf->ecx = 0; // Reserved, undefined
660
    leaf->edx = 0;
661
  }
662
}
663
 
664
#endif
665
 
666
#endif
667
 
668
void bx_generic_cpuid_t::init_isa_extensions_bitmask(void)
669
{
670
  Bit64u features_bitmask = 0;
671
 
672
#if BX_SUPPORT_FPU
673
  features_bitmask |= BX_ISA_X87;
674
#endif
675
 
676
#if BX_CPU_LEVEL >= 4
677
  static unsigned cpu_level = SIM->get_param_num(BXPN_CPUID_LEVEL)->get();
678
//AO  if (cpu_level < 5) {
679
  if (cpu_level < 4) {
680
    BX_PANIC(("Unsupported CPUID level selected %d", cpu_level));
681
  }
682
 
683
  features_bitmask |= BX_ISA_486;
684
 
685
#if BX_CPU_LEVEL >= 5
686
  static bx_bool mmx_enabled = SIM->get_param_bool(BXPN_CPUID_MMX)->get();
687
 
688
  if (cpu_level >= 5) {
689
    features_bitmask |= BX_ISA_PENTIUM;
690
 
691
    if (mmx_enabled)
692
      features_bitmask |= BX_ISA_MMX;
693
 
694
#if BX_SUPPORT_3DNOW
695
    features_bitmask |= BX_ISA_3DNOW;
696
    if (! mmx_enabled) {
697
      BX_PANIC(("PANIC: 3DNOW emulation requires MMX support !"));
698
      return;
699
    }
700
#endif
701
  }
702
 
703
#if BX_CPU_LEVEL >= 6
704
  if (cpu_level >= 6)
705
    features_bitmask |= BX_ISA_P6;
706
 
707
#if BX_SUPPORT_MONITOR_MWAIT
708
  static bx_bool mwait_enabled = SIM->get_param_bool(BXPN_CPUID_MWAIT)->get();
709
  if (mwait_enabled) {
710
    features_bitmask |= BX_ISA_MONITOR_MWAIT;
711
    if (cpu_level < 6)
712
      BX_PANIC(("PANIC: MONITOR/MWAIT emulation requires P6 CPU level support !"));
713
  }
714
#endif
715
 
716
  static unsigned sse_enabled = SIM->get_param_enum(BXPN_CPUID_SSE)->get();
717
  // determine SSE in runtime
718
  switch (sse_enabled) {
719
    case BX_CPUID_SUPPORT_SSE4_2:
720
      features_bitmask |= BX_ISA_SSE4_2;
721
    case BX_CPUID_SUPPORT_SSE4_1:
722
      features_bitmask |= BX_ISA_SSE4_1;
723
    case BX_CPUID_SUPPORT_SSSE3:
724
      features_bitmask |= BX_ISA_SSSE3;
725
    case BX_CPUID_SUPPORT_SSE3:
726
      features_bitmask |= BX_ISA_SSE3;
727
    case BX_CPUID_SUPPORT_SSE2:
728
      features_bitmask |= BX_ISA_SSE2;
729
    case BX_CPUID_SUPPORT_SSE:
730
      features_bitmask |= BX_ISA_SSE;
731
    case BX_CPUID_SUPPORT_NOSSE:
732
    default:
733
      break;
734
  };
735
 
736
  if (sse_enabled) {
737
    if (mmx_enabled == 0 || cpu_level < 6 || BX_CPU_LEVEL < 6) {
738
      BX_PANIC(("PANIC: SSE support requires P6 emulation with MMX enabled !"));
739
      return;
740
    }
741
  }
742
 
743
  // enable CLFLUSH only when SSE2 or higher is enabled
744
  if (sse_enabled >= BX_CPUID_SUPPORT_SSE2)
745
    features_bitmask |= BX_ISA_CLFLUSH;
746
 
747
  // enable POPCNT if SSE4.2 is enabled
748
  if (sse_enabled >= BX_CPUID_SUPPORT_SSE4_2)
749
    features_bitmask |= BX_ISA_POPCNT;
750
 
751
  static bx_bool sse4a_enabled = SIM->get_param_bool(BXPN_CPUID_SSE4A)->get();
752
  if (sse4a_enabled) {
753
    features_bitmask |= BX_ISA_SSE4A;
754
 
755
    if (! sse_enabled) {
756
      BX_PANIC(("PANIC: SSE4A require SSE to be enabled !"));
757
      return;
758
    }
759
  }
760
 
761
  static bx_bool sep_enabled = SIM->get_param_bool(BXPN_CPUID_SEP)->get();
762
  if (sep_enabled) {
763
    features_bitmask |= BX_ISA_SYSENTER_SYSEXIT;
764
    if (cpu_level < 6)
765
      BX_PANIC(("PANIC: SYSENTER/SYSEXIT emulation requires P6 CPU level support !"));
766
  }
767
 
768
  static bx_bool xsave_enabled = SIM->get_param_bool(BXPN_CPUID_XSAVE)->get();
769
  if (xsave_enabled) {
770
    features_bitmask |= BX_ISA_XSAVE;
771
 
772
    if (! sse_enabled) {
773
       BX_PANIC(("PANIC: XSAVE emulation requires SSE support !"));
774
       return;
775
    }
776
  }
777
 
778
  static bx_bool xsaveopt_enabled = SIM->get_param_bool(BXPN_CPUID_XSAVEOPT)->get();
779
  if (xsaveopt_enabled) {
780
    features_bitmask |= BX_ISA_XSAVEOPT;
781
 
782
    if (! xsave_enabled) {
783
      BX_PANIC(("PANIC: XSAVEOPT emulation requires XSAVE !"));
784
      return;
785
    }
786
  }
787
 
788
  static bx_bool aes_enabled = SIM->get_param_bool(BXPN_CPUID_AES)->get();
789
  if (aes_enabled) {
790
    features_bitmask |= BX_ISA_AES_PCLMULQDQ;
791
 
792
    // AES required 3-byte opcode (SSS3E support or more)
793
    if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) {
794
      BX_PANIC(("PANIC: AES support requires SSSE3 or higher !"));
795
      return;
796
    }
797
  }
798
 
799
  static bx_bool movbe_enabled = SIM->get_param_bool(BXPN_CPUID_MOVBE)->get();
800
  if (movbe_enabled) {
801
    features_bitmask |= BX_ISA_MOVBE;
802
 
803
    // MOVBE required 3-byte opcode (SSS3E support or more)
804
    if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) {
805
      BX_PANIC(("PANIC: MOVBE support requires SSSE3 or higher !"));
806
      return;
807
    }
808
  }
809
 
810
  static bx_bool adx_enabled = SIM->get_param_bool(BXPN_CPUID_ADX)->get();
811
  if (adx_enabled) {
812
    features_bitmask |= BX_ISA_ADX;
813
 
814
    // ADX required 3-byte opcode (SSS3E support or more)
815
    if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) {
816
      BX_PANIC(("PANIC: ADX support requires SSSE3 or higher !"));
817
      return;
818
    }
819
  }
820
 
821
#if BX_SUPPORT_X86_64
822
  static bx_bool x86_64_enabled = SIM->get_param_bool(BXPN_CPUID_X86_64)->get();
823
  if (x86_64_enabled) {
824
    if (cpu_level < 6)
825
      BX_PANIC(("PANIC: x86-64 emulation requires P6 CPU level support !"));
826
 
827
    features_bitmask |= BX_ISA_CMPXCHG16B | BX_ISA_RDTSCP | BX_ISA_LM_LAHF_SAHF;
828
 
829
    if (sse_enabled < BX_CPUID_SUPPORT_SSE2) {
830
      BX_PANIC(("PANIC: x86-64 emulation requires SSE2 support !"));
831
      return;
832
    }
833
 
834
    if (! sep_enabled) {
835
      BX_PANIC(("PANIC: x86-64 emulation requires SYSENTER/SYSEXIT support !"));
836
      return;
837
    }
838
 
839
    static bx_bool fsgsbase_enabled = SIM->get_param_bool(BXPN_CPUID_FSGSBASE)->get();
840
    if (fsgsbase_enabled)
841
      features_bitmask |= BX_ISA_FSGSBASE;
842
 
843
    static unsigned apic_enabled = SIM->get_param_enum(BXPN_CPUID_APIC)->get();
844
    if (apic_enabled < BX_CPUID_SUPPORT_XAPIC) {
845
      BX_PANIC(("PANIC: x86-64 emulation requires XAPIC support !"));
846
      return;
847
    }
848
  }
849
  else {
850
    if (BX_SUPPORT_VMX >= 2) {
851
      BX_PANIC(("PANIC: VMX=2 emulation requires x86-64 support !"));
852
      return;
853
    }
854
  }
855
 
856
#if BX_SUPPORT_AVX
857
  static unsigned avx_enabled = SIM->get_param_num(BXPN_CPUID_AVX)->get();
858
  if (avx_enabled) {
859
    features_bitmask |= BX_ISA_AVX;
860
 
861
    if (! xsave_enabled) {
862
      BX_PANIC(("PANIC: AVX emulation requires XSAVE support !"));
863
      return;
864
    }
865
 
866
    if (! x86_64_enabled) {
867
      BX_PANIC(("PANIC: AVX emulation requires x86-64 support !"));
868
      return;
869
    }
870
 
871
    if (avx_enabled >= 2)
872
      features_bitmask |= BX_ISA_AVX2;
873
  }
874
 
875
  static bx_bool avx_f16c_enabled = SIM->get_param_bool(BXPN_CPUID_AVX_F16CVT)->get();
876
  if (avx_f16c_enabled) {
877
    if (! avx_enabled) {
878
      BX_PANIC(("PANIC: Float16 convert emulation requires AVX support !"));
879
      return;
880
    }
881
 
882
    features_bitmask |= BX_ISA_AVX_F16C;
883
  }
884
 
885
  static bx_bool avx_fma_enabled = SIM->get_param_bool(BXPN_CPUID_AVX_FMA)->get();
886
  if (avx_fma_enabled) {
887
    if (avx_enabled < 2) {
888
      BX_PANIC(("PANIC: FMA emulation requires AVX2 support !"));
889
      return;
890
    }
891
 
892
    features_bitmask |= BX_ISA_AVX_FMA;
893
  }
894
 
895
  static unsigned bmi_enabled = SIM->get_param_num(BXPN_CPUID_BMI)->get();
896
  if (bmi_enabled) {
897
    features_bitmask |= BX_ISA_BMI1 | BX_ISA_LZCNT;
898
 
899
    if (! avx_enabled) {
900
      BX_PANIC(("PANIC: Bit Manipulation Instructions (BMI) emulation requires AVX support !"));
901
      return;
902
    }
903
 
904
    if (bmi_enabled >= 2)
905
      features_bitmask |= BX_ISA_BMI2;
906
  }
907
 
908
  static bx_bool fma4_enabled = SIM->get_param_bool(BXPN_CPUID_FMA4)->get();
909
  if (fma4_enabled) {
910
    if (! avx_enabled) {
911
      BX_PANIC(("PANIC: FMA4 emulation requires AVX support !"));
912
      return;
913
    }
914
 
915
    features_bitmask |= BX_ISA_FMA4;
916
  }
917
 
918
  static bx_bool xop_enabled = SIM->get_param_bool(BXPN_CPUID_XOP)->get();
919
  if (xop_enabled) {
920
    if (! avx_enabled) {
921
      BX_PANIC(("PANIC: XOP emulation requires AVX support !"));
922
      return;
923
    }
924
 
925
    features_bitmask |= BX_ISA_XOP;
926
  }
927
 
928
  static bx_bool tbm_enabled = SIM->get_param_bool(BXPN_CPUID_TBM)->get();
929
  if (tbm_enabled) {
930
    if (! avx_enabled || ! xop_enabled) {
931
      BX_PANIC(("PANIC: TBM emulation requires AVX and XOP support !"));
932
      return;
933
    }
934
 
935
    features_bitmask |= BX_ISA_TBM;
936
  }
937
#endif // BX_SUPPORT_AVX
938
 
939
#endif // BX_SUPPORT_X86_64
940
 
941
#if BX_SUPPORT_VMX
942
  static unsigned vmx_enabled = SIM->get_param_num(BXPN_CPUID_VMX)->get();
943
  if (vmx_enabled) {
944
    features_bitmask |= BX_ISA_VMX;
945
 
946
    if (! sep_enabled) {
947
      BX_PANIC(("PANIC: VMX emulation requires SYSENTER/SYSEXIT support !"));
948
      return;
949
    }
950
  }
951
#endif
952
 
953
#if BX_SUPPORT_SVM
954
  static unsigned svm_enabled = SIM->get_param_num(BXPN_CPUID_SVM)->get();
955
  if (svm_enabled) {
956
    features_bitmask |= BX_ISA_SVM;
957
 
958
    if (! x86_64_enabled) {
959
      BX_PANIC(("PANIC: SVM emulation requires x86-64 support !"));
960
      return;
961
    }
962
  }
963
#endif
964
 
965
#if BX_SUPPORT_VMX && BX_SUPPORT_SVM
966
  if (vmx_enabled && svm_enabled) {
967
    BX_PANIC(("PANIC: VMX and SVM emulation cannot be enabled together in same configuration !"));
968
    return;
969
  }
970
#endif
971
 
972
#endif // CPU_LEVEL >= 6
973
 
974
#endif // CPU_LEVEL >= 5
975
 
976
#endif // CPU_LEVEL >= 4
977
 
978
  this->isa_extensions_bitmask = features_bitmask;
979
}
980
 
981
void bx_generic_cpuid_t::init_cpu_extensions_bitmask(void)
982
{
983
  Bit32u features_bitmask = 0;
984
 
985
  static unsigned cpu_level = SIM->get_param_num(BXPN_CPUID_LEVEL)->get();
986
//AO  if (cpu_level < 5) {
987
  if (cpu_level < 4) {
988
    BX_PANIC(("Unsupported CPUID level selected %d", cpu_level));
989
  }
990
 
991
#if BX_SUPPORT_APIC
992
  static unsigned apic_enabled = SIM->get_param_enum(BXPN_CPUID_APIC)->get();
993
 
994
  if (cpu_level < 6) {
995
    if (apic_enabled != BX_CPUID_SUPPORT_LEGACY_APIC && apic_enabled != BX_CPUID_SUPPORT_XAPIC)
996
      BX_PANIC(("PANIC: APIC extensions emulation require P6 CPU level support !"));
997
  }
998
 
999
  switch (apic_enabled) {
1000
#if BX_CPU_LEVEL >= 6
1001
    case BX_CPUID_SUPPORT_X2APIC:
1002
      features_bitmask |= BX_CPU_X2APIC | BX_CPU_XAPIC;
1003
      break;
1004
    case BX_CPUID_SUPPORT_XAPIC_EXT:
1005
      features_bitmask |= BX_CPU_XAPIC_EXT | BX_CPU_XAPIC;
1006
      break;
1007
#endif
1008
    case BX_CPUID_SUPPORT_XAPIC:
1009
      features_bitmask |= BX_CPU_XAPIC;
1010
      break;
1011
    case BX_CPUID_SUPPORT_LEGACY_APIC:
1012
      break;
1013
    default:
1014
      BX_PANIC(("unknown APIC option %d", apic_enabled));
1015
  };
1016
#endif
1017
 
1018
#if BX_CPU_LEVEL >= 5
1019
  if (cpu_level >= 5) {
1020
    features_bitmask |= BX_CPU_VME;
1021
    features_bitmask |= BX_CPU_DEBUG_EXTENSIONS;
1022
    features_bitmask |= BX_CPU_PSE;
1023
 
1024
#if BX_PHY_ADDRESS_LONG
1025
    features_bitmask |= BX_CPU_PSE36;
1026
#endif
1027
  }
1028
 
1029
#if BX_CPU_LEVEL >= 6
1030
  if (cpu_level >= 6) {
1031
    features_bitmask |= BX_CPU_PAE;
1032
    features_bitmask |= BX_CPU_PGE;
1033
    features_bitmask |= BX_CPU_MTRR;
1034
    features_bitmask |= BX_CPU_PAT;
1035
  }
1036
 
1037
  static bx_bool misaligned_sse_enabled = SIM->get_param_bool(BXPN_CPUID_MISALIGNED_SSE)->get();
1038
  if (misaligned_sse_enabled) {
1039
    features_bitmask |= BX_CPU_MISALIGNED_SSE;
1040
    if (cpu_level < 6)
1041
      BX_PANIC(("PANIC: Misaligned SSE emulation requires P6 CPU level support !"));
1042
  }
1043
 
1044
  static bx_bool smep_enabled = SIM->get_param_bool(BXPN_CPUID_SMEP)->get();
1045
  if (smep_enabled) {
1046
    features_bitmask |= BX_CPU_SMEP;
1047
    if (cpu_level < 6)
1048
      BX_PANIC(("PANIC: SMEP emulation requires P6 CPU level support !"));
1049
  }
1050
 
1051
  static bx_bool smap_enabled = SIM->get_param_bool(BXPN_CPUID_SMAP)->get();
1052
  if (smap_enabled) {
1053
    features_bitmask |= BX_ISA_SMAP;
1054
    if (cpu_level < 6)
1055
      BX_PANIC(("PANIC: SMAP emulation requires P6 CPU level support !"));
1056
  }
1057
 
1058
#if BX_SUPPORT_X86_64
1059
  static bx_bool x86_64_enabled = SIM->get_param_bool(BXPN_CPUID_X86_64)->get();
1060
  if (x86_64_enabled) {
1061
    if (cpu_level < 6)
1062
      BX_PANIC(("PANIC: x86-64 emulation requires P6 CPU level support !"));
1063
 
1064
    features_bitmask |= BX_CPU_LONG_MODE | BX_CPU_FFXSR | BX_CPU_NX;
1065
 
1066
    static bx_bool pcid_enabled = SIM->get_param_bool(BXPN_CPUID_PCID)->get();
1067
    if (pcid_enabled)
1068
      features_bitmask |= BX_CPU_PCID;
1069
 
1070
    static bx_bool xlarge_pages = SIM->get_param_bool(BXPN_CPUID_1G_PAGES)->get();
1071
    if (xlarge_pages)
1072
      features_bitmask |= BX_CPU_1G_PAGES;
1073
  }
1074
 
1075
#if BX_SUPPORT_SVM
1076
  static bx_bool svm_enabled = SIM->get_param_bool(BXPN_CPUID_SVM)->get();
1077
  if (svm_enabled) {
1078
    features_bitmask |= BX_CPU_ALT_MOV_CR8 | BX_CPU_XAPIC_EXT; // auto-enable together with SVM
1079
    if (! x86_64_enabled) {
1080
      BX_PANIC(("PANIC: SVM emulation requires x86-64 support !"));
1081
      return;
1082
    }
1083
  }
1084
#endif
1085
 
1086
#endif // BX_SUPPORT_X86_64
1087
 
1088
#endif // CPU_LEVEL >= 6
1089
 
1090
#endif // CPU_LEVEL >= 5
1091
 
1092
  this->cpu_extensions_bitmask = features_bitmask;
1093
}
1094
 
1095
#if BX_SUPPORT_VMX
1096
void bx_generic_cpuid_t::init_vmx_extensions_bitmask(void)
1097
{
1098
  Bit32u features_bitmask = 0;
1099
 
1100
  static unsigned vmx_enabled = SIM->get_param_num(BXPN_CPUID_VMX)->get();
1101
  if (vmx_enabled) {
1102
    features_bitmask |= BX_VMX_VIRTUAL_NMI;
1103
 
1104
    static bx_bool x86_64_enabled = SIM->get_param_bool(BXPN_CPUID_X86_64)->get();
1105
    if (x86_64_enabled) {
1106
      features_bitmask |= BX_VMX_TPR_SHADOW |
1107
                          BX_VMX_APIC_VIRTUALIZATION |
1108
                          BX_VMX_WBINVD_VMEXIT;
1109
 
1110
#if BX_SUPPORT_VMX >= 2
1111
      if (vmx_enabled >= 2) {
1112
        features_bitmask |= BX_VMX_PREEMPTION_TIMER |
1113
                            BX_VMX_PAT |
1114
                            BX_VMX_EFER |
1115
                            BX_VMX_EPT |
1116
                            BX_VMX_VPID |
1117
                            BX_VMX_UNRESTRICTED_GUEST |
1118
                            BX_VMX_DESCRIPTOR_TABLE_EXIT |
1119
                            BX_VMX_X2APIC_VIRTUALIZATION |
1120
                            BX_VMX_PAUSE_LOOP_EXITING |
1121
                            BX_VMX_EPT_ACCESS_DIRTY |
1122
                            BX_VMX_VINTR_DELIVERY |
1123
                            BX_VMX_VMCS_SHADOWING |
1124
                            BX_VMX_EPTP_SWITCHING | BX_VMX_EPT_EXCEPTION;
1125
 
1126
        features_bitmask |= BX_VMX_SAVE_DEBUGCTL_DISABLE |
1127
                         /* BX_VMX_MONITOR_TRAP_FLAG | */ // not implemented yet
1128
                            BX_VMX_PERF_GLOBAL_CTRL;
1129
      }
1130
#endif
1131
    }
1132
  }
1133
 
1134
  this->vmx_extensions_bitmask = features_bitmask;
1135
}
1136
#endif
1137
 
1138
#if BX_SUPPORT_SVM
1139
void bx_generic_cpuid_t::init_svm_extensions_bitmask(void)
1140
{
1141
  Bit32u features_bitmask = 0;
1142
 
1143
  static bx_bool svm_enabled = SIM->get_param_bool(BXPN_CPUID_SVM)->get();
1144
  if (svm_enabled) {
1145
    features_bitmask = BX_CPUID_SVM_NESTED_PAGING |
1146
                       BX_CPUID_SVM_NRIP_SAVE;
1147
  }
1148
 
1149
  this->svm_extensions_bitmask = features_bitmask;
1150
}
1151
#endif
1152
 
1153
/*
1154
 * Get CPU version information:
1155
 *
1156
 * [3:0]   Stepping ID
1157
 * [7:4]   Model: starts at 1
1158
 * [11:8]  Family: 4=486, 5=Pentium, 6=PPro, ...
1159
 * [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved
1160
 * [19:16] Extended Model
1161
 * [27:29] Extended Family
1162
 */
1163
 
1164
Bit32u bx_generic_cpuid_t::get_cpu_version_information(void) const
1165
{
1166
  static Bit32u level = SIM->get_param_num(BXPN_CPUID_LEVEL)->get();
1167
  static Bit32u stepping = SIM->get_param_num(BXPN_CPUID_STEPPING)->get();
1168
  static Bit32u model = SIM->get_param_num(BXPN_CPUID_MODEL)->get();
1169
  static Bit32u family = SIM->get_param_num(BXPN_CPUID_FAMILY)->get();
1170
 
1171
  if (family < 6 && family != level)
1172
    BX_PANIC(("PANIC: CPUID family %x not matching configured cpu level %d", family, level));
1173
 
1174
  return ((family & 0xfff0) << 16) |
1175
         ((model & 0xf0) << 12) |
1176
         ((family & 0x0f) << 8) |
1177
         ((model & 0x0f) << 4) | stepping;
1178
}
1179
 
1180
#if BX_CPU_LEVEL >= 6
1181
 
1182
/* Get CPU extended feature flags. */
1183
Bit32u bx_generic_cpuid_t::get_extended_cpuid_features(void) const
1184
{
1185
  // [0:0]   SSE3: SSE3 Instructions
1186
  // [1:1]   PCLMULQDQ Instruction support
1187
  // [2:2]   DTES64: 64-bit DS area
1188
  // [3:3]   MONITOR/MWAIT support
1189
  // [4:4]   DS-CPL: CPL qualified debug store
1190
  // [5:5]   VMX: Virtual Machine Technology
1191
  // [6:6]   SMX: Secure Virtual Machine Technology
1192
  // [7:7]   EST: Enhanced Intel SpeedStep Technology
1193
  // [8:8]   TM2: Thermal Monitor 2
1194
  // [9:9]   SSSE3: SSSE3 Instructions
1195
  // [10:10] CNXT-ID: L1 context ID
1196
  // [11:11] reserved
1197
  // [12:12] FMA Instructions support
1198
  // [13:13] CMPXCHG16B: CMPXCHG16B instruction support
1199
  // [14:14] xTPR update control
1200
  // [15:15] PDCM - Perfon and Debug Capability MSR
1201
  // [16:16] reserved
1202
  // [17:17] PCID: Process Context Identifiers
1203
  // [18:18] DCA - Direct Cache Access
1204
  // [19:19] SSE4.1 Instructions
1205
  // [20:20] SSE4.2 Instructions
1206
  // [21:21] X2APIC
1207
  // [22:22] MOVBE instruction
1208
  // [23:23] POPCNT instruction
1209
  // [24:24] TSC Deadline
1210
  // [25:25] AES Instructions
1211
  // [26:26] XSAVE extensions support
1212
  // [27:27] OSXSAVE support
1213
  // [28:28] AVX extensions support
1214
  // [29:29] AVX F16C - Float16 conversion support
1215
  // [30:30] RDRAND instruction
1216
  // [31:31] reserved
1217
 
1218
  Bit32u features = 0;
1219
 
1220
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE3))
1221
    features |= BX_CPUID_EXT_SSE3;
1222
 
1223
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AES_PCLMULQDQ))
1224
    features |= BX_CPUID_EXT_PCLMULQDQ;
1225
 
1226
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MONITOR_MWAIT))
1227
    features |= BX_CPUID_EXT_MONITOR_MWAIT;
1228
 
1229
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_VMX))
1230
    features |= BX_CPUID_EXT_VMX;
1231
 
1232
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSSE3))
1233
    features |= BX_CPUID_EXT_SSSE3;
1234
 
1235
#if BX_SUPPORT_X86_64
1236
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE))
1237
    features |= BX_CPUID_EXT_CMPXCHG16B;
1238
 
1239
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PCID))
1240
    features |= BX_CPUID_EXT_PCID;
1241
#endif
1242
 
1243
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE4_1))
1244
    features |= BX_CPUID_EXT_SSE4_1;
1245
 
1246
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE4_2))
1247
    features |= BX_CPUID_EXT_SSE4_2;
1248
 
1249
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_X2APIC))
1250
    features |= BX_CPUID_EXT_X2APIC;
1251
 
1252
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MOVBE))
1253
    features |= BX_CPUID_EXT_MOVBE;
1254
 
1255
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_POPCNT))
1256
    features |= BX_CPUID_EXT_POPCNT;
1257
 
1258
  // support for AES
1259
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AES_PCLMULQDQ))
1260
    features |= BX_CPUID_EXT_AES;
1261
 
1262
  // support XSAVE extensions
1263
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVE)) {
1264
    features |= BX_CPUID_EXT_XSAVE;
1265
    if (cpu->cr4.get_OSXSAVE())
1266
      features |= BX_CPUID_EXT_OSXSAVE;
1267
  }
1268
 
1269
#if BX_SUPPORT_AVX
1270
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AVX))
1271
    features |= BX_CPUID_EXT_AVX;
1272
 
1273
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AVX_F16C))
1274
    features |= BX_CPUID_EXT_AVX_F16C;
1275
 
1276
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AVX_FMA))
1277
    features |= BX_CPUID_EXT_FMA;
1278
#endif
1279
 
1280
  return features;
1281
}
1282
 
1283
#endif
1284
 
1285
/* Get CPU feature flags. Returned by CPUID functions 1 and 80000001.  */
1286
Bit32u bx_generic_cpuid_t::get_std_cpuid_features(void) const
1287
{
1288
  //   [0:0]   FPU on chip
1289
  //   [1:1]   VME: Virtual-8086 Mode enhancements
1290
  //   [2:2]   DE: Debug Extensions (I/O breakpoints)
1291
  //   [3:3]   PSE: Page Size Extensions
1292
  //   [4:4]   TSC: Time Stamp Counter
1293
  //   [5:5]   MSR: RDMSR and WRMSR support
1294
  //   [6:6]   PAE: Physical Address Extensions
1295
  //   [7:7]   MCE: Machine Check Exception
1296
  //   [8:8]   CXS: CMPXCHG8B instruction
1297
  //   [9:9]   APIC: APIC on Chip
1298
  //   [10:10] Reserved
1299
  //   [11:11] SYSENTER/SYSEXIT support
1300
  //   [12:12] MTRR: Memory Type Range Reg
1301
  //   [13:13] PGE/PTE Global Bit
1302
  //   [14:14] MCA: Machine Check Architecture
1303
  //   [15:15] CMOV: Cond Mov/Cmp Instructions
1304
  //   [16:16] PAT: Page Attribute Table
1305
  //   [17:17] PSE-36: Physical Address Extensions
1306
  //   [18:18] PSN: Processor Serial Number
1307
  //   [19:19] CLFLUSH: CLFLUSH Instruction support
1308
  //   [20:20] Reserved
1309
  //   [21:21] DS: Debug Store
1310
  //   [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities
1311
  //   [23:23] MMX Technology
1312
  //   [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
1313
  //   [25:25] SSE: SSE Extensions
1314
  //   [26:26] SSE2: SSE2 Extensions
1315
  //   [27:27] Self Snoop
1316
  //   [28:28] Hyper Threading Technology
1317
  //   [29:29] TM: Thermal Monitor
1318
  //   [30:30] Reserved
1319
  //   [31:31] PBE: Pending Break Enable
1320
 
1321
  Bit32u features = 0;
1322
 
1323
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_X87))
1324
    features |= BX_CPUID_STD_X87;
1325
 
1326
#if BX_CPU_LEVEL >= 5
1327
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_PENTIUM)) {
1328
    // Pentium only features
1329
    features |= BX_CPUID_STD_TSC;
1330
    features |= BX_CPUID_STD_MSR;
1331
    // support Machine Check
1332
    features |= BX_CPUID_STD_MCE | BX_CPUID_STD_MCA;
1333
    features |= BX_CPUID_STD_CMPXCHG8B;
1334
  }
1335
 
1336
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_VME))
1337
    features |= BX_CPUID_STD_VME;
1338
 
1339
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_DEBUG_EXTENSIONS))
1340
    features |= BX_CPUID_STD_DEBUG_EXTENSIONS;
1341
 
1342
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PSE))
1343
    features |= BX_CPUID_STD_PSE;
1344
#endif
1345
 
1346
#if BX_SUPPORT_APIC
1347
  // if MSR_APICBASE APIC Global Enable bit has been cleared,
1348
  // the CPUID feature flag for the APIC is set to 0.
1349
  if (cpu->msr.apicbase & 0x800)
1350
    features |= BX_CPUID_STD_APIC; // APIC on chip
1351
#endif
1352
 
1353
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SYSENTER_SYSEXIT))
1354
    features |= BX_CPUID_STD_SYSENTER_SYSEXIT;
1355
 
1356
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CLFLUSH))
1357
    features |= BX_CPUID_STD_CLFLUSH;
1358
 
1359
#if BX_CPU_LEVEL >= 5
1360
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MMX))
1361
    features |= BX_CPUID_STD_MMX;
1362
#endif
1363
 
1364
#if BX_CPU_LEVEL >= 6
1365
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_P6)) {
1366
    features |= BX_CPUID_STD_CMOV;
1367
    features |= BX_CPUID_STD_ACPI;
1368
  }
1369
 
1370
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_MTRR))
1371
    features |= BX_CPUID_STD_MTRR;
1372
 
1373
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PAT))
1374
    features |= BX_CPUID_STD_PAT;
1375
 
1376
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PAE))
1377
    features |= BX_CPUID_STD_PAE;
1378
 
1379
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PGE))
1380
    features |= BX_CPUID_STD_GLOBAL_PAGES;
1381
 
1382
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PSE36))
1383
    features |= BX_CPUID_STD_PSE36;
1384
 
1385
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE))
1386
    features |= BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE;
1387
 
1388
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE2))
1389
    features |= BX_CPUID_STD_SSE2;
1390
 
1391
  if (BX_CPU_VENDOR_INTEL)
1392
    features |= BX_CPUID_STD_SELF_SNOOP;
1393
//AO#endif
1394
//AO new
1395
  features |= BX_CPUID_STD_HT;
1396
#endif
1397
//AO new
1398
  return features;
1399
}
1400
 
1401
#if BX_CPU_LEVEL >= 6
1402
 
1403
/* Get CPU feature flags. Returned by CPUID function 80000001 in EDX register */
1404
Bit32u bx_generic_cpuid_t::get_std2_cpuid_features(void) const
1405
{
1406
  // Many of the bits in EDX are the same as EAX [*] for AMD
1407
  // [*] [0:0]   FPU on chip
1408
  // [*] [1:1]   VME: Virtual-8086 Mode enhancements
1409
  // [*] [2:2]   DE: Debug Extensions (I/O breakpoints)
1410
  // [*] [3:3]   PSE: Page Size Extensions
1411
  // [*] [4:4]   TSC: Time Stamp Counter
1412
  // [*] [5:5]   MSR: RDMSR and WRMSR support
1413
  // [*] [6:6]   PAE: Physical Address Extensions
1414
  // [*] [7:7]   MCE: Machine Check Exception
1415
  // [*] [8:8]   CXS: CMPXCHG8B instruction
1416
  // [*] [9:9]   APIC: APIC on Chip
1417
  //     [10:10] Reserved
1418
  //     [11:11] SYSCALL/SYSRET support
1419
  // [*] [12:12] MTRR: Memory Type Range Reg
1420
  // [*] [13:13] PGE/PTE Global Bit
1421
  // [*] [14:14] MCA: Machine Check Architecture
1422
  // [*] [15:15] CMOV: Cond Mov/Cmp Instructions
1423
  // [*] [16:16] PAT: Page Attribute Table
1424
  // [*] [17:17] PSE-36: Physical Address Extensions
1425
  //     [18:19] Reserved
1426
  //     [20:20] No-Execute page protection
1427
  //     [21:21] Reserved
1428
  //     [22:22] AMD MMX Extensions
1429
  // [*] [23:23] MMX Technology
1430
  // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
1431
  //     [25:25] Fast FXSAVE/FXRSTOR mode support
1432
  //     [26:26] 1G paging support
1433
  //     [27:27] Support RDTSCP Instruction
1434
  //     [28:28] Reserved
1435
  //     [29:29] Long Mode
1436
  //     [30:30] AMD 3DNow! Extensions
1437
  //     [31:31] AMD 3DNow! Instructions
1438
  Bit32u features = BX_CPU_VENDOR_INTEL ? 0 : get_std_cpuid_features();
1439
  features &= 0x0183F3FF;
1440
#if BX_SUPPORT_3DNOW
1441
  // only AMD is interesting in AMD MMX extensions
1442
  features |= BX_CPUID_STD2_AMD_MMX_EXT | BX_CPUID_STD2_3DNOW_EXT | BX_CPUID_STD2_3DNOW;
1443
#endif
1444
#if BX_SUPPORT_X86_64
1445
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) {
1446
    features |= BX_CPUID_STD2_LONG_MODE;
1447
 
1448
    if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_RDTSCP))
1449
      features |= BX_CPUID_STD2_RDTSCP;
1450
    if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_NX))
1451
      features |= BX_CPUID_STD2_NX;
1452
    if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_FFXSR))
1453
      features |= BX_CPUID_STD2_FFXSR;
1454
    if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_1G_PAGES))
1455
      features |= BX_CPUID_STD2_1G_PAGES;
1456
 
1457
    if (cpu->long64_mode())
1458
      features |= BX_CPUID_STD2_SYSCALL_SYSRET;
1459
  }
1460
#endif
1461
 
1462
  return features;
1463
}
1464
 
1465
/* Get CPU feature flags. Returned by CPUID function 80000001 in ECX register */
1466
Bit32u bx_generic_cpuid_t::get_ext2_cpuid_features(void) const
1467
{
1468
  // ECX:
1469
  //   [0:0]   LAHF/SAHF instructions support in 64-bit mode
1470
  //   [1:1]   CMP_Legacy: Core multi-processing legacy mode (AMD)
1471
  //   [2:2]   SVM: Secure Virtual Machine (AMD)
1472
  //   [3:3]   Extended APIC Space
1473
  //   [4:4]   AltMovCR8: LOCK MOV CR0 means MOV CR8
1474
  //   [5:5]   LZCNT: LZCNT instruction support
1475
  //   [6:6]   SSE4A: SSE4A Instructions support (deprecated?)
1476
  //   [7:7]   Misaligned SSE support
1477
  //   [8:8]   PREFETCHW: PREFETCHW instruction support
1478
  //   [9:9]   OSVW: OS visible workarounds (AMD)
1479
  //   [10:10] IBS: Instruction based sampling
1480
  //   [11:11] XOP: Extended Operations Support and XOP Prefix
1481
  //   [12:12] SKINIT support
1482
  //   [13:13] WDT: Watchdog timer support
1483
  //   [14:14] reserved
1484
  //   [15:15] LWP: Light weight profiling
1485
  //   [16:16] FMA4: Four-operand FMA instructions support
1486
  //   [18:17] reserved
1487
  //   [19:19] NodeId: Indicates support for NodeId MSR (0xc001100c)
1488
  //   [20:20] reserved
1489
  //   [21:21] TBM: trailing bit manipulation instructions support
1490
  //   [22:22] Topology extensions support
1491
  //   [31:23] reserved
1492
 
1493
  Bit32u features = 0;
1494
 
1495
#if BX_SUPPORT_X86_64
1496
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE))
1497
    features |= BX_CPUID_EXT2_LAHF_SAHF | BX_CPUID_EXT2_PREFETCHW;
1498
#endif
1499
 
1500
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_MISALIGNED_SSE))
1501
    features |= BX_CPUID_EXT2_MISALIGNED_SSE;
1502
 
1503
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_LZCNT))
1504
    features |= BX_CPUID_EXT2_LZCNT;
1505
 
1506
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE4A))
1507
    features |= BX_CPUID_EXT2_SSE4A;
1508
 
1509
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XOP))
1510
    features |= BX_CPUID_EXT2_XOP;
1511
 
1512
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_FMA4))
1513
    features |= BX_CPUID_EXT2_FMA4;
1514
 
1515
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_TBM))
1516
    features |= BX_CPUID_EXT2_TBM;
1517
 
1518
  return features;
1519
}
1520
 
1521
Bit32u bx_generic_cpuid_t::get_ext3_cpuid_features(void) const
1522
{
1523
  Bit32u features = 0;
1524
 
1525
  //   [0:0]    FS/GS BASE access instructions
1526
  //   [2:1]    reserved
1527
  //   [3:3]    BMI1: Advanced Bit Manipulation Extensions
1528
  //   [4:4]    HLE: Hardware Lock Elision
1529
  //   [5:5]    AVX2
1530
  //   [6:6]    reserved
1531
  //   [7:7]    SMEP: Supervisor Mode Execution Protection
1532
  //   [8:8]    BMI2: Advanced Bit Manipulation Extensions
1533
  //   [9:9]    Support for Enhanced REP MOVSB/STOSB
1534
  //   [10:10]  Support for INVPCID instruction
1535
  //   [11:11]  RTM: Restricted Transactional Memory
1536
  //   [17:12]  reserved
1537
  //   [18:18]  RDSEED instruction support
1538
  //   [19:19]  ADCX/ADOX instructions support
1539
  //   [20:20]  SMAP: Supervisor Mode Access Prevention
1540
  //   [31:21]  reserved
1541
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_FSGSBASE))
1542
    features |= BX_CPUID_EXT3_FSGSBASE;
1543
 
1544
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_BMI1))
1545
    features |= BX_CPUID_EXT3_BMI1;
1546
 
1547
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AVX2))
1548
    features |= BX_CPUID_EXT3_AVX2;
1549
 
1550
  if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_SMEP))
1551
    features |= BX_CPUID_EXT3_SMEP;
1552
 
1553
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_BMI2))
1554
    features |= BX_CPUID_EXT3_BMI2;
1555
 
1556
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_INVPCID))
1557
    features |= BX_CPUID_EXT3_INVPCID;
1558
 
1559
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ADX))
1560
    features |= BX_CPUID_EXT3_ADX;
1561
 
1562
  if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SMAP))
1563
    features |= BX_CPUID_EXT3_SMAP;
1564
 
1565
  return features;
1566
}
1567
 
1568
#endif
1569
 
1570
void bx_generic_cpuid_t::dump_cpuid(void) const
1571
{
1572
  struct cpuid_function_t leaf;
1573
  unsigned n;
1574
 
1575
  for (n=0; n <= max_std_leaf; n++) {
1576
    get_cpuid_leaf(n, 0x00000000, &leaf);
1577
    BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx));
1578
  }
1579
 
1580
#if BX_CPU_LEVEL >= 6
1581
  if (max_ext_leaf > 0) {
1582
    for (n=0x80000000; n <= max_ext_leaf; n++) {
1583
      get_cpuid_leaf(n, 0x00000000, &leaf);
1584
      BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx));
1585
    }
1586
  }
1587
#endif
1588
}
1589
 
1590
bx_cpuid_t *create_bx_generic_cpuid(BX_CPU_C *cpu) { return new bx_generic_cpuid_t(cpu); }
1591
 
1592
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.