def compile(f, fout): global ADDR_SHIFT parsed_source = None with open(f, 'r') as source: parsed_source = map(parse_line, enumerate(source.readlines())) for label in COMPILER_LABELS: info = COMPILER_LABELS[label] if info['end'] == -1: error(info['start'], "missing a matching .end call for label: " + label) if len(COMPILER_ERRORS) != 0: return (False, COMPILER_ERRORS) # 0. flatten the list parsed_source = list(itertools.chain(*parsed_source)) # 1. remove blank lines pps = [line for line in parsed_source if len(line) != 0] # 2. find all label markers and calculate their absolute positions abspos = {} for (n, line) in enumerate(pps): if line[0] == '.': label_id = line.replace('.', '') abspos[label_id] = ADDR_SHIFT + (n - len(abspos.keys())) pps[n] = None debug.log(" # %d: found marker for label '%s'" % (n, label_id)) pps = [line for line in pps if line != None] # 3. replace label markers with actual locations # (and expand $! with current position) for (n, line) in enumerate(pps): pos = line.find('%') if pos != -1: label_id = line[pos:line.rfind('%')+1].replace('%', '') replacement = abspos[label_id] pps[n] = (line[0:pos] + util.fixedbin(replacement, 8)).ljust(16, '0') debug.log("%3d: inserting label address lbl%s -> %d" % (n, label_id, replacement)) pos = line.find('!') if pos != -1: debug.log("%3d: inserting current location" % n) pps[n] = (line[0:pos] + util.fixedbin(n, 8)).ljust(16, '0') debug.log("%3d: %s" % (n, pps[n])) with open(fout, 'wb') as out: debug.log(" # Writing binary to '%s'..." % fout) [out.write(raw_instr(line)) for line in pps] if ADDR_SHIFT > 0: print(" Note: You're using address shifting. Binary won't be executable on its own.") return (True, None)
def endf(source, lbl): if not lbl in COMPILER_LABELS: error(source[0], ".endf called for an undefined label: " + lbl) return n = source[0] debug.log(" # %d: inserting implicit return instruction" % n) COMPILER_LABELS[lbl]['end'] = n return [util.fixedbin(instructions.MNEM_DICT['ret'], 5).ljust(16, '0')]
def compile(f, fout): global ADDR_SHIFT parsed_source = None with open(f, 'r') as source: parsed_source = map(parse_line, enumerate(source.readlines())) for label in COMPILER_LABELS: info = COMPILER_LABELS[label] if info['end'] == -1: error(info['start'], "missing a matching .end call for label: " + label) if len(COMPILER_ERRORS) != 0: return (False, COMPILER_ERRORS) # 0. flatten the list parsed_source = list(itertools.chain(*parsed_source)) # 1. remove blank lines pps = [line for line in parsed_source if len(line) != 0] # 2. find all label markers and calculate their absolute positions abspos = {} for (n, line) in enumerate(pps): if line[0] == '.': label_id = line.replace('.', '') abspos[label_id] = ADDR_SHIFT + (n - len(abspos.keys())) pps[n] = None debug.log(" # %d: found marker for label '%s'" % (n, label_id)) pps = [line for line in pps if line != None] # 3. replace label markers with actual locations # (and expand $! with current position) for (n, line) in enumerate(pps): pos = line.find('%') if pos != -1: label_id = line[pos:line.rfind('%') + 1].replace('%', '') replacement = abspos[label_id] pps[n] = (line[0:pos] + util.fixedbin(replacement, 8)).ljust( 16, '0') debug.log("%3d: inserting label address lbl%s -> %d" % (n, label_id, replacement)) pos = line.find('!') if pos != -1: debug.log("%3d: inserting current location" % n) pps[n] = (line[0:pos] + util.fixedbin(n, 8)).ljust(16, '0') debug.log("%3d: %s" % (n, pps[n])) with open(fout, 'wb') as out: debug.log(" # Writing binary to '%s'..." % fout) [out.write(raw_instr(line)) for line in pps] if ADDR_SHIFT > 0: print( " Note: You're using address shifting. Binary won't be executable on its own." ) return (True, None)
opcode = instructions.MNEM_DICT[instr] except KeyError, e: error(n, "unknown instruction: '%s'" % instr) return '' bas = instructions.INSTRUCTIONS[opcode].__bas__ parsed_args = [parse_arg(n, arg.strip()) for arg in line[1:]] try: args = [arg.zfill(bas[n]) for (n, arg) in enumerate(parsed_args)] except IndexError, e: error( n, "too many arguments: '%s' requires %d but provided with %d" % (instr, len(bas), len(parsed_args))) return [''] return [(util.fixedbin(opcode, 5) + ''.join(args)).ljust(16, '0')] # $var_name => expands variable # $! => address of the current instruction # @a => 97 => 1100001 # %fn => address of function/label 'fn' # 123 => 1111011 def parse_arg(n, arg): sig = arg[0] val = arg[1:].decode('string_escape') if sig == '$': if val == '!': return '!'.ljust(8, '!') else:
def store(rx, md): val = util.fixedbin(regs.REGS[rx], 16) log(" # store %s (%d) => m%s" % (val, regs.REGS[rx], md)) regs.MEM[md] = val
error(n, "unknown instruction: '%s'" % instr) return '' bas = instructions.INSTRUCTIONS[opcode].__bas__ parsed_args = [parse_arg(n, arg.strip()) for arg in line[1:]] try: args= [arg.zfill(bas[n]) for (n, arg) in enumerate(parsed_args)] except IndexError, e: error(n, "too many arguments: '%s' requires %d but provided with %d" % ( instr, len(bas), len(parsed_args) )) return [''] return [(util.fixedbin(opcode, 5) + ''.join(args)).ljust(16, '0')] # $var_name => expands variable # $! => address of the current instruction # @a => 97 => 1100001 # %fn => address of function/label 'fn' # 123 => 1111011 def parse_arg(n, arg): sig = arg[0] val = arg[1:].decode('string_escape') if sig == '$': if val == '!': return '!'.ljust(8, '!') else: if not val in COMPILER_VARS: