489 lines
16 KiB
Plaintext
489 lines
16 KiB
Plaintext
.BP
|
|
.AP "EM INTERPRETER"
|
|
.nf
|
|
.ta 8 16 24 32 40 48 56 64 72 80
|
|
.so em.i
|
|
.fi
|
|
.BP
|
|
.AP "EM CODE TABLES"
|
|
The following table is used by the assembler for EM machine
|
|
language.
|
|
It specifies the opcodes used for each instruction and
|
|
how arguments are mapped to machine language arguments.
|
|
The table is presented in three columns,
|
|
each line in each column contains three or four fields.
|
|
Each line describes a range of interpreter opcodes by
|
|
specifying for which instruction the range is used, the type of the
|
|
opcodes (mini, shortie, etc..) and range for the instruction
|
|
argument.
|
|
.A
|
|
The first field on each line gives the EM instruction mnemonic,
|
|
the second field gives some flags.
|
|
If the opcodes are minis or shorties the third field specifies
|
|
how many minis/shorties are used.
|
|
The last field gives the number of the (first) interpreter
|
|
opcode.
|
|
.N 1
|
|
Flags :
|
|
.IS 3
|
|
.N 1
|
|
Opcode type, only one of the following may be specified.
|
|
.PS - 5 " "
|
|
.PT -
|
|
opcode without argument
|
|
.PT m
|
|
mini
|
|
.PT s
|
|
shortie
|
|
.PT 2
|
|
opcode with 2-byte signed argument
|
|
.PT 4
|
|
opcode with 4-byte signed argument
|
|
.PT 8
|
|
opcode with 8-byte signed argument
|
|
.PE
|
|
Secondary (escaped) opcodes.
|
|
.PS - 5 " "
|
|
.PT e
|
|
The opcode thus marked is in the secondary opcode group instead
|
|
of the primary
|
|
.PE
|
|
restrictions on arguments
|
|
.PS - 5 " "
|
|
.PT N
|
|
Negative arguments only
|
|
.PT P
|
|
Positive and zero arguments only
|
|
.PE
|
|
mapping of arguments
|
|
.PS - 5 " "
|
|
.PT w
|
|
argument must be divisible by the wordsize and is divided by the
|
|
wordsize before use as opcode argument.
|
|
.PT o
|
|
argument ( possibly after division ) must be >= 1 and is
|
|
decremented before use as opcode argument
|
|
.PE
|
|
.IE
|
|
If the opcode type is 2,4 or 8 the resulting argument is used as
|
|
opcode argument (least significant byte first).
|
|
.N
|
|
If the opcode type is mini, the argument is added
|
|
to the first opcode - if in range - .
|
|
If the argument is negative, the absolute value minus one is
|
|
used in the algorithm above.
|
|
.N
|
|
For shorties with positive arguments the first opcode is used
|
|
for arguments in the range 0..255, the second for the range
|
|
256..511, etc..
|
|
For shorties with negative arguments the first opcode is used
|
|
for arguments in the range -1..-256, the second for the range
|
|
-257..-512, etc..
|
|
The byte following the opcode contains the least significant
|
|
byte of the argument.
|
|
First some examples of these specifications.
|
|
.PS - 5
|
|
.PT "aar mwPo 1 34"
|
|
Indicates that opcode 34 is used as a mini for Positive
|
|
instruction arguments only.
|
|
The w and o indicate division and decrementing of the
|
|
instruction argument.
|
|
Because the resulting argument must be zero ( only opcode 34 may be used
|
|
), this mini can only be used for instruction argument 2.
|
|
Conclusion: opcode 34 is for "AAR 2".
|
|
.PT "adp sP 1 41"
|
|
Opcode 41 is used as shortie for ADP with arguments in the range
|
|
0..255.
|
|
.PT "bra sN 2 60"
|
|
Opcode 60 is used as shortie for BRA with arguments -1..-256,
|
|
61 is used for arguments -257..-512.
|
|
.PT "zer e- 145"
|
|
Escaped opcode 145 is used for ZER.
|
|
.PE
|
|
The interpreter opcode table:
|
|
.N 1
|
|
.IS 3
|
|
.DS B
|
|
.so itables
|
|
.DE 0
|
|
.IE
|
|
.P
|
|
The table above results in the following dispatch tables.
|
|
Dispatch tables are used by interpreters to jump to the
|
|
routines implementing the EM instructions, indexed by the next opcode.
|
|
Each line of the dispatch tables gives the routine names
|
|
of eight consecutive opcodes, preceded by the first opcode number
|
|
on that line.
|
|
Routine names consist of an EM mnemonic followed by a suffix.
|
|
The suffices show the encoding used for each opcode.
|
|
.N
|
|
The following suffices exist:
|
|
.N 1
|
|
.VS 1 0
|
|
.IS 4
|
|
.PS - 11
|
|
.PT .z
|
|
no arguments
|
|
.PT .l
|
|
16-bit argument
|
|
.PT .lw
|
|
16-bit argument divided by the wordsize
|
|
.PT .p
|
|
positive 16-bit argument
|
|
.PT .pw
|
|
positive 16-bit argument divided by the wordsize
|
|
.PT .n
|
|
negative 16-bit argument
|
|
.PT .nw
|
|
negative 16-bit argument divided by the wordsize
|
|
.PT .s<num>
|
|
shortie with <num> as high order argument byte
|
|
.PT .sw<num>
|
|
shortie with argument divided by the wordsize
|
|
.PT .<num>
|
|
mini with <num> as argument
|
|
.PT .<num>W
|
|
mini with <num>*wordsize as argument
|
|
.PE 3
|
|
<num> is a possibly negative integer.
|
|
.VS 1 1
|
|
.IE
|
|
The dispatch table for the 256 primary opcodes:
|
|
.DS B
|
|
0 loc.0 loc.1 loc.2 loc.3 loc.4 loc.5 loc.6 loc.7
|
|
8 loc.8 loc.9 loc.10 loc.11 loc.12 loc.13 loc.14 loc.15
|
|
16 loc.16 loc.17 loc.18 loc.19 loc.20 loc.21 loc.22 loc.23
|
|
24 loc.24 loc.25 loc.26 loc.27 loc.28 loc.29 loc.30 loc.31
|
|
32 loc.32 loc.33 aar.1W adf.s0 adi.1W adi.2W adp.l adp.1
|
|
40 adp.2 adp.s0 adp.s-1 ads.1W and.1W asp.1W asp.2W asp.3W
|
|
48 asp.4W asp.5W asp.w0 beq.l beq.s0 bge.s0 bgt.s0 ble.s0
|
|
56 blm.s0 blt.s0 bne.s0 bra.l bra.s-1 bra.s-2 bra.s0 bra.s1
|
|
64 cal.1 cal.2 cal.3 cal.4 cal.5 cal.6 cal.7 cal.8
|
|
72 cal.9 cal.10 cal.11 cal.12 cal.13 cal.14 cal.15 cal.16
|
|
80 cal.17 cal.18 cal.19 cal.20 cal.21 cal.22 cal.23 cal.24
|
|
88 cal.25 cal.26 cal.27 cal.28 cal.s0 cff.z cif.z cii.z
|
|
96 cmf.s0 cmi.1W cmi.2W cmp.z cms.s0 csa.1W csb.1W dec.z
|
|
104 dee.w0 del.w-1 dup.1W dvf.s0 dvi.1W fil.l inc.z ine.lw
|
|
112 ine.w0 inl.-1W inl.-2W inl.-3W inl.w-1 inn.s0 ior.1W ior.s0
|
|
120 lae.l lae.w0 lae.w1 lae.w2 lae.w3 lae.w4 lae.w5 lae.w6
|
|
128 lal.p lal.n lal.0 lal.-1 lal.w0 lal.w-1 lal.w-2 lar.W
|
|
136 ldc.0 lde.lw lde.w0 ldl.0 ldl.w-1 lfr.1W lfr.2W lfr.s0
|
|
144 lil.w-1 lil.w0 lil.0 lil.1W lin.l lin.s0 lni.z loc.l
|
|
152 loc.-1 loc.s0 loc.s-1 loe.lw loe.w0 loe.w1 loe.w2 loe.w3
|
|
160 loe.w4 lof.l lof.1W lof.2W lof.3W lof.4W lof.s0 loi.l
|
|
168 loi.1 loi.1W loi.2W loi.3W loi.4W loi.s0 lol.pw lol.nw
|
|
176 lol.0 lol.1W lol.2W lol.3W lol.-1W lol.-2W lol.-3W lol.-4W
|
|
184 lol.-5W lol.-6W lol.-7W lol.-8W lol.w0 lol.w-1 lxa.1 lxl.1
|
|
192 lxl.2 mlf.s0 mli.1W mli.2W rck.1W ret.0 ret.1W ret.s0
|
|
200 rmi.1W sar.1W sbf.s0 sbi.1W sbi.2W sdl.w-1 set.s0 sil.w-1
|
|
208 sil.w0 sli.1W ste.lw ste.w0 ste.w1 ste.w2 stf.l stf.W
|
|
216 stf.2W stf.s0 sti.1 sti.1W sti.2W sti.3W sti.4W sti.s0
|
|
224 stl.pw stl.nw stl.0 stl.1W stl.-1W stl.-2W stl.-3W stl.-4W
|
|
232 stl.-5W stl.w-1 teq.z tgt.z tlt.z tne.z zeq.l zeq.s0
|
|
240 zeq.s1 zer.s0 zge.s0 zgt.s0 zle.s0 zlt.s0 zne.s0 zne.s-1
|
|
248 zre.lw zre.w0 zrl.-1W zrl.-2W zrl.w-1 zrl.nw escape1 escape2
|
|
.DE 2
|
|
The list of secondary opcodes (escape1):
|
|
.N 1
|
|
.DS B
|
|
0 aar.l aar.z adf.l adf.z adi.l adi.z ads.l ads.z
|
|
8 adu.l adu.z and.l and.z asp.lw ass.l ass.z bge.l
|
|
16 bgt.l ble.l blm.l bls.l bls.z blt.l bne.l cai.z
|
|
24 cal.l cfi.z cfu.z ciu.z cmf.l cmf.z cmi.l cmi.z
|
|
32 cms.l cms.z cmu.l cmu.z com.l com.z csa.l csa.z
|
|
40 csb.l csb.z cuf.z cui.z cuu.z dee.lw del.pw del.nw
|
|
48 dup.l dus.l dus.z dvf.l dvf.z dvi.l dvi.z dvu.l
|
|
56 dvu.z fef.l fef.z fif.l fif.z inl.pw inl.nw inn.l
|
|
64 inn.z ior.l ior.z lar.l lar.z ldc.l ldf.l ldl.pw
|
|
72 ldl.nw lfr.l lil.pw lil.nw lim.z los.l los.z lor.s0
|
|
80 lpi.l lxa.l lxl.l mlf.l mlf.z mli.l mli.z mlu.l
|
|
88 mlu.z mon.z ngf.l ngf.z ngi.l ngi.z nop.z rck.l
|
|
96 rck.z ret.l rmi.l rmi.z rmu.l rmu.z rol.l rol.z
|
|
104 ror.l ror.z rtt.z sar.l sar.z sbf.l sbf.z sbi.l
|
|
112 sbi.z sbs.l sbs.z sbu.l sbu.z sde.l sdf.l sdl.pw
|
|
120 sdl.nw set.l set.z sig.z sil.pw sil.nw sim.z sli.l
|
|
128 sli.z slu.l slu.z sri.l sri.z sru.l sru.z sti.l
|
|
136 sts.l sts.z str.s0 tge.z tle.z trp.z xor.l xor.z
|
|
144 zer.l zer.z zge.l zgt.l zle.l zlt.l zne.l zrf.l
|
|
152 zrf.z zrl.pw dch.z exg.s0 exg.l exg.z lpb.z gto.l
|
|
.DE 2
|
|
Finally, the list of opcodes with four byte arguments (escape2).
|
|
.DS
|
|
|
|
0 loc
|
|
.DE 0
|
|
.BP
|
|
.AP "AN EXAMPLE PROGRAM"
|
|
.DS B
|
|
1 program example(output);
|
|
2 {This program just demonstrates typical EM code.}
|
|
3 type rec = record r1: integer; r2:real; r3: boolean end;
|
|
4 var mi: integer; mx:real; r:rec;
|
|
5
|
|
6 function sum(a,b:integer):integer;
|
|
7 begin
|
|
8 sum := a + b
|
|
9 end;
|
|
10
|
|
11 procedure test(var r: rec);
|
|
12 label 1;
|
|
13 var i,j: integer;
|
|
14 x,y: real;
|
|
15 b: boolean;
|
|
16 c: char;
|
|
17 a: array[1..100] of integer;
|
|
18
|
|
19 begin
|
|
20 j := 1;
|
|
21 i := 3 * j + 6;
|
|
22 x := 4.8;
|
|
23 y := x/0.5;
|
|
24 b := true;
|
|
25 c := 'z';
|
|
26 for i:= 1 to 100 do a[i] := i * i;
|
|
27 r.r1 := j+27;
|
|
28 r.r3 := b;
|
|
29 r.r2 := x+y;
|
|
30 i := sum(r.r1, a[j]);
|
|
31 while i > 0 do begin j := j + r.r1; i := i - 1 end;
|
|
32 with r do begin r3 := b; r2 := x+y; r1 := 0 end;
|
|
33 goto 1;
|
|
34 1: writeln(j, i:6, x:9:3, b)
|
|
35 end; {test}
|
|
36 begin {main program}
|
|
37 mx := 15.96;
|
|
38 mi := 99;
|
|
39 test(r)
|
|
40 end.
|
|
.DE 0
|
|
.BP
|
|
The EM code as produced by the Pascal-VU compiler is given below. Comments
|
|
have been added manually. Note that this code has already been optimized.
|
|
.DS B
|
|
mes 2,2,2 ; wordsize 2, pointersize 2
|
|
.1
|
|
rom 't.p\e000' ; the name of the source file
|
|
hol 552,-32768,0 ; externals and buf occupy 552 bytes
|
|
exp $sum ; sum can be called from other modules
|
|
pro $sum,2 ; procedure sum; 2 bytes local storage
|
|
lin 8 ; code from source line 8
|
|
ldl 0 ; load two locals ( a and b )
|
|
adi 2 ; add them
|
|
ret 2 ; return the result
|
|
end 2 ; end of procedure ( still two bytes local storage )
|
|
.2
|
|
rom 1,99,2 ; descriptor of array a[]
|
|
exp $test ; the compiler exports all level 0 procedures
|
|
pro $test,226 ; procedure test, 226 bytes local storage
|
|
.3
|
|
rom 4.8F8 ; assemble Floating point 4.8 (8 bytes) in
|
|
.4 ; global storage
|
|
rom 0.5F8 ; same for 0.5
|
|
mes 3,-226,2,2 ; compiler temporary not referenced by address
|
|
mes 3,-24,2,0 ; the same is true for i, j, b and c in test
|
|
mes 3,-22,2,0
|
|
mes 3,-4,2,0
|
|
mes 3,-2,2,0
|
|
mes 3,-20,8,0 ; and for x and y
|
|
mes 3,-12,8,0
|
|
lin 20 ; maintain source line number
|
|
loc 1
|
|
stl -4 ; j := 1
|
|
lni ; lin 21 prior to optimization
|
|
lol -4
|
|
loc 3
|
|
mli 2
|
|
loc 6
|
|
adi 2
|
|
stl -2 ; i := 3 * j + 6
|
|
lni ; lin 22 prior to optimization
|
|
lae .3
|
|
loi 8
|
|
lal -12
|
|
sti 8 ; x := 4.8
|
|
lni ; lin 23 prior to optimization
|
|
lal -12
|
|
loi 8
|
|
lae .4
|
|
loi 8
|
|
dvf 8
|
|
lal -20
|
|
sti 8 ; y := x / 0.5
|
|
lni ; lin 24 prior to optimization
|
|
loc 1
|
|
stl -22 ; b := true
|
|
lni ; lin 25 prior to optimization
|
|
loc 122
|
|
stl -24 ; c := 'z'
|
|
lni ; lin 26 prior to optimization
|
|
loc 1
|
|
stl -2 ; for i:= 1
|
|
2
|
|
lol -2
|
|
dup 2
|
|
mli 2 ; i*i
|
|
lal -224
|
|
lol -2
|
|
lae .2
|
|
sar 2 ; a[i] :=
|
|
lol -2
|
|
loc 100
|
|
beq *3 ; to 100 do
|
|
inl -2 ; increment i and loop
|
|
bra *2
|
|
3
|
|
lin 27
|
|
lol -4
|
|
loc 27
|
|
adi 2 ; j + 27
|
|
sil 0 ; r.r1 :=
|
|
lni ; lin 28 prior to optimization
|
|
lol -22 ; b
|
|
lol 0
|
|
stf 10 ; r.r3 :=
|
|
lni ; lin 29 prior to optimization
|
|
lal -20
|
|
loi 16
|
|
adf 8 ; x + y
|
|
lol 0
|
|
adp 2
|
|
sti 8 ; r.r2 :=
|
|
lni ; lin 23 prior to optimization
|
|
lal -224
|
|
lol -4
|
|
lae .2
|
|
lar 2 ; a[j]
|
|
lil 0 ; r.r1
|
|
cal $sum ; call now
|
|
asp 4 ; remove parameters from stack
|
|
lfr 2 ; get function result
|
|
stl -2 ; i :=
|
|
4
|
|
lin 31
|
|
lol -2
|
|
zle *5 ; while i > 0 do
|
|
lol -4
|
|
lil 0
|
|
adi 2
|
|
stl -4 ; j := j + r.r1
|
|
del -2 ; i := i - 1
|
|
bra *4 ; loop
|
|
5
|
|
lin 32
|
|
lol 0
|
|
stl -226 ; make copy of address of r
|
|
lol -22
|
|
lol -226
|
|
stf 10 ; r3 := b
|
|
lal -20
|
|
loi 16
|
|
adf 8
|
|
lol -226
|
|
adp 2
|
|
sti 8 ; r2 := x + y
|
|
loc 0
|
|
sil -226 ; r1 := 0
|
|
lin 34 ; note the abscence of the unnecesary jump
|
|
lae 22 ; address of output structure
|
|
lol -4
|
|
cal $_wri ; write integer with default width
|
|
asp 4 ; pop parameters
|
|
lae 22
|
|
lol -2
|
|
loc 6
|
|
cal $_wsi ; write integer width 6
|
|
asp 6
|
|
lae 22
|
|
lal -12
|
|
loi 8
|
|
loc 9
|
|
loc 3
|
|
cal $_wrf ; write fixed format real, width 9, precision 3
|
|
asp 14
|
|
lae 22
|
|
lol -22
|
|
cal $_wrb ; write boolean, default width
|
|
asp 4
|
|
lae 22
|
|
cal $_wln ; writeln
|
|
asp 2
|
|
ret 0 ; return, no result
|
|
end 226
|
|
exp $_main
|
|
pro $_main,0 ; main program
|
|
.6
|
|
con 2,-1,22 ; description of external files
|
|
.5
|
|
rom 15.96F8
|
|
fil .1 ; maintain source file name
|
|
lae .6 ; description of external files
|
|
lae 0 ; base of hol area to relocate buffer addresses
|
|
cal $_ini ; initialize files, etc...
|
|
asp 4
|
|
lin 37
|
|
lae .5
|
|
loi 8
|
|
lae 2
|
|
sti 8 ; mx := 15.96
|
|
lni ; lin 38 prior to optimization
|
|
loc 99
|
|
ste 0 ; mi := 99
|
|
lni ; lin 39 prior to optimization
|
|
lae 10 ; address of r
|
|
cal $test
|
|
asp 2
|
|
loc 0 ; normal exit
|
|
cal $_hlt ; cleanup and finish
|
|
asp 2
|
|
end 0
|
|
mes 5 ; reals were used
|
|
.DE 0
|
|
The compact code corresponding to the above program is listed below.
|
|
Read it horizontally, line by line, not column by column.
|
|
Each number represents a byte of compact code, printed in decimal.
|
|
The first two bytes form the magic word.
|
|
.N 1
|
|
.IS 3
|
|
.DS B
|
|
173 0 159 122 122 122 255 242 1 161 250 124 116 46 112 0
|
|
255 156 245 40 2 245 0 128 120 155 249 123 115 117 109 160
|
|
249 123 115 117 109 122 67 128 63 120 3 122 88 122 152 122
|
|
242 2 161 121 219 122 255 155 249 124 116 101 115 116 160 249
|
|
124 116 101 115 116 245 226 0 242 3 161 253 128 123 52 46
|
|
56 255 242 4 161 253 128 123 48 46 53 255 159 123 245 30
|
|
255 122 122 255 159 123 96 122 120 255 159 123 98 122 120 255
|
|
159 123 116 122 120 255 159 123 118 122 120 255 159 123 100 128
|
|
120 255 159 123 108 128 120 255 67 140 69 121 113 116 68 73
|
|
116 69 123 81 122 69 126 3 122 113 118 68 57 242 3 72
|
|
128 58 108 112 128 68 58 108 72 128 57 242 4 72 128 44
|
|
128 58 100 112 128 68 69 121 113 98 68 69 245 122 0 113
|
|
96 68 69 121 113 118 182 73 118 42 122 81 122 58 245 32
|
|
255 73 118 57 242 2 94 122 73 118 69 220 10 123 54 118
|
|
18 122 183 67 147 73 116 69 147 3 122 104 120 68 73 98
|
|
73 120 111 130 68 58 100 72 136 2 128 73 120 4 122 112
|
|
128 68 58 245 32 255 73 116 57 242 2 59 122 65 120 20
|
|
249 123 115 117 109 8 124 64 122 113 118 184 67 151 73 118
|
|
128 125 73 116 65 120 3 122 113 116 41 118 18 124 185 67
|
|
152 73 120 113 245 30 255 73 98 73 245 30 255 111 130 58
|
|
100 72 136 2 128 73 245 30 255 4 122 112 128 69 120 104
|
|
245 30 255 67 154 57 142 73 116 20 249 124 95 119 114 105
|
|
8 124 57 142 73 118 69 126 20 249 124 95 119 115 105 8
|
|
126 57 142 58 108 72 128 69 129 69 123 20 249 124 95 119
|
|
114 102 8 134 57 142 73 98 20 249 124 95 119 114 98 8
|
|
124 57 142 20 249 124 95 119 108 110 8 122 88 120 152 245
|
|
226 0 155 249 125 95 109 97 105 110 160 249 125 95 109 97
|
|
105 110 120 242 6 151 122 119 142 255 242 5 161 253 128 125
|
|
49 53 46 57 54 255 50 242 1 57 242 6 57 120 20 249
|
|
124 95 105 110 105 8 124 67 157 57 242 5 72 128 57 122
|
|
112 128 68 69 219 110 120 68 57 130 20 249 124 116 101 115
|
|
116 8 122 69 120 20 249 124 95 104 108 116 8 122 152 120
|
|
159 124 160 255 159 125 255
|
|
.DE 0
|
|
.IE
|
|
.MS T A 0
|
|
.ME
|
|
.BP
|
|
.MS B A 0
|
|
.ME
|
|
.CT
|