#!/usr/bin/python import math import sys import tokenize namelist = [] match = {} mask = {} arguments = {} types = {} arglut = {} arglut['rs2'] = (14,10) arglut['rs1'] = (9,5) arglut['rd'] = (4,0) arglut['rs3'] = (19,15) arglut['imm25'] = (24,0) arglut['imm20'] = (24,5) arglut['imm12'] = (21,10) arglut['imm12lo'] = (4,0) arglut['imm12hi'] = (21,15) arglut['shamt'] = (15,10) arglut['shamtw'] = (14,10) arglut['rm'] = (22,20) typelut = {} # 0=unimp,1=j,2=lui,3=imm,4=r,5=r4,6=ish,7=ishw,10=b typelut[0x00] = 0 typelut[0x60] = 1 typelut[0x61] = 1 typelut[0x62] = 3 typelut[0x63] = 10 typelut[0x71] = 2 typelut[0x74] = 3 typelut[0x75] = 4 typelut[0x76] = 3 typelut[0x77] = 4 typelut[0x78] = 3 typelut[0x79] = 10 typelut[0x7a] = 4 typelut[0x7b] = 4 typelut[0x68] = 3 typelut[0x69] = 10 typelut[0x6a] = 4 typelut[0x6b] = 4 typelut[0x6c] = 5 typelut[0x6d] = 5 typelut[0x6e] = 5 typelut[0x6f] = 5 def binary(n, digits=0): 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])) def make_switch(match,mask): opcode_base = 25 opcode_size = 7 funct_base = 22 funct_size = 3 opcode_mask = ((1<<(opcode_base+opcode_size))-(1<> 0x%x) & 0x%x)' % (opcode_base,(1<> 0x%x) & 0x%x)' % (funct_base,(1<> 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 + ',' ret = ret.replace('imm12lo,imm12hi','imm12') ret = ret.replace(',rm','[,rm]') 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,25,7),7), \ str_arg('imm25','',match,arguments), \ str_inst(name,arguments) \ ) def print_lui_type(name,match,arguments): print """ & \\multicolumn{1}{|c|}{%s} & \\multicolumn{7}{c|}{%s} & \\multicolumn{1}{c|}{%s} & %s \\\\ \\cline{2-10} """ % \ ( \ binary(yank(match,25,7),7), \ str_arg('imm20','',match,arguments), \ str_arg('rd','',match,arguments), \ str_inst(name,arguments) \ ) def print_b_type(name,match,arguments): print """ & \\multicolumn{1}{|c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{3}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & %s \\\\ \\cline{2-10} """ % \ ( \ binary(yank(match,25,7),7), \ binary(yank(match,22,3),3), \ str_arg('imm12hi','',match,arguments), \ str_arg('rs2','',match,arguments), \ str_arg('rs1','',match,arguments), \ str_arg('imm12lo','',match,arguments), \ str_inst(name,arguments) \ ) def print_i_type(name,match,arguments): print """ & \\multicolumn{1}{|c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{4}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & %s \\\\ \\cline{2-10} """ % \ ( \ binary(yank(match,25,7),7), \ binary(yank(match,22,3),3), \ str_arg('imm12','',match,arguments), \ str_arg('rs1','',match,arguments), \ str_arg('rd','',match,arguments), \ str_inst(name,arguments) \ ) def print_ish_type(name,match,arguments): print """ & \\multicolumn{1}{|c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & %s \\\\ \\cline{2-10} """ % \ ( \ binary(yank(match,25,7),7), \ binary(yank(match,22,3),3), \ binary(yank(match,16,6),6), \ str_arg('shamt','',match,arguments), \ str_arg('rs1','',match,arguments), \ str_arg('rd','',match,arguments), \ str_inst(name,arguments) \ ) def print_ishw_type(name,match,arguments): print """ & \\multicolumn{1}{|c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{1}{c|}{0} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & %s \\\\ \\cline{2-10} """ % \ ( \ binary(yank(match,25,7),7), \ binary(yank(match,22,3),3), \ binary(yank(match,16,6),6), \ str_arg('shamtw','',match,arguments), \ str_arg('rd','',match,arguments), \ str_arg('rs1','',match,arguments), \ str_inst(name,arguments) \ ) def print_r_type(name,match,arguments): print """ & \\multicolumn{1}{|c|}{%s} & \\multicolumn{5}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & %s \\\\ \\cline{2-10} """ % \ ( \ binary(yank(match,25,7),7), \ binary(yank(match,15,10),10), \ str_arg('rs2','',match,arguments), \ str_arg('rs1','',match,arguments), \ str_arg('rd','',match,arguments), \ str_inst(name,arguments) \ ) def print_r_rm_type(name,match,arguments): print """ & \\multicolumn{1}{|c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & %s \\\\ \\cline{2-10} """ % \ ( \ binary(yank(match,25,7),7), \ binary(yank(match,23,2),2), \ str_arg('rm','',match,arguments), \ binary(yank(match,15,5),5), \ str_arg('rs2','',match,arguments), \ str_arg('rs1','',match,arguments), \ str_arg('rd','',match,arguments), \ str_inst(name,arguments) \ ) def print_r4_type(name,match,arguments): print """ & \\multicolumn{1}{|c|}{%s} & \\multicolumn{3}{c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & %s \\\\ \\cline{2-10} """ % \ ( \ binary(yank(match,25,7),7), \ binary(yank(match,20,5),5), \ str_arg('rs3','',match,arguments), \ str_arg('rs2','',match,arguments), \ str_arg('rs1','',match,arguments), \ str_arg('rd','',match,arguments), \ str_inst(name,arguments) \ ) def print_r4_rm_type(name,match,arguments): print """ & \\multicolumn{1}{|c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{2}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & \\multicolumn{1}{c|}{%s} & %s \\\\ \\cline{2-10} """ % \ ( \ binary(yank(match,25,7),7), \ binary(yank(match,23,2),2), \ str_arg('rm','',match,arguments), \ str_arg('rs3','',match,arguments), \ str_arg('rs2','',match,arguments), \ str_arg('rs1','',match,arguments), \ str_arg('rd','',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.3in} & \\hspace*{0.1in} & \\hspace*{0.2in} & \\hspace*{0.2in} & \\hspace*{0.1in} & \\hspace*{0.3in} & \\hspace*{0.3in} & \\hspace*{0.3in} \\\\ & \\instbitrange{31}{25} & \\instbitrange{24}{23} & \\instbit{22} & \\instbitrange{21}{20} & \\instbitrange{19}{16} & \\instbit{15} & \\instbitrange{14}{10} & \\instbitrange{9}{5} & \\instbitrange{4}{0} \\\\ \\cline{2-10} & \\multicolumn{1}{|c|}{opcode} & \\multicolumn{8}{c|}{jump target} & J-type \\\\ \\cline{2-10} & \\multicolumn{1}{|c|}{opcode} & \\multicolumn{7}{c|}{LUI-immediate} & \\multicolumn{1}{c|}{rd} & LUI-type \\\\ \\cline{2-10} & \\multicolumn{1}{|c|}{opcode} & \\multicolumn{2}{c|}{funct3} & \\multicolumn{4}{c|}{immediate} & \\multicolumn{1}{c|}{rs1} & \\multicolumn{1}{c|}{rd} & I-type \\\\ \\cline{2-10} & \\multicolumn{1}{|c|}{opcode} & \\multicolumn{2}{c|}{funct3} & \\multicolumn{3}{c|}{immed[11:5]} & \\multicolumn{1}{c|}{rs2} & \\multicolumn{1}{c|}{rs1} & \\multicolumn{1}{c|}{immed[4:0]} & B-type \\\\ \\cline{2-10} & \\multicolumn{1}{|c|}{opcode} & \\multicolumn{5}{c|}{funct10} & \\multicolumn{1}{c|}{rs2} & \\multicolumn{1}{c|}{rs1} & \\multicolumn{1}{c|}{rd} & R-type \\\\ \\cline{2-10} & \\multicolumn{1}{|c|}{opcode} & \\multicolumn{3}{c|}{funct5} & \\multicolumn{2}{c|}{rs3} & \\multicolumn{1}{c|}{rs2} & \\multicolumn{1}{c|}{rs1} & \\multicolumn{1}{c|}{rd} & R4-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,name,type,min,max): for n in namelist: if yank(match[n],25,7) == opcode or n == name: if type == -1 or types[n] == type: if types[n] == 0: print_unimp_type(n,match[n],arguments[n]) elif types[n] == 1: print_j_type(n,match[n],arguments[n]) elif types[n] == 2: print_lui_type(n,match[n],arguments[n]) elif types[n] == 3: print_i_type(n,match[n],arguments[n]) elif types[n] == 4 \ and (min == -1 or yank(match[n],5,10) >= min) \ and (max == -1 or yank(match[n],5,10) <= max): print_r_type(n,match[n],arguments[n]) elif types[n] == 5: print_r4_type(n,match[n],arguments[n]) elif types[n] == 6: print_ish_type(n,match[n],arguments[n]) elif types[n] == 7: print_ishw_type(n,match[n],arguments[n]) elif types[n] == 8: print_r4_rm_type(n,match[n],arguments[n]) elif types[n] == 9: print_r_rm_type(n,match[n],arguments[n]) elif types[n] == 10: print_b_type(n,match[n],arguments[n]) def make_latex_table(): print_header() print_subtitle('Unimplemented Instruction') print_insts(0x00,'',-1,-1,-1) print_subtitle('Control Transfer Instructions') print_insts(0x60,'',-1,-1,-1) print_insts(0x61,'',-1,-1,-1) print_insts(0x62,'',-1,-1,-1) print_insts(0x63,'',-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(0x68,'',-1,-1,-1) print_insts(0x69,'',-1,-1,-1) print_subtitle('Floating-Point Compute Instructions') print_insts(-1,'add.s',-1,-1,-1) print_insts(-1,'sub.s',-1,-1,-1) print_insts(-1,'mul.s',-1,-1,-1) print_insts(-1,'div.s',-1,-1,-1) print_insts(-1,'sqrt.s',-1,-1,-1) print_insts(-1,'add.d',-1,-1,-1) print_insts(-1,'sub.d',-1,-1,-1) print_insts(-1,'mul.d',-1,-1,-1) print_insts(-1,'div.d',-1,-1,-1) print_insts(-1,'sqrt.d',-1,-1,-1) print_insts(-1,'madd.s',-1,-1,-1) print_insts(-1,'msub.s',-1,-1,-1) print_insts(-1,'nmsub.s',-1,-1,-1) print_insts(-1,'nmadd.s',-1,-1,-1) print_insts(-1,'madd.d',-1,-1,-1) print_insts(-1,'msub.d',-1,-1,-1) print_insts(-1,'nmsub.d',-1,-1,-1) print_insts(-1,'nmadd.d',-1,-1,-1) print_footer(0) print_header() print_subtitle('Floating-Point Move \& Conversion Instructions') print_insts(-1,'sgninj.s',-1,-1,-1) print_insts(-1,'sgninjn.s',-1,-1,-1) print_insts(-1,'sgnmul.s',-1,-1,-1) print_insts(-1,'sgninj.d',-1,-1,-1) print_insts(-1,'sgninjn.d',-1,-1,-1) print_insts(-1,'sgnmul.d',-1,-1,-1) print_insts(-1,'cvt.s.d',-1,-1,-1) print_insts(-1,'cvt.d.s',-1,-1,-1) print_subtitle('Integer to Floating-Point Move \& Conversion Instructions') print_insts(-1,'cvt.s.l',-1,-1,-1) print_insts(-1,'cvtu.s.l',-1,-1,-1) print_insts(-1,'cvt.s.w',-1,-1,-1) print_insts(-1,'cvtu.s.w',-1,-1,-1) print_insts(-1,'cvt.d.l',-1,-1,-1) print_insts(-1,'cvtu.d.l',-1,-1,-1) print_insts(-1,'cvt.d.w',-1,-1,-1) print_insts(-1,'cvtu.d.w',-1,-1,-1) print_insts(-1,'mtflh.d',-1,-1,-1) print_insts(-1,'mtf.s',-1,-1,-1) print_insts(-1,'mtf.d',-1,-1,-1) print_subtitle('Floating-Point to Integer Move \& Conversion Instructions') print_insts(-1,'cvt.l.s',-1,-1,-1) print_insts(-1,'cvtu.l.s',-1,-1,-1) print_insts(-1,'cvt.w.s',-1,-1,-1) print_insts(-1,'cvtu.w.s',-1,-1,-1) print_insts(-1,'cvt.l.d',-1,-1,-1) print_insts(-1,'cvtu.l.d',-1,-1,-1) print_insts(-1,'cvt.w.d',-1,-1,-1) print_insts(-1,'cvtu.w.d',-1,-1,-1) print_insts(-1,'mffl.d',-1,-1,-1) print_insts(-1,'mffh.d',-1,-1,-1) print_insts(-1,'mff.s',-1,-1,-1) print_insts(-1,'mff.d',-1,-1,-1) print_footer(0) print_header() print_subtitle('Floating-Point Compare Instructions') print_insts(-1,'c.eq.s',-1,-1,-1) print_insts(-1,'c.lt.s',-1,-1,-1) print_insts(-1,'c.le.s',-1,-1,-1) print_insts(-1,'c.eq.d',-1,-1,-1) print_insts(-1,'c.lt.d',-1,-1,-1) print_insts(-1,'c.le.d',-1,-1,-1) print_subtitle('Miscellaneous Instructions') print_insts(0x7b,'',-1,-1,-1) print_subtitle('Privileged Instructions') print_insts(0x6b,'',-1,-1,-1) print_footer(1) def str_verilog_arg(arg0,arg1,match,arguments): if arg0 in arguments: return '?' * (arglut[arg0][0] - arglut[arg0][1] + 1) elif arg1 in arguments: return '?' * (arglut[arg0][0] - arglut[arg0][1] + 1) else: start = arglut[arg0][1] len = arglut[arg0][0] - arglut[arg0][1] + 1 return binary(yank(match,start,len),len) def print_verilog_unimp_type(name,match,arguments): print "`define %-10s 32'b%s" % \ ( \ name.replace('.','_').upper(), \ '0'*32 \ ) def print_verilog_j_type(name,match,arguments): print "`define %-10s 32'b%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ str_verilog_arg('imm25','',match,arguments) \ ) def print_verilog_lui_type(name,match,arguments): print "`define %-10s 32'b%s_%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ str_verilog_arg('imm20','',match,arguments), \ str_verilog_arg('rd','',match,arguments) \ ) def print_verilog_b_type(name,match,arguments): print "`define %-10s 32'b%s_%s_%s_%s_%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ binary(yank(match,22,3),3), \ str_verilog_arg('imm12hi','',match,arguments), \ str_verilog_arg('rs2','',match,arguments), \ str_verilog_arg('rs1','',match,arguments), \ str_verilog_arg('imm12lo','',match,arguments) \ ) def print_verilog_i_type(name,match,arguments): print "`define %-10s 32'b%s_%s_%s_%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ binary(yank(match,22,3),3), \ str_verilog_arg('imm12','',match,arguments), \ str_verilog_arg('rs1','',match,arguments), \ str_verilog_arg('rd','',match,arguments) \ ) def print_verilog_ish_type(name,match,arguments): print "`define %-10s 32'b%s_%s_%s_%s_%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ binary(yank(match,22,3),3), \ binary(yank(match,16,6),6), \ str_verilog_arg('shamt','',match,arguments), \ str_verilog_arg('rs1','',match,arguments), \ str_verilog_arg('rd','',match,arguments) \ ) def print_verilog_ishw_type(name,match,arguments): print "`define %-10s 32'b%s_%s_%s_0_%s_%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ binary(yank(match,22,3),3), \ binary(yank(match,16,6),6), \ str_verilog_arg('shamtw','',match,arguments), \ str_verilog_arg('rs1','',match,arguments), \ str_verilog_arg('rd','',match,arguments) \ ) def print_verilog_r4_type(name,match,arguments): print "`define %-10s 32'b%s_%s_%s_%s_%s_%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ binary(yank(match,22,3),3), \ binary(yank(match,20,2),2), \ str_verilog_arg('rs3','',match,arguments), \ str_verilog_arg('rs2','',match,arguments), \ str_verilog_arg('rs1','',match,arguments), \ str_verilog_arg('rd','',match,arguments) \ ) def print_verilog_r4_rm_type(name,match,arguments): print "`define %-10s 32'b%s_%s_%s_%s_%s_%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ binary(yank(match,23,2),2), \ str_verilog_arg('rm','',match,arguments), \ str_verilog_arg('rs3','',match,arguments), \ str_verilog_arg('rs2','',match,arguments), \ str_verilog_arg('rs1','',match,arguments), \ str_verilog_arg('rd','',match,arguments) \ ) def print_verilog_r_rm_type(name,match,arguments): print "`define %-10s 32'b%s_%s_%s_%s_%s_%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ binary(yank(match,23,2),2), \ str_verilog_arg('rm','',match,arguments), \ binary(yank(match,15,5),5), \ str_verilog_arg('rs2','',match,arguments), \ str_verilog_arg('rs1','',match,arguments), \ str_verilog_arg('rd','',match,arguments) \ ) def print_verilog_r_type(name,match,arguments): print "`define %-10s 32'b%s_%s_%s_%s_%s" % \ ( \ name.replace('.','_').upper(), \ binary(yank(match,25,7),7), \ binary(yank(match,15,10),10), \ str_verilog_arg('rs2','',match,arguments), \ str_verilog_arg('rs1','',match,arguments), \ str_verilog_arg('rd','',match,arguments) \ ) def make_verilog(): for name in namelist: if types[name] == 0: print_verilog_unimp_type(name,match[name],arguments[name]) elif types[name] == 1: print_verilog_j_type(name,match[name],arguments[name]) elif types[name] == 2: print_verilog_lui_type(name,match[name],arguments[name]) elif types[name] == 3: print_verilog_i_type(name,match[name],arguments[name]) elif types[name] == 4: print_verilog_r_type(name,match[name],arguments[name]) elif types[name] == 5: print_verilog_r4_type(name,match[name],arguments[name]) elif types[name] == 6: print_verilog_ish_type(name,match[name],arguments[name]) elif types[name] == 7: print_verilog_ishw_type(name,match[name],arguments[name]) elif types[name] == 8: print_verilog_r4_rm_type(name,match[name],arguments[name]) elif types[name] == 9: print_verilog_r_rm_type(name,match[name],arguments[name]) elif types[name] == 10: print_verilog_b_type(name,match[name],arguments[name]) 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 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<