import csv, os, re, subprocess, sys
FILES = """rv_i rv32_i rv64_i rv_m rv64_m rv_a rv64_a rv_f rv64_f rv_d rv64_d
rv_q rv64_q rv_c rv32_c rv64_c rv_c_d rv32_c_f rv_zicsr rv_zifencei rv_system
rv_s rv_sdext rv_zicntr rv_zba rv64_zba rv_zbb rv32_zbb rv64_zbb rv_zbc rv_zbs
rv32_zbs rv64_zbs""".split()
root = sys.argv[1]
ext_dir = os.path.join(root, 'extensions')
fields = {name: (int(hi), int(lo)) for name, hi, lo in csv.reader(open(os.path.join(root, 'arg_lut.csv')), skipinitialspace=True)}
def field_mask(name):
hi, lo = fields[name]
return ((1 << (hi - lo + 1)) - 1) << lo
def parse_line(tokens):
name, rest = tokens[0], tokens[1:]
match = mask = 0
nz, n2 = {}, 0
for t in rest:
m = re.fullmatch(r'(\d+)(?:\.\.(\d+))?=(\w+)', t)
if m:
hi = int(m.group(1)); lo = int(m.group(2) or hi)
bits = ((1 << (hi - lo + 1)) - 1) << lo
match |= (int(m.group(3), 0) << lo) & bits
mask |= bits
continue
if t.endswith('_n0') or t.endswith('_n0_e') or t in ('rd_n2',):
nz[t] = field_mask(t)
if t == 'rd_n2':
n2 = field_mask(t)
nm = re.match(r'c_nz(u?imm\d+)', t)
if nm: nz[nm.group(1)] = nz.get(nm.group(1), 0) | field_mask(t)
return name, match, mask, list(nz.values()), n2
def file_lines(f):
for line in open(os.path.join(ext_dir, f)):
line = line.split('#', 1)[0].strip()
if line:
yield line.split()
def find_def(f, name):
for tokens in file_lines(f):
if tokens[0] == name:
return tokens
raise KeyError(f'{name} not in {f}')
def strip_suffix(name):
return re.sub(r'[._]rv(32|64)$', '', name)
rev = subprocess.run(['git', '-C', root, 'rev-parse', 'HEAD'], capture_output=True, text=True).stdout.strip()
print(f'# Generated by scripts/gen-riscv-opcodes.py from riscv-opcodes {rev}.')
print('# riscv-opcodes is Copyright (c) 2022 RISC-V International, BSD-3-Clause.')
print('# isas name base match mask nonzero not-two')
for f in FILES:
isas = {'rv': '32,64', 'rv32': '32', 'rv64': '64'}[f.split('_')[0]]
for tokens in file_lines(f):
base = '-'
if tokens[0] == '$import':
src, name = tokens[1].split('::')
tokens = find_def(src, name)
elif tokens[0] == '$pseudo_op':
base = strip_suffix(tokens[1].split('::')[1])
tokens = tokens[2:]
name, match, mask, nz, n2 = parse_line(tokens)
nzs = ','.join(f'{m:x}' for m in nz) or '-'
print(f"{isas} {strip_suffix(name)} {base} {match:x} {mask:x} {nzs} {n2:x}" if n2 else
f"{isas} {strip_suffix(name)} {base} {match:x} {mask:x} {nzs} -")