Exemplo n.º 1
0
def _codegen_jmp(context: Context, op: Op) -> Tuple[Context, Op]:
    """JMP pseudoinstruction: several underlying variants."""
    op = op._replace(args=parse_args_if_able(
        _PARSE_OPTIONS, context, op, Type.ADDRESS | Type.DEREF_REGISTER
        | Type.DEREF_ADDRESS))
    # Since this pseudoinstruction can produce code of different lengths, we
    # handle updating pos when "not all_args_parsed" in a special way.
    if not all_args_parsed(op.args):
        advance = 4 if op.args[0].argtype & Type.ADDRESS else 2
        return context.advance_by_bytes(advance), op

    # We are branching to an address literal.
    if op.args[0].argtype & Type.ADDRESS:
        _jmpdestcheck(op.args[0])
        op = op._replace(todo=None,
                         hex='D001{:04X}'.format(op.args[0].integer))

    # We are branching to an address stored at a memory location in a register.
    # (To branch to an address inside a register, use RET).
    elif op.args[0].argtype & Type.DEREF_REGISTER:
        _regderefcheck(op.args[0], postcrem_from=0, postcrem_to=0)
        op = op._replace(todo=None, hex='D0{:X}8'.format(op.args[0].integer))

    # We are branching to an address stored at a low memory location.
    else:
        _lowwordaddrcheck(op.args[0])
        op = op._replace(todo=None,
                         hex='20{:02X}'.format(op.args[0].integer // 2))

    return context.advance(op.hex), op
Exemplo n.º 2
0
def _codegen_call(context: Context, op: Op) -> Tuple[Context, Op]:
    """CALL pseudoinstruction: several underlying variants."""
    op = op._replace(args=parse_args_if_able(
        _PARSE_OPTIONS, context, op, Type.ADDRESS | Type.REGISTER
        | Type.DEREF_REGISTER | Type.DEREF_ADDRESS, Type.REGISTER))
    # Since this pseudoinstruction can produce code of different lengths, we
    # handle updating pos when "not all_args_parsed" in a special way.
    if not all_args_parsed(op.args):
        advance = 6 if op.args[0].argtype & Type.ADDRESS else 4
        return context.advance_by_bytes(advance), op

    # We are calling an address literal. Note that there is a way to do this in
    # two halfwords: for that, use the RCALL pseudoinstruction.
    if op.args[0].argtype & Type.ADDRESS:
        _jmpdestcheck(op.args[0])
        _regcheck(op.args[1])
        digits_a = (op.args[1].integer, op.args[1].integer, op.args[0].integer)
        op = op._replace(todo=None,
                         hex='0{:X}03D0{:X}1{:04X}'.format(*digits_a))

    # We are calling an address stored inside a register.
    elif op.args[0].argtype & Type.REGISTER:
        _callregcheck(op.args[0], op.args[1])
        digits_r = (op.args[1].integer, op.args[0].integer)
        op = op._replace(todo=None, hex='0{:X}0300{:X}4'.format(*digits_r))

    # We are calling an address stored at a memory location in a register.
    elif op.args[0].argtype & Type.DEREF_REGISTER:
        _callregcheck(op.args[0], op.args[1])
        _regderefcheck(op.args[0], postcrem_from=-2, postcrem_to=2)  # Words.
        modifier = _postcrement_to_modifier(2 * op.args[0].postcrement)
        digits_d = (op.args[1].integer, op.args[0].integer, modifier)
        op = op._replace(todo=None, hex='0{:X}03D0{:X}{:X}'.format(*digits_d))

    # We are calling an address stored at a low memory location.
    else:
        _regcheck(op.args[1])
        _lowwordaddrcheck(op.args[0])
        assert op.opcode is not None  # mypy...
        if op.args[0].precrement or op.args[0].postcrement:
            raise ValueError(
                'No (in/de)crementation is allowed for address dereference arguments '
                'to {}'.format(op.opcode.upper()))
        digits = (op.args[1].integer, op.args[0].integer // 2)
        op = op._replace(todo=None, hex='0{:X}0320{:02X}'.format(*digits))

    return context.advance(op.hex), op
Exemplo n.º 3
0
  def codegen_data(context: Context, op: Op) -> Tuple[Context, Op]:
    # Accumulate hex code here, and track whether we have its final value worked
    # out, or if we're still waiting on labels.
    hexparts = []
    all_hex_ok = True

    # Align the data to match the data quantum, if directed.
    if align:
      if element_size != 1:
        if context.pos is None: raise ValueError(
            'Unresolved labels above this line (or other factors) make it '
            'impossible to know how to align this data statement. Consider '
            "an ORG statement to make this data's memory location explicit.")
        hexparts.append('00' * (context.pos % element_size))

    # Generate data for each arg. Unlike nearly all other statements, we do most
    # of the parsing ourselves.
    for arg in op.args:
      # Is the argument a string?
      if arg.stripped.startswith('"') or arg.stripped.startswith("'"):
        hexparts.append(''.join(
            val.to_bytes(element_size, endianity).hex().upper()
            for val in parse_string(parse_options, context, arg.stripped)))

      # No, it must be a single integer value.
      else:
        # Does the argument look like a label? If so, try to resolve it and take
        # its value. If not, let's parse the argument as an integer value.
        if LABEL_RE.fullmatch(arg.stripped):
          all_hex_ok &= arg.stripped in context.labels
          val = context.labels[arg.stripped] if all_hex_ok else 0
        else:
          val = parse_integer(parse_options, context, arg.stripped)
        # Now encode the value as hex.
        hexparts.append(val.to_bytes(element_size, endianity).hex().upper())

    # Package the hex data from all the args and, if appropriate, mark our job
    # as complete.
    op = op._replace(todo=None if all_hex_ok else op.todo,
                     hex=''.join(hexparts))
    return context.advance(op.hex), op
Exemplo n.º 4
0
def _codegen_nop(context: Context, op: Op) -> Tuple[Context, Op]:
    """NOP pseudoinstruction: MOVE R0, R0."""
    # This opcode takes no arguments. We still parse to make sure there are none.
    op = op._replace(args=parse_args_if_able(_PARSE_OPTIONS, context, op))
    op = op._replace(todo=None, hex='0004')
    return context.advance(op.hex), op