241 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * This file contains the main part of the top element size computation phase. 
 | 
						|
 *
 | 
						|
 * Author: Hans van Eck. 
 | 
						|
 */
 | 
						|
#include <assert.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <em_spec.h>
 | 
						|
#include <em_mnem.h>
 | 
						|
#include <em_pseu.h>
 | 
						|
#include "param.h"
 | 
						|
#include "types.h"
 | 
						|
#include "tes.h"
 | 
						|
#include "alloc.h"
 | 
						|
#include "proinf.h"
 | 
						|
#include "line.h"
 | 
						|
#include "ext.h"
 | 
						|
#include "pop_push.h"
 | 
						|
 | 
						|
extern char *pop_push[];
 | 
						|
extern char flow_tab[];
 | 
						|
 | 
						|
#define NON_CONTINUABLE(i)	(flow_tab[i]&JUMP)
 | 
						|
#define ISABRANCH(i)		(flow_tab[i]&HASLABEL)
 | 
						|
#define ISCONDBRANCH(i)		(flow_tab[i]&CONDBRA)
 | 
						|
 | 
						|
#define INSTR(lnp)      (lnp->l_instr & BMASK)
 | 
						|
#define TYPE(lnp)       lnp->l_optyp
 | 
						|
#define SHORT(lnp)      lnp->l_a.la_short
 | 
						|
#define MINI(lnp)	((lnp->l_optyp & BMASK) - Z_OPMINI)
 | 
						|
 | 
						|
#define IS_MINI(lnp)	(lnp->l_optyp >= OPMINI)
 | 
						|
#define IS_LOC(l)	(l!=(line_p) 0 && INSTR(l)==op_loc && IS_MINI(l))
 | 
						|
 | 
						|
int state;
 | 
						|
static int stacktop = 0;
 | 
						|
 | 
						|
/* Forward declarations */
 | 
						|
static void do_inst_label(line_p);
 | 
						|
static void assign_label(register num_p);
 | 
						|
 | 
						|
void init_state(void)
 | 
						|
{
 | 
						|
	stacktop = 0;
 | 
						|
	state = KNOWN;
 | 
						|
}
 | 
						|
 | 
						|
