ack/util/opt/putline.c
1984-05-17 13:57:07 +00:00

380 lines
7 KiB
C

#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "assert.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "../../h/em_mnem.h"
#include "../../h/em_flag.h"
#include "alloc.h"
#include "line.h"
#include "lookup.h"
#include "proinf.h"
#include "optim.h"
#include "ext.h"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
#define outbyte(b) putc(b,outfile)
putlines(lnp) register line_p lnp; {
register arg_p ap;
line_p temp;
register instr;
short curlin= -2;
short thislin;
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;
#ifdef LONGOFF
case OPLVAL:
outocc(lnp->l_a.la_lval.lalv_sp);
break;
#endif
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;
}
break;
}
/*
* global symbols now taken care of
*/
switch(instr) {
case ps_sym:
break;
case op_lni:
if (curlin != -2)
curlin++;
outinst(instr);
break;
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;
break;
case op_lab:
curlin = -2;
break;
default:
outinst(instr);
}
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;
#ifdef LONGOFF
case OPOFFSET:
outoff(lnp->l_a.la_offset);
break;
#endif
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;
#ifdef LONGOFF
case OPLVAL:
outbyte( (byte) sp_doff) ;
outsym(lnp->l_a.la_lval.lalv_sp);
outoff(lnp->l_a.la_lval.lalv_offset);
break;
#endif
case OPLIST:
putargs(lnp->l_a.la_arg);
switch(instr) {
case ps_con:
case ps_rom:
case ps_mes:
outbyte( (byte) sp_cend) ;
}
}
/*
* instruction is output now.
* remove its useless body
*/
temp = lnp->l_next;
oldline(lnp);
lnp = temp;
if (ferror(outfile))
error("write error");
}
}
putargs(ap) register arg_p ap; {
while (ap != (arg_p) 0) {
switch(ap->a_typ) {
default:
assert(FALSE);
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;
}
ap = ap->a_next;
}
}
putstr(abp) register argb_p abp; {
register argb_p tbp;
register length;
length = 0;
tbp = abp;
while (tbp!= (argb_p) 0) {
length += tbp->ab_index;
tbp = tbp->ab_next;
}
outint(length);
while (abp != (argb_p) 0) {
for (length=0;length<abp->ab_index;length++)
outbyte( (byte) abp->ab_contents[length] );
abp = abp->ab_next;
}
}
outdef(sp) register sym_p sp; {
/*
* The surrounding If statement is removed to be friendly
* to Backend writers having to deal with assemblers
* not following our conventions.
if ((sp->s_flags&SYMOUT)==0) {
*/
sp->s_flags |= SYMOUT;
if (sp->s_flags&SYMGLOBAL) {
outinst(sp->s_flags&SYMPRO ? ps_exp : ps_exa);
outsym(sp);
}
/*
}
*/
}
outocc(sp) register sym_p sp; {
if ((sp->s_flags&SYMOUT)==0) {
sp->s_flags |= SYMOUT;
if ((sp->s_flags&SYMGLOBAL)==0) {
outinst(sp->s_flags&SYMPRO ? ps_inp : ps_ina);
outsym(sp);
}
}
}
outpro() {
outdef(curpro.symbol);
outinst(ps_pro);
outsym(curpro.symbol);
outoff(curpro.localbytes);
}
outend() {
outinst(ps_end);
outoff(curpro.localbytes);
}
outinst(m) {
outbyte( (byte) m );
}
outoff(off) offset off; {
#ifdef LONGOFF
if ((short) off == off)
#endif
outint((short) off);
#ifdef LONGOFF
else {
outbyte( (byte) sp_cst4) ;
outshort( (short) (off&0177777L) );
outshort( (short) (off>>16) );
}
#endif
}
outint(i) short i; {
if (i>= -sp_zcst0 && i< sp_ncst0-sp_zcst0)
outbyte( (byte) (i+sp_zcst0+sp_fcst0) );
else {
outbyte( (byte) sp_cst2) ;
outshort(i);
}
}
outshort(i) short i; {
outbyte( (byte) (i&BMASK) );
outbyte( (byte) (i>>8) );
}
numlab(np) register num_p np; {
if (np->n_number < sp_nilb0)
outbyte( (byte) (np->n_number + sp_filb0) );
else
outnum(np);
}
outnum(np) register num_p np; {
if(np->n_number<256) {
outbyte( (byte) sp_ilb1) ;
outbyte( (byte) (np->n_number) );
} else {
outbyte( (byte) sp_ilb2) ;
outshort((short) np->n_number);
}
}
outsym(sp) register sym_p sp; {
register byte *p;
register unsigned num;
if (sp->s_name[0] == '.') {
num = atoi(&sp->s_name[1]);
if (num < 256) {
outbyte( (byte) sp_dlb1) ;
outbyte( (byte) (num) );
} else {
outbyte( (byte) sp_dlb2) ;
outshort((short) num);
}
} else {
p= sp->s_name;
while (*p && p < &sp->s_name[IDL])
p++;
num = p - sp->s_name;
outbyte( (byte) (sp->s_flags&SYMPRO ? sp_pnam : sp_dnam) );
outint((short) num);
p = sp->s_name;
while (num--)
outbyte( (byte) *p++ );
}
}