Heath8080A — Product Design : H8 Processing

Page last updated

home    release    support    design    resources    legal    site map

14-September-2002

 

On this page

initialization
interrupts

Related links

system architecture
i/o package
8080a emulation

H8 Processing

Allow me, please, to appologize for the very poor name of this module.

The purpose of this module is to glue the 8080A emulator into the H8 hardware architecture, providing interrupt vectors when necessary and updating the front panel lamps when RUN and Interrupt Enabled status changes. It's called repeatedly by the scheduling loop in the event handler to execute one 8080A instruction, and therefore is on the critical execution path from a performance perspective.


Processor Initialization

At system startup and when the H8 is reset, H8 Processing will reset the 8080A and the I/O package, then will rebuild low memory.

Low memory is laid out as follows:

    Address Range

    Length

    Description

    000.00A - 003.377A

    1K bytes

    PAM/8 ROM

    004.000A - 023.377A

    3K bytes

    unused; init to zero

    024.000A - 027.377A

    2K bytes

    H-17 work space (write protected)

    030.000A - 037.377A

    2K bytes

    HDOS Driver ROM

Initialization loads the ROMs from 'CODE' resources, and zeros the unused memory space. The 2K of write-protected H-17 work space is left untouched.

go to top


Interrupt Dispatch

All Interrupts

H8 Processing must check for interrupts before dispatching each instruction, so this mechanism is in the critical execution path and must be fast.

The problem is that there are a lot of interrupt sources: the system clock, single-step hardware and the four 8250 UARTs. That's a lot of polling for interrupts, polling that takes too much time.

Starting with the 4.1 release, polling for interrupts is replaced with an interrupt mask byte. Each bit in the mask byte corresponds with its interrupt level — bit 1 is associated with vector 1, etc. Any object wanting to schedule an interrupt calls h8SetIntMask with its interrupt mask in order to set the mask bit. (When the condition clears, it can call h8ClrIntMask to clear the bit.)

The mask is checked on each pass. If it is zero, we handle setting the single-step interrupt (see below) then the instruction is dispatched. If the mask is non-zero, we isolate the low-order bit (the highest-priority interrupt) and then use that value to look up the associated restart instruction to pass to 8080A emulation:

    if ( intMask )
    {
        thisMask = intMask & (-intMask); // isolate low bit
        vector = vectors[thisMask];
        pState.processorRunning = 1;     // if halted, running now
    }

The "vectors" array is preloaded with restart instructions during initialization:

    vectors[0]  = 0 * 8;
    vectors[1]  = 1 * 8;
    vectors[2]  = 2 * 8;
    vectors[4]  = 3 * 8;
    vectors[8]  = 4 * 8;
    vectors[16] = 5 * 8;
    vectors[32] = 6 * 8;
    vectors[64] = 7 * 8;
    intMask     = 0;
    

Clock and single-step interrupts are handled by H8 Processing so those mask flags are cleared here. The I/O Package will clear its own interrupt flags when the interrupt is serviced.

This change from polling for interrupts to setting mask bits resulted in a processor speed increase of about 25% on the author's system.

Single-Step Interrupt

The H8 supports single-step hardware that allows PAM/8 and the dbug package to execute a single user instruction at a time. This hardware is enabled by setting bit 4 (CB.SSI) on the front panel control port (360q). This must be done with interrupts disabled.

Enable Interrupt (EI) is delayed one instruction. Ordinarily, if you:

        EI        Enable interrupts
        RET       Return to user code

...with another interrupt pending, the RET will execute then you will immediately reenter interrupt processing. The single-step hardware is designed to hold back the single-step interrupt for one instruction time following the actual enabling of interrupts, so that you can run one single instruction following that RET before you reenter interrupt handling.

We accomplish that here by checking the status of the CB.SSI bit after we check the interrupt mask. If CB.SSI has been set and interrupts are enabled, we'll set the interrupt mask bit for vector 2 for the next pass. This ensures that we'll run precisely one user instruction before interrupting again.

go to top



home   release   support   design   resources   legal   site map