Compare commits
113 Commits
unlabeled-
...
distr2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d7ceb6d6c | ||
|
|
d10d14acac | ||
|
|
ca5599714b | ||
|
|
f337b8df6d | ||
|
|
7cd58cabab | ||
|
|
8b4f21bd95 | ||
|
|
ab820d3083 | ||
|
|
fb23d440f0 | ||
|
|
f70b857d1b | ||
|
|
bd07643039 | ||
|
|
686e5af1bb | ||
|
|
34ccddfc2d | ||
|
|
b6f73fdc29 | ||
|
|
c19324dfea | ||
|
|
772b64fabd | ||
|
|
ef92740400 | ||
|
|
ee9c5be180 | ||
|
|
ca9a6feeb0 | ||
|
|
022cb596be | ||
|
|
9eb53c3d47 | ||
|
|
dfcfa9883b | ||
|
|
fb6d291d38 | ||
|
|
e4e29ae837 | ||
|
|
94534b7c15 | ||
|
|
491040b2c7 | ||
|
|
b4adc21f19 | ||
|
|
bae4084355 | ||
|
|
d394fe5dda | ||
|
|
dcfe4e8a97 | ||
|
|
be9e253a2f | ||
|
|
620216fb26 | ||
|
|
70d71f4355 | ||
|
|
6b87f1082e | ||
|
|
fd44c34a61 | ||
|
|
6c247029bd | ||
|
|
6bbdb92784 | ||
|
|
22182c0d7f | ||
|
|
87f66789de | ||
|
|
1879c8e724 | ||
|
|
693830b09a | ||
|
|
e3fa99632e | ||
|
|
b3d11b1fa5 | ||
|
|
2b6187a009 | ||
|
|
a8fc6009f7 | ||
|
|
92141b52ce | ||
|
|
b63f304db1 | ||
|
|
ec3e755168 | ||
|
|
a41ff68078 | ||
|
|
244e172413 | ||
|
|
da936740a6 | ||
|
|
35fae90a9d | ||
|
|
c5a739c68f | ||
|
|
dc92fe358e | ||
|
|
59996174b6 | ||
|
|
84f9364d4c | ||
|
|
a635fb0203 | ||
|
|
e3e1c5ac20 | ||
|
|
e3e9add8b1 | ||
|
|
ffd0d165a7 | ||
|
|
c1d5a0c721 | ||
|
|
3e743d78f3 | ||
|
|
90c847ca59 | ||
|
|
1b162c577e | ||
|
|
a5f4b01d82 | ||
|
|
c5508c7c0b | ||
|
|
80e349860b | ||
|
|
157b243956 | ||
|
|
eabf214312 | ||
|
|
d52117c8dd | ||
|
|
d457c50945 | ||
|
|
b294ab5042 | ||
|
|
9d0812746b | ||
|
|
9f203c9a17 | ||
|
|
0c92039ba4 | ||
|
|
cf6d084155 | ||
|
|
7e6a6f6de2 | ||
|
|
954d3a0326 | ||
|
|
6f6356e0b4 | ||
|
|
9e26d0e0c0 | ||
|
|
bf3ba84e92 | ||
|
|
7a790e48fb | ||
|
|
32bc0f2982 | ||
|
|
fb4a3fd479 | ||
|
|
ccdb8693ee | ||
|
|
a8c5699241 | ||
|
|
e0c4e4b686 | ||
|
|
8a40c25069 | ||
|
|
0fd729951a | ||
|
|
7a30dc4868 | ||
|
|
4b1965afbc | ||
|
|
b2b281f525 | ||
|
|
d2a6847715 | ||
|
|
2690f07cbd | ||
|
|
aa82964563 | ||
|
|
c636aba734 | ||
|
|
ce92663b0a | ||
|
|
a89ba7074f | ||
|
|
a71e706aa4 | ||
|
|
736a2d1022 | ||
|
|
17e13e9e71 | ||
|
|
9d7b94ba34 | ||
|
|
218f7ed718 | ||
|
|
cb0b2e08cf | ||
|
|
c2a990768d | ||
|
|
36537eccc0 | ||
|
|
6cdcb391fb | ||
|
|
9d9c9ae97b | ||
|
|
c478b62711 | ||
|
|
e7f7f33f60 | ||
|
|
c1f3dbba33 | ||
|
|
d5098fe70f | ||
|
|
469d075e77 | ||
|
|
2a4b3fd616 |
14
Action
14
Action
@@ -67,7 +67,7 @@ dir mach/6809
|
|||||||
indir
|
indir
|
||||||
end
|
end
|
||||||
name "Intel 8080 support"
|
name "Intel 8080 support"
|
||||||
dir mach/8080
|
dir mach/i80
|
||||||
indir
|
indir
|
||||||
end
|
end
|
||||||
name "2-2 Interpreter support"
|
name "2-2 Interpreter support"
|
||||||
@@ -90,6 +90,10 @@ name "Motorola 68000 2-4 support"
|
|||||||
dir mach/m68k2
|
dir mach/m68k2
|
||||||
indir
|
indir
|
||||||
end
|
end
|
||||||
|
name "Motorola 68000 4-4 support"
|
||||||
|
dir mach/m68k4
|
||||||
|
indir
|
||||||
|
end
|
||||||
name "NS16032 support"
|
name "NS16032 support"
|
||||||
dir mach/ns
|
dir mach/ns
|
||||||
indir
|
indir
|
||||||
@@ -102,6 +106,10 @@ name "PMDS support"
|
|||||||
dir mach/pmds
|
dir mach/pmds
|
||||||
indir
|
indir
|
||||||
end
|
end
|
||||||
|
name "PMDS 4/4 support"
|
||||||
|
dir mach/pmds4
|
||||||
|
indir
|
||||||
|
end
|
||||||
name "Signetics 2650 support"
|
name "Signetics 2650 support"
|
||||||
dir mach/s2650
|
dir mach/s2650
|
||||||
indir
|
indir
|
||||||
@@ -122,10 +130,6 @@ name "Zilog Z8000 support"
|
|||||||
dir mach/z8000
|
dir mach/z8000
|
||||||
indir
|
indir
|
||||||
end
|
end
|
||||||
name "Nascom support"
|
|
||||||
dir mach/z80a
|
|
||||||
indir
|
|
||||||
end
|
|
||||||
name "Pascal frontend"
|
name "Pascal frontend"
|
||||||
dir lang/pc/pem
|
dir lang/pc/pem
|
||||||
end
|
end
|
||||||
|
|||||||
35
Makefile
35
Makefile
@@ -1,35 +0,0 @@
|
|||||||
cmp: # compile everything and compare
|
|
||||||
(cd etc ; make cmp )
|
|
||||||
(cd util ; make cmp )
|
|
||||||
(cd lang ; make cmp )
|
|
||||||
(cd mach ; make cmp )
|
|
||||||
|
|
||||||
install: # compile everything to machine code
|
|
||||||
(cd etc ; make install )
|
|
||||||
(cd util ; make install )
|
|
||||||
(cd lang/cem ; make install )
|
|
||||||
(cd mach ; make install )
|
|
||||||
(cd lang/pc ; make install )
|
|
||||||
|
|
||||||
clean: # remove all non-sources, except boot-files
|
|
||||||
(cd doc ; make clean )
|
|
||||||
(cd man ; make clean )
|
|
||||||
(cd h ; make clean )
|
|
||||||
(cd etc ; make clean )
|
|
||||||
(cd util ; make clean )
|
|
||||||
(cd lang ; make clean )
|
|
||||||
(cd mach ; make clean )
|
|
||||||
|
|
||||||
opr: # print all sources
|
|
||||||
make pr | opr
|
|
||||||
|
|
||||||
pr: # print all sources
|
|
||||||
@( pr Makefile ; \
|
|
||||||
(cd doc ; make pr ) ; \
|
|
||||||
(cd man ; make pr ) ; \
|
|
||||||
(cd h ; make pr ) ; \
|
|
||||||
(cd etc ; make pr ) ; \
|
|
||||||
(cd lang ; make pr ) ; \
|
|
||||||
(cd util ; make pr ) ; \
|
|
||||||
(cd mach ; make pr ) \
|
|
||||||
)
|
|
||||||
17
NEW
Normal file
17
NEW
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
What's new:
|
||||||
|
A lot of things have changed since that previous distribution.
|
||||||
|
It is not wise to mix files created by the previous version of the Kit
|
||||||
|
with files belonging to this version, although that might sometimes work.
|
||||||
|
The major additions are:
|
||||||
|
- Basic frontend
|
||||||
|
- New codegenerator
|
||||||
|
- LL(1) parser generator
|
||||||
|
- Vax backend with 4-byte wordsize
|
||||||
|
- Motorola 68000 backend with 4-byte wordsize
|
||||||
|
- Motorola 68000 interpreter for 2- and 4-byte wordsize
|
||||||
|
- Z8000 assembler and backend.
|
||||||
|
- 6805 assembler
|
||||||
|
- NatSem 16032 assembler
|
||||||
|
- Intel 8080 backend
|
||||||
|
- Zilog Z80 backend
|
||||||
|
- Signetics 2650 assembler
|
||||||
1
bin/em.pascal
Executable file
1
bin/em.pascal
Executable file
@@ -0,0 +1 @@
|
|||||||
|
exec /usr/em/doc/em.doc/int/em /usr/em/doc/em.doc/int/tables ${1-e.out} core
|
||||||
15
distr/Action
Normal file
15
distr/Action
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
name "Installation manual"
|
||||||
|
dir doc
|
||||||
|
end
|
||||||
|
name "EM documentation"
|
||||||
|
dir doc/em.doc
|
||||||
|
end
|
||||||
|
name "Pascal bootstrap files"
|
||||||
|
dir lang/pc/pem
|
||||||
|
end
|
||||||
|
name "LLgen bootstrap files"
|
||||||
|
dir util/LLgen
|
||||||
|
end
|
||||||
|
name "MSC6500 vend_library"
|
||||||
|
dir mach/6500/libem
|
||||||
|
end
|
||||||
6
distr/Action1
Normal file
6
distr/Action1
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
name "vax2/cg bootstrap files"
|
||||||
|
dir mach/vax2/cg
|
||||||
|
end
|
||||||
|
name "vax4/cg bootstrap files"
|
||||||
|
dir mach/vax4/cg
|
||||||
|
end
|
||||||
42
distr/Exceptions
Normal file
42
distr/Exceptions
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
-- ./bin/em.pascal no RCS file
|
||||||
|
-- ./doc/em.doc/doc.pr no RCS file
|
||||||
|
-- ./doc/install.pr no RCS file
|
||||||
|
-- ./h/em_mnem.h no RCS file
|
||||||
|
-- ./h/em_pseu.h no RCS file
|
||||||
|
-- ./h/em_spec.h no RCS file
|
||||||
|
-- ./lang/basic/src/y.tab.c no RCS file
|
||||||
|
-- ./lang/basic/src/y.tab.h no RCS file
|
||||||
|
-- ./lang/pc/pem/pem22.m no RCS file
|
||||||
|
-- ./lang/pc/pem/pem24.m no RCS file
|
||||||
|
-- ./lib/LLgen/incl no RCS file
|
||||||
|
-- ./lib/LLgen/rec no RCS file
|
||||||
|
-- ./lib/ix/head_em no RCS file
|
||||||
|
-- ./lib/ix/head_i no RCS file
|
||||||
|
-- ./lib/ix/tail_em no RCS file
|
||||||
|
-- ./lib/ix/tail_em.vend no RCS file
|
||||||
|
-- ./lib/ix/tail_mon no RCS file
|
||||||
|
-- ./mach/6500/libem/tail_em.ve.s.a no RCS file
|
||||||
|
-- ./mach/vax2/cg/tables1.c no RCS file
|
||||||
|
-- ./mach/vax2/cg/tables1.h no RCS file
|
||||||
|
-- ./mach/vax4/cg/tables1.c no RCS file
|
||||||
|
-- ./mach/vax4/cg/tables1.h no RCS file
|
||||||
|
-- ./mach/z80/int/libpc/pc_tail.c.a no RCS file
|
||||||
|
-- ./mkun/pubmac no distr2 yet
|
||||||
|
-- ./mkun/tmac.q no distr2 yet
|
||||||
|
-- ./mkun/tmac.q1 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q2 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q3 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q4 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q5 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q6 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q7 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q8 no distr2 yet
|
||||||
|
-- ./util/LLgen/src/parser no RCS file
|
||||||
|
-- ./util/LLgen/src/LLgen.c no RCS file
|
||||||
|
-- ./util/LLgen/src/Lpars.c no RCS file
|
||||||
|
-- ./util/LLgen/src/Lpars.h no RCS file
|
||||||
|
-- ./util/LLgen/src/tokens.c no RCS file
|
||||||
|
-- ./util/data/em_flag.c no RCS file
|
||||||
|
-- ./util/data/em_mnem.c no RCS file
|
||||||
|
-- ./util/data/em_pseu.c no RCS file
|
||||||
|
-- ./util/data/em_ptyp.c no RCS file
|
||||||
74
distr/How_To
Normal file
74
distr/How_To
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
How to make a fresh distribution:
|
||||||
|
For a distribution you need ".distr" files and RCS files.
|
||||||
|
The EM home directory contains a file called ".distr". It contains
|
||||||
|
the names of all the files and directories you want to have in the distribution.
|
||||||
|
The directories should contain .distr files, the other files should
|
||||||
|
be placed under RCS.
|
||||||
|
The current RCS revision name is "distr2".
|
||||||
|
The are files that derive from other files and yet should be placed
|
||||||
|
in the distribution.
|
||||||
|
These files should not be placed under RCS.
|
||||||
|
The file "Exceptions" in this directory contains the current list of
|
||||||
|
these files.
|
||||||
|
|
||||||
|
When all this is correct, use the shell script mktree the extract
|
||||||
|
the distribution from the EM tree.
|
||||||
|
cd /usr/em ; sh distr/mktree destination_tree >distr/f.attf 2>&1
|
||||||
|
Make sure that the destination tree exists and is empty!
|
||||||
|
Failing to do that will almost certainly result in a welter of
|
||||||
|
error messages.
|
||||||
|
The file f.attf contains mktree error messages and should be compared
|
||||||
|
to Exceptions.
|
||||||
|
The actions of mktree are quite complicated. It starts in the current
|
||||||
|
directory reading the ".distr" file, after copying that file to the
|
||||||
|
destination tree.
|
||||||
|
For each file mentioned there it performes certain actions:
|
||||||
|
1- Directory Change to that directory and call yourself recursively.
|
||||||
|
2- File
|
||||||
|
a- Try to do "co -rdistr2 destination_tree/path/destination_file"
|
||||||
|
on succes "chmod +w destination_file"
|
||||||
|
else
|
||||||
|
b- Try to do "co destination_tree/destination_file"
|
||||||
|
on succes "chmod +w destination_file" and
|
||||||
|
give message that says "Missing distr2 entry" (or some such).
|
||||||
|
else
|
||||||
|
c- I Does a file LIST exist in this directory AND
|
||||||
|
is the first line of LIST equal to the name of the
|
||||||
|
destination file? If so, try to extract all the files
|
||||||
|
named in the rest of the LIST file and call the program
|
||||||
|
arch to create a library "arch cr `cat LIST`".
|
||||||
|
In this manner libraries can be distributed whose members
|
||||||
|
have their own RCS file!
|
||||||
|
else
|
||||||
|
II try to do "cp file destination_tree/path/destination_file"
|
||||||
|
on succes give message that says "Missing RCS entry"
|
||||||
|
(or some such).
|
||||||
|
else
|
||||||
|
d-
|
||||||
|
give message that says "Missing entry" (or some such).
|
||||||
|
|
||||||
|
Now you have the tree but not everything is kosher yet.
|
||||||
|
Some files derive from other files in the tree, those derivations should
|
||||||
|
be done with the use of an already installed distribution.
|
||||||
|
The files Action and Action1 in this directory contain the actions
|
||||||
|
we now take. (Confession: most of the time we use /usr/em)
|
||||||
|
One warning, to re-nroff the IR-81 report it takes more then just nroff
|
||||||
|
because most nroff's can't stand that report and stop half-way.
|
||||||
|
The ntroff program does the trick, but only on the 11's.
|
||||||
|
tbl sources | ntroff -Tlp | ntlp
|
||||||
|
|
||||||
|
After running these re-derivation programs the distrubtion tree starts
|
||||||
|
to look like the tree you need.
|
||||||
|
There are too many files there though, especially the files created by
|
||||||
|
the derivation process.
|
||||||
|
That is why we now give the command:
|
||||||
|
dtar cdf distr2 .
|
||||||
|
The file distr2 is the one you should put on tape!
|
||||||
|
But,.... before doing that: Try it out!
|
||||||
|
Repeat the process described in the installation manual.
|
||||||
|
Only if that succeeds you are sure that you included the files needed,
|
||||||
|
and gave all other files the correct "distr2" RCS id.
|
||||||
|
After you sent the tape away, forbid ANYBODY to touch the distr2 id
|
||||||
|
in your RCS files.
|
||||||
|
Good Luck,
|
||||||
|
Ed Keizer, 85/4/15.
|
||||||
25
distr/dwalk
Executable file
25
distr/dwalk
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
: ${CDIR=.}
|
||||||
|
if test ! -r .distr
|
||||||
|
then
|
||||||
|
echo ++ no .distr in $CDIR
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
${DS-:} $CDIR
|
||||||
|
for i in `cat .distr`
|
||||||
|
do
|
||||||
|
if test -d $i
|
||||||
|
then
|
||||||
|
( if cd $i
|
||||||
|
then
|
||||||
|
${DD-:} $CDIR $i
|
||||||
|
CDIR=$CDIR/$i
|
||||||
|
export CDIR
|
||||||
|
exec /usr/em/distr/dwalk
|
||||||
|
else
|
||||||
|
echo ++ Could not access $CDIR/$i
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
else
|
||||||
|
${DF-:} $CDIR $i
|
||||||
|
fi
|
||||||
|
done
|
||||||
1
distr/echod
Executable file
1
distr/echod
Executable file
@@ -0,0 +1 @@
|
|||||||
|
echo $1/$2
|
||||||
42
distr/f.attf
Normal file
42
distr/f.attf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
-- ./bin/em.pascal no RCS file
|
||||||
|
-- ./doc/em.doc/doc.pr no RCS file
|
||||||
|
-- ./doc/install.pr no RCS file
|
||||||
|
-- ./h/em_mnem.h no RCS file
|
||||||
|
-- ./h/em_pseu.h no RCS file
|
||||||
|
-- ./h/em_spec.h no RCS file
|
||||||
|
-- ./lang/basic/src/y.tab.c no RCS file
|
||||||
|
-- ./lang/basic/src/y.tab.h no RCS file
|
||||||
|
-- ./lang/pc/pem/pem22.m no RCS file
|
||||||
|
-- ./lang/pc/pem/pem24.m no RCS file
|
||||||
|
-- ./lib/LLgen/incl no RCS file
|
||||||
|
-- ./lib/LLgen/rec no RCS file
|
||||||
|
-- ./lib/ix/head_em no RCS file
|
||||||
|
-- ./lib/ix/head_i no RCS file
|
||||||
|
-- ./lib/ix/tail_em no RCS file
|
||||||
|
-- ./lib/ix/tail_em.vend no RCS file
|
||||||
|
-- ./lib/ix/tail_mon no RCS file
|
||||||
|
-- ./mach/6500/libem/tail_em.ve.s.a no RCS file
|
||||||
|
-- ./mach/vax2/cg/tables1.c no RCS file
|
||||||
|
-- ./mach/vax2/cg/tables1.h no RCS file
|
||||||
|
-- ./mach/vax4/cg/tables1.c no RCS file
|
||||||
|
-- ./mach/vax4/cg/tables1.h no RCS file
|
||||||
|
-- ./mach/z80/int/libpc/pc_tail.c.a no RCS file
|
||||||
|
-- ./mkun/pubmac no distr2 yet
|
||||||
|
-- ./mkun/tmac.q no distr2 yet
|
||||||
|
-- ./mkun/tmac.q1 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q2 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q3 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q4 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q5 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q6 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q7 no distr2 yet
|
||||||
|
-- ./mkun/tmac.q8 no distr2 yet
|
||||||
|
-- ./util/LLgen/src/parser no RCS file
|
||||||
|
-- ./util/LLgen/src/LLgen.c no RCS file
|
||||||
|
-- ./util/LLgen/src/Lpars.c no RCS file
|
||||||
|
-- ./util/LLgen/src/Lpars.h no RCS file
|
||||||
|
-- ./util/LLgen/src/tokens.c no RCS file
|
||||||
|
-- ./util/data/em_flag.c no RCS file
|
||||||
|
-- ./util/data/em_mnem.c no RCS file
|
||||||
|
-- ./util/data/em_pseu.c no RCS file
|
||||||
|
-- ./util/data/em_ptyp.c no RCS file
|
||||||
10
distr/listall
Executable file
10
distr/listall
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
case $# in
|
||||||
|
0) DIR=. ;;
|
||||||
|
1) DIR=$1 ;;
|
||||||
|
*) echo $0 [directory] ; exit 1 ;;
|
||||||
|
esac
|
||||||
|
DD=`pwd`/listall.d
|
||||||
|
DW=`pwd`/dwalk
|
||||||
|
export DD
|
||||||
|
cd $DIR
|
||||||
|
$DW
|
||||||
2
distr/listall.d
Executable file
2
distr/listall.d
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
echo "<$1/$2>"
|
||||||
|
ls -bCdx `cat .distr`
|
||||||
10
distr/listdirs
Executable file
10
distr/listdirs
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
case $# in
|
||||||
|
0) DIR=. ;;
|
||||||
|
1) DIR=$1 ;;
|
||||||
|
*) echo $0 [directory] ; exit 1 ;;
|
||||||
|
esac
|
||||||
|
DD=`pwd`/echod
|
||||||
|
DW=`pwd`/dwalk
|
||||||
|
export DD
|
||||||
|
cd $DIR
|
||||||
|
$DW
|
||||||
9
distr/mka
Executable file
9
distr/mka
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
set -e
|
||||||
|
for i in `tail +2 $DESTDIR/$1/LIST`
|
||||||
|
do
|
||||||
|
${DF-false} $1 $i
|
||||||
|
done
|
||||||
|
cd $DESTDIR/$1
|
||||||
|
arch cr `cat LIST`
|
||||||
|
: I do not remove the files constituating the library, because
|
||||||
|
: they might be present in .distr
|
||||||
23
distr/mkf
Executable file
23
distr/mkf
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
if co -q -rdistr2 $DESTDIR/$1/$2 >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
chmod +w $DESTDIR/$1/$2
|
||||||
|
elif co -q $DESTDIR/$1/$2 >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
chmod +w $DESTDIR/$1/$2
|
||||||
|
echo -- $1/$2 no distr2 yet
|
||||||
|
elif grep LIST .distr >/dev/null 2>&1 &&
|
||||||
|
(test "$2" = "`head -1 $DESTDIR/$1/LIST`") >/dev/null 2>&1 &&
|
||||||
|
${DA-false} "$1" "$2"
|
||||||
|
then
|
||||||
|
: Fetched library contents one by one and put them together
|
||||||
|
elif cp $2 $DESTDIR/$1/$2 >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
echo -- $1/$2 no RCS file
|
||||||
|
else
|
||||||
|
echo ++ $1/$2 not present
|
||||||
|
fi
|
||||||
|
case $2 in
|
||||||
|
LIST) if (test -r $DESTDIR/$1/`head -1 $DESTDIR/$1/LIST`) >/dev/null 2>&1
|
||||||
|
then echo ++ LIST files must be in .distr before their libraries!!!
|
||||||
|
fi ;;
|
||||||
|
esac
|
||||||
15
distr/mktree
Normal file
15
distr/mktree
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
case $# in
|
||||||
|
1) ;;
|
||||||
|
*) echo $0 directory ; exit 1 ;;
|
||||||
|
esac
|
||||||
|
DDIR=/usr/em/distr
|
||||||
|
case $1 in
|
||||||
|
/*) DESTDIR=$1 ;;
|
||||||
|
*) DESTDIR=`pwd`/$1 ;;
|
||||||
|
esac
|
||||||
|
DS=$DDIR/mks
|
||||||
|
DD=$DDIR/mkd
|
||||||
|
DF=$DDIR/mkf
|
||||||
|
DA=$DDIR/mka
|
||||||
|
export DESTDIR DS DD DF DA
|
||||||
|
$DDIR/dwalk
|
||||||
@@ -51,11 +51,8 @@ ordered alphabetically.
|
|||||||
Appendix A discusses the differences with
|
Appendix A discusses the differences with
|
||||||
Microsoft BASIC. Appendix B describes all reserved symbols.
|
Microsoft BASIC. Appendix B describes all reserved symbols.
|
||||||
Appendix C lists the error messages in use.
|
Appendix C lists the error messages in use.
|
||||||
.sp
|
|
||||||
Additional information about EM and the Amsterdam Compiler Kit
|
|
||||||
can be obtained from .... and found in ......
|
|
||||||
.SH
|
.SH
|
||||||
SyNTAX NOTATION
|
SYNTAX NOTATION
|
||||||
.LP
|
.LP
|
||||||
The conventions for syntax presentation are as follows:
|
The conventions for syntax presentation are as follows:
|
||||||
.IP CAPS 10
|
.IP CAPS 10
|
||||||
@@ -80,8 +77,6 @@ GENERAL INFORMATION
|
|||||||
The BASIC-EM compiler is designed for a UNIX based environment.
|
The BASIC-EM compiler is designed for a UNIX based environment.
|
||||||
It accepts a text file with your BASIC program (suffix .b) and generates
|
It accepts a text file with your BASIC program (suffix .b) and generates
|
||||||
an executable file, called a.out.
|
an executable file, called a.out.
|
||||||
.LP
|
|
||||||
Should we call the preprocessor first?
|
|
||||||
.NH 2
|
.NH 2
|
||||||
LINE FORMAT
|
LINE FORMAT
|
||||||
.LP
|
.LP
|
||||||
@@ -145,7 +140,7 @@ Defines a double precision variable
|
|||||||
Defines a string variable.
|
Defines a string variable.
|
||||||
.LP
|
.LP
|
||||||
NOTE: Two variables with the same name but different type is
|
NOTE: Two variables with the same name but different type is
|
||||||
considered illegal (DONE?).
|
considered illegal.
|
||||||
.LP
|
.LP
|
||||||
Beside single valued variables, values may be grouped
|
Beside single valued variables, values may be grouped
|
||||||
into tables or arrays.
|
into tables or arrays.
|
||||||
@@ -542,7 +537,7 @@ MID$
|
|||||||
MID$(<string expr1>,n[,m])=<string expr2>
|
MID$(<string expr1>,n[,m])=<string expr2>
|
||||||
.PU
|
.PU
|
||||||
To replace a portion of a string with another string value.
|
To replace a portion of a string with another string value.
|
||||||
The characters of <string expr> replaces characters in <string expr1>
|
The characters of <string expr2> replaces characters in <string expr1>
|
||||||
starting at position n. If m is present, at most m characters are copied,
|
starting at position n. If m is present, at most m characters are copied,
|
||||||
otherwise all characters are copied.
|
otherwise all characters are copied.
|
||||||
However, the string obtained never exceeds the length of string expr1.
|
However, the string obtained never exceeds the length of string expr1.
|
||||||
|
|||||||
830
doc/i80.doc
Normal file
830
doc/i80.doc
Normal file
@@ -0,0 +1,830 @@
|
|||||||
|
." $Header$
|
||||||
|
.RP
|
||||||
|
.TL
|
||||||
|
Back end table for the Intel 8080 micro-processor
|
||||||
|
.AU
|
||||||
|
Gerard Buskermolen
|
||||||
|
.AB
|
||||||
|
A back end is a part of the Amsterdam Compiler Kit (ACK).
|
||||||
|
It translates EM, a family of intermediate languages, into the
|
||||||
|
assembly language of some target machine, here the Intel 8080 and Intel 8085 microprocessors.
|
||||||
|
.AE
|
||||||
|
.NH1
|
||||||
|
INTRODUCTION
|
||||||
|
.PP
|
||||||
|
To simplify the task of producing portable (cross) compilers and
|
||||||
|
interpreters, the Vrije Universiteit designed an integrated collection
|
||||||
|
of programs, the Amsterdam Compiler Kit (ACK).
|
||||||
|
It is based on the old UNCOL-idea ([4]) which attempts to solve the problem
|
||||||
|
of making a compiler for each of
|
||||||
|
.B N
|
||||||
|
languages on
|
||||||
|
.B M
|
||||||
|
different machines without having to write
|
||||||
|
.B N\ *\ M
|
||||||
|
programs.
|
||||||
|
.sp 1
|
||||||
|
The UNCOL approach is to write
|
||||||
|
.B N
|
||||||
|
"front ends", each of which translates one source language into
|
||||||
|
a common intermediate language, UNCOL (UNiversal Computer Oriented
|
||||||
|
Language), and
|
||||||
|
.B M
|
||||||
|
"back ends", each of which translates programs in UNCOL into a
|
||||||
|
specific machine language.
|
||||||
|
Under these conditions, only
|
||||||
|
.B N\ +\ M
|
||||||
|
programs should be written to provide all
|
||||||
|
.B N
|
||||||
|
languages on all
|
||||||
|
.B M
|
||||||
|
machines, instead of
|
||||||
|
.B N\ *\ M
|
||||||
|
programs.
|
||||||
|
.sp 1
|
||||||
|
The intermediate language for the Amsterdam Compiler Kit is the machine
|
||||||
|
language for a simple stack machine called EM (Encoding Machine).
|
||||||
|
So a back end for the Intel 8080 micro translates EM code into
|
||||||
|
8080 assembly language.
|
||||||
|
.sp 1
|
||||||
|
The back end is a single program that is driven by a machine dependent
|
||||||
|
driving table.
|
||||||
|
This driving table, or back end table,
|
||||||
|
defines the mapping from EM code to the machine's assembly language.
|
||||||
|
.NH 1
|
||||||
|
THE 8080 MICRO PROCESSOR
|
||||||
|
.PP
|
||||||
|
This back end table can be used without modification for the Intel 8085
|
||||||
|
processor.
|
||||||
|
Except for two additional instructions, the 8085 instruction set
|
||||||
|
is identical and fully compatible with the 8080 instruction set.
|
||||||
|
So everywhere in this document '8080' can be read as '8080 and 8085'.
|
||||||
|
.NH 2
|
||||||
|
Registers
|
||||||
|
.PP
|
||||||
|
The 8080 processor has an 8 bit accumulator,
|
||||||
|
six general purpose 8-bit registers,
|
||||||
|
a 16 bit programcounter and a 16 bit stackpointer.
|
||||||
|
Assembler programs can refer the accumulator by A and
|
||||||
|
the general purpose registers by B, C, D, E, H and L. (*)
|
||||||
|
.FS
|
||||||
|
* In this document 8080 registers and mnemonics are referenced by capitals, for the sake of clarity.
|
||||||
|
Nevertheless the assembler expects small letters.
|
||||||
|
.FE
|
||||||
|
Several instructions address registers in groups of two, thus creating
|
||||||
|
16 bit registers:
|
||||||
|
.DS
|
||||||
|
Registers referenced: Symbolic reference:
|
||||||
|
B and C B
|
||||||
|
D and E D
|
||||||
|
H and L H
|
||||||
|
.DE
|
||||||
|
The first named register, contains the high order byte
|
||||||
|
(H and L stand for High and Low).
|
||||||
|
.br
|
||||||
|
The instruction determines how the processor interprets the reference.
|
||||||
|
For example, ADD B is an 8 bit operation, adding the contents of
|
||||||
|
register B to accumulator A. By contrast PUSH B is a 16 bit operation
|
||||||
|
pushing B and C onto the stack.
|
||||||
|
.sp 1
|
||||||
|
There are no index registers.
|
||||||
|
.sp 1
|
||||||
|
.NH 2
|
||||||
|
Flip-flops
|
||||||
|
.PP
|
||||||
|
The 8080 microprocessor provides five flip-flops used as condition flags
|
||||||
|
(S, Z, P, C, AC) and one interrupt enable flip-flop IE.
|
||||||
|
.br
|
||||||
|
The sign bit S is set (cleared) by certain instructions when the most significant
|
||||||
|
bit of the result of an operation equals one (zero).
|
||||||
|
.br
|
||||||
|
The zero bit Z is set (cleared) by certain operations when the
|
||||||
|
8-bit result of an operation equals (does not equal) zero.
|
||||||
|
.br
|
||||||
|
The parity bit P is set (cleared) if the 8-bit result of an
|
||||||
|
operation includes an even (odd) number of ones.
|
||||||
|
.br
|
||||||
|
C is the normal carry bit.
|
||||||
|
.br
|
||||||
|
AC is an auxiliary carry that indicates whether there has been a carry
|
||||||
|
out of bit 3 of the accumulator.
|
||||||
|
This auxiliary carry is used only by the DAA instruction, which
|
||||||
|
adjusts the 8-bit value in the accumulator to form two 4-bit
|
||||||
|
binary coded decimal digits.
|
||||||
|
Needless to say this instruction is not used in the back-end.
|
||||||
|
.sp 1
|
||||||
|
The interrupt enable flip-flop IE is set and cleared under
|
||||||
|
program control using the instructions EI (Enable Interrupt) and
|
||||||
|
DI (Disable Interrupt).
|
||||||
|
It is automatically cleared when the CPU is reset and when
|
||||||
|
an interrupt occurs, disabling further interrupts until IE = 1 again.
|
||||||
|
.NH 2
|
||||||
|
Addressing modes
|
||||||
|
.NH 3
|
||||||
|
Implied addressing
|
||||||
|
.PP
|
||||||
|
The addressing mode of some instructions is implied by the instruction itself.
|
||||||
|
For example, the RAL (rotate accumulator left) instruction deals only with
|
||||||
|
the accumulator, and PCHL loads the programcounter with the contents
|
||||||
|
of register-pair HL.
|
||||||
|
.NH 3
|
||||||
|
Register addressing
|
||||||
|
.PP
|
||||||
|
|
||||||
|
With each intruction using register addressing,
|
||||||
|
only one register is specified (except for the MOV instruction),
|
||||||
|
although in many of them the accumulator is implied as
|
||||||
|
second operand.
|
||||||
|
Examples are CMP E, which compares register E with the accumulator,
|
||||||
|
and DCR B, which decrements register B.
|
||||||
|
.br
|
||||||
|
A few instructions deal with 16 bit register-pairs:
|
||||||
|
examples are DCX B, which decrements register-pair BC and the
|
||||||
|
PUSH and POP instructions.
|
||||||
|
.NH 3
|
||||||
|
Register indirect addressing
|
||||||
|
.PP
|
||||||
|
Each instruction that may refer to an 8 bit register, may
|
||||||
|
refer also to a memory location. In this case the letter M
|
||||||
|
(for Memory) has to be used instead of a register.
|
||||||
|
It indicates the memory location pointed to by H and L,
|
||||||
|
so ADD M adds the contents of the memory location specified
|
||||||
|
by H and L to the contents of the accumulator.
|
||||||
|
.br
|
||||||
|
The register-pairs BC and DE can also be used for indirect addressing,
|
||||||
|
but only to load or store the accumulator.
|
||||||
|
For example, STAX B stores the contents of the accumulator
|
||||||
|
into the memory location addressed by register-pair BC.
|
||||||
|
.NH 3
|
||||||
|
Immediate addressing
|
||||||
|
.PP
|
||||||
|
The immediate value can be an 8 bit value, as in ADI 10 which
|
||||||
|
adds 10 to the accumulator, or a 16 bit value, as in
|
||||||
|
LXI H,1000, which loads 1000 in the register-pair HL.
|
||||||
|
.NH 3
|
||||||
|
Direct addressing
|
||||||
|
.PP
|
||||||
|
Jump instructions include a 16 bit address as part of the instruction.
|
||||||
|
.br
|
||||||
|
The instruction SHLD 1234 stores the contents of register
|
||||||
|
pair HL on memory locations 1234 and 1235.
|
||||||
|
The high order byte is stored at the highest address.
|
||||||
|
.NH 1
|
||||||
|
THE 8080 BACK END TABLE
|
||||||
|
.PP
|
||||||
|
The back end table is designed as described in [5].
|
||||||
|
So for an overall design of a back end table I refer to this document.
|
||||||
|
.br
|
||||||
|
This section deals with problems encountered in writing the
|
||||||
|
8080 back-end table.
|
||||||
|
Some remarks are made about particular parts
|
||||||
|
of the table that might not seem clear at first sight.
|
||||||
|
.NH 2
|
||||||
|
Constant definitions
|
||||||
|
.PP
|
||||||
|
Word size (EM_WSIZE) and pointer size (EM_PSIZE) are both
|
||||||
|
defined as two bytes.
|
||||||
|
The hole between AB and LB (EM_BSIZE) is four bytes: only the
|
||||||
|
return address and the localbase are saved.
|
||||||
|
.NH 2
|
||||||
|
Registers and their properties
|
||||||
|
.PP
|
||||||
|
All properties have the default size of two bytes, because one-byte
|
||||||
|
registers also cover two bytes when put on the real stack.
|
||||||
|
.sp 1
|
||||||
|
The next considerations led to the choise of register-pair BC
|
||||||
|
as localbase.
|
||||||
|
Though saving the localbase in memory would leave one more register-pair
|
||||||
|
available as scratch register, it would slow down instructions
|
||||||
|
as 'lol' and 'stl' too much.
|
||||||
|
So a register-pair should be sacrificed as localbase.
|
||||||
|
Because a back-end without a free register-pair HL is completely
|
||||||
|
broken-winged, the only reasonable choises are BC and DE.
|
||||||
|
Though the choise between them might seem arbitrary at first sight,
|
||||||
|
there is a difference between register-pairs BC and DE:
|
||||||
|
the instruction XCHG exchanges the contents of register-pairs DE and
|
||||||
|
HL.
|
||||||
|
When DE and HL are both heavily used on the fake-stack, this instruction
|
||||||
|
is very usefull.
|
||||||
|
Since it won't be usefull too often to exchange HL with the localbase
|
||||||
|
and since an instruction exchanging BC and HL does not exist, BC is
|
||||||
|
chosen as localbase.
|
||||||
|
.sp 1
|
||||||
|
Many of the register properties are never mentioned in the
|
||||||
|
PATTERNS part of the table.
|
||||||
|
They are only needed to define the INSTRUCTIONS correctly.
|
||||||
|
.sp 1
|
||||||
|
The properties really used in the PATTERNS part are:
|
||||||
|
.IP areg: 24
|
||||||
|
the accumulator only
|
||||||
|
.IP reg:
|
||||||
|
any of the registers A, D, E, H or L. Of course the registers B and C which are
|
||||||
|
used as localbase don't possess this property.
|
||||||
|
When there is a single register on the fake-stack, its value
|
||||||
|
is always considered non-negative.
|
||||||
|
.IP dereg:
|
||||||
|
register-pair DE only
|
||||||
|
.IP hlreg:
|
||||||
|
register-pair HL only
|
||||||
|
.IP hl_or_de:
|
||||||
|
register-pairs HL and DE both have this property
|
||||||
|
.IP localbase:
|
||||||
|
used only once (i.e. in the EM-instruction 'str 0')
|
||||||
|
.PP
|
||||||
|
.sp 1
|
||||||
|
The stackpointer SP and the processor status word PSW have to be
|
||||||
|
defined explicitely because they are needed in some instructions
|
||||||
|
(i.e. SP in LXI, DCX and INX and PSW in PUSH and POP).
|
||||||
|
.br
|
||||||
|
It doesn't matter that the processor status word is not just register A
|
||||||
|
but includes the condition flags.
|
||||||
|
.NH 2
|
||||||
|
Tokens
|
||||||
|
.PP
|
||||||
|
The tokens 'm' and 'const1' are used in the INSTRUCTIONS- and MOVES parts only.
|
||||||
|
They will never be on the fake-stack.
|
||||||
|
.sp 1
|
||||||
|
The token 'label' reflects addresses known at assembly time.
|
||||||
|
It is used to take full profit of the instructions LHLD
|
||||||
|
(Load HL Direct) and SHLD (Store HL Direct).
|
||||||
|
.sp 1
|
||||||
|
Compared with many other back-end tables, there are only a small number of
|
||||||
|
different tokens (four).
|
||||||
|
Reasons are the limited addressing modes of the 8080 microprocessor,
|
||||||
|
no index registers etc.
|
||||||
|
.br
|
||||||
|
For example to translate the EM-instruction
|
||||||
|
.DS
|
||||||
|
lol 10
|
||||||
|
.DE
|
||||||
|
the next 8080 instructions are generated:
|
||||||
|
.DS L
|
||||||
|
LXI H,10 /* load registers pair HL with value 10 */
|
||||||
|
DAD B /* add localbase (BC) to HL */
|
||||||
|
MOV E,M /* load E with byte pointed to by HL */
|
||||||
|
INX H /* increment HL */
|
||||||
|
MOV D,M /* load D with next byte */
|
||||||
|
.DE
|
||||||
|
Of course, instead of emitting code immmediately, it could be postponed
|
||||||
|
by placing something like a {LOCAL,10} on the fake-stack, but some day the above
|
||||||
|
mentioned code will have to be generated, so a LOCAL-token is
|
||||||
|
hardly usefull.
|
||||||
|
.br
|
||||||
|
See also the comment on the load instructions.
|
||||||
|
.NH 2
|
||||||
|
Sets
|
||||||
|
.PP
|
||||||
|
Only 'src1or2' is used in the PATTERNS.
|
||||||
|
.NH 2
|
||||||
|
Instructions
|
||||||
|
.PP
|
||||||
|
Each instruction indicates whether or not the condition flags
|
||||||
|
are affected, but this information will never have any influence
|
||||||
|
because there are no tests in the PATTERNS part of the table.
|
||||||
|
.sp 1
|
||||||
|
For each instruction a cost vector indicates the number of bytes
|
||||||
|
the instruction occupies and the number of time periods it takes
|
||||||
|
to execute the instruction.
|
||||||
|
The length of a time period depends on the clock frequency
|
||||||
|
and may range from 480 nanoseconds to 2 microseconds on a
|
||||||
|
8080 system and from 320 nanoseconds to 2 microseconds
|
||||||
|
on a 8085 system.
|
||||||
|
.sp 1
|
||||||
|
In the TOKENS-part the cost of token 'm' is defined as (0,3).
|
||||||
|
In fact it usually takes 3 extra time periods when this register indirect mode
|
||||||
|
is used instead of register mode, but since the costs are not completely
|
||||||
|
orthogonal this results in small deficiencies for the DCR, INR and MOV
|
||||||
|
instructions.
|
||||||
|
Although it is not particularly usefull these deficiencies are
|
||||||
|
corrected in the INSTRUCTIONS part, by treating the register indirect
|
||||||
|
mode seperately.
|
||||||
|
.sp 1
|
||||||
|
The costs of the conditional call and return instructions really
|
||||||
|
depend on whether or not the call resp. return is actually made.
|
||||||
|
Unimportant.
|
||||||
|
.sp 1
|
||||||
|
Instructions not used in this table have been commented out.
|
||||||
|
Of course many of them are used in the library routines.
|
||||||
|
.NH 2
|
||||||
|
Moves
|
||||||
|
.PP
|
||||||
|
This section is supposed to be straight-forward.
|
||||||
|
.NH 2
|
||||||
|
Tests
|
||||||
|
.PP
|
||||||
|
The TESTS section is only included to refrain
|
||||||
|
.B cgg
|
||||||
|
from complaining.
|
||||||
|
.NH 2
|
||||||
|
Stackingrules
|
||||||
|
.PP
|
||||||
|
When, for example, the token {const2,10} has to be stacked while
|
||||||
|
no free register-pair is available, the next code is generated:
|
||||||
|
.DS
|
||||||
|
PUSH H
|
||||||
|
LXI H,10
|
||||||
|
XTHL
|
||||||
|
.DE
|
||||||
|
The last instruction exchanges the contents of HL with the value
|
||||||
|
on top of the stack, giving HL its original value again.
|
||||||
|
.NH 2
|
||||||
|
Coercions
|
||||||
|
.PP
|
||||||
|
The coercion to unstack register A, is somewhat tricky,
|
||||||
|
but unfortunately just popping PSW leaves the high-order byte in
|
||||||
|
the accumulator.
|
||||||
|
.sp 1
|
||||||
|
The cheapest way to coerce HL to DE (or DE to HL) is by using
|
||||||
|
the XCHG instruction, but it is not possible to explain
|
||||||
|
.B cgg
|
||||||
|
this instruction in fact exchanges the contents of these
|
||||||
|
register-pairs.
|
||||||
|
Before the coercion is carried out other appearances of DE and HL
|
||||||
|
on the fake-stack will be moved to the real stack, because in
|
||||||
|
the INSTRUCTION-part is told that XCHG destroyes the contents
|
||||||
|
of both DE and HL.
|
||||||
|
.br
|
||||||
|
The coercion transposing one register-pair to another one by
|
||||||
|
emitting two MOV-instructions, will be used only if
|
||||||
|
one of the register-pairs is the localbase.
|
||||||
|
.NH 2
|
||||||
|
Patterns
|
||||||
|
.PP
|
||||||
|
As a general habit I have allocated (uses ...) all registers
|
||||||
|
that should be free to generate the code, although it is not
|
||||||
|
always necessary.
|
||||||
|
For example in the code rule
|
||||||
|
.DS
|
||||||
|
pat loe
|
||||||
|
uses hlreg
|
||||||
|
gen lhld {label,$1} yields hl
|
||||||
|
.DE
|
||||||
|
the 'uses'-clause could have been omitted because
|
||||||
|
.B cgg
|
||||||
|
knows that LHLD destroyes register-pair HL.
|
||||||
|
.sp 1
|
||||||
|
Since there is only one register with property 'hlreg',
|
||||||
|
there is no difference between 'uses hlreg' (allocate a
|
||||||
|
register with property 'hlreg') and 'kills hlreg' (remove
|
||||||
|
all registers with property 'hlreg' from the fake-stack).
|
||||||
|
The same applies for the property 'dereg'.
|
||||||
|
.br
|
||||||
|
As a consequence 'kills' is rarely used in this back-end table.
|
||||||
|
.NH 3
|
||||||
|
Group 1: Load instructions
|
||||||
|
.PP
|
||||||
|
When a local variable must be squared, there will probably be EM-code like:
|
||||||
|
.DS
|
||||||
|
lol 10
|
||||||
|
lol 10
|
||||||
|
mli 2
|
||||||
|
.DE
|
||||||
|
When the code for the first 'lol 10' has been executed, DE contains the
|
||||||
|
wanted value.
|
||||||
|
To refrain
|
||||||
|
.B cgg
|
||||||
|
from emitting the code for 'lol 10' again, an extra
|
||||||
|
pattern is included in the table for cases like this.
|
||||||
|
.br
|
||||||
|
The same applies for two consecutive 'loe'-s or 'lil'-s.
|
||||||
|
.sp 1
|
||||||
|
A bit tricky is 'lof'.
|
||||||
|
It expects either DE or HL on the fake-stack, moves {const2,$1}
|
||||||
|
into the other one, and eventually adds them.
|
||||||
|
The 'kills' part is necessary here because if DE was on the fake-stack,
|
||||||
|
.B cgg
|
||||||
|
doesn't see that the contents of DE is destroyed by the code
|
||||||
|
(in fact 'kills dereg' would have been sufficient: because of the
|
||||||
|
DAD instruction
|
||||||
|
.B cgg
|
||||||
|
knows that HL is destroyed).
|
||||||
|
.sp 1
|
||||||
|
By lookahead,
|
||||||
|
.B cgg
|
||||||
|
can make a clever choise between the first and
|
||||||
|
second code rule of 'loi 4'.
|
||||||
|
The same applies for several other instructions.
|
||||||
|
.NH 3
|
||||||
|
Group 2: Store instructions
|
||||||
|
.PP
|
||||||
|
A similar idea as with the two consecutive identical load instructions
|
||||||
|
in Group 1, applies for a store instruction followed by a corresponding load instruction.
|
||||||
|
.NH 3
|
||||||
|
Groups 3 and 4: Signed and unsigned integer arithmetic
|
||||||
|
.PP
|
||||||
|
Since the 8080 instruction set doesn't provide multiply and
|
||||||
|
divide instructions, special routines are made to accomplish these tasks.
|
||||||
|
.sp 1
|
||||||
|
Instead of providing four slighty differing routines for 16 bit signed or
|
||||||
|
unsigned division, yielding the quotient or the remainder,
|
||||||
|
the routines are merged.
|
||||||
|
This saves space and assembly time
|
||||||
|
when several variants are used in a particular program,
|
||||||
|
at the cost of a little speed.
|
||||||
|
.br
|
||||||
|
When the routine is called, bit 7 of register A indicates whether
|
||||||
|
the operands should be considered as signed or as unsigned integers,
|
||||||
|
and bit 0 of register A indicates whether the quotient or the
|
||||||
|
remainder has to be delivered.
|
||||||
|
.br
|
||||||
|
The same applies for 32 bit division.
|
||||||
|
.sp 1
|
||||||
|
The routine doing the 16 bit unsigned multiplication could
|
||||||
|
have been used for 16 bit signed multiplication too.
|
||||||
|
Nevertheless a special 16 bit signed multiplication routine is
|
||||||
|
provided, because this one will usually be much faster.
|
||||||
|
.NH 3
|
||||||
|
Group 5: Floating point arithmetic
|
||||||
|
.PP
|
||||||
|
Floating points are not implemented.
|
||||||
|
.br
|
||||||
|
Whenever an EM-instruction involving floating points is offered
|
||||||
|
to the code-generator, it generates the code 'call eunimpl',
|
||||||
|
which traps with trap number 63.
|
||||||
|
Some of the Pascal and C library routines output floating point
|
||||||
|
EM-instructions, so code has to be generated for them.
|
||||||
|
Of course this doesn't imply the code will ever be executed.
|
||||||
|
.NH 3
|
||||||
|
Group 12: Compare instructions
|
||||||
|
.PP
|
||||||
|
The code for 'cmu 2', with its 4 labels, is terrible.
|
||||||
|
But it is the best I could find.
|
||||||
|
.NH 3
|
||||||
|
Group 9: Logical instructions
|
||||||
|
.PP
|
||||||
|
I have tried to merge both variants of the instructions 'and 2', 'ior 2' and 'xor 2',
|
||||||
|
as in
|
||||||
|
.DS
|
||||||
|
pat and $1==2
|
||||||
|
with hl_or_de hl_or_de
|
||||||
|
uses reusing %1, reusing %2, hl_or_de, areg
|
||||||
|
gen mov a,%1.2
|
||||||
|
ana %2.2
|
||||||
|
mov %a.2,a
|
||||||
|
mov a,%1.1
|
||||||
|
ana %2.1
|
||||||
|
mov %a.1,a yields %a
|
||||||
|
.DE
|
||||||
|
but the current version of
|
||||||
|
.B cgg
|
||||||
|
doesn't approve this.
|
||||||
|
.br
|
||||||
|
In any case
|
||||||
|
.B cgg
|
||||||
|
chooses either DE or HL to store the result, using lookahead.
|
||||||
|
.NH 3
|
||||||
|
Group 14: Procedure call instructions
|
||||||
|
.PP
|
||||||
|
There is an 8 bytes function return area, called '.fra'.
|
||||||
|
If only 2 bytes have to be returned, register-pair DE is used.
|
||||||
|
.NH 1
|
||||||
|
LIBRARY ROUTINES
|
||||||
|
.PP
|
||||||
|
Most of the library routines start with saving the return address
|
||||||
|
and the localbase, so that the parameters are on the top of the stack
|
||||||
|
and the registers B and C are available as scratch registers.
|
||||||
|
Since register-pair HL is needed to accomplish these tasks,
|
||||||
|
and also to restore everything just before the routine returns,
|
||||||
|
it is not possible to transfer data between the routines and the
|
||||||
|
surrounding world through register H or L.
|
||||||
|
Only registers A, D and E can be used for this.
|
||||||
|
.sp
|
||||||
|
When a routine returns 2 bytes, they are usually returned in
|
||||||
|
registers-pair DE.
|
||||||
|
When it returns more than 2 bytes they are pushed onto the stack.
|
||||||
|
.br
|
||||||
|
|
||||||
|
It would have been possible to let the 32 bit arithmetic routines
|
||||||
|
return 2 bytes in DE and the remaining 2 bytes on the stack
|
||||||
|
(this often would have saved some space and execution time),
|
||||||
|
but I don't consider that as well-structured programming.
|
||||||
|
.NH 1
|
||||||
|
TRAPS
|
||||||
|
.PP
|
||||||
|
Whenever a trap, for example trying to divide by zero,
|
||||||
|
occurs in a program that originally was written in C or Pascal,
|
||||||
|
a special trap handler is called.
|
||||||
|
.br
|
||||||
|
This trap handler wants to write an appropriate error message on the
|
||||||
|
monitor.
|
||||||
|
It tries to read the message from a file (e.g. etc/pc_rt_errors in the
|
||||||
|
EM home directory for Pascal programs), but since the 8080 back-end
|
||||||
|
doesn't know about files, we are in trouble.
|
||||||
|
This problem is solved, as far as possible, by including the 'open'-monitor call in the mon-routine.
|
||||||
|
It returns with file descriptor -1.
|
||||||
|
The trap handler reacts by generating another trap, with the original
|
||||||
|
trap number.
|
||||||
|
But this time, instead of calling the C- or Pascal trap handler again,
|
||||||
|
the next message is printed on the monitor:
|
||||||
|
.DS L
|
||||||
|
trap number <TN>
|
||||||
|
line <LN> of file <FN>
|
||||||
|
|
||||||
|
where <TN> is the trap number (decimal)
|
||||||
|
<LN> is the line number (decimal)
|
||||||
|
<FN> is the filename of the original program
|
||||||
|
.DE
|
||||||
|
.sp 1
|
||||||
|
Trap numbers are subdivided as follows:
|
||||||
|
.IP 1-27: 20
|
||||||
|
EM-machine error, as described in [3]
|
||||||
|
.IP 63:
|
||||||
|
an unimplemented EM-instruction is used
|
||||||
|
.IP 64-127:
|
||||||
|
generated by compilers, runtime systems, etc.
|
||||||
|
.IP 128-252:
|
||||||
|
generated by user programs
|
||||||
|
.NH 1
|
||||||
|
IMPLEMENTATION
|
||||||
|
.PP
|
||||||
|
It will not be possible to run the entire Amsterdam Compiler Kit on a
|
||||||
|
8080-based computer system.
|
||||||
|
One has to write a program on another
|
||||||
|
system, a system where the compiler kit runs on.
|
||||||
|
This program may be a mixture of high-level languages, such as
|
||||||
|
C or Pascal, EM and 8080 assembly code.
|
||||||
|
The program should be compiled using the compiler kit, producing 8080 machine code.
|
||||||
|
This code should come available to the 8080 machine
|
||||||
|
for example by downloading or
|
||||||
|
by storing it in ROM (Read Only Memory).
|
||||||
|
.sp 1
|
||||||
|
Depending on the characteristics of the particular 8080 based system, some
|
||||||
|
adaptions have to be made:
|
||||||
|
.IP 1) 10
|
||||||
|
In 'head_em': the base address, which is the address where the first
|
||||||
|
8080 instruction will be stored, and the initial value of the
|
||||||
|
stackpointer are set to 0x1000 and 0x8000 respectivally.
|
||||||
|
.br
|
||||||
|
Other systems require other values.
|
||||||
|
.IP 2)
|
||||||
|
In 'head_em': before calling "_m_a_i_n", the environment
|
||||||
|
pointer, argument vector and argument count will have to be pushed
|
||||||
|
onto the stack.
|
||||||
|
Since this back-end is tested on a system without any knowledge
|
||||||
|
of these things, dummies are pushed now.
|
||||||
|
.IP 3)
|
||||||
|
In 'tail_em': proper routines "putchar" and "getchar" should
|
||||||
|
be provided.
|
||||||
|
They should write resp. read a character on/from the monitor.
|
||||||
|
Maybe some conversions will have to be made.
|
||||||
|
.IP 4)
|
||||||
|
In 'head_em': an application program returns control to the monitor by
|
||||||
|
jumping to address 0xFB52.
|
||||||
|
If this is not the right way on your system, change it.
|
||||||
|
.IP 5)
|
||||||
|
In 'tail_em': the current version of the 8080 back-end has very limited I/O
|
||||||
|
capabilities, because it was tested on a system that
|
||||||
|
had no knowlegde of files.
|
||||||
|
So the implementation of the EM-instruction 'mon' is very simple;
|
||||||
|
it can only do the following things:
|
||||||
|
.RS
|
||||||
|
.IP Monitor\ call\ 1: 40
|
||||||
|
Exit
|
||||||
|
.IP Monitor\ call\ 3:
|
||||||
|
read, always reads from the monitor.
|
||||||
|
.br
|
||||||
|
echos the read character.
|
||||||
|
.br
|
||||||
|
ignores file descriptor.
|
||||||
|
.IP Monitor\ call\ 4:
|
||||||
|
write, always writes on the monitor.
|
||||||
|
.br
|
||||||
|
ignores file descriptor.
|
||||||
|
.IP Monitor\ call\ 5:
|
||||||
|
open file, returns file descriptor -1.
|
||||||
|
.br
|
||||||
|
(compare chapter about TRAPS)
|
||||||
|
.IP Monitor\ call\ 6:
|
||||||
|
close file, returns error code = 0.
|
||||||
|
.IP Monitor\ call\ 54:
|
||||||
|
io-control, returns error code = 0.
|
||||||
|
.RE
|
||||||
|
.sp
|
||||||
|
If the system should do file-handling the routine ".mon"
|
||||||
|
should be extended thoroughly.
|
||||||
|
.NH 1
|
||||||
|
INTEL 8080 VERSUS ZILOG Z80 AND INTEL 8086
|
||||||
|
.NH 2
|
||||||
|
Introduction
|
||||||
|
.PP
|
||||||
|
At about the same time I develloped the back end
|
||||||
|
for the Intel 8080 and Intel 8085,
|
||||||
|
Frans van Haarlem did the same job for the Zilog z80 microprocessor.
|
||||||
|
Since the z80 processor is an extension of the 8080,
|
||||||
|
any machine code offered to a 8080 processor can be offered
|
||||||
|
to a z80 too.
|
||||||
|
The assembly languages are quite different however.
|
||||||
|
.br
|
||||||
|
During the devellopments of the back ends we have used
|
||||||
|
two micro-computers, both equiped with a z80 microprocessor.
|
||||||
|
Of course the output of the 8080 back end is assembled by an
|
||||||
|
8080 assembler. This should assure I have never used any of
|
||||||
|
the features that are potentially available in the z80 processor,
|
||||||
|
but are not part of a true 8080 processor.
|
||||||
|
.sp 1
|
||||||
|
As a final job, I have
|
||||||
|
investigated the differences between the 8080 and z80 processors
|
||||||
|
and their influence on the back ends.
|
||||||
|
I have tried to measure this influence by examining the length of
|
||||||
|
the generated code.
|
||||||
|
I have also involved the 8086 micro-processor in this measurements.
|
||||||
|
.NH 2
|
||||||
|
Differences between the 8080 and z80 processors
|
||||||
|
.PP
|
||||||
|
Except for some features that are less important concerning back ends,
|
||||||
|
there are two points where the z80 improves the 8080:
|
||||||
|
.IP First, 18
|
||||||
|
the z80 has two additional index registers, IX and IY.
|
||||||
|
They are used as in
|
||||||
|
.DS
|
||||||
|
LD B,(IX+10)
|
||||||
|
.DE
|
||||||
|
The offset, here 10, should fit in one byte.
|
||||||
|
.IP Second,
|
||||||
|
the z80 has several additional instructions.
|
||||||
|
The most important ones are:
|
||||||
|
.RS
|
||||||
|
.IP 1) 8
|
||||||
|
The 8080 can only load or store register-pair HL direct
|
||||||
|
(using LHLD or SHLD).
|
||||||
|
The z80 can handle BC, DE and SP too.
|
||||||
|
.IP 2)
|
||||||
|
Instructions are included to ease block movements.
|
||||||
|
.IP 3)
|
||||||
|
There is a 16 bit subtract instruction.
|
||||||
|
.IP 4)
|
||||||
|
While the 8080 can only rotate the accumulator, the z80
|
||||||
|
can rotate and shift each 8 bit register.
|
||||||
|
.IP 5)
|
||||||
|
Special routines are included to jump to near locations, saving 1 byte.
|
||||||
|
.RE
|
||||||
|
.NH 2
|
||||||
|
Consequences for the 8080 and z80 back end
|
||||||
|
.PP
|
||||||
|
The most striking difference between the 8080 and z80 back ends
|
||||||
|
is the choise of the localbase.
|
||||||
|
The writer of the z80 back end chose index register IY as localbase,
|
||||||
|
because this results in the cheapest coding of EM-instructions
|
||||||
|
like 'lol' and 'stl'.
|
||||||
|
.br
|
||||||
|
The z80 instructions that load local 10, for example
|
||||||
|
.DS
|
||||||
|
LD E,(IY+10)
|
||||||
|
LD D,(IY+11)
|
||||||
|
.DE
|
||||||
|
occupy 6 bytes and take 38 time periods to execute.
|
||||||
|
The five corresponding 8080 instructions loading a local
|
||||||
|
occupy 7 bytes and take 41 time periods.
|
||||||
|
Although the profit of the z80 might be not world-shocking,
|
||||||
|
it should be noted that as a side effect it may save some
|
||||||
|
pushing and popping since register pair HL is not used.
|
||||||
|
.sp 1
|
||||||
|
The choise of IY as localbase has its drawbacks too.
|
||||||
|
The root of the problem is that it is not possible to add
|
||||||
|
IY to HL.
|
||||||
|
For the EM-instruction
|
||||||
|
.DS
|
||||||
|
lal 20
|
||||||
|
.DE
|
||||||
|
the z80 back end generates code like
|
||||||
|
.DS
|
||||||
|
LD BC,20
|
||||||
|
PUSH IY
|
||||||
|
POP HL
|
||||||
|
ADD HL,BC
|
||||||
|
.DE
|
||||||
|
leaving the wanted address in HL.
|
||||||
|
.br
|
||||||
|
This annoying push and pop instructions are also needed in some
|
||||||
|
other instructions, for instance in 'lol' when the offset
|
||||||
|
doesn't fit in one byte.
|
||||||
|
.sp 1
|
||||||
|
Beside the choise of the localbase, I think there is no
|
||||||
|
fundamental difference between the 8080 and z80 back ends,
|
||||||
|
except of course that the z80 back end has register pair BC
|
||||||
|
and, less important, index register IX available as scratch registers.
|
||||||
|
.sp 1
|
||||||
|
Most of the PATTERNS in the 8080 and z80 tables are more or less
|
||||||
|
a direct translation of each other.
|
||||||
|
.NH 2
|
||||||
|
What did I do?
|
||||||
|
.PP
|
||||||
|
To get an idea of the quality of the code generated by
|
||||||
|
the 8080, z80 and 8086 back ends I have gathered
|
||||||
|
some C programs and some Pascal programs.
|
||||||
|
Then I produced 8080, z80 and 8086 code for them.
|
||||||
|
Investigating the assembler listing I found the
|
||||||
|
lengths of the different parts of the generated code.
|
||||||
|
.br
|
||||||
|
I have checked two areas:
|
||||||
|
.IP 1) 8
|
||||||
|
the entire text part
|
||||||
|
.IP 2)
|
||||||
|
the text part without any library routine, so only the plain user program
|
||||||
|
.LP
|
||||||
|
I have to admit that neither one of them is really honest.
|
||||||
|
When the entire text part is checked, the result is disturbed
|
||||||
|
because not always the same library routines are loaded.
|
||||||
|
And when only the user program itself is considered, the result is
|
||||||
|
disturbed too.
|
||||||
|
For example the 8086 has a multiply instruction,
|
||||||
|
so the EM-instruction 'mli 2' is translated in the main program,
|
||||||
|
but the 8080 and z80 call a library routine that is not counted.
|
||||||
|
Also the 8080 uses library routines at some places where the
|
||||||
|
z80 does not.
|
||||||
|
.sp 1
|
||||||
|
But nevertheless I think the measurements will give an idea
|
||||||
|
about the code produced by the three back ends.
|
||||||
|
.NH 2
|
||||||
|
The results
|
||||||
|
.PP
|
||||||
|
The table below should be read as follows.
|
||||||
|
For all programs I have computed the ratio of the code-lengths
|
||||||
|
of the 8080, z80 and 8086.
|
||||||
|
The averages of all Pascal/C programs are listed in the table,
|
||||||
|
standarized to '100' for the 8080.
|
||||||
|
So the listed '107' indicates that the lengths
|
||||||
|
of the text parts of the z80 programs that originally were Pascal programs,
|
||||||
|
averaged 7 percent larger than in the corresponding 8080 programs.
|
||||||
|
.DS C
|
||||||
|
--------------------------------------------------
|
||||||
|
| | 8080 | z80 | 8086 |
|
||||||
|
--------------------------------------------------
|
||||||
|
| C, text part | 100 | 103 | 65 |
|
||||||
|
| Pascal, text part | 100 | 107 | 55 |
|
||||||
|
| C, user program | 100 | 110 | 71 |
|
||||||
|
| Pascal, user program | 100 | 118 | 67 |
|
||||||
|
--------------------------------------------------
|
||||||
|
.DE
|
||||||
|
.TE
|
||||||
|
The most striking thing in this table is that the z80 back end appears
|
||||||
|
to produce larger code than the 8080 back end.
|
||||||
|
The reason is that the current z80 back end table is
|
||||||
|
not very elaborate yet.
|
||||||
|
For instance it doesn't look for any EM-pattern longer than one.
|
||||||
|
So the table shows that the preparations in the 8080 back end table
|
||||||
|
to produce faster code (like recognizing special EM-patterns
|
||||||
|
and permitting one byte registers on the fake-stack)
|
||||||
|
was not just for fun, but really improved the generated code
|
||||||
|
significantly.
|
||||||
|
.sp 1
|
||||||
|
The table shows that the 8080 table is relativelly better
|
||||||
|
when only the plain user program is considered instead of the entire text part.
|
||||||
|
This is not very surprising since the 8080 back end sometimes
|
||||||
|
uses library routines where the z80 and especially the 8086 don't.
|
||||||
|
.sp 1
|
||||||
|
The difference between the 8080 and z80 on the one hand and the 8086
|
||||||
|
on the other is very big.
|
||||||
|
But of course it was not equal game:
|
||||||
|
the 8086 is a 16 bit processor that is much more advanced than the
|
||||||
|
8080 or z80 and the 8086 back end is known to produce
|
||||||
|
very good code.
|
||||||
|
.bp
|
||||||
|
.B REFERENCES
|
||||||
|
.sp 2
|
||||||
|
.IP [1] 10
|
||||||
|
8080/8085 Assembly Language Programming Manual,
|
||||||
|
.br
|
||||||
|
Intel Corporation (1977,1978)
|
||||||
|
.IP [2]
|
||||||
|
Andrew S. Tanenbaum, Hans van Staveren, E.G. Keizer and Johan W. Stevenson,
|
||||||
|
.br
|
||||||
|
A practical tool kit for making portable compilers,
|
||||||
|
.br
|
||||||
|
Informatica report 74, Vrije Universiteit, Amsterdam, 1983.
|
||||||
|
.sp
|
||||||
|
An overview on the Amsterdam Compiler Kit.
|
||||||
|
.IP [3]
|
||||||
|
Tanenbaum, A.S., Stevenson, J.W., Keizer, E.G., and van Staveren, H.
|
||||||
|
.br
|
||||||
|
Desciption of an experimental machine architecture for use with block
|
||||||
|
structured languages,
|
||||||
|
.br
|
||||||
|
Informatica report 81, Vrije Universiteit, Amsterdam, 1983.
|
||||||
|
.sp
|
||||||
|
The defining document for EM.
|
||||||
|
.IP [4]
|
||||||
|
Steel, T.B., Jr.
|
||||||
|
.br
|
||||||
|
UNCOL: The myth and the Fact. in Ann. Rev. Auto. Prog.
|
||||||
|
.br
|
||||||
|
Goodman, R. (ed.), vol. 2, (1960), p325-344.
|
||||||
|
.sp
|
||||||
|
An introduction to the UNCOL idea by its originator.
|
||||||
|
.IP [5]
|
||||||
|
van Staveren, Hans
|
||||||
|
.br
|
||||||
|
The table driven code generator from the Amsterdam Compiler Kit
|
||||||
|
(Second Revised Edition),
|
||||||
|
.br
|
||||||
|
Vrije Universiteit, Amsterdam.
|
||||||
|
.sp
|
||||||
|
The defining document for writing a back end table.
|
||||||
|
.IP [6]
|
||||||
|
Voors, Jan
|
||||||
|
.br
|
||||||
|
A back end for the Zilog z8000 micro,
|
||||||
|
.br
|
||||||
|
Vrije Universiteit, Amsterdam.
|
||||||
|
.sp
|
||||||
|
A document like this one, but for the z8000.
|
||||||
1077
doc/install.doc
1077
doc/install.doc
File diff suppressed because it is too large
Load Diff
366
doc/ncg.doc
366
doc/ncg.doc
@@ -57,7 +57,7 @@ and the assembly code of the machine at hand.
|
|||||||
.NH 1
|
.NH 1
|
||||||
What has changed since version 1 ?
|
What has changed since version 1 ?
|
||||||
.PP
|
.PP
|
||||||
This chapter can be skipped by anyone not familiar with the first version.
|
This section can be skipped by anyone not familiar with the first version.
|
||||||
It is not needed to understand the current version.
|
It is not needed to understand the current version.
|
||||||
.PP
|
.PP
|
||||||
This paper describes the second version of the code generator system.
|
This paper describes the second version of the code generator system.
|
||||||
@@ -116,39 +116,40 @@ Alternatively one can think of the real stack as an infinite extension
|
|||||||
at the bottom of the fake stack.
|
at the bottom of the fake stack.
|
||||||
Both ways, the concatenation of the real stack and the fake stack
|
Both ways, the concatenation of the real stack and the fake stack
|
||||||
will be the stack as it would have been on a real EM machine (see figure).
|
will be the stack as it would have been on a real EM machine (see figure).
|
||||||
.KF
|
.TS
|
||||||
.DS L
|
center;
|
||||||
.ta 8 16 24 32 40 48 56 64 72
|
cw(3.5c) cw(3c) cw(3.5c)
|
||||||
EM machine target machine
|
cw(3.5c) cw(3c) cw(3.5c)
|
||||||
|
|cw(3.5c)| cw(3c) |cw(3.5c)| .
|
||||||
| | | |
|
EM machine target machine
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | real stack |
|
|
||||||
| | | | |
|
|
||||||
| | | | | growing
|
|
||||||
| EM stack | | | |
|
|
||||||
| | |_______________| \e|/
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | fake stack |
|
|
||||||
| | | |
|
|
||||||
|_______________| |_______________|
|
|
||||||
|
|
||||||
|
|
||||||
.I
|
|
||||||
Relation between EM stack, real stack and fake stack.
|
|
||||||
.R
|
|
||||||
.DE
|
real stack
|
||||||
.KE
|
stack
|
||||||
|
grows
|
||||||
|
EM stack \s+2\(br\s0
|
||||||
|
\s+2\(br\s0
|
||||||
|
\s+2\(br\s0 _
|
||||||
|
\s+2\(br\s0
|
||||||
|
\s+2\(da\s0
|
||||||
|
fake stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_ _
|
||||||
|
.T&
|
||||||
|
ci s s.
|
||||||
|
Relation between EM stack, real stack and fake stack.
|
||||||
|
.TE
|
||||||
During code generation tokens will be kept on the fake stack as long
|
During code generation tokens will be kept on the fake stack as long
|
||||||
as possible but when they are moved to the real stack,
|
as possible but when they are moved to the real stack,
|
||||||
by generating code for the push,
|
by generating code for the push,
|
||||||
all tokens above\u*\d
|
all tokens above\v'-.25m'\(dg\v'.25m'
|
||||||
.FS
|
.FS
|
||||||
* in this document the stack is assumed to grow downwards,
|
\(dg in this document the stack is assumed to grow downwards,
|
||||||
although the top of the stack will mean the first element that will
|
although the top of the stack will mean the first element that will
|
||||||
be popped.
|
be popped.
|
||||||
.FE
|
.FE
|
||||||
@@ -233,7 +234,7 @@ to register variables in the rest of this document.
|
|||||||
.PP
|
.PP
|
||||||
The front ends generate messages to the back ends telling them which
|
The front ends generate messages to the back ends telling them which
|
||||||
local variables could go into registers.
|
local variables could go into registers.
|
||||||
The information given is the offset of the local, it's size and type
|
The information given is the offset of the local, its size and type
|
||||||
and a scoring number, roughly the number of times it occurs.
|
and a scoring number, roughly the number of times it occurs.
|
||||||
.PP
|
.PP
|
||||||
The decision which variable to put in which register is taken by the
|
The decision which variable to put in which register is taken by the
|
||||||
@@ -297,8 +298,9 @@ at will to improve legibility.
|
|||||||
Identifiers used in the table have the same syntax as C identifiers,
|
Identifiers used in the table have the same syntax as C identifiers,
|
||||||
upper and lower case considered different, all characters significant.
|
upper and lower case considered different, all characters significant.
|
||||||
Here is a list of reserved words; all of these are unavailable as identifiers.
|
Here is a list of reserved words; all of these are unavailable as identifiers.
|
||||||
.DS L
|
.TS
|
||||||
.ta 14 28 42 56
|
box;
|
||||||
|
l l l l l.
|
||||||
ADDR STACK from reg_any test
|
ADDR STACK from reg_any test
|
||||||
COERCIONS STACKINGRULES gen reg_float to
|
COERCIONS STACKINGRULES gen reg_float to
|
||||||
INSTRUCTIONS TESTS highw reg_loop ufit
|
INSTRUCTIONS TESTS highw reg_loop ufit
|
||||||
@@ -309,7 +311,7 @@ PROPERTIES cost loww reusing
|
|||||||
REGISTERS defined move rom
|
REGISTERS defined move rom
|
||||||
SETS exact pat samesign
|
SETS exact pat samesign
|
||||||
SIZEFACTOR example proc sfit
|
SIZEFACTOR example proc sfit
|
||||||
.DE
|
.TE
|
||||||
C style comments are accepted.
|
C style comments are accepted.
|
||||||
.DS
|
.DS
|
||||||
/* this is a comment */
|
/* this is a comment */
|
||||||
@@ -330,7 +332,7 @@ NAME=value
|
|||||||
.DE
|
.DE
|
||||||
value being an integer or string.
|
value being an integer or string.
|
||||||
Three constants must be defined here:
|
Three constants must be defined here:
|
||||||
.IP EM_WSIZE 10
|
.IP EM_WSIZE 14
|
||||||
Number of bytes in a machine word.
|
Number of bytes in a machine word.
|
||||||
This is the number of bytes
|
This is the number of bytes
|
||||||
a \fBloc\fP instruction will put on the stack.
|
a \fBloc\fP instruction will put on the stack.
|
||||||
@@ -360,21 +362,21 @@ This is given as
|
|||||||
FORMAT = string
|
FORMAT = string
|
||||||
.DE
|
.DE
|
||||||
The string must be a valid printf(III) format,
|
The string must be a valid printf(III) format,
|
||||||
and defaults to "%d" or "%ld" depending on the wordsize of
|
and defaults to "%ld".
|
||||||
the machine. For example on the PDP-11 one can use
|
For example on the PDP-11 one can use
|
||||||
.DS
|
.DS
|
||||||
FORMAT= "0%o"
|
FORMAT= "0%lo"
|
||||||
.DE
|
.DE
|
||||||
to satisfy the old UNIX assembler that reads octal unless followed by
|
to satisfy the old UNIX assembler that reads octal unless followed by
|
||||||
a period, and the ACK assembler that follows C conventions.
|
a period, and the ACK assembler that follows C conventions.
|
||||||
.PP
|
.PP
|
||||||
Tables under control of programs like
|
Tables under control of source code control systems like
|
||||||
.I sccs
|
.I sccs
|
||||||
or
|
or
|
||||||
.I rcs
|
.I rcs
|
||||||
can put their id-string here, for example
|
can put their id-string here, for example
|
||||||
.DS
|
.DS
|
||||||
rcsid="$Header$"
|
rcsid="$\&Header$"
|
||||||
.DE
|
.DE
|
||||||
These strings, like all strings in the table, will eventually
|
These strings, like all strings in the table, will eventually
|
||||||
end up in the binary code generator produced.
|
end up in the binary code generator produced.
|
||||||
@@ -385,6 +387,7 @@ same order of magnitude.
|
|||||||
This can be done as
|
This can be done as
|
||||||
.DS
|
.DS
|
||||||
SIZEFACTOR = C\d3\u/C\d4\u
|
SIZEFACTOR = C\d3\u/C\d4\u
|
||||||
|
.sp
|
||||||
TIMEFACTOR = C\d1\u/C\d2\u
|
TIMEFACTOR = C\d1\u/C\d2\u
|
||||||
.DE
|
.DE
|
||||||
Above numbers must be read as rational numbers.
|
Above numbers must be read as rational numbers.
|
||||||
@@ -403,24 +406,24 @@ It consists of a list of user-defined
|
|||||||
identifiers optionally followed by the size
|
identifiers optionally followed by the size
|
||||||
of the property in parentheses, default EM_WSIZE.
|
of the property in parentheses, default EM_WSIZE.
|
||||||
Example for the PDP-11:
|
Example for the PDP-11:
|
||||||
.DS
|
.TS
|
||||||
.ta 8 16 24 32 40
|
l l.
|
||||||
PROPERTIES /* The header word for this section */
|
PROPERTIES /* The header word for this section */
|
||||||
|
|
||||||
GENREG /* All PDP registers */
|
GENREG /* All PDP registers */
|
||||||
REG /* Normal registers (allocatable) */
|
REG /* Normal registers (allocatable) */
|
||||||
ODDREG /* All odd registers (allocatable) */
|
ODDREG /* All odd registers (allocatable) */
|
||||||
REGPAIR(4) /* Register pairs for division */
|
REGPAIR(4) /* Register pairs for division */
|
||||||
FLTREG(4) /* Floating point registers */
|
FLTREG(4) /* Floating point registers */
|
||||||
DBLREG(8) /* Same, double precision */
|
DBLREG(8) /* Same, double precision */
|
||||||
GENFREG(4) /* generic floating point */
|
GENFREG(4) /* generic floating point */
|
||||||
GENDREG(8) /* Same, double precision */
|
GENDREG(8) /* Same, double precision */
|
||||||
FLTREGPAIR(8) /* register pair for modf */
|
FLTREGPAIR(8) /* register pair for modf */
|
||||||
DBLREGPAIR(16) /* Same, double precision */
|
DBLREGPAIR(16) /* Same, double precision */
|
||||||
LOCALBASE /* Guess what */
|
LOCALBASE /* Guess what */
|
||||||
STACKPOINTER
|
STACKPOINTER
|
||||||
PROGRAMCOUNTER
|
PROGRAMCOUNTER
|
||||||
.DE
|
.TE
|
||||||
Registers are allocated by asking for a property,
|
Registers are allocated by asking for a property,
|
||||||
so if for some reason in later parts of the table
|
so if for some reason in later parts of the table
|
||||||
one particular register must be allocated it
|
one particular register must be allocated it
|
||||||
@@ -438,22 +441,22 @@ Syntax:
|
|||||||
<register> : ident [ '(' string ')' ] [ '=' ident [ '+' ident ] ]
|
<register> : ident [ '(' string ')' ] [ '=' ident [ '+' ident ] ]
|
||||||
.DE
|
.DE
|
||||||
Example for the PDP-11:
|
Example for the PDP-11:
|
||||||
.DS L
|
.TS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
l l.
|
||||||
REGISTERS
|
REGISTERS
|
||||||
|
|
||||||
r0,r2,r4 : GENREG,REG.
|
r0,r2,r4 : GENREG,REG.
|
||||||
r1,r3 : GENREG,REG,ODDREG.
|
r1,r3 : GENREG,REG,ODDREG.
|
||||||
r01("r0")=r0+r1 : REGPAIR.
|
r01("r0")=r0+r1 : REGPAIR.
|
||||||
fr0("r0"),fr1("r1"),fr2("r2"),fr3("r3") : GENFREG,FLTREG.
|
fr0("r0"),fr1("r1"),fr2("r2"),fr3("r3") : GENFREG,FLTREG.
|
||||||
dr0("r0")=fr0,dr1("r1")=fr1,
|
dr0("r0")=fr0,dr1("r1")=fr1,
|
||||||
dr2("r2")=fr2,dr3("r3")=fr3 : GENDREG,DBLREG.
|
dr2("r2")=fr2,dr3("r3")=fr3 : GENDREG,DBLREG.
|
||||||
fr01("r0")=fr0+fr1,fr23("r2")=fr2+fr3 : FLTREGPAIR.
|
fr01("r0")=fr0+fr1,fr23("r2")=fr2+fr3 : FLTREGPAIR.
|
||||||
dr01("r0")=dr0+dr1,dr23("r2")=dr2+dr3 : DBLREGPAIR.
|
dr01("r0")=dr0+dr1,dr23("r2")=dr2+dr3 : DBLREGPAIR.
|
||||||
lb("r5") : GENREG,LOCALBASE.
|
lb("r5") : GENREG,LOCALBASE.
|
||||||
sp : GENREG,STACKPOINTER.
|
sp : GENREG,STACKPOINTER.
|
||||||
pc : GENREG,PROGRAMCOUNTER.
|
pc : GENREG,PROGRAMCOUNTER.
|
||||||
.DE
|
.TE
|
||||||
.PP
|
.PP
|
||||||
The names in the left hand lists are names of registers as used
|
The names in the left hand lists are names of registers as used
|
||||||
in the table.
|
in the table.
|
||||||
@@ -525,20 +528,21 @@ Tokens should usually be declared for every addressing mode
|
|||||||
of the machine at hand and for every size directly usable in
|
of the machine at hand and for every size directly usable in
|
||||||
a machine instruction.
|
a machine instruction.
|
||||||
Example for the PDP-11 (incomplete):
|
Example for the PDP-11 (incomplete):
|
||||||
.DS L
|
.TS
|
||||||
|
l l.
|
||||||
TOKENS
|
TOKENS
|
||||||
|
|
||||||
const2 = { INT num; } 2 cost(2,300) "$" num .
|
const2 = { INT num; } 2 cost(2,300) "$" num .
|
||||||
addr_local = { INT ind; } 2 .
|
addr_local = { INT ind; } 2 .
|
||||||
addr_external = { ADDR off; } 2 "$" off.
|
addr_external = { ADDR off; } 2 "$" off.
|
||||||
|
|
||||||
regdef2 = { GENREG reg; } 2 "*" reg.
|
regdef2 = { GENREG reg; } 2 "*" reg.
|
||||||
regind2 = { GENREG reg; ADDR off; } 2 off "(" reg ")" .
|
regind2 = { GENREG reg; ADDR off; } 2 off "(" reg ")" .
|
||||||
reginddef2 = { GENREG reg; ADDR off; } 2 "*" off "(" reg ")" .
|
reginddef2 = { GENREG reg; ADDR off; } 2 "*" off "(" reg ")" .
|
||||||
regconst2 = { GENREG reg; ADDR off; } 2 .
|
regconst2 = { GENREG reg; ADDR off; } 2 .
|
||||||
relative2 = { ADDR off; } 2 off .
|
relative2 = { ADDR off; } 2 off .
|
||||||
reldef2 = { ADDR off; } 2 "*" off.
|
reldef2 = { ADDR off; } 2 "*" off.
|
||||||
.DE
|
.TE
|
||||||
.PP
|
.PP
|
||||||
Types allowed in the struct are ADDR, INT and all register properties.
|
Types allowed in the struct are ADDR, INT and all register properties.
|
||||||
The type ADDR means a string and an integer,
|
The type ADDR means a string and an integer,
|
||||||
@@ -574,7 +578,7 @@ that can adjust the time/space tradeoff to all positions
|
|||||||
from 100% time to 100% space.
|
from 100% time to 100% space.
|
||||||
.LP
|
.LP
|
||||||
By supplying different code rules in certain situations
|
By supplying different code rules in certain situations
|
||||||
it is possible to get a code generator that can adjust it's
|
it is possible to get a code generator that can adjust its
|
||||||
code to the need of the moment.
|
code to the need of the moment.
|
||||||
This is probably most useful with small machines,
|
This is probably most useful with small machines,
|
||||||
experience has shown that on the larger micro's and mini's
|
experience has shown that on the larger micro's and mini's
|
||||||
@@ -620,21 +624,21 @@ in the remainder of the table,
|
|||||||
but for clarity it is usually better not to.
|
but for clarity it is usually better not to.
|
||||||
.LP
|
.LP
|
||||||
Example for the PDP-11 (incomplete):
|
Example for the PDP-11 (incomplete):
|
||||||
.DS L
|
.TS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
l l.
|
||||||
SETS
|
SETS
|
||||||
|
|
||||||
src2 = GENREG + regdef2 + regind2 + reginddef2 + relative2 +
|
src2 = GENREG + regdef2 + regind2 + reginddef2 + relative2 +
|
||||||
reldef2 + addr_external + const2 + LOCAL + ILOCAL +
|
\h'\w'= 'u'reldef2 + addr_external + const2 + LOCAL + ILOCAL +
|
||||||
autodec + autoinc .
|
\h'\w'= 'u'autodec + autoinc .
|
||||||
dst2 = src2 - ( const2 + addr_external ) .
|
dst2 = src2 - ( const2 + addr_external ) .
|
||||||
xsrc2 = src2 + ftoint .
|
xsrc2 = src2 + ftoint .
|
||||||
src1 = regdef1 + regind1 + reginddef1 + relative1 + reldef1 .
|
src1 = regdef1 + regind1 + reginddef1 + relative1 + reldef1 .
|
||||||
dst1 = src1 .
|
dst1 = src1 .
|
||||||
src1or2 = src1 + src2 .
|
src1or2 = src1 + src2 .
|
||||||
src4 = relative4 + regdef4 + DLOCAL + regind4 .
|
src4 = relative4 + regdef4 + DLOCAL + regind4 .
|
||||||
dst4 = src4 .
|
dst4 = src4 .
|
||||||
.DE
|
.TE
|
||||||
Permissible in the set construction are all the usual set operators, i.e.
|
Permissible in the set construction are all the usual set operators, i.e.
|
||||||
.IP +
|
.IP +
|
||||||
set union
|
set union
|
||||||
@@ -1154,9 +1158,10 @@ This can of course be done with
|
|||||||
.DS
|
.DS
|
||||||
kills ALL
|
kills ALL
|
||||||
.DE
|
.DE
|
||||||
or by ending the stack pattern with the word STACK, which is equivalent,
|
or by ending the stack pattern with the word STACK,
|
||||||
if the stack pattern does not start with
|
if the stack pattern does not start with
|
||||||
.I exact .
|
.I exact .
|
||||||
|
The latter does not erase the contents of registers.
|
||||||
.PP
|
.PP
|
||||||
It is unfortunate that this part is still present in the table
|
It is unfortunate that this part is still present in the table
|
||||||
but it is too much for now to let the
|
but it is too much for now to let the
|
||||||
@@ -1248,7 +1253,7 @@ The author of
|
|||||||
.I cgg
|
.I cgg
|
||||||
could not get
|
could not get
|
||||||
.I yacc
|
.I yacc
|
||||||
to be silent without it.
|
to accept his syntax without it.
|
||||||
Sorry about this.
|
Sorry about this.
|
||||||
.IP 2)
|
.IP 2)
|
||||||
a
|
a
|
||||||
@@ -1366,20 +1371,19 @@ A list of examples for the PDP-11 is given here.
|
|||||||
Far from being complete it gives examples of most kinds
|
Far from being complete it gives examples of most kinds
|
||||||
of instructions.
|
of instructions.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat loc yields {const2, $1}
|
pat loc yields {const2, $1}
|
||||||
|
|
||||||
pat ldc yields {const2, loww($1)}
|
pat ldc yields {const2, loww($1)} {const2, highw($1)}
|
||||||
{const2, highw($1)}
|
|
||||||
.DE
|
.DE
|
||||||
These simple patterns just push one or more tokens onto the fake stack.
|
These simple patterns just push one or more tokens onto the fake stack.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat lof
|
pat lof
|
||||||
with REG yields {regind2,%1,$1}
|
with REG yields {regind2,%1,$1}
|
||||||
with exact regconst2 yields {regind2,%1.reg,$1+%1.off}
|
with exact regconst2 yields {regind2,%1.reg,$1+%1.off}
|
||||||
with exact addr_external yields {relative2,$1+%1.off}
|
with exact addr_external yields {relative2,$1+%1.off}
|
||||||
with exact addr_local yields {LOCAL, %1.ind + $1,2}
|
with exact addr_local yields {LOCAL, %1.ind + $1,2}
|
||||||
.DE
|
.DE
|
||||||
This pattern shows the possibility to do different things
|
This pattern shows the possibility to do different things
|
||||||
depending on the fake stack contents,
|
depending on the fake stack contents,
|
||||||
@@ -1389,13 +1393,12 @@ not preceded by
|
|||||||
that can always be taken after a coercion,
|
that can always be taken after a coercion,
|
||||||
if necessary.
|
if necessary.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat lxl $1>3
|
pat lxl $1>3
|
||||||
uses REG={LOCAL, SL, 2},
|
uses REG={LOCAL, SL, 2}, REG={const2,$1-1}
|
||||||
REG={const2,$1-1}
|
|
||||||
gen 1:
|
gen 1:
|
||||||
move {regind2,%a, SL},%a
|
move {regind2,%a, SL},%a
|
||||||
sob %b,{label,1b} yields %a
|
sob %b,{label,1b} yields %a
|
||||||
.DE
|
.DE
|
||||||
This rule shows register allocation with initialisation,
|
This rule shows register allocation with initialisation,
|
||||||
and the use of a temporary label.
|
and the use of a temporary label.
|
||||||
@@ -1404,7 +1407,7 @@ of the static link,
|
|||||||
that is pushed by the Pascal compiler as the last argument of
|
that is pushed by the Pascal compiler as the last argument of
|
||||||
a function.
|
a function.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat stf
|
pat stf
|
||||||
with regconst2 xsrc2
|
with regconst2 xsrc2
|
||||||
kills allexeptcon
|
kills allexeptcon
|
||||||
@@ -1419,7 +1422,7 @@ part in a store instruction.
|
|||||||
The set allexeptcon contains all tokens that can be the destination
|
The set allexeptcon contains all tokens that can be the destination
|
||||||
of an indirect store.
|
of an indirect store.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat sde
|
pat sde
|
||||||
with exact FLTREG
|
with exact FLTREG
|
||||||
kills posextern
|
kills posextern
|
||||||
@@ -1445,51 +1448,52 @@ The third rule is taken by default,
|
|||||||
resulting in two separate stores,
|
resulting in two separate stores,
|
||||||
nothing better exists on the PDP-11.
|
nothing better exists on the PDP-11.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat sbi $1==2
|
pat sbi $1==2
|
||||||
with src2 REG
|
with src2 REG
|
||||||
gen sub %1,%2 yields %2
|
gen sub %1,%2 yields %2
|
||||||
with exact REG src2-REG
|
with exact REG src2-REG
|
||||||
gen sub %2,%1
|
gen sub %2,%1
|
||||||
neg %1 yields %1
|
neg %1 yields %1
|
||||||
.DE
|
.DE
|
||||||
This rule for
|
This rule for
|
||||||
.I sbi
|
.I sbi
|
||||||
has a normal first part,
|
has a normal first part,
|
||||||
and a hand optimized special case as it's second part.
|
and a hand optimized special case as its second part.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat mli $1==2
|
pat mli $1==2
|
||||||
with ODDREG src2
|
with ODDREG src2
|
||||||
gen mul %2,%1 yields %1
|
gen mul %2,%1 yields %1
|
||||||
with src2 ODDREG
|
with src2 ODDREG
|
||||||
gen mul %1,%2 yields %2
|
gen mul %1,%2 yields %2
|
||||||
.DE
|
.DE
|
||||||
This shows the general property for rules with commutative
|
This shows the general property for rules with commutative
|
||||||
operators,
|
operators,
|
||||||
heuristics or look ahead will have to decide which rule is the best.
|
heuristics or look ahead will have to decide which rule is the best.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat loc sli $1==1 && $2==2
|
pat loc sli $1==1 && $2==2
|
||||||
with REG
|
with REG
|
||||||
gen asl %1 yields %1
|
gen asl %1 yields %1
|
||||||
.DE
|
.DE
|
||||||
A simple rule involving a longer EM-pattern,
|
A simple rule involving a longer EM-pattern,
|
||||||
to make use of a specialized instruction available.
|
to make use of a specialized instruction available.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat loc loc cii $1==1 && $2==2
|
pat loc loc cii $1==1 && $2==2
|
||||||
with src1or2
|
with src1or2
|
||||||
uses reusing %1,REG
|
uses reusing %1,REG
|
||||||
gen movb %1,%a yields %a
|
gen movb %1,%a yields %a
|
||||||
.DE
|
.DE
|
||||||
A somewhat more complicated example of the same.
|
A somewhat more complicated example of the same.
|
||||||
Note the
|
Note the
|
||||||
.I reusing
|
.I reusing
|
||||||
clause.
|
clause.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat loc loc loc cii $1>=0 && $2==2 && $3==4 leaving loc $1 loc 0
|
pat loc loc loc cii $1>=0 && $2==2 && $3==4
|
||||||
|
leaving loc $1 loc 0
|
||||||
.DE
|
.DE
|
||||||
Shows a trivial example of EM-replacement.
|
Shows a trivial example of EM-replacement.
|
||||||
This is a rule that could be done by the
|
This is a rule that could be done by the
|
||||||
@@ -1498,40 +1502,40 @@ if word order in longs was defined in EM.
|
|||||||
On a `big-endian' machine the two replacement
|
On a `big-endian' machine the two replacement
|
||||||
instructions would be the other way around.
|
instructions would be the other way around.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat and $1==2
|
pat and $1==2
|
||||||
with const2 REG
|
with const2 REG
|
||||||
gen bic {const2,~%1.num},%2 yields %2
|
gen bic {const2,~%1.num},%2 yields %2
|
||||||
with REG const2
|
with REG const2
|
||||||
gen bic {const2,~%2.num},%1 yields %1
|
gen bic {const2,~%2.num},%1 yields %1
|
||||||
with REG REG
|
with REG REG
|
||||||
gen com %1
|
gen com %1
|
||||||
bic %1,%2 yields %2
|
bic %1,%2 yields %2
|
||||||
.DE
|
.DE
|
||||||
Shows the way you have to twist the table,
|
Shows the way you have to twist the table,
|
||||||
if an
|
if an
|
||||||
.I and -instruction
|
.I and -instruction
|
||||||
is not available on your machine.
|
is not available on your machine.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat set $1==2
|
pat set $1==2
|
||||||
with REG
|
with REG
|
||||||
uses REG={const2,1}
|
uses REG={const2,1}
|
||||||
gen ash %1,%a yields %a
|
gen ash %1,%a yields %a
|
||||||
.DE
|
.DE
|
||||||
Shows the building of a word-size set.
|
Shows the building of a word-size set.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)==0
|
pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)==0
|
||||||
leaving adi 2
|
leaving adi 2
|
||||||
|
|
||||||
pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)!=0
|
pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)!=0
|
||||||
leaving adi 2 adp 0-rom($1,1)
|
leaving adi 2 adp 0-rom($1,1)
|
||||||
.DE
|
.DE
|
||||||
Two rules showing the use of the rom pseudo function,
|
Two rules showing the use of the rom pseudo function,
|
||||||
and some array optimalisation.
|
and some array optimalisation.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat bra
|
pat bra
|
||||||
with STACK
|
with STACK
|
||||||
gen jbr {label, $1}
|
gen jbr {label, $1}
|
||||||
@@ -1540,7 +1544,7 @@ A simple jump.
|
|||||||
The stack pattern guarantees that everything will be stacked
|
The stack pattern guarantees that everything will be stacked
|
||||||
before the jump is taken.
|
before the jump is taken.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat cal
|
pat cal
|
||||||
with STACK
|
with STACK
|
||||||
gen jsr pc,{label, $1}
|
gen jsr pc,{label, $1}
|
||||||
@@ -1548,9 +1552,9 @@ gen jsr pc,{label, $1}
|
|||||||
A simple call.
|
A simple call.
|
||||||
Same comments as previous rule.
|
Same comments as previous rule.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat lfr $1==2 yields r0
|
pat lfr $1==2 yields r0
|
||||||
pat lfr $1==4 yields r1 r0
|
pat lfr $1==4 yields r1 r0
|
||||||
.DE
|
.DE
|
||||||
Shows the return area conventions of the PDP-11 table.
|
Shows the return area conventions of the PDP-11 table.
|
||||||
At this point a reminder:
|
At this point a reminder:
|
||||||
@@ -1560,7 +1564,7 @@ instruction, and some other instructions must leave
|
|||||||
the function return area intact.
|
the function return area intact.
|
||||||
See the defining document for EM for exact information.
|
See the defining document for EM for exact information.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat ret $1==0
|
pat ret $1==0
|
||||||
with STACK
|
with STACK
|
||||||
gen mov lb,sp
|
gen mov lb,sp
|
||||||
@@ -1574,7 +1578,7 @@ In a table with register variables the
|
|||||||
part would just contain
|
part would just contain
|
||||||
.I return .
|
.I return .
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat blm
|
pat blm
|
||||||
with REG REG
|
with REG REG
|
||||||
uses REG={const2,$1/2}
|
uses REG={const2,$1/2}
|
||||||
@@ -1592,16 +1596,16 @@ It uses the marriage thesis from Hall,
|
|||||||
a thesis from combinatorial mathematics,
|
a thesis from combinatorial mathematics,
|
||||||
to accomplish this.
|
to accomplish this.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat exg $1==2
|
pat exg $1==2
|
||||||
with src2 src2 yields %1 %2
|
with src2 src2 yields %1 %2
|
||||||
.DE
|
.DE
|
||||||
This rule shows the exchanging of two elements on the fake stack.
|
This rule shows the exchanging of two elements on the fake stack.
|
||||||
.NH 2
|
.NH 2
|
||||||
Code rules using procedures
|
Code rules using procedures
|
||||||
.PP
|
.PP
|
||||||
To start this chapter it must be admitted at once that the
|
To start this section it must be admitted at once that the
|
||||||
word procedure is chosen here mainly for it's advertising
|
word procedure is chosen here mainly for its advertising
|
||||||
value.
|
value.
|
||||||
It more resembles a glorified goto but this of course can
|
It more resembles a glorified goto but this of course can
|
||||||
not be admitted in the glossy brochures.
|
not be admitted in the glossy brochures.
|
||||||
@@ -1660,12 +1664,12 @@ The string `*' can be used as an equivalent for `[1]'.
|
|||||||
Just in case this is not clear, here is an example for
|
Just in case this is not clear, here is an example for
|
||||||
a procedure to increment/decrement a register.
|
a procedure to increment/decrement a register.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
incop REG:rw:cc . /* in the INSTRUCTIONS part of course */
|
incop REG:rw:cc . /* in the INSTRUCTIONS part of course */
|
||||||
|
|
||||||
proc incdec
|
proc incdec
|
||||||
with REG
|
with REG
|
||||||
gen incop* %1 yields %1
|
gen incop* %1 yields %1
|
||||||
.DE
|
.DE
|
||||||
The procedure is called with parameter "inc" or "dec".
|
The procedure is called with parameter "inc" or "dec".
|
||||||
.PP
|
.PP
|
||||||
@@ -1676,18 +1680,18 @@ call <identifier> '(' string [ ',' string ] ')'
|
|||||||
.DE
|
.DE
|
||||||
which leads to the following large example:
|
which leads to the following large example:
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
proc bxx example beq
|
proc bxx example beq
|
||||||
with src2 src2 STACK
|
with src2 src2 STACK
|
||||||
gen cmp %2,%1
|
gen cmp %2,%1
|
||||||
jxx* {label, $1}
|
jxx* {label, $1}
|
||||||
|
|
||||||
pat blt call bxx("jlt")
|
pat blt call bxx("jlt")
|
||||||
pat ble call bxx("jle")
|
pat ble call bxx("jle")
|
||||||
pat beq call bxx("jeq")
|
pat beq call bxx("jeq")
|
||||||
pat bne call bxx("jne")
|
pat bne call bxx("jne")
|
||||||
pat bgt call bxx("jgt")
|
pat bgt call bxx("jgt")
|
||||||
pat bge call bxx("jge")
|
pat bge call bxx("jge")
|
||||||
.DE
|
.DE
|
||||||
.NH 2
|
.NH 2
|
||||||
Move definitions
|
Move definitions
|
||||||
@@ -1852,38 +1856,38 @@ The next part of the table defines the coercions that are possible
|
|||||||
on the defined tokens.
|
on the defined tokens.
|
||||||
Example for the PDP-11:
|
Example for the PDP-11:
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
COERCIONS
|
COERCIONS
|
||||||
|
|
||||||
from STACK
|
from STACK
|
||||||
uses REG
|
uses REG
|
||||||
gen mov {autoinc,sp},%a yields %a
|
gen mov {autoinc,sp},%a yields %a
|
||||||
|
|
||||||
from STACK
|
from STACK
|
||||||
uses DBLREG
|
uses DBLREG
|
||||||
gen movf {autoinc,sp},%a yields %a
|
gen movf {autoinc,sp},%a yields %a
|
||||||
|
|
||||||
from STACK
|
from STACK
|
||||||
uses REGPAIR
|
uses REGPAIR
|
||||||
gen mov {autoinc,sp},%a.1
|
gen mov {autoinc,sp},%a.1
|
||||||
mov {autoinc,sp},%a.2 yields %a
|
mov {autoinc,sp},%a.2 yields %a
|
||||||
.DE
|
.DE
|
||||||
These three coercions just deliver a certain type
|
These three coercions just deliver a certain type
|
||||||
of register by popping it from the real stack.
|
of register by popping it from the real stack.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
from LOCAL yields {regind2,lb,%1.ind}
|
from LOCAL yields {regind2,lb,%1.ind}
|
||||||
|
|
||||||
from DLOCAL yields {regind4,lb,%1.ind}
|
from DLOCAL yields {regind4,lb,%1.ind}
|
||||||
|
|
||||||
from REG yields {regconst2, %1, 0}
|
from REG yields {regconst2, %1, 0}
|
||||||
.DE
|
.DE
|
||||||
These three are zero-cost rewriting rules.
|
These three are zero-cost rewriting rules.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
from regconst2 %1.off==1
|
from regconst2 %1.off==1
|
||||||
uses reusing %1,REG=%1.reg
|
uses reusing %1,REG=%1.reg
|
||||||
gen inc %a yields %a
|
gen inc %a yields %a
|
||||||
|
|
||||||
from regconst2
|
from regconst2
|
||||||
uses reusing %1,REG=%1.reg
|
uses reusing %1,REG=%1.reg
|
||||||
@@ -1892,7 +1896,7 @@ gen add {addr_external, %1.off},%a yields %a
|
|||||||
from addr_local
|
from addr_local
|
||||||
uses REG
|
uses REG
|
||||||
gen mov lb,%a
|
gen mov lb,%a
|
||||||
add {const2, %1.ind},%a yields %a
|
add {const2, %1.ind},%a yields %a
|
||||||
.DE
|
.DE
|
||||||
The last three are three different cases of the coercion
|
The last three are three different cases of the coercion
|
||||||
register+constant to register.
|
register+constant to register.
|
||||||
@@ -1900,19 +1904,19 @@ Only in the last case is it always necessary to allocate
|
|||||||
an extra register,
|
an extra register,
|
||||||
since arithmetic on the localbase is unthinkable.
|
since arithmetic on the localbase is unthinkable.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
from xsrc2
|
from xsrc2
|
||||||
uses reusing %1, REG=%1 yields %a
|
uses reusing %1, REG=%1 yields %a
|
||||||
|
|
||||||
from longf4
|
from longf4
|
||||||
uses FLTREG=%1 yields %a
|
uses FLTREG=%1 yields %a
|
||||||
|
|
||||||
from double8
|
from double8
|
||||||
uses DBLREG=%1 yields %a
|
uses DBLREG=%1 yields %a
|
||||||
|
|
||||||
from src1
|
from src1
|
||||||
uses REG={const2,0}
|
uses REG={const2,0}
|
||||||
gen bisb %1,%a yields %a
|
gen bisb %1,%a yields %a
|
||||||
.DE
|
.DE
|
||||||
These examples show the coercion of different
|
These examples show the coercion of different
|
||||||
tokens to a register of the needed type.
|
tokens to a register of the needed type.
|
||||||
@@ -1921,14 +1925,14 @@ ensure bytes are not sign-extended.
|
|||||||
In EM it is defined that the result of a \fBloi\fP\ 1
|
In EM it is defined that the result of a \fBloi\fP\ 1
|
||||||
instruction is an integer in the range 0..255.
|
instruction is an integer in the range 0..255.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
from REGPAIR yields %1.2 %1.1
|
from REGPAIR yields %1.2 %1.1
|
||||||
|
|
||||||
from regind4 yields {regind2,%1.reg,2+%1.off}
|
from regind4 yields {regind2,%1.reg,2+%1.off}
|
||||||
{regind2,%1.reg,%1.off}
|
{regind2,%1.reg,%1.off}
|
||||||
|
|
||||||
from relative4 yields {relative2,2+%1.off}
|
from relative4 yields {relative2,2+%1.off}
|
||||||
{relative2,%1.off}
|
{relative2,%1.off}
|
||||||
.DE
|
.DE
|
||||||
The last examples are splitting rules.
|
The last examples are splitting rules.
|
||||||
.PP
|
.PP
|
||||||
@@ -1953,7 +1957,7 @@ and TEM_PSIZE.
|
|||||||
The type 'int' is used for things like counters that won't require
|
The type 'int' is used for things like counters that won't require
|
||||||
more than 16 bits precision.
|
more than 16 bits precision.
|
||||||
The type 'word' is used among others to assemble datawords and
|
The type 'word' is used among others to assemble datawords and
|
||||||
is of type 'long' if TEM_WSIZE>2.
|
is of type 'long'.
|
||||||
The type 'full' is used for addresses and is of type 'long' if
|
The type 'full' is used for addresses and is of type 'long' if
|
||||||
TEM_WSIZE>2 or TEM_PSIZE>2.
|
TEM_WSIZE>2 or TEM_PSIZE>2.
|
||||||
.PP
|
.PP
|
||||||
@@ -2082,25 +2086,25 @@ If omitted no initialization is assumed.
|
|||||||
.NH 3
|
.NH 3
|
||||||
Example mach.h for the PDP-11
|
Example mach.h for the PDP-11
|
||||||
.DS L
|
.DS L
|
||||||
.ta 8 16 24 32 40 48 56
|
.ta 4c
|
||||||
#define ex_ap(y) fprintf(codefile,"\et.globl %s\en",y)
|
#define ex_ap(y) fprintf(codefile,"\et.globl %s\en",y)
|
||||||
#define in_ap(y) /* nothing */
|
#define in_ap(y) /* nothing */
|
||||||
|
|
||||||
#define newplb(x) fprintf(codefile,"%s:\en",x)
|
#define newplb(x) fprintf(codefile,"%s:\en",x)
|
||||||
#define newilb(x) fprintf(codefile,"%s:\en",x)
|
#define newilb(x) fprintf(codefile,"%s:\en",x)
|
||||||
#define newdlb(x) fprintf(codefile,"%s:\en",x)
|
#define newdlb(x) fprintf(codefile,"%s:\en",x)
|
||||||
#define dlbdlb(x,y) fprintf(codefile,"%s=%s\en",x,y)
|
#define dlbdlb(x,y) fprintf(codefile,"%s=%s\en",x,y)
|
||||||
#define newlbss(l,x) fprintf(codefile,"%s:.=.+%d.\en",l,x);
|
#define newlbss(l,x) fprintf(codefile,"%s:.=.+%d.\en",l,x);
|
||||||
|
|
||||||
#define cst_fmt "$%d."
|
#define cst_fmt "$%d."
|
||||||
#define off_fmt "%d."
|
#define off_fmt "%d."
|
||||||
#define ilb_fmt "I%02x%x"
|
#define ilb_fmt "I%x_%x"
|
||||||
#define dlb_fmt "_%d"
|
#define dlb_fmt "_%d"
|
||||||
#define hol_fmt "hol%d"
|
#define hol_fmt "hol%d"
|
||||||
|
|
||||||
#define hol_off "%d.+hol%d"
|
#define hol_off "%ld.+hol%d"
|
||||||
|
|
||||||
#define con_cst(x) fprintf(codefile,"%d.\en",x)
|
#define con_cst(x) fprintf(codefile,"%ld.\en",x)
|
||||||
#define con_ilb(x) fprintf(codefile,"%s\en",x)
|
#define con_ilb(x) fprintf(codefile,"%s\en",x)
|
||||||
#define con_dlb(x) fprintf(codefile,"%s\en",x)
|
#define con_dlb(x) fprintf(codefile,"%s\en",x)
|
||||||
|
|
||||||
@@ -2153,7 +2157,7 @@ mes(w_mesno)
|
|||||||
This function is called when a
|
This function is called when a
|
||||||
.B mes
|
.B mes
|
||||||
pseudo is seen that is not handled by the machine independent part.
|
pseudo is seen that is not handled by the machine independent part.
|
||||||
Example below shows all you probably have to know about that.
|
The example below shows all you probably have to know about that.
|
||||||
.IP -
|
.IP -
|
||||||
segname[]
|
segname[]
|
||||||
.br
|
.br
|
||||||
@@ -2212,7 +2216,7 @@ Example mach.c for the PDP-11
|
|||||||
As an example of the sort of code expected,
|
As an example of the sort of code expected,
|
||||||
the mach.c for the PDP-11 is presented here.
|
the mach.c for the PDP-11 is presented here.
|
||||||
.DS L
|
.DS L
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 0.5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i
|
||||||
/*
|
/*
|
||||||
* machine dependent back end routines for the PDP-11
|
* machine dependent back end routines for the PDP-11
|
||||||
*/
|
*/
|
||||||
@@ -2678,7 +2682,7 @@ otherwise the register is marked empty.
|
|||||||
.NH 4
|
.NH 4
|
||||||
DO_INSTR
|
DO_INSTR
|
||||||
.PP
|
.PP
|
||||||
This prints an instruction and it's operands.
|
This prints an instruction and its operands.
|
||||||
Only done on toplevel.
|
Only done on toplevel.
|
||||||
.NH 4
|
.NH 4
|
||||||
DO_MOVE
|
DO_MOVE
|
||||||
|
|||||||
68
doc/z80.doc
Normal file
68
doc/z80.doc
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
THE Z80 BACK END TABLE
|
||||||
|
|
||||||
|
INTRODUCTION
|
||||||
|
|
||||||
|
This table was written to make it run, not to make it clever!
|
||||||
|
The effect is, that the table written for the intel 8080,
|
||||||
|
which was made very clever runs faster and requiers less space!!
|
||||||
|
So, for anyone to run programs on a z80 machine:
|
||||||
|
You could try to make the table as clever as the one for the i80,
|
||||||
|
or you could run the i80 table, for that can run on every z80 too.
|
||||||
|
|
||||||
|
IMPLEMENTATION
|
||||||
|
|
||||||
|
It will not be possible to run the entire Amsterdam Compiler Kit on a
|
||||||
|
Z80-based computer system.
|
||||||
|
One has to write a program on another
|
||||||
|
system, a system where the compiler kit runs on.
|
||||||
|
This program may be a mixture of high-level languages, such as
|
||||||
|
C or Pascal, EM and z80 assembly code.
|
||||||
|
The program should be compiled using the compiler kit,
|
||||||
|
producing z80 machine code.
|
||||||
|
This code should come available to the z80 machine
|
||||||
|
for example by downloading or
|
||||||
|
by storing it in ROM (Read Only Memory).
|
||||||
|
Depending on the characteristics of the particular z80 based system, some
|
||||||
|
adaptions have to be made:
|
||||||
|
1) In 'head_em': the base address, which is the address where the first
|
||||||
|
z80 instruction will be stored, and the initial value of the
|
||||||
|
stackpointer are set to 0x1000 and 0x7ffe respectivally.
|
||||||
|
The latter because it could run on a 32K machine as well.
|
||||||
|
Other systems require other values.
|
||||||
|
2) In 'head_em': before calling "_m_a_i_n", the environment
|
||||||
|
pointer, argument vector and argument count will have to be pushed
|
||||||
|
onto the stack.
|
||||||
|
Since this back-end is tested on a system without any knowledge
|
||||||
|
of these things, dummies are pushed now.
|
||||||
|
3) In 'tail_em': proper routines "putchar" and "getchar" should
|
||||||
|
be provided.
|
||||||
|
They should write resp. read a character on/from the monitor.
|
||||||
|
Maybe some conversions will have to be made.
|
||||||
|
The ones for the Nascom and Hermac z80 micro's are to be found
|
||||||
|
in the EM-library.
|
||||||
|
4) In 'head_em': an application program returns control to the monitor by
|
||||||
|
jumping to address 0x20.
|
||||||
|
If this is not the right way on your system, change it.
|
||||||
|
For an CPM-machine for example this should be 0x5, to provide a warm boot.
|
||||||
|
5) In 'tail_em': the current version of the z80 back-end has very limited I/O
|
||||||
|
capabilities, because it was tested on a system that
|
||||||
|
had no knowlegde of files.
|
||||||
|
So the implementation of the EM-instruction 'mon' is very simple;
|
||||||
|
it can only do the following things:
|
||||||
|
Monitor call 1:
|
||||||
|
Exit
|
||||||
|
Monitor call 3:
|
||||||
|
read, always reads from the monitor.
|
||||||
|
echos the read character.
|
||||||
|
ignores file descriptor.
|
||||||
|
Monitor call 4:
|
||||||
|
write, always writes on the monitor.
|
||||||
|
ignores file descriptor.
|
||||||
|
Monitor call 5:
|
||||||
|
open file, returns file descriptor -1.
|
||||||
|
Monitor call 6:
|
||||||
|
close file, returns error code = 0.
|
||||||
|
Monitor call 54:
|
||||||
|
io-control, returns error code = 0.
|
||||||
|
If the system should do file-handling the routine ".mon"
|
||||||
|
should be extended thoroughly.
|
||||||
22
first/first
22
first/first
@@ -4,6 +4,21 @@ then :
|
|||||||
else
|
else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
: check write-ability of /tmp and /usr/tmp
|
||||||
|
if ( >/usr/tmp/aaax.$$ )
|
||||||
|
then
|
||||||
|
rm /usr/tmp/aaax.$$
|
||||||
|
else
|
||||||
|
echo /usr/tmp must exist and be writable.
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if ( >/tmp/aaax.$$ )
|
||||||
|
then
|
||||||
|
rm /tmp/aaax.$$
|
||||||
|
else
|
||||||
|
echo /tmp must exist and be writable.
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
: set ACK HOME Directory in ../h/em_path.h
|
: set ACK HOME Directory in ../h/em_path.h
|
||||||
rm -f em_path.h
|
rm -f em_path.h
|
||||||
sed -e "/^#define[ ]*EM_DIR/s@\".*\"@\"`cd .. ; pwd`\"@" <../h/em_path.h >em_path.h
|
sed -e "/^#define[ ]*EM_DIR/s@\".*\"@\"`cd .. ; pwd`\"@" <../h/em_path.h >em_path.h
|
||||||
@@ -31,7 +46,6 @@ vax_bsd4_1c VAX11 with BSD4.1c
|
|||||||
vax_bsd4_2 VAX11 with BSD4.2
|
vax_bsd4_2 VAX11 with BSD4.2
|
||||||
pc_ix IBM PC with PC/IX
|
pc_ix IBM PC with PC/IX
|
||||||
m68_unisoft Motorola 68000 with Unisoft UNIX
|
m68_unisoft Motorola 68000 with Unisoft UNIX
|
||||||
m68_pmds Philips PMDS
|
|
||||||
ANY Neither of the above
|
ANY Neither of the above
|
||||||
|
|
||||||
system type: "
|
system type: "
|
||||||
@@ -40,9 +54,8 @@ system type: "
|
|||||||
echo echo "$SYSNAME" >../bin/ack_sys
|
echo echo "$SYSNAME" >../bin/ack_sys
|
||||||
chmod +x ../bin/ack_sys
|
chmod +x ../bin/ack_sys
|
||||||
case `ack_sys` in
|
case `ack_sys` in
|
||||||
pdp_v7|vax_bsd4_1[ac]|vax_bsd4_2|pc_ix|m68_unisoft|m68_pmds) ;;
|
pdp_v7|vax_bsd4_1[ac]|vax_bsd4_2|pc_ix|m68_unisoft) ;;
|
||||||
*) echo None of the software especially intended for
|
*) echo None of the software especially intended for the named systems will work ;;
|
||||||
the named systems will work ;;
|
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
echo Sorry, got EOF when reading system name.
|
echo Sorry, got EOF when reading system name.
|
||||||
@@ -95,7 +108,6 @@ vax_bsd4_1[ac]) ACM=vax2 ;;
|
|||||||
vax_bsd4_2) ACM=vax2 ;;
|
vax_bsd4_2) ACM=vax2 ;;
|
||||||
pc_ix) ACM=ix ;;
|
pc_ix) ACM=ix ;;
|
||||||
m68_unisoft) ACM=m68k2 ;;
|
m68_unisoft) ACM=m68k2 ;;
|
||||||
m68_pmds) ACM=pmds ;;
|
|
||||||
*) ACM=m68k2 ;;
|
*) ACM=m68k2 ;;
|
||||||
esac
|
esac
|
||||||
rm -f local.h
|
rm -f local.h
|
||||||
|
|||||||
@@ -4,4 +4,4 @@
|
|||||||
# define VERSION 3 /* 16 bits number */
|
# define VERSION 3 /* 16 bits number */
|
||||||
|
|
||||||
/* The default machine used by ack, acc, apc */
|
/* The default machine used by ack, acc, apc */
|
||||||
# define ACKM "vax2"
|
# define ACKM "pdp"
|
||||||
|
|||||||
120
h/out.h
120
h/out.h
@@ -1,120 +0,0 @@
|
|||||||
/* $Header$ */
|
|
||||||
/*
|
|
||||||
* output format for ACK assemblers
|
|
||||||
*/
|
|
||||||
#ifndef ushort
|
|
||||||
#define ushort unsigned short
|
|
||||||
#endif ushort
|
|
||||||
|
|
||||||
struct outhead {
|
|
||||||
ushort oh_magic; /* magic number */
|
|
||||||
ushort oh_stamp; /* version stamp */
|
|
||||||
ushort oh_flags; /* several format flags */
|
|
||||||
ushort oh_nsect; /* number of outsect structures */
|
|
||||||
ushort oh_nrelo; /* number of outrelo structures */
|
|
||||||
ushort oh_nname; /* number of outname structures */
|
|
||||||
long oh_nemit; /* sum of all os_flen */
|
|
||||||
long oh_nchar; /* size of string area */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define O_MAGIC 0x0201 /* magic number of output file */
|
|
||||||
#define O_STAMP 0 /* version stamp */
|
|
||||||
|
|
||||||
#ifdef JOHAN
|
|
||||||
#define HF_BREV 0x0001 /* high order byte lowest address */
|
|
||||||
#define HF_WREV 0x0002 /* high order word lowest address */
|
|
||||||
#endif JOHAN
|
|
||||||
#define HF_LINK 0x0004 /* unresolved references left */
|
|
||||||
#define HF_8086 0x0008 /* os_base specially encoded */
|
|
||||||
|
|
||||||
struct outsect {
|
|
||||||
long os_base; /* startaddress in machine */
|
|
||||||
long os_size; /* section size in machine */
|
|
||||||
long os_foff; /* startaddress in file */
|
|
||||||
long os_flen; /* section size in file */
|
|
||||||
long os_lign; /* section alignment */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct outrelo {
|
|
||||||
char or_type; /* type of reference */
|
|
||||||
char or_sect; /* referencing section */
|
|
||||||
ushort or_nami; /* referenced symbol index */
|
|
||||||
long or_addr; /* referencing address */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct outname {
|
|
||||||
union {
|
|
||||||
char *on_ptr; /* symbol name (in core) */
|
|
||||||
long on_off; /* symbol name (in file) */
|
|
||||||
} on_u;
|
|
||||||
#define on_mptr on_u.on_ptr
|
|
||||||
#define on_foff on_u.on_off
|
|
||||||
ushort on_type; /* symbol type */
|
|
||||||
ushort on_desc; /* debug info */
|
|
||||||
long on_valu; /* symbol value */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* relocation type bits
|
|
||||||
*/
|
|
||||||
#define RELSZ 0x07 /* relocation length */
|
|
||||||
#define RELO1 1 /* 1 byte */
|
|
||||||
#define RELO2 2 /* 2 bytes */
|
|
||||||
#define RELO4 4 /* 4 bytes */
|
|
||||||
#define RELPC 0x08 /* pc relative */
|
|
||||||
#ifndef JOHAN
|
|
||||||
#define RELBR 0x10 /* High order byte lowest address. */
|
|
||||||
#define RELWR 0x20 /* High order word lowest address. */
|
|
||||||
#endif JOHAN
|
|
||||||
|
|
||||||
/*
|
|
||||||
* section type bits and fields
|
|
||||||
*/
|
|
||||||
#define S_TYP 0x007F /* undefined, absolute or relative */
|
|
||||||
#define S_EXT 0x0080 /* external flag */
|
|
||||||
#define S_ETC 0x7F00 /* for symbolic debug, bypassing 'as' */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* S_TYP field values
|
|
||||||
*/
|
|
||||||
#define S_UND 0x0000 /* undefined item */
|
|
||||||
#define S_ABS 0x0001 /* absolute item */
|
|
||||||
#define S_MIN 0x0002 /* first user section */
|
|
||||||
#define S_MAX S_TYP /* last user section */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* S_ETC field values
|
|
||||||
*/
|
|
||||||
#define S_SCT 0x0100 /* section names */
|
|
||||||
#define S_LIN 0x0200 /* hll source line item */
|
|
||||||
#define S_FIL 0x0300 /* hll source file item */
|
|
||||||
#define S_MOD 0x0400 /* ass source file item */
|
|
||||||
#ifndef JOHAN
|
|
||||||
#define S_COM 0x1000 /* Common name. */
|
|
||||||
#endif JOHAN
|
|
||||||
|
|
||||||
/*
|
|
||||||
* structure format strings
|
|
||||||
*/
|
|
||||||
#define SF_HEAD "22222244"
|
|
||||||
#define SF_SECT "44444"
|
|
||||||
#define SF_RELO "1124"
|
|
||||||
#define SF_NAME "4224"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* structure sizes (bytes in file; add digits in SF_*)
|
|
||||||
*/
|
|
||||||
#define SZ_HEAD 20
|
|
||||||
#define SZ_SECT 20
|
|
||||||
#define SZ_RELO 8
|
|
||||||
#define SZ_NAME 12
|
|
||||||
|
|
||||||
/*
|
|
||||||
* file access macros
|
|
||||||
*/
|
|
||||||
#define BADMAGIC(x) ((x).oh_magic!=O_MAGIC)
|
|
||||||
#define OFF_SECT(x) SZ_HEAD
|
|
||||||
#define OFF_EMIT(x) (OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
|
|
||||||
#define OFF_RELO(x) (OFF_EMIT(x) + (x).oh_nemit)
|
|
||||||
#define OFF_NAME(x) (OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
|
|
||||||
#define OFF_CHAR(x) (OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))
|
|
||||||
25
h/ranlib.h
25
h/ranlib.h
@@ -1,25 +0,0 @@
|
|||||||
/* $Header$ */
|
|
||||||
|
|
||||||
#ifndef SYMDEF
|
|
||||||
# define SYMDEF "__.SYMDEF"
|
|
||||||
#endif SYMDEF
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structure of the SYMDEF table of contents for an archive.
|
|
||||||
* SYMDEF begins with a long giving the number of ranlib
|
|
||||||
* structures that immediately follow, and then continues with a string
|
|
||||||
* table consisting of a long giving the number of bytes of
|
|
||||||
* strings that follow and then the strings themselves.
|
|
||||||
*/
|
|
||||||
struct ranlib {
|
|
||||||
union {
|
|
||||||
char *ran__ptr; /* symbol name (in core) */
|
|
||||||
long ran__off; /* symbol name (in file) */
|
|
||||||
} ran_u;
|
|
||||||
#define ran_ptr ran_u.ran__ptr
|
|
||||||
#define ran_off ran_u.ran__off
|
|
||||||
long ran_pos; /* library member is at this position */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SZ_RAN 8
|
|
||||||
#define SF_RAN "44"
|
|
||||||
@@ -19,7 +19,7 @@ double d;
|
|||||||
String *s;
|
String *s;
|
||||||
|
|
||||||
s= _newstr(buffer);
|
s= _newstr(buffer);
|
||||||
* ( (double *)s->strval ) = i ;
|
* ( (double *)s->strval ) = d ;
|
||||||
return(s);
|
return(s);
|
||||||
}
|
}
|
||||||
long _cvi(s)
|
long _cvi(s)
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
# $Revision$
|
|
||||||
var w=2
|
|
||||||
var i=2
|
|
||||||
var p=2
|
|
||||||
var s=2
|
|
||||||
var l=4
|
|
||||||
var f=4
|
|
||||||
var d=8
|
|
||||||
var NAME=m6805
|
|
||||||
var M=6805
|
|
||||||
var LIB=lib/{M}/tail_
|
|
||||||
var RT=lib/{M}/head_
|
|
||||||
var INCLUDES=-I{EM}/include -I/usr/include
|
|
||||||
name asld
|
|
||||||
from .s.a
|
|
||||||
to .out
|
|
||||||
outfile a.out
|
|
||||||
program {EM}/lib/{M}/as
|
|
||||||
mapflag -l* LNAME={EM}/{LIB}*
|
|
||||||
mapflag -d* ASFL={ASFL?} -d*
|
|
||||||
args {ASFL?} (.e:{HEAD}={EM}/{RT}em) \
|
|
||||||
({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
|
||||||
(.p:{TAIL}={EM}/{LIB}pc) \
|
|
||||||
(.b:{TAIL}={EM}/{LIB}bc) \
|
|
||||||
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
|
||||||
(.b.c.p:{TAIL}={EM}/{LIB}mon) \
|
|
||||||
(.e:{TAIL}={EM}/{LIB}em)
|
|
||||||
linker
|
|
||||||
end
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# $Revision$
|
|
||||||
var w=2
|
|
||||||
var p=2
|
|
||||||
var s=2
|
|
||||||
var l=4
|
|
||||||
var f=4
|
|
||||||
var d=8
|
|
||||||
var NAME=i8086
|
|
||||||
var M=i86
|
|
||||||
var LIB=lib/i86/tail_
|
|
||||||
var LIBIBM=lib/ibm/tail_
|
|
||||||
var RT=lib/i86/head_
|
|
||||||
var RTIBM=lib/ibm/head_
|
|
||||||
var CPP_F=-Dunix
|
|
||||||
var INCLUDES=-I{EM}/include -I{EM}/lib/ibm/include
|
|
||||||
name be
|
|
||||||
from .m.g
|
|
||||||
to .s
|
|
||||||
program {EM}/lib/{M}/cg
|
|
||||||
args <
|
|
||||||
stdout
|
|
||||||
need .e
|
|
||||||
end
|
|
||||||
name asld
|
|
||||||
from .s.a
|
|
||||||
to .out
|
|
||||||
outfile a.out
|
|
||||||
program {EM}/lib/{M}/as
|
|
||||||
mapflag -l* LNAME={EM}/{LIB}*
|
|
||||||
mapflag -i IFILE={EM}/{RT}i
|
|
||||||
args {IFILE?} (.e:{HEAD}={EM}/{RTIBM}em) \
|
|
||||||
({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
|
||||||
(.p:{TAIL}={EM}/{LIB}pc) \
|
|
||||||
(.b:{TAIL}={EM}/{LIB}bc) \
|
|
||||||
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
|
||||||
(.e:{TAIL}={EM}/{LIBIBM}em) \
|
|
||||||
(.b.c.p:{TAIL}={EM}/{LIBIBM}mon) \
|
|
||||||
(.e:{TAIL}={EM}/{LIBIBM}em.vend)
|
|
||||||
linker
|
|
||||||
end
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# $Revision$
|
|
||||||
var w=2
|
|
||||||
var p=4
|
|
||||||
var s=2
|
|
||||||
var l=4
|
|
||||||
var f=4
|
|
||||||
var d=8
|
|
||||||
var NAME=m68k2
|
|
||||||
var M=m68k2
|
|
||||||
var LIBDIR=/lib/{M}
|
|
||||||
var LIB=lib/{M}/tail_
|
|
||||||
var RT=lib/{M}/head_
|
|
||||||
var INCLUDES=-I{EM}/include -I/usr/include
|
|
||||||
name be
|
|
||||||
from .m.g
|
|
||||||
to .s
|
|
||||||
program {EM}/lib/{M}/cg
|
|
||||||
args <
|
|
||||||
stdout
|
|
||||||
need .e
|
|
||||||
end
|
|
||||||
name asld
|
|
||||||
from .s.a
|
|
||||||
to .out
|
|
||||||
outfile a.out
|
|
||||||
program {EM}/lib/{M}/as
|
|
||||||
mapflag -l* LNAME={EM}/{LIB}*
|
|
||||||
args (.e:{HEAD}={EM}/{RT}em) \
|
|
||||||
({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
|
||||||
(.p.c.b:{TAIL}={EM}/{LIBDIR}/sys1.s) (.p:{TAIL}={EM}/{LIBDIR}/sys2.s) \
|
|
||||||
(.c:{TAIL}={EM}/{LIBDIR}/write.s) \
|
|
||||||
(.p:{TAIL}={EM}/{LIB}pc) \
|
|
||||||
(.b:{TAIL}={EM}/{LIB}bc) \
|
|
||||||
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
|
||||||
(.b.c:{TAIL}={EM}/{LIB}mon {EM}/{LIB}fake) \
|
|
||||||
(.e:{TAIL}={EM}/{LIB}em.rt {EM}/{LIB}em.vend)
|
|
||||||
prep cond
|
|
||||||
linker
|
|
||||||
end
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# $Revision$
|
|
||||||
var w=1
|
|
||||||
var p=2
|
|
||||||
var s=1
|
|
||||||
var l=2
|
|
||||||
var f=4
|
|
||||||
var d=8
|
|
||||||
var NAME=nascom
|
|
||||||
var M=z80a
|
|
||||||
var LIB=lib/{M}/tail_
|
|
||||||
var RT=lib/{M}/head_
|
|
||||||
var INCLUDES=-I{EM}/include -I/usr/include
|
|
||||||
name be
|
|
||||||
from .m.g
|
|
||||||
to .s
|
|
||||||
program {EM}/lib/{M}/be
|
|
||||||
args <
|
|
||||||
stdout
|
|
||||||
need .e
|
|
||||||
end
|
|
||||||
name asld
|
|
||||||
from .s.a
|
|
||||||
to .out
|
|
||||||
outfile a.out
|
|
||||||
program {EM}/lib/z80/as
|
|
||||||
mapflag -l* LNAME={EM}/{LIB}*
|
|
||||||
args (.e:{HEAD}={EM}/{RT}em) ({RTS}:.b.c={EM}/{RT}cc) -o > \
|
|
||||||
(.e:{TAIL}={EM}/{LIB}em.1 {EM}/{LIB}em.2)
|
|
||||||
linker
|
|
||||||
end
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
var w=2
|
|
||||||
var p=2
|
|
||||||
var s=2
|
|
||||||
var l=4
|
|
||||||
var f=4
|
|
||||||
var d=8
|
|
||||||
var NAME=i8086
|
|
||||||
var M=i86
|
|
||||||
var LIB=mach/i86/lib/tail_
|
|
||||||
var RT=mach/i86/lib/head_
|
|
||||||
var INCLUDES=-I{EM}/include -I/usr/include
|
|
||||||
name be
|
|
||||||
from .m
|
|
||||||
to .s
|
|
||||||
program {EM}/lib/{M}_cg
|
|
||||||
args <
|
|
||||||
prop >
|
|
||||||
need .e
|
|
||||||
end
|
|
||||||
name asld
|
|
||||||
from .s.a
|
|
||||||
to a.out
|
|
||||||
program {EM}/lib/{M}_as
|
|
||||||
mapflag -l* LNAME={EM}/{LIB}*
|
|
||||||
mapflag -i IFILE={EM}/{RT}i
|
|
||||||
args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \
|
|
||||||
({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
|
||||||
(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
|
||||||
(.c.p.e:{TAIL}={EM}/{LIB}netio) (.c.p.e:{TAIL}={EM}/{LIB}alo) \
|
|
||||||
(.c.p:{TAIL}={EM}/{LIB}mon) (.e:{TAIL}={EM}/{LIB}em)
|
|
||||||
prop C
|
|
||||||
end
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
var w=2
|
|
||||||
var p=2
|
|
||||||
var s=2
|
|
||||||
var l=4
|
|
||||||
var f=4
|
|
||||||
var d=8
|
|
||||||
var NAME=i8086
|
|
||||||
var M=i86
|
|
||||||
var LIB=mach/i86/lib/tail_
|
|
||||||
var ALIB=mach/i86/lib/sat_tail_
|
|
||||||
var RT=mach/i86/lib/head_
|
|
||||||
var ART=mach/i86/lib/sat_head_
|
|
||||||
var CCP_F=-Dunix
|
|
||||||
var INCLUDES=-I{EM}/include -I/usr/include
|
|
||||||
name be
|
|
||||||
from .m
|
|
||||||
to .s
|
|
||||||
program {EM}/lib/{M}_cg
|
|
||||||
args <
|
|
||||||
prop >
|
|
||||||
need .e
|
|
||||||
end
|
|
||||||
name asld
|
|
||||||
from .s.a
|
|
||||||
to a.out
|
|
||||||
program {EM}/lib/{M}_as
|
|
||||||
mapflag -l* LNAME={EM}/{LIB}*
|
|
||||||
args (.e:{HEAD}={EM}/{ART}em) \
|
|
||||||
({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
|
||||||
(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
|
||||||
(.c.p:{TAIL}={EM}/{ALIB}mon) (.c.p.e:{TAIL}={EM}/{LIB}alo) \
|
|
||||||
(.e:{TAIL}={EM}/{LIB}em)
|
|
||||||
prop C
|
|
||||||
end
|
|
||||||
@@ -6,7 +6,7 @@ var l=4
|
|||||||
var f=4
|
var f=4
|
||||||
var d=8
|
var d=8
|
||||||
var NAME=i8080
|
var NAME=i8080
|
||||||
var M=8080
|
var M=i80
|
||||||
var LIB=lib/{M}/tail_
|
var LIB=lib/{M}/tail_
|
||||||
var RT=lib/{M}/head_
|
var RT=lib/{M}/head_
|
||||||
var INCLUDES=-I{EM}/include -I/usr/include
|
var INCLUDES=-I{EM}/include -I/usr/include
|
||||||
@@ -31,6 +31,6 @@ name asld
|
|||||||
(.b:{TAIL}={EM}/{LIB}bc) \
|
(.b:{TAIL}={EM}/{LIB}bc) \
|
||||||
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
||||||
(.b.c.p:{TAIL}={EM}/{LIB}mon) \
|
(.b.c.p:{TAIL}={EM}/{LIB}mon) \
|
||||||
(.e:{TAIL}={EM}/{LIB}em)
|
(.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}sys)
|
||||||
linker
|
linker
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ end
|
|||||||
name asld
|
name asld
|
||||||
from .s.a
|
from .s.a
|
||||||
to .out
|
to .out
|
||||||
outfile a.out
|
|
||||||
program {EM}/lib/{M}/as
|
program {EM}/lib/{M}/as
|
||||||
mapflag -l* LNAME={EM}/{LIB}*
|
mapflag -l* LNAME={EM}/{LIB}*
|
||||||
args (.e:{HEAD}={EM}/{RT}em) \
|
args (.e:{HEAD}={EM}/{RT}em) \
|
||||||
@@ -34,3 +33,10 @@ name asld
|
|||||||
prep cond
|
prep cond
|
||||||
linker
|
linker
|
||||||
end
|
end
|
||||||
|
name cv
|
||||||
|
from .out
|
||||||
|
to .cv
|
||||||
|
program {EM}/lib/{M}/cv
|
||||||
|
args < >
|
||||||
|
outfile a.out
|
||||||
|
end
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# $Revision$
|
# $Revision 2.2$
|
||||||
var w=4
|
var w=4
|
||||||
var p=4
|
var p=4
|
||||||
var s=2
|
var s=2
|
||||||
@@ -7,32 +7,37 @@ var f=4
|
|||||||
var d=8
|
var d=8
|
||||||
var NAME=m68k4
|
var NAME=m68k4
|
||||||
var M=m68k4
|
var M=m68k4
|
||||||
var LIBDIR=/lib/{M}
|
var LIB=lib/m68k4/tail_
|
||||||
var LIB=lib/{M}/tail_
|
var RT=lib/m68k4/head_
|
||||||
var RT=lib/{M}/head_
|
|
||||||
var CPP_F=-Dunix
|
|
||||||
var INCLUDES=-I{EM}/include -I/usr/include
|
var INCLUDES=-I{EM}/include -I/usr/include
|
||||||
name be
|
name be
|
||||||
from .m.g
|
from .m
|
||||||
to .s
|
to .o
|
||||||
program {EM}/lib/{M}/cg
|
program {EM}/lib/{M}/cg
|
||||||
args <
|
args <
|
||||||
stdout
|
stdout
|
||||||
need .e
|
need .e
|
||||||
end
|
end
|
||||||
name asld
|
name asld
|
||||||
from .s.a
|
from .s.a.o
|
||||||
to .out
|
to .out
|
||||||
outfile a.out
|
|
||||||
program {EM}/lib/m68k2/as
|
program {EM}/lib/m68k2/as
|
||||||
mapflag -l* LNAME={EM}/{LIB}*
|
mapflag -l* LNAME={EM}/{LIB}*
|
||||||
args (.e:{HEAD}={EM}/{RT}em) \
|
mapflag -d* LFLAG={LFLAG?} -d*
|
||||||
({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
mapflag -s* LFLAG={LFLAG?} -s*
|
||||||
(.p.c.b:{TAIL}={EM}/{LIBDIR}/sys1.s) (.p:{TAIL}={EM}/{LIBDIR}/sys2.s) \
|
mapflag -n*
|
||||||
(.c.b:{TAIL}={EM}/{LIBDIR}/write.s) \
|
mapflag -i*
|
||||||
(.p:{TAIL}={EM}/{LIB}pc) (.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
args {LFLAG?} (.e:{HEAD}={EM}/{RT}em) \
|
||||||
(.c.b:{TAIL}={EM}/{LIB}mon {EM}/{LIB}fake) \
|
({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
||||||
(.e:{TAIL}={EM}/{LIB}em.rt {EM}/{LIB}em.vend)
|
(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
||||||
|
(.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em)
|
||||||
prep cond
|
prep cond
|
||||||
linker
|
linker
|
||||||
end
|
end
|
||||||
|
name cv
|
||||||
|
from .out
|
||||||
|
to .cv
|
||||||
|
program {EM}/lib/m68k2/cv
|
||||||
|
args < >
|
||||||
|
outfile a.out
|
||||||
|
end
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
# $Revision$
|
# $Revision$
|
||||||
# Script for use of ACK as cross C-compiler on VAX for PMDS machine
|
# Script for use of ACK as cross C-compiler on VAX for PMDS machine
|
||||||
# The output has its int's in the pmds order.
|
|
||||||
# Conversion from VU-a.out to PMDS-a.out should still be done on the pmds.
|
|
||||||
var w=2
|
var w=2
|
||||||
var p=4
|
var p=4
|
||||||
var s=2
|
var s=2
|
||||||
@@ -46,7 +44,7 @@ end
|
|||||||
name cv
|
name cv
|
||||||
from .out
|
from .out
|
||||||
to .cv
|
to .cv
|
||||||
program {EM}/lib/{PMDS}/pmcv
|
program {EM}/lib/{PMDS}/cv
|
||||||
args < >
|
args < >
|
||||||
outfile a.out
|
outfile a.out
|
||||||
end
|
end
|
||||||
|
|||||||
43
lib/pmds4/descr
Normal file
43
lib/pmds4/descr
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# $Header$
|
||||||
|
var w=4
|
||||||
|
var p=4
|
||||||
|
var s=2
|
||||||
|
var l=4
|
||||||
|
var f=4
|
||||||
|
var d=8
|
||||||
|
var NAME=m68k4
|
||||||
|
var M=m68k4
|
||||||
|
var LIB=mach/m68k4/lib/tail_
|
||||||
|
var RT=mach/m68k4/lib/head_
|
||||||
|
var INCLUDES=-I{EM}/include
|
||||||
|
name be
|
||||||
|
from .m
|
||||||
|
to .o
|
||||||
|
program {EM}/lib/{M}/cg
|
||||||
|
args <
|
||||||
|
stdout
|
||||||
|
need .e
|
||||||
|
end
|
||||||
|
name asld
|
||||||
|
from .s.a.o
|
||||||
|
to .out
|
||||||
|
program {EM}/lib/m68k2/as
|
||||||
|
mapflag -l* LNAME={EM}/{LIB}*
|
||||||
|
mapflag -d* LFLAG={LFLAG?} -d*
|
||||||
|
mapflag -s* LFLAG={LFLAG?} -s*
|
||||||
|
mapflag -n*
|
||||||
|
mapflag -i*
|
||||||
|
args {LFLAG?} (.e:{HEAD}={EM}/lib/pmds4/head_em) \
|
||||||
|
({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
||||||
|
(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
||||||
|
(.e:{TAIL}={EM}/{LIB}em {EM}/lib/pmds4/mon {EM}/end_em)
|
||||||
|
prep cond
|
||||||
|
linker
|
||||||
|
end
|
||||||
|
name cv
|
||||||
|
from .out
|
||||||
|
to .cv
|
||||||
|
program {EM}/lib/{PMDS}/cv
|
||||||
|
args < >
|
||||||
|
outfile a.out
|
||||||
|
end
|
||||||
@@ -24,13 +24,13 @@ name asld
|
|||||||
outfile a.out
|
outfile a.out
|
||||||
program {EM}/lib/{M}/as
|
program {EM}/lib/{M}/as
|
||||||
mapflag -l* LNAME={EM}/{LIB}*
|
mapflag -l* LNAME={EM}/{LIB}*
|
||||||
mapflag -i IFILE={EM}/{RT}i
|
mapflag -i
|
||||||
args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \
|
args (.e:{HEAD}={EM}/{RT}em) \
|
||||||
({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
|
||||||
(.p:{TAIL}={EM}/{LIB}pc) \
|
(.p:{TAIL}={EM}/{LIB}pc) \
|
||||||
(.b:{TAIL}={EM}/{LIB}bc) \
|
(.b:{TAIL}={EM}/{LIB}bc) \
|
||||||
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
|
||||||
(.b.c.p:{TAIL}={EM}/{LIB}mon) \
|
(.b.c.p:{TAIL}={EM}/{LIB}mon) \
|
||||||
(.e:{TAIL}={EM}/{LIB}em)
|
(.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}sys {EM}/lib/{M}/end_em)
|
||||||
linker
|
linker
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
.define endtext, enddata, endbss, end
|
.define endtext, enddata, endbss, end
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.align 2
|
|
||||||
endtext:
|
endtext:
|
||||||
|
.align 2
|
||||||
.data
|
.data
|
||||||
.align 2
|
.align 2
|
||||||
enddata:
|
enddata:
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
name "4-4 Interpreter C libraries"
|
name "4-4 Interpreter C libraries"
|
||||||
dir libcc
|
dir libcc
|
||||||
end
|
end
|
||||||
name "4-4 Interpreter Pascal library"
|
|
||||||
dir libpc
|
|
||||||
end
|
|
||||||
name "4-4 Interpreter Basic library"
|
name "4-4 Interpreter Basic library"
|
||||||
dir libbc
|
dir libbc
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ MACHDEF="MACH=int44" "SUF=m"
|
|||||||
BCDEF="PREF=bc" "SUB=" "SRC=lang/basic/lib"
|
BCDEF="PREF=bc" "SUB=" "SRC=lang/basic/lib"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
RANLIB=ranlib ; export RANLIB ;\
|
|
||||||
make -f $(MAKEFILE) $(BCDEF) $(MACHDEF) tailcp
|
make -f $(MAKEFILE) $(BCDEF) $(MACHDEF) tailcp
|
||||||
|
|
||||||
cmp:
|
cmp:
|
||||||
|
|||||||
@@ -1,3 +1,24 @@
|
|||||||
name "Intel 8080 assembler"
|
name "Intel 8080 assembler"
|
||||||
dir as
|
dir as
|
||||||
end
|
end
|
||||||
|
name "Intel 8080 code generator"
|
||||||
|
dir cg
|
||||||
|
end
|
||||||
|
name "Intel 8080 download programs"
|
||||||
|
dir dl
|
||||||
|
end
|
||||||
|
name "Intel 8080 Basic library"
|
||||||
|
dir libbc
|
||||||
|
end
|
||||||
|
name "Intel 8080 C libraries"
|
||||||
|
dir libcc
|
||||||
|
end
|
||||||
|
name "Intel 8080 EM library"
|
||||||
|
dir libem
|
||||||
|
end
|
||||||
|
name "Intel 8080 Pascal library"
|
||||||
|
dir libpc
|
||||||
|
end
|
||||||
|
name "Intel 8080 System library"
|
||||||
|
dir libsys
|
||||||
|
end
|
||||||
|
|||||||
19
mach/i80/dl/Makefile
Normal file
19
mach/i80/dl/Makefile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
head: mccpm nascom
|
||||||
|
|
||||||
|
mccpm: mccpm.c
|
||||||
|
cc -o mccpm mccpm.c
|
||||||
|
|
||||||
|
nascom: nascom.c
|
||||||
|
cc -o nascom nascom.c
|
||||||
|
|
||||||
|
install:
|
||||||
|
@echo Nothing is installed
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm nascom mccpm
|
||||||
|
|
||||||
|
pr:
|
||||||
|
@pr `pwd`/Makefile `pwd`/mccpm.c `pwd`/nascom.c
|
||||||
|
|
||||||
|
opr:
|
||||||
|
make pr | opr
|
||||||
5
mach/i80/dl/README
Normal file
5
mach/i80/dl/README
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
This directory contains files mccpm.c and nascom.c.
|
||||||
|
The first one downloads the mc/cpm
|
||||||
|
computer, using the standard Intel hex-dump format.
|
||||||
|
The output appears on standard output.
|
||||||
|
The latter does the same for the Nascom.
|
||||||
@@ -1,18 +1,32 @@
|
|||||||
static char rcsid[] = "$Header$";
|
/*
|
||||||
|
* dit programma leest een a.out file
|
||||||
|
* voor een kleine uP (adres space = 64K)
|
||||||
|
* en levert aan de standaard output een
|
||||||
|
* download formaat voor de MCCPM computer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#define MAXBYTE 24
|
#define MAXBYTE 24
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
char hex[] = "0123456789ABCDEF";
|
char hex[] = "0123456789ABCDEF";
|
||||||
FILE *fp, *fopen();
|
FILE *fp, *fopen();
|
||||||
char **s;
|
char **s;
|
||||||
int bytes, bytcnt, checksum;
|
int bytes, bytcnt, checksum;
|
||||||
long pc;
|
unsigned pc;
|
||||||
|
unsigned offset;
|
||||||
|
unsigned htou();
|
||||||
|
|
||||||
|
|
||||||
main (argc,argv)
|
main (argc,argv)
|
||||||
int argc;
|
int argc;
|
||||||
char *argv[];
|
char *argv[];
|
||||||
{
|
{
|
||||||
if (argc != 2) fatal ("usage: %s filename\n",argv[0]);
|
if (argc > 3)
|
||||||
|
fatal ("usage: %s filename [start-adres]\n",argv[0]);
|
||||||
|
offset = 0;
|
||||||
|
if (argc == 3)
|
||||||
|
if (!(offset = htou(argv[2])))
|
||||||
|
fatal ("adres error %s\n", argv[2]);
|
||||||
if ((fp = fopen (*++argv,"r")) == NULL)
|
if ((fp = fopen (*++argv,"r")) == NULL)
|
||||||
fatal ("can't open %s\n",*argv);
|
fatal ("can't open %s\n",*argv);
|
||||||
else {
|
else {
|
||||||
@@ -28,50 +42,44 @@ convert ()
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
pc = getword ();
|
pc = getword ();
|
||||||
pc = (pc << 16) | getword ();
|
pc -= offset;
|
||||||
|
bytes = getword ();
|
||||||
bytes = getword ();
|
bytes = getword ();
|
||||||
while (bytes != 0)
|
while (bytes != 0)
|
||||||
{
|
{
|
||||||
bytcnt = (bytes < MAXBYTE) ? bytes : MAXBYTE;
|
bytcnt = (bytes < MAXBYTE) ? bytes : MAXBYTE;
|
||||||
bytes -= bytcnt;
|
bytes -= bytcnt;
|
||||||
checksum = 0;
|
checksum = 0;
|
||||||
if (pc > 0xffffL) S2record (); else S1record ();
|
Irecord ();
|
||||||
}
|
}
|
||||||
c = getc (fp);
|
c = getc (fp);
|
||||||
ungetc (c, fp);
|
ungetc (c, fp);
|
||||||
}
|
}
|
||||||
while (c != EOF);
|
while (c != EOF);
|
||||||
printf ("S9030000FC\n");
|
printf (":00000001FF\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
S2record ()
|
Irecord ()
|
||||||
{
|
{
|
||||||
printf ("S2");
|
printf (":");
|
||||||
|
outbyte (bytcnt);
|
||||||
bytcnt += 4;
|
bytcnt += 4;
|
||||||
outbyte (bytcnt);
|
outbyte (pc >> 8);
|
||||||
outbyte (pc);
|
outbyte (pc);
|
||||||
|
outbyte (0);
|
||||||
record ();
|
record ();
|
||||||
}
|
}
|
||||||
|
|
||||||
S1record ()
|
|
||||||
{
|
|
||||||
printf ("S1");
|
|
||||||
bytcnt += 3;
|
|
||||||
outbyte (bytcnt);
|
|
||||||
record ();
|
|
||||||
}
|
|
||||||
|
|
||||||
record ()
|
record ()
|
||||||
{
|
{
|
||||||
outbyte (pc << 8);
|
|
||||||
outbyte (pc << 16);
|
|
||||||
while (bytcnt != 0)
|
while (bytcnt != 0)
|
||||||
{
|
{
|
||||||
outbyte (getbyte ());
|
outbyte (getbyte ());
|
||||||
pc ++;
|
pc ++;
|
||||||
}
|
}
|
||||||
outbyte (~checksum);
|
outbyte (-checksum);
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
putchar (0);
|
putchar (0);
|
||||||
putchar (0);
|
putchar (0);
|
||||||
@@ -80,9 +88,9 @@ record ()
|
|||||||
outbyte (b)
|
outbyte (b)
|
||||||
int b;
|
int b;
|
||||||
{
|
{
|
||||||
checksum = (checksum + b) & 0377;
|
checksum = (checksum + b) & 0xFF;
|
||||||
putchar (hex[(b>>4) & 017]);
|
putchar (hex[(b>>4) & 0xF]);
|
||||||
putchar (hex[b & 017]);
|
putchar (hex[b & 0xF]);
|
||||||
-- bytcnt;
|
-- bytcnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,3 +112,24 @@ fatal (s,a)
|
|||||||
printf (s,a);
|
printf (s,a);
|
||||||
exit (-1);
|
exit (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* convert a string of hex digits to an unsigned 16 bit number */
|
||||||
|
|
||||||
|
unsigned htou(t)
|
||||||
|
char *t;
|
||||||
|
{
|
||||||
|
unsigned n = 0;
|
||||||
|
char c;
|
||||||
|
while(c = *t++){
|
||||||
|
if(c >= '0' && c <= '9')
|
||||||
|
c -= '0';
|
||||||
|
else if(c >= 'a' && c <= 'f')
|
||||||
|
c -= 'a' - 10;
|
||||||
|
else if(c >= 'A' && c <= 'F')
|
||||||
|
c -= 'A' - 10;
|
||||||
|
else
|
||||||
|
return(0);
|
||||||
|
n = n * 16 + c;
|
||||||
|
}
|
||||||
|
return(n);
|
||||||
|
}
|
||||||
139
mach/i80/dl/nascom.c
Normal file
139
mach/i80/dl/nascom.c
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Download Z80 load module into the NASCOM
|
||||||
|
*
|
||||||
|
* Johan Stevenson, Vrije Universiteit, Amsterdam
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sgtty.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
int check;
|
||||||
|
int nascom = 1;
|
||||||
|
int nl = '\037';
|
||||||
|
int zero = 0;
|
||||||
|
int disp = 0;
|
||||||
|
|
||||||
|
char hex[] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
struct sgttyb ttynormal;
|
||||||
|
struct sgttyb ttyraw;
|
||||||
|
int rawmode = 0;
|
||||||
|
|
||||||
|
stop(code) {
|
||||||
|
if (rawmode)
|
||||||
|
stty(1, &ttynormal);
|
||||||
|
exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
main(argc,argv) char **argv; {
|
||||||
|
register unsigned nd,pc;
|
||||||
|
register char *s;
|
||||||
|
|
||||||
|
while (argc > 1 && argv[1][0] == '-') {
|
||||||
|
switch (argv[1][1]) {
|
||||||
|
case 'u':
|
||||||
|
/* unix output */
|
||||||
|
nascom = 0;
|
||||||
|
nl = '\n';
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
/* fill EPROM. make minimal change */
|
||||||
|
zero = 0xFF;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
/* displacement at load time */
|
||||||
|
disp = atoi(&argv[1][2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
s = "a.out";
|
||||||
|
if (argc == 2)
|
||||||
|
s = argv[1];
|
||||||
|
else if (argc != 1) {
|
||||||
|
fprintf(stderr,"usage: %s [flags] [object file]\n",argv[0]);
|
||||||
|
stop(-1);
|
||||||
|
}
|
||||||
|
if (freopen(s,"r",stdin) == NULL) {
|
||||||
|
fprintf(stderr,"%s: can't open %s\n",argv[0],s);
|
||||||
|
stop(-1);
|
||||||
|
}
|
||||||
|
if (nascom) {
|
||||||
|
signal(SIGHUP, SIG_IGN);
|
||||||
|
signal(SIGINT, SIG_IGN);
|
||||||
|
signal(SIGQUIT, stop);
|
||||||
|
signal(SIGTERM, stop);
|
||||||
|
if (gtty(1, &ttynormal) < 0) {
|
||||||
|
fprintf(stderr, "no tty\n");
|
||||||
|
stop(-1);
|
||||||
|
}
|
||||||
|
rawmode++;
|
||||||
|
ttyraw = ttynormal;
|
||||||
|
ttyraw.sg_flags |= RAW;
|
||||||
|
ttyraw.sg_ispeed = B1200;
|
||||||
|
ttyraw.sg_ospeed = B1200;
|
||||||
|
stty(1, &ttyraw);
|
||||||
|
sleep(5);
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
pc = get2c(stdin);
|
||||||
|
if (feof(stdin))
|
||||||
|
break;
|
||||||
|
nd = get2c(stdin);
|
||||||
|
nd = get2c(stdin);
|
||||||
|
if (nd > 256) {
|
||||||
|
fprintf(stderr,"bad format on %s\n",s);
|
||||||
|
stop(1);
|
||||||
|
}
|
||||||
|
while (nd > 8) {
|
||||||
|
data(8,pc);
|
||||||
|
nd -= 8;
|
||||||
|
pc += 8;
|
||||||
|
}
|
||||||
|
if (nd > 0)
|
||||||
|
data(nd,pc);
|
||||||
|
assert(feof(stdin) == 0);
|
||||||
|
}
|
||||||
|
putchar('.');
|
||||||
|
putchar(nl);
|
||||||
|
if (nascom)
|
||||||
|
sleep(5);
|
||||||
|
stop(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
data(nd,pc) {
|
||||||
|
register i;
|
||||||
|
|
||||||
|
check = 0;
|
||||||
|
pc += disp;
|
||||||
|
byte(pc>>8);
|
||||||
|
byte(pc);
|
||||||
|
for (i = 0; i < nd; i++) {
|
||||||
|
putchar(' ');
|
||||||
|
byte(getc(stdin));
|
||||||
|
}
|
||||||
|
while (i < 8) {
|
||||||
|
putchar(' ');
|
||||||
|
byte(zero);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
putchar(' ');
|
||||||
|
byte(check);
|
||||||
|
putchar(nl);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte(b) {
|
||||||
|
|
||||||
|
check += b;
|
||||||
|
putchar(hex[(b>>4) & 017]);
|
||||||
|
putchar(hex[b & 017]);
|
||||||
|
}
|
||||||
|
|
||||||
|
get2c(f) FILE *f; {
|
||||||
|
register c;
|
||||||
|
|
||||||
|
c = getc(f);
|
||||||
|
return((getc(f) << 8) | c);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
MAKEFILE=../../proto/libg/Makefile
|
MAKEFILE=../../proto/libg/Makefile
|
||||||
MACHDEF="MACH=8080" "SUF=s"
|
MACHDEF="MACH=i80" "SUF=s"
|
||||||
BCDEF="PREF=bc" "SUB=" "SRC=lang/basic/lib"
|
BCDEF="PREF=bc" "SUB=" "SRC=lang/basic/lib"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
${MACH?ack} -I../../../h ${MACHFL?} $1 1>&2
|
if ${MACH?ack} -DCPM -I../../../h ${MACHFL?} $1 1>&2
|
||||||
echo `basename $1 $2`.s
|
then echo `basename $1 $2`.s
|
||||||
|
else rm -f `basename $1 $2`.s
|
||||||
|
fi
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
MAKEFILE=../../proto/libg/Makefile
|
MAKEFILE=../../proto/libg/Makefile
|
||||||
MACHDEF="MACH=8080" "SUF=s"
|
MACHDEF="MACH=i80" "SUF=s"
|
||||||
STDIO="PREF=cc" "SUB=.1s" "SRC=lang/cem/libcc/stdio"
|
STDIO="PREF=cc" "SUB=.1s" "SRC=lang/cem/libcc/stdio"
|
||||||
GEN="PREF=cc" "SUB=.2g" "SRC=lang/cem/libcc/gen"
|
GEN="PREF=cc" "SUB=.2g" "SRC=lang/cem/libcc/gen"
|
||||||
MON="PREF=mon" "SRC=lang/cem/libcc/mon"
|
MON="PREF=mon" "SRC=lang/cem/libcc/mon"
|
||||||
|
|||||||
4
mach/i80/libcc/compmodule
Executable file
4
mach/i80/libcc/compmodule
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
if ${MACH?ack} -DCPM -I../../../h ${MACHFL?} $1 1>&2
|
||||||
|
then echo `basename $1 $2`.s
|
||||||
|
else rm -f `basename $1 $2`.s
|
||||||
|
fi
|
||||||
37
mach/i80/libem/LIST
Normal file
37
mach/i80/libem/LIST
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
tail
|
||||||
|
aar2.s
|
||||||
|
adi4.s
|
||||||
|
and.s
|
||||||
|
blm.s
|
||||||
|
cii.s
|
||||||
|
cmi4.s
|
||||||
|
cms.s
|
||||||
|
com.s
|
||||||
|
csa.s
|
||||||
|
csb.s
|
||||||
|
dup.s
|
||||||
|
dvi2.s
|
||||||
|
exg.s
|
||||||
|
inn.s
|
||||||
|
ior.s
|
||||||
|
lar2.s
|
||||||
|
mli2.s
|
||||||
|
mli4.s
|
||||||
|
mlu2.s
|
||||||
|
ngi4.s
|
||||||
|
nop.s
|
||||||
|
rol4.s
|
||||||
|
ror4.s
|
||||||
|
sar2.s
|
||||||
|
sbi4.s
|
||||||
|
set.s
|
||||||
|
set2.s
|
||||||
|
sli2.s
|
||||||
|
sli4.s
|
||||||
|
sri2.s
|
||||||
|
sri4.s
|
||||||
|
xor.s
|
||||||
|
loi.s
|
||||||
|
sti.s
|
||||||
|
dvi4.s
|
||||||
|
rck.s
|
||||||
14
mach/i80/libem/Makefile
Normal file
14
mach/i80/libem/Makefile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
install: tail
|
||||||
|
../../install tail tail_em
|
||||||
|
|
||||||
|
cmp: tail
|
||||||
|
-../../compare tail tail_em
|
||||||
|
|
||||||
|
tail:
|
||||||
|
arch cr `cat LIST`
|
||||||
|
|
||||||
|
opr:
|
||||||
|
make pr | opr
|
||||||
|
pr:
|
||||||
|
@pr `pwd`/Makefile
|
||||||
|
@pr -l33 `tail +1 LIST|sort`
|
||||||
42
mach/i80/libem/aar2.s
Normal file
42
mach/i80/libem/aar2.s
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
.define .aar2
|
||||||
|
|
||||||
|
! Load address of array element, decriptor contains 2-bytes integers
|
||||||
|
! Expects on stack: pointer to array descriptor
|
||||||
|
! index
|
||||||
|
! base address
|
||||||
|
! Yields on stack: address of array element
|
||||||
|
|
||||||
|
.aar2:
|
||||||
|
pop h
|
||||||
|
shld .retadr1
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop h ! hl = pointer to descriptor
|
||||||
|
pop d ! de = index
|
||||||
|
mov a,e ! bc = index - lower bound
|
||||||
|
sub m
|
||||||
|
inx h
|
||||||
|
mov c,a
|
||||||
|
mov a,d
|
||||||
|
sbb m
|
||||||
|
inx h
|
||||||
|
mov b,a
|
||||||
|
push b ! first operand to multiply
|
||||||
|
inx h
|
||||||
|
inx h
|
||||||
|
mov c,m ! bc = size
|
||||||
|
inx h
|
||||||
|
mov b,m
|
||||||
|
push b ! second operand to multiply
|
||||||
|
call .mli2 ! de = size * (index - lower bound)
|
||||||
|
pop h ! hl = base address
|
||||||
|
dad d ! hl = address of array[index]
|
||||||
|
push h
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr1
|
||||||
|
pchl
|
||||||
23
mach/i80/libem/adi4.s
Normal file
23
mach/i80/libem/adi4.s
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
.define .adi4
|
||||||
|
|
||||||
|
! Add two 32 bits signed or unsigned integers
|
||||||
|
! Expects on stack: operands
|
||||||
|
! Yields on stack: result
|
||||||
|
|
||||||
|
.adi4: pop h
|
||||||
|
shld .retadr ! get return address out of the way
|
||||||
|
pop d
|
||||||
|
pop h
|
||||||
|
xthl
|
||||||
|
dad d
|
||||||
|
shld .tmp1
|
||||||
|
pop d
|
||||||
|
pop h
|
||||||
|
jnc 1f
|
||||||
|
inx h
|
||||||
|
1: dad d
|
||||||
|
push h
|
||||||
|
lhld .tmp1
|
||||||
|
push h
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
37
mach/i80/libem/and.s
Normal file
37
mach/i80/libem/and.s
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
.define .and
|
||||||
|
|
||||||
|
! Any size logical-'and'.
|
||||||
|
! Expects: size in de-registers
|
||||||
|
! operands on stack
|
||||||
|
! Yields: result on stack
|
||||||
|
|
||||||
|
.and: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
mov c,l
|
||||||
|
mov b,h !now bc points to top of first operand
|
||||||
|
dad d !and hl points to top of second perand
|
||||||
|
push h !this will be the new stackpointer
|
||||||
|
1: ldax b
|
||||||
|
ana m
|
||||||
|
mov m,a
|
||||||
|
inx h
|
||||||
|
inx b
|
||||||
|
dcx d
|
||||||
|
mov a,e
|
||||||
|
ora d
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
pop h
|
||||||
|
sphl
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
31
mach/i80/libem/blm.s
Normal file
31
mach/i80/libem/blm.s
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
.define .blm
|
||||||
|
|
||||||
|
! Block move
|
||||||
|
! Expects in de-reg: size of block
|
||||||
|
! Expects on stack: destination address
|
||||||
|
! source address
|
||||||
|
|
||||||
|
.blm: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop h ! hl = destination address
|
||||||
|
pop b ! bc = source address
|
||||||
|
|
||||||
|
1: ldax b
|
||||||
|
mov m,a
|
||||||
|
inx b
|
||||||
|
inx h
|
||||||
|
dcx d
|
||||||
|
mov a,d
|
||||||
|
ora e
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
|
|
||||||
84
mach/i80/libem/cii.s
Normal file
84
mach/i80/libem/cii.s
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
.define .cii
|
||||||
|
|
||||||
|
! Convert integer to integer
|
||||||
|
! Expects in a-reg: 1 for signed integer to signed integer (cii)
|
||||||
|
! 0 for unsigned integer to unsigned integer (cuu)
|
||||||
|
! Expects on stack: destination size
|
||||||
|
! source size
|
||||||
|
! source
|
||||||
|
! Yields on stack: result
|
||||||
|
|
||||||
|
.cii: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
sta .areg ! save a-register
|
||||||
|
pop b
|
||||||
|
mov e,c
|
||||||
|
pop b ! c = source size
|
||||||
|
mov b,e ! b = destination size
|
||||||
|
mov a,b
|
||||||
|
cmp c
|
||||||
|
jz 3f ! destination size = source size
|
||||||
|
jc shrink ! destination size < source size
|
||||||
|
|
||||||
|
! if destination size > source size only:
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
mov e,l
|
||||||
|
mov d,h ! de = stackpointer
|
||||||
|
mov a,b
|
||||||
|
sub c ! c = (still) source size
|
||||||
|
mov b,a ! b = destination size - source size
|
||||||
|
cma
|
||||||
|
mov l,a
|
||||||
|
mvi h,255
|
||||||
|
inx h
|
||||||
|
dad d ! hl = stackpointer - (dest. size - source size)
|
||||||
|
sphl ! new stackpointer
|
||||||
|
|
||||||
|
1: ldax d ! move source downwards
|
||||||
|
mov m,a
|
||||||
|
inx d
|
||||||
|
inx h
|
||||||
|
dcr c
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
ral ! a-reg still contains most significant byte of source
|
||||||
|
jnc 1f ! jump if is a positive integer
|
||||||
|
lda .areg
|
||||||
|
ora a
|
||||||
|
jz 1f ! jump if it is a cuu
|
||||||
|
mvi c,255 ! c-reg contains filler byte
|
||||||
|
|
||||||
|
1: mov m,c ! fill
|
||||||
|
inx h
|
||||||
|
dcr b
|
||||||
|
jnz 1b
|
||||||
|
jmp 3f ! done
|
||||||
|
|
||||||
|
!if destination size < source size only:
|
||||||
|
shrink: mov l,c ! load source size in hl
|
||||||
|
mvi h,0
|
||||||
|
dad sp
|
||||||
|
mov d,h
|
||||||
|
mov e,l ! de points just above source
|
||||||
|
mov l,b ! load destination size in hl
|
||||||
|
mvi h,0
|
||||||
|
dad sp ! hl points just above "destination"
|
||||||
|
|
||||||
|
1: dcx d ! move upwards
|
||||||
|
dcx h
|
||||||
|
mov a,m
|
||||||
|
stax d
|
||||||
|
dcr b
|
||||||
|
jnz 1b
|
||||||
|
sphl
|
||||||
|
|
||||||
|
3: lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
66
mach/i80/libem/cmi4.s
Normal file
66
mach/i80/libem/cmi4.s
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
.define .cmi4
|
||||||
|
|
||||||
|
! Compare 32 bits integers
|
||||||
|
! Expects: operands on stack
|
||||||
|
! a-register = 1 for signed integers
|
||||||
|
! a-register = 0 for unsigned integers
|
||||||
|
! Yields in de-registers: -1 if second operand < first operand
|
||||||
|
! 0 if second operand = first operand
|
||||||
|
! 1 if second operand > first operand
|
||||||
|
|
||||||
|
.cmi4: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
lxi b,4
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
dad b
|
||||||
|
dcx h
|
||||||
|
mov d,h
|
||||||
|
mov e,l !now de points to the first operand
|
||||||
|
dad b !and hl to the second
|
||||||
|
ora a !is it a cmi or cmu?
|
||||||
|
jz 1f
|
||||||
|
|
||||||
|
!for cmi only:
|
||||||
|
mov a,m
|
||||||
|
ral
|
||||||
|
jnc 2f
|
||||||
|
ldax d !second operand is negative
|
||||||
|
ral
|
||||||
|
jc 1f !jump if both operands are negative
|
||||||
|
lxi d,-1 !second operand is smaller
|
||||||
|
jmp 4f
|
||||||
|
2: ldax d !second operand is positive
|
||||||
|
ral
|
||||||
|
jnc 1f !jump if both operand are positive
|
||||||
|
lxi d,1 !second operand is larger
|
||||||
|
jmp 4f
|
||||||
|
|
||||||
|
!cmi and cmu rejoin here
|
||||||
|
1: ldax d
|
||||||
|
cmp m
|
||||||
|
jz 3f
|
||||||
|
jnc 2f
|
||||||
|
lxi d,1 !second operand is larger
|
||||||
|
jmp 4f
|
||||||
|
2: lxi d,-1 !second operand is smaller
|
||||||
|
jmp 4f
|
||||||
|
3: dcx d
|
||||||
|
dcx h
|
||||||
|
dcr c
|
||||||
|
jnz 1b
|
||||||
|
lxi d,0 !operands are equal
|
||||||
|
|
||||||
|
4: lxi h,8
|
||||||
|
dad sp
|
||||||
|
sphl
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
35
mach/i80/libem/cms.s
Normal file
35
mach/i80/libem/cms.s
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
.define .cms
|
||||||
|
|
||||||
|
! Any size compare
|
||||||
|
! Expects: size in de-registers
|
||||||
|
! operands on stack
|
||||||
|
! Yields in de-registers: 0 if operands are equal
|
||||||
|
! 1 if operands are not equal
|
||||||
|
|
||||||
|
.cms:
|
||||||
|
pop h
|
||||||
|
shld .retadr
|
||||||
|
|
||||||
|
mov l,e
|
||||||
|
mov h,d
|
||||||
|
mov a,l
|
||||||
|
rar
|
||||||
|
cc eoddz !trap is size is odd
|
||||||
|
dad sp !now hl points to second operand
|
||||||
|
!and sp points to the first.
|
||||||
|
1: dcx sp
|
||||||
|
pop psw !get next byte in accumulator
|
||||||
|
cmp m
|
||||||
|
inx h
|
||||||
|
dcx d
|
||||||
|
jnz 2f !jump if bytes are not equal
|
||||||
|
mov a,d
|
||||||
|
ora e
|
||||||
|
jnz 1b
|
||||||
|
jmp 3f
|
||||||
|
2: dad d
|
||||||
|
lxi d,1
|
||||||
|
3: sphl
|
||||||
|
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
20
mach/i80/libem/com.s
Normal file
20
mach/i80/libem/com.s
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
.define .com
|
||||||
|
|
||||||
|
! Complement bytes on top of stack.
|
||||||
|
! Expects in de-registers: number of bytes
|
||||||
|
|
||||||
|
.com: pop h
|
||||||
|
shld .retadr
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
1: mov a,m
|
||||||
|
cma
|
||||||
|
mov m,a
|
||||||
|
inx h
|
||||||
|
dcx d
|
||||||
|
mov a,e
|
||||||
|
ora d
|
||||||
|
jnz 1b
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
|
|
||||||
52
mach/i80/libem/csa.s
Normal file
52
mach/i80/libem/csa.s
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
.define .csa
|
||||||
|
|
||||||
|
! Case jump
|
||||||
|
! Expects on stack: address of case descriptor
|
||||||
|
! case index
|
||||||
|
! This is not a subroutine, but just a piece of code that computes
|
||||||
|
! the jump address and jumps to it.
|
||||||
|
! Traps if resulting address is zero.
|
||||||
|
|
||||||
|
.csa: pop h !hl = address of case descriptor
|
||||||
|
pop d !de = index
|
||||||
|
push b !save localbase
|
||||||
|
mov c,m
|
||||||
|
inx h
|
||||||
|
mov b,m
|
||||||
|
inx h
|
||||||
|
push b !save default pointer on stack
|
||||||
|
mov a,e
|
||||||
|
sub m
|
||||||
|
inx h
|
||||||
|
mov c,a
|
||||||
|
mov a,d
|
||||||
|
sbb m
|
||||||
|
inx h
|
||||||
|
mov b,a !bc = index - lower bound
|
||||||
|
jc 1f !get default pointer
|
||||||
|
mov a,m
|
||||||
|
inx h
|
||||||
|
sub c
|
||||||
|
mov a,m
|
||||||
|
inx h
|
||||||
|
sbb b
|
||||||
|
jc 1f !upper-lower should be >= index-lower
|
||||||
|
dad b
|
||||||
|
dad b !hl now points to the wanted pointer
|
||||||
|
mov a,m
|
||||||
|
inx h
|
||||||
|
mov h,m
|
||||||
|
mov l,a !hl = pointer for index
|
||||||
|
ora h
|
||||||
|
jz 1f !get default pointer if pointer = 0
|
||||||
|
pop b !remove default pointer
|
||||||
|
pop b !localbase
|
||||||
|
pchl !jump!!!!
|
||||||
|
|
||||||
|
1: pop h !get default pointer
|
||||||
|
mov a,l
|
||||||
|
ora h
|
||||||
|
cz ecase !trap
|
||||||
|
pop b !restore localbase
|
||||||
|
pchl !jump!!!!
|
||||||
|
|
||||||
53
mach/i80/libem/csb.s
Normal file
53
mach/i80/libem/csb.s
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
.define .csb
|
||||||
|
|
||||||
|
! Table lookup jump
|
||||||
|
! Expects on stack: address of case descriptor
|
||||||
|
! case index
|
||||||
|
! This is not a subroutine, but just a piece of code that computes
|
||||||
|
! the jump address and jumps to it.
|
||||||
|
! Traps if resulting address is zero.
|
||||||
|
|
||||||
|
.csb: pop h !hl = pointer to descriptor
|
||||||
|
pop d !de = case index
|
||||||
|
push b !save localbase
|
||||||
|
mov c,m !bc = default pointer
|
||||||
|
inx h
|
||||||
|
mov b,m
|
||||||
|
inx h
|
||||||
|
push b !save default on stack
|
||||||
|
mov c,m !bc = number of entries
|
||||||
|
inx h
|
||||||
|
mov b,m
|
||||||
|
inx h
|
||||||
|
!loop: try to find the case index in the descriptor
|
||||||
|
1: mov a,b
|
||||||
|
ora c
|
||||||
|
jz 4f !done, index not found
|
||||||
|
mov a,m !do we have the right index?
|
||||||
|
inx h
|
||||||
|
cmp e
|
||||||
|
jnz 2f !no
|
||||||
|
mov a,m
|
||||||
|
inx h
|
||||||
|
cmp d
|
||||||
|
jnz 3f !no
|
||||||
|
mov a,m
|
||||||
|
inx h
|
||||||
|
mov h,m
|
||||||
|
mov l,a
|
||||||
|
pop psw !remove default pointer
|
||||||
|
jmp 5f
|
||||||
|
|
||||||
|
2: inx h !skip high byte of index
|
||||||
|
3: inx h !skip jump address
|
||||||
|
inx h
|
||||||
|
dcx b
|
||||||
|
jmp 1b
|
||||||
|
|
||||||
|
4: pop h !take default exit
|
||||||
|
5: pop b !restore localbase
|
||||||
|
mov a,l !jump address is zero?
|
||||||
|
ora h
|
||||||
|
cz ecase !trap
|
||||||
|
pchl !jump!!!!
|
||||||
|
|
||||||
34
mach/i80/libem/dup.s
Normal file
34
mach/i80/libem/dup.s
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
.define .dup
|
||||||
|
|
||||||
|
! Duplicate top bytes of stack
|
||||||
|
! Expects in de-registers: number of bytes to duplicate
|
||||||
|
|
||||||
|
.dup: mov a,e !trap if number is odd
|
||||||
|
rar
|
||||||
|
cc eoddz
|
||||||
|
|
||||||
|
pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
mov h,d
|
||||||
|
mov l,e
|
||||||
|
dad sp
|
||||||
|
1: dcx h
|
||||||
|
mov b,m
|
||||||
|
dcx h
|
||||||
|
mov c,m
|
||||||
|
push b
|
||||||
|
dcx d
|
||||||
|
dcx d !number of bytes must be a word-multiple i.e. even
|
||||||
|
mov a,d
|
||||||
|
ora e
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
114
mach/i80/libem/dvi2.s
Normal file
114
mach/i80/libem/dvi2.s
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
.define .dvi2
|
||||||
|
|
||||||
|
! 16 bits signed and unsigned integer divide and remainder routine
|
||||||
|
! Bit 0 of a-reg is set iff quotient has to be delivered
|
||||||
|
! Bit 7 of a-reg is set iff the operands are signed, so:
|
||||||
|
! Expects in a-reg: 0 if called by rmu 2
|
||||||
|
! 1 if called by dvu 2
|
||||||
|
! 128 if called by rmi 2
|
||||||
|
! 129 if called by dvi 2
|
||||||
|
! Expects on stack: divisor
|
||||||
|
! dividend
|
||||||
|
! Yields in de-reg: quotient or remainder
|
||||||
|
|
||||||
|
.dvi2: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
sta .areg
|
||||||
|
pop b ! bc = divisor
|
||||||
|
mov a,b ! trap if divisor = 0
|
||||||
|
ora c
|
||||||
|
cz eidivz
|
||||||
|
pop d ! de = dividend
|
||||||
|
|
||||||
|
mvi h,0
|
||||||
|
lda .areg
|
||||||
|
ral
|
||||||
|
jnc 0f ! jump if unsigned
|
||||||
|
|
||||||
|
mov a,d
|
||||||
|
ral
|
||||||
|
jnc 1f ! jump if dividend >= 0
|
||||||
|
mvi h,129 ! indicate dividend is negative
|
||||||
|
xra a ! negate dividend
|
||||||
|
sub e
|
||||||
|
mov e,a
|
||||||
|
mvi a,0
|
||||||
|
sbb d
|
||||||
|
mov d,a
|
||||||
|
! de is positive now
|
||||||
|
|
||||||
|
1: mov a,b
|
||||||
|
ral
|
||||||
|
jc 2f ! jump if divisor < 0
|
||||||
|
0: inr h ! indicate negation
|
||||||
|
xra a ! negate divisor
|
||||||
|
sub c
|
||||||
|
mov c,a
|
||||||
|
mvi a,0
|
||||||
|
sbb b
|
||||||
|
mov b,a
|
||||||
|
! bc is negative now
|
||||||
|
|
||||||
|
2: push h ! save h-reg
|
||||||
|
lxi h,0 ! initial value of remainder
|
||||||
|
mvi a,16 ! initialize loop counter
|
||||||
|
|
||||||
|
3: push psw ! save loop counter
|
||||||
|
dad h ! shift left: hl <- de <- 0
|
||||||
|
xchg
|
||||||
|
dad h
|
||||||
|
xchg
|
||||||
|
jnc 4f
|
||||||
|
inx h
|
||||||
|
|
||||||
|
4: push h ! save remainder
|
||||||
|
dad b ! subtract divisor (add negative)
|
||||||
|
jnc 5f
|
||||||
|
xthl
|
||||||
|
inx d
|
||||||
|
|
||||||
|
5: pop h
|
||||||
|
pop psw ! restore loop counter
|
||||||
|
dcr a
|
||||||
|
jnz 3b
|
||||||
|
|
||||||
|
pop b ! b-reg becomes what once was h-reg
|
||||||
|
lda .areg
|
||||||
|
rar ! what has to be delivered: quotient or remainder?
|
||||||
|
jnc 6f
|
||||||
|
|
||||||
|
! for dvi 2 and dvu 2 only:
|
||||||
|
mov a,b
|
||||||
|
rar
|
||||||
|
jc 8f ! jump if divisor and dividend had same sign
|
||||||
|
xra a ! negate quotient
|
||||||
|
sub e
|
||||||
|
mov e,a
|
||||||
|
mvi a,0
|
||||||
|
sbb d
|
||||||
|
mov d,a
|
||||||
|
jmp 8f
|
||||||
|
|
||||||
|
! for rmi 2 and rmu 2 only:
|
||||||
|
6: mov a,b
|
||||||
|
ral
|
||||||
|
jnc 7f ! negate remainder if dividend was negative
|
||||||
|
xra a
|
||||||
|
sub l
|
||||||
|
mov l,a
|
||||||
|
mvi a,0
|
||||||
|
sbb h
|
||||||
|
mov h,a
|
||||||
|
7: mov d,h ! return remainder
|
||||||
|
mov e,l
|
||||||
|
|
||||||
|
8: lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
145
mach/i80/libem/dvi4.s
Normal file
145
mach/i80/libem/dvi4.s
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
.define .dvi4
|
||||||
|
|
||||||
|
! 32 bits integer divide and remainder routine
|
||||||
|
! Bit 0 of a-reg is set iff quotient has to be delivered
|
||||||
|
! Bit 7 of a-reg is set iff the operands are signed, so:
|
||||||
|
! Expects in a-reg: 0 if called by rmu 4
|
||||||
|
! 1 if called by dvu 4
|
||||||
|
! 128 if called by rmi 4
|
||||||
|
! 129 if called by dvi 4
|
||||||
|
! Expects on stack: divisor
|
||||||
|
! dividend
|
||||||
|
! Yields on stack: quotient or remainder
|
||||||
|
|
||||||
|
.dvi4: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
sta .areg
|
||||||
|
pop h ! store divisor
|
||||||
|
shld block3
|
||||||
|
xchg
|
||||||
|
pop h
|
||||||
|
shld block3+2
|
||||||
|
dad d
|
||||||
|
jc 1f
|
||||||
|
mov a,l
|
||||||
|
ora h
|
||||||
|
cz eidivz ! trap if divisor = 0
|
||||||
|
|
||||||
|
1: pop h ! store dividend
|
||||||
|
shld block1
|
||||||
|
pop h
|
||||||
|
shld block1+2
|
||||||
|
lxi h,0 ! store initial value of remainder
|
||||||
|
shld block2
|
||||||
|
shld block2+2
|
||||||
|
|
||||||
|
mvi b,0
|
||||||
|
lda .areg
|
||||||
|
ral
|
||||||
|
jnc 2f ! jump if unsigned
|
||||||
|
|
||||||
|
lda block1+3
|
||||||
|
ral
|
||||||
|
jnc 1f
|
||||||
|
mvi b,129
|
||||||
|
lxi h,block1
|
||||||
|
call compl ! dividend is positive now
|
||||||
|
|
||||||
|
1: lda block3+3
|
||||||
|
ral
|
||||||
|
jnc 2f
|
||||||
|
inr b
|
||||||
|
lxi h,block3
|
||||||
|
call compl ! divisor is positive now
|
||||||
|
|
||||||
|
2: push b ! save b-reg
|
||||||
|
mvi b,32
|
||||||
|
|
||||||
|
dv0: lxi h,block1 ! left shift: block2 <- block1 <- 0
|
||||||
|
mvi c,8
|
||||||
|
xra a
|
||||||
|
1: mov a,m
|
||||||
|
ral
|
||||||
|
mov m,a
|
||||||
|
inx h
|
||||||
|
dcr c
|
||||||
|
jnz 1b
|
||||||
|
lxi h,block2+3 ! which is larger: divisor or remainder?
|
||||||
|
lxi d,block3+3
|
||||||
|
mvi c,4
|
||||||
|
1: ldax d
|
||||||
|
cmp m
|
||||||
|
jz 0f
|
||||||
|
jnc 3f
|
||||||
|
jmp 4f
|
||||||
|
0: dcx d
|
||||||
|
dcx h
|
||||||
|
dcr c
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
4: lxi d,block2 ! remainder is larger or equal: subtract divisor
|
||||||
|
lxi h,block3
|
||||||
|
mvi c,4
|
||||||
|
xra a
|
||||||
|
1: ldax d
|
||||||
|
sbb m
|
||||||
|
stax d
|
||||||
|
inx d
|
||||||
|
inx h
|
||||||
|
dcr c
|
||||||
|
jnz 1b
|
||||||
|
lxi h,block1
|
||||||
|
inr m
|
||||||
|
|
||||||
|
3: dcr b
|
||||||
|
jnz dv0 ! keep looping
|
||||||
|
|
||||||
|
pop b
|
||||||
|
lda .areg ! quotient or remainder?
|
||||||
|
rar
|
||||||
|
jnc 4f
|
||||||
|
|
||||||
|
! for dvi 4 and dvu 4 only:
|
||||||
|
mov a,b
|
||||||
|
rar
|
||||||
|
lxi h,block1 ! complement quotient if divisor
|
||||||
|
cc compl ! and dividend have different signs
|
||||||
|
lhld block1+2 ! push quotient
|
||||||
|
push h
|
||||||
|
lhld block1
|
||||||
|
push h
|
||||||
|
jmp 5f
|
||||||
|
|
||||||
|
! for rmi 4 and rmu 4 only:
|
||||||
|
4: mov a,b
|
||||||
|
ral
|
||||||
|
lxi h,block2
|
||||||
|
cc compl ! negate remainder if dividend was negative
|
||||||
|
lhld block2+2
|
||||||
|
push h
|
||||||
|
lhld block2
|
||||||
|
push h
|
||||||
|
|
||||||
|
5: lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
|
|
||||||
|
! make 2's complement of 4 bytes pointed to by hl.
|
||||||
|
compl: push b
|
||||||
|
mvi c,4
|
||||||
|
xra a
|
||||||
|
1: mvi a,0
|
||||||
|
sbb m
|
||||||
|
mov m,a
|
||||||
|
inx h
|
||||||
|
dcr c
|
||||||
|
jnz 1b
|
||||||
|
pop b
|
||||||
|
ret
|
||||||
|
|
||||||
40
mach/i80/libem/exg.s
Normal file
40
mach/i80/libem/exg.s
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
.define .exg
|
||||||
|
|
||||||
|
! Exchange top bytes of stack
|
||||||
|
! Expects in de-registers the number of bytes to be exchanged.
|
||||||
|
|
||||||
|
.exg: mov a,e
|
||||||
|
rar
|
||||||
|
cc eoddz !trap if numer of bytes is odd
|
||||||
|
pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
mov b,h
|
||||||
|
mov c,l !now bc points to first operand
|
||||||
|
dad d !and hl to the second
|
||||||
|
push d !place number of bytes on top of stack
|
||||||
|
1: mov d,m
|
||||||
|
ldax b
|
||||||
|
mov m,a
|
||||||
|
mov a,d
|
||||||
|
stax b
|
||||||
|
xthl !caused by a lack of registers
|
||||||
|
dcx h !decrement top of stack
|
||||||
|
mov a,h
|
||||||
|
ora l
|
||||||
|
xthl
|
||||||
|
inx h
|
||||||
|
inx b
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
pop d
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
61
mach/i80/libem/inn.s
Normal file
61
mach/i80/libem/inn.s
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
.define .inn
|
||||||
|
|
||||||
|
! Any size bit test on set.
|
||||||
|
! Expects in de-reg: size of set (in bytes)
|
||||||
|
! Expects on stack: bit number
|
||||||
|
! set to be tested
|
||||||
|
! Yields in de-reg.: 0 if bit is reset or bit number out of range
|
||||||
|
! 1 if bit is set
|
||||||
|
|
||||||
|
.inn: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop h
|
||||||
|
xchg !hl = size, de = bit number
|
||||||
|
mov a,d !test if bit number is negative
|
||||||
|
ral
|
||||||
|
jc 3f
|
||||||
|
mov a,e
|
||||||
|
ani 7
|
||||||
|
mov b,a !save bits 0-2 of bit number in b-reg
|
||||||
|
mvi c,3
|
||||||
|
1: xra a
|
||||||
|
mov a,d !shift bit number right 3 times
|
||||||
|
rar
|
||||||
|
mov d,a
|
||||||
|
mov a,e
|
||||||
|
rar
|
||||||
|
mov e,a
|
||||||
|
dcr c
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
mov a,l !test if bit number is small enough
|
||||||
|
sub e
|
||||||
|
mov a,h
|
||||||
|
sbb d
|
||||||
|
jc 3f
|
||||||
|
xchg
|
||||||
|
dad sp
|
||||||
|
xchg
|
||||||
|
ldax d !a-register = wanted byte
|
||||||
|
2: dcr b !dcr doesn't affect carry bit
|
||||||
|
jm 4f
|
||||||
|
rar
|
||||||
|
jmp 2b
|
||||||
|
|
||||||
|
3: xra a !return 0 if bit number out of range
|
||||||
|
4: ani 1
|
||||||
|
mov e,a
|
||||||
|
mvi d,0
|
||||||
|
dad sp
|
||||||
|
sphl
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
|
|
||||||
38
mach/i80/libem/ior.s
Normal file
38
mach/i80/libem/ior.s
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
.define .ior
|
||||||
|
|
||||||
|
|
||||||
|
! Any size inclusive-or.
|
||||||
|
! Expects: size in de-registers
|
||||||
|
! operands on stack
|
||||||
|
! Yields: result on stack
|
||||||
|
|
||||||
|
.ior: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
mov c,l
|
||||||
|
mov b,h !now bc points to top of first operand
|
||||||
|
dad d !and hl points to top of second operand
|
||||||
|
push h !this will be the new stackpointer
|
||||||
|
1: ldax b
|
||||||
|
ora m
|
||||||
|
mov m,a
|
||||||
|
inx h
|
||||||
|
inx b
|
||||||
|
dcx d
|
||||||
|
mov a,e
|
||||||
|
ora d
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
pop h
|
||||||
|
sphl
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
71
mach/i80/libem/lar2.s
Normal file
71
mach/i80/libem/lar2.s
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
.define .lar2
|
||||||
|
|
||||||
|
! Load array element, descriptor contains 2-bytes integers
|
||||||
|
! Expects on stack: pointer to array descriptor
|
||||||
|
! index
|
||||||
|
! base address
|
||||||
|
! Yields on stack: array element
|
||||||
|
! Adapted from .aar2 and .loi
|
||||||
|
|
||||||
|
.lar2:
|
||||||
|
pop h
|
||||||
|
shld .retadr1
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop h ! hl = pointer to descriptor
|
||||||
|
pop d ! de = index
|
||||||
|
mov a,e ! bc = index - lower bound
|
||||||
|
sub m
|
||||||
|
inx h
|
||||||
|
mov c,a
|
||||||
|
mov a,d
|
||||||
|
sbb m
|
||||||
|
inx h
|
||||||
|
mov b,a
|
||||||
|
push b ! first operand to multiply
|
||||||
|
inx h
|
||||||
|
inx h
|
||||||
|
mov c,m ! bc = size
|
||||||
|
inx h
|
||||||
|
mov b,m
|
||||||
|
push b ! second operand to multiply
|
||||||
|
call .mli2 ! de = size * (index - lower bound)
|
||||||
|
pop h ! hl = base address
|
||||||
|
dad d ! hl = address of array[index]
|
||||||
|
dad b ! hl= load pointer
|
||||||
|
xra a ! clear carry bit
|
||||||
|
mov a,b ! divide bc by 2
|
||||||
|
rar
|
||||||
|
mov b,a
|
||||||
|
mov a,c
|
||||||
|
rar
|
||||||
|
mov c,a
|
||||||
|
jnc 1f
|
||||||
|
|
||||||
|
! for 1 byte array element only:
|
||||||
|
mov a,c ! trap if bc odd and <>1
|
||||||
|
ora b
|
||||||
|
cnz eoddz
|
||||||
|
dcx h
|
||||||
|
mov e,m
|
||||||
|
mvi d,0
|
||||||
|
push d
|
||||||
|
jmp 2f
|
||||||
|
|
||||||
|
1: dcx h
|
||||||
|
mov d,m
|
||||||
|
dcx h
|
||||||
|
mov e,m
|
||||||
|
push d
|
||||||
|
dcx b
|
||||||
|
mov a,b
|
||||||
|
ora c
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
2: lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr1
|
||||||
|
pchl
|
||||||
50
mach/i80/libem/loi.s
Normal file
50
mach/i80/libem/loi.s
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
.define .loi
|
||||||
|
|
||||||
|
! Load indirect
|
||||||
|
! Expects in de-registers: number of bytes to be loaded
|
||||||
|
! (this number should be 1 or even )
|
||||||
|
! Expects on stack: base address
|
||||||
|
! Yields on stack: result
|
||||||
|
|
||||||
|
.loi: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov l,c ! free bc for scratch
|
||||||
|
mov h,b
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop h ! hl = base address
|
||||||
|
dad d ! hl = load pointer
|
||||||
|
xra a ! clear carry bit
|
||||||
|
mov a,d ! divide d by 2
|
||||||
|
rar
|
||||||
|
mov d,a
|
||||||
|
mov a,e
|
||||||
|
rar
|
||||||
|
mov e,a
|
||||||
|
jnc 1f
|
||||||
|
|
||||||
|
! if 1 byte has to be loaded only:
|
||||||
|
mov a,d
|
||||||
|
ora e
|
||||||
|
cnz eoddz ! trap if number is odd and <> 1
|
||||||
|
dcx h
|
||||||
|
mov c,m
|
||||||
|
mvi b,0
|
||||||
|
push b
|
||||||
|
jmp 2f
|
||||||
|
|
||||||
|
1: dcx h
|
||||||
|
mov b,m
|
||||||
|
dcx h
|
||||||
|
mov c,m
|
||||||
|
push b
|
||||||
|
dcx d ! is count exhausted?
|
||||||
|
mov a,d
|
||||||
|
ora e
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
2: lhld .bcreg
|
||||||
|
mov c,l
|
||||||
|
mov b,h
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
80
mach/i80/libem/mli2.s
Normal file
80
mach/i80/libem/mli2.s
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
.define .mli2
|
||||||
|
|
||||||
|
! 16 bits signed integer multiply
|
||||||
|
! the algorithm multiples A * B, where A = A0*2^8 + A1 and B = B0*2^8 + B1
|
||||||
|
! product is thus A0*B0*2^16 + 2^8 * (A0 * B1 + B0 * A1) + A0 * B0
|
||||||
|
! hence either A0 = 0 or B0 = 0 or overflow.
|
||||||
|
! initial part of code determines which high byte is 0 (also for negative #s)
|
||||||
|
! then the multiply is reduced to 8 x 16 bits, with the 8 bit number in the
|
||||||
|
! a register, the 16 bit number in the hl register, and the product in de
|
||||||
|
! Expects operands on stack
|
||||||
|
! Yields result in de-registers
|
||||||
|
|
||||||
|
.mli2: pop h
|
||||||
|
shld .retadr ! get the return address out of the way
|
||||||
|
lxi h,255
|
||||||
|
pop d
|
||||||
|
mov a,d ! check hi byte for 0
|
||||||
|
cmp h ! h = 0
|
||||||
|
jz 1f ! jump if de is a positive 8 bit number
|
||||||
|
cmp l
|
||||||
|
jz 5f ! jump if de is a negative 8 bit number
|
||||||
|
xchg
|
||||||
|
shld .tmp1 ! we ran out of scratch registers
|
||||||
|
pop h
|
||||||
|
mov a,h
|
||||||
|
cmp e
|
||||||
|
jz 7f ! jump if second operand is 8 bit negative
|
||||||
|
jmp 6f ! assume second operand is 8 bit positive
|
||||||
|
|
||||||
|
1: mov a,e ! 8 bit positive number in a
|
||||||
|
pop h ! 16 bit number in hl
|
||||||
|
|
||||||
|
! here is the main loop of the multiplication. the a register is shifted
|
||||||
|
! right 1 bit to load the carry bit for testing.
|
||||||
|
! as soon as the a register goes to zero, the loop terminates.
|
||||||
|
! in most cases this requires fewer than 8 iterations.
|
||||||
|
2: lxi d,0
|
||||||
|
ora a
|
||||||
|
3: rar ! load carry bit from a
|
||||||
|
jnc 4f ! add hl to de if low bit was a 1
|
||||||
|
xchg
|
||||||
|
dad d
|
||||||
|
xchg
|
||||||
|
4: dad h
|
||||||
|
ora a ! sets zero correct and resets carry bit
|
||||||
|
jnz 3b ! if a has more bits, continue the loop
|
||||||
|
lhld .retadr ! go get return address
|
||||||
|
pchl
|
||||||
|
|
||||||
|
! the 8 bit operand is negative. negate both operands
|
||||||
|
5: pop h
|
||||||
|
mov a,l
|
||||||
|
cma
|
||||||
|
mov l,a
|
||||||
|
mov a,h
|
||||||
|
cma
|
||||||
|
mov h,a
|
||||||
|
inx h ! 16 bit negate is 1s complement + 1
|
||||||
|
xra a
|
||||||
|
sub e ! negate 8 bit operand
|
||||||
|
jmp 2b
|
||||||
|
|
||||||
|
! second operand is small and positive
|
||||||
|
6: mov a,l
|
||||||
|
lhld .tmp1
|
||||||
|
jmp 2b
|
||||||
|
|
||||||
|
! second operand is small and negative
|
||||||
|
7: mov e,l
|
||||||
|
lhld .tmp1
|
||||||
|
mov a,l
|
||||||
|
cma
|
||||||
|
mov l,a
|
||||||
|
mov a,h
|
||||||
|
cma
|
||||||
|
mov h,a
|
||||||
|
inx h
|
||||||
|
xra a
|
||||||
|
sub e
|
||||||
|
jmp 2b
|
||||||
72
mach/i80/libem/mli4.s
Normal file
72
mach/i80/libem/mli4.s
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
.define .mli4
|
||||||
|
|
||||||
|
! 32 bits signed and unsigned integer multiply routine
|
||||||
|
! Expects operands on stack
|
||||||
|
! Yields product on stack
|
||||||
|
|
||||||
|
.mli4: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop h ! store multiplier
|
||||||
|
shld block1
|
||||||
|
pop h
|
||||||
|
shld block1+2
|
||||||
|
pop h ! store multiplicand
|
||||||
|
shld block2
|
||||||
|
pop h
|
||||||
|
shld block2+2
|
||||||
|
lxi h,0
|
||||||
|
shld block3 ! product = 0
|
||||||
|
shld block3+2
|
||||||
|
lxi b,0
|
||||||
|
lp1: lxi h,block1
|
||||||
|
dad b
|
||||||
|
mov a,m ! get next byte of multiplier
|
||||||
|
mvi b,8
|
||||||
|
lp2: rar
|
||||||
|
jnc 2f
|
||||||
|
lhld block2 ! add multiplicand to product
|
||||||
|
xchg
|
||||||
|
lhld block3
|
||||||
|
dad d
|
||||||
|
shld block3
|
||||||
|
lhld block2+2
|
||||||
|
jnc 1f
|
||||||
|
inx h
|
||||||
|
1: xchg
|
||||||
|
lhld block3+2
|
||||||
|
dad d
|
||||||
|
shld block3+2
|
||||||
|
|
||||||
|
2: lhld block2 ! shift multiplicand left
|
||||||
|
dad h
|
||||||
|
shld block2
|
||||||
|
lhld block2+2
|
||||||
|
jnc 3f
|
||||||
|
dad h
|
||||||
|
inx h
|
||||||
|
jmp 4f
|
||||||
|
3: dad h
|
||||||
|
4: shld block2+2
|
||||||
|
|
||||||
|
dcr b
|
||||||
|
jnz lp2
|
||||||
|
|
||||||
|
inr c
|
||||||
|
mov a,c
|
||||||
|
cpi 4
|
||||||
|
jnz lp1
|
||||||
|
|
||||||
|
lhld block3+2
|
||||||
|
push h
|
||||||
|
lhld block3
|
||||||
|
push h
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
46
mach/i80/libem/mlu2.s
Normal file
46
mach/i80/libem/mlu2.s
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
.define .mlu2
|
||||||
|
|
||||||
|
! 16 bits unsigned multiply routine
|
||||||
|
! Expects operands on stack
|
||||||
|
! Yields result in de-registers
|
||||||
|
! This routine could also be used for signed integers, but it won't
|
||||||
|
! because there is a more clever one just for signed integers.
|
||||||
|
|
||||||
|
.mlu2:
|
||||||
|
pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop b ! bc = multiplier
|
||||||
|
pop d ! de = multiplicand
|
||||||
|
lxi h,0 ! hl = product
|
||||||
|
|
||||||
|
1: mov a,b ! if multiplier = 0 then finished
|
||||||
|
ora c
|
||||||
|
jz 3f
|
||||||
|
|
||||||
|
xra a ! reset carry
|
||||||
|
mov a,b ! shift multiplier right
|
||||||
|
rar
|
||||||
|
mov b,a
|
||||||
|
mov a,c
|
||||||
|
rar
|
||||||
|
mov c,a
|
||||||
|
|
||||||
|
jnc 2f !if carry set: add multiplicand to product
|
||||||
|
dad d
|
||||||
|
|
||||||
|
2: xchg ! shift multiplicand left
|
||||||
|
dad h
|
||||||
|
xchg
|
||||||
|
jmp 1b ! keep looping
|
||||||
|
|
||||||
|
3: xchg ! de becomes product
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
26
mach/i80/libem/ngi4.s
Normal file
26
mach/i80/libem/ngi4.s
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
.define .ngi4
|
||||||
|
|
||||||
|
! Exchange 32 bits integer by its two's complement
|
||||||
|
! Expects operand on stack
|
||||||
|
! Yields result on stack
|
||||||
|
|
||||||
|
.ngi4: pop d
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
xra a
|
||||||
|
sub m
|
||||||
|
mov m,a
|
||||||
|
inx h
|
||||||
|
mvi a,0
|
||||||
|
sbb m
|
||||||
|
mov m,a
|
||||||
|
inx h
|
||||||
|
mvi a,0
|
||||||
|
sbb m
|
||||||
|
mov m,a
|
||||||
|
inx h
|
||||||
|
mvi a,0
|
||||||
|
sbb m
|
||||||
|
mov m,a
|
||||||
|
push d
|
||||||
|
ret
|
||||||
25
mach/i80/libem/nop.s
Normal file
25
mach/i80/libem/nop.s
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
.define .nop
|
||||||
|
|
||||||
|
.nop: push b
|
||||||
|
lhld hol0+4
|
||||||
|
mov d,h
|
||||||
|
mov e,l
|
||||||
|
call prstring
|
||||||
|
lxi d,lin
|
||||||
|
call prstring
|
||||||
|
lhld hol0
|
||||||
|
call prdec
|
||||||
|
lxi d,stpr
|
||||||
|
call prstring
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
call prdec
|
||||||
|
lxi d,newline
|
||||||
|
call prstring
|
||||||
|
pop b
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
lin: .asciz " lin:"
|
||||||
|
stpr: .asciz " sp:"
|
||||||
|
newline:.asciz "\n"
|
||||||
52
mach/i80/libem/rck.s
Normal file
52
mach/i80/libem/rck.s
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
.define .rck
|
||||||
|
|
||||||
|
! Range check
|
||||||
|
! Expects on stack: address of range check descriptor
|
||||||
|
! index
|
||||||
|
! Yields index on stack unchanged
|
||||||
|
! Causes a trap if index is out of bounds
|
||||||
|
|
||||||
|
.rck: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop h ! hl = return address
|
||||||
|
pop d ! de = index
|
||||||
|
mov c,m ! bc = lower bound
|
||||||
|
inx h
|
||||||
|
mov b,m
|
||||||
|
inx h
|
||||||
|
mov a,d
|
||||||
|
xor b
|
||||||
|
jm 1f ! jump if index and l.b. have different signs
|
||||||
|
mov a,e
|
||||||
|
sub c
|
||||||
|
mov a,d
|
||||||
|
sbb b
|
||||||
|
jmp 2f
|
||||||
|
|
||||||
|
1: xor b ! now a = d again
|
||||||
|
2: cm erange ! trap if index too small
|
||||||
|
|
||||||
|
mov c,m
|
||||||
|
inx h
|
||||||
|
mov b,m
|
||||||
|
mov a,d
|
||||||
|
xor b
|
||||||
|
jm 1f ! jump if index and u.b. have different signs
|
||||||
|
mov a,c
|
||||||
|
sub e
|
||||||
|
mov a,b
|
||||||
|
sbb d
|
||||||
|
jmp 2f
|
||||||
|
|
||||||
|
1: xor d ! now a = b
|
||||||
|
2: cm erange ! trap if index is too large
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
47
mach/i80/libem/rol4.s
Normal file
47
mach/i80/libem/rol4.s
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
.define .rol4
|
||||||
|
|
||||||
|
! Rotate 4 bytes left
|
||||||
|
! Expects in de-reg: number of rotates
|
||||||
|
! Expects on stack: operand
|
||||||
|
! Yields on stack: result
|
||||||
|
|
||||||
|
.rol4 pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
.rol4: pop h ! low-order bytes of operand
|
||||||
|
pop b ! high order bytes of operand
|
||||||
|
|
||||||
|
mov a,e
|
||||||
|
ani 31
|
||||||
|
jz 2f
|
||||||
|
mov e,a
|
||||||
|
|
||||||
|
mov a,b
|
||||||
|
ral
|
||||||
|
1: mov a,l
|
||||||
|
ral
|
||||||
|
mov l,a
|
||||||
|
mov a,h
|
||||||
|
ral
|
||||||
|
mov h,a
|
||||||
|
mov a,c
|
||||||
|
ral
|
||||||
|
mov c,a
|
||||||
|
mov a,b
|
||||||
|
ral
|
||||||
|
mov b,a
|
||||||
|
|
||||||
|
dcr e
|
||||||
|
jnz 1b ! keep looping
|
||||||
|
|
||||||
|
2: push b
|
||||||
|
push h
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
47
mach/i80/libem/ror4.s
Normal file
47
mach/i80/libem/ror4.s
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
.define .ror4
|
||||||
|
|
||||||
|
! Rotate 4 bytes right
|
||||||
|
! Expects in de-reg: number of rotates
|
||||||
|
! Expects on stack: operand
|
||||||
|
! Yields on stack: result
|
||||||
|
|
||||||
|
.ror4 pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
.ror4: pop h ! low-order bytes of operand
|
||||||
|
pop b ! high order bytes of operand
|
||||||
|
|
||||||
|
mov a,e
|
||||||
|
ani 31
|
||||||
|
jz 2f
|
||||||
|
mov e,a
|
||||||
|
|
||||||
|
mov a,l
|
||||||
|
rar
|
||||||
|
1: mov a,b
|
||||||
|
rar
|
||||||
|
mov b,a
|
||||||
|
mov a,c
|
||||||
|
rar
|
||||||
|
mov c,a
|
||||||
|
mov a,h
|
||||||
|
rar
|
||||||
|
mov h,a
|
||||||
|
mov a,l
|
||||||
|
rar
|
||||||
|
mov l,a
|
||||||
|
|
||||||
|
dcr e
|
||||||
|
jnz 1b ! keep looping
|
||||||
|
|
||||||
|
2: push b
|
||||||
|
push h
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
68
mach/i80/libem/sar2.s
Normal file
68
mach/i80/libem/sar2.s
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
.define .sar2
|
||||||
|
|
||||||
|
! Store array element, descriptor contains 2-bytes integers
|
||||||
|
! Expects on stack: pointer to array descriptor
|
||||||
|
! index
|
||||||
|
! base address
|
||||||
|
! array element
|
||||||
|
! Adapted from .aar2 and .sti
|
||||||
|
|
||||||
|
.sar2:
|
||||||
|
pop h
|
||||||
|
shld .retadr1
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop h ! hl = pointer to descriptor
|
||||||
|
pop d ! de = index
|
||||||
|
mov a,e ! bc = index - lower bound
|
||||||
|
sub m
|
||||||
|
inx h
|
||||||
|
mov c,a
|
||||||
|
mov a,d
|
||||||
|
sbb m
|
||||||
|
inx h
|
||||||
|
mov b,a
|
||||||
|
push b ! first operand to multiply
|
||||||
|
inx h
|
||||||
|
inx h
|
||||||
|
mov c,m ! bc = size
|
||||||
|
inx h
|
||||||
|
mov b,m
|
||||||
|
push b ! second operand to multiply
|
||||||
|
call .mli2 ! de = size * (index - lower bound)
|
||||||
|
pop h ! hl = base address
|
||||||
|
dad d ! hl = address of array[index]
|
||||||
|
xra a
|
||||||
|
mov a,b
|
||||||
|
rar
|
||||||
|
mov b,a
|
||||||
|
mov a,c
|
||||||
|
rar
|
||||||
|
mov c,a ! bc = word count
|
||||||
|
jnc 1f
|
||||||
|
|
||||||
|
! if 1 byte array element only:
|
||||||
|
mov a,c ! trap if bc odd and <>1
|
||||||
|
ora b
|
||||||
|
cnz eoddz
|
||||||
|
pop d
|
||||||
|
mov m,e
|
||||||
|
jmp 2f
|
||||||
|
|
||||||
|
1: pop d
|
||||||
|
mov m,e
|
||||||
|
inx h
|
||||||
|
mov m,d
|
||||||
|
inx h
|
||||||
|
dcx b
|
||||||
|
mov a,b
|
||||||
|
ora c
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
2: lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr1
|
||||||
|
pchl
|
||||||
37
mach/i80/libem/sbi4.s
Normal file
37
mach/i80/libem/sbi4.s
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
.define .sbi4
|
||||||
|
|
||||||
|
! Subtract two 32 bits signed or unsigned integers.
|
||||||
|
! Expects operands on stack
|
||||||
|
! Yields result on stack
|
||||||
|
|
||||||
|
.sbi4:
|
||||||
|
pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
lxi h,0
|
||||||
|
dad sp !now hl points to the first operand
|
||||||
|
mov d,h
|
||||||
|
mov e,l
|
||||||
|
inx d
|
||||||
|
inx d
|
||||||
|
inx d
|
||||||
|
inx d !and de points to the second.
|
||||||
|
mvi b,4
|
||||||
|
xra a
|
||||||
|
1: ldax d
|
||||||
|
sbb m
|
||||||
|
stax d
|
||||||
|
inx d
|
||||||
|
inx h
|
||||||
|
dcr b
|
||||||
|
jnz 1b
|
||||||
|
sphl
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
65
mach/i80/libem/set.s
Normal file
65
mach/i80/libem/set.s
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
.define .set
|
||||||
|
|
||||||
|
! Create set with one bit on
|
||||||
|
! Expects in de-reg: size of set to be created
|
||||||
|
! Expects on stack: bit number
|
||||||
|
! Yields on stack: resulting set
|
||||||
|
|
||||||
|
.set: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
mov a,e
|
||||||
|
rar
|
||||||
|
cc eoddz ! trap if size is odd
|
||||||
|
xchg ! hl = size of set
|
||||||
|
pop d ! de = bit number
|
||||||
|
mov a,e ! c = bit number in byte
|
||||||
|
ani 7
|
||||||
|
sta .areg ! save bit number in byte
|
||||||
|
|
||||||
|
mvi b,3 ! de = byte number
|
||||||
|
1: xra a
|
||||||
|
mov a,d
|
||||||
|
rar
|
||||||
|
mov d,a
|
||||||
|
mov a,e
|
||||||
|
rar
|
||||||
|
mov e,a
|
||||||
|
dcr b
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
mov a,l ! trap if bit number is too large
|
||||||
|
sub e
|
||||||
|
mov a,h
|
||||||
|
sbb d
|
||||||
|
cc eset
|
||||||
|
|
||||||
|
lxi b,0 ! make empty set on stack
|
||||||
|
1: push b
|
||||||
|
dcx h
|
||||||
|
dcx h
|
||||||
|
mov a,l
|
||||||
|
ora h
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
dad d ! hl points to byte that will contain a one
|
||||||
|
lda .areg
|
||||||
|
mov c,a ! c = bit number in byte
|
||||||
|
mvi a,1
|
||||||
|
1: dcr c
|
||||||
|
jm 2f
|
||||||
|
rlc
|
||||||
|
jmp 1b
|
||||||
|
|
||||||
|
2: mov m,a
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
36
mach/i80/libem/set2.s
Normal file
36
mach/i80/libem/set2.s
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
.define .set2
|
||||||
|
|
||||||
|
! Create 16 bits set with one bit on
|
||||||
|
! Expects in de-reg: bit number
|
||||||
|
! Yields in de-reg: resulting set
|
||||||
|
|
||||||
|
.set2: mov a,d !trap if bit number >= 16
|
||||||
|
ora a
|
||||||
|
cnz eset
|
||||||
|
mov a,e
|
||||||
|
cpi 16
|
||||||
|
cnc eset
|
||||||
|
|
||||||
|
pop h
|
||||||
|
shld .retadr
|
||||||
|
mov a,e
|
||||||
|
ani 7
|
||||||
|
mov d,a
|
||||||
|
mvi a,1
|
||||||
|
1: dcr d
|
||||||
|
jm 2f
|
||||||
|
rlc
|
||||||
|
jmp 1b
|
||||||
|
2: mov d,a
|
||||||
|
mov a,e
|
||||||
|
ani 8
|
||||||
|
jnz 3f ! jump if bit 3 is set
|
||||||
|
|
||||||
|
mov e,d
|
||||||
|
mvi d,0
|
||||||
|
jmp 4f
|
||||||
|
|
||||||
|
3: mvi e,0
|
||||||
|
|
||||||
|
4: lhld .retadr
|
||||||
|
pchl
|
||||||
28
mach/i80/libem/sli2.s
Normal file
28
mach/i80/libem/sli2.s
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
.define .sli2
|
||||||
|
|
||||||
|
! Shift 16 bits integer left
|
||||||
|
! Expects on stack: number of shifts
|
||||||
|
! number to be shifted
|
||||||
|
! Yields in de-reg: result
|
||||||
|
|
||||||
|
.sli2: pop h
|
||||||
|
shld .retadr
|
||||||
|
|
||||||
|
pop d !de = number of shifts
|
||||||
|
pop h !hl= number to be shifted
|
||||||
|
mov a,d !if de>15 return zero
|
||||||
|
ora a
|
||||||
|
jnz 2f
|
||||||
|
mov a,e
|
||||||
|
cpi 16
|
||||||
|
jnc 2f
|
||||||
|
1: dcr e
|
||||||
|
jm 3f
|
||||||
|
dad h
|
||||||
|
jmp 1b
|
||||||
|
|
||||||
|
2: lxi h,0
|
||||||
|
3: xchg !result in de-registers
|
||||||
|
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
45
mach/i80/libem/sli4.s
Normal file
45
mach/i80/libem/sli4.s
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
.define .sli4
|
||||||
|
|
||||||
|
! Shift 32 bits integer left
|
||||||
|
! Expects on stack: number of shifts
|
||||||
|
! number to be shifted
|
||||||
|
! Yields on stack: result
|
||||||
|
|
||||||
|
.sli4:
|
||||||
|
pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop b !number of shifts
|
||||||
|
pop d !low-order bytes of number to be shifted
|
||||||
|
pop h !high-order bytes
|
||||||
|
mov a,b !if bc>=32 return 0
|
||||||
|
ora a
|
||||||
|
jnz 2f
|
||||||
|
mov a,c
|
||||||
|
cpi 32
|
||||||
|
jnc 2f
|
||||||
|
1: dcr c
|
||||||
|
jm 3f
|
||||||
|
dad h
|
||||||
|
xchg
|
||||||
|
dad h
|
||||||
|
xchg
|
||||||
|
jnc 1b
|
||||||
|
inx h
|
||||||
|
jmp 1b
|
||||||
|
|
||||||
|
2: lxi h,0
|
||||||
|
lxi d,0
|
||||||
|
|
||||||
|
3: push h
|
||||||
|
push d
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
|
|
||||||
43
mach/i80/libem/sri2.s
Normal file
43
mach/i80/libem/sri2.s
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
.define .sri2
|
||||||
|
|
||||||
|
! Shift 16 bits signed or unsigned integer right
|
||||||
|
! Expects in a-reg.: 1 if signed integer
|
||||||
|
! 0 if unsigned integer
|
||||||
|
! Expects on stack: number of shifts
|
||||||
|
! number to be shifted
|
||||||
|
! Yields in de-reg.: result
|
||||||
|
|
||||||
|
.sri2: pop h
|
||||||
|
shld .retadr
|
||||||
|
|
||||||
|
pop h !hl = number of shifts
|
||||||
|
pop d !de = number to be shifted
|
||||||
|
mvi h,0
|
||||||
|
ora a
|
||||||
|
jz 1f !jump if unsigned integer
|
||||||
|
mov a,d
|
||||||
|
ral
|
||||||
|
jnc 1f !jump if positive signed integer
|
||||||
|
mvi h,255 !now h=1 if negative signed number, h=0 otherwise.
|
||||||
|
|
||||||
|
1: mov a,l !return 0 or -1 if hl>=16
|
||||||
|
cpi 16
|
||||||
|
jnc 3f
|
||||||
|
|
||||||
|
2: dcr l
|
||||||
|
jm 4f
|
||||||
|
mov a,h
|
||||||
|
rar !set carry bit correct
|
||||||
|
mov a,d
|
||||||
|
rar
|
||||||
|
mov d,a
|
||||||
|
mov a,e
|
||||||
|
rar
|
||||||
|
mov e,a
|
||||||
|
jmp 2b
|
||||||
|
|
||||||
|
3: mov d,h
|
||||||
|
mov e,h
|
||||||
|
|
||||||
|
4: lhld .retadr
|
||||||
|
pchl
|
||||||
61
mach/i80/libem/sri4.s
Normal file
61
mach/i80/libem/sri4.s
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
.define .sri4
|
||||||
|
|
||||||
|
! Shift 32 bits signed or unsigned integer right
|
||||||
|
! Expects in a-reg.: 1 if signed integer
|
||||||
|
! 0 if unsigned integer
|
||||||
|
! Expects on stack: number of shifts
|
||||||
|
! number to be shifted
|
||||||
|
! Yields on stack: result
|
||||||
|
|
||||||
|
.sri4: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
pop b !number of shifts
|
||||||
|
pop d !low-order bytes of number to be shifted
|
||||||
|
pop h !high-order bytes
|
||||||
|
mvi b,0
|
||||||
|
ora a
|
||||||
|
jz 1f !jump if unsigned integer
|
||||||
|
mov a,h
|
||||||
|
ral
|
||||||
|
jnc 1f !jump if positive signed integer
|
||||||
|
mvi b,255
|
||||||
|
|
||||||
|
1: mov a,c
|
||||||
|
cpi 32
|
||||||
|
jnc 3f
|
||||||
|
|
||||||
|
2: dcr c
|
||||||
|
jm 4f
|
||||||
|
mov a,b
|
||||||
|
rar
|
||||||
|
mov a,h
|
||||||
|
rar
|
||||||
|
mov h,a
|
||||||
|
mov a,l
|
||||||
|
rar
|
||||||
|
mov l,a
|
||||||
|
mov a,d
|
||||||
|
rar
|
||||||
|
mov d,a
|
||||||
|
mov a,e
|
||||||
|
rar
|
||||||
|
mov e,a
|
||||||
|
jmp 2b
|
||||||
|
|
||||||
|
3: mov d,b
|
||||||
|
mov e,b
|
||||||
|
mov h,b
|
||||||
|
mov l,b
|
||||||
|
|
||||||
|
4: push h
|
||||||
|
push d
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
46
mach/i80/libem/sti.s
Normal file
46
mach/i80/libem/sti.s
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
.define .sti
|
||||||
|
|
||||||
|
! Store indirect
|
||||||
|
! Expects on stack: number of bytes to be stored
|
||||||
|
! bytes to be stored
|
||||||
|
|
||||||
|
.sti: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov l,c
|
||||||
|
mov h,b
|
||||||
|
shld .bcreg ! save bc
|
||||||
|
|
||||||
|
pop h
|
||||||
|
xra a
|
||||||
|
mov a,d
|
||||||
|
rar
|
||||||
|
mov d,a
|
||||||
|
mov a,e
|
||||||
|
rar
|
||||||
|
mov e,a ! de = word count
|
||||||
|
jnc 1f
|
||||||
|
|
||||||
|
! if 1 byte array element only:
|
||||||
|
mov a,d ! trap if de odd and <>1
|
||||||
|
ora e
|
||||||
|
cnz eoddz
|
||||||
|
pop b
|
||||||
|
mov m,c
|
||||||
|
jmp 2f
|
||||||
|
|
||||||
|
1: pop b
|
||||||
|
mov m,c
|
||||||
|
inx h
|
||||||
|
mov m,b
|
||||||
|
inx h
|
||||||
|
dcx d
|
||||||
|
mov a,d
|
||||||
|
ora e
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
2: lhld .bcreg
|
||||||
|
mov c,l
|
||||||
|
mov b,h
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
|
|
||||||
38
mach/i80/libem/xor.s
Normal file
38
mach/i80/libem/xor.s
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
.define .xor
|
||||||
|
|
||||||
|
|
||||||
|
! Any size exclusive-or.
|
||||||
|
! Expects: size in de-registers
|
||||||
|
! operands on stack
|
||||||
|
! Yields: result on stack
|
||||||
|
|
||||||
|
.xor: pop h
|
||||||
|
shld .retadr
|
||||||
|
mov h,b
|
||||||
|
mov l,c
|
||||||
|
shld .bcreg
|
||||||
|
|
||||||
|
lxi h,0
|
||||||
|
dad sp
|
||||||
|
mov c,l
|
||||||
|
mov b,h !now bc points to top of first operand
|
||||||
|
dad d !and hl points to top of second operand
|
||||||
|
push h !this will be the new stackpointer
|
||||||
|
1: ldax b
|
||||||
|
xra m
|
||||||
|
mov m,a
|
||||||
|
inx h
|
||||||
|
inx b
|
||||||
|
dcx d
|
||||||
|
mov a,e
|
||||||
|
ora d
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
pop h
|
||||||
|
sphl
|
||||||
|
|
||||||
|
lhld .bcreg
|
||||||
|
mov b,h
|
||||||
|
mov c,l
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
8
mach/i80/libmon/LIST
Normal file
8
mach/i80/libmon/LIST
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
tail
|
||||||
|
mon.s
|
||||||
|
trp.s
|
||||||
|
inn2.s
|
||||||
|
prstring.s
|
||||||
|
prdec.s
|
||||||
|
char.her.s
|
||||||
|
tail.s
|
||||||
16
mach/i80/libmon/Makefile
Normal file
16
mach/i80/libmon/Makefile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
install: tail
|
||||||
|
../../install head.s head_em
|
||||||
|
../../install tail tail_sys
|
||||||
|
|
||||||
|
cmp: tail
|
||||||
|
-../../compare head.s head_em
|
||||||
|
-../../compare tail tail_sys
|
||||||
|
|
||||||
|
tail:
|
||||||
|
arch cr `cat LIST`
|
||||||
|
|
||||||
|
opr:
|
||||||
|
make pr | opr
|
||||||
|
pr:
|
||||||
|
@pr `pwd`/Makefile `pwd`/head.s
|
||||||
|
@pr -l33 `tail +1 LIST|sort`
|
||||||
6
mach/i80/libmon/README
Normal file
6
mach/i80/libmon/README
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
This library should contain one of the files char.her.s, that has routines
|
||||||
|
getchar and putchar for the MC-CPM, and char.nas.s, that
|
||||||
|
has the same routines for the Nascom.
|
||||||
|
The default is char.her.s.
|
||||||
|
The file char.nas.s is presented in this directory and not included
|
||||||
|
in the libarary.
|
||||||
31
mach/i80/libmon/char.her.s
Normal file
31
mach/i80/libmon/char.her.s
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
.define getchar, putchar
|
||||||
|
|
||||||
|
! These getchar and putchar routines can be used for HERMAC computer
|
||||||
|
|
||||||
|
! Read a character from HERMAC-monitor
|
||||||
|
! Character is returned in a-reg
|
||||||
|
|
||||||
|
getchar:
|
||||||
|
in 0xF1
|
||||||
|
ani 1
|
||||||
|
jz getchar
|
||||||
|
in 0xF0
|
||||||
|
cpi 0x0D
|
||||||
|
jnz 1f
|
||||||
|
mvi a,0x0A
|
||||||
|
1: ret
|
||||||
|
|
||||||
|
! Write character on HERMAC monitor
|
||||||
|
! Assumes character in a-reg
|
||||||
|
|
||||||
|
putchar:
|
||||||
|
cpi 0x0A
|
||||||
|
jnz 1f
|
||||||
|
mvi a,0x1F
|
||||||
|
1: push psw
|
||||||
|
2: in 0xF1
|
||||||
|
ani 4
|
||||||
|
jz 2b
|
||||||
|
pop psw
|
||||||
|
out 0xF0
|
||||||
|
ret
|
||||||
50
mach/i80/libmon/char.nas.s
Normal file
50
mach/i80/libmon/char.nas.s
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
.define getchar, putchar
|
||||||
|
|
||||||
|
! These getchar and putchar routines can be used for NASCOM computer.
|
||||||
|
|
||||||
|
! Read character from NASCOM-monitor
|
||||||
|
! Character is returned in a-reg
|
||||||
|
|
||||||
|
getchar:
|
||||||
|
call 0x69
|
||||||
|
jnc getchar
|
||||||
|
cpi 0x1F
|
||||||
|
jz CR
|
||||||
|
cpi 0x1D
|
||||||
|
jz BS
|
||||||
|
ret
|
||||||
|
|
||||||
|
CR: mvi a,0x0A
|
||||||
|
ret
|
||||||
|
|
||||||
|
BS: mvi a,0x08
|
||||||
|
ret
|
||||||
|
|
||||||
|
! Write charcacter on NASCOM-monitor
|
||||||
|
! Assumes character in a-reg
|
||||||
|
|
||||||
|
putchar:
|
||||||
|
push h
|
||||||
|
push b
|
||||||
|
lxi h,tab
|
||||||
|
mvi b,5
|
||||||
|
1: cmp m
|
||||||
|
jz fetch
|
||||||
|
inx h
|
||||||
|
inx h
|
||||||
|
dcr b
|
||||||
|
jnz 1b
|
||||||
|
2: call 0x013B
|
||||||
|
pop b
|
||||||
|
pop h
|
||||||
|
ret
|
||||||
|
fetch: inx h
|
||||||
|
mov a,m
|
||||||
|
jmp 2b
|
||||||
|
! conversion table for NASCOM characters
|
||||||
|
tab: .byte 0x0D,0x00
|
||||||
|
.byte 0x1B,0x1E
|
||||||
|
.byte 0x08,0x1D
|
||||||
|
.byte 0x0A,0x1F
|
||||||
|
.byte 0x7F,0x00
|
||||||
|
|
||||||
49
mach/i80/libmon/head.s
Normal file
49
mach/i80/libmon/head.s
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
.define hol0, argv, envp, begbss
|
||||||
|
.define .ignmask,.reghp,.trapproc,.fra
|
||||||
|
.define .retadr,.retadr1,.areg,.bcreg,.tmp1
|
||||||
|
.define block1, block2, block3
|
||||||
|
.define .stop
|
||||||
|
|
||||||
|
.base 0x1000
|
||||||
|
.text
|
||||||
|
lxi h,0x1000 ! stack will grow from 0x1000 downwards
|
||||||
|
sphl
|
||||||
|
lxi h,begbss ! clear bss
|
||||||
|
lxi d,endbss-begbss
|
||||||
|
mvi c,0
|
||||||
|
|
||||||
|
2: mov m,c
|
||||||
|
inx h
|
||||||
|
dcx d
|
||||||
|
mov a,e
|
||||||
|
ora d
|
||||||
|
jnz 2b
|
||||||
|
|
||||||
|
lxi h,envp ! call main
|
||||||
|
push h
|
||||||
|
lxi h,argv
|
||||||
|
push h
|
||||||
|
lxi h,0
|
||||||
|
push h
|
||||||
|
call _m_a_i_n
|
||||||
|
.stop: jmp 0xfb52
|
||||||
|
|
||||||
|
.bss
|
||||||
|
begbss:
|
||||||
|
.trapproc: .space 2
|
||||||
|
.ignmask: .space 2
|
||||||
|
.data
|
||||||
|
hol0: .space 8
|
||||||
|
.reghp: .word endbss
|
||||||
|
argv: .word 0
|
||||||
|
envp: .word 0
|
||||||
|
.retadr: .space 2 ! used to save return address
|
||||||
|
.retadr1: .space 2 ! reserve
|
||||||
|
.bcreg: .space 2 ! used to save localbase
|
||||||
|
.areg: .space 1
|
||||||
|
.tmp1: .space 2
|
||||||
|
.fra: .space 8 ! 8 bytes function return area
|
||||||
|
block1: .space 4 ! used by 32 bits divide and
|
||||||
|
block2: .space 4 ! multiply routines
|
||||||
|
block3: .space 4
|
||||||
|
|
||||||
38
mach/i80/libmon/inn2.s
Normal file
38
mach/i80/libmon/inn2.s
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
.define .inn2
|
||||||
|
|
||||||
|
! Bit test on 16 bits set
|
||||||
|
! Expects on stack: bit number
|
||||||
|
! set to be tested
|
||||||
|
! Yields in de-registers: 0 if bit is reset or bit number out of range
|
||||||
|
! 1 if bit is set
|
||||||
|
|
||||||
|
.inn2: pop h
|
||||||
|
shld .retadr
|
||||||
|
|
||||||
|
pop d !bit number
|
||||||
|
pop h !set to be tested
|
||||||
|
mov a,e
|
||||||
|
cpi 16
|
||||||
|
jnc 3f
|
||||||
|
cpi 8
|
||||||
|
jnc 1f
|
||||||
|
mov e,a
|
||||||
|
mov a,l !l-reg contains the wanted bit
|
||||||
|
jmp 2f
|
||||||
|
|
||||||
|
1: sbi 8
|
||||||
|
mov e,a
|
||||||
|
mov a,h !h-reg contains the wanted bit
|
||||||
|
|
||||||
|
2: dcr e
|
||||||
|
jm 4f
|
||||||
|
rar
|
||||||
|
jmp 2b
|
||||||
|
|
||||||
|
3: xra a !return 0 if bit number out of range
|
||||||
|
4: ani 1
|
||||||
|
mov e,a
|
||||||
|
mvi d,0
|
||||||
|
|
||||||
|
lhld .retadr
|
||||||
|
pchl
|
||||||
@@ -7,6 +7,9 @@
|
|||||||
! number 1: exit
|
! number 1: exit
|
||||||
! number 3: read
|
! number 3: read
|
||||||
! number 4: write
|
! number 4: write
|
||||||
|
! number 5: open
|
||||||
|
! number 6: close
|
||||||
|
! number 54: ioctl
|
||||||
! If called with a number of a call that is not implemented,
|
! If called with a number of a call that is not implemented,
|
||||||
! a trap is generated.
|
! a trap is generated.
|
||||||
|
|
||||||
@@ -24,10 +27,16 @@
|
|||||||
jz monread ! is it a read?
|
jz monread ! is it a read?
|
||||||
cpi 4
|
cpi 4
|
||||||
jz monwrite ! is it a write?
|
jz monwrite ! is it a write?
|
||||||
|
cpi 5
|
||||||
|
jz monopen ! is it an open?
|
||||||
|
cpi 6
|
||||||
|
jz monclose ! is it a close?
|
||||||
|
cpi 54
|
||||||
|
jz monioctl
|
||||||
jmp ebadmon ! trap
|
jmp ebadmon ! trap
|
||||||
|
|
||||||
monexit:
|
monexit:
|
||||||
rst 4
|
jmp .stop
|
||||||
|
|
||||||
monread:
|
monread:
|
||||||
pop h ! file-descriptor, not used
|
pop h ! file-descriptor, not used
|
||||||
@@ -69,6 +78,28 @@ monwrite:
|
|||||||
2: push d ! no error
|
2: push d ! no error
|
||||||
jmp monret
|
jmp monret
|
||||||
|
|
||||||
|
|
||||||
|
monopen:
|
||||||
|
pop h ! pointer to string
|
||||||
|
pop h ! flag
|
||||||
|
lxi h,-1
|
||||||
|
push h ! push file descriptor
|
||||||
|
push h ! push error code twice
|
||||||
|
push h
|
||||||
|
jmp monret
|
||||||
|
|
||||||
|
monclose:
|
||||||
|
lxi h,0
|
||||||
|
xthl ! remove file descriptor and push error code
|
||||||
|
jmp monret
|
||||||
|
|
||||||
|
monioctl:
|
||||||
|
pop h ! file descriptor
|
||||||
|
pop h ! request
|
||||||
|
lxi h,0
|
||||||
|
xthl ! remove argp and push error code
|
||||||
|
jmp monret
|
||||||
|
|
||||||
monret:
|
monret:
|
||||||
lhld .bcreg
|
lhld .bcreg
|
||||||
mov b,h
|
mov b,h
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user