/* * (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 */ #include #include #include "param.h" #include "types.h" #include "tes.h" #include #include #include #include #include "alloc.h" #include "line.h" #include "putline.h" #include "util.h" #include "lookup.h" #include "proinf.h" #include "optim.h" #include "ext.h" #define outbyte(b) putc(b,outfile) /* 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) { register arg_p ap; line_p temp; register int 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: if ((em_flag[instr - sp_fmnem] & EM_FLO) == FLO_P) curlin = -2; 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"); } } static void putargs(register arg_p ap) { 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; } ap = ap->a_next; } } static void putstr(register argb_p abp) { register argb_p tbp; register int 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; } } void outdef(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); } /* } */ } void outocc(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); } } } void outpro(void) { outdef(curpro.symbol); outinst(ps_pro); outsym(curpro.symbol); outoff(curpro.localbytes); } void outend(void) { outinst(ps_end); outoff(curpro.localbytes); } void outinst(int m) { outbyte((byte ) m); } void outoff(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 } void outint(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); } } void outshort(short i) { outbyte((byte) (i&BMASK)); outbyte((byte ) (i >> 8)); } static void numlab(register num_p np) { if (np->n_number < sp_nilb0) outbyte((byte) (np->n_number + sp_filb0)); else outnum(np); } 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); outshort((short) np->n_number); } } void outsym(register sym_p sp) { register char *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; /* This is not a real warning, because s_name is dynamically * allocated as necessary. */ 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++); } }