def _write_entry(self, entry, write_refs, show_text): has_end_directive = False for directive, value in entry.asm_directives: if directive == AD_END: has_end_directive = True else: self.write_asm_directive(directive, value) if entry.has_ignoreua_directive(TITLE): self.write_asm_directive(AD_IGNOREUA) if entry.ctl == 'i' and entry.blocks[-1].end >= 65536 and not entry.title and all([b.ctl == 'i' for b in entry.blocks]): return for block in entry.bad_blocks: warn('Code block at {} overlaps the following block at {}'.format(self.address_str(block.start, False), self.address_str(block.end, False))) if entry.title: self.write_comment(entry.title) wrote_desc = self._write_entry_description(entry, write_refs) if entry.registers: if not wrote_desc: self._write_empty_paragraph() wrote_desc = True self._write_registers(entry) else: wrote_desc = False self._write_body(entry, wrote_desc, write_refs, show_text) if entry.has_ignoreua_directive(END): self.write_asm_directive(AD_IGNOREUA) self.write_paragraphs(entry.end_comment) if has_end_directive: self.write_asm_directive(AD_END)
def _write_entry(self, entry, write_refs, show_text): if entry.header: for line in entry.header: write_line(line) write_line('') self.write_asm_directives(*entry.asm_directives) self.write_asm_directives(entry.get_ignoreua_directive(TITLE)) if entry.ctl == 'i' and entry.blocks[-1].end >= 65536 and not entry.has_title and all([b.ctl == 'i' for b in entry.blocks]): return for block in entry.bad_blocks: addr1 = self.address_str(block.instructions[-1].address, False) addr2 = self.address_str(block.end, False) warn('Instruction at {} overlaps the following instruction at {}'.format(addr1, addr2)) if entry.has_title: self.write_comment(entry.title) wrote_desc = self._write_entry_description(entry, write_refs) wrote_desc = self._write_registers(entry, wrote_desc) else: wrote_desc = False self._write_body(entry, wrote_desc, write_refs, show_text and entry.ctl != 't') self.write_asm_directives(entry.get_ignoreua_directive(END)) self.write_paragraphs(entry.end_comment) if entry.footer: write_line('') for line in entry.footer: write_line(line)
def _write_entry(self, entry, write_refs, show_text): self.write_asm_directives(*entry.asm_directives) if entry.has_ignoreua_directive(TITLE): self.write_asm_directives(AD_IGNOREUA) if entry.ctl == 'i' and entry.blocks[ -1].end >= 65536 and not entry.title and all( [b.ctl == 'i' for b in entry.blocks]): return for block in entry.bad_blocks: warn('Code block at {} overlaps the following block at {}'.format( self.address_str(block.start, False), self.address_str(block.end, False))) if entry.title: self.write_comment(entry.title) wrote_desc = self._write_entry_description(entry, write_refs) if entry.registers: if not wrote_desc: self._write_empty_paragraph() wrote_desc = True self._write_registers(entry) else: wrote_desc = False self._write_body(entry, wrote_desc, write_refs, show_text) if entry.has_ignoreua_directive(END): self.write_asm_directives(AD_IGNOREUA) self.write_paragraphs(entry.end_comment)
def _write_entry(self, entry, write_refs, show_text): if entry.header: for line in entry.header: write_line(line) write_line('') self.write_asm_directives(*entry.asm_directives) if entry.has_ignoreua_directive(TITLE): self.write_asm_directives(AD_IGNOREUA) if entry.ctl == 'i' and entry.blocks[-1].end >= 65536 and not entry.has_title and all([b.ctl == 'i' for b in entry.blocks]): return for block in entry.bad_blocks: addr1 = self.address_str(block.instructions[-1].address, False) addr2 = self.address_str(block.end, False) warn('Instruction at {} overlaps the following instruction at {}'.format(addr1, addr2)) if entry.has_title: self.write_comment(entry.title) wrote_desc = self._write_entry_description(entry, write_refs) wrote_desc = self._write_registers(entry, wrote_desc) else: wrote_desc = False self._write_body(entry, wrote_desc, write_refs, show_text and entry.ctl != 't') if entry.has_ignoreua_directive(END): self.write_asm_directives(AD_IGNOREUA) self.write_paragraphs(entry.end_comment) if entry.footer: write_line('') for line in entry.footer: write_line(line)
def _parse_instruction(self, line, removed): try: address = get_int_param(line[1:6]) except ValueError: raise SkoolParsingError("Invalid address ({}):\n{}".format( line[1:6], line.rstrip())) original_op = partition_unquoted(line[6:], ';')[0].strip() subbed = max(self.subs) if subbed: operations = [ partition_unquoted(s, ';') for s in self.subs[subbed] ] else: operations = [(original_op, '', '')] self.subs = defaultdict(list, {0: []}) for op, sep, comment in operations: operation = op.strip() or original_op if operation: data = assemble(operation, address) if data: end_address = address + len(data) if address not in removed: self.snapshot[address:end_address] = data self.base_address = min(self.base_address, address) self.end_address = max(self.end_address, end_address) if subbed: removed.update(range(address, end_address)) address = end_address else: warn("Failed to assemble:\n {} {}".format( address, operation)) break original_op = None
def _parse_instruction(self, line): try: address = get_int_param(line[1:6]) except ValueError: raise SkoolParsingError("Invalid address ({}):\n{}".format(line[1:6], line.rstrip())) for sub in self.subs: if sub is not None: operation = sub self.subs = [None] * 4 break else: comment_index = find_unquoted(line, ';', 6) operation = line[7:comment_index].strip() data = assemble(operation, address) if data: end_address = address + len(data) self.snapshot[address:end_address] = data self.base_address = min(self.base_address, address) self.end_address = max(self.end_address, end_address) else: warn("Failed to assemble:\n {} {}".format(address, operation))
def warn(self, s): if self.mode.warn: warn(s)
def parse_ctl(self, ctlfile, min_address=0, max_address=65536): entry_ctl = None f = open_file(ctlfile) for line_no, line in enumerate(f, 1): s_line = line.rstrip() if not s_line: continue try: ctl, start, end, text, lengths, asm_directive = self._parse_ctl_line(s_line, entry_ctl) except CtlParserError as e: warn('Ignoring line {} in {} ({}):\n{}'.format(line_no, ctlfile, e.args[0], s_line)) continue if ctl: ctl = ctl.strip() if ctl.islower(): entry_ctl = ctl if not min_address <= start < max_address: continue if ctl.islower(): self._ctls[start] = ctl self._titles[start] = text elif ctl in 'D': self._descriptions.setdefault(start, []).append(text) self._subctls.setdefault(start, None) elif ctl in 'N': self._mid_block_comments.setdefault(start, []).append(text) self._subctls.setdefault(start, None) elif ctl == 'E': self._end_comments.setdefault(start, []).append(text) elif ctl == 'R': if text: fields = text.split(' ', 1) if len(fields) == 1: fields.append('') self._registers.setdefault(start, []).append(fields) elif ctl == 'M': self._multiline_comments[start] = (end, text) self._subctls.setdefault(start, None) elif ctl == 'L': count = lengths[0][0] if count > 1: if len(lengths) > 1: repeat_entries = lengths[1][0] else: repeat_entries = 0 loop_end = start + count * (end - start) if loop_end > 65536: warn('Loop crosses 64K boundary:\n{}'.format(s_line)) self._loops.append((start, end, count, repeat_entries)) self._subctls[loop_end] = None else: self._subctls[start] = ctl.lower() self._instruction_comments[start] = text if end: self._subctls[end] = None if ctl != 'L' and lengths: self._lengths[start] = lengths[0][1] if len(lengths) > 1: address = start + lengths[0][0] subctl = self._subctls[start] for length, sublengths in lengths[1:]: self._lengths[address] = sublengths self._subctls[address] = subctl address += length if text: self._multiline_comments[start] = (address, text) elif asm_directive: directive, address = asm_directive self._asm_directives.setdefault(address, []).append(directive) f.close() self._terminate_multiline_comments() self._unroll_loops(max_address) self._ctls[max_address] = 'i'
def parse_ctl(self, ctlfile, min_address=0, max_address=65536): ctl_lines = [] with open_file(ctlfile) as f: for line in f: s_line = line.rstrip() if s_line: ctl_lines.append(s_line) if s_line.startswith( ('b', 'c', 'g', 'i', 's', 't', 'u', 'w')): try: address = get_int_param(s_line[1:].lstrip().split( ' ', 1)[0]) if min_address <= address < max_address: self._ctls[address] = s_line[0] except ValueError: pass entry_addresses = sorted(self._ctls) for line_no, s_line in enumerate(ctl_lines, 1): try: ctl, start, end, text, lengths, asm_directive = self._parse_ctl_line( s_line, entry_addresses) except CtlParserError as e: warn('Ignoring line {} in {} ({}):\n{}'.format( line_no, ctlfile, e.args[0], s_line)) continue if ctl: if not min_address <= start < max_address: continue if ctl == '>': if end: self._footers[start].append(text or '') else: self._headers[start].append(text or '') elif ctl.islower(): self._titles[start] = text elif ctl == 'D': self._descriptions.setdefault(start, []).append(text) self._subctls.setdefault(start, None) elif ctl == 'N': self._mid_block_comments.setdefault(start, []).append(text) self._subctls.setdefault(start, None) elif ctl == 'E': self._end_comments.setdefault(start, []).append(text) elif ctl == 'R': if text: fields = text.split(' ', 1) if len(fields) == 1: fields.append('') self._registers.setdefault(start, []).append(fields) elif ctl == 'M': self._multiline_comments[start] = (end, text) self._subctls.setdefault(start, None) elif ctl == 'L': count = lengths[0][0] if count > 1: if len(lengths) > 1: repeat_entries = lengths[1][0] else: repeat_entries = 0 loop_end = start + count * (end - start) if loop_end > 65536: warn('Loop crosses 64K boundary:\n{}'.format( s_line)) self._loops.append((start, end, count, repeat_entries)) self._subctls[loop_end] = None else: self._subctls[start] = ctl.lower() self._instruction_comments[start] = text if end: self._subctls[end] = None if ctl != 'L' and lengths: self._lengths[start] = lengths[0][1] if len(lengths) > 1: address = start + lengths[0][0] subctl = self._subctls[start] for length, sublengths in lengths[1:]: self._lengths[address] = sublengths self._subctls[address] = subctl address += length if text: self._multiline_comments[start] = (address, text) elif asm_directive: directive, address = asm_directive self._asm_directives.setdefault(address, []).append(directive) self._terminate_multiline_comments() self._unroll_loops(max_address) self._ctls[max_address] = 'i'
def _warn(self, message, instruction): if self.warn: warn('{}:\n {}'.format(message, instruction))
def warn(self, s): if self.show_warnings: warn(s)
def parse_ctls(self, ctlfiles, min_address=0, max_address=65536): ctl_lines = [] for ctlfile in ctlfiles: self._parse_ctl_file(ctlfile, ctl_lines, min_address, max_address) entry_addresses = sorted(self._ctls) ctl_addr = None comment = [] for line_no, s_line in enumerate(ctl_lines, 1): try: ctl, start, end, text, lengths, asm_directive = self._parse_ctl_line(s_line, entry_addresses) except CtlParserError as e: warn('Ignoring line {} in {} ({}):\n{}'.format(line_no, ctlfile, e.args[0], s_line)) continue if ctl: if ctl in '.:': if ctl_addr is not None and min_address <= ctl_addr < max_address: comment.append(('.:'.index(ctl), text)) continue ctl_addr = start if not min_address <= start < max_address: continue comment = [(0, text or '')] if ctl == '>': if end: self._footers[start].append(text or '') else: self._headers[start].append(text or '') if text and text.startswith(('@defb=', '@defs=', '@defw=')): self._asm_data_directives[start].append(text[1:]) elif ctl.islower(): self._titles[start] = comment elif ctl == 'D': self._descriptions[start].append(comment) self._subctls.setdefault(start, None) elif ctl == 'N': self._mid_block_comments[start].append(comment) self._subctls.setdefault(start, None) elif ctl == 'E': self._end_comments[start].append(comment) elif ctl == 'R': self._registers[start].append(comment) elif ctl == 'M': self._multiline_comments[start] = (end, comment) self._subctls.setdefault(start, None) elif ctl == 'L': count = lengths[0][0] if count > 1: if len(lengths) > 1: repeat_entries = lengths[1][0] else: repeat_entries = 0 loop_end = start + count * (end - start) if loop_end > 65536: warn('Loop crosses 64K boundary:\n{}'.format(s_line)) self._loops.append((start, end, count, repeat_entries)) self._subctls[loop_end] = None else: self._subctls[start] = ctl.lower() self._instruction_comments[start] = comment if end: self._subctls[end] = None if ctl != 'L' and lengths: self._lengths[start] = lengths[0][1] if len(lengths) > 1: address = start + lengths[0][0] subctl = self._subctls[start] for length, sublengths in lengths[1:]: self._lengths[address] = sublengths self._subctls[address] = subctl address += length self._multiline_comments.setdefault(start, (address, comment)) elif asm_directive: directive, address = asm_directive self._asm_directives[address].append(directive) self._terminate_multiline_comments() self._unroll_loops(max_address) self._ctls[max_address] = 'i'
def parse_ctls(self, ctlfiles, min_address=0, max_address=65536): ctl_lines = [] for ctlfile in ctlfiles: self._parse_ctl_file(ctlfile, ctl_lines, min_address, max_address) entry_addresses = sorted(self._ctls) comment = [] for line_no, s_line in enumerate(ctl_lines, 1): try: ctl, start, end, text, lengths, asm_directive = self._parse_ctl_line(s_line, entry_addresses) except CtlParserError as e: warn('Ignoring line {} in {} ({}):\n{}'.format(line_no, ctlfile, e.args[0], s_line)) continue if ctl: if ctl in '.:': comment.append(('.:'.index(ctl), text)) continue if not min_address <= start < max_address: continue comment = [(0, text or '')] if ctl == '>': if end: self._footers[start].append(text or '') else: self._headers[start].append(text or '') elif ctl.islower(): self._titles[start] = comment elif ctl == 'D': self._descriptions[start].append(comment) self._subctls.setdefault(start, None) elif ctl == 'N': self._mid_block_comments[start].append(comment) self._subctls.setdefault(start, None) elif ctl == 'E': self._end_comments[start].append(comment) elif ctl == 'R': self._registers[start].append(comment) elif ctl == 'M': self._multiline_comments[start] = (end, comment) self._subctls.setdefault(start, None) elif ctl == 'L': count = lengths[0][0] if count > 1: if len(lengths) > 1: repeat_entries = lengths[1][0] else: repeat_entries = 0 loop_end = start + count * (end - start) if loop_end > 65536: warn('Loop crosses 64K boundary:\n{}'.format(s_line)) self._loops.append((start, end, count, repeat_entries)) self._subctls[loop_end] = None else: self._subctls[start] = ctl.lower() self._instruction_comments[start] = comment if end: self._subctls[end] = None if ctl != 'L' and lengths: self._lengths[start] = lengths[0][1] if len(lengths) > 1: address = start + lengths[0][0] subctl = self._subctls[start] for length, sublengths in lengths[1:]: self._lengths[address] = sublengths self._subctls[address] = subctl address += length self._multiline_comments[start] = (address, comment) elif asm_directive: directive, address = asm_directive self._asm_directives[address].append(directive) self._terminate_multiline_comments() self._unroll_loops(max_address) self._ctls[max_address] = 'i'