|
def err(string): |
|
print("\033[93m{}\033[0m".format(string)) |
|
def ok(string, end="\n"): |
|
print("\033[92m{}\033[0m".format(string), end=end) |
|
def warning(string): |
|
print("\033[92m{}\033[0m".format(string)) |
|
|
|
class Inst: |
|
def __init__(self, name, FIX_LENGTH = 32): |
|
self.name = name |
|
self.field_map = {} |
|
self.idx = 0 |
|
self.match_macro = None |
|
self.mask_macro = None |
|
self.cFIX_LENGTH = 32 |
|
|
|
def add(self, end, code): |
|
expected_len = end - self.idx + 1 |
|
|
|
if isinstance(code, int): |
|
if code == 0: |
|
self.field_map[end] = 0 |
|
self.idx += expected_len |
|
return True |
|
else: |
|
return self.error("[ERROR] invalid code {} in {}".format(code, self.name)) |
|
|
|
# 0 padding |
|
if len(code) < expected_len: |
|
self.field_map[end] = '0' * (expected_len - len(code)) + code |
|
elif (len(code) == expected_len): |
|
self.field_map[end] = code |
|
else: |
|
return self.error("""[ERROR] it is supposed to get code {} ending at pos {} in {}, but it ends at pos {}""".format( |
|
code, self.idx + expected_len, self.name, len(code) + self.idx)) |
|
|
|
self.idx += expected_len |
|
return True |
|
|
|
def error(self, string): |
|
err(string) |
|
self.field_map = {} |
|
return False |
|
|
|
@staticmethod |
|
def str_to_bin(bin_str, base = 2): |
|
return bin(int(bin_str, base)) |
|
|
|
@staticmethod |
|
def str_to_hex(bin_str, base = 2): |
|
return hex(int(bin_str, base)) |
|
|
|
def adds(self, end_code_pairs = False, show = True): |
|
if isinstance(end_code_pairs, list): |
|
for end, code in end_code_pairs: |
|
if not self.add(end, code): |
|
warning("[Warning] Stop add fields for {}".format(self.name)) |
|
break |
|
|
|
def gen(self, show = True): |
|
if self.mask_macro is not None: |
|
return [self.match_macro, self.mask_macro] |
|
|
|
if len(self.field_map) == 0: |
|
err("[Skip] Haven't set fields in {}".format(self.name)) |
|
return |
|
|
|
# maybe sometimes I do not follow the order |
|
list_field_map = sorted(self.field_map.items(), key=lambda t: t[0]) |
|
opcode = '' |
|
mask = '' |
|
|
|
for k, v in list_field_map: |
|
if v == 0: |
|
opcode = (k-len(opcode)+1) * '0' + opcode |
|
mask = (k-len(mask)+1) * '0' + mask |
|
else: |
|
opcode = v + opcode |
|
mask = (k-len(mask)+1) * '1' + mask |
|
|
|
if len(opcode) != self.cFIX_LENGTH: |
|
err("[ERROR] invalid length of opcode, we expect {}, but we expect {} but got {}!".format(opcode, self.cFIX_LENGTH, len(opcode))) |
|
return |
|
|
|
if len(mask) != self.cFIX_LENGTH: |
|
err("[ERROR] invalid length of mask, we expect {}, but we expect {} but got {}!".format(mask, self.cFIX_LENGTH, len(mask))) |
|
return |
|
|
|
inst_name = self.name.upper() |
|
|
|
self.match_macro = "#define MATCH_{} {}\n".format(inst_name, Inst.str_to_hex(opcode, 2)) |
|
self.mask_macro = "#define MASK_{} {}\n".format(inst_name, Inst.str_to_hex(mask, 2)) |
|
|
|
if show: |
|
ok("{}".format(inst_name)) |
|
ok(self.match_macro, "") |
|
ok(self.mask_macro, "") |
|
print("length : ", len(opcode)) |
|
print("opcoede: ", opcode) |
|
print("mask : ", mask) |
|
|
|
return True |
|
|
|
|
|
if __name__ == "__main__": |
|
file_path = "opcode.txt" |
|
op_p = [6, '1110111'] |
|
|
|
insts = { |
|
"kadd8": Inst("kadd8"), |
|
"kadd16": Inst("kadd16"), |
|
"kadd64": Inst("kadd64"), |
|
"kaddh": Inst("kaddh"), |
|
"kaddw": Inst("kaddw"), |
|
} |
|
|
|
insts["kadd8"].adds([ |
|
# add field by field |
|
op_p, # 0~6 |
|
[11, 0], # 7~11, 0 => reg field, '0' => non-reg field |
|
[14, '0'], # 12~14 |
|
[24, 0], # 15~24 |
|
[31, '1100'] # 25~31 |
|
]) |
|
|
|
insts["kaddh"].adds([ |
|
op_p, # 0~6 |
|
[11, 0], # 7~11 |
|
[14, '001'], # 12~14 |
|
[24, 0], # 15~24 |
|
[31, '10'] # 25~31 |
|
]) |
|
|
|
output = [[inst.match_macro, inst.mask_macro, ] for inst in insts.values() if inst.gen()] |
|
|
|
with open(file_path, "w") as f: |
|
for ret in output: |
|
f.writelines(ret) |