1990-09-04 16:42:43 +00:00
|
|
|
/*
|
|
|
|
* This file contains the main part of the top element size computation phase.
|
|
|
|
*
|
|
|
|
* Author: Hans van Eck.
|
|
|
|
*/
|
2017-11-10 03:22:13 +00:00
|
|
|
#include <assert.h>
|
1990-09-04 16:42:43 +00:00
|
|
|
#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;
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
/* Forward declarations */
|
|
|
|
static void do_inst_label(line_p);
|
|
|
|
static void assign_label(register num_p);
|
|
|
|
|
|
|
|
void init_state(void)
|
1990-09-04 16:42:43 +00:00
|
|
|
{
|
|
|
|
stacktop = 0;
|
|
|
|
state = KNOWN;
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void tes_pseudos(void)
|
1990-09-04 16:42:43 +00:00
|
|
|
{
|
|
|
|
register line_p lp;
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
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;
|
1990-09-04 16:42:43 +00:00
|
|
|
}
|
|
|
|
}
|
2019-05-10 17:17:40 +00:00
|
|
|
else if (lp->l_optyp == OPNUMLAB)
|
|
|
|
assign_label(lp->l_a.la_np->n_repl);
|
1990-09-04 16:42:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void tes_instr(line_p lnp, line_p x, line_p y)
|
1990-09-04 16:42:43 +00:00
|
|
|
{
|
|
|
|
char *s;
|
2019-05-10 17:17:40 +00:00
|
|
|
register int instr = INSTR(lnp);
|
1990-09-04 16:42:43 +00:00
|
|
|
register int arg, argdef;
|
1990-11-06 13:22:15 +00:00
|
|
|
int neg = 0;
|
1990-09-04 16:42:43 +00:00
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if (instr == op_lab)
|
|
|
|
{
|
1990-09-04 16:42:43 +00:00
|
|
|
do_inst_label(lnp);
|
|
|
|
return;
|
|
|
|
}
|
2019-05-10 17:17:40 +00:00
|
|
|
if (instr < sp_fmnem || instr > sp_lmnem)
|
|
|
|
{
|
1990-09-04 16:42:43 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if (state == NOTREACHED)
|
|
|
|
return; /* What else ? */
|
1990-09-04 16:42:43 +00:00
|
|
|
s = pop_push[instr];
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if (*s != '0')
|
|
|
|
{
|
|
|
|
while (*s != '\0')
|
|
|
|
{
|
1990-11-06 13:22:15 +00:00
|
|
|
neg = (*s++ == '-');
|
1990-09-04 16:42:43 +00:00
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if (TYPE(lnp) == OPSHORT)
|
|
|
|
{
|
1990-09-04 16:42:43 +00:00
|
|
|
arg = SHORT(lnp);
|
2019-05-10 17:17:40 +00:00
|
|
|
if (arg < wordsize)
|
|
|
|
arg = wordsize;
|
1990-09-04 16:42:43 +00:00
|
|
|
argdef = TRUE;
|
2019-05-10 17:17:40 +00:00
|
|
|
}
|
|
|
|
else if (IS_MINI(lnp))
|
|
|
|
{
|
1990-09-04 16:42:43 +00:00
|
|
|
arg = MINI(lnp);
|
2019-05-10 17:17:40 +00:00
|
|
|
if (arg > 0 && arg < wordsize)
|
|
|
|
arg = wordsize;
|
|
|
|
if (arg < 0 && -arg < wordsize)
|
|
|
|
arg = -wordsize;
|
1990-09-04 16:42:43 +00:00
|
|
|
argdef = TRUE;
|
2019-05-10 17:17:40 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1990-09-04 16:42:43 +00:00
|
|
|
argdef = FALSE;
|
|
|
|
}
|
2019-05-10 17:17:40 +00:00
|
|
|
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 '?':
|
1990-09-04 16:42:43 +00:00
|
|
|
stacktop = 0;
|
2019-05-10 17:17:40 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(FALSE);
|
1990-09-04 16:42:43 +00:00
|
|
|
}
|
|
|
|
}
|
1990-11-06 13:22:15 +00:00
|
|
|
/*
|
|
|
|
* When the last argument was negative, the element size
|
|
|
|
* must be negated. This is to catch 'asp -4'.
|
|
|
|
*/
|
2019-05-10 17:17:40 +00:00
|
|
|
if (neg)
|
|
|
|
stacktop = -stacktop;
|
1990-09-04 16:42:43 +00:00
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if (stacktop < 0)
|
|
|
|
stacktop = 0;
|
1990-09-04 16:42:43 +00:00
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if (ISABRANCH(instr))
|
|
|
|
do_inst_label(lnp);
|
|
|
|
if (NON_CONTINUABLE(instr))
|
|
|
|
{
|
1990-09-04 16:42:43 +00:00
|
|
|
state = NOTREACHED;
|
|
|
|
stacktop = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
static void assign_label(register num_p label)
|
1990-09-04 16:42:43 +00:00
|
|
|
{
|
2019-05-10 17:17:40 +00:00
|
|
|
if (label->n_flags & NUMSET)
|
|
|
|
{
|
|
|
|
if (state == NOTREACHED || stacktop > label->n_size)
|
|
|
|
{
|
1991-01-31 15:17:04 +00:00
|
|
|
stacktop = label->n_size;
|
2019-05-10 17:17:40 +00:00
|
|
|
}
|
|
|
|
else if (stacktop < label->n_size)
|
|
|
|
{
|
1991-01-31 15:17:04 +00:00
|
|
|
label->n_size = stacktop;
|
1990-09-04 16:42:43 +00:00
|
|
|
}
|
2019-05-10 17:17:40 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1991-01-31 15:17:04 +00:00
|
|
|
label->n_size = stacktop;
|
1990-09-04 16:42:43 +00:00
|
|
|
label->n_flags |= NUMSET;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
/* (re-)install a label */
|
|
|
|
static void do_inst_label(line_p lnp)
|
1990-09-04 16:42:43 +00:00
|
|
|
{
|
|
|
|
num_p label = lnp->l_a.la_np->n_repl;
|
|
|
|
int instr = INSTR(lnp);
|
|
|
|
|
|
|
|
assign_label(label);
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if (instr == op_lab)
|
|
|
|
{
|
|
|
|
if (state == NOTREACHED)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1991-01-31 15:17:04 +00:00
|
|
|
label->n_flags |= NUMFALLTHROUGH;
|
1990-09-04 16:42:43 +00:00
|
|
|
}
|
2019-05-10 17:17:40 +00:00
|
|
|
}
|
|
|
|
else if (ISCONDBRANCH(instr))
|
|
|
|
{ /* conditional branch */
|
1990-09-04 16:42:43 +00:00
|
|
|
label->n_flags |= NUMCOND;
|
|
|
|
}
|
|
|
|
state = KNOWN;
|
|
|
|
}
|