Пример #1
0
    def assemble_indexed_operand(self, operand: Indexed, opcode_key, statement,
                                 opcode_bytes):
        if operand.base in RR:
            rr = RR[operand.base]
            if operand.offset in ACCUMULATOR_OFFSET_POST_BYTE:
                # Accumulator offset
                post_byte = ACCUMULATOR_OFFSET_POST_BYTE[operand.offset]
                post_byte |= rr << 5
                return bytes((post_byte, ))
            elif isinstance(operand.offset, Integral):
                if operand.offset == 0:
                    post_byte = 0b10000100
                    post_byte |= rr << 5
                    return bytes((post_byte, ))
                elif -16 <= operand.offset <= +15:
                    # 5-bit offset
                    post_byte = twos_complement(operand.offset, 5)
                    post_byte |= rr << 5
                    return bytes((post_byte, ))
                elif -128 <= operand.offset <= +127:
                    # 8-bit offset
                    post_byte = 0b10001000
                    post_byte |= rr << 5
                    offset_byte = twos_complement(operand.offset, 8)
                    return bytes((post_byte, offset_byte))
                elif -32768 <= operand.offset <= +32767:
                    # 16-bit offset
                    post_byte = 0b10001001
                    post_byte |= rr << 5
                    offset_bytes = twos_complement(operand.offset, 16)
                    return bytes(
                        (post_byte, hi(offset_bytes), lo(offset_bytes)))
            else:
                raise ValueError(
                    f"Cannot use indexed addressing offset {operand.offset} with base {operand.base}"
                )

        elif isinstance(operand.base, AutoIncrementedRegister):
            if operand.base.register not in RR:
                raise ValueError(
                    f"Cannot use auto pre-/post- increment or decrement with register {operand.base.register}"
                )
            rr = RR[operand.base.register]
            post_byte = INDEX_CREMENT_POST_BYTE[operand.base.delta]
            post_byte |= rr << 5
            return bytes((post_byte, ))
        else:
            raise ValueError(
                f"Cannot use {operand.base} as a base register for indexed addressing modes"
            )
Пример #2
0
def test_smallest_in_range_does_not_raise_value_error(num_bits):
    smallest = -(2**(num_bits - 1))
    v = twos_complement(smallest, num_bits)
    c = int(
        ''.join(str(int(not int(x)))
                for x in bin(abs(smallest) - 1)[2:]).rjust(num_bits, '1'), 2)
    assert v == c
Пример #3
0
def test_twos_complement_negative(d):
    num_bits = d.draw(integers(min_value=1, max_value=32))
    value = d.draw(integers(min_value=-2**(num_bits - 1), max_value=-1))
    c = int(
        ''.join(str(int(not int(x)))
                for x in bin(abs(value) - 1)[2:]).rjust(num_bits, '1'), 2)
    assert twos_complement(value, num_bits) == c
Пример #4
0
def test_index_with_eight_bit_offset(index_register, offset):
    asm = AsmDsl()
    asm(LDA, {offset: index_register}, "8-BIT OFFSET FROM INDEX REGISTER")

    code = assemble(statements(asm))
    assert code[0] == bytes(
        (0xA6, 0b10001000 | INDEX_REGISTER_CODES[index_register],
         twos_complement(offset, 8)))
Пример #5
0
def test_index_with_sixteen_bit_offset(offset, index_register):
    asm = AsmDsl()
    asm(LDA, {offset: index_register}, "16-BIT OFFSET FROM INDEX REGISTER")

    code = assemble(statements(asm))
    assert code[0] == (bytes(
        (0xA6, 0b10001001 | INDEX_REGISTER_CODES[index_register])) +
                       twos_complement(offset, 16).to_bytes(
                           length=2, byteorder='big', signed=False))
