Ejemplo n.º 1
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)
Ejemplo n.º 2
0
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')]
Ejemplo n.º 3
0
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')]
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
        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:
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
    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: