Created
August 1, 2012 18:33
-
-
Save ehabkost/3229602 to your computer and use it in GitHub Desktop.
Script to convert QEMU cpudefs to C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 '/* 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