/* Copyright 1996 Tommy Johnson
**
** Permission is hereby granted to copy, reproduce, redistribute or otherwise
** use this software as long as: there is no monetary profit gained
** specifically from the use or reproduction of this software, it is not
** sold, rented, traded or otherwise marketed, and this copyright notice is
** included prominently in any copy made.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ANY USE OF THIS
** SOFTWARE IS AT THE USER'S OWN RISK.
*/ 

#include<stdio.h>
#include"asm.h"
#include"table.h"

/* uses vars:  offset, pc, admode, arg1, arg2, arg3, exprlist
*/

/* watch char set.  Note there are three spaces.  The first one is a
** divide char, and the second one is a beep
*/
char watchcharset[]={'0','1','2','3','4','5','6','7','8','9',\
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',\
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',\
'y', 'z',\
' ', '!', '\"', '#', '$', '%', '&', '\'', '(', ')',\
'*', '+', ',', '-', '.', '/', ';', '\\', ' ', '=',\
'\07', '?'};

#undef DEBUG

#define TCOMP(x)	(((x)<0)?((~(-(x)))+1):(x))

int gencode(char *opcode)
{
	int i,f,inst;

	f=-1;      /* if we don't know addressing mode yet, look it up */
		   /* from the opcode used. */
	switch(admode)
	{
		case UNKNOWN1:
	{
		for(i=0;(i<NUMINST) &&(f<0);i++)
			if (!strcmp(table[i].name,opcode))
			{
				if ((table[i].format==DIR) || (table[i].format==REL))
				{
					admode=table[i].format;
					f=i;
				}
			}
	}
		break;
		case UNKNOWN2:
	{
		for(i=0;(i<NUMINST) &&(f<0);i++)
			if (!strcmp(table[i].name,opcode))
			{
				if ((table[i].format==DIR3))
				{
					admode=table[i].format;
					f=i;
				}
			}
	}
	}  /* end of switch */

	  /* correct addressing mode, if range of original is too small */
	if ((admode==IX1) && (arg1>255))
	{
		admode=IX2;
		f=-1;
	}
	if ((admode==DIR) && (arg1>255))
	{
		admode=EXT;
		f=-1;
	}

	if (f<0)   /* look up opcode if we don't know it yet */
	{
		for(i=0;(i<NUMINST) &&(f<0);i++)
			if ((table[i].format==admode) &&(!strcmp(table[i].name,opcode)))
				f=i;
	}

	if (f<0)
		fprintf(stderr,"line %d: Illegal instruction/addressing mode combination\n",lineno);

	inst=(f>=0)?table[f].opcode:0;

	if ((admode==DIR2) || (admode==DIR3))
	{
		inst=(inst&0xF1)|((arg1&7)<<1);
		arg1=arg2;
		arg2=arg3;
	}

#ifdef DEBUG
	fprintf(stderr,"line %d pc %x opcode %s %x mode %d args %x %x %x\n",lineno,pc,opcode,inst,admode,arg1,arg2,arg3);
#endif

	if (pass==2)
	{
		fputc(inst,output);
		switch(admode)       /* for args */
		{
			case IX2:
			case EXT:
				fputc((arg1>>8)&0xFF,output);
				fputc((arg1  )&0xFF,output);
				break;
			case DIR2:
				fputc((arg1  )&0xFF,output);
				fputc(TCOMP(arg2-(pc+3))&0xFF,output);
				break;
			case DIR:
			case DIR3:
			case IMM:
			case IX1:
				fputc((arg1  )&0xFF,output);
				break;
			case REL:
				fputc((TCOMP(arg1-(pc+2)))&0xFF,output);
				break;
		}
	}
	pc++; offset++;   /* for opcode */
	switch(admode)       /* for args */
	{
		case IX2:
		case EXT:
		case DIR2:
			pc+=2; offset+=2;
			break;
		case DIR3:
		case DIR:
		case REL:
		case IX1:
		case IMM:
			pc++; offset++;
			break;
	}
}

int gendb(int count)
{
	int i;

#ifdef DEBUG
	fprintf(stderr, "db: len %d\n",count);
#endif
	if (pass==2)
		for(i=(count-1);i>=0;i--)
		{
			fputc(exprlist[i],output);
		}

	pc+=count;
	offset+=count;
}

int gentimex(char *istr)
{
	int i,j;
	int len;
	char *str;

	len=strlen(istr);
	istr[len]=0;
	str=&istr[1];    /* lop off " chars from the parser */
	len-=2;

#ifdef DEBUG
	fprintf(stderr,"timex: len %d\n",len);
#endif
	if (pass==2)
	{
		for(i=0;i<len;i++)
			if (isupper(str[i]))
				str[i]=tolower(str[i]);
		for(i=0;i<len;i++)
		{
			for(j=0;j<63;j++)
				if (str[i]==watchcharset[j])
				{
					fputc(j,output);
					j=64;
				}
		}
	}
	pc+=len;
	offset+=len;
}
