import re from file_util import FileUtil LD_NAME = 'dkr.ld' ASM_DIR = './asm' class LD: def __init__(self, file): print('Generating linker file...') self.files = self.get_asm_files() self.indentLevel = 0 self.file = file self.gen_comment('linker script generated by generate_ld.py') self.gen_newline() self.gen_line('OUTPUT_ARCH (mips)') self.gen_newline() #self.gen_macros() self.gen_sections() print('New linker file created!') def gen_macros(self): self.gen_line('#define BEGIN_SEG(name, addr) \\') self.increase_indent() self.gen_line('_##name##SegmentStart = ADDR(.name); \\') self.gen_line('_##name##SegmentRomStart = __romPos; \\') self.gen_line('.name addr : AT(__romPos)') self.decrease_indent() self.gen_newline() self.gen_line('#define END_SEG(name) \\') self.increase_indent() self.gen_line('_##name##SegmentEnd = ADDR(.name) + SIZEOF(.name); \\') self.gen_line('_##name##SegmentRomEnd = __romPos + SIZEOF(.name); \\') self.gen_line('__romPos += SIZEOF(.name);') self.decrease_indent() self.gen_newline() def gen_sections(self): self.gen_line('SECTIONS') self.gen_open_block() self.gen_line('romPos = 0x0;') self.gen_boot_section() self.gen_main_section() self.gen_assets_section() self.gen_discard() self.gen_close_block() def gen_boot_section(self): self.gen_line('.boot 0 : AT(romPos)') self.gen_open_block() self.gen_line('build/asm/boot/rom_header.o(.text);') self.gen_line('build/asm/boot/rom_boot.o(.text);') self.gen_close_block() self.gen_line('romPos += SIZEOF(.boot);') self.gen_newline() def gen_main_section(self): self.gen_line('.main 0x80000400 : AT(romPos) SUBALIGN(16)') self.gen_open_block() self.files.sort(key = lambda x: x[2]) # Sort tuples by RAM address for asmFile in self.files: self.gen_line(asmFile[0] + '.o(.text);') self.gen_close_block() self.gen_line('romPos += SIZEOF(.main);') self.gen_newline() def gen_assets_section(self): self.gen_line('.assets 0 : AT(romPos)') self.gen_open_block() self.gen_line('build/asm/assets/assets.o(.text);') self.gen_close_block() self.gen_line('romPos += SIZEOF(.assets);') self.gen_newline() def gen_discard(self): self.gen_comment('Discard everything not specifically mentioned above.') self.gen_line('/DISCARD/ :') self.gen_open_block() self.gen_line('*(*);') self.gen_close_block() def increase_indent(self): self.indentLevel += 1 def decrease_indent(self): self.indentLevel -= 1 def gen_open_block(self): self.gen_line('{') self.increase_indent() def gen_close_block(self): self.decrease_indent() self.gen_line('}') def gen_line(self, text): spaces = 4 * self.indentLevel while spaces > 0: self.file.write(' ') spaces -= 1 self.file.write(text) self.gen_newline() def gen_comment(self, text): spaces = 4 * self.indentLevel while spaces > 0: self.file.write(' ') spaces -= 1 self.file.write('/* ' + text + ' */') self.gen_newline() def gen_newline(self): self.file.write('\n') def get_asm_files(self): asmFiles = [] asmFilenames = FileUtil.get_filenames_from_directory(ASM_DIR, ('.s',)) regex = r'[\/][*]\s*([0-9A-F]{6})\s*([0-9A-F]{8})\s*([0-9A-F]{8})\s*[*][\/]' for filename in asmFilenames: with open(ASM_DIR + '/' + filename, 'r') as asmFile: notDone = True line = asmFile.readline() while line: matches = re.match(regex, line) if matches is None: line = asmFile.readline() continue matchedGroups = matches.groups() asmFiles.append(('build/asm/' + filename[:-2], matchedGroups[0], matchedGroups[1])) break return asmFiles with open(LD_NAME, 'w') as ldFile: LD(ldFile)