#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;lengthab_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++ ); } }