189 lines
3.4 KiB
C
189 lines
3.4 KiB
C
/*
|
|
* (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);
|
|
}
|
|
}
|
|
}
|