/*
 *	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.
 *
 *	Disassembler module.
 */
#include "pdp8.h"
#include "pdp8regs.h"
#include "pdp8txt.h"

STATIC BYTE strtemp [40] ;
/* -------------------------------------------------------------------- */
VOID disassem (VOID)
{
    INT i, temp, addr ;

    switch (INST & 07000)
    {
/*
 *	Process a memory reference instruction.
 *
 *	          1      1       2
 *	   3 5    0      7       5
 *	Instruction  (Dir) ((Indir))
 *	TAD I 7776 (2345) ((6712))
 */
	case 00000 :				/* AND			*/
	case 01000 :				/* TAD			*/
	case 02000 :				/* ISZ			*/
	case 03000 :				/* DCA			*/
	case 04000 :				/* JMS			*/
	case 05000 :				/* JMP			*/
	    sprintf (pdp8exec, "%3s ", mritxt [INST >> 9]) ;
	    if (INST & 0400)
		strcat(pdp8exec, "I ") ;
	    addr = INST & 0177 ;
	    if (INST & 0200)
		addr += PC & 07600 ;
	    i = PC - addr ;
	    if (INST >= 04000 && addr > 0177 && !i)
		sprintf (strtemp, ".") ;
	    else if (INST >= 04000 && addr > 0177 && i > 0 && i < 5)
		sprintf (strtemp, ".-%d", i) ;
	    else
	    {
		if (INST >= 04000 && addr > 0177
						&& i < 0 && i > -5)
		    sprintf (strtemp, ".+%d", -i) ;
		else
		    sprintf (strtemp, "%o", addr) ;
	    }
	    strcat (pdp8exec, strtemp) ;
/*
 *	           1      1      2
 *	    4 6    1      8      5
 *	Code       (Dir) ((Indir))
 *	TAD I 7776 (2345) ((6712))
 */
	    if (run)
	    {
		temp = (INST >= 04000 && !(INST & 0400) && IB != IF)
							? IB : IF ;
		addr = INST & 0177 ;
		if (INST & 0200)
		    addr += PC & 07600 ;
		i = ((INST & 0400) && addr > 07 && addr < 020) ? 1 : 0 ;
		addr = (*(base + (temp + addr)) + i) & 07777 ;
		if (INST < 05000 || INST >= 05400)
		{
		    sprintf (strtemp, " (%04o)", addr) ;
		    strcat (pdp8exec, strtemp) ;
		}
		if (INST < 05000 && (INST & 0400))
		{
		    temp = (INST < 04000) ? DF : IB ;
		    addr = *(base + temp + addr) ;
		    sprintf (strtemp, " ((%04o))", addr) ;
		    strcat (pdp8exec, strtemp) ;
		}
	    }
	    break ;
/*
 *	Process an IOT instruction.
 *
 *	0
 *	Code
 *	CDF 10
 *	CDI 30
 */
	case 06000 :				/* IOT			*/
	    sprintf (pdp8exec, "%s", iottxt [INST & 0777]) ;
	    break ;
/*
 *	Process an OPR instruction.
 *
 *	Code      (Dir) ((Indir))
 *	SPA SNA SZL CLA OSR HLT
 */
	case 07000 :				/* OPR			*/
	    switch (INST & 07401)
	    {
		case 07000 :			/* OPR Group I		*/
		case 07001 :
		    sprintf (pdp8exec, "%s",
				oprtxt1 [INST & 0377]) ;
		    break ;
		case 07400 :			/* OPR Group II		*/
		    sprintf (pdp8exec, "%s",
					oprtxt2 [(INST & 0377) >> 1]) ;
		    break ;
/*
 *		|           |           |           |
 *		|---|---|---|---|---|---|---|---|---|
 *		| 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
 *		| 1 |CLA|MQA|SCA|MQL|   |   |   | 1 |	Group III Mode A
 *		|---|---|---|---|---|---|---|---|---|
 *	Sequence:     1   2       2  \____3____/
 *					  V
 *		0 = NOP   2 = MUY#   4 = NMI    6 = ASR#
 *		1 = SCL#  3 = DVI#   5 = SHL#   7 = LSR#
 *
 *		|           |           |           |
 *		|---|---|---|---|---|---|---|---|---|
 *		| 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
 *		| 1 |CLA|MQA|   |MQL|   |   |   | 1 |	Group III Mode B
 *		|---|---|---|---|---|---|---|---|---|
 *	Sequence:     1   2  \    2            /
 *			      \_______3_______/
 *				      V
 *		0 = NOP    4 = NMI    10 = SCA    14 = DPSZ
 *		1 = ACS    5 = SHL#   11 = DAD#   15 = DPIC*
 *		2 = MUY#   6 = ASR#   12 = DST#   16 = DCM*
 *		3 = DVI#   7 = LSR#   13 = SWBA   17 = SAM
 *		# = 2-word instructions
 *		* = (MQL & MQA must be set)
 *
 *	                                3
 *	0                               2
 *	Code      (Dir) ((Indir))
 *	CLA MQL MQA SCA MUY 1234
 *	CLA MQL MQA DST 61234
 *	CLA MQL MQA DAD 61234 (23456701)
 *
 *	Process an EAE instruction.
 */
		case 07401 :			/* EAE			*/
		    i = (INST &0377) >> 1 ;
		    if (EAE != 'B')
		    {
			sprintf (pdp8exec, "%s ", eaetxta [i]) ;
			switch (INST & 016)
			{
			    case  02 :	/* SCL	*/
			    case  04 :	/* MUY	*/
			    case  06 :	/* DVI	*/
			    case 012 :	/* SHL	*/
			    case 014 :	/* ASR	*/
			    case 016 :	/* LSR	*/
				sprintf (strtemp, "%04o",
				    *(base + (IF + ((PC + 1) & 07777))));
				if (!run)
				    incrPC = TRUE ;
				strcat (pdp8exec, strtemp) ;
			    default :
				break ;
			}
		    }
		    else				/* EAE Mode B	*/
		    {
			sprintf (pdp8exec, "%s ", eaetxtb [i]) ;
			switch (INST & 056)
			{
			    case  04 :	/* MUY	*/
			    case  06 :	/* DVI	*/
				i = DF + *(base + (IF
						+ ((PC + 1) & 07777))) ;
				if (run)
				{
				    sprintf (strtemp, "%05o", i) ;
				    strcat (pdp8exec, strtemp) ;
				    sprintf (strtemp, " (%04o)",
							*(base + i)) ;
				}
				else
				{
				    sprintf (strtemp, "%04o", i & 07777) ;
				    incrPC = TRUE ;
				}
				strcat (pdp8exec, strtemp) ;
				break ;
			    case 012 :	/* SHL	*/
			    case 014 :	/* ASR	*/
			    case 016 :	/* LSR	*/
				sprintf (strtemp, "%04o",
						*(base + (IF
						+ ((PC + 1) & 07777)))) ;
				strcat (pdp8exec, strtemp) ;
				if (!run)
				    incrPC = TRUE ;
				break ;
			    case 042 :	/* DAD	*/
			    case 044 :	/* DST	*/
				if (run)
				{
				    i = DF + *(base + (IF
						+ ((PC + 1) & 07777))) ;
				    sprintf (strtemp, "%05o", i) ;
				    strcat (pdp8exec, strtemp) ;
				    if (INST & 2)
				    {
					sprintf (strtemp, " (%04o",
						*(base + i++)) ;
				        strcat (pdp8exec, strtemp) ;
				        sprintf (strtemp, "%04o)",
						*(base + i)) ;
				        strcat (pdp8exec, strtemp) ;
				    }
				}
				else
				{
				    sprintf (strtemp, "%04o",
						*(base + (IF + PC + 1))) ;
				    incrPC = TRUE ;
				    strcat (pdp8exec, strtemp) ;
				}
			    default :
				break ;
			}
		    }
	    }
	    break ;
    }
    return ;
}
/* -------------------------------------------------------------------- */
