From 166bccd1b5065925391edfe3b7215ce620d63968 Mon Sep 17 00:00:00 2001 From: keie Date: Mon, 2 Jul 1984 15:35:56 +0000 Subject: [PATCH] Initial revision --- etc/ip_spec.t | 298 ++++++++++++++++ util/ass/Makefile | 77 +++++ util/ass/ass30.c | 371 ++++++++++++++++++++ util/ass/ass40.c | 55 +++ util/ass/ass50.c | 190 ++++++++++ util/ass/ass60.c | 211 +++++++++++ util/ass/ass70.c | 341 ++++++++++++++++++ util/ass/ass80.c | 412 ++++++++++++++++++++++ util/ass/assci.c | 847 +++++++++++++++++++++++++++++++++++++++++++++ util/ass/asscm.c | 137 ++++++++ util/ass/assda.c | 125 +++++++ util/ass/assex.h | 158 +++++++++ util/ass/assrl.c | 298 ++++++++++++++++ util/ass/ip_spec.h | 33 ++ util/ass/maktab.c | 475 +++++++++++++++++++++++++ 15 files changed, 4028 insertions(+) create mode 100644 etc/ip_spec.t create mode 100644 util/ass/Makefile create mode 100644 util/ass/ass30.c create mode 100644 util/ass/ass40.c create mode 100644 util/ass/ass50.c create mode 100644 util/ass/ass60.c create mode 100644 util/ass/ass70.c create mode 100644 util/ass/ass80.c create mode 100644 util/ass/assci.c create mode 100644 util/ass/asscm.c create mode 100644 util/ass/assda.c create mode 100644 util/ass/assex.h create mode 100644 util/ass/assrl.c create mode 100644 util/ass/ip_spec.h create mode 100644 util/ass/maktab.c diff --git a/etc/ip_spec.t b/etc/ip_spec.t new file mode 100644 index 000000000..1d7bdbd29 --- /dev/null +++ b/etc/ip_spec.t @@ -0,0 +1,298 @@ +aar mwPo 1 34 +adf sP 1 35 +adi mwPo 2 36 +adp 2 38 +adp mPo 2 39 +adp sP 1 41 +adp sN 1 42 +ads mwPo 1 43 +and mwPo 1 44 +asp mwPo 5 45 +asp swP 1 50 +beq 2 51 +beq sP 1 52 +bge sP 1 53 +bgt sP 1 54 +ble sP 1 55 +blm sP 1 56 +blt sP 1 57 +bne sP 1 58 +bra 2 59 +bra sN 2 60 +bra sP 2 62 +cal mPo 28 64 +cal sP 1 92 +cff - 93 +cif - 94 +cii - 95 +cmf sP 1 96 +cmi mwPo 2 97 +cmp - 99 +cms sP 1 100 +csa mwPo 1 101 +csb mwPo 1 102 +dec - 103 +dee sw 1 104 +del swN 1 105 +dup mwPo 1 106 +dvf sP 1 107 +dvi mwPo 1 108 +fil 2 109 +inc - 110 +ine w2 111 +ine sw 1 112 +inl mwN 3 113 +inl swN 1 116 +inn sP 1 117 +ior mwPo 1 118 +ior sP 1 119 +lae 2 120 +lae sw 7 121 +lal P2 128 +lal N2 129 +lal m 1 130 +lal mN 1 131 +lal swP 1 132 +lal swN 2 133 +lar mwPo 1 135 +ldc mP 1 136 +lde w2 137 +lde sw 1 138 +ldl mP 1 139 +ldl swN 1 140 +lfr mwPo 2 141 +lfr sP 1 143 +lil swN 1 144 +lil swP 1 145 +lil mwP 2 146 +lin 2 148 +lin sP 1 149 +lni - 150 +loc 2 151 +loc mP 34 0 +loc mN 1 152 +loc sP 1 153 +loc sN 1 154 +loe w2 155 +loe sw 5 156 +lof 2 161 +lof mwPo 4 162 +lof sP 1 166 +loi 2 167 +loi mPo 1 168 +loi mwPo 4 169 +loi sP 1 173 +lol wP2 174 +lol wN2 175 +lol mwP 4 176 +lol mwN 8 180 +lol swP 1 188 +lol swN 1 189 +lxa mPo 1 190 +lxl mPo 2 191 +mlf sP 1 193 +mli mwPo 2 194 +rck mwPo 1 196 +ret mwP 2 197 +ret sP 1 199 +rmi mwPo 1 200 +sar mwPo 1 201 +sbf sP 1 202 +sbi mwPo 2 203 +sdl swN 1 205 +set sP 1 206 +sil swN 1 207 +sil swP 1 208 +sli mwPo 1 209 +ste w2 210 +ste sw 3 211 +stf 2 214 +stf mwPo 2 215 +stf sP 1 217 +sti mPo 1 218 +sti mwPo 4 219 +sti sP 1 223 +stl wP2 224 +stl wN2 225 +stl mwP 2 226 +stl mwN 5 228 +stl swN 1 233 +teq - 234 +tgt - 235 +tlt - 236 +tne - 237 +zeq 2 238 +zeq sP 2 239 +zer sP 1 241 +zge sP 1 242 +zgt sP 1 243 +zle sP 1 244 +zlt sP 1 245 +zne sP 1 246 +zne sN 1 247 +zre w2 248 +zre sw 1 249 +zrl mwN 2 250 +zrl swN 1 252 +zrl wN2 253 +aar e2 0 +aar e- 1 +adf e2 2 +adf e- 3 +adi e2 4 +adi e- 5 +ads e2 6 +ads e- 7 +adu e2 8 +adu e- 9 +and e2 10 +and e- 11 +asp ew2 12 +ass e2 13 +ass e- 14 +bge e2 15 +bgt e2 16 +ble e2 17 +blm e2 18 +bls e2 19 +bls e- 20 +blt e2 21 +bne e2 22 +cai e- 23 +cal e2 24 +cfi e- 25 +cfu e- 26 +ciu e- 27 +cmf e2 28 +cmf e- 29 +cmi e2 30 +cmi e- 31 +cms e2 32 +cms e- 33 +cmu e2 34 +cmu e- 35 +com e2 36 +com e- 37 +csa e2 38 +csa e- 39 +csb e2 40 +csb e- 41 +cuf e- 42 +cui e- 43 +cuu e- 44 +dee ew2 45 +del ewP2 46 +del ewN2 47 +dup e2 48 +dus e2 49 +dus e- 50 +dvf e2 51 +dvf e- 52 +dvi e2 53 +dvi e- 54 +dvu e2 55 +dvu e- 56 +fef e2 57 +fef e- 58 +fif e2 59 +fif e- 60 +inl ewP2 61 +inl ewN2 62 +inn e2 63 +inn e- 64 +ior e2 65 +ior e- 66 +lar e2 67 +lar e- 68 +ldc e2 69 +ldf e2 70 +ldl ewP2 71 +ldl ewN2 72 +lfr e2 73 +lil ewP2 74 +lil ewN2 75 +lim e- 76 +los e2 77 +los e- 78 +lor esP 1 79 +lpi e2 80 +lxa e2 81 +lxl e2 82 +mlf e2 83 +mlf e- 84 +mli e2 85 +mli e- 86 +mlu e2 87 +mlu e- 88 +mon e- 89 +ngf e2 90 +ngf e- 91 +ngi e2 92 +ngi e- 93 +nop e- 94 +rck e2 95 +rck e- 96 +ret e2 97 +rmi e2 98 +rmi e- 99 +rmu e2 100 +rmu e- 101 +rol e2 102 +rol e- 103 +ror e2 104 +ror e- 105 +rtt e- 106 +sar e2 107 +sar e- 108 +sbf e2 109 +sbf e- 110 +sbi e2 111 +sbi e- 112 +sbs e2 113 +sbs e- 114 +sbu e2 115 +sbu e- 116 +sde e2 117 +sdf e2 118 +sdl ewP2 119 +sdl ewN2 120 +set e2 121 +set e- 122 +sig e- 123 +sil ewP2 124 +sil ewN2 125 +sim e- 126 +sli e2 127 +sli e- 128 +slu e2 129 +slu e- 130 +sri e2 131 +sri e- 132 +sru e2 133 +sru e- 134 +sti e2 135 +sts e2 136 +sts e- 137 +str esP 1 138 +tge e- 139 +tle e- 140 +trp e- 141 +xor e2 142 +xor e- 143 +zer e2 144 +zer e- 145 +zge e2 146 +zgt e2 147 +zle e2 148 +zlt e2 149 +zne e2 150 +zrf e2 151 +zrf e- 152 +zrl ewP2 153 +dch e- 154 +exg esP 1 155 +exg e2 156 +exg e- 157 +lpb e- 158 +gto e2 159 +ldc 4 0 diff --git a/util/ass/Makefile b/util/ass/Makefile new file mode 100644 index 000000000..45131b0ee --- /dev/null +++ b/util/ass/Makefile @@ -0,0 +1,77 @@ +d=../.. +l=$d/lib +h=$d/h +ASS_PATH=$l/em_ass + +SEP_OPT=-i + +CFLAGS=-O + +all: ass$(SEP_OPT) + +clean: + -rm -f ass-i ass-n *.o maktab *.old asstb.c + +install : all + cp ass$(SEP_OPT) $(ASS_PATH) + +cmp : all + cmp ass$(SEP_OPT) $(ASS_PATH) + +lint: ass00.c ass30.c ass40.c ass50.c ass60.c ass70.c \ + ass80.c assci.c assda.c assrl.c asstb.c asscm.c + lint -hpvbx \ + ass00.c ass30.c ass40.c ass50.c ass60.c ass70.c \ + ass80.c assci.c assda.c assrl.c asstb.c asscm.c + + +ass-n: ass00.o ass30.o ass40.o ass50.o ass60.o ass70.o \ + ass80.o assci.o assda.o assrl.o asstb.o asscm.o \ + $l/em_data.a + cc -n $(CFLAGS) -o ass-n \ + ass00.o ass30.o ass40.o ass50.o ass60.o ass70.o \ + ass80.o assci.o assda.o assrl.o asstb.o asscm.o \ + $l/em_data.a + +ass-i: ass00.o ass30.o ass40.o ass50.o ass60.o ass70.o \ + ass80.o assci.o assda.o assrl.o asstb.o asscm.o \ + $l/em_data.a + cc -i $(CFLAGS) -o ass-i \ + ass00.o ass30.o ass40.o ass50.o ass60.o ass70.o \ + ass80.o assci.o assda.o assrl.o asstb.o asscm.o \ + $l/em_data.a + +ass00.o ass40.o ass60.o ass70.o ass80.o assrl.c: \ + $h/local.h $h/em_spec.h $h/as_spec.h \ + $h/em_flag.h $h/arch.h ass00.h assex.h + +assci.o: $h/local.h $h/em_spec.h $h/as_spec.h \ + $h/em_flag.h $h/em_mes.h $h/em_pseu.h \ + $h/em_ptyp.h $h/arch.h ass00.h assex.h + +ass30.o ass50.o : \ + $h/local.h $h/em_spec.h $h/as_spec.h \ + $h/em_flag.h ip_spec.h ass00.h assex.h + +ass80.o: $h/em_path.h + +assda.o: $h/local.h $h/em_spec.h $h/as_spec.h \ + $h/em_flag.h $h/arch.h ass00.h + +asscm.o: ass00.h + +asstb.o: asstb.c + +asstb.c: maktab ip_spec.t + maktab ip_spec.t asstb.c + +maktab: maktab.c $h/em_spec.h ip_spec.h $h/em_flag.h \ + $l/em_data.a + cc -O -o maktab maktab.c $l/em_data.a + +opr: + make pr ^ opr + +pr: + @(pr ass00.h assex.h ip_spec.h ass?0.c ass[rcd]?.c \ + maktab.c ; pr -3 ip_spec.t) diff --git a/util/ass/ass30.c b/util/ass/ass30.c new file mode 100644 index 000000000..8cd64a857 --- /dev/null +++ b/util/ass/ass30.c @@ -0,0 +1,371 @@ +/* + * (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 + * + */ + +#include "ass00.h" +#include "assex.h" +#include "ip_spec.h" + +short opt_line ; /* max_line_no - # lines removed from end + after perfoming exc's. + Used to estimate the distance in # of + instructions. + */ +/* +** Determine the exact instruction length & format where possible, and the +** the upper and lower limits otherwise. Enter limits in labeltable +*/ +pass_3() +{ + register line_t *lnp, *rev_lnp; + line_t *tmp_lnp; + locl_t *lbp; + int min_l, max_l, min_bytes; + short last_line ; + short hol_err_line ; + register insno ; + + pass = 3; + opt_line= line_num ; hol_err_line=0 ; + min_bytes = max_bytes = 0; rev_lnp= lnp_cast 0 ; + for (lnp = pstate.s_fline ; lnp ; opt_line--, line_num-- ) { + pstate.s_fline= lnp; + insno = ctrunc(lnp->instr_num); + switch( insno ) { + case sp_fpseu : + last_line = line_num ; + line_num = lnp->ad.ad_ln.ln_first ; + opt_line -= lnp->ad.ad_ln.ln_extra ; + lnp->ad.ad_ln.ln_first= last_line ; + break ; + case sp_ilb1 : + lbp = lnp->ad.ad_lp; + lbp->l_defined = SEEN; + lbp->l_min = min_bytes; + lbp->l_max = max_bytes; + break ; + default: + if ( lnp->type1==CONST && (em_flag[insno]&EM_PAR)==PAR_G ) { + if (holbase != 0) { + lnp->ad.ad_i += holbase; + if (lnp->ad.ad_i >= holsize) { + hol_err_line= line_num ; + } + } + } else + if ( lnp->type1>=VALLOW && (em_flag[insno]&EM_PAR)==PAR_G ) { + if (holbase != 0) { + pstate.s_fline= lnp->l_next ; + newline(CONST) ; + pstate.s_fline->instr_num= insno ; + pstate.s_fline->ad.ad_i= + VAL1(lnp->type1)+holbase ; + freearea((area_t)lnp, + (unsigned)linesize[VALLOW]) ; + lnp= pstate.s_fline ; + if ( VAL1(lnp->type1) >= holsize) { + hol_err_line= line_num ; + } + } + } + if ( !valid(lnp) ) fatal("Invalid operand") ; + + determine_props(lnp, &min_l, &max_l); + min_bytes += min_l; max_bytes += max_l; + break ; + } + tmp_lnp= lnp->l_next ; + lnp->l_next= rev_lnp ; rev_lnp= lnp ; + lnp= tmp_lnp ; + } + pstate.s_fline= rev_lnp ; + if ( hol_err_line ) { + line_num= hol_err_line ; + werror("address exceeds holsize") ; + } +} + + +/* +** Determine the format that should be used for each instruction, +** depending on its offsets +*/ + +determine_props(lnp, min_len, max_len) + line_t *lnp; + int *min_len, *max_len; +{ + cons_t val ; + register int insno ; + register char *f_off, *l_off ; + char defined ; + + insno=ctrunc(lnp->instr_num) ; + val=parval(lnp,&defined) ; + if ( !defined ) { + switch(em_flag[insno]&EM_PAR) { + case PAR_NO: + case PAR_W: + f_off = findnop(insno) ; + break ; + case PAR_G: + /* We want the maximum address that is a multiple + of the wordsize. + Assumption: there is no shortie for + intr max_word_multiple + where intr is a instruction allowing parameters + that are not a word multiple (PAR_G). + */ + f_off = findfit(insno, maxadr&(~(wordsize-1))) ; + break ; + case PAR_B: + f_off = findfit(insno, (cons_t)0) ; + l_off = findfit(insno, val ) ; + if ( f_off != l_off ) { + *min_len=oplength(*f_off) ; + *max_len=oplength(*l_off) ; + lnp->opoff = NO_OFF ; + return ; + } + break ; + } + } else { + f_off = findfit(insno,val) ; + } + lnp->opoff = f_off ; + *min_len = *max_len = oplength(*f_off) ; +} + +char *findfit(instr,val) int instr ; cons_t val ; { + register char *currc,*endc ; + int found, flags, number ; + char *opc ; + + endc = opindex[instr+1] ; + for ( currc=opindex[instr], found=0 ; + !found && currc=0 ) return 0 ; + break ; + } + if ( flag&OPWORD ) { + if ( val%wordsize ) return 0 ; + val /= wordsize ; + } + if ( flag&OPNZ ) { + if ( val==0 ) return 0 ; + val-- ; + } + switch ( flag&OPTYPE ) { + case OPMINI : + if ( val<0 ) val = -1-val ; + return val>=0 && val=0 && val=0 && val<=maxadr ; + return val>= -32768 && val<=32767 ; + case OP32 : + return TRUE ; + default : + fatal("illegal OPTYPE value") ; + /* NOTREACHED */ + } +} + +int oplength(flag) int flag ; { + int cnt ; + + cnt=1 ; + if ( flag&OPESC ) cnt++ ; + switch( flag&OPTYPE ) { + case OPNO : + case OPMINI : break ; + case OP8 : + case OPSHORT : cnt++ ; break ; + case OP16 : cnt+=2 ; break ; + case OP32 : cnt+=5 ; break ; + case OP64 : cnt+=9 ; break ; + } + return cnt ; +} + +/* +** return estimation of value of parameter +*/ +cons_t parval(lnp,defined) + line_t *lnp; + char *defined; +{ + register int type; + register locl_t *lbp; + register glob_t *gbp; + cons_t offs ; + + *defined = TRUE ; + type = lnp->type1; + switch(type) { + default: if ( type>=VALLOW && type<=VALHIGH ) + return VAL1(type) ; + error("bad type during parval"); + break; + case CONST: + return(lnp->ad.ad_i); + case GLOSYM: + case GLOOFF: + if ( type!=GLOOFF) { + gbp = lnp->ad.ad_gp; + offs= 0 ; + } else { + gbp =lnp->ad.ad_df.df_gp ; + offs=lnp->ad.ad_df.df_i ; + } + if(gbp->g_status&DEF) + return(gbp->g_val.g_addr+offs); + else { + *defined = FALSE ; + return offs ; + } + case LOCSYM: + lbp = lnp->ad.ad_lp; + switch(pass) { + default:error("bad pass in parval"); + case 3: + *defined = FALSE; + switch(lbp->l_defined) { + default : fatal("Illegal local label") ; + case NO : + error("Undefined local label") ; + lbp->l_defined= NOTPRESENT ; + case NOTPRESENT: + return max_bytes; + case SEEN : + return max_bytes - lbp->l_min ; + case YES : + /* l_min contains line_num + adjusted for exc's. + */ + return (lbp->l_min - opt_line -1 ) * maxinsl ; + } + case 4: if(lbp->l_defined == YES) + return(lbp->l_min-prog_size-maxinsl); + return max_bytes - lbp->l_max- prog_size; + case 5: if (lbp->l_defined == YES ) + return lbp->l_min ; + *defined = FALSE ; + break ; + } + break; + case MISSING: + *defined = FALSE ; + break; + case PROCNAME: + return(lnp->ad.ad_pp->p_num); + } + return(0); +} +int valid(lnp) register line_t *lnp ; { + cons_t val ; + char type ; + + type = lnp->type1 ; + if ( type>=VALLOW && type<=VALHIGH ) { + val= VAL1(type) ; + type= CONST ; + } else if ( type==CONST ) val = lnp->ad.ad_i ; + switch ( em_flag[ctrunc(lnp->instr_num)]&EM_PAR ) { + case PAR_NO: + return type==MISSING ; + case PAR_C: + if ( type!=CONST ) return FALSE; + if ( val>maxint && val<=maxunsig ) { + lnp->ad.ad_i = val -maxunsig -1 ; + } + return TRUE ; + case PAR_D: + if ( type!=CONST ) return FALSE; + if ( val>maxdint && val<=maxdunsig ) { + lnp->ad.ad_i = val -maxdunsig -1 ; + } + return TRUE ; + case PAR_L: + case PAR_F: + return type==CONST ; + case PAR_N: + return type==CONST && val>=0 ; + case PAR_G: + return type==CONST || type==GLOSYM || type==GLOOFF ; + case PAR_W: + if ( type==MISSING ) return TRUE ; + case PAR_S: + return type==CONST && val>0 && val%wordsize==0 ; + case PAR_Z: + return type==CONST && val>=0 && val%wordsize==0 ; + case PAR_O: + return type==CONST && val>=0 && + ( val >= wordsize ? val%wordsize : wordsize%val ) == 0 ; + case PAR_P: + return type==PROCNAME ; + case PAR_B: + return type==LOCSYM ; + case PAR_R: + return type==CONST && val>=0 && val<=3 ; + default: + fatal("Unknown parameter type") ; + /* NOTREACHED */ + } +} diff --git a/util/ass/ass40.c b/util/ass/ass40.c new file mode 100644 index 000000000..e561110fa --- /dev/null +++ b/util/ass/ass40.c @@ -0,0 +1,55 @@ +/* + * (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 + * + */ + +#include "ass00.h" +#include "assex.h" +/* +** Make scans to do final assignment of instruction sizes & formats +** to those not already done. assign final values to labels +*/ +pass_4() +{ + register line_t *lnp; + register locl_t *lbp; + int min_l, max_l; + int instr; + + pass = 4; + prog_size= 0 ; + for (lnp = pstate.s_fline ; lnp ; lnp= lnp->l_next, line_num++) { + instr = ctrunc(lnp->instr_num); + if ( instr==sp_fpseu ) { + line_num = lnp->ad.ad_ln.ln_first ; + continue ; + } + if ( instr==sp_ilb1 ) { + lbp = lnp->ad.ad_lp; + lbp->l_min= prog_size; lbp->l_defined = YES; + continue ; + } + + if (lnp->opoff == NO_OFF) + { + determine_props(lnp, &min_l, &max_l); + if (min_l != max_l) + fatal("no size known"); + } else { + min_l = oplength(*(lnp->opoff)) ; + } + prog_size += min_l ; + } +} diff --git a/util/ass/ass50.c b/util/ass/ass50.c new file mode 100644 index 000000000..9692acdcc --- /dev/null +++ b/util/ass/ass50.c @@ -0,0 +1,190 @@ +/* + * (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 + * + */ + +#include "ass00.h" +#include "assex.h" +#include "ip_spec.h" + +/* +** Pass 5 of EM1 assembler/loader +** Fix reloc tables +** Write out code +*/ + +pass_5() { + 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 %D\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 */ + +genop(startc,value,i_flag) char *startc ; cons_t value ; int i_flag ; { + char *currc ; + register flag ; + char opc ; + + /* + * Real code generation. + */ + + 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: + put16(int_cast value) ; + break ; + case OP32: + put32(value) ; + break ; + case OP64: + put64(value) ; + break ; + } +} + +patchcase() { + 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); + } + } +} diff --git a/util/ass/ass60.c b/util/ass/ass60.c new file mode 100644 index 000000000..d3d56953e --- /dev/null +++ b/util/ass/ass60.c @@ -0,0 +1,211 @@ +/* + * (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 + * + */ + +#include "ass00.h" +#include "assex.h" +#include "ip_spec.h" + +#ifdef DUMP +static char *typestr[] = + {"missing","const","procname","glosym","locsym","glosym+off","pseudo"}; +static char *labstr[] = {"EMPTY","no","yes","seen","notpresent"}; +static char formstr[] = { 'm','s','-','1','2','4','8' }; +static char *r_data[] = { "null","glob","head","loc","adr" }; + +cons_t nicepr(typ,ap) addr_u *ap; char typ; { + register proc_t *pl; + + switch (typ) { + case CONST: + return(ap->ad_i); + case LOCSYM: + return(int_cast ap->ad_lp); + case GLOOFF: + return(ap->ad_df.df_gp - mglobs); + case GLOSYM: + return(ap->ad_gp - mglobs); + case PROCNAME: + pl = ap->ad_pp;; + if (pl->p_status&EXT) + return((pl-xprocs)+1000); + else + return(pl-mprocs); + default: + if ( typ>=VALLOW && typ<=VALHIGH ) return VAL1(typ) ; + break ; + } + return(0); +} + +char *pflags(flg) int flg ; { + static char res[9] ; + register char *cp ; + + cp=res ; + if ( flg&OPESC ) *cp++ = 'e' ; + switch ( flg&OPRANGE ) { + case OP_NEG : *cp++ = 'N' ; break ; + case OP_POS : *cp++ = 'P' ; break ; + } + if ( flg&OPWORD ) *cp++ = 'w' ; + if ( flg&OPNZ ) *cp++ = 'o' ; + *cp++ = formstr[flg&OPTYPE] ; + *cp++ = 0 ; + return res ; +} + + +dump(n) +{ + register glob_t *gb; + register line_t *ln; + register locl_t *lbp; + register locl_t *lbhead; + proc_t *pl; + int i; + int insno; + extern char em_mnem[][4] ; + + if (d_flag==0) return; +if ( (n==0 && d_flag) || (n==4 && d_flag>=2) || (n<100 && d_flag>=3) ) { + printf("\nEM1-assembler ***** pass %1d complete:\n",n); + printf("current size %D\n",prog_size) ; + printf(" %9.9s%9.9s%14.14s%8.8s%8.8s\n", "instr_nr", + "type1","addr1","length","format"); + for (ln = pstate.s_fline ; ln ; + ln = ln->l_next, n>=3 || n==0 ? i++ : i-- ) { + insno = ctrunc(ln->instr_num) ; + if ( insno==sp_fpseu ) { + i= ln->ad.ad_ln.ln_first ; + continue ; + } + printf("%4d ",i) ; + switch(insno) { + default: + printf( + " %3.3s",em_mnem[insno]) ; + break ; + case sp_ilb1: + printf("l "); + break; + case sp_fpseu: + printf("p "); + break; + } + printf(" %9.9s%14D", + typestr[ln->type1type1 : CONST], + nicepr(ln->type1,&ln->ad)) ; + if ( ln->opoff != NO_OFF ) + printf("%5d %.6s", + oplength(*(ln->opoff)),pflags(*(ln->opoff))); + printf("\n"); + } + printf("\n %8s%8s%8s%8s%8s\n","labnum","labid","minval","maxval", + "defined"); + for ( i = 0, lbhead= *pstate.s_locl ; il_defined!=EMPTY ) printf("%4d\n",i); + for (lbp= lbhead; lbp != lbp_cast 0; lbp= lbp->l_chain) { + if (lbp->l_defined!=EMPTY) + printf(" %8d%8d%8d%8d %-s\n", + lbp->l_hinum*LOCLABSIZE + i, + int_cast lbp,lbp->l_min, + lbp->l_max, labstr[lbp->l_defined]); + } + } +} +if ( ( (n==0 || n>=100) && d_flag) || (n<=1 && d_flag>=2) ) { + if ( n==0 || n==100 ) { + printf("File %s",curfile) ; + if ( archmode ) printf("(%.14s)",archhdr.ar_name); + printf(" :\n\n") ; + } + printf("Local data labels:\n"); + printf( + "\n\t%8.8s %8.8s %8.8s\n","g_name","g_status","g_addr"); + for (gb = mglobs,i = 0;gb < &mglobs[oursize->n_mlab]; gb++, i++) + if (gb->g_name[0] != 0) { + printf("%5d\t%8.6s",i,gb->g_name); + printf(" %8o %8ld\n",gb->g_status,gb->g_val.g_addr); + } + printf("\n\nGlobal data labels\n"); + printf("\n\t%8.8s %8.8s %8.8s\n", + "g_name","g_status","g_addr"); + for (gb = xglobs,i = 0;gb < &xglobs[oursize->n_glab]; gb++, i++) + if (gb->g_name[0] != 0) { + printf("%5d\t%8.6s",i,gb->g_name); + printf(" %8o %8ld\n",gb->g_status,gb->g_val.g_addr); + } + printf("\n\nLocal procedures\n"); + printf("\n\t%8.8s%8s%8s\t%8s%8s\n", + "name","status","num","off","locals"); + for (pl=mprocs;pl< &mprocs[oursize->n_mproc]; pl++) + if (pl->p_name[0]) { + printf("%4d\t%-8s%8o%8d", + pl-mprocs,pl->p_name,pl->p_status,pl->p_num); + if (pl->p_status&DEF) + printf("\t%8ld%8ld",proctab[pl->p_num].pr_off, + proctab[pl->p_num].pr_loc); + printf("\n"); + } + printf("\nGlobal procedures\n"); + printf("\n\t%8s%8s%8s\t%8s%8s\n", + "name","status","num","off","locals"); + for (pl=xprocs;pl< &xprocs[oursize->n_xproc]; pl++) + if (pl->p_name[0]) { + printf("%4d\t%-8s%8o%8d", + pl-xprocs,pl->p_name,pl->p_status,pl->p_num); + if (pl->p_status&DEF) + printf("\t%8ld%8ld",proctab[pl->p_num].pr_off, + proctab[pl->p_num].pr_loc); + printf("\n"); + } + if ( r_flag ) { + register relc_t *rl ; + printf("\nData relocation\n") ; + printf("\n\t%10s %10s %10s\n","offset","type","value"); + for ( rl=f_data ; rl ; rl= rl->r_next ) { + printf("\t%10D %10s ",rl->r_off,r_data[rl->r_typ]); + switch(rl->r_typ) { + case RELADR: + case RELHEAD: + printf("%10D\n",rl->r_val.rel_i) ; + break ; + case RELGLO: + printf("%8.8s\n",rl->r_val.rel_gp->g_name) ; + break ; + case RELLOC: + printf("%10d\n",rl->r_val.rel_lp) ; + break ; + case RELNULL: + printf("\n"); break ; + } + } + printf("\n\nText relocation\n") ; + printf("\n\t%10s %10s %10s\n","offset","flags","value"); + for ( rl=f_text; rl ; rl= rl->r_next ) { + printf("\t%10D %10s ", + rl->r_off,pflags(opchoice[rl->r_typ&~RELMNS])) ; + if ( rl->r_typ&RELMNS ) + printf("%10D\n",rl->r_val.rel_i) ; + else printf("\n") ; + } + } + + +} +} +#endif diff --git a/util/ass/ass70.c b/util/ass/ass70.c new file mode 100644 index 000000000..ae123b3a9 --- /dev/null +++ b/util/ass/ass70.c @@ -0,0 +1,341 @@ +/* + * (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 + * + */ + +#include "ass00.h" +#include "assex.h" +/* +** utilities of EM1-assembler/loader +*/ + +static int globstep; + +/* + * glohash returns an index in table and leaves a stepsize in globstep + * + */ + +static int glohash(aname,size) char *aname; { + register char *p; + register i; + register sum; + + /* + * Computes a hash-value from a string. + * Algorithm is adding all the characters after shifting some way. + */ + + for(sum=i=0,p=aname;*p;i += 3) + sum += (*p++)<<(i&07); + sum &= 077777; + globstep = (sum / size) + 7; + return(sum % size); +} + +/* + * lookup idname in labeltable , if it is not there enter it + * return index in labeltable + */ + +glob_t *glo2lookup(name,status) char *name; { + + return(glolookup(name,status,mglobs,oursize->n_mlab)); +} + +glob_t *xglolookup(name,status) char *name; { + + return(glolookup(name,status,xglobs,oursize->n_glab)); +} + +static void findext(g) glob_t *g ; { + glob_t *x; + + x = xglolookup(g->g_name,ENTERING); + if (x && (x->g_status&DEF)) { + g->g_status |= DEF; + g->g_val.g_addr = x->g_val.g_addr; + } + g->g_status |= EXT; +} + +glob_t *glolookup(name,status,table,size) +char *name; /* name */ +int status; /* kind of lookup */ +glob_t *table; /* which table to use */ +int size; /* size for hash */ +{ + register glob_t *g; + register rem,j; + int new; + + /* + * lookup global symbol name in specified table. + * Various actions are taken depending on status. + * + * DEFINING: + * Lookup or enter the symbol, check for mult. def. + * OCCURRING: + * Lookup the symbol, export if not known. + * INTERNING: + * Enter symbol local to the module. + * EXTERNING: + * Enter symbol visable from every module. + * SEARCHING: + * Lookup the symbol, return 0 if not found. + * ENTERING: + * Lookup or enter the symbol, don't check + */ + + rem = glohash(name,size); + j = 0; new=0; + g = &table[rem]; + while (g->g_name[0] != 0 && strcmp(name,g->g_name) != 0) { + j++; + if (j>size) + fatal("global label table overflow"); + rem = (rem + globstep) % size; + g = &table[rem]; + } + if (g->g_name[0] == 0) { + /* + * This symbol is shining new. + * Enter it in table except for status = SEARCHING + */ + if (status == SEARCHING) + return(0); + strcpy(g->g_name,name); + g->g_status = 0; + g->g_val.g_addr=0; + new++; + } + switch(status) { + case SEARCHING: /* nothing special */ + case ENTERING: + break; + case INTERNING: + if (!new) + werror("INA must be first occurrence of '%s'",name); + break; + case EXTERNING: /* lookup in other table */ + /* + * The If statement is removed to be friendly + * to Backend writers having to deal with assemblers + * not following our conventions. + if (!new) + error("EXA must be first occurrence of '%s'",name); + */ + findext(g); + break; + case DEFINING: /* Thou shalt not redefine */ + if (g->g_status&DEF) + error("global symbol '%s' redefined",name); + g->g_status |= DEF; + break; + case OCCURRING: + if ( new ) + findext(g); + g->g_status |= OCC; + break; + default: + fatal("bad status in glolookup"); + } + return(g); +} + +locl_t *loclookup(an,status) { + register locl_t *lbp,*l_lbp; + register unsigned num; + char hinum; + + if ( !pstate.s_locl ) fatal("label outside procedure"); + num = an; + if ( num/LOCLABSIZE>255 ) fatal("local label number too large"); + hinum = num/LOCLABSIZE; + l_lbp= lbp= &(*pstate.s_locl)[num%LOCLABSIZE]; + if ( lbp->l_defined==EMPTY ) { + lbp= lbp_cast 0 ; + } else { + while ( lbp!= lbp_cast 0 && lbp->l_hinum != hinum ) { + l_lbp = lbp ; + lbp = lbp->l_chain; + } + } + if ( lbp == lbp_cast 0 ) { + if ( l_lbp->l_defined!=EMPTY ) { + lbp = lbp_cast getarea(sizeof *lbp); + l_lbp->l_chain= lbp ; + } else lbp= l_lbp ; + lbp->l_chain= lbp_cast 0 ; + lbp->l_hinum=hinum; + lbp->l_defined = (status==OCCURRING ? NO : YES); + lbp->l_min= line_num; + } else + if (status == DEFINING) { + if (lbp->l_defined == YES) + error("multiple defined local symbol"); + else + lbp->l_defined = YES; + } + if ( status==DEFINING ) lbp->l_min= line_num ; + return(lbp); +} + +proc_t *prolookup(name,status) char *name; { + register proc_t *p; + register pstat; + + /* + * Look up a procedure name according to status + * + * PRO_OCC: Occurrence + * Search both tables, local table first. + * If not found, enter in global table + * PRO_INT: INP + * Enter symbol in local table. + * PRO_DEF: Definition + * Define local procedure. + * PRO_EXT: EXP + * Enter symbol in global table. + * + * The EXT bit in this table indicates the the name is used + * as external in this module. + */ + + switch(status) { + case PRO_OCC: + p = searchproc(name,mprocs,oursize->n_mproc); + if (p->p_name[0]) { + p->p_status |= OCC; + return(p); + } + p = searchproc(name,xprocs,oursize->n_xproc); + if (p->p_name[0]) { + p->p_status |= OCC; + return(p); + } + pstat = OCC|EXT; + unresolved++ ; + break; + case PRO_INT: + p = searchproc(name,xprocs,oursize->n_xproc); + if (p->p_name[0] && (p->p_status&EXT) ) + error("pro '%s' conflicting use",name); + + p = searchproc(name,mprocs,oursize->n_mproc); + if (p->p_name[0]) + werror("INP must be first occurrence of '%s'",name); + pstat = 0; + break; + case PRO_EXT: + p = searchproc(name,mprocs,oursize->n_mproc); + if (p->p_name[0]) + error("pro '%s' exists already localy",name); + p = searchproc(name,xprocs,oursize->n_xproc); + if (p->p_name[0]) { + /* + * The If statement is removed to be friendly + * to Backend writers having to deal with assemblers + * not following our conventions. + if ( p->p_status&EXT ) + werror("EXP must be first occurrence of '%s'", + name) ; + */ + p->p_status |= EXT; + return(p); + } + pstat = EXT; + unresolved++; + break; + case PRO_DEF: + p = searchproc(name,xprocs,oursize->n_xproc); + if (p->p_name[0] && (p->p_status&EXT) ) { + if (p->p_status&DEF) + error("global pro '%s' redeclared",name); + else + unresolved-- ; + p->p_status |= DEF; + return(p); + } else { + p = searchproc(name,mprocs,oursize->n_mproc); + if (p->p_name[0]) { + if (p->p_status&DEF) + error("local pro '%s' redeclared", + name); + p->p_status |= DEF; + return(p); + } + } + pstat = DEF; + break; + default: + fatal("bad status in prolookup"); + } + return(enterproc(name,pstat,p)); +} + +proc_t *searchproc(name,table,size) + char *name; + proc_t *table; + int size; +{ + register proc_t *p; + register rem,j; + + /* + * return a pointer into table to the place where the procedure + * name is or should be if in the table. + */ + + rem = glohash(name,size); + j = 0; + p = &table[rem]; + while (p->p_name[0] != 0 && strcmp(name,p->p_name) != 0) { + j++; + if (j>size) + fatal("procedure table overflow"); + rem = (rem + globstep) % size; + p = &table[rem]; + } + return(p); +} + +proc_t *enterproc(name,status,place) +char *name; +char status; +proc_t *place; { + register proc_t *p; + + /* + * Enter the procedure name into the table at place place. + * Place had better be computed by searchproc(). + * + * NOTE: + * At this point the procedure gets assigned a number. + * This number is used as a parameter of cal and in some + * other ways. There exists a 1-1 correspondence between + * procedures and numbers. + * Two local procedures with the same name in different + * modules have different numbers. + */ + + p=place; + strcpy(p->p_name,name); + p->p_status = status; + if (procnum>=oursize->n_proc) + fatal("too many procedures"); + p->p_num = procnum++; + return(p); +} diff --git a/util/ass/ass80.c b/util/ass/ass80.c new file mode 100644 index 000000000..85c1514ac --- /dev/null +++ b/util/ass/ass80.c @@ -0,0 +1,412 @@ +/* + * (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 + * + */ + +#include "ass00.h" +#include "assex.h" +#include "../../h/em_path.h" + +/* + * this file contains several library routines. + */ + +zero(area,length) char *area; unsigned length ; { + register char *p; + register n; + /* + * Clear area of length bytes. + */ + if ((n=length)==0) + return; + p = area; + do *p++=0; while (--n); +} + +/* VARARGS1 */ +static void pr_error(string1,a1,a2,a3,a4) char *string1 ; { + /* + * diagnostic output + */ + fprintf(stderr,"%s: ",progname); + if (curfile) { + fprintf(stderr,"file %s",curfile); + if (archmode) + fprintf(stderr," (%.14s)",archhdr.ar_name); + fprintf(stderr,": "); + } + if ( pstate.s_curpro ) { + fprintf(stderr,"proc %s, ",pstate.s_curpro->p_name); + } + fprintf(stderr,"line %d: ",line_num); + fprintf(stderr,string1,a1,a2,a3,a4); + fprintf(stderr,"\n"); +} + +/* VARARGS1 */ +void error(string1,a1,a2,a3,a4) char *string1 ; { + pr_error(string1,a1,a2,a3,a4) ; + nerrors++ ; +} + +/* VARARGS1 */ +void werror(string1,a1,a2,a3,a4) char *string1 ; { + if ( wflag ) return ; + pr_error(string1,a1,a2,a3,a4) ; +} + +fatal(s) char *s; { + /* + * handle fatal errors + */ + error("Fatal error: %s",s); + dump(0); + exit(-1); +} + +#ifndef CPM +FILE *frewind(f) FILE *f ; { + /* Rewind a file open for writing and open it for reading */ + /* Assumption, file descriptor is r/w */ + register FILE *tmp ; + rewind(f); + tmp=fdopen(dup(fileno(f)),"r"); + fclose(f); + return tmp ; +} +#endif + +int xgetc(af) register FILE *af; { + register int nextc; + /* + * read next character; fatal if there isn't one + */ + nextc=fgetc(af) ; + if ( feof(af) ) + fatal("unexpected end of file"); + return nextc ; +} + +xputc(c,af) register FILE *af; { + /* output one character and scream if it gives an error */ + fputc(c,af) ; + if ( ferror(af) ) fatal("write error") ; +} + + +putblk(stream,from,amount) + register FILE *stream; register char *from ; register int amount ; { + + for ( ; amount-- ; from++ ) { + fputc(*from,stream) ; + if ( ferror(stream) ) fatal("write error") ; + } +} + +int getblk(stream,from,amount) + register FILE *stream; register char *from ; register int amount ; { + + for ( ; amount-- ; from++ ) { + *from = fgetc(stream) ; + if ( feof(stream) ) return 1 ; + } + return 0 ; +} + +xput16(w,f) FILE *f; { + /* + * two times xputc + */ + xputc(w,f); + xputc(w>>8,f); +} + +xputarb(l,w,f) int l ; cons_t w ; FILE *f ; { + while ( l-- ) { + xputc( int_cast w,f) ; + w >>=8 ; + } +} + +put8(n) { + xputc(n,tfile); + textoff++; +} + +put16(n) { + /* + * note reversed order of bytes. + * this is done for faster interpretation. + */ + xputc(n>>8,tfile); + xputc(n&0377,tfile); + textoff += 2; +} + +put32(n) cons_t n ; { + put16( int_cast (n>>16)) ; + put16( int_cast n) ; +} + +put64(n) cons_t n ; { + fatal("put64 called") ; +} + +int xget8() { + /* + * Read one byte from ifile. + */ + if (libeof && inpoff >= libeof) + return EOF ; + inpoff++; + return fgetc(ifile) ; +} + +unsigned get8() { + register int nextc; + /* + * Read one byte from ifile. + */ + nextc=xget8(); + if ( nextc==EOF ) { + if (libeof) + fatal("Tried to read past end of arentry\n"); + else + fatal("end of file on input"); + } + return nextc ; +} + +cons_t xgetarb(l,f) int l; FILE *f ; { + cons_t val ; + register int shift ; + + shift=0 ; val=0 ; + while ( l-- ) { + val += ((cons_t)ctrunc(xgetc(f)))<>= 8 ; + } +} + +extarb(size,value) int size ; long value ; { + /* Assemble the 'size' constant value. + * The bytes are again written low to high. + */ + register i ; + for ( i=size ; i-- ; ) { + ext8( int_cast value ) ; + value >>=8 ; + } +} + +extadr(a) cons_t a ; { + /* Assemble the word constant a. + * NOTE: The bytes are written low to high. + */ + register i ; + for ( i=ptrsize ; i-- ; ) { + ext8( int_cast a) ; + a >>= 8 ; + } +} + +xputa(a,f) cons_t a ; FILE *f ; { + /* Assemble the pointer constant a. + * NOTE: The bytes are written low to high. + */ + register i ; + for ( i=ptrsize ; i-- ; ) { + xputc( int_cast a,f) ; + a >>= 8 ; + } +} + +cons_t xgeta(f) FILE *f ; { + /* Read the pointer constant a. + * NOTE: The bytes were written low to high. + */ + register i, shift ; + cons_t val ; + val = 0 ; shift=0 ; + for ( i=ptrsize ; i-- ; ) { + val += ((cons_t)xgetc(f))<MAXBYTE) fatal("Descriptor overflow"); + return amount ; +} + +setmode(mode) { + + if (datamode==mode) { /* in right mode already */ + switch ( datamode ) { + case DATA_CONST: + if ( (dataoff-lastoff)/wordsize < MAXBYTE ) return ; + break ; + case DATA_BYTES: + if ( dataoff-lastoff < MAXBYTE ) return ; + break ; + case DATA_IPTR: + case DATA_DPTR: + if ( (dataoff-lastoff)/ptrsize < MAXBYTE ) return ; + break ; + case DATA_ICON: + case DATA_FCON: + case DATA_UCON: + break ; + default: + return ; + } + setmode(DATA_NUL) ; /* flush current descriptor */ + setmode(mode) ; + return; + } + switch(datamode) { /* terminate current mode */ + case DATA_NUL: + break; /* nothing to terminate */ + case DATA_CONST: + lastheader->r_val.rel_i=icount(wordsize) ; + lastheader->r_typ = RELHEAD; + datablocks++; + break; + case DATA_BYTES: + lastheader->r_val.rel_i=icount(1) ; + lastheader->r_typ = RELHEAD; + datablocks++; + break; + case DATA_DPTR: + case DATA_IPTR: + lastheader->r_val.rel_i=icount(ptrsize) ; + lastheader->r_typ = RELHEAD; + datablocks++; + break; + default: + datablocks++; + break; + } + datamode=mode; + switch(datamode) { + case DATA_NUL: + break; + case DATA_CONST: + ext8(HEADCONST); + lastheader=data_reloc( chp_cast 0,dataoff,RELNULL); + ext8(0); + lastoff=dataoff; + break; + case DATA_BYTES: + ext8(HEADBYTE); + lastheader=data_reloc( chp_cast 0,dataoff,RELNULL); + ext8(0); + lastoff=dataoff; + break; + case DATA_IPTR: + ext8(HEADIPTR); + lastheader=data_reloc( chp_cast 0,dataoff,RELNULL); + ext8(0); + lastoff=dataoff; + break; + case DATA_DPTR: + ext8(HEADDPTR); + lastheader=data_reloc( chp_cast 0,dataoff,RELNULL); + ext8(0); + lastoff=dataoff; + break; + case DATA_ICON: + ext8(HEADICON) ; + ext8( int_cast consiz) ; + break; + case DATA_FCON: + ext8(HEADFCON) ; + ext8( int_cast consiz) ; + break; + case DATA_UCON: + ext8(HEADUCON) ; + ext8( int_cast consiz) ; + break; + case DATA_REP: + ext8(HEADREP) ; + break ; + default: + fatal("Unknown mode in setmode") ; + } +} + +#ifndef CPM +int tmpfil() { + register char *fname, *cpname ; + char *sfname; + register fildes,pid; + static char name[80] = TMP_DIR ; + int count; + /* + * This procedure returns a file-descriptor of a temporary + * file valid for reading and writing. + * After closing the tmpfil-descriptor the file is lost + * Calling this routine frees the program from generating uniqe names. + */ + sfname = fname = "tmp.00000"; + count = 10; + pid = getpid(); + fname += 4; + while (pid!=0) { + *fname++ = (pid&07) + '0'; + pid >>= 3; + } + *fname = 0; + for ( fname=name ; *fname ; fname++ ) ; + cpname=sfname ; + while ( *fname++ = *cpname++ ) ; + do { + fname = name; + if ((fildes = creat(fname, 0600)) < 0) + if ((fildes = creat(fname=sfname, 0600)) < 0) + return(-1); + if (close(fildes) < 0) + ; + } while((fildes = open(fname, 2)) < 0 && count--); + if (unlink(fname) < 0) + ; + return(fildes); +} +#endif diff --git a/util/ass/assci.c b/util/ass/assci.c new file mode 100644 index 000000000..42b4a14bd --- /dev/null +++ b/util/ass/assci.c @@ -0,0 +1,847 @@ +/* + * (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 + * + */ + +#include "ass00.h" +#include "assex.h" +#include "../../h/em_mes.h" +#include "../../h/em_pseu.h" +#include "../../h/em_ptyp.h" + +/* + * read compact code and fill in tables + */ + +static int tabval; +static cons_t argval; + +static int oksizes; /* MES EMX,.,. seen */ + +static enum m_type { CON, ROM, HOLBSS } memtype ; +static int valtype; /* Transfer of type information between + valsize ans putval + */ + +int table3(i) { + + switch(i) { + case sp_ilb1: + tabval = get8(); + break; + case sp_dlb1: + make_string(get8()); + i= sp_dnam; + break; + case sp_dlb2: + tabval = get16(); + if ( tabval<0 ) { + error("illegal data label .%d",tabval); + tabval=0 ; + } + make_string(tabval); + i= sp_dnam; + break; + case sp_cst2: + argval = get16(); + break; + case sp_ilb2: + tabval = get16(); + if ( tabval<0 ) { + error("illegal instruction label %d",tabval); + tabval=0 ; + } + i = sp_ilb1; + break; + case sp_cst4: + i = sp_cst2; + argval = get32(); + break; + case sp_dnam: + case sp_pnam: + inident(); + break ; + case sp_scon: + getstring() ; + break; + case sp_doff: + getarg(sym_ptyp); + getarg(cst_ptyp); + break; + case sp_icon: + case sp_ucon: + case sp_fcon: + getarg(cst_ptyp); + consiz = argval; + if ( consiz=128 ) h_byte -= 256 ; + return l_byte | (h_byte*256) ; +} + +cons_t get32() { + register cons_t l; + register int h_byte; + + l = get8(); l |= (unsigned)get8()*256 ; l |= get8()*256L*256L ; + h_byte = get8() ; + if ( h_byte>=128 ) h_byte -= 256 ; + return l | (h_byte*256L*256*256L) ; +} + +int table1() { + register i; + + i = xget8(); + if (i < sp_fmnem+sp_nmnem && i >= sp_fmnem) { + tabval = i-sp_fmnem; + return(sp_fmnem); + } + if (i < sp_fpseu+sp_npseu && i >= sp_fpseu) { + tabval = i; + return(sp_fpseu); + } + if (i < sp_filb0+sp_nilb0 && i >= sp_filb0) { + tabval = i - sp_filb0; + return(sp_ilb1); + } + return(table3(i)); +} + +int table2() { + register i; + + i = get8(); + if (i < sp_fcst0+sp_ncst0 && i >= sp_fcst0) { + argval = i - sp_zcst0; + return(sp_cst2); + } + return(table3(i)); +} + +int getarg(typset) { + register t,argtyp; + + argtyp = t = table2(); + t -= sp_fspec; + t = 1 << t; + if ((typset & t) == 0) + error("bad argument type %d",argtyp); + return(argtyp); +} + +cons_t getint() { + getarg(cst_ptyp); + return(argval); +} + +glob_t *getlab(status) { + getarg(sym_ptyp); + return(glo2lookup(string,status)); +} + +char *inproname() { + getarg(ptyp(sp_pnam)); + return(string); +} + +int needed() { + register glob_t *g; + register proc_t *p; + + for(;;){ + switch ( table2() ) { + case sp_dnam : + if (g = xglolookup(string,SEARCHING)) { + if ((g->g_status&DEF) != 0) + continue ; + } else continue ; + break ; + case sp_pnam : + p = searchproc(string,xprocs,oursize->n_xproc); + if (p->p_name[0]) { + if ((p->p_status & DEF) != 0) + continue ; + } else continue ; + break ; + default : + error("Unexpected byte after ms_ext") ; + case sp_cend : + return FALSE ; + } + while ( table2()!=sp_cend ) ; + return TRUE ; + } +} + +cons_t valsize() { + switch(valtype=table2()) { /* valtype is used by putval */ + case sp_cst2: + return wordsize ; + case sp_ilb1: + case sp_dnam: + case sp_doff: + case sp_pnam: + return ptrsize ; + case sp_scon: + return strlngth ; + case sp_fcon: + case sp_icon: + case sp_ucon: + return consiz ; + case sp_cend: + return 0 ; + default: + fatal("value expected") ; + /* NOTREACHED */ + } +} + +newline(type) { + register line_t *n_lnp ; + + if ( type>VALLOW ) type=VALLOW ; + n_lnp = lnp_cast getarea((unsigned)linesize[type]) ; + n_lnp->l_next = pstate.s_fline ; + pstate.s_fline = n_lnp ; + n_lnp->type1 = type ; + n_lnp->opoff = NO_OFF ; +} + +read_compact() { + + /* + * read module in compact EM1 code + */ + init_module(); + pass = 1; + eof_seen = 0; + do { + compact_line() ; + line_num++; + } while (!eof_seen) ; + endproc() ; /* Throw away unwanted garbage */ + if ( mod_sizes ) end_module(); + /* mod_sizes is only false for rejected library modules */ +} + +int compact_line() { + register instr_no ; + + /* + * read one "line" of compact code. + */ + curglosym=0; + switch (table1()) { + default: + fatal("unknown byte at start of \"line\""); /* NOTREACHED */ + case EOF: + eof_seen++ ; + while ( pstate.s_prevstat != pst_cast 0 ) { + error("missing end") ; do_proc() ; + } + return ; + case sp_fmnem: + if ( pstate.s_curpro == prp_cast 0) { + error("instruction outside procedure"); + } + instr_no = tabval; + if ( (em_flag[instr_no]&EM_PAR)==PAR_NO ) { + newline(MISSING) ; + pstate.s_fline->instr_num= instr_no ; + return ; + } + /* + * This instruction should have an opcode, so read it after + * this switch. + */ + break; + case sp_dnam: + chkstart() ; + align(wordsize) ; + curglosym = glo2lookup(string,DEFINING); + curglosym->g_val.g_addr = databytes; + lastglosym = curglosym; + setline() ; line_num++ ; + if (table1() != sp_fpseu) + fatal("no pseudo after global label"); + case sp_fpseu: + inpseudo(tabval); + setline() ; + return ; + case sp_ilb1: + newline(LOCSYM) ; + pstate.s_fline->ad.ad_lp = loclookup(tabval,DEFINING); + pstate.s_fline->instr_num = sp_ilb1; + return ; + } + + /* + * Now process argument + */ + + switch(table2()) { + default: + fatal("unknown byte at start of argument"); /*NOTREACHED*/ + case sp_cst2: + if ( (em_flag[instr_no]&EM_PAR)==PAR_B ) { + /* value indicates a label */ + newline(LOCSYM) ; + pstate.s_fline->ad.ad_lp= + loclookup((int)argval,OCCURRING) ; + } else { + if ( argval>=VAL1(VALLOW) && argval<=VAL1(VALHIGH)) { + newline(VALLOW) ; + pstate.s_fline->type1 = argval+VALMID ; + } else { + newline(CONST) ; + pstate.s_fline->ad.ad_i = argval; + pstate.s_fline->type1 = CONST; + } + } + break; + case sp_ilb1: + newline(LOCSYM) ; + pstate.s_fline->ad.ad_lp = loclookup(tabval,OCCURRING); + break; + case sp_dnam: + newline(GLOSYM) ; + pstate.s_fline->ad.ad_gp = glo2lookup(string,OCCURRING); + break; + case sp_pnam: + newline(PROCNAME) ; + pstate.s_fline->ad.ad_pp=prolookup(string,PRO_OCC); + break; + case sp_cend: + if ( (em_flag[instr_no]&EM_PAR)!=PAR_W ) { + fatal("missing operand") ; + } + newline(MISSING) ; + break ; + case sp_doff: + newline(GLOOFF) ; + pstate.s_fline->ad.ad_df.df_i = argval ; + pstate.s_fline->ad.ad_df.df_gp= glo2lookup(string,OCCURRING) ; + break ; + } + pstate.s_fline->instr_num= instr_no ; + return ; +} + +inpseudo(instr_no) { + cons_t cst; + register proc_t *prptr; + cons_t objsize; + cons_t par1,par2; + register char *pars; + + /* + * get operands of pseudo (if needed) and process it. + */ + + switch ( ctrunc(instr_no) ) { + case ps_bss: + chkstart() ; + typealign(HOLBSS) ; + cst = getint(); /* number of bytes */ + extbss(cst); + break; + case ps_hol: + chkstart() ; + typealign(HOLBSS) ; + holsize=getint(); + holbase=databytes; + extbss(holsize); + break; + case ps_rom: + case ps_con: + chkstart() ; + typealign( ctrunc(instr_no)==ps_rom ? ROM : CON ) ; + while( (objsize=valsize())!=0 ) { + sizealign(objsize) ; + putval() ; + databytes+=objsize ; + } + break; + case ps_end: + prptr= pstate.s_curpro ; + if ( prptr == prp_cast 0 ) fatal("unexpected END") ; + proctab[prptr->p_num].pr_off = textbytes; + if (procflag) { + printf("%6lu\t%6lo\t%5d\t%-12s\t%s", + textbytes,textbytes, + prptr->p_num,prptr->p_name,curfile); + if (archmode) + printf("(%.14s)",archhdr.ar_name); + printf("\n"); + } + par2 = proctab[prptr->p_num].pr_loc ; + if ( getarg(cst_ptyp|ptyp(sp_cend))==sp_cend ) { + if ( par2 == -1 ) { + fatal("size of local area unspecified") ; + } + } else { + if ( par2 != -1 && argval!=par2 ) { + fatal("inconsistent local area size") ; + } + proctab[prptr->p_num].pr_loc = argval ; + } + setline(); + do_proc(); + break; + case ps_mes: + switch( int_cast getint() ) { + case ms_err: + error("module with error") ; ertrap(); + /* NOTREACHED */ + case ms_emx: + if ( oksizes ) { + if ( wordsize!=getint() ) { + fatal("Inconsistent word size"); + } + if ( ptrsize!=getint() ) { + fatal("Inconsistent pointer size"); + } + } else { + oksizes++ ; + wordsize=getint();ptrsize=getint(); + if ( wordsize!=2 && wordsize!=4 ) { + fatal("Illegal word size"); + } + if ( ptrsize!=2 && ptrsize!=4 ) { + fatal("Illegal pointer size"); + } + setsizes() ; + } + ++mod_sizes ; + break; + case ms_src: + break; + case ms_flt: + intflags |= 020; break; /*floats used*/ + case ms_ext: + if ( !needed() ) { + eof_seen++ ; + } + if ( line_num!=1 ) { + werror("mes ms_ext must be first pseudo") ; + } + return ; + } + while (table2() != sp_cend) + ; + break; + case ps_exc: + par1 = getint(); + par2 = getint(); + if (par1 == 0 || par2 == 0) + break; + exchange((int)par2,(int)par1) ; + break; + case ps_exa: + getlab(EXTERNING); + break; + case ps_ina: + getlab(INTERNING); + break; + case ps_pro: + chkstart() ; + initproc(); + pars = inproname(); + if ( getarg(cst_ptyp|ptyp(sp_cend))==sp_cend ) { + par2 = -1 ; + } else { + par2 = argval ; + } + prptr = prolookup(pars,PRO_DEF); + proctab[prptr->p_num].pr_loc = par2; + pstate.s_curpro=prptr; + break; + case ps_inp: + prptr = prolookup(inproname(),PRO_INT); + break; + case ps_exp: + prptr = prolookup(inproname(),PRO_EXT); + break; + default: + fatal("unknown pseudo"); + } + if ( !mod_sizes ) fatal("Missing size specification"); + if ( databytes>maxadr ) error("Maximum data area size exceeded") ; +} + +setline() { + + /* Get line numbers correct */ + + if ( pstate.s_fline && + ctrunc(pstate.s_fline->instr_num) == sp_fpseu ) { + /* Already one present */ + pstate.s_fline->ad.ad_ln.ln_extra++ ; + } else { + newline(LINES) ; + pstate.s_fline->instr_num= sp_fpseu ; + pstate.s_fline->ad.ad_ln.ln_extra= 0 ; + pstate.s_fline->ad.ad_ln.ln_first= line_num ; + } + +} + +cons_t maxval(bits) int bits ; { + /* find the maximum positive value, + * fitting in 'bits' bits AND + * fitting in a 'cons_t' . + */ + + cons_t val ; + val=1 ; + while ( bits-- ) { + val<<= 1 ; + if ( val<0 ) return ~val ; + } + return val-1 ; +} + +setsizes() { + maxadr = maxval(8*ptrsize) ; + maxint = maxval(8*wordsize-1) ; + maxunsig = maxval(8*wordsize) ; + maxdint = maxval(2*8*wordsize-1) ; + maxdunsig = maxval(2*8*wordsize) ; +} + +char *getdig(str,number) char *str; register unsigned number; { + register int remain; + + remain= number%10; + number /= 10; + if ( number ) str= getdig(str,number) ; + *str++ = '0'+remain ; + return str ; +} + +make_string(n) unsigned n ; { + string[0] = '.'; + *getdig(&string[1],n)= 0; +} + + +getstring() { + register char *p; + register n; + + getarg(cst_ptyp); + if ( argval < 0 || argval >= MAXSTRING-1 ) + fatal("string/identifier too long"); + strlngth = n = argval; + p = string; + while (--n >= 0) + *p++ = get8(); + *p = 0 ; +} + +inident() { + getstring(); + string[IDLENGTH] = '\0'; +} + +exchange(p1,p2) { + int size, line ; + int l_of_p1, l_of_p2, l_of_before ; + register line_t *t_lnp,*a_lnp, *b_lnp ; + + /* Since the lines are linked backwards it is easy + * to count the number of lines backwards. + * Each instr counts for 1, each pseudo for ln_extra + 1. + * The line numbers in error messages etc. are INCORRECT + * If exc's are used. + */ + + line= line_num ; size=0 ; + newline(LINES) ; a_lnp=pstate.s_fline ; + a_lnp->instr_num= sp_fpseu ; + a_lnp->ad.ad_ln.ln_first= line ; + a_lnp->ad.ad_ln.ln_extra= -1 ; + for ( ; a_lnp ; a_lnp= a_lnp->l_next ) { + line-- ; + switch ( ctrunc(a_lnp->instr_num) ) { + case sp_fpseu : + line= a_lnp->ad.ad_ln.ln_first ; + size += a_lnp->ad.ad_ln.ln_extra ; + break ; + case sp_ilb1 : + a_lnp->ad.ad_lp->l_min -= p2 ; + break ; + } + size++ ; + if ( size>=p1 ) break ; + } + if ( ( size-= p1 )>0 ) { + if ( ctrunc(a_lnp->instr_num) !=sp_fpseu ) { + fatal("EXC inconsistency") ; + } + doinsert(a_lnp,line,a_lnp->ad.ad_ln.ln_extra-size) ; + a_lnp->ad.ad_ln.ln_first += size ; + a_lnp->ad.ad_ln.ln_extra = size-1 ; + size=0 ; + b_lnp=a_lnp->l_next ; + } else { + doinsert(a_lnp,line,-1) ; + b_lnp= a_lnp ; + } + while ( b_lnp ) { + b_lnp= b_lnp->l_next ; + line-- ; + switch ( ctrunc(b_lnp->instr_num) ) { + case sp_fpseu : + size += b_lnp->ad.ad_ln.ln_extra ; + line = b_lnp->ad.ad_ln.ln_first ; + break ; + case sp_ilb1 : + b_lnp->ad.ad_lp->l_min += p1 ; + break ; + } + size++ ; + if ( size>=p2 ) break ; + } + if ( ( size-= p2 )>0 ) { + if ( ctrunc(b_lnp->instr_num) !=sp_fpseu ) { + fatal("EXC inconsistency") ; + } + doinsert(b_lnp,line,b_lnp->ad.ad_ln.ln_extra-size) ; + b_lnp->ad.ad_ln.ln_first += size ; + b_lnp->ad.ad_ln.ln_extra = size-1 ; + } else { + doinsert(b_lnp,line,-1) ; + } + if ( !b_lnp ) { /* if a_lnp==0, so is b_lnp */ + fatal("Cannot perform exchange") ; + } + t_lnp = b_lnp->l_next ; + b_lnp->l_next = pstate.s_fline ; + pstate.s_fline= a_lnp->l_next ; + a_lnp->l_next=t_lnp ; +} + +doinsert(lnp,first,extra) line_t *lnp ; { + /* Beware : s_fline will be clobbered and restored */ + register line_t *t_lnp ; + + t_lnp= pstate.s_fline; + pstate.s_fline= lnp->l_next ; + newline(LINES) ; + pstate.s_fline->instr_num= sp_fpseu ; + pstate.s_fline->ad.ad_ln.ln_first= first ; + pstate.s_fline->ad.ad_ln.ln_extra= extra ; + lnp->l_next= pstate.s_fline ; + pstate.s_fline= t_lnp; /* restore */ +} + +putval() { + switch(valtype){ + case sp_cst2: + extconst(argval); + return ; + case sp_ilb1: + extloc(loclookup(tabval,OCCURRING)); + return ; + case sp_dnam: + extglob(glo2lookup(string,OCCURRING),(cons_t)0); + return ; + case sp_doff: + extglob(glo2lookup(string,OCCURRING),argval); + return ; + case sp_pnam: + extpro(prolookup(string,PRO_OCC)); + return ; + case sp_scon: + extstring() ; + return ; + case sp_fcon: + extxcon(DATA_FCON) ; + return ; + case sp_icon: + extvcon(DATA_ICON) ; + return ; + case sp_ucon: + extvcon(DATA_UCON) ; + return ; + default: + fatal("putval notreached") ; + /* NOTREACHED */ + } +} + +chkstart() { + static int absout = 0 ; + + if ( absout ) return ; + if ( !oksizes ) fatal("missing size specification") ; + setmode(DATA_CONST) ; + extconst((cons_t)0) ; + setmode(DATA_REP) ; + extadr( (cons_t) (ABSSIZE/wordsize-1) ) ; + absout++ ; + databytes = ABSSIZE ; + memtype= HOLBSS ; +} + +typealign(new) enum m_type new ; { + if ( memtype==new ) return ; + align(wordsize); + memtype=new ; +} + +sizealign(size) cons_t size ; { + align( size>wordsize ? wordsize : (int)size ) ; +} + +align(size) int size ; { + register unsigned gapsize ; + + for ( gapsize= databytes%size ; gapsize ; gapsize-- ) { + setmode(DATA_BYTES) ; + ext8(0) ; + databytes++ ; + } +} + +extconst(n) cons_t n ; { + setmode(DATA_CONST); + extword(n); +} + +extbss(n) cons_t n ; { + cons_t objsize,amount ; + + if ( n<=0 ) { + if ( n<0 ) werror("negative bss/hol size") ; + if ( table2()==sp_cend || table2()==sp_cend) { + werror("Unexpected end-of-line") ; + } + return ; + } + setmode(DATA_NUL) ; /* flush descriptor */ + objsize= valsize(); + if ( objsize==0 ) { + werror("Unexpected end-of-line"); + return; + } + if ( n%objsize != 0 ) error("BSS/HOL incompatible sizes"); + putval(); + amount= n/objsize ; + if ( amount>1 ) { + setmode(DATA_REP); + extadr(amount-1) ; + } + databytes +=n ; + getarg(sp_cst2); + if ( argval<0 || argval>1 ) error("illegal last argument") ; +} + +extloc(lbp) register locl_t *lbp; { + + /* + * assemble a pointer constant from a local label. + * For example con *1 + */ + setmode(DATA_IPTR); + data_reloc( chp_cast lbp,dataoff,RELLOC); + extadr((cons_t)0); +} + +extglob(agbp,off) glob_t *agbp; cons_t off; { + register glob_t *gbp; + + /* + * generate a word of data that is defined by a global symbol. + * Various relocation has to be prepared here in some cases + */ + gbp=agbp; + setmode(DATA_DPTR); + if ( gbp->g_status&DEF ) { + extadr(gbp->g_val.g_addr+off); + } else { + data_reloc( chp_cast gbp,dataoff,RELGLO); + extadr(off); + } +} + +extpro(aprp) proc_t *aprp; { + /* + * generate a addres that is defined by a procedure descriptor. + */ + consiz= ptrsize ; setmode(DATA_UCON); + extarb((int)ptrsize,(long)(aprp->p_num)); +} + +extstring() { + register char *s; + register n ; + + /* + * generate data for a string. + */ + for(n=strlngth,s=string ; n--; ) { + setmode(DATA_BYTES) ; + ext8(*s++); + } + return ; +} + +extxcon(header) { + register char *s ; + register n; + + /* + * generate data for a floating constant initialized by a string. + */ + + setmode(header); + s = string ; + for (n=strlngth ; n-- ;) { + if ( *s==0 ) error("Zero byte in initializer") ; + ext8(*s++); + } + ext8(0); + return ; +} + +extvcon(header) { + extern long atol() ; + /* + * generate data for a constant initialized by a string. + */ + + setmode(header); + if ( consiz>4 ) { + error("Size of initializer exceeds loader capability") ; + } + extarb((int)consiz,atol(string)) ; + return ; +} diff --git a/util/ass/asscm.c b/util/ass/asscm.c new file mode 100644 index 000000000..db91b1335 --- /dev/null +++ b/util/ass/asscm.c @@ -0,0 +1,137 @@ +/* + * (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 + * + */ + +/* Core management for the EM assembler. + two routines: + getarea(size) + returns a pointer to a free area of 'size' bytes. + freearea(ptr,size) + free's the area of 'size' bytes pointed to by ptr + + Free blocks are linked together and kept sorted. + Adjacent free blocks are collapsed. + Free blocks with a size smaller then the administration cannot + exist. + The algorithm is first fit. +*/ + +#include "ass00.h" + +#ifdef MEMUSE +static unsigned m_used = 0 ; +static unsigned m_free = 0 ; +#endif + +struct freeblock { + struct freeblock *f_next ; + unsigned f_size ; +} ; + +static struct freeblock freexx[2] = { + { freexx, 0 }, + { freexx+1, 0 } +} ; + +#define freehead freexx[1] + +#define CHUNK 2048 /* Smallest chunk to be gotten from UNIX */ + +area_t getarea(size) unsigned size ; { + register struct freeblock *c_ptr,*l_ptr ; + register char *ptr ; + unsigned rqsize ; + char *malloc() ; + +#ifdef MEMUSE + m_used += size ; + m_free -= size ; +#endif + for(;;) { + for ( l_ptr= &freehead, c_ptr= freehead.f_next ; + c_ptr!= &freehead ; c_ptr = c_ptr->f_next ) { + if ( size==c_ptr->f_size ) { + l_ptr->f_next= c_ptr->f_next ; + return (area_t) c_ptr ; + } + if ( size+sizeof freehead <= c_ptr->f_size ) { + c_ptr->f_size -= size ; + return (area_t) ((char *) c_ptr + c_ptr->f_size) ; + } + l_ptr = c_ptr ; + } + rqsize = sizef_next ) { + if ( (area_t)c_ptr>ptr ) break ; + l_ptr= c_ptr ; + } + /* now insert between l_ptr and c_ptr */ + /* Beware they may both point to freehead */ + +#ifdef MEMUSE + if ( ((char *)l_ptr)+l_ptr->f_size> (char *)ptr && l_ptr<=ptr ) + fatal("Double freed") ; + if ( ((char *)ptr)+size > (char *)c_ptr && ptr<=c_ptr ) + fatal("Frreed double") ; +#endif + /* Is the block before this one adjacent ? */ + if ( ((char *)l_ptr) + l_ptr->f_size == (char *) ptr ) { + l_ptr->f_size += size ; /* yes */ + } else { + /* No, create an entry */ + ((struct freeblock *)ptr)->f_next = c_ptr ; + ((struct freeblock *)ptr)->f_size = size ; + l_ptr->f_next = (struct freeblock *)ptr ; + l_ptr = (struct freeblock *)ptr ; + } + /* Are the two entries adjacent ? */ + if ( (char *)l_ptr + l_ptr->f_size == (char *) c_ptr ) { + /* the two entries are adjacent */ + l_ptr->f_next = c_ptr->f_next ; + l_ptr->f_size += c_ptr->f_size ; + } +} + +#ifdef MEMUSE +memuse() { + printf("Free %7u, Used %7u, Total %7u\n",m_free,m_used,m_free+m_used); +} +#endif diff --git a/util/ass/assda.c b/util/ass/assda.c new file mode 100644 index 000000000..b15d11083 --- /dev/null +++ b/util/ass/assda.c @@ -0,0 +1,125 @@ +#include "ass00.h" +#include "assex.h" +/* + * global data + */ + +int wordsize ; +int ptrsize ; +cons_t maxadr ; +cons_t maxint; +cons_t maxdint; +cons_t maxunsig; +cons_t maxdunsig; + +/* + The structure containing used for procedure environment stacking +*/ +stat_t pstate ; + +/* + * pointers to not yet allocated storage + */ +glob_t *mglobs; /* pointer to module symbols */ +glob_t *xglobs; /* pointer to extern symbols */ +proc_t *mprocs; /* pointer to local procs */ +proc_t *xprocs; /* pointer to external procs */ +ptab_t *proctab; /* pointer to proctab[] */ + +/* + * some array and structures of known size + */ +FILE *ifile; /* input file buffer */ +FILE *tfile; /* code file buffer */ +FILE *dfile; /* data file buffer */ +FILE *rtfile; /* code file buffer */ +FILE *rdfile; /* data file buffer */ +char string[MAXSTRING]; + +/* + * some other pointers + */ +glob_t *lastglosym; /* last global symbol */ +glob_t *curglosym; /* current global symbol */ +relc_t *f_data = (relc_t *)0 ; /* first data reloc pointer */ +relc_t *l_data = (relc_t *)0 ; /* last data reloc pointer */ +relc_t *f_text = (relc_t *)0 ; /* first text reloc pointer */ +relc_t *l_text = (relc_t *)0 ; /* last text reloc pointer */ + +/* + * some indices + */ +int strlngth; /* index in string[] */ +FOFFSET inpoff; /* offset in current input file */ +FOFFSET libeof; /* ceiling for above number */ + +/* + * some other counters + */ +int procnum; /* generic for unique proc-descr. */ +cons_t prog_size; /* length of current proc */ +int max_bytes; +int pass; +int line_num; /* line number for error messages */ +int nerrors; /* number of nonfatal errors */ +cons_t consiz; /* size of U,I or F value */ +cons_t textbytes; /* size of code file */ +cons_t databytes; /* highwater mark in data */ +FOFFSET dataoff; /* size of data file */ +FOFFSET textoff; /* size of text file */ +FOFFSET lastoff; /* previous size before last block */ +int datamode; /* what kind of data */ +int datablocks; /* number of datablocks written out */ +relc_t *lastheader; /* pointer into datareloc */ +cons_t holbase; +cons_t holsize; +int unresolved; /* # of unresolved references */ +int sourcelines; /* number of lines in source program*/ +int intflags = 1; /* flags for interpreter */ +/* + * some flags + */ +int archmode; /* reading library ? */ +int procflag; /* print "namelist" of procedures */ +#ifdef DUMP +int c_flag; /* print unused opcodes */ +char opcnt1[256]; /* count primary opcodes */ +char opcnt2[256]; /* count secondary opcodes */ +char opcnt3[256]; /* count long opcodes */ +#endif +int d_flag = 0; /* don't dump */ +int r_flag = 0; /* don't dump relocation tables */ +#ifdef JOHAN +int jflag; +#endif +int wflag = 0; /* don't issue warning messages */ +int eof_seen; +int mod_sizes; /* Size info in current module ok? */ + +#define BASE (sizeof (struct lines) - sizeof (addr_u)) + +char linesize[VALLOW+1] = { + BASE, /* MISSING */ + BASE + sizeof (cons_t), /* CONST */ + BASE + sizeof prp_cast, /* PROCNAME */ + BASE + sizeof gbp_cast, /* GLOSYM */ + BASE + sizeof lbp_cast, /* LOCSYM */ + BASE + sizeof (struct sad_df), /* GLOOFF */ + BASE + sizeof (struct sad_ln), /* LINES */ + BASE /* VALLOW */ +} ; + +/* + * miscellaneous + */ +char *progname; /* argv[0] */ +char *curfile = 0; /* name of current file */ +char *eout = "e.out"; +arch_t archhdr; +size_t sizes[NDEFAULT] = { +/* mlab, glab,mproc,xproc, proc */ + { 151, 29, 31, 73, 130 }, + { 307, 127, 151, 401, 460 }, + { 601, 251, 151, 401, 600 } +}; +size_t *oursize = &sizes[1] ; /* point to selected sizes */ diff --git a/util/ass/assex.h b/util/ass/assex.h new file mode 100644 index 000000000..00612d91c --- /dev/null +++ b/util/ass/assex.h @@ -0,0 +1,158 @@ +/* + * global data + */ + +extern int wordsize; +extern int ptrsize; +extern cons_t maxadr; +extern cons_t maxint; +extern cons_t maxdint; +extern cons_t maxunsig; +extern cons_t maxdunsig; + +/* + * tables loaded from em_libraries + */ +extern char em_flag[]; + +/* + The structure containing used for procedure environment stacking + */ +extern stat_t pstate ; + +/* + * pointers to not yet allocated storage + */ +extern glob_t *mglobs; +extern glob_t *xglobs; +extern proc_t *mprocs; +extern proc_t *xprocs; +extern ptab_t *proctab; + +extern FILE *ifile; +extern FILE *tfile; +extern FILE *dfile; +extern FILE *rtfile; +extern FILE *rdfile; +extern char string[]; + +/* + * some other pointers + */ +extern glob_t *lastglosym; +extern glob_t *curglosym; +extern size_t *oursize; +extern relc_t *f_data; +extern relc_t *l_data; +extern relc_t *f_text; +extern relc_t *l_text; + +/* + * some indices + */ +extern int strlngth; +extern FOFFSET inpoff; +extern FOFFSET libeof; + +/* + * some other counters + */ +extern int procnum; +extern cons_t prog_size; +extern int max_bytes; +extern int pass; +extern int line_num; +extern int nerrors; +extern cons_t textbytes; +extern cons_t databytes; +extern FOFFSET dataoff; +extern FOFFSET textoff; +extern FOFFSET lastoff; +extern int datamode; +extern int datablocks; +extern relc_t *lastheader; +extern cons_t holbase; +extern cons_t holsize; +extern int unresolved; +extern int sourcelines; +extern int intflags; +/* + * some flags + */ +extern int archmode; +extern int procflag; +#ifdef DUMP +extern int c_flag; +extern char opcnt1[]; +extern char opcnt2[]; +extern char opcnt3[]; +#endif +extern int d_flag; +extern int r_flag; +#ifdef JOHAN +extern int jflag; +#endif +extern int wflag; +extern int eof_seen; +extern int mod_sizes; +/* + * miscellaneous + */ +extern cons_t consiz; +extern char *progname; +extern char *curfile; +extern char *eout; +extern arch_t archhdr; +extern size_t sizes[]; + +extern char linesize[]; + +/* + * from asstb.c + */ + +extern char *opindex[] ; +extern char opchoice[] ; +extern int maxinsl ; + +/* + * types of value returning routines + */ +#ifndef CPM +extern int tmpfil(); +extern FILE *frewind(); +#endif +extern int xgetc(); +extern unsigned get8(); +extern int get16(); +extern cons_t get32(); +extern cons_t xgeta(); +extern cons_t parval(); +extern cons_t valsize(); +extern cons_t xgetarb(); +extern char *findnop(); +extern char *findfit(); +extern glob_t *glolookup(); +extern glob_t *glo2lookup(); +extern glob_t *xglolookup(); +extern locl_t *loclookup(); +extern proc_t *prolookup(); +extern proc_t *enterproc(); +extern proc_t *searchproc(); +extern relc_t *text_reloc(); +extern relc_t *data_reloc(); +extern area_t getarea(); + +/* + * all used library routines + */ +extern char *malloc(); +extern int open(); +extern int creat(); +extern int getpid(); +extern int unlink(); +extern int close(); +extern int strcmp(); +extern char *strcpy(); + +#define void int diff --git a/util/ass/assrl.c b/util/ass/assrl.c new file mode 100644 index 000000000..5ec0f0c62 --- /dev/null +++ b/util/ass/assrl.c @@ -0,0 +1,298 @@ +/* + * (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 + * + */ + +#include "ass00.h" +#include "assex.h" + +#define COPYFINAL 1 +#define COPYTEMP 0 + +/* + * collection of routines to deal with relocation business + */ + +void dataprocess(); +void textprocess(); +relc_t * +text_reloc(glosym,off,typ) glob_t *glosym; FOFFSET off ; int typ ; { + + /* + * prepare the relocation that has to be done at text-offset off + * according to global symbol glosym. + * NOTE: The pointer glosym will point into mglobs[], while at + * the time copyout() is called all the symbols here + * will have disappeared. + * The procedure upd_reloc() will change this pointer + * into the one in xglobs[] later. + */ + + register relc_t *nxtextreloc ; + + nxtextreloc= rlp_cast getarea(sizeof *nxtextreloc) ; + if ( !f_text ) { + f_text= nxtextreloc ; + } else { + l_text->r_next= nxtextreloc ; + } + nxtextreloc->r_next= rlp_cast 0 ; + l_text= nxtextreloc ; + nxtextreloc->r_off = off; + nxtextreloc->r_val.rel_gp = glosym; + nxtextreloc->r_typ = typ; /* flags of instruction */ + return(nxtextreloc); +} + +relc_t * +data_reloc(arg,off,typ) char *arg ; FOFFSET off ; int typ ; { + + /* + * Same as above. + */ + + register relc_t *nxdatareloc ; + + nxdatareloc= rlp_cast getarea(sizeof *nxdatareloc) ; + if ( !f_data ) { + f_data= nxdatareloc ; + } else { + l_data->r_next= nxdatareloc ; + } + nxdatareloc->r_next= rlp_cast 0 ; + l_data= nxdatareloc ; + nxdatareloc->r_off = off; + nxdatareloc->r_val.rel_lp = lbp_cast arg; + nxdatareloc->r_typ = typ; + return(nxdatareloc); +} + +copyout() { + register i; + int remtext ; + + /* + * Make the e.out file that looks as follows: + * + * __________________________ + * | MAGIC | \ + * | FLAGS | \ + * | UNRESOLVED | \ + * | VERSION | | 8*(2-byte word) header + * | WORDSIZE | | for interpreter selection + * | PTRSIZE | / + * | | / + * | | / + * | NTEXT | \ + * | NDATA | \ + * | NPROC | \ + * | ENTRY-POINT | | 8*(wordsize-word) header + * | NLINES | | for interpreter proper + * | | / + * | | / + * | | / + * |________________________| + * | | + * | TEXT | zero filled + * | | if not word multiple + * |________________________| + * | | + * | DATA | + * | | + * |________________________| + * | | + * | PROCTABLE | + * | | + * |________________________| + * + * + */ + + remtext = textbytes%wordsize ; + if ( remtext != 0 ) remtext = wordsize-remtext ; + + if ((ifile = fopen(eout,"w")) == NULL ) + fatal("can't create e.out"); +#ifdef CPM + fclose(tfile); tfile=fopen("TFILE.$$$, "r"); + fclose(dfile); dfile=fopen("DFILE.$$$, "r"); +#else + tfile=frewind(tfile); + dfile=frewind(dfile); +#endif + xput16(as_magic,ifile); + xput16(intflags,ifile); + xput16(unresolved,ifile); + xput16(VERSION,ifile); + xput16(wordsize,ifile); + xput16(ptrsize,ifile); + xput16(0,ifile); + xput16(0,ifile); + xputa(textbytes+remtext ,ifile); + xputa((cons_t)datablocks,ifile); + xputa((cons_t)procnum,ifile); + xputa((cons_t)searchproc(MAIN,xprocs,oursize->n_xproc)->p_num, + ifile); + xputa((cons_t)sourcelines,ifile); + xputa((cons_t)databytes,ifile); + xputa((cons_t)0,ifile); + xputa((cons_t)0,ifile); + + textprocess(tfile,ifile); + while ( remtext-- ) xputc(0,ifile) ; + + dataprocess(dfile,ifile); + for (i=0;ig_status&DEF) { + xputa(xgeta(f1)+ + datareloc.r_val.rel_gp->g_val.g_addr, + f2); + i+= ptrsize-1 ; + break ; + } + if ( unresolved == 0 ) + fatal("Definition botch") ; + case RELHEAD: + xputc((int)(xgetc(f1)+datareloc.r_val.rel_i), + f2); + break; + default: + fatal("Bad r_typ in dataprocess"); + } + ieof=getblk(rdfile,(char *)(&datareloc.r_off), + sizeof datareloc - sizeof datareloc.r_next) ; + } else + xputc(xgetc(f1),f2); + } + for ( ; ig_status&DEF) { + n=textreloc.r_val.rel_gp->g_val.g_addr; + } else { + if ( unresolved==0 ) + fatal("Definition botch") ; + xputc(xgetc(f1),f2) ; + ieof=getblk(rtfile,(char *)(&textreloc.r_off), + sizeof textreloc-sizeof textreloc.r_next); + continue ; + } + } + op_curr = &opchoice[textreloc.r_typ& ~RELMNS] ; + insl = oplength(*op_curr) ; + genop(op_curr, n+xgetarb(insl,f1), PAR_G); + i += insl-1 ; + ieof=getblk(rtfile,(char *)(&textreloc.r_off), + sizeof textreloc - sizeof textreloc.r_next) ; + } else { + xputc(xgetc(f1),f2) ; + } + } + for ( ; ir_val.rel_gp ; + if( gbp->g_status&DEF ) { + p->r_typ |= RELMNS; + p->r_val.rel_i = gbp->g_val.g_addr; + } else + p->r_val.rel_gp = gbp->g_val.g_gp; + putblk(rtfile,(char *)(&(p->r_off)),sizeof *p - sizeof p) ; + f_text= p->r_next ; freearea( (area_t) p , sizeof *p ) ; + } + + while( p= f_data ) { + if (p->r_typ == RELGLO) { + gbp= p->r_val.rel_gp ; + if(gbp->g_status&DEF) { + p->r_typ = RELADR; + p->r_val.rel_i = gbp->g_val.g_addr; + } else + p->r_val.rel_gp = gbp->g_val.g_gp; + } + putblk(rdfile,(char *)(&(p->r_off)),sizeof *p - sizeof p) ; + f_data= p->r_next ; freearea( (area_t) p , sizeof *p ) ; + } + l_data= rlp_cast 0 ; +} diff --git a/util/ass/ip_spec.h b/util/ass/ip_spec.h new file mode 100644 index 000000000..cf39b9f63 --- /dev/null +++ b/util/ass/ip_spec.h @@ -0,0 +1,33 @@ +/* Contents of flags used when describing interpreter opcodes */ + +#define OPTYPE 07 /* type field in flag */ + +#define OPMINI 0 /* m MINI */ +#define OPSHORT 1 /* s SHORT */ +#define OPNO 2 /* - No operand */ +#define OP8 3 /* 1 1-byte signed operand */ +#define OP16 4 /* 2 2-byte signed operand */ +#define OP32 5 /* 4 4-byte signed operand */ +#define OP64 6 /* 8 8-byte signed operand */ + +#define OPESC 010 /* e escaped opcode */ +#define OPWORD 020 /* w operand is word multiple */ +#define OPNZ 040 /* o operand starts at 1 ( or wordsize if w-flag) */ + +#define OPRANGE 0300 /* Range of operands: Positive, negative, both */ + +#define OP_BOTH 0000 /* the default */ +#define OP_POS 0100 /* p Positive (>=0) operands only */ +#define OP_NEG 0200 /* n Negative (<0) operands only */ + +struct opform { + char i_opcode ; /* the opcode number */ + char i_flag ; /* the flag byte */ + char i_low ; /* the interpreter first opcode */ + char i_num ; /* the number of shorts/minis (optional) */ +}; + +/* Escape indicators */ + +#define ESC 254 /* To escape group */ +#define ESC_L 255 /* To 32 and 64 bit operands */ diff --git a/util/ass/maktab.c b/util/ass/maktab.c new file mode 100644 index 000000000..9fa57e32a --- /dev/null +++ b/util/ass/maktab.c @@ -0,0 +1,475 @@ +/* + * (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 + * + */ + +#include "ip_spec.h" +#include +#include "../../h/em_spec.h" +#include "../../h/em_flag.h" + +/* This program reads the human readable interpreter specification + and produces a efficient machine representation that can be + translated by a C-compiler. +*/ + +#define NOTAB 600 /* The max no of interpreter specs */ +#define ESCAP 256 + +struct opform intable[NOTAB] ; +struct opform *lastform = intable-1 ; + +int nerror = 0 ; +int atend = 0 ; +int line = 1 ; +int maxinsl= 0 ; + +extern char em_mnem[][4] ; +char esca[] = "escape" ; +#define ename(no) ((no)==ESCAP?esca:em_mnem[(no)]) + +extern char em_flag[] ; + +main(argc,argv) char **argv ; { + if ( argc>1 ) { + if ( freopen(argv[1],"r",stdin)==NULL) { + fatal("Cannot open %s",argv[1]) ; + } + } + if ( argc>2 ) { + if ( freopen(argv[2],"w",stdout)==NULL) { + fatal("Cannot create %s",argv[2]) ; + } + } + if ( argc>3 ) { + fatal("%s [ file [ file ] ]",argv[0]) ; + } + atend=0 ; + readin(); + atend=1 ; + checkall(); + if ( nerror==0 ) { + writeout(); + } + return nerror ; +} + +readin() { + register struct opform *nextform ; + char *ident(); + char *firstid ; + register maxl ; + + maxl = 0 ; + for ( nextform=intable ; + !feof(stdin) && nextform<&intable[NOTAB] ; ) { + firstid=ident() ; + if ( *firstid=='\n' || feof(stdin) ) continue ; + lastform=nextform ; + nextform->i_opcode = getmnem(firstid) ; + nextform->i_flag = decflag(ident()) ; + switch ( nextform->i_flag&OPTYPE ) { + case OPMINI: + case OPSHORT: + nextform->i_num = atoi(ident()) ; + break ; + } + nextform->i_low = atoi(ident()) ; + if ( *ident()!='\n' ) { + int c ; + error("End of line expected"); + while ( (c=readchar())!='\n' && c!=EOF ) ; + } + if ( oplength(nextform)>maxl ) maxl=oplength(nextform) ; + nextform++ ; + } + if ( !feof(stdin) ) fatal("Internal table too small") ; + maxinsl = maxl ; +} + +char *ident() { + /* skip spaces and tabs, anything up to space,tab or eof is + a identifier. + Anything from # to end-of-line is an end-of-line. + End-of-line is an identifier all by itself. + */ + + static char array[200] ; + register int c ; + register char *cc ; + + do { + c=readchar() ; + } while ( c==' ' || c=='\t' ) ; + for ( cc=array ; cc<&array[(sizeof array) - 1] ; cc++ ) { + if ( c=='#' ) { + do { + c=readchar(); + } while ( c!='\n' && c!=EOF ) ; + } + *cc = c ; + if ( c=='\n' && cc==array ) break ; + c=readchar() ; + if ( c=='\n' ) { + pushback(c) ; + break ; + } + if ( c==' ' || c=='\t' || c==EOF ) break ; + } + *++cc=0 ; + return array ; +} + +int getmnem(str) char *str ; { + char (*ptr)[4] ; + + for ( ptr = em_mnem ; *ptr<= &em_mnem[sp_lmnem-sp_fmnem][0] ; ptr++ ) { + if ( strcmp(*ptr,str)==0 ) return (ptr-em_mnem) ; + } + error("Illegal mnemonic") ; + return 0 ; +} + +error(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; { + if ( !atend ) fprintf(stderr,"line %d: ",line) ; + fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ; + fprintf(stderr,"\n"); + nerror++ ; +} + +mess(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; { + if ( !atend ) fprintf(stderr,"line %d: ",line) ; + fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ; + fprintf(stderr,"\n"); +} + +fatal(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; { + error(str,a1,a2,a3,a4,a5,a6) ; + exit(1) ; +} + +#define ILLGL -1 + +check(val) int val ; { + if ( val!=ILLGL ) error("Illegal flag combination") ; +} + +int decflag(str) char *str ; { + int type ; + int escape ; + int range ; + int wordm ; + int notzero ; + + type=escape=range=wordm=notzero= ILLGL ; + while ( *str ) switch ( *str++ ) { + case 'm' : + check(type) ; type=OPMINI ; break ; + case 's' : + check(type) ; type=OPSHORT ; break ; + case '-' : + check(type) ; type=OPNO ; break ; + case '1' : + check(type) ; type=OP8 ; break ; + case '2' : + check(type) ; type=OP16 ; break ; + case '4' : + check(type) ; type=OP32 ; break ; + case '8' : + check(type) ; type=OP64 ; break ; + case 'e' : + check(escape) ; escape=0 ; break ; + case 'N' : + check(range) ; range= 2 ; break ; + case 'P' : + check(range) ; range= 1 ; break ; + case 'w' : + check(wordm) ; wordm=0 ; break ; + case 'o' : + check(notzero) ; notzero=0 ; break ; + default : + error("Unknown flag") ; + } + if ( type==ILLGL ) error("Type must be specified") ; + switch ( type ) { + case OP64 : + case OP32 : + if ( escape!=ILLGL ) error("Conflicting escapes") ; + escape=ILLGL ; + case OP16 : + case OP8 : + case OPSHORT : + case OPNO : + if ( notzero!=ILLGL ) mess("Improbable OPNZ") ; + if ( type==OPNO && range!=ILLGL ) { + mess("No operand in range") ; + } + } + if ( escape!=ILLGL ) type|=OPESC ; + if ( wordm!=ILLGL ) type|=OPWORD ; + switch ( range) { + case ILLGL : type|=OP_BOTH ; break ; + case 1 : type|=OP_POS ; break ; + case 2 : type|=OP_NEG ; break ; + } + if ( notzero!=ILLGL ) type|=OPNZ ; + return type ; +} + +writeout() { + register struct opform *next ; + int elem[sp_lmnem-sp_fmnem+1+1] ; + /* for each op points to first of descr. */ + register int i,currop ; + int nch ; + int compare() ; + + qsort(intable,(lastform-intable)+1,sizeof intable[0],compare) ; + + printf("int\tmaxinsl\t= %d ;\n",maxinsl) ; + currop= -1 ; nch=0 ; + printf("char opchoice[] = {\n") ; + for (next=intable ; next<=lastform ; next++ ) { + if ( (next->i_opcode&0377)!=currop ) { + for ( currop++ ; + currop<(next->i_opcode&0377) ; currop++ ) { + elem[currop]= nch ; + error("Missing opcode %s",em_mnem[currop]) ; + } + elem[currop]= nch ; + } + printf("%d, %d,",next->i_flag&0377,next->i_low&0377) ; + nch+=2 ; + switch ( next->i_flag&OPTYPE ) { + case OPMINI : + case OPSHORT : + printf("%d,",next->i_num&0377) ; nch++ ; + } + printf("\n") ; + } + for ( currop++ ; currop<=sp_lmnem-sp_fmnem ; currop++ ) { + elem[currop]= nch ; + error("Missing opcode %s",em_mnem[currop]) ; + } + elem[sp_lmnem-sp_fmnem+1]=nch ; + printf("0 } ;\n\nchar *opindex[] = {\n"); + for ( i=0 ; i<=sp_lmnem-sp_fmnem+1 ; i++ ) { + printf(" &opchoice[%d],\n",elem[i]) ; + } + printf("} ;\n") ; +} + +int compare(a,b) struct opform *a,*b ; { + if ( a->i_opcode!=b->i_opcode ) { + return (a->i_opcode&0377)-(b->i_opcode&0377) ; + } + return oplength(a)-oplength(b) ; +} + +int oplength(a) struct opform *a ; { + int cnt ; + + cnt=1 ; + if ( a->i_flag&OPESC ) cnt++ ; + switch( a->i_flag&OPTYPE ) { + case OPNO : + case OPMINI : break ; + case OP8 : + case OPSHORT : cnt++ ; break ; + case OP16 : cnt+=2 ; break ; + case OP32 : cnt+=5 ; break ; + case OP64 : cnt+=9 ; break ; + } + return cnt ; +} + +/* ----------- checking --------------*/ + +int ecodes[256],codes[256],lcodes[256] ; + +#define NMNEM (sp_lmnem-sp_fmnem+1) +#define MUST 1 +#define MAY 2 +#define FORB 3 + +char negc[NMNEM], zc[NMNEM], posc[NMNEM] ; + +checkall() { + register i,flag ; + register struct opform *next ; + int opc,low ; + + for ( i=0 ; ii_flag&0377 ; + opc = next->i_opcode&0377 ; + low = next->i_low&0377 ; + chkc(flag,low,opc) ; + switch(flag&OPTYPE) { + case OPNO : zc[opc]++ ; break ; + case OPMINI : + case OPSHORT : + for ( i=1 ; i<((next->i_num)&0377) ; i++ ) { + chkc(flag,low+i,opc) ; + } + if ( !(em_flag[opc]&PAR_G) && + (flag&OPRANGE)==OP_BOTH) { + mess("Mini's and shorties should have P or N"); + } + break ; + case OP8 : + error("OP8 is removed") ; + break ; + case OP16 : + if ( flag&OP_NEG ) + negc[opc]++ ; + else if ( flag&OP_POS ) + posc[opc]++ ; + break ; + case OP32 : + case OP64 : + break ; + default : + error("Illegal type") ; + break ; + } + } + atend=1 ; + for ( i=0 ; i<256 ; i++ ) if ( codes[i]== -1 ) { + mess("interpreter opcode %d not used",i) ; + } + for ( opc=0 ; opc1 ) mess("More then one OPNO for %s",ename(emc)) ; + if ( posc[emc]>1 ) mess("More then one OP16(pos) for %s",ename(emc)) ; + if ( negc[emc]>1 ) mess("More then one OP16(neg) for %s",ename(emc)) ; + switch(zf) { + case MUST: + if ( zc[emc]==0 ) mess("No OPNO for %s",ename(emc)) ; + break ; + case FORB: + if ( zc[emc]==1 ) mess("Forbidden OPNO for %s",ename(emc)) ; + break ; + } + switch(pf) { + case MUST: + if ( posc[emc]==0 ) mess("No OP16(pos) for %s",ename(emc)) ; + break ; + case FORB: + if ( posc[emc]==1 ) + mess("Forbidden OP16(pos) for %s",ename(emc)) ; + break ; + } + switch(nf) { + case MUST: + if ( negc[emc]==0 ) mess("No OP16(neg) for %s",ename(emc)) ; + break ; + case FORB: + if ( negc[emc]==1 ) + mess("Forbidden OP16(neg) for %s",ename(emc)) ; + break ; + } +} + +static int pushchar ; +static int pushf ; + +int readchar() { + int c ; + + if ( pushf ) { + pushf=0 ; + c = pushchar ; + } else { + if ( feof(stdin) ) return EOF ; + c=getc(stdin) ; + } + if ( c=='\n' ) line++ ; + return c ; +} + +pushback(c) { + if ( pushf ) { + fatal("Double pushback") ; + } + pushf++ ; + pushchar=c ; + if ( c=='\n' ) line-- ; +}