

/*************************************************************************

                      Copyright (c) 1984 by Nick de Smith

        This software is supplied for interest and non-profit making
        purposes  only.   Under  no  circumstance  shall it be lent,
        copied or otherwise used for profit.  All  rights  regarding
        the  use  and  ownership of this software shall at all times
        remain with the author, who does not guarantee the  accuracy
        or  reliabilty  of this software and who will not accept any
        liability for its use.

        This software may not be copied or distributed  without  the
        inclusion of the above copyright notice.

        January 31st 1984

*************************************************************************/


/*************************************************************************


	Program :	DISMAC.C

	Author	:	Nick de Smith		November/December 1982

	Description :

			CAM program to test the CAMTBL drive tables.


*************************************************************************/

#include	<stdio.h>
#ifdef	vax11c
#include	ctype
#endif

#define	MAIN				/* Force root code in CAMTBL.H	*/
#include	"camtbl.h"		/* Drive table interface spec	*/

/*	Table of instruction type descriptions				*/

char	*types[] = {
	"No operands",
	"SS,DD  src, dest       Mov etc",
	"R,DD   reg, dest       Jsr + Xor",
	"SS,R   src, reg        Mul etc",
	"SS     src             Jmp, Clr etc",
	"R      reg             Rts, Fadd etc",
	"R,OO   reg, 6 bit off  Sob",
	"OOO    8 bit off       Branches",
	"NNNNNN 16 bit data     .Word",
	"NNN    8 bit data      Emt + Trap",
	"NN     6 bit data      Mark",
	"N      3 bit data      Spl",
	"Fsrc, Acc              Mulf, Modf etc",
	"Acc, Fdst              Stf + Stcfd",
	"Src, Acc               Ldcif + Ldexp",
	"Acc, Dst               Stcfi + Stexp",
	"Fsrc                   Clrf etc",

/*	'Macro' instructions		*/

	"Jmp for Jmp/Jmpx",
	"Rts for Return/Return Rn",
	"Jsr for Call/Callx",
	"Clr -(Sp) or Mov x,-(Sp)",
	"Tst (Sp)+ or Mov (Sp)+,x"
	};

int	debug;				/* In debug mode		*/
int	ir;				/* 'instruction register'	*/


/*************************************************************************
*
*
*				m a i n
*				-------
*
*	Main program.
*
*************************************************************************/

main(argc, argv)
char	*argv[];
{
	register int i,c;
	register char *p;

	for (i = 1; i < argc; ++i) {
		p = argv[i];
#ifdef	c_vms
		if (*p == '-' || *p == '/') {
			p++;
#else
		if (*p++ == '-') {
#endif
			while (c = *p++) {
				switch (isupper(c) ? tolower(c) : c) {

				case 'd':
					debug++;
					break;

		/* Table patch options	*/

				case 'e':	/* Use RSX not RSTS emts*/
					x104[0].t_flags = T_END | T_NNN;
					x104[0].t_next  = emtext;
					x10437[7].t_next  = "dir$";
					break;

				case 'f':	/* Disable floating pt.	*/
					x1[7].t_flags = T_END | T_NNNNNN;
					x1[7].t_next  = word;
					break;

				case 'k':	/* Disable kernal opcodes */
					/* halt		*/
					x00000[0].t_flags = T_END | T_NNNNNN;
					x00000[0].t_next  = word;
					/* wait		*/
					x00000[1].t_flags = T_END | T_NNNNNN;
					x00000[1].t_next  = word;
					/* reset	*/
					x00000[5].t_flags = T_END | T_NNNNNN;
					x00000[5].t_next  = word;
					/* mfpt		*/
					x00000[7].t_flags = T_END | T_NNNNNN;
					x00000[7].t_next  = word;
					/* mfpi		*/
					x006[5].t_flags = T_END | T_NNNNNN;
					x006[5].t_next  = word;
					/* mtpi		*/
					x006[6].t_flags = T_END | T_NNNNNN;
					x006[6].t_next  = word;
					/* mtps		*/
					x106[4].t_flags = T_END | T_NNNNNN;
					x106[4].t_next  = word;
					/* mfpd		*/
					x106[5].t_flags = T_END | T_NNNNNN;
					x106[5].t_next  = word;
					/* mtpd		*/
					x106[6].t_flags = T_END | T_NNNNNN;
					x106[6].t_next  = word;
					/* mfps		*/
					x106[7].t_flags = T_END | T_NNNNNN;
					x106[7].t_next  = word;
					break;

				case 'm':	/* Disable 'macros'	*/
					/* change PUSH/POP to MOV	*/
					x0[1].t_flags	= T_END | T_SSDD;
					x0[1].t_next	= "mov";
					/* change PUSH to CLR -(SP)	*/
					x005[0].t_flags	= T_END | T_SS;
					x005[0].t_next	= "clr";
					/* change POP to TST (SP)+	*/
					x005[7].t_flags	= T_END | T_SS;
					x005[7].t_next	= "tst";
					/* change CALL to JSR		*/
					x00[4].t_flags	= T_END | T_RDD;
					x00[4].t_next	= "jsr";
					/* change RETURN to RTS		*/
					x0002[0].t_flags= T_END | T_R;
					x0002[0].t_next	= "rts";
					/* change JMP/JMPX to JMP	*/
					x000[1].t_flags	= T_END | T_SS;
					break;

				default:
					usage();
				}
			}
		}
		else
			examine(argv[i]);
	}
}

/*************************************************************************
*
*
*				e x a m i n e
*				-------------
*
*	Examine a passed argument - If it's an octal number, try to
*	decode it as an 'ir'.
*
*************************************************************************/

examine(arg)
char	*arg;
{
	if (octal(arg, &ir))
		opcode();
	else
		printf("\"%s\" is not octal\n", arg);
}


/*************************************************************************
*
*
*				o p c o d e 
*				-----------
*
*	Decode an 'ir'.
*
*************************************************************************/

opcode()
{
	register TREE_PTR node;
	register int branch;
	register int _ir;

	int	offset;

	offset = 014;
	node   = ((_ir = ir) & 0100000 ? x1 : x0);

	for (;;) {
		if ((node = &node[(_ir & (007 << offset)) >> offset])->t_flags & T_END)
			break;
		node = node->t_next;
		offset -= 3;
	}

	printf("%06o = \"%-6s\", %s\n", ir, node->t_next,
		types[node->t_flags & T_TYPE]);
}


/*************************************************************************
*
*
*				o c t a l
*				---------
*
*	Evaluate an octal number. Return TRUE if number is ok, FALSE else.
*
*************************************************************************/

octal(arg, loc)
char	*arg;
int	*loc;
{
	char	*p;

	*loc = 0;
	p = arg;
	while (*p) {
		if (*p < '0' || *p > '7')
			return(FALSE);
		*loc *= 8;
		*loc += (*p++ - '0');
	}
	return (TRUE);
}
		
/*************************************************************************
*
*
*				u s a g e
*				---------
*
*	How to luse this utility.
*
*************************************************************************/

usage()
{
	error("Usage: dis -defkm arg1 [flags] [arg2...]");
}