Пример #6
0
def test_index_with_five_bit_offset(index_register, offset):
    assume(offset != 0)
    asm = AsmDsl()
    asm(LDA, {offset: index_register}, "5-BIT OFFSET FROM INDEX REGISTER")

    code = assemble(statements(asm))
    assert code[0] == bytes(
        (0xA6,
         INDEX_REGISTER_CODES[index_register] | twos_complement(offset, 5)))
Пример #7
0
 def _assemble_relative_operand(self, operand, operand_bytes_length,
                                opcode_bytes):
     if isinstance(operand.address, Label):
         if operand.name in self._label_addresses:
             target_address = self._label_addresses[operand.name]
             # TODO: Consider threading opcode_bytes through as an argument
             offset = target_address - self.pos - len(
                 opcode_bytes) - operand_bytes_length
             unsigned_offset = twos_complement(offset,
                                               operand_bytes_length * 8)
             result = self.value_to_bytes(unsigned_offset,
                                          operand_bytes_length)
             self._unresolved_labels.discard(operand)
         else:
             self._more_passes_required = True
             result = bytes(operand_bytes_length)
             self._unresolved_labels.add(operand)
         self._unreferenced_labels.discard(operand)
     else:
         # TODO: What if the operand is a number?
         raise NotImplementedError
     return result
Пример #8
0
def _(operand, opcode_key, asm, statement):
    # If we know the address of the label, use it
    if operand.name in asm._label_addresses:
        target_address = asm._label_addresses[operand.name]
        if opcode_key in branch_operand_widths:
            operand_bytes_length = branch_operand_widths[opcode_key]
            offset = target_address - asm.pos - len(
                asm._opcode_bytes) - operand_bytes_length
            unsigned_offset = twos_complement(offset, operand_bytes_length * 8)
            if opcode_key == REL8:
                return (unsigned_offset, )
            elif opcode_key == REL16:
                return (hi(unsigned_offset), lo(unsigned_offset))
        else:
            assert opcode_key is IMM
            return (hi(target_address), lo(target_address))
    else:
        asm._more_passes_required = True
        if opcode_key in branch_operand_widths:
            return (0, ) * branch_operand_widths[opcode_key]
        else:
            assert opcode_key is IMM
            return (0, 0)
Пример #9
0
def test_twos_complement_non_positive_num_bits_raises_value_error(num_bits):
    with raises(ValueError):
        twos_complement(0, num_bits)
Пример #10
0
def test_largest_out_of_range_raises_value_error(num_bits):
    largest = -(2**(num_bits - 1)) - 1
    with raises(ValueError):
        twos_complement(largest, num_bits)
Пример #11
0
def test_smallest_out_of_range_does_raises_value_error(num_bits):
    smallest = (2**(num_bits - 1))
    with raises(ValueError):
        twos_complement(smallest, num_bits)
Пример #12
0
def test_largest_in_range_does_not_raise_value_error(num_bits):
    largest = (2**(num_bits - 1)) - 1
    v = twos_complement(largest, num_bits)
    assert v == largest
Пример #13
0
def test_twos_complement_negative_too_narrow(d):
    value = d.draw(integers(max_value=-2))
    num_bits = d.draw(integers(min_value=1, max_value=value.bit_length() - 1))
    with raises(ValueError):
        twos_complement(value, num_bits)
Пример #14
0
def test_twos_complement_minus_one_too_narrow():
    with raises(ValueError):
        twos_complement(-1, 0)
Пример #15
0
def test_twos_complement_positive_too_narrow(d):
    value = d.draw(integers(min_value=0))
    num_bits = d.draw(integers(min_value=0, max_value=value.bit_length()))
    assume(num_bits >= 1)
    with raises(ValueError):
        twos_complement(value, num_bits)
Пример #16
0
def test_twos_complement_positive(d):
    num_bits = d.draw(integers(min_value=1, max_value=32))
    value = d.draw(integers(min_value=0, max_value=(2**(num_bits - 1)) - 1))
    assert twos_complement(value, num_bits) == value