void tes_pseudos(void)
 | 
						|
{
 | 
						|
	register line_p lp;
 | 
						|
 | 
						|
	for (lp = pseudos; lp != (line_p) 0; lp = lp->l_next)
 | 
						|
	{
 | 
						|
		switch (INSTR(lp))
 | 
						|
		{
 | 
						|
			case ps_con:
 | 
						|
			case ps_rom:
 | 
						|
				if (lp->l_optyp == OPLIST)
 | 
						|
				{
 | 
						|
					register arg_p ap = lp->l_a.la_arg;
 | 
						|
 | 
						|
					while (ap != (arg_p) 0)
 | 
						|
					{
 | 
						|
						if (ap->a_typ == ARGNUM)
 | 
						|
						{
 | 
						|
							assign_label(ap->a_a.a_np->n_repl);
 | 
						|
						}
 | 
						|
						ap = ap->a_next;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				else if (lp->l_optyp == OPNUMLAB)
 | 
						|
					assign_label(lp->l_a.la_np->n_repl);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void tes_instr(line_p lnp, line_p x, line_p y)
 | 
						|
{
 | 
						|
	char *s;
 | 
						|
	register int instr = INSTR(lnp);
 | 
						|
	register int arg, argdef;
 | 
						|
	int neg = 0;
 | 
						|
 | 
						|
	if (instr == op_lab)
 | 
						|
	{
 | 
						|
		do_inst_label(lnp);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (instr < sp_fmnem || instr > sp_lmnem)
 | 
						|
	{
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if (state == NOTREACHED)
 | 
						|
		return; /* What else ? */
 | 
						|
	s = pop_push[instr];
 | 
						|
 | 
						|
	if (*s != '0')
 | 
						|
	{
 | 
						|
		while (*s != '\0')
 | 
						|
		{
 | 
						|
			neg = (*s++ == '-');
 | 
						|
 | 
						|
			if (TYPE(lnp) == OPSHORT)
 | 
						|
			{
 | 
						|
				arg = SHORT(lnp);
 | 
						|
				if (arg < wordsize)
 | 
						|
					arg = wordsize;
 | 
						|
				argdef = TRUE;
 | 
						|
			}
 | 
						|
			else if (IS_MINI(lnp))
 | 
						|
			{
 | 
						|
				arg = MINI(lnp);
 | 
						|
				if (arg > 0 && arg < wordsize)
 | 
						|
					arg = wordsize;
 | 
						|
				if (arg < 0 && -arg < wordsize)
 | 
						|
					arg = -wordsize;
 | 
						|
				argdef = TRUE;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				argdef = FALSE;
 | 
						|
			}
 | 
						|
			switch (*s++)
 | 
						|
			{
 | 
						|
				case 'w':
 | 
						|
					stacktop = wordsize;
 | 
						|
					break;
 | 
						|
				case 'd':
 | 
						|
					stacktop = wordsize * 2;
 | 
						|
					break;
 | 
						|
				case 'p':
 | 
						|
					stacktop = pointersize;
 | 
						|
					break;
 | 
						|
				case 'a':
 | 
						|
					if (argdef == FALSE || instr == op_ass)
 | 
						|
					{
 | 
						|
						stacktop = 0;
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						stacktop = arg;
 | 
						|
					}
 | 
						|
					break;
 | 
						|
				case 'x':
 | 
						|
					if (IS_LOC(x))
 | 
						|
					{
 | 
						|
						arg = MINI(x);
 | 
						|
						if (arg < wordsize)
 | 
						|
							arg = wordsize;
 | 
						|
						stacktop = arg;
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						stacktop = 0;
 | 
						|
					}
 | 
						|
					break;
 | 
						|
				case 'y':
 | 
						|
					if (IS_LOC(y))
 | 
						|
					{
 | 
						|
						arg = MINI(y);
 | 
						|
						if (arg < wordsize)
 | 
						|
							arg = wordsize;
 | 
						|
						stacktop = arg;
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						stacktop = 0;
 | 
						|
					}
 | 
						|
					break;
 | 
						|
				case '?':
 | 
						|
					stacktop = 0;
 | 
						|
					break;
 | 
						|
				default:
 | 
						|
					assert(FALSE);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/*
 | 
						|
		 * When the last argument was negative, the element size
 | 
						|
		 * must be negated.  This is to catch 'asp -4'.
 | 
						|
		 */
 | 
						|
		if (neg)
 | 
						|
			stacktop = -stacktop;
 | 
						|
	}
 | 
						|
 | 
						|
	if (stacktop < 0)
 | 
						|
		stacktop = 0;
 | 
						|
 | 
						|
	if (ISABRANCH(instr))
 | 
						|
		do_inst_label(lnp);
 | 
						|
	if (NON_CONTINUABLE(instr))
 | 
						|
	{
 | 
						|
		state = NOTREACHED;
 | 
						|
		stacktop = 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void assign_label(register num_p label)
 | 
						|
{
 | 
						|
	if (label->n_flags & NUMSET)
 | 
						|
	{
 | 
						|
		if (state == NOTREACHED || stacktop > label->n_size)
 | 
						|
		{
 | 
						|
			stacktop = label->n_size;
 | 
						|
		}
 | 
						|
		else if (stacktop < label->n_size)
 | 
						|
		{
 | 
						|
			label->n_size = stacktop;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		label->n_size = stacktop;
 | 
						|
		label->n_flags |= NUMSET;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* (re-)install a label */
 | 
						|
static void do_inst_label(line_p lnp)
 | 
						|
{
 | 
						|
	num_p label = lnp->l_a.la_np->n_repl;
 | 
						|
	int instr = INSTR(lnp);
 | 
						|
 | 
						|
	assign_label(label);
 | 
						|
 | 
						|
	if (instr == op_lab)
 | 
						|
	{
 | 
						|
		if (state == NOTREACHED)
 | 
						|
		{
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			label->n_flags |= NUMFALLTHROUGH;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else if (ISCONDBRANCH(instr))
 | 
						|
	{ /* conditional branch */
 | 
						|
		label->n_flags |= NUMCOND;
 | 
						|
	}
 | 
						|
	state = KNOWN;
 | 
						|
}
 |