/* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". * */ #include "ass00.h" #include "assex.h" #include "assrl.h" #include "ip_spec.h" /* ** Pass 5 of EM1 assembler/loader ** Fix reloc tables ** Write out code */ static void patchcase(void); void pass_5(void) { register line_t *lnp; cons_t off1; char defined ; int afterlength, partype ; register int inslength, ope; char *op_curr ; pass = 5; afterlength = 0; for (lnp = pstate.s_fline ; lnp ; lnp= lnp->l_next, line_num++ ) { ope = ctrunc(lnp->instr_num); if ( ope==sp_ilb1 ) continue ; if ( ope==sp_fpseu ) { line_num = lnp->ad.ad_ln.ln_first ; continue ; } off1 = parval(lnp,&defined); if ( (op_curr = lnp->opoff)==NO_OFF ) { fatal("opoff assertion failed") ; } inslength = oplength(*op_curr) ; afterlength += inslength ; /* * Change absolute offset to a relative for branches. */ partype= em_flag[ope]&EM_PAR ; if ( partype==PAR_B && defined ) { off1 -= afterlength; } #ifdef JOHAN if ( jflag ) { extern char em_mnem[][4] ; printf("%s %ld\n",em_mnem[ope],off1) ; } #endif if ( !defined && partype==PAR_G ) { /* must be external */ text_reloc((lnp->type1==GLOSYM ? lnp->ad.ad_gp:lnp->ad.ad_df.df_gp), (FOFFSET)(textbytes+afterlength-inslength) , op_curr-opchoice); xputarb(inslength,off1,tfile); textoff += inslength ; } else { genop(op_curr,off1,partype) ; } } /* end forloop */ line_num-- ; patchcase(); textbytes += prog_size; if ( textbytes>maxadr ) fatal("Maximum code area size exceeded") ; } /* end pass_5 */ /** * Real code generation. */ void genop(char *startc,cons_t value,int i_flag) { char *currc ; register int flag ; char opc ; currc= startc ; flag = ctrunc(*currc++); opc = *currc++; if ( (flag&OPTYPE)!=OPNO ) { if ( !opfit(flag,*currc,value,i_flag) ) { fatal("parameter value unsuitable for selected opcode") ; } if ( flag&OPWORD ) { if ( value%wordsize!=0 ) { error("parameter not word multiple"); } value /= wordsize ; } if ( flag&OPNZ ) { if ( value<=0 ) error("negative parameter"); value-- ; } } if ( flag&OPESC ) put8(ESC) ; switch ( flag&OPTYPE ) { case OPMINI : opc += value<0 ? -1-value : value ; break ; case OPSHORT : if ( value<0 ) { opc += -1-(value>>8) ; } else { opc += value>>8 ; } break ; case OP32 : case OP64 : put8(ESC_L) ; } #ifdef DUMP if ( c_flag ) { switch(flag&OPTYPE) { case OP32 : case OP64 : opcnt3[opc&0377]= 1 ; break ; default : if ( flag&OPESC ) opcnt2[opc&0377]= 1 ; else opcnt1[opc&0377]= 1 ; break ; } } #endif put8(opc) ; switch( flag&OPTYPE ) { case OPNO: case OPMINI: break ; case OPSHORT: case OP8: put8((char)value) ; break ; case OP16: case OP16U: put16(int_cast value) ; break ; case OP32: put32(value) ; break ; case OP64: put64(value) ; break ; } } static void patchcase(void) { register relc_t *r; register locl_t *k; if ( (r= pstate.s_fdata) ) { r= r->r_next ; } else { r= f_data ; } for( ; r ; r= r->r_next ) { if (r->r_typ == RELLOC) { r->r_typ = RELADR; k = r->r_val.rel_lp; if (k->l_defined==YES) r->r_val.rel_i = k->l_min + textbytes; else error("case label at line %d undefined", k->l_min); } } }