Esempio n. 1
0
def adm(self) -> Tuple[int, int]:
    """
    Name:           Add from memory with carry.

    Function:       The DATA RAM data character specified by the
                    last SRC instruction, plus the carry bit, are
                    added to the accumulator.
                    The data character is unaffected.
    Syntax:         ADM
    Assembled:      1110 1000
    Symbolic:       (M) + (ACC) + (CY) --> ACC, CY
    Execution:      1 word, 8-bit code and an execution time of 10.8 usec.
    Side-effects:   The carry/link is set to 1 if a sum greater than
                    MAX_4_BITS was generated to indicate a carry out;
                    otherwise, the carry/link is set to 0.
    """
    # Get value
    crb = self.read_current_ram_bank()
    chip, register, address = \
        decode_command_register(self.COMMAND_REGISTER, 'DATA_RAM_CHAR')
    absolute_address = convert_to_absolute_address(self, crb, chip, register,
                                                   address)
    # Perform addition
    self.ACCUMULATOR = (self.ACCUMULATOR + self.RAM[absolute_address] +
                        self.read_carry())
    # Check for carry bit set/reset when an overflow is detected
    # i.e. the result is more than a 4-bit number (MAX_4_BITS)
    check_overflow(self)
    self.increment_pc(1)
    return self.ACCUMULATOR, self.CARRY
Esempio n. 2
0
def wrr(self) -> int:
    """
    Name:           Write ROM port.

    Function:       The content of the accumulator is transferred to the ROM
                    output port of the previously selected ROM chip.
                    The data is available on the output pins until a new WRR
                    is executed on the same chip.
                    The content of the ACC and the carry/link are unaffected.
    Syntax:         WRR
    Assembled:      1110 0010
    Symbolic:       (ACC) --> ROM output lines
    Execution:      1 word, 8-bit code and an execution time of 10.8 usec.
    Side-effects:   The LSB bit of the accumulator appears on I/O 0, Pin 16,
                    of the 4001 ROM chip until it is changed.
    Notes:          No operation is performed on I/O lines coded as inputs.

    4 chips per bank, 8 banks = 32 addressable ROM ports.

    An address set by the previous SRC instruction is interpreted as follows:

    (Bits in this order : 12345678)

    Bits 1 - 4 = The ROM chip targetted
    Bits 5 - 8 = Not relevant
    """
    rom, _unused1, _unused2 = \
        decode_command_register(self.COMMAND_REGISTER, 'ROM_PORT')
    self.ROM_PORT[rom] = self.ACCUMULATOR
    self.increment_pc(1)
    return self.ACCUMULATOR
Esempio n. 3
0
def sbm(self) -> Tuple[int, int]:
    """
    Name:           Subtract DATA RAM from memory with borrow.

    Function:       The value of the DATA RAM character specified
                    by the last SRC instruction is subtracted from
                    the accumulator with borrow.
                    The data character is unaffected.
    Syntax:         SDM
    Assembled:      1110 1000
    Symbolic:       (M) + (ACC) + (CY) --> ACC, CY
    Execution:      1 word, 8-bit code and an execution time of 10.8 usec.
    Side-effects:   This instruction sets the carry bit if the result
                    generates no borrow, and resets the carry bit if
                    the result generates a borrow.
    Notes:  1       A borrow from the previous subtraction is indicated
                    by the carry bit being equal to one at the beginning
                    of this instruction.

            2       No borrow from the previous subtraction is indicated
                    by the carry bit being equal to zero at the beginning
                    of this instruction.

            3       The subtract with borrow operation is actually
                    performed by complementing each bit of the data
                    character and adding the resulting value plus
                    the complement of the carry bit to the accumulator.

            4       When this instruction is used to subtract numbers
                    greater than 4 bits in lengthJ the carry bit must
                    be complemented by the program between each required
                    subtraction operation.
    """
    # Get value
    crb = self.read_current_ram_bank()
    chip, register, address = \
        decode_command_register(self.COMMAND_REGISTER, 'DATA_RAM_CHAR')
    absolute_address = convert_to_absolute_address(self, crb, chip, register,
                                                   address)
    value = self.RAM[absolute_address]

    # Perform addition
    value_complement = int(ones_complement(value, 4), 2)
    carry_complement = self.read_complement_carry()
    self.ACCUMULATOR = (self.ACCUMULATOR + value_complement + carry_complement)
    # Check for carry bit set/reset when an overflow is detected
    # i.e. the result is more than a 4-bit number (MAX_4_BITS)
    check_overflow(self)
    self.increment_pc(1)
    return self.ACCUMULATOR, self.CARRY
Esempio n. 4
0
def rdr(self) -> int:
    """
    Name:           Read ROM Port.

    Function:       The ROM port specified by the last SRC instruction is read.
                    When using the 4001 ROM,each of the 4 lines of the port may
                    be an input or an output line; the data on the input lines
                    is transferred to the corresponding bits of the
                    accumulator.
                    Any output lines cause either a 0 or a 1 to be transferred
                    to the corresponding bits of the accumulator.
                    Whether a 0 or a 1 is transferred is a function of the
                    hardware, not under control of the programmer. (See Note 3)
                    The Carry bit is unaffected.
    Syntax:         RDR
    Assembled:      1110 1010
    Symbolic:       (ROM input lines) --> ACC
    Execution:      1 word, 8-bit code and an execution time of 10.8 usec.

    Notes:  1       The i4001 chip has a 256-byte ROM (256 8-bit program
                    instructions), and one built-in 4-bit I/O port.
                    The MCS-4 has 16 i4001 ROM chips.

            2       On the INTELLEC 4, a ROM port may be used for either
                    input or output. If programs tested on the INTELLEC 4 are
                    to be run later with a 4001 ROM the programmer must be
                    careful not to use one port for both functions.

            3       On the physical devices, if the leftmost I/O line is an
                    output line and the remaining I/O lines are input lines
                    containing 010B, the accumulator will contain either
                    1010B or 0010B.

    Implementation  This software implementation of the i4004 will ALWAYS
                    return the values of the output lines as-is.
    """
    rom, _unused1, _unused2 = \
        decode_command_register(self.COMMAND_REGISTER, 'ROM_PORT')
    self.ACCUMULATOR = self.ROM_PORT[rom]
    self.increment_pc(1)
    return self.ACCUMULATOR
