def parse_insts(f): """ 从文件中解析出所有的指令,生成 Inst 对象并加入到 insts 列表中 假设 ins 文件中指令系统部分不会出现 \xff,故以此为循环结束条件 """ tmp_data = handle_00_byte(f) log(f"开始解析指令部分,当前文件指针的位置为 {f.tell()}") while tmp_data != b'\xff': try: mnemonic_len = read(f)[0] tmp_mnemonic = ''.join([ read(f).decode('ascii') for _ in range(mnemonic_len) ]) tmp_addr = read(f)[0] op_num1 = op_num_map[read(f)] op_num2 = op_num_map[read(f)] tmp_inst = Inst(tmp_mnemonic, tmp_addr, op_num1, op_num2) log(f"解析出指令 {tmp_inst}") insts.append(tmp_inst) handle_int_inst(f, tmp_mnemonic) tmp_data = handle_00_byte(f) except Exception as err: error(f"解析失败,原因 {err}") log("指令部分解析结束")
def decode(self): """Instruction decoder. Returns the number of bytes decoded.""" inst = Inst(myInput = self.input, add = self.pc, mode = self.dis_mode, syntax = self.syntax) self.error = 0 self.input.start () if get_prefixes(self, inst) != 0: pass # ;print('prefixes error') # error elif search_itab(self, inst) != 0: pass #; print('itab error') # error elif do_mode(self, inst) != 0: pass #; print('mode error') # error elif disasm_operands(self, inst) != 0: pass #; print('operand error') # error elif resolve_operator(self, inst) != 0: pass #; print('operator error') # error # Handle decode error. if self.error: inst.clear() inst.size = self.input.ctr + 1 inst.raw = self.input.buffer[0:inst.size] inst.set_pc(inst.add + inst.size) return inst
def load_fd(fd): offsets = { 'const': len(const_table), 'label': len(label_table), 'inst': len(inst_table), } # constants block num_constants = read_int(fd) for _ in range(0, num_constants): const = read_constant(fd) const_table.register(const) # symbols block num_symbols = read_int(fd) symbol_translation = [0] * num_symbols for i in range(0, num_symbols): val = read_str(fd) symbol_translation[i] = sym(val) num_labels = read_int(fd) for _ in range(0, num_labels): name = read_str(fd) addr = read_int(fd) + offsets['inst'] trace = None has_trace = read_int(fd) trace = None if has_trace == 1: trace = read_str(fd) label = Label(name, addr, trace) register_label(label) num_insts = read_int(fd) for i in range(0, num_insts): command = read_str(fd) num_args = read_int(fd) raw_args = [999] * num_args for i in range(0, num_args): raw_args[i] = read_int(fd) inst_type = inst_type_table.get(command) args = inst_type.reindex(raw_args, offsets, symbol_translation) inst_table.register(Inst(inst_type.id, args))
def filter_change(origin_inst, dump_file_content, base, newcode, line_index, reversal_bit_id): """Compare the origin inst and redisassember inst, and record the changed part @:return: It currently presents the judgment of operands' different """ tmp_result2 = code_line_reg.findall(dump_file_content) if not tmp_result2: logging.warning("generated file %s has no legal content" % newcode) tmp_line = tmp_result2[line_index] tmp_inst = Inst(tmp_line) # confirm opcode part if tmp_inst.op != origin_inst.op: logging.info( "Opcode changes: %s => %s when bit [%d] is flipped from [%d]\t\tChange to:%s", origin_inst.op, tmp_inst.op, reversal_bit_id, (base >> reversal_bit_id) & 0x1, tmp_line[0]) # bits = bits | (((base >> i) & 0x1) << i) origin_inst.opcode_positions.append(reversal_bit_id) # confirm modifier part elif tmp_inst.modifier != origin_inst.modifier: logging.info( "Modifier changes: %s => %s when bit [%d] is flipped from [%d]\t\tChange to:%s", origin_inst.modifier, tmp_inst.modifier, reversal_bit_id, (base >> reversal_bit_id) & 0x1, tmp_line[0]) origin_inst.modifier_positions.append(reversal_bit_id) else: len_origin = len(origin_inst.operands) len_tmp = len(tmp_inst.operands) for i in range(min(len_origin, len_tmp)): if origin_inst.operands[i] != tmp_inst.operands[i]: return i, tmp_inst # if len_tmp > len_origin: # return len_origin return None, None
def work(input_file_name, output_file, section_start): global sass_content, ops_bits arch = "sm_75" # for debug # input_file_name = 'gaussian.cubin' init_sass_cubin_files(input_file_name, arch) logging.basicConfig(format="%(message)s", filename="./log/%s" % output_file, filemode="a", level=logging.INFO) logging.info("Time:\t%s" % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) com_lib.kernel_section_start_offset = int(section_start, 16) with open("%s.sass" % os.path.splitext(input_file_name)[0], 'r') as fin: sass_content = fin.read() tmp_result = code_line_reg.findall(sass_content) if not tmp_result: logging.error("Not found pairs") return # @todo: check is there any irregular code # how many lines will be checked. for j, line in enumerate(tmp_result[:1]): logging.info("================================") logging.info("raw line:\t\t%s" % line[0]) a_origin_inst = Inst(line) instructions.append(a_origin_inst) base = a_origin_inst.enc bits = 0x0 origin_operand_types = check_operand_types(a_origin_inst) if FLAG_CHECK_OPERAND: if len(a_origin_inst.operands) and origin_operand_types: logging.info( "Original op and modifier:%s:\t%s" % (a_origin_inst.op, "".join(a_origin_inst.modifier))) logging.info("0b{:0128b}".format(base) + ": " + "".join(a_origin_inst.operands)) logging.info("newcode operand:") # if you just want to check operand, uncomment the following else branch else: continue # In volta and turing, len of the instruction code is 128bitk for i in range(0, 128): # i from right to left mask = 2**i newcode = base ^ mask dump_file_content = dump("0x{:032x}".format(newcode), arch, j) # print(dump_file_content) # Compare the disassemble to check which field changes: opcode, operand or modifer if dump_file_content and dump_file_content.find( "?") == -1 and dump_file_content.find("error") == -1: tmp_pp, tmp_inst = filter_change(a_origin_inst, dump_file_content, base, newcode, j, i) if tmp_pp is not None: # the ith bit affects tmp_ppth operand a_origin_inst.operand_positions[tmp_pp].append(i) # @todo print the reverse bit logging.info("%s: %d\t%s" % ("0b{:0128b}".format(newcode), i, " ".join( tmp_inst.operands))) # if len(positions) > 0: # logging.info("0b{:0128b}".format(bits) + ": %s opcode bits %s: ", origin_inst.op, positions) if len(a_origin_inst.opcode_positions) > 0: ops_bits[a_origin_inst.op] = list( set( ops_bits.get(a_origin_inst.op, []) + a_origin_inst.opcode_positions)) logging.info("Operand combination types: %s", origin_operand_types) for i in range(0, len(a_origin_inst.operand_positions)): if len(origin_operand_types) > i: tmp_type = origin_operand_types[i] else: tmp_type = 'None' logging.info("Operand type: %s", tmp_type) logging.info("Encoding: %s", a_origin_inst.operand_positions[i]) for node in ops_bits: logging.info("%s:\t[%s]", node, ",".join(str(x) for x in ops_bits[node]))
from sets import Set from inst import Inst import subprocess import sys if __name__ == "__main__": opset = Set([]) with open(sys.argv[1]) as f: for line in f: field = line.split() inst = Inst(field, False) if not inst.op() in opset: opset.add(inst.op()) sys.stdout.write(line)
if len(sys.argv) >= 5: limit = sys.argv[4] else: limit = 100 count = 0 version = int(arch.split("_")[1]) with open(sass) as f: for line in f: pos = [] bits = 0x0 count += 1 if count == limit: break line_split = line.split() # Construct instruction structure origin = Inst(line_split) # Find the 64-bit encodings base = int(origin.enc(), 16) # Bit by bit xor, observe whether opcode changes and guess what this bit represent for i in range(0, 64): mask = 2**i newcode = base ^ mask # Disassemble the new code dump_file = dump("0x{:016x}".format(newcode), arch) # Compare the disassemble to check which field changes: opcode, operand or modifer if dump_file and dump_file.find("?") == -1 and dump_file.find( "error") == -1: line = dump_file.split("\n") if version < 40: line_inst = line[1].split() else:
from inst import Inst, asm, print_asm, print_ihex rd = [] for i in range(50): rd.append(i) rs = [] for i in range(50): rs.append(i) seg_pattern = [0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6] program = [ Inst.LUI(5,0x10001000), ] for i in range(10): program.append(Inst.ADDI(rd[6],rs[0],seg_pattern[i])) program.append(Inst.SB(rd[5],rs[6],i)) program_main = [ Inst.LUI(rd[6], 0x04000000), Inst.ADD(rd[7],rs[0],rs[0]), Inst.LW(rd[10], rs[6], 0x48), 'mainloop', Inst.ADD(rd[8],rs[7],rs[5]), Inst.ANDI(rd[11],rs[10],0x01), Inst.LBEQ(rd[11],0,'dontpush'), 'push', Inst.LBU(rd[9],rs[8],0),
from inst import Inst, asm, print_asm, print_ihex program = [ Inst.LUI(5, 0x10000000), # memory = 0x10000000 Inst.ADD(6, 0, 0), # x6 = 0 (counter) 'loop', Inst.SW(5, 6, 0x100), # memory[x5+0x100] = x6 Inst.ADDI(6, 6, 1), # x6++ Inst.LJAL(0, 'loop') # goto loop ] r = asm(program) print_asm(r) print() print_ihex(r)
from inst import Inst, asm, print_asm, print_ihex program = [ Inst.LUI(5, 0x04000000), # r5 に7 セグのアドレスを代入 Inst.ADDI(10, 0, 0x60), # セグ「1」のパタンをr10 に代入 Inst.SB(5, 10, 0x00), # r5[0] = 0x60 (7 セグのアドレスに0x60 をストア) Inst.JAL(0, -4 * 1) # 1 命令前に無条件分岐 ] r = asm(program) print_asm(r) print() print_ihex(r)
_score2 = 22 _counterX = 23 _intervalX = 24 _counterY = 25 _intervalY = 26 _memAddr = 27 _memBase = 28 _count = 29 _tmp2 = 30 # 初期化部分 sys_init = [ Inst.LUI(_addrBase, 0x0400_0000), # addrBase = [0x0400_0000] Inst.ADDI(_wr, _num0, 1), # wr = 1 Inst.SLLI(_wr, _wr, 14), # wr <<= 14 Inst.ADDI(_barY1u, _num0, 1), # barY1u = 1 Inst.ADDI(_barY1d, _num0, 2), # barY1d = 2 Inst.ADDI(_barY2u, _num0, 1), # barY2u = 1 Inst.ADDI(_barY2d, _num0, 2), # barY2d = 2 Inst.ADDI(_velX, _num0, 1), # velX = 1 Inst.ADDI(_velY, _num0, 1), # velY = 1 Inst.ADDI(_score1, _num0, 0), # score1 = 0 Inst.ADDI(_score2, _num0, 0), # score2 = 0 Inst.ADDI(_counterX, _num0, 0), # counterX = 0 Inst.ADDI(_counterY, _num0, 0), # counterY = 0 Inst.ADDI(_intervalX, _num0, 3), # interval = 1 Inst.ADDI(_intervalY, _num0, 3), # interval = 1 Inst.ADDI(_num1, _num0, 1), # num1 = 1
def bin_decode(bin_line): if bin_line == '0': inst = Inst() d = { "op": "pass", "dests": [], "srcs": [] } inst.fromDict(d) return inst op_bits = bin_line[:op_bit] dests = [] srcs = [] op = code.op_inv[int(op_bits, 2)] start_point = op_bit for i in range(3): ns_bits = bin_line[start_point:start_point + ns_bit] ns = code.ns_inv[int(ns_bits, 2)] if ns == "NN": pe_pu_bit = bin_line[start_point + ns_bit + index_bit + nn_nb_bit - 1] if pe_pu_bit == '0': ns = "NN0_out" else: ns = "NN1_out" elif ns == "NB": pe_pu_bit = bin_line[start_point + ns_bit + index_bit + nn_nb_bit - 1] if pe_pu_bit == '0': ns = "NB0_out" else: ns = "NB1_out" index_bits = bin_line[start_point + ns_bit:start_point + ns_bit + index_bit] index = int(index_bits, 2) dest = { "dest_nid": ns, "dest_index": index } dests.append(dest) start_point += (ns_bit + index_bit + nn_nb_bit) for i in range(3): ns_bits = bin_line[start_point:start_point + ns_bit] ns = code.ns_inv[int(ns_bits, 2)] if ns == "NN": pe_pu_bit = bin_line[start_point + ns_bit + index_bit + nn_nb_bit - 1] if pe_pu_bit == '0': ns = "NN0_in" else: ns = "NN1_in" elif ns == "NB": pe_pu_bit = bin_line[start_point + ns_bit + index_bit + nn_nb_bit - 1] if pe_pu_bit == '0': ns = "NB0_in" else: ns = "NB1_in" index_bits = bin_line[start_point + ns_bit:start_point + ns_bit + index_bit] index = int(index_bits, 2) src = { "src_nid": ns, "src_index": index } srcs.append(src) start_point += (ns_bit + index_bit + nn_nb_bit) inst = Inst() d = { "op": op, "dests": dests, "srcs": srcs } inst.fromDict(d) return inst
# 0~9をループするカウンタ ## わかっているクソ仕様 ## SBを一回使用した後にADDIを実行すると機能しない。 ## これを回避するためにはダミーのSBが必要。 from inst import Inst, asm, print_asm, print_ihex program = [ # Store 7seg led patterns Inst.LUI(5, 0x10001000), # memory = 0x10001000 Inst.ADDI(6, 0, 0b11111100), # 7seg: 0 Inst.SB(5, 6, 0x0), Inst.SB(5, 6, 0x1), #dummySB Inst.ADDI(6, 0, 0b01100000), # 1 Inst.SB(5, 6, 0x1), Inst.SB(5, 6, 0x2), #dummySB Inst.ADDI(6, 0, 0b11011010), # 2 Inst.SB(5, 6, 0x2), Inst.SB(5, 6, 0x3), #dummySB Inst.ADDI(6, 0, 0b11110010), # 3 Inst.SB(5, 6, 0x3), Inst.SB(5, 6, 0x4), #dummySB Inst.ADDI(6, 0, 0b01100110), # 4 Inst.SB(5, 6, 0x4), Inst.SB(5, 6, 0x5), #dummySB Inst.ADDI(6, 0, 0b10110110), # 5 Inst.SB(5, 6, 0x5), Inst.SB(5, 6, 0x6), #dummySB Inst.ADDI(6, 0, 0b10111110), # 6 Inst.SB(5, 6, 0x6), Inst.SB(5, 6, 0x7), #dummySB
def disassemble(self, add): try: self.seek(add) return self.decode() except DecodeException: return Inst(self.input)
from inst import Inst, asm, print_asm, print_ihex seg_pattern = [0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6] x_0 = 0 pattern_mem = 5 pattern_tmp = 6 program = [Inst.LUI(pattern_mem, 0x10001000)] for i in range(10): print(seg_pattern[i]) program.append(Inst.ADDI(pattern_tmp, 0, seg_pattern[i])) program.append(Inst.SB(pattern_mem, pattern_tmp, i)) seg = 6 counter = 7 pattern_mem_addr = 8 pattern = 9 max = 15 program_main = [ 'main', Inst.LUI(seg, 0x04000000), Inst.ADDI(counter, x_0, 0), Inst.ADDI(max, x_0, 9), 'loop', Inst.ADD(pattern_mem_addr, counter, pattern_mem), Inst.LBU(pattern, pattern_mem_addr, 0), Inst.SB(seg, pattern, 0), Inst.ADDI(counter, counter, 1), Inst.LBEQ(counter, max, 'reset'),
from inst import Inst, asm, print_asm, print_ihex program = [ # Store 7seg led patterns Inst.LUI(5, 0x10001000), # memory = 0x10001000 Inst.ADDI(6, 0, 0b11111100), # 7seg: 0 Inst.SB(5, 6, 0x0), Inst.ADDI(6, 0, 0b01100000), # 1 Inst.SB(5, 6, 0x1), Inst.ADDI(6, 0, 0b11011010), # 2 Inst.SB(5, 6, 0x2), Inst.ADDI(6, 0, 0b11110010), # 3 Inst.SB(5, 6, 0x3), Inst.ADDI(6, 0, 0b01100110), # 4 Inst.SB(5, 6, 0x4), Inst.ADDI(6, 0, 0b10110110), # 5 Inst.SB(5, 6, 0x5), Inst.ADDI(6, 0, 0b10111110), # 6 Inst.SB(5, 6, 0x6), Inst.ADDI(6, 0, 0b11100000), # 7 Inst.SB(5, 6, 0x7), Inst.ADDI(6, 0, 0b11111110), # 8 Inst.SB(5, 6, 0x8), Inst.ADDI(6, 0, 0b11110110), # 9 Inst.SB(5, 6, 0x9), # Main Inst.LUI(6, 0x04000000), Inst.ADD(7, 0, 0), # x7 = 0 (counter) ’loop’, Inst.ADD(8, 7, 5), # address of memory[x7] Inst.LBU(9, 8, 0), # x9 = memory[x7]
#! /usr/bin/env python3 from inst import Inst filename = 'sample1_7seg.hex' program = [] program.append(Inst.LUI(5, 0x04000000)) program.append(Inst.ADDI(10, 0, 0xff)) program.append(Inst.SB(5, 10, 0x00)) program.append(Inst.JAL(0, -4 * 2)) # generate assembly #print('') print('sample program 1') for i in program: print('{:08x} | {}'.format(i.gen_code(), i.gen_mnemonic())) # generate intel hex format with open(filename, 'w', encoding='utf-8') as file: for offset, inst in enumerate(program): file.write(inst.gen_HEX(offset)) file.write("\n") file.write(':00000001FF\n')
arch = sys.argv[2] if len(sys.argv) >= 5: limit = sys.argv[4] else: limit = 100 count = 0 version = int(arch.split("_")[1]) with open(sass) as f: for line in f: pos = [] count += 1 if count == limit: break line_split = line.split() # Construct instruction structure origin = Inst(line_split) # Find the 64-bit encodings base = int(origin.enc(), 16) # Bit by bit xor, observe whether opcode changes and guess what this bit represent for i in range(0, 64): mask = 2**i newcode = base ^ mask # Disassemble the new code dump_file = dump("0x{:016x}".format(newcode), arch) # Compare the disassemble to check which field changes: opcode, operand or modifer if dump_file and dump_file.find("?") == -1 and dump_file.find( "error") == -1: line = dump_file.split("\n") if version < 40: line_inst = line[1].split() else:
arch = sys.argv[2] if len(sys.argv) >= 5: limit = sys.argv[4] else: limit = 100 count = 0 version = int(arch.split("_")[1]) with open(sys.argv[1]) as f: for line in f: pos = [] count += 1 if count == limit: break line_split = line.split() # Construct instruction structure origin = Inst(line_split) # Find the 64-bit encodings base = int(origin.enc(), 16) origin_operand_types = check_operand_types(origin) if len(origin.operands()) and origin_operand_types.find('X') == -1: pp = [[] for i in range(len(origin_operand_types))] logging.info(origin.op() + " " + origin.modifier()) logging.info("0b{:064b}".format(base) + ": " + origin.operands()) for i in range(0, 64): mask = 2**i newcode = base ^ mask # Disassemble the new code dump_file = dump("0x{:016x}".format(newcode), arch) if dump_file and dump_file.find( "?") == -1 and dump_file.find("error") == -1:
from inst import Inst, asm, print_asm, print_ihex program = [ Inst.LUI(5, 0x04000000), Inst.ADDI(6, 0, 0xFF), Inst.LW(10, 5, 0x48), Inst.ANDI(11, 10, 0x01), Inst.BEQ(11, 0, 0x08), Inst.SB(5, 6, 0x000), Inst.JAL(0, 4), Inst.SB(5, 0, 0x000), Inst.JAL(0, -28) ] r = asm(program) print_asm(r) print() print_ihex(r)