2019-05-10 17:17:40 +00:00
|
|
|
/*
|
|
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
|
|
*
|
|
|
|
* Author: Hans van Staveren
|
|
|
|
*/
|
2017-11-10 03:22:13 +00:00
|
|
|
#include <assert.h>
|
2019-05-10 17:17:40 +00:00
|
|
|
#include <stdlib.h>
|
1984-05-17 13:42:36 +00:00
|
|
|
#include "param.h"
|
|
|
|
#include "types.h"
|
1990-09-04 16:42:43 +00:00
|
|
|
#include "tes.h"
|
1988-09-12 09:13:49 +00:00
|
|
|
#include <em_spec.h>
|
|
|
|
#include <em_pseu.h>
|
|
|
|
#include <em_mnem.h>
|
|
|
|
#include <em_flag.h>
|
1984-05-17 13:42:36 +00:00
|
|
|
#include "alloc.h"
|
|
|
|
#include "line.h"
|
2019-05-10 17:17:40 +00:00
|
|
|
#include "putline.h"
|
|
|
|
#include "util.h"
|
1984-05-17 13:42:36 +00:00
|
|
|
#include "lookup.h"
|
|
|
|
#include "proinf.h"
|
|
|
|
#include "optim.h"
|
|
|
|
#include "ext.h"
|
|
|
|
|
|
|
|
#define outbyte(b) putc(b,outfile)
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
/* Forward declarations. */
|
|
|
|
static void numlab(register num_p);
|
|
|
|
static void putargs(register arg_p);
|
|
|
|
static void putstr(register argb_p);
|
|
|
|
|
|
|
|
void putlines(register line_p lnp)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
register arg_p ap;
|
|
|
|
line_p temp;
|
2019-05-10 17:17:40 +00:00
|
|
|
register int instr;
|
|
|
|
short curlin = -2;
|
1984-05-17 13:42:36 +00:00
|
|
|
short thislin;
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
while (lnp != (line_p) 0)
|
|
|
|
{
|
|
|
|
instr = lnp->l_instr & BMASK;
|
|
|
|
switch (lnp->l_optyp)
|
|
|
|
{
|
|
|
|
case OPSYMBOL:
|
|
|
|
if ((lnp->l_instr & BMASK) == ps_sym)
|
|
|
|
outdef(lnp->l_a.la_sp);
|
|
|
|
else
|
|
|
|
outocc(lnp->l_a.la_sp);
|
|
|
|
break;
|
|
|
|
case OPSVAL:
|
|
|
|
outocc(lnp->l_a.la_sval.lasv_sp);
|
|
|
|
break;
|
1984-05-17 13:42:36 +00:00
|
|
|
#ifdef LONGOFF
|
2019-05-10 17:17:40 +00:00
|
|
|
case OPLVAL:
|
|
|
|
outocc(lnp->l_a.la_lval.lalv_sp);
|
|
|
|
break;
|
1984-05-17 13:42:36 +00:00
|
|
|
#endif
|
2019-05-10 17:17:40 +00:00
|
|
|
case OPLIST:
|
|
|
|
ap = lnp->l_a.la_arg;
|
|
|
|
while (ap != (arg_p) 0)
|
|
|
|
{
|
|
|
|
switch (ap->a_typ)
|
|
|
|
{
|
|
|
|
case ARGSYM:
|
|
|
|
outocc(ap->a_a.a_sp);
|
|
|
|
break;
|
|
|
|
case ARGVAL:
|
|
|
|
outocc(ap->a_a.a_val.av_sp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ap = ap->a_next;
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
2019-05-10 17:17:40 +00:00
|
|
|
break;
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* global symbols now taken care of
|
|
|
|
*/
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
switch (instr)
|
|
|
|
{
|
|
|
|
case ps_sym:
|
|
|
|
break;
|
|
|
|
case op_lni:
|
|
|
|
if (curlin != -2)
|
|
|
|
curlin++;
|
1984-05-17 13:42:36 +00:00
|
|
|
outinst(instr);
|
|
|
|
break;
|
2019-05-10 17:17:40 +00:00
|
|
|
case op_lin:
|
|
|
|
switch (lnp->l_optyp)
|
|
|
|
{
|
|
|
|
case OPNO:
|
|
|
|
case OPOFFSET:
|
|
|
|
case OPNUMLAB:
|
|
|
|
case OPSYMBOL:
|
|
|
|
case OPSVAL:
|
|
|
|
case OPLVAL:
|
|
|
|
case OPLIST:
|
|
|
|
outinst(instr);
|
|
|
|
goto processoperand;
|
|
|
|
case OPSHORT:
|
|
|
|
thislin = lnp->l_a.la_short;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
thislin = (lnp->l_optyp & BMASK) - Z_OPMINI;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (thislin == curlin && !nflag)
|
|
|
|
{
|
|
|
|
temp = lnp->l_next;
|
|
|
|
oldline(lnp);
|
|
|
|
lnp = temp;
|
|
|
|
OPTIM(O_LINGONE);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (thislin == curlin + 1 && !nflag)
|
|
|
|
{
|
|
|
|
instr = op_lni;
|
|
|
|
outinst(instr);
|
|
|
|
temp = lnp->l_next;
|
|
|
|
oldline(lnp);
|
|
|
|
OPTIM(O_LINLNI);
|
|
|
|
lnp = newline(OPNO);
|
|
|
|
lnp->l_next = temp;
|
|
|
|
lnp->l_instr = instr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outinst(instr);
|
|
|
|
}
|
|
|
|
curlin = thislin;
|
1984-05-17 13:42:36 +00:00
|
|
|
break;
|
2019-05-10 17:17:40 +00:00
|
|
|
case op_lab:
|
1984-07-12 09:29:49 +00:00
|
|
|
curlin = -2;
|
2019-05-10 17:17:40 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if ((em_flag[instr - sp_fmnem] & EM_FLO) == FLO_P)
|
|
|
|
curlin = -2;
|
|
|
|
outinst(instr);
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
2019-05-10 17:17:40 +00:00
|
|
|
processoperand: switch (lnp->l_optyp)
|
|
|
|
{
|
|
|
|
case OPNO:
|
|
|
|
if ((em_flag[instr - sp_fmnem] & EM_PAR) != PAR_NO)
|
|
|
|
outbyte((byte) sp_cend);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
outint((lnp->l_optyp & BMASK) - Z_OPMINI);
|
|
|
|
break;
|
|
|
|
case OPSHORT:
|
|
|
|
outint(lnp->l_a.la_short);
|
|
|
|
break;
|
1984-05-17 13:42:36 +00:00
|
|
|
#ifdef LONGOFF
|
2019-05-10 17:17:40 +00:00
|
|
|
case OPOFFSET:
|
|
|
|
outoff(lnp->l_a.la_offset);
|
|
|
|
break;
|
1984-05-17 13:42:36 +00:00
|
|
|
#endif
|
2019-05-10 17:17:40 +00:00
|
|
|
case OPNUMLAB:
|
|
|
|
if (instr == op_lab)
|
|
|
|
numlab(lnp->l_a.la_np->n_repl);
|
|
|
|
else if (instr < sp_fpseu) /* plain instruction */
|
|
|
|
outint((short) lnp->l_a.la_np->n_repl->n_number);
|
|
|
|
else
|
|
|
|
outnum(lnp->l_a.la_np->n_repl);
|
|
|
|
break;
|
|
|
|
case OPSYMBOL:
|
|
|
|
outsym(lnp->l_a.la_sp);
|
|
|
|
break;
|
|
|
|
case OPSVAL:
|
|
|
|
outbyte((byte) sp_doff);
|
|
|
|
outsym(lnp->l_a.la_sval.lasv_sp);
|
|
|
|
outint(lnp->l_a.la_sval.lasv_short);
|
|
|
|
break;
|
1984-05-17 13:42:36 +00:00
|
|
|
#ifdef LONGOFF
|
2019-05-10 17:17:40 +00:00
|
|
|
case OPLVAL:
|
|
|
|
outbyte((byte) sp_doff);
|
|
|
|
outsym(lnp->l_a.la_lval.lalv_sp);
|
|
|
|
outoff(lnp->l_a.la_lval.lalv_offset);
|
|
|
|
break;
|
1984-05-17 13:42:36 +00:00
|
|
|
#endif
|
2019-05-10 17:17:40 +00:00
|
|
|
case OPLIST:
|
|
|
|
putargs(lnp->l_a.la_arg);
|
|
|
|
switch (instr)
|
|
|
|
{
|
|
|
|
case ps_con:
|
|
|
|
case ps_rom:
|
|
|
|
case ps_mes:
|
|
|
|
outbyte((byte) sp_cend);
|
|
|
|
}
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* instruction is output now.
|
|
|
|
* remove its useless body
|
|
|
|
*/
|
|
|
|
|
|
|
|
temp = lnp->l_next;
|
|
|
|
oldline(lnp);
|
|
|
|
lnp = temp;
|
|
|
|
if (ferror(outfile))
|
|
|
|
error("write error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
static void putargs(register arg_p ap)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
while (ap != (arg_p) 0)
|
|
|
|
{
|
|
|
|
switch (ap->a_typ)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(FALSE);
|
|
|
|
break;
|
|
|
|
case ARGOFF:
|
|
|
|
outoff(ap->a_a.a_offset);
|
|
|
|
break;
|
|
|
|
case ARGNUM:
|
|
|
|
outnum(ap->a_a.a_np->n_repl);
|
|
|
|
break;
|
|
|
|
case ARGSYM:
|
|
|
|
outsym(ap->a_a.a_sp);
|
|
|
|
break;
|
|
|
|
case ARGVAL:
|
|
|
|
outbyte((byte) sp_doff);
|
|
|
|
outsym(ap->a_a.a_val.av_sp);
|
|
|
|
outoff(ap->a_a.a_val.av_offset);
|
|
|
|
break;
|
|
|
|
case ARGSTR:
|
|
|
|
outbyte((byte) sp_scon);
|
|
|
|
putstr(&ap->a_a.a_string);
|
|
|
|
break;
|
|
|
|
case ARGICN:
|
|
|
|
outbyte((byte) sp_icon);
|
|
|
|
goto casecon;
|
|
|
|
case ARGUCN:
|
|
|
|
outbyte((byte) sp_ucon);
|
|
|
|
goto casecon;
|
|
|
|
case ARGFCN:
|
|
|
|
outbyte((byte) sp_fcon);
|
|
|
|
casecon: outint(ap->a_a.a_con.ac_length);
|
|
|
|
putstr(&ap->a_a.a_con.ac_con);
|
|
|
|
break;
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
|
|
|
ap = ap->a_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
static void putstr(register argb_p abp)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
register argb_p tbp;
|
2019-05-10 17:17:40 +00:00
|
|
|
register int length;
|
1984-05-17 13:42:36 +00:00
|
|
|
|
|
|
|
length = 0;
|
|
|
|
tbp = abp;
|
2019-05-10 17:17:40 +00:00
|
|
|
while (tbp != (argb_p) 0)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
length += tbp->ab_index;
|
|
|
|
tbp = tbp->ab_next;
|
|
|
|
}
|
|
|
|
outint(length);
|
2019-05-10 17:17:40 +00:00
|
|
|
while (abp != (argb_p) 0)
|
|
|
|
{
|
|
|
|
for (length = 0; length < abp->ab_index; length++)
|
|
|
|
outbyte((byte ) abp->ab_contents[length]);
|
1984-05-17 13:42:36 +00:00
|
|
|
abp = abp->ab_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outdef(register sym_p sp)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The surrounding If statement is removed to be friendly
|
|
|
|
* to Backend writers having to deal with assemblers
|
|
|
|
* not following our conventions.
|
2019-05-10 17:17:40 +00:00
|
|
|
if ((sp->s_flags&SYMOUT)==0) {
|
1984-05-17 13:42:36 +00:00
|
|
|
*/
|
2019-05-10 17:17:40 +00:00
|
|
|
sp->s_flags |= SYMOUT;
|
|
|
|
if (sp->s_flags & SYMGLOBAL)
|
|
|
|
{
|
|
|
|
outinst(sp->s_flags & SYMPRO ? ps_exp : ps_exa);
|
|
|
|
outsym(sp);
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
2019-05-10 17:17:40 +00:00
|
|
|
/*
|
|
|
|
}
|
1984-05-17 13:42:36 +00:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outocc(register sym_p sp)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if ((sp->s_flags & SYMOUT) == 0)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
sp->s_flags |= SYMOUT;
|
2019-05-10 17:17:40 +00:00
|
|
|
if ((sp->s_flags & SYMGLOBAL) == 0)
|
|
|
|
{
|
|
|
|
outinst(sp->s_flags & SYMPRO ? ps_inp : ps_ina);
|
1984-05-17 13:42:36 +00:00
|
|
|
outsym(sp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outpro(void)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
outdef(curpro.symbol);
|
|
|
|
outinst(ps_pro);
|
|
|
|
outsym(curpro.symbol);
|
|
|
|
outoff(curpro.localbytes);
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outend(void)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
outinst(ps_end);
|
|
|
|
outoff(curpro.localbytes);
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outinst(int m)
|
|
|
|
{
|
|
|
|
outbyte((byte ) m);
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outoff(offset off)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
#ifdef LONGOFF
|
|
|
|
if ((short) off == off)
|
|
|
|
#endif
|
|
|
|
outint((short) off);
|
|
|
|
#ifdef LONGOFF
|
2019-05-10 17:17:40 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
outbyte((byte) sp_cst4);
|
|
|
|
outshort((short) (off & 0177777L));
|
|
|
|
outshort((short) (off >> 16));
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outint(short i)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if (i >= -sp_zcst0 && i < sp_ncst0 - sp_zcst0)
|
|
|
|
outbyte((byte) (i+sp_zcst0+sp_fcst0));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outbyte((byte) sp_cst2);
|
1984-05-17 13:42:36 +00:00
|
|
|
outshort(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outshort(short i)
|
|
|
|
{
|
|
|
|
outbyte((byte) (i&BMASK));
|
|
|
|
outbyte((byte ) (i >> 8));
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
static void numlab(register num_p np)
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
if (np->n_number < sp_nilb0)
|
2019-05-10 17:17:40 +00:00
|
|
|
outbyte((byte) (np->n_number + sp_filb0));
|
1984-05-17 13:42:36 +00:00
|
|
|
else
|
|
|
|
outnum(np);
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outnum(register num_p np)
|
|
|
|
{
|
|
|
|
if (np->n_number < 256)
|
|
|
|
{
|
|
|
|
outbyte((byte) sp_ilb1);
|
|
|
|
outbyte((byte ) (np->n_number));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outbyte((byte) sp_ilb2);
|
1984-05-17 13:42:36 +00:00
|
|
|
outshort((short) np->n_number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
void outsym(register sym_p sp)
|
|
|
|
{
|
|
|
|
register char *p;
|
1984-05-17 13:42:36 +00:00
|
|
|
register unsigned num;
|
|
|
|
|
2019-05-10 17:17:40 +00:00
|
|
|
if (sp->s_name[0] == '.')
|
|
|
|
{
|
1984-05-17 13:42:36 +00:00
|
|
|
num = atoi(&sp->s_name[1]);
|
2019-05-10 17:17:40 +00:00
|
|
|
if (num < 256)
|
|
|
|
{
|
|
|
|
outbyte((byte) sp_dlb1);
|
|
|
|
outbyte((byte ) (num));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outbyte((byte) sp_dlb2);
|
1984-05-17 13:42:36 +00:00
|
|
|
outshort((short) num);
|
|
|
|
}
|
2019-05-10 17:17:40 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p = sp->s_name;
|
|
|
|
/* This is not a real warning, because s_name is dynamically
|
|
|
|
* allocated as necessary.
|
|
|
|
*/
|
1984-05-17 13:42:36 +00:00
|
|
|
while (*p && p < &sp->s_name[IDL])
|
|
|
|
p++;
|
|
|
|
num = p - sp->s_name;
|
2019-05-10 17:17:40 +00:00
|
|
|
outbyte((byte) (sp->s_flags&SYMPRO ? sp_pnam : sp_dnam));
|
1984-05-17 13:42:36 +00:00
|
|
|
outint((short) num);
|
|
|
|
p = sp->s_name;
|
|
|
|
while (num--)
|
2019-05-10 17:17:40 +00:00
|
|
|
outbyte((byte ) *p++);
|
1984-05-17 13:42:36 +00:00
|
|
|
}
|
|
|
|
}
|