
/*
 *	dasm.c
 *
 *	(C) Copyright 2003 by Robert Krten, all rights reserved.
 *	Please see the LICENSE file for more information.
 *
 *	This module contains the PDP-8 disassembler.
 *	Note that the 8/I and 8/L are featured at this point; other models
 *	should be added (particularly the 8/E's EAE instructions, as well
 *	as new IOT decodings, etc)
 *
 *	2003 12 16	R. Krten		created
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include "iot.h"							// decode table for IOTs

extern	char	*progname;					// main.c
extern	char	*version;					// version.c

extern	int		optv;						// main.c

/*
 *	dasm8
 *
 *	This takes the current address and the instruction value
 *	and prints the decoded instruction.  A static variable
 *	is used to kludge up 2-word instructions (e.g., MUY <const>).
 *
 *	The IOTs are coded in a table; in some cases, conflicts exist, you'll
 *	need to select the appropriate #defines to make them go away :-)
 *	As shipped, the #defines match my preferences.
*/

static const char *codes [8] = {"AND", "TAD", "ISZ", "DCA", "JMS", "JMP", "IOT", "OPR"};

static unsigned short int two_word = 0;		// set to hold two-word instruction, else zero (instruction 0 is not a two-word instruction)

void
dasm8 (int addr, unsigned short int buf)
{
	int		indirect;
	int		curpage;

	// calculate the indirect and curpage flags; only valid for instructions 0000 -> 05777
	indirect = buf & 00400;
	curpage = buf & 00200;

	if (two_word) {
		printf ("%04o\n", buf);
		two_word = 0;
		return;
	}

	printf ("%04o, %04o ", addr, buf);

	switch (buf & 07000) {
	case	00000:			// AND
	case	01000:			// TAD
	case	02000:			// ISZ
	case	03000:			// DCA
	case	04000:			// JMS
	case	05000:			// JMP
		printf ("    %-4s %c%c %04o\n", codes [buf >> 9], indirect ? 'I' : ' ', curpage ? ' ' : 'Z', curpage ? (addr & 07600) + (buf & 00177) : buf & 00177);
		break;
	case	06000:			// IOT
		printf ("    %-4s\n", iots [buf & 00777]);
		break;
	case	07000:			// OPR
		// perform "short form" OPRs here first...
		// switch/case the few that exist...
		switch (buf) {
			case	07000: printf ("    NOP\n"); break;
			case	07041: printf ("    CIA\n"); break;
			case	07120: printf ("    STL\n"); break;
			case	07204: printf ("    GLK\n"); break;
			case	07240: printf ("    STA\n"); break;
			case	07410: printf ("    SKP\n"); break;
			case	07604: printf ("    LAS\n"); break;
			case	07621: printf ("    CAM\n"); break;
			default:

				// determine group (0401 is 0000/0001 for group 1, 0400 for group 2, 0401 for EAE)
				switch (buf & 00401) {
				case	00000:	// group 1
				case	00001:	// group 1
					printf ("    ");
					// sequence 1
					if (buf & 00200) {
						printf ("CLA ");
					}
					if (buf & 00100) {
						printf ("CLL ");
					}
					// sequence 2
					if (buf & 00040) {
						printf ("CMA ");
					}
					if (buf & 00020) {
						printf ("CML ");
					}
					// sequence 3
					if (buf & 00001) {
						printf ("IAC ");
					}
					// sequence 4
					if (buf & 00010) {
						if (buf & 00002) {
							printf ("RTR ");
						} else {
							printf ("RAR ");
						}
					}
					if (buf & 00004) {
						if (buf & 00002) {
							printf ("RTL ");
						} else {
							printf ("RAL ");
						}
					}
					printf ("\n");
					break;
		
				case	00400:	// group 2
					printf ("    ");
					// sequence 1
					if (buf & 00100) {
						if (buf & 00010) {
							printf ("SPA ");
						} else {
							printf ("SMA ");
						}
					}
					if (buf & 00040) {
						if (buf & 00010) {
							printf ("SNA ");
						} else {
							printf ("SZA ");
						}
					}
					if (buf & 00020) {
						if (buf & 00010) {
							printf ("SZL ");
						} else {
							printf ("SNL ");
						}
					}
					// sequence 2
					if (buf & 00200) {
						printf ("CLA ");
					}
					// sequence 3
					if (buf & 00004) {
						printf ("OSR ");
					}
					if (buf & 00002) {
						printf ("HLT ");
					}
					printf ("\n");
					break;
				case	00401:	// EAE
					printf ("    ");
					// sequence 1
					if (buf & 00200) {
						printf ("CLA ");
					}
					// sequence 2
					if (buf & 00100) {
						printf ("MQA ");
					}
					if (buf & 00040) {
						printf ("SCA ");
					}
					if (buf & 00020) {
						printf ("MQL ");
					}
					// sequence 3
					switch (buf & 00016) {
					case	0:		// no further ops, done
						printf ("\n");
						break;
					case	002:
						printf ("SCL ");
						two_word = buf;
						break;
					case	004:
						printf ("MUY ");
						two_word = buf;
						break;
					case	006:
						printf ("DVI ");
						two_word = buf;
						break;
					case	010:
						printf ("NMI\n");
						break;
					case	012:
						printf ("SHL ");
						two_word = buf;
						break;
					case	014:
						printf ("ASR ");
						two_word = buf;
						break;
					case	016:
						printf ("LSR ");
						two_word = buf;
						break;
					}
					break;
				}
				break;
		}
		break;
	}
}

