summaryrefslogtreecommitdiff
path: root/parse-opcodes
diff options
context:
space:
mode:
authorGravatar Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2010-07-28 19:08:04 -0700
committerGravatar Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2010-07-28 19:08:04 -0700
commit056659263eaebb716eee839054e540cb83e3381b (patch)
treecc2784954954b5bf684077b1c2b405eb59f97acd /parse-opcodes
parent491e8f77c1e8fb1d2dce0df5e7f12000ce1da859 (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-xparse-opcodes226
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