Initial revision
This commit is contained in:
parent
61c04182b8
commit
166bccd1b5
298
etc/ip_spec.t
Normal file
298
etc/ip_spec.t
Normal file
|
@ -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
|
77
util/ass/Makefile
Normal file
77
util/ass/Makefile
Normal file
|
@ -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)
|
371
util/ass/ass30.c
Normal file
371
util/ass/ass30.c
Normal file
|
@ -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<endc ; currc++ ) {
|
||||
opc = currc ;
|
||||
flags=ctrunc(*currc++) ;
|
||||
switch ( flags&OPTYPE ) {
|
||||
case OPNO :
|
||||
continue ;
|
||||
case OPMINI :
|
||||
case OPSHORT :
|
||||
number=ctrunc(*++currc) ;
|
||||
}
|
||||
found = opfit(flags, number, val, em_flag[instr]&EM_PAR ) ;
|
||||
}
|
||||
if ( !found ) fatal("Cannot find interpreter opcode") ;
|
||||
return opc ;
|
||||
}
|
||||
|
||||
char *findnop(instr) int instr ; {
|
||||
register char *currc,*endc ;
|
||||
|
||||
endc = opindex[instr+1] ;
|
||||
for ( currc=opindex[instr] ; currc<endc ; currc++ ) {
|
||||
switch ( ctrunc(*currc)&OPTYPE ) {
|
||||
case OPNO :
|
||||
return currc ;
|
||||
case OPSHORT :
|
||||
case OPMINI :
|
||||
currc++ ;
|
||||
}
|
||||
currc++ ;
|
||||
}
|
||||
fatal("Cannot find interpreter opcode") ;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int opfit(flag,number,val,i_flag)
|
||||
int i_flag,flag,number ; cons_t val ; {
|
||||
/* Number is invalid if flag does not contain MINI or SHORT */
|
||||
switch ( flag&OPRANGE ) {
|
||||
case OP_POS :
|
||||
if ( val<0 ) return 0 ;
|
||||
break ;
|
||||
case OP_NEG :
|
||||
if ( val>=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<number ;
|
||||
case OPSHORT :
|
||||
if ( val<0 ) val = -1-val ;
|
||||
return val>=0 && val<number*256 ;
|
||||
case OP16 :
|
||||
if ( i_flag==PAR_G ) return 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 */
|
||||
}
|
||||
}
|
55
util/ass/ass40.c
Normal file
55
util/ass/ass40.c
Normal file
|
@ -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 ;
|
||||
}
|
||||
}
|
190
util/ass/ass50.c
Normal file
190
util/ass/ass50.c
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
211
util/ass/ass60.c
Normal file
211
util/ass/ass60.c
Normal file
|
@ -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->type1<VALLOW ? ln->type1 : 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 ; i<LOCLABSIZE ; lbhead++,i++) {
|
||||
if ( lbhead->l_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
|
341
util/ass/ass70.c
Normal file
341
util/ass/ass70.c
Normal file
|
@ -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);
|
||||
}
|
412
util/ass/ass80.c
Normal file
412
util/ass/ass80.c
Normal file
|
@ -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)))<<shift ;
|
||||
shift += 8 ;
|
||||
}
|
||||
return val ;
|
||||
}
|
||||
|
||||
ext8(b) {
|
||||
/*
|
||||
* Handle one byte of data.
|
||||
*/
|
||||
++dataoff;
|
||||
xputc(b,dfile);
|
||||
}
|
||||
|
||||
extword(w) cons_t w ; {
|
||||
/* Assemble the word constant w.
|
||||
* NOTE: The bytes are written low to high.
|
||||
*/
|
||||
register i ;
|
||||
for ( i=wordsize ; i-- ; ) {
|
||||
ext8( int_cast w) ;
|
||||
w >>= 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))<<shift ;
|
||||
shift += 8 ;
|
||||
}
|
||||
return val ;
|
||||
}
|
||||
|
||||
#define MAXBYTE 255
|
||||
|
||||
int icount(size) {
|
||||
int amount ;
|
||||
amount=(dataoff-lastoff)/size ;
|
||||
if ( amount>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
|
847
util/ass/assci.c
Normal file
847
util/ass/assci.c
Normal file
|
@ -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<wordsize ?
|
||||
wordsize%consiz!=0 : consiz%wordsize!=0 ) {
|
||||
fatal("illegal object size") ;
|
||||
}
|
||||
getstring();
|
||||
break;
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
int get16() {
|
||||
register int l_byte, h_byte;
|
||||
|
||||
l_byte = get8();
|
||||
h_byte = get8();
|
||||
if ( h_byte>=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 ;
|
||||
}
|
137
util/ass/asscm.c
Normal file
137
util/ass/asscm.c
Normal file
|
@ -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 = size<CHUNK ? CHUNK : size ;
|
||||
for(;;){
|
||||
ptr = malloc( rqsize ) ;
|
||||
if ( ptr ) break ; /* request succesfull */
|
||||
rqsize /= 2 ;
|
||||
rqsize -= rqsize%sizeof (short) ;
|
||||
if ( rqsize < sizeof freehead ) {
|
||||
fatal("Out of memory") ;
|
||||
}
|
||||
}
|
||||
freearea((area_t)ptr,rqsize) ;
|
||||
#ifdef MEMUSE
|
||||
m_used += rqsize ;
|
||||
#endif
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
freearea(ptr,size) register area_t ptr ; unsigned size ; {
|
||||
register struct freeblock *c_ptr, *l_ptr ;
|
||||
|
||||
#ifdef MEMUSE
|
||||
m_free += size ;
|
||||
m_used -= size ;
|
||||
#endif
|
||||
for ( l_ptr= &freehead, c_ptr=freehead.f_next ;
|
||||
c_ptr!= &freehead ; c_ptr= c_ptr->f_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
|
125
util/ass/assda.c
Normal file
125
util/ass/assda.c
Normal file
|
@ -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 */
|
158
util/ass/assex.h
Normal file
158
util/ass/assex.h
Normal file
|
@ -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
|
298
util/ass/assrl.c
Normal file
298
util/ass/assrl.c
Normal file
|
@ -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 | /
|
||||
* | <UNUSED> | /
|
||||
* | <UNUSED> | /
|
||||
* | NTEXT | \
|
||||
* | NDATA | \
|
||||
* | NPROC | \
|
||||
* | ENTRY-POINT | | 8*(wordsize-word) header
|
||||
* | NLINES | | for interpreter proper
|
||||
* | <UNUSED> | /
|
||||
* | <UNUSED> | /
|
||||
* | <UNUSED> | /
|
||||
* |________________________|
|
||||
* | |
|
||||
* | 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;i<procnum;i++) {
|
||||
xputarb(ptrsize,proctab[i].pr_loc,ifile);
|
||||
xputarb(ptrsize,proctab[i].pr_off,ifile);
|
||||
}
|
||||
if ( fclose(ifile)==EOF ) ;
|
||||
}
|
||||
|
||||
dataprocess(f1,f2) FILE *f1,*f2; {
|
||||
relc_t datareloc;
|
||||
FOFFSET i;
|
||||
register ieof ;
|
||||
|
||||
#ifdef CPM
|
||||
fclose(rdfile); rdfile=fopen("RDFILE.$$$, "r");
|
||||
#else
|
||||
rdfile=frewind(rdfile) ;
|
||||
#endif
|
||||
ieof=getblk(rdfile,(char *)(&datareloc.r_off),
|
||||
sizeof datareloc - sizeof datareloc.r_next) ;
|
||||
for (i=0 ; i<dataoff && !ieof ; i++) {
|
||||
if (i==datareloc.r_off) {
|
||||
switch(datareloc.r_typ) {
|
||||
case RELADR:
|
||||
xputa(xgeta(f1)+datareloc.r_val.rel_i,f2) ;
|
||||
i += ptrsize-1 ;
|
||||
break ;
|
||||
case RELGLO:
|
||||
if (datareloc.r_val.rel_gp->g_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 ( ; i<dataoff ; i++ ) xputc(xgetc(f1),f2) ;
|
||||
if ( !ieof && !getblk(rdfile,(char *)&datareloc,1) )
|
||||
fatal("data relocation botch") ;
|
||||
}
|
||||
|
||||
textprocess(f1,f2) FILE *f1,*f2; {
|
||||
relc_t textreloc;
|
||||
cons_t n;
|
||||
FOFFSET i;
|
||||
FILE *otfile ;
|
||||
int insl ; register int ieof ;
|
||||
char *op_curr ;
|
||||
register FOFFSET keep ;
|
||||
|
||||
#ifdef CPM
|
||||
fclose(rtfile); rtfile=fopen("RTFILE.$$$, "r");
|
||||
#else
|
||||
rtfile=frewind(rtfile) ;
|
||||
#endif
|
||||
keep = textoff ; textoff=0 ; otfile=tfile ; tfile=f2 ;
|
||||
/* This redirects the output of genop */
|
||||
ieof=getblk(rtfile,(char *)(&textreloc.r_off),
|
||||
sizeof textreloc - sizeof textreloc.r_next) ;
|
||||
for(i=0;i<keep && !ieof ;i++) {
|
||||
if( i == textreloc.r_off ) {
|
||||
if (textreloc.r_typ&RELMNS) {
|
||||
n=textreloc.r_val.rel_i;
|
||||
} else {
|
||||
if (textreloc.r_val.rel_gp->g_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 ( ; i<keep ; i++ ) xputc(xgetc(f1),f2) ;
|
||||
if ( !ieof && !getblk(rtfile,(char *)&textreloc,1) )
|
||||
fatal("text relocation botch") ;
|
||||
textoff = keep ;
|
||||
tfile = otfile ;
|
||||
}
|
||||
|
||||
upd_reloc() {
|
||||
register relc_t *p;
|
||||
register glob_t *gbp;
|
||||
|
||||
/*
|
||||
* Change reloc-tables such that for every pointer into mglobs
|
||||
* either the corresponding pointer into xglobs or its value
|
||||
* is substituted.
|
||||
*
|
||||
* Use is made of the known order of mglobs and xglobs
|
||||
* see also getcore()
|
||||
*/
|
||||
|
||||
while ( p= f_text ) {
|
||||
gbp= p->r_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 ;
|
||||
}
|
33
util/ass/ip_spec.h
Normal file
33
util/ass/ip_spec.h
Normal file
|
@ -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 */
|
475
util/ass/maktab.c
Normal file
475
util/ass/maktab.c
Normal file
|
@ -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 <stdio.h>
|
||||
#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 ; i<NMNEM ; i++ ) negc[i]=zc[i]=posc[i]=0 ;
|
||||
for ( i=0 ; i<256 ; i++ ) lcodes[i]= codes[i]= ecodes[i]= -1 ;
|
||||
codes[254]=codes[255]=ESCAP;
|
||||
|
||||
atend=0 ; line=0 ;
|
||||
for ( next=intable ; next<=lastform ; next++ ) {
|
||||
line++ ;
|
||||
flag = next->i_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 ; opc<NMNEM ; opc++ ) {
|
||||
switch(em_flag[opc]&EM_PAR) {
|
||||
case PAR_NO :
|
||||
ckop(opc,MUST,FORB,FORB) ;
|
||||
break ;
|
||||
case PAR_C:
|
||||
case PAR_D:
|
||||
case PAR_F:
|
||||
case PAR_B:
|
||||
ckop(opc,FORB,MAY,MAY) ;
|
||||
break ;
|
||||
case PAR_N:
|
||||
case PAR_G:
|
||||
case PAR_S:
|
||||
case PAR_Z:
|
||||
case PAR_O:
|
||||
case PAR_P:
|
||||
ckop(opc,FORB,MAY,FORB) ;
|
||||
break ;
|
||||
case PAR_R:
|
||||
ckop(opc,FORB,MAY,FORB) ;
|
||||
break ;
|
||||
case PAR_L:
|
||||
ckop(opc,FORB,MUST,MUST) ;
|
||||
break ;
|
||||
case PAR_W:
|
||||
ckop(opc,MUST,MAY,FORB) ;
|
||||
break ;
|
||||
default :
|
||||
error("Unknown instruction type of %s",ename(opc)) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chkc(flag,icode,emc) {
|
||||
if ( flag&OPESC ) {
|
||||
if ( ecodes[icode]!=-1 ) {
|
||||
mess("Escaped opcode %d used by %s and %s",
|
||||
icode,ename(emc),ename(ecodes[icode])) ;
|
||||
}
|
||||
ecodes[icode]=emc;
|
||||
} else switch ( flag&OPTYPE ) {
|
||||
default:
|
||||
if ( codes[icode]!=-1 ) {
|
||||
mess("Opcode %d used by %s and %s",
|
||||
icode,ename(emc),ename(codes[icode])) ;
|
||||
}
|
||||
codes[icode]=emc;
|
||||
break ;
|
||||
case OP32:
|
||||
case OP64:
|
||||
if ( lcodes[icode]!=-1 ) {
|
||||
mess("Long opcode %d used by %s and %s",
|
||||
icode,ename(emc),ename(codes[icode])) ;
|
||||
}
|
||||
lcodes[icode]=emc;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
ckop(emc,zf,pf,nf) {
|
||||
if ( zc[emc]>1 ) 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-- ;
|
||||
}
|
Loading…
Reference in a new issue