diff options
author | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2010-07-28 19:08:04 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2010-07-28 19:08:04 -0700 |
commit | 056659263eaebb716eee839054e540cb83e3381b (patch) | |
tree | cc2784954954b5bf684077b1c2b405eb59f97acd /parse-opcodes | |
parent | 491e8f77c1e8fb1d2dce0df5e7f12000ce1da859 (diff) |
[sim,xcc] Changed instruction format to RISC-V
Massive changes to gcc, binutils to support new instruction encoding.
Simulator reflects these changes.
Diffstat (limited to 'parse-opcodes')
-rwxr-xr-x | parse-opcodes | 226 |
1 files changed, 137 insertions, 89 deletions
diff --git a/parse-opcodes b/parse-opcodes index 6c735d3..e9d0249 100755 --- a/parse-opcodes +++ b/parse-opcodes @@ -4,84 +4,105 @@ import math import sys import tokenize -opcode_base = 26 -opcode_size = 6 -funct_base = 0 -funct_size = 6 +match = {} +mask = {} -nopcode = 1 << opcode_size -nfunct = 1 << funct_size -opcodes = nopcode*[None] +args = {} +args['ra'] = (24,20) +args['rb'] = (19,15) +args['rc'] = (4,0) +args['imm27'] = (26,0) +args['imm20'] = (19,0) +args['imm'] = (11,0) +args['shamt'] = (9,5) +args['fmt'] = (9,5) def binary(n, digits=0): rep = bin(n)[2:] return rep if digits == 0 else ('0' * (digits - len(rep))) + rep -def make_latex_table(opcodes, captions, labels, upper_opcode=None): - if upper_opcode is None: print '% Automatically generated by parse-opcodes' - print '\\begin{table}[h]' - print '\\begin{center}' - print '\\begin{tabular}{r|c|c|c|c|c|c|c|c|}' - cols = 8 - print '\\multicolumn{1}{r}{}&', - for i in range(cols): - print '\\multicolumn{1}{c}{%s}' % binary(i,int(math.log(cols,2))),('&' if i < cols-1 else '\\\\\n'), - print '\\cline{2-%d}' % (cols+1) - for opcode, insn in enumerate(opcodes): - if not opcode % cols: print binary(opcode/cols,int(math.log(nopcode/cols,2))),'&', - if isinstance(insn, list): - print 'Table \\ref{table:%s}' % labels[1] % {'opcode':opcode}, - else: - print ' ' if insn is None else insn, - print '&' if (opcode+1) % cols else '\\\\\\cline{2-%d}\n' % (cols+1), - print '\\end{tabular}' - print '\\end{center}' - print '\\caption{%s}' % captions[0] % {'opcode':upper_opcode} - print '\\label{table:%s}' % labels[0] % {'opcode':upper_opcode} - print '\\end{table}' - - for opcode, insn in enumerate(opcodes): - if isinstance(insn, list): - make_latex_table(insn, captions[1:], labels[1:], opcode) - -def make_disasm_table(opcodes, upper_opcode=None): - if upper_opcode is None: print '/* Automatically generated by parse-opcodes */' - for opcode, insn in enumerate(opcodes): - if isinstance(insn, list): - make_disasm_table(insn, opcode) - elif isinstance(insn, basestring): - mask = ((1 << opcode_size)-1) << opcode_base - if upper_opcode is None: - match = opcode << opcode_base - else: - mask |= ((1 << funct_size)-1) << funct_base - match = (upper_opcode << opcode_base) | (opcode << funct_base) - insn = insn.upper().replace('.','_') - print '#define MATCH_%s %s' % (insn, hex(match)) - print '#define MASK_%s %s' % (insn, hex(mask)) - -def make_switch(opcodes, upper_opcode=None): - if upper_opcode is None: print '/* Automatically generated by parse-opcodes */' - pad = '' if upper_opcode is None else ' ' - print '%sswitch(%s)' % (pad,'opcode' if upper_opcode is None else 'funct') - print '%s{' % pad - for opcode, insn in enumerate(opcodes): - if insn is None: continue - print '%s case %d:' % (pad,opcode) - print '%s {' % pad - if isinstance(insn, list): - make_switch(insn, opcode) - else: - insn = insn.lower().replace('.','_') - print '%s #include "insns/%s.h"' % (pad,insn) - print '%s }' % pad - print '%s break;' % pad - print '%s default:' % pad - print '%s {' % pad - print '%s #include "insns/unimp.h"' % pad - print '%s }' % pad - print '%s break;' % pad - print '%s }' % pad +def make_disasm_table(match,mask): + print '/* Automatically generated by parse-opcodes */' + for name,match in match.iteritems(): + name2 = name.upper().replace('.','_') + print '#define MATCH_%s %s' % (name2, hex(match)) + print '#define MASK_%s %s' % (name2, hex(mask[name])) + +def make_switch(match,mask): + opcode_base = 25 + opcode_size = 7 + funct_base = 12 + funct_size = 3 + + opcode_mask = ((1<<(opcode_base+opcode_size))-(1<<opcode_base)) + funct_mask = ((1<<(funct_base+funct_size))-(1<<funct_base)) + + print '/* Automatically generated by parse-opcodes */' + print 'switch((insn.bits >> 0x%x) & 0x%x)' % (opcode_base,(1<<opcode_size)-1) + print '{' + + for opc in range(0,1<<opcode_size): + has_some_instruction = 0 + for name in match.iterkeys(): + if ((opc << opcode_base) & mask[name]) == (match[name] & mask[name] & opcode_mask): + has_some_instruction = 1 + if not has_some_instruction: continue + + print ' case 0x%x:' % opc + print ' {' + done = 0 + for name in match.iterkeys(): + name2 = name.replace('.','_') + # case 0: opcode fully describes insn + if ((opc << opcode_base) & mask[name]) == match[name] and (opcode_mask & mask[name]) == mask[name]: + print ' #include "insns/%s.h"' % name2 + done = 1 + break + + if not done: + print ' switch((insn.bits >> 0x%x) & 0x%x)' % (funct_base,(1<<funct_size)-1) + print ' {' + for funct in range(0,1<<funct_size): + has_some_instruction = 0 + for name in match.iterkeys(): + if (opc << opcode_base | funct << funct_base) == (match[name] & (opcode_mask | funct_mask)): + has_some_instruction = 1 + if not has_some_instruction: continue + print ' case 0x%x:' % funct + print ' {' + done = 0 + for name in match.iterkeys(): + name2 = name.replace('.','_') + # case 1: opcode + funct code completely describe insn + if ((opc << opcode_base | funct << funct_base) & mask[name]) == match[name] and ((opcode_mask | funct_mask) & mask[name]) == mask[name]: + print ' #include "insns/%s.h"' % name2 + print ' break;' + done = 1 + break + if not done: + for name in match.iterkeys(): + name2 = name.replace('.','_') + # case 2: general case: opcode + funct incompletely describe insn + if (opc << opcode_base | funct << funct_base) == (match[name] & (opcode_mask | funct_mask)): + print ' if((insn.bits & 0x%x) == 0x%x)' % (mask[name],match[name]) + print ' {' + print ' #include "insns/%s.h"' % name2 + print ' break;' + print ' }' + print ' #include "insns/unimp.h"' + print ' }' + print ' default:' + print ' {' + print ' #include "insns/unimp.h"' + print ' }' + print ' }' + print ' break;' + print ' }' + print ' default:' + print ' {' + print ' #include "insns/unimp.h"' + print ' }' + print '}' for line in sys.stdin: line = line.partition('#') @@ -89,27 +110,54 @@ for line in sys.stdin: if len(tokens) == 0: continue - assert len(tokens) in [2,3] - - opcode = int(tokens[1],0) - name = tokens[0].strip() - assert opcode < nopcode - assert not isinstance(opcodes[opcode], basestring) - - if len(tokens) == 3: - funct = int(tokens[2],0) - if opcodes[opcode] is None: - opcodes[opcode] = nfunct*[None] - assert not isinstance(opcodes[opcode][funct], basestring) - opcodes[opcode][funct] = name - else: - opcodes[opcode] = name + assert len(tokens) >= 2 + + name = tokens[0] + mymatch = 0 + mymask = 0 + cover = 0 + + for token in tokens[1:len(tokens)]: + if len(token.split('=')) == 2: + tmp = token.split('=') + val = int(tmp[1],0) + if len(tmp[0].split('..')) == 2: + tmp = tmp[0].split('..') + hi = int(tmp[0]) + lo = int(tmp[1]) + if hi <= lo: + sys.exit("%s: bad range %d..%d" % (name,hi,lo)) + else: + hi = lo = int(tmp[0]) + if val >= (1 << (hi-lo+1)): + sys.exit("%s: bad value %d for range %d..%d" % (name,val,hi,lo)) + mymatch = mymatch | (val << lo) + mymask = mymask | ((1<<(hi+1))-(1<<lo)) + if cover & ((1<<(hi+1))-(1<<lo)): + sys.exit("%s: overspecified" % name) + cover = cover | ((1<<(hi+1))-(1<<lo)) + elif token in args: + if cover & ((1<<(args[token][0]+1))-(1<<args[token][1])): + sys.exit("%s: overspecified" % name) + cover = cover | ((1<<(args[token][0]+1))-(1<<args[token][1])) + else: + sys.exit("%s: unknown token %s" % (name,token)); + + if cover != 0xFFFFFFFF: + sys.exit("%s: not all bits are covered" % name) + + for name2,match2 in match.iteritems(): + if (match2 & mymask) == mymatch: + sys.exit("%s and %s overlap" % (name,name2)); + + mask[name] = mymask; + match[name] = mymatch; if sys.argv[1] == '-tex': make_latex_table(opcodes, ['Instructions encoded by opcode field','Instructions encoded by funct field when opcode = %(opcode)d'], ['opcodes','opcode%(opcode)d']) elif sys.argv[1] == '-disasm': - make_disasm_table(opcodes) + make_disasm_table(match,mask) elif sys.argv[1] == '-switch': - make_switch(opcodes) + make_switch(match,mask) else: assert 0 |