Ejemplo n.º 1
0
def src(self, registerpair: int) -> int:
    """
    Name:           Send register control.

    Function:       The 8 bit content of the designated index register pair
                    is sent to the RAM address register at X2 and X3.
                    A subsequent read, write, or I/O operation of the RAM will
                    utilize this address. Specifically, the first 2 bits of the
                    address designate a RAM chip; the second 2 bits designate
                    1 out of 4 registers within the chip;
                    the last 4 bits designate 1 out of 16 4-bit main memory
                    characters within the register.

                    This command is also used to designate a ROM for a
                    subsequent ROM I/O port operation. The first 4 bits
                    designate the ROM chip number to be selected. The address
                    in ROM or RAM is not cleared until the next SRC
                    instruction is executed.
                    The 8 bit content of the index register is unaffected.
    Syntax:         SRC
    Assembled:      0010 RRR1
    Symbolic:       (RRRO) --> DB (X2)
                    (RRR1) --> DB (X3)
    Execution:      1 word, 8-bit code and an execution time of 10.8 usec..
    Side-effects:   Not Applicable
    """
    from hardware.suboperation import decimal_to_binary
    if registerpair > 7:
        raise InvalidRegisterPair('Register pair : ' + str(registerpair))

    self.increment_pc(1)
    address = self.read_registerpair(registerpair)
    self.COMMAND_REGISTER = decimal_to_binary(8, address)
    return address
Ejemplo n.º 2
0
def test_validate_instruction(register):
    """Ensure instruction's characteristics are valid."""
    chip_test = Processor()
    # Validate the instruction's opcode and characteristics:
    op = chip_test.INSTRUCTIONS[176 + register]
    known = {
        "opcode": 176 + register,
        "mnemonic": "xch(" + str(register) + ")",
        "exe": 10.8,
        "bits": ["1011", decimal_to_binary(4, register)],
        "words": 1
    }  # noqa
    assert op == known
Ejemplo n.º 3
0
def test_validate_instruction(value):
    """Ensure instruction's characteristics are valid."""
    chip_test = Processor()
    # Validate the instruction's opcode and characteristics:
    op = chip_test.INSTRUCTIONS[49 + (value * 2)]
    known = {
        "opcode": 49 + (value * 2),
        "mnemonic": "jin(" + str(value) + ")",
        "exe": 10.8,
        "bits": ["0011", decimal_to_binary(4, (2 * value) + 1)],
        "words": 1
    }  # noqa
    assert op == known
Ejemplo n.º 4
0
def test_validate_instruction(registerpair):
    """Ensure instruction's characteristics are valid."""
    chip_test = Processor()
    # Validate the instruction's opcode and characteristics:
    op = chip_test.INSTRUCTIONS[48 + (registerpair * 2)]
    known = {
        "opcode": 48 + (registerpair * 2),
        "mnemonic": "fin(" + str(registerpair) + ")",
        "exe": 21.6,
        "bits": ["0011", decimal_to_binary(4, registerpair * 2)],
        "words": 1
    }  # noqa
    assert op == known
Ejemplo n.º 5
0
def test_validate_instruction(increment):
    """Ensure instruction's characteristics are valid."""
    chip_test = Processor()
    # Validate the instruction's opcode and characteristics:
    op = chip_test.INSTRUCTIONS[192 + increment]
    known = {
        "opcode": 192 + increment,
        "mnemonic": "bbl(" + str(increment) + ")",
        "exe": 10.8,
        "bits": ["1100", decimal_to_binary(4, increment)],
        "words": 1
    }  # noqa
    assert op == known
def test_validate_instruction(increment):
    """Ensure instruction's characteristics are valid."""
    chip_test = Processor()
    # Validate the instruction's opcode and characteristics:
    op = chip_test.INSTRUCTIONS[80 + increment]
    known = {
        "opcode": 80 + increment,
        "mnemonic": "jms(address12)",
        "exe": 21.6,
        "bits": ["0101", decimal_to_binary(4, increment)],
        "words": 2
    }  # noqa
    assert op == known
Ejemplo n.º 7
0
def test_validate_instruction(value):
    """Ensure instruction's characteristics are valid."""
    chip_test = Processor()
    # Validate the instruction's opcode and characteristics:
    op = chip_test.INSTRUCTIONS[64 + value]
    known = {"opcode": 64 + value, "mnemonic": "jun(address12)", "exe": 21.6, "bits": ["0100", decimal_to_binary(4, value)], "words": 2}  # noqa
    assert op == known
def test_validate_instruction(value):
    """Ensure instruction's characteristics are valid."""
    chip_test = Processor()
    # Validate the instruction's opcode and characteristics:
    op = chip_test.INSTRUCTIONS[112 + value]
    known = {"opcode": 112 + value, "mnemonic": "isz(" + str(value) + ",address8)", "exe": 10.8, "bits": ["0111", decimal_to_binary(4,  value)], "words": 2}  # noqa
    assert op == known