Esempio n. 5
0
def rdm(self) -> int:
    """
    Name:           Read Data RAM data character.

    Function:       The content of the previously selected RAM main memory
                    character is transferred to the accumulator
                    The carry/link is unaffected.
                    The 4-bit data in memory is unaffected.
    Syntax:         RDM
    Assembled:      1110 1001
    Symbolic:       (M) --> ACC
    Execution:      1 word, 8-bit code and an execution time of 10.8 usec.
    """
    crb = self.read_current_ram_bank()
    chip, register, address = \
        decode_command_register(self.COMMAND_REGISTER, 'DATA_RAM_CHAR')
    absolute_address = convert_to_absolute_address(self, crb, chip, register,
                                                   address)
    self.ACCUMULATOR = self.RAM[absolute_address]
    self.increment_pc(1)
    return self.ACCUMULATOR
Esempio n. 6
0
def wrm(self) -> int:
    """
    Name:           Write accumulator into RAM character.

    Function:       The accumulator content is written into the previously
                    selected RAM main memory character location.
                    The accumulator and carry/link are unaffected.
    Syntax:         WRM
    Assembled:      1110 0000
    Symbolic:       (ACC) --> M
    Execution:      1 word, 8-bit code and an execution time of 10.8 usec.
    Side-effects:   Not Applicable
    """
    value = self.ACCUMULATOR
    crb = self.read_current_ram_bank()
    chip, register, address = \
        decode_command_register(self.COMMAND_REGISTER, 'DATA_RAM_CHAR')
    absolute_address = convert_to_absolute_address(self, crb, chip, register,
                                                   address)
    self.RAM[absolute_address] = value
    self.increment_pc(1)
    return self.PROGRAM_COUNTER
Esempio n. 7
0
def write_ram_status(self, char: int) -> bool:
    """
    Write to a RAM status character.

    Parameters
    ----------
    self: Processor, mandatory
        The instance of the processor containing the registers, accumulator etc

    char: int, mandatory
        specified status character

    Returns
    -------
    True
        if the value is set successfully

    Raises
    ------
    N/A

    Notes
    -----
    No error checking is done in this function
    All parameters cannot be out of range, since the functions to
    place them in various registers etc all have range checking built in .

    Eventually - there will be error checking here

    """
    value = self.read_accumulator()
    crb = self.read_current_ram_bank()

    chip, register, _none = \
        decode_command_register(self.COMMAND_REGISTER,
                                'DATA_RAM_STATUS_CHAR')
    self.STATUS_CHARACTERS[crb][chip][register][char] = value
    return True
Esempio n. 8
0
def wmp(self) -> int:
    """
    Name:           Write memory port.

    Function:       The content of the accumulator is transferred to the
                    RAM output port of the previously selected RAM chip.
                    The data is available on the output pins until a new
                    WMP is executed on the same RAM chip.
                    The content of the ACC and the carry/link are unaffected.
    Syntax:         WMP
    Assembled:      1110 0001
    Symbolic:       (ACC) --> RAM output register
    Execution:      1 word, 8-bit code and an execution time of 10.8 usec.
    Side-effects:   The LSB bit of the accumulator appears on I/O 0, Pin 16,
                    of the 4002 RAM chip until it is changed.

    There is a 4-bit register on each DATA RAM Chip -  on the base MCS-4
    system (one i4004 CPU, 32 * i4002, and ? * i4001 ) - additionally, a i4003
    shift register.

    Therefore - 4 chips per bank, 8 banks = 32 addressable memory ports.

    An address set by the previous SRC instruction is interpreted as follows:

    (Bits in this order : 12345678)

    Bits 1 - 2 = The port associated with 1 of 4 DATA RAM
                 chips within the DATA RAM bank previously
                 selected by a DCL instruction
    Bits 3 - 8 = Not relevant
    """
    crb = self.read_current_ram_bank()
    chip, _unused1, _unused2 = \
        decode_command_register(self.COMMAND_REGISTER, 'RAM_PORT')
    self.RAM_PORT[crb][chip] = self.ACCUMULATOR
    self.increment_pc(1)
    return self.ACCUMULATOR
Esempio n. 9
0
def rdx(self, character) -> int:
    """
    Read RAM status character X.

    Parameters
    ----------
    self : Processor, mandatory
        The instance of the Processor containing the registers, accumulator etc

    character:
        RAM STATUS CHARACTER to read

    Returns
    -------
    self.ACCUMULATOR
        The value read from the specified RAM STATUS CHARACTER

    """
    crb = self.read_current_ram_bank()
    chip, register, _none = \
        decode_command_register(self.COMMAND_REGISTER, 'DATA_RAM_STATUS_CHAR')
    self.ACCUMULATOR = self.STATUS_CHARACTERS[crb][chip][register][character]
    self.increment_pc(1)
    return self.ACCUMULATOR
Esempio n. 10
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]