diff options
author | Yunsup Lee <yunsup@cs.berkeley.edu> | 2010-09-10 18:06:42 -0700 |
---|---|---|
committer | Yunsup Lee <yunsup@cs.berkeley.edu> | 2010-09-10 18:06:42 -0700 |
commit | d57c842302c4ea3a07756ccd2be8684b54c5d478 (patch) | |
tree | 03bc5b29846d5bea94b267fb19730b2684be679b /parse-opcodes | |
parent | 1d3012afdc84df7620e245195704f085add97c41 (diff) | |
download | riscv-opcodes-d57c842302c4ea3a07756ccd2be8684b54c5d478.zip riscv-opcodes-d57c842302c4ea3a07756ccd2be8684b54c5d478.tar.gz riscv-opcodes-d57c842302c4ea3a07756ccd2be8684b54c5d478.tar.bz2 |
[opcodes] latex table generation added, new opcode mapping
Diffstat (limited to 'parse-opcodes')
-rwxr-xr-x | parse-opcodes | 642 |
1 files changed, 500 insertions, 142 deletions
diff --git a/parse-opcodes b/parse-opcodes index a2302d4..10ade79 100755 --- a/parse-opcodes +++ b/parse-opcodes @@ -4,161 +4,519 @@ import math import sys import tokenize +namelist = [] match = {} mask = {} +arguments = {} +types = {} -args = {} -args['ra'] = (24,20) -args['rb'] = (19,15) -args['rc'] = (4,0) -args['rd'] = (9,5) -args['imm27'] = (26,0) -args['imm20'] = (19,0) -args['imm'] = (11,0) -args['shamt'] = (10,5) -args['shamtw'] = (9,5) +arglut = {} +arglut['xa'] = (24,20) +arglut['xb'] = (19,15) +arglut['xc'] = (4,0) +arglut['fa'] = (24,20) +arglut['fb'] = (19,15) +arglut['fc'] = (4,0) +arglut['fd'] = (9,5) +arglut['imm27'] = (26,0) +arglut['imm20'] = (19,0) +arglut['imm'] = (11,0) +arglut['shamt'] = (10,5) +arglut['shamtw'] = (9,5) + +typelut = {} # 0=unimp,1=j,2=lui,3=imm,4=r,5=r4,6=rsh,7=rshw +typelut[0x00] = 0 +typelut[0x60] = 1 +typelut[0x64] = 1 +typelut[0x71] = 2 +typelut[0x73] = 3 +typelut[0x74] = 3 +typelut[0x75] = 4 +typelut[0x76] = 3 +typelut[0x77] = 4 +typelut[0x78] = 3 +typelut[0x79] = 3 +typelut[0x7a] = 4 +typelut[0x7b] = 4 +typelut[0x7e] = 4 +typelut[0x68] = 4 +typelut[0x69] = 3 +typelut[0x6a] = 4 +typelut[0x6b] = 5 def binary(n, digits=0): - rep = bin(n)[2:] - return rep if digits == 0 else ('0' * (digits - len(rep))) + rep + rep = bin(n)[2:] + return rep if digits == 0 else ('0' * (digits - len(rep))) + rep 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])) + 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 '}' + 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 '}' + +def yank(num,start,len): + return (num >> start) & ((1 << len) - 1) + +def str_arg(arg0,arg1,match,arguments): + if arg0 in arguments: + return arg0 + elif arg1 in arguments: + return arg1 + else: + start = arglut[arg0][1] + len = arglut[arg0][0] - arglut[arg0][1] + 1 + return binary(yank(match,start,len),len) + +def str_inst(name,arguments): + ret = name.upper() + ' ' + for idx in range(len(arguments)): + ret = ret + arguments[idx] + if idx != len(arguments)-1: + ret = ret + ',' + return ret + +def print_unimp_type(name,match,arguments): + print """ +& +\\multicolumn{9}{|c|}{%s} & %s \\\\ +\\cline{2-10} + """ % \ + ( \ + '0'*32, \ + 'UNIMP' \ + ) + +def print_j_type(name,match,arguments): + print """ +& +\\multicolumn{1}{|c|}{%s} & +\\multicolumn{8}{c|}{%s} & %s \\\\ +\\cline{2-10} + """ % \ + ( \ + binary(yank(match,27,5),5), \ + str_arg('imm27','',match,arguments), \ + str_inst(name,arguments) \ + ) + +def print_lui_type(name,match,arguments): + print """ +& +\\multicolumn{2}{|c|}{%s} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{6}{c|}{%s} & %s \\\\ +\\cline{2-10} + """ % \ + ( \ + binary(yank(match,25,7),7), \ + str_arg('xa','fa',match,arguments), \ + str_arg('imm20','',match,arguments), \ + str_inst(name,arguments) \ + ) + +def print_i_type(name,match,arguments): + print """ +& +\\multicolumn{2}{|c|}{%s} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{4}{c|}{%s} & %s \\\\ +\\cline{2-10} + """ % \ + ( \ + binary(yank(match,25,7),7), \ + str_arg('xa','fa',match,arguments), \ + str_arg('xb','fb',match,arguments), \ + binary(yank(match,12,3),3), \ + str_arg('imm','',match,arguments), \ + str_inst(name,arguments) \ + ) + +def print_rsh_type(name,match,arguments): + print """ +& +\\multicolumn{2}{|c|}{%s} & +\\multicolumn{1}{c|}{00000} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{2}{c|}{%s} & +\\multicolumn{2}{c|}{%s} & +\\multicolumn{1}{c|}{%s} & %s \\\\ +\\cline{2-10} + """ % \ + ( \ + binary(yank(match,25,7),7), \ + str_arg('xb','',match,arguments), \ + binary(yank(match,11,4),4), \ + str_arg('shamt','',match,arguments), \ + str_arg('xc','',match,arguments), \ + str_inst(name,arguments) \ + ) + +def print_rshw_type(name,match,arguments): + print """ +& +\\multicolumn{2}{|c|}{%s} & +\\multicolumn{1}{c|}{00000} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{2}{c|}{%s} & +\\multicolumn{1}{c|}{0} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{1}{c|}{%s} & %s \\\\ +\\cline{2-10} + """ % \ + ( \ + binary(yank(match,25,7),7), \ + str_arg('xb','',match,arguments), \ + binary(yank(match,11,4),4), \ + str_arg('shamtw','',match,arguments), \ + str_arg('xc','',match,arguments), \ + str_inst(name,arguments) \ + ) + +def print_r4_type(name,match,arguments): + print """ +& +\\multicolumn{2}{|c|}{%s} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{3}{c|}{%s} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{1}{c|}{%s} & %s \\\\ +\\cline{2-10} + """ % \ + ( \ + binary(yank(match,25,7),7), \ + str_arg('fa','',match,arguments), \ + str_arg('fb','',match,arguments), \ + binary(yank(match,10,5),5), \ + str_arg('fd','',match,arguments), \ + str_arg('fc','',match,arguments), \ + str_inst(name,arguments) \ + ) + +def print_r_type(name,match,arguments): + print """ +& +\\multicolumn{2}{|c|}{%s} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{1}{c|}{%s} & +\\multicolumn{4}{c|}{%s} & +\\multicolumn{1}{c|}{%s} & %s \\\\ +\\cline{2-10} + """ % \ + ( \ + binary(yank(match,25,7),7), \ + str_arg('xa','fa',match,arguments), \ + str_arg('xb','fb',match,arguments), \ + binary(yank(match,5,10),10), \ + str_arg('xc','fc',match,arguments), \ + str_inst(name,arguments) \ + ) + +def print_header(): + print """ +\\newpage + +\\begin{table}[p] +\\begin{small} +\\begin{center} +\\begin{tabular}{rcccccccccl} + & +\\hspace*{0.6in} & +\\hspace*{0.2in} & +\\hspace*{0.5in} & +\\hspace*{0.5in} & +\\hspace*{0.3in} & +\\hspace*{0.1in} & +\\hspace*{0.1in} & +\\hspace*{0.5in} & +\\hspace*{0.5in} \\\\ + & +\\instbitrange{31}{27} & +\\instbitrange{26}{25} & +\\instbitrange{24}{20} & +\\instbitrange{19}{15} & +\\instbitrange{14}{12} & +\\instbit{11} & +\\instbit{10} & +\\instbitrange{9}{5} & +\\instbitrange{4}{0} \\\\ +\\cline{2-10} +& +\\multicolumn{1}{|c|}{opcode5} & +\\multicolumn{8}{c|}{jump target} & J-type \\\\ +\\cline{2-10} +& +\\multicolumn{2}{|c|}{opcode} & +\\multicolumn{1}{c|}{ra} & +\\multicolumn{6}{c|}{LUI-immediate} & LUI-type \\\\ +\\cline{2-10} +& +\\multicolumn{2}{|c|}{opcode} & +\\multicolumn{1}{c|}{ra} & +\\multicolumn{1}{c|}{rb} & +\\multicolumn{1}{c|}{funct3} & +\\multicolumn{4}{c|}{immediate} & I-type \\\\ +\\cline{2-10} +& +\\multicolumn{2}{|c|}{opcode} & +\\multicolumn{1}{c|}{00000} & +\\multicolumn{1}{c|}{rb} & +\\multicolumn{2}{c|}{funct4} & +\\multicolumn{2}{c|}{shamt} & +\\multicolumn{1}{c|}{rc} & RSH-type \\\\ +\\cline{2-10} +& +\\multicolumn{2}{|c|}{opcode} & +\\multicolumn{1}{c|}{ra} & +\\multicolumn{1}{c|}{rb} & +\\multicolumn{3}{c|}{funct5} & +\\multicolumn{1}{c|}{rd} & +\\multicolumn{1}{c|}{rc} & R4-type \\\\ +\\cline{2-10} +& +\\multicolumn{2}{|c|}{opcode} & +\\multicolumn{1}{c|}{ra} & +\\multicolumn{1}{c|}{rb} & +\\multicolumn{4}{c|}{funct10} & +\\multicolumn{1}{c|}{rc} & R-type \\\\ +\\cline{2-10} + """ + +def print_subtitle(title): + print """ +& +\\multicolumn{9}{c}{} & \\\\ +& +\\multicolumn{9}{c}{\\bf %s} & \\\\ +\\cline{2-10} + """ % title + +def print_footer(caption): + print """ +\\end{tabular} +\\end{center} +\\end{small} +%s +\\label{instr-table} +\\end{table} + """ % (caption and '\\caption{Instruction listing for RISC-V}' or '') + +def print_insts(opcode,type,min,max): + for name in namelist: + if yank(match[name],25,7) == opcode: + if type == -1 or types[name] == type: + if types[name] == 0: + print_unimp_type(name,match[name],arguments[name]) + elif types[name] == 1: + print_j_type(name,match[name],arguments[name]) + elif types[name] == 2: + print_lui_type(name,match[name],arguments[name]) + elif types[name] == 3: + print_i_type(name,match[name],arguments[name]) + elif types[name] == 4 \ + and (min == -1 or yank(match[name],5,10) >= min) \ + and (max == -1 or yank(match[name],5,10) <= max): + print_r_type(name,match[name],arguments[name]) + elif types[name] == 5: + print_r4_type(name,match[name],arguments[name]) + elif types[name] == 6: + print_rsh_type(name,match[name],arguments[name]) + elif types[name] == 7: + print_rshw_type(name,match[name],arguments[name]) + +def make_latex_table(): + print_header() + print_subtitle('Unimplemented Instruction') + print_insts(0x00,-1,-1,-1) + print_subtitle('Control Instructions') + print_insts(0x60,-1,-1,-1) + print_insts(0x64,-1,-1,-1) + print_insts(0x7b,-1,0x000,0x002) + print_insts(0x73,-1,-1,-1) + print_subtitle('Memory Instructions') + print_insts(0x78,-1,-1,-1) + print_insts(0x79,-1,-1,-1) + print_subtitle('Atomic Memory Instructions') + print_insts(0x7a,-1,-1,-1) + print_footer(0) + + print_header() + print_subtitle('Integer Compute Instructions') + print_insts(0x71,-1,-1,-1) + print_insts(0x74,-1,-1,-1) + print_insts(0x75,-1,-1,-1) + print_subtitle('32-bit Integer Compute Instructions') + print_insts(0x76,-1,-1,-1) + print_insts(0x77,-1,-1,-1) + print_footer(0) + + print_header() + print_subtitle('Floating Point Memory Instructions') + print_insts(0x69,-1,-1,-1) + print_subtitle('Floating Point Compute Instructions') + print_insts(0x68,-1,0x000,0x01F) + print_insts(0x68,-1,0x300,0x31F) + print_insts(0x6b,-1,-1,-1) + print_subtitle('Floating Point Compare Instructions') + print_insts(0x68,-1,0x040,0x05F) + print_insts(0x68,-1,0x340,0x35F) + print_footer(0) + + print_header() + print_subtitle('Integer/Floating Point Moves\&Conversion Instructions') + print_insts(0x68,-1,0x020,0x03F) + print_insts(0x68,-1,0x320,0x33F) + print_insts(0x6a,-1,-1,-1) + print_subtitle('Miscellaneous Instructions') + print_insts(0x7b,-1,0x080,0x300) + print_subtitle('Privileged Instructions') + print_insts(0x7e,-1,-1,-1) + print_footer(1) for line in sys.stdin: - line = line.partition('#') - tokens = line[0].split() - - if len(tokens) == 0: - continue - 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; + line = line.partition('#') + tokens = line[0].split() + + if len(tokens) == 0: + continue + assert len(tokens) >= 2 + + name = tokens[0] + mymatch = 0 + mymask = 0 + cover = 0 + + if not name in arguments.keys(): + arguments[name] = [] + + for token in tokens[1:]: + 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 arglut: + if cover & ((1<<(arglut[token][0]+1))-(1<<arglut[token][1])): + sys.exit("%s: overspecified" % name) + cover = cover | ((1<<(arglut[token][0]+1))-(1<<arglut[token][1])) + + arguments[name].append(token) + 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 + types[name] = typelut[yank(mymatch,25,7)] + if 'shamtw' in arguments[name]: + types[name] = 7 + elif 'shamt' in arguments[name]: + types[name] = 6 + namelist.append(name) 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']) + make_latex_table() elif sys.argv[1] == '-disasm': - make_disasm_table(match,mask) + make_disasm_table(match,mask) elif sys.argv[1] == '-switch': - make_switch(match,mask) + make_switch(match,mask) else: - assert 0 + assert 0 |