view src/pseudo.c @ 8:f1df096aa76f 1.1

Tagged 1.1 bugfix release
author lost
date Sun, 04 Jan 2009 05:46:07 +0000
parents 34568fab6058
children 804d7465e0f9
line wrap: on
line source

/*
pseudo.c
Copyright © 2008 William Astle

This file is part of LWASM.

LWASM is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.

You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.


This file implements the various pseudo operations.
*/

#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "lwasm.h"
#include "instab.h"

#include <stdio.h>

void pseudo_org(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int v1, rval;
	
	if (cl -> hassym)
	{
		register_error(as, cl, ERR_SYM);
		cl -> hassym = 0;
	}
	rval = eval_expr(as, cl, optr, &v1);
	cl -> addr = v1;
	cl -> addrset = 1;
	as -> addr = v1;
}

void pseudo_include(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int v1;

	if (as -> passnum != 1)
		return;
	while (**optr && isspace(**optr))
		(*optr)++;
	if (!**optr)
	{
		register_error(as, cl, ERR_BADFN);
		return;
	}
	for (v1 = 0; *((*optr)+v1) && !isspace(*((*optr)+v1)); v1++)
		;
	{
		char *fn = malloc(v1 + 1);
		strncpy(fn, *optr, v1);
		fn[v1] = '\0';
		lwasm_read_file(as, fn);
	}
}


void pseudo_rmb(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_FORWARD);
		return;
	}
	if (v1 < 0)
	{
		errorp1(ERR_BADOPER);
		return;
	}
	cl -> len = v1;
	cl -> nocode = 1;
}

void pseudo_rmd(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_FORWARD);
		return;
	}
	if (v1 < 0)
	{
		errorp1(ERR_BADOPER);
		return;
	}
	cl -> len = v1 * 2;
	cl -> nocode = 1;
}

void pseudo_rmq(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_FORWARD);
		return;
	}
	if (v1 < 0)
	{
		errorp1(ERR_BADOPER);
		return;
	}
	cl -> len = v1 * 4;
	cl -> nocode = 1;
}

void pseudo_zmb(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_FORWARD);
		return;
	}
	if (v1 < 0)
	{
		errorp1(ERR_BADOPER);
		return;
	}
	while (v1--)
		emit(0);
}

void pseudo_zmd(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_FORWARD);
		return;
	}
	if (v1 < 0)
	{
		errorp1(ERR_BADOPER);
		return;
	}
	while (v1--)
	{
		emit(0);
		emit(0);
	}
}

void pseudo_zmq(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_FORWARD);
		return;
	}
	if (v1 < 0)
	{
		errorp1(ERR_BADOPER);
		return;
	}
	while (v1--)
	{
		emit(0);
		emit(0);
		emit(0);
		emit(0);
	}
}

void pseudo_end(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
	while (**optr && isspace(**optr))
		;
	if (**optr && **optr != '*' && **optr != ';')
	{
		rval = eval_expr(as, cl, optr, &v1);
		if (rval < 0)
		{
			errorp1(ERR_FORWARD);
			return;
		}
	}
	else
	{
		v1 = 0;
	}
	if (as -> passnum == 2)
		as -> execaddr = v1;
}				

void pseudo_align(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	int cn;

	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_FORWARD);
		return;
	}
	cn = cl -> addr % v1;
	if (cn)
	cn = v1 - cn; 

	while (cn)
	{
		emit(0);
		cn--;
	}
}

void pseudo_equ(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
	if (cl -> hassym == 0)
	{
		errorp1(ERR_NOSYM);
		return;
	}
	rval = eval_expr(as, cl, optr, &v1);
	// eval_expr returns -1 if there was a forward ref
	// or -2 if the expr was invalid
	if (rval == -2)
	{
		// carp
		errorp1(ERR_FORWARD);
	}
	if (rval < 0)
	{
		// remove symbol ref
		cl -> hassym = 0;
		// mark as a "comment" so it isn't processed next time
		cl -> opcode = -1;
		return;
	}
	cl -> code_symloc = v1;
	cl -> isequ = 1;
	cl -> symaddr = v1 & 0xFFFF;
}

void pseudo_set(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
	if (cl -> hassym == 0)
	{
		errorp1(ERR_NOSYM);
		return;
	}
	rval = eval_expr(as, cl, optr, &v1);
	// eval_expr returns -1 if there was a forward ref
	// or -2 if the expr was invalid
	if (rval == -2)
	{
		// carp
		errorp1(ERR_FORWARD);
	}
	if (rval < 0)
	{
		// remove symbol ref
		cl -> hassym = 0;
		// mark as a "comment" so it isn't processed next time
		cl -> opcode = -1;
		return;
	}
	cl -> code_symloc = v1;
	cl -> isset = 1;
	cl -> isequ = 1;
	cl -> symaddr = v1 & 0xFFFF;
}

void pseudo_setdp(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;

	if (cl -> hassym)
	{
		register_error(as, cl, ERR_SYM);
		cl -> hassym = 0;
		return;
	}
	else
	{
		rval = eval_expr(as, cl, optr, &v1);
		if (rval == -1)
		{
			errorp1(ERR_FORWARD);
		}
		if (rval < 0)
		{
			cl -> opcode = -1;
			return;
		}
	}
	// setdp needs to resolve properly on pass 2
	if (v1 > 0xff || v1 < 0)
	{
		errorp1(ERR_OVERFLOW);
	}	
	as -> dpval = v1 & 0xff;
	cl -> dpval = v1 & 0xff;
	cl -> issetdp = 1;
	cl -> numcodebytes = 0;
//printf("%s\n", "SETDP2");
}

void pseudo_fcc(asmstate_t *as, sourceline_t *cl, char **optr)
{		
	int cn = 0;
	int delim = 0;
				
	delim = *(*optr)++;
	if (!delim)
	{
		errorp1(ERR_BADOPER);
	}
	else
	{
		while (**optr && **optr != delim)
		{
			emit(**optr);
			(*optr)++;
			cn += 1;
		}
	}
	cl -> len = cn;
}
		
void pseudo_fcs(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int cn = 0;
	int delim = 0;
				
	delim = *(*optr)++;
	if (!delim)
	{
		errorp1(ERR_BADOPER);
	}
	else
	{
		while (**optr && **optr != delim)
		{
			if (!*((*optr) + 1) || *((*optr) + 1) == delim)
				emit((**optr) | 0x80);
			else
				emit(**optr);
			(*optr)++;
			cn += 1;
		}
	}
	cl -> len = cn;
}

void pseudo_fcn(asmstate_t *as, sourceline_t *cl, char **optr)
{		
	int cn = 0;
	int delim = 0;
				
	delim = *(*optr)++;
	if (!delim)
	{
		errorp1(ERR_BADOPER);
	}
	else
	{
		while (**optr && **optr != delim)
		{
			emit(**optr);
			(*optr)++;
			cn += 1;
		}
	}
	emit(0);
	cl -> len = cn + 1;
}
		
void pseudo_fcb(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int rval, v1;
	
fcb_again:
	rval = eval_expr(as, cl, optr, &v1);
	if (v1 < -127 || v1 > 0xff)
		errorp2(ERR_OVERFLOW);
	emit(v1 & 0xff);
	if (**optr == ',')
	{
		(*optr)++;
		goto fcb_again;
	}
}

void pseudo_fdb(asmstate_t *as, sourceline_t *cl, char **optr)
{			
	int rval, v1;
	
fdb_again:
	rval = eval_expr(as, cl, optr, &v1);
	emit((v1 >> 8) & 0xff);
	emit(v1 & 0xff);
	if (**optr == ',')
	{
		(*optr)++;
		goto fdb_again;
	}
}

void pseudo_fqb(asmstate_t *as, sourceline_t *cl, char **optr)
{	
	int rval, v1;

fqb_again:
	rval = eval_expr(as, cl, optr, &v1);
	emit((v1 >> 24) & 0xff);
	emit((v1 >> 16) & 0xff);
	emit((v1 >> 8) & 0xff);
	emit(v1 & 0xff);
	if (**optr == ',')
	{
		(*optr)++;
		goto fqb_again;
	}
}

// don't need to do anything if we are executing one of these
void pseudo_endc(asmstate_t *as, sourceline_t *cl, char **optr)
{
	return;
}

// if "else" executes, we must be going into an "ignore" state
void pseudo_else(asmstate_t *as, sourceline_t *cl, char **optr)
{
	as -> skipcond = 1;
	as -> skipcount = 1;
}

void pseudo_ifne(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int v1;
	int rval;
//	printf("ifne %s\n", *optr);
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_BADCOND);
	}
	else
	{
//	printf("Condition value: %d\n", v1);
		if (!v1)
		{
//		printf("condition no match\n");
			as -> skipcond = 1;
			as -> skipcount = 1;
		}
	}
}
void pseudo_ifeq(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int v1;
	int rval;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_BADCOND);
	}
	else
	{
		if (v1)
		{
			as -> skipcond = 1;
			as -> skipcount = 1;
		}
	}
}
void pseudo_iflt(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int v1;
	int rval;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_BADCOND);
	}
	else
	{
		if (v1 >= 0)
		{
			as -> skipcond = 1;
			as -> skipcount = 1;
		}
	}
}
void pseudo_ifle(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int v1;
	int rval;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_BADCOND);
	}
	else
	{
		if (v1 > 0)
		{
			as -> skipcond = 1;
			as -> skipcount = 1;
		}
	}
}
void pseudo_ifgt(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int v1;
	int rval;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_BADCOND);
	}
	else
	{
		if (v1 <= 0)
		{
			as -> skipcond = 1;
			as -> skipcount = 1;
		}
	}
}
void pseudo_ifge(asmstate_t *as, sourceline_t *cl, char **optr)
{
	int v1;
	int rval;
	
	rval = eval_expr(as, cl, optr, &v1);
	if (rval < 0)
	{
		errorp1(ERR_BADCOND);
	}
	else
	{
		if (v1 < 0)
		{
			as -> skipcond = 1;
			as -> skipcount = 1;
		}
	}
}

void pseudo_error(asmstate_t *as, sourceline_t *cl, char **optr)
{
	cl -> user_error = strdup(*optr);
	errorp1(ERR_USER);
}