Ejemplo n.º 9
0
def wpm(self) -> Tuple[int, int]:
    """
    Name:           Write program RAM.

    Function:       This is a special instruction which may be used to write
                    the contents of the accumulator into a half byte of
                    program RAM, or read the contents of a half byte of program
                    RAM into a ROM input port where it can be accessed by a
                    program.
                    The Carry bit is unaffected.
    Syntax:         WPM
    Assembled:      1110 0011
    Symbolic:       (A) --> (PRAM)
    Execution:      1 word, 8-bit code and an execution time of 10.8 usec.

    Notes:  1       Two WPM instructions must always appear in close
                    succession; that is, each time one WPM instruction
                    references a half byte of program RAM as indicated by an
                    SRC address, another WPM must access the other half byte
                    before the SRC address is altered. An internal counter
                    keeps track of which half-byte is being accessed. If only
                    one WPM occurs, this counter will be out of sync with the
                    program and errors will occur. In this situation, a RESET
                    pulse must be used to re-initialize the machine.

            2       A WPM instruction requires an SRC address to access program
                    RAM. Whenever a WPM is executed, the DATA RAM which happens
                    to correspond to this SRC address will also be written.
                    If data needed later in the program is being held in such
                    a DATA RAM, the programmer must save it elsewhere before
                    executing the WPM instruction.


    """
    chip, register, addr = decode_command_register(
        decimal_to_binary(8, self.COMMAND_REGISTER), 'DATA_RAM_CHAR')
    rambank = self.read_current_ram_bank()
    address = convert_to_absolute_address(self, rambank, chip, register, addr)
    # Get the value of the WPM Counter
    wpm_counter = read_wpm_counter(self)

    # Writing
    if self.ROM_PORT[14] == 1:
        # Write enabled, so store
        if wpm_counter == 'LEFT':
            value = self.ACCUMULATOR << 4
            self.PRAM[address] = value
            self.RAM[address] = value
        if wpm_counter == 'RIGHT':
            value = self.ACCUMULATOR
            self.RAM[address] = self.RAM[address] + value
            self.PRAM[address] = self.PRAM[address] + value

    # Reading
    if self.ROM_PORT[14] != 1:
        # read
        if wpm_counter == 'LEFT':
            self.ROM_PORT[14] = self.PRAM[address] >> 4 << 4
        if wpm_counter == 'RIGHT':
            self.ROM_PORT[15] = self.PRAM[address] << 4 >> 4

    flip_wpm_counter(self)

    self.increment_pc(1)

    return self.ROM_PORT[14], self.ROM_PORT[15]
Ejemplo n.º 10
0
def jcn(self, conditions: int, address: int) -> int:
    """
    Name:           Jump conditional.

    Function:       If the designated condition code is true, program control
                    is transferred to the instruction located at the 8 bit
                    address AAAA2, AAAA1 on the same page (ROM) where JCN is
                    located.
                    If the condition is not true the next instruction in
                    sequence after JCN is executed.
                    The condition bits are assigned as follows:
                    C1 = 0 Do not invert jump condition }
                    C1 = 1 Invert jump condition        }
                    C2 = 1 Jump if the accumulator content is zero
                    C3 = 1 Jump if the carry/link content is 1
                    C4 = 1 Jump if test signal (pin 10 on 4004) is zero.
    Syntax:         JCN
    Assembled:      0001 C1C2C3C4
                    AAAA2 AAAA1
    Symbolic:       If C1C2C3C4 is true, A2A2A2A2 --> PM
                    A1A1A1A1 --> PL, PH unchanged
                    if C1C2C3C4 is false,
                    (PH) --> PH, (PM) --> PM, (PL + 2) --> PL
    Execution:      2 words, 16-bit code and an execution time of 21.6 usec.

    Sample:

    OPR     OPA
    0001    0110  Jump if accumulator is zero or carry = 1

    Several conditions can be tested simultaneously.

    The logic equation describing the condition for a jump is give below:
    JUMP = ~C1 . ((ACC = 0) . C2 + (CY = 1) . C3 + ~TEST . C4) +
                C1 . ~((ACC != 0) . C2 + (CY = 1) . C3 + ~TEST . C4)

                        +---------+---------+
                        | Symbol  | Logical |
                        +---------+---------+
                        |    ~    +   NOT   +
                        |    .    +   AND   +
                        |    +    +   OR    +
                        +---------+---------+

    Side-effects:   Not Applicable

    Info about signal/test pin 10 on intel4004
    https://tams.informatik.uni-hamburg.de/applets/hades/webdemos/80-mcs4/jmp/jmp_test.html

    Assembler:
            jcn     IACT    lbl

    I - Invert other conditions
    A - Accumulator = 0
    C - Carry Bit set (i.e. = 1)
    T - Test Signal on Intel4004 Pin 10 = 0

    Need to do "if JCN at end of page" code

    """
    from hardware.suboperations.utility import decimal_to_binary  # noqa

    accumulator = self.read_accumulator()
    checks = str(decimal_to_binary(4, conditions))

    c1 = checks[0:1] == '1'
    c2 = checks[1:2] == '1'
    c3 = checks[2:3] == '1'
    c4 = checks[3:4] == '1'
    notc1 = True if c1 is False else False
    notc2 = True if c2 is False else False
    notc3 = True if c3 is False else False
    notc4 = True if c4 is False else False

    # Use symbolic logic to determine whether to jump
    jump = notc1 and ((accumulator == 0) and c2 or (self.read_carry() == 1)
                      and c3 or (not self.read_pin10()) and c4) or \
        c1 and (((accumulator != 0) or notc2) and
                ((self.read_carry() == 0) or notc3) and
                ((not self.read_pin10()) or notc4))

    if jump is True:
        self.PROGRAM_COUNTER = address
    else:
        self.increment_pc(2)
    return self.PROGRAM_COUNTER