/*
 *	EMUL-8: a pdp8e emulator.
 *
 *	Author:
 *		Bill Haygood
 *		41832 Ernest Road
 *		Loon Lake, WA 99148-9607
 *		Internet: billh@comtch.iea.com
 *		Voice/AnsMach/FAX \
 *			or	   509-233-2555
 *		  Cellular/Pager  /
 *
 *	Copyright 1992, 1993, 1994 by the author with all rights reserved.
 *
 *	Run module.
 */
#include "pdp8.h"
#include "pdp8regs.h"
#include "pdp8dis.h"
#include "pdp8itab.h"
#include "pdp8loc.h"
#include "pdp8misc.h"
/* -------------------------------------------------------------------- */
VOID exec8 (VOID)
{
    if (trace || breakflag || tabulate || profile)
    {
	while (run)
	{
/*
 *	Check for a clock tick.
 */
	    if (!--clkcntr)
	    {
		checkvdus++ ;
		clkcntr = CLKCNT ;
		if (clocktype && (curtime = clock ()) >= ticktime)
		{
		    ticktime += ticks ;
		    io_flags |= clockFLAG ;
		}
	    }
/*
 *	Check for a keyboard strike.
 */
	    if (checkvdus || diag)
	    {
		if (KeyStrike (003))
		    io_flags |= coninFLAG ;
		if (aux_vdu && KeyStrike (040))
		    io_flags |= auxinFLAG ;
		checkvdus = FALSE ;
	    }
/*
 *	Handle any pending interrupts.
 */
	    if (int_ena && (io_flags & int_mask)
				&& delay == FALSE && int_inh == FALSE)
	    {
		base [0] = PC & 07777 ;
		PC = 1 ;
		SF = (UF >> 6) | (IF >> 9) | (DF >> 12) ;
		IB = IF = DF = UB = UF = int_ena = FALSE ;
	    }
	    delay = FALSE ;
/*
 *	Fetch the pdp8 instruction.
 */
	    INST = *(base + (IF + PC)) ;
/*
 *	If tracing, prepare output text line.
 */
	    if (trace && ((cpu_trace && (INST & 07401) != 07401)
			|| (eae_trace && (INST & 07401) == 07401)))
		sprintf (chrsout, "%06o ", (DF << 3) + IF + PC) ;
/*
 *	Check for a break address or a break instruction.
 */
	    if (breakflag && ((INST & instmask) == breakinst
				|| ((IF + PC) & addrmask) == breakaddr))
		run = FALSE ;
	    if (run)
	    {
/*
 *	Tabulate instruction usage.
 */
		if (tabulate)
		    ++(*(tab + UF + INST)) ;
/*
 *	Build profile histogram.
 */
		if (profile)
		    ++(*(histo + ((IF + PC) >> 2))) ;
/*
 *	Output instruction trace information.
 */
		if (trace && ((cpu_trace && (INST & 07401) != 07401)
			|| (eae_trace && (INST & 07401) == 07401)))
		{
		    sprintf (pdp8exec, "%04o ", INST) ;
		    strcat (chrsout, pdp8exec) ;
		    disassem () ;
		    strcat (chrsout, pdp8exec) ;
		    if (INST == breakinst)
			run = FALSE ;
		}
/*
 *	Save the address of this instruction.
 */
		lastPC = PC ;
/*
 *	Execute the pdp8 instruction.
 */
		(*itab [UF + INST]) () ;
/*
 *	Count instructions executed, if requested.
 */
		if (cpu_count && ((INST & 07401) != 07401))
		    cpu_count++ ;
		if (eae_count && ((INST & 07401) == 07401))
		    eae_count++ ;
/*
 *	Update the pdp8 program counter.
 */
		if (++PC & 010000)
		    PC &= 07777 ;
/*
 *	If tracing, output the trace text line.
 */
		if (trace && ((cpu_trace && ((INST & 07401) != 07401))
			|| (eae_trace && ((INST & 07401) == 07401))))
		{
		    outline () ;
		    if (--trace <= 0)
			run = trace = FALSE ;
		}
		if (fpp_run)
		    fppexec () ;
		if (exec && --exec == 0)
		    run = FALSE ;
	    }
	}
    }
/*
 *	Execute pdp8 instructions with only the 'exec', 'diag'
 *	and 'fpp' impediments.
 */
    if (exec)
    {
	while (run)
	{
/*
 *	Check for a clock tick.
 */
	    if (!--clkcntr)
	    {
		checkvdus++ ;
		clkcntr = CLKCNT ;
		if (clocktype && (curtime = clock ()) >= ticktime)
		{
		    ticktime += ticks ;
		    io_flags |= clockFLAG ;
		}
	    }
/*
 *	Check for a keyboard strike.
 */
	    if (checkvdus || diag)
	    {
		if (KeyStrike (003))
		    io_flags |= coninFLAG ;
		if (aux_vdu && KeyStrike (040))
		    io_flags |= auxinFLAG ;
		checkvdus = FALSE ;
	    }
/*
 *	Handle any pending interrupts.
 */
	    if (int_ena && (io_flags & int_mask)
				&& delay == FALSE && int_inh == FALSE)
	    {
		base [0] = PC & 07777 ;
		PC = 1 ;
		SF = (UF >> 6) | (IF >> 9) | (DF >> 12) ;
		IB = IF = DF = UB = UF = int_ena = FALSE ;
	    }
	    delay = FALSE ;
/*
 *	Fetch and execute the pdp8 instruction.
 */
	    (*itab [UF + (INST = *(base + (IF + PC)))]) () ;
/*
 *	Count instructions executed, if requested.
 */
	    if (cpu_count && ((INST & 07401) != 07401))
		cpu_count++ ;
	    if (eae_count && ((INST & 07401) == 07401))
		eae_count++ ;
/*
 *	Update the pdp8 program counter.
 */
	    if (++PC & 010000)
		PC &= 07777 ;
	    if (fpp_run)
		fppexec () ;
	    if (!--exec)
		run = FALSE ;
	}
    }
/*
 *	Execute pdp8 instructions with only the 'fpp', 'diag'
 *	and 'count' impediments.
 */
    if (FPP)
    {
	while (run)
	{
/*
 *	Check for a clock tick.
 */
	    if (!--clkcntr)
	    {
		checkvdus++ ;
		clkcntr = CLKCNT ;
		if (clocktype && (curtime = clock ()) >= ticktime)
		{
		    ticktime += ticks ;
		    io_flags |= clockFLAG ;
		}
	    }
/*
 *	Check for a keyboard strike.
 */
	    if (checkvdus || diag)
	    {
		if (KeyStrike (003))
		    io_flags |= coninFLAG ;
		if (aux_vdu && KeyStrike (040))
		    io_flags |= auxinFLAG ;
		checkvdus = FALSE ;
	    }
/*
 *	Handle any pending interrupts.
 */
	    if (int_ena && (io_flags & int_mask)
				&& delay == FALSE && int_inh == FALSE)
	    {
		base [0] = PC & 07777 ;
		PC = 1 ;
		SF = (UF >> 6) | (IF >> 9) | (DF >> 12) ;
		IB = IF = DF = UB = UF = int_ena = FALSE ;
	    }
	    delay = FALSE ;
/*
 *	Fetch and execute the pdp8 instruction.
 */
	    (*itab [UF + (INST = *(base + (IF + PC)))]) () ;
/*
 *	Count instructions executed, if requested.
 */
	    if (cpu_count && ((INST & 07401) != 07401))
		cpu_count++ ;
	    if (eae_count && ((INST & 07401) == 07401))
		eae_count++ ;
/*
 *	Update the pdp8 program counter.
 */
	    if (++PC & 010000)
		PC &= 07777 ;
	    if (fpp_run)
		fppexec () ;
	}
    }
/*
 *	Execute pdp8 instructions with only the 'diag'
 *	and 'count' impediments.
 */
    if (diag)
    {
	while (run)
	{
/*
 *	Check for a clock tick.
 */
	    if (!--clkcntr)
	    {
		checkvdus++ ;
		clkcntr = CLKCNT ;
		if (clocktype && (curtime = clock ()) >= ticktime)
		{
		    ticktime += ticks ;
		    io_flags |= clockFLAG ;
		}
	    }
/*
 *	Check for a keyboard strike.
 */
	    if (checkvdus || diag)
	    {
		if (KeyStrike (003))
		    io_flags |= coninFLAG ;
		if (aux_vdu && KeyStrike (040))
		    io_flags |= auxinFLAG ;
		checkvdus = FALSE ;
	    }
/*
 *	Handle any pending interrupts.
 */
	    if (int_ena && (io_flags & int_mask)
				&& delay == FALSE && int_inh == FALSE)
	    {
		base [0] = PC & 07777 ;
		PC = 1 ;
		SF = (UF >> 6) | (IF >> 9) | (DF >> 12) ;
		IB = IF = DF = UB = UF = int_ena = FALSE ;
	    }
	    delay = FALSE ;
/*
 *	Fetch and execute the pdp8 instruction.
 */
	    (*itab [UF + (INST = *(base + (IF + PC)))]) () ;
/*
 *	Count instructions executed, if requested.
 */
	    if (cpu_count && ((INST & 07401) != 07401))
		cpu_count++ ;
	    if (eae_count && ((INST & 07401) == 07401))
		eae_count++ ;
/*
 *	Update the pdp8 program counter.
 */
	    if (++PC & 010000)
		PC &= 07777 ;
	}
    }
/*
 *	Execute pdp8 instructions with only 'count' impediment.
 */
    if (cpu_count || eae_count)
    {
	while (run)
	{
/*
 *	Check for a clock tick.
 */
	    if (!--clkcntr)
	    {
		clkcntr = CLKCNT ;
		if (clocktype && (curtime = clock ()) >= ticktime)
		{
		    ticktime += ticks ;
		    io_flags |= clockFLAG ;
		}
/*
 *	Check for a keyboard strike.
 */
		if (KeyStrike (003))
		    io_flags |= coninFLAG ;
		if (aux_vdu && KeyStrike (040))
		    io_flags |= auxinFLAG ;
	    }
/*
 *	Handle any pending interrupts.
 */
	    if (int_ena && (io_flags & int_mask)
				&& delay == FALSE && int_inh == FALSE)
	    {
		base [0] = PC & 07777 ;
		PC = 1 ;
		SF = (UF >> 6) | (IF >> 9) | (DF >> 12) ;
		IB = IF = DF = UB = UF = int_ena = FALSE ;
	    }
	    delay = FALSE ;
/*
 *	Fetch and execute the pdp8 instruction.
 */
	    (*itab [UF + (INST = *(base + (IF + PC)))]) () ;
/*
 *	Count instructions executed, if requested.
 */
	    if (cpu_count && ((INST & 07401) != 07401))
		cpu_count++ ;
	    if (eae_count && ((INST & 07401) == 07401))
		eae_count++ ;
/*
 *	Update the pdp8 program counter.
 */
	    if (++PC & 010000)
		PC &= 07777 ;
	}
    }
/*
 *	Execute pdp8 instructions with no impediments.
 */
    while (run)
    {
/*
 *	Check for a clock tick.
 */
	if (!--clkcntr)
	{
	    clkcntr = CLKCNT ;
	    if (clocktype && (curtime = clock ()) >= ticktime)
	    {
		ticktime += ticks ;
		io_flags |= clockFLAG ;
	    }
/*
 *	Check for a keyboard strike.
 */
	    if (KeyStrike (003))
		io_flags |= coninFLAG ;
	    if (aux_vdu && KeyStrike (040))
		io_flags |= auxinFLAG ;
	}
/*
 *	Handle any pending interrupts.
 */
	if (int_ena && (io_flags & int_mask)
				&& delay == FALSE && int_inh == FALSE)
	{
	    base [0] = PC & 07777 ;
	    PC = 1 ;
	    SF = (UF >> 6) | (IF >> 9) | (DF >> 12) ;
	    IB = IF = DF = UB = UF = int_ena = FALSE ;
	}
	delay = FALSE ;
/*
 *	Fetch and execute the pdp8 instruction.
 */
	(*itab [UF + (INST = *(base + (IF + PC)))]) () ;
/*
 *	Update the pdp8 program counter.
 */
	if (++PC & 010000)
	    PC &= 07777 ;
    }
}
/* -------------------------------------------------------------------- */
