Skip to content

Instantly share code, notes, and snippets.

@ehabkost
Created August 1, 2012 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ehabkost/3229602 to your computer and use it in GitHub Desktop.
Save ehabkost/3229602 to your computer and use it in GitHub Desktop.
Script to convert QEMU cpudefs to C
#!/usr/bin/env python
import re
feature_names = {
'': [
"fpu", "vme", "de", "pse",
"tsc", "msr", "pae", "mce",
"cx8", "apic", None, "sep",
"mtrr", "pge", "mca", "cmov",
"pat", "pse36", "pn", "clflush",
None, "ds", "acpi", "mmx",
"fxsr", "sse", "sse2", "ss",
"ht", "tm", "ia64", "pbe",
],
'ext': [
"pni|sse3", "pclmulqdq|pclmuldq", "dtes64", "monitor",
"ds_cpl", "vmx", "smx", "est",
"tm2", "ssse3", "cid", None,
"fma", "cx16", "xtpr", "pdcm",
None, "pcid", "dca", "sse4.1|sse4_1",
"sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
"tsc-deadline", "aes", "xsave", "osxsave",
"avx", None, None, "hypervisor",
],
'ext2': [
"fpu", "vme", "de", "pse",
"tsc", "msr", "pae", "mce",
"cx8", "apic", None, "syscall",
"mtrr", "pge", "mca", "cmov",
"pat", "pse36", None, None,
"nx|xd", None, "mmxext", "mmx",
"fxsr", "fxsr_opt|ffxsr", "pdpe1gb", "rdtscp",
None, "lm|i64", "3dnowext", "3dnow",
],
'ext3': [
"lahf_lm", "cmp_legacy", "svm", "extapic",
"cr8legacy", "abm", "sse4a", "misalignsse",
"3dnowprefetch", "osvw", "ibs", "xop",
"skinit", "wdt", None, None,
"fma4", None, "cvt16", "nodeid_msr",
None, None, None, None,
None, None, None, None,
None, None, None, None,
],
'kvm': [
"kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", "kvm_asyncpf", None, "kvm_pv_eoi", None,
None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None,
],
'svm': [
"npt", "lbrv", "svm_lock", "nrip_save",
"tsc_scale", "vmcb_clean", "flushbyasid", "decodeassists",
None, None, "pause_filter", None,
"pfthreshold", None, None, None,
None, None, None, None,
None, None, None, None,
None, None, None, None,
None, None, None, None,
],
}
feature_constants = {
'':{
'CPUID_FP87': (1 << 0),
'CPUID_VME': (1 << 1),
'CPUID_DE': (1 << 2),
'CPUID_PSE': (1 << 3),
'CPUID_TSC': (1 << 4),
'CPUID_MSR': (1 << 5),
'CPUID_PAE': (1 << 6),
'CPUID_MCE': (1 << 7),
'CPUID_CX8': (1 << 8),
'CPUID_APIC': (1 << 9),
'CPUID_SEP': (1 << 11),
'CPUID_MTRR': (1 << 12),
'CPUID_PGE': (1 << 13),
'CPUID_MCA': (1 << 14),
'CPUID_CMOV': (1 << 15),
'CPUID_PAT': (1 << 16),
'CPUID_PSE36': (1 << 17),
'CPUID_PN': (1 << 18),
'CPUID_CLFLUSH': (1 << 19),
'CPUID_DTS': (1 << 21),
'CPUID_ACPI': (1 << 22),
'CPUID_MMX': (1 << 23),
'CPUID_FXSR': (1 << 24),
'CPUID_SSE': (1 << 25),
'CPUID_SSE2': (1 << 26),
'CPUID_SS': (1 << 27),
'CPUID_HT': (1 << 28),
'CPUID_TM': (1 << 29),
'CPUID_IA64': (1 << 30),
'CPUID_PBE': (1 << 31),
},
'ext':{
'CPUID_EXT_SSE3': (1 << 0),
'CPUID_EXT_DTES64': (1 << 2),
'CPUID_EXT_MONITOR': (1 << 3),
'CPUID_EXT_DSCPL': (1 << 4),
'CPUID_EXT_VMX': (1 << 5),
'CPUID_EXT_SMX': (1 << 6),
'CPUID_EXT_EST': (1 << 7),
'CPUID_EXT_TM2': (1 << 8),
'CPUID_EXT_SSSE3': (1 << 9),
'CPUID_EXT_CID': (1 << 10),
'CPUID_EXT_CX16': (1 << 13),
'CPUID_EXT_XTPR': (1 << 14),
'CPUID_EXT_PDCM': (1 << 15),
'CPUID_EXT_DCA': (1 << 18),
'CPUID_EXT_SSE41': (1 << 19),
'CPUID_EXT_SSE42': (1 << 20),
'CPUID_EXT_X2APIC': (1 << 21),
'CPUID_EXT_MOVBE': (1 << 22),
'CPUID_EXT_POPCNT': (1 << 23),
'CPUID_EXT_TSC_DEADLINE_TIMER': (1 << 24),
'CPUID_EXT_XSAVE': (1 << 26),
'CPUID_EXT_OSXSAVE': (1 << 27),
'CPUID_EXT_HYPERVISOR': (1 << 31),
},
'ext2':{
'CPUID_EXT2_SYSCALL': (1 << 11),
'CPUID_EXT2_MP': (1 << 19),
'CPUID_EXT2_NX': (1 << 20),
'CPUID_EXT2_MMXEXT': (1 << 22),
'CPUID_EXT2_FFXSR': (1 << 25),
'CPUID_EXT2_PDPE1GB': (1 << 26),
'CPUID_EXT2_RDTSCP': (1 << 27),
'CPUID_EXT2_LM': (1 << 29),
'CPUID_EXT2_3DNOWEXT': (1 << 30),
'CPUID_EXT2_3DNOW': (1 << 31),
},
'ext3':{
'CPUID_EXT3_LAHF_LM': (1 << 0),
'CPUID_EXT3_CMP_LEG': (1 << 1),
'CPUID_EXT3_SVM': (1 << 2),
'CPUID_EXT3_EXTAPIC': (1 << 3),
'CPUID_EXT3_CR8LEG': (1 << 4),
'CPUID_EXT3_ABM': (1 << 5),
'CPUID_EXT3_SSE4A': (1 << 6),
'CPUID_EXT3_MISALIGNSSE': (1 << 7),
'CPUID_EXT3_3DNOWPREFETCH': (1 << 8),
'CPUID_EXT3_OSVW': (1 << 9),
'CPUID_EXT3_IBS': (1 << 10),
'CPUID_EXT3_SKINIT': (1 << 12),
},
'svn':{
'CPUID_SVM_NPT': (1 << 0),
'CPUID_SVM_LBRV': (1 << 1),
'CPUID_SVM_SVMLOCK': (1 << 2),
'CPUID_SVM_NRIPSAVE': (1 << 3),
'CPUID_SVM_TSCSCALE': (1 << 4),
'CPUID_SVM_VMCBCLEAN': (1 << 5),
'CPUID_SVM_FLUSHASID': (1 << 6),
'CPUID_SVM_DECODEASSIST': (1 << 7),
'CPUID_SVM_PAUSEFILTER': (1 << 10),
'CPUID_SVM_PFTHRESHOLD': (1 << 12),
},
}
def item_index(word, i):
for idx,f in enumerate(feature_names[word]):
if f is None:
continue
if i in f.split('|'):
return idx
raise Exception('feature named %s:%s not found' % (word, i))
NEW_DEFINES = {}
def feature_to_constant(word, i):
global NEW_DEFINES
idx = item_index(word, i)
for d in feature_constants[word].keys():
if feature_constants[word][d] == (1 << idx):
return '%s' % (d)
d = 'CPUID_%s_%s' % (word.upper(), i.upper())
NEW_DEFINES[d] = (word, idx)
return d
def translate_features(word, string):
items = string.split()
r = []
for i in items:
r.append(feature_to_constant(word, i))
return r
def test():
assert translate_features('ext', 'movbe x2apic') == ['CPUID_EXT_MOVBE', 'CPUID_EXT_X2APIC']
assert translate_features('ext2', 'lm rdtscp') == ['CPUID_EXT2_LM', 'CPUID_EXT2_RDTSCP']
assert translate_features('ext2', 'i64 rdtscp') == ['CPUID_EXT2_LM', 'CPUID_EXT2_RDTSCP']
def dbg(s, *args):
if len(args):
s = s % args
print >> sys.stderr, s
def parse_model(lines, line_len):
if len(lines) == 0:
return
yield '{'
for l in lines:
dbg('line: %s', l)
l = re.sub('#.*$', '', l) # strip comments at the end
field,value = l.split('=')
field = field.strip()
value = value.strip()
value = value.strip('"')
if field in ['name', 'model_id']:
# simple string fields
yield ' .%s = "%s",' % (field, value)
elif field in ['level', 'xlevel', 'family', 'model', 'stepping']:
# simple integer fields
yield ' .%s = %s,' % (field, value)
elif field == 'vendor':
if value == 'GenuineIntel':
v = 'INTEL'
elif value == 'AuthenticAMD':
v = 'AMD'
else:
raise Exception("don't know how to encode vendor: %s" % (value))
for i in 1,2,3:
yield ' .vendor%d = CPUID_VENDOR_%s_%d,' % (i, v, i)
elif field.startswith('feature_') or field.startswith('extfeature_'):
register = field.split('_')[1]
is_ext = field.startswith('ext')
words = {('edx', False):'',
('ecx', False):'ext',
('edx', True):'ext2',
('ecx', True):'ext3'}
word = words[register,is_ext]
defines = translate_features(word, value)
if defines:
text = ' .%s%sfeatures =' % (word, word and '_' or '')
for i,d in enumerate(defines):
if i > 0:
text += ' |'
last = (i == len(defines) - 1)
if last:
item_len = 1 + len(d) + 1 # make room for ","
else:
item_len = 1 + len(d) + 2 # make room for "| "
if len(text.split('\n')[-1]) + item_len > line_len:
text += '\n '
text += ' '
text += d
text += ','
yield text
else:
raise Exception("Unsupported field: %s" % (field))
yield '},'
def main(f):
models = []
def new_model(l):
models.append(l)
def dump_model(m):
for l in parse_model(m, 80 - 4):
for nl in l.split('\n'):
print ' %s' % (nl)
def dump_models():
for m in models:
dump_model(m)
cur = []
for l in f.xreadlines():
l = l.strip()
if not l:
continue
if l.startswith('#'):
continue
if l == '[cpudef]':
new_model(cur)
cur = []
else:
cur.append(l)
new_model(cur)
#models = reversed(models)
dump_models()
if NEW_DEFINES:
print
print '/* Missing CPUID defines: */'
define_items = NEW_DEFINES.items()
define_items.sort(key = lambda item: (item[1][0],item[1][1]))
for d,(word, idx) in define_items:
print '#define %s (1 << %d)' % (d, idx)
test()
import sys
if len(sys.argv) > 1:
f = open(sys.argv[1], 'r')
else:
f = sys.stdin
main(f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment