view lwasm/pseudo.c @ 350:f5666775d76f

Even more pseudo ops
author lost@starbug
date Sat, 27 Mar 2010 22:59:15 -0600
parents dcd2978a7d18
children 4dba8c7e242c
line wrap: on
line source

/*
pseudo.c
Copyright © 2010 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/>.

*/

#include <config.h>

#include "lwasm.h"
#include "instab.h"

#include "lw_string.h"

// for "end"
PARSEFUNC(pseudo_parse_end)
{
	lw_expr_t addr;
	
	as -> endseen = 1;
	
	if (as -> output_format != OUTPUT_DECB)
	{
		skip_operand(p);
		return;
	}
	
	addr = lwasm_parse_expr(as, p);
	if (!addr)
	{
		lwasm_register_error(as, l, "Bad expression");
		addr = lw_expr_build(lw_expr_type_int, 0);
	}
	lwasm_save_expr(l, 0, addr);
}

EMITFUNC(pseudo_emit_end)
{
	lw_expr_t addr;
	
	addr = lwasm_fetch_expr(l, 0);
	
	if (addr)
	{
		if (!lw_expr_istype(addr, lw_expr_type_int))
			lwasm_register_error(as, l, "Exec address not constant!");
		else
			as -> execaddr = lw_expr_intval(addr);
	}
	as -> endseen = 1;
}

PARSEFUNC(pseudo_parse_fcb)
{
	int i = 0;
	lw_expr_t e;
	
	for (;;)
	{
		e = lwasm_parse_expr(as, p);
		if (!e)
		{
			lwasm_register_error(as, l, "Bad expression (#%s)", i);
			break;
		}
		lwasm_save_expr(l, i, e);
		i++;
	}
	
	l -> len = i;
}

EMITFUNC(pseudo_emit_fcb)
{
	int i;
	lw_expr_t e;
	int v;
	
	for (i = 0; i < l -> len; i++)
	{
		e = lwasm_fetch_expr(l, i);
		lwasm_emitexpr(l, e, 1);
	}
}

PARSEFUNC(pseudo_parse_fdb)
{
	int i = 0;
	lw_expr_t e;
	
	for (;;)
	{
		e = lwasm_parse_expr(as, p);
		if (!e)
		{
			lwasm_register_error(as, l, "Bad expression (#%s)", i);
			break;
		}
		lwasm_save_expr(l, i, e);
		i++;
	}
	
	l -> len = i * 2;
}

EMITFUNC(pseudo_emit_fdb)
{
	int i;
	lw_expr_t e;
	int v;
	
	for (i = 0; i < (l -> len)/2; i++)
	{
		e = lwasm_fetch_expr(l, i);
		lwasm_emitexpr(l, e, 2);
	}
}

PARSEFUNC(pseudo_parse_fqb)
{
	int i = 0;
	lw_expr_t e;
	
	for (;;)
	{
		e = lwasm_parse_expr(as, p);
		if (!e)
		{
			lwasm_register_error(as, l, "Bad expression (#%s)", i);
			break;
		}
		lwasm_save_expr(l, i, e);
		i++;
	}
	
	l -> len = i * 4;
}

EMITFUNC(pseudo_emit_fqb)
{
	int i;
	lw_expr_t e;
	int v;
	
	for (i = 0; i < (l -> len)/4; i++)
	{
		e = lwasm_fetch_expr(l, i);
		lwasm_emitexpr(l, e, 4);
	}
}

PARSEFUNC(pseudo_parse_fcc)
{
	char delim;
	int i;
	
	if (!**p)
	{
		lwasm_register_error(as, l, "Bad operand");
		return;
	}
	
	delim = **p;
	(*p)++;
	
	for (i = 0; (*p)[i] && (*p)[i] != delim; i++)
		/* do nothing */ ;
	
	if ((*p)[i] != delim)
	{
		lwasm_register_error(as, l, "Bad operand");
		return;
	}
	
	l -> lstr = lw_strndup(*p, i);
	(*p) += i + 1;
	
	l -> len = i;
}

EMITFUNC(pseudo_emit_fcc)
{
	int i;
	
	for (i = 0; i < l -> len; i++)
		lwasm_emit(l, l -> lstr[i]);
}

PARSEFUNC(pseudo_parse_fcs)
{
	char delim;
	int i;
	
	if (!**p)
	{
		lwasm_register_error(as, l, "Bad operand");
		return;
	}
	
	delim = **p;
	(*p)++;
	
	for (i = 0; (*p)[i] && (*p)[i] != delim; i++)
		/* do nothing */ ;
	
	if ((*p)[i] != delim)
	{
		lwasm_register_error(as, l, "Bad operand");
		return;
	}
	
	l -> lstr = lw_strndup(*p, i);
	(*p) += i + 1;
	
	l -> len = i;
}

EMITFUNC(pseudo_emit_fcs)
{
	int i;
	
	for (i = 0; i < l -> len - 1; i++)
		lwasm_emit(l, l -> lstr[i]);
	lwasm_emit(l, l -> lstr[i] | 0x80);
}

PARSEFUNC(pseudo_parse_fcn)
{
	char delim;
	int i;
	
	if (!**p)
	{
		lwasm_register_error(as, l, "Bad operand");
		return;
	}
	
	delim = **p;
	(*p)++;
	
	for (i = 0; (*p)[i] && (*p)[i] != delim; i++)
		/* do nothing */ ;
	
	if ((*p)[i] != delim)
	{
		lwasm_register_error(as, l, "Bad operand");
		return;
	}
	
	l -> lstr = lw_strndup(*p, i);
	(*p) += i + 1;
	
	l -> len = i;
}

EMITFUNC(pseudo_emit_fcn)
{
	int i;
	
	for (i = 0; i < l -> len; i++)
		lwasm_emit(l, l -> lstr[i]);
	lwasm_emit(l, 0);
}

PARSEFUNC(pseudo_parse_rmb)
{
	lw_expr_t expr;
	
	expr = lwasm_parse_expr(as, p);
	if (!expr)
	{
		lwasm_register_error(as, l, "Bad expression");
	}
	
	lwasm_save_expr(l, 0, expr);
}

RESOLVEFUNC(pseudo_resolve_rmb)
{
	lw_expr_t expr;
	
	if (l -> len >= 0)
		return;
	
	expr = lwasm_fetch_expr(l, 0);
	
	if (lw_expr_istype(expr, lw_expr_type_int))
	{
		l -> len = lw_expr_intval(expr);
	}
}

EMITFUNC(pseudo_emit_rmb)
{
	if (l -> len < 0)
		lwasm_register_error(as, l, "Expression not constant");
}

PARSEFUNC(pseudo_parse_rmd)
{
	lw_expr_t expr;
	
	expr = lwasm_parse_expr(as, p);
	if (!expr)
	{
		lwasm_register_error(as, l, "Bad expression");
	}
	
	lwasm_save_expr(l, 0, expr);
}

RESOLVEFUNC(pseudo_resolve_rmd)
{
	lw_expr_t expr;
	
	if (l -> len >= 0)
		return;
	
	expr = lwasm_fetch_expr(l, 0);
	
	if (lw_expr_istype(expr, lw_expr_type_int))
	{
		l -> len = lw_expr_intval(expr) * 2;
	}
}

EMITFUNC(pseudo_emit_rmd)
{
	if (l -> len < 0)
		lwasm_register_error(as, l, "Expression not constant");
}


PARSEFUNC(pseudo_parse_rmq)
{
	lw_expr_t expr;
	
	expr = lwasm_parse_expr(as, p);
	if (!expr)
	{
		lwasm_register_error(as, l, "Bad expression");
	}
	
	lwasm_save_expr(l, 0, expr);
}

RESOLVEFUNC(pseudo_resolve_rmq)
{
	lw_expr_t expr;
	
	if (l -> len >= 0)
		return;
	
	expr = lwasm_fetch_expr(l, 0);
	
	if (lw_expr_istype(expr, lw_expr_type_int))
	{
		l -> len = lw_expr_intval(expr) * 4;
	}
}

EMITFUNC(pseudo_emit_rmq)
{
	if (l -> len < 0)
		lwasm_register_error(as, l, "Expression not constant");
}


PARSEFUNC(pseudo_parse_zmq)
{
	lw_expr_t expr;
	
	expr = lwasm_parse_expr(as, p);
	if (!expr)
	{
		lwasm_register_error(as, l, "Bad expression");
	}
	
	lwasm_save_expr(l, 0, expr);
}

RESOLVEFUNC(pseudo_resolve_zmq)
{
	lw_expr_t expr;
	
	if (l -> len >= 0)
		return;
	
	expr = lwasm_fetch_expr(l, 0);
	
	if (lw_expr_istype(expr, lw_expr_type_int))
	{
		l -> len = lw_expr_intval(expr) * 4;
	}
}

EMITFUNC(pseudo_emit_zmq)
{
	int i;

	if (l -> len < 0)
	{
		lwasm_register_error(as, l, "Expression not constant");
		return;
	}

	for (i = 0; i < l -> len; i++)
		lwasm_emit(l, 0);	
}


PARSEFUNC(pseudo_parse_zmd)
{
	lw_expr_t expr;
	
	expr = lwasm_parse_expr(as, p);
	if (!expr)
	{
		lwasm_register_error(as, l, "Bad expression");
	}
	
	lwasm_save_expr(l, 0, expr);
}

RESOLVEFUNC(pseudo_resolve_zmd)
{
	lw_expr_t expr;
	
	if (l -> len >= 0)
		return;
	
	expr = lwasm_fetch_expr(l, 0);
	
	if (lw_expr_istype(expr, lw_expr_type_int))
	{
		l -> len = lw_expr_intval(expr) * 2;
	}
}

EMITFUNC(pseudo_emit_zmd)
{
	int i;

	if (l -> len < 0)
	{
		lwasm_register_error(as, l, "Expression not constant");
		return;
	}

	for (i = 0; i < l -> len; i++)
		lwasm_emit(l, 0);	
}

PARSEFUNC(pseudo_parse_zmb)
{
	lw_expr_t expr;
	
	expr = lwasm_parse_expr(as, p);
	if (!expr)
	{
		lwasm_register_error(as, l, "Bad expression");
	}
	
	lwasm_save_expr(l, 0, expr);
}

RESOLVEFUNC(pseudo_resolve_zmb)
{
	lw_expr_t expr;
	
	if (l -> len >= 0)
		return;
	
	expr = lwasm_fetch_expr(l, 0);
	
	if (lw_expr_istype(expr, lw_expr_type_int))
	{
		l -> len = lw_expr_intval(expr);
	}
}

EMITFUNC(pseudo_emit_zmb)
{
	int i;

	if (l -> len < 0)
	{
		lwasm_register_error(as, l, "Expression not constant");
		return;
	}

	for (i = 0; i < l -> len; i++)
		lwasm_emit(l, 0);	
}

PARSEFUNC(pseudo_parse_org)
{
	lw_expr_t e;
	
	e = lwasm_parse_expr(as, p);
	if (!e)
	{
		lwasm_register_error(as, l, "Bad operand");
		return;
	}
	
	lw_expr_destroy(l -> addr);
	l -> addr = e;
	l -> len = 0;
}

PARSEFUNC(pseudo_parse_equ)
{
	lw_expr_t e;
	
	if (!(l -> sym))
	{
		lwasm_register_error(as, l, "Missing symbol");
		return;
	}
	
	e = lwasm_parse_expr(as, p);
	if (!e)
	{
		lwasm_register_error(as, l, "Bad operand");
		return;
	}
	
	register_symbol(as, l, l -> sym, e, symbol_flag_none);
	l -> symset = 1;
}