aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--BENCHES330
-rw-r--r--INSTALL99
-rw-r--r--Makefile157
-rw-r--r--Makefile.def-samples/MakeDef.cad25
-rw-r--r--Makefile.def-samples/MakeDef.dos32
-rw-r--r--Makefile.def-samples/MakeDef.dpmi30
-rw-r--r--Makefile.def-samples/Makefile.def-alpha-dec-osf13.227
-rw-r--r--Makefile.def-samples/Makefile.def-alpha-dec-osf14.027
-rw-r--r--Makefile.def-samples/Makefile.def-alpha-unknown-linux2.x.x25
-rw-r--r--Makefile.def-samples/Makefile.def-hppa-hp-hpux-10.028
-rw-r--r--Makefile.def-samples/Makefile.def-hppa-hp-hpux-9.026
-rw-r--r--Makefile.def-samples/Makefile.def-i386-unknown-dpmi30
-rw-r--r--Makefile.def-samples/Makefile.def-i386-unknown-linux2.x.x27
-rw-r--r--Makefile.def-samples/Makefile.def-i386-unknown-msdos32
-rw-r--r--Makefile.def-samples/Makefile.def-i386-unknown-os233
-rw-r--r--Makefile.def-samples/Makefile.def-i386-unknown-os2-visualage31
-rw-r--r--Makefile.def-samples/Makefile.def-i386-unknown-win3228
-rw-r--r--Makefile.def-samples/Makefile.def-m68k-pcs-munix325
-rw-r--r--Makefile.def-samples/Makefile.def-m68k-sun-netbsd1.228
-rw-r--r--Makefile.def-samples/Makefile.def-mips-dec-netbsd1.228
-rw-r--r--Makefile.def-samples/Makefile.def-mips-dec-ultrix4.325
-rw-r--r--Makefile.def-samples/Makefile.def-mips-sgi-irix6.225
-rw-r--r--Makefile.def-samples/Makefile.def-mips64-sgi-irix6.425
-rw-r--r--Makefile.def-samples/Makefile.def-rs6k-ibm-aix4128
-rw-r--r--Makefile.def-samples/Makefile.def-sparc-sun-solaris2.x24
-rw-r--r--Makefile.def-samples/Makefile.def-sparc-sun-sunos4.1.325
-rw-r--r--Makefile.def-samples/Makefile.def-vax-dec-ultrix4.125
-rw-r--r--Makefile.def.tmpl25
-rwxr-xr-xMakefile.dos120
-rw-r--r--Makefile.os2100
-rw-r--r--README98
-rw-r--r--README.DOS26
-rw-r--r--README.KR55
-rw-r--r--README.LANGS197
-rw-r--r--README.OS226
-rw-r--r--TODO6
-rw-r--r--a2k.c193
-rw-r--r--addcr.c14
-rw-r--r--as.c2985
-rw-r--r--as.h11
-rw-r--r--as.res983
-rw-r--r--as1750.c1295
-rw-r--r--as1750.h18
-rw-r--r--asl.1377
-rw-r--r--asl.def2
-rw-r--r--asmallg.c1341
-rw-r--r--asmallg.h21
-rw-r--r--asmcode.c239
-rw-r--r--asmcode.h27
-rw-r--r--asmdebug.c320
-rw-r--r--asmdebug.h20
-rw-r--r--asmdef.c315
-rw-r--r--asmdef.h400
-rw-r--r--asmfnums.c167
-rw-r--r--asmfnums.h29
-rw-r--r--asmif.c433
-rw-r--r--asmif.h37
-rw-r--r--asminclist.c116
-rw-r--r--asminclist.h19
-rw-r--r--asmitree.c277
-rw-r--r--asmitree.h65
-rw-r--r--asmmac.c503
-rw-r--r--asmmac.h105
-rw-r--r--asmpars.c3822
-rw-r--r--asmpars.h207
-rw-r--r--asmrelocs.c133
-rw-r--r--asmrelocs.h22
-rw-r--r--asmsub.c1526
-rw-r--r--asmsub.h166
-rw-r--r--bincmp.c46
-rw-r--r--bpemu.c239
-rw-r--r--bpemu.h33
-rw-r--r--changelog729
-rw-r--r--chardefs.h237
-rw-r--r--chunks.c228
-rw-r--r--chunks.h44
-rw-r--r--cmdarg.c222
-rw-r--r--cmdarg.h46
-rw-r--r--cmdarg.res24
-rw-r--r--code166.c1697
-rw-r--r--code166.h11
-rw-r--r--code16c5x.c448
-rw-r--r--code16c5x.h12
-rw-r--r--code16c8x.c472
-rw-r--r--code16c8x.h11
-rw-r--r--code17c4x.c521
-rw-r--r--code17c4x.h11
-rw-r--r--code29k.c887
-rw-r--r--code29k.h11
-rw-r--r--code3201x.c553
-rw-r--r--code3201x.h11
-rw-r--r--code3202x.c1122
-rw-r--r--code3202x.h9
-rw-r--r--code3203x.c1511
-rw-r--r--code3203x.h11
-rw-r--r--code3205x.c1852
-rw-r--r--code3205x.h9
-rw-r--r--code3206x.c2313
-rw-r--r--code3206x.h12
-rw-r--r--code370.c1117
-rw-r--r--code370.h11
-rw-r--r--code4004.c503
-rw-r--r--code4004.h11
-rw-r--r--code4500.c397
-rw-r--r--code4500.h11
-rw-r--r--code47c00.c1126
-rw-r--r--code47c00.h11
-rw-r--r--code48.c998
-rw-r--r--code48.h11
-rw-r--r--code51.c2304
-rw-r--r--code51.h11
-rw-r--r--code53c8xx.c1055
-rw-r--r--code53c8xx.h11
-rw-r--r--code56k.c2566
-rw-r--r--code56k.h11
-rw-r--r--code601.c2017
-rw-r--r--code601.h11
-rw-r--r--code65.c736
-rw-r--r--code65.h11
-rw-r--r--code68.c847
-rw-r--r--code68.h11
-rw-r--r--code6804.c451
-rw-r--r--code6804.h11
-rw-r--r--code6805.c786
-rw-r--r--code6805.h11
-rw-r--r--code6809.c1318
-rw-r--r--code6809.h11
-rw-r--r--code6812.c1143
-rw-r--r--code6812.h11
-rw-r--r--code6816.c1073
-rw-r--r--code6816.h11
-rw-r--r--code68k.c4428
-rw-r--r--code68k.h11
-rw-r--r--code7000.c1315
-rw-r--r--code7000.h11
-rw-r--r--code75k0.c1436
-rw-r--r--code75k0.h11
-rw-r--r--code7700.c1304
-rw-r--r--code7700.h11
-rw-r--r--code7720.c587
-rw-r--r--code7720.h11
-rw-r--r--code77230.c1024
-rw-r--r--code77230.h11
-rw-r--r--code78c10.c978
-rw-r--r--code78c10.h11
-rw-r--r--code78k0.c1228
-rw-r--r--code78k0.h11
-rw-r--r--code8008.c356
-rw-r--r--code8008.h11
-rw-r--r--code85.c423
-rw-r--r--code85.h11
-rw-r--r--code86.c2600
-rw-r--r--code86.h11
-rw-r--r--code87c800.c1316
-rw-r--r--code87c800.h11
-rw-r--r--code8x30x.c559
-rw-r--r--code8x30x.h11
-rw-r--r--code90c141.c1293
-rw-r--r--code90c141.h11
-rw-r--r--code96.c1253
-rw-r--r--code96.h11
-rw-r--r--code960.c767
-rw-r--r--code960.h11
-rw-r--r--code96c141.c2331
-rw-r--r--code96c141.h11
-rw-r--r--code97c241.c2190
-rw-r--r--code97c241.h11
-rw-r--r--code9900.c685
-rw-r--r--code9900.h11
-rw-r--r--codeace.c767
-rw-r--r--codeace.h11
-rw-r--r--codeavr.c784
-rw-r--r--codeavr.h11
-rw-r--r--codecop8.c727
-rw-r--r--codecop8.h11
-rw-r--r--codeflt1750.c158
-rw-r--r--codeflt1750.h7
-rw-r--r--codefmc8.c1017
-rw-r--r--codefmc8.h11
-rw-r--r--codeh8_3.c1707
-rw-r--r--codeh8_3.h11
-rw-r--r--codeh8_5.c1510
-rw-r--r--codeh8_5.h11
-rw-r--r--codem16.c2819
-rw-r--r--codem16.h11
-rw-r--r--codem16c.c2360
-rw-r--r--codem16c.h11
-rw-r--r--codemcore.c806
-rw-r--r--codemcore.h11
-rw-r--r--codemsp.c539
-rw-r--r--codemsp.h11
-rw-r--r--codepseudo.c1246
-rw-r--r--codepseudo.h37
-rw-r--r--codesc14xxx.c441
-rw-r--r--codesc14xxx.h16
-rw-r--r--codescmp.c326
-rw-r--r--codescmp.h11
-rw-r--r--codest6.c634
-rw-r--r--codest6.h11
-rw-r--r--codest7.c878
-rw-r--r--codest7.h11
-rw-r--r--codest9.c1878
-rw-r--r--codest9.h11
-rw-r--r--codetms7.c954
-rw-r--r--codetms7.h11
-rw-r--r--codevars.c14
-rw-r--r--codevars.h12
-rw-r--r--codexa.c1975
-rw-r--r--codexa.h11
-rw-r--r--codez8.c856
-rw-r--r--codez8.h11
-rw-r--r--codez80.c2814
-rw-r--r--codez80.h11
-rw-r--r--datatypes.h55
-rw-r--r--doc_DE/Makefile37
-rw-r--r--doc_DE/as.tex11792
-rw-r--r--doc_DE/dina4.sty135
-rw-r--r--doc_DE/pscomm.tex16
-rw-r--r--doc_DE/pscpu.tex420
-rw-r--r--doc_DE/tabids.tex33
-rw-r--r--doc_DE/taborg1.tex48
-rw-r--r--doc_DE/taborg2.tex49
-rw-r--r--doc_DE/taborg3.tex51
-rw-r--r--doc_DE/taborg4.tex11
-rw-r--r--doc_EN/Makefile36
-rw-r--r--doc_EN/as.tex11521
-rw-r--r--endian.c333
-rw-r--r--endian.h54
-rw-r--r--equs.h6
-rw-r--r--fileformat.h40
-rw-r--r--findhyphen.c270
-rw-r--r--findhyphen.h9
-rw-r--r--grhyph.c569
-rw-r--r--grhyph.h12
-rw-r--r--header.res6
-rw-r--r--headids.c124
-rw-r--r--headids.h28
-rw-r--r--hex.c72
-rw-r--r--hex.h19
-rw-r--r--include/80c50x.inc257
-rw-r--r--include/80c552.inc228
-rw-r--r--include/bitfuncs.inc85
-rw-r--r--include/ctype.inc94
-rw-r--r--include/h8_3048.inc560
-rw-r--r--include/reg166.inc780
-rw-r--r--include/reg251.inc225
-rw-r--r--include/reg29k.inc127
-rw-r--r--include/reg53x.inc344
-rw-r--r--include/reg683xx.inc700
-rw-r--r--include/reg7000.inc120
-rw-r--r--include/reg78k0.inc245
-rw-r--r--include/reg96.inc610
-rw-r--r--include/regavr.inc329
-rw-r--r--include/regcop8.inc242
-rw-r--r--include/reghc12.inc228
-rw-r--r--include/regm16c.inc421
-rw-r--r--include/regmsp.inc227
-rw-r--r--include/regst9.inc624
-rw-r--r--include/regz380.inc68
-rw-r--r--include/stddef04.inc54
-rw-r--r--include/stddef16.inc188
-rw-r--r--include/stddef17.inc116
-rw-r--r--include/stddef18.inc262
-rw-r--r--include/stddef2x.inc53
-rw-r--r--include/stddef37.inc527
-rw-r--r--include/stddef3x.inc96
-rw-r--r--include/stddef47.inc279
-rw-r--r--include/stddef51.inc374
-rw-r--r--include/stddef56k.inc69
-rw-r--r--include/stddef5x.inc109
-rw-r--r--include/stddef60.inc674
-rw-r--r--include/stddef62.inc147
-rw-r--r--include/stddef75.inc699
-rw-r--r--include/stddef87.inc218
-rw-r--r--include/stddef90.inc129
-rw-r--r--include/stddef96.inc170
-rw-r--r--include/stddefxa.inc405
-rw-r--r--include/stddefz8.inc56
-rw-r--r--install.bat24
-rw-r--r--install.cmd24
-rwxr-xr-xinstall.sh66
-rw-r--r--ioerrs.c193
-rw-r--r--ioerrs.h13
-rw-r--r--ioerrs.res212
-rw-r--r--makedefs.files35
-rw-r--r--makedefs.src53
-rw-r--r--makedefs.str41
-rw-r--r--marks.asm29
-rw-r--r--nlmessages.c210
-rw-r--r--nlmessages.h24
-rw-r--r--nls.c644
-rw-r--r--nls.h60
-rw-r--r--objdefs.dos14
-rw-r--r--objdefs.unix14
-rw-r--r--p2bin.1241
-rw-r--r--p2bin.c536
-rw-r--r--p2bin.res46
-rw-r--r--p2hex.1288
-rw-r--r--p2hex.c987
-rw-r--r--p2hex.res77
-rw-r--r--pascstyle.h17
-rw-r--r--pbind.1145
-rw-r--r--pbind.c182
-rw-r--r--pbind.res34
-rw-r--r--plist.184
-rw-r--r--plist.c169
-rw-r--r--plist.res57
-rw-r--r--reltypes.c9
-rw-r--r--rescomp.c433
-rw-r--r--specchars.h13
-rw-r--r--stdhandl.c110
-rw-r--r--stdhandl.h21
-rw-r--r--stdinc.h45
-rw-r--r--stringlists.c151
-rw-r--r--stringlists.h43
-rw-r--r--strutil.c461
-rw-r--r--strutil.h70
-rw-r--r--sysdefs.h774
-rw-r--r--tests/t_166/asflags0
-rw-r--r--tests/t_166/t_166.asm232
-rw-r--r--tests/t_166/t_166.doc5
-rw-r--r--tests/t_166/t_166.oribin0 -> 534 bytes
-rw-r--r--tests/t_16c5x/asflags0
-rwxr-xr-xtests/t_16c5x/t_16c5x.asm45
-rw-r--r--tests/t_16c5x/t_16c5x.doc5
-rwxr-xr-xtests/t_16c5x/t_16c5x.oribin0 -> 70 bytes
-rw-r--r--tests/t_16c84/asflags0
-rw-r--r--tests/t_16c84/t_16c84.asm53
-rw-r--r--tests/t_16c84/t_16c84.doc5
-rw-r--r--tests/t_16c84/t_16c84.oribin0 -> 90 bytes
-rw-r--r--tests/t_17c42/asflags0
-rw-r--r--tests/t_17c42/t_17c42.asm66
-rw-r--r--tests/t_17c42/t_17c42.doc5
-rw-r--r--tests/t_17c42/t_17c42.oribin0 -> 112 bytes
-rw-r--r--tests/t_251/asflags0
-rw-r--r--tests/t_251/t_251.asm399
-rw-r--r--tests/t_251/t_251.doc5
-rw-r--r--tests/t_251/t_251.oribin0 -> 1035 bytes
-rw-r--r--tests/t_296/asflags0
-rw-r--r--tests/t_296/t_296.asm132
-rw-r--r--tests/t_296/t_296.doc6
-rwxr-xr-xtests/t_296/t_296.oribin0 -> 463 bytes
-rw-r--r--tests/t_29k/asflags0
-rw-r--r--tests/t_29k/t_29k.asm80
-rw-r--r--tests/t_29k/t_29k.doc5
-rw-r--r--tests/t_29k/t_29k.oribin0 -> 220 bytes
-rw-r--r--tests/t_32/asflags0
-rw-r--r--tests/t_32/t_32.asm39
-rw-r--r--tests/t_32/t_32.doc6
-rw-r--r--tests/t_32/t_32.oribin0 -> 134 bytes
-rw-r--r--tests/t_3201x/asflags0
-rw-r--r--tests/t_3201x/t_3201x.asm74
-rw-r--r--tests/t_3201x/t_3201x.doc5
-rw-r--r--tests/t_3201x/t_3201x.oribin0 -> 148 bytes
-rw-r--r--tests/t_3203x/asflags0
-rw-r--r--tests/t_3203x/t_3203x.asm271
-rw-r--r--tests/t_3203x/t_3203x.doc5
-rwxr-xr-xtests/t_3203x/t_3203x.oribin0 -> 816 bytes
-rw-r--r--tests/t_3205x/asflags0
-rw-r--r--tests/t_3205x/t_3205x.asm499
-rw-r--r--tests/t_3205x/t_3205x.doc7
-rw-r--r--tests/t_3205x/t_3205x.oribin0 -> 866 bytes
-rw-r--r--tests/t_3206x/asflags0
-rw-r--r--tests/t_3206x/t_3206x.asm241
-rw-r--r--tests/t_3206x/t_3206x.doc5
-rw-r--r--tests/t_3206x/t_3206x.oribin0 -> 744 bytes
-rw-r--r--tests/t_370/asflags0
-rw-r--r--tests/t_370/t_370.asm163
-rw-r--r--tests/t_370/t_370.doc5
-rw-r--r--tests/t_370/t_370.oribin0 -> 317 bytes
-rw-r--r--tests/t_4004/asflags0
-rw-r--r--tests/t_4004/t_4004.asm205
-rw-r--r--tests/t_4004/t_4004.doc5
-rw-r--r--tests/t_4004/t_4004.oribin0 -> 240 bytes
-rw-r--r--tests/t_403/asflags0
-rw-r--r--tests/t_403/t_403.asm27
-rw-r--r--tests/t_403/t_403.doc6
-rw-r--r--tests/t_403/t_403.oribin0 -> 64 bytes
-rw-r--r--tests/t_4500/asflags0
-rw-r--r--tests/t_4500/t_4500.asm109
-rw-r--r--tests/t_4500/t_4500.doc5
-rw-r--r--tests/t_4500/t_4500.oribin0 -> 246 bytes
-rw-r--r--tests/t_47c00/asflags0
-rw-r--r--tests/t_47c00/t_47c00.asm255
-rw-r--r--tests/t_47c00/t_47c00.doc5
-rw-r--r--tests/t_47c00/t_47c00.oribin0 -> 529 bytes
-rw-r--r--tests/t_48/asflags0
-rw-r--r--tests/t_48/t_48.asm178
-rw-r--r--tests/t_48/t_48.doc5
-rw-r--r--tests/t_48/t_48.oribin0 -> 137 bytes
-rw-r--r--tests/t_56000/asflags0
-rw-r--r--tests/t_56000/t_56000.asm244
-rw-r--r--tests/t_56000/t_56000.doc5
-rw-r--r--tests/t_56000/t_56000.oribin0 -> 980 bytes
-rw-r--r--tests/t_56300/asflags0
-rw-r--r--tests/t_56300/t_56300.asm1462
-rw-r--r--tests/t_56300/t_56300.doc6
-rw-r--r--tests/t_56300/t_56300.oribin0 -> 6788 bytes
-rw-r--r--tests/t_65/asflags0
-rwxr-xr-xtests/t_65/t_65.asm283
-rw-r--r--tests/t_65/t_65.doc5
-rwxr-xr-xtests/t_65/t_65.oribin0 -> 460 bytes
-rw-r--r--tests/t_6502u/asflags0
-rw-r--r--tests/t_6502u/t_6502u.asm110
-rw-r--r--tests/t_6502u/t_6502u.doc7
-rw-r--r--tests/t_6502u/t_6502u.oribin0 -> 207 bytes
-rw-r--r--tests/t_6804/asflags0
-rw-r--r--tests/t_6804/t_6804.asm72
-rw-r--r--tests/t_6804/t_6804.doc5
-rw-r--r--tests/t_6804/t_6804.oribin0 -> 92 bytes
-rw-r--r--tests/t_68040/asflags0
-rw-r--r--tests/t_68040/t_68040.asm29
-rw-r--r--tests/t_68040/t_68040.doc6
-rw-r--r--tests/t_68040/t_68040.oribin0 -> 60 bytes
-rw-r--r--tests/t_6805/asflags0
-rwxr-xr-xtests/t_6805/t_6805.asm244
-rw-r--r--tests/t_6805/t_6805.doc5
-rwxr-xr-xtests/t_6805/t_6805.oribin0 -> 405 bytes
-rw-r--r--tests/t_6808/asflags0
-rw-r--r--tests/t_6808/t_6808.asm406
-rw-r--r--tests/t_6808/t_6808.doc6
-rw-r--r--tests/t_6808/t_6808.oribin0 -> 671 bytes
-rw-r--r--tests/t_6812/asflags0
-rw-r--r--tests/t_6812/t_6812.asm644
-rw-r--r--tests/t_6812/t_6812.doc5
-rw-r--r--tests/t_6812/t_6812.oribin0 -> 1104 bytes
-rw-r--r--tests/t_6816/asflags0
-rw-r--r--tests/t_6816/t_6816.asm1037
-rw-r--r--tests/t_6816/t_6816.doc5
-rw-r--r--tests/t_6816/t_6816.oribin0 -> 2874 bytes
-rw-r--r--tests/t_7000/asflags0
-rw-r--r--tests/t_7000/t_7000.asm249
-rw-r--r--tests/t_7000/t_7000.doc5
-rw-r--r--tests/t_7000/t_7000.oribin0 -> 428 bytes
-rw-r--r--tests/t_75k0/asflags0
-rw-r--r--tests/t_75k0/t_75k0.asm191
-rw-r--r--tests/t_75k0/t_75k0.doc5
-rw-r--r--tests/t_75k0/t_75k0.oribin0 -> 262 bytes
-rw-r--r--tests/t_7700/asflags0
-rw-r--r--tests/t_7700/t_7700.asm356
-rw-r--r--tests/t_7700/t_7700.doc5
-rw-r--r--tests/t_7700/t_7700.oribin0 -> 934 bytes
-rw-r--r--tests/t_7720/asflags0
-rw-r--r--tests/t_7720/t_7720.asm141
-rw-r--r--tests/t_7720/t_7720.doc5
-rw-r--r--tests/t_7720/t_7720.oribin0 -> 392 bytes
-rw-r--r--tests/t_77230/asflags0
-rw-r--r--tests/t_77230/t_77230.asm245
-rw-r--r--tests/t_77230/t_77230.doc5
-rw-r--r--tests/t_77230/t_77230.oribin0 -> 668 bytes
-rw-r--r--tests/t_7725/asflags0
-rw-r--r--tests/t_7725/t_7725.asm171
-rw-r--r--tests/t_7725/t_7725.doc5
-rw-r--r--tests/t_7725/t_7725.oribin0 -> 508 bytes
-rw-r--r--tests/t_78c1x/asflags0
-rw-r--r--tests/t_78c1x/t_78c1x.asm258
-rw-r--r--tests/t_78c1x/t_78c1x.doc5
-rw-r--r--tests/t_78c1x/t_78c1x.oribin0 -> 465 bytes
-rw-r--r--tests/t_78k0/asflags0
-rw-r--r--tests/t_78k0/t_78k0.asm291
-rw-r--r--tests/t_78k0/t_78k0.doc5
-rw-r--r--tests/t_78k0/t_78k0.oribin0 -> 606 bytes
-rw-r--r--tests/t_85/asflags0
-rw-r--r--tests/t_85/t_85.asm134
-rw-r--r--tests/t_85/t_85.doc5
-rw-r--r--tests/t_85/t_85.oribin0 -> 180 bytes
-rw-r--r--tests/t_87c800/asflags0
-rw-r--r--tests/t_87c800/t_87c800.asm310
-rw-r--r--tests/t_87c800/t_87c800.doc5
-rw-r--r--tests/t_87c800/t_87c800.oribin0 -> 609 bytes
-rw-r--r--tests/t_8x30x/asflags0
-rw-r--r--tests/t_8x30x/t_8x30x.asm57
-rw-r--r--tests/t_8x30x/t_8x30x.doc5
-rw-r--r--tests/t_8x30x/t_8x30x.oribin0 -> 80 bytes
-rw-r--r--tests/t_96/asflags0
-rw-r--r--tests/t_96/t_96.asm217
-rw-r--r--tests/t_96/t_96.doc5
-rw-r--r--tests/t_96/t_96.oribin0 -> 531 bytes
-rw-r--r--tests/t_960/asflags0
-rw-r--r--tests/t_960/t_960.asm101
-rw-r--r--tests/t_960/t_960.doc5
-rw-r--r--tests/t_960/t_960.oribin0 -> 404 bytes
-rw-r--r--tests/t_97c241/asflags0
-rw-r--r--tests/t_97c241/t_97c241.asm336
-rw-r--r--tests/t_97c241/t_97c241.doc5
-rw-r--r--tests/t_97c241/t_97c241.oribin0 -> 1100 bytes
-rw-r--r--tests/t_9900/asflags0
-rw-r--r--tests/t_9900/t_9900.asm222
-rw-r--r--tests/t_9900/t_9900.doc5
-rw-r--r--tests/t_9900/t_9900.oribin0 -> 550 bytes
-rw-r--r--tests/t_ace/asflags0
-rw-r--r--tests/t_ace/t_ace.asm132
-rw-r--r--tests/t_ace/t_ace.doc5
-rw-r--r--tests/t_ace/t_ace.oribin0 -> 159 bytes
-rw-r--r--tests/t_avr/asflags0
-rw-r--r--tests/t_avr/t_avr.asm229
-rw-r--r--tests/t_avr/t_avr.doc5
-rw-r--r--tests/t_avr/t_avr.oribin0 -> 238 bytes
-rw-r--r--tests/t_bas52/asflags0
-rw-r--r--tests/t_bas52/bas52.clk18
-rw-r--r--tests/t_bas52/bas52.fp1616
-rw-r--r--tests/t_bas52/bas52.out75
-rw-r--r--tests/t_bas52/bas52.pgm125
-rw-r--r--tests/t_bas52/bas52.pwm25
-rw-r--r--tests/t_bas52/bas52.rst111
-rw-r--r--tests/t_bas52/bas52.tl16
-rw-r--r--tests/t_bas52/look52.inc779
-rw-r--r--tests/t_bas52/t_bas52.asm4644
-rw-r--r--tests/t_bas52/t_bas52.doc11
-rw-r--r--tests/t_bas52/t_bas52.inc2
-rw-r--r--tests/t_bas52/t_bas52.oribin0 -> 8192 bytes
-rw-r--r--tests/t_buf32/asflags0
-rw-r--r--tests/t_buf32/t_buf32.asm4883
-rw-r--r--tests/t_buf32/t_buf32.doc5
-rw-r--r--tests/t_buf32/t_buf32.inc2
-rw-r--r--tests/t_buf32/t_buf32.oribin0 -> 8192 bytes
-rw-r--r--tests/t_cop8/asflags0
-rw-r--r--tests/t_cop8/t_cop8.asm128
-rw-r--r--tests/t_cop8/t_cop8.doc5
-rw-r--r--tests/t_cop8/t_cop8.oribin0 -> 262 bytes
-rw-r--r--tests/t_f2mc8l/asflags0
-rw-r--r--tests/t_f2mc8l/t_f2mc8l.asm242
-rw-r--r--tests/t_f2mc8l/t_f2mc8l.doc5
-rw-r--r--tests/t_f2mc8l/t_f2mc8l.oribin0 -> 314 bytes
-rw-r--r--tests/t_fl90/asflags0
-rw-r--r--tests/t_fl90/cpu_time.inc170
-rw-r--r--tests/t_fl90/float.inc1601
-rw-r--r--tests/t_fl90/macros.inc57
-rw-r--r--tests/t_fl90/mon.inc11
-rw-r--r--tests/t_fl90/t_fl90.asm179
-rw-r--r--tests/t_fl90/t_fl90.doc6
-rw-r--r--tests/t_fl90/t_fl90.oribin0 -> 5466 bytes
-rw-r--r--tests/t_fl900/asflags0
-rw-r--r--tests/t_fl900/conout.inc154
-rw-r--r--tests/t_fl900/cpu_time.inc240
-rw-r--r--tests/t_fl900/float.inc973
-rw-r--r--tests/t_fl900/macros.inc16
-rw-r--r--tests/t_fl900/t_fl900.asm166
-rw-r--r--tests/t_fl900/t_fl900.doc6
-rw-r--r--tests/t_fl900/t_fl900.inc2
-rwxr-xr-xtests/t_fl900/t_fl900.oribin0 -> 3408 bytes
-rw-r--r--tests/t_full09/asflags1
-rw-r--r--tests/t_full09/t_full09.asm1604
-rw-r--r--tests/t_full09/t_full09.doc6
-rw-r--r--tests/t_full09/t_full09.oribin0 -> 7308 bytes
-rw-r--r--tests/t_h8_3/asflags0
-rw-r--r--tests/t_h8_3/t_h8_3.asm353
-rw-r--r--tests/t_h8_3/t_h8_3.doc5
-rw-r--r--tests/t_h8_3/t_h8_3.oribin0 -> 1156 bytes
-rw-r--r--tests/t_h8_5/asflags0
-rw-r--r--tests/t_h8_5/t_h8_5.asm229
-rw-r--r--tests/t_h8_5/t_h8_5.doc5
-rw-r--r--tests/t_h8_5/t_h8_5.oribin0 -> 407 bytes
-rw-r--r--tests/t_m16c/asflags0
-rw-r--r--tests/t_m16c/t_m16c.asm4051
-rw-r--r--tests/t_m16c/t_m16c.doc6
-rw-r--r--tests/t_m16c/t_m16c.oribin0 -> 15722 bytes
-rw-r--r--tests/t_mcore/asflags0
-rw-r--r--tests/t_mcore/t_mcore.asm140
-rw-r--r--tests/t_mcore/t_mcore.doc5
-rw-r--r--tests/t_mcore/t_mcore.oribin0 -> 240 bytes
-rw-r--r--tests/t_mic51/DEBUG.ASM532
-rw-r--r--tests/t_mic51/MAKRO1.ASM542
-rw-r--r--tests/t_mic51/MEM1.ASM727
-rw-r--r--tests/t_mic51/RUN1.ASM773
-rw-r--r--tests/t_mic51/TAST1.ASM250
-rw-r--r--tests/t_mic51/TEACH1.ASM504
-rw-r--r--tests/t_mic51/asflags1
-rw-r--r--tests/t_mic51/defKey.inc83
-rw-r--r--tests/t_mic51/defModul.inc18
-rw-r--r--tests/t_mic51/defMsg.inc141
-rw-r--r--tests/t_mic51/defParam.inc46
-rw-r--r--tests/t_mic51/defgequ.inc48
-rw-r--r--tests/t_mic51/defint.inc234
-rw-r--r--tests/t_mic51/defmacro.inc175
-rw-r--r--tests/t_mic51/net_lcd.inc33
-rw-r--r--tests/t_mic51/t_mic51.asm2197
-rw-r--r--tests/t_mic51/t_mic51.doc6
-rw-r--r--tests/t_mic51/t_mic51.inc165
-rwxr-xr-xtests/t_mic51/t_mic51.oribin0 -> 17582 bytes
-rw-r--r--tests/t_mic51/t_mod1.asm487
-rw-r--r--tests/t_msp/asflags0
-rw-r--r--tests/t_msp/t_msp.asm116
-rw-r--r--tests/t_msp/t_msp.doc5
-rw-r--r--tests/t_msp/t_msp.oribin0 -> 363 bytes
-rw-r--r--tests/t_parsys/asflags1
-rw-r--r--tests/t_parsys/float.i681226
-rw-r--r--tests/t_parsys/float81.i68293
-rw-r--r--tests/t_parsys/parsys.i68115
-rw-r--r--tests/t_parsys/t_parsys.asm994
-rw-r--r--tests/t_parsys/t_parsys.doc8
-rw-r--r--tests/t_parsys/t_parsys.inc10
-rw-r--r--tests/t_parsys/t_parsys.oribin0 -> 7516 bytes
-rw-r--r--tests/t_scmp/asflags0
-rw-r--r--tests/t_scmp/t_scmp.asm59
-rw-r--r--tests/t_scmp/t_scmp.doc5
-rwxr-xr-xtests/t_scmp/t_scmp.oribin0 -> 68 bytes
-rw-r--r--tests/t_secdrive/asflags0
l---------tests/t_secdrive/lowlevel.inc1
-rw-r--r--tests/t_secdrive/secparam.inc1619
-rw-r--r--tests/t_secdrive/t_secdrive.asm1476
-rw-r--r--tests/t_secdrive/t_secdrive.doc9
-rwxr-xr-xtests/t_secdrive/t_secdrive.oribin0 -> 11271 bytes
-rw-r--r--tests/t_secdrive/wd1002xt.inc773
-rw-r--r--tests/t_secdrive/wd1003at.inc952
-rw-r--r--tests/t_st6/asflags0
-rwxr-xr-xtests/t_st6/t_st6.asm82
-rw-r--r--tests/t_st6/t_st6.doc5
-rwxr-xr-xtests/t_st6/t_st6.oribin0 -> 102 bytes
-rw-r--r--tests/t_st7/asflags0
-rw-r--r--tests/t_st7/t_st7.asm561
-rw-r--r--tests/t_st7/t_st7.doc5
-rw-r--r--tests/t_st7/t_st7.oribin0 -> 1313 bytes
-rw-r--r--tests/t_st9/asflags0
-rw-r--r--tests/t_st9/t_st9.asm1243
-rw-r--r--tests/t_st9/t_st9.doc5
-rwxr-xr-xtests/t_st9/t_st9.oribin0 -> 3290 bytes
-rw-r--r--tests/t_tms7/asflags0
-rwxr-xr-xtests/t_tms7/t_tms7.asm364
-rw-r--r--tests/t_tms7/t_tms7.doc5
-rwxr-xr-xtests/t_tms7/t_tms7.oribin0 -> 696 bytes
-rw-r--r--tests/t_xa/asflags0
-rw-r--r--tests/t_xa/t_xa.asm603
-rw-r--r--tests/t_xa/t_xa.doc5
-rw-r--r--tests/t_xa/t_xa.oribin0 -> 1525 bytes
-rw-r--r--tests/t_z380/asflags0
-rw-r--r--tests/t_z380/t_z380.asm677
-rw-r--r--tests/t_z380/t_z380.doc5
-rw-r--r--tests/t_z380/t_z380.oribin0 -> 1650 bytes
-rw-r--r--tests/t_z8/asflags0
-rw-r--r--tests/t_z8/t_z8.asm116
-rw-r--r--tests/t_z8/t_z8.doc5
-rw-r--r--tests/t_z8/t_z8.oribin0 -> 180 bytes
-rwxr-xr-xtests/testall38
-rw-r--r--tests/testall.bat117
-rw-r--r--tests/testall.cmd117
-rw-r--r--tests/warnlog.DE35
-rw-r--r--tests/warnlog.EN35
-rw-r--r--tex2doc.c2247
-rw-r--r--tex2html.c2570
-rw-r--r--tools.res35
-rw-r--r--tools2.res70
-rw-r--r--toolutils.c293
-rw-r--r--toolutils.h52
-rw-r--r--tsc.h3
-rw-r--r--umlaut.c65
-rw-r--r--unumlaut.c91
-rw-r--r--ushyph.c696
-rw-r--r--ushyph.h14
-rw-r--r--version.c28
-rw-r--r--version.h12
652 files changed, 204311 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c45abd5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+*.o
+*.msg
+*.rsc
+asl
+p2bin
+p2hex
+pbind
+plist
+rescomp
diff --git a/BENCHES b/BENCHES
new file mode 100644
index 0000000..767ec86
--- /dev/null
+++ b/BENCHES
@@ -0,0 +1,330 @@
+This is a file I use to collect the assembly time of a selected subset of
+the AS test suite. It might give you a rough estimate of the performance
+you may expect from your machine. The times are the wallclock times AS
+prints itself, measured three times, averaged and rounded to 1/100's of
+seconds. As system overhead goes into these times, memory size and disk
+speed play a role, so do not quarrel if the results you get vary by a few
+percent... Furthermore, I sometimes manage to make AS itself a bit faster,
+what furtherly distorts the results... the fresher the measuring is (see
+last column), the more accurate a value probably is. When measuring, assure
+that your machine is otherwise unloaded and all the files are on a local
+filesystem (if possible)! Speed of screen output is also an issue, so it
+may not be a bright idea to do the tests on a Sparc console in single user
+mode...
+
+Optimization is the highest available, with some CPU-specific optimi-
+zations (e.g. -m486) ...
+
+
+Alpha AXP-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+Digital Pers. Workstation 433au 21164a 433 [8K+8K/96K]/??? 128 Digital Unix 4.0 DEC-C 3.11 | 0.25s 0.14s 1.52s 245.48 0.567 [ 4. 8.1997]
+Digital AlphaStation 500/266 21164 267 [8K+8K/96K]/2M 128 Digital Unix 4.0 DEC-C 3.11 | 0.43s 0.25s 2.76s 138.59 0.521 [ 1.11.1997]
+Digital PC164 board 21164 500 [8K+8K/96K]/1M 128 Linux 2.1.42 gcc 2.7.2 | 0.62s 0.35s 3.51s 101.08 0.202
+Digital DECpc AXP/150 21064 150 [8K+8K]/512K 32 Linux 2.1.125 gcc 2.7.2.3 | 1.98s 1.04s 11.59s 32.05 0.214 [ 7. 2.1999 comp 96min]
+Digital DECpc AXP/150 21064 150 [8K+8K]/512K 32 Linux 2.1.74 egcs 1.0.1 | 2.05s 0.99s 12.44s 31.51 0.210 [20.06.1998]
+Digital DECpc AXP/150 21064 150 [8K+8K]/512K 32 Linux 1.99.12 DEC-C 3.11 | 2.02s 1.04s 12.09s 31.40 0.209
+Digital DEC 3000 Model 400 21064 133 [8K+8K]/512K 64 Digital Unix 4.0 DEC-C 3.11 | 2.18s 1.09s 12.79s 29.58 0.222
+Digital DEC 3000 Model 300X 21064 175 [8K+8K]/256K 64 Digital Unix 4.0 DEC-C 3.11 | 2.44s 1.30s 14.80s 25.59 0.093
+Digital DEC 3000 Model 300 21064 150 [8K+8K]/256K 64 Digital Unix 4.0 DEC-C 3.11 | 2.84s 1.42s 15.24s 23.38 0.156
+Digital DEC 3000 Model 300LX 21064 125 [8K+8K]/256K 48 Digital Unix 4.0 DEC-C 3.11 | 3.34s 1.59s 18.19s 20.11 0.161
+Digital Noname board 21066 166 [8K+8K]/256K 64 Linux 2.0.34 egcs 1.0.2 | 4.09s 1.87s 21.97s 16.74 0.100 [18. 4.1999 comp 150min]
+
+Sparc-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+Sun Ultra 1/170 UltraSparc-1 167 [16K+16K]/512K 128 Solaris 2.5.1 gcc 2.7.2 | 1.08s 0.56s 5.89s 60.40 0.362
+Sun Ultra 1/140 UltraSparc-1 143 [16K+16K]/512K 64 Solaris 2.5 Sun-C 3.0.1 | 1.13s 0.59s 5.55s 59.74 0.418
+Sun SPARCstation 20/712 2xSuperSparc-2 75 [20K+16K]/1M 256 Solaris 2.5.1 Sun-C 3.0.1 | 1.87s 0.93s 9.78s 35.88 0.478
+Sun SPARCstation 20/612 2xSuperSparc-2 60 [20K+16K]/1M 64 Solaris 2.4 Sun-C 3.0.1 | 2.24s 1.12s 11.58s 30.01 0.500
+Sun SPARCstation 20/612 2xSuperSparc-2 50 [20K+16K]/1M 64 Solaris 2.5 Sun-C 3.0.1 | 2.90s 1.41s 14.53s 23.66 0.473
+Sun SPARCstation 4 MicroSparc-2 85 [16K+8K] ??? Solaris 2.4 Sun-C 3.0.1 | 3.37s 1.56s 17.23s 20.56 0.242
+Sun SPARCstation 10/20 SuperSparc-1 33 [20K+16K] 64 Solaris 2.5 Sun-C 3.0.1 | 4.54s 2.23s 22.54s 15.11 0.458
+Sun SPARCstation Classic MicroSparc 50 [4K+2K] 24 Solaris 2.5.1 Sun-C 3.0.1 | 6.92s 3.22s 37.45s 9.81 0.196
+Sun SPARCstation 1+ LSI L64801 25 64K 16 Solaris 2.4 Sun-C 3.0.1 | 9.16s 4.51s 48.96s 7.30 0.292
+Sun 4/670MP ??? 40(?) 64K(?) ??? SunOS 4.1.3 gcc 2.6.3 | 8.29s 4.87s 51.48s 7.24 0.181
+
+
+Mips-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+SGI Origin 2000 R10000 200 [32K+32K]/4M 512(?) Irix 6.4 SGI-C | 0.64s 0.37s 3.74s 96.16 0.481 [ 4. 8.1997]
+SGI Indigo 2 R4400 200 [16K+16K]/2M 64 Irix 5.3 SGI-C (2) | 1.78s 0.88s 9.70s 37.25 0.186
+SGI Onyx R4400 150 [16K+16K]/4M 256 Irix 5.3 SGI-C (2) | 2.08s 1.07s 11.80s 31.03 0.207
+Digital DECStation 5000/240 R3400 40 64K+64K ??? Ultrix 4.3 gcc 2.7.2 | 3.90s 2.45s 24.45s 15.03 0.376
+Digital DECStation 5000/200 R3000+R3010 25 64K+64K 48 NetBSD 1.3.3 gcc 2.7.2.2 | 8.10s 3.85s 47.64s 8.09 0.324 [17. 1.1999]
+Digital DECStation 3100 R2000+R2010 16.7 64K+64K 16 NetBSD 1.3.3 gcc 2.7.2.2 | 12.78s 6.09s 74.79s 5.14 0.308 [17. 1.1999]
+
+
+RS/6000 / PowerPC-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+IBM R50 8xPPC604e 200 [32K+32K]/2M 4096 AIX 4.2.1 IBM XLC | 0.85s 0.53s 4.60s 72.67 0.363 [29. 8.1997]
+IBM 43P-140 PPC604e 166 [32K+32K]/1M ??? AIX 4.1.3 IBM XLC | 0.94s 0.60s 5.66s 62.89 0.379 [20. 8.1997]
+IBM G40 2xPPC604 112 [16K+16K]/512K ??? AIX 4.2.1 IBM XLC | 1.76s 0.97s 9.86s 36.01 0.322 [ 5. 8.1997]
+IBM RS/6000 Model 390 POWER 2 66.7 [32K+64K]/1M 128 AIX 4.1.3 IBM XLC | 2.21s 1.14s 11.52s 30.03 0.450
+IBM RS/6000 Model 250 MPC601 66 [32K] ??? AIX 4.1 IBM XLC | 4.27s 2.08s 21.60s 16.00 0.242
+IBM RS/6000 Model 320H POWER 1 ? ? 64 AIX 3.2 IBM XLC | 7.00s 3.41s 42.48s 9.20 [29. 7.1999 comp 93min]
+IBM RS/6000 Model 220 RSC3308 33.3 [8K] 16 AIX 4.1 IBM XLC | 11.32s 5.60s 66.56s 5.71 0.172
+
+
+PA-Risc-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+HP HP9000/715 PA7100 50 64K+64K 32 HP-UX 9.0 HP-C | 5.63s 2.88s 29.97s 11.72 0.234
+
+
+VAX-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+Digital VAXstation 3100 M38 CVAX 16.6666 [???]/64K 16 Ultrix 4.5 gcc 2.7.2 | 22.74s 11.71s 147.15s 2.72 0.163 [ 9. 2.1999 comp 352min]
+Digital MicroVAX 3100 (1) (2) CVAX 11.1111 [???] 16 NetBSD 1.3I egcs 1.1 | 39.59s 20.09s 260.70s 1.56 0.141 [14. 2.1999]
+Digital VAXstation 2000 MVAX [0.9VUP] none 6 Ultrix 4.1 gcc 2.7.2 | 79.66s 40.43s 512.77s 0.78 ????? [12. 7.1998]
+
+68xxx-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+Sun 3/260 MC68020+MC68881 25+20 [0.25K]/64K 16 NetBSD 1.2 gcc 2.7.2 | 28.98s 13.98s 155.79s 2.32 0.093
+PCS Cadmus 9600/5 MC68020+MC68881 25+20 [0.25K]/64K 8 Munix V.3.3-1 cc | 26.12s 14.36s 202.96s 2.20 0.088 [20.06.1998]
+Sun 3/60 MC68020+MC68881 20 [0.25K] 24 SunOS 4.1.1u1 egcs 1.1b | 28.31s 14.64s 203.45s 2.19 0.106 [17. 1.1999]
+Sun 3/60 (tuned) MC68030+MC68882 24 [0.25K] 16 NetBSD 1.2 gcc 2.7.2 | 38.29s 19.48s 220.14s 1.68 0.070
+Sun 3/160 MC68020+MC68881 16.67 [0.25K] 16 NetBSD 1.2 gcc 2.7.2 | 49.58s 24.79s 282.11s 1.31 0.079
+PCS Cadmus 9600/4 MC68020+MC68881 16.67 [0.25K]/16K 8 Munix V.3.3-1 cc | 53.49s 29.97s 317.50s 1.16 0.069
+Sun 3/50 MC68020+MC68881 15.8 [0.25K] 4 NetBSD 1.2 gcc 2.7.2 | 71.01s 47.11s 422.60s 0.83 0.052
+
+
+Pentium-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+<Noname> 2*Pentium2 450 Linux gcc | 0.28s 0.14s 1.62s 231.31 0.514
+<Noname> Asus T2P4 AMD K6 233 [32K+32K]/512K 64 Linux 2.1.74 gcc 2.7.2 | 0.44s 0.25s 2.69s 138.57 0.595 [20.06.1998]
+<Noname> Asus T2P4 AMD K6 200 [32K+32K]/512K 128 Linux 2.0.32 gcc 2.7.2 | 0.47s 0.24s 2.77s 136.00 0.680 [20.06.1998]
+<Noname> Natoma Chipset PPro 233 [16K+16K]/256K 64 Linux 2.1.42 pent-gcc | 0.82s 0.45s 4.53s 77.76 0.334
+<Noname> Asus T2P4 AMD K6 200 [32K+32K]/512K 128 Linux 2.0.32 emx 0.9 | 0.87s 0.72s 3.65s 73.30 0.367 [20.06.1998]
+<Noname> SIS551x Chipset Intel Pentium 100 [8K+8K]/256K 16 Linux 2.0.35 gcc 2.7.2.3 | 1.49s 0.73s 8.89s 43.31 0.433 [25. 7.1999 comp 36min]
+<Noname> Asus PCI/I-P5MP3 Intel Pentium 66.6666 [8K+8K]/256K 32 Linux 2.0.27 gcc 2.7.2 | 1.82s 0.93s 11.78s 34.11 0.512 [17. 1.1999]
+<Noname> SIS551x Chipset Intel Pentium 75 [8K+8K]/256K 16 Linux 2.0.35 gcc 2.7.2.3 | 2.02s 0.97s 11.63s 32.51 0.433 [25. 7.1999 comp 47min]
+<Noname> Asus PCI/I-P5MP3 Intel Pentium 60 [8K+8K]/256K 32 Linux 2.0.27 gcc 2.7.2 | 2.03s 1.05s 12.18s 31.17 0.520 [17. 1.1999]
+<Noname> FIC PA-2002 Intel Pentium 75 [8K+8K] 6 Linux 2.0.27 gcc 2.7.2 | 4.74s 2.15s 23.77s 14.82 0.198 [30. 1.1999]
+
+
+486-based systems
+
+Note for the 486's: To avoid confusion, I named the 486 CPU's according
+to the factor they physically use in multiplying the external clock.
+E.g., an Am486DX4/100 which physically triples the clock is named
+Am486DX3, and an Am5x86 which physically quadruples the clock is named
+Am486DX4!
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+<Noname> Eteq 491/493-Chipset Am486DX4 133 [16K(WT)]/256K 20 Linux 2.2.6 gcc 2.7.2.3 | 2.23s 1.09s 12.28s 29.76 0.223 [19. 9.1999 comp 56min]
+<Noname> Eteq 491/493-Chipset i486DX3 100 [16K(WT)]/256K 20 Linux 2.2.6 gcc 2.7.2.3 | 2.51s 1.14s 13.35s 27.47 0.275 [19. 9.1999 comp 58min]
+<Noname> SISATQ-Chipset Am486DX4 112 [16K]/256K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 2.67s 1.33s 12.73s 25.92 0.231 [15.10.1999 comp 62min]
+<Noname> SISATQ-Chipset i486DX3 96 [16K]/256K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 2.60s 1.50s 14.04s 24.35 0.254 [14.10.1999 comp 65min]
+IBM PS/2 Model 85 i486DX2 66.666 [8K]/256K 16 Linux 2.2.10 gcc 2.7.2.3 | 3.22s 1.68s 18.76s 19.79 0.297 [16.10.1999 comp 70min]
+<Noname> UMC 481A/482A-Chipset Am486DX4 144 [16K(WT)]/128K(WB) 7.875 Linux 2.2.6 gcc 2.7.2.3 | 3.25s 1.92s 16.62s 19.69 0.137 [16. 9.1999 comp 85min]
+<Noname> Eteq 491/493-Chipset i486DX2 66.7 [8K]/256K 20 Linux 2.2.6 gcc 2.7.2.3 | 3.31s 1.70s 19.43s 19.29 0.289 [18. 9.1999 comp 82min]
+<Noname> UMC 481A/482A-Chipset i486DX3 108 [16K(WT)]/128K(WB) 7.875 Linux 2.2.6 gcc 2.7.2.3 | 3.51s 1.88s 17.17s 19.10 0.177 [12. 9.1999 comp 85min]
+IBM PS/2 Model 77s i486DX2 66.666 [8K]/128K 32 Linux 2.2.10 gcc 2.7.2.3 | 3.57s 1.64s 20.24s 18.83 0.283 [19. 9.1999 comp 72min]
+<Noname> Eteq 491/493-Chipset Cx486DX2 66.7 [8K]/256K 20 Linux 2.2.6 gcc 2.7.2.3 | 3.60s 1.80s 21.65s 17.77 0.266 [18. 9.1999 comp 87min]
+<Noname> SISATQ-Chipset i486DX2 64 [8K]/256K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 3.74s 1.83s 20.79s 17.68 0.276 [14.10.1999 comp 84min]
+<Noname> Eteq 491/493-Chipset Am486DX4 133 [16K(WT)] 20 Linux 2.2.6 gcc 2.7.2.3 | 4.19s 1.81s 19.98s 17.35 0.130 [19. 9.1999 comp 95min]
+<Noname> Eteq 491/493-Chipset i486DX3 100 [16K(WT)] 20 Linux 2.2.6 gcc 2.7.2.3 | 4.25s 1.87s 20.64s 16.90 0.169 [19. 9.1999 comp 97min]
+<Noname> VIA 486/482-Chipset i486DX2 66.7 [8K]/256K 15.625 Linux 2.2.10 gcc 2.7.2.3 | 4.10s 1.91s 22.94s 16.37 0.246 [ 6.11.1999 comp 97min]
+<Noname> VIA 486/482-Chipset Cx486DX2 66.7 [8K]/256K 15.625 Linux 2.2.10 gcc 2.7.2.3 | 4.20s 1.97s 24.01s 15.82 0.237 [ 5.11.1999 comp 100min]
+<Noname> UM8498-Chipset Am486DX4 133 [16K(WT)]/256K 12 Linux 2.0.27 gcc 2.7.2 | 4.19s 2.17s 23.00s 15.54 0.116
+<Noname> VIA 481/495-Chipset i486DX2 66.7 [8K]/256K(WB) 7.625 Linux 2.2.10 gcc 2.7.2.3 | 3.07s 2.09s 26.85s 15.41 0.231 [ 3.10.1999 comp 116min]
+<Noname> SISATQ-Chipset Cx486DX2 64 [8K]/256K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 4.35s 2.11s 24.50s 15.18 0.237 [13.10.1999 comp 94min]
+<Noname> VIA 481/495-Chipset Cx486DX2 66.7 [8K]/256K(WB) 7.625 Linux 2.2.10 gcc 2.7.2.3 | 4.17s 2.49s 23.31s 14.82 0.222 [ 3.10.1999 comp 98min]
+<Noname> UMC 481A/482A-Chipset i486DX2 72 [8K]/128K(WB) 7.875 Linux 2.2.6 gcc 2.7.2.3 | 4.77s 2.20s 25.32s 14.35 0.199 [17. 9.1999 comp 109min]
+<Noname> UMC 481A/482A-Chipset Cx486DX2 72 [8K]/128K(WB) 7.875 Linux 2.2.6 gcc 2.7.2.3 | 4.79s 2.31s 27.63s 13.71 0.190 [11. 9.1999 comp 114min]
+IBM PS/2 Model 76i i486DX2 66.666 [8K] 16 Linux 2.2.10 gcc 2.7.2.3 | 5.31s 2.35s 28.64s 13.03 0.195 [ 9.10.1999 comp 118min]
+<Noname> Eteq 491/492-Chipset Am486DX4 133 [16K(WT)]/256K 20 OS/2 Warp 3 emx 0.99 | 5.10s 2.92s 24.96s 12.88 0.097
+<Noname> Asus SP3G Am486DX3 100 [8K]/256K 32 Linux 2.0.7 gcc 2.7.2 | 5.16s 2.45s 29.16s 12.88 0.129
+<Noname> Eteq 491/493-Chipset i486SX 33.3 [8K]/256K(WB) 7.875 Linux 2.2.6 gcc 2.7.2.3 | 5.35s 2.49s 32.14s 12.28 0.368 [18. 9.1999 comp 111min]
+<Noname> Asus SP3G-PVI Am486DX3 100 [8K]/256K 32 Linux 2.0.21 gcc 2.7.2 | 5.77s 2.77s 32.32s 11.50 0.115
+<Noname> SISATQ-Chipset i486SX 32 [8K]/256K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 5.41s 2.89s 33.26s 11.47 0.359 [12.10.1999 comp 115min]
+<Noname> SISATQ-Chipset Am486DX4 112 [16K] 7.875 Linux 2.2.10 gcc 2.7.2.3 | 6.25s 2.92s 29.71s 11.33 0.101 [15.10.1999 comp 151min]
+<Noname> SISATQ-Chipset i486DX3 96 [16K] 7.875 Linux 2.2.10 gcc 2.7.2.3 | 6.35s 2.98s 30.38s 11.11 0.116 [14.10.1999 comp 152min]
+<Noname> VIA 486/482-Chipset i486SX 33.3 [8K]/256K 15.625 Linux 2.2.10 gcc 2.7.2.3 | 5.93s 2.79s 35.15s 11.07 0.332 [ 4.11.1999 comp 122min]
+<Noname> UMC 481A/482A-Chipset i486DX3 108 [16K(WT)] 7.875 Linux 2.2.6 gcc 2.7.2.3 | 6.48s 2.99s 31.14s 10.93 0.101 [12. 9.1999 comp 151min]
+<Noname> UMC 481A/482A-Chipset Am486DX4 144 [16K(WT)] 7.875 Linux 2.2.6 gcc 2.7.2.3 | 6.31s 3.15s 30.83s 10.88 0.076 [16. 9.1999 comp 151min]
+<Noname> Eteq 491/493-Chipset Cx486DX2 66.7 [8K] 20 Linux 2.2.6 gcc 2.7.2.3 | 6.42s 2.86s 35.35s 10.67 0.160 [18. 9.1999 comp 146min]
+<Noname> Eteq 491/493-Chipset i486DX2 66.7 [8K] 20 Linux 2.2.6 gcc 2.7.2.3 | 6.53s 2.97s 34.98s 10.51 0.158 [18. 7.1999 comp 149min]
+<Noname> UMC 481A/482A-Chipset i486SX 36 [8K]/128K(WB) 7.875 Linux 2.2.6 gcc 2.7.2.3 | 6.94s 2.99s 36.46s 10.15 0.282 [11. 9.1999 comp 132min]
+<Noname> VIA 486/482-Chipset Cx486DX2 66.7 [8K] 15.625 Linux 2.2.10 gcc 2.7.2.3 | 7.23s 3.18s 38.93s 9.59 0.144 [ 4.11.1999 comp 166min]
+<Noname> VIA 481/495-Chipset i486SX 33.3 [8K]/256K(WB) 7.625 Linux 2.2.10 gcc 2.7.2.3 | 7.45s 3.36s 39.12s 9.29 0.279 [ 2.10.1999 comp 122min]
+IBM PS/2 Model 76 i486SX 33 [8K] 7.875 Linux 2.0.35 gcc 2.7.2.3 | 7.52s 3.66s 44.65s 8.62 0.261 [24. 7.1999 comp 151min]
+<Noname> VIA 486/482-Chipset i486DX2 66.7 [8K] 15.625 Linux 2.2.10 gcc 2.7.2.3 | 7.58s 3.28s 39.82s 9.27 0.139 [ 6.11.1999 comp 169min]
+<Noname> Eteq 491/493-Chipset i486SX 33.3 [8K] 20 Linux 2.2.6 gcc 2.7.2.3 | 8.58s 3.92s 48.60s 7.85 0.235 [19. 7.1999 comp 169min]
+<Noname> VIA 481/495-Chipset Cx486DX2 66.7 [8K] 7.625 Linux 2.2.10 gcc 2.7.2.3 | 8.76s 3.87s 51.85s 7.67 0.115 [ 3.10.1999 comp 209min]
+<Noname> Eteq 491/492-Chipset i486DX2 66.7 [8K]/64K 5 Linux 2.0.27 gcc 2.7.2 | 8.61s 4.52s 46.33s 7.58 0.114
+<Noname> VIA 481/495-Chipset i486DX2 66.7 [8K] 7.625 Linux 2.2.10 gcc 2.7.2.3 | 9.23s 4.10s 47.81s 7.58 0.114 [ 3.10.1999 comp 219min]
+<Noname> Eteq 491/492-Chipset Cx486DX2 66.7 [8K]/64K 5 Linux 2.0.27 gcc 2.7.2 | 9.03s 4.46s 46.73s 7.47 0.112
+<Noname> UMC 481A/482A-Chipset Cx486DX2 72 [8K] 7.875 Linux 2.2.6 gcc 2.7.2.3 | 9.14s 4.28s 48.42s 7.46 0.104 [11. 9.1999 comp 214min]
+<Noname> No Chipset Am486DX4 100 [16K(WT)] 16 Linux 1.99.12 gcc 2.7.2 | 9.18s 4.36s 48.27s 7.41 0.074
+<Noname> UMC 481A/482A-Chipset i486DX2 72 [8K] 7.875 Linux 2.2.6 gcc 2.7.2.3 | 9.60s 4.36s 49.99s 7.22 0.100 [17. 9.1999 comp 220min]
+<Noname> SISATQ-Chipset Cx486DX2 64 [8K] 7.875 Linux 2.2.10 gcc 2.7.2.3 | 9.73s 4.40s 50.44s 7.15 0.112 [12.10.1999 comp 225min]
+<Noname> SISATQ-Chipset i486DX2 64 [8K]/64K(no dirty) 4 Linux 2.0.27 gcc 2.7.2 | 9.46s 4.46s 49.44s 7.13 0.111
+<Noname> SISATQ-Chipset Cx486DX2 64 [8K]/64K(no dirty) 4 Linux 2.0.27 gcc 2.7.2 | 9.27s 4.64s 51.35s 7.08 0.111
+<Noname> VIA 486/482-Chipset i486SX 33.3 [8K] 15.625 Linux 2.0.27 gcc 2.7.2 | 9.79s 4.23s 54.60s 7.05 0.212 [ 3.11.1999 comp 189min]
+IBM PS/2 Model 70-R21 i486DX 25 [8K] 8 Linux 2.0.35 gcc 2.7.2.3 | 9.26s 4.70s 53.86s 6.95 0.278 [ 2. 3.1999 comp 206min]
+<Noname> SIS BTQ Chipset i486SX 33.333 [8K] 4 Linux 2.0.27 gcc 2.7.2 | 9.25s 5.76s 50.80s 6.65 0.199 [ 7.12.1997]
+<Noname> UMC 481A/482A-Chipset i486SX 36 [8K]/256K(WB) 5 Linux 2.0.27 gcc 2.7.2 | 9.83s 5.15s 57.31s 6.47 0.179
+<Noname> UMC 481/482-Chipset i486SX 36 [8K] 7.875 Linux 2.2.6 gcc 2.7.2.3 | 11.49s 5.09s 62.54s 6.00 0.167 [11. 9.1999 comp 233min]
+<Noname> No Chipset i486DX2 50 [8K] 16 Linux 2.0.27 gcc 2.7.2 | 11.53s 5.41s 66.61s 5.75 0.115
+<Noname> VIA 486/482-Chipset i486DX2 66.7 [8K]/64K 4 Linux 2.0.27 gcc 2.7.2 | 11.72s 6.00s 62.43s 5.63 0.085
+<Noname> VIA 481/495-Chipset i486SX 33.3 [8K] 7.625 Linux 2.2.10 gcc 2.7.2.3 | 12.35s 5.42s 66.84s 5.61 0.168 [ 2.10.1999 comp 244min]
+<Noname> Eteq 491/492-Chipset i486SX 33.3 [8K]/64K 5 Linux 2.0.27 gcc 2.7.2 | 11.79s 5.93s 65.39s 5.55 0.167
+<Noname> SISATQ-Chipset i486DX2 64 [8K] 7.875 Linux 2.2.10 gcc 2.7.2.3 | 10.30s 4.85s 52.87s 6.68 0.104 [13.10.1999 comp 237min]
+<Noname> VIA 486/482-Chipset Cx486DX2 66.7 [8K]/64K 4 Linux 2.0.27 gcc 2.7.2 | 11.90s 6.26s 67.01s 5.39 0.081
+<Noname> SISATQ-Chipset i486SX 32 [8K]/64K(no dirty) 4 Linux 2.0.27 gcc 2.7.2 | 12.03s 6.32s 67.79s 5.34 0.167
+<Noname> SISATQ-Chipset i486SX 32 [8K] 7.875 Linux 2.2.10 gcc 2.7.2.3 | 12.94s 5.70s 70.58s 5.33 0.166 [11.10.1999 comp 260min]
+<Noname> UMC 481/482-Chipset i486DX 33 [8K]/256K 16 Linux 2.0.18 gcc 2.7.2 | 16.19s 7.59s 91.05s 4.13 0.125
+<Noname> VIA 486/482-Chipset i486SX 33.3 [8K]/64K 4 Linux 2.0.27 gcc 2.7.2 | 15.86s 7.83s 97.15s 4.03 0.121
+
+
+386DX-based systems
+
+Note for the 386's: Though Cyrix claimed that the Cx486DLC is a 486,
+I will show it in this list because it fits into 386DX sockets. Similar
+is valid for the IBM chips.
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+IBM PS/2 Model 57SLC3 IBM486DLC3 75 [16K] 11.875 Linux 2.0.35 gcc 2.7.2.3 | 8.24s 3.63s 44.14s 8.42 0.112 [ 4. 9.1999 comp 161min]
+<Noname> OPTi 391/392-Chipset Am386DX+Cx83D87DX 40 64K 7,875 Linux 2.2.6 gcc 2.7.2.3 | 8.34s 4.28s 52.53s 7.50 0.187 [ 3. 9.9999 comp 193min]
+<Noname> Opti 495-Chipset Am386DX+Cx83D87 40 128K(no dirty) 7.625 Linux 2.2.10 gcc 2.7.2.3 | 8.17s 4.44s 54.11s 7.39 0.185 [30. 9.1999 comp 199min]
+<Noname> VIA 481/495-Chipset Am386DX 40 128K(WB) 7.625 Linux 2.2.10 gcc 2.7.2.3 | 8.85s 4.58s 57.33s 6.98 0.174 [ 4.10.1999 comp 196min]
+<Noname> Bioteq 3491-Chipset Am386DX 40 128K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 8.83s 4.71s 56.70s 6.94 0.174 [28.10.1999 comp 190min]
+<Noname> UMC 482/391-Chipset i386DX+Cx83D87 33.3 128K(no dirty) 5 Linux 2.0.27 gcc 2.7.2 | 9.56s 4.91s 62.83s 6.45 0.194 [ 2.11.1999 comp 232min]
+<Noname> Opti 495-Chipset Am386DX+Cx83D87 33.3 128K(no dirty) 7.625 Linux 2.2.10 gcc 2.7.2.3 | 10.13s 5.22s 66.24s 6.09 0.183 [28. 9.1999 comp 242min]
+<Noname> Eteq 491/493-Chipset i386DX 40 64K 4 Linux 2.0.27 gcc 2.7.2 | 10.08s 5.98s 63.64s 5.90 0.148 [ 1.11.1997]
+<Noname> Bioteq 3491-Chipset Am386DX 33 128K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 10.59s 5.47s 69.72s 5.81 0.176 [28.10.1999 comp 227min]
+<Noname> UMC 482/391-Chipset Cx486DLC+Cx83D87 33.3 [1K]/128K(no dirty) 5 Linux 2.0.27 gcc 2.7.2 | 12.37s 6.75s 71.72s 5.08 0.153
+IBM PS/2 Model 80-A21 i386DX+i387DX 25 64K 7.875 Linux 2.0.35 gcc 2.7.2.3 | 11.99s 6.62s 81.10s 4.98 0.199 [19. 5.1999, comp 258min]
+IBM PS/2 Model 70-A16 i386DX 25 64K 7.875 Linux 2.0.30 gcc 2.7.2 | 12.10s 6.62s 81.14s 4.96 0.198 [ 7. 2.1999, comp 232min]
+<Noname> SIS 85C3x0-Chipset i386DX 25 64K 4 Linux 2.0.27 gcc 2.7.2 | 13.02s 6.41s 84.31s 4.83 0.193 [ 1.11.1997]
+IBM PS/2 Model P70-386 Cx486DLC+Cx83D87 20 [1K] 7.875 Linux 2.2.10 gcc 2.7.2.3 | 13.11s 6.92s 84.75s 4.69 0.234 [20. 7.1999, comp 329min]
+<Noname> TI TACT823x-Chipset i386DX 33 32K(WB) 4 Linux 2.0.27 gcc 2.7.2 | 13.50s 7.22s 81.02s 4.63 0.140 [14.11.1997]
+<Noname> Bioteq 3491-Chipset Am386DX 25 128K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 14.48s 6.96s 91.47s 4.41 0.177 [28.10.1999 comp 301min]
+<Noname> Opti 495-Chipset Am386DX+Cx83D87 25 128K(no dirty) 7.625 Linux 2.2.10 gcc 2.7.2.3 | 13.77s 7.32s 91.80s 4.41 0.176 [28. 9.1999 comp 323min]
+<Noname> UMC 482/391-Chipset Cx486DLC+Cx83D87 33.3 [1K] 5 Linux 2.0.27 gcc 2.7.2 | 15.38s 8.05s 89.57s 4.14 0.124
+<Noname> VIA 481/495-Chipset i386DX 40 none 7.625 Linux 2.2.10 gcc 2.7.2.3 | 15.27s 8.09s 103.11s 3.97 0.099 [ 4.10.1999 comp 365min]
+<Noname> AMI MK II i386DX+Cx83D87 33 64K 4 Linux 2.0.27 gcc 2.7.2 | 17.19s 9.26s 96.46s 3.71 0.112
+<Noname> C&T PEAK/DM-Chipset i386DX+Cx83D87 33.3 64K 4 Linux 2.0.27 gcc 2.7.2 | 17.35s 9.09s 97.07s 3.71 0.111
+<Noname> Opti 495-Chipset Am386DX+Cx83D87 20 128K(no dirty) 7.625 Linux 2.2.10 gcc 2.7.2.3 | 16.94s 8.85s 117.47s 3.56 0.178 [26. 9.1999 comp 399min]
+IBM PS/2 Model 70-121 i386DX+i387DX 20 none 5.875 Linux 2.0.7 gcc 2.7.2 | 17.26s 9.57s 108.70s 3.53 0.176 [23.11.1997 comp 362min]
+<Noname> Bioteq 3491-Chipset Am386DX 20 128K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 17.92s 8.85s 115.57s 3.51 0.176 [26.10.1999 comp 388min]
+<Noname> C&T PEAK/DM-Chipset i386DX 33.3 none 7.875 Linux 2.2.10 gcc 2.7.2.3 | 17.64s 9.00s 118.49s 3.48 0.105 [ 7.11.1999 comp 401min]
+IBM PS/2 Model P70-386 i386DX+i387DX 20 none 7.875 Linux 2.0.35 gcc 2.7.2.3 | 18.22s 10.22s 123.62s 3.25 0.163 [18. 4.1999 comp 425min]
+<Noname> UMC 482/391-Chipset i386DX+IIT3C87 16.7 128K(no dirty) 7.875 Linux 2.2.10 gcc 2.7.2.3 | 19.07s 10.07s 127.44s 3.19 0.191 [ 1.11.1999 comp 463min]
+<Noname> Opti 495-Chipset Am386DX+Cx83D87 40 none 7.625 Linux 2.2.10 gcc 2.7.2.3 | 19.88s 10.40s 133.73s 3.06 0.076 [29. 9.1999 comp 494min]
+<Noname> SIS 85C3x0-Chipset i386DX+Cx83D87 25 64K 4 Linux 2.0.27 gcc 2.7.2 | 22.62s 11.47s 120.07s 2.93 0.117
+IBM PS/2 Model 80-311 i386DX+i387DX 20 none 9.875 Linus 2.0.35 gcc 2.7.2.3 | 21.69s 10.99s 141.28s 2.87 0.143
+<Noname> Bioteq 3491-Chipset Am386DX 40 none 7.875 Linux 2.2.10 gcc 2.7.2.3 | 21.44s 10.96s 142.41s 2.87 0.072 [29.10.1999 comp 502min]
+<Noname> C&T PEAK/DM-Chipset i386DX+Cx83D87 25 64K 4 Linux 2.0.27 gcc 2.7.2 | 23.56s 12.47s 131.00s 2.73 0.109
+<Noname> Opti 495-Chipset Am386DX+Cx83D87 33.3 none 7.625 Linux 2.2.10 gcc 2.7.2.3 | 23.70s 13.44s 160.44s 2.50 0.074 [28. 9.1999 comp 591min]
+<Noname> UMC 482/391-Chipset i386DX+IIT3C87 33.3 none 5 Linux 2.0.27 gcc 2.7.2 | 24.34s 12.82s 166.97s 2.48 0.074 [ 2.11.1999 comp 598min]
+<Noname> Bioteq 3491-Chipset Am386DX 33 none 7.875 Linux 2.2.10 gcc 2.7.2.3 | 26.02s 14.55s 174.90s 2.29 0.069 [28.10.1999 comp 609min]
+<Noname> C&T 8230-Chipset i386DX+i387DX 25 none 8 Linux 2.0.27 gcc 2.7.2 | 27.57s 14.97s 162.15s 2.27 0.091
+<Noname> C&T PEAK/DM-Chipset i386DX+Cx83D87 20 64K 4 Linux 2.0.27 gcc 2.7.2 | 29.10s 15.34s 165.43s 2.19 0.110
+<Noname> OPTi 381/382-Chipset i386DX+Cx83D87 25 none 4 Linux 2.0.27 gcc 2.7.2 | 30.57s 15.83s 168.03s 2.13 0.085
+<Noname> SIS 85C3x0-Chipset i386DX+Cx83D87 25 none 4 Linux 2.0.27 gcc 2.7.2 | 32.94s 16.95s 180.37s 1.98 0.079
+<Noname> Opti 495-Chipset Am386DX+Cx83D87 25 none 7.625 Linux 2.2.10 gcc 2.7.2.3 | 32.64s 16.63s 220.51s 1.88 0.075 [27. 9.1999 comp 794min]
+<Noname> C&T PEAK/DM-Chipset i386DX+Cx83D87 16 64K 4 Linux 2.0.27 gcc 2.7.2 | 37.12s 19.37s 206.50s 1.74 0.109
+<Noname> Bioteq 3491-Chipset Am386DX 25 none 7.875 Linux 2.2.10 gcc 2.7.2.3 | 35.59s 18.00s 236.35s 1.74 0.070 [27.10.1999 comp 824min]
+<Noname> C&T 8230-Chipset i386DX+Cx83D87 20 none 4 Linux 2.0.27 gcc 2.7.2 | 40.56s 22.26s 220.02s 1.63 0.082
+<Noname> C&T PEAK/DM-Chipset i386DX+Cx83D87 25 none 4 Linux 2.0.27 gcc 2.7.2 | 42.91s 22.23s 244.48s 1.50 0.060
+<Noname> Opti 495-Chipset Am386DX+Cx83D87 20 none 7.625 Linux 2.2.10 gcc 2.7.2.3 | 40.97s 21.04s 276.59s 1.49 0.074 [26. 9.1999 comp 1020min]
+<Noname> Bioteq 3491-Chipset Am386DX 20 none 7.875 Linux 2.2.10 gcc 2.7.2.3 | 45.58s 22.78s 304.22s 1.36 0.068 [24.10.1999 comp 1052min]
+<Noname> C&T 8230-Chipset i386DX+Cx83D87 16 none 4 Linux 2.0.27 gcc 2.7.2 | 48.10s 25.91s 274.92s 1.32 0.082
+<Noname> C&T PEAK/DM-Chipset i386DX+Cx83D87 20 none 4 Linux 2.0.27 gcc 2.7.2 | 53.93s 28.07s 310.04s 1.19 0.059
+<Noname> UMC 482/391-Chipset i386DX+IIT3C87 16.7 none 7.875 Linux 2.2.10 gcc 2.7.2.3 | 52.42s 26.57s 345.95s 1.18 0.071 [ 1.11.1999 comp 1229min]
+Tandon TM8000 i386DX 16 none 4 Linux 2.0.27 gcc 2.7.2 | 60.64s 32.08s 350.00s 1.05 0.066
+<Noname> C&T PEAK/DM-Chipset i386DX+Cx83D87 16 none 4 Linux 2.0.27 gcc 2.7.2 | 69.79s 36.19s 399.86s 0.92 0.057
+<Noname> TI TACT823x-Chipset i386DX 33 none 4 Linux 2.0.27 gcc 2.7.2 | 68.13s 34.92s 444.39s 0.91 0.028 [14.11.1997]
+Tandon TM8000 i386DX 8 none 4 Linux 2.0.27 gcc 2.7.2 | 87.33s 45.53s 504.37s 0.73 0.091
+
+
+386SX-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+IBM PS/2 Model 56SLC2 IBM 486SLC2 50 [16K] 11.875 Linux 2.0.35 gcc 2.7.2.3 | 7.44s 3.73s 43.22s 8.69 0.173 [ 8. 4.1999 comp 161min]
+IBM PS/2 Model 56SLC IBM 386SLC 20 [8K] 7.875 Linux 2.0.35 gcc 2.7.2.3 | 17.56s 8.89s 106.39s 3.63 0.181 [ 9. 5.1999 comp 363min]
+<Noname> Cyclone RC2016-Chipset Am386SX 33.3 none 7.625 Linux 2.2.6 gcc 2.7.2.3 | 19.05s 9.70s 128.13s 3.23 0.097 [15. 9.1999 comp 449min]
+<Noname> Headland HT18-Chipset i386SX 25 none 7.625 Linux 2.2.10 gcc 2.7.2.3 | 21.84s 12.00s 146.17s 2.74 0.110 [ 9.10.1999 comp 507min]
+<Noname> Intel 8234x-Chipset i386SX 20 none 4 Linux 2.0.27 gcc 2.7.2 | 24.11s 12.84s 153.16s 2.55 0.128 [31.12.1997]
+IBM PS/2 Model 56SX i386SX 20 none 7.875 Linux 2.2.10 gcc 2.7.2.3 | 24.76s 12.27s 164.25s 2.52 0.126 [ 3.10.1999 comp 565min]
+IBM PS/2 Model 57SX i386SX 20 none 7.875 Linux 2.0.35 gcc 2.7.2.3 | 26.61s 13.55s 178.55s 2.31 0.116 [ 8. 4.1999 comp 564min]
+<Noname> VLSI-82C33x-Chipset i386SX 20 none 7.625 Linux 2.2.6 gcc 2.7.2.3 | 27.41s 13.93s 183.47s 2.25 0.112 [30. 9.1999 comp 641min]
+<Noname> Cyclone RC2016-Chipset Am386SX 40 none 4 Linux 2.0.27 gcc 2.7.2 | 28.41s 14.92s 162.07s 2.25 0.056
+<Noname> C&T 8221-Chipset i386SX 16 none 7.625 Linux 2.2.10 gcc 2.7.2.3 | 30.60s 15.37s 204.90s 2.02 0.126 [ 6.11.1999 comp 705min]
+<Noname> PCChips Chip 2 Am386SX 33.3 none 4 Linux 2.0.27 gcc 2.7.2 | 33.03s 16.98s 176.92s 1.99 0.060
+<Noname> UMC 336-Chipset i386SX 16 none 7.875 Linux 2.2.10 gcc 2.7.2.3 | 30.23s 15.31s 202.86s 2.04 0.127 [10.10.1999 comp 692min]
+<Noname> Cyclone RC2016-Chipset Am386SX 20 none 7.625 Linux 2.2.6 gcc 2.7.2.3 | 32.42s 16.55s 218.44s 1.89 0.095 [14. 9.1999 comp 758min]
+<Noname> Cyclone RC2016-Chipset Am386SX 16.7 none 7.625 Linux 2.2.6 gcc 2.7.2.3 | 35.68s 17.79s 237.24s 1.74 0.104 [14. 9.1999 comp 817min]
+<Noname> Intel 82335-Chipset i386SX 16 none 4 Linux 2.0.27 gcc 2.7.2 | 63.16s 31.86s 350.67s 1.04 0.065
+<Noname> PCChips Chip 2 Am386SX 8 none 4 Linux 2.0.27 gcc 2.7.2 | 140.13s 71.44s 778.46s 0.47 0.058
+
+
+286-based systems
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+<Noname> Suntac 241/203-Cipset Am286+i287 16 none 0.875 MS-DOS 5.0 BC++ 3.1 | 62.00s 36.73s 321.28s 1.03 0.064 [24. 8.1997]
+<Noname> C&T 8221-Chipset i286 16 none 1 MS-DOS 5.0 BC++ 3.1 | 67.80s 39.09s 357.13s 0.94 0.059 [24. 8.1997]
+<Noname> VLSI VL82C10x-Chipset i286 12 none 1 MS-DOS 5.0 BC++ 3.1 | 75.06s 42.86s 407.07s 0.84 0.070 [24. 8.1997]
+<Noname> Headland HT101/102/113 Am286 16 none 1.125 MS-DOS 5.0 BC++ 3.1 | 85.33s 51.42s 416.75s 0.76 0.047 [24. 8.1997]
+Toshiba T1600 i286+Am80C287 12+8 none 0.9375 MS-DOS 5.0 BC++ 3.1 | 86.02s 50.26s 471.03s 0.73 0.061 [24. 8.1997]
+<Noname> C&T 8220-Chipset i286 12 none 1 MS-DOS 5.0 BC++ 3.1 | 93.47s 53.05s 510.81s 0.68 0.056 [24. 8.1997]
+<Noname> G2 GC101/102-Chipset i286 12.5 none 1 MS-DOS 5.0 BC++ 3.1 | 92.56s 52.46s 505.70s 0.68 0.055 [24. 8.1997]
+IBM PS/2 Model 50Z i286+i287 10 none 1 MS-DOS 5.0 BC++ 3.1 | 102.50s 59.11s 557.61s 0.62 0.062 [24. 8.1997]
+<Noname> Suntac ST62-Chipset i286 10 none 1 MS-DOS 5.0 BC++ 3.1 | 119.15s 66.87s 651.05s 0.53 0.053 [17. 8.1997]
+<Noname> Suntac ST62-Chipset i286 8 none 1 MS-DOS 5.0 BC++ 3.1 | 153.73s 87.69s 826.73s 0.41 0.052 [17. 8.1997]
+
+8088/8086-based systems (yes I know I'm a pervert...)
+
+Vendor Machine CPU Clock(MHz) Cache [on]offchip Memory(MB) OS Compiler | BUF32 FL900 MIC51 Index rel.
+-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------
+<Noname> no chipset V20+i8087 10 none 0.625+0.5 MS-DOS 3.3 BC++ 3.1 | 225.26s 133.13s 1176.93s 0.28 0.028 [24. 8.1997]
+<Noname> CBM PC10-I V20+i8087 4.77 none 0.6875 MS-DOS 3.3 BC++ 3.1 | 472.15s 276.51s 2500.47s 0.13 0.028 [24. 8.1997]
+
+
+Notes:
+
+(1) non-local filesystem(diskless machine)
+(2) Program did not work with -O3, -O2 chosen
+(3) a.out-based
+(4) node program, very slow I/O!
+(5) half of memory is slow 16bit/7.16MHz
+(6) slower (100ns) memory
+(7) best performance achieved with optimization level 1 ?!
+
+The index numbers at the end of the lines can be calculated with the following
+HP28 program:
+
+<< 359.52 SWAP / ROT 65.12 SWAP / ROT 33.52 SWAP / + + 3 / >>
+
+whereby the last value is the second last divided by the clock frequency.
+
+Non-UPN-wheenies may also use the freshly built AS to assemble the 'marks'
+assembler program in this distribution.
+
+You have to find out the rest for yourself ;-)
+
+I calculated this weighed ratio to get a unique number to sort the list;
+there is so far no special name for this measure. Call them ASstones,
+ASmarks, SPECas or whatever you like ;-)
+
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..ca7234d
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,99 @@
+This file is intended to be a short guide for getting AS compiled on
+a Unix-like operating system. If you are interested in a more in-depth
+discussion of the source code of AS, take a look in the appropriate chapter
+of the AS user's manual (german resp. english version located in the doc_DE/
+resp. doc_EN/ subdirectory). I highly recommend reading this chapter before
+you make extensions or modifications to the source code.
+
+The installation process consists of the following steps:
+
+(1) see if there are additional README files for your platform
+(2) create a Makefile.def
+(3) compile
+(4) execute the test suite
+(5) build the documentation
+(6) install into the system directories
+
+Step (1):
+
+On some (especially non-Unix) platforms, some additional preliminaries
+are needed:
+
+--> If you do not have a C compiler conforming to the ANSI standard,
+ take a look into 'README.KR'.
+
+--> For MS-DOS and OS/2 platforms, additionally read README.DOS resp.
+ README.OS2
+
+Step (2):
+
+Settings that may vary from platform to platform are located in a file
+called 'Makefile.def'. Your task is either to select an approriate file
+from the 'Makefile.def-samples' directory, or to create an own one. I know
+this is a bit tedious process, and one day I will probably replace this
+scheme with an autoconf-style configuration, but for now we will have to
+live with it. A good starting point for a gcc-based, 'normal' Unix system
+is the file 'Makefile.def.tmpl'. The settings to make include:
+
+- CC, LD, CFLAGS, LDFLAGS: The compiler and linker you want to use (nice
+ if you have more than just 'cc' on your machine), plus flags that should
+ be passed to them. like optimization settings and libraries needed for
+ linking.
+
+- BINDIR, INCDIR, MANDIR, LIBDIR, DOCDIR: directiories where AS should be
+ placed after compilation.
+
+- CHARSET: character encoding for non ASCII national special characters.
+ If your system is absolutely 8-bit-unclean, the ASCII7 setting is a good
+ idea. Most modern Unix systems default to ISO8859-1, and the IBM437
+ resp. IBM850 settings are only needed for DOS and OS/2 platforms.
+
+Step (3):
+
+Compilation should be a simple matter of saying 'make' and waiting...
+depending on your machine, compliation time can be between a few minutes
+(a modern Pentium-based PC or a fast Alpha) and a day (VAXstation 2000).
+A few compilers (like newer egcs releases or Borland-C) are known to
+generate a lot of warnings about ambigious statements or unused parameters.
+I will try to eliminate them when time permits, but I have no high priority
+for doing this since they are harmless.
+
+If you are compiling AS for a new platform, you will probably run into
+an error message saying that you have to edit 'sysdefs.h'. This file
+collects information about the anomalies and specialities of certain
+systems. The include file detects a system by querying macros the compiler
+predefines and makes the appropriate definitions. The file is sorted by
+
+1. processor architecture
+ 2. manufacturer
+ 3. operating system
+
+Find out the preprocessor symbols your compiler defines, make a new section
+in 'sysdefs.h' and send it to me so I can include it in the next release of
+AS!
+
+Step (4):
+
+Type 'make test' and the freshly compiled AS will be run on a couple of
+test programs. For each program, the output is compared to a reference
+binary included in the distribution. The binary output has to match
+*exactly*, i.e. ther must not be any difference. Any failed test reported
+by the script has to be investigated, even if it happens for a target
+platform you never intend to use!
+
+Step (5):
+
+The documentation of AS is distributed in LaTeX format. I chose this format
+because TeX is available on about any platform suitable for AS I can think
+of. Other formats are created by typing 'make docs': simple ASCII, HTML,
+and Postscript. You need a TeX distribution including dvips for the latter,
+while converters to ASCII and HTML are included.
+
+Step (6):
+
+Type 'make install'. Depending on the target directories you chose in Step
+(1), you may have to acquire root privileges to install AS.
+
+Have fun!
+
+Alfred Arnold, alfred@ccac.rwth-aachen.de
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..41ddbaa
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,157 @@
+include Makefile.def
+
+CURRDIR=./
+TAPE=/dev/ntape
+DATE=`date +"%d%m%Y"`
+
+include makedefs.src
+
+include objdefs.unix
+
+include makedefs.files
+
+ALLFLAGS = $(CFLAGS) -D$(CHARSET) -DSTDINCLUDES=\"$(INCDIR)\" -DLIBDIR=\"$(LIBDIR)\"
+
+#---------------------------------------------------------------------------
+# primary targets
+
+all: $(ALLTARGETS)
+
+docs: $(TEX2DOCTARGET) $(TEX2HTMLTARGET)
+ cd doc_DE; $(MAKE) TEX2DOC=../$(TEX2DOCTARGET) TEX2HTML=../$(TEX2HTMLTARGET) RM="rm -f"
+ cd doc_EN; $(MAKE) TEX2DOC=../$(TEX2DOCTARGET) TEX2HTML=../$(TEX2HTMLTARGET) RM="rm -f"
+
+$(ASLTARGET): $(AS_OBJECTS) $(ASM_OBJECTS) $(ST_OBJECTS) $(CODE_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(ASLTARGET) $(ASM_OBJECTS) $(AS_OBJECTS) $(ST_OBJECTS) $(CODE_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(PLISTTARGET): $(PLIST_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(PLISTTARGET) $(PLIST_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(PBINDTARGET): $(PBIND_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(PBINDTARGET) $(PBIND_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(P2HEXTARGET): $(P2HEX_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(P2HEXTARGET) $(P2HEX_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(P2BINTARGET): $(P2BIN_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(P2BINTARGET) $(P2BIN_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(RESCOMPTARGET): $(RESCOMP_OBJECTS)
+ $(LD) -o $(RESCOMPTARGET) $(RESCOMP_OBJECTS) $(LDFLAGS)
+
+$(TEX2DOCTARGET): $(TEX2DOC_OBJECTS)
+ $(LD) -o $(TEX2DOCTARGET) $(TEX2DOC_OBJECTS) $(LDFLAGS) -lm
+
+$(TEX2HTMLTARGET): $(TEX2HTML_OBJECTS)
+ $(LD) -o $(TEX2HTMLTARGET) $(TEX2HTML_OBJECTS) $(LDFLAGS) -lm
+
+$(UNUMLAUTTARGET): $(UNUMLAUT_OBJECTS)
+ $(LD) -o $(UNUMLAUTTARGET) $(UNUMLAUT_OBJECTS) $(LDFLAGS)
+
+#---------------------------------------------------------------------------
+# special rules for objects dependant on string resource files
+
+include makedefs.str
+
+#---------------------------------------------------------------------------
+# supplementary targets
+
+test: $(ALLTARGETS)
+ cd tests; ./testall
+
+install: $(ALLTARGETS)
+ ./install.sh $(BINDIR) $(INCDIR) $(MANDIR) $(LIBDIR) $(DOCDIR)
+
+clean:
+ rm -f $(ALLTARGETS) $(RESCOMPTARGET) $(TEX2DOCTARGET) $(TEX2HTMLTARGET) *.$(OBJEXTENSION) *.p *.rsc tests/testlog
+ cd doc_DE; $(MAKE) RM="rm -f" clean
+ cd doc_EN; $(MAKE) RM="rm -f" clean
+
+#---------------------------------------------------------------------------
+# create distributions
+
+distrib: unjunk
+ mkdir ../asl-$(VERSION)
+ tar cf - $(DISTARCHFILES) | (cd ../asl-$(VERSION); tar xvf -)
+ cd ..; tar cvf asl-$(VERSION).tar asl-$(VERSION)
+ mv ../asl-$(VERSION).tar ./
+ rm -rf ../asl-$(VERSION)
+ gzip -9 -f asl-$(VERSION).tar
+
+bindist:
+ mkdir asl-$(VERSION)
+ chmod 755 asl-$(VERSION)
+ ./install.sh asl-$(VERSION)/bin asl-$(VERSION)/include asl-$(VERSION)/man asl-$(VERSION)/lib asl-$(VERSION)/doc
+ tar cvf asl-$(VERSION)-bin.tar asl-$(VERSION)
+ rm -rf asl-$(VERSION)
+ gzip -9 -f asl-$(VERSION)-bin.tar
+
+#---------------------------------------------------------------------------
+# for my own use only...
+
+tape: unjunk
+ tar cvf $(TAPE) $(ARCHFILES)
+
+disk: unjunk archive
+ mcopy -nvm asport.tar.gz a:ASPORT.TGZ
+
+disks: unjunk archives
+ echo Insert disk 1...
+ read tmp
+ mcopy -nvm asport1.tar.gz a:ASPORT1.TGZ
+ echo Insert disk 2...
+ read tmp
+ mcopy -nvm asport2.tar.gz a:ASPORT2.TGZ
+
+archive: unjunk asport.tar.gz
+
+barchive: unjunk asport.tar.bz2
+
+archives: unjunk asport1.tar.gz asport2.tar.gz
+
+asport.tar.gz: $(ARCHFILES)
+ tar cvf asport.tar $(ARCHFILES)
+ gzip -9 -f asport.tar
+
+asport.tar.bz2: $(ARCHFILES)
+ tar cvf asport.tar $(ARCHFILES)
+ bzip2 asport.tar
+
+asport1.tar.gz: $(ARCH1FILES)
+ tar cvf asport1.tar $(ARCH1FILES)
+ gzip -9 -f asport1.tar
+
+asport2.tar.gz: $(ARCH2FILES)
+ tar cvf asport2.tar $(ARCH2FILES)
+ gzip -9 -f asport2.tar
+
+snap: unjunk
+ -mount /mo
+ -mkdir -p /mo/public/asport/snap_$(DATE)
+ cp -av $(ARCHFILES) /mo/public/asport/snap_$(DATE)
+ umount /mo
+
+unjunk:
+ rm -f tmp.* n.c include/stddef56.inc asmpars.cas.c include/fileform* config.h test.h loc.c gennop.c \
+ nops.asm bind.* asmutils.* asmmessages.* filenums.* includelist.* tests/warnlog_* \
+ insttree.* flt1750.* t_65.* test87c8.* testst9.* testst7.* testtms7.* test3203.* \
+ ioerrors.new.c codeallg.* ASM*.c *_msg*.h p2BIN.* \
+ decodecmd.* ioerrors.* stringutil.* *split.c marks.c \
+ `find . -name "testlog" -print` \
+ `find . -name "*~" -print` \
+ `find . -name "core" -print` \
+ `find . -name "*.core" -print` \
+ `find . -name "*.lst" -print` \
+ `find . -name "lst" -print` \
+ `find . -name "*.noi" -print`
+ cd doc_DE; $(MAKE) clean RM="rm -f"
+ cd doc_EN; $(MAKE) clean RM="rm -f"
+
+depend:
+ $(CC) $(ALLFLAGS) -MM *.c >depfile
+
+#---------------------------------------------------------------------------
+
+.SUFFIXES: .c
+.c.$(OBJEXTENSION):
+ $(CC) $(ALLFLAGS) -c $*.c
diff --git a/Makefile.def-samples/MakeDef.cad b/Makefile.def-samples/MakeDef.cad
new file mode 100644
index 0000000..11ba842
--- /dev/null
+++ b/Makefile.def-samples/MakeDef.cad
@@ -0,0 +1,25 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = cc
+LD = cc
+CFLAGS = -O -D__MUNIX__ -I/usr/include/bsd -Dsigned= -Dvoid=int -Dconst=
+LDFLAGS = -lbsd
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.def-samples/MakeDef.dos b/Makefile.def-samples/MakeDef.dos
new file mode 100644
index 0000000..444f7ca
--- /dev/null
+++ b/Makefile.def-samples/MakeDef.dos
@@ -0,0 +1,32 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = bcc
+LD = bcc
+CFLAGS =-ml -Y -Oe -k- -Z -d
+OVR1FLAG=-Y
+OVR2FLAG=-Yo
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = c:\as\bin
+INCDIR = c:\as\include
+MANDIR = c:\as\man
+LIBDIR = c:\as\lib
+DOCDIR = c:\as\doc
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+CHARSET = CHARSET_IBM437
+# CHARSET = CHARSET_IBM850
+
+# -------------------------------------------------------------------------
+# DOS special...
+
+EXEXTENSION=.exe
diff --git a/Makefile.def-samples/MakeDef.dpmi b/Makefile.def-samples/MakeDef.dpmi
new file mode 100644
index 0000000..bf2ed48
--- /dev/null
+++ b/Makefile.def-samples/MakeDef.dpmi
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = bcc
+LD = bcc -WX
+CFLAGS =-WX -ml -Oe -k- -Z -d -dc
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = c:\as\bin
+INCDIR = c:\as\include
+MANDIR = c:\as\man
+LIBDIR = c:\as\lib
+DOCDIR = c:\as\doc
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+CHARSET = CHARSET_IBM437
+# CHARSET = CHARSET_IBM850
+
+# -------------------------------------------------------------------------
+# DOS special...
+
+EXEXTENSION=.exe
diff --git a/Makefile.def-samples/Makefile.def-alpha-dec-osf13.2 b/Makefile.def-samples/Makefile.def-alpha-dec-osf13.2
new file mode 100644
index 0000000..7f88057
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-alpha-dec-osf13.2
@@ -0,0 +1,27 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = cc
+LD = cc -non_shared -om
+CFLAGS = -std1 -O4 -Olimit 3000 -tune ev5 -fast
+# ^^^^^^^^^
+# |||||||||
+# adapt this to your target cpu (ev4 or ev5)
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
diff --git a/Makefile.def-samples/Makefile.def-alpha-dec-osf14.0 b/Makefile.def-samples/Makefile.def-alpha-dec-osf14.0
new file mode 100644
index 0000000..784fbc5
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-alpha-dec-osf14.0
@@ -0,0 +1,27 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = cc
+LD = cc -non_shared -om
+CFLAGS = -std1 -O5 -Olimit 3000 -tune ev5 -fast
+# ^^^^^^^^^
+# |||||||||
+# adapt this to your target cpu (ev4 or ev5)
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
diff --git a/Makefile.def-samples/Makefile.def-alpha-unknown-linux2.x.x b/Makefile.def-samples/Makefile.def-alpha-unknown-linux2.x.x
new file mode 100644
index 0000000..369572e
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-alpha-unknown-linux2.x.x
@@ -0,0 +1,25 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = gcc
+LD = gcc
+CFLAGS = -O3 -fomit-frame-pointer -Wall
+LDFLAGS =
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
diff --git a/Makefile.def-samples/Makefile.def-hppa-hp-hpux-10.0 b/Makefile.def-samples/Makefile.def-hppa-hp-hpux-10.0
new file mode 100644
index 0000000..9f08148
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-hppa-hp-hpux-10.0
@@ -0,0 +1,28 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = c89
+LD = c89
+CFLAGS = +O2 +DA715 +ESlit +e -D_INCLUDE_POSIX_SOURCE -D_INCLUDE_XOPEN_SOURCE -D_INCLUDE_XOPEN_SOURCE_EXTENDED
+LDFLAGS =
+# ^^^^^^
+# ||||||
+# adapt to your target machine!
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
diff --git a/Makefile.def-samples/Makefile.def-hppa-hp-hpux-9.0 b/Makefile.def-samples/Makefile.def-hppa-hp-hpux-9.0
new file mode 100644
index 0000000..cb64e8d
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-hppa-hp-hpux-9.0
@@ -0,0 +1,26 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = c89
+LD = c89
+CFLAGS = +O3 +DA715 +ESlit +e \
+ -D_INCLUDE_AES_SOURCE -D_INCLUDE_POSIX_SOURCE -D_INCLUDE_XOPEN_SOURCE -D_INCLUDE_HPUX_SOURCE
+LDFLAGS =
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
diff --git a/Makefile.def-samples/Makefile.def-i386-unknown-dpmi b/Makefile.def-samples/Makefile.def-i386-unknown-dpmi
new file mode 100644
index 0000000..bf2ed48
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-i386-unknown-dpmi
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = bcc
+LD = bcc -WX
+CFLAGS =-WX -ml -Oe -k- -Z -d -dc
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = c:\as\bin
+INCDIR = c:\as\include
+MANDIR = c:\as\man
+LIBDIR = c:\as\lib
+DOCDIR = c:\as\doc
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+CHARSET = CHARSET_IBM437
+# CHARSET = CHARSET_IBM850
+
+# -------------------------------------------------------------------------
+# DOS special...
+
+EXEXTENSION=.exe
diff --git a/Makefile.def-samples/Makefile.def-i386-unknown-linux2.x.x b/Makefile.def-samples/Makefile.def-i386-unknown-linux2.x.x
new file mode 100644
index 0000000..ae0fbd0
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-i386-unknown-linux2.x.x
@@ -0,0 +1,27 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = gcc
+LD = gcc
+CFLAGS = -O3 -m486 -fomit-frame-pointer -Wall
+LDFLAGS =
+# ^^^^^
+# |||||
+# adapt this to your target cpu (386/486 or higher)
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
diff --git a/Makefile.def-samples/Makefile.def-i386-unknown-msdos b/Makefile.def-samples/Makefile.def-i386-unknown-msdos
new file mode 100644
index 0000000..444f7ca
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-i386-unknown-msdos
@@ -0,0 +1,32 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = bcc
+LD = bcc
+CFLAGS =-ml -Y -Oe -k- -Z -d
+OVR1FLAG=-Y
+OVR2FLAG=-Yo
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = c:\as\bin
+INCDIR = c:\as\include
+MANDIR = c:\as\man
+LIBDIR = c:\as\lib
+DOCDIR = c:\as\doc
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+CHARSET = CHARSET_IBM437
+# CHARSET = CHARSET_IBM850
+
+# -------------------------------------------------------------------------
+# DOS special...
+
+EXEXTENSION=.exe
diff --git a/Makefile.def-samples/Makefile.def-i386-unknown-os2 b/Makefile.def-samples/Makefile.def-i386-unknown-os2
new file mode 100644
index 0000000..4fdab90
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-i386-unknown-os2
@@ -0,0 +1,33 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = gcc
+LD = gcc
+CFLAGS = -O3 -m486 -fomit-frame-pointer -g -Wall
+LDFLAGS =
+# ^^^^^
+# |||||
+# adapt this to your target cpu (386/486 or higher)
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_IBM850
+
+# -------------------------------------------------------------------------
+# OS/2 special...
+
+EXEXTENSION = .exe
diff --git a/Makefile.def-samples/Makefile.def-i386-unknown-os2-visualage b/Makefile.def-samples/Makefile.def-i386-unknown-os2-visualage
new file mode 100644
index 0000000..b076f9f
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-i386-unknown-os2-visualage
@@ -0,0 +1,31 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = vicc
+LD = vlink
+OBJOPT = "/Fo"
+CFLAGS =
+OUTOPT = "/O:"
+LDFLAGS = /PM:VIO
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = .
+INCDIR = m:/as/include
+MANDIR = .
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_IBM850
+
+# -------------------------------------------------------------------------
+# OS/2 special...
+
+EXEXTENSION = .exe
diff --git a/Makefile.def-samples/Makefile.def-i386-unknown-win32 b/Makefile.def-samples/Makefile.def-i386-unknown-win32
new file mode 100644
index 0000000..d46abdb
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-i386-unknown-win32
@@ -0,0 +1,28 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = gcc
+LD = gcc
+CFLAGS = -O0 -g -Wall -Wno-parentheses -Wno-sign-compare
+LDFLAGS =
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+EXEXTENSION=.exe
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_IBM850
+# CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.def-samples/Makefile.def-m68k-pcs-munix3 b/Makefile.def-samples/Makefile.def-m68k-pcs-munix3
new file mode 100644
index 0000000..11ba842
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-m68k-pcs-munix3
@@ -0,0 +1,25 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = cc
+LD = cc
+CFLAGS = -O -D__MUNIX__ -I/usr/include/bsd -Dsigned= -Dvoid=int -Dconst=
+LDFLAGS = -lbsd
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.def-samples/Makefile.def-m68k-sun-netbsd1.2 b/Makefile.def-samples/Makefile.def-m68k-sun-netbsd1.2
new file mode 100644
index 0000000..6c49567
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-m68k-sun-netbsd1.2
@@ -0,0 +1,28 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = gcc
+LD = gcc
+CFLAGS = -O3 -fomit-frame-pointer -m68030 -Wall
+LDFLAGS =
+# ^^^^^^^
+# |||||||
+# adapt to your cpu type!
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
diff --git a/Makefile.def-samples/Makefile.def-mips-dec-netbsd1.2 b/Makefile.def-samples/Makefile.def-mips-dec-netbsd1.2
new file mode 100644
index 0000000..f0770f9
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-mips-dec-netbsd1.2
@@ -0,0 +1,28 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = gcc
+LD = gcc
+# You might want to adapt the -m-option to your cpu type
+# Strange: on a 5000/200, things get slower with higher optimization
+# levels...that doesn't happen on a 3100...
+CFLAGS = -O1 -mcpu=r3000 -fomit-frame-pointer -Wall
+LDFLAGS =
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.def-samples/Makefile.def-mips-dec-ultrix4.3 b/Makefile.def-samples/Makefile.def-mips-dec-ultrix4.3
new file mode 100644
index 0000000..fe6b04e
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-mips-dec-ultrix4.3
@@ -0,0 +1,25 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = c89
+LD = c89
+CFLAGS = -O2 -Olimit 2500
+LDFLAGS = -lcV
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.def-samples/Makefile.def-mips-sgi-irix6.2 b/Makefile.def-samples/Makefile.def-mips-sgi-irix6.2
new file mode 100644
index 0000000..5e7574e
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-mips-sgi-irix6.2
@@ -0,0 +1,25 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = cc
+LD = cc
+CFLAGS = -O2 -Olimit 5000
+LDFLAGS =
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.def-samples/Makefile.def-mips64-sgi-irix6.4 b/Makefile.def-samples/Makefile.def-mips64-sgi-irix6.4
new file mode 100644
index 0000000..e2187d4
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-mips64-sgi-irix6.4
@@ -0,0 +1,25 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = cc
+LD = cc
+CFLAGS = -O3 -OPT:Olimit=5000 -mips4 -xgot
+LDFLAGS =
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.def-samples/Makefile.def-rs6k-ibm-aix41 b/Makefile.def-samples/Makefile.def-rs6k-ibm-aix41
new file mode 100644
index 0000000..0634744
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-rs6k-ibm-aix41
@@ -0,0 +1,28 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = xlc
+LD = xlc
+CFLAGS = -O3 -qarch=pwr2 -qtune=pwr2
+LDFLAGS =
+# ^^^^^^^^^^^^^^^^^^^^^^^
+# |||||||||||||||||||||||
+# adapt to your processor architecture (pwr/pwr2/ppc)
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.def-samples/Makefile.def-sparc-sun-solaris2.x b/Makefile.def-samples/Makefile.def-sparc-sun-solaris2.x
new file mode 100644
index 0000000..5d4ecb1
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-sparc-sun-solaris2.x
@@ -0,0 +1,24 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = cc
+LD = cc
+CFLAGS = -xO4 -xcg92
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
diff --git a/Makefile.def-samples/Makefile.def-sparc-sun-sunos4.1.3 b/Makefile.def-samples/Makefile.def-sparc-sun-sunos4.1.3
new file mode 100644
index 0000000..f470d8d
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-sparc-sun-sunos4.1.3
@@ -0,0 +1,25 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = gcc
+LD = gcc
+CFLAGS = -O3 -Wall -D__USE_FIXED_PROTOTYPES__
+LDFLAGS =
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+CHARSET = CHARSET_ISO8859_1
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
diff --git a/Makefile.def-samples/Makefile.def-vax-dec-ultrix4.1 b/Makefile.def-samples/Makefile.def-vax-dec-ultrix4.1
new file mode 100644
index 0000000..8f2381a
--- /dev/null
+++ b/Makefile.def-samples/Makefile.def-vax-dec-ultrix4.1
@@ -0,0 +1,25 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = gcc
+LD = gcc
+CFLAGS = -O3 -fomit-frame-pointer -Wall
+LDFLAGS = -lcV
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.def.tmpl b/Makefile.def.tmpl
new file mode 100644
index 0000000..a11b1e6
--- /dev/null
+++ b/Makefile.def.tmpl
@@ -0,0 +1,25 @@
+# -------------------------------------------------------------------------
+# choose your compiler (must be ANSI-compliant!) and linker command, plus
+# any additionally needed flags
+
+CC = gcc
+LD = gcc
+CFLAGS = -O3 -fomit-frame-pointer -Wall
+LDFLAGS =
+
+# -------------------------------------------------------------------------
+# directories where binaries, includes, and manpages should go during
+# installation
+
+BINDIR = /usr/local/bin
+INCDIR = /usr/local/include/asl
+MANDIR = /usr/local/man
+LIBDIR = /usr/local/lib/asl
+DOCDIR = /usr/local/doc/asl
+
+# -------------------------------------------------------------------------
+# character encoding to use (choose one of them)
+
+# CHARSET = CHARSET_ASCII7
+# CHARSET = CHARSET_IBM437
+CHARSET = CHARSET_ISO8859_1
diff --git a/Makefile.dos b/Makefile.dos
new file mode 100755
index 0000000..8858b44
--- /dev/null
+++ b/Makefile.dos
@@ -0,0 +1,120 @@
+!include Makefile.def
+
+CURRDIR=.\\
+
+!include makedefs.src
+
+!include objdefs.dos
+
+!include makedefs.files
+
+ALLFLAGS = $(CFLAGS) -D$(CHARSET) -DSTDINCLUDES="$(INCDIR)" -DLIBDIR="$(LIBDIR)"
+
+#---------------------------------------------------------------------------
+# primary targets
+
+all: $(ALLTARGETS)
+
+docs: $(TEX2DOCTARGET) $(TEX2HTMLTARGET)
+ cd doc_DE
+ $(MAKE) TEX2DOC=..\$(TEX2DOCTARGET) TEX2HTML=..\$(TEX2HTMLTARGET) RM=del
+ cd ..\doc_EN
+ $(MAKE) TEX2DOC=..\$(TEX2DOCTARGET) TEX2HTML=..\$(TEX2HTMLTARGET) RM=del
+ cd ..
+
+$(ASLTARGET): $(AS_OBJECTS) $(ASM_OBJECTS) $(ST_OBJECTS) $(CODE_OBJECTS) $(NLS_OBJECTS)
+ $(LD) @&&!
+-ml $(OVR1FLAG) -e$(ASLTARGET)
+$(AS_OBJECTS) $(ASM_OBJECTS)
+$(ST_OBJECTS) $(NLS_OBJECTS)
+$(OVR2FLAG) $(CODE_OBJECTS)
+!
+
+$(PLISTTARGET): $(PLIST_OBJECTS) $(NLS_OBJECTS)
+ $(LD) @&&!
+-ml -e$(PLISTTARGET)
+$(PLIST_OBJECTS) n*.$(OBJEXTENSION)
+!
+
+$(PBINDTARGET): $(PBIND_OBJECTS) $(NLS_OBJECTS)
+ $(LD) @&&!
+-ml -e$(PBINDTARGET)
+$(PBIND_OBJECTS) n*.$(OBJEXTENSION)
+!
+
+$(P2HEXTARGET): $(P2HEX_OBJECTS) $(NLS_OBJECTS)
+ $(LD) @&&!
+-ml -e$(P2HEXTARGET)
+$(P2HEX_OBJECTS)
+$(NLS_OBJECTS)
+!
+
+$(P2BINTARGET): $(P2BIN_OBJECTS) $(NLS_OBJECTS)
+ $(LD) @&&!
+-ml -e$(P2BINTARGET)
+$(P2BIN_OBJECTS) n*.$(OBJEXTENSION)
+!
+
+$(RESCOMPTARGET): $(RESCOMP_OBJECTS)
+ $(LD) -ml -e$(RESCOMPTARGET) $(RESCOMP_OBJECTS) $(LDFLAGS)
+
+$(TEX2DOCTARGET): $(TEX2DOC_OBJECTS)
+ $(LD) -ml -e$(TEX2DOCTARGET) $(TEX2DOC_OBJECTS) $(LDFLAGS)
+
+$(TEX2HTMLTARGET): $(TEX2HTML_OBJECTS)
+ $(LD) -ml -e$(TEX2HTMLTARGET) $(TEX2HTML_OBJECTS) $(LDFLAGS)
+
+$(UNUMLAUTTARGET): $(UNUMLAUT_OBJECTS)
+ $(LD) -ml -e$(UNUMLAUTTARGET) $(UNUMLAUT_OBJECTS) $(LDFLAGS)
+
+#---------------------------------------------------------------------------
+# special rules for objects dependant on string resource files
+
+!include makedefs.str
+
+#---------------------------------------------------------------------------
+# supplementary targets
+
+test: $(ALLTARGETS)
+ cd tests
+ copy t_secdri\wd1003at.inc t_secdri\lowlevel.inc
+ testall
+ cd ..
+
+install: $(ALLTARGETS) $(UNUMLAUTTARGET)
+ install $(BINDIR) $(INCDIR) $(MANDIR) $(LIBDIR) $(DOCDIR)
+
+clean:
+ del $(ALLTARGETS)
+ del $(TEX2DOCTARGET)
+ del $(TEX2HTMLTARGET)
+ del $(RESCOMPTARGET)
+ del *.$(OBJEXTENSION)
+ del *.p
+ del testlog
+ del *.rsc
+ cd doc_DE
+ $(MAKE) RM=del clean
+ cd ..\doc_EN
+ $(MAKE) RM=del clean
+ cd ..
+
+#---------------------------------------------------------------------------
+# create distributions
+
+bindist: $(UNUMLAUTTARGET)
+ mkdir as
+ install as\bin as\include as\man as\lib as\doc
+ cd as
+ zip -9 -r ..\as$(VERSION) *.*
+ cd ..
+ deltree as
+
+#---------------------------------------------------------------------------
+# for my own use only...
+
+#---------------------------------------------------------------------------
+
+.SUFFIXES: .c
+.c.$(OBJEXTENSION):
+ $(CC) $(ALLFLAGS) -c $*.c
diff --git a/Makefile.os2 b/Makefile.os2
new file mode 100644
index 0000000..5c967d9
--- /dev/null
+++ b/Makefile.os2
@@ -0,0 +1,100 @@
+include Makefile.def
+
+CURRDIR=.\\
+
+include makedefs.src
+
+include objdefs.unix
+
+include makedefs.files
+
+ALLFLAGS = $(CFLAGS) -D$(CHARSET) -DSTDINCLUDES=\"$(INCDIR)\" -DLIBDIR=\"$(LIBDIR)\"
+
+#---------------------------------------------------------------------------
+# primary targets
+
+all: $(ALLTARGETS)
+
+docs: $(TEX2DOCTARGET) $(TEX2HTMLTARGET)
+ cd doc_DE & $(MAKE) TEX2DOC=..\$(TEX2DOCTARGET) TEX2HTML=..\$(TEX2HTMLTARGET) RM=del
+ cd doc_EN & $(MAKE) TEX2DOC=..\$(TEX2DOCTARGET) TEX2HTML=..\$(TEX2HTMLTARGET) RM=del
+
+$(ASLTARGET): $(AS_OBJECTS) $(ASM_OBJECTS) $(ST_OBJECTS) $(CODE_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(ASLTARGET) $(ASM_OBJECTS) $(AS_OBJECTS) $(ST_OBJECTS) $(CODE_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(PLISTTARGET): $(PLIST_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(PLISTTARGET) $(PLIST_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(PBINDTARGET): $(PBIND_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(PBINDTARGET) $(PBIND_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(P2HEXTARGET): $(P2HEX_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(P2HEXTARGET) $(P2HEX_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(P2BINTARGET): $(P2BIN_OBJECTS) $(NLS_OBJECTS)
+ $(LD) -o $(P2BINTARGET) $(P2BIN_OBJECTS) $(NLS_OBJECTS) -lm $(LDFLAGS)
+
+$(RESCOMPTARGET): $(RESCOMP_OBJECTS)
+ $(LD) -o $(RESCOMPTARGET) $(RESCOMP_OBJECTS) $(LDFLAGS)
+
+$(TEX2DOCTARGET): $(TEX2DOC_OBJECTS)
+ $(LD) -o $(TEX2DOCTARGET) $(TEX2DOC_OBJECTS) $(LDFLAGS) -lm
+
+$(TEX2HTMLTARGET): $(TEX2HTML_OBJECTS)
+ $(LD) -o $(TEX2HTMLTARGET) $(TEX2HTML_OBJECTS) $(LDFLAGS) -lm
+
+$(UNUMLAUTTARGET): $(UNUMLAUT_OBJECTS)
+ $(LD) -o $(UNUMLAUTTARGET) $(UNUMLAUT_OBJECTS) $(LDFLAGS)
+
+#---------------------------------------------------------------------------
+# special rules for objects dependant on string resource files
+
+include makedefs.str
+
+#---------------------------------------------------------------------------
+# supplementary targets
+
+test: $(ALLTARGETS)
+ cd tests & copy t_secdrive\wd1003at.inc t_secdrive\lowlevel.inc & .\testall
+
+install: $(ALLTARGETS)
+ .\install $(BINDIR) $(INCDIR) $(MANDIR) $(LIBDIR) $(DOCDIR)
+
+clean:
+ -del $(ALLTARGETS)
+ -del $(TEX2DOCTARGET)
+ -del $(TEX2HTMLTARGET)
+ -del $(RESCOMPTARGET)
+ -del *.$(OBJEXTENSION)
+ -del *.p
+ -del testlog
+ -del *.rsc
+ cd doc_DE & $(MAKE) RM=del clean
+ cd doc_EN & $(MAKE) RM=del clean
+
+#---------------------------------------------------------------------------
+# create distributions
+
+bindist: $(UNUMLAUTTARGET)
+ mkdir as & cmd /cinstall as\bin as\include as\man as\lib as\doc
+ cd as & zip -9 -r ..\as2$(VERSION) *
+ -del as\bin\* /n
+ -del as\include\* /n
+ -del as\man\* /n
+ -del as\lib /n
+ -del as\doc\* /n
+ -rmdir as\bin
+ -rmdir as\include
+ -rmdir as\man
+ -rmdir as\lib
+ -rmdir as\doc
+ -rmdir as
+
+#---------------------------------------------------------------------------
+# for my own use only...
+
+#---------------------------------------------------------------------------
+
+.SUFFIXES: .c
+.c.$(OBJEXTENSION):
+ $(CC) $(ALLFLAGS) -c $*.c
diff --git a/README b/README
new file mode 100644
index 0000000..3656479
--- /dev/null
+++ b/README
@@ -0,0 +1,98 @@
+Hello, AS-Users,
+
+OK, here it is, the C-Version of AS that is theoretically compilable
+on any system that has an ANSI-C-compiler! After a couple of
+optimizations, the performance degradations due to the way C handles
+strings have been compensated, so the C version should effectively run
+a bit faster than the original Pascal version.
+
+LICENSING
+
+Those who have already used the original DOS/Pascal version of AS
+will know that AS is completely free: you may use and modify AS for
+whatever purpose you like (regardless whether it is commercial or
+not), given that you do not remove my copyright from the sources and
+that programs that build upon the AS sources are given out under the
+same license terms. Of course, if you add something significant,
+you may also add your own name to the copyright list!
+
+To make things a bit more interesting (for me), I have added a detail
+to the license terms of the C version: it is wineware! If you want
+and have time, you may send me a bottle of your favourite wine...
+
+
+PLATFORMS
+
+The C version of AS was designed primarily to work with a Unix-like system
+with an ANSI-C compilant compiler. Specifically, I have tested this version
+of AS on the following machines:
+
+- Digital Unix 3.2/4.0 with DEC-C
+- Digital Ultrix for Mips 4.3/4.5 with gcc 2.7.2
+- Digital Ultrix for VAX 4.1/4.5 with gcc 2.7.2
+- Linux/Alpha with gcc 2.7.2
+- Linux/Intel with gcc 2.7.2
+- HP9000/7xx HP-UX 9.0/10.0 with HP-C
+- MS-DOS with Borland-C 3.1 resp. 4.5
+- OS/2 with emx 0.9
+- Munix V.3 with cc
+- NetBSD/Sun3 with gcc 2.7.2
+- NetBSD/pmax with gcc 2.7.2
+- SGI Irix 5.3/6.2 with SGI-C
+- SunOS 4.1.3/Sparc with gcc 2.6.3 or cc
+- Solaris 2.5/Sparc with Sun-C 3.0.1
+- IBM RS/6000 AIX 4.1 with IBM XLC
+
+DIFFERENCES / THINGS TO DO
+
+The portable C version of AS has the following, known differences to
+the original BP version:
+
+- Floating point values are internally only stored as IEEE double
+ precision values, not in the 80-bit format Intel NPUs use.
+ Therefore, floating point ranges and accuracy are not as good as in
+ the BP version. Currently, there seems to be no portable,
+ standardized 128-bit-format for FP numbers. Every vendor (IBM,
+ SUN, CRAY, SGI...) uses his own format, so supporting them all
+ looks like a lot of work...
+
++ On most systems, integer arithmetic is done with 64-bit-numbers.
+ This should hurt only programs that explicitly exploit overflow
+ and sign effects on 32-bit-versions of AS.
+
+- String variables must not contain NUL characters. This is due to
+ the fact that C uses the NUL character as an end-of-string marker,
+ and is probably the hardest thing to resolve :-(
+
+~ most UNIX systems name their own assembler already 'as', so I had
+ to modify the name to 'asl'. The additional letter is to the honor
+ of a person that did quite a lot to spread the UNIX philosophy ;-)
+ I also had to rename 'bind' to 'pbind', but I guess that this won't
+ matter too much as it is a rarely used tool.
+
+- the C version was designed to have exactly the same command line
+ interface as the original BP version; however, UNIX shells
+ interprete some special characters like the dollar sign for hex
+ values in their own way, so you might have to work with escape (\)
+ and quote characters.
+
++ the USEXMS resp. USEEMS and ASXSWAP environment variables do not
+ exist for Unix platforms (thankfully).
+
+- the AS2MSG filter does not exist (wouldn't make sense because there
+ is no Borland Pascal for Unix.)
+
++ This version now contains dynamic switching of program messages, i.e.
+ you do not have to compile AS any more for a specific language. Instead,
+ AS will test the LC_MESSAGES, LC_ALL, or LANG environment variables
+ on Unix resp. the COUNTRY settings on OS/2 and MSDOS to dynamically
+ load the correct set of messages at runtime.
+
+
+INSTALLATION
+
+See the file 'INSTALL'
+
+FEEDBACK
+
+In case of problems or questions, send them to alfred@ccac.rwth-aachen.de .
diff --git a/README.DOS b/README.DOS
new file mode 100644
index 0000000..5f476c2
--- /dev/null
+++ b/README.DOS
@@ -0,0 +1,26 @@
+All right, I couldn't resist to port the C version back to DOS. It was
+tricky, and I had to fight again all the limitations and bullshit MS-DOS
+brings. For porting, I used Borland C in version 3.1 . Older versions
+might work also, but you will probably have to take out a lot of code
+generator modules if your version of Turbo/Borland-C does not offer
+overlays. Porting to compilers from other manufacturers is probably not
+impossible, but surely more effort than buying a used copy of BC3.1...
+
+Don't bother with the dozens of warnings issued by the compiler concerning
+unused parameters: Things have to be like that since functions are called
+via pointers and some functions need the parameters and some not. There
+must be a switch somewhere to silence the compiler..
+
+Copy 'Makefile.dos' to 'Makefile' and move the 'makedef.dos' (I hate this
+8+3 limit!) to 'Makefile.def'. Compiling and test run should then work
+as usual. Assure that you have at least 600 Kbytes of free DOS memory
+or otherwise the larger tests might fail! For the DOS platform, the
+CKMALLOC symbol is defined to automatically check for out-of-memory
+conditions. The 'wrapped' functions are malloc(), realloc(), and strdup().
+There must be a function missing, since AS still occasionally crashes when
+he runs out of memory....
+
+Compiling for DOS protected mode is also possible. Use the 'makedef.dpmi'
+as 'Makefile.def'. I tested this with Borland-C 4.5 and the Powerpack for
+BC 4.X .
+
diff --git a/README.KR b/README.KR
new file mode 100644
index 0000000..7347391
--- /dev/null
+++ b/README.KR
@@ -0,0 +1,55 @@
+All right, you want to compile AS with a K&R compiler, and I hope you
+have really thought about it before attemptimg this. Think a second
+and third time before you really go this way! The procedure is
+tedious and error-prone. I really regard K&R C as being obsolete, and
+that is why I did not provide an 'automatic' way to compile AS with a
+K&R compiler. You will probably face more problems than mentioned
+here, since K&R systems are mostly old systems that also lack library
+functions of newer systems. The K&R support is mostly here because I
+have an old PCS/Cadmus system (the first german company in the 80s
+that built Unix systems, 68k-equipped and with a very bare System V.3
+port) whose compiler is even too stupid to compile GNU-C, so the
+description will orient along the things I had to do for the Cadmus.
+This scheme however has also already worked for SunOS/Sparc with the
+old 'cc' compiler from Sun....
+
+1. remove the '#error' directives from 'sysdefs.h' - K&R
+ preprocessors do not know them.
+
+2. construct an appropriate 'Makefile.def' for your system. Since
+ most older systems do not define OS-specific symbols, you might
+ have to define them yourself and correlate them to what you query
+ in 'sysdefs.h' for your system. For a K&R compiler, '-Dsigned=
+ -Dconst=' is a good start to remove ANSI extensions. For the
+ Cadmus, I also had to to add '-Dvoid=int' because the compiler's
+ void datatype was broken.
+
+3. There is a tool called 'a2k' to convert ANSI sources (headers &
+ c-files) to K&R style. This mainly involves removing the
+ prototypes. Don't think this is a general ANSI-->K&R converter,
+ since it heavily depends on my way of formatting C sources and
+ some additional differences are handled in the sources themselves
+ via __STDC__ queries! To build a2k, a simple 'make a2k' should
+ suffice.
+
+4. Convert all header files to K&R, like in the following:
+
+ for i in *.h; do
+ cp $i $i.ansi
+ a2k $i.ansi $i
+ done
+
+5. Change the Makefile so that a2k is called as a preprocessor to the
+ compiler. The simplest way is to modify the implicit rule:
+
+ .c.o:
+ a2k $*.c tmp.c
+ $(CC) $(ALLFLAGS) -c tmp.c
+ mv tmp.o $*.o
+ rm -f tmp.c
+
+6. Type 'make' and pray...
+
+One more thing: older Unix systems do not know symbolic links, so a manual
+'cp tests/t_secdrive/wd1003at.inc cp tests/t_secdrive/lowlevel.inc' might be
+necessary...
diff --git a/README.LANGS b/README.LANGS
new file mode 100644
index 0000000..2e5eeda
--- /dev/null
+++ b/README.LANGS
@@ -0,0 +1,197 @@
+The current version of AS supports the concept loadable language modules,
+i.e. the language AS speaks to you is not set during compile time. Instead,
+AS tries to detect the language environment at startup and then to load
+the appropriate set of messages dynamically. The process of detection
+differs depending on the platform: On MS-DOS and OS/2 systems, AS queries
+the COUNTRY setting made from CONFIG.SYS. On Unix systems, AS looks for
+the environment variables
+
+LC_MESSAGES
+LC_ALL
+LANG
+
+and takes the first two letters from the variable that is found first.
+These two letters are interpreted as a code for the country you live
+in.
+
+Currently, AS knows the languages 'german' (code 049 resp. DE) and
+english (code 001 resp. EN). Any other setting leads to the default
+english language. Sorry, but I do not know more languages good enough
+to do other translations. You may now ask if you could add more
+languages to AS, and this is just what I hoped for when I wrote these
+lines ;-)
+
+Messages are stored in text files with the extension '.res'. Since
+parsing text files at every startup of the assembler would be quite
+inefficient, the '.res' files are transformed into a binary, indexed
+format that can be read with a few block read statements. The
+translation is done during the build process with a special tool
+called 'rescomp' (you might have seen the execution of rescomp while
+you built the C version of AS). rescomp parses the input file(s),
+assigns a number to each message, packs the messages to a single array
+of chars with an index table, and creates an additional header file
+that contains the numbers assigned to each message. A run-time
+library then allows to look up the messages via their numbers.
+
+A message source file consists of a couple of control statements.
+Empty lines are ignored; lines that start with a semicolon are
+treated as comments (i.e. they are also ignored). The first
+control statement a message file contains is the 'Langs' statement,
+which indicates the languages the messages in this file will support.
+This is a *GLOBAL* setting, i.e. you cannot omit languages for single
+messages! The Command has the following form:
+
+Langs <Code>(<Country-Code(s),...>) ....
+
+'Code' is the two-letter abbreviation for a language, e.g. 'DE' for
+german. Please use only UPPERcase! The code is followed by a
+comma-separated list of DOS-style country codes for DOS and OS/2
+environments. As you see, several country codes may point to a
+single language this way. For example, if you want to assign the
+english language to both americans and british people, write
+
+Langs EN(001,061) <further languages>
+
+In case AS finds a language environment that was not explicitly
+handled in the message file, the first language given to the 'Langs'
+command is used. You may override this via the 'Default' statement.
+e.g.
+
+Default DE
+
+Once the language is specified, the 'Message' command is the
+only one left to be explained. This command starts the definition of
+a message. The message file compiler reads the next 'n' lines, with
+'n' being the number of languages defined by the 'Langs' command. A
+sample message definition would look like
+
+Message TestMessage
+ "Dies ist ein Test"
+ "This is a test"
+
+given that you specified german and english language with the 'Langs'
+command.
+
+In case the messages become longer than a single line (messages may
+contain newline characters, more about this later), the use of a
+backslash (\) as a line continuation parameter is allowed:
+
+Message TestMessage2
+ "Dies ist eine" \
+ "zweizeilige Nachricht"
+ "This is a" \
+ "two-line message"
+
+Since we deal with non-english languages, we also have to deal with
+characters that are not part of the standard ASCII character set - a
+point where UNIX systems are traditionally weak. Since we cannot
+assume that all terminals have the capability to enter all
+language-specific character directly, there must be an 'escape
+mechanism' to write them as a sequence of standard ASCII characters.
+The message file compiler uses a subset of the sequences used in SGML
+and HTML:
+
+ &auml; &euml; &iuml; &ouml; &uuml;
+ --> lowercase umlauted characters
+ &Auml; &Euml; &Iuml; &Ouml; &Uuml;
+ --> uppercase umlauted characters
+ &szlig;
+ --> german sharp s
+ &sup2;
+ --> exponential 2
+ &micro;
+ --> micron character
+ &agrave; &egrave; &igrave; &ograve; &ugrave;
+ --> lowercase accent grave characters
+ &Agrave; &Egrave; &Igrave; &Ograve; &Ugrave;
+ --> uppercase accent grave characters
+ &aacute; &eacute; &iacute; &oacute; &uacute;
+ --> lowercase accent acute characters
+ &Aacute; &Eacute; &Iacute; &Oacute; &Uacute;
+ --> uppercase accent acute characters
+ &acirc; &ecirc; &icirc; &ocirc; &ucirc;
+ --> lowercase accent circonflex characters
+ &Acirc; &Ecirc; &Icirc; &Ocirc; &Ucirc;
+ --> uppercase accent circonflex characters
+ &ccedil; &Ccedil;
+ --> lowercase / uppercase cedilla
+ &ntilde; &Ntilde;
+ --> lowercase / uppercase tilded n
+ &aring; &Aring;
+ --> lowercase / uppercase ringed a
+ &aelig; &Aelig;
+ --> lowercase / uppercase ae diphtong
+ &iquest; &iexcl;
+ --> inverted question / exclamation mark
+ \n
+ --> newline character
+
+Upon translation of a message file, the message file compiler will
+replace these sequences with the correct character encodings for the
+target platform. In the extreme case of a bare 7-bit-ASCII system,
+this may imply the translation to a sequence of ASCII characters that
+'emulate' the non-ASCII character. *NEVER* use the special characters
+directly in the message source files, as this would destroy their
+portability!!!
+
+The number of supported language-specific characters used to be
+strongly biased to the german language. The reason for this is
+simple: german is the only non-english language AS currently
+supports...sorry, but English and German is the amount of languages
+im am sufficiently fluent in to make a translation...help of others to
+extend the range is mostly welcome, and this is the primary reason
+why I explained the whole stuff ;-)
+
+So, if you feel brave enough to add a language (don't forget that
+there's also an almost-300-page user's manual that waits for
+translation ;-), the following steps have to be taken:
+
+ 1. Find out which non-ASCII characters you additionally need.
+ I can then extend the message file compiler appropriately.
+ 2. Add your language to the 'Langs' statement in 'header.res'.
+ This file is included into all other message files, so you
+ only have to do this once :-)
+ 3. go through all other '.res' files and add the line to all
+ messages........
+ 4. recompile AS
+ 5. You're done!
+
+That's about everything to be said about the technical side.
+Let's go to the political side. I'm prepared to get confronted
+with two opinions after you read this:
+
+ "Gee, that's far too much effort for such a tool. And anyway, who
+ needs anything else than english on a Unix system? Unix is some-
+ thing that was born to be english, and you better accept that!"
+
+ "Hey, why did you reinvent the wheel? There's catgets(), there's
+ GNU-gettext, and..."
+
+Well, i'll try to stay polite ;-)
+
+First, the fact that Unix is so biased towards the english language is
+in no way god-given, it's just the way it evolved. Unix was developed
+in the USA, and the typical Unix users were up to now people who had
+no problems with english - university students, developers etc. But
+the times have changed: Linux and *BSD have made Unix cheap, and we are
+facing more and more Unix users from other circles - people who
+previously only knew MS-LOSS and MS-Windog, and who were told by their
+nearest freak that Unix is a great thing. Such users typically will not
+accept a system that only speaks english, given that every 500-Dollar-
+Windows PC speaks to them in their native language, so why not this
+Unix system that claims to be sooo great ?!
+
+Furthermore, do not forget that AS is not a Unix-only tool: It runs
+on MS-DOS and OS/2 too, and a some people try to make it go on Macs
+(though this seems to be a much harder piece of work...). On these
+systems, localization is the standard!
+
+The portability to non-Unix platforms is the reason why I did not choose
+an existing package to manage message catalogs. catgets() seems to be
+Unix-specific (and it even is not available on all Unix systems!), and
+about gettext...well, I just did not look into it...it might have worked,
+but most of the GNU tools ported to DOS I have seen so far needed 32-bit-
+extenders, which I wanted to avoid. So I quickly hacked up my own
+library, but I promise that I will at least reuse it for my own projects!
+
+chardefs.h
diff --git a/README.OS2 b/README.OS2
new file mode 100644
index 0000000..4e59cc1
--- /dev/null
+++ b/README.OS2
@@ -0,0 +1,26 @@
+Additional hints for OS/2 users:
+
+- if you only have FAT file systems, forget compiling AS rightaway - we
+ need the long filenames and therefore a HPFS file system!
+
+- You need the following Unix tools, ported to OS/2 :
+
+ - 'gzip' and 'tar' to unpack the archive, but you obviously already
+ have managed that ;-)
+
+ - Eberhard Matthes' port of the GNU-C compiler for OS/2. I haven't
+ made personally any attempts with other OS/2 compilers so far, but
+ it might be worth a try.... AS includes already patches for IBM's
+ Visual Age C 3.0 made by Steffen Schuemann <s.schuemann@pobox.com>
+ relative to the original r6 distribution. I couldn't test them
+ myself since I do not have the IBM compiler :-(
+
+ - a make utility to process the Makefile. A port of GNU's make should
+ be perfect.
+
+- Copy 'Makefile.os2' (for emx) resp. 'Makefile.vac' (for IBM Visual Age C)
+ to 'Makefile' .
+
+- If you make a binary distribution, don't forget to include the emx
+ runtime libaries...
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..7b2fa19
--- /dev/null
+++ b/TODO
@@ -0,0 +1,6 @@
+- Benchmarks Dual-P2 einarbeiten
+- README-Verweise in Anleitung
+- Anleitung: Lieferumfang : Binaer-Basis, Zusatzfiles, Source wird
+ bisheriger Unix-Teil
+- Anleitung: Quellenkapitel neuschreiben
+- Anleitung: FAQ wenn viele Passes
diff --git a/a2k.c b/a2k.c
new file mode 100644
index 0000000..43685f9
--- /dev/null
+++ b/a2k.c
@@ -0,0 +1,193 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+/*** valid sym. character */
+
+int readline(file,dest)
+FILE *file;
+char *dest;
+{
+ char *run=dest;
+ int zeichen='a';
+
+ while ((!feof(file))&&(zeichen!=EOF)&&(zeichen!='\n'))
+ {
+ zeichen=fgetc(file);
+ if ((zeichen!=EOF)&&(zeichen!='\n')) *(run++)=zeichen;
+ }
+ *run='\0';
+ return 0;
+}
+
+int isblankline(line)
+char *line;
+{
+ for (; *line!='\0'; line++) if (!isspace(*line)) return 0;
+ return 1;
+}
+
+int linestartswidth(line,needle)
+char *line;
+char *needle;
+{
+ while (isspace(*line)) line++;
+ return (strncmp(line,needle,strlen(needle))==0);
+}
+
+#define BUFFERSIZE 10
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ FILE *inpfile,*outfile;
+ char lines[BUFFERSIZE][500],*p;
+ char orig[1000],dest[1000],params[1000],single[1000],save;
+ int BufferFill,start,z,flag;
+
+ if (argc!=3)
+ {
+ fprintf(stderr,"usage: %s <input file> <output file>\n",argv[0]);
+ exit(1);
+ }
+
+ if (strcmp(argv[1],"-")==0) inpfile=stdin;
+ else inpfile=fopen(argv[1],"r");
+ if (inpfile==NULL)
+ {
+ perror(argv[1]); return 2;
+ }
+
+ if (strcmp(argv[2],"-")==0) outfile=stdout;
+ else outfile=fopen(argv[2],"w");
+ if (outfile==NULL)
+ {
+ perror(argv[2]); return 2;
+ }
+
+ BufferFill=0;
+ while (!feof(inpfile))
+ {
+ if (BUFFERSIZE==BufferFill)
+ {
+ fprintf(outfile,"%s\n",lines[0]);
+ for (z=0; z<BufferFill; z++) strcpy(lines[z],lines[z+1]);
+ BufferFill--;
+ }
+ readline(inpfile,lines[BufferFill++]);
+
+ /* condition for a function header:
+ 1. body begins with '{' or 'BEGIN' in first column
+ 2. header searched backward until blank, comment, or preprocessor
+ line detected */
+
+ if ((strcmp(lines[BufferFill-1],"BEGIN")==0)||(strcmp(lines[BufferFill-1],"{")==0))
+ {
+ for (start=BufferFill-1; start>=0; start--)
+ if (isblankline(lines[start])) break;
+ else if (*lines[start]=='#') break;
+ else if (strncmp(lines[start],"/*",2)==0) break;
+ else if (strcmp(lines[start]+strlen(lines[start])-2,"*/")==0) break;
+ start++;
+
+ /* found: assemble source lines into a single line */
+
+ for (z=start,*orig='\0'; z<=BufferFill-2; z++)
+ {
+ p=lines[z]; while (isspace(*p)) p++; strcat(orig,p);
+ if (z!=BufferFill-2) strcat(orig," ");
+ }
+
+ /* cut function name+prefixes: parameter list starts at first '(' */
+
+ p=strchr(orig,'('); *p='\0';
+ sprintf(dest,"\t%s",orig); strcat(dest,"("); strcpy(orig,p+1);
+
+ /* cut trailing ')' */
+
+ for (p=orig+strlen(orig)-1; *p!=')'; p--); *p='\0';
+
+ /* loop through parameters: discard 'void' entries */
+
+ *params=0; flag=0;
+ while (*orig!='\0')
+ {
+ p=strchr(orig,',');
+ if (p==NULL)
+ {
+ strcpy(single,orig); *orig='\0';
+ }
+ else
+ {
+ *p='\0'; strcpy(single,orig); strcpy(orig,p+1);
+ }
+ for (p=single; isspace(*p); p++); strcpy(single,p);
+ for (p=single+strlen(single)-1; isspace(*p); p--); p[1]='\0';
+ if (strncmp(single,"const ",6)==0) strcpy(single,single+6);
+ if (strcmp(single,"void")!=0)
+ {
+ strcat(params,single); strcat(params,";\n");
+ for (p=single+strlen(single)-1; (isalnum(*p))||(*p=='_'); p--);
+ if (flag) strcat(dest,","); strcat(dest,p+1); flag=1;
+ }
+ }
+
+ /* close function head */
+
+ strcat(dest,")");
+
+ /* flush contents berore header from buffer */
+
+ for (z=0; z<start; fprintf(outfile,"%s\n",lines[z++]));
+
+ /* print K&R header; don't forget opening of function body! */
+
+ fprintf(outfile,"%s\n%sBEGIN\n",dest,params);
+
+ /* flush buffer */
+
+ BufferFill=0;
+ }
+
+ /* Detect 'extern' definitions in header files */
+
+ else if (linestartswidth(lines[BufferFill-1],"extern "))
+ {
+ /* find opening parenthesis. if none, it's a variable definition */
+
+ p=strchr(lines[BufferFill-1],'(');
+ if (p!=NULL)
+ {
+ /* if next character is a '*', we have an external definition of
+ a function pointer and have to find the next '(' */
+
+ if (p[1]=='*') p=strchr(p+1,'(');
+
+ /* copy out first part, extend by ');' and write the 'prototype'.
+ flush line buffer before. */
+
+ save=p[1];
+ p[1]='\0'; strcpy(dest,lines[BufferFill-1]); strcat(dest,");");
+ p[1]=save;
+
+ for (z=0; z<BufferFill-1; fprintf(outfile,"%s\n",lines[z++]));
+ fprintf(outfile,"%s\n",dest);
+
+ /* discard lines until end of prototype */
+
+ strcpy(dest,lines[BufferFill-1]); BufferFill=0;
+ while (strcmp(dest+strlen(dest)-2,");")!=0)
+ {
+ readline(inpfile,dest);
+ }
+ }
+ }
+ }
+
+ for (z=0; z<BufferFill; fprintf(outfile,"%s\n",lines[z++]));
+
+ fclose(inpfile); fclose(outfile);
+ return 0;
+} \ No newline at end of file
diff --git a/addcr.c b/addcr.c
new file mode 100644
index 0000000..85e6147
--- /dev/null
+++ b/addcr.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ int ch;
+
+ while (!feof(stdin))
+ {
+ ch=fgetc(stdin);
+ if (ch==10) fputc(13,stdout);
+ if (ch!=EOF) fputc(ch,stdout);
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/as.c b/as.c
new file mode 100644
index 0000000..1ce4579
--- /dev/null
+++ b/as.c
@@ -0,0 +1,2985 @@
+/* as.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Hauptmodul */
+/* */
+/* Historie: 4. 5.1996 Grundsteinlegung */
+/* 24. 6.1998 Zeichenübersetzungstabellen */
+/* 30. 6.1998 Ausgabe in MacPro-File auch wenn Zeile nur aus */
+/* Kommentar oder Label besteht */
+/* 18. 7.1998 IRPC-Statement */
+/* 24. 7.1998 Debug-Modus NoICE */
+/* 25. 7.1998 Formate glattgezogen */
+/* 16. 8.1998 Datei-Adressbereiche zurücksetzen */
+/* 17. 8.1998 InMacroFlag nach asmdef verschoben */
+/* 19. 8.1998 BranchExt-Initialisierung */
+/* 25. 8.1998 i960-Initialisierung */
+/* 28. 8.1998 32-Bit-Listen gehen auch korrekt mit */
+/* Codelaengen != 4*n um */
+/* 30. 8.1998 uPD7720-Initialisierung */
+/* Einrueckung fuer 'R' in Retracted-Zeilen im Listing */
+/* war nicht korrekt */
+/* 13. 9.1998 uPD77230-Initialisierung */
+/* 30. 9.1998 SYM53C8xx-Initialisierung */
+/* 3.12.1998 8008-Initialisierung */
+/* 9. 1.1999 PCs erst nach Schreiben des Codes hochzaehlen */
+/* ChkPC mit Adresse als Parameter */
+/* 30. 1.1999 Formate maschinenunabhaengig gemacht */
+/* 12. 2.1999 Compilerwarnungen beseitigt */
+/* 25. 3.1999 SC14xxx-Initialisierung */
+/* 17. 4.1999 CPU per Kommandozeile setzen */
+/* 18. 4.1999 Ausgabeliste Sharefiles */
+/* 4. 7.1999 F2MC8-Initialisierung */
+/* 8. 8.1999 Externliste immer am Ende einer Zeile loeschen */
+/* 14. 8.1999 Initialisierung ACE */
+/* 5.11.1999 ExtendErrors, 2. Stufe */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+#include <setjmp.h>
+
+#include "version.h"
+#include "endian.h"
+#include "bpemu.h"
+
+#include "stdhandl.h"
+#include "cmdarg.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "as.rsc"
+#include "ioerrs.h"
+#include "strutil.h"
+#include "stringlists.h"
+#include "asmitree.h"
+#include "chunks.h"
+#include "asminclist.h"
+#include "asmfnums.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmmac.h"
+#include "asmif.h"
+#include "asmcode.h"
+#include "asmdebug.h"
+#include "asmrelocs.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "as.h"
+
+#include "code68k.h"
+#include "code56k.h"
+#include "code601.h"
+#include "codemcore.h"
+#include "code68.h"
+#include "code6805.h"
+#include "code6809.h"
+#include "code6812.h"
+#include "code6816.h"
+#include "codeh8_3.h"
+#include "codeh8_5.h"
+#include "code7000.h"
+#include "code65.h"
+#include "code7700.h"
+#include "code4500.h"
+#include "codem16.h"
+#include "codem16c.h"
+#include "code4004.h"
+#include "code8008.h"
+#include "code48.h"
+#include "code51.h"
+#include "code96.h"
+#include "code85.h"
+#include "code86.h"
+#include "code960.h"
+#include "code8x30x.h"
+#include "codexa.h"
+#include "codeavr.h"
+#include "code29k.h"
+#include "code166.h"
+#include "codez80.h"
+#include "codez8.h"
+#include "code96c141.h"
+#include "code90c141.h"
+#include "code87c800.h"
+#include "code47c00.h"
+#include "code97c241.h"
+#include "code16c5x.h"
+#include "code16c8x.h"
+#include "code17c4x.h"
+#include "codest6.h"
+#include "codest7.h"
+#include "codest9.h"
+#include "code6804.h"
+#include "code3201x.h"
+#include "code3202x.h"
+#include "code3203x.h"
+#include "code3205x.h"
+#include "code3206x.h"
+#include "code9900.h"
+#include "codetms7.h"
+#include "code370.h"
+#include "codemsp.h"
+#include "codescmp.h"
+#include "codecop8.h"
+#include "codesc14xxx.h"
+#include "codeace.h"
+#include "code78c10.h"
+#include "code75k0.h"
+#include "code78k0.h"
+#include "code7720.h"
+#include "code77230.h"
+#include "code53c8xx.h"
+#include "codefmc8.h"
+#include "as1750.h"
+/** Code21xx};**/
+
+/**
+VAR
+ ParCnt,k:Integer;
+ CPU:CPUVar;**/
+static String FileMask;
+static long StartTime,StopTime;
+static Boolean GlobErrFlag;
+static Boolean MasterFile;
+
+/*=== Zeilen einlesen ======================================================*/
+
+
+#if 0
+#define dbgentry(str) printf("***enter %s\n",str);
+#define dbgexit(str) printf("***exit %s\n",str);
+#else
+#define dbgentry(str) {}
+#define dbgexit(str) {}
+#endif
+
+ static void NULL_Restorer(PInputTag PInp)
+BEGIN
+END
+
+ static Boolean NULL_GetPos(PInputTag PInp, char *dest)
+BEGIN
+ *dest='\0'; return False;
+END
+
+ static void GenerateProcessor(PInputTag *PInp)
+BEGIN
+ *PInp=(PInputTag) malloc(sizeof(TInputTag));
+ (*PInp)->IsMacro=False;
+ (*PInp)->Next=Nil;
+ (*PInp)->First=True;
+ (*PInp)->OrigDoLst=DoLst;
+ (*PInp)->StartLine=CurrLine;
+ (*PInp)->ParCnt=0; (*PInp)->ParZ=0;
+ InitStringList(&((*PInp)->Params));
+ (*PInp)->LineCnt=0; (*PInp)->LineZ=1;
+ (*PInp)->Lines=Nil;
+ (*PInp)->SpecName[0]='\0';
+ (*PInp)->IsEmpty=False;
+ (*PInp)->Buffer=Nil;
+ (*PInp)->Datei=Nil;
+ (*PInp)->IfLevel=SaveIFs();
+ (*PInp)->Restorer=NULL_Restorer;
+ (*PInp)->GetPos=NULL_GetPos;
+END
+
+/*=========================================================================*/
+/* Listing erzeugen */
+
+ static void MakeList_Gen2Line(char *h, Word EffLen, Word *n)
+BEGIN
+ int z,Rest;
+
+ Rest=EffLen-(*n); if (Rest>8) Rest=8; if (DontPrint) Rest=0;
+ for (z=0; z<(Rest>>1); z++)
+ BEGIN
+ strmaxcat(h,HexString(WAsmCode[(*n)>>1],4),255);
+ strmaxcat(h," ",255);
+ (*n)+=2;
+ END
+ if ((Rest&1)!=0)
+ BEGIN
+ strmaxcat(h,HexString(BAsmCode[*n],2),255);
+ strmaxcat(h," ",255);
+ (*n)++;
+ END
+ for (z=1; z<=(8-Rest)>>1; z++)
+ strmaxcat(h," ",255);
+END
+
+ static void MakeList_Gen4Line(char *h, Word EffLen, Word *n)
+BEGIN
+ int z,Rest,wr=0;
+
+ Rest=EffLen-(*n); if (Rest>8) Rest=8; if (DontPrint) Rest=0;
+ for (z=0; z<(Rest>>2); z++)
+ BEGIN
+ strmaxcat(h,HexString(DAsmCode[(*n)>>2],8),255);
+ strmaxcat(h," ",255);
+ (*n)+=4; wr+=9;
+ END
+ for (z=0; z<(Rest&3); z++)
+ BEGIN
+ strmaxcat(h,HexString(BAsmCode[(*n)++],2),255);
+ strmaxcat(h," ",255);
+ wr+=3;
+ END
+ strmaxcat(h,Blanks(20-wr),255);
+END
+
+ static void MakeList(void)
+BEGIN
+ String h,h2,Tmp;
+ Byte i,k;
+ Word n;
+ Word EffLen;
+
+ EffLen=CodeLen*Granularity();
+
+ if ((NOT ListToNull) AND (DoLst) AND ((ListMask&1)!=0) AND (NOT IFListMask()))
+ BEGIN
+ /* Zeilennummer / Programmzaehleradresse: */
+
+ if (IncDepth==0) strmaxcpy(h2," ",255);
+ else
+ BEGIN
+ sprintf(Tmp,IntegerFormat,IncDepth);
+ sprintf(h2,"(%s)",Tmp);
+ END
+ if ((ListMask&0x10)!=0)
+ BEGIN
+ sprintf(h,"%5d/",CurrLine); strmaxcat(h2,h,255);
+ END
+ strmaxcpy(h,h2,255); strmaxcat(h,HexBlankString(EProgCounter()-CodeLen,8),255);
+ strmaxcat(h,Retracted?" R ":" : ",255);
+
+ /* Extrawurst in Listing ? */
+
+ if (*ListLine!='\0')
+ BEGIN
+ strmaxcat(h,ListLine,255);
+ strmaxcat(h,Blanks(20-strlen(ListLine)),255);
+ strmaxcat(h,OneLine,255);
+ WrLstLine(h);
+ *ListLine='\0';
+ END
+
+ /* Code ausgeben */
+
+ else
+ switch (ActListGran)
+ BEGIN
+ case 4:
+ n=0; MakeList_Gen4Line(h,EffLen,&n);
+ strmaxcat(h,OneLine,255); WrLstLine(h);
+ if (NOT DontPrint)
+ while (n<EffLen)
+ BEGIN
+ strmaxcpy(h," ",255);
+ MakeList_Gen4Line(h,EffLen,&n);
+ WrLstLine(h);
+ END
+ break;
+ case 2:
+ n=0; MakeList_Gen2Line(h,EffLen,&n);
+ strmaxcat(h,OneLine,255); WrLstLine(h);
+ if (NOT DontPrint)
+ while (n<EffLen)
+ BEGIN
+ strmaxcpy(h," ",255);
+ MakeList_Gen2Line(h,EffLen,&n);
+ WrLstLine(h);
+ END
+ break;
+ default:
+ if ((TurnWords) AND (Granularity()!=ActListGran)) DreheCodes();
+ for (i=0; i<6; i++)
+ if ((NOT DontPrint) AND (EffLen>i))
+ BEGIN
+ strmaxcat(h,HexString(BAsmCode[i],2),255); strmaxcat(h," ",255);
+ END
+ else strmaxcat(h," ",255);
+ strmaxcat(h," ",255); strmaxcat(h,OneLine,255);
+ WrLstLine(h);
+ if ((EffLen>6) AND (NOT DontPrint))
+ BEGIN
+ EffLen-=6;
+ n=EffLen/6; if ((EffLen%6)==0) n--;
+ for (i=0; i<=n; i++)
+ BEGIN
+ strmaxcpy(h," ",255);
+ for (k=0; k<6; k++)
+ if (EffLen>i*6+k)
+ BEGIN
+ strmaxcat(h,HexString(BAsmCode[i*6+k+6],2),255);
+ strmaxcat(h," ",255);
+ END
+ WrLstLine(h);
+ END
+ END
+ if ((TurnWords) AND (Granularity()!=ActListGran)) DreheCodes();
+ END
+
+ END
+END
+
+/*=========================================================================*/
+/* Makroprozessor */
+
+/*-------------------------------------------------------------------------*/
+/* allgemein gebrauchte Subfunktionen */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* werden gebraucht, um festzustellen, ob innerhalb eines Makrorumpfes weitere
+ Makroschachtelungen auftreten */
+
+ Boolean MacroStart(void)
+BEGIN
+ return ((Memo("MACRO")) OR (Memo("IRP")) OR (Memo("IRPC")) OR (Memo("REPT")) OR (Memo("WHILE")));
+END
+
+ Boolean MacroEnd(void)
+BEGIN
+ return (Memo("ENDM"));
+END
+
+/*-------------------------------------------------------------------------*/
+/* Dieser Einleseprozessor dient nur dazu, eine fehlerhafte Makrodefinition
+ bis zum Ende zu ueberlesen */
+
+ static void WaitENDM_Processor(void)
+BEGIN
+ POutputTag Tmp;
+
+ if (MacroStart()) FirstOutputTag->NestLevel++;
+ else if (MacroEnd()) FirstOutputTag->NestLevel--;
+ if (FirstOutputTag->NestLevel<=-1)
+ BEGIN
+ Tmp=FirstOutputTag;
+ FirstOutputTag=Tmp->Next;
+ free(Tmp);
+ END
+END
+
+ static void AddWaitENDM_Processor(void)
+BEGIN
+ POutputTag Neu;
+
+ Neu=(POutputTag) malloc(sizeof(TOutputTag));
+ Neu->Processor=WaitENDM_Processor;
+ Neu->NestLevel=0;
+ Neu->Next=FirstOutputTag;
+ FirstOutputTag=Neu;
+END
+
+/*-------------------------------------------------------------------------*/
+/* normale Makros */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Diese Routine leitet die Quellcodezeilen bei der Makrodefinition in den
+ Makro-Record um */
+
+ static void MACRO_OutProcessor(void)
+BEGIN
+ POutputTag Tmp;
+ int z;
+ StringRecPtr l;
+ PMacroRec GMacro;
+ String s;
+
+ if ((MacroOutput) AND (FirstOutputTag->DoExport))
+ BEGIN
+ errno=0;
+ fprintf(MacroFile,"%s\n",OneLine);
+ ChkIO(10004);
+ END
+ if (MacroStart()) FirstOutputTag->NestLevel++;
+ else if (MacroEnd()) FirstOutputTag->NestLevel--;
+ if (FirstOutputTag->NestLevel!=-1)
+ BEGIN
+ strmaxcpy(s,OneLine,255); KillCtrl(s);
+ l=FirstOutputTag->Params;
+ for (z=1; z<=FirstOutputTag->Mac->ParamCount; z++)
+ CompressLine(GetStringListNext(&l),z,s);
+ if (HasAttrs) CompressLine(AttrName,ParMax+1,s);
+ AddStringListLast(&(FirstOutputTag->Mac->FirstLine),s);
+ END
+
+ if (FirstOutputTag->NestLevel==-1)
+ BEGIN
+ if (IfAsm)
+ BEGIN
+ AddMacro(FirstOutputTag->Mac,FirstOutputTag->PubSect,True);
+ if ((FirstOutputTag->DoGlobCopy) AND (SectionStack!=Nil))
+ BEGIN
+ GMacro=(PMacroRec) malloc(sizeof(MacroRec));
+ GMacro->Name=strdup(FirstOutputTag->GName);
+ GMacro->ParamCount=FirstOutputTag->Mac->ParamCount;
+ GMacro->FirstLine=DuplicateStringList(FirstOutputTag->Mac->FirstLine);
+ AddMacro(GMacro,FirstOutputTag->GlobSect,False);
+ END
+ END
+ else ClearMacroRec(&(FirstOutputTag->Mac));
+
+ Tmp=FirstOutputTag; FirstOutputTag=Tmp->Next;
+ ClearStringList(&(Tmp->Params)); free(Tmp);
+ END
+END
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Hierher kommen bei einem Makroaufruf die expandierten Zeilen */
+
+ Boolean MACRO_Processor(PInputTag PInp, char *erg)
+BEGIN
+ StringRecPtr Lauf;
+ int z;
+ Boolean Result;
+
+ Result=True;
+
+ Lauf=PInp->Lines; for (z=1; z<=PInp->LineZ-1; z++) Lauf=Lauf->Next;
+ strcpy(erg,Lauf->Content);
+ Lauf=PInp->Params;
+ for (z=1; z<=PInp->ParCnt; z++)
+ BEGIN
+ ExpandLine(Lauf->Content,z,erg);
+ Lauf=Lauf->Next;
+ END
+ if (HasAttrs) ExpandLine(PInp->SaveAttr,ParMax+1,erg);
+
+ CurrLine=PInp->StartLine;
+ InMacroFlag=True;
+
+ if (PInp->LineZ==1) PushLocHandle(GetLocHandle());
+
+ if (++(PInp->LineZ)>PInp->LineCnt) Result=False;
+
+ return Result;
+END
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Initialisierung des Makro-Einleseprozesses */
+
+ static Boolean ReadMacro_SearchArg(char *Test, char *Comp, Boolean *Erg)
+BEGIN
+ if (strcasecmp(Test,Comp)==0)
+ BEGIN
+ *Erg=True; return True;
+ END
+ else if ((strlen(Test)>2) AND (strncasecmp(Test,"NO",2)==0) AND (strcasecmp(Test+2,Comp)==0))
+ BEGIN
+ *Erg=False; return True;
+ END
+ else return False;
+END
+
+ static Boolean ReadMacro_SearchSect(char *Test_O, char *Comp, Boolean *Erg, LongInt *Section)
+BEGIN
+ char *p;
+ String Test,Sect;
+
+ strmaxcpy(Test,Test_O,255); KillBlanks(Test);
+ p=strchr(Test,':');
+ if (p==Nil) *Sect='\0';
+ else
+ BEGIN
+ strmaxcpy(Sect,p+1,255); *p='\0';
+ END
+ if ((strlen(Test)>2) AND (strncasecmp(Test,"NO",2)==0) AND (strcasecmp(Test+2,Comp)==0))
+ BEGIN
+ *Erg=False; return True;
+ END
+ else if (strcasecmp(Test,Comp)==0)
+ BEGIN
+ *Erg=True;
+ return (IdentifySection(Sect,Section));
+ END
+ else return False;
+END
+
+ static void ReadMacro(void)
+BEGIN
+ String PList;
+ PSaveSection RunSection;
+ PMacroRec OneMacro;
+ int z1,z2;
+ POutputTag Neu;
+
+ Boolean DoMacExp,DoPublic;
+ LongInt HSect;
+ Boolean ErrFlag;
+
+ CodeLen=0; ErrFlag=False;
+
+ /* Makronamen pruefen */
+ /* Definition nur im ersten Pass */
+
+ if (PassNo!=1) ErrFlag=True;
+ else if (NOT ExpandSymbol(LabPart)) ErrFlag=True;
+ else if (NOT ChkSymbName(LabPart))
+ BEGIN
+ WrXError(1020,LabPart); ErrFlag=True;
+ END
+
+ Neu=(POutputTag) malloc(sizeof(TOutputTag));
+ Neu->Processor=MACRO_OutProcessor;
+ Neu->NestLevel=0;
+ Neu->Params=Nil;
+ Neu->DoExport=False;
+ Neu->DoGlobCopy=False;
+ Neu->Next=FirstOutputTag;
+
+ /* Argumente ueberpruefen */
+
+ DoMacExp=LstMacroEx; DoPublic=False;
+ *PList='\0'; z2=0;
+ for (z1=1; z1<=ArgCnt; z1++)
+ if ((ArgStr[z1][0]=='{') AND (ArgStr[z1][strlen(ArgStr[z1])-1]=='}'))
+ BEGIN
+ strcpy(ArgStr[z1],ArgStr[z1]+1); ArgStr[z1][strlen(ArgStr[z1])-1]='\0';
+ if (ReadMacro_SearchArg(ArgStr[z1],"EXPORT",&(Neu->DoExport)));
+ else if (ReadMacro_SearchArg(ArgStr[z1],"EXPAND",&DoMacExp))
+ BEGIN
+ strmaxcat(PList,",",255); strmaxcat(PList,ArgStr[z1],255);
+ END
+ else if (ReadMacro_SearchSect(ArgStr[z1],"GLOBAL",&(Neu->DoGlobCopy),&(Neu->GlobSect)));
+ else if (ReadMacro_SearchSect(ArgStr[z1],"PUBLIC",&DoPublic,&(Neu->PubSect)));
+ else
+ BEGIN
+ WrXError(1465,ArgStr[z1]); ErrFlag=True;
+ END
+ END
+ else
+ BEGIN
+ strmaxcat(PList,",",255); strmaxcat(PList,ArgStr[z1],255); z2++;
+ if (NOT ChkMacSymbName(ArgStr[z1]))
+ BEGIN
+ WrXError(1020,ArgStr[z1]); ErrFlag=True;
+ END
+ AddStringListLast(&(Neu->Params),ArgStr[z1]);
+ END
+
+ /* Abbruch bei Fehler */
+
+ if (ErrFlag)
+ BEGIN
+ ClearStringList(&(Neu->Params));
+ free(Neu);
+ AddWaitENDM_Processor();
+ return;
+ END
+
+ /* Bei Globalisierung Namen des Extramakros ermitteln */
+
+ if (Neu->DoGlobCopy)
+ BEGIN
+ strmaxcpy(Neu->GName,LabPart,255);
+ RunSection=SectionStack; HSect=MomSectionHandle;
+ while ((HSect!=Neu->GlobSect) AND (RunSection!=Nil))
+ BEGIN
+ strmaxprep(Neu->GName,"_",255); strmaxprep(Neu->GName,GetSectionName(HSect),255);
+ HSect=RunSection->Handle; RunSection=RunSection->Next;
+ END
+ END
+ if (NOT DoPublic) Neu->PubSect=MomSectionHandle;
+
+ OneMacro=(PMacroRec) malloc(sizeof(MacroRec)); Neu->Mac=OneMacro;
+ if ((MacroOutput) AND (Neu->DoExport))
+ BEGIN
+ if (strlen(PList)!=0) strcpy(PList,PList+1);
+ errno=0;
+ if (Neu->DoGlobCopy) fprintf(MacroFile,"%s MACRO %s\n",Neu->GName,PList);
+ else fprintf(MacroFile,"%s MACRO %s\n",LabPart,PList);
+ ChkIO(10004);
+ END
+ OneMacro->Used=False;
+ OneMacro->Name=strdup(LabPart);
+ OneMacro->ParamCount=z2;
+ OneMacro->FirstLine=Nil; OneMacro->LocMacExp=DoMacExp;
+
+ FirstOutputTag=Neu;
+END
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Beendigung der Expansion eines Makros */
+
+ static void MACRO_Cleanup(PInputTag PInp)
+BEGIN
+ ClearStringList(&(PInp->Params));
+END
+
+ static Boolean MACRO_GetPos(PInputTag PInp, char *dest)
+BEGIN
+ String Tmp;
+
+ sprintf(Tmp,LongIntFormat,PInp->LineZ-1);
+ sprintf(dest,"%s(%s) ",PInp->SpecName,Tmp);
+ return False;
+END
+
+ static void MACRO_Restorer(PInputTag PInp)
+BEGIN
+ PopLocHandle();
+ DoLst=PInp->OrigDoLst;
+END
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Dies initialisiert eine Makroexpansion */
+
+ static void ExpandMacro(PMacroRec OneMacro)
+BEGIN
+ int z1;
+ StringRecPtr Lauf;
+ PInputTag Tag;
+
+ CodeLen=0;
+
+ /* if (OneMacro->Used) WrError(1850);
+ else */
+
+ BEGIN
+ OneMacro->Used=True;
+
+ /* 1. Tag erzeugen */
+
+ GenerateProcessor(&Tag);
+ Tag->Processor=MACRO_Processor;
+ Tag->Restorer =MACRO_Restorer;
+ Tag->Cleanup =MACRO_Cleanup;
+ Tag->GetPos =MACRO_GetPos;
+ strmaxcpy(Tag->SpecName,OneMacro->Name,255);
+ strmaxcpy(Tag->SaveAttr,AttrPart,255);
+ Tag->IsMacro =True;
+
+ /* 2. Parameterzahl anpassen */
+
+ if (ArgCnt<OneMacro->ParamCount)
+ for (z1=ArgCnt+1; z1<=OneMacro->ParamCount; z1++) *(ArgStr[z1])='\0';
+ ArgCnt=OneMacro->ParamCount;
+
+ /* 3. Parameterliste aufbauen - umgekehrt einfacher */
+
+ for (z1=ArgCnt; z1>=1; z1--)
+ BEGIN
+ if (NOT CaseSensitive) UpString(ArgStr[z1]);
+ AddStringListFirst(&(Tag->Params),ArgStr[z1]);
+ END
+ Tag->ParCnt=ArgCnt;
+
+ /* 4. Zeilenliste anhaengen */
+
+ Tag->Lines=OneMacro->FirstLine; Tag->IsEmpty=(OneMacro->FirstLine==Nil);
+ Lauf=OneMacro->FirstLine;
+ while (Lauf!=Nil)
+ BEGIN
+ Tag->LineCnt++; Lauf=Lauf->Next;
+ END
+ END
+
+ /* 5. anhaengen */
+
+ if (IfAsm)
+ BEGIN
+ NextDoLst=(DoLst AND OneMacro->LocMacExp);
+ Tag->Next=FirstInputTag; FirstInputTag=Tag;
+ END
+ else
+ BEGIN
+ ClearStringList(&(Tag->Params)); free(Tag);
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/* vorzeitiger Abbruch eines Makros */
+
+ static void ExpandEXITM(void)
+BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (FirstInputTag==Nil) WrError(1805);
+ else if (NOT FirstInputTag->IsMacro) WrError(1805);
+ else if (IfAsm)
+ BEGIN
+ FirstInputTag->Cleanup(FirstInputTag);
+ RestoreIFs(FirstInputTag->IfLevel);
+ FirstInputTag->IsEmpty=True;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/*--- IRP (was das bei MASM auch immer heissen mag...)
+ Ach ja: Individual Repeat! Danke Bernhard, jetzt hab'
+ ich's gerafft! -----------------------*/
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Diese Routine liefert bei der Expansion eines IRP-Statements die expan-
+ dierten Zeilen */
+
+ Boolean IRP_Processor(PInputTag PInp, char *erg)
+BEGIN
+ StringRecPtr Lauf;
+ int z;
+ Boolean Result;
+
+ Result=True;
+
+ Lauf=PInp->Lines; for (z=1; z<=PInp->LineZ-1; z++) Lauf=Lauf->Next;
+ strcpy(erg,Lauf->Content);
+ Lauf=PInp->Params; for (z=1; z<=PInp->ParZ-1; z++) Lauf=Lauf->Next;
+ ExpandLine(Lauf->Content,1,erg); CurrLine=PInp->StartLine+PInp->LineZ;
+
+ if (PInp->LineZ==1)
+ BEGIN
+ if (NOT PInp->First) PopLocHandle(); PInp->First=False;
+ PushLocHandle(GetLocHandle());
+ END
+
+
+ if (++(PInp->LineZ)>PInp->LineCnt)
+ BEGIN
+ PInp->LineZ=1;
+ if (++(PInp->ParZ)>PInp->ParCnt) Result=False;
+ END
+
+ return Result;
+END
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Aufraeumroutine IRP/IRPC */
+
+ static void IRP_Cleanup(PInputTag PInp)
+BEGIN
+ StringRecPtr Lauf;
+
+ /* letzten Parameter sichern, wird evtl. noch fuer GetPos gebraucht!
+ ... SaveAttr ist aber frei */
+ if (PInp->Processor==IRP_Processor)
+ BEGIN
+ for (Lauf=PInp->Params; Lauf->Next!=Nil; Lauf=Lauf->Next);
+ strmaxcpy(PInp->SaveAttr,Lauf->Content,255);
+ END
+
+ ClearStringList(&(PInp->Lines));
+ ClearStringList(&(PInp->Params));
+END
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Posisionsangabe im IRP(C) fuer Fehlermeldungen */
+
+ static Boolean IRP_GetPos(PInputTag PInp, char *dest)
+BEGIN
+ StringRecPtr Lauf=PInp->Params;
+ int z,z1=PInp->ParZ,z2=PInp->LineZ;
+ char *IRPType,*IRPVal,tmp[10];
+
+ if (PInp->Processor==IRP_Processor)
+ BEGIN
+ IRPType="IRP";
+ if (*PInp->SaveAttr!='\0') IRPVal=PInp->SaveAttr;
+ else
+ BEGIN
+ for (z=1; z<=z1-1; z++) Lauf=Lauf->Next;
+ IRPVal=Lauf->Content;
+ END
+ END
+ else
+ BEGIN
+ IRPType="IRPC";
+ sprintf(tmp,"'%c'",PInp->SpecName[z1-1]); IRPVal=tmp;
+ END
+
+ if (--z2<=0)
+ BEGIN
+ z2=PInp->LineCnt; z1--;
+ END
+ sprintf(dest,"%s:%s/%ld ",IRPType,IRPVal,(long)z2);
+
+ return False;
+END
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Diese Routine sammelt waehrend der Definition eines IRP(C)-Statements die
+ Quellzeilen ein */
+
+ static void IRP_OutProcessor(void)
+BEGIN
+ POutputTag Tmp;
+ StringRecPtr Dummy;
+ String s;
+
+ /* Schachtelungen mitzaehlen */
+
+ if (MacroStart()) FirstOutputTag->NestLevel++;
+ else if (MacroEnd()) FirstOutputTag->NestLevel--;
+
+ /* falls noch nicht zuende, weiterzaehlen */
+
+ if (FirstOutputTag->NestLevel>-1)
+ BEGIN
+ strmaxcpy(s,OneLine,255); KillCtrl(s);
+ CompressLine(GetStringListFirst(FirstOutputTag->Params,&Dummy),1,s);
+ AddStringListLast(&(FirstOutputTag->Tag->Lines),s);
+ FirstOutputTag->Tag->LineCnt++;
+ END
+
+ /* alles zusammen? Dann umhaengen */
+
+ if (FirstOutputTag->NestLevel==-1)
+ BEGIN
+ Tmp=FirstOutputTag; FirstOutputTag=FirstOutputTag->Next;
+ Tmp->Tag->IsEmpty=(Tmp->Tag->Lines==Nil);
+ if (IfAsm)
+ BEGIN
+ NextDoLst=DoLst AND LstMacroEx;
+ Tmp->Tag->Next=FirstInputTag; FirstInputTag=Tmp->Tag;
+ END
+ else
+ BEGIN
+ ClearStringList(&(Tmp->Tag->Lines)); ClearStringList(&(Tmp->Tag->Params));
+ free(Tmp->Tag);
+ END
+ ClearStringList(&(Tmp->Params));
+ free(Tmp);
+ END
+END
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Initialisierung der IRP-Bearbeitung */
+
+ static void ExpandIRP(void)
+BEGIN
+ String Parameter;
+ int z1;
+ PInputTag Tag;
+ POutputTag Neu;
+ Boolean ErrFlag;
+
+ /* 1.Parameter pruefen */
+
+ if (ArgCnt<2)
+ BEGIN
+ WrError(1110); ErrFlag=True;
+ END
+ else
+ BEGIN
+ strmaxcpy(Parameter,ArgStr[1],255);
+ if (NOT ChkMacSymbName(ArgStr[1]))
+ BEGIN
+ WrXError(1020,Parameter); ErrFlag=True;
+ END
+ else ErrFlag=False;
+ END
+ if (ErrFlag)
+ BEGIN
+ AddWaitENDM_Processor();
+ return;
+ END
+
+ /* 2. Tag erzeugen */
+
+ GenerateProcessor(&Tag);
+ Tag->ParCnt=ArgCnt-1;
+ Tag->Processor=IRP_Processor;
+ Tag->Restorer =MACRO_Restorer;
+ Tag->Cleanup =IRP_Cleanup;
+ Tag->GetPos =IRP_GetPos;
+ Tag->ParZ =1;
+ Tag->IsMacro =True;
+ *Tag->SaveAttr='\0';
+
+ /* 3. Parameterliste aufbauen; rueckwaerts einen Tucken schneller */
+
+ for (z1=ArgCnt; z1>=2; z1--)
+ BEGIN
+ UpString(ArgStr[z1]);
+ AddStringListFirst(&(Tag->Params),ArgStr[z1]);
+ END
+
+ /* 4. einbetten */
+
+ Neu=(POutputTag) malloc(sizeof(TOutputTag));
+ Neu->Next=FirstOutputTag;
+ Neu->Processor=IRP_OutProcessor;
+ Neu->NestLevel=0;
+ Neu->Tag=Tag;
+ Neu->Params=Nil; AddStringListFirst(&(Neu->Params),ArgStr[1]);
+ FirstOutputTag=Neu;
+END
+
+/*--- IRPC: dito für Zeichen eines Strings ---------------------------------*/
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Diese Routine liefert bei der Expansion eines IRPC-Statements die expan-
+ dierten Zeilen */
+
+ Boolean IRPC_Processor(PInputTag PInp, char *erg)
+BEGIN
+ StringRecPtr Lauf;
+ int z;
+ Boolean Result;
+ char tmp[5];
+
+ Result=True;
+
+ Lauf=PInp->Lines; for (z=1; z<=PInp->LineZ-1; z++) Lauf=Lauf->Next;
+ strcpy(erg,Lauf->Content);
+ *tmp=PInp->SpecName[PInp->ParZ-1]; tmp[1]='\0';
+ ExpandLine(tmp,1,erg); CurrLine=PInp->StartLine+PInp->LineZ;
+
+ if (PInp->LineZ==1)
+ BEGIN
+ if (NOT PInp->First) PopLocHandle(); PInp->First=False;
+ PushLocHandle(GetLocHandle());
+ END
+
+
+ if (++(PInp->LineZ)>PInp->LineCnt)
+ BEGIN
+ PInp->LineZ=1;
+ if (++(PInp->ParZ)>PInp->ParCnt) Result=False;
+ END
+
+ return Result;
+END
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Initialisierung der IRPC-Bearbeitung */
+
+ static void ExpandIRPC(void)
+BEGIN
+ String Parameter;
+ PInputTag Tag;
+ POutputTag Neu;
+ Boolean ErrFlag;
+
+ /* 1.Parameter pruefen */
+
+ if (ArgCnt<2)
+ BEGIN
+ WrError(1110); ErrFlag=True;
+ END
+ else
+ BEGIN
+ strmaxcpy(Parameter,ArgStr[1],255);
+ if (NOT ChkMacSymbName(ArgStr[1]))
+ BEGIN
+ WrXError(1020,Parameter); ErrFlag=True;
+ END
+ else ErrFlag=False;
+ END
+ if (NOT ErrFlag)
+ BEGIN
+ EvalStringExpression(ArgStr[2],&ErrFlag,Parameter);
+ ErrFlag=NOT ErrFlag;
+ END
+ if (ErrFlag)
+ BEGIN
+ AddWaitENDM_Processor();
+ return;
+ END
+
+ /* 2. Tag erzeugen */
+
+ GenerateProcessor(&Tag);
+ Tag->ParCnt =strlen(Parameter);
+ Tag->Processor=IRPC_Processor;
+ Tag->Restorer =MACRO_Restorer;
+ Tag->Cleanup =IRP_Cleanup;
+ Tag->GetPos =IRP_GetPos;
+ Tag->ParZ =1;
+ Tag->IsMacro =True;
+ *Tag->SaveAttr='\0';
+ strmaxcpy(Tag->SpecName,Parameter,255);
+
+ /* 4. einbetten */
+
+ Neu=(POutputTag) malloc(sizeof(TOutputTag));
+ Neu->Next=FirstOutputTag;
+ Neu->Processor=IRP_OutProcessor;
+ Neu->NestLevel=0;
+ Neu->Tag=Tag;
+ Neu->Params=Nil; AddStringListFirst(&(Neu->Params),ArgStr[1]);
+ FirstOutputTag=Neu;
+END
+
+/*--- Repetition -----------------------------------------------------------*/
+
+ static void REPT_Cleanup(PInputTag PInp)
+BEGIN
+ ClearStringList(&(PInp->Lines));
+END
+
+ static Boolean REPT_GetPos(PInputTag PInp, char *dest)
+BEGIN
+ int z1=PInp->ParZ,z2=PInp->LineZ;
+
+ if (--z2<=0)
+ BEGIN
+ z2=PInp->LineCnt; z1--;
+ END
+ sprintf(dest,"REPT %ld/%ld",(long)z1,(long)z2);
+ return False;
+END
+
+ Boolean REPT_Processor(PInputTag PInp, char *erg)
+BEGIN
+ StringRecPtr Lauf;
+ int z;
+ Boolean Result;
+
+ Result=True;
+
+ Lauf=PInp->Lines; for(z=1; z<=PInp->LineZ-1; z++) Lauf=Lauf->Next;
+ strcpy(erg,Lauf->Content); CurrLine=PInp->StartLine+PInp->LineZ;
+
+ if (PInp->LineZ==1)
+ BEGIN
+ if (NOT PInp->First) PopLocHandle(); PInp->First=False;
+ PushLocHandle(GetLocHandle());
+ END
+
+ if ((++PInp->LineZ)>PInp->LineCnt)
+ BEGIN
+ PInp->LineZ=1;
+ if ((++PInp->ParZ)>PInp->ParCnt) Result=False;
+ END
+
+ return Result;
+END
+
+ static void REPT_OutProcessor(void)
+BEGIN
+ POutputTag Tmp;
+
+ /* Schachtelungen mitzaehlen */
+
+ if (MacroStart()) FirstOutputTag->NestLevel++;
+ else if (MacroEnd()) FirstOutputTag->NestLevel--;
+
+ /* falls noch nicht zuende, weiterzaehlen */
+
+ if (FirstOutputTag->NestLevel>-1)
+ BEGIN
+ AddStringListLast(&(FirstOutputTag->Tag->Lines),OneLine);
+ FirstOutputTag->Tag->LineCnt++;
+ END
+
+ /* alles zusammen? Dann umhaengen */
+
+ if (FirstOutputTag->NestLevel==-1)
+ BEGIN
+ Tmp=FirstOutputTag; FirstOutputTag=FirstOutputTag->Next;
+ Tmp->Tag->IsEmpty=(Tmp->Tag->Lines==Nil);
+ if ((IfAsm) AND (Tmp->Tag->ParCnt>0))
+ BEGIN
+ NextDoLst=(DoLst AND LstMacroEx);
+ Tmp->Tag->Next=FirstInputTag; FirstInputTag=Tmp->Tag;
+ END
+ else
+ BEGIN
+ ClearStringList(&(Tmp->Tag->Lines));
+ free(Tmp->Tag);
+ END
+ free(Tmp);
+ END
+END
+
+ static void ExpandREPT(void)
+BEGIN
+ Boolean ValOK;
+ LongInt ReptCount=0;
+ PInputTag Tag;
+ POutputTag Neu;
+ Boolean ErrFlag;
+
+ /* 1.Repetitionszahl ermitteln */
+
+ if (ArgCnt!=1)
+ BEGIN
+ WrError(1110); ErrFlag=True;
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ ReptCount=EvalIntExpression(ArgStr[1],Int32,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ ErrFlag=((NOT ValOK) OR (FirstPassUnknown));
+ END
+ if (ErrFlag)
+ BEGIN
+ AddWaitENDM_Processor();
+ return;
+ END
+
+ /* 2. Tag erzeugen */
+
+ GenerateProcessor(&Tag);
+ Tag->ParCnt=ReptCount;
+ Tag->Processor=REPT_Processor;
+ Tag->Restorer =MACRO_Restorer;
+ Tag->Cleanup =REPT_Cleanup;
+ Tag->GetPos =REPT_GetPos;
+ Tag->IsMacro =True;
+ Tag->ParZ=1;
+
+ /* 3. einbetten */
+
+ Neu=(POutputTag) malloc(sizeof(TOutputTag));
+ Neu->Processor=REPT_OutProcessor;
+ Neu->NestLevel=0;
+ Neu->Next=FirstOutputTag;
+ Neu->Tag=Tag;
+ FirstOutputTag=Neu;
+END
+
+/*- bedingte Wiederholung -------------------------------------------------------*/
+
+ static void WHILE_Cleanup(PInputTag PInp)
+BEGIN
+ ClearStringList(&(PInp->Lines));
+END
+
+ static Boolean WHILE_GetPos(PInputTag PInp, char *dest)
+BEGIN
+ int z1=PInp->ParZ,z2=PInp->LineZ;
+
+ if (--z2<=0)
+ BEGIN
+ z2=PInp->LineCnt; z1--;
+ END
+ sprintf(dest, "WHILE %ld/%ld", (long)z1, (long)z2);
+ return False;
+END
+
+ Boolean WHILE_Processor(PInputTag PInp, char *erg)
+BEGIN
+ StringRecPtr Lauf;
+ int z;
+ Boolean OK,Result;
+
+ CurrLine=PInp->StartLine+PInp->LineZ;
+
+ if (PInp->LineZ==1)
+ BEGIN
+ if (NOT PInp->First) PopLocHandle(); PInp->First=False;
+ PushLocHandle(GetLocHandle());
+ END
+ else OK=True;
+
+ Lauf=PInp->Lines; for (z=1; z<=PInp->LineZ-1; z++) Lauf=Lauf->Next;
+ strcpy(erg,Lauf->Content);
+
+ if ((++PInp->LineZ)>PInp->LineCnt)
+ BEGIN
+ PInp->LineZ=1; PInp->ParZ++;
+ z=EvalIntExpression(PInp->SpecName,Int32,&OK);
+ OK=(OK AND (z!=0));
+ Result=OK;
+ END
+ else Result=True;
+
+ return Result;
+END
+
+ static void WHILE_OutProcessor(void)
+BEGIN
+ POutputTag Tmp;
+ Boolean OK;
+ LongInt Erg;
+
+ /* Schachtelungen mitzaehlen */
+
+ if (MacroStart()) FirstOutputTag->NestLevel++;
+ else if (MacroEnd()) FirstOutputTag->NestLevel--;
+
+ /* falls noch nicht zuende, weiterzaehlen */
+
+ if (FirstOutputTag->NestLevel>-1)
+ BEGIN
+ AddStringListLast(&(FirstOutputTag->Tag->Lines),OneLine);
+ FirstOutputTag->Tag->LineCnt++;
+ END
+
+ /* alles zusammen? Dann umhaengen */
+
+ if (FirstOutputTag->NestLevel==-1)
+ BEGIN
+ Tmp=FirstOutputTag; FirstOutputTag=FirstOutputTag->Next;
+ Tmp->Tag->IsEmpty=(Tmp->Tag->Lines==Nil);
+ FirstPassUnknown=False;
+ Erg=EvalIntExpression(Tmp->Tag->SpecName,Int32,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ OK=(OK AND (NOT FirstPassUnknown) AND (Erg!=0));
+ if ((IfAsm) AND (OK))
+ BEGIN
+ NextDoLst=(DoLst AND LstMacroEx);
+ Tmp->Tag->Next=FirstInputTag; FirstInputTag=Tmp->Tag;
+ END
+ else
+ BEGIN
+ ClearStringList(&(Tmp->Tag->Lines));
+ free(Tmp->Tag);
+ END
+ free(Tmp);
+ END
+END
+
+ static void ExpandWHILE(void)
+BEGIN
+ PInputTag Tag;
+ POutputTag Neu;
+ Boolean ErrFlag;
+
+ /* 1.Bedingung ermitteln */
+
+ if (ArgCnt!=1)
+ BEGIN
+ WrError(1110); ErrFlag=True;
+ END
+ else ErrFlag=False;
+ if (ErrFlag)
+ BEGIN
+ AddWaitENDM_Processor();
+ return;
+ END
+
+ /* 2. Tag erzeugen */
+
+ GenerateProcessor(&Tag);
+ Tag->Processor=WHILE_Processor;
+ Tag->Restorer =MACRO_Restorer;
+ Tag->Cleanup =WHILE_Cleanup;
+ Tag->GetPos =WHILE_GetPos;
+ Tag->IsMacro =True;
+ Tag->ParZ=1;
+ strmaxcpy(Tag->SpecName,ArgStr[1],255);
+
+ /* 3. einbetten */
+
+ Neu=(POutputTag) malloc(sizeof(TOutputTag));
+ Neu->Processor=WHILE_OutProcessor;
+ Neu->NestLevel=0;
+ Neu->Next=FirstOutputTag;
+ Neu->Tag=Tag;
+ FirstOutputTag=Neu;
+END
+
+/*--------------------------------------------------------------------------*/
+/* Einziehen von Include-Files */
+
+ static void INCLUDE_Cleanup(PInputTag PInp)
+BEGIN
+ String Tmp;
+
+ fclose(PInp->Datei);
+ free(PInp->Buffer);
+ LineSum+=MomLineCounter;
+ if ((*LstName!='\0') AND (NOT QuietMode))
+ BEGIN
+ sprintf(Tmp,LongIntFormat,CurrLine);
+ printf("%s(%s)",NamePart(CurrFileName),Tmp);
+ printf("%s\n",ClrEol); fflush(stdout);
+ END
+ if (MakeIncludeList) PopInclude();
+END
+
+ static Boolean INCLUDE_GetPos(PInputTag PInp, char *dest)
+BEGIN
+ String Tmp;
+
+ sprintf(Tmp,LongIntFormat,CurrLine);
+ sprintf(dest,"%s(%s) ",NamePart(CurrFileName),Tmp);
+ return True;
+END
+
+ Boolean INCLUDE_Processor(PInputTag PInp, char *Erg)
+BEGIN
+ Boolean Result;
+
+ Result=True;
+
+ if (feof(PInp->Datei)) *Erg='\0';
+ else
+ BEGIN
+ ReadLn(PInp->Datei,Erg);
+ /**ChkIO(10003);**/
+ END
+ CurrLine=(++MomLineCounter);
+ if (feof(PInp->Datei)) Result=False;
+
+ return Result;
+END
+
+ static void INCLUDE_Restorer(PInputTag PInp)
+BEGIN
+ MomLineCounter=PInp->StartLine;
+ strmaxcpy(CurrFileName,PInp->SpecName,255);
+ IncDepth--;
+END
+
+ static void ExpandINCLUDE(Boolean SearchPath)
+BEGIN
+ PInputTag Tag;
+
+ if (NOT IfAsm) return;
+
+ if (ArgCnt!=1)
+ BEGIN
+ WrError(1110); return;
+ END
+
+ strmaxcpy(ArgPart,ArgStr[1],255);
+ if (*ArgPart=='"') strcpy(ArgPart,ArgPart+1);
+ if (ArgPart[strlen(ArgPart)-1]=='"') ArgPart[strlen(ArgPart)-1]='\0';
+ AddSuffix(ArgPart,IncSuffix); strmaxcpy(ArgStr[1],ArgPart,255);
+ if (SearchPath)
+ BEGIN
+ strmaxcpy(ArgPart,FExpand(FSearch(ArgPart,IncludeList)),255);
+ if (ArgPart[strlen(ArgPart)-1]=='/') strmaxcat(ArgPart,ArgStr[1],255);
+ END
+
+ /* Tag erzeugen */
+
+ GenerateProcessor(&Tag);
+ Tag->Processor=INCLUDE_Processor;
+ Tag->Restorer =INCLUDE_Restorer;
+ Tag->Cleanup =INCLUDE_Cleanup;
+ Tag->GetPos =INCLUDE_GetPos;
+ Tag->Buffer =(void *) malloc(BufferArraySize);
+
+ /* Sicherung alter Daten */
+
+ Tag->StartLine=MomLineCounter;
+ strmaxcpy(Tag->SpecName,CurrFileName,255);
+
+ /* Datei oeffnen */
+
+ Tag->Datei=fopen(ArgPart,"r");
+ if (Tag->Datei==Nil) ChkIO(10001);
+ setvbuf(Tag->Datei,Tag->Buffer,_IOFBF,BufferArraySize);
+
+ /* neu besetzen */
+
+ strmaxcpy(CurrFileName,ArgPart,255); MomLineCounter=0;
+ NextIncDepth++; AddFile(ArgPart);
+ PushInclude(ArgPart);
+
+ /* einhaengen */
+
+ Tag->Next=FirstInputTag; FirstInputTag=Tag;
+END
+
+/*=========================================================================*/
+/* Einlieferung von Zeilen */
+
+ static void GetNextLine(char *Line)
+BEGIN
+ PInputTag HTag;
+
+ InMacroFlag=False;
+
+ while ((FirstInputTag!=Nil) AND (FirstInputTag->IsEmpty))
+ BEGIN
+ FirstInputTag->Restorer(FirstInputTag);
+ HTag=FirstInputTag; FirstInputTag=HTag->Next;
+ free(HTag);
+ END
+
+ if (FirstInputTag==Nil)
+ BEGIN
+ *Line='\0'; return;
+ END
+
+ if (NOT FirstInputTag->Processor(FirstInputTag,Line))
+ BEGIN
+ FirstInputTag->Cleanup(FirstInputTag);
+ FirstInputTag->IsEmpty=True;
+ END
+
+ MacLineSum++;
+END
+
+ char *GetErrorPos(void)
+BEGIN
+ String ActPos;
+ PInputTag RunTag;
+ char *ErgPos=strdup(""),*tmppos;
+ Boolean Last;
+
+ for (RunTag=FirstInputTag; RunTag!=Nil; RunTag=RunTag->Next)
+ BEGIN
+ Last=RunTag->GetPos(RunTag,ActPos);
+ tmppos=(char *) malloc(strlen(ErgPos)+strlen(ActPos)+1);
+ strcpy(tmppos,ActPos); strcat(tmppos,ErgPos);
+ free(ErgPos); ErgPos=tmppos;
+ if (Last) break;
+ END
+
+ return ErgPos;
+END
+
+ static Boolean InputEnd(void)
+BEGIN
+ PInputTag Lauf;
+
+ Lauf=FirstInputTag;
+ while (Lauf!=Nil)
+ BEGIN
+ if (NOT Lauf->IsEmpty) return False;
+ Lauf=Lauf->Next;
+ END
+
+ return True;
+END
+
+
+/*=== Eine Quelldatei ( Haupt-oder Includedatei ) bearbeiten ===============*/
+
+/*--- aus der zerlegten Zeile Code erzeugen --------------------------------*/
+
+ Boolean HasLabel(void)
+BEGIN
+ if (*LabPart=='\0') return False;
+ if (IsDef()) return False;
+
+ switch (*OpPart)
+ BEGIN
+ case '=':
+ return (NOT Memo("="));
+ case ':':
+ return (NOT Memo(":"));
+ case 'M':
+ return (NOT Memo("MACRO"));
+ case 'F':
+ return (NOT Memo("FUNCTION"));
+ case 'L':
+ return (NOT Memo("LABEL"));
+ case 'S':
+ return ((NOT Memo("SET")) OR (SetIsOccupied)) AND (NOT Memo("STRUCT"));
+ case 'E':
+ return ((NOT Memo("EVAL")) OR (NOT SetIsOccupied)) AND (NOT Memo("EQU")) AND (NOT Memo("ENDSTRUCT"));
+ default:
+ return True;
+ END
+END
+
+ static void Produce_Code(void)
+BEGIN
+ Byte z;
+ PMacroRec OneMacro;
+ Boolean SearchMacros,Found;
+ String tmp,tmp2;
+ PStructure ZStruct;
+
+ ActListGran=ListGran();
+
+ /* Makrosuche unterdruecken ? */
+
+ if (*OpPart=='!')
+ BEGIN
+ SearchMacros=False; strcpy(OpPart,OpPart+1);
+ END
+ else
+ BEGIN
+ SearchMacros=True; ExpandSymbol(OpPart);
+ END
+ strcpy(LOpPart,OpPart); NLS_UpString(OpPart);
+
+ /* Prozessor eingehaengt ? */
+
+ if (FirstOutputTag!=Nil)
+ BEGIN
+ FirstOutputTag->Processor(); return;
+ END
+
+ /* ansonsten Code erzeugen */
+
+ /* evtl. voranstehendes Label ablegen */
+
+ if (IfAsm)
+ BEGIN
+ if (HasLabel())
+ if (StructureStack!=Nil)
+ BEGIN
+ strmaxcpy(tmp,LabPart,255);
+ for (ZStruct=StructureStack; ZStruct!=Nil; ZStruct=ZStruct->Next)
+ if (ZStruct->DoExt)
+ BEGIN
+ sprintf(tmp2,"%s_",ZStruct->Name);
+ strmaxprep(tmp,tmp2,255);
+ END
+ EnterIntSymbol(tmp,EProgCounter(),SegNone,False);
+ END
+ else EnterIntSymbol(LabPart,EProgCounter(),ActPC,False);
+ END
+
+ Found=False;
+ switch (*OpPart)
+ BEGIN
+ case 'I':
+ /* Makroliste ? */
+ if ((Found=Memo("IRP"))) ExpandIRP();
+ else if ((Found=Memo("IRPC"))) ExpandIRPC();
+ break;
+ case 'R':
+ /* Repetition ? */
+ if ((Found=Memo("REPT"))) ExpandREPT(); break;
+ case 'W':
+ /* bedingte Repetition ? */
+ if ((Found=Memo("WHILE"))) ExpandWHILE(); break;
+ END
+
+ /* bedingte Assemblierung ? */
+
+ if (NOT Found) Found=CodeIFs();
+
+ if (NOT Found)
+ switch (*OpPart)
+ BEGIN
+ case 'M':
+ /* Makrodefinition ? */
+ if ((Found=Memo(("MACRO")))) ReadMacro(); break;
+ case 'E':
+ /* Abbruch Makroexpansion ? */
+ if ((Found=Memo(("EXITM")))) ExpandEXITM(); break;
+ case 'I':
+ /* Includefile? */
+ if ((Found=Memo(("INCLUDE"))))
+ BEGIN
+ ExpandINCLUDE(True);
+ MasterFile=False;
+ END
+ break;
+ END
+
+ if (Found);
+
+ /* Makroaufruf ? */
+
+ else if ((SearchMacros) AND (FoundMacro(&OneMacro)))
+ BEGIN
+ if (IfAsm) ExpandMacro(OneMacro);
+ if (IfAsm) strmaxcpy(ListLine,"(MACRO)",255);
+ END
+
+ else
+ BEGIN
+ StopfZahl=0; CodeLen=0; DontPrint=False;
+
+ if (IfAsm)
+ BEGIN
+ if (NOT CodeGlobalPseudo()) MakeCode();
+ if ((MacProOutput) AND ((*OpPart!='\0') OR (*LabPart!='\0') OR (*CommPart!='\0')))
+ BEGIN
+ errno=0; fprintf(MacProFile,"%s\n",OneLine); ChkIO(10002);
+ END
+ END
+
+ for (z=0; z<StopfZahl; z++)
+ BEGIN
+ switch (ActListGran)
+ BEGIN
+ case 4:DAsmCode[CodeLen>>2]=NOPCode; break;
+ case 2:WAsmCode[CodeLen>>1]=NOPCode; break;
+ case 1:BAsmCode[CodeLen ]=NOPCode; break;
+ END
+ CodeLen+=ActListGran/Granularity();
+ END
+
+ if ((ActPC!=StructSeg) AND (NOT ChkPC(PCs[ActPC]+CodeLen-1)) AND (CodeLen!=0))
+ WrError(1925);
+ else
+ BEGIN
+ if ((NOT DontPrint) AND (ActPC!=StructSeg) AND (CodeLen>0)) BookKeeping();
+ if (ActPC==StructSeg)
+ BEGIN
+ if ((CodeLen!=0) AND (NOT DontPrint)) WrError(1940);
+ END
+ else if (CodeOutput)
+ BEGIN
+ if (DontPrint) NewRecord(PCs[ActPC]+CodeLen);
+ else WriteBytes();
+ END
+ PCs[ActPC]+=CodeLen;
+ END
+ END
+
+ /* dies ueberprueft implizit, ob von der letzten Eval...-Operation noch
+ externe Referenzen liegengeblieben sind. */
+
+ SetRelocs(Nil);
+END
+
+/*--- Zeile in Listing zerteilen -------------------------------------------*/
+
+ static void SplitLine(void)
+BEGIN
+ jmp_buf Retry;
+ String h;
+ char *i,*k,*p,*div,*run;
+ int l;
+ Boolean lpos;
+
+ Retracted=False;
+
+ /* Kommentar loeschen */
+
+ strmaxcpy(h,OneLine,255); i=QuotPos(h,';');
+ if (i!=Nil)
+ BEGIN
+ strcpy(CommPart,i+1);
+ *i='\0';
+ END
+ else *CommPart='\0';
+
+ /* alles in Grossbuchstaben wandeln, Praeprozessor laufen lassen */
+
+ ExpandDefines(h);
+
+ /* Label abspalten */
+
+ if ((*h!='\0') AND (NOT isspace((unsigned char)*h)))
+ BEGIN
+ for (i=h; *i!='\0'; i++)
+ if ((isspace(((unsigned char)*i)&0xff)) OR (*i==':')) break;
+ if (*i=='\0')
+ BEGIN
+ strcpy(LabPart,h); *h='\0';
+ END
+ else
+ BEGIN
+ *i='\0'; strcpy(LabPart,h); strcpy(h,i+1);
+ END
+ if (LabPart[l=(strlen(LabPart)-1)]==':') LabPart[l]='\0';
+ END
+ else *LabPart='\0';
+
+ /* Opcode & Argument trennen */
+ setjmp(Retry);
+ KillPrefBlanks(h);
+ i=FirstBlank(h);
+ SplitString(h,OpPart,ArgPart,i);
+
+ /* Falls noch kein Label da war, kann es auch ein Label sein */
+
+ i=strchr(OpPart,':');
+ if ((*LabPart=='\0') AND (i!=Nil) AND (i[1]=='\0'))
+ BEGIN
+ *i='\0'; strcpy(LabPart,OpPart); strcpy(OpPart,i+1);
+ if (*OpPart=='\0')
+ BEGIN
+ strcpy(h,ArgPart);
+ longjmp(Retry,1);
+ END
+ END
+
+ /* Attribut abspalten */
+
+ if (HasAttrs)
+ BEGIN
+ k=Nil; AttrSplit=' ';
+ for (run=AttrChars; *run!='\0'; run++)
+ BEGIN
+ p=strchr(OpPart,*run);
+ if (p!=Nil) if ((k==Nil) OR (p<k)) k=p;
+ END
+ if (k!=Nil)
+ BEGIN
+ AttrSplit=(*k);
+ strmaxcpy(AttrPart,k+1,255); *k='\0';
+ if ((*OpPart=='\0') AND (*AttrPart!='\0'))
+ BEGIN
+ strmaxcpy(OpPart,AttrPart,255); *AttrPart='\0';
+ END
+ END
+ else *AttrPart='\0';
+ END
+ else *AttrPart='\0';
+
+ KillPostBlanks(ArgPart);
+
+ /* Argumente zerteilen: Da alles aus einem String kommt und die Teile alle auch
+ so lang sind, koennen wir uns Laengenabfragen sparen */
+ ArgCnt=0; strcpy(h,ArgPart); run=h;
+ if (*run!='\0')
+ do
+ BEGIN
+ while ((*run!='\0') AND (isspace((unsigned char)*run))) run++;
+ i=Nil;
+ for (div=DivideChars; *div!='\0'; div++)
+ BEGIN
+ p=QuotPos(run,*div);
+ if (p!=Nil) if ((i==Nil) OR (p<i)) i=p;
+ END
+ lpos=((i!=Nil) AND (i[1]=='\0'));
+ if (i!=Nil) *i='\0';
+ strcpy(ArgStr[++ArgCnt],run);
+ if ((lpos) AND (ArgCnt!=ParMax)) *ArgStr[++ArgCnt]='\0';
+ KillPostBlanks(ArgStr[ArgCnt]);
+ run=(i==Nil) ? i : i+1;
+ END
+ while ((run!=Nil) AND (ArgCnt!=ParMax) AND (NOT lpos));
+
+ if ((run!=Nil) AND (*run!='\0')) WrError(1140);
+
+ Produce_Code();
+END
+
+/**
+CONST
+ LineBuffer:String='';
+ InComment:Boolean=FALSE;
+
+ static void C_SplitLine(void)
+BEGIN
+ p,p2:int;
+ SaveLine,h:String;
+
+ { alten Inhalt sichern }
+
+ SaveLine:=OneLine; h:=OneLine;
+
+ { Falls in Kommentar, nach schliessender Klammer suchen und den Teil bis
+ dahin verwerfen; falls keine Klammer drin ist, die ganze Zeile weg-
+ schmeissen; da wir dann OneLine bisher noch nicht veraendert hatten,
+ stoert der Abbruch ohne Wiederherstellung von Oneline nicht. }
+
+ IF InComment THEN
+ BEGIN
+ p:=Pos('}',h);
+ IF p>Length(h) THEN Exit
+ ELSE
+ BEGIN
+ Delete(h,1,p); InComment:=False;
+ END;
+ END;
+
+ { in der Zeile befindliche Teile loeschen; falls am Ende keine
+ schliessende Klammer kommt, muessen wir das Kommentarflag setzen. }
+
+ REPEAT
+ p:=QuotPos(h,'{');
+ IF p>Length(h) THEN p:=0
+ ELSE
+ BEGIN
+ p2:=QuotPos(h,'}');
+ IF (p2>p) AND (Length(h)>=p2) THEN Delete(h,p,p2-p+1)
+ ELSE
+ BEGIN
+ Byte(h[0]):=Pred(p);
+ InComment:=True;
+ p:=0;
+ END;
+ END;
+ UNTIL p=0;
+
+ { alten Inhalt zurueckkopieren }
+
+ OneLine:=SaveLine;
+END;**/
+
+/*------------------------------------------------------------------------*/
+
+ static void ProcessFile(String FileName)
+BEGIN
+ long NxtTime,ListTime;
+ String Num;
+ char *Name, *Run;
+
+ dbgentry("ProcessFile");
+
+ sprintf(OneLine," INCLUDE \"%s\"",FileName); MasterFile=False;
+ NextIncDepth=IncDepth;
+ SplitLine();
+ IncDepth=NextIncDepth;
+
+ ListTime=GTime();
+
+ while ((NOT InputEnd()) AND (NOT ENDOccured))
+ BEGIN
+ /* Zeile lesen */
+
+ GetNextLine(OneLine);
+
+ /* Ergebnisfelder vorinitialisieren */
+
+ DontPrint=False; CodeLen=0; *ListLine='\0';
+
+ NextDoLst=DoLst;
+ NextIncDepth=IncDepth;
+
+ for (Run=OneLine; *Run!='\0'; Run++)
+ if (NOT isspace(((unsigned int)*Run)&0xff)) break;
+ if (*Run=='#') Preprocess();
+ else SplitLine();
+
+ MakeList();
+ DoLst=NextDoLst;
+ IncDepth=NextIncDepth;
+
+ /* Zeilenzaehler */
+
+ if (NOT QuietMode)
+ BEGIN
+ NxtTime=GTime();
+ if (((NOT ListToStdout) OR ((ListMask&1)==0)) AND (DTime(ListTime,NxtTime)>50))
+ BEGIN
+ sprintf(Num,LongIntFormat,MomLineCounter); Name=NamePart(CurrFileName);
+ printf("%s(%s)%s",Name,Num,ClrEol);
+ /*for (z=0; z<strlen(Name)+strlen(Num)+2; z++) putchar('\b');*/
+ putchar('\r'); fflush(stdout);
+ ListTime=NxtTime;
+ END
+ END
+
+ /* bei Ende Makroprozessor ausraeumen
+ OK - das ist eine Hauruckmethode... */
+
+ if (ENDOccured)
+ while (FirstInputTag!=Nil) GetNextLine(OneLine);
+ END
+
+ while (FirstInputTag!=Nil) GetNextLine(OneLine);
+
+ /* irgendeine Makrodefinition nicht abgeschlossen ? */
+
+ if (FirstOutputTag!=Nil) WrError(1800);
+
+ dbgexit("ProcessFile");
+END
+
+/****************************************************************************/
+
+ static char *TWrite_Plur(int n)
+BEGIN
+ return (n!=1) ? getmessage(Num_ListPlurName) : "";
+END
+
+ static void TWrite_RWrite(char *dest, Double r, Byte Stellen)
+BEGIN
+ String s;
+
+ sprintf(s,"%20.*f",Stellen,r);
+ while (*s==' ') strcpy(s,s+1); strcat(dest,s);
+END
+
+ static void TWrite(Double DTime, char *dest)
+BEGIN
+ int h;
+ String s;
+
+ *dest='\0';
+ h=(int) floor(DTime/3600.0);
+ if (h>0)
+ BEGIN
+ sprintf(s,"%d",h);
+ strcat(dest,s);
+ strcat(dest,getmessage(Num_ListHourName));
+ strcat(dest,TWrite_Plur(h));
+ strcat(dest,", ");
+ DTime-=3600.0*h;
+ END
+ h=(int) floor(DTime/60.0);
+ if (h>0)
+ BEGIN
+ sprintf(s,"%d",h);
+ strcat(dest,s);
+ strcat(dest,getmessage(Num_ListMinuName));
+ strcat(dest,TWrite_Plur(h));
+ strcat(dest,", ");
+ DTime-=60.0*h;
+ END
+ TWrite_RWrite(dest,DTime,2); strcat(dest,getmessage(Num_ListSecoName));
+ if (DTime!=1) strcat(dest,getmessage(Num_ListPlurName));
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void AssembleFile_InitPass(void)
+BEGIN
+ static char DateS[31],TimeS[31];
+ int z;
+ String ArchVal;
+
+ dbgentry("AssembleFile_InitPass");
+
+ FirstInputTag=Nil; FirstOutputTag=Nil;
+
+ MomLineCounter=0; MomLocHandle=(-1); LocHandleCnt=0;
+
+ SectionStack=Nil;
+ FirstIfSave=Nil;
+ FirstSaveState=Nil;
+ StructureStack=Nil;
+
+ InitPassProc();
+
+ ActPC=SegCode; PCs[ActPC]=0; ENDOccured=False;
+ ErrorCount=0; WarnCount=0; LineSum=0; MacLineSum=0;
+ for (z=1; z<=StructSeg; z++)
+ BEGIN
+ PCsUsed[z]=(z==SegCode);
+ Phases[z]=0;
+ InitChunk(&SegChunks[z]);
+ END
+
+ TransTables=CurrTransTable=(PTransTable) malloc(sizeof(TTransTable));
+ CurrTransTable->Next=Nil;
+ CurrTransTable->Name=strdup("STANDARD");
+ CurrTransTable->Table=(unsigned char *) malloc(256*sizeof(char));
+ for (z=0; z<256; z++) CurrTransTable->Table[z]=z;
+
+ strmaxcpy(CurrFileName,"INTERNAL",255);
+ AddFile(CurrFileName); CurrLine=0;
+
+ IncDepth=(-1);
+ DoLst=True;
+
+ /* Pseudovariablen initialisieren */
+
+ ResetSymbolDefines(); ResetMacroDefines();
+ EnterIntSymbol(FlagTrueName,1,0,True);
+ EnterIntSymbol(FlagFalseName,0,0,True);
+ EnterFloatSymbol(PiName,4.0*atan(1.0),True);
+ EnterIntSymbol(VerName,VerNo,0,True);
+ sprintf(ArchVal,"%s-%s",ARCHPRNAME,ARCHSYSNAME);
+ EnterStringSymbol(ArchName,ArchVal,True);
+#ifdef HAS64
+ EnterIntSymbol(Has64Name,1,0,True);
+#else
+ EnterIntSymbol(Has64Name,0,0,True);
+#endif
+ EnterIntSymbol(CaseSensName,Ord(CaseSensitive),0,True);
+ if (PassNo==0)
+ BEGIN
+ NLS_CurrDateString(DateS);
+ NLS_CurrTimeString(False,TimeS);
+ END
+ EnterStringSymbol(DateName,DateS,True);
+ EnterStringSymbol(TimeName,TimeS,True);
+
+ if (*DefCPU == '\0')
+ SetCPU(0, True);
+ else
+ if (NOT SetNCPU(DefCPU, True)) SetCPU(0, True);
+
+ SetFlag(&SupAllowed,SupAllowedName,False);
+ SetFlag(&FPUAvail,FPUAvailName,False);
+ SetFlag(&DoPadding,DoPaddingName,True);
+ SetFlag(&Maximum,MaximumName,False);
+ SetFlag(&DoBranchExt,BranchExtName,False);
+ EnterIntSymbol(ListOnName,ListOn=1,0,True);
+ SetFlag(&LstMacroEx,LstMacroExName,True);
+ SetFlag(&RelaxedMode,RelaxedName,False);
+ CopyDefSymbols();
+
+ ResetPageCounter();
+
+ StartAdrPresent=False;
+
+ Repass=False; PassNo++;
+
+ dbgexit("AssembleFile_InitPass");
+END
+
+ static void AssembleFile_ExitPass(void)
+BEGIN
+ SwitchFrom();
+ ClearLocStack();
+ ClearStacks();
+ TossRegDefs(-1);
+ if (FirstIfSave!=Nil) WrError(1470);
+ if (FirstSaveState!=Nil) WrError(1460);
+ if (SectionStack!=Nil) WrError(1485);
+ if (StructureStack!=Nil) WrXError(1551,StructureStack->Name);
+END
+
+ static void AssembleFile(char *Name)
+BEGIN
+ String s,Tmp;
+
+ dbgentry("AssembleFile");
+
+ strmaxcpy(SourceFile,Name,255);
+ if (MakeDebug) fprintf(Debug,"File %s\n",SourceFile);
+
+ /* Untermodule initialisieren */
+
+ AsmDefInit(); AsmParsInit(); AsmIFInit(); InitFileList(); ResetStack();
+
+ /* Kommandozeilenoptionen verarbeiten */
+
+ strmaxcpy(OutName,GetFromOutList(),255);
+ if (OutName[0]=='\0')
+ BEGIN
+ strmaxcpy(OutName,SourceFile,255); KillSuffix(OutName);
+ AddSuffix(OutName,PrgSuffix);
+ END
+
+ if (*ErrorPath=='\0')
+ BEGIN
+ strmaxcpy(ErrorName,SourceFile,255);
+ KillSuffix(ErrorName);
+ AddSuffix(ErrorName,LogSuffix);
+ unlink(ErrorName);
+ END
+
+ switch (ListMode)
+ BEGIN
+ case 0: strmaxcpy(LstName,NULLDEV,255); break;
+ case 1: strmaxcpy(LstName,"!1",255); break;
+ case 2:
+ strmaxcpy(LstName,SourceFile,255);
+ KillSuffix(LstName);
+ AddSuffix(LstName,LstSuffix);
+ break;
+ END
+ ListToStdout=(strcmp(LstName,"!1")==0);
+ ListToNull=(strcmp(LstName,NULLDEV)==0);
+
+ if (ShareMode!=0)
+ BEGIN
+ strmaxcpy(ShareName,GetFromShareOutList(),255);
+ if (*ShareName == '\0')
+ BEGIN
+ strmaxcpy(ShareName,SourceFile,255);
+ KillSuffix(ShareName);
+ switch (ShareMode)
+ BEGIN
+ case 1: AddSuffix(ShareName,".inc"); break;
+ case 2: AddSuffix(ShareName,".h"); break;
+ case 3: AddSuffix(ShareName,IncSuffix); break;
+ END
+ END
+ END
+
+ if (MacProOutput)
+ BEGIN
+ strmaxcpy(MacProName,SourceFile,255); KillSuffix(MacProName);
+ AddSuffix(MacProName,PreSuffix);
+ END
+
+ if (MacroOutput)
+ BEGIN
+ strmaxcpy(MacroName,SourceFile,255); KillSuffix(MacroName);
+ AddSuffix(MacroName,MacSuffix);
+ END
+
+ ClearIncludeList();
+
+ if (DebugMode!=DebugNone) InitLineInfo();
+
+ /* Variablen initialisieren */
+
+ StartTime=GTime();
+
+ PassNo=0; MomLineCounter=0;
+
+ /* Listdatei eroeffnen */
+
+ if (NOT QuietMode) printf("%s%s\n",getmessage(Num_InfoMessAssembling),SourceFile);
+
+ do
+ BEGIN
+ /* Durchlauf initialisieren */
+
+ AssembleFile_InitPass(); AsmSubInit();
+ if (NOT QuietMode)
+ BEGIN
+ sprintf(Tmp,IntegerFormat,PassNo);
+ printf("%s%s%s\n",getmessage(Num_InfoMessPass),Tmp,ClrEol);
+ END
+
+ /* Dateien oeffnen */
+
+ if (CodeOutput) OpenFile();
+
+ if (ShareMode!=0)
+ BEGIN
+ ShareFile=fopen(ShareName,"w");
+ if (ShareFile==Nil) ChkIO(10001);
+ errno=0;
+ switch (ShareMode)
+ BEGIN
+ case 1:fprintf(ShareFile,"(* %s-Includefile f%sr CONST-Sektion *)\n",SourceFile,CH_ue); break;
+ case 2:fprintf(ShareFile,"/* %s-Includefile f%sr C-Programm */\n",SourceFile,CH_ue); break;
+ case 3:fprintf(ShareFile,"; %s-Includefile f%sr Assembler-Programm\n",SourceFile,CH_ue); break;
+ END
+ ChkIO(10002);
+ END
+
+ if (MacProOutput)
+ BEGIN
+ MacProFile=fopen(MacProName,"w");
+ if (MacProFile==Nil) ChkIO(10001);
+ END
+
+ if ((MacroOutput) AND (PassNo==1))
+ BEGIN
+ MacroFile=fopen(MacroName,"w");
+ if (MacroFile==Nil) ChkIO(10001);
+ END
+
+ /* Listdatei oeffnen */
+
+ RewriteStandard(&LstFile,LstName);
+ if (LstFile==Nil) ChkIO(10001);
+ errno=0; fprintf(LstFile,"%s",PrtInitString); ChkIO(10002);
+ if ((ListMask&1)!=0) NewPage(0,False);
+
+ /* assemblieren */
+
+ ProcessFile(SourceFile);
+ AssembleFile_ExitPass();
+
+ /* Dateien schliessen */
+
+ if (CodeOutput) CloseFile();
+
+ if (ShareMode!=0)
+ BEGIN
+ errno=0;
+ switch (ShareMode)
+ BEGIN
+ case 1: fprintf(ShareFile,"(* Ende Includefile f%sr CONST-Sektion *)\n",CH_ue); break;
+ case 2: fprintf(ShareFile,"/* Ende Includefile f%sr C-Programm */\n",CH_ue); break;
+ case 3: fprintf(ShareFile,"; Ende Includefile f%sr Assembler-Programm\n",CH_ue); break;
+ END
+ ChkIO(10002);
+ fclose(ShareFile);
+ END
+
+ if (MacProOutput) fclose(MacProFile);
+ if ((MacroOutput) AND (PassNo==1)) fclose(MacroFile);
+
+ /* evtl. fuer naechsten Durchlauf aufraeumen */
+
+ if ((ErrorCount==0) AND (Repass))
+ BEGIN
+ fclose(LstFile);
+ if (CodeOutput) unlink(OutName);
+ CleanupRegDefs();
+ ClearCodepages();
+ if (MakeUseList) ClearUseList();
+ if (MakeCrossList) ClearCrossList();
+ ClearDefineList();
+ if (DebugMode!=DebugNone) ClearLineInfo();
+ ClearIncludeList();
+ if (DebugMode!=DebugNone) ResetAddressRanges();
+ END
+ END
+ while ((ErrorCount==0) AND (Repass));
+
+ /* bei Fehlern loeschen */
+
+ if (ErrorCount!=0)
+ BEGIN
+ if (CodeOutput) unlink(OutName);
+ if (MacProOutput) unlink(MacProName);
+ if ((MacroOutput) AND (PassNo==1)) unlink(MacroName);
+ if (ShareMode!=0) unlink(ShareName);
+ GlobErrFlag=True;
+ END
+
+ /* Debug-Ausgabe muss VOR die Symbollistenausgabe, weil letztere die
+ Symbolliste loescht */
+
+ if (DebugMode!=DebugNone)
+ BEGIN
+ if (ErrorCount==0) DumpDebugInfo();
+ ClearLineInfo();
+ END
+
+ /* Listdatei abschliessen */
+
+ if (strcmp(LstName,NULLDEV)!=0)
+ BEGIN
+ if ((ListMask&2)!=0) PrintSymbolList();
+
+ if ((ListMask&64)!=0) PrintRegDefs();
+
+ if ((ListMask&4)!=0) PrintMacroList();
+
+ if ((ListMask&8)!=0) PrintFunctionList();
+
+ if ((ListMask&32)!=0) PrintDefineList();
+
+ if ((ListMask&128)!=0) PrintCodepages();
+
+ if (MakeUseList)
+ BEGIN
+ NewPage(ChapDepth,True);
+ PrintUseList();
+ END
+
+ if (MakeCrossList)
+ BEGIN
+ NewPage(ChapDepth,True);
+ PrintCrossList();
+ END
+
+ if (MakeSectionList) PrintSectionList();
+
+ if (MakeIncludeList) PrintIncludeList();
+
+ errno=0; fprintf(LstFile,"%s",PrtExitString); ChkIO(10002);
+ END
+
+ if (MakeUseList) ClearUseList();
+
+ if (MakeCrossList) ClearCrossList();
+
+ ClearSectionList();
+
+ ClearIncludeList();
+
+ if ((*ErrorPath=='\0') AND (IsErrorOpen))
+ BEGIN
+ fclose(ErrorFile); IsErrorOpen=False;
+ END
+
+ ClearUpProc();
+
+ /* Statistik ausgeben */
+
+ StopTime=GTime();
+ TWrite(DTime(StartTime,StopTime)/100.0,s);
+ if (NOT QuietMode) printf("\n%s%s%s\n\n",s,getmessage(Num_InfoMessAssTime),ClrEol);
+ if (ListMode==2)
+ BEGIN
+ WrLstLine("");
+ strmaxcat(s,getmessage(Num_InfoMessAssTime),255); WrLstLine(s);
+ WrLstLine("");
+ END
+
+ strcpy(s,Dec32BlankString(LineSum,7));
+ strmaxcat(s,getmessage((LineSum==1)?Num_InfoMessAssLine:Num_InfoMessAssLines),255);
+ if (NOT QuietMode) printf("%s%s\n",s,ClrEol);
+ if (ListMode==2) WrLstLine(s);
+
+ if (LineSum!=MacLineSum)
+ BEGIN
+ strcpy(s,Dec32BlankString(MacLineSum,7));
+ strmaxcat(s,getmessage((MacLineSum==1)?Num_InfoMessMacAssLine:Num_InfoMessMacAssLines),255);
+ if (NOT QuietMode) printf("%s%s\n",s,ClrEol);
+ if (ListMode==2) WrLstLine(s);
+ END
+
+ strcpy(s,Dec32BlankString(PassNo,7));
+ strmaxcat(s,getmessage((PassNo==1)?Num_InfoMessPassCnt:Num_InfoMessPPassCnt),255);
+ if (NOT QuietMode) printf("%s%s\n",s,ClrEol);
+ if (ListMode==2) WrLstLine(s);
+
+ if ((ErrorCount>0) AND (Repass) AND (ListMode!=0))
+ WrLstLine(getmessage(Num_InfoMessNoPass));
+
+#ifdef __TURBOC__
+ sprintf(s,"%s%s",Dec32BlankString(coreleft()>>10,7),getmessage(Num_InfoMessRemainMem));
+ if (NOT QuietMode) printf("%s%s\n",s,ClrEol);
+ if (ListMode==2) WrLstLine(s);
+
+ sprintf(s,"%s%s",Dec32BlankString(StackRes(),7),getmessage(Num_InfoMessRemainStack));
+ if (NOT QuietMode) printf("%s%s\n",s,ClrEol);
+ if (ListMode==2) WrLstLine(s);
+#endif
+
+ sprintf(s,"%s%s",Dec32BlankString(ErrorCount,7),getmessage(Num_InfoMessErrCnt));
+ if (ErrorCount!=1) strmaxcat(s,getmessage(Num_InfoMessErrPCnt),255);
+ if (NOT QuietMode) printf("%s%s\n",s,ClrEol);
+ if (ListMode==2) WrLstLine(s);
+
+ sprintf(s,"%s%s",Dec32BlankString(WarnCount,7),getmessage(Num_InfoMessWarnCnt));
+ if (WarnCount!=1) strmaxcat(s,getmessage(Num_InfoMessWarnPCnt),255);
+ if (NOT QuietMode) printf("%s%s\n",s,ClrEol);
+ if (ListMode==2) WrLstLine(s);
+
+ fclose(LstFile);
+
+ /* verstecktes */
+
+ if (MakeDebug) PrintSymbolDepth();
+
+ /* Speicher freigeben */
+
+ ClearSymbolList();
+ ClearRegDefs();
+ ClearCodepages();
+ ClearMacroList();
+ ClearFunctionList();
+ ClearDefineList();
+ ClearFileList();
+
+ dbgentry("AssembleFile");
+END
+
+ static void AssembleGroup(void)
+BEGIN
+ AddSuffix(FileMask,SrcSuffix);
+ if (NOT DirScan(FileMask,AssembleFile))
+ fprintf(stderr,"%s%s\n",FileMask,getmessage(Num_InfoMessNFilesFound));
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static CMDResult CMD_SharePascal(Boolean Negate, char *Arg)
+BEGIN
+ if (NOT Negate) ShareMode=1;
+ else if (ShareMode==1) ShareMode=0;
+ return CMDOK;
+END
+
+ static CMDResult CMD_ShareC(Boolean Negate, char *Arg)
+BEGIN
+ if (NOT Negate) ShareMode=2;
+ else if (ShareMode==2) ShareMode=0;
+ return CMDOK;
+END
+
+ static CMDResult CMD_ShareAssembler(Boolean Negate, char *Arg)
+BEGIN
+ if (NOT Negate) ShareMode=3;
+ else if (ShareMode==3) ShareMode=0;
+ return CMDOK;
+END
+
+ static CMDResult CMD_DebugMode(Boolean Negate, char *Arg)
+BEGIN
+ UpString(Arg);
+
+ if (Negate)
+ if (Arg[0]!='\0') return CMDErr;
+ else
+ BEGIN
+ DebugMode=DebugNone; return CMDOK;
+ END
+ else if (strcmp(Arg,"")==0)
+ BEGIN
+ DebugMode=DebugMAP; return CMDOK;
+ END
+ else if (strcmp(Arg,"ATMEL")==0)
+ BEGIN
+ DebugMode=DebugAtmel; return CMDArg;
+ END
+ else if (strcmp(Arg,"MAP")==0)
+ BEGIN
+ DebugMode=DebugMAP; return CMDArg;
+ END
+ else if (strcmp(Arg,"NOICE")==0)
+ BEGIN
+ DebugMode=DebugNoICE; return CMDArg;
+ END
+ /*else if (strcmp(Arg,"A.OUT")==0)
+ BEGIN
+ DebugMode=DebugAOUT; return CMDArg;
+ END
+ else if (strcmp(Arg,"COFF")==0)
+ BEGIN
+ DebugMode=DebugCOFF; return CMDArg;
+ END
+ else if (strcmp(Arg,"ELF")==0)
+ BEGIN
+ DebugMode=DebugELF; return CMDArg;
+ END*/
+ else return CMDErr;
+
+/* if (Negate) DebugMode=DebugNone;
+ else DebugMode=DebugMAP;
+ return CMDOK;*/
+END
+
+ static CMDResult CMD_ListConsole(Boolean Negate, char *Arg)
+BEGIN
+ if (NOT Negate) ListMode=1;
+ else if (ListMode==1) ListMode=0;
+ return CMDOK;
+END
+
+ static CMDResult CMD_ListFile(Boolean Negate, char *Arg)
+BEGIN
+ if (NOT Negate) ListMode=2;
+ else if (ListMode==2) ListMode=0;
+ return CMDOK;
+END
+
+ static CMDResult CMD_SuppWarns(Boolean Negate, char *Arg)
+BEGIN
+ SuppWarns=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_UseList(Boolean Negate, char *Arg)
+BEGIN
+ MakeUseList=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_CrossList(Boolean Negate, char *Arg)
+BEGIN
+ MakeCrossList=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_SectionList(Boolean Negate, char *Arg)
+BEGIN
+ MakeSectionList=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_BalanceTree(Boolean Negate, char *Arg)
+BEGIN
+ BalanceTree=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_MakeDebug(Boolean Negate, char *Arg)
+BEGIN
+ if (NOT Negate)
+ BEGIN
+ MakeDebug=True;
+ errno=0; Debug=fopen("as.deb","w");
+ if (Debug==Nil) ChkIO(10002);
+ END
+ else if (MakeDebug)
+ BEGIN
+ MakeDebug=False;
+ fclose(Debug);
+ END
+ return CMDOK;
+END
+
+ static CMDResult CMD_MacProOutput(Boolean Negate, char *Arg)
+BEGIN
+ MacProOutput=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_MacroOutput(Boolean Negate, char *Arg)
+BEGIN
+ MacroOutput=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_MakeIncludeList(Boolean Negate, char *Arg)
+BEGIN
+ MakeIncludeList=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_CodeOutput(Boolean Negate, char *Arg)
+BEGIN
+ CodeOutput=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_MsgIfRepass(Boolean Negate, String Arg)
+BEGIN
+ Boolean OK;
+
+ MsgIfRepass=NOT Negate;
+ if (MsgIfRepass)
+ if (Arg[0]=='\0')
+ BEGIN
+ PassNoForMessage=1; return CMDOK;
+ END
+ else
+ BEGIN
+ PassNoForMessage=ConstLongInt(Arg,&OK);
+ if (NOT OK)
+ BEGIN
+ PassNoForMessage=1; return CMDOK;
+ END
+ else if (PassNoForMessage<1) return CMDErr;
+ else return CMDArg;
+ END
+ else return CMDOK;
+END
+
+ static CMDResult CMD_ExtendErrors(Boolean Negate, char *Arg)
+BEGIN
+ if ((Negate) AND (ExtendErrors > 0))
+ ExtendErrors--;
+ else if ((NOT Negate) AND (ExtendErrors < 2))
+ ExtendErrors++;
+
+ return CMDOK;
+END
+
+ static CMDResult CMD_NumericErrors(Boolean Negate, char *Arg)
+BEGIN
+ NumericErrors=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_HexLowerCase(Boolean Negate, char *Arg)
+BEGIN
+ HexLowerCase=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_QuietMode(Boolean Negate, char *Arg)
+BEGIN
+ QuietMode=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_ThrowErrors(Boolean Negate, char *Arg)
+BEGIN
+ ThrowErrors=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_CaseSensitive(Boolean Negate, char *Arg)
+BEGIN
+ CaseSensitive=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_IncludeList(Boolean Negate, char *Arg)
+BEGIN
+ char *p;
+ String Copy,part;
+
+ if (*Arg=='\0') return CMDErr;
+ else
+ BEGIN
+ strncpy(Copy,Arg,255);
+ do
+ BEGIN
+ p=strrchr(Copy,DIRSEP);
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(part,Copy,255);
+ *Copy='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(part,p+1,255);
+ END
+ if (Negate) RemoveIncludeList(part); else AddIncludeList(part);
+ END
+ while (Copy[0]!='\0');
+ return CMDArg;
+ END
+END
+
+ static CMDResult CMD_ListMask(Boolean Negate, char *Arg)
+BEGIN
+ Byte erg;
+ Boolean OK;
+
+ if (Arg[0]=='\0') return CMDErr;
+ else
+ BEGIN
+ erg=ConstLongInt(Arg,&OK);
+ if ((NOT OK) OR (erg>31)) return CMDErr;
+ else
+ BEGIN
+ if (Negate) ListMask&=(~erg);
+ else ListMask|=erg;
+ return CMDArg;
+ END
+ END
+END
+
+ static CMDResult CMD_DefSymbol(Boolean Negate, char *Arg)
+BEGIN
+ String Copy,Part,Name;
+ char *p;
+ TempResult t;
+
+ if (Arg[0]=='\0') return CMDErr;
+
+ strmaxcpy(Copy,Arg,255);
+ do
+ BEGIN
+ p=QuotPos(Copy,',');
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Part,Copy,255); Copy[0]='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(Part,Copy,255); strcpy(Copy,p+1);
+ END
+ UpString(Part);
+ p=QuotPos(Part,'=');
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Name,Part,255); Part[0]='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(Name,Part,255); strcpy(Part,p+1);
+ END
+ if (NOT ChkSymbName(Name)) return CMDErr;
+ if (Negate) RemoveDefSymbol(Name);
+ else
+ BEGIN
+ AsmParsInit();
+ if (Part[0]!='\0')
+ BEGIN
+ FirstPassUnknown=False;
+ EvalExpression(Part,&t);
+ if ((t.Typ==TempNone) OR (FirstPassUnknown)) return CMDErr;
+ END
+ else
+ BEGIN
+ t.Typ=TempInt; t.Contents.Int=1;
+ END
+ AddDefSymbol(Name,&t);
+ END
+ END
+ while (Copy[0]!='\0');
+
+ return CMDArg;
+END
+
+ static CMDResult CMD_ErrorPath(Boolean Negate, String Arg)
+BEGIN
+ if (Negate) return CMDErr;
+ else if (Arg[0]=='\0')
+ BEGIN
+ ErrorPath[0]='\0'; return CMDOK;
+ END
+ else
+ BEGIN
+ strncpy(ErrorPath,Arg,255); return CMDArg;
+ END
+END
+
+ static CMDResult CMD_HardRanges(Boolean Negate, char *Arg)
+BEGIN
+ HardRanges=Negate; return CMDOK;
+END
+
+ static CMDResult CMD_OutFile(Boolean Negate, char *Arg)
+BEGIN
+ if (Arg[0]=='\0')
+ if (Negate)
+ BEGIN
+ ClearOutList(); return CMDOK;
+ END
+ else return CMDErr;
+ else
+ BEGIN
+ if (Negate) RemoveFromOutList(Arg);
+ else AddToOutList(Arg);
+ return CMDArg;
+ END
+END
+
+ static CMDResult CMD_ShareOutFile(Boolean Negate, char *Arg)
+BEGIN
+ if (Arg[0]=='\0')
+ if (Negate)
+ BEGIN
+ ClearShareOutList(); return CMDOK;
+ END
+ else return CMDErr;
+ else
+ BEGIN
+ if (Negate) RemoveFromShareOutList(Arg);
+ else AddToShareOutList(Arg);
+ return CMDArg;
+ END
+END
+
+
+ static Boolean CMD_CPUAlias_ChkCPUName(char *s)
+BEGIN
+ int z;
+
+ for(z=0; z<strlen(s); z++)
+ if (NOT isalnum((unsigned int) s[z])) return False;
+ return True;
+END
+
+ static CMDResult CMD_CPUAlias(Boolean Negate, char *Arg)
+BEGIN
+ char *p;
+ String s1,s2;
+
+ if (Negate) return CMDErr;
+ else if (Arg[0]=='\0') return CMDErr;
+ else
+ BEGIN
+ p=strchr(Arg,'=');
+ if (p==Nil) return CMDErr;
+ else
+ BEGIN
+ *p='\0';
+ strmaxcpy(s1,Arg,255); UpString(s1);
+ strmaxcpy(s2,p+1,255); UpString(s2);
+ *p='=';
+ if (NOT (CMD_CPUAlias_ChkCPUName(s1) AND CMD_CPUAlias_ChkCPUName(s2)))
+ return CMDErr;
+ else if (NOT AddCPUAlias(s2,s1)) return CMDErr;
+ else return CMDArg;
+ END
+ END
+END
+
+ static CMDResult CMD_SetCPU(Boolean Negate, char *Arg)
+BEGIN
+ if (Negate)
+ BEGIN
+ *DefCPU = '\0';
+ return CMDOK;
+ END
+ else
+ BEGIN
+ if (*Arg == '\0') return CMDErr;
+ strmaxcpy(DefCPU, Arg, sizeof(DefCPU) - 1);
+ NLS_UpString(DefCPU);
+ return CMDArg;
+ END
+END
+
+ static void ParamError(Boolean InEnv, char *Arg)
+BEGIN
+ printf("%s%s\n",getmessage((InEnv) ? Num_ErrMsgInvEnvParam : Num_ErrMsgInvParam),Arg);
+ exit(4);
+END
+
+#define ASParamCnt 33
+static CMDRec ASParams[ASParamCnt]=
+ {{"A" , CMD_BalanceTree},
+ {"ALIAS", CMD_CPUAlias},
+ {"a" , CMD_ShareAssembler},
+ {"C" , CMD_CrossList},
+ {"c" , CMD_ShareC},
+ {"CPU" , CMD_SetCPU},
+ {"D" , CMD_DefSymbol},
+ {"E" , CMD_ErrorPath},
+ {"g" , CMD_DebugMode},
+ {"G" , CMD_CodeOutput},
+ {"h" , CMD_HexLowerCase},
+ {"i" , CMD_IncludeList},
+ {"I" , CMD_MakeIncludeList},
+ {"L" , CMD_ListFile},
+ {"l" , CMD_ListConsole},
+ {"M" , CMD_MacroOutput},
+ {"n" , CMD_NumericErrors},
+ {"o" , CMD_OutFile},
+ {"P" , CMD_MacProOutput},
+ {"p" , CMD_SharePascal},
+ {"q" , CMD_QuietMode},
+ {"QUIET", CMD_QuietMode},
+ {"r" , CMD_MsgIfRepass},
+ {"s" , CMD_SectionList},
+ {"SHAREOUT", CMD_ShareOutFile},
+ {"t" , CMD_ListMask},
+ {"u" , CMD_UseList},
+ {"U" , CMD_CaseSensitive},
+ {"w" , CMD_SuppWarns},
+ {"WARNRANGES", CMD_HardRanges},
+ {"x" , CMD_ExtendErrors},
+ {"X" , CMD_MakeDebug},
+ {"Y" , CMD_ThrowErrors}};
+
+/*--------------------------------------------------------------------------*/
+
+
+
+#ifdef __sunos__
+
+ extern void on_exit(void (*procp)(int status, caddr_t arg),caddr_t arg);
+
+ static void GlobExitProc(int status, caddr_t arg)
+BEGIN
+ if (MakeDebug) fclose(Debug);
+END
+
+#else
+
+ static void GlobExitProc(void)
+BEGIN
+ if (MakeDebug) fclose(Debug);
+END
+
+#endif
+
+static int LineZ;
+
+ static void NxtLine(void)
+BEGIN
+ if (++LineZ==23)
+ BEGIN
+ LineZ=0;
+ if (Redirected!=NoRedir) return;
+ printf("%s",getmessage(Num_KeyWaitMsg)); fflush(stdout);
+ while (getchar()!='\n');
+ printf("%s%s",CursUp,ClrEol);
+ END
+END
+
+ static void WrHead(void)
+BEGIN
+ if (!QuietMode)
+ BEGIN
+ printf("%s%s\n",getmessage(Num_InfoMessMacroAss),Version); NxtLine();
+ printf("(%s-%s)\n",ARCHPRNAME,ARCHSYSNAME); NxtLine();
+ printf("%s\n",InfoMessCopyright); NxtLine();
+ WriteCopyrights(NxtLine);
+ printf("\n"); NxtLine();
+ END
+END
+
+ int main(int argc, char **argv)
+BEGIN
+ char *Env,*ph1,*ph2;
+ String Dummy;
+ int i;
+ static Boolean First=TRUE;
+ CMDProcessed ParUnprocessed; /* bearbeitete Kommandozeilenparameter */
+
+ ParamCount=argc-1; ParamStr=argv;
+
+ if (First)
+ BEGIN
+ endian_init(); nls_init(); bpemu_init(); stdhandl_init();
+ strutil_init(); stringlists_init(); chunks_init();
+
+ NLS_Initialize();
+
+ nlmessages_init("as.msg",*argv,MsgId1,MsgId2); ioerrs_init(*argv);
+ cmdarg_init(*argv);
+
+ asmfnums_init(); asminclist_init(); asmitree_init();
+
+ asmdef_init(); asmsub_init(); asmpars_init();
+
+ asmmac_init(); asmif_init(); asmcode_init(); asmdebug_init();
+
+ codeallg_init(); codepseudo_init();
+
+ code68k_init();
+ code56k_init();
+ code601_init();
+ codemcore_init();
+ code68_init(); code6805_init(); code6809_init(); code6812_init(); code6816_init();
+ codeh8_3_init(); codeh8_5_init(); code7000_init();
+ code65_init(); code7700_init(); code4500_init(); codem16_init(); codem16c_init();
+ code4004_init(); code8008_init(); code48_init(); code51_init(); code96_init(); code85_init(); code86_init(); code960_init();
+ code8x30x_init(); codexa_init();
+ codeavr_init();
+ code29k_init();
+ code166_init();
+ codez80_init(); codez8_init();
+ code96c141_init(); code90c141_init(); code87c800_init(); code47c00_init(); code97c241_init();
+ code16c5x_init(); code16c8x_init(); code17c4x_init();
+ codest6_init(); codest7_init(); codest9_init(); code6804_init();
+ code3201x_init(); code3202x_init(); code3203x_init(); code3205x_init(); code3206x_init();
+ code9900_init(); codetms7_init(); code370_init(); codemsp_init();
+ code78c10_init(); code75k0_init(); code78k0_init(); code7720_init(); code77230_init();
+ codescmp_init(); codecop8_init(); codesc14xxx_init();
+ codeace_init();
+ code53c8xx_init();
+ codef2mc8_init();
+ /*as1750_init();*/
+ First=FALSE;
+ END
+
+#ifdef __sunos__
+ on_exit(GlobExitProc,(caddr_t) Nil);
+#else
+#ifndef __MUNIX__
+ atexit(GlobExitProc);
+#endif
+#endif
+
+ *CursUp='\0'; *ClrEol='\0';
+ switch (Redirected)
+ BEGIN
+ case NoRedir:
+ Env=getenv("USEANSI"); strncpy(Dummy,(Env!=Nil)?Env:"Y",255);
+ if (toupper(Dummy[0])=='N')
+ BEGIN
+ END
+ else
+ BEGIN
+ strcpy(ClrEol," [K"); ClrEol[0]=Char_ESC; /* ANSI-Sequenzen */
+ strcpy(CursUp," [A"); CursUp[0]=Char_ESC;
+ END
+ break;
+ case RedirToDevice:
+ /* Basissteuerzeichen fuer Geraete */
+ for (i=1; i<=20; i++) strcat(ClrEol," ");
+ for (i=1; i<=20; i++) strcat(ClrEol,"\b");
+ break;
+ case RedirToFile:
+ strcpy(ClrEol,"\n"); /* CRLF auf Datei */
+ END
+
+ ShareMode=0; ListMode=0; IncludeList[0]='\0'; SuppWarns=False;
+ MakeUseList=False; MakeCrossList=False; MakeSectionList=False;
+ MakeIncludeList=False; ListMask=0xff;
+ MakeDebug=False; ExtendErrors=0;
+ MacroOutput=False; MacProOutput=False; CodeOutput=True;
+ strcpy(ErrorPath,"!2"); MsgIfRepass=False; QuietMode=False;
+ NumericErrors=False; DebugMode=DebugNone; CaseSensitive=False;
+ ThrowErrors=False; HardRanges=True;
+
+ LineZ=0;
+
+ if (ParamCount==0)
+ BEGIN
+ WrHead();
+ printf("%s%s%s\n",getmessage(Num_InfoMessHead1),GetEXEName(),getmessage(Num_InfoMessHead2)); NxtLine();
+ for (ph1=getmessage(Num_InfoMessHelp),ph2=strchr(ph1,'\n'); ph2!=Nil; ph1=ph2+1,ph2=strchr(ph1,'\n'))
+ BEGIN
+ *ph2='\0';
+ printf("%s\n",ph1); NxtLine();
+ *ph2='\n';
+ END
+ PrintCPUList(NxtLine);
+ ClearCPUList();
+ exit(1);
+ END
+
+#if defined(STDINCLUDES)
+ CMD_IncludeList(False,STDINCLUDES);
+#endif
+ ProcessCMD(ASParams,ASParamCnt,ParUnprocessed,EnvName,ParamError);
+
+ /* wegen QuietMode dahinter */
+
+ WrHead();
+
+ GlobErrFlag=False;
+ if (ErrorPath[0]!='\0')
+ BEGIN
+ strcpy(ErrorName,ErrorPath);
+ unlink(ErrorName);
+ END
+ IsErrorOpen=False;
+
+ for (i=1; i<=ParamCount; i++)
+ if (ParUnprocessed[i]) break;
+ if (i>ParamCount)
+ BEGIN
+ printf("%s [%s] ",getmessage(Num_InvMsgSource),SrcSuffix); fflush(stdout);
+ fgets(FileMask,255,stdin);
+ if (FileMask[strlen(FileMask)-1]=='\n') FileMask[strlen(FileMask)-1]='\0';
+ AssembleGroup();
+ END
+ else
+ for (i=1; i<=ParamCount; i++)
+ if (ParUnprocessed[i])
+ BEGIN
+ strmaxcpy(FileMask,ParamStr[i],255);
+ AssembleGroup();
+ END
+
+ if ((ErrorPath[0]!='\0') AND (IsErrorOpen))
+ BEGIN
+ fclose(ErrorFile); IsErrorOpen=False;
+ END
+
+ ClearCPUList();
+
+ if (GlobErrFlag) return (2); else return (0);
+END
diff --git a/as.h b/as.h
new file mode 100644
index 0000000..c0e9c93
--- /dev/null
+++ b/as.h
@@ -0,0 +1,11 @@
+/* as.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Hauptmodul */
+/* */
+/* Historie: 4. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern char *GetErrorPos(void);
diff --git a/as.res b/as.res
new file mode 100644
index 0000000..4c5f01d
--- /dev/null
+++ b/as.res
@@ -0,0 +1,983 @@
+;* as.res
+;*****************************************************************************
+;* AS-Portierung *
+;* *
+;* String-Definitionen fuer AS *
+;* *
+;* Historie: 4. 5.1996 Grundsteinlegung *
+;* 19. 1.1997 Kommandozeilenoption U *
+;* 21. 1.1997 Warnung nicht bitadressierbare Speicherstelle *
+;* 22. 1.1997 Fehler;Warnungen fuer Stacks *
+;* 1. 2.1997 Warnung wegen NUL-Zeichen *
+;* 29. 3.1997 Kommandozeilenoption g *
+;* 30. 5.1997 Warnung wg. inkorrektem Listing *
+;* 12. 7.1997 Kommandozeilenoption Y *
+;* 5. 8.1997 Meldungen fuer Strukturen *
+;* 7. 9.1997 Warnung Bereichsueberschreitung *
+;* 24. 9.1997 Kopfzeile Registerdefinitionsliste *
+;* 19.10.1997 Warnung neg. DUP-Anzahl *
+;* 26. 6.1998 Fehlermeldung Codepage nicht gefunden *
+;* 27. 6.1998 Meldungen für Codepage-Liste *
+;* 18. 4.1999 Kommandozeilenoptionen cpu, shareout *
+;* 2. 5.1999 'order' --> 'instruction' *
+;* 13. 7.1999 Fehlermeldungen fuer extern-Symbole *
+;* *
+;*****************************************************************************
+
+Include header.res
+
+;-----------------------------------------------------------------------------
+; Fehlermeldungen
+
+Message ErrName
+ ": Fehler "
+ ": error "
+
+Message WarnName
+ ": Warnung "
+ ": warning "
+
+Message InLineName
+ " in Zeile "
+ " in line "
+
+Message ErrMsgUselessDisp
+ "Displacement=0, &uuml;berfl&uuml;ssig"
+ "useless displacement 0"
+
+Message ErrMsgShortAddrPossible
+ "Kurzadressierung m&ouml;glich"
+ "short addressing possible"
+
+Message ErrMsgShortJumpPossible
+ "kurzer Sprung m&ouml;glich"
+ "short jump possible"
+
+Message ErrMsgNoShareFile
+ "kein Sharefile angelegt, SHARED ignoriert"
+ "no sharefile created, SHARED ignored"
+
+Message ErrMsgBigDecFloat
+ "FPU liest Wert evtl. nicht korrekt ein (>=1E1000)"
+ "FPU possibly cannot read this value (> 1E1000)"
+
+Message ErrMsgPrivOrder
+ "privilegierte Anweisung"
+ "privileged instruction"
+
+Message ErrMsgDistNull
+ "Distanz 0 nicht bei Kurzsprung erlaubt (NOP erzeugt)"
+ "distance of 0 not allowed for short jump (NOP created instead)"
+
+Message ErrMsgWrongSegment
+ "Symbol aus falschem Segment"
+ "symbol out of wrong segment"
+
+Message ErrMsgInAccSegment
+ "Segment nicht adressierbar"
+ "segment not accessible"
+
+Message ErrMsgPhaseErr
+ "&Auml;nderung des Symbolwertes erzwingt zus&auml;tzlichen Pass"
+ "change of symbol values forces additional pass"
+
+Message ErrMsgOverlap
+ "&uuml;berlappende Speicherbelegung"
+ "overlapping memory usage"
+
+Message ErrMsgNoCaseHit
+ "keine CASE-Bedingung zugetroffen"
+ "none of the CASE conditions was true"
+
+Message ErrMsgInAccPage
+ "Seite m&ouml;glicherweise nicht adressierbar"
+ "page might not be addressable"
+
+Message ErrMsgRMustBeEven
+ "Registernummer mu&szlig; gerade sein"
+ "register number must be even"
+
+Message ErrMsgObsolete
+ "veralteter Befehl"
+ "obsolete instruction, usage discouraged"
+
+Message ErrMsgUnpredictable
+ "nicht vorhersagbare Ausf&uuml;hrung dieser Anweisung"
+ "unpredictable execution of this instruction"
+
+Message ErrMsgAlphaNoSense
+ "Lokaloperator au&szlig;erhalb einer Sektion &uuml;berfl&uuml;ssig"
+ "localization operator senseless out of a section"
+
+Message ErrMsgSenseless
+ "sinnlose Operation"
+ "senseless instruction"
+
+Message ErrMsgRepassUnknown
+ "unbekannter Symbolwert erzwingt zus&auml;tzlichen Pass"
+ "unknown symbol value forces additional pass"
+
+Message ErrMsgAddrNotAligned
+ "Adresse nicht ausgerichtet"
+ "address is not properly aligned"
+
+Message ErrMsgIOAddrNotAllowed
+ "I/O-Adresse darf nicht verwendet werden"
+ "I/O-address must not be used here"
+
+Message ErrMsgPipeline
+ "m&ouml;gliche Pipelining-Effekte"
+ "possible pipelining effects"
+
+Message ErrMsgDoubleAdrRegUse
+ "mehrfache Adre&szlig;registerbenutzung in einer Anweisung"
+ "multiple use of address register in one instruction"
+
+Message ErrMsgNotBitAddressable
+ "Speicherstelle nicht bitadressierbar"
+ "memory location is not bit addressable"
+
+Message ErrMsgStackNotEmpty
+ "Stack ist nicht leer"
+ "stack is not empty"
+
+Message ErrMsgNULCharacter
+ "NUL-Zeichen in String, Ergebnis undefiniert"
+ "NUL character in string, result is undefined"
+
+Message ErrMsgPageCrossing
+ "Befehl &uuml;berschreitet Seitengrenze"
+ "instruction crosses page boundary"
+
+Message ErrMsgWOverRange
+ "Bereichs&uuml;berschreitung"
+ "range overflow"
+
+Message ErrMsgNegDUP
+ "negatives Argument f&uuml;r DUP"
+ "negative argument for DUP"
+
+;*****
+
+Message ErrMsgDoubleDef
+ "Symbol doppelt definiert"
+ "symbol double defined"
+
+Message ErrMsgSymbolUndef
+ "Symbol nicht definiert"
+ "symbol undefined"
+
+Message ErrMsgInvSymName
+ "ung&uuml;ltiger Symbolname"
+ "invalid symbol name"
+
+Message ErrMsgInvFormat
+ "ung&uuml;ltiges Format"
+ "invalid format"
+
+Message ErrMsgUseLessAttr
+ "&uuml;berfl&uuml;ssiges Attribut"
+ "useless attribute"
+
+Message ErrMsgUndefAttr
+ "undefiniertes Attribut"
+ "undefined attribute"
+
+Message ErrMsgTooLongAttr
+ "Attribut darf nur 1 Zeichen lang sein"
+ "attribute may only be one character long"
+
+Message ErrMsgWrongArgCnt
+ "unpassende Operandenzahl"
+ "wrong number of operands"
+
+Message ErrMsgWrongOptCnt
+ "unpassende Optionszahl"
+ "wrong number of options"
+
+Message ErrMsgOnlyImmAddr
+ "nur immediate-Adressierung erlaubt"
+ "addressing mode must be immediate"
+
+Message ErrMsgInvOpsize
+ "unpassende Operandengr&ouml;&szlig;e"
+ "invalid operand size"
+
+Message ErrMsgConfOpSizes
+ "widersprechende Operandengr&ouml;&szlig;en"
+ "conflicting operand sizes"
+
+Message ErrMsgUndefOpSizes
+ "undefinierte Operandengr&ouml;&szlig;e"
+ "undefined operand size"
+
+Message ErrMsgInvOpType
+ "unpassender Operandentyp"
+ "invalid operand type"
+
+Message ErrMsgTooMuchArgs
+ "zuviele Argumente"
+ "too many arguments"
+
+Message ErrMsgUnknownOpcode
+ "unbekannter Befehl"
+ "unknown opcode"
+
+Message ErrMsgBrackErr
+ "Klammerfehler"
+ "number of opening/closing parentheses does not match"
+
+Message ErrMsgDivByZero
+ "Division durch 0"
+ "division by 0"
+
+Message ErrMsgUnderRange
+ "Bereichsunterschreitung"
+ "range underflow"
+
+Message ErrMsgOverRange
+ "Bereichs&uuml;berschreitung"
+ "range overflow"
+
+Message ErrMsgNotAligned
+ "Adresse nicht ausgerichtet"
+ "address is not properly aligned"
+
+Message ErrMsgDistTooBig
+ "Distanz zu gro&szlig;"
+ "distance too big"
+
+Message ErrMsgInAccReg
+ "Register nicht zugreifbar"
+ "register not accessible"
+
+Message ErrMsgNoShortAddr
+ "Kurzadressierung nicht m&ouml;glich"
+ "short addressing not allowed"
+
+Message ErrMsgInvAddrMode
+ "unerlaubter Adressierungsmodus"
+ "addressing mode not allowed here"
+
+Message ErrMsgMustBeEven
+ "Nummer mu&szlig; ausgerichtet sein"
+ "number must be aligned"
+
+Message ErrMsgInvParAddrMode
+ "Adressierungsmodus im Parallelbetrieb nicht erlaubt"
+ "addressing mode not allowed in parallel operation"
+
+Message ErrMsgUndefCond
+ "undefinierte Bedingung"
+ "undefined condition"
+
+Message ErrMsgJmpDistTooBig
+ "Sprungdistanz zu gro&szlig;"
+ "jump distance too big"
+
+Message ErrMsgDistIsOdd
+ "Sprungdistanz ist ungerade"
+ "jump distance is odd"
+
+Message ErrMsgInvShiftArg
+ "ung&uuml;ltiges Schiebeargument"
+ "invalid argument for shifting"
+
+Message ErrMsgRange18
+ "nur Bereich 1..8 erlaubt"
+ "operand must be in range 1..8"
+
+Message ErrMsgShiftCntTooBig
+ "Schiebezahl zu gro&szlig;"
+ "shift amplitude too big"
+
+Message ErrMsgInvRegList
+ "ung&uuml;ltige Registerliste"
+ "invalid register list"
+
+Message ErrMsgInvCmpMode
+ "ung&uuml;ltiger Modus mit CMP"
+ "invalid addressing mode for CMP"
+
+Message ErrMsgInvCPUType
+ "ung&uuml;ltiger Prozessortyp"
+ "invalid CPU type"
+
+Message ErrMsgInvCtrlReg
+ "ung&uuml;ltiges Kontrollregister"
+ "invalid control register"
+
+Message ErrMsgInvReg
+ "ung&uuml;ltiges Register"
+ "invalid register"
+
+Message ErrMsgNoSaveFrame
+ "RESTORE ohne SAVE"
+ "RESTORE without SAVE"
+
+Message ErrMsgNoRestoreFrame
+ "fehlendes RESTORE"
+ "missing RESTORE"
+
+Message ErrMsgUnknownMacArg
+ "unbekannte Makro-Steueranweisung"
+ "unknown macro control instruction"
+
+Message ErrMsgMissEndif
+ "fehlendes ENDIF/ENDCASE"
+ "missing ENDIF/ENDCASE"
+
+Message ErrMsgInvIfConst
+ "ung&uuml;ltiges IF-Konstrukt"
+ "invalid IF-structure"
+
+Message ErrMsgDoubleSection
+ "doppelter Sektionsname"
+ "section name double defined"
+
+Message ErrMsgInvSection
+ "unbekannte Sektion"
+ "unknown section"
+
+Message ErrMsgMissingEndSect
+ "fehlendes ENDSECTION"
+ "missing ENDSECTION"
+
+Message ErrMsgWrongEndSect
+ "falsches ENDSECTION"
+ "wrong ENDSECTION"
+
+Message ErrMsgNotInSection
+ "ENDSECTION ohne SECTION"
+ "ENDSECTION without SECTION"
+
+Message ErrMsgUndefdForward
+ "nicht aufgel&ouml;ste Vorw&auml;rtsdeklaration"
+ "unresolved forward declaration"
+
+Message ErrMsgContForward
+ "widersprechende FORWARD <-> PUBLIC-Deklaration"
+ "conflicting FORWARD <-> PUBLIC-declaration"
+
+Message ErrMsgInvFuncArgCnt
+ "falsche Argumentzahl f&uuml;r Funktion"
+ "wrong numbers of function arguments"
+
+Message ErrMsgMissingLTORG
+ "unaufgel&ouml;ste Literale (LTORG fehlt)"
+ "unresolved literals (missing LTORG)"
+
+Message ErrMsgNotOnThisCPU1
+ "Befehl auf dem "
+ "instruction not allowed on "
+
+Message ErrMsgNotOnThisCPU2
+ " nicht vorhanden"
+ ""
+
+Message ErrMsgNotOnThisCPU3
+ "Adressierungsart auf dem "
+ "addressing mode not allowed on "
+
+Message ErrMsgInvBitPos
+ "ung&uuml;ltige Bitstelle"
+ "invalid bit position"
+
+Message ErrMsgOnlyOnOff
+ "nur ON/OFF erlaubt"
+ "only ON/OFF allowed"
+
+Message ErrMsgStackEmpty
+ "Stack ist leer oder nicht definiert"
+ "stack is empty or undefined"
+
+Message ErrMsgNotOneBit
+ "Nicht genau ein Bit gesetzt"
+ "not exactly one bit set"
+
+Message ErrMsgMissingStruct
+ "ENDSTRUCT ohne STRUCT"
+ "ENDSTRUCT without STRUCT"
+
+Message ErrMsgOpenStruct
+ "offene Strukturdefinition"
+ "open structure definition"
+
+Message ErrMsgWrongStruct
+ "falsches ENDSTRUCT"
+ "wrong ENDSTRUCT"
+
+Message ErrMsgPhaseDisallowed
+ "Phasendefinition nicht in Strukturen erlaubt"
+ "phase definition not allowed in structure definition"
+
+Message ErrMsgInvStructDir
+ "Ung&uuml;ltige STRUCT-Direktive"
+ "invalid STRUCT directive"
+
+Message ErrMsgShortRead
+ "vorzeitiges Dateiende"
+ "unexpected end of file"
+
+Message ErrMsgUnknownCodepage
+ "unbekannte Zeichentabelle"
+ "unknown codepage"
+
+Message ErrMsgRomOffs063
+ "ROM-Offset geht nur von 0..63"
+ "ROM-offset must be in range 0..63"
+
+Message ErrMsgInvFCode
+ "ung&uuml;ltiger Funktionscode"
+ "invalid function code"
+
+Message ErrMsgInvFMask
+ "ung&uuml;ltige Funktionscodemaske"
+ "invalid function code mask"
+
+Message ErrMsgInvMMUReg
+ "ung&uuml;ltiges MMU-Register"
+ "invalid MMU register"
+
+Message ErrMsgLevel07
+ "Level nur von 0..7"
+ "level must be in range 0..7"
+
+Message ErrMsgInvBitMask
+ "ung&uuml;ltige Bitmaske"
+ "invalid bit mask"
+
+Message ErrMsgInvRegPair
+ "ung&uuml;ltiges Registerpaar"
+ "invalid register pair"
+
+Message ErrMsgOpenMacro
+ "offene Makrodefinition"
+ "open macro definition"
+
+Message ErrMsgDoubleMacro
+ "doppelte Makrodefinition"
+ "macro double defined"
+
+Message ErrMsgTooManyMacParams
+ "mehr als 10 Makroparameter"
+ "more than 10 macro parameters"
+
+Message ErrMsgEXITMOutsideMacro
+ "EXITM au&szlig;erhalb eines Makrorumpfes"
+ "EXITM not called from within macro"
+
+Message ErrMsgFirstPassCalc
+ "Ausdruck mu&szlig; im ersten Pass berechenbar sein"
+ "expression must be evaluatable in first pass"
+
+Message ErrMsgTooManyNestedIfs
+ "zu viele verschachtelte IFs"
+ "too many nested IFs"
+
+Message ErrMsgMissingIf
+ "ELSEIF/ENDIF ohne IF"
+ "ELSEIF/ENDIF without IF"
+
+Message ErrMsgRekMacro
+ "verschachtelter/rekursiver Makroaufruf"
+ "nested/recursive makro call"
+
+Message ErrMsgUnknownFunc
+ "unbekannte Funktion"
+ "unknown function"
+
+Message ErrMsgInvFuncArg
+ "Funktionsargument au&szlig;erhalb Definitionsbereich"
+ "function argument out of definition range"
+
+Message ErrMsgFloatOverflow
+ "Gleitkomma&uuml;berlauf"
+ "floating point overflow"
+
+Message ErrMsgInvArgPair
+ "ung&uuml;ltiges Wertepaar"
+ "invalid value pair"
+
+Message ErrMsgNotOnThisAddress
+ "Befehl darf nicht auf dieser Adresse liegen"
+ "instruction must not start on this address"
+
+Message ErrMsgNotFromThisAddress
+ "ung&uuml;ltiges Sprungziel"
+ "invalid jump target"
+
+Message ErrMsgTargOnDiffPage
+ "Sprungziel nicht auf gleicher Seite"
+ "jump target not on same page"
+
+Message ErrMsgCodeOverflow
+ "Code&uuml;berlauf"
+ "code overflow"
+
+Message ErrMsgMixDBDS
+ "Konstanten und Platzhalter nicht mischbar"
+ "constants and placeholders cannot be mixed"
+
+Message ErrMsgNotInStruct
+ "Codeerzeugung in Strukturdefinition nicht zul&auml;ssig"
+ "code must not be generated in structure definition"
+
+Message ErrMsgParNotPossible
+ "paralleles Konstrukt nicht m&ouml;glich"
+ "parallel construct not possible here"
+
+Message ErrMsgAdrOverflow
+ "Adre&szlig;&uuml;berlauf"
+ "address overflow"
+
+Message ErrMsgInvSegment
+ "ung&uuml;ltiges Segment"
+ "invalid segment"
+
+Message ErrMsgUnknownSegment
+ "unbekanntes Segment"
+ "unknown segment"
+
+Message ErrMsgUnknownSegReg
+ "unbekanntes Segmentregister"
+ "unknown segment register"
+
+Message ErrMsgInvString
+ "ung&uuml;ltiger String"
+ "invalid string"
+
+Message ErrMsgInvRegName
+ "ung&uuml;ltiger Registername"
+ "invalid register name"
+
+Message ErrMsgInvArg
+ "ung&uuml;ltiges Argument"
+ "invalid argument"
+
+Message ErrMsgNoIndir
+ "keine Indirektion erlaubt"
+ "indirect mode not allowed"
+
+Message ErrMsgNotInThisSegment
+ "nicht im aktuellen Segment erlaubt"
+ "not allowed in current segment"
+
+Message ErrMsgNotInMaxmode
+ "nicht im Maximum-Modus zul&auml;ssig"
+ "not allowed in maximum mode"
+
+Message ErrMsgOnlyInMaxmode
+ "nicht im Minimum-Modus zul&auml;ssig"
+ "not allowed in minimum mode"
+
+Message ErrMsgOpeningFile
+ "Fehler beim &Ouml;ffnen der Datei"
+ "error in opening file"
+
+Message ErrMsgListWrError
+ "Listingschreibfehler"
+ "error in writing listing"
+
+Message ErrMsgFileReadError
+ "Dateilesefehler"
+ "file read error"
+
+Message ErrMsgFileWriteError
+ "Dateischreibfehler"
+ "file write error"
+
+Message ErrMsgIntError
+ "interne(r) Fehler/Warnung"
+ "internal error/warning"
+
+Message ErrMsgHeapOvfl
+ "Speicher&uuml;berlauf"
+ "heap overflow"
+
+Message ErrMsgStackOvfl
+ "Stapel&uuml;berlauf"
+ "stack overflow"
+
+Message ErrMsgIsFatal
+ "Fataler Fehler, Assembler abgebrochen"
+ "fatal error, assembly terminated"
+
+Message ErrMsgOvlyError
+ "Overlayfehler - Programmabbruch"
+ "overlay error - program terminated"
+
+Message PrevDefMsg
+ "vorherige Definition in"
+ "previous definition in"
+
+Message ErrMsgInvSwapSize
+ "ung&uuml;ltige Gr&ouml;&szlig;enangabe f&uuml;r Swapfile - Programmabbruch"
+ "swap file size not correctly specified - program terminated"
+
+Message ErrMsgSwapTooBig
+ "zuwenig Platz f&uuml;r Swapfile - Programmabbruch"
+ "insufficient space for swap file - program terminated"
+
+Message ErrMsgNoRelocs
+ "relokatible Symbole nicht erlaubt"
+ "relocatable symbols not allowed"
+
+Message ErrMsgUnresRelocs
+ "unverarbeitete externe Referenzen"
+ "unresolved external references"
+
+;----------------------------------------------------------------------------
+; Strings in Listingkopfzeile
+
+Message HeadingFileNameLab
+ " - Quelle "
+ " - source file "
+
+Message HeadingPageLab
+ " - Seite "
+ " - page "
+
+;----------------------------------------------------------------------------
+; Strings in Listing
+
+Message ListSymListHead1
+ " Symboltabelle (*=unbenutzt):"
+ " symbol table (* = unused):"
+
+Message ListSymListHead2
+ " ----------------------------"
+ " ------------------------"
+
+Message ListSymSumMsg
+ " Symbol"
+ " symbol"
+
+Message ListSymSumsMsg
+ " Symbole"
+ " symbols"
+
+Message ListUSymSumMsg
+ " unbenutztes Symbol"
+ " unused symbol"
+
+Message ListUSymSumsMsg
+ " unbenutzte Symbole"
+ " unused symbols"
+
+Message ListRegDefListHead1
+ " Registerdefinitionen (*=unbenutzt):"
+ " register definitions (*=unused):"
+
+Message ListRegDefListHead2
+ " -----------------------------------"
+ " --------------------------------"
+
+Message ListRegDefSumMsg
+ " Definition"
+ " definition"
+
+Message ListRegDefSumsMsg
+ " Definitionen"
+ " definitions"
+
+Message ListRegDefUSumMsg
+ " unbenutzte Definition"
+ " unused definition"
+
+Message ListRegDefUSumsMsg
+ " unbenutzte Definitionen"
+ " unused definitions"
+
+Message ListCodepageListHead1
+ " Zeichentabellen:"
+ " codepages:"
+
+Message ListCodepageListHead2
+ " ----------------"
+ " ----------"
+
+Message ListCodepageChange
+ " ver&auml;ndertes Zeichen"
+ " changed character"
+
+Message ListCodepagePChange
+ " ver&auml;nderte Zeichen"
+ " changed characters"
+
+Message ListCodepageSumMsg
+ " Zeichentabelle"
+ " code page"
+
+Message ListCodepageSumsMsg
+ " Zeichentabellen"
+ " code pages"
+
+Message ListMacListHead1
+ " definierte Makros:"
+ " defined macros:"
+
+Message ListMacListHead2
+ " ------------------"
+ " ---------------"
+
+Message ListMacSumMsg
+ " Makro"
+ " macro"
+
+Message ListMacSumsMsg
+ " Makros"
+ " macros"
+
+Message ListFuncListHead1
+ " definierte Funktionen:"
+ " defined functions:"
+
+Message ListFuncListHead2
+ " ----------------------"
+ " ------------------"
+
+Message ListDefListHead1
+ " DEFINEs:"
+ " DEFINEs:"
+
+Message ListDefListHead2
+ " --------"
+ " --------"
+
+Message ListSegListHead1
+ "in "
+ "space used in "
+
+Message ListSegListHead2
+ " belegte Bereiche:"
+ " :"
+
+Message ListCrossListHead1
+ " Querverweisliste:"
+ " cross reference list:"
+
+Message ListCrossListHead2
+ " -----------------"
+ " ---------------------"
+
+Message ListSectionListHead1
+ " Sektionen:"
+ " sections:"
+
+Message ListSectionListHead2
+ " ----------"
+ " ---------"
+
+Message ListIncludeListHead1
+ " Include-Verschachtelung:"
+ " nested include files:"
+
+Message ListIncludeListHead2
+ " ------------------------"
+ " ---------------------"
+
+Message ListCrossSymName
+ "Symbol "
+ "symbol "
+
+Message ListCrossFileName
+ "Datei "
+ "file "
+
+Message ListPlurName
+ "n"
+ "s"
+
+Message ListHourName
+ " Stunde"
+ " hour"
+
+Message ListMinuName
+ " Minute"
+ " minute"
+
+Message ListSecoName
+ " Sekunde"
+ " second"
+
+;---------------------------------------------------------------------------
+; Durchsagen...
+
+Message InfoMessAssembling
+ "Assembliere "
+ "assembling "
+
+Message InfoMessPass
+ "PASS "
+ "PASS "
+
+Message InfoMessPass1
+ "PASS 1 "
+ "PASS 1 "
+
+Message InfoMessPass2
+ "PASS 2 "
+ "PASS 2 "
+
+Message InfoMessAssTime
+ " Assemblierzeit"
+ " assembly time"
+
+Message InfoMessAssLine
+ " Zeile Quelltext"
+ " line source file"
+
+Message InfoMessAssLines
+ " Zeilen Quelltext"
+ " lines source file"
+
+Message InfoMessPassCnt
+ " Durchlauf"
+ " pass"
+
+Message InfoMessPPassCnt
+ " Durchl&auml;ufe"
+ " passes"
+
+Message InfoMessNoPass
+ " zus&auml;tzliche erforderliche Durchl&auml;ufe wegen Fehlern nicht\n durchgef&uuml;hrt, Listing m&ouml;glicherweise inkorrekt"
+ " additional necessary passes not started due to\n errors, listing possibly incorrect"
+
+Message InfoMessMacAssLine
+ " Zeile inkl. Makroexpansionen"
+ " line incl. macro expansions"
+
+Message InfoMessMacAssLines
+ " Zeilen inkl. Makroexpansionen"
+ " lines incl. macro expansions"
+
+Message InfoMessWarnCnt
+ " Warnung"
+ " warning"
+
+Message InfoMessWarnPCnt
+ "en"
+ "s"
+
+Message InfoMessErrCnt
+ " Fehler"
+ " error"
+
+Message InfoMessErrPCnt
+ ""
+ "s"
+
+Message InfoMessRemainMem
+ " KByte verf&uuml;gbarer Restspeicher"
+ " Kbytes available memory"
+
+Message InfoMessRemainStack
+ " Byte verf&uuml;gbarer Stack"
+ " bytes available stack"
+
+Message InfoMessNFilesFound
+ ": keine Datei(en) zu assemblieren!"
+ ": no file(s) to assemble!"
+
+Message InfoMessMacroAss
+ "Makroassembler "
+ "macro assembler "
+
+Message InfoMessVar
+ "Version"
+ "version"
+
+Message InfoMessHead1
+ "Aufruf : "
+ "calling convention : "
+
+Message InfoMessHead2
+ " [Optionen] [Datei] [Optionen] ..."
+ " [options] [file] [options] ..."
+
+Message KeyWaitMsg
+ "--- weiter mit <ENTER> ---"
+ "--- <ENTER> to go on ---"
+
+Message ErrMsgInvParam
+ "ung&uuml;ltige Option: "
+ "invalid option: "
+
+Message ErrMsgInvEnvParam
+ "ung&uuml;ltige Environment-Option: "
+ "invalid environment option: "
+
+Message InvMsgSource
+ "Quelldatei?"
+ "source file?"
+
+Message InfoMessHelp
+ "--------\n" \
+ "\n" \
+ "Optionen :\n" \
+ "----------\n" \
+ "\n" \
+ "-p : Sharefile im Pascal-Format -c : Sharefile im C-Format\n" \
+ "-a : Sharefile im AS-Format\n" \
+ "-o <Name> : Namen der Code-Datei neu setzen\n" \
+ "-shareout <Name> : Namen des Sharefiles neu setzen\n" \
+ "-q, -quiet : Stille &Uuml;bersetzung\n" \
+ "-cpu <Name> : Zielprozessor setzen\n" \
+ "-alias <neu>=<alt> : Prozessor-Alias definieren\n" \
+ "-l : Listing auf Konsole -L : Listing auf Datei\n" \
+ "-i <Pfad>[:Pfad]... : Pfadliste f&uuml;r Includedateien\n" \
+ "-D <Symbol>[,Symbol]... : Symbole vordefinieren\n" \
+ "-E [Name] : Zieldatei f&uuml;r Fehlerliste,\n" \
+ " !0..!4 f&uuml;r Standardhandles\n" \
+ " Default <Quelldatei>.LOG\n" \
+ "-r : Meldungen erzeugen, falls zus&auml;tzlicher Pass erforderlich\n" \
+ "-Y : Sprungfehlerunterdr&uuml;ckung (siehe Anleitung)\n" \
+ "-w : Warnungen unterdr&uuml;cken +G : Code-Erzeugung unterdr&uuml;cken\n" \
+ "-s : Sektionsliste erzeugen -t : Listing-Teile ein/ausblenden\n" \
+ "-u : Belegungsliste erzeugen -C : Querverweisliste erzeugen\n" \
+ "-I : Include-Verschachtelungsliste ausgeben\n" \
+ "-g : Debug-Informationen schreiben\n" \
+ "-A : kompaktere Symbolablage\n" \
+ "-U : Case-sensitiv arbeiten\n" \
+ "-x : erweiterte Fehlermeldungen -n : Fehlermeldungen mit Nummer\n" \
+ "-P : Makroprozessorausgabe erzeugen -M : Makrodefinitionen extrahieren\n" \
+ "-h : Hexadezimalzahlen mit Kleinbuchstaben\n" \
+ "\n" \
+ "Quelldateiangabe darf Jokerzeichen enthalten\n" \
+ "\n" \
+ "implementierte Prozessoren :\n"
+ "--------------------\n" \
+ "\n" \
+ "options :\n" \
+ "---------\n" \
+ "\n" \
+ "-p : share file formatted for Pascal -c : share file formatted for C\n" \
+ "-a : share file formatted for AS\n" \
+ "-o <name> : change name of code file\n" \
+ "-shareout <nname> : change name of share file\n" \
+ "-q, -quiet : silent compilation\n" \
+ "-cpu <name> : set target processor\n" \
+ "-alias <new>=<old> : define processor alias\n" \
+ "-l : listing to console -L : listing to file\n" \
+ "-i <path>[;path]... : list of paths for include files\n" \
+ "-D <symbol>[,symbol]... : predefine symbols\n" \
+ "-E <name> : target file for error list,\n" \
+ " !0..!4 for standard handles\n" \
+ " default is <srcname>.LOG\n" \
+ "-r : generate messages if repassing necessary\n" \
+ "-Y : branch error suppression (see manual)\n" \
+ "-w : suppress warnings +G : suppress code generation\n" \
+ "-s : generate section list -t : enable/disable parts of listing\n" \
+ "-u : generate usage list -C : generate cross reference list\n" \
+ "-I : generate include nesting list\n" \
+ "-g : write debug info\n" \
+ "-A : compact symbol table\n" \
+ "-U : case-sensitive operation\n" \
+ "-x : extended error messages -n : add error #s to error messages\n" \
+ "-P : write macro processor output -M : extract macro definitions\n" \
+ "-h : use lower case in hexadecimal output\n" \
+ "\n" \
+ "source file specification may contain wildcards\n" \
+ "\n" \
+ "implemented processors :\n"
diff --git a/as1750.c b/as1750.c
new file mode 100644
index 0000000..13301b4
--- /dev/null
+++ b/as1750.c
@@ -0,0 +1,1295 @@
+/***************************************************************************/
+/* */
+/* Project : as1750 -- Mil-Std-1750 Assembler and Linker */
+/* */
+/* Component : as1750.c -- 1750 instruction assembly */
+/* */
+/* Copyright : (C) Daimler-Benz Aerospace AG, 1994-1997 */
+/* */
+/* Author : Oliver M. Kellogg, Dornier Satellite Systems, */
+/* Dept. RST13, D-81663 Munich, Germany. */
+/* Contact : oliver.kellogg@space.otn.dasa.de */
+/* */
+/* Disclaimer: */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/***************************************************************************/
+
+#ifdef AS1750
+#include "common.h"
+#include "utils.h"
+#else /* ASL */
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include "datatypes.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "as1750.h"
+#define bool char
+#define ushort unsigned short
+#define ulong unsigned long
+#define status unsigned
+#define dtoi(ascii_char) (ascii_char - '0')
+#endif
+
+
+#ifndef AS1750
+static
+#endif
+ status /* Output an error text (printf style). */
+error (char *layout,...) /* Return the ERROR status code. */
+{
+ va_list vargu;
+ char output_line[132];
+
+ va_start (vargu, layout);
+ vsprintf (output_line, layout, vargu);
+#ifdef AS1750
+ fprintf (stderr, "%s line%5d: %s\n", nopath (file[curr_file].name),
+ file[curr_file].line_number, output_line);
+#else /* ASL */
+ WrErrorString (output_line, "\0", 0, 0);
+#endif
+ va_end (vargu);
+ return ERROR;
+}
+
+
+/* Get a number. Return pointer to first position in s after the end of
+ * the number, or NULL for error.
+ * Will also read character constants of the form: 'x', and two-character
+ * packed strings of the form "xy" (where x=>highbyte,y=>lowbyte.)
+ */
+
+#ifdef AS1750
+
+char *
+get_num (char *s, int *outnum)
+{
+ bool is_neg = FALSE, intel = FALSE, c_lang = FALSE, tld = FALSE;
+ char *start;
+
+ *outnum = 0;
+ if (*s == '-')
+ {
+ is_neg = TRUE;
+ ++s;
+ }
+ else if (*s == '+')
+ ++s;
+ /* determine if Intel format */
+ if (isdigit (*s))
+ {
+ char *p = s;
+ while (isxdigit (*++p))
+ ;
+ if (upcase (*p) == 'H')
+ intel = TRUE;
+ }
+ if (intel
+ || (c_lang = (*s == '0' && upcase (*(s + 1)) == 'X'))
+ || (tld = strncmp (s, "16#", 3) == 0))
+ {
+ s += c_lang ? 2 : tld ? 3 : 0;
+ start = s;
+ while (isxdigit (*s))
+ {
+ *outnum = (*outnum << 4) | xtoi (*s);
+ ++s;
+ }
+ if (s - start > 4)
+ {
+ error ("get_num -- number at '%s' too large", start);
+ return NULL;
+ }
+ if (intel)
+ s++;
+ else if (tld)
+ {
+ if (*s != '#')
+ {
+ error ("get_num -- expecting '#' at end of number");
+ return NULL;
+ }
+ s++;
+ }
+ }
+ else if (*s == '0' || (tld = (*s == '8' && *(s + 1) == '#')))
+ {
+ s += tld ? 2 : 1;
+ start = s;
+ while (*s >= '0' && *s <= '7')
+ {
+ *outnum = (*outnum << 3) | (*s - '0');
+ ++s;
+ }
+ if (s - start > 6)
+ {
+ error ("get_num -- number at '%s' too large", start);
+ return NULL;
+ }
+ if (tld)
+ {
+ if (*s != '#')
+ {
+ error ("get_num -- expecting '#' at end of number");
+ return NULL;
+ }
+ ++s;
+ }
+ }
+ else if (*s == '@' || (tld = (*s == '2' && *(s + 1) == '#')))
+ {
+ s += (tld ? 2 : 1);
+ start = s;
+ while (*s == '0' || *s == '1')
+ {
+ *outnum = (*outnum << 1) | (*s - '0');
+ ++s;
+ }
+ if (s - start > 16)
+ {
+ error ("get_num -- number at '%s' too large", start);
+ return NULL;
+ }
+ if (tld)
+ {
+ if (*s != '#')
+ {
+ error ("get_num -- expecting '#' at end of number");
+ return NULL;
+ }
+ ++s;
+ }
+ }
+ else if (isdigit (*s))
+ {
+ start = s;
+ while (isdigit (*s))
+ {
+ *outnum = (*outnum * 10) + dtoi (*s);
+ ++s;
+ }
+ if (s - start > 5)
+ {
+ error ("get_num -- number at '%s' too large", start);
+ return NULL;
+ }
+ }
+ else if (*s == '\'')
+ {
+ start = s;
+ if (*++s == '\\')
+ {
+ switch (*++s)
+ {
+ case 't':
+ *outnum = 9;
+ break;
+ case 'n':
+ *outnum = 10;
+ break;
+ case 'r':
+ *outnum = 13;
+ break;
+ default:
+ error ("get_num -- unknown escape '\\%c'", *s);
+ return NULL;
+ }
+ }
+ else
+ *outnum = (int) *s & 0xFF;
+ if (*++s != '\'')
+ {
+ error ("get_num -- character constant incorrectly terminated", start);
+ return NULL;
+ }
+ ++s;
+ }
+ else if (*s == '"')
+ {
+ start = s;
+ *outnum = ((int) *++s & 0xFF) << 8;
+ *outnum |= (int) *++s & 0xFF;
+ if (*++s != '"')
+ {
+ error ("get_num -- character tuple incorrectly terminated", start);
+ return NULL;
+ }
+ ++s;
+ }
+ else
+ return NULL;
+ if (is_neg)
+ *outnum = -*outnum;
+ return s;
+}
+
+/* Get a constant symbol (previously defined by EQU) or a number.
+ * Return pointer to first character after the symbol or number consumed,
+ * or NULL if reading the symbol or number was unsuccessful.
+ */
+char *
+get_sym_num (char *s, int *outnum)
+{
+ char *p, c;
+ symbol_t sym;
+
+ if ((p = get_num (s, outnum)) != NULL)
+ return p;
+
+ /* Didn't find a raw number; try symbol. */
+ if (!issymstart (*s))
+ {
+ error ("expecting symbol at '%s'", s);
+ return NULL;
+ }
+ p = s;
+ while (issymchar (*p))
+ p++;
+ c = *p;
+ *p = '\0';
+ if ((sym = find_symbol (s)) == SNULL)
+ {
+ error ("unidentified symbol at '%s'", s);
+ return NULL;
+ }
+ *p = c;
+ if (!sym->is_constant)
+ {
+ error ("symbol must be constant in this context");
+ return NULL;
+ }
+ *outnum = (int) sym->value;
+ return p;
+}
+
+
+extern int curr_frag; /* imported from main.c */
+
+/* Enter a 16-bit word into the object space */
+void
+add_word (ushort word)
+{
+ struct objblock *obj = &objblk[curr_frag];
+
+ if (obj->data == (ushort *) 0)
+ {
+ obj->n_allocated = 256;
+ obj->data = (ushort *) malloc (obj->n_allocated * sizeof (ushort));
+ obj->line = (struct linelist **) malloc
+ (obj->n_allocated * sizeof (struct linelist *));
+ }
+ else if (obj->n_used == obj->n_allocated)
+ {
+ obj->n_allocated *= 2;
+ obj->data = (ushort *) realloc (obj->data,
+ obj->n_allocated * sizeof (ushort));
+ obj->line = (struct linelist **) realloc (obj->line,
+ obj->n_allocated * sizeof (struct linelist *));
+ }
+ if (obj->data == (ushort *) 0 || obj->line == (struct linelist **) 0)
+ problem ("request for object space refused by OS");
+ obj->data[obj->n_used] = word;
+ obj->line[obj->n_used] = line;
+ obj->n_used++;
+}
+
+void
+add_reloc (symbol_t sym) /* auxiliary to parse_addr() */
+{
+ struct reloc *rel;
+
+ if (relblk.data == (struct reloc *) 0)
+ {
+ relblk.n_allocated = 256;
+ relblk.data = (struct reloc *) malloc
+ (relblk.n_allocated * sizeof (struct reloc));
+ }
+ else if (relblk.n_used == relblk.n_allocated)
+ {
+ relblk.n_allocated *= 2;
+ relblk.data = (struct reloc *) realloc (relblk.data,
+ relblk.n_allocated * sizeof (struct reloc));
+ }
+ if (relblk.data == (struct reloc *) 0)
+ problem ("request for relocation space refused by OS");
+ rel = &relblk.data[relblk.n_used];
+ rel->done = FALSE; /* default initializations */
+ rel->reltype = Word_Reloc;
+ rel->frag_index = curr_frag;
+ rel->obj_index = objblk[curr_frag].n_used;
+ rel->sym = sym;
+ relblk.n_used++;
+}
+
+
+/* Parse the address expression at s into object space.
+ Returns OKAY or ERROR. */
+status
+parse_addr (char *s)
+{
+ int num;
+ char *p, c, c1;
+ symbol_t sym, sym1;
+
+ if (issymstart (*s))
+ {
+ p = skip_symbol (s);
+ c = *p; /* prepare for symbol lookup */
+ *p = '\0';
+ if ((sym = find_or_enter (s)) == SNULL)
+ return ERROR;
+ sym->is_referenced = TRUE;
+ *p = c;
+ s = p++;
+ if (c == '\0')
+ {
+ if (sym->is_constant)
+ add_word ((ushort) sym->value);
+ else
+ {
+ add_reloc (sym);
+ add_word (0);
+ }
+ }
+ else if (c != '+' && c != '-')
+ return error ("error after symbolname at: %s", s);
+ else if (issymstart (*p))
+ {
+ s = skip_symbol (p);
+ if (*s != '\0' && *s != ',')
+ return error ("address expression too complex");
+ c1 = *s; /* prepare for symbol lookup */
+ *s = '\0';
+ if ((sym1 = find_or_enter (p)) == SNULL)
+ return ERROR;
+ sym1->is_referenced = TRUE;
+ *s = c1;
+ if (c == '+')
+ {
+ if (sym->is_constant)
+ {
+ if (sym1->is_constant)
+ {
+ long sum = sym->value + sym1->value;
+ if (sum < -0x8000L)
+ return error ("negative overflow in symbol addition");
+ else if (sum > 0xFFFFL)
+ return error ("positive overflow in symbol addition");
+ add_word ((ushort) sum);
+ }
+ else
+ {
+ add_reloc (sym1);
+ add_word ((ushort) sym->value);
+ }
+ }
+ else
+ {
+ if (sym1->is_constant)
+ {
+ add_reloc (sym);
+ add_word ((ushort) sym1->value);
+ }
+ else
+ return error ("cannot add relocatable symbols");
+ }
+ }
+ else
+ /* subtraction */
+ {
+ if (sym->is_constant)
+ {
+ if (sym1->is_constant)
+ {
+ long dif = sym->value - sym1->value;
+ if (dif < -0x8000L)
+ return error ("negative overflow in symbol subtraction");
+ else if (dif > 0xFFFFL)
+ return error ("positive overflow symbol subtraction");
+ add_word ((ushort) dif);
+ }
+ else
+ error ("cannot subtract relocatable symbol from constant symbol");
+ }
+ else
+ {
+ if (sym1->is_constant)
+ {
+ add_reloc (sym);
+ add_word ((ushort) - sym1->value);
+ }
+ else
+ {
+ if (objblk[sym->frag_index].section !=
+ objblk[sym1->frag_index].section)
+ return error
+ ("cannot subtract relocatable symbols from different fragments");
+ if (sym->value < sym1->value)
+ error ("warning: strange subtraction of relocatable symbols");
+ add_word ((ushort) (sym->value - sym1->value));
+ }
+ }
+ }
+ }
+ else
+ {
+ if (get_num (s, &num) == NULL)
+ return ERROR;
+ if (sym->is_constant)
+ {
+ long sum = sym->value + (long) num;
+ if (sum < -32768L)
+ return error ("neg. overflow in symbolic expression");
+ else if (sum > 65535L)
+ return error ("overflow in symbolic expression");
+ add_word ((ushort) sum);
+ }
+ else
+ {
+ add_reloc (sym);
+ add_word ((ushort) num);
+ }
+ }
+ }
+ else if ((s = get_num (s, &num)) == NULL)
+ return ERROR;
+ else
+ {
+ if (*s == '\0')
+ add_word ((ushort) num);
+ else if (*s != '+')
+ return error ("expected '+' in address expression at: %s", s);
+ else
+ {
+ ++s;
+ if (!issymstart (*s))
+ return error ("expected symbolname in address expression at: %s", s);
+ p = skip_symbol (s);
+ if (*p != '\0' && *p != ',')
+ return error ("illegal characters after symbolname at: %s", s);
+ c = *p; /* prepare for symbol lookup */
+ *p = '\0';
+ if ((sym = find_or_enter (s)) == SNULL)
+ return ERROR;
+ sym->is_referenced = TRUE;
+ *p = c;
+ s = p;
+ if (sym->is_constant)
+ add_word ((ushort) (sym->value + (long) num));
+ else
+ {
+ add_reloc (sym);
+ add_word ((ushort) num);
+ }
+ }
+ }
+ return OKAY;
+}
+
+#else /* ASL */
+
+static char *
+get_sym_num (char *s, int *outnum)
+{
+ Boolean okay;
+ *outnum = (int) EvalIntExpression (s, Int16, &okay);
+ if (!okay)
+ return NULL;
+ return (s + strlen (s)); /* Any non-NULL value will do here. */
+}
+
+
+#define add_word(word) WAsmCode[CodeLen++]=word
+
+static status
+parse_addr (char *s)
+{
+ int value;
+ Boolean okay;
+ value = (int) EvalIntExpression (s, Int16, &okay);
+ if (!okay)
+ return ERROR;
+ add_word ((ushort) value);
+ return OKAY;
+}
+
+#endif /* from #else of #ifdef AS1750 */
+
+/* From here on, everything is identical between as1750 and ASL. */
+
+static ushort
+get_num_bounded (char *s, int lowlim, int highlim)
+{
+ int num;
+ if (get_sym_num (s, &num) == NULL)
+ return ERROR;
+ if (num < lowlim || num > highlim)
+ return error ("number not in range %d..%d", lowlim, highlim);
+ return (ushort) num;
+}
+
+static ushort
+get_regnum (char *s)
+{
+ ushort regnum;
+ *s = toupper (*s);
+ if (*s != 'R')
+ return error ("expecting register at '%s'", s);
+ ++s;
+ if (!isdigit (*s))
+ return error ("expecting register at '%s'", s);
+ regnum = dtoi (*s);
+ ++s;
+ if (isdigit (*s))
+ {
+ regnum = regnum * 10 + dtoi (*s);
+ if (regnum > 15)
+ return error ("register number out of range");
+ ++s;
+ }
+ return regnum;
+}
+
+
+/**********************************************************************/
+/* Functions to process opcode arguments according to addressing mode */
+
+static int n_args;
+static char *arg[4];
+
+static status
+check_indexreg (void)
+{
+ if (n_args > 2)
+ {
+ ushort rx;
+
+ if ((rx = get_regnum (arg[2])) == ERROR)
+ return ERROR;
+ if (rx == 0)
+ return error ("R0 not an index register");
+#ifdef AS1750
+ objblk[curr_frag].data[objblk[curr_frag].n_used - 2] |= rx;
+#else /* ASL */
+ WAsmCode[0] |= rx;
+#endif
+ }
+ return OKAY;
+}
+
+
+static ushort
+as_r (ushort oc)
+{
+ ushort ra, rb;
+ if (n_args != 2)
+ return error ("incorrect number of operands");
+ if ((ra = get_regnum (arg[0])) == ERROR)
+ return ERROR;
+ if ((rb = get_regnum (arg[1])) == ERROR)
+ return ERROR;
+
+ add_word (oc | (ra << 4) | rb);
+ return 1;
+}
+
+static ushort
+as_mem (ushort oc)
+{
+ ushort ra;
+ if (n_args < 2)
+ return error ("insufficient number of operands");
+ if ((ra = get_regnum (arg[0])) == ERROR)
+ return ERROR;
+ add_word (oc | (ra << 4));
+ if (parse_addr (arg[1]))
+ return ERROR;
+ if (check_indexreg ())
+ return ERROR;
+ return 2;
+}
+
+static ushort
+as_addr (ushort oc) /* LST and LSTI */
+{
+ if (n_args < 1)
+ return error ("insufficient number of operands");
+ add_word (oc);
+ if (parse_addr (arg[0]))
+ return ERROR;
+ n_args++; /* cheat check_indexreg() */
+ arg[2] = arg[1];
+ if (check_indexreg ())
+ return ERROR;
+ return 2;
+}
+
+static ushort
+as_xmem (ushort oc) /* MIL-STD-1750B extended mem. addr. */
+{
+ ushort ra;
+
+ if (n_args < 2)
+ return error ("insufficient number of operands");
+ if ((ra = get_regnum (arg[0])) == ERROR)
+ return ERROR;
+ add_word (oc | (ra << 4));
+ if (parse_addr (arg[1]))
+ return ERROR;
+ if (n_args > 2)
+ {
+ ushort rx;
+ if ((rx = get_regnum (arg[2])) == ERROR)
+ return ERROR;
+#ifdef AS1750
+ objblk[curr_frag].data[objblk[curr_frag].n_used - 2] |= rx;
+#else /* ASL */
+ WAsmCode[0] |= rx;
+#endif
+ }
+ return 2;
+}
+
+static ushort
+as_im_0_15 (ushort oc) /* for STC, LM, TB,SB,RB,TSB */
+{
+ ushort ra;
+ if (n_args < 2)
+ return error ("insufficient number of operands");
+ if ((ra = get_num_bounded (arg[0], 0, 15)) == ERROR)
+ return ERROR;
+ add_word (oc | (ra << 4));
+ if (parse_addr (arg[1]))
+ return ERROR;
+ if (check_indexreg ())
+ return ERROR;
+ return 2;
+}
+
+static ushort
+as_im_1_16 (ushort oc)
+{
+ ushort ra;
+ if (n_args < 2)
+ return error ("insufficient number of operands");
+ if ((ra = get_num_bounded (arg[0], 1, 16)) == ERROR)
+ return ERROR;
+ add_word (oc | ((ra - 1) << 4));
+ if (parse_addr (arg[1]))
+ return ERROR;
+ if (check_indexreg ())
+ return ERROR;
+ return 2;
+}
+
+static ushort
+as_im_ocx (ushort oc)
+{
+ ushort ra;
+ if (n_args != 2)
+ return error ("incorrect number of operands");
+ if ((ra = get_regnum (arg[0])) == ERROR)
+ return ERROR;
+ add_word (oc | (ra << 4)); /* oc has OCX in LSnibble */
+ if (parse_addr (arg[1]))
+ return ERROR;
+ return 2;
+}
+
+static ushort
+as_is (ushort oc)
+{
+ ushort ra, i;
+ if (n_args != 2)
+ return error ("incorrect number of operands");
+ if ((ra = get_regnum (arg[0])) == ERROR)
+ return ERROR;
+ if ((i = get_num_bounded (arg[1], 1, 16)) == ERROR)
+ return ERROR;
+ add_word (oc | (ra << 4) | (i - 1));
+ return 1;
+}
+
+static ushort
+as_icr (ushort oc)
+{
+#ifdef AS1750
+ struct objblock *obj = &objblk[curr_frag];
+ int last = obj->n_used;
+#endif
+ if (n_args != 1)
+ return error ("incorrect number of operands");
+ if (parse_addr (arg[0]))
+ return ERROR;
+#ifdef AS1750
+ /* If symbol relocation, then set the relocation type to Byte_Reloc */
+ if (relblk.n_used > 0)
+ {
+ struct reloc *rel = &relblk.data[relblk.n_used - 1];
+ if (rel->frag_index == curr_frag && rel->obj_index == last)
+ rel->reltype = Byte_Reloc;
+ }
+ obj->data[last] &= 0x00FF;
+ obj->data[last] |= oc;
+#else /* ASL */
+ {
+ const short target = (short) WAsmCode[0];
+ const long curr_pc = (long) EProgCounter () & 0xFFFFL;
+ const long diff = (long) target - curr_pc;
+ if (diff < -128L || diff > 127L)
+ return error
+ ("address distance too large in Instruction Counter Relative operation");
+ WAsmCode[0] = oc | (ushort) (diff & 0xFFL);
+ }
+#endif
+ return 1;
+}
+
+static ushort
+as_b (ushort oc)
+{
+ char r;
+ ushort br, lobyte;
+ if (n_args != 2)
+ return error ("incorrect number of operands");
+ r = toupper (*arg[0]);
+ if (r != 'B' && r != 'R')
+ return error ("expecting base register");
+ if ((br = get_num_bounded (arg[0] + 1, 12, 15)) == ERROR)
+ return ERROR;
+ if ((lobyte = get_num_bounded (arg[1], 0, 255)) == ERROR)
+ return ERROR;
+ add_word (oc | ((br - 12) << 8) | lobyte);
+ return 1;
+}
+
+static ushort
+as_bx (ushort oc)
+{
+ char r;
+ ushort br, rx = 0;
+ if (n_args != 2)
+ return error ("incorrect number of operands");
+ r = toupper (*arg[0]);
+ if ((r != 'B' && r != 'R')
+ || (br = get_num_bounded (arg[0] + 1, 12, 15)) == ERROR)
+ return error ("expecting base register");
+ if ((rx = get_regnum (arg[1])) == ERROR)
+ return ERROR;
+ if (rx == 0)
+ return error ("R0 not an index register");
+ add_word (oc | ((br - 12) << 8) | rx);
+ return 1;
+}
+
+static ushort
+as_r_imm (ushort oc) /* for shifts with immediate shiftcount */
+{
+ ushort rb, n;
+ if (n_args != 2)
+ return error ("incorrect number of operands");
+ if ((rb = get_regnum (arg[0])) == ERROR)
+ return ERROR;
+ if ((n = get_num_bounded (arg[1], 1, 16)) == ERROR)
+ return ERROR;
+ add_word (oc | ((n - 1) << 4) | rb);
+ return 1;
+}
+
+static ushort
+as_imm_r (ushort oc) /* for test/set/reset-bit in reg. */
+{
+ ushort n, rb;
+ if (n_args != 2)
+ return error ("incorrect number of operands");
+ if ((n = get_num_bounded (arg[0], 0, 15)) == ERROR)
+ return ERROR;
+ if ((rb = get_regnum (arg[1])) == ERROR)
+ return ERROR;
+ add_word (oc | (n << 4) | rb);
+ return 1;
+}
+
+static ushort
+as_jump (ushort oc)
+{
+ ushort condcode = 0xFFFF;
+ static const struct
+ {
+ char *name;
+ ushort value;
+ }
+ cond[] =
+ { /* CPZN */
+ { "LT", 0x1 }, /* 0001 */
+ { "LZ", 0x1 }, /* 0001 */
+ { "EQ", 0x2 }, /* 0010 */
+ { "EZ", 0x2 }, /* 0010 */
+ { "LE", 0x3 }, /* 0011 */
+ { "LEZ", 0x3 }, /* 0011 */
+ { "GT", 0x4 }, /* 0100 */
+ { "GTZ", 0x4 }, /* 0100 */
+ { "NE", 0x5 }, /* 0101 */
+ { "NZ", 0x5 }, /* 0101 */
+ { "GE", 0x6 }, /* 0110 */
+ { "GEZ", 0x6 }, /* 0110 */
+ { "ALL", 0x7 }, /* 0111 */
+ { "CY", 0x8 }, /* 1000 */
+ { "CLT", 0x9 }, /* 1001 */
+ { "CEQ", 0xA }, /* 1010 */
+ { "CEZ", 0xA }, /* 1010 */
+ { "CLE", 0xB }, /* 1011 */
+ { "CGT", 0xC }, /* 1100 */
+ { "CNZ", 0xD }, /* 1101 */
+ { "CGE", 0xE }, /* 1110 */
+ { "UC", 0xF } /* 1111 */
+ };
+ if (n_args < 2)
+ return error ("insufficient number of operands");
+ if (isalpha (*arg[0]))
+ {
+ int i;
+ for (i = 0; i < 22; i++)
+ if (!strcasecmp (arg[0], cond[i].name))
+ {
+ condcode = cond[i].value;
+ break;
+ }
+ }
+ if (condcode == 0xFFFF)
+ if ((condcode = get_num_bounded (arg[0], 0, 15)) == ERROR)
+ return ERROR;
+ add_word (oc | (condcode << 4));
+ if (parse_addr (arg[1]))
+ return ERROR;
+ if (check_indexreg ())
+ return ERROR;
+ return 2;
+}
+
+static ushort
+as_s (ushort oc) /* For the moment, BEX only. */
+{
+ ushort lsnibble;
+ if (n_args != 1)
+ return error ("incorrect number of operands");
+ if ((lsnibble = get_num_bounded (arg[0], 0, 15)) == ERROR)
+ return ERROR;
+ add_word (oc | lsnibble);
+ return 1;
+}
+
+static ushort
+as_sr (ushort oc) /* XBR and URS. */
+{
+ ushort hlp;
+ if (n_args != 1)
+ return error ("incorrect number of operands");
+ if ((hlp = get_regnum (arg[0])) == ERROR)
+ return ERROR;
+ add_word (oc | (hlp << 4));
+ return 1;
+}
+
+static ushort
+as_xio (ushort oc)
+{
+ ushort ra;
+ int cmdfld = -1;
+ static const struct
+ {
+ char *mnem;
+ ushort cmd;
+ }
+ xio[] =
+ {
+ { "SMK", 0x2000 },
+ { "CLIR", 0x2001 },
+ { "ENBL", 0x2002 },
+ { "DSBL", 0x2003 },
+ { "RPI", 0x2004 },
+ { "SPI", 0x2005 },
+ { "OD", 0x2008 },
+ { "RNS", 0x200A },
+ { "WSW", 0x200E },
+ { "CO", 0x4000 },
+ { "CLC", 0x4001 },
+ { "MPEN", 0x4003 },
+ { "ESUR", 0x4004 },
+ { "DSUR", 0x4005 },
+ { "DMAE", 0x4006 },
+ { "DMAD", 0x4007 },
+ { "TAS", 0x4008 },
+ { "TAH", 0x4009 },
+ { "OTA", 0x400A },
+ { "GO", 0x400B },
+ { "TBS", 0x400C },
+ { "TBH", 0x400D },
+ { "OTB", 0x400E },
+ { "LMP", 0x5000 },
+ { "WIPR", 0x5100 },
+ { "WOPR", 0x5200 },
+ { "RMP", 0xD000 },
+ { "RIPR", 0xD100 },
+ { "ROPR", 0xD200 },
+ { "RMK", 0xA000 },
+ { "RIC1", 0xA001 },
+ { "RIC2", 0xA002 },
+ { "RPIR", 0xA004 },
+ { "RDOR", 0xA008 },
+ { "RDI", 0xA009 },
+ { "TPIO", 0xA00B },
+ { "RMFS", 0xA00D },
+ { "RSW", 0xA00E },
+ { "RCFR", 0xA00F },
+ { "CI", 0xC000 },
+ { "RCS", 0xC001 },
+ { "ITA", 0xC00A },
+ { "ITB", 0xC00E },
+ { "", 0xFFFF }
+ };
+
+ if (n_args < 2)
+ return error ("incorrect number of operands");
+ if ((ra = get_regnum (arg[0])) == ERROR)
+ return ERROR;
+ add_word (oc | (ra << 4));
+ /* Get the XIO command field. */
+ if (isalpha (*arg[1]))
+ {
+ int i;
+ for (i = 0; xio[i].cmd != 0xFFFF; i++)
+ if (!strcasecmp (arg[1], xio[i].mnem))
+ break;
+ if (xio[i].cmd != 0xFFFF)
+ cmdfld = xio[i].cmd;
+ }
+ if (cmdfld == -1)
+ if (get_sym_num (arg[1], &cmdfld) == NULL)
+ return ERROR;
+ add_word ((ushort) cmdfld);
+ if (check_indexreg ())
+ return ERROR;
+ return 2;
+}
+
+static ushort
+as_none (ushort oc)
+{
+ add_word (oc);
+ return 1;
+}
+
+/* end of argument assembly functions */
+
+/***********************************************************************/
+
+static struct
+ {
+ char *mnemon;
+ ushort opcode;
+ ushort (*as_args) (ushort);
+ } optab[] =
+ {
+ { "AISP", 0xA200, as_is }, /* Sorted by beginning letter. */
+ { "AIM", 0x4A01, as_im_ocx }, /* Within each beginning letter, */
+ { "AR", 0xA100, as_r }, /* sorted by approximate */
+ { "A", 0xA000, as_mem }, /* instruction frequency. */
+ { "ANDM", 0x4A07, as_im_ocx },
+ { "ANDR", 0xE300, as_r },
+ { "AND", 0xE200, as_mem },
+ { "ABS", 0xA400, as_r },
+ { "AB", 0x1000, as_b },
+ { "ANDB", 0x3400, as_b },
+ { "ABX", 0x4040, as_bx },
+ { "ANDX", 0x40E0, as_bx },
+ { "BEZ", 0x7500, as_icr },
+ { "BNZ", 0x7A00, as_icr },
+ { "BGT", 0x7900, as_icr },
+ { "BLE", 0x7800, as_icr },
+ { "BGE", 0x7B00, as_icr },
+ { "BLT", 0x7600, as_icr },
+ { "BR", 0x7400, as_icr },
+ { "BEX", 0x7700, as_s },
+ { "BPT", 0xFFFF, as_none },
+ { "BIF", 0x4F00, as_s },
+ { "CISP", 0xF200, as_is },
+ { "CIM", 0x4A0A, as_im_ocx },
+ { "CR", 0xF100, as_r },
+ { "C", 0xF000, as_mem },
+ { "CISN", 0xF300, as_is },
+ { "CB", 0x3800, as_b },
+ { "CBL", 0xF400, as_mem },
+ { "CBX", 0x40C0, as_bx },
+ { "DLR", 0x8700, as_r },
+ { "DL", 0x8600, as_mem },
+ { "DST", 0x9600, as_mem },
+ { "DSLL", 0x6500, as_r_imm },
+ { "DSRL", 0x6600, as_r_imm },
+ { "DSRA", 0x6700, as_r_imm },
+ { "DSLC", 0x6800, as_r_imm },
+ { "DSLR", 0x6D00, as_r },
+ { "DSAR", 0x6E00, as_r },
+ { "DSCR", 0x6F00, as_r },
+ { "DECM", 0xB300, as_im_1_16 },
+ { "DAR", 0xA700, as_r },
+ { "DA", 0xA600, as_mem },
+ { "DSR", 0xB700, as_r },
+ { "DS", 0xB600, as_mem },
+ { "DMR", 0xC700, as_r },
+ { "DM", 0xC600, as_mem },
+ { "DDR", 0xD700, as_r },
+ { "DD", 0xD600, as_mem },
+ { "DCR", 0xF700, as_r },
+ { "DC", 0xF600, as_mem },
+ { "DLB", 0x0400, as_b },
+ { "DSTB", 0x0C00, as_b },
+ { "DNEG", 0xB500, as_r },
+ { "DABS", 0xA500, as_r },
+ { "DR", 0xD500, as_r },
+ { "D", 0xD400, as_mem },
+ { "DISP", 0xD200, as_is },
+ { "DIM", 0x4A05, as_im_ocx },
+ { "DISN", 0xD300, as_is },
+ { "DVIM", 0x4A06, as_im_ocx },
+ { "DVR", 0xD100, as_r },
+ { "DV", 0xD000, as_mem },
+ { "DLI", 0x8800, as_mem },
+ { "DSTI", 0x9800, as_mem },
+ { "DB", 0x1C00, as_b },
+ { "DBX", 0x4070, as_bx },
+ { "DLBX", 0x4010, as_bx },
+ { "DSTX", 0x4030, as_bx },
+ { "DLE", 0xDF00, as_xmem },
+ { "DSTE", 0xDD00, as_xmem },
+ { "EFL", 0x8A00, as_mem },
+ { "EFST", 0x9A00, as_mem },
+ { "EFCR", 0xFB00, as_r },
+ { "EFC", 0xFA00, as_mem },
+ { "EFAR", 0xAB00, as_r },
+ { "EFA", 0xAA00, as_mem },
+ { "EFSR", 0xBB00, as_r },
+ { "EFS", 0xBA00, as_mem },
+ { "EFMR", 0xCB00, as_r },
+ { "EFM", 0xCA00, as_mem },
+ { "EFDR", 0xDB00, as_r },
+ { "EFD", 0xDA00, as_mem },
+ { "EFLT", 0xEB00, as_r },
+ { "EFIX", 0xEA00, as_r },
+ { "FAR", 0xA900, as_r },
+ { "FA", 0xA800, as_mem },
+ { "FSR", 0xB900, as_r },
+ { "FS", 0xB800, as_mem },
+ { "FMR", 0xC900, as_r },
+ { "FM", 0xC800, as_mem },
+ { "FDR", 0xD900, as_r },
+ { "FD", 0xD800, as_mem },
+ { "FCR", 0xF900, as_r },
+ { "FC", 0xF800, as_mem },
+ { "FABS", 0xAC00, as_r },
+ { "FIX", 0xE800, as_r },
+ { "FLT", 0xE900, as_r },
+ { "FNEG", 0xBC00, as_r },
+ { "FAB", 0x2000, as_b },
+ { "FABX", 0x4080, as_bx },
+ { "FSB", 0x2400, as_b },
+ { "FSBX", 0x4090, as_bx },
+ { "FMB", 0x2800, as_b },
+ { "FMBX", 0x40A0, as_bx },
+ { "FDB", 0x2C00, as_b },
+ { "FDBX", 0x40B0, as_bx },
+ { "FCB", 0x3C00, as_b },
+ { "FCBX", 0x40D0, as_bx },
+ { "INCM", 0xA300, as_im_1_16 },
+ { "JC", 0x7000, as_jump },
+ { "J", 0x7400, as_icr }, /* TBD (GAS) */
+ { "JEZ", 0x7500, as_icr }, /* TBD (GAS) */
+ { "JLE", 0x7800, as_icr }, /* TBD (GAS) */
+ { "JGT", 0x7900, as_icr }, /* TBD (GAS) */
+ { "JNZ", 0x7A00, as_icr }, /* TBD (GAS) */
+ { "JGE", 0x7B00, as_icr }, /* TBD (GAS) */
+ { "JLT", 0x7600, as_icr }, /* TBD (GAS) */
+ { "JCI", 0x7100, as_jump },
+ { "JS", 0x7200, as_mem },
+ { "LISP", 0x8200, as_is },
+ { "LIM", 0x8500, as_mem },
+ { "LR", 0x8100, as_r },
+ { "L", 0x8000, as_mem },
+ { "LISN", 0x8300, as_is },
+ { "LB", 0x0000, as_b },
+ { "LBX", 0x4000, as_bx },
+ { "LSTI", 0x7C00, as_addr },
+ { "LST", 0x7D00, as_addr },
+ { "LI", 0x8400, as_mem },
+ { "LM", 0x8900, as_im_0_15 },
+ { "LUB", 0x8B00, as_mem },
+ { "LLB", 0x8C00, as_mem },
+ { "LUBI", 0x8D00, as_mem },
+ { "LLBI", 0x8E00, as_mem },
+ { "LE", 0xDE00, as_xmem },
+ { "MISP", 0xC200, as_is },
+ { "MSIM", 0x4A04, as_im_ocx },
+ { "MSR", 0xC100, as_r },
+ { "MS", 0xC000, as_mem },
+ { "MISN", 0xC300, as_is },
+ { "MIM", 0x4A03, as_im_ocx },
+ { "MR", 0xC500, as_r },
+ { "M", 0xC400, as_mem },
+ { "MOV", 0x9300, as_r },
+ { "MB", 0x1800, as_b },
+ { "MBX", 0x4060, as_bx },
+ { "NEG", 0xB400, as_r },
+ { "NOP", 0xFF00, as_none },
+ { "NIM", 0x4A0B, as_im_ocx },
+ { "NR", 0xE700, as_r },
+ { "N", 0xE600, as_mem },
+ { "ORIM", 0x4A08, as_im_ocx },
+ { "ORR", 0xE100, as_r },
+ { "OR", 0xE000, as_mem },
+ { "ORB", 0x3000, as_b },
+ { "ORBX", 0x40F0, as_bx },
+ { "PSHM", 0x9F00, as_r },
+ { "POPM", 0x8F00, as_r },
+ { "RBR", 0x5400, as_imm_r },
+ { "RVBR", 0x5C00, as_r },
+ { "RB", 0x5300, as_im_0_15 },
+ { "RBI", 0x5500, as_im_0_15 },
+ { "ST", 0x9000, as_mem },
+ { "STC", 0x9100, as_im_0_15 },
+ { "SISP", 0xB200, as_is },
+ { "SIM", 0x4A02, as_im_ocx },
+ { "SR", 0xB100, as_r },
+ { "S", 0xB000, as_mem },
+ { "SLL", 0x6000, as_r_imm },
+ { "SRL", 0x6100, as_r_imm },
+ { "SRA", 0x6200, as_r_imm },
+ { "SLC", 0x6300, as_r_imm },
+ { "SLR", 0x6A00, as_r },
+ { "SAR", 0x6B00, as_r },
+ { "SCR", 0x6C00, as_r },
+ { "SJS", 0x7E00, as_mem },
+ { "STB", 0x0800, as_b },
+ { "SBR", 0x5100, as_imm_r },
+ { "SB", 0x5000, as_im_0_15 },
+ { "SVBR", 0x5A00, as_r },
+ { "SOJ", 0x7300, as_mem },
+ { "SBB", 0x1400, as_b },
+ { "STBX", 0x4020, as_bx },
+ { "SBBX", 0x4050, as_bx },
+ { "SBI", 0x5200, as_im_0_15 },
+ { "STZ", 0x9100, as_addr },
+ { "STCI", 0x9200, as_im_0_15 },
+ { "STI", 0x9400, as_mem },
+ { "SFBS", 0x9500, as_r },
+ { "SRM", 0x9700, as_mem },
+ { "STM", 0x9900, as_im_0_15 },
+ { "STUB", 0x9B00, as_mem },
+ { "STLB", 0x9C00, as_mem },
+ { "SUBI", 0x9D00, as_mem },
+ { "SLBI", 0x9E00, as_mem },
+ { "STE", 0xDC00, as_xmem },
+ { "TBR", 0x5700, as_imm_r },
+ { "TB", 0x5600, as_im_0_15 },
+ { "TBI", 0x5800, as_im_0_15 },
+ { "TSB", 0x5900, as_im_0_15 },
+ { "TVBR", 0x5E00, as_r },
+ { "URS", 0x7F00, as_sr },
+ { "UAR", 0xAD00, as_r },
+ { "UA", 0xAE00, as_mem },
+ { "USR", 0xBD00, as_r },
+ { "US", 0xBE00, as_mem },
+ { "UCIM", 0xF500, as_im_ocx },
+ { "UCR", 0xFC00, as_r },
+ { "UC", 0xFD00, as_mem },
+ { "VIO", 0x4900, as_mem },
+ { "XORR", 0xE500, as_r },
+ { "XORM", 0x4A09, as_im_ocx },
+ { "XOR", 0xE400, as_mem },
+ { "XWR", 0xED00, as_r },
+ { "XBR", 0xEC00, as_sr },
+ { "XIO", 0x4800, as_xio },
+ { "", 0, as_none } /* end-of-array marker */
+};
+
+/* Offset table with indexes into optab: indexed by starting letter
+ (A => 0, B => 1, ..., Z => 25), returns the starting index
+ and number of entries for that letter in optab[].
+ start_index is -1 if no entries for that starting letter in optab[]. */
+
+static struct
+ {
+ int start_index;
+ int n_entries;
+ }
+ofstab[26];
+
+/* Initialize ofstab[]. This must be called before as1750() can be used. */
+void
+init_as1750 ()
+{
+ int optab_ndx, ofstab_ndx = 1;
+ char c;
+
+ ofstab[0].start_index = 0;
+ ofstab[0].n_entries = 1;
+ for (optab_ndx = 1; (c = *optab[optab_ndx].mnemon) != '\0'; optab_ndx++)
+ {
+ if (c != *optab[optab_ndx - 1].mnemon)
+ {
+ while (ofstab_ndx != c - 'A')
+ ofstab[ofstab_ndx++].start_index = -1;
+ ofstab[ofstab_ndx].start_index = optab_ndx;
+ ofstab[ofstab_ndx++].n_entries = 1;
+ }
+ else
+ ofstab[ofstab_ndx - 1].n_entries++;
+ }
+}
+
+
+/************************** HERE'S THE BEEF: ****************************/
+
+ushort
+as1750 (char *operation, int n_operands, char *operand[])
+{
+ int i, optab_ndx, firstletter;
+ bool found = FALSE;
+
+ if (n_operands < 0 || n_operands > 3 || *operation < 'A' || *operation > 'X')
+ return NO_OPCODE;
+ n_args = n_operands;
+ for (i = 0; i < n_args; i++)
+ arg[i] = operand[i];
+ firstletter = (int) (*operation - 'A');
+ if ((optab_ndx = ofstab[firstletter].start_index) < 0)
+ return NO_OPCODE;
+ for (i = 0; i < ofstab[firstletter].n_entries; i++, optab_ndx++)
+ if (!strcmp (operation + 1, optab[optab_ndx].mnemon + 1))
+ {
+ found = TRUE;
+ break;
+ }
+ if (!found)
+ return NO_OPCODE;
+ return (*optab[optab_ndx].as_args) (optab[optab_ndx].opcode);
+}
+
diff --git a/as1750.h b/as1750.h
new file mode 100644
index 0000000..2f9adf3
--- /dev/null
+++ b/as1750.h
@@ -0,0 +1,18 @@
+/* as1750.h -- exports of as1750.c */
+
+extern void init_as1750 ();
+extern unsigned short as1750 (char *operation,
+ int n_operands, char *operand[]);
+
+#ifdef AS1750
+extern void add_word (ushort word);
+extern void add_reloc (symbol_t sym);
+extern char *get_num (char *s, int *outnum);
+extern char *get_sym_num (char *s, int *outnum);
+extern status parse_addr (char *s);
+extern status error (char *layout, ...);
+#else /* ASL */
+#define OKAY 0
+#define ERROR 0xFFFD
+#define NO_OPCODE 0xFFFE
+#endif
diff --git a/asl.1 b/asl.1
new file mode 100644
index 0000000..557312a
--- /dev/null
+++ b/asl.1
@@ -0,0 +1,377 @@
+.TH asl 1
+
+.SH NAME
+.B asl \- cross assembler for microprocessors and -controllers
+
+.SH SYNTAX
+.B asl
+[ option(s) ] file(s) [ option(s) ] file(s) ...
+
+.SH DESCRIPTION
+
+AS is a cross assembler that can be used to write assembler programs
+for a variety of different microprocessors and -controllers.
+.B asl
+is the UNIX/C implementation of AS. A complete description of AS is
+far beyond the scope of this manual page, which is only intended as
+a quick reference for AS's command line interface. For a more detailed
+introduction into the usage of AS, see the user's manual.
+
+.SH COMMAND-LINE PARAMETERS
+
+Every argument that starts with a slash (/), plus (+) or minus (-) sign
+is regarded as a command-line parameter. Some command-line parameters
+take an argument as additional parameter. Every argument that is not
+recognized as a command-line parameter is regarded as an assembler source
+file to be assembled. A source file name that does not have an extension
+is automatically extended with the default extension '.asm'.
+Options are turned on with a parameter starting with
+a slash (/) or minus sign (-), whereas a parameter with a leading plus sign
+(+) turns an option off. In the following list, all options will be shown in
+the form that is needed to change the default behaviour, which might be a
+plus or minus sign, depening on wether the option is on or off by default.
+
+.B asl
+accepts the following command-line parameters:
+.TP
+.B -A
+
+Change the data structure that is internally used to store the symbol table.
+By default, AS uses binary trees to store macro and symbol definitions. Turning
+this option on will change this to AVL-balanced trees. Depending on the ratio
+of symbol entries and lookups, this might speed up assembly. Using AVL-balanced
+trees helps also reducing the stack usage, which is however irrelevant for the C
+version of AS.
+.TP
+.B -a
+
+Instruct AS to write out the shared symbol definitions in a format suitable
+for including into an AS assembler program. The file's name is constructed by
+replacing the source file's extension with '.inc'. See the user manual for more
+information about symbol sharing.
+.TP
+.B -cpu <name>
+Set the target processor to <name>. Use this option if the source file does
+not contain a CPU statement.
+.TP
+.B -alias <new name=old name>
+Define a CPU alias. An alias is a name that can be used as an argument to the
+CPU pseudo-instruction just like an intrinsic CPU type. Its usage will set
+the same target as the old name, however the predefined symbols MOMCPU and
+MOMCPUNAME will be set to the new name. This option is primarily useful for
+adding a new member to a processor family that has the same core, but is
+different in its internal peripherals, thus allowing to distinguish between
+them.
+.TP
+.B -C
+
+Add a cross reference table to the assembler listing. A cross reference
+table lists all symbols that have been referenced at least once during assembly,
+including the source line number(s) and count of every reference. This option
+only makes sense when the generation of an assembly listing has been turned on
+via the
+.B -L
+or
+.B -l
+parameters.
+.TP
+.B -c
+
+Instruct AS to write out the shared symbol definitions in a format suitable
+for including into a C program. The file's name is constructed by replacing
+the source file's extension with '.h'. See the user manual for more information
+about symbol sharing.
+.TP
+.B -D <name[=value]>[,...]
+Pre-define symbols. Predefined symbols are entered into the global symbol
+table prior to assembly of the source file(s). If no value is given for a
+symbol, it is assigned the integer value 1. Value expressions may contain
+arithmetic expressions as described in the user manual, but they may not
+reference any other predefined or internal symbols.
+.TP
+.B -E [file]
+Force AS to send warning and error messages to
+.B file
+rather than to the standard error output. The file names !0 to !4 are used
+to refer to the standard input, output, error, auxilliary, and printer channels
+predefined by the operating system (on some systems, some of these handles
+might not exist). If the [file] specification is omitted, a name is constructed
+by replacing the source file's extension with '.log'.
+.TP
+.B +G
+Supress code generation, reducing the functionality of AS to macro
+preprocessing.
+.TP
+.B -g [MAP/Atmel]
+
+Instruct AS to write an additional file containing debug information. This
+information covers the symbol table and the relation between source line
+numbers and machine addresses. The argument specifies whether debug info
+shall be written in AS's own MAP format or the object format for Atmel's AVR
+tools. If no argument is given, MAP will be chosen. The file's name is
+constructed by replacing the source file's extension with '.map' or '.obj'
+respectively.
+.TP
+.B -h
+
+Force AS to print all hexadecimal constants with lowercase letters, rather
+than with uppercase letters A..F which is the default.
+.TP
+.B -i <path[:path...]>
+Add new entries to the list of paths that are searched for include files.
+New entries are prepended to the current include path list, so if multiple
+paths are given with one command-line parameter, they will be entered into
+the path list in reverse order.
+.TP
+.B -I
+
+Add an include file list to the assembly listing. An include file list contains
+all files that have been included while assembling the source files, including
+multiple and nested inclusion. Nesting of inclusion is identified by different
+indention. This option only makes sense when the generation of an assembly
+listing has been turned on via the
+.B -L
+or
+.B -l
+parameters.
+.TP
+.B -L
+
+Turn on generation of an assembly listing and send it to a file whose name is
+constructed by replacing the source file's extension with '.lst'.
+.TP
+.B -l
+
+Turn on generation of an assembly listing and send it to the console.
+.TP
+.B -M
+
+Turn on generation of a macro definition file. A macro definition file is
+a file that contains all macro definitions that have been detected during
+assembly, in a format suitable for an inclusion into another file. The macro
+definition file's name is constructed by replacing the source file's
+extension with '.mac'.
+.TP
+.B -n
+
+Force AS to extend all error and warning messages with their internal error
+resp. warning number.
+.TP
+.B -o <name>
+Tell AS to write the code output to a file <name>. By default, the code
+output file's name is constructed by replacing the source file's extension
+with '.p'. If multiple files are assembled with one command, this parameter
+may also be given multiply. If there are less output specifications than
+source file names, AS will switch back to the default naming convention after
+all output specifications have been used up.
+.TP
+.B -shareout <name>
+Tell AS to write shared symbol definitions to a file <name>, instead of
+constructing the name from the source file's name. See the user manual for
+more information about symbol sharing.
+.TP
+.B -P
+
+Turn on generation of a macro output file. A macro output file contains the
+intermediate source code that remains after macro expansion and conditional assembly.
+The macro output file's name is constructed by replacing the source file's
+extension with '.i'.
+.TP
+.B -p
+
+Instruct AS to write out the shared symbol definitions in a format suitable
+for including into a Pascal or Modula-2 program. The file's name is
+constructed by replacing the source file's extension with '.inc'. See the
+user manual for more information about symbol sharing.
+.TP
+.B -q or -quiet
+Turn on silent assembly mode. In silent compilation mode, AS will not
+do any console output except for warning and error messages.
+.TP
+.B -r [pass number]
+Tell AS to output warnings when a situation appears in a source file that
+forces another pass of assembly. Such situations either take place when a symbol
+is undefined in the first pass or a symbol's value has changed compared to the
+previous pass. This option is useful to track down sources of excessive
+multi-passing, but be aware that it might yield a fairly large number of
+warnings, especially in the first pass. Optionally, a pass number may be added
+to this option to inhibit output until a certain pass is reached.
+.TP
+.B -s
+
+Add a section list to the assembly listing. A section list contains
+all sections that have been defined in the source files, marking their
+nesting level by different levels of indentation. This option only
+makes sense when the generation of an assembly listing has been turned
+on via the
+.B -L
+or
+.B -l
+parameters.
+.TP
+.B -t <mask>
+Turn on or off parts of the assembly listing that have no individual
+command line parameter. AS internally keeps an integer value whose bits
+represent certain components of the listing. A positive command line
+parameter (-t or /t) sets the bits set in <mask>, whereas a negated
+parameter (+t) resets the bits set in <mask>. The individual bits have
+the following meaning: bit 0 = source lines and generated machine code,
+bit 1 = symbol table, bit 2 = macro table, bit 3 = function table, bit 4 =
+line numbering.
+.TP
+.B -u
+
+Tell AS to do additional bookkeeping about which address ranges have been
+used by the assembled program. This option enables the detection of overlapping
+memory usage. If an assembly listing has been turned on via the
+.B -L
+or
+.B -l
+parameters, it will also contain a list of all used memory areas.
+.TP
+.B -U
+
+Force AS to operate in case-sensitive mode. By default, names of symbols,
+macros, user-defined functions and sections are treated in a case-insensitive
+manner.
+.TP
+.B -w
+
+Suppress output of warnings.
+.TP
+.B -x
+
+Turn on extended error reporting. With extended error reporting, several
+error and warning messages will also print the item that created the message,
+e.g. the name of an unknown instruction. When this option is given twice,
+the erroneous source line is additinally printed.
+
+.SH PRESETTING PARAMETERS
+
+Parameters need not neccessarily be given in the command line itself. Before
+processing of command line parameters starts, AS will look if the
+.B ASCMD
+environment variable is defined. If it exists, its contents will be
+treated as additional command line parameters whose syntax is absolutely
+equal to normal command line parameters. An exception is made if the
+variable's contents start with a '@' sign; in such a case, the string after
+the '@' sign is treated as the name of a file that contains the options.
+Such a file (also called a 'key file') has the advantage that it allows
+the options to be written in different lines, and it does not have a size
+limit. Some operating systems (like MS-DOS) have a length limit on
+command lines and environment variable contents, so the key file may be
+your only option if you have a lot of lengthy parameters for AS.
+
+As parameters given in the
+.B ASCMD
+environment variable or a key file are processed prior to the command line
+itself, and can therefore be overridden by command line parameters.
+
+.SH NATIONAL LANGUAGE SUPPORT
+
+AS supports the needs of different languages and countries in the sense that
+it will try to adapt to the language and date/time formats valid for the
+current environment. Upon startup, the COUNTRY setting made in the
+CONFIG.SYS file is queried for DOS and OS/2 implementations of AS. For
+UNIX systems, AS tries to read the LC_TIME resp. LC_MESSAGES environment
+variables to find out the correct format for date/time outputs resp. the
+local language. If this fails, the LC_ALL and finally LANG variables are
+probed. If none of these environment variables points to a specific local
+environment resp. contains a locale specification unknown to AS, the
+standard english/C locale is used.
+
+The messages AS can output in different languages are stored in separate
+files with the extension '.msg' . AS will search for these files in the
+following directories:
+
+- The current directory
+
+- The directory the executable of AS was loaded from (only on DOS platforms version >=3.0 or if path was explicitly specified)
+
+- The directory specified in the AS_MSGPATH environment variable resp. the directories listed in the PATH environment variable if AS_MSGPATH does not exist.
+
+- The LIBDIR directory set at compile time from the Makefile.
+
+
+.SH RETURN CODES
+
+Depending on the assembly's turnout,
+.B asl
+will generate different return codes:
+.TP
+.B 0
+No errors, warnings might have occured.
+.TP
+.B 1
+No command line parameters were given, AS printed a short list
+of possible command line parameters and terminated thereafter.
+.TP
+.B 2
+Errors occured during assembly of at least one source file, no
+code file was generated for the corresponding source file(s).
+.TP
+.B 3
+A fatal error occured during assembly that forced immediate
+program termination. Code files may be generated, but are probably
+unusuable.
+.TP
+.B 4
+Program termination already occured during initialization. This
+might be either due to a incorrect command line parameter or an error
+during loading the program's overlay file (only possible on MS-DOS).
+.TP
+.B 255
+During initialization, an internal error happened that should not
+occur. If the reaction is reproducable, note down the situation and
+send a bug report to the author.
+
+.SH EXAMPLES
+
+To assemble a source file
+.B file1.asm
+without any additional bells and whistles, use:
+.PP
+.B asl file1
+.PP
+which will create an output file
+.B file1.p
+given that there are no errors. If you additionally want a listing and
+rename the output file to
+.B a.out,
+use
+.PP
+.B asl -L file1 -o a.out
+.PP
+To make the listing as comprehensive as possible and to get more detailed
+error messages, use:
+.PP
+.B asl -LuCIs -t 16 -nx file1
+
+.SH TIPS
+
+calling AS without any parameters will print a short help containing all
+command line parameters and implemented target processors, while calling
+with command line parameters but without any source file name will result
+in AS asking for a source file name on the console.
+
+.SH SEE ALSO
+
+plist(1), pbind(1), p2hex(1), p2bin(1)
+
+.SH HISTORY
+
+AS originally appeared as a DOS program in 1989, written in
+Borland-Pascal, and was ported to C and UNIX in 1996.
+
+.SH BUGS
+
+There are too many options.
+
+Command line interpreters of some operating systems reserve some
+characters for their own use, so it might be necessary to give
+command line parameters with certain tricks (e.g., with the help
+of escape characters).
+
+.SH AUTHOR(S)
+
+Alfred Arnold (a.arnold@kfa-juelich.de), and a few others...
diff --git a/asl.def b/asl.def
new file mode 100644
index 0000000..827702b
--- /dev/null
+++ b/asl.def
@@ -0,0 +1,2 @@
+STACKSIZE 40960
+
diff --git a/asmallg.c b/asmallg.c
new file mode 100644
index 0000000..abe52a1
--- /dev/null
+++ b/asmallg.c
@@ -0,0 +1,1341 @@
+/* codeallg.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* von allen Codegeneratoren benutzte Pseudobefehle */
+/* */
+/* Historie: 10. 5.1996 Grundsteinlegung */
+/* 24. 6.1998 CODEPAGE-Kommando */
+/* 17. 7.1998 CHARSET ohne Argumente */
+/* 17. 8.1998 BookKeeping-Aufruf bei ALIGN */
+/* 18. 8.1998 RADIX-Kommando */
+/* 2. 1.1999 Standard-ChkPC-Routine */
+/* 9. 1.1999 BINCLUDE gefixt... */
+/* 30. 5.1999 OUTRADIX-Kommando */
+/* 12. 7.1999 EXTERN-Kommando */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+
+#include "nls.h"
+#include "strutil.h"
+#include "stringlists.h"
+#include "bpemu.h"
+#include "cmdarg.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmmac.h"
+#include "asmcode.h"
+#include "asmitree.h"
+#include "codepseudo.h"
+
+/*--------------------------------------------------------------------------*/
+
+static char *PseudoStrs[3]={Nil,Nil,Nil};
+
+static PInstTable PseudoTable=Nil,ONOFFTable;
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean DefChkPC(LargeWord Addr)
+BEGIN
+ if (((1 << ActPC) & ValidSegs) == 0) return 0;
+ else return (Addr <= SegLimits[ActPC]);
+END
+
+ void SetCPU(CPUVar NewCPU, Boolean NotPrev)
+BEGIN
+ LongInt HCPU;
+ char *z,*dest;
+ Boolean ECPU;
+ char s[11];
+ PCPUDef Lauf;
+
+ Lauf=FirstCPUDef;
+ while ((Lauf!=Nil) AND (Lauf->Number!=NewCPU)) Lauf=Lauf->Next;
+ if (Lauf==Nil) return;
+
+ strmaxcpy(MomCPUIdent,Lauf->Name,11);
+ MomCPU=Lauf->Orig;
+ MomVirtCPU=Lauf->Number;
+ strmaxcpy(s,MomCPUIdent,11);
+ for (z=dest=s; *z!='\0'; z++)
+ if (((*z>='0') AND (*z<='9')) OR ((*z>='A') AND (*z<='F')))
+ *(dest++)=(*z);
+ *dest='\0';
+ for (z=s; *z!='\0'; z++)
+ if ((*z>='0') AND (*z<='9')) break;
+ if (*z!='\0') strcpy(s,z);
+ strprep(s,"$");
+ HCPU=ConstLongInt(s,&ECPU);
+ if (ParamCount!=0)
+ BEGIN
+ EnterIntSymbol(MomCPUName,HCPU,SegNone,True);
+ EnterStringSymbol(MomCPUIdentName,MomCPUIdent,True);
+ END
+
+ InternSymbol=Default_InternSymbol;
+ ChkPC = DefChkPC;
+ if (NOT NotPrev) SwitchFrom();
+ Lauf->SwitchProc();
+
+ DontPrint=True;
+END
+
+ Boolean SetNCPU(char *Name, Boolean NoPrev)
+BEGIN
+ PCPUDef Lauf;
+
+ Lauf = FirstCPUDef;
+ while ((Lauf != Nil) AND (strcmp(Name, Lauf->Name) != 0))
+ Lauf = Lauf->Next;
+ if (Lauf == Nil) WrXError(1430, Name);
+ else SetCPU(Lauf->Number, NoPrev);
+ return (Lauf != Nil);
+END
+
+ char *IntLine(LongInt Inp)
+BEGIN
+ static String s;
+
+ switch (ConstMode)
+ BEGIN
+ case ConstModeIntel:
+ sprintf(s,"%sH",HexString(Inp,0));
+ if (*s>'9') strmaxprep(s,"0",255);
+ break;
+ case ConstModeMoto:
+ sprintf(s,"$%s",HexString(Inp,0));
+ break;
+ case ConstModeC:
+ sprintf(s,"0x%s",HexString(Inp,0));
+ break;
+ END
+
+ return s;
+END
+
+
+ static void CodeSECTION(Word Index)
+BEGIN
+ PSaveSection Neu;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (ExpandSymbol(ArgStr[1]))
+ if (NOT ChkSymbName(ArgStr[1])) WrXError(1020,ArgStr[1]);
+ else if ((PassNo==1) AND (GetSectionHandle(ArgStr[1],False,MomSectionHandle)!=-2)) WrError(1483);
+ else
+ BEGIN
+ Neu=(PSaveSection) malloc(sizeof(TSaveSection));
+ Neu->Next=SectionStack;
+ Neu->Handle=MomSectionHandle;
+ Neu->LocSyms=Nil; Neu->GlobSyms=Nil; Neu->ExportSyms=Nil;
+ SetMomSection(GetSectionHandle(ArgStr[1],True,MomSectionHandle));
+ SectionStack=Neu;
+ END
+END
+
+
+ static void CodeENDSECTION_ChkEmptList(PForwardSymbol *Root)
+BEGIN
+ PForwardSymbol Tmp;
+
+ while (*Root!=Nil)
+ BEGIN
+ WrXError(1488,(*Root)->Name);
+ free((*Root)->Name);
+ Tmp=(*Root); *Root=Tmp->Next; free(Tmp);
+ END
+END
+
+ static void CodeENDSECTION(Word Index)
+BEGIN
+ PSaveSection Tmp;
+
+ if (ArgCnt>1) WrError(1110);
+ else if (SectionStack==Nil) WrError(1487);
+ else if ((ArgCnt==0) OR (ExpandSymbol(ArgStr[1])))
+ if ((ArgCnt==1) AND (GetSectionHandle(ArgStr[1],False,SectionStack->Handle)!=MomSectionHandle)) WrError(1486);
+ else
+ BEGIN
+ Tmp=SectionStack; SectionStack=Tmp->Next;
+ CodeENDSECTION_ChkEmptList(&(Tmp->LocSyms));
+ CodeENDSECTION_ChkEmptList(&(Tmp->GlobSyms));
+ CodeENDSECTION_ChkEmptList(&(Tmp->ExportSyms));
+ TossRegDefs(MomSectionHandle);
+ if (ArgCnt==0)
+ sprintf(ListLine,"[%s]",GetSectionName(MomSectionHandle));
+ SetMomSection(Tmp->Handle);
+ free(Tmp);
+ END
+END
+
+
+ static void CodeCPU(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ if (SetNCPU(ArgStr[1], False)) ActPC = SegCode;
+ END
+END
+
+
+ static void CodeSETEQU(Word Index)
+BEGIN
+ TempResult t;
+ Boolean MayChange;
+ Integer DestSeg;
+
+ FirstPassUnknown=False;
+ MayChange=((NOT Memo("EQU")) AND (NOT Memo("=")));
+ if (*AttrPart!='\0') WrError(1100);
+ else if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ EvalExpression(ArgStr[1],&t);
+ if (NOT FirstPassUnknown)
+ BEGIN
+ if (ArgCnt==1) DestSeg=SegNone;
+ else
+ BEGIN
+ NLS_UpString(ArgStr[2]);
+ if (strcmp(ArgStr[2],"MOMSEGMENT")==0) DestSeg=ActPC;
+ else if (*ArgStr[2]=='\0') DestSeg=SegNone;
+ else
+ BEGIN
+ DestSeg=0;
+ while ((DestSeg<=PCMax) AND
+ (strcmp(ArgStr[2],SegNames[DestSeg])!=0))
+ DestSeg++;
+ END
+ END
+ if (DestSeg>PCMax) WrXError(1961,ArgStr[2]);
+ else
+ BEGIN
+ SetListLineVal(&t);
+ PushLocHandle(-1);
+ switch (t.Typ)
+ BEGIN
+ case TempInt : EnterIntSymbol (LabPart,t.Contents.Int,DestSeg,MayChange); break;
+ case TempFloat : EnterFloatSymbol (LabPart,t.Contents.Float,MayChange); break;
+ case TempString: EnterStringSymbol(LabPart,t.Contents.Ascii,MayChange); break;
+ case TempNone : break;
+ END
+ PopLocHandle();
+ END
+ END
+ END
+END
+
+
+ static void CodeORG(Word Index)
+BEGIN
+ LargeInt HVal;
+ Boolean ValOK;
+
+ FirstPassUnknown=False;
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+#ifndef HAS64
+ HVal=EvalIntExpression(ArgStr[1],UInt32,&ValOK);
+#else
+ HVal=EvalIntExpression(ArgStr[1],Int64,&ValOK);
+#endif
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ BEGIN
+ PCs[ActPC]=HVal; DontPrint=True;
+ END
+ END
+END
+
+
+ static void CodeSHARED_BuildComment(char *c)
+BEGIN
+ switch (ShareMode)
+ BEGIN
+ case 1: sprintf(c,"(* %s *)",CommPart); break;
+ case 2: sprintf(c,"/* %s */",CommPart); break;
+ case 3: sprintf(c,"; %s",CommPart); break;
+ END
+END
+
+ static void CodeSHARED(Word Index)
+BEGIN
+ int z;
+ Boolean ValOK;
+ LargeInt HVal;
+ Double FVal;
+ String s,c;
+
+ if (ShareMode==0) WrError(30);
+ else if ((ArgCnt==0) AND (*CommPart!='\0'))
+ BEGIN
+ CodeSHARED_BuildComment(c);
+ errno=0; fprintf(ShareFile,"%s\n",c); ChkIO(10004);
+ END
+ else
+ for (z=1; z<=ArgCnt; z++)
+ BEGIN
+ if (IsSymbolString(ArgStr[z]))
+ BEGIN
+ ValOK=GetStringSymbol(ArgStr[z],s);
+ if (ShareMode==1)
+ BEGIN
+ strmaxprep(s,"\'",255); strmaxcat(s,"\'",255);
+ END
+ else
+ BEGIN
+ strmaxprep(s,"\"",255); strmaxcat(s,"\"",255);
+ END
+ END
+ else if (IsSymbolFloat(ArgStr[z]))
+ BEGIN
+ ValOK=GetFloatSymbol(ArgStr[z],&FVal);
+ sprintf(s,"%0.17g",FVal);
+ END
+ else
+ BEGIN
+ ValOK=GetIntSymbol(ArgStr[z],&HVal);
+ switch (ShareMode)
+ BEGIN
+ case 1: sprintf(s,"$%s",HexString(HVal,0)); break;
+ case 2: sprintf(s,"0x%s",HexString(HVal,0)); break;
+ case 3: strmaxcpy(s,IntLine(HVal),255); break;
+ END
+ END
+ if (ValOK)
+ BEGIN
+ if ((z==1) AND (*CommPart!='\0'))
+ BEGIN
+ CodeSHARED_BuildComment(c); strmaxprep(c," ",255);
+ END
+ else *c='\0';
+ errno=0;
+ switch (ShareMode)
+ BEGIN
+ case 1:
+ fprintf(ShareFile,"%s = %s;%s\n",ArgStr[z],s,c); break;
+ case 2:
+ fprintf(ShareFile,"#define %s %s%s\n",ArgStr[z],s,c); break;
+ case 3:
+ strmaxprep(s,IsSymbolChangeable(ArgStr[z])?"set ":"equ ",255);
+ fprintf(ShareFile,"%s %s%s\n",ArgStr[z],s,c); break;
+ END
+ ChkIO(10004);
+ END
+ else if (PassNo==1)
+ BEGIN
+ Repass=True;
+ if ((MsgIfRepass) AND (PassNo>=PassNoForMessage)) WrXError(170,ArgStr[z]);
+ END
+ END
+END
+
+
+ static void CodePAGE(Word Index)
+BEGIN
+ Integer LVal,WVal;
+ Boolean ValOK;
+
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ LVal=EvalIntExpression(ArgStr[1],UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ if ((LVal<5) AND (LVal!=0)) LVal=5;
+ if (ArgCnt==1)
+ BEGIN
+ WVal=0; ValOK=True;
+ END
+ else WVal=EvalIntExpression(ArgStr[2],UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ if ((WVal<5) AND (WVal!=0)) WVal=5;
+ PageLength=LVal; PageWidth=WVal;
+ END
+ END
+ END
+END
+
+
+ static void CodeNEWPAGE(Word Index)
+BEGIN
+ ShortInt HVal8;
+ Boolean ValOK;
+
+ if (ArgCnt>1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ HVal8=0; ValOK=True;
+ END
+ else HVal8=EvalIntExpression(ArgStr[1],Int8,&ValOK);
+ if ((ValOK) OR (ArgCnt==0))
+ BEGIN
+ if (HVal8>ChapMax) HVal8=ChapMax;
+ else if (HVal8<0) HVal8=0;
+ NewPage(HVal8,True);
+ END
+ END
+END
+
+
+ static void CodeString(Word Index)
+BEGIN
+ String tmp;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ EvalStringExpression(ArgStr[1],&OK,tmp);
+ if (NOT OK) WrError(1970); else strmaxcpy(PseudoStrs[Index],tmp,255);
+ END
+END
+
+
+ static void CodePHASE(Word Index)
+BEGIN
+ Boolean OK;
+ LongInt HVal;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (ActPC==StructSeg) WrError(1553);
+ else
+ BEGIN
+ HVal=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (OK) Phases[ActPC]=HVal-ProgCounter();
+ END
+END
+
+
+ static void CodeDEPHASE(Word Index)
+BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (ActPC==StructSeg) WrError(1553);
+ else Phases[ActPC]=0;
+END
+
+
+ static void CodeWARNING(Word Index)
+BEGIN
+ String mess;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ EvalStringExpression(ArgStr[1],&OK,mess);
+ if (NOT OK) WrError(1970);
+ else WrErrorString(mess,"",True,False);
+ END
+END
+
+
+ static void CodeMESSAGE(Word Index)
+BEGIN
+ String mess;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ EvalStringExpression(ArgStr[1],&OK,mess);
+ if (NOT OK) WrError(1970);
+ printf("%s%s\n",mess,ClrEol);
+ if (strcmp(LstName,"/dev/null")!=0) WrLstLine(mess);
+ END
+END
+
+
+ static void CodeERROR(Word Index)
+BEGIN
+ String mess;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ EvalStringExpression(ArgStr[1],&OK,mess);
+ if (NOT OK) WrError(1970);
+ else WrErrorString(mess,"",False,False);
+ END
+END
+
+
+ static void CodeFATAL(Word Index)
+BEGIN
+ String mess;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ EvalStringExpression(ArgStr[1],&OK,mess);
+ if (NOT OK) WrError(1970);
+ else WrErrorString(mess,"",False,True);
+ END
+END
+
+ static void CodeCHARSET(Word Index)
+BEGIN
+ TempResult t;
+ FILE *f;
+ unsigned char tfield[256];
+ LongWord Start,l,TStart,Stop,z;
+ Boolean OK;
+
+ if (ArgCnt>3) WrError(1110);
+ else if (ArgCnt==0)
+ BEGIN
+ for (z=0; z<256; z++) CharTransTable[z]=z;
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False; EvalExpression(ArgStr[1],&t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (FirstPassUnknown) t.Contents.Int&=255;
+ if (ChkRange(t.Contents.Int,0,255))
+ if (ArgCnt<2) WrError(1110);
+ else
+ BEGIN
+ Start=t.Contents.Int;
+ FirstPassUnknown=False; EvalExpression(ArgStr[2],&t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt: /* Übersetzungsbereich als Character-Angabe */
+ if (FirstPassUnknown) t.Contents.Int&=255;
+ if (ArgCnt==2)
+ BEGIN
+ Stop=Start; TStart=t.Contents.Int;
+ OK=ChkRange(TStart,0,255);
+ END
+ else
+ BEGIN
+ Stop=t.Contents.Int; OK=ChkRange(Stop,Start,255);
+ if (OK) TStart=EvalIntExpression(ArgStr[3],UInt8,&OK);
+ else TStart=0;
+ END
+ if (OK)
+ for (z=Start; z<=Stop; z++) CharTransTable[z]=TStart+(z-Start);
+ break;
+ case TempString:
+ l=strlen(t.Contents.Ascii); /* Übersetzungsstring ab Start */
+ if (Start+l>256) WrError(1320);
+ else
+ for (z=0; z<l; z++)
+ CharTransTable[Start+z]=t.Contents.Ascii[z];
+ break;
+ case TempFloat:
+ WrError(1135);
+ break;
+ default:
+ break;
+ END
+ END
+ break;
+ case TempString:
+ if (ArgCnt!=1) WrError(1110); /* Tabelle von Datei lesen */
+ else
+ BEGIN
+ f=fopen(t.Contents.Ascii,OPENRDMODE);
+ if (f==Nil) ChkIO(10001);
+ if (fread(tfield,sizeof(char),256,f)!=256) ChkIO(10003);
+ fclose(f); memcpy(CharTransTable,tfield,sizeof(char)*256);
+ END
+ break;
+ case TempFloat:
+ WrError(1135);
+ break;
+ default:
+ break;
+ END
+ END
+END
+
+ static void CodePRSET(Word Index)
+BEGIN
+ int z,z2;
+
+ for (z=0; z<16; z++)
+ BEGIN
+ for (z2=0; z2<16; z2++) printf(" %02x",CharTransTable[z*16+z2]);
+ printf(" ");
+ for (z2=0; z2<16; z2++) printf("%c",CharTransTable[z*16+z2]>' ' ? CharTransTable[z*16+z2] : '.');
+ putchar('\n');
+ END
+END
+
+ static void CodeCODEPAGE(Word Index)
+BEGIN
+ PTransTable Prev,Run,New,Source;
+ int erg=0;
+
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if (NOT ChkSymbName(ArgStr[1])) WrXError(1020,ArgStr[1]);
+ else
+ BEGIN
+ if (NOT CaseSensitive)
+ BEGIN
+ UpString(ArgStr[1]);
+ if (ArgCnt==2) UpString(ArgStr[2]);
+ END
+
+ if (ArgCnt==1) Source=CurrTransTable;
+ else
+ for (Source=TransTables; Source!=Nil; Source=Source->Next)
+ if (strcmp(Source->Name,ArgStr[2])==0) break;
+
+ if (Source==Nil) WrXError(1610,ArgStr[2]);
+ else
+ BEGIN
+ for (Prev=Nil,Run=TransTables; Run!=Nil; Prev=Run,Run=Run->Next)
+ if ((erg=strcmp(ArgStr[1],Run->Name))<=0) break;
+
+ if ((Run==Nil) OR (erg<0))
+ BEGIN
+ New=(PTransTable) malloc(sizeof(TTransTable));
+ New->Next=Run;
+ New->Name=strdup(ArgStr[1]);
+ New->Table=(unsigned char *) malloc(256*sizeof(char));
+ memcpy(New->Table,Source->Table,256*sizeof(char));
+ if (Prev==Nil) TransTables=New; else Prev->Next=New;
+ CurrTransTable=New;
+ END
+ else CurrTransTable=Run;
+ END
+ END
+END
+
+
+ static void CodeFUNCTION(Word Index)
+BEGIN
+ String FName;
+ Boolean OK;
+ int z;
+
+ if (ArgCnt<2) WrError(1110);
+ else
+ BEGIN
+ OK=True; z=1;
+ do
+ BEGIN
+ OK=(OK AND ChkMacSymbName(ArgStr[z]));
+ if (NOT OK) WrXError(1020,ArgStr[z]);
+ z++;
+ END
+ while ((z<ArgCnt) AND (OK));
+ if (OK)
+ BEGIN
+ strmaxcpy(FName,ArgStr[ArgCnt],255);
+ for (z=1; z<ArgCnt; z++)
+ CompressLine(ArgStr[z],z,FName);
+ EnterFunction(LabPart,FName,ArgCnt-1);
+ END
+ END
+END
+
+
+ static void CodeSAVE(Word Index)
+BEGIN
+ PSaveState Neu;
+
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ Neu=(PSaveState) malloc(sizeof(TSaveState));
+ Neu->Next=FirstSaveState;
+ Neu->SaveCPU=MomCPU;
+ Neu->SavePC=ActPC;
+ Neu->SaveListOn=ListOn;
+ Neu->SaveLstMacroEx=LstMacroEx;
+ Neu->SaveTransTable=CurrTransTable;
+ FirstSaveState=Neu;
+ END
+END
+
+
+ static void CodeRESTORE(Word Index)
+BEGIN
+ PSaveState Old;
+
+ if (ArgCnt!=0) WrError(1110);
+ else if (FirstSaveState==Nil) WrError(1450);
+ else
+ BEGIN
+ Old=FirstSaveState; FirstSaveState=Old->Next;
+ if (Old->SavePC!=ActPC)
+ BEGIN
+ ActPC=Old->SavePC; DontPrint=True;
+ END
+ if (Old->SaveCPU!=MomCPU) SetCPU(Old->SaveCPU,False);
+ EnterIntSymbol(ListOnName,ListOn=Old->SaveListOn,0,True);
+ SetFlag(&LstMacroEx,LstMacroExName,Old->SaveLstMacroEx);
+ CurrTransTable=Old->SaveTransTable;
+ free(Old);
+ END
+END
+
+
+ static void CodeSEGMENT(Word Index)
+BEGIN
+ Byte SegZ;
+ Word Mask;
+ Boolean Found;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Found=False; NLS_UpString(ArgStr[1]);
+ for (SegZ=1,Mask=2; SegZ<=PCMax; SegZ++,Mask<<=1)
+ if (((ValidSegs&Mask)!=0) AND (strcmp(ArgStr[1],SegNames[SegZ])==0))
+ BEGIN
+ Found=True;
+ if (ActPC!=SegZ)
+ BEGIN
+ ActPC=SegZ;
+ if (NOT PCsUsed[ActPC]) PCs[ActPC]=SegInits[ActPC];
+ PCsUsed[ActPC]=True;
+ DontPrint=True;
+ END
+ END
+ if (NOT Found) WrXError(1961,ArgStr[1]);
+ END
+END
+
+
+ static void CodeLABEL(Word Index)
+BEGIN
+ LongInt Erg;
+ Boolean OK;
+
+ FirstPassUnknown=False;
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Erg=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ PushLocHandle(-1);
+ EnterIntSymbol(LabPart,Erg,SegCode,False);
+ sprintf(ListLine,"=%s",IntLine(Erg));
+ PopLocHandle();
+ END
+ END
+END
+
+
+ static void CodeREAD(Word Index)
+BEGIN
+ String Exp;
+ TempResult Erg;
+ Boolean OK;
+ LongInt SaveLocHandle;
+
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==2) EvalStringExpression(ArgStr[1],&OK,Exp);
+ else
+ BEGIN
+ sprintf(Exp,"Read %s ? ",ArgStr[1]); OK=True;
+ END
+ if (OK)
+ BEGIN
+ setbuf(stdout,Nil); printf("%s",Exp);
+ fgets(Exp,255,stdin); UpString(Exp);
+ FirstPassUnknown=False;
+ EvalExpression(Exp,&Erg);
+ if (OK)
+ BEGIN
+ SetListLineVal(&Erg);
+ SaveLocHandle=MomLocHandle; MomLocHandle=(-1);
+ if (FirstPassUnknown) WrError(1820);
+ else switch (Erg.Typ)
+ BEGIN
+ case TempInt : EnterIntSymbol(ArgStr[ArgCnt],Erg.Contents.Int,SegNone,True); break;
+ case TempFloat : EnterFloatSymbol(ArgStr[ArgCnt],Erg.Contents.Float,True); break;
+ case TempString: EnterStringSymbol(ArgStr[ArgCnt],Erg.Contents.Ascii,True); break;
+ case TempNone : break;
+ END
+ MomLocHandle=SaveLocHandle;
+ END
+ END
+ END
+END
+
+ static void CodeRADIX(Word Index)
+BEGIN
+ Boolean OK;
+ LargeWord tmp;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ tmp=ConstLongInt(ArgStr[1],&OK);
+ if (NOT OK) WrError(1135);
+ else if (ChkRange(tmp,2,36))
+ BEGIN
+ if (Index == 1) OutRadixBase = tmp;
+ else RadixBase = tmp;
+ END
+ END
+END
+
+ static void CodeALIGN(Word Index)
+BEGIN
+ Word Dummy;
+ Boolean OK;
+ LongInt NewPC;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Dummy=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if (FirstPassUnknown) WrError(1820);
+ else
+ BEGIN
+ NewPC=ProgCounter()+Dummy-1;
+ NewPC-=NewPC%Dummy;
+ CodeLen=NewPC-ProgCounter();
+ DontPrint=(CodeLen!=0);
+ if (DontPrint) BookKeeping();
+ END
+ END
+END
+
+
+ static void CodeENUM(Word Index)
+BEGIN
+ int z;
+ char *p=Nil;
+ Boolean OK;
+ LongInt Counter,First=0,Last=0;
+ String SymPart;
+
+ Counter=0;
+ if (ArgCnt==0) WrError(1110);
+ else
+ for (z=1; z<=ArgCnt; z++)
+ BEGIN
+ p=QuotPos(ArgStr[z],'=');
+ if (p!=Nil)
+ BEGIN
+ strmaxcpy(SymPart,p+1,255);
+ FirstPassUnknown=False;
+ Counter=EvalIntExpression(SymPart,Int32,&OK);
+ if (NOT OK) return;
+ if (FirstPassUnknown)
+ BEGIN
+ WrXError(1820,SymPart); return;
+ END
+ *p='\0';
+ END
+ EnterIntSymbol(ArgStr[z],Counter,SegNone,False);
+ if (z==1) First=Counter;
+ else if (z==ArgCnt) Last=Counter;
+ Counter++;
+ END
+ sprintf(ListLine,"=%s",IntLine(First));
+ if (ArgCnt!=1)
+ BEGIN
+ strmaxcat(ListLine,"..",255);
+ strmaxcat(ListLine,IntLine(Last),255);
+ END
+END
+
+
+ static void CodeEND(Word Index)
+BEGIN
+ LongInt HVal;
+ Boolean OK;
+
+ if (ArgCnt>1) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ FirstPassUnknown=False;
+ HVal=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ ChkSpace(SegCode);
+ StartAdr=HVal;
+ StartAdrPresent=True;
+ END
+ END
+ ENDOccured=True;
+ END
+END
+
+
+ static void CodeLISTING(Word Index)
+BEGIN
+ Byte Value=0xff;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ OK=True; NLS_UpString(ArgStr[1]);
+ if (strcmp(ArgStr[1],"OFF")==0) Value=0;
+ else if (strcmp(ArgStr[1],"ON")==0) Value=1;
+ else if (strcmp(ArgStr[1],"NOSKIPPED")==0) Value=2;
+ else if (strcmp(ArgStr[1],"PURECODE")==0) Value=3;
+ else OK=False;
+ if (NOT OK) WrError(1520);
+ else EnterIntSymbol(ListOnName,ListOn=Value,0,True);
+ END
+END
+
+ static void CodeBINCLUDE(Word Index)
+BEGIN
+ FILE *F;
+ LongInt Len=(-1);
+ LongWord Ofs=0,Curr,Rest,FSize;
+ Word RLen;
+ Boolean OK,SaveTurnWords;
+ LargeWord OldPC;
+ String Name;
+
+ if ((ArgCnt<1) OR (ArgCnt>3)) WrError(1110);
+ else if (ActPC==StructSeg) WrError(1940);
+ else
+ BEGIN
+ if (ArgCnt==1) OK=True;
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Ofs=EvalIntExpression(ArgStr[2],Int32,&OK);
+ if (FirstPassUnknown)
+ BEGIN
+ WrError(1820); OK=False;
+ END
+ if (OK)
+ if (ArgCnt==2) Len=(-1);
+ else
+ BEGIN
+ Len=EvalIntExpression(ArgStr[3],Int32,&OK);
+ if (FirstPassUnknown)
+ BEGIN
+ WrError(1820); OK=False;
+ END
+ END
+ END
+ if (OK)
+ BEGIN
+ strmaxcpy(Name,ArgStr[1],255);
+ if (*Name=='"') strcpy(Name,Name+1);
+ if (Name[strlen(Name)-1]=='"') Name[strlen(Name)-1]='\0';
+ strmaxcpy(ArgStr[1],Name,255);
+ strmaxcpy(Name,FExpand(FSearch(Name,IncludeList)),255);
+ if (Name[strlen(Name)-1]=='/') strmaxcat(Name,ArgStr[1],255);
+ F=fopen(Name,OPENRDMODE); ChkIO(10001);
+ FSize=FileSize(F); ChkIO(10003);
+ if (Len==-1)
+ if ((Len=FSize-Ofs)<0)
+ BEGIN
+ fclose(F); WrError(1600); return;
+ END
+ if (NOT ChkPC(PCs[ActPC]+Len-1)) WrError(1925);
+ else
+ BEGIN
+ fseek(F,Ofs,SEEK_SET); ChkIO(10003);
+ Rest=Len; SaveTurnWords=TurnWords; TurnWords=False;
+ OldPC = ProgCounter();
+ do
+ BEGIN
+ if (Rest<MaxCodeLen) Curr=Rest; else Curr=MaxCodeLen;
+ RLen=fread(BAsmCode,1,Curr,F); ChkIO(10003);
+ CodeLen=RLen;
+ WriteBytes();
+ PCs[ActPC]+=CodeLen;
+ Rest-=RLen;
+ END
+ while ((Rest!=0) AND (RLen==Curr));
+ if (Rest!=0) WrError(1600);
+ TurnWords=SaveTurnWords;
+ DontPrint=True; CodeLen=ProgCounter()-OldPC;
+ PCs[ActPC]=OldPC;
+ END
+ fclose(F);
+ END
+ END
+END
+
+ static void CodePUSHV(Word Index)
+BEGIN
+ int z;
+
+ if (ArgCnt<2) WrError(1110);
+ else
+ BEGIN
+ if (NOT CaseSensitive) NLS_UpString(ArgStr[1]);
+ for (z=2; z<=ArgCnt; z++)
+ PushSymbol(ArgStr[z],ArgStr[1]);
+ END
+END
+
+ static void CodePOPV(Word Index)
+BEGIN
+ int z;
+
+ if (ArgCnt<2) WrError(1110);
+ else
+ BEGIN
+ if (NOT CaseSensitive) NLS_UpString(ArgStr[1]);
+ for (z=2; z<=ArgCnt; z++)
+ PopSymbol(ArgStr[z],ArgStr[1]);
+ END
+END
+
+ static PForwardSymbol CodePPSyms_SearchSym(PForwardSymbol Root, char *Comp)
+BEGIN
+ PForwardSymbol Lauf=Root;
+
+ while ((Lauf!=Nil) AND (strcmp(Lauf->Name,Comp)!=0)) Lauf=Lauf->Next;
+ return Lauf;
+END
+
+
+ static void CodeSTRUCT(Word Index)
+BEGIN
+ PStructure NStruct;
+ int z;
+ Boolean OK;
+
+ if (ArgCnt>1) WrError(1110);
+ else if (NOT ChkSymbName(LabPart)) WrXError(1020,LabPart);
+ else
+ BEGIN
+ if (NOT CaseSensitive) NLS_UpString(LabPart);
+ if (StructureStack!=Nil) StructureStack->CurrPC=ProgCounter();
+ NStruct=(PStructure) malloc(sizeof(TStructure));
+ NStruct->Name=strdup(LabPart);
+ NStruct->CurrPC=0; NStruct->DoExt=True;
+ NStruct->Next=StructureStack;
+ OK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (OK)
+ if (strcasecmp(ArgStr[z],"EXTNAMES")==0) NStruct->DoExt=True;
+ else if (strcasecmp(ArgStr[z],"NOEXTNAMES")==0) NStruct->DoExt=False;
+ else
+ BEGIN
+ WrXError(1554,ArgStr[z]); OK=False;
+ END
+ if (OK)
+ BEGIN
+ StructureStack=NStruct;
+ if (ActPC!=StructSeg) StructSaveSeg=ActPC; ActPC=StructSeg;
+ PCs[ActPC]=0;
+ Phases[ActPC]=0;
+ Grans[ActPC]=Grans[SegCode]; ListGrans[ActPC]=ListGrans[SegCode];
+ ClearChunk(SegChunks+StructSeg);
+ CodeLen=0; DontPrint=True;
+ END
+ else
+ BEGIN
+ free(NStruct->Name); free(NStruct);
+ END
+ END
+END
+
+ static void CodeENDSTRUCT(Word Index)
+BEGIN
+ Boolean OK;
+ PStructure OStruct;
+ TempResult t;
+ String tmp;
+
+ if (ArgCnt>1) WrError(1110);
+ else if (StructureStack==Nil) WrError(1550);
+ else
+ BEGIN
+ if (*LabPart=='\0') OK=True;
+ else
+ BEGIN
+ if (NOT CaseSensitive) NLS_UpString(LabPart);
+ OK=(strcmp(LabPart,StructureStack->Name)==0);
+ if (NOT OK) WrError(1552);
+ END
+ if (OK)
+ BEGIN
+ OStruct=StructureStack; StructureStack=OStruct->Next;
+ if (ArgCnt==0) sprintf(tmp,"%s_len",OStruct->Name);
+ else strmaxcpy(tmp,ArgStr[1],255);
+ EnterIntSymbol(tmp,ProgCounter(),SegNone,False);
+ t.Typ=TempInt; t.Contents.Int=ProgCounter(); SetListLineVal(&t);
+ free(OStruct->Name);
+ free(OStruct);
+ if (StructureStack==Nil) ActPC=StructSaveSeg;
+ else PCs[ActPC]+=StructureStack->CurrPC;
+ ClearChunk(SegChunks+StructSeg);
+ CodeLen=0; DontPrint=True;
+ END
+ END
+END
+
+ static void CodeEXTERN(Word Index)
+BEGIN
+ char *Split;
+ int i;
+ Boolean OK;
+ Byte Type;
+
+ if (ArgCnt < 1) WrError(1110);
+ else
+ BEGIN
+ i = 1; OK = True;
+ while ((OK) && (i <= ArgCnt))
+ BEGIN
+ Split = strrchr(ArgStr[i], ':');
+ if (Split == NULL)
+ Type = SegNone;
+ else
+ BEGIN
+ for (Type = SegNone + 1; Type <= PCMax; Type++)
+ if (strcasecmp(Split + 1, SegNames[Type]) == 0)
+ break;
+ if (Type > PCMax) WrXError(1961, Split + 1);
+ else
+ BEGIN
+ *Split = '\0';
+ EnterExtSymbol(ArgStr[i], 0, Type, FALSE);
+ END
+ END
+ i++;
+ END
+ END
+END
+
+ static void CodePPSyms(PForwardSymbol *Orig,
+ PForwardSymbol *Alt1,
+ PForwardSymbol *Alt2)
+BEGIN
+ PForwardSymbol Lauf;
+ int z;
+ String Sym,Section;
+
+ if (ArgCnt==0) WrError(1110);
+ else
+ for (z=1; z<=ArgCnt; z++)
+ BEGIN
+ SplitString(ArgStr[z],Sym,Section,QuotPos(ArgStr[z],':'));
+ if (NOT ExpandSymbol(Sym)) return;
+ if (NOT ExpandSymbol(Section)) return;
+ if (NOT CaseSensitive) NLS_UpString(Sym);
+ Lauf=CodePPSyms_SearchSym(*Alt1,Sym);
+ if (Lauf!=Nil) WrXError(1489,ArgStr[z]);
+ else
+ BEGIN
+ Lauf=CodePPSyms_SearchSym(*Alt2,Sym);
+ if (Lauf!=Nil) WrXError(1489,ArgStr[z]);
+ else
+ BEGIN
+ Lauf=CodePPSyms_SearchSym(*Orig,Sym);
+ if (Lauf==Nil)
+ BEGIN
+ Lauf=(PForwardSymbol) malloc(sizeof(TForwardSymbol));
+ Lauf->Next=(*Orig); *Orig=Lauf;
+ Lauf->Name=strdup(Sym);
+ END
+ IdentifySection(Section,&(Lauf->DestSection));
+ END
+ END
+ END
+END
+
+/*------------------------------------------------------------------------*/
+
+#define ONOFFMax 32
+static int ONOFFCnt=0;
+typedef struct
+ {
+ Boolean Persist,*FlagAddr;
+ char *FlagName,*InstName;
+ } ONOFFTab;
+static ONOFFTab ONOFFList[ONOFFMax];
+
+ static void DecodeONOFF(Word Index)
+BEGIN
+ ONOFFTab *Tab=ONOFFList+Index;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ if (*AttrPart!='\0') WrError(1100);
+ else if ((strcasecmp(ArgStr[1],"ON")!=0) AND (strcasecmp(ArgStr[1],"OFF")!=0)) WrError(1520);
+ else
+ BEGIN
+ OK=(strcasecmp(ArgStr[1],"ON")==0);
+ SetFlag(Tab->FlagAddr,Tab->FlagName,OK);
+ END
+ END
+END
+
+ void AddONOFF(char *InstName, Boolean *Flag, char *FlagName, Boolean Persist)
+BEGIN
+ if (ONOFFCnt==ONOFFMax) exit(255);
+ ONOFFList[ONOFFCnt].Persist=Persist;
+ ONOFFList[ONOFFCnt].FlagAddr=Flag;
+ ONOFFList[ONOFFCnt].FlagName=FlagName;
+ ONOFFList[ONOFFCnt].InstName=InstName;
+ AddInstTable(ONOFFTable,InstName,ONOFFCnt++,DecodeONOFF);
+END
+
+ void ClearONOFF(void)
+BEGIN
+ int z,z2;
+
+ for (z=0; z<ONOFFCnt; z++)
+ if (NOT ONOFFList[z].Persist) break;
+
+ for (z2=ONOFFCnt-1; z2>=z; z2--)
+ RemoveInstTable(ONOFFTable,ONOFFList[z2].InstName);
+
+ ONOFFCnt=z;
+END
+
+/*------------------------------------------------------------------------*/
+
+typedef struct
+ {
+ char *Name;
+ void (*Proc)(
+#ifdef __PROTOS__
+ Word Index
+#endif
+ );
+ } PseudoOrder;
+static PseudoOrder Pseudos[]=
+ {{"ALIGN", CodeALIGN },
+ {"BINCLUDE", CodeBINCLUDE },
+ {"CHARSET", CodeCHARSET },
+ {"CODEPAGE", CodeCODEPAGE },
+ {"CPU", CodeCPU },
+ {"DEPHASE", CodeDEPHASE },
+ {"END", CodeEND },
+ {"ENDSECTION", CodeENDSECTION},
+ {"ENDSTRUCT", CodeENDSTRUCT },
+ {"ENUM", CodeENUM },
+ {"ERROR", CodeERROR },
+ {"EXTERN", CodeEXTERN },
+ {"FATAL", CodeFATAL },
+ {"FUNCTION", CodeFUNCTION },
+ {"LABEL", CodeLABEL },
+ {"LISTING", CodeLISTING },
+ {"MESSAGE", CodeMESSAGE },
+ {"NEWPAGE", CodeNEWPAGE },
+ {"ORG", CodeORG },
+ {"PAGE", CodePAGE },
+ {"PHASE", CodePHASE },
+ {"POPV", CodePOPV },
+ {"PRSET", CodePRSET },
+ {"PUSHV", CodePUSHV },
+ {"RADIX", CodeRADIX },
+ {"READ", CodeREAD },
+ {"RESTORE", CodeRESTORE },
+ {"SAVE", CodeSAVE },
+ {"SECTION", CodeSECTION },
+ {"SEGMENT", CodeSEGMENT },
+ {"SHARED", CodeSHARED },
+ {"STRUCT", CodeSTRUCT },
+ {"WARNING", CodeWARNING },
+ {"" , Nil }};
+
+ Boolean CodeGlobalPseudo(void)
+BEGIN
+ switch (*OpPart)
+ BEGIN
+ case 'S':
+ if ((NOT SetIsOccupied) AND (Memo("SET")))
+ BEGIN
+ CodeSETEQU(0); return True;
+ END
+ break;
+ case 'E':
+ if ((SetIsOccupied) AND (Memo("EVAL")))
+ BEGIN
+ CodeSETEQU(0); return True;
+ END
+ break;
+ END
+
+ if (LookupInstTable(ONOFFTable,OpPart)) return True;
+
+ if (LookupInstTable(PseudoTable,OpPart)) return True;
+
+ if (SectionStack!=Nil)
+ BEGIN
+ if (Memo("FORWARD"))
+ BEGIN
+ if (PassNo<=MaxSymPass)
+ CodePPSyms(&(SectionStack->LocSyms),
+ &(SectionStack->GlobSyms),
+ &(SectionStack->ExportSyms));
+ return True;
+ END
+ if (Memo("PUBLIC"))
+ BEGIN
+ CodePPSyms(&(SectionStack->GlobSyms),
+ &(SectionStack->LocSyms),
+ &(SectionStack->ExportSyms));
+ return True;
+ END
+ if (Memo("GLOBAL"))
+ BEGIN
+ CodePPSyms(&(SectionStack->ExportSyms),
+ &(SectionStack->LocSyms),
+ &(SectionStack->GlobSyms));
+ return True;
+ END
+ END
+
+ return False;
+END
+
+
+ void codeallg_init(void)
+BEGIN
+ PseudoOrder *POrder;
+
+ PseudoStrs[0]=PrtInitString;
+ PseudoStrs[1]=PrtExitString;
+ PseudoStrs[2]=PrtTitleString;
+
+ PseudoTable=CreateInstTable(201);
+ for (POrder=Pseudos; POrder->Proc!=Nil; POrder++)
+ AddInstTable(PseudoTable,POrder->Name,0,POrder->Proc);
+ AddInstTable(PseudoTable,"OUTRADIX", 1, CodeRADIX);
+ AddInstTable(PseudoTable,"EQU",0,CodeSETEQU);
+ AddInstTable(PseudoTable,"=",0,CodeSETEQU);
+ AddInstTable(PseudoTable,":=",0,CodeSETEQU);
+ AddInstTable(PseudoTable,"PRTINIT",0,CodeString);
+ AddInstTable(PseudoTable,"PRTEXIT",1,CodeString);
+ AddInstTable(PseudoTable,"TITLE",2,CodeString);
+ ONOFFTable=CreateInstTable(47);
+ AddONOFF("MACEXP",&LstMacroEx,LstMacroExName,True);
+ AddONOFF("RELAXED",&RelaxedMode,RelaxedName,True);
+END
diff --git a/asmallg.h b/asmallg.h
new file mode 100644
index 0000000..1035b0f
--- /dev/null
+++ b/asmallg.h
@@ -0,0 +1,21 @@
+/* codeallg.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* von allen Codegeneratoren benutzte Pseudobefehle */
+/* */
+/* Historie: 10. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void SetCPU(CPUVar NewCPU, Boolean NotPrev);
+
+extern Boolean SetNCPU(char *Name, Boolean NotPrev);
+
+extern void AddONOFF(char *InstName, Boolean *Flag, char *FlagName, Boolean Persist);
+
+extern void ClearONOFF(void);
+
+extern Boolean CodeGlobalPseudo(void);
+
+extern void codeallg_init(void);
diff --git a/asmcode.c b/asmcode.c
new file mode 100644
index 0000000..46e8283
--- /dev/null
+++ b/asmcode.c
@@ -0,0 +1,239 @@
+/* asmcode.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung der Code-Datei */
+/* */
+/* Historie: 18. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "version.h"
+#include "endian.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+
+static Word LenSoFar;
+static LongInt RecPos,LenPos;
+
+#define CodeBufferSize 512
+
+static Word CodeBufferFill;
+static Byte CodeBuffer[CodeBufferSize+1];
+
+/**
+ static Boolean Write2(void *Buffer)
+BEGIN
+ Boolean OK;
+
+ if (BigEndian) WSwap(Buffer,2);
+ OK=(fwrite(Buffer,1,2,PrgFile)==2);
+ if (BigEndian) WSwap(Buffer,2);
+ return OK;
+END
+
+ static Boolean Write4(void *Buffer)
+BEGIN
+ Boolean OK;
+
+ if (BigEndian) DSwap(Buffer,4);
+ OK=(fwrite(Buffer,1,4,PrgFile)==4);
+ if (BigEndian) DSwap(Buffer,4);
+ return OK;
+END
+**/
+ static void FlushBuffer(void)
+BEGIN
+ if (CodeBufferFill>0)
+ BEGIN
+ if (fwrite(CodeBuffer,1,CodeBufferFill,PrgFile)!=CodeBufferFill) ChkIO(10004);
+ CodeBufferFill=0;
+ END
+END
+
+ void DreheCodes(void)
+BEGIN
+ int z;
+ LongInt l=CodeLen*Granularity();
+
+ switch (ActListGran)
+ BEGIN
+ case 2:
+ for (z=0; z<(l>>1); z++)
+ WAsmCode[z]=((WAsmCode[z]&0xff)<<8)+((WAsmCode[z]&0xff00)>>8);
+ break;
+ case 4:
+ for (z=0; z<(l>>2); z++)
+ {
+#ifdef __STDC__
+ DAsmCode[z]=((DAsmCode[z]&0xff000000u)>>24)+
+ ((DAsmCode[z]&0x00ff0000u)>>8)+
+ ((DAsmCode[z]&0x0000ff00u)<<8)+
+ ((DAsmCode[z]&0x000000ffu)<<24);
+#else
+ DAsmCode[z]=((DAsmCode[z]&0xff000000)>>24)+
+ ((DAsmCode[z]&0x00ff0000)>>8)+
+ ((DAsmCode[z]&0x0000ff00)<<8)+
+ ((DAsmCode[z]&0x000000ff)<<24);
+#endif
+ }
+ break;
+ END
+END
+
+/*--- neuen Record in Codedatei anlegen. War der bisherige leer, so wird ---
+ ---- dieser ueberschrieben. ------------------------------------------------*/
+
+ static void WrRecHeader(void)
+BEGIN
+ Byte b;
+
+ if (ActPC!=SegCode)
+ BEGIN
+ b=FileHeaderDataRec; if (fwrite(&b,1,1,PrgFile)!=1) ChkIO(10004);
+ END
+ if (fwrite(&HeaderID,1,1,PrgFile)!=1) ChkIO(10004);
+ if (ActPC!=SegCode)
+ BEGIN
+ b=ActPC; if (fwrite(&b,1,1,PrgFile)!=1) ChkIO(10004);
+ b=Grans[ActPC]; if (fwrite(&b,1,1,PrgFile)!=1) ChkIO(10004);
+ END
+END
+
+ void NewRecord(LargeWord NStart)
+BEGIN
+ LongInt h;
+ LongWord PC;
+
+ FlushBuffer();
+ if (LenSoFar==0)
+ BEGIN
+ if (fseek(PrgFile,RecPos,SEEK_SET)!=0) ChkIO(10003);
+ WrRecHeader();
+ h=NStart;
+ if (NOT Write4(PrgFile,&h)) ChkIO(10004);
+ LenPos=ftell(PrgFile);
+ if (NOT Write2(PrgFile,&LenSoFar)) ChkIO(10004);
+ END
+ else
+ BEGIN
+ h=ftell(PrgFile);
+ if (fseek(PrgFile,LenPos,SEEK_SET)!=0) ChkIO(10003);
+ if (NOT Write2(PrgFile,&LenSoFar)) ChkIO(10004);
+ if (fseek(PrgFile,h,SEEK_SET)!=0) ChkIO(10003);
+
+ RecPos=h; LenSoFar=0;
+ WrRecHeader();
+ PC=NStart;
+ if (NOT Write4(PrgFile,&PC)) ChkIO(10004);
+ LenPos=ftell(PrgFile);
+ if (NOT Write2(PrgFile,&LenSoFar)) ChkIO(10004);
+ END
+END
+
+/*--- Codedatei eroeffnen --------------------------------------------------*/
+
+ void OpenFile(void)
+BEGIN
+ Word h;
+
+ errno=0;
+ PrgFile=fopen(OutName,OPENWRMODE);
+ if (PrgFile==Nil) ChkIO(10001);
+
+ errno=0; h=FileMagic;
+ if (NOT Write2(PrgFile,&h)) ChkIO(10004);
+
+ CodeBufferFill=0;
+ RecPos=ftell(PrgFile); LenSoFar=0;
+ NewRecord(PCs[ActPC]);
+END
+
+/*---- Codedatei schliessen -------------------------------------------------*/
+
+ void CloseFile(void)
+BEGIN
+ Byte Head;
+ String h;
+ LongWord Adr;
+
+ sprintf(h,"AS %s/%s-%s",Version,ARCHPRNAME,ARCHSYSNAME);
+
+ NewRecord(PCs[ActPC]);
+ fseek(PrgFile,RecPos,SEEK_SET);
+
+ if (StartAdrPresent)
+ BEGIN
+ Head=FileHeaderStartAdr;
+ if (fwrite(&Head,sizeof(Head),1,PrgFile)!=1) ChkIO(10004);
+ Adr=StartAdr;
+ if (NOT Write4(PrgFile,&Adr)) ChkIO(10004);
+ END
+
+ Head=FileHeaderEnd;
+ if (fwrite(&Head,sizeof(Head),1,PrgFile)!=1) ChkIO(10004);
+ if (fwrite(h,1,strlen(h),PrgFile)!=strlen(h)) ChkIO(10004);
+ fclose(PrgFile); if (Magic!=0) unlink(OutName);
+END
+
+/*--- erzeugten Code einer Zeile in Datei ablegen ---------------------------*/
+
+ void WriteBytes(void)
+BEGIN
+ Word ErgLen;
+
+ if (CodeLen==0) return; ErgLen=CodeLen*Granularity();
+ if ((TurnWords!=0)!=(BigEndian!=0)) DreheCodes();
+ if (((LongInt)LenSoFar)+((LongInt)ErgLen)>0xffff) NewRecord(PCs[ActPC]);
+ if (CodeBufferFill+ErgLen<CodeBufferSize)
+ BEGIN
+ memcpy(CodeBuffer+CodeBufferFill,BAsmCode,ErgLen);
+ CodeBufferFill+=ErgLen;
+ END
+ else
+ BEGIN
+ FlushBuffer();
+ if (ErgLen<CodeBufferSize)
+ BEGIN
+ memcpy(CodeBuffer,BAsmCode,ErgLen); CodeBufferFill=ErgLen;
+ END
+ else if (fwrite(BAsmCode,1,ErgLen,PrgFile)!=ErgLen) ChkIO(10004);
+ END
+ LenSoFar+=ErgLen;
+ if ((TurnWords!=0)!=(BigEndian!=0)) DreheCodes();
+END
+
+ void RetractWords(Word Cnt)
+BEGIN
+ Word ErgLen;
+
+ ErgLen=Cnt*Granularity();
+ if (LenSoFar<ErgLen)
+ BEGIN
+ WrError(1950); return;
+ END
+
+ if (MakeUseList) DeleteChunk(SegChunks+ActPC,ProgCounter()-Cnt,Cnt);
+
+ PCs[ActPC]-=Cnt;
+
+ if (CodeBufferFill>=ErgLen) CodeBufferFill-=ErgLen;
+ else
+ BEGIN
+ if (fseek(PrgFile,-(ErgLen-CodeBufferFill),SEEK_CUR)==-1)
+ ChkIO(10004);
+ CodeBufferFill=0;
+ END
+
+ LenSoFar-=ErgLen;
+
+ Retracted=True;
+END
+
+ void asmcode_init(void)
+BEGIN
+END
diff --git a/asmcode.h b/asmcode.h
new file mode 100644
index 0000000..661940e
--- /dev/null
+++ b/asmcode.h
@@ -0,0 +1,27 @@
+/* asmcode.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung der Code-Datei */
+/* */
+/* Historie: 18. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern Word LenSoFar;
+extern LongInt RecPos;
+
+
+extern void DreheCodes(void);
+
+extern void NewRecord(LargeWord NStart);
+
+extern void OpenFile(void);
+
+extern void CloseFile(void);
+
+extern void WriteBytes(void);
+
+extern void RetractWords(Word Cnt);
+
+extern void asmcode_init(void);
diff --git a/asmdebug.c b/asmdebug.c
new file mode 100644
index 0000000..f94cf09
--- /dev/null
+++ b/asmdebug.c
@@ -0,0 +1,320 @@
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung der Debug-Informationen zur Assemblierzeit */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* 24. 7.1998 NoICE-Format */
+/* 25. 7.1998 Adresserfassung Dateien */
+/* 16. 8.1998 Case-Sensitivitaet NoICE */
+/* NoICE-Zeileninfo nach Dateien sortiert */
+/* 29. 1.1999 uninitialisierten Speicherzugriff beseitigt */
+/* 2. 5.1999 optional mehrere Records im Atmel-Format schreiben */
+/* */
+/*****************************************************************************/
+
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "endian.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmfnums.h"
+
+#include "asmdebug.h"
+
+
+typedef struct
+ {
+ Boolean InMacro;
+ LongInt LineNum;
+ Integer FileName;
+ ShortInt Space;
+ LargeInt Address;
+ Word Code;
+ } TLineInfo;
+
+typedef struct _TLineInfoList
+ {
+ struct _TLineInfoList *Next;
+ TLineInfo Contents;
+ } TLineInfoList,*PLineInfoList;
+
+String TempFileName;
+FILE *TempFile;
+PLineInfoList LineInfoRoot;
+
+
+ void AddLineInfo(Boolean InMacro, LongInt LineNum, char *FileName,
+ ShortInt Space, LargeInt Address, LargeInt Len)
+BEGIN
+ PLineInfoList PNeu, PFirst, PLast, Run, Link;
+ int RecCnt, z;
+ Integer FNum;
+
+ /* wieviele Records schreiben ? */
+
+ if ((DebugMode == DebugAtmel) AND (CodeLen > 1)) RecCnt = CodeLen;
+ else RecCnt = 1;
+
+ FNum = GetFileNum(FileName);
+
+ /* Einfuegepunkt in Liste finden */
+
+ Run = LineInfoRoot;
+ if (Run == Nil)
+ Link = Nil;
+ else
+ BEGIN
+ while ((Run->Next != Nil) AND (Run->Next->Contents.Space < Space)) Run = Run->Next;
+ while ((Run->Next != Nil) AND (Run->Next->Contents.FileName < FNum)) Run = Run->Next;
+ while ((Run->Next != Nil) AND (Run->Next->Contents.Address < Address)) Run = Run->Next;
+ Link = Run->Next;
+ END
+
+ /* neue Teilliste bilden */
+
+ PLast = PFirst = NULL;
+ for (z = 0; z < RecCnt; z++)
+ BEGIN
+ PNeu = (PLineInfoList) malloc(sizeof(TLineInfoList));
+ PNeu->Contents.InMacro = InMacro;
+ PNeu->Contents.LineNum = LineNum;
+ PNeu->Contents.FileName = FNum;
+ PNeu->Contents.Space = Space;
+ PNeu->Contents.Address = Address + z;
+ PNeu->Contents.Code = ((CodeLen < z + 1) OR (DontPrint)) ? 0 : WAsmCode[z];
+ if (z == 0) PFirst = PNeu;
+ if (PLast != NULL) PLast->Next = PNeu;
+ PLast = PNeu;
+ END
+
+ /* Teilliste einhaengen */
+
+ if (Run == Nil) LineInfoRoot = PFirst;
+ else Run->Next = PFirst;
+ PLast->Next = Link;
+
+ if (Space == SegCode)
+ AddAddressRange(FNum, Address, Len);
+END
+
+
+ void InitLineInfo(void)
+BEGIN
+ TempFileName[0]='\0'; LineInfoRoot=Nil;
+END
+
+
+ void ClearLineInfo(void)
+BEGIN
+ PLineInfoList Run;
+
+ if (TempFileName[0]!='\0')
+ BEGIN
+ fclose(TempFile); unlink(TempFileName);
+ END
+
+ while (LineInfoRoot!=Nil)
+ BEGIN
+ Run=LineInfoRoot; LineInfoRoot=LineInfoRoot->Next;
+ free(Run);
+ END
+
+ InitLineInfo();
+END
+
+
+ static void DumpDebugInfo_MAP(void)
+BEGIN
+ PLineInfoList Run;
+ Integer ActFile;
+ int ModZ;
+ ShortInt ActSeg;
+ FILE *MAPFile;
+ String MAPName,Tmp;
+
+ strmaxcpy(MAPName,SourceFile,255); KillSuffix(MAPName); AddSuffix(MAPName,MapSuffix);
+ MAPFile=fopen(MAPName,"w"); if (MAPFile==Nil) ChkIO(10001);
+
+ Run=LineInfoRoot; ActSeg=(-1); ActFile=(-1); ModZ=0;
+ while (Run!=Nil)
+ BEGIN
+ if (Run->Contents.Space!=ActSeg)
+ BEGIN
+ ActSeg=Run->Contents.Space;
+ if (ModZ!=0)
+ BEGIN
+ errno=0; fprintf(MAPFile,"\n"); ChkIO(10004);
+ END
+ ModZ=0;
+ errno=0; fprintf(MAPFile,"Segment %s\n",SegNames[ActSeg]); ChkIO(10004);
+ ActFile=(-1);
+ END
+ if (Run->Contents.FileName!=ActFile)
+ BEGIN
+ ActFile=Run->Contents.FileName;
+ if (ModZ!=0)
+ BEGIN
+ errno=0; fprintf(MAPFile,"\n"); ChkIO(10004);
+ END
+ ModZ=0;
+ errno=0; fprintf(MAPFile,"File %s\n",GetFileName(Run->Contents.FileName)); ChkIO(10004);
+ END;
+ errno=0;
+ sprintf(Tmp,LongIntFormat,Run->Contents.LineNum);
+ fprintf(MAPFile,"%5s:%s ",Tmp,HexString(Run->Contents.Address,8));
+ ChkIO(10004);
+ if (++ModZ==5)
+ BEGIN
+ errno=0; fprintf(MAPFile,"\n"); ChkIO(10004); ModZ=0;
+ END
+ Run=Run->Next;
+ END
+ if (ModZ!=0)
+ BEGIN
+ errno=0; fprintf(MAPFile,"\n"); ChkIO(10004);
+ END
+
+ PrintDebSymbols(MAPFile);
+
+ PrintDebSections(MAPFile);
+
+ fclose(MAPFile);
+END
+
+ static void DumpDebugInfo_Atmel(void)
+BEGIN
+ static char *OBJString="AVR Object File";
+ PLineInfoList Run;
+ LongInt FNamePos,RecPos;
+ FILE *OBJFile;
+ String OBJName;
+ char *FName;
+ Byte TByte,TNum,NameCnt;
+ int z;
+ LongInt LTurn;
+ Word WTurn;
+
+ strmaxcpy(OBJName,SourceFile,255);
+ KillSuffix(OBJName); AddSuffix(OBJName,OBJSuffix);
+ OBJFile=fopen(OBJName,OPENWRMODE); if (OBJFile==Nil) ChkIO(10001);
+
+ /* initialer Kopf, Positionen noch unbekannt */
+
+ FNamePos=0; RecPos=0;
+ if (NOT Write4(OBJFile,&FNamePos)) ChkIO(10004);
+ if (NOT Write4(OBJFile,&RecPos)) ChkIO(10004);
+ TByte=9; if (fwrite(&TByte,1,1,OBJFile)!=1) ChkIO(10004);
+ NameCnt=GetFileCount()-1; if (fwrite(&NameCnt,1,1,OBJFile)!=1) ChkIO(10004);
+ if (fwrite(OBJString,1,strlen(OBJString)+1,OBJFile)!=strlen(OBJString)+1) ChkIO(10004);
+
+ /* Objekt-Records */
+
+ RecPos=ftell(OBJFile);
+ for (Run=LineInfoRoot; Run!=Nil; Run=Run->Next)
+ if (Run->Contents.Space==SegCode)
+ BEGIN
+ LTurn=Run->Contents.Address; if (NOT BigEndian) DSwap(&LTurn,4);
+ if (fwrite(((Byte *) &LTurn)+1,1,3,OBJFile)!=3) ChkIO(10004);
+ WTurn=Run->Contents.Code; if (NOT BigEndian) WSwap(&WTurn,2);
+ if (fwrite(&WTurn,1,2,OBJFile)!=2) ChkIO(10004);
+ TNum=Run->Contents.FileName-1; if (fwrite(&TNum,1,1,OBJFile)!=1) ChkIO(10004);
+ WTurn=Run->Contents.LineNum; if (NOT BigEndian) WSwap(&WTurn,2);
+ if (fwrite(&WTurn,1,2,OBJFile)!=2) ChkIO(10004);
+ TNum=Ord(Run->Contents.InMacro); if (fwrite(&TNum,1,1,OBJFile)!=1) ChkIO(10004);
+ END
+
+ /* Dateinamen */
+
+ FNamePos=ftell(OBJFile);
+ for (z=1; z<=NameCnt; z++)
+ BEGIN
+ FName=NamePart(GetFileName(z));
+ if (fwrite(FName,1,strlen(FName)+1,OBJFile)!=strlen(FName)+1) ChkIO(10004);
+ END
+ TByte=0;
+ if (fwrite(&TByte,1,1,OBJFile)!=1) ChkIO(10004);
+
+ /* korrekte Positionen in Kopf schreiben */
+
+ rewind(OBJFile);
+ if (NOT BigEndian) DSwap(&FNamePos,4);
+ if (fwrite(&FNamePos,1,4,OBJFile)!=4) ChkIO(10004);
+ if (NOT BigEndian) DSwap(&RecPos,4);
+ if (fwrite(&RecPos,1,4,OBJFile)!=4) ChkIO(10004);
+
+ fclose(OBJFile);
+END
+
+ static void DumpDebugInfo_NOICE(void)
+BEGIN
+ PLineInfoList Run;
+ Integer ActFile;
+ FILE *MAPFile;
+ String MAPName,Tmp1,Tmp2;
+ LargeWord Start,End;
+ Boolean HadLines;
+
+ strmaxcpy(MAPName,SourceFile,255); KillSuffix(MAPName); AddSuffix(MAPName,".noi");
+ MAPFile=fopen(MAPName,"w"); if (MAPFile==Nil) ChkIO(10001);
+
+ fprintf(MAPFile,"CASE %d\n",(CaseSensitive) ? 1 : 0);
+
+ PrintNoISymbols(MAPFile);
+
+ for (ActFile=0; ActFile<GetFileCount(); ActFile++)
+ BEGIN
+ HadLines=FALSE;
+ Run=LineInfoRoot;
+ while (Run!=Nil)
+ BEGIN
+ if ((Run->Contents.Space==SegCode) AND (Run->Contents.FileName==ActFile))
+ BEGIN
+ if (NOT HadLines)
+ BEGIN
+ GetAddressRange(ActFile,&Start,&End);
+ sprintf(Tmp1,LargeIntFormat,Start);
+ errno=0;
+ fprintf(MAPFile,"FILE %s %s\n",GetFileName(Run->Contents.FileName),Tmp1);
+ ChkIO(10004);
+ END
+ errno=0;
+ sprintf(Tmp1,LongIntFormat,Run->Contents.LineNum);
+ sprintf(Tmp2,LargeIntFormat,Run->Contents.Address-Start);
+ fprintf(MAPFile,"LINE %s %s\n",Tmp1,Tmp2);
+ ChkIO(10004);
+ HadLines=TRUE;
+ END
+ Run=Run->Next;
+ END
+ if (HadLines)
+ BEGIN
+ sprintf(Tmp1,LongIntFormat,End);
+ errno=0; fprintf(MAPFile,"ENDFILE %s\n",Tmp1); ChkIO(10004);
+ END
+ END
+
+ fclose(MAPFile);
+END
+
+
+ void DumpDebugInfo(void)
+BEGIN
+ switch (DebugMode)
+ BEGIN
+ case DebugMAP: DumpDebugInfo_MAP(); break;
+ case DebugAtmel: DumpDebugInfo_Atmel(); break;
+ case DebugNoICE: DumpDebugInfo_NOICE(); break;
+ default: break;
+ END
+END
+
+
+ void asmdebug_init(void)
+BEGIN
+END
diff --git a/asmdebug.h b/asmdebug.h
new file mode 100644
index 0000000..435deb4
--- /dev/null
+++ b/asmdebug.h
@@ -0,0 +1,20 @@
+/* asmdebug.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung der Debug-Informationen zur Assemblierzeit */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void AddLineInfo(Boolean InMacro, LongInt LineNum, char *FileName,
+ ShortInt Space, LargeInt Address, LargeInt Len);
+
+extern void InitLineInfo(void);
+
+extern void ClearLineInfo(void);
+
+extern void DumpDebugInfo(void);
+
+extern void asmdebug_init(void);
diff --git a/asmdef.c b/asmdef.c
new file mode 100644
index 0000000..ac3a1fc
--- /dev/null
+++ b/asmdef.c
@@ -0,0 +1,315 @@
+/* asmdef.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* global benutzte Variablen */
+/* */
+/* Historie: 4. 5.1996 Grundsteinlegung */
+/* 24. 6.1998 Zeichenübersetzungstabellen */
+/* 25. 7.1998 PassNo --> Integer */
+/* 17. 8.1998 InMacroFlag hierher verschoben */
+/* 18. 8.1998 RadixBase hinzugenommen */
+/* ArgStr-Feld war eins zu kurz */
+/* 19. 8.1998 BranchExt-Variablen */
+/* 29. 8.1998 ActListGran hinzugenommen */
+/* 11. 9.1998 ROMDATA-Segment hinzugenommen */
+/* 1. 1.1999 SegLimits dazugenommen */
+/* SegInits --> LargeInt */
+/* 9. 1.1999 ChkPC jetzt mit Adresse als Parameter */
+/* 18. 1.1999 PCSymbol initialisiert */
+/* 17. 4.1999 DefCPU hinzugenommen */
+/* 30. 5.1999 OutRadixBase hinzugenommen */
+/* 5.11.1999 ExtendErrors von Boolean nach ShortInt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include "stringlists.h"
+#include "chunks.h"
+
+#include "asmdef.h"
+#include "asmsub.h"
+
+char SrcSuffix[]=".asm"; /* Standardendungen: Hauptdatei */
+char IncSuffix[]=".inc"; /* Includedatei */
+char PrgSuffix[]=".p"; /* Programmdatei */
+char LstSuffix[]=".lst"; /* Listingdatei */
+char MacSuffix[]=".mac"; /* Makroausgabe */
+char PreSuffix[]=".i"; /* Ausgabe Makroprozessor */
+char LogSuffix[]=".log"; /* Fehlerdatei */
+char MapSuffix[]=".map"; /* Debug-Info/Map-Format */
+char OBJSuffix[]=".obj";
+
+char *EnvName="ASCMD"; /* Environment-Variable fuer Default-
+ Parameter */
+
+char *SegNames[PCMax+1]={"NOTHING","CODE","DATA","IDATA","XDATA","YDATA",
+ "BITDATA","IO","REG","ROMDATA"};
+char SegShorts[PCMax+1]={'-','C','D','I','X','Y','B','P','R','O'};
+LongInt Magic=0x1b34244d;
+
+char *InfoMessCopyright="(C) 1992,1998 Alfred Arnold";
+
+/** ValidSymChars:SET OF Char=['A'..'Z','a'..'z',#128..#165,'0'..'9','_','.']; **/
+
+ StringPtr SourceFile; /* Hauptquelldatei */
+
+ StringPtr ClrEol; /* String fuer loeschen bis Zeilenende */
+ StringPtr CursUp; /* " " Cursor hoch */
+
+ LargeWord PCs[StructSeg+1]; /* Programmzaehler */
+ LargeWord StartAdr; /* Programmstartadresse */
+ Boolean StartAdrPresent; /* " definiert? */
+ LargeWord Phases[StructSeg+1]; /* Verschiebungen */
+ Word Grans[StructSeg+1]; /* Groesse der Adressierungselemente */
+ Word ListGrans[StructSeg+1]; /* Wortgroesse im Listing */
+ ChunkList SegChunks[StructSeg+1]; /* Belegungen */
+ Integer ActPC; /* gewaehlter Programmzaehler */
+ Boolean PCsUsed[StructSeg+1]; /* PCs bereits initialisiert ? */
+ LargeInt SegInits[PCMax+1]; /* Segmentstartwerte */
+ LargeInt SegLimits[PCMax+1]; /* Segmentgrenzwerte */
+ LongInt ValidSegs; /* erlaubte Segmente */
+ Boolean ENDOccured; /* END-Statement aufgetreten ? */
+ Boolean Retracted; /* Codes zurueckgenommen ? */
+ Boolean ListToStdout,ListToNull; /* Listing auf Konsole/Nulldevice ? */
+
+ Word TypeFlag; /* Welche Adressraeume genutzt ? */
+ ShortInt SizeFlag; /* Welche Operandengroessen definiert ? */
+
+ Integer PassNo; /* Durchlaufsnummer */
+ Integer JmpErrors; /* Anzahl fraglicher Sprungfehler */
+ Boolean ThrowErrors; /* Fehler verwerfen bei Repass ? */
+ Boolean Repass; /* noch ein Durchlauf erforderlich */
+ Byte MaxSymPass; /* Pass, nach dem Symbole definiert sein muessen */
+ Byte ShareMode; /* 0=kein SHARED,1=Pascal-,2=C-Datei, 3=ASM-Datei */
+ DebugType DebugMode; /* Ausgabeformat Debug-Datei */
+ Byte ListMode; /* 0=kein Listing,1=Konsole,2=auf Datei */
+ Byte ListOn; /* Listing erzeugen ? */
+ Boolean MakeUseList; /* Belegungsliste ? */
+ Boolean MakeCrossList; /* Querverweisliste ? */
+ Boolean MakeSectionList; /* Sektionsliste ? */
+ Boolean MakeIncludeList; /* Includeliste ? */
+ Boolean RelaxedMode; /* alle Integer-Syntaxen zulassen ? */
+ Byte ListMask; /* Listingmaske */
+ ShortInt ExtendErrors; /* erweiterte Fehlermeldungen */
+ Boolean NumericErrors; /* Fehlermeldungen mit Nummer */
+ Boolean CodeOutput; /* Code erzeugen */
+ Boolean MacProOutput; /* Makroprozessorausgabe schreiben */
+ Boolean MacroOutput; /* gelesene Makros schreiben */
+ Boolean QuietMode; /* keine Meldungen */
+ Boolean HardRanges; /* Bereichsfehler echte Fehler ? */
+ char *DivideChars; /* Trennzeichen fuer Parameter. Inhalt Read Only! */
+ Boolean HasAttrs; /* Opcode hat Attribut */
+ char *AttrChars; /* Zeichen, mit denen Attribut abgetrennt wird */
+ Boolean MsgIfRepass; /* Meldungen, falls neuer Pass erforderlich */
+ Integer PassNoForMessage; /* falls ja: ab welchem Pass ? */
+ Boolean CaseSensitive; /* Gross/Kleinschreibung unterscheiden ? */
+
+ FILE *PrgFile; /* Codedatei */
+
+ StringPtr ErrorPath,ErrorName; /* Ausgabedatei Fehlermeldungen */
+ StringPtr OutName; /* Name Code-Datei */
+ Boolean IsErrorOpen;
+ StringPtr CurrFileName; /* mom. bearbeitete Datei */
+ LongInt MomLineCounter; /* Position in mom. Datei */
+ LongInt CurrLine; /* virtuelle Position */
+ LongInt LineSum; /* Gesamtzahl Quellzeilen */
+ LongInt MacLineSum; /* inkl. Makroexpansion */
+
+ LongInt NOPCode; /* Maschinenbefehl NOP zum Stopfen */
+ Boolean TurnWords; /* TRUE = Motorola-Wortformat */
+ /* FALSE = Intel-Wortformat */
+ Byte HeaderID; /* Kennbyte des Codeheaders */
+ char *PCSymbol; /* Symbol, womit Programmzaehler erreicht wird. Inhalt Read Only! */
+ TConstMode ConstMode;
+ Boolean SetIsOccupied; /* TRUE: SET ist Prozessorbefehl */
+#ifdef __PROTOS__
+ void (*MakeCode)(void); /* Codeerzeugungsprozedur */
+ Boolean (*ChkPC)(LargeWord Addr);/* ueberprueft Codelaengenueberschreitungen */
+ Boolean (*IsDef)(void); /* ist Label nicht als solches zu werten ? */
+ void (*SwitchFrom)(void); /* bevor von einer CPU weggeschaltet wird */
+ void (*InternSymbol)(char *Asc, TempResult *Erg); /* vordefinierte Symbole ? */
+ void (*InitPassProc)(void); /* Funktion zur Vorinitialisierung vor einem Pass */
+ void (*ClearUpProc)(void); /* Aufraeumen nach Assemblierung */
+#else
+ void (*MakeCode)();
+ Boolean (*ChkPC)();
+ Boolean (*IsDef)();
+ void (*SwitchFrom)();
+ void (*InternSymbol)();
+ void (*InitPassProc)();
+ void (*ClearUpProc)();
+#endif
+
+ StringPtr IncludeList; /* Suchpfade fuer Includedateien */
+ Integer IncDepth,NextIncDepth; /* Verschachtelungstiefe INCLUDEs */
+ FILE *ErrorFile; /* Fehlerausgabe */
+ FILE *LstFile; /* Listdatei */
+ FILE *ShareFile; /* Sharefile */
+ FILE *MacProFile; /* Makroprozessorausgabe */
+ FILE *MacroFile; /* Ausgabedatei Makroliste */
+ Boolean InMacroFlag; /* momentan wird Makro expandiert */
+ StringPtr LstName; /* Name der Listdatei */
+ StringPtr MacroName,MacProName;
+ Boolean DoLst,NextDoLst; /* Listing an */
+ StringPtr ShareName; /* Name des Sharefiles */
+/** PrgName:String; { Name der Codedatei }**/
+
+ CPUVar MomCPU,MomVirtCPU; /* definierter/vorgegaukelter Prozessortyp */
+ char DefCPU[20]; /* per Kommandozeile vorgegebene CPU */
+ char MomCPUIdent[10]; /* dessen Name in ASCII */
+ PCPUDef FirstCPUDef; /* Liste mit Prozessordefinitionen */
+ CPUVar CPUCnt; /* Gesamtzahl Prozessoren */
+
+ Boolean FPUAvail; /* Koprozessor erlaubt ? */
+ Boolean DoPadding; /* auf gerade Byte-Zahl ausrichten ? */
+ Boolean SupAllowed; /* Supervisormode freigegeben */
+ Boolean Maximum; /* CPU nicht kastriert */
+ Boolean DoBranchExt; /* Spruenge automatisch verlaengern */
+
+ LargeWord RadixBase; /* Default-Zahlensystem im Formelparser*/
+ LargeWord OutRadixBase; /* dito fuer Ausgabe */
+
+ StringPtr LabPart,OpPart,AttrPart, /* Komponenten der Zeile */
+ ArgPart,CommPart,LOpPart;
+ char AttrSplit;
+ ArgStrField ArgStr; /* Komponenten des Arguments */
+ Byte ArgCnt; /* Argumentzahl */
+ StringPtr OneLine; /* eingelesene Zeile */
+
+ Byte LstCounter; /* Zeilenzaehler fuer automatischen Umbruch */
+ Word PageCounter[ChapMax+1]; /* hierarchische Seitenzaehler */
+ Byte ChapDepth; /* momentane Kapitelverschachtelung */
+ StringPtr ListLine; /* alternative Ausgabe vor Listing fuer EQU */
+ Byte PageLength,PageWidth; /* Seitenlaenge/breite in Zeilen/Spalten */
+ Boolean LstMacroEx; /* Makroexpansionen auflisten */
+ StringPtr PrtInitString; /* Druckerinitialisierungsstring */
+ StringPtr PrtExitString; /* Druckerdeinitialisierungsstring */
+ StringPtr PrtTitleString; /* Titelzeile */
+ StringPtr ExtendError; /* erweiterte Fehlermeldung */
+
+ LongInt MomSectionHandle; /* mom. Namensraum */
+ PSaveSection SectionStack; /* gespeicherte Sektionshandles */
+
+ LongInt CodeLen; /* Laenge des erzeugten Befehls */
+ LongWord *DAsmCode; /* Zwischenspeicher erzeugter Code */
+ Word *WAsmCode;
+ Byte *BAsmCode;
+
+ Boolean DontPrint; /* Flag:PC veraendert, aber keinen Code erzeugt */
+ Word ActListGran; /* uebersteuerte List-Granularitaet */
+/** MultiFace:RECORD Case Byte OF
+ 0:(Feld:WordField);
+ 1:(Val32:Single);
+ 2:(Val64:Double);
+ 3:(Val80:Extended);
+ 4:(ValCo:Comp);
+ END;**/
+
+ Byte StopfZahl; /* Anzahl der im 2.Pass festgestellten
+ ueberfluessigen Worte, die mit NOP ge-
+ fuellt werden muessen */
+
+ Boolean SuppWarns;
+
+ PTransTable TransTables, /* Liste mit Codepages */
+ CurrTransTable; /* aktuelle Codepage */
+
+ PFunction FirstFunction; /* Liste definierter Funktionen */
+
+ PDefinement FirstDefine; /* Liste von Praeprozessor-Defines */
+
+ PStructure StructureStack; /* momentan offene Strukturen */
+ int StructSaveSeg; /* gesichertes Segment waehrend Strukturdef.*/
+
+ PSaveState FirstSaveState; /* gesicherte Zustaende */
+
+ Boolean MakeDebug; /* Debugginghilfe */
+ FILE *Debug;
+
+
+ void AsmDefInit(void)
+BEGIN
+ LongInt z;
+
+ DoLst=True; PassNo=1; MaxSymPass=1;
+
+ LineSum=0;
+
+ for (z=0; z<=ChapMax; PageCounter[z++]=0);
+ LstCounter=0; ChapDepth=0;
+
+ PrtInitString[0]='\0'; PrtExitString[0]='\0'; PrtTitleString[0]='\0';
+
+ ExtendError[0]='\0';
+
+ CurrFileName[0]='\0'; MomLineCounter=0;
+
+ FirstFunction=Nil; FirstDefine=Nil; FirstSaveState=Nil;
+END
+
+ void NullProc(void)
+BEGIN
+END
+
+ void Default_InternSymbol(char *Asc, TempResult *Erg)
+BEGIN
+ Erg->Typ=TempNone;
+END
+
+ static char *GetString(void)
+BEGIN
+ return malloc(256*sizeof(char));
+END
+
+ void asmdef_init(void)
+BEGIN
+ int z;
+
+ InitPassProc=NullProc;
+ ClearUpProc=NullProc;
+ FirstCPUDef=Nil;
+ CPUCnt=0;
+ SwitchFrom=NullProc;
+ InternSymbol=Default_InternSymbol;
+
+ DAsmCode=(LongWord *) malloc(MaxCodeLen/4);
+ WAsmCode=(Word *) DAsmCode;
+ BAsmCode=(Byte *) DAsmCode;
+
+ RelaxedMode=True; ConstMode=ConstModeC;
+
+ /* auf diese Weise wird PCSymbol defaultmaessig nicht erreichbar
+ da das schon von den Konstantenparsern im Formelparser abgefangen
+ wuerde */
+
+ PCSymbol = "1";
+ *DefCPU = '\0';
+
+ for (z=0; z<=ParMax; z++) ArgStr[z]=GetString();
+ SourceFile=GetString();
+ ClrEol=GetString();
+ CursUp=GetString();
+ ErrorPath=GetString();
+ ErrorName=GetString();
+ OutName=GetString();
+ CurrFileName=GetString();
+ IncludeList=GetString();
+ LstName=GetString();
+ MacroName=GetString();
+ MacProName=GetString();
+ ShareName=GetString();
+ LabPart=GetString();
+ OpPart=GetString();
+ AttrPart=GetString();
+ ArgPart=GetString();
+ CommPart=GetString();
+ LOpPart=GetString();
+ OneLine=GetString();
+ ListLine=GetString();
+ PrtInitString=GetString();
+ PrtExitString=GetString();
+ PrtTitleString=GetString();
+ ExtendError=GetString();
+END
diff --git a/asmdef.h b/asmdef.h
new file mode 100644
index 0000000..94fb312
--- /dev/null
+++ b/asmdef.h
@@ -0,0 +1,400 @@
+/* asmdef.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* global benutzte Variablen und Definitionen */
+/* */
+/* Historie: 4. 5.1996 Grundsteinlegung */
+/* 24. 6.1998 Zeichenübersetzungstabellen */
+/* 24. 7.1998 Debug-Modus NoICE */
+/* 25. 7.1998 PassNo --> Integer */
+/* 17. 8.1998 InMacroFlag hierher verschoben */
+/* 18. 8.1998 RadixBase hinzugenommen */
+/* ArgStr-Feld war eins zu kurz */
+/* 19. 8.1998 BranchExt-Variablen */
+/* 29. 8.1998 ActListGran hinzugenommen */
+/* 1. 1.1999 SegLimits dazugenommen */
+/* SegInits --> LargeInt */
+/* 9. 1.1999 ChkPC jetzt mit Adresse als Parameter */
+/* 17. 4.1999 DefCPU hinzugenommen */
+/* 30. 5.1999 OutRadixBase hinzugenommen */
+/* 10. 7.1999 Symbolrecord hierher verschoben */
+/* 22. 9.1999 RelocEntry definiert */
+/* 5.11.1999 ExtendErrors von Boolean nach ShortInt */
+/* */
+/*****************************************************************************/
+
+#include "chunks.h"
+
+#include "fileformat.h"
+
+typedef Byte CPUVar;
+
+typedef struct _TCPUDef
+ {
+ struct _TCPUDef *Next;
+ char *Name;
+ CPUVar Number,Orig;
+ void (*SwitchProc)(
+#ifdef __PROTOS__
+ void
+#endif
+ );
+ } TCPUDef,*PCPUDef;
+
+typedef enum {TempInt,TempFloat,TempString,TempNone} TempType;
+
+typedef struct _RelocEntry
+ {
+ struct _RelocEntry *Next;
+ char *Ref;
+ Byte Add;
+ } TRelocEntry, *PRelocEntry;
+
+typedef struct
+ {
+ TempType Typ;
+ PRelocEntry Relocs;
+ union
+ {
+ LargeInt Int;
+ Double Float;
+ String Ascii;
+ } Contents;
+ } TempResult;
+
+typedef struct
+ {
+ TempType Typ;
+ TRelocEntry *Relocs;
+ union
+ {
+ LargeInt IWert;
+ Double FWert;
+ char *SWert;
+ } Contents;
+ } SymbolVal;
+
+typedef struct _TCrossRef
+ {
+ struct _TCrossRef *Next;
+ Byte FileNum;
+ LongInt LineNum;
+ Integer OccNum;
+ } TCrossRef,*PCrossRef;
+
+typedef struct _SymbolEntry
+ {
+ struct _SymbolEntry *Left,*Right;
+ ShortInt Balance;
+ LongInt Attribute;
+ char *SymName;
+ Byte SymType;
+ ShortInt SymSize;
+ Boolean Defined,Used,Changeable;
+ SymbolVal SymWert;
+ PCrossRef RefList;
+ Byte FileNum;
+ LongInt LineNum;
+ TRelocEntry *Relocs;
+ } SymbolEntry,*SymbolPtr;
+
+typedef struct _TPatchEntry
+ {
+ struct _TPatchEntry *Next;
+ LargeWord Address;
+ Byte *RelocType;
+ } TPatchEntry, *PPatchEntry;
+
+typedef enum {DebugNone,DebugMAP,DebugAOUT,DebugCOFF,DebugELF,DebugAtmel,DebugNoICE} DebugType;
+
+#define Char_NUL 0
+#define Char_BEL '\a'
+#define Char_BS '\b'
+#define Char_HT 9
+#define Char_LF '\n'
+#define Char_FF 12
+#define Char_CR 13
+#define Char_ESC 27
+
+#ifdef HAS64
+#define MaxLargeInt 0x7fffffffffffffffll
+#else
+#define MaxLargeInt 0x7fffffffl
+#endif
+
+extern char SrcSuffix[],IncSuffix[],PrgSuffix[],LstSuffix[],
+ MacSuffix[],PreSuffix[],LogSuffix[],MapSuffix[],
+ OBJSuffix[];
+
+#define MomCPUName "MOMCPU" /* mom. Prozessortyp */
+#define MomCPUIdentName "MOMCPUNAME" /* mom. Prozessortyp */
+#define SupAllowedName "INSUPMODE" /* privilegierte Befehle erlaubt */
+#define DoPaddingName "PADDING" /* Padding an */
+#define MaximumName "INMAXMODE" /* CPU im Maximum-Modus */
+#define FPUAvailName "HASFPU" /* FPU-Befehle erlaubt */
+#define LstMacroExName "MACEXP" /* expandierte Makros anzeigen */
+#define ListOnName "LISTON" /* Listing an/aus */
+#define RelaxedName "RELAXED" /* alle Zahlenschreibweisen zugelassen */
+#define SrcModeName "INSRCMODE" /* CPU im Quellcode-kompatiblen Modus */
+#define BigEndianName "BIGENDIAN" /* Datenablage MSB first */
+#define BranchExtName "BRANCHEXT" /* Spruenge autom. verlaengern */
+#define FlagTrueName "TRUE" /* Flagkonstanten */
+#define FlagFalseName "FALSE"
+#define PiName "CONSTPI" /* Zahl Pi */
+#define DateName "DATE" /* Datum & Zeit */
+#define TimeName "TIME"
+#define VerName "VERSION" /* speichert Versionsnummer */
+#define CaseSensName "CASESENSITIVE" /* zeigt Gross/Kleinunterscheidung an */
+#define Has64Name "HAS64" /* arbeitet Parser mit 64-Bit-Integers ? */
+#define ArchName "ARCHITECTURE" /* Zielarchitektur von AS */
+#define AttrName "ATTRIBUTE" /* Attributansprache in Makros */
+#define DefStackName "DEFSTACK" /* Default-Stack */
+
+extern char *EnvName;
+
+#define ParMax 20
+
+#define ChapMax 4
+
+#define StructSeg (PCMax+1)
+
+extern char *SegNames[PCMax+1];
+extern char SegShorts[PCMax+1];
+
+extern LongInt Magic;
+
+#define AscOfs '0'
+
+#define MaxCodeLen 1024
+
+extern char *InfoMessCopyright;
+
+typedef void (*SimpProc)(
+#ifdef __PROTOS__
+void
+#endif
+);
+
+typedef Word WordField[6]; /* fuer Zahlenumwandlung */
+typedef char *ArgStrField[ParMax+1];/* Feld mit Befehlsparametern */
+typedef char *StringPtr;
+
+typedef enum {ConstModeIntel, /* Hex xxxxh, Okt xxxxo, Bin xxxxb */
+ ConstModeMoto, /* Hex $xxxx, Okt @xxxx, Bin %xxxx */
+ ConstModeC} /* Hex 0x..., Okt 0...., Bin ----- */
+ TConstMode;
+
+typedef struct _TFunction
+ {
+ struct _TFunction *Next;
+ Byte ArguCnt;
+ StringPtr Name,Definition;
+ } TFunction,*PFunction;
+
+typedef struct _TTransTable
+ {
+ struct _TTransTable *Next;
+ char *Name;
+ unsigned char *Table;
+ } TTransTable,*PTransTable;
+
+typedef struct _TSaveState
+ {
+ struct _TSaveState *Next;
+ CPUVar SaveCPU;
+ Integer SavePC;
+ Byte SaveListOn;
+ Boolean SaveLstMacroEx;
+ PTransTable SaveTransTable;
+ } TSaveState,*PSaveState;
+
+typedef struct _TForwardSymbol
+ {
+ struct _TForwardSymbol *Next;
+ StringPtr Name;
+ LongInt DestSection;
+ } TForwardSymbol,*PForwardSymbol;
+
+typedef struct _TSaveSection
+ {
+ struct _TSaveSection *Next;
+ PForwardSymbol LocSyms,GlobSyms,ExportSyms;
+ LongInt Handle;
+ } TSaveSection,*PSaveSection;
+
+typedef struct _TDefinement
+ {
+ struct _TDefinement *Next;
+ StringPtr TransFrom,TransTo;
+ Byte Compiled[256];
+ } TDefinement,*PDefinement;
+
+typedef struct _TStructure
+ {
+ struct _TStructure *Next;
+ Boolean DoExt;
+ char *Name;
+ LargeWord CurrPC;
+ } TStructure,*PStructure;
+
+extern StringPtr SourceFile;
+
+extern StringPtr ClrEol;
+extern StringPtr CursUp;
+
+extern LargeWord PCs[StructSeg+1];
+extern LargeWord StartAdr;
+extern Boolean StartAdrPresent;
+extern LargeWord Phases[StructSeg+1];
+extern Word Grans[StructSeg+1];
+extern Word ListGrans[StructSeg+1];
+extern ChunkList SegChunks[StructSeg+1];
+extern Integer ActPC;
+extern Boolean PCsUsed[StructSeg+1];
+extern LargeInt SegInits[PCMax+1];
+extern LargeInt SegLimits[PCMax+1];
+extern LongInt ValidSegs;
+extern Boolean ENDOccured;
+extern Boolean Retracted;
+extern Boolean ListToStdout,ListToNull;
+
+extern Word TypeFlag;
+extern ShortInt SizeFlag;
+
+extern Integer PassNo;
+extern Integer JmpErrors;
+extern Boolean ThrowErrors;
+extern Boolean Repass;
+extern Byte MaxSymPass;
+extern Byte ShareMode;
+extern DebugType DebugMode;
+extern Byte ListMode;
+extern Byte ListOn;
+extern Boolean MakeUseList;
+extern Boolean MakeCrossList;
+extern Boolean MakeSectionList;
+extern Boolean MakeIncludeList;
+extern Boolean RelaxedMode;
+extern Byte ListMask;
+extern ShortInt ExtendErrors;
+
+extern LongInt MomSectionHandle;
+extern PSaveSection SectionStack;
+
+extern LongInt CodeLen;
+extern Byte *BAsmCode;
+extern Word *WAsmCode;
+extern LongWord *DAsmCode;
+
+extern Boolean DontPrint;
+extern Word ActListGran;
+
+extern Boolean NumericErrors;
+extern Boolean CodeOutput;
+extern Boolean MacProOutput;
+extern Boolean MacroOutput;
+extern Boolean QuietMode;
+extern Boolean HardRanges;
+extern char *DivideChars;
+extern Boolean HasAttrs;
+extern char *AttrChars;
+extern Boolean MsgIfRepass;
+extern Integer PassNoForMessage;
+extern Boolean CaseSensitive;
+
+extern FILE *PrgFile;
+
+extern StringPtr ErrorPath,ErrorName;
+extern StringPtr OutName;
+extern Boolean IsErrorOpen;
+extern StringPtr CurrFileName;
+extern LongInt CurrLine;
+extern LongInt MomLineCounter;
+extern LongInt LineSum;
+extern LongInt MacLineSum;
+
+extern LongInt NOPCode;
+extern Boolean TurnWords;
+extern Byte HeaderID;
+extern char *PCSymbol;
+extern TConstMode ConstMode;
+extern Boolean SetIsOccupied;
+extern void (*MakeCode)(void);
+extern Boolean (*ChkPC)(LargeWord Addr);
+extern Boolean (*IsDef)(void);
+extern void (*SwitchFrom)(void);
+extern void (*InternSymbol)(char *Asc, TempResult *Erg);
+extern void (*InitPassProc)(void);
+extern void (*ClearUpProc)(void);
+
+extern StringPtr IncludeList;
+extern Integer IncDepth,NextIncDepth;
+extern FILE *ErrorFile;
+extern FILE *LstFile;
+extern FILE *ShareFile;
+extern FILE *MacProFile;
+extern FILE *MacroFile;
+extern Boolean InMacroFlag;
+extern StringPtr LstName,MacroName,MacProName;
+extern Boolean DoLst,NextDoLst;
+extern StringPtr ShareName;
+extern CPUVar MomCPU,MomVirtCPU;
+extern char DefCPU[20];
+extern char MomCPUIdent[10];
+extern PCPUDef FirstCPUDef;
+extern CPUVar CPUCnt;
+
+extern Boolean FPUAvail;
+extern Boolean DoPadding;
+extern Boolean SupAllowed;
+extern Boolean Maximum;
+extern Boolean DoBranchExt;
+
+extern LargeWord RadixBase, OutRadixBase;
+
+extern StringPtr LabPart,OpPart,AttrPart,ArgPart,CommPart,LOpPart;
+extern char AttrSplit;
+extern ArgStrField ArgStr;
+extern Byte ArgCnt;
+extern StringPtr OneLine;
+
+extern Byte LstCounter;
+extern Word PageCounter[ChapMax+1];
+extern Byte ChapDepth;
+extern StringPtr ListLine;
+extern Byte PageLength,PageWidth;
+extern Boolean LstMacroEx;
+extern StringPtr PrtInitString;
+extern StringPtr PrtExitString;
+extern StringPtr PrtTitleString;
+extern StringPtr ExtendError;
+
+extern Byte StopfZahl;
+
+extern Boolean SuppWarns;
+
+#define CharTransTable CurrTransTable->Table
+extern PTransTable TransTables,CurrTransTable;
+
+extern PFunction FirstFunction;
+
+extern PDefinement FirstDefine;
+
+extern PStructure StructureStack;
+extern int StructSaveSeg;
+
+extern PSaveState FirstSaveState;
+
+extern Boolean MakeDebug;
+extern FILE *Debug;
+
+
+extern void AsmDefInit(void);
+
+extern void NullProc(void);
+
+extern void Default_InternSymbol(char *Asc, TempResult *Erg);
+
+
+extern void asmdef_init(void);
diff --git a/asmfnums.c b/asmfnums.c
new file mode 100644
index 0000000..7352ff2
--- /dev/null
+++ b/asmfnums.c
@@ -0,0 +1,167 @@
+/* asmfnums.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung von Datei-Nummern */
+/* */
+/* Historie: 15. 5.1996 Grundsteinlegung */
+/* 25. 7.1998 GetFileName jetzt mit int statt Byte */
+/* Verwaltung Adreßbereiche */
+/* Caching FileCount */
+/* 16. 8.1998 Ruecksetzen Adressbereiche */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+
+#include "asmfnums.h"
+
+#ifdef HAS64
+#define ADRMAX 9223372036854775807ll;
+#else
+#define ADRMAX 4294967295l;
+#endif
+
+
+typedef struct _TToken
+ {
+ struct _TToken *Next;
+ LargeWord FirstAddr,LastAddr;
+ char *Name;
+ } TToken,*PToken;
+
+static PToken FirstFile;
+static int FileCount;
+
+ void InitFileList(void)
+BEGIN
+ FirstFile=Nil; FileCount=0;
+END
+
+
+ void ClearFileList(void)
+BEGIN
+ PToken F;
+
+ while (FirstFile!=Nil)
+ BEGIN
+ F=FirstFile->Next;
+ free(FirstFile->Name);
+ free(FirstFile);
+ FirstFile=F;
+ END
+ FileCount=0;
+END
+
+
+ static PToken SearchToken(int Num)
+BEGIN
+ PToken Lauf=FirstFile;
+
+ while (Num>0)
+ BEGIN
+ if (Lauf==Nil) return Nil;
+ Num--; Lauf=Lauf->Next;
+ END
+ return Lauf;
+END
+
+
+ void AddFile(char *FName)
+BEGIN
+ PToken Lauf,Neu;
+
+ if (GetFileNum(FName)!=-1) return;
+
+ Neu=(PToken) malloc(sizeof(TToken));
+ Neu->Next=Nil;
+ Neu->Name=strdup(FName);
+ Neu->FirstAddr=ADRMAX;
+ Neu->LastAddr=0;
+ if (FirstFile==Nil) FirstFile=Neu;
+ else
+ BEGIN
+ Lauf=FirstFile;
+ while (Lauf->Next!=Nil) Lauf=Lauf->Next;
+ Lauf->Next=Neu;
+ END
+ FileCount++;
+END
+
+
+ Integer GetFileNum(char *Name)
+BEGIN
+ PToken FLauf=FirstFile;
+ int Cnt=0;
+
+ while ((FLauf!=Nil) AND (strcmp(FLauf->Name,Name)!=0))
+ BEGIN
+ Cnt++;
+ FLauf=FLauf->Next;
+ END
+ return (FLauf==Nil)?(-1):(Cnt);
+END
+
+
+ char *GetFileName(int Num)
+BEGIN
+ PToken Lauf=SearchToken(Num);
+ static char *Dummy="";
+
+ return (Lauf==Nil)?(Dummy):(Lauf->Name);
+END
+
+
+ Integer GetFileCount(void)
+BEGIN
+ return FileCount;
+END
+
+
+ void AddAddressRange(int File, LargeWord Start, LargeWord Len)
+BEGIN
+ PToken Lauf=SearchToken(File);
+
+ if (Lauf==Nil) return;
+
+ if (Start<Lauf->FirstAddr) Lauf->FirstAddr=Start;
+ if ((Len+=Start-1)>Lauf->LastAddr) Lauf->LastAddr=Len;
+END
+
+
+ void GetAddressRange(int File, LargeWord *Start, LargeWord *End)
+BEGIN
+ PToken Lauf=SearchToken(File);
+
+ if (Lauf==Nil)
+ BEGIN
+ *Start=ADRMAX; *End=0;
+ END
+ else
+ BEGIN
+ *Start=Lauf->FirstAddr; *End=Lauf->LastAddr;
+ END
+END
+
+ void ResetAddressRanges(void)
+BEGIN
+ PToken Run;
+
+ for (Run=FirstFile; Run!=Nil; Run=Run->Next)
+ BEGIN
+ Run->FirstAddr=ADRMAX;
+ Run->LastAddr=0;
+ END
+END
+
+ void asmfnums_init(void)
+BEGIN
+ FirstFile=Nil; FileCount=0;
+END
+
diff --git a/asmfnums.h b/asmfnums.h
new file mode 100644
index 0000000..74bec99
--- /dev/null
+++ b/asmfnums.h
@@ -0,0 +1,29 @@
+/* asmfnums.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung von Datei-Nummern */
+/* */
+/* Historie: 15. 5.96 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void InitFileList(void);
+
+extern void ClearFileList(void);
+
+extern void AddFile(char *FName);
+
+extern Integer GetFileNum(char *Name);
+
+extern char *GetFileName(int Num);
+
+extern Integer GetFileCount(void);
+
+extern void AddAddressRange(int File, LargeWord Start, LargeWord Len);
+
+extern void GetAddressRange(int File, LargeWord *Start, LargeWord *End);
+
+extern void ResetAddressRanges(void);
+
+extern void asmfnums_init(void);
diff --git a/asmif.c b/asmif.c
new file mode 100644
index 0000000..18a616e
--- /dev/null
+++ b/asmif.c
@@ -0,0 +1,433 @@
+/* asmif.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Befehle zur bedingten Assemblierung */
+/* */
+/* Historie: 15. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "bpemu.h"
+#include "chunks.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+
+#include "asmif.h"
+
+
+PIfSave FirstIfSave;
+Boolean IfAsm; /* FALSE: in einer neg. IF-Sequenz-->kein Code */
+
+static Boolean ActiveIF;
+
+ static LongInt GetIfVal(char *Cond)
+BEGIN
+ Boolean IfOK;
+ LongInt Tmp;
+
+ FirstPassUnknown=False;
+ Tmp=EvalIntExpression(Cond,Int32,&IfOK);
+ if ((FirstPassUnknown) OR (NOT IfOK))
+ BEGIN
+ Tmp=1;
+ if (FirstPassUnknown) WrError(1820);
+ else if (NOT IfOK) WrError(1135);
+ END
+
+ return Tmp;
+END
+
+
+ static void AddBoolFlag(Boolean Flag)
+BEGIN
+ strmaxcpy(ListLine,Flag?"=>TRUE":"=>FALSE",255);
+END
+
+
+ static void PushIF(LongInt IfExpr)
+BEGIN
+ PIfSave NewSave;
+
+ NewSave=(PIfSave) malloc(sizeof(TIfSave));
+ NewSave->NestLevel=SaveIFs()+1;
+ NewSave->Next=FirstIfSave; NewSave->SaveIfAsm=IfAsm;
+ NewSave->State=IfState_IFIF; NewSave->CaseFound=(IfExpr!=0);
+ FirstIfSave=NewSave;
+ IfAsm=(IfAsm AND (IfExpr!=0));
+END
+
+
+ static void CodeIF(void)
+BEGIN
+ LongInt IfExpr;
+
+ ActiveIF=IfAsm;
+
+ if (NOT IfAsm) IfExpr=1;
+ else if (ArgCnt!=1)
+ BEGIN
+ WrError(1110); IfExpr=1;
+ END
+ else IfExpr=GetIfVal(ArgStr[1]);
+ if (IfAsm) AddBoolFlag(IfExpr!=0);
+ PushIF(IfExpr);
+END
+
+
+ static void CodeIFDEF(void)
+BEGIN
+ LongInt IfExpr;
+ Boolean Defined;
+
+ ActiveIF=IfAsm;
+
+ if (NOT IfAsm) IfExpr=1;
+ else if (ArgCnt!=1)
+ BEGIN
+ WrError(1110); IfExpr=1;
+ END
+ else
+ BEGIN
+ Defined=IsSymbolDefined(ArgStr[1]);
+ if (IfAsm)
+ strmaxcpy(ListLine,(Defined)?"=>DEFINED":"=>UNDEFINED",255);
+ if (Memo("IFDEF")) IfExpr=(Defined)?1:0;
+ else IfExpr=(Defined)?0:1;
+ END
+ PushIF(IfExpr);
+END
+
+
+ static void CodeIFUSED(void)
+BEGIN
+ LongInt IfExpr;
+ Boolean Used;
+
+ ActiveIF=IfAsm;
+
+ if (NOT IfAsm) IfExpr=1;
+ else if (ArgCnt!=1)
+ BEGIN
+ WrError(1110); IfExpr=1;
+ END
+ else
+ BEGIN
+ Used=IsSymbolUsed(ArgStr[1]);
+ if (IfAsm)
+ strmaxcpy(ListLine,(Used)?"=>USED":"=>UNUSED",255);
+ if (Memo("IFUSED")) IfExpr=(Used)?1:0;
+ else IfExpr=(Used)?0:1;
+ END
+ PushIF(IfExpr);
+END
+
+
+ void CodeIFEXIST(void)
+BEGIN
+ LongInt IfExpr;
+ Boolean Found;
+ String NPath;
+
+ ActiveIF=IfAsm;
+
+ if (NOT IfAsm) IfExpr=1;
+ else if (ArgCnt!=1)
+ BEGIN
+ WrError(1110); IfExpr=1;
+ END
+ else
+ BEGIN
+ strmaxcpy(ArgPart,ArgStr[1],255);
+ if (*ArgPart=='"') strcpy(ArgPart,ArgPart+1);
+ if (ArgPart[strlen(ArgPart)-1]=='"') ArgPart[strlen(ArgPart)-1]='\0';
+ AddSuffix(ArgPart,IncSuffix);
+ strmaxcpy(NPath,IncludeList,255); strmaxprep(NPath,".:",255);
+ Found=(*(FSearch(ArgPart,NPath))!='\0');
+ if (IfAsm)
+ strmaxcpy(ListLine,(Found)?"=>FOUND":"=>NOT FOUND",255);
+ if (Memo("IFEXIST")) IfExpr=(Found)?1:0;
+ else IfExpr=(Found)?0:1;
+ END
+ PushIF(IfExpr);
+END
+
+
+ static void CodeIFB(void)
+BEGIN
+ Boolean Blank=True;
+ LongInt IfExpr;
+ int z;
+
+ ActiveIF=IfAsm;
+
+ if (NOT IfAsm) IfExpr=1;
+ else
+ BEGIN
+ for (z=1; z<=ArgCnt; z++) if (strlen(ArgStr[z++])>0) Blank=False;
+ if (IfAsm)
+ strmaxcpy(ListLine,(Blank)?"=>BLANK":"=>NOT BLANK",255);
+ if (Memo("IFB")) IfExpr=(Blank)?1:0;
+ else IfExpr=(Blank)?0:1;
+ END
+ PushIF(IfExpr);
+END
+
+
+ static void CodeELSEIF(void)
+BEGIN
+ LongInt IfExpr;
+
+ if (FirstIfSave==Nil) WrError(1840);
+ else if (ArgCnt==0)
+ BEGIN
+ if (FirstIfSave->State!=IfState_IFIF) WrError(1480);
+ else if (FirstIfSave->SaveIfAsm) AddBoolFlag(IfAsm=(NOT FirstIfSave->CaseFound));
+ FirstIfSave->State=IfState_IFELSE;
+ END
+ else if (ArgCnt==1)
+ BEGIN
+ if (FirstIfSave->State!=IfState_IFIF) WrError(1480);
+ else
+ BEGIN
+ if (NOT FirstIfSave->SaveIfAsm) IfExpr=1;
+ else if (FirstIfSave->CaseFound) IfExpr=0;
+ else IfExpr=GetIfVal(ArgStr[1]);
+ IfAsm=((FirstIfSave->SaveIfAsm) AND (IfExpr!=0) AND (NOT FirstIfSave->CaseFound));
+ if (FirstIfSave->SaveIfAsm) AddBoolFlag(IfExpr!=0);
+ if (IfExpr!=0) FirstIfSave->CaseFound=True;
+ END
+ END
+ else WrError(1110);
+
+ ActiveIF=(FirstIfSave==Nil) OR (FirstIfSave->SaveIfAsm);
+END
+
+
+ static void CodeENDIF(void)
+BEGIN
+ PIfSave NewSave;
+
+ if (ArgCnt!=0) WrError(1110);
+ if (FirstIfSave==Nil) WrError(1840);
+ else
+ BEGIN
+ if ((FirstIfSave->State!=IfState_IFIF) AND (FirstIfSave->State!=IfState_IFELSE)) WrError(1480);
+ else
+ BEGIN
+ IfAsm=FirstIfSave->SaveIfAsm;
+ NewSave=FirstIfSave; FirstIfSave=NewSave->Next;
+ free(NewSave);
+ END
+ END
+
+ ActiveIF=IfAsm;
+END
+
+
+ static void EvalIfExpression(char *Cond, TempResult *erg)
+BEGIN
+ FirstPassUnknown=False;
+ EvalExpression(Cond,erg);
+ if ((erg->Typ==TempNone) OR (FirstPassUnknown))
+ BEGIN
+ erg->Typ=TempInt; erg->Contents.Int=1;
+ if (FirstPassUnknown) WrError(1820);
+ END
+END
+
+
+ static void CodeSWITCH(void)
+BEGIN
+ PIfSave NewSave;
+
+ ActiveIF=IfAsm;
+
+ NewSave=(PIfSave) malloc(sizeof(TIfSave));
+ NewSave->NestLevel=SaveIFs()+1;
+ NewSave->Next=FirstIfSave; NewSave->SaveIfAsm=IfAsm;
+ NewSave->CaseFound=False; NewSave->State=IfState_CASESWITCH;
+ if (ArgCnt!=1)
+ BEGIN
+ NewSave->SaveExpr.Typ=TempInt;
+ NewSave->SaveExpr.Contents.Int=1;
+ if (IfAsm) WrError(1110);
+ END
+ else
+ BEGIN
+ EvalIfExpression(ArgStr[1],&(NewSave->SaveExpr));
+ SetListLineVal(&(NewSave->SaveExpr));
+ END
+ FirstIfSave=NewSave;
+END
+
+
+ static void CodeCASE(void)
+BEGIN
+ Boolean eq;
+ int z;
+ TempResult t;
+
+ if (FirstIfSave==Nil) WrError(1840);
+ else if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ if ((FirstIfSave->State!=IfState_CASESWITCH) AND (FirstIfSave->State!=IfState_CASECASE)) WrError(1480);
+ else
+ BEGIN
+ if (NOT FirstIfSave->SaveIfAsm) eq=True;
+ else if (FirstIfSave->CaseFound) eq=False;
+ else
+ BEGIN
+ eq=False; z=1;
+ do
+ BEGIN
+ EvalIfExpression(ArgStr[z],&t);
+ eq=(FirstIfSave->SaveExpr.Typ==t.Typ);
+ if (eq)
+ switch (t.Typ)
+ BEGIN
+ case TempInt: eq=(t.Contents.Int==FirstIfSave->SaveExpr.Contents.Int); break;
+ case TempFloat: eq=(t.Contents.Float==FirstIfSave->SaveExpr.Contents.Float); break;
+ case TempString: eq=(strcmp(t.Contents.Ascii,FirstIfSave->SaveExpr.Contents.Ascii)==0); break;
+ case TempNone: eq=False; break;
+ END
+ z++;
+ END
+ while ((NOT eq) AND (z<=ArgCnt));
+ END;
+ IfAsm=((FirstIfSave->SaveIfAsm) AND (eq) AND (NOT FirstIfSave->CaseFound));
+ if (FirstIfSave->SaveIfAsm) AddBoolFlag(eq AND (NOT FirstIfSave->CaseFound));
+ if (eq) FirstIfSave->CaseFound=True;
+ FirstIfSave->State=IfState_CASECASE;
+ END
+ END
+
+ ActiveIF=(FirstIfSave==Nil) OR (FirstIfSave->SaveIfAsm);
+END
+
+
+ static void CodeELSECASE(void)
+BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ if ((FirstIfSave->State!=IfState_CASESWITCH) AND (FirstIfSave->State!=IfState_CASECASE)) WrError(1480);
+ else IfAsm=(FirstIfSave->SaveIfAsm AND (NOT FirstIfSave->CaseFound));
+ if (FirstIfSave->SaveIfAsm) AddBoolFlag(NOT FirstIfSave->CaseFound);
+ FirstIfSave->CaseFound=True;
+ FirstIfSave->State=IfState_CASEELSE;
+ END
+
+ ActiveIF=(FirstIfSave==Nil) OR (FirstIfSave->SaveIfAsm);
+END
+
+
+ static void CodeENDCASE(void)
+BEGIN
+ PIfSave NewSave;
+
+ if (ArgCnt!=0) WrError(1110);
+ if (FirstIfSave==Nil) WrError(1840);
+ else
+ BEGIN
+ if ((FirstIfSave->State!=IfState_CASESWITCH)
+ AND (FirstIfSave->State!=IfState_CASECASE)
+ AND (FirstIfSave->State!=IfState_CASEELSE)) WrError(1480);
+ else
+ BEGIN
+ IfAsm=FirstIfSave->SaveIfAsm;
+ if (NOT FirstIfSave->CaseFound) WrError(100);
+ NewSave=FirstIfSave; FirstIfSave=NewSave->Next;
+ free(NewSave);
+ END
+ END
+
+ ActiveIF=IfAsm;
+END
+
+
+ Boolean CodeIFs(void)
+BEGIN
+ Boolean Result=True;
+
+ ActiveIF=False;
+
+ switch (toupper(*OpPart))
+ BEGIN
+ case 'I':
+ if (Memo("IF")) CodeIF();
+ else if ((Memo("IFDEF")) OR (Memo("IFNDEF"))) CodeIFDEF();
+ else if ((Memo("IFUSED")) OR (Memo("IFNUSED"))) CodeIFUSED();
+ else if ((Memo("IFEXIST")) OR (Memo("IFNEXIST"))) CodeIFEXIST();
+ else if ((Memo("IFB")) OR (Memo("IFNB"))) CodeIFB();
+ else Result=False;
+ break;
+ case 'E':
+ if ((Memo("ELSE")) OR (Memo("ELSEIF"))) CodeELSEIF();
+ else if (Memo("ENDIF")) CodeENDIF();
+ else if (Memo("ELSECASE")) CodeELSECASE();
+ else if (Memo("ENDCASE")) CodeENDCASE();
+ else Result=False;
+ break;
+ case 'S':
+ if (Memo("SWITCH")) CodeSWITCH();
+ else Result=False;
+ break;
+ case 'C':
+ if (Memo("CASE")) CodeCASE();
+ else Result=False;
+ break;
+ default:
+ Result=False;
+ END
+
+ return Result;
+END
+
+ Integer SaveIFs(void)
+BEGIN
+ return (FirstIfSave==Nil) ? 0 : FirstIfSave->NestLevel;
+END
+
+ void RestoreIFs(Integer Level)
+BEGIN
+ PIfSave OldSave;
+
+ while ((FirstIfSave!=Nil) AND (FirstIfSave->NestLevel!=Level))
+ BEGIN
+ OldSave=FirstIfSave; FirstIfSave=OldSave->Next;
+ IfAsm=OldSave->SaveIfAsm;
+ free(OldSave);
+ END
+END
+
+
+ Boolean IFListMask(void)
+BEGIN
+ switch (ListOn)
+ BEGIN
+ case 0: return True;
+ case 1: return False;
+ case 2: return ((NOT ActiveIF) AND (NOT IfAsm));
+ case 3: return (ActiveIF OR (NOT IfAsm));
+ END
+ return True;
+END
+
+
+ void AsmIFInit(void)
+BEGIN
+ IfAsm=True;
+END
+
+
+ void asmif_init(void)
+BEGIN
+END
diff --git a/asmif.h b/asmif.h
new file mode 100644
index 0000000..a3253ec
--- /dev/null
+++ b/asmif.h
@@ -0,0 +1,37 @@
+/* asmif.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Befehle zur bedingten Assemblierung */
+/* */
+/* Historie: 15. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+typedef struct _TIfSave
+ {
+ struct _TIfSave *Next;
+ Integer NestLevel;
+ Boolean SaveIfAsm;
+ TempResult SaveExpr;
+ enum {IfState_IFIF,IfState_IFELSE,
+ IfState_CASESWITCH,IfState_CASECASE,IfState_CASEELSE} State;
+ Boolean CaseFound;
+ } TIfSave,*PIfSave;
+
+
+extern Boolean IfAsm;
+extern PIfSave FirstIfSave;
+
+
+extern Boolean CodeIFs(void);
+
+extern void AsmIFInit(void);
+
+extern Integer SaveIFs(void);
+
+extern void RestoreIFs(Integer Level);
+
+extern Boolean IFListMask(void);
+
+extern void asmif_init(void);
diff --git a/asminclist.c b/asminclist.c
new file mode 100644
index 0000000..9645e85
--- /dev/null
+++ b/asminclist.c
@@ -0,0 +1,116 @@
+/* asminclist.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung der Include-Verschachtelungsliste */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "strutil.h"
+#include "chunks.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "as.rsc"
+#include "asmfnums.h"
+#include "asmdef.h"
+#include "asmsub.h"
+
+#include "asminclist.h"
+
+
+typedef void **PFileArray;
+typedef struct _TFileNode
+ {
+ Integer Name;
+ Integer Len;
+ struct _TFileNode *Parent;
+ PFileArray Subs;
+ } TFileNode,*PFileNode;
+
+static PFileNode Root,Curr;
+
+
+ void PushInclude(char *S)
+BEGIN
+ PFileNode Neu;
+
+ Neu=(PFileNode) malloc(sizeof(TFileNode));
+ Neu->Name=GetFileNum(S);
+ Neu->Len=0; Neu->Subs=Nil;
+ Neu->Parent=Curr;
+ if (Root==Nil) Root=Neu;
+ if (Curr==Nil) Curr=Neu;
+ else
+ BEGIN
+ if (Curr->Len==0)
+ Curr->Subs=(PFileArray) malloc(sizeof(void *));
+ else
+ Curr->Subs=(PFileArray) realloc(Curr->Subs,sizeof(void *)*(Curr->Len+1));
+ Curr->Subs[Curr->Len++]=(void *)Neu;
+ Curr=Neu;
+ END
+END
+
+
+ void PopInclude(void)
+BEGIN
+ if (Curr!=Nil) Curr=Curr->Parent;
+END
+
+
+ static void PrintIncludeList_PrintNode(PFileNode Node, int Indent)
+BEGIN
+ int z;
+ String h;
+
+ ChkStack();
+
+ if (Node!=Nil)
+ BEGIN
+ strmaxcpy(h,Blanks(Indent),255);
+ strmaxcat(h,GetFileName(Node->Name),255);
+ WrLstLine(h);
+ for (z=0; z<Node->Len; z++) PrintIncludeList_PrintNode(Node->Subs[z],Indent+5);
+ END
+END
+
+ void PrintIncludeList(void)
+BEGIN
+ NewPage(ChapDepth,True);
+ WrLstLine(getmessage(Num_ListIncludeListHead1));
+ WrLstLine(getmessage(Num_ListIncludeListHead2));
+ WrLstLine("");
+ PrintIncludeList_PrintNode(Root,0);
+END
+
+
+ static void ClearIncludeList_ClearNode(PFileNode Node)
+BEGIN
+ int z;
+
+ ChkStack();
+
+ if (Node!=Nil)
+ BEGIN
+ for (z=0; z<Node->Len; ClearIncludeList_ClearNode(Node->Subs[z++]));
+ if (Node->Len>0) free(Node->Subs);
+ free(Node);
+ END
+END
+
+ void ClearIncludeList(void)
+BEGIN
+ ClearIncludeList_ClearNode(Root);
+ Curr=Nil; Root=Nil;
+END
+
+
+ void asminclist_init(void)
+BEGIN
+ Root=Nil; Curr=Nil;
+END
diff --git a/asminclist.h b/asminclist.h
new file mode 100644
index 0000000..0c15e75
--- /dev/null
+++ b/asminclist.h
@@ -0,0 +1,19 @@
+/* asminclist.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung der Include-Verschachtelungsliste */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void PushInclude(char *S);
+
+extern void PopInclude(void);
+
+extern void PrintIncludeList(void);
+
+extern void ClearIncludeList(void);
+
+extern void asminclist_init(void);
diff --git a/asmitree.c b/asmitree.c
new file mode 100644
index 0000000..12ef168
--- /dev/null
+++ b/asmitree.c
@@ -0,0 +1,277 @@
+/* asmitree.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Opcode-Abfrage als Binaerbaum */
+/* */
+/* Historie: 30.10.1996 Grundsteinlegung */
+/* 8.10.1997 Hash-Tabelle */
+/* 6.12.1998 dynamisches Kopieren der Namen */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "chunks.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+
+#include "asmitree.h"
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean AddSingle(PInstTreeNode *Node, char *NName, InstProc NProc, Word NIndex)
+BEGIN
+ PInstTreeNode p1,p2;
+ Boolean Result=False;
+
+ ChkStack();
+
+ if (*Node==Nil)
+ BEGIN
+ *Node=(PInstTreeNode) malloc(sizeof(TInstTreeNode));
+ (*Node)->Left=Nil; (*Node)->Right=Nil;
+ (*Node)->Proc=NProc; (*Node)->Index=NIndex;
+ (*Node)->Balance=0;
+ (*Node)->Name=strdup(NName);
+ Result=True;
+ END
+ else if (strcmp(NName,(*Node)->Name)<0)
+ BEGIN
+ if (AddSingle(&((*Node)->Left),NName,NProc,NIndex))
+ switch ((*Node)->Balance)
+ BEGIN
+ case 1:
+ (*Node)->Balance=0;
+ break;
+ case 0:
+ (*Node)->Balance=(-1);
+ Result=True;
+ break;
+ case -1:
+ p1=(*Node)->Left;
+ if (p1->Balance==-1)
+ BEGIN
+ (*Node)->Left=p1->Right; p1->Right=(*Node);
+ (*Node)->Balance=0; *Node=p1;
+ END
+ else
+ BEGIN
+ p2=p1->Right;
+ p1->Right=p2->Left; p2->Left=p1;
+ (*Node)->Left=p2->Right; p2->Right=(*Node);
+ if (p2->Balance==-1) (*Node)->Balance= 1; else (*Node)->Balance=0;
+ if (p2->Balance== 1) p1 ->Balance=(-1); else p1 ->Balance=0;
+ *Node=p2;
+ END
+ (*Node)->Balance=0;
+ break;
+ END
+ END
+ else
+ BEGIN
+ if (AddSingle(&((*Node)->Right),NName,NProc,NIndex))
+ switch ((*Node)->Balance)
+ BEGIN
+ case -1:
+ (*Node)->Balance=0;
+ break;
+ case 0:
+ (*Node)->Balance=1;
+ Result=True;
+ break;
+ case 1:
+ p1=(*Node)->Right;
+ if (p1->Balance==1)
+ BEGIN
+ (*Node)->Right=p1->Left; p1->Left=(*Node);
+ (*Node)->Balance=0; *Node=p1;
+ END
+ else
+ BEGIN
+ p2=p1->Left;
+ p1->Left=p2->Right; p2->Right=p1;
+ (*Node)->Right=p2->Left; p2->Left=(*Node);
+ if (p2->Balance== 1) (*Node)->Balance=(-1); else (*Node)->Balance=0;
+ if (p2->Balance==-1) p1 ->Balance= 1; else p1 ->Balance=0;
+ *Node=p2;
+ END
+ (*Node)->Balance=0;
+ break;
+ END
+ END
+ return Result;
+END
+
+ void AddInstTree(PInstTreeNode *Root, char *NName, InstProc NProc, Word NIndex)
+BEGIN
+ AddSingle(Root,NName,NProc,NIndex);
+END
+
+ static void ClearSingle(PInstTreeNode *Node)
+BEGIN
+ ChkStack();
+
+ if (*Node!=Nil)
+ BEGIN
+ free((*Node)->Name);
+ ClearSingle(&((*Node)->Left));
+ ClearSingle(&((*Node)->Right));
+ free(*Node); *Node=Nil;
+ END
+END
+
+ void ClearInstTree(PInstTreeNode *Root)
+BEGIN
+ ClearSingle(Root);
+END
+
+ Boolean SearchInstTree(PInstTreeNode Root, char *OpPart)
+BEGIN
+ int z;
+
+ z=0;
+ while ((Root!=Nil) AND (strcmp(Root->Name,OpPart)!=0))
+ BEGIN
+ Root=(strcmp(OpPart,Root->Name)<0)? Root->Left : Root->Right;
+ z++;
+ END
+
+ if (Root==Nil) return False;
+ else
+ BEGIN
+ Root->Proc(Root->Index);
+ return True;
+ END
+END
+
+ static void PNode(PInstTreeNode Node, Word Lev)
+BEGIN
+ ChkStack();
+ if (Node!=Nil)
+ BEGIN
+ PNode(Node->Left,Lev+1);
+ printf("%*s %s %p %p %d\n",5*Lev,"",Node->Name,Node->Left,Node->Right,Node->Balance);
+ PNode(Node->Right,Lev+1);
+ END
+END
+
+ void PrintInstTree(PInstTreeNode Root)
+BEGIN
+ PNode(Root,0);
+END
+
+/*----------------------------------------------------------------------------*/
+
+ static int GetKey(char *Name, LongWord TableSize)
+BEGIN
+ register unsigned char *p;
+ LongWord tmp=0;
+
+ for (p=(unsigned char *)Name; *p!='\0'; p++) tmp=(tmp<<2)+((LongWord)*p);
+ return tmp%TableSize;
+END
+
+ PInstTable CreateInstTable(int TableSize)
+BEGIN
+ int z;
+ PInstTableEntry tmp;
+ PInstTable tab;
+
+ tmp=(PInstTableEntry) malloc(sizeof(TInstTableEntry)*TableSize);
+ for (z=0; z<TableSize; z++) tmp[z].Name=Nil;
+ tab=(PInstTable) malloc(sizeof(TInstTable));
+ tab->Fill=0; tab->Size=TableSize; tab->Entries=tmp; tab->Dynamic=FALSE;
+ return tab;
+END
+
+ void SetDynamicInstTable(PInstTable Table)
+BEGIN
+ Table->Dynamic=TRUE;
+END
+
+ void DestroyInstTable(PInstTable tab)
+BEGIN
+ int z;
+
+ if (tab->Dynamic)
+ for (z=0; z<tab->Size; z++)
+ free(tab->Entries[z].Name);
+
+ free(tab->Entries);
+ free(tab);
+END
+
+ void AddInstTable(PInstTable tab, char *Name, Word Index, InstProc Proc)
+BEGIN
+ LongWord h0=GetKey(Name,tab->Size),z=0;
+
+ /* mindestens ein freies Element lassen, damit der Sucher garantiert terminiert */
+
+ if (tab->Size-1<=tab->Fill) exit(255);
+ while (1)
+ BEGIN
+ if (tab->Entries[h0].Name==Nil)
+ BEGIN
+ tab->Entries[h0].Name=(tab->Dynamic) ? strdup(Name) : Name;
+ tab->Entries[h0].Proc=Proc;
+ tab->Entries[h0].Index=Index;
+ tab->Entries[h0].Coll=z;
+ tab->Fill++;
+ return;
+ END
+ z++;
+ if ((++h0)==tab->Size) h0=0;
+ END
+END
+
+ void RemoveInstTable(PInstTable tab, char *Name)
+BEGIN
+ LongWord h0=GetKey(Name,tab->Size);
+
+ while (1)
+ BEGIN
+ if (tab->Entries[h0].Name==Nil) return;
+ else if (strcmp(tab->Entries[h0].Name,Name)==0)
+ BEGIN
+ tab->Entries[h0].Name=Nil;
+ tab->Entries[h0].Proc=Nil;
+ tab->Fill--;
+ return;
+ END
+ if ((++h0)==tab->Size) h0=0;
+ END
+END
+
+ Boolean LookupInstTable(PInstTable tab, char *Name)
+BEGIN
+ LongWord h0=GetKey(Name,tab->Size);
+
+ while (1)
+ BEGIN
+ if (tab->Entries[h0].Name==Nil) return False;
+ else if (strcmp(tab->Entries[h0].Name,Name)==0)
+ BEGIN
+ tab->Entries[h0].Proc(tab->Entries[h0].Index);
+ return True;
+ END
+ if ((++h0)==tab->Size) h0=0;
+ END
+END
+
+ void PrintInstTable(FILE *stream, PInstTable tab)
+BEGIN
+ int z;
+
+ for (z=0; z<tab->Size; z++)
+ if (tab->Entries[z].Name!=Nil)
+ fprintf(stream,"[%3d]: %-10s Index %4d Coll %2d\n",z,tab->Entries[z].Name,tab->Entries[z].Index,tab->Entries[z].Coll);
+END
+
+/*----------------------------------------------------------------------------*/
+
+ void asmitree_init(void)
+BEGIN
+END
diff --git a/asmitree.h b/asmitree.h
new file mode 100644
index 0000000..511447b
--- /dev/null
+++ b/asmitree.h
@@ -0,0 +1,65 @@
+/* asmitree.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Opcode-Abfrage als Binaerbaum */
+/* */
+/* Historie: 30.10.1996 Grundsteinlegung */
+/* 6.12.1998 dynamische Variante */
+/* */
+/*****************************************************************************/
+
+typedef void (*InstProc)(
+#ifdef __PROTOS__
+Word Index
+#endif
+);
+typedef struct _TInstTreeNode
+ {
+ struct _TInstTreeNode *Left,*Right;
+ InstProc Proc;
+ char *Name;
+ Word Index;
+ ShortInt Balance;
+ } TInstTreeNode,*PInstTreeNode;
+
+typedef struct _TInstTableEntry
+ {
+ InstProc Proc;
+ char *Name;
+ Word Index;
+ int Coll;
+ }
+ TInstTableEntry,*PInstTableEntry;
+
+typedef struct
+ {
+ int Fill,Size;
+ Boolean Dynamic;
+ PInstTableEntry Entries;
+ } TInstTable,*PInstTable;
+
+extern void AddInstTree(PInstTreeNode *Root, char *NName, InstProc NProc, Word NIndex);
+
+extern void ClearInstTree(PInstTreeNode *Root);
+
+extern Boolean SearchInstTree(PInstTreeNode Root, char *OpPart);
+
+extern void PrintInstTree(PInstTreeNode Root);
+
+
+extern PInstTable CreateInstTable(int TableSize);
+
+extern void SetDynamicInstTable(PInstTable Table);
+
+extern void DestroyInstTable(PInstTable tab);
+
+extern void AddInstTable(PInstTable tab, char *Name, Word Index, InstProc Proc);
+
+extern void RemoveInstTable(PInstTable tab, char *Name);
+
+extern Boolean LookupInstTable(PInstTable tab, char *Name);
+
+extern void PrintInstTable(FILE *stream, PInstTable tab);
+
+extern void asmitree_init(void);
diff --git a/asmmac.c b/asmmac.c
new file mode 100644
index 0000000..8a694e4
--- /dev/null
+++ b/asmmac.c
@@ -0,0 +1,503 @@
+/* asmmac.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Unterroutinen des Makroprozessors */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* 1. 7.1998 Korrektur Boyer-Moore-Algorithmus, wenn Ungleichheit */
+/* nicht direkt am Ende */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "nlmessages.h"
+#include "as.rsc"
+#include "stringlists.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmif.h"
+
+#include "asmmac.h"
+
+
+PInputTag FirstInputTag;
+POutputTag FirstOutputTag;
+
+/*=== Praeprozessor =======================================================*/
+
+/*-------------------------------------------------------------------------*/
+/* Verwaltung define-Symbole */
+
+ static void FreeDefine(PDefinement P)
+BEGIN
+ free(P->TransFrom);
+ free(P->TransTo);
+ free(P);
+END
+
+ static void EnterDefine(char *Name, char *Definition)
+BEGIN
+ PDefinement Neu;
+ int z,l;
+
+ if (NOT ChkSymbName(Name))
+ BEGIN
+ WrXError(1020,Name); return;
+ END;
+
+ Neu=FirstDefine;
+ while (Neu!=Nil)
+ BEGIN
+ if (strcmp(Neu->TransFrom,Name)==0)
+ BEGIN
+ if (PassNo==1) WrXError(1000,Name); return;
+ END;
+ Neu=Neu->Next;
+ END
+
+ Neu=(PDefinement) malloc(sizeof(TDefinement));
+ Neu->Next=FirstDefine;
+ Neu->TransFrom=strdup(Name); if (NOT CaseSensitive) NLS_UpString(Neu->TransFrom);
+ Neu->TransTo=strdup(Definition);
+ l=strlen(Name);
+ for (z=0; z<256; Neu->Compiled[z++]=l);
+ for (z=0; z<l-1; z++) Neu->Compiled[(unsigned int)Neu->TransFrom[z]]=l-(z+1);
+ FirstDefine=Neu;
+END
+
+ static void RemoveDefine(char *Name_O)
+BEGIN
+ PDefinement Lauf,Del;
+ String Name;
+
+ strmaxcpy(Name,Name_O,255);
+ if (NOT CaseSensitive) NLS_UpString(Name);
+
+ Del=Nil;
+
+ if (FirstDefine!=Nil)
+ BEGIN
+ if (strcmp(FirstDefine->TransFrom,Name)==0)
+ BEGIN
+ Del=FirstDefine; FirstDefine=FirstDefine->Next;
+ END
+ else
+ BEGIN
+ Lauf=FirstDefine;
+ while ((Lauf->Next!=Nil) AND (strcmp(Lauf->Next->TransFrom,Name)!=0))
+ Lauf=Lauf->Next;
+ if (Lauf->Next!=Nil)
+ BEGIN
+ Del=Lauf->Next; Lauf->Next=Del->Next;
+ END
+ END
+ END
+
+ if (Del==Nil) WrXError(1010,Name);
+ else FreeDefine(Del);
+END
+
+ void PrintDefineList(void)
+BEGIN
+ PDefinement Lauf;
+ String OneS;
+
+ if (FirstDefine==Nil) return;
+
+ NewPage(ChapDepth,True);
+ WrLstLine(getmessage(Num_ListDefListHead1));
+ WrLstLine(getmessage(Num_ListDefListHead2));
+ WrLstLine("");
+
+ Lauf=FirstDefine;
+ while (Lauf!=Nil)
+ BEGIN
+ strmaxcpy(OneS,Lauf->TransFrom,255);
+ strmaxcat(OneS,Blanks(10-(strlen(Lauf->TransFrom)%10)),255);
+ strmaxcat(OneS," = ",255);
+ strmaxcat(OneS,Lauf->TransTo,255);
+ WrLstLine(OneS);
+ Lauf=Lauf->Next;
+ END
+ WrLstLine("");
+END
+
+ void ClearDefineList(void)
+BEGIN
+ PDefinement Temp;
+
+ while (FirstDefine!=Nil)
+ BEGIN
+ Temp=FirstDefine; FirstDefine=FirstDefine->Next;
+ FreeDefine(Temp);
+ END
+END
+
+/*------------------------------------------------------------------------*/
+/* Interface */
+
+ void Preprocess(void)
+BEGIN
+ String h,Cmd,Arg;
+ char *p;
+
+ p=strchr(OneLine,'#')+1;
+ strmaxcpy(h,p,255);
+ p=FirstBlank(h);
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Cmd,h,255); *h='\0';
+ END
+ else SplitString(h,Cmd,h,p);
+
+ KillPrefBlanks(h); KillPostBlanks(h);
+
+ if (NOT IfAsm) return;
+
+ if (strcasecmp(Cmd,"DEFINE")==0)
+ BEGIN
+ p=FirstBlank(h);
+ if (p!=Nil)
+ BEGIN
+ SplitString(h,Arg,h,p); KillPrefBlanks(h);
+ EnterDefine(Arg,h);
+ END
+ END
+ else if (strcasecmp(Cmd,"UNDEF")==0) RemoveDefine(h);
+
+ CodeLen=0;
+END
+
+ static Boolean ExpandDefines_NErl(char inp)
+BEGIN
+ return (((inp>='0') AND (inp<='9')) OR ((inp>='A') AND (inp<='Z')) OR ((inp>='a') AND (inp<='z')));
+END
+
+#define t_toupper(ch) ((CaseSensitive) ? (ch) : (toupper(ch)))
+
+ void ExpandDefines(char *Line)
+BEGIN
+ PDefinement Lauf;
+ sint LPos,Diff,p,p2,p3,z,z2,FromLen,ToLen,LineLen;
+
+ Lauf=FirstDefine;
+ while (Lauf!=Nil)
+ BEGIN
+ LPos=0; FromLen=strlen(Lauf->TransFrom); ToLen=strlen(Lauf->TransTo);
+ Diff=ToLen-FromLen;
+ do
+ BEGIN
+ /* Stelle, ab der verbatim, suchen -->p */
+ p=LPos;
+ while ((p<strlen(Line)) AND (Line[p]!='\'') AND (Line[p]!='"')) p++;
+ /* nach Quellstring suchen, ersetzen, bis keine Treffer mehr */
+ p2=LPos;
+ do
+ BEGIN
+ z2=0;
+ while ((z2>=0) AND (p2<=p-FromLen))
+ BEGIN
+ z2=FromLen-1; z=p2+z2;
+ while ((z2>=0) AND (t_toupper(Line[z])==Lauf->TransFrom[z2]))
+ BEGIN
+ z2--; z--;
+ END
+ if (z2>=0) p2+=Lauf->Compiled[(unsigned int)t_toupper(Line[p2+FromLen-1])];
+ END
+ if (z2==-1)
+ BEGIN
+ if (((p2==0) OR (NOT ExpandDefines_NErl(Line[p2-1])))
+ AND ((p2+FromLen==p) OR (NOT ExpandDefines_NErl(Line[p2+FromLen]))))
+ BEGIN
+ if (Diff!=0)
+ memmove(Line+p2+ToLen,Line+p2+FromLen,strlen(Line)-p2-FromLen+1);
+ memcpy(Line+p2,Lauf->TransTo,ToLen);
+ p+=Diff; /* !!! */
+ p2+=ToLen;
+ END
+ else p2+=FromLen;
+ END
+ END
+ while (z2==-1);
+ /* Endposition verbatim suchen */
+ p3=p+1; LineLen=strlen(Line);
+ while ((p3<LineLen) AND (Line[p3]!=Line[p])) p3++;
+ /* Zaehler entsprechend herauf */
+ LPos=p3+1;
+ END
+ while (LPos<=LineLen-FromLen);
+ Lauf=Lauf->Next;
+ END
+END
+
+/*=== Makrolistenverwaltung ===============================================*/
+
+typedef struct _TMacroNode
+ {
+ struct _TMacroNode *Left,*Right; /* Soehne im Baum */
+ ShortInt Balance;
+ LongInt DefSection; /* Gueltigkeitssektion */
+ Boolean Defined;
+ PMacroRec Contents;
+ } TMacroNode,*PMacroNode;
+
+static PMacroNode MacroRoot;
+
+ static Boolean AddMacro_AddNode(PMacroNode *Node, PMacroRec Neu,
+ LongInt DefSect, Boolean Protest)
+BEGIN
+ Boolean Grown;
+ PMacroNode p1,p2;
+ Boolean Result;
+ int SErg;
+
+ ChkStack();
+
+
+ if (*Node==Nil)
+ BEGIN
+ *Node=(PMacroNode) malloc(sizeof(TMacroNode));
+ (*Node)->Left=Nil; (*Node)->Right=Nil;
+ (*Node)->Balance=0; (*Node)->Defined=True;
+ (*Node)->DefSection=DefSect; (*Node)->Contents=Neu;
+ return True;
+ END
+ else Result=False;
+
+ SErg=StrCmp(Neu->Name,(*Node)->Contents->Name,DefSect,(*Node)->DefSection);
+ if (SErg>0)
+ BEGIN
+ Grown=AddMacro_AddNode(&((*Node)->Right),Neu,DefSect,Protest);
+ if ((BalanceTree) AND (Grown))
+ switch ((*Node)->Balance)
+ BEGIN
+ case -1:
+ (*Node)->Balance=0;
+ break;
+ case 0:
+ (*Node)->Balance=1; Result=True;
+ break;
+ case 1:
+ p1=(*Node)->Right;
+ if (p1->Balance==1)
+ BEGIN
+ (*Node)->Right=p1->Left; p1->Left=(*Node);
+ (*Node)->Balance=0; *Node=p1;
+ END
+ else
+ BEGIN
+ p2=p1->Left;
+ p1->Left=p2->Right; p2->Right=p1;
+ (*Node)->Right=p2->Left; p2->Left=(*Node);
+ if (p2->Balance== 1) (*Node)->Balance=(-1); else (*Node)->Balance=0;
+ if (p2->Balance==-1) p1 ->Balance= 1; else p1 ->Balance=0;
+ *Node=p2;
+ END
+ (*Node)->Balance=0;
+ break;
+ END
+ END
+ else if (SErg<0)
+ BEGIN
+ Grown=AddMacro_AddNode(&((*Node)->Left),Neu,DefSect,Protest);
+ if ((BalanceTree) AND (Grown))
+ switch ((*Node)->Balance)
+ BEGIN
+ case 1:
+ (*Node)->Balance=0;
+ break;
+ case 0:
+ (*Node)->Balance=(-1); Result=True;
+ break;
+ case -1:
+ p1=(*Node)->Left;
+ if (p1->Balance==-1)
+ BEGIN
+ (*Node)->Left=p1->Right; p1->Right=(*Node);
+ (*Node)->Balance=0; *Node=p1;
+ END
+ else
+ BEGIN
+ p2=p1->Right;
+ p1->Right=p2->Left; p2->Left=p1;
+ (*Node)->Left=p2->Right; p2->Right=(*Node);
+ if (p2->Balance==-1) (*Node)->Balance= 1; else (*Node)->Balance=0;
+ if (p2->Balance== 1) p1 ->Balance=(-1); else p1 ->Balance=0;
+ *Node=p2;
+ END
+ (*Node)->Balance=0;
+ break;
+ END
+ END
+ else
+ BEGIN
+ if ((*Node)->Defined)
+ if (Protest) WrXError(1815,Neu->Name);
+ else
+ BEGIN
+ ClearMacroRec(&((*Node)->Contents)); (*Node)->Contents=Neu;
+ (*Node)->DefSection=DefSect;
+ END
+ else
+ BEGIN
+ ClearMacroRec(&((*Node)->Contents)); (*Node)->Contents=Neu;
+ (*Node)->DefSection=DefSect; (*Node)->Defined=True;
+ END
+ END
+
+ return Result;
+END
+
+ void AddMacro(PMacroRec Neu, LongInt DefSect, Boolean Protest)
+BEGIN
+ if (NOT CaseSensitive) NLS_UpString(Neu->Name);
+ AddMacro_AddNode(&MacroRoot,Neu,DefSect,Protest);
+END
+
+ static Boolean FoundMacro_FNode(LongInt Handle,PMacroRec *Erg, char *Part)
+BEGIN
+ PMacroNode Lauf;
+ int CErg;
+
+ Lauf=MacroRoot; CErg=2;
+ while ((Lauf!=Nil) AND (CErg!=0))
+ BEGIN
+ if ((CErg=StrCmp(Part,Lauf->Contents->Name,Handle,Lauf->DefSection))<0) Lauf=Lauf->Left;
+ else if (CErg>0) Lauf=Lauf->Right;
+ END
+ if (Lauf!=Nil) *Erg=Lauf->Contents;
+ return (Lauf!=Nil);
+END
+
+ Boolean FoundMacro(PMacroRec *Erg)
+BEGIN
+ PSaveSection Lauf;
+ String Part;
+
+ strmaxcpy(Part,LOpPart,255); if (NOT CaseSensitive) NLS_UpString(Part);
+
+ if (FoundMacro_FNode(MomSectionHandle,Erg,Part)) return True;
+ Lauf=SectionStack;
+ while (Lauf!=Nil)
+ BEGIN
+ if (FoundMacro_FNode(Lauf->Handle,Erg,Part)) return True;
+ Lauf=Lauf->Next;
+ END
+ return False;
+END
+
+ static void ClearMacroList_ClearNode(PMacroNode *Node)
+BEGIN
+ ChkStack();
+
+ if (*Node==Nil) return;
+
+ ClearMacroList_ClearNode(&((*Node)->Left));
+ ClearMacroList_ClearNode(&((*Node)->Right));
+
+ ClearMacroRec(&((*Node)->Contents)); free(*Node); *Node=Nil;
+END
+
+ void ClearMacroList(void)
+BEGIN
+ ClearMacroList_ClearNode(&MacroRoot);
+END
+
+ static void ResetMacroDefines_ResetNode(PMacroNode Node)
+BEGIN
+ ChkStack();
+
+ if (Node==Nil) return;
+
+ ResetMacroDefines_ResetNode(Node->Left);
+ ResetMacroDefines_ResetNode(Node->Right);
+ Node->Defined=False;
+END
+
+ void ResetMacroDefines(void)
+BEGIN
+ ResetMacroDefines_ResetNode(MacroRoot);
+END
+
+ void ClearMacroRec(PMacroRec *Alt)
+BEGIN
+ free((*Alt)->Name);
+ ClearStringList(&((*Alt)->FirstLine));
+ free(*Alt); *Alt=Nil;
+END
+
+ static void PrintMacroList_PNode(PMacroNode Node, LongInt *Sum, Boolean *cnt, char *OneS)
+BEGIN
+ String h;
+
+ strmaxcpy(h,Node->Contents->Name,255);
+ if (Node->DefSection!=-1)
+ BEGIN
+ strmaxcat(h,"[",255);
+ strmaxcat(h,GetSectionName(Node->DefSection),255);
+ strmaxcat(h,"]",255);
+ END
+ strmaxcat(OneS,h,255);
+ if (strlen(h)<37) strmaxcat(OneS,Blanks(37-strlen(h)),255);
+ if (NOT (*cnt)) strmaxcat(OneS," | ",255);
+ else
+ BEGIN
+ WrLstLine(OneS); OneS[0]='\0';
+ END
+ *cnt=NOT (*cnt); (*Sum)++;
+END
+
+ static void PrintMacroList_PrintNode(PMacroNode Node, LongInt *Sum, Boolean *cnt, char *OneS)
+BEGIN
+ if (Node==Nil) return;
+ ChkStack();
+
+ PrintMacroList_PrintNode(Node->Left,Sum,cnt,OneS);
+
+ PrintMacroList_PNode(Node,Sum,cnt,OneS);
+
+ PrintMacroList_PrintNode(Node->Right,Sum,cnt,OneS);
+END
+
+ void PrintMacroList(void)
+BEGIN
+ String OneS;
+ Boolean cnt;
+ LongInt Sum;
+
+ if (MacroRoot==Nil) return;
+
+ NewPage(ChapDepth,True);
+ WrLstLine(getmessage(Num_ListMacListHead1));
+ WrLstLine(getmessage(Num_ListMacListHead2));
+ WrLstLine("");
+
+ OneS[0]='\0'; cnt=False; Sum=0;
+ PrintMacroList_PrintNode(MacroRoot,&Sum,&cnt,OneS);
+ if (cnt)
+ BEGIN
+ OneS[strlen(OneS)-1]='\0';
+ WrLstLine(OneS);
+ END
+ WrLstLine("");
+ sprintf(OneS,"%7d",Sum);
+ strmaxcat(OneS,getmessage((Sum==1)?Num_ListMacSumMsg:Num_ListMacSumsMsg),255);
+ WrLstLine(OneS);
+ WrLstLine("");
+END
+
+/*=== Eingabefilter Makroprozessor ========================================*/
+
+
+ void asmmac_init(void)
+BEGIN
+ MacroRoot=Nil;
+END
diff --git a/asmmac.h b/asmmac.h
new file mode 100644
index 0000000..7320058
--- /dev/null
+++ b/asmmac.h
@@ -0,0 +1,105 @@
+/* asmmac.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Unterroutinen des Makroprozessors */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+typedef struct _MacroRec
+ {
+ char *Name; /* Name des Makros */
+ Byte ParamCount; /* Anzahl Parameter */
+ StringList FirstLine; /* Zeiger auf erste Zeile */
+ Boolean Used; /* wird gerade benutzt-verhindert Rekusion */
+ Boolean LocMacExp; /* Makroexpansion wird aufgelistet */
+ } MacroRec,*PMacroRec;
+
+#define BufferArraySize 1024
+
+typedef struct _TInputTag
+ {
+ struct _TInputTag *Next;
+ Boolean IsMacro;
+ Integer IfLevel;
+ Boolean First;
+ Boolean OrigDoLst;
+ LongInt StartLine;
+ Boolean (*Processor)(
+#ifdef __PROTOS__
+ struct _TInputTag *P, char *erg
+#endif
+ );
+ LongInt ParCnt,ParZ;
+ StringList Params;
+ LongInt LineCnt,LineZ;
+ StringRecPtr Lines;
+ String SpecName,SaveAttr;
+ Boolean IsEmpty;
+ FILE *Datei;
+ void *Buffer;
+ void (*Cleanup)(
+#ifdef __PROTOS__
+ struct _TInputTag *P
+#endif
+ );
+ void (*Restorer)(
+#ifdef __PROTOS__
+ struct _TInputTag *P
+#endif
+ );
+ Boolean (*GetPos)(
+#ifdef __PROTOS__
+ struct _TInputTag *P, char *Dest
+#endif
+ );
+ } TInputTag,*PInputTag;
+
+typedef struct _TOutputTag
+ {
+ struct _TOutputTag *Next;
+ void (*Processor)(
+#ifdef __PROTOS__
+void
+#endif
+);
+ Integer NestLevel;
+ PInputTag Tag;
+ PMacroRec Mac;
+ StringList Params;
+ LongInt PubSect,GlobSect;
+ Boolean DoExport,DoGlobCopy;
+ String GName;
+ } TOutputTag,*POutputTag;
+
+
+extern PInputTag FirstInputTag;
+extern POutputTag FirstOutputTag;
+
+
+extern void Preprocess(void);
+
+
+extern void AddMacro(PMacroRec Neu, LongInt DefSect, Boolean Protest);
+
+extern Boolean FoundMacro(PMacroRec *Erg);
+
+extern void ClearMacroList(void);
+
+extern void ResetMacroDefines(void);
+
+extern void ClearMacroRec(PMacroRec *Alt);
+
+extern void PrintMacroList(void);
+
+
+extern void PrintDefineList(void);
+
+extern void ClearDefineList(void);
+
+extern void ExpandDefines(char *Line);
+
+
+extern void asmmac_init(void);
diff --git a/asmpars.c b/asmpars.c
new file mode 100644
index 0000000..34b2b9b
--- /dev/null
+++ b/asmpars.c
@@ -0,0 +1,3822 @@
+/* asmpars.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung von Symbolen und das ganze Drumherum... */
+/* */
+/* Historie: 5. 5.1996 Grundsteinlegung */
+/* 4. 1.1997 Umstellung wg. case-sensitiv */
+/* 24. 9.1997 Registersymbole */
+/* 26. 6.1998 Codepages */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 17. 7.1998 Korrektur Maskentabellen */
+/* 16. 8.1998 NoICE-Symbolausgabe */
+/* 18. 8.1998 Benutzung RadixBase */
+/* 19. 8.1998 == als Alias fuer = - Operator */
+/* 1. 9.1998 RefList nicht initialisiert bei Symbolen */
+/* ACOT korrigiert */
+/* 6.12.1998 UInt14 */
+/* 30. 1.1999 Formate maschinenunabhaengig gemacht */
+/* 12. 2.1999 Compilerwarnungen beseitigt */
+/* 17. 4.1999 Abfrage auf PCSymbol gegen Nullzeigerzugriff ge- */
+/* schuetzt. */
+/* 30. 5.1999 OutRadixBase beruecksichtigt */
+/* 12. 7.1999 angefangen mit externen Symbolen */
+/* 14. 7.1999 Relocs im Parser beruecksichtigt */
+/* 1. 8.1999 Relocs im Formelparser durch */
+/* 8. 8.1999 Relocs in EvalIntExpression beruecksichtigt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "endian.h"
+#include "bpemu.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "as.rsc"
+#include "strutil.h"
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmfnums.h"
+#include "asmrelocs.h"
+#include "chunks.h"
+
+#include "asmpars.h"
+
+LargeWord IntMasks[IntTypeCnt]=
+ {0x00000001l, /* UInt1 */
+ 0x00000003l, /* UInt2 */
+ 0x00000007l, /* UInt3 */
+ 0x00000007l,0x0000000fl,0x0000000fl, /* SInt4 UInt4 Int4 */
+ 0x0000000fl,0x0000001fl,0x0000001fl, /* SInt5 UInt5 Int5 */
+ 0x0000003fl, /* UInt6 */
+ 0x0000003fl,0x0000007fl, /* SInt7 UInt7 */
+ 0x0000007fl,0x000000ffl,0x000000ffl, /* SInt8 UInt8 Int8 */
+ 0x000001ffl, /* UInt9 */
+ 0x000003ffl,0x000003ffl, /* UInt10 Int10 */
+ 0x000007ffl, /* UInt11 */
+ 0x00000fffl,0x00000fffl, /* UInt12 Int12 */
+ 0x00001fffl, /* UInt13 */
+ 0x00003fffl, /* UInt14 */
+ 0x00007fffl, /* UInt15 */
+ 0x00007fffl,0x0000ffffl,0x0000ffffl, /* SInt16 UInt16 Int16 */
+ 0x0003ffffl, /* UInt18 */
+ 0x0007ffffl,0x000fffffl,0x000fffffl, /* SInt20 UInt20 Int20 */
+ 0x003fffffl, /* UInt22 */
+ 0x007fffffl,0x00ffffffl,0x00ffffffl, /* SInt24 UInt24 Int24 */
+ 0xffffffffl,0xffffffffl,0xffffffffl /* SInt32 UInt32 Int32 */
+#ifdef HAS64
+ ,0xffffffffffffffffllu /* Int64 */
+#endif
+ };
+
+LargeInt IntMins[IntTypeCnt]=
+ { 0l, /* UInt1 */
+ 0l, /* UInt2 */
+ 0l, /* UInt3 */
+ -8l, 0l, -8l, /* SInt4 UInt4 Int4 */
+ -16l, 0l, -16l, /* SInt5 UInt5 Int5 */
+ 0l, /* UInt6 */
+ -64, 0l, /* SInt7 UInt7 */
+ -128l, 0l, -128l, /* SInt8 UInt8 Int8 */
+ 0l, /* UInt9 */
+ 0l, -512l, /* UInt10 Int10 */
+ 0l, /* UInt11 */
+ 0l, -2047l, /* UInt12 Int12 */
+ 0l, /* UInt13 */
+ 0l, /* UInt14 */
+ 0l, /* UInt15 */
+ -32768l, 0l, -32768l, /* SInt16 UInt16 Int16 */
+ 0l, /* UInt18 */
+ -524288l, 0l, -524288l, /* SInt20 UInt20 Int20 */
+ 0l, /* UInt22 */
+ -8388608l, 0l, -8388608l, /* SInt24 UInt24 Int24 */
+ -2147483647l, 0l,-2147483647l /* SInt32 UInt32 Int32 */
+#ifdef HAS64
+ ,-9223372036854775807ll /* Int64 */
+#endif
+ };
+
+LargeInt IntMaxs[IntTypeCnt]=
+ { 1l, /* UInt1 */
+ 3l, /* UInt2 */
+ 7l, /* UInt3 */
+ 7l, 15l, 15l, /* SInt4 UInt4 Int4 */
+ 15l, 31l, 31l, /* SInt5 UInt5 Int5 */
+ 63l, /* UInt6 */
+ 63l, 127l, /* SInt7 UInt7 */
+ 127l, 255l, 255l, /* SInt8 UInt8 Int8 */
+ 511l, /* UInt9 */
+ 1023l, 1023l, /* UInt10 Int10 */
+ 2047l, /* UInt11 */
+ 4095l, 4095l, /* UInt12 Int12 */
+ 8191l, /* UInt13 */
+ 16383l, /* UInt14 */
+ 32767l, /* UInt15 */
+ 32767l, 65535l, 65535l, /* SInt16 UInt16 Int16 */
+ 262143l, /* UInt18 */
+ 524287l, /* SInt20 */
+ 1048575l, 1048575l, /* UInt20 Int20 */
+ 4194303l, /* UInt22 */
+#ifdef __STDC__
+ 8388607l, 16777215l, 16777215l, /* SInt24 UInt24 Int24 */
+ 2147483647l, 4294967295ul,4294967295ul /* SInt32 UInt32 Int32 */
+#else
+ 8388607l, 16777215l, 16777215l, /* SInt24 UInt24 Int24 */
+ 2147483647l, 4294967295l, 4294967295l /* SInt32 UInt32 Int32 */
+#endif
+#ifdef HAS64
+ , 9223372036854775807ll /* Int64 */
+#endif
+ };
+
+
+Boolean FirstPassUnknown; /* Hinweisflag: evtl. im ersten Pass unbe-
+ kanntes Symbol, Ausdruck nicht ausgewertet */
+Boolean SymbolQuestionable; /* Hinweisflag: Dadurch, dass Phasenfehler
+ aufgetreten sind, ist dieser Symbolwert evtl.
+ nicht mehr aktuell */
+Boolean UsesForwards; /* Hinweisflag: benutzt Vorwaertsdefinitionen */
+LongInt MomLocHandle; /* Merker, den lokale Symbole erhalten */
+
+LongInt LocHandleCnt; /* mom. verwendeter lokaler Handle */
+
+Boolean BalanceTree; /* Symbolbaum ausbalancieren */
+
+
+static char BaseIds[3]={'%','@','$'};
+static char BaseLetters[3]={'B','O','H'};
+static Byte BaseVals[3]={2,8,16};
+
+typedef struct _TSymbolStackEntry
+ {
+ struct _TSymbolStackEntry *Next;
+ SymbolVal Contents;
+ } TSymbolStackEntry,*PSymbolStackEntry;
+
+typedef struct _TSymbolStack
+ {
+ struct _TSymbolStack *Next;
+ char *Name;
+ PSymbolStackEntry Contents;
+ } TSymbolStack,*PSymbolStack;
+
+typedef struct _TDefSymbol
+ {
+ struct _TDefSymbol *Next;
+ char *SymName;
+ TempResult Wert;
+ } TDefSymbol,*PDefSymbol;
+
+typedef struct _TCToken
+ {
+ struct _TCToken *Next;
+ char *Name;
+ LongInt Parent;
+ ChunkList Usage;
+ } TCToken,*PCToken;
+
+typedef struct Operator
+ {
+ char *Id;
+ int IdLen;
+ Boolean Dyadic;
+ Byte Priority;
+ Boolean MayInt;
+ Boolean MayFloat;
+ Boolean MayString;
+ Boolean Present;
+ } Operator;
+
+typedef struct _TLocHeap
+ {
+ struct _TLocHeap *Next;
+ LongInt Cont;
+ } TLocHeap,*PLocHandle;
+
+typedef struct _TRegDefList
+ {
+ struct _TRegDefList *Next;
+ LongInt Section;
+ char *Value;
+ Boolean Used;
+ } TRegDefList,*PRegDefList;
+
+typedef struct _TRegDef
+ {
+ struct _TRegDef *Left,*Right;
+ char *Orig;
+ PRegDefList Defs,DoneDefs;
+ } TRegDef,*PRegDef;
+
+static SymbolPtr FirstSymbol,FirstLocSymbol;
+static PDefSymbol FirstDefSymbol;
+/*static*/ PCToken FirstSection;
+static PRegDef FirstRegDef;
+static Boolean DoRefs; /* Querverweise protokollieren */
+static PLocHandle FirstLocHandle;
+static PSymbolStack FirstStack;
+static PCToken MomSection;
+
+ void AsmParsInit(void)
+BEGIN
+ FirstSymbol=Nil;
+
+ FirstLocSymbol = Nil; MomLocHandle = (-1); SetMomSection(-1);
+ FirstSection = Nil;
+ FirstLocHandle = Nil;
+ FirstStack = Nil;
+ FirstRegDef = Nil;
+ DoRefs = True;
+ RadixBase = 10;
+ OutRadixBase = 16;
+END
+
+
+ Boolean RangeCheck(LargeInt Wert, IntType Typ)
+BEGIN
+#ifndef HAS64
+ if (((int)Typ)>=((int)SInt32)) return True;
+#else
+ if (((int)Typ)>=((int)Int64)) return True;
+#endif
+ else return ((Wert>=IntMins[(int)Typ]) AND (Wert<=IntMaxs[(int)Typ]));
+END
+
+ Boolean FloatRangeCheck(Double Wert, FloatType Typ)
+BEGIN
+ switch (Typ)
+ BEGIN
+ case Float32 : return (fabs(Wert)<=3.4e38);
+ case Float64 : return (fabs(Wert)<=1.7e308);
+/** case FloatCo : FloatRangeCheck:=Abs(Wert)<=9.22e18;
+ case Float80 : FloatRangeCheck:=True;
+ case FloatDec : FloatRangeCheck:=True;**/
+ default: return False;
+ END
+/** IF (Typ=FloatDec) AND (Abs(Wert)>1e1000) THEN WrError(40);**/
+END
+
+
+ Boolean SingleBit(LargeInt Inp, LargeInt *Erg)
+BEGIN
+ *Erg=0;
+ do
+ BEGIN
+ if (NOT Odd(Inp)) (*Erg)++;
+ if (NOT Odd(Inp)) Inp=Inp>>1;
+ END
+ while ((*Erg!=LARGEBITS) AND (NOT Odd(Inp)));
+ return (*Erg!=LARGEBITS) AND (Inp==1);
+END
+
+
+ static Boolean ProcessBk(char **Start, char *Erg)
+BEGIN
+ LongInt System=0,Acc=0,Digit=0;
+ char ch;
+ int cnt;
+ Boolean Finish;
+
+ switch (toupper(**Start))
+ BEGIN
+ case '\'': case '\\': case '"':
+ *Erg=**Start; (*Start)++; return True;
+ case 'H':
+ *Erg='\''; (*Start)++; return True;
+ case 'I':
+ *Erg='"'; (*Start)++; return True;
+ case 'B':
+ *Erg=Char_BS; (*Start)++; return True;
+ case 'A':
+ *Erg=Char_BEL; (*Start)++; return True;
+ case 'E':
+ *Erg=Char_ESC; (*Start)++; return True;
+ case 'T':
+ *Erg=Char_HT; (*Start)++; return True;
+ case 'N':
+ *Erg=Char_LF; (*Start)++; return True;
+ case 'R':
+ *Erg=Char_CR; (*Start)++; return True;
+ case 'X':
+ System=16; (*Start)++;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (System==0) System=(**Start=='0')?8:10;
+ cnt=(System==16) ? 1 : ((System==10) ? 0 : -1);
+ do
+ BEGIN
+ ch=toupper(**Start); Finish=False;
+ if ((ch>='0') AND (ch<='9')) Digit=ch-'0';
+ else if ((System==16) AND (ch>='A') AND (ch<='F')) Digit=(ch-'A')+10;
+ else Finish=True;
+ if (NOT Finish)
+ BEGIN
+ (*Start)++; cnt++;
+ if (Digit>=System)
+ BEGIN
+ WrError(1320); return False;
+ END
+ Acc=(Acc*System)+Digit;
+ END
+ END
+ while ((NOT Finish) AND (cnt<3));
+ if (NOT ChkRange(Acc,0,255)) return False;
+ *Erg=Acc; return True;
+ default:
+ WrError(1135); return False;
+ END
+END
+
+ static void ReplaceBkSlashes(char *s)
+BEGIN
+ char *p,*n;
+ char ErgChar;
+
+ p=strchr(s,'\\');
+ while (p!=Nil)
+ BEGIN
+ n=p+1; if (ProcessBk(&n,&ErgChar)) *p=ErgChar;
+ strcpy(p+1,n);
+ p=strchr(p+1,'\\');
+ END
+END
+
+
+ Boolean ExpandSymbol(char *Name)
+BEGIN
+ char *p1,*p2;
+ String h;
+ Boolean OK;
+
+ do
+ BEGIN
+ if ((p1=strchr(Name,'{'))==Nil) return True;
+ strmaxcpy(h,p1+1,255);
+ if ((p2=QuotPos(h,'}'))==Nil)
+ BEGIN
+ WrXError(1020,Name);
+ return False;
+ END
+ strcpy(p1,p2+1); *p2='\0';
+ FirstPassUnknown=False;
+ EvalStringExpression(h,&OK,h);
+ if (FirstPassUnknown)
+ BEGIN
+ WrError(1820); return False;
+ END
+ if (NOT CaseSensitive) UpString(h);
+ strmaxins(Name,h,p1-Name,255);
+ END
+ while (p1!=Nil);
+ return True;
+END
+
+ Boolean IdentifySection(char *Name, LongInt *Erg)
+BEGIN
+ PSaveSection SLauf;
+ sint Depth;
+
+ if (NOT ExpandSymbol(Name)) return False;
+ if (NOT CaseSensitive) NLS_UpString(Name);
+
+ if (*Name=='\0')
+ BEGIN
+ *Erg=(-1); return True;
+ END
+ else if (((strlen(Name)==6) OR (strlen(Name)==7))
+ AND (strncasecmp(Name,"PARENT",6)==0)
+ AND ((strlen(Name)==6) OR ((Name[6]>='0') AND (Name[6]<='9'))))
+ BEGIN
+ if (strlen(Name)==6) Depth=1; else Depth=Name[6]-AscOfs;
+ SLauf=SectionStack; *Erg=MomSectionHandle;
+ while ((Depth>0) AND (*Erg!=(-2)))
+ BEGIN
+ if (SLauf==Nil) *Erg=(-2);
+ else
+ BEGIN
+ *Erg=SLauf->Handle;
+ SLauf=SLauf->Next;
+ END
+ Depth--;
+ END
+ if (*Erg==(-2))
+ BEGIN
+ WrError(1484); return False;
+ END
+ else return True;
+ END
+ else if (strcmp(Name,GetSectionName(MomSectionHandle))==0)
+ BEGIN
+ *Erg=MomSectionHandle; return True;
+ END
+ else
+ BEGIN
+ SLauf=SectionStack;
+ while ((SLauf!=Nil) AND (strcmp(GetSectionName(SLauf->Handle),Name)!=0))
+ SLauf=SLauf->Next;
+ if (SLauf==Nil)
+ BEGIN
+ WrError(1484); return False;
+ END
+ else
+ BEGIN
+ *Erg=SLauf->Handle; return True;
+ END
+ END
+END
+
+ static Boolean GetSymSection(char *Name, LongInt *Erg)
+BEGIN
+ String Part;
+ char *q;
+ int l=strlen(Name);
+
+ if (Name[l-1]!=']')
+ BEGIN
+ *Erg=(-2); return True;
+ END
+
+ Name[l-1]='\0';
+ q=RQuotPos(Name,'[');
+ Name[l-1]=']';
+ if (Name+strlen(Name)-q<=2)
+ BEGIN
+ WrXError(1020,Name); return False;
+ END
+
+ Name[strlen(Name)-1]='\0';
+ strmaxcpy(Part,q+1,255);
+ *q='\0';
+
+ return IdentifySection(Part,Erg);
+END
+
+ int DigitVal(char ch, int Base)
+BEGIN
+ static char *DigitVals="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ char *pos=strchr(DigitVals,ch);
+ int erg;
+
+ if (pos==Nil) return -1;
+ else if ((erg=pos-DigitVals)>=Base) return -1;
+ return erg;
+END
+
+ LargeInt ConstIntVal(char *Asc_O, IntType Typ, Boolean *Ok)
+BEGIN
+ String Asc;
+ int Search;
+ Byte Base,Digit;
+ LargeInt Wert;
+ Boolean NegFlag;
+ TConstMode ActMode=ConstModeC;
+ Boolean Found;
+ char *z,ch;
+ int l;
+
+ *Ok=False; Wert=0; strmaxcpy(Asc,Asc_O,255);
+ if (Asc[0]=='\0')
+ BEGIN
+ *Ok=True; return 0;
+ END
+
+ /* ASCII herausfiltern */
+
+ else if (*Asc=='\'')
+ BEGIN
+ if (Asc[strlen(Asc)-1]!='\'') return -1;
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0'; ReplaceBkSlashes(Asc);
+ for (Search=0; Search<strlen(Asc); Search++)
+ BEGIN
+ Digit=(usint) Asc[Search];
+ Wert=(Wert<<8)+CharTransTable[Digit&0xff];
+ END
+ NegFlag=False;
+ END
+
+ /* Zahlenkonstante */
+
+ else
+ BEGIN
+ /* Vorzeichen */
+
+ if (*Asc=='+') strcpy(Asc,Asc+1);
+ NegFlag=(*Asc=='-');
+ if (NegFlag) strcpy(Asc,Asc+1);
+
+ /* automatische Syntaxermittlung */
+
+ if (RelaxedMode)
+ BEGIN
+ Found=False;
+ if ((strlen(Asc)>=2) AND (*Asc=='0') AND (toupper(Asc[1])=='X'))
+ BEGIN
+ ActMode=ConstModeC; Found=True;
+ END
+ if ((NOT Found) AND (strlen(Asc)>=2))
+ BEGIN
+ for (Search=0; Search<3; Search++)
+ if (Asc[0]==BaseIds[Search])
+ BEGIN
+ ActMode=ConstModeMoto; Found=True; break;
+ END
+ END
+ if ((NOT Found) AND (strlen(Asc)>=2) AND (*Asc>='0') AND (*Asc<='9'))
+ BEGIN
+ ch=toupper(Asc[strlen(Asc)-1]);
+ if (DigitVal(ch,RadixBase)==-1)
+ for (Search=0; Search<3; Search++)
+ if (ch==BaseLetters[Search])
+ BEGIN
+ ActMode=ConstModeIntel; Found=True; break;
+ END
+ END
+ if (NOT Found) ActMode=ConstModeC;
+ END
+ else ActMode=ConstMode;
+
+ /* Zahlensystem ermitteln/pruefen */
+
+ Base=RadixBase;
+ switch (ActMode)
+ BEGIN
+ case ConstModeIntel:
+ l=strlen(Asc); ch=toupper(Asc[l-1]);
+ if (DigitVal(ch,RadixBase)==-1)
+ for (Search=0; Search<3; Search++)
+ if (ch==BaseLetters[Search])
+ BEGIN
+ Base=BaseVals[Search]; Asc[l-1]='\0'; break;
+ END
+ break;
+ case ConstModeMoto:
+ for (Search=0; Search<3; Search++)
+ if (Asc[0]==BaseIds[Search])
+ BEGIN
+ Base=BaseVals[Search]; strcpy(Asc,Asc+1); break;
+ END
+ break;
+ case ConstModeC:
+ if (strcmp(Asc,"0")==0)
+ BEGIN
+ *Ok=True; return 0;
+ END
+ else if (*Asc!='0') Base=RadixBase;
+ else if (strlen(Asc)<2) return -1;
+ else
+ BEGIN
+ strcpy(Asc,Asc+1);
+ ch=toupper(*Asc);
+ if ((RadixBase!=10) && (DigitVal(ch,RadixBase)!=-1)) Base=RadixBase;
+ else switch (toupper(*Asc))
+ BEGIN
+ case 'X': strcpy(Asc,Asc+1); Base=16; break;
+ case 'B': strcpy(Asc,Asc+1); Base=2; break;
+ default: Base=8; break;
+ END
+ if (Asc[0]=='\0') return -1;
+ END
+ END
+
+ if (Asc[0]=='\0') return -1;
+
+ if (ActMode==ConstModeIntel)
+ if ((Asc[0]<'0') OR (Asc[0]>'9')) return -1;
+
+ for (z=Asc; *z!='\0'; z++)
+ BEGIN
+ Search=DigitVal(toupper(*z),Base); if (Search==-1) return -1;
+ Wert=Wert*Base+Search;
+ END
+ END
+
+ if (NegFlag) Wert=(-Wert);
+
+ *Ok=RangeCheck(Wert,Typ);
+ if (Ok) return Wert;
+ else if (HardRanges)
+ BEGIN
+ WrError(1320);
+ return -1;
+ END
+ else
+ BEGIN
+ *Ok=True; WrError(260); return Wert&IntMasks[(int)Typ];
+ END
+END
+
+ Double ConstFloatVal(char *Asc_O, FloatType Typ, Boolean *Ok)
+BEGIN
+ Double Erg;
+ char *end;
+
+ if (*Asc_O)
+ BEGIN
+ Erg=strtod(Asc_O,&end);
+ *Ok=(*end=='\0');
+ END
+ else
+ BEGIN
+ Erg=0.0;
+ *Ok=True;
+ END
+ return Erg;
+END
+
+ void ConstStringVal(char *Asc_O, char *Erg, Boolean *OK)
+BEGIN
+ String Asc,tmp,Part;
+ char *z,Save;
+ int l;
+ Boolean OK2;
+ TempResult t;
+
+ *OK=False;
+
+ if ((strlen(Asc_O)<2) OR (*Asc_O!='"') OR (Asc_O[strlen(Asc_O)-1]!='"')) return;
+
+ strmaxcpy(Asc,Asc_O+1,255); Asc[strlen(Asc)-1]='\0'; *tmp='\0';
+
+ while (*Asc!='\0')
+ BEGIN
+ z=strchr(Asc,'\\'); if (z==Nil) z=Asc+strlen(Asc);
+ Save=(*z); *z='\0'; if (strchr(Asc,'"')!=Nil) return;
+ strmaxcat(tmp,Asc,255); *z=Save; strcpy(Asc,z);
+ if (*Asc=='\\')
+ BEGIN
+ if (Asc[1]=='{')
+ BEGIN
+ z=QuotPos(Asc,'}'); if (z==Nil) return;
+ FirstPassUnknown=False;
+ *(z++)='\0'; strmaxcpy(Part,Asc+2,255); KillBlanks(Part);
+ EvalExpression(Part,&t);
+ if (FirstPassUnknown)
+ BEGIN
+ WrXError(1820,Part); return;
+ END
+ else if (t.Relocs != Nil)
+ BEGIN
+ WrError(1150); FreeRelocs(&t.Relocs); return;
+ END
+ else switch(t.Typ)
+ BEGIN
+ case TempInt: strmaxcat(tmp,SysString(t.Contents.Int,OutRadixBase,0),255); break;
+ case TempFloat: strmaxcat(tmp,FloatString(t.Contents.Float),255); break;
+ case TempString: strmaxcat(tmp,t.Contents.Ascii,255); break;
+ default: return;
+ END
+ END
+ else
+ BEGIN
+ z=Asc+1; OK2=ProcessBk(&z,&Save);
+ if (NOT OK2) return;
+ l=strlen(tmp); tmp[l++]=Save; tmp[l++]='\0';
+ END
+ strcpy(Asc,z);
+ END
+ END
+
+ *OK=True; strmaxcpy(Erg,tmp,255);
+END
+
+
+ static SymbolPtr FindLocNode(
+#ifdef __PROTOS__
+char *Name, TempType SearchType
+#endif
+);
+
+ static SymbolPtr FindNode(
+#ifdef __PROTOS__
+char *Name, TempType SearchType
+#endif
+);
+
+
+ static void EvalExpression_ChgFloat(TempResult *T)
+BEGIN
+ if (T->Typ!=TempInt) return;
+ T->Typ=TempFloat; T->Contents.Float=T->Contents.Int;
+END
+
+#define LEAVE goto func_exit
+
+ void EvalExpression(char *Asc_O, TempResult *Erg)
+BEGIN
+#define OpCnt 24
+static Operator Operators[OpCnt+1]=
+ /* Dummynulloperator */
+ {{" " ,1 , False, 0, False, False, False, False},
+ /* Einerkomplement */
+ {"~" ,1 , False, 1, True , False, False, False},
+ /* Linksschieben */
+ {"<<",2 , True , 3, True , False, False, False},
+ /* Rechtsschieben */
+ {">>",2 , True , 3, True , False, False, False},
+ /* Bitspiegelung */
+ {"><",2 , True , 4, True , False, False, False},
+ /* binaeres AND */
+ {"&" ,1 , True , 5, True , False, False, False},
+ /* binaeres OR */
+ {"|" ,1 , True , 6, True , False, False, False},
+ /* binaeres EXOR */
+ {"!" ,1 , True , 7, True , False, False, False},
+ /* allg. Potenz */
+ {"^" ,1 , True , 8, True , True , False, False},
+ /* Produkt */
+ {"*" ,1 , True , 11, True , True , False, False},
+ /* Quotient */
+ {"/" ,1 , True , 11, True , True , False, False},
+ /* Modulodivision */
+ {"#" ,1 , True , 11, True , False, False, False},
+ /* Summe */
+ {"+" ,1 , True , 13, True , True , True , False},
+ /* Differenz */
+ {"-" ,1 , True , 13, True , True , False, False},
+ /* logisches NOT */
+ {"~~",2 , False, 2, True , False, False, False},
+ /* logisches AND */
+ {"&&",2 , True , 15, True , False, False, False},
+ /* logisches OR */
+ {"||",2 , True , 16, True , False, False, False},
+ /* logisches EXOR */
+ {"!!",2 , True , 17, True , False, False, False},
+ /* Gleichheit */
+ {"=" ,1 , True , 23, True , True , True , False},
+ {"==",2 , True , 23, True , True , True , False},
+ /* Groesser als */
+ {">" ,1 , True , 23, True , True , True , False},
+ /* Kleiner als */
+ {"<" ,1 , True , 23, True , True , True , False},
+ /* Kleiner oder gleich */
+ {"<=",2 , True , 23, True , True , True , False},
+ /* Groesser oder gleich */
+ {">=",2 , True , 23, True , True , True , False},
+ /* Ungleichheit */
+ {"<>",2 , True , 23, True , True , True , False}};
+ static Operator *OpEnd=Operators+OpCnt;
+ Operator *FOps[OpCnt+1];
+ LongInt FOpCnt=0;
+
+ Boolean OK,FFound;
+ TempResult LVal,RVal,MVal;
+ int z1,cnt;
+ Operator *Op;
+ char Save='\0';
+ sint LKlamm,RKlamm,WKlamm,zop;
+ sint OpMax,LocOpMax,OpPos=(-1),OpLen;
+ Boolean OpFnd,InHyp,InQuot;
+ LargeInt HVal;
+ Double FVal;
+ SymbolPtr Ptr;
+ PFunction ValFunc;
+ String Asc,stemp,ftemp;
+ char *KlPos,*zp,*DummyPtr;
+ PRelocEntry TReloc;
+
+ memset(&LVal, 0, sizeof(LVal));
+ memset(&RVal, 0, sizeof(RVal));
+
+ ChkStack();
+
+ strmaxcpy(Asc, Asc_O, 255);
+ strmaxcpy(stemp, Asc, 255); KillBlanks(Asc);
+ if (MakeDebug) fprintf(Debug, "Parse %s", Asc);
+
+ /* Annahme Fehler */
+
+ Erg->Typ = TempNone;
+ Erg->Relocs = Nil;
+
+ /* Programmzaehler ? */
+
+ if ((PCSymbol != NULL) AND (strcasecmp(Asc,PCSymbol) == 0))
+ BEGIN
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = EProgCounter();
+ Erg->Relocs = Nil;
+ LEAVE;
+ END
+
+ /* Konstanten ? */
+
+ Erg->Contents.Int = ConstIntVal(Asc, (IntType) (IntTypeCnt-1), &OK);
+ if (OK)
+ BEGIN
+ Erg->Typ = TempInt;
+ Erg->Relocs = Nil;
+ LEAVE;
+ END
+
+ Erg->Contents.Float = ConstFloatVal(Asc, Float80, &OK);
+ if (OK)
+ BEGIN
+ Erg->Typ = TempFloat;
+ Erg->Relocs = Nil;
+ LEAVE;
+ END
+
+ ConstStringVal(Asc,Erg->Contents.Ascii,&OK);
+ if (OK)
+ BEGIN
+ Erg->Typ = TempString;
+ Erg->Relocs = Nil;
+ LEAVE;
+ END
+
+ /* durch Codegenerator gegebene Konstanten ? */
+
+ Erg->Relocs = Nil;
+ InternSymbol(Asc, Erg);
+ if (Erg->Typ != TempNone) LEAVE;
+
+ /* Zaehler initialisieren */
+
+ LocOpMax = 0; OpMax = 0; LKlamm = 0; RKlamm = 0; WKlamm = 0;
+ InHyp = False; InQuot = False;
+ for (Op=Operators+1; Op<=OpEnd; Op++)
+ if (((Op->IdLen==1)?(strchr(Asc,*Op->Id)):(strstr(Asc,Op->Id)))!=Nil) FOps[FOpCnt++]=Op;
+/* if (strstr(Asc,Op->Id)!=Nil) FOps[FOpCnt++]=Op;*/
+
+ /* nach Operator hoechster Rangstufe ausserhalb Klammern suchen */
+
+ for (zp=Asc; *zp!='\0'; zp++)
+ BEGIN
+ switch (*zp)
+ BEGIN
+ case '(': if (NOT (InHyp OR InQuot)) LKlamm++; break;
+ case ')': if (NOT (InHyp OR InQuot)) RKlamm++; break;
+ case '{': if (NOT (InHyp OR InQuot)) WKlamm++; break;
+ case '}': if (NOT (InHyp OR InQuot)) WKlamm--; break;
+ case '"': if (NOT InHyp) InQuot=NOT InQuot; break;
+ case '\'':if (NOT InQuot) InHyp=NOT InHyp; break;
+ default:
+ if ((LKlamm==RKlamm) AND (WKlamm==0) AND (NOT InHyp) AND (NOT InQuot))
+ BEGIN
+ OpFnd=False; OpLen=0; LocOpMax=0;
+ for (zop=0; zop<FOpCnt; zop++)
+ if (strncmp(zp,FOps[zop]->Id,FOps[zop]->IdLen)==0)
+ if (FOps[zop]->IdLen>=OpLen)
+ BEGIN
+ OpFnd=True; OpLen=FOps[zop]->IdLen; LocOpMax=FOps[zop]-Operators;
+ if (Operators[LocOpMax].Priority>=Operators[OpMax].Priority)
+ BEGIN
+ OpMax=LocOpMax; OpPos=zp-Asc;
+ END
+ END
+ if (OpFnd) zp+=strlen(Operators[LocOpMax].Id)-1;
+ END
+ END
+ END
+
+ /* Klammerfehler ? */
+
+ if (LKlamm != RKlamm)
+ BEGIN
+ WrXError(1300, Asc); LEAVE;
+ END
+
+ /* Operator gefunden ? */
+
+ if (OpMax!=0)
+ BEGIN
+ Op=Operators + OpMax;
+
+ /* Minuszeichen sowohl mit einem als auch 2 Operanden */
+
+ if (strcmp(Op->Id, "-") == 0) Op->Dyadic = (OpPos>0);
+
+ /* Operandenzahl pruefen */
+
+ if (((Op->Dyadic) AND (OpPos == 0)) OR ((NOT Op->Dyadic) AND (OpPos != 0)) OR (OpPos == strlen(Asc)-1))
+ BEGIN
+ WrError(1110); LEAVE;
+ END
+
+ /* Teilausdruecke rekursiv auswerten */
+
+ Save = Asc[OpPos]; Asc[OpPos] = '\0';
+ if (Op->Dyadic) EvalExpression(Asc, &LVal);
+ else
+ BEGIN
+ LVal.Typ = TempInt; LVal.Contents.Int = 0; LVal.Relocs = Nil;
+ END
+ EvalExpression(Asc + OpPos + strlen(Op->Id), &RVal);
+ Asc[OpPos] = Save;
+
+ /* Abbruch, falls dabei Fehler */
+
+ if ((LVal.Typ == TempNone) OR (RVal.Typ == TempNone)) LEAVE;
+
+ /* relokatible Symbole nur fuer + und - erlaubt */
+
+ if ((OpMax != 12) AND (OpMax != 13) AND ((LVal.Relocs != Nil) OR (RVal.Relocs != Nil)))
+ BEGIN
+ WrError(1150);
+ LEAVE;
+ END
+
+ /* Typueberpruefung */
+
+ if ((Op->Dyadic) AND (LVal.Typ != RVal.Typ))
+ BEGIN
+ if ((LVal.Typ == TempString) OR (RVal.Typ == TempString))
+ BEGIN
+ WrError(1135); LEAVE;
+ END
+ if (LVal.Typ == TempInt) EvalExpression_ChgFloat(&LVal);
+ if (RVal.Typ == TempInt) EvalExpression_ChgFloat(&RVal);
+ END
+
+ switch (RVal.Typ)
+ BEGIN
+ case TempInt:
+ if (NOT Op->MayInt)
+ BEGIN
+ if (NOT Op->MayFloat)
+ BEGIN
+ WrError(1135); LEAVE;
+ END
+ else
+ BEGIN
+ EvalExpression_ChgFloat(&RVal);
+ if (Op->Dyadic) EvalExpression_ChgFloat(&LVal);
+ END
+ END
+ break;
+ case TempFloat:
+ if (NOT Op->MayFloat)
+ BEGIN
+ WrError(1135); LEAVE;
+ END
+ break;
+ case TempString:
+ if (NOT Op->MayString)
+ BEGIN
+ WrError(1135); LEAVE;
+ END;
+ break;
+ default:
+ break;
+ END
+
+ /* Operanden abarbeiten */
+
+ switch (OpMax)
+ BEGIN
+ case 1: /* ~ */
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = ~RVal.Contents.Int;
+ break;
+ case 2: /* << */
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = LVal.Contents.Int << RVal.Contents.Int;
+ break;
+ case 3: /* >> */
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = LVal.Contents.Int >> RVal.Contents.Int;
+ break;
+ case 4: /* >< */
+ Erg->Typ = TempInt;
+ if ((RVal.Contents.Int < 1) OR (RVal.Contents.Int > 32)) WrError(1320);
+ else
+ BEGIN
+ Erg->Contents.Int = (LVal.Contents.Int >> RVal.Contents.Int) << RVal.Contents.Int;
+ RVal.Contents.Int--;
+ for (z1 = 0; z1 <= RVal.Contents.Int; z1++)
+ BEGIN
+ if ((LVal.Contents.Int & (1 << (RVal.Contents.Int - z1))) != 0)
+ Erg->Contents.Int += (1 << z1);
+ END
+ END
+ break;
+ case 5: /* & */
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = LVal.Contents.Int & RVal.Contents.Int;
+ break;
+ case 6: /* | */
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = LVal.Contents.Int | RVal.Contents.Int;
+ break;
+ case 7: /* ! */
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = LVal.Contents.Int ^ RVal.Contents.Int;
+ break;
+ case 8: /* ^ */
+ switch (Erg->Typ = LVal.Typ)
+ BEGIN
+ case TempInt:
+ if (RVal.Contents.Int < 0) Erg->Contents.Int = 0;
+ else
+ BEGIN
+ Erg->Contents.Int = 1;
+ while (RVal.Contents.Int > 0)
+ BEGIN
+ if ((RVal.Contents.Int&1) == 1) Erg->Contents.Int *= LVal.Contents.Int;
+ RVal.Contents.Int >>= 1;
+ if (RVal.Contents.Int != 0) LVal.Contents.Int *= LVal.Contents.Int;
+ END
+ END
+ break;
+ case TempFloat:
+ if (RVal.Contents.Float == 0.0) Erg->Contents.Float = 1.0;
+ else if (LVal.Contents.Float == 0.0) Erg->Contents.Float = 0.0;
+ else if (LVal.Contents.Float > 0) Erg->Contents.Float = pow(LVal.Contents.Float, RVal.Contents.Float);
+ else if ((abs(RVal.Contents.Float) <= ((double)MaxLongInt)) AND (floor(RVal.Contents.Float) == RVal.Contents.Float))
+ BEGIN
+ HVal = (LongInt) floor(RVal.Contents.Float+0.5);
+ if (HVal < 0)
+ BEGIN
+ LVal.Contents.Float = 1 / LVal.Contents.Float; HVal = (-HVal);
+ END
+ Erg->Contents.Float = 1.0;
+ while (HVal > 0)
+ BEGIN
+ if ((HVal & 1) == 1) Erg->Contents.Float *= LVal.Contents.Float;
+ LVal.Contents.Float *= LVal.Contents.Float; HVal >>= 1;
+ END
+ END
+ else
+ BEGIN
+ WrError(1890); Erg->Typ = TempNone;
+ END
+ break;
+ default:
+ break;
+ END
+ break;
+ case 9: /* * */
+ switch (Erg->Typ = LVal.Typ)
+ BEGIN
+ case TempInt:
+ Erg->Contents.Int = LVal.Contents.Int * RVal.Contents.Int; break;
+ case TempFloat:
+ Erg->Contents.Float = LVal.Contents.Float * RVal.Contents.Float; break;
+ default:
+ break;
+ END
+ break;
+ case 10: /* / */
+ switch (LVal.Typ)
+ BEGIN
+ case TempInt:
+ if (RVal.Contents.Int == 0) WrError(1310);
+ else
+ BEGIN
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = LVal.Contents.Int / RVal.Contents.Int;
+ END
+ break;
+ case TempFloat:
+ if (RVal.Contents.Float == 0.0) WrError(1310);
+ else
+ BEGIN
+ Erg->Typ = TempFloat;
+ Erg->Contents.Float = LVal.Contents.Float / RVal.Contents.Float;
+ END
+ default:
+ break;
+ END
+ break;
+ case 11: /* # */
+ if (RVal.Contents.Int == 0) WrError(1310);
+ else
+ BEGIN
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = LVal.Contents.Int % RVal.Contents.Int;
+ END
+ break;
+ case 12: /* + */
+ switch (Erg->Typ = LVal.Typ)
+ BEGIN
+ case TempInt :
+ Erg->Contents.Int = LVal.Contents.Int + RVal.Contents.Int;
+ Erg->Relocs = MergeRelocs(&(LVal.Relocs), &(RVal.Relocs), TRUE);
+ break;
+ case TempFloat :
+ Erg->Contents.Float = LVal.Contents.Float + RVal.Contents.Float;
+ break;
+ case TempString:
+ strmaxcpy(Erg->Contents.Ascii, LVal.Contents.Ascii, 255);
+ strmaxcat(Erg->Contents.Ascii, RVal.Contents.Ascii, 255);
+ break;
+ default:
+ break;
+ END
+ break;
+ case 13: /* - */
+ if (Op->Dyadic)
+ switch (Erg->Typ = LVal.Typ)
+ BEGIN
+ case TempInt:
+ Erg->Contents.Int = LVal.Contents.Int-RVal.Contents.Int;
+ Erg->Relocs = MergeRelocs(&(LVal.Relocs), &(RVal.Relocs), FALSE);
+ break;
+ case TempFloat:
+ Erg->Contents.Float = LVal.Contents.Float - RVal.Contents.Float;
+ break;
+ default:
+ break;
+ END
+ else
+ switch (Erg->Typ = RVal.Typ)
+ BEGIN
+ case TempInt:
+ Erg->Contents.Int = (-RVal.Contents.Int);
+ InvertRelocs(&(Erg->Relocs), &(RVal.Relocs));
+ break;
+ case TempFloat:
+ Erg->Contents.Float = (-RVal.Contents.Float);
+ break;
+ default:
+ break;
+ END
+ break;
+ case 14: /* ~~ */
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = (RVal.Contents.Int == 0) ? 1 : 0;
+ break;
+ case 15: /* && */
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = ((LVal.Contents.Int != 0) AND (RVal.Contents.Int != 0)) ? 1 : 0;
+ break;
+ case 16: /* || */
+ Erg->Typ = TempInt;
+ Erg->Contents.Int = ((LVal.Contents.Int != 0) OR (RVal.Contents.Int != 0)) ? 1 : 0;
+ break;
+ case 17: /* !! */
+ Erg->Typ = TempInt;
+ if ((LVal.Contents.Int != 0) AND (RVal.Contents.Int == 0))
+ Erg->Contents.Int = 1;
+ else if ((LVal.Contents.Int == 0) AND (RVal.Contents.Int != 0))
+ Erg->Contents.Int = 1;
+ else Erg->Contents.Int = 0;
+ break;
+ case 18: /* = */
+ case 19: /* == */
+ Erg->Typ = TempInt;
+ switch (LVal.Typ)
+ BEGIN
+ case TempInt:
+ Erg->Contents.Int = (LVal.Contents.Int == RVal.Contents.Int) ? 1 : 0;
+ break;
+ case TempFloat:
+ Erg->Contents.Int = (LVal.Contents.Float == RVal.Contents.Float) ? 1 : 0;
+ break;
+ case TempString:
+ Erg->Contents.Int = (strcmp(LVal.Contents.Ascii, RVal.Contents.Ascii) == 0) ? 1 : 0;
+ break;
+ default:
+ break;
+ END
+ break;
+ case 20: /* > */
+ Erg->Typ = TempInt;
+ switch (LVal.Typ)
+ BEGIN
+ case TempInt:
+ Erg->Contents.Int = (LVal.Contents.Int > RVal.Contents.Int) ? 1 : 0;
+ break;
+ case TempFloat:
+ Erg->Contents.Int = (LVal.Contents.Float > RVal.Contents.Float) ? 1 : 0;
+ break;
+ case TempString:
+ Erg->Contents.Int = (strcmp(LVal.Contents.Ascii, RVal.Contents.Ascii) > 0) ? 1 : 0;
+ break;
+ default:
+ break;
+ END
+ break;
+ case 21: /* < */
+ Erg->Typ = TempInt;
+ switch (LVal.Typ)
+ BEGIN
+ case TempInt:
+ Erg->Contents.Int = (LVal.Contents.Int < RVal.Contents.Int) ? 1 : 0;
+ break;
+ case TempFloat:
+ Erg->Contents.Int = (LVal.Contents.Float < RVal.Contents.Float) ? 1 : 0;
+ break;
+ case TempString:
+ Erg->Contents.Int = (strcmp(LVal.Contents.Ascii, RVal.Contents.Ascii) < 0) ? 1 : 0;
+ break;
+ default:
+ break;
+ END
+ break;
+ case 22: /* <= */
+ Erg->Typ = TempInt;
+ switch (LVal.Typ)
+ BEGIN
+ case TempInt:
+ Erg->Contents.Int = (LVal.Contents.Int <= RVal.Contents.Int) ? 1 : 0;
+ break;
+ case TempFloat:
+ Erg->Contents.Int = (LVal.Contents.Float <= RVal.Contents.Float) ? 1 : 0;
+ break;
+ case TempString:
+ Erg->Contents.Int = (strcmp(LVal.Contents.Ascii, RVal.Contents.Ascii) <= 0) ? 1 : 0; break;
+ default:
+ break;
+ END
+ break;
+ case 23: /* >= */
+ Erg->Typ=TempInt;
+ switch (LVal.Typ)
+ BEGIN
+ case TempInt:
+ Erg->Contents.Int=(LVal.Contents.Int>=RVal.Contents.Int)?1:0; break;
+ case TempFloat:
+ Erg->Contents.Int=(LVal.Contents.Float>=RVal.Contents.Float)?1:0; break;
+ case TempString:
+ Erg->Contents.Int=(strcmp(LVal.Contents.Ascii,RVal.Contents.Ascii)>=0)?1:0; break;
+ default:
+ break;
+ END
+ break;
+ case 24: /* <> */
+ Erg->Typ=TempInt;
+ switch (LVal.Typ)
+ BEGIN
+ case TempInt:
+ Erg->Contents.Int=(LVal.Contents.Int!=RVal.Contents.Int)?1:0; break;
+ case TempFloat:
+ Erg->Contents.Int=(LVal.Contents.Float!=RVal.Contents.Float)?1:0; break;
+ case TempString:
+ Erg->Contents.Int=(strcmp(LVal.Contents.Ascii,RVal.Contents.Ascii)!=0)?1:0; break;
+ default:
+ break;
+ END
+ break;
+ END
+ LEAVE;
+ END
+
+ /* kein Operator gefunden: Klammerausdruck ? */
+
+ if (LKlamm!=0)
+ BEGIN
+
+ /* erste Klammer suchen, Funktionsnamen abtrennen */
+
+ KlPos=strchr(Asc,'(');
+
+ /* Funktionsnamen abschneiden */
+
+ *KlPos='\0'; strmaxcpy(ftemp,Asc,255);
+ strcpy(Asc,KlPos+1); Asc[strlen(Asc)-1]='\0';
+
+ /* Nullfunktion: nur Argument */
+
+ if (ftemp[0]=='\0')
+ BEGIN
+ EvalExpression(Asc,&LVal);
+ *Erg=LVal; LEAVE;
+ END
+
+ /* selbstdefinierte Funktion ? */
+
+ if ((ValFunc=FindFunction(ftemp))!=Nil)
+ BEGIN
+ strmaxcpy(ftemp,ValFunc->Definition,255);
+ for (z1=1; z1<=ValFunc->ArguCnt; z1++)
+ BEGIN
+ if (Asc[0]=='\0')
+ BEGIN
+ WrError(1490); LEAVE;
+ END;
+ KlPos=QuotPos(Asc,','); if (KlPos!=Nil) *KlPos='\0';
+ EvalExpression(Asc,&LVal);
+ if (LVal.Relocs != Nil)
+ BEGIN
+ WrError(1150); FreeRelocs(&LVal.Relocs); return;
+ END
+ if (KlPos==Nil) Asc[0]='\0'; else strcpy(Asc,KlPos+1);
+ switch (LVal.Typ)
+ BEGIN
+ case TempInt:
+ sprintf(stemp,"%s",LargeString(LVal.Contents.Int));
+ break;
+ case TempFloat:
+ sprintf(stemp,"%0.16e",LVal.Contents.Float);
+ KillBlanks(stemp);
+ break;
+ case TempString:
+ strcpy(stemp,"\"");
+ strmaxcat(stemp,LVal.Contents.Ascii,255);
+ strmaxcat(stemp,"\"",255);
+ break;
+ default:
+ LEAVE;
+ END
+ memmove(stemp+1,stemp,strlen(stemp)+1);
+ stemp[0]='('; strmaxcat(stemp,")",255);
+ ExpandLine(stemp,z1,ftemp);
+ END
+ if (Asc[0]!='\0')
+ BEGIN
+ WrError(1490); LEAVE;
+ END
+ EvalExpression(ftemp,Erg);
+ LEAVE;
+ END
+
+ /* hier einmal umwandeln ist effizienter */
+
+ NLS_UpString(ftemp);
+
+ /* symbolbezogene Funktionen */
+
+ if (strcmp(ftemp,"SYMTYPE")==0)
+ BEGIN
+ Erg->Typ=TempInt;
+ if (FindRegDef(Asc,&DummyPtr)) Erg->Contents.Int=0x80;
+ else Erg->Contents.Int=GetSymbolType(Asc);
+ LEAVE;
+ END
+
+ /* Unterausdruck auswerten (interne Funktionen maxmimal mit drei Argumenten) */
+
+ z1 = 0; KlPos = Asc;
+ do
+ BEGIN
+ zp = QuotPos(KlPos, ',');
+ if (zp != Nil) *zp = '\0';
+ switch (z1)
+ BEGIN
+ case 0:
+ EvalExpression(KlPos, &LVal);
+ if (LVal.Typ == TempNone) LEAVE;
+ TReloc = LVal.Relocs;
+ break;
+ case 1:
+ EvalExpression(KlPos, &MVal);
+ if (MVal.Typ == TempNone) LEAVE;
+ TReloc = MVal.Relocs;
+ break;
+ case 2:
+ EvalExpression(KlPos, &RVal);
+ if (RVal.Typ == TempNone) LEAVE;
+ TReloc = RVal.Relocs;
+ break;
+ default:
+ WrError(1490); LEAVE;
+ END
+ if (TReloc != Nil)
+ BEGIN
+ WrError(1150); FreeRelocs(&TReloc); LEAVE;
+ END
+ if (zp != Nil) KlPos = zp + 1;
+ z1++;
+ END
+ while (zp!=Nil);
+
+ /* ein paar Funktionen mit zwei,drei Argumenten */
+
+ if (z1==3)
+ BEGIN
+ if (strcmp(ftemp,"SUBSTR")==0)
+ BEGIN
+ if ((LVal.Typ!=TempString) OR (MVal.Typ!=TempInt) OR (RVal.Typ!=TempInt)) WrError(1135);
+ else
+ BEGIN
+ cnt=strlen(LVal.Contents.Ascii)-MVal.Contents.Int;
+ if ((RVal.Contents.Int!=0) AND (RVal.Contents.Int<cnt)) cnt=RVal.Contents.Int;
+ if (cnt<0) cnt=0;
+ memcpy(Erg->Contents.Ascii,LVal.Contents.Ascii+MVal.Contents.Int,cnt);
+ Erg->Contents.Ascii[cnt]='\0';
+ Erg->Typ=TempString;
+ END
+ END
+ else WrXError(1860,ftemp);
+ LEAVE;
+ END
+ else if (z1==2)
+ BEGIN
+ if (strcmp(ftemp,"STRSTR")==0)
+ BEGIN
+ if ((LVal.Typ!=TempString) OR (MVal.Typ!=TempString)) WrError(1135);
+ else
+ BEGIN
+ zp=strstr(LVal.Contents.Ascii,MVal.Contents.Ascii);
+ Erg->Typ=TempInt;
+ Erg->Contents.Int=(zp==Nil) ? -1 : (zp-LVal.Contents.Ascii);
+ END
+ END
+ else WrXError(1860,ftemp);
+ LEAVE;
+ END
+
+ /* Funktionen fuer Stringargumente */
+
+ if (LVal.Typ==TempString)
+ BEGIN
+ /* in Grossbuchstaben wandeln ? */
+
+ if (strcmp(ftemp,"UPSTRING")==0)
+ BEGIN
+ Erg->Typ=TempString; strmaxcpy(Erg->Contents.Ascii,LVal.Contents.Ascii,255);
+ for (KlPos=Erg->Contents.Ascii; *KlPos!='\0'; KlPos++)
+ *KlPos=toupper(*KlPos);
+ END
+
+ /* in Kleinbuchstaben wandeln ? */
+
+ else if (strcmp(ftemp,"LOWSTRING")==0)
+ BEGIN
+ Erg->Typ=TempString; strmaxcpy(Erg->Contents.Ascii,LVal.Contents.Ascii,255);
+ for (KlPos=Erg->Contents.Ascii; *KlPos!='\0'; KlPos++)
+ *KlPos=tolower(*KlPos);
+ END
+
+ /* Laenge ermitteln ? */
+
+ else if (strcmp(ftemp,"STRLEN")==0)
+ BEGIN
+ Erg->Typ=TempInt; Erg->Contents.Int=strlen(LVal.Contents.Ascii);
+ END
+
+ /* Parser aufrufen ? */
+
+ else if (strcmp(ftemp,"VAL")==0)
+ BEGIN
+ EvalExpression(LVal.Contents.Ascii,Erg);
+ END
+
+ /* nix gefunden ? */
+
+ else
+ BEGIN
+ WrXError(1860,ftemp); Erg->Typ=TempNone;
+ END
+ END
+
+ /* Funktionen fuer Zahlenargumente */
+
+ else
+ BEGIN
+ FFound=False; Erg->Typ=TempNone;
+
+ /* reine Integerfunktionen */
+
+ if (strcmp(ftemp,"TOUPPER")==0)
+ BEGIN
+ if (LVal.Typ!=TempInt) WrError(1135);
+ else if ((LVal.Contents.Int<0) OR (LVal.Contents.Int>255)) WrError(1320);
+ else
+ BEGIN
+ Erg->Typ=TempInt;
+ Erg->Contents.Int=toupper(LVal.Contents.Int);
+ END
+ FFound=True;
+ END
+
+ else if (strcmp(ftemp,"TOLOWER")==0)
+ BEGIN
+ if (LVal.Typ!=TempInt) WrError(1135);
+ else if ((LVal.Contents.Int<0) OR (LVal.Contents.Int>255)) WrError(1320);
+ else
+ BEGIN
+ Erg->Typ=TempInt;
+ Erg->Contents.Int=tolower(LVal.Contents.Int);
+ END
+ FFound=True;
+ END
+
+ else if (strcmp(ftemp,"BITCNT")==0)
+ BEGIN
+ if (LVal.Typ!=TempInt) WrError(1135);
+ else
+ BEGIN
+ Erg->Typ=TempInt;
+ Erg->Contents.Int=0;
+ for (z1=0; z1<LARGEBITS; z1++)
+ BEGIN
+ Erg->Contents.Int+=(LVal.Contents.Int & 1);
+ LVal.Contents.Int=LVal.Contents.Int >> 1;
+ END
+ END
+ FFound=True;
+ END
+
+ else if (strcmp(ftemp,"FIRSTBIT")==0)
+ BEGIN
+ if (LVal.Typ!=TempInt) WrError(1135);
+ else
+ BEGIN
+ Erg->Typ=TempInt;
+ Erg->Contents.Int=0;
+ do
+ BEGIN
+ if (NOT Odd(LVal.Contents.Int)) Erg->Contents.Int++;
+ LVal.Contents.Int=LVal.Contents.Int >> 1;
+ END
+ while ((Erg->Contents.Int<LARGEBITS) AND (NOT Odd(LVal.Contents.Int)));
+ if (Erg->Contents.Int>=LARGEBITS) Erg->Contents.Int=(-1);
+ END
+ FFound=True;
+ END
+
+ else if (strcmp(ftemp,"LASTBIT")==0)
+ BEGIN
+ if (LVal.Typ!=TempInt) WrError(1135);
+ else
+ BEGIN
+ Erg->Typ=TempInt;
+ Erg->Contents.Int=(-1);
+ for (z1=0; z1<LARGEBITS; z1++)
+ BEGIN
+ if (Odd(LVal.Contents.Int)) Erg->Contents.Int=z1;
+ LVal.Contents.Int=LVal.Contents.Int >> 1;
+ END
+ END
+ FFound=True;
+ END
+
+ else if (strcmp(ftemp,"BITPOS")==0)
+ BEGIN
+ if (LVal.Typ!=TempInt) WrError(1135);
+ else
+ BEGIN
+ Erg->Typ=TempInt;
+ if (NOT SingleBit(LVal.Contents.Int,&Erg->Contents.Int))
+ BEGIN
+ Erg->Contents.Int=(-1); WrError(1540);
+ END
+ END
+ FFound=True;
+ END
+
+ /* variable Integer/Float-Funktionen */
+
+ else if (strcmp(ftemp,"ABS")==0)
+ BEGIN
+ switch (Erg->Typ=LVal.Typ)
+ BEGIN
+ case TempInt: Erg->Contents.Int=abs(LVal.Contents.Int); break;
+ case TempFloat: Erg->Contents.Float=fabs(LVal.Contents.Float);break;
+ default: break;
+ END
+ FFound=True;
+ END
+
+ else if (strcmp(ftemp,"SGN")==0)
+ BEGIN
+ Erg->Typ=TempInt;
+ switch (LVal.Typ)
+ BEGIN
+ case TempInt:
+ if (LVal.Contents.Int<0) Erg->Contents.Int=(-1);
+ else if (LVal.Contents.Int>0) Erg->Contents.Int=1;
+ else Erg->Contents.Int=0;
+ break;
+ case TempFloat:
+ if (LVal.Contents.Float<0) Erg->Contents.Int=(-1);
+ else if (LVal.Contents.Float>0) Erg->Contents.Int=1;
+ else Erg->Contents.Int=0;
+ break;
+ default:
+ break;
+ END
+ FFound=True;
+ END
+
+ /* Funktionen Float und damit auch Int */
+
+ if (NOT FFound)
+ BEGIN
+ /* Typkonvertierung */
+
+ EvalExpression_ChgFloat(&LVal);
+ Erg->Typ=TempFloat;
+
+ /* Integerwandlung */
+
+ if (strcmp(ftemp,"INT")==0)
+ BEGIN
+ if (fabs(LVal.Contents.Float)>MaxLargeInt)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1320);
+ END
+ else
+ BEGIN
+ Erg->Typ=TempInt; Erg->Contents.Int=(LargeInt) floor(LVal.Contents.Float);
+ END
+ END
+
+ /* Quadratwurzel */
+
+ else if (strcmp(ftemp,"SQRT")==0)
+ BEGIN
+ if (LVal.Contents.Float<0)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1870);
+ END
+ else Erg->Contents.Float=sqrt(LVal.Contents.Float);
+ END
+
+ /* trigonometrische Funktionen */
+
+ else if (strcmp(ftemp,"SIN")==0) Erg->Contents.Float=sin(LVal.Contents.Float);
+ else if (strcmp(ftemp,"COS")==0) Erg->Contents.Float=cos(LVal.Contents.Float);
+ else if (strcmp(ftemp,"TAN")==0)
+ BEGIN
+ if (cos(LVal.Contents.Float)==0.0)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1870);
+ END
+ else Erg->Contents.Float=tan(LVal.Contents.Float);
+ END
+ else if (strcmp(ftemp,"COT")==0)
+ BEGIN
+ if ((FVal=sin(LVal.Contents.Float))==0.0)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1870);
+ END
+ else Erg->Contents.Float=cos(LVal.Contents.Float)/FVal;
+ END
+
+ /* inverse trigonometrische Funktionen */
+
+ else if (strcmp(ftemp,"ASIN")==0)
+ BEGIN
+ if (fabs(LVal.Contents.Float)>1)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1870);
+ END
+ else Erg->Contents.Float=asin(LVal.Contents.Float);
+ END
+ else if (strcmp(ftemp,"ACOS")==0)
+ BEGIN
+ if (fabs(LVal.Contents.Float)>1)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1870);
+ END
+ else Erg->Contents.Float=acos(LVal.Contents.Float);
+ END
+ else if (strcmp(ftemp,"ATAN")==0) Erg->Contents.Float=atan(LVal.Contents.Float);
+ else if (strcmp(ftemp,"ACOT")==0) Erg->Contents.Float=M_PI/2-atan(LVal.Contents.Float);
+
+ /* exponentielle & hyperbolische Funktionen */
+
+ else if (strcmp(ftemp,"EXP")==0)
+ BEGIN
+ if (LVal.Contents.Float>709)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else Erg->Contents.Float=exp(LVal.Contents.Float);
+ END
+ else if (strcmp(ftemp,"ALOG")==0)
+ BEGIN
+ if (LVal.Contents.Float>308)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else Erg->Contents.Float=exp(LVal.Contents.Float*log(10.0));
+ END
+ else if (strcmp(ftemp,"ALD")==0)
+ BEGIN
+ if (LVal.Contents.Float>1022)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else Erg->Contents.Float=exp(LVal.Contents.Float*log(2.0));
+ END
+ else if (strcmp(ftemp,"SINH")==0)
+ BEGIN
+ if (LVal.Contents.Float>709)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else Erg->Contents.Float=sinh(LVal.Contents.Float);
+ END
+ else if (strcmp(ftemp,"COSH")==0)
+ BEGIN
+ if (LVal.Contents.Float>709)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else Erg->Contents.Float=cosh(LVal.Contents.Float);
+ END
+ else if (strcmp(ftemp,"TANH")==0)
+ BEGIN
+ if (LVal.Contents.Float>709)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else Erg->Contents.Float=tanh(LVal.Contents.Float);
+ END
+ else if (strcmp(ftemp,"COTH")==0)
+ BEGIN
+ if (LVal.Contents.Float>709)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else if ((FVal=tanh(LVal.Contents.Float))==0.0)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1870);
+ END
+ else Erg->Contents.Float=1.0/FVal;
+ END
+
+ /* logarithmische & inverse hyperbolische Funktionen */
+
+ else if (strcmp(ftemp,"LN")==0)
+ BEGIN
+ if (LVal.Contents.Float<=0)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1870);
+ END
+ else Erg->Contents.Float=log(LVal.Contents.Float);
+ END
+ else if (strcmp(ftemp,"LOG")==0)
+ BEGIN
+ if (LVal.Contents.Float<=0)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1870);
+ END
+ else Erg->Contents.Float=log10(LVal.Contents.Float);
+ END
+ else if (strcmp(ftemp,"LD")==0)
+ BEGIN
+ if (LVal.Contents.Float<=0)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1870);
+ END
+ else Erg->Contents.Float=log(LVal.Contents.Float)/log(2.0);
+ END
+ else if (strcmp(ftemp,"ASINH")==0)
+ Erg->Contents.Float=log(LVal.Contents.Float+sqrt(LVal.Contents.Float*LVal.Contents.Float+1));
+ else if (strcmp(ftemp,"ACOSH")==0)
+ BEGIN
+ if (LVal.Contents.Float<1)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else Erg->Contents.Float=log(LVal.Contents.Float+sqrt(LVal.Contents.Float*LVal.Contents.Float-1));
+ END
+ else if (strcmp(ftemp,"ATANH")==0)
+ BEGIN
+ if (fabs(LVal.Contents.Float)>=1)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else Erg->Contents.Float=0.5*log((1+LVal.Contents.Float)/(1-LVal.Contents.Float));
+ END
+ else if (strcmp(ftemp,"ACOTH")==0)
+ BEGIN
+ if (fabs(LVal.Contents.Float)<=1)
+ BEGIN
+ Erg->Typ=TempNone; WrError(1880);
+ END
+ else Erg->Contents.Float=0.5*log((LVal.Contents.Float+1)/(LVal.Contents.Float-1));
+ END
+
+ /* nix gefunden ? */
+
+ else
+ BEGIN
+ WrXError(1860,ftemp); Erg->Typ=TempNone;
+ END
+ END
+ END
+ LEAVE;
+ END
+
+ /* nichts dergleichen, dann einfaches Symbol: */
+
+ /* interne Symbole ? */
+
+ strmaxcpy(Asc,stemp,255); KillPrefBlanks(Asc); KillPostBlanks(Asc);
+
+ if (strcasecmp(Asc,"MOMFILE")==0)
+ BEGIN
+ Erg->Typ=TempString;
+ strmaxcpy(Erg->Contents.Ascii,CurrFileName,255);
+ LEAVE;
+ END;
+
+ if (strcasecmp(Asc,"MOMLINE")==0)
+ BEGIN
+ Erg->Typ=TempInt;
+ Erg->Contents.Int=CurrLine;
+ LEAVE;
+ END
+
+ if (strcasecmp(Asc,"MOMPASS")==0)
+ BEGIN
+ Erg->Typ=TempInt;
+ Erg->Contents.Int=PassNo;
+ LEAVE;
+ END
+
+ if (strcasecmp(Asc,"MOMSECTION")==0)
+ BEGIN
+ Erg->Typ=TempString;
+ strmaxcpy(Erg->Contents.Ascii,GetSectionName(MomSectionHandle),255);
+ LEAVE;
+ END
+
+ if (strcasecmp(Asc,"MOMSEGMENT")==0)
+ BEGIN
+ Erg->Typ=TempString;
+ strmaxcpy(Erg->Contents.Ascii,SegNames[ActPC],255);
+ LEAVE;
+ END
+
+ if (NOT ExpandSymbol(Asc)) LEAVE;
+
+ KlPos=strchr(Asc,'[');
+ if (KlPos!=Nil)
+ BEGIN
+ Save=(*KlPos); *KlPos='\0';
+ END
+ OK=ChkSymbName(Asc);
+ if (KlPos!=Nil) *KlPos=Save;
+ if (NOT OK)
+ BEGIN
+ WrXError(1020,Asc); LEAVE;
+ END;
+
+ Ptr = FindLocNode(Asc, TempNone);
+ if (Ptr == Nil) Ptr=FindNode(Asc, TempNone);
+ if (Ptr != Nil)
+ BEGIN
+ switch (Erg->Typ = Ptr->SymWert.Typ)
+ BEGIN
+ case TempInt: Erg->Contents.Int=Ptr->SymWert.Contents.IWert; break;
+ case TempFloat: Erg->Contents.Float=Ptr->SymWert.Contents.FWert; break;
+ case TempString: strmaxcpy(Erg->Contents.Ascii,Ptr->SymWert.Contents.SWert,255);
+ default: break;
+ END
+ if (Erg->Typ != TempNone) Erg->Relocs = DupRelocs(Ptr->Relocs);
+ if (Ptr->SymType != 0) TypeFlag |= (1 << Ptr->SymType);
+ if ((Ptr->SymSize != (-1)) AND (SizeFlag == (-1))) SizeFlag = Ptr->SymSize;
+ if (NOT Ptr->Defined)
+ BEGIN
+ if (Repass) SymbolQuestionable = True;
+ UsesForwards = True;
+ END
+ Ptr->Used = True;
+ LEAVE;
+ END
+
+ /* Symbol evtl. im ersten Pass unbekannt */
+
+ if (PassNo<=MaxSymPass)
+ BEGIN
+ Erg->Typ=TempInt; Erg->Contents.Int=EProgCounter();
+ Repass=True;
+ if ((MsgIfRepass) AND (PassNo>=PassNoForMessage)) WrXError(170,Asc);
+ FirstPassUnknown=True;
+ END
+
+ /* alles war nix, Fehler */
+
+ else WrXError(1010,Asc);
+
+func_exit:
+ if (LVal.Relocs != NULL) FreeRelocs(&LVal.Relocs);
+ if (RVal.Relocs != NULL) FreeRelocs(&RVal.Relocs);
+END
+
+
+ LargeInt EvalIntExpression(char *Asc, IntType Typ, Boolean *OK)
+BEGIN
+ TempResult t;
+
+ *OK = False;
+ TypeFlag = 0; SizeFlag = (-1);
+ UsesForwards = False;
+ SymbolQuestionable = False;
+ FirstPassUnknown = False;
+
+ EvalExpression(Asc, &t);
+ SetRelocs(t.Relocs);
+ if (t.Typ != TempInt)
+ BEGIN
+ if (t.Typ != TempNone) WrError(1135);
+ FreeRelocs(&LastRelocs);
+ return -1;
+ END
+
+ if (FirstPassUnknown) t.Contents.Int &= IntMasks[(int)Typ];
+
+ if (NOT RangeCheck(t.Contents.Int,Typ))
+ if (HardRanges)
+ BEGIN
+ FreeRelocs(&LastRelocs);
+ WrError(1320); return -1;
+ END
+ else
+ BEGIN
+ WrError(260); *OK = True; return t.Contents.Int&IntMasks[(int)Typ];
+ END
+ else
+ BEGIN
+ *OK = True; return t.Contents.Int;
+ END
+END
+
+ Double EvalFloatExpression(char *Asc, FloatType Typ, Boolean *OK)
+BEGIN
+ TempResult t;
+
+ *OK=False;
+ TypeFlag=0; SizeFlag=(-1);
+ UsesForwards=False;
+ SymbolQuestionable=False;
+ FirstPassUnknown=False;
+
+ EvalExpression(Asc,&t);
+ switch (t.Typ)
+ BEGIN
+ case TempNone:
+ return -1;
+ case TempInt:
+ t.Contents.Float=t.Contents.Int;
+ break;
+ case TempString:
+ WrError(1135); return -1;
+ default:
+ break;
+ END
+
+ if (NOT FloatRangeCheck(t.Contents.Float,Typ))
+ BEGIN
+ WrError(1320); return -1;
+ END
+
+ *OK=True; return t.Contents.Float;
+END
+
+ void EvalStringExpression(char *Asc, Boolean *OK, char *Result)
+BEGIN
+ TempResult t;
+
+ *OK=False;
+ TypeFlag=0; SizeFlag=(-1);
+ UsesForwards=False;
+ SymbolQuestionable=False;
+ FirstPassUnknown=False;
+
+ EvalExpression(Asc,&t);
+ if (t.Typ!=TempString)
+ BEGIN
+ *Result='\0';
+ if (t.Typ!=TempNone) WrError(1135);
+ return;
+ END
+
+ strmaxcpy(Result,t.Contents.Ascii,255); *OK=True;
+END
+
+
+ static void FreeSymbol(SymbolPtr *Node)
+BEGIN
+ PCrossRef Lauf;
+
+ free((*Node)->SymName);
+
+ if ((*Node)->SymWert.Typ == TempString)
+ free((*Node)->SymWert.Contents.SWert);
+
+ while ((*Node)->RefList != Nil)
+ BEGIN
+ Lauf = (*Node)->RefList->Next;
+ free((*Node)->RefList);
+ (*Node)->RefList = Lauf;
+ END
+
+ FreeRelocs(&((*Node)->Relocs));
+
+ free(*Node); *Node = Nil;
+END
+
+static String serr,snum;
+
+ Boolean EnterTreeNode(SymbolPtr *Node, SymbolPtr Neu, Boolean MayChange, Boolean DoCross)
+BEGIN
+ SymbolPtr Hilf,p1,p2;
+ Boolean Grown,Result;
+ ShortInt CompErg;
+
+ /* Stapelueberlauf pruefen, noch nichts eingefuegt */
+
+ ChkStack(); Result = False;
+
+ /* an einem Blatt angelangt--> einfach anfuegen */
+
+ if (*Node == Nil)
+ BEGIN
+ (*Node) = Neu;
+ (*Node)->Balance = 0; (*Node)->Left = Nil; (*Node)->Right = Nil;
+ (*Node)->Defined = True; (*Node)->Used = False;
+ (*Node)->Changeable = MayChange; (*Node)->RefList = Nil;
+ if (DoCross)
+ BEGIN
+ (*Node)->FileNum = GetFileNum(CurrFileName);
+ (*Node)->LineNum = CurrLine;
+ END
+ return True;
+ END
+
+ CompErg = StrCmp(Neu->SymName, (*Node)->SymName, Neu->Attribute,
+ (*Node)->Attribute);
+
+ if (CompErg > 0)
+ BEGIN
+ Grown = EnterTreeNode(&((*Node)->Right), Neu, MayChange, DoCross);
+ if ((BalanceTree) AND (Grown))
+ switch ((*Node)->Balance)
+ BEGIN
+ case -1:
+ (*Node)->Balance = 0; break;
+ case 0:
+ (*Node)->Balance = 1; Result = True; break;
+ case 1:
+ p1 = (*Node)->Right;
+ if (p1->Balance == 1)
+ BEGIN
+ (*Node)->Right = p1->Left; p1->Left = (*Node);
+ (*Node)->Balance = 0; *Node = p1;
+ END
+ else
+ BEGIN
+ p2 = p1->Left;
+ p1->Left = p2->Right; p2->Right = p1;
+ (*Node)->Right = p2->Left; p2->Left = (*Node);
+ if (p2->Balance == 1) (*Node)->Balance = (-1); else (*Node)->Balance = 0;
+ if (p2->Balance == -1) p1 ->Balance = 1; else p1 ->Balance = 0;
+ *Node = p2;
+ END
+ (*Node)->Balance = 0;
+ break;
+ END
+ END
+ else if (CompErg < 0)
+ BEGIN
+ Grown = EnterTreeNode(&((*Node)->Left), Neu, MayChange, DoCross);
+ if ((BalanceTree) AND (Grown))
+ switch ((*Node)->Balance)
+ BEGIN
+ case 1:
+ (*Node)->Balance = 0; break;
+ case 0:
+ (*Node)->Balance = (-1); Result = True; break;
+ case -1:
+ p1 = (*Node)->Left;
+ if (p1->Balance == (-1))
+ BEGIN
+ (*Node)->Left = p1->Right; p1->Right = (*Node);
+ (*Node)->Balance = 0; (*Node) = p1;
+ END
+ else
+ BEGIN
+ p2 = p1->Right;
+ p1->Right = p2->Left; p2->Left = p1;
+ (*Node)->Left = p2->Right; p2->Right = (*Node);
+ if (p2->Balance == (-1)) (*Node)->Balance = 1; else (*Node)->Balance = 0;
+ if (p2->Balance == 1) p1 ->Balance = (-1); else p1 ->Balance = 0;
+ *Node = p2;
+ END
+ (*Node)->Balance = 0;
+ break;
+ END
+ END
+ else
+ BEGIN
+ if (((*Node)->Defined) AND (NOT MayChange))
+ BEGIN
+ strmaxcpy(serr, (*Node)->SymName, 255);
+ if (DoCross)
+ BEGIN
+ sprintf(snum, ",%s %s:%ld", getmessage(Num_PrevDefMsg),
+ GetFileName((*Node)->FileNum), (long)((*Node)->LineNum));
+ strmaxcat(serr, snum, 255);
+ END
+ WrXError(1000, serr);
+ FreeSymbol(&Neu);
+ END
+ else
+ BEGIN
+ if (NOT MayChange)
+ BEGIN
+ if ((Neu->SymWert.Typ != (*Node)->SymWert.Typ)
+ OR ((Neu->SymWert.Typ == TempString) AND (strcmp(Neu->SymWert.Contents.SWert, (*Node)->SymWert.Contents.SWert) != 0))
+ OR ((Neu->SymWert.Typ == TempFloat ) AND (Neu->SymWert.Contents.FWert != (*Node)->SymWert.Contents.FWert))
+ OR ((Neu->SymWert.Typ == TempInt ) AND (Neu->SymWert.Contents.IWert != (*Node)->SymWert.Contents.IWert)))
+ BEGIN
+ if ((NOT Repass) AND (JmpErrors>0))
+ BEGIN
+ if (ThrowErrors) ErrorCount -= JmpErrors;
+ JmpErrors = 0;
+ END
+ Repass = True;
+ if ((MsgIfRepass) AND (PassNo >= PassNoForMessage))
+ BEGIN
+ strmaxcpy(serr, Neu->SymName, 255);
+ if (Neu->Attribute != (-1))
+ BEGIN
+ strmaxcat(serr, "[", 255);
+ strmaxcat(serr, GetSectionName(Neu->Attribute), 255);
+ strmaxcat(serr, "]", 255);
+ END
+ WrXError(80, serr);
+ END
+ END
+ END
+ Neu->Left = (*Node)->Left; Neu->Right = (*Node)->Right;
+ Neu->Balance = (*Node)->Balance;
+ if (DoCross)
+ BEGIN
+ Neu->LineNum = (*Node)->LineNum; Neu->FileNum = (*Node)->FileNum;
+ END
+ Neu->RefList = (*Node)->RefList; (*Node)->RefList = Nil;
+ Neu->Defined = True; Neu->Used = (*Node)->Used; Neu->Changeable = MayChange;
+ Hilf = (*Node); *Node = Neu;
+ FreeSymbol(&Hilf);
+ END
+ END
+
+ return Result;
+END
+
+ static void EnterLocSymbol(SymbolPtr Neu)
+BEGIN
+ Neu->Attribute=MomLocHandle;
+ if (NOT CaseSensitive) NLS_UpString(Neu->SymName);
+ EnterTreeNode(&FirstLocSymbol,Neu,False,False);
+END
+
+ static void EnterSymbol_Search(PForwardSymbol *Lauf, PForwardSymbol *Prev,
+ PForwardSymbol **RRoot, SymbolPtr Neu,
+ PForwardSymbol *Root, Byte ResCode, Byte *SearchErg)
+BEGIN
+ *Lauf=(*Root); *Prev=Nil; *RRoot=Root;
+ while ((*Lauf!=Nil) AND (strcmp((*Lauf)->Name,Neu->SymName)!=0))
+ BEGIN
+ *Prev=(*Lauf); *Lauf=(*Lauf)->Next;
+ END
+ if (*Lauf!=Nil) *SearchErg=ResCode;
+END
+
+ static void EnterSymbol(SymbolPtr Neu, Boolean MayChange, LongInt ResHandle)
+BEGIN
+ PForwardSymbol Lauf,Prev;
+ PForwardSymbol *RRoot;
+ Byte SearchErg;
+ String CombName;
+ PSaveSection RunSect;
+ LongInt MSect;
+ SymbolPtr Copy;
+
+/* Neu^.Attribute:=MomSectionHandle;
+ IF SectionStack<>Nil THEN
+ BEGIN
+ Search(SectionStack^.GlobSyms);
+ IF Lauf<>Nil THEN Neu^.Attribute:=Lauf^.DestSection
+ ELSE Search(SectionStack^.LocSyms);
+ IF Lauf<>Nil THEN
+ BEGIN
+ FreeMem(Lauf^.Name,Length(Lauf^.Name^)+1);
+ IF Prev=Nil THEN RRoot^:=Lauf^.Next
+ ELSE Prev^.Next:=Lauf^.Next;
+ Dispose(Lauf);
+ END;
+ END;
+ IF EnterTreeNode(FirstSymbol,Neu,MayChange,MakeCrossList) THEN;*/
+
+ if (NOT CaseSensitive) NLS_UpString(Neu->SymName);
+
+ SearchErg = 0;
+ Neu->Attribute = (ResHandle == (-2)) ? (MomSectionHandle) : (ResHandle);
+ if ((SectionStack != Nil) AND (Neu->Attribute == MomSectionHandle))
+ BEGIN
+ EnterSymbol_Search(&Lauf, &Prev, &RRoot, Neu, &(SectionStack->LocSyms),
+ 1, &SearchErg);
+ if (Lauf == Nil)
+ EnterSymbol_Search(&Lauf, &Prev, &RRoot, Neu,
+ &(SectionStack->GlobSyms), 2, &SearchErg);
+ if (Lauf == Nil)
+ EnterSymbol_Search(&Lauf, &Prev, &RRoot, Neu,
+ &(SectionStack->ExportSyms), 3, &SearchErg);
+ if (SearchErg == 2) Neu->Attribute = Lauf->DestSection;
+ if (SearchErg == 3)
+ BEGIN
+ strmaxcpy(CombName, Neu->SymName, 255);
+ RunSect = SectionStack; MSect = MomSectionHandle;
+ while ((MSect != Lauf->DestSection) AND (RunSect != Nil))
+ BEGIN
+ strmaxprep(CombName, "_", 255);
+ strmaxprep(CombName, GetSectionName(MSect), 255);
+ MSect = RunSect->Handle; RunSect = RunSect->Next;
+ END
+ Copy = (SymbolPtr) malloc(sizeof(SymbolEntry)); *Copy = (*Neu);
+ Copy->SymName = strdup(CombName);
+ Copy->Attribute = Lauf->DestSection;
+ Copy->Relocs = DupRelocs(Neu->Relocs);
+ if (Copy->SymWert.Typ == TempString)
+ Copy->SymWert.Contents.SWert = strdup(Neu->SymWert.Contents.SWert);
+ EnterTreeNode(&FirstSymbol, Copy, MayChange, MakeCrossList);
+ END
+ if (Lauf != Nil)
+ BEGIN
+ free(Lauf->Name);
+ if (Prev == Nil) *RRoot = Lauf->Next;
+ else Prev->Next = Lauf->Next;
+ free(Lauf);
+ END
+ END
+ EnterTreeNode(&FirstSymbol, Neu, MayChange, MakeCrossList);
+END
+
+ void PrintSymTree(char *Name)
+BEGIN
+ fprintf(Debug,"---------------------\n");
+ fprintf(Debug,"Enter Symbol %s\n\n",Name);
+ PrintSymbolTree(); PrintSymbolDepth();
+END
+
+ void EnterIntSymbol(char *Name_O, LargeInt Wert, Byte Typ, Boolean MayChange)
+BEGIN
+ SymbolPtr Neu;
+ LongInt DestHandle;
+ String Name;
+
+ strmaxcpy(Name, Name_O, 255);
+ if (NOT ExpandSymbol(Name)) return;
+ if (NOT GetSymSection(Name, &DestHandle)) return;
+ if (NOT ChkSymbName(Name))
+ BEGIN
+ WrXError(1020, Name); return;
+ END
+
+ Neu=(SymbolPtr) malloc(sizeof(SymbolEntry));
+ Neu->SymName = strdup(Name);
+ Neu->SymWert.Typ = TempInt;
+ Neu->SymWert.Contents.IWert = Wert;
+ Neu->SymType = Typ;
+ Neu->SymSize = (-1);
+ Neu->RefList = Nil;
+ Neu->Relocs = Nil;
+
+ if ((MomLocHandle == (-1)) OR (DestHandle != (-2)))
+ BEGIN
+ EnterSymbol(Neu, MayChange, DestHandle);
+ if (MakeDebug) PrintSymTree(Name);
+ END
+ else EnterLocSymbol(Neu);
+END
+
+ void EnterExtSymbol(char *Name_O, LargeInt Wert, Byte Typ, Boolean MayChange)
+BEGIN
+ SymbolPtr Neu;
+ LongInt DestHandle;
+ String Name;
+
+ strmaxcpy(Name, Name_O, 255);
+ if (NOT ExpandSymbol(Name)) return;
+ if (NOT GetSymSection(Name, &DestHandle)) return;
+ if (NOT ChkSymbName(Name))
+ BEGIN
+ WrXError(1020, Name); return;
+ END
+
+ Neu=(SymbolPtr) malloc(sizeof(SymbolEntry));
+ Neu->SymName = strdup(Name);
+ Neu->SymWert.Typ = TempInt;
+ Neu->SymWert.Contents.IWert = Wert;
+ Neu->SymType = Typ;
+ Neu->SymSize = (-1);
+ Neu->RefList = Nil;
+ Neu->Relocs = (PRelocEntry) malloc(sizeof(TRelocEntry));
+ Neu->Relocs->Next = Nil;
+ Neu->Relocs->Ref = strdup(Name);
+ Neu->Relocs->Add = True;
+
+ if ((MomLocHandle == (-1)) OR (DestHandle != (-2)))
+ BEGIN
+ EnterSymbol(Neu, MayChange, DestHandle);
+ if (MakeDebug) PrintSymTree(Name);
+ END
+ else EnterLocSymbol(Neu);
+END
+
+ void EnterFloatSymbol(char *Name_O, Double Wert, Boolean MayChange)
+BEGIN
+ SymbolPtr Neu;
+ LongInt DestHandle;
+ String Name;
+
+ strmaxcpy(Name, Name_O,255);
+ if (NOT ExpandSymbol(Name)) return;
+ if (NOT GetSymSection(Name,&DestHandle)) return;
+ if (NOT ChkSymbName(Name))
+ BEGIN
+ WrXError(1020, Name); return;
+ END
+ Neu=(SymbolPtr) malloc(sizeof(SymbolEntry));
+ Neu->SymName=strdup(Name);
+ Neu->SymWert.Typ = TempFloat;
+ Neu->SymWert.Contents.FWert = Wert;
+ Neu->SymType = 0;
+ Neu->SymSize = (-1);
+ Neu->RefList = Nil;
+ Neu->Relocs = Nil;
+
+ if ((MomLocHandle == (-1)) OR (DestHandle != (-2)))
+ BEGIN
+ EnterSymbol(Neu, MayChange, DestHandle);
+ if (MakeDebug) PrintSymTree(Name);
+ END
+ else EnterLocSymbol(Neu);
+END
+
+ void EnterStringSymbol(char *Name_O, char *Wert, Boolean MayChange)
+BEGIN
+ SymbolPtr Neu;
+ LongInt DestHandle;
+ String Name;
+
+ strmaxcpy(Name, Name_O, 255);
+ if (NOT ExpandSymbol(Name)) return;
+ if (NOT GetSymSection(Name,&DestHandle)) return;
+ if (NOT ChkSymbName(Name))
+ BEGIN
+ WrXError(1020, Name); return;
+ END
+ Neu=(SymbolPtr) malloc(sizeof(SymbolEntry));
+ Neu->SymName = strdup(Name);
+ Neu->SymWert.Contents.SWert = strdup(Wert);
+ Neu->SymWert.Typ = TempString;
+ Neu->SymType = 0;
+ Neu->SymSize = (-1);
+ Neu->RefList = Nil;
+ Neu->Relocs = Nil;
+
+ if ((MomLocHandle == (-1)) OR (DestHandle != (-2)))
+ BEGIN
+ EnterSymbol(Neu, MayChange, DestHandle);
+ if (MakeDebug) PrintSymTree(Name);
+ END
+ else EnterLocSymbol(Neu);
+END
+
+ static void AddReference(SymbolPtr Node)
+BEGIN
+ PCrossRef Lauf,Neu;
+
+ /* Speicher belegen */
+
+ Neu=(PCrossRef) malloc(sizeof(TCrossRef));
+ Neu->LineNum=CurrLine; Neu->OccNum=1; Neu->Next=Nil;
+
+ /* passende Datei heraussuchen */
+
+ Neu->FileNum=GetFileNum(CurrFileName);
+
+ /* suchen, ob Eintrag schon existiert */
+
+ Lauf=Node->RefList;
+ while ((Lauf!=Nil)
+ AND ((Lauf->FileNum!=Neu->FileNum) OR (Lauf->LineNum!=Neu->LineNum)))
+ Lauf=Lauf->Next;
+
+ /* schon einmal in dieser Datei in dieser Zeile aufgetaucht: nur Zaehler
+ rauf: */
+
+ if (Lauf!=Nil)
+ BEGIN
+ Lauf->OccNum++; free(Neu);
+ END
+
+ /* ansonsten an Kettenende anhaengen */
+
+ else if (Node->RefList==Nil) Node->RefList=Neu;
+
+ else
+ BEGIN
+ Lauf=Node->RefList;
+ while (Lauf->Next!=Nil) Lauf=Lauf->Next;
+ Lauf->Next=Neu;
+ END
+END
+
+ static Boolean FindNode_FNode(char *Name, TempType SearchType,
+ SymbolPtr *FindNode_Result, LongInt Handle)
+BEGIN
+ SymbolPtr Lauf=FirstSymbol;
+ ShortInt SErg=(-1);
+ Boolean Result=False;
+
+ while ((Lauf!=Nil) AND (SErg!=0))
+ BEGIN
+ SErg=StrCmp(Name,Lauf->SymName,Handle,Lauf->Attribute);
+ if (SErg<0) Lauf=Lauf->Left;
+ else if (SErg>0) Lauf=Lauf->Right;
+ END
+ if (Lauf!=Nil)
+ if ((SearchType==TempNone) OR (Lauf->SymWert.Typ==SearchType))
+ BEGIN
+ *FindNode_Result=Lauf; Result=True;
+ if (MakeCrossList AND DoRefs) AddReference(Lauf);
+ END
+
+ return Result;
+END
+
+ static Boolean FindNode_FSpec(char *Name, PForwardSymbol Root)
+BEGIN
+ while ((Root!=Nil) AND (strcmp(Root->Name,Name)!=0)) Root=Root->Next;
+ return (Root!=Nil);
+END
+
+ static SymbolPtr FindNode(char *Name_O, TempType SearchType)
+BEGIN
+ PSaveSection Lauf;
+ LongInt DestSection;
+ SymbolPtr FindNode_Result;
+ String Name;
+
+ strmaxcpy(Name,Name_O,255);
+ FindNode_Result=Nil;
+ if (NOT GetSymSection(Name,&DestSection)) return FindNode_Result;
+ if (NOT CaseSensitive) NLS_UpString(Name);
+ if (SectionStack!=Nil)
+ if (PassNo<=MaxSymPass)
+ if (FindNode_FSpec(Name,SectionStack->LocSyms)) DestSection=MomSectionHandle;
+/* if (FSpec(SectionStack->GlobSyms)) return; */
+ if (DestSection==(-2))
+ BEGIN
+ if (FindNode_FNode(Name,SearchType,&FindNode_Result,MomSectionHandle)) return FindNode_Result;
+ Lauf=SectionStack;
+ while (Lauf!=Nil)
+ BEGIN
+ if (FindNode_FNode(Name,SearchType,&FindNode_Result,Lauf->Handle)) return FindNode_Result;
+ Lauf=Lauf->Next;
+ END
+ END
+ else FindNode_FNode(Name,SearchType,&FindNode_Result,DestSection);
+
+ return FindNode_Result;
+END
+
+ static Boolean FindLocNode_FNode(char *Name, TempType SearchType,
+ SymbolPtr *FindLocNode_Result, LongInt Handle)
+BEGIN
+ SymbolPtr Lauf=FirstLocSymbol;
+ ShortInt SErg=(-1);
+ Boolean Result=False;
+
+ while ((Lauf!=Nil) AND (SErg!=0))
+ BEGIN
+ SErg=StrCmp(Name,Lauf->SymName,Handle,Lauf->Attribute);
+ if (SErg<0) Lauf=Lauf->Left;
+ else if (SErg>0) Lauf=Lauf->Right;
+ END
+
+ if (Lauf!=Nil)
+ if ((SearchType==TempNone) OR (Lauf->SymWert.Typ==SearchType))
+ BEGIN
+ *FindLocNode_Result=Lauf; Result=True;
+ END
+
+ return Result;
+END
+
+ static SymbolPtr FindLocNode(char *Name_O, TempType SearchType)
+BEGIN
+ PLocHandle RunLocHandle;
+ SymbolPtr FindLocNode_Result;
+ String Name;
+
+ FindLocNode_Result=Nil;
+
+ strmaxcpy(Name,Name_O,255); if (NOT CaseSensitive) NLS_UpString(Name);
+
+ if (MomLocHandle==(-1)) return FindLocNode_Result;
+
+ if (FindLocNode_FNode(Name,SearchType,&FindLocNode_Result,MomLocHandle))
+ return FindLocNode_Result;
+
+ RunLocHandle=FirstLocHandle;
+ while ((RunLocHandle!=Nil) AND (RunLocHandle->Cont!=(-1)))
+ BEGIN
+ if (FindLocNode_FNode(Name,SearchType,&FindLocNode_Result,RunLocHandle->Cont))
+ return FindLocNode_Result;
+ RunLocHandle=RunLocHandle->Next;
+ END
+
+ return FindLocNode_Result;
+END
+/**
+ void SetSymbolType(char *Name, Byte NTyp)
+BEGIN
+ Lauf:SymbolPtr;
+ HRef:Boolean;
+
+ IF NOT ExpandSymbol(Name) THEN Exit;
+ HRef:=DoRefs; DoRefs:=False;
+ Lauf:=FindLocNode(Name,TempInt);
+ IF Lauf=Nil THEN Lauf:=FindNode(Name,TempInt);
+ IF Lauf<>Nil THEN Lauf^.SymType:=NTyp;
+ DoRefs:=HRef;
+END
+**/
+
+ Boolean GetIntSymbol(char *Name, LargeInt *Wert)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return False;
+ Lauf=FindLocNode(NName,TempInt);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempInt);
+ if (Lauf!=Nil)
+ BEGIN
+ *Wert=Lauf->SymWert.Contents.IWert;
+ if (Lauf->SymType!=0) TypeFlag|=(1<<Lauf->SymType);
+ if ((Lauf->SymSize!=(-1)) AND (SizeFlag!=(-1))) SizeFlag=Lauf->SymSize;
+ Lauf->Used=True;
+ END
+ else
+ BEGIN
+ if (PassNo>MaxSymPass) WrXError(1010,Name);
+ *Wert=EProgCounter();
+ END
+ return (Lauf!=Nil);
+END
+
+ Boolean GetFloatSymbol(char *Name, Double *Wert)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return False;
+ Lauf=FindLocNode(Name,TempFloat);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempFloat);
+ if (Lauf!=Nil)
+ BEGIN
+ *Wert=Lauf->SymWert.Contents.FWert;
+ Lauf->Used=True;
+ END
+ else
+ BEGIN
+ if (PassNo>MaxSymPass) WrXError(1010,Name);
+ *Wert=0;
+ END
+ return (Lauf!=Nil);
+END
+
+ Boolean GetStringSymbol(char *Name, char *Wert)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return False;
+ Lauf=FindLocNode(NName,TempString);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempString);
+ if (Lauf!=Nil)
+ BEGIN
+ strcpy(Wert,Lauf->SymWert.Contents.SWert);
+ Lauf->Used=True;
+ END
+ else
+ BEGIN
+ if (PassNo>MaxSymPass) WrXError(1010,Name);
+ *Wert='\0';
+ END
+ return (Lauf!=Nil);
+END
+
+ void SetSymbolSize(char *Name, ShortInt Size)
+BEGIN
+ SymbolPtr Lauf;
+ Boolean HRef;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return;
+ HRef=DoRefs; DoRefs=False;
+ Lauf=FindLocNode(NName,TempInt);
+ if (Lauf==Nil) Lauf=FindNode(Name,TempInt);
+ if (Lauf!=Nil) Lauf->SymSize=Size;
+ DoRefs=HRef;
+END
+
+ ShortInt GetSymbolSize(char *Name)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return -1;
+ Lauf=FindLocNode(NName,TempInt);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempInt);
+ return ((Lauf!=Nil) ? Lauf->SymSize : -1);
+END
+
+ Boolean IsSymbolFloat(char *Name)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return False;
+
+ Lauf=FindLocNode(NName,TempFloat);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempFloat);
+ return ((Lauf!=Nil) AND (Lauf->SymWert.Typ==TempFloat));
+END
+
+ Boolean IsSymbolString(char *Name)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return False;
+
+ Lauf=FindLocNode(NName,TempString);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempString);
+ return ((Lauf!=Nil) AND (Lauf->SymWert.Typ==TempString));
+END
+
+ Boolean IsSymbolDefined(char *Name)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return False;
+
+ Lauf=FindLocNode(NName,TempInt);
+ if (Lauf==Nil) Lauf=FindLocNode(NName,TempFloat);
+ if (Lauf==Nil) Lauf=FindLocNode(NName,TempString);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempInt);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempFloat);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempString);
+ return ((Lauf!=Nil) AND (Lauf->Defined));
+END
+
+ Boolean IsSymbolUsed(char *Name)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return False;
+
+ Lauf=FindLocNode(NName,TempInt);
+ if (Lauf==Nil) Lauf=FindLocNode(NName,TempFloat);
+ if (Lauf==Nil) Lauf=FindLocNode(NName,TempString);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempInt);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempFloat);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempString);
+ return ((Lauf!=Nil) AND (Lauf->Used));
+END
+
+ Boolean IsSymbolChangeable(char *Name)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return False;
+
+ Lauf=FindLocNode(NName,TempInt);
+ if (Lauf==Nil) Lauf=FindLocNode(NName,TempFloat);
+ if (Lauf==Nil) Lauf=FindLocNode(NName,TempString);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempInt);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempFloat);
+ if (Lauf==Nil) Lauf=FindNode(NName,TempString);
+ return ((Lauf!=Nil) AND (Lauf->Changeable));
+END
+
+ Integer GetSymbolType(char *Name)
+BEGIN
+ SymbolPtr Lauf;
+ String NName;
+
+ strmaxcpy(NName,Name,255);
+ if (NOT ExpandSymbol(NName)) return -1;
+
+ Lauf=FindLocNode(Name,TempInt);
+ if (Lauf==Nil) Lauf=FindLocNode(Name,TempFloat);
+ if (Lauf==Nil) Lauf=FindLocNode(Name,TempString);
+ if (Lauf==Nil) Lauf=FindNode(Name,TempInt);
+ if (Lauf==Nil) Lauf=FindNode(Name,TempFloat);
+ if (Lauf==Nil) Lauf=FindNode(Name,TempString);
+ return (Lauf==Nil) ? -1 : Lauf->SymType;
+END
+
+ static void ConvertSymbolVal(SymbolVal *Inp, TempResult *Outp)
+BEGIN
+ switch (Outp->Typ=Inp->Typ)
+ BEGIN
+ case TempInt :Outp->Contents.Int =Inp->Contents.IWert; break;
+ case TempFloat :Outp->Contents.Float=Inp->Contents.FWert; break;
+ case TempString:strmaxcpy(Outp->Contents.Ascii,Inp->Contents.SWert,255); break;
+ default: break;
+ END
+END
+
+static int ActPageWidth,cwidth;
+
+ static void PrintSymbolList_AddOut(char *s, char *Zeilenrest, int Width)
+BEGIN
+ if (strlen(s)+strlen(Zeilenrest)>Width)
+ BEGIN
+ Zeilenrest[strlen(Zeilenrest)-1]='\0';
+ WrLstLine(Zeilenrest); strmaxcpy(Zeilenrest,s,255);
+ END
+ else strmaxcat(Zeilenrest,s,255);
+END
+
+ static void PrintSymbolList_PNode(SymbolPtr Node, int Width,
+ LongInt *Sum, LongInt *USum,
+ char *Zeilenrest)
+BEGIN
+ String s1,sh;
+ int l1;
+ TempResult t;
+
+ ConvertSymbolVal(&(Node->SymWert),&t); StrSym(&t,False,s1);
+
+ strmaxcpy(sh,Node->SymName,255);
+ if (Node->Attribute!=(-1))
+ BEGIN
+ strmaxcat(sh," [",255);
+ strmaxcat(sh,GetSectionName(Node->Attribute),255);
+ strmaxcat(sh,"]",255);
+ END
+ strmaxprep(sh,(Node->Used)?" ":"*",255);
+ l1=(strlen(s1)+strlen(sh)+6)%(cwidth);
+ if (l1<cwidth-2) strmaxprep(s1,Blanks(cwidth-2-l1),255);
+ strmaxprep(s1," : ",255);
+ strmaxprep(s1,sh,255);
+ strmaxcat(s1," ",255);
+ s1[l1=strlen(s1)]=SegShorts[Node->SymType]; s1[l1+1]='\0';
+ strmaxcat(s1," | ",255);
+ PrintSymbolList_AddOut(s1,Zeilenrest,Width); (*Sum)++;
+ if (NOT Node->Used) (*USum)++;
+END
+
+ static void PrintSymbolList_PrintNode(SymbolPtr Node, int Width,
+ LongInt *Sum, LongInt *USum,
+ char *Zeilenrest)
+BEGIN
+ ChkStack();
+
+ if (Node==Nil) return;
+
+ PrintSymbolList_PrintNode(Node->Left,Width,Sum,USum,Zeilenrest);
+ PrintSymbolList_PNode(Node,Width,Sum,USum,Zeilenrest);
+ PrintSymbolList_PrintNode(Node->Right,Width,Sum,USum,Zeilenrest);
+END
+
+ void PrintSymbolList(void)
+BEGIN
+ int Width;
+ String Zeilenrest;
+ LongInt Sum,USum;
+
+ Width=(PageWidth==0)?80:PageWidth;
+ NewPage(ChapDepth,True);
+ WrLstLine(getmessage(Num_ListSymListHead1));
+ WrLstLine(getmessage(Num_ListSymListHead2));
+ WrLstLine("");
+
+ Zeilenrest[0]='\0'; Sum=0; USum=0;
+ ActPageWidth=(PageWidth==0) ? 80 : PageWidth; cwidth=ActPageWidth>>1;
+ PrintSymbolList_PrintNode(FirstSymbol,Width,&Sum,&USum,Zeilenrest);
+ if (Zeilenrest[0]!='\0')
+ BEGIN
+ Zeilenrest[strlen(Zeilenrest)-1]='\0';
+ WrLstLine(Zeilenrest);
+ END
+ WrLstLine("");
+ sprintf(Zeilenrest,"%7d",Sum);
+ strmaxcat(Zeilenrest,getmessage((Sum==1)?Num_ListSymSumMsg:Num_ListSymSumsMsg),255);
+ WrLstLine(Zeilenrest);
+ sprintf(Zeilenrest,"%7d",USum);
+ strmaxcat(Zeilenrest,getmessage((USum==1)?Num_ListUSymSumMsg:Num_ListUSymSumsMsg),255);
+ WrLstLine(Zeilenrest);
+ WrLstLine("");
+END
+
+static Boolean HWritten;
+static int Space;
+
+ static void PrintDebSymbols_PNode(FILE *f, SymbolPtr Node)
+BEGIN
+ char *p;
+ int l1;
+ TempResult t;
+ String s;
+
+ if (NOT HWritten)
+ BEGIN
+ fprintf(f,"\n"); ChkIO(10004);
+ fprintf(f,"Symbols in Segment %s\n",SegNames[Space]); ChkIO(10004);
+ HWritten=True;
+ END
+
+ fprintf(f,"%s",Node->SymName); ChkIO(10004); l1=strlen(Node->SymName);
+ if (Node->Attribute!=(-1))
+ BEGIN
+ sprintf(s,"[%d]", (int)Node->Attribute);
+ fprintf(f,"%s",s); ChkIO(10004);
+ l1+=strlen(s);
+ END
+ fprintf(f,"%s ",Blanks(37-l1)); ChkIO(10004);
+ switch (Node->SymWert.Typ)
+ BEGIN
+ case TempInt: fprintf(f,"Int "); break;
+ case TempFloat: fprintf(f,"Float "); break;
+ case TempString: fprintf(f,"String "); break;
+ default: break;
+ END
+ ChkIO(10004);
+ if (Node->SymWert.Typ==TempString)
+ BEGIN
+ l1=0;
+ for (p=Node->SymWert.Contents.SWert; *p!='\0'; p++)
+ BEGIN
+ if ((*p=='\\') OR (*p<=' '))
+ BEGIN
+ fprintf(f,"\\%03d",*p); l1+=4;
+ END
+ else
+ BEGIN
+ fputc(*p,f); ChkIO(10004); l1++;
+ END
+ END
+ END
+ else
+ BEGIN
+ ConvertSymbolVal(&(Node->SymWert),&t); StrSym(&t,False,s);
+ l1=strlen(s);
+ fprintf(f,"%s",s); ChkIO(10004);
+ END
+ fprintf(f,"%s %-3d %d\n",Blanks(25-l1),Node->SymSize,(int)Node->Used);
+ ChkIO(10004);
+END
+
+ static void PrintDebSymbols_PrintNode(FILE *f, SymbolPtr Node)
+BEGIN
+ ChkStack();
+
+ if (Node==Nil) return;
+
+ PrintDebSymbols_PrintNode(f,Node->Left);
+
+ if (Node->SymType==Space) PrintDebSymbols_PNode(f,Node);
+
+ PrintDebSymbols_PrintNode(f,Node->Right);
+END
+
+ void PrintDebSymbols(FILE *f)
+BEGIN
+ for (Space=0; Space<PCMax; Space++)
+ BEGIN
+ HWritten=False;
+ PrintDebSymbols_PrintNode(f,FirstSymbol);
+ END
+END
+
+ static void PrNoISection(FILE *f, SymbolPtr Node, LongInt Handle)
+BEGIN
+ if (Node->Left!=Nil) PrNoISection(f,Node->Left,Handle);
+ if ((Node->SymType==SegCode) AND (Node->Attribute==Handle) AND (Node->SymWert.Typ==TempInt))
+ BEGIN
+ errno=0; fprintf(f,"DEFINE %s ",Node->SymName); ChkIO(10004);
+ errno=0; fprintf(f,LargeIntFormat,Node->SymWert.Contents.IWert); ChkIO(10004);
+ errno=0; fprintf(f,"\n"); ChkIO(10004);
+ END
+ if (Node->Right!=Nil) PrNoISection(f,Node->Right,Handle);
+END
+
+ void PrintNoISymbols(FILE *f)
+BEGIN
+ PCToken CurrSection;
+ LongInt z;
+
+ PrNoISection(f,FirstSymbol,-1); z=0;
+ for (CurrSection=FirstSection; CurrSection!=Nil; CurrSection=CurrSection->Next)
+ if (ChunkSum(&CurrSection->Usage)>0)
+ BEGIN
+ fprintf(f,"FUNCTION %s ",CurrSection->Name); ChkIO(10004);
+ fprintf(f,LargeIntFormat,ChunkMin(&CurrSection->Usage)); ChkIO(10004);
+ fprintf(f,"\n"); ChkIO(10004);
+ PrNoISection(f,FirstSymbol,z++);
+ fprintf(f,"ENDFUNC "); ChkIO(10004);
+ fprintf(f,LargeIntFormat,ChunkMax(&CurrSection->Usage)); ChkIO(10004);
+ fprintf(f,"\n"); ChkIO(10004);
+ END
+END
+
+ static void PrintSymbolTree_PrintNode(SymbolPtr Node, int Shift)
+BEGIN
+ Byte z;
+
+ if (Node==Nil) return;
+
+ PrintSymbolTree_PrintNode(Node->Left,Shift+1);
+
+ for (z=1; z<=Shift; z++) fprintf(Debug,"%6s","");
+ fprintf(Debug,"%s\n",Node->SymName);
+
+ PrintSymbolTree_PrintNode(Node->Right,Shift+1);
+END
+
+ void PrintSymbolTree(void)
+BEGIN
+ PrintSymbolTree_PrintNode(FirstSymbol,0);
+END
+
+ static void ClearSymbolList_ClearNode(SymbolPtr *Node)
+BEGIN
+ if ((*Node)->Left!=Nil) ClearSymbolList_ClearNode(&((*Node)->Left));
+ if ((*Node)->Right!=Nil) ClearSymbolList_ClearNode(&((*Node)->Right));
+ FreeSymbol(Node);
+END
+
+ void ClearSymbolList(void)
+BEGIN
+
+ if (FirstSymbol!=Nil) ClearSymbolList_ClearNode(&FirstSymbol);
+
+ if (FirstLocSymbol!=Nil) ClearSymbolList_ClearNode(&FirstLocSymbol);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Stack-Verwaltung */
+
+ Boolean PushSymbol(char *SymName_O, char *StackName_O)
+BEGIN
+ SymbolPtr Src;
+ PSymbolStack LStack,NStack,PStack;
+ PSymbolStackEntry Elem;
+ String SymName,StackName;
+
+ strmaxcpy(SymName,SymName_O,255);
+ if (NOT ExpandSymbol(SymName)) return False;
+
+ Src=FindNode(SymName,TempInt);
+ if (Src==Nil) Src=FindNode(SymName,TempFloat);
+ if (Src==Nil) Src=FindNode(SymName,TempString);
+ if (Src==Nil)
+ BEGIN
+ WrXError(1010,SymName); return False;
+ END
+
+ strmaxcpy(StackName,(*StackName_O=='\0')?DefStackName:StackName_O,255);
+ if (NOT ExpandSymbol(StackName)) return False;
+ if (NOT ChkSymbName(StackName))
+ BEGIN
+ WrXError(1020,StackName); return False;
+ END
+
+ LStack=FirstStack; PStack=Nil;
+ while ((LStack!=Nil) AND (strcmp(LStack->Name,StackName)<0))
+ BEGIN
+ PStack=LStack;
+ LStack=LStack->Next;
+ END
+
+ if ((LStack==Nil) OR (strcmp(LStack->Name,StackName)>0))
+ BEGIN
+ NStack=(PSymbolStack) malloc(sizeof(TSymbolStack));
+ NStack->Name=strdup(StackName);
+ NStack->Contents=Nil;
+ NStack->Next=LStack;
+ if (PStack==Nil) FirstStack=NStack; else PStack->Next=NStack;
+ LStack=NStack;
+ END
+
+ Elem=(PSymbolStackEntry) malloc(sizeof(TSymbolStackEntry));
+ Elem->Next=LStack->Contents;
+ Elem->Contents=Src->SymWert;
+ LStack->Contents=Elem;
+
+ return True;
+END
+
+ Boolean PopSymbol(char *SymName_O, char *StackName_O)
+BEGIN
+ SymbolPtr Dest;
+ PSymbolStack LStack,PStack;
+ PSymbolStackEntry Elem;
+ String SymName,StackName;
+
+ strmaxcpy(SymName,SymName_O,255);
+ if (NOT ExpandSymbol(SymName)) return False;
+
+ Dest=FindNode(SymName,TempInt);
+ if (Dest==Nil) Dest=FindNode(SymName,TempFloat);
+ if (Dest==Nil) Dest=FindNode(SymName,TempString);
+ if (Dest==Nil)
+ BEGIN
+ WrXError(1010,SymName); return False;
+ END
+
+ strmaxcpy(StackName,(*StackName_O=='\0')?DefStackName:StackName_O,255);
+ if (NOT ExpandSymbol(StackName)) return False;
+ if (NOT ChkSymbName(StackName))
+ BEGIN
+ WrXError(1020,StackName); return False;
+ END
+
+ LStack=FirstStack; PStack=Nil;
+ while ((LStack!=Nil) AND (strcmp(LStack->Name,StackName)<0))
+ BEGIN
+ PStack=LStack;
+ LStack=LStack->Next;
+ END
+
+ if ((LStack==Nil) OR (strcmp(LStack->Name,StackName)>0))
+ BEGIN
+ WrXError(1530,StackName); return False;
+ END
+
+ Elem=LStack->Contents;
+ Dest->SymWert=Elem->Contents;
+ if ((LStack->Contents=Elem->Next)==Nil)
+ BEGIN
+ if (PStack==Nil) FirstStack=LStack->Next; else PStack->Next=LStack->Next;
+ free(LStack->Name);
+ free(LStack);
+ END
+ free(Elem);
+
+ return True;
+END
+
+ void ClearStacks(void)
+BEGIN
+ PSymbolStack Act;
+ PSymbolStackEntry Elem;
+ int z;
+ String s;
+
+ while (FirstStack!=Nil)
+ BEGIN
+ z=0; Act=FirstStack;
+ while (Act->Contents!=Nil)
+ BEGIN
+ Elem=Act->Contents; Act->Contents=Elem->Next;
+ free(Elem); z++;
+ END
+ sprintf(s,"%s(%d)", Act->Name, z);
+ WrXError(230,s);
+ free(Act->Name);
+ FirstStack=Act->Next; free(Act);
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/* Funktionsverwaltung */
+
+ void EnterFunction(char *FName, char *FDefinition, Byte NewCnt)
+BEGIN
+ PFunction Neu;
+ String FName_N;
+
+ if (NOT CaseSensitive)
+ BEGIN
+ strmaxcpy(FName_N,FName,255); NLS_UpString(FName_N); FName=FName_N;
+ END
+
+ if (NOT ChkSymbName(FName))
+ BEGIN
+ WrXError(1020,FName); return;
+ END
+
+ if (FindFunction(FName)!=Nil)
+ BEGIN
+ if (PassNo==1) WrXError(1000,FName); return;
+ END
+
+ Neu=(PFunction) malloc(sizeof(TFunction));
+ Neu->Next=FirstFunction; Neu->ArguCnt=NewCnt;
+ Neu->Name=strdup(FName);
+ Neu->Definition=strdup(FDefinition);
+ FirstFunction=Neu;
+END
+
+ PFunction FindFunction(char *Name)
+BEGIN
+ PFunction Lauf=FirstFunction;
+ String Name_N;
+
+ if (NOT CaseSensitive)
+ BEGIN
+ strmaxcpy(Name_N,Name,255); NLS_UpString(Name_N); Name=Name_N;
+ END
+
+ while ((Lauf!=Nil) AND (strcmp(Lauf->Name,Name)!=0)) Lauf=Lauf->Next;
+ return Lauf;
+END
+
+ void PrintFunctionList(void)
+BEGIN
+ PFunction Lauf;
+ String OneS;
+ Boolean cnt;
+
+ if (FirstFunction==Nil) return;
+
+ NewPage(ChapDepth,True);
+ WrLstLine(getmessage(Num_ListFuncListHead1));
+ WrLstLine(getmessage(Num_ListFuncListHead2));
+ WrLstLine("");
+
+ OneS[0]='\0'; Lauf=FirstFunction; cnt=False;
+ while (Lauf!=Nil)
+ BEGIN
+ strmaxcat(OneS,Lauf->Name,255);
+ if (strlen(Lauf->Name)<37) strmaxcat(OneS,Blanks(37-strlen(Lauf->Name)),255);
+ if (NOT cnt) strmaxcat(OneS," | ",255);
+ else
+ BEGIN
+ WrLstLine(OneS); OneS[0]='\0';
+ END
+ cnt=NOT cnt;
+ Lauf=Lauf->Next;
+ END
+ if (cnt)
+ BEGIN
+ OneS[strlen(OneS)-1]='\0';
+ WrLstLine(OneS);
+ END
+ WrLstLine("");
+END
+
+ void ClearFunctionList(void)
+BEGIN
+ PFunction Lauf;
+
+ while (FirstFunction!=Nil)
+ BEGIN
+ Lauf=FirstFunction->Next;
+ free(FirstFunction->Name);
+ free(FirstFunction->Definition);
+ free(FirstFunction);
+ FirstFunction=Lauf;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void ResetSymbolDefines_ResetNode(SymbolPtr Node)
+BEGIN
+ if (Node->Left !=Nil) ResetSymbolDefines_ResetNode(Node->Left);
+ if (Node->Right!=Nil) ResetSymbolDefines_ResetNode(Node->Right);
+ Node->Defined=False; Node->Used=False;
+END
+
+ void ResetSymbolDefines(void)
+BEGIN
+
+ if (FirstSymbol!=Nil) ResetSymbolDefines_ResetNode(FirstSymbol);
+
+ if (FirstLocSymbol!=Nil) ResetSymbolDefines_ResetNode(FirstLocSymbol);
+END
+
+ void SetFlag(Boolean *Flag, char *Name, Boolean Wert)
+BEGIN
+ *Flag=Wert; EnterIntSymbol(Name,(*Flag)?1:0,0,True);
+END
+
+ void AddDefSymbol(char *Name, TempResult *Value)
+BEGIN
+ PDefSymbol Neu;
+
+ Neu=FirstDefSymbol;
+ while (Neu!=Nil)
+ BEGIN
+ if (strcmp(Neu->SymName,Name)==0) return;
+ Neu=Neu->Next;
+ END
+
+ Neu=(PDefSymbol) malloc(sizeof(TDefSymbol));
+ Neu->Next=FirstDefSymbol;
+ Neu->SymName=strdup(Name);
+ Neu->Wert=(*Value);
+ FirstDefSymbol=Neu;
+END
+
+ void RemoveDefSymbol(char *Name)
+BEGIN
+ PDefSymbol Save,Lauf;
+
+ if (FirstDefSymbol==Nil) return;
+
+ if (strcmp(FirstDefSymbol->SymName,Name)==0)
+ BEGIN
+ Save=FirstDefSymbol; FirstDefSymbol=FirstDefSymbol->Next;
+ END
+ else
+ BEGIN
+ Lauf=FirstDefSymbol;
+ while ((Lauf->Next!=Nil) AND (strcmp(Lauf->Next->SymName,Name)!=0)) Lauf=Lauf->Next;
+ if (Lauf->Next==Nil) return;
+ Save=Lauf->Next; Lauf->Next=Lauf->Next->Next;
+ END
+ free(Save->SymName); free(Save);
+END
+
+ void CopyDefSymbols(void)
+BEGIN
+ PDefSymbol Lauf;
+
+ Lauf=FirstDefSymbol;
+ while (Lauf!=Nil)
+ BEGIN
+ switch (Lauf->Wert.Typ)
+ BEGIN
+ case TempInt: EnterIntSymbol(Lauf->SymName,Lauf->Wert.Contents.Int,0,True); break;
+ case TempFloat: EnterFloatSymbol(Lauf->SymName,Lauf->Wert.Contents.Float,True); break;
+ case TempString: EnterStringSymbol(Lauf->SymName,Lauf->Wert.Contents.Ascii,True); break;
+ default: break;
+ END
+ Lauf=Lauf->Next;
+ END
+END
+
+ static void PrintSymbolDepth_SearchTree(SymbolPtr Lauf, LongInt SoFar,
+ LongInt *TreeMin, LongInt *TreeMax)
+BEGIN
+ if (Lauf==Nil)
+ BEGIN
+ if (SoFar>*TreeMax) *TreeMax=SoFar;
+ if (SoFar<*TreeMin) *TreeMin=SoFar;
+ END
+ else
+ BEGIN
+ PrintSymbolDepth_SearchTree(Lauf->Right,SoFar+1,TreeMin,TreeMax);
+ PrintSymbolDepth_SearchTree(Lauf->Left,SoFar+1,TreeMin,TreeMax);
+ END
+END
+
+ void PrintSymbolDepth(void)
+BEGIN
+ LongInt TreeMin,TreeMax;
+
+ TreeMin=MaxLongInt; TreeMax=0;
+ PrintSymbolDepth_SearchTree(FirstSymbol,0,&TreeMin,&TreeMax);
+ fprintf(Debug," MinTree %ld\n", (long)TreeMin);
+ fprintf(Debug," MaxTree %ld\n", (long)TreeMax);
+END
+
+ LongInt GetSectionHandle(char *SName_O, Boolean AddEmpt, LongInt Parent)
+BEGIN
+ PCToken Lauf,Prev;
+ LongInt z;
+ String SName;
+
+ strmaxcpy(SName,SName_O,255); if (NOT CaseSensitive) NLS_UpString(SName);
+
+ Lauf=FirstSection; Prev=Nil; z=0;
+ while ((Lauf!=Nil) AND ((strcmp(Lauf->Name,SName)!=0) OR (Lauf->Parent!=Parent)))
+ BEGIN
+ z++; Prev=Lauf; Lauf=Lauf->Next;
+ END
+
+ if (Lauf==Nil)
+ if (AddEmpt)
+ BEGIN
+ Lauf=(PCToken) malloc(sizeof(TCToken));
+ Lauf->Parent=MomSectionHandle;
+ Lauf->Name=strdup(SName);
+ Lauf->Next=Nil;
+ InitChunk(&(Lauf->Usage));
+ if (Prev==Nil) FirstSection=Lauf; else Prev->Next=Lauf;
+ END
+ else z=(-2);
+ return z;
+END
+
+ char *GetSectionName(LongInt Handle)
+BEGIN
+ PCToken Lauf=FirstSection;
+ static char *Dummy="";
+
+ if (Handle==(-1)) return Dummy;
+ while ((Handle>0) AND (Lauf!=Nil))
+ BEGIN
+ Lauf=Lauf->Next; Handle--;
+ END
+ return (Lauf==Nil)?Dummy:Lauf->Name;
+END
+
+ void SetMomSection(LongInt Handle)
+BEGIN
+ LongInt z;
+
+ MomSectionHandle=Handle;
+ if (Handle<0) MomSection=Nil;
+ else
+ BEGIN
+ MomSection=FirstSection;
+ for (z=1; z<=Handle; z++)
+ if (MomSection!=Nil) MomSection=MomSection->Next;
+ END
+END
+
+ void AddSectionUsage(LongInt Start,LongInt Length)
+BEGIN
+ if ((ActPC!=SegCode) OR (MomSection==Nil)) return;
+ AddChunk(&(MomSection->Usage),Start,Length,False);
+END
+
+ static void PrintSectionList_PSection(LongInt Handle, int Indent)
+BEGIN
+ PCToken Lauf;
+ LongInt Cnt;
+ String h;
+
+ ChkStack();
+ if (Handle!=(-1))
+ BEGIN
+ strmaxcpy(h,Blanks(Indent<<1),255);
+ strmaxcat(h,GetSectionName(Handle),255);
+ WrLstLine(h);
+ END
+ Lauf=FirstSection; Cnt=0;
+ while (Lauf!=Nil)
+ BEGIN
+ if (Lauf->Parent==Handle) PrintSectionList_PSection(Cnt,Indent+1);
+ Lauf=Lauf->Next; Cnt++;
+ END
+END
+
+ void PrintSectionList(void)
+BEGIN
+ if (FirstSection==Nil) return;
+
+ NewPage(ChapDepth,True);
+ WrLstLine(getmessage(Num_ListSectionListHead1));
+ WrLstLine(getmessage(Num_ListSectionListHead2));
+ WrLstLine("");
+ PrintSectionList_PSection(-1,0);
+END
+
+ void PrintDebSections(FILE *f)
+BEGIN
+ PCToken Lauf;
+ LongInt Cnt,z,l,s;
+
+ Lauf=FirstSection; Cnt=0;
+ while (Lauf!=Nil)
+ BEGIN
+ fputs("\nInfo for Section ", f); ChkIO(10004);
+ fprintf(f, LongIntFormat, Cnt); ChkIO(10004);
+ fputc(' ', f); ChkIO(10004);
+ fputs(GetSectionName(Cnt), f); ChkIO(10004);
+ fputc(' ', f); ChkIO(10004);
+ fprintf(f, LongIntFormat, Lauf->Parent); ChkIO(10004);
+ fputc('\n', f); ChkIO(10004);
+ for (z=0; z<Lauf->Usage.RealLen; z++)
+ BEGIN
+ l=Lauf->Usage.Chunks[z].Length;
+ s=Lauf->Usage.Chunks[z].Start;
+ fprintf(f,"%s",HexString(s,0)); ChkIO(10004);
+ if (l==1) fprintf(f,"\n"); else fprintf(f,"-%s\n",HexString(s+l-1,0)); ChkIO(10004);
+ END
+ Lauf=Lauf->Next;
+ Cnt++;
+ END
+END
+
+ void ClearSectionList(void)
+BEGIN
+ PCToken Tmp;
+
+ while (FirstSection!=Nil)
+ BEGIN
+ Tmp=FirstSection;
+ free(Tmp->Name);
+ ClearChunk(&(Tmp->Usage));
+ FirstSection=Tmp->Next; free(Tmp);
+ END
+END
+
+/*---------------------------------------------------------------------------------*/
+
+ static void PrintCrossList_PNode(SymbolPtr Node)
+BEGIN
+ int FileZ;
+ PCrossRef Lauf;
+ String LinePart,LineAcc;
+ String h,h2;
+ TempResult t;
+
+ if (Node->RefList==Nil) return;
+
+ ConvertSymbolVal(&(Node->SymWert),&t);
+ strcpy(h," (=");
+ StrSym(&t,False,h2); strmaxcat(h,h2,255);
+ strmaxcat(h,",",255);
+ strmaxcat(h,GetFileName(Node->FileNum),255);
+ strmaxcat(h,":",255);
+ sprintf(h2, LongIntFormat, Node->LineNum); strmaxcat(h,h2,255);
+ strmaxcat(h,"):",255);
+ if (Node->Attribute!=(-1))
+ BEGIN
+ strmaxprep(h,"] ",255);
+ strmaxprep(h,GetSectionName(Node->Attribute),255);
+ strmaxprep(h," [",255);
+ END
+
+ strmaxprep(h,Node->SymName,255);
+ strmaxprep(h,getmessage(Num_ListCrossSymName),255);
+ WrLstLine(h);
+
+ for (FileZ=0; FileZ<GetFileCount(); FileZ++)
+ BEGIN
+ Lauf=Node->RefList;
+
+ while ((Lauf!=Nil) AND (Lauf->FileNum!=FileZ)) Lauf=Lauf->Next;
+
+ if (Lauf!=Nil)
+ BEGIN
+ strcpy(h," ");
+ strmaxcat(h,getmessage(Num_ListCrossFileName),255);
+ strmaxcat(h,GetFileName(FileZ),255);
+ strmaxcat(h," :",255);
+ WrLstLine(h);
+ strcpy(LineAcc," ");
+ while (Lauf!=Nil)
+ BEGIN
+ sprintf(LinePart,"%5ld", (long)Lauf->LineNum);
+ strmaxcat(LineAcc,LinePart,255);
+ if (Lauf->OccNum!=1)
+ BEGIN
+ sprintf(LinePart,"(%2ld)", (long)Lauf->OccNum);
+ strmaxcat(LineAcc,LinePart,255);
+ END
+ else strmaxcat(LineAcc," ",255);
+ if (strlen(LineAcc)>=72)
+ BEGIN
+ WrLstLine(LineAcc); strcpy(LineAcc," ");
+ END
+ Lauf=Lauf->Next;
+ END
+ if (strcmp(LineAcc," ")!=0) WrLstLine(LineAcc);
+ END
+ END
+ WrLstLine("");
+END
+
+ static void PrintCrossList_PrintNode(SymbolPtr Node)
+BEGIN
+ if (Node==Nil) return;
+
+ PrintCrossList_PrintNode(Node->Left);
+
+ PrintCrossList_PNode(Node);
+
+ PrintCrossList_PrintNode(Node->Right);
+END
+
+ void PrintCrossList(void)
+BEGIN
+
+ WrLstLine("");
+ WrLstLine(getmessage(Num_ListCrossListHead1));
+ WrLstLine(getmessage(Num_ListCrossListHead2));
+ WrLstLine("");
+ PrintCrossList_PrintNode(FirstSymbol);
+ WrLstLine("");
+END
+
+ static void ClearCrossList_CNode(SymbolPtr Node)
+BEGIN
+ PCrossRef Lauf;
+
+ if (Node->Left!=Nil) ClearCrossList_CNode(Node->Left);
+
+ if (Node!=Nil)
+ while (Node->RefList!=Nil)
+ BEGIN
+ Lauf=Node->RefList->Next;
+ free(Node->RefList);
+ Node->RefList=Lauf;
+ END
+
+ if (Node->Right!=Nil) ClearCrossList_CNode(Node->Right);
+END
+
+ void ClearCrossList(void)
+BEGIN
+ ClearCrossList_CNode(FirstSymbol);
+END
+
+ LongInt GetLocHandle(void)
+BEGIN
+ return LocHandleCnt++;
+END
+
+ void PushLocHandle(LongInt NewLoc)
+BEGIN
+ PLocHandle NewLocHandle;
+
+ NewLocHandle=(PLocHandle) malloc(sizeof(TLocHeap));
+ NewLocHandle->Cont=MomLocHandle;
+ NewLocHandle->Next=FirstLocHandle;
+ FirstLocHandle=NewLocHandle; MomLocHandle=NewLoc;
+END
+
+ void PopLocHandle(void)
+BEGIN
+ PLocHandle OldLocHandle;
+
+ OldLocHandle=FirstLocHandle;
+ if (OldLocHandle==Nil) return;
+ MomLocHandle=OldLocHandle->Cont;
+ FirstLocHandle=OldLocHandle->Next;
+ free(OldLocHandle);
+END
+
+ void ClearLocStack()
+BEGIN
+ while (MomLocHandle!=(-1)) PopLocHandle();
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static PRegDef LookupReg(char *Name, Boolean CreateNew)
+BEGIN
+ PRegDef Run,Neu,Prev;
+ int cmperg=0;
+
+ Prev=Nil; Run=FirstRegDef;
+ while ((Run!=Nil) AND ((cmperg=strcmp(Run->Orig,Name))!=0))
+ BEGIN
+ Prev=Run; Run=(cmperg<0) ? Run->Left : Run->Right;
+ END
+ if ((Run==Nil) AND (CreateNew))
+ BEGIN
+ Neu=(PRegDef) malloc(sizeof(TRegDef));
+ Neu->Orig=strdup(Name);
+ Neu->Left=Neu->Right=Nil;
+ Neu->Defs=Nil;
+ Neu->DoneDefs=Nil;
+ if (Prev==Nil) FirstRegDef=Neu;
+ else if (cmperg<0) Prev->Left=Neu; else Prev->Right=Neu;
+ return Neu;
+ END
+ else return Run;
+END
+
+ void AddRegDef(char *Orig_N, char *Repl_N)
+BEGIN
+ PRegDef Node;
+ PRegDefList Neu;
+ String Orig,Repl;
+
+ strmaxcpy(Orig,Orig_N,255); strmaxcpy(Repl,Repl_N,255);
+ if (NOT CaseSensitive)
+ BEGIN
+ NLS_UpString(Orig); NLS_UpString(Repl);
+ END
+ if (NOT ChkSymbName(Orig))
+ BEGIN
+ WrXError(1020,Orig); return;
+ END
+ if (NOT ChkSymbName(Repl))
+ BEGIN
+ WrXError(1020,Repl); return;
+ END
+ Node=LookupReg(Orig,True);
+ if ((Node->Defs!=Nil) AND (Node->Defs->Section==MomSectionHandle))
+ WrXError(1000,Orig);
+ else
+ BEGIN
+ Neu=(PRegDefList) malloc(sizeof(TRegDefList));
+ Neu->Next=Node->Defs; Neu->Section=MomSectionHandle;
+ Neu->Value=strdup(Repl);
+ Neu->Used=False;
+ Node->Defs=Neu;
+ END
+END
+
+ Boolean FindRegDef(char *Name_N, char **Erg)
+BEGIN
+ LongInt Sect;
+ PRegDef Node;
+ PRegDefList Def;
+ String Name;
+
+ if (*Name_N=='[') return FALSE;
+
+ strmaxcpy(Name,Name_N,255);
+
+ if (NOT GetSymSection(Name,&Sect)) return False;
+ if (NOT CaseSensitive) NLS_UpString(Name);
+ Node=LookupReg(Name,False);
+ if (Node==Nil) return False;
+ Def=Node->Defs;
+ if (Sect!=-2)
+ while ((Def!=Nil) AND (Def->Section!=Sect)) Def=Def->Next;
+ if (Def==Nil) return False;
+ else
+ BEGIN
+ *Erg=Def->Value; Def->Used=True; return True;
+ END
+END
+
+ static void TossRegDefs_TossSingle(PRegDef Node, LongInt Sect)
+BEGIN
+ PRegDefList Tmp;
+
+ if (Node==Nil) return; ChkStack();
+
+ if ((Node->Defs!=Nil) AND (Node->Defs->Section==Sect))
+ BEGIN
+ Tmp=Node->Defs; Node->Defs=Node->Defs->Next;
+ Tmp->Next=Node->DoneDefs; Node->DoneDefs=Tmp;
+ END
+
+ TossRegDefs_TossSingle(Node->Left,Sect);
+ TossRegDefs_TossSingle(Node->Right,Sect);
+END
+
+ void TossRegDefs(LongInt Sect)
+BEGIN
+ TossRegDefs_TossSingle(FirstRegDef,Sect);
+END
+
+ static void ClearRegDefList(PRegDefList Start)
+BEGIN
+ PRegDefList Tmp;
+
+ while (Start!=Nil)
+ BEGIN
+ Tmp=Start; Start=Start->Next;
+ free(Tmp->Value);
+ free(Tmp);
+ END
+END
+
+ static void CleanupRegDefs_CleanupNode(PRegDef Node)
+BEGIN
+ if (Node==Nil) return; ChkStack();
+ ClearRegDefList(Node->DoneDefs); Node->DoneDefs=Nil;
+ CleanupRegDefs_CleanupNode(Node->Left);
+ CleanupRegDefs_CleanupNode(Node->Right);
+END
+
+ void CleanupRegDefs(void)
+BEGIN
+ CleanupRegDefs_CleanupNode(FirstRegDef);
+END
+
+ static void ClearRegDefs_ClearNode(PRegDef Node)
+BEGIN
+ if (Node==Nil) return; ChkStack();
+ ClearRegDefList(Node->Defs); Node->Defs=Nil;
+ ClearRegDefList(Node->DoneDefs); Node->DoneDefs=Nil;
+ ClearRegDefs_ClearNode(Node->Left); ClearRegDefs_ClearNode(Node->Right);
+ free(Node->Orig);
+ free(Node);
+END
+
+ void ClearRegDefs(void)
+BEGIN
+ ClearRegDefs_ClearNode(FirstRegDef);
+END
+
+ static void PrintRegDefs_PNode(PRegDef Node, char *buf, LongInt *Sum, LongInt *USum)
+BEGIN
+ PRegDefList Lauf;
+ String tmp,tmp2;
+
+ for (Lauf=Node->DoneDefs; Lauf!=Nil; Lauf=Lauf->Next)
+ BEGIN
+ if (Lauf->Section!=-1)
+ sprintf(tmp2,"[%s]",GetSectionName(Lauf->Section));
+ else
+ *tmp2='\0';
+ sprintf(tmp,"%c%s%s --> %s",(Lauf->Used) ? ' ' : '*',Node->Orig,tmp2,Lauf->Value);
+ if (strlen(tmp)>cwidth-3)
+ BEGIN
+ if (*buf!='\0') WrLstLine(buf); *buf='\0'; WrLstLine(tmp);
+ END
+ else
+ BEGIN
+ strmaxcat(tmp,Blanks(cwidth-3-strlen(tmp)),255);
+ if (*buf=='\0') strcpy(buf,tmp);
+ else
+ BEGIN
+ strcat(buf," | "); strcat(buf,tmp);
+ WrLstLine(buf); *buf='\0';
+ END
+ END
+ (*Sum)++; if (NOT Lauf->Used) (*USum)++;
+ END
+END
+
+ static void PrintRegDefs_PrintSingle(PRegDef Node, char *buf, LongInt *Sum, LongInt *USum)
+BEGIN
+ if (Node==Nil) return; ChkStack();
+
+ PrintRegDefs_PrintSingle(Node->Left,buf,Sum,USum);
+ PrintRegDefs_PNode(Node,buf,Sum,USum);
+ PrintRegDefs_PrintSingle(Node->Right,buf,Sum,USum);
+END
+
+ void PrintRegDefs(void)
+BEGIN
+ String buf;
+ LongInt Sum,USum;
+
+ if (FirstRegDef==Nil) return;
+
+ NewPage(ChapDepth,True);
+ WrLstLine(getmessage(Num_ListRegDefListHead1));
+ WrLstLine(getmessage(Num_ListRegDefListHead2));
+ WrLstLine("");
+
+ *buf='\0'; Sum=0; USum=0;
+ ActPageWidth=(PageWidth==0) ? 80 : PageWidth;
+ cwidth=ActPageWidth>>1;
+ PrintRegDefs_PrintSingle(FirstRegDef,buf,&Sum,&USum);
+
+ if (*buf!='\0') WrLstLine(buf);
+ WrLstLine("");
+ sprintf(buf,"%7ld%s",
+ (long) Sum,
+ getmessage((Sum==1)?Num_ListRegDefSumMsg:Num_ListRegDefSumsMsg));
+ WrLstLine(buf);
+ sprintf(buf,"%7ld%s",
+ (long)USum,
+ getmessage((USum==1)?Num_ListRegDefUSumMsg:Num_ListRegDefUSumsMsg));
+ WrLstLine("");
+END
+
+/*--------------------------------------------------------------------------*/
+
+ void ClearCodepages(void)
+BEGIN
+ PTransTable Old;
+
+ while (TransTables!=Nil)
+ BEGIN
+ Old=TransTables; TransTables=Old->Next;
+ free(Old->Name); free(Old->Table); free(Old);
+ END
+END
+
+ void PrintCodepages(void)
+BEGIN
+ char buf[500];
+ PTransTable Table;
+ int z,cnt,cnt2;
+
+ NewPage(ChapDepth,True);
+ WrLstLine(getmessage(Num_ListCodepageListHead1));
+ WrLstLine(getmessage(Num_ListCodepageListHead2));
+ WrLstLine("");
+
+ cnt2=0;
+ for (Table=TransTables; Table!=Nil; Table=Table->Next)
+ BEGIN
+ for (z=cnt=0; z<256; z++)
+ if (Table->Table[z]!=z) cnt++;
+ sprintf(buf,"%s (%d%s)",Table->Name,cnt,
+ getmessage((cnt==1) ? Num_ListCodepageChange : Num_ListCodepagePChange));
+ WrLstLine(buf);
+ cnt2++;
+ END
+ WrLstLine("");
+ sprintf(buf,"%d%s",cnt2,
+ getmessage((cnt2==1) ? Num_ListCodepageSumMsg : Num_ListCodepageSumsMsg));
+END
+
+/*--------------------------------------------------------------------------*/
+
+ void asmpars_init(void)
+BEGIN
+ FirstDefSymbol=Nil;
+ FirstFunction=Nil;
+ BalanceTree=False;
+ IntMins[(int)Int32]--;
+ IntMins[(int)SInt32]--;
+#ifdef HAS64
+ IntMins[(int)Int64]--;
+#endif
+END
+
diff --git a/asmpars.h b/asmpars.h
new file mode 100644
index 0000000..2f944b0
--- /dev/null
+++ b/asmpars.h
@@ -0,0 +1,207 @@
+/* asmpars.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung von Symbolen und das ganze Drumherum... */
+/* */
+/* Historie: 5. 5.1996 Grundsteinlegung */
+/* 26. 6.1998 Codepages */
+/* 16. 8.1998 NoICE-Symbolausgabe */
+/* 6.12.1998 UInt14 */
+/* 12. 7.1999 angefangen mit externen Symbolen */
+/* */
+/*****************************************************************************/
+
+typedef enum {UInt1 ,
+ UInt2 ,
+ UInt3 ,
+ SInt4 ,UInt4 , Int4 ,
+ SInt5 ,UInt5 , Int5 ,
+ UInt6 ,
+ SInt7 ,UInt7 ,
+ SInt8 ,UInt8 , Int8 ,
+ UInt9 ,
+ UInt10 , Int10 ,
+ UInt11 ,
+ UInt12 , Int12 ,
+ UInt13 ,
+ UInt14 ,
+ UInt15 ,
+ SInt16 ,UInt16 , Int16 ,
+ UInt18 ,
+ SInt20 ,UInt20 , Int20 ,
+ UInt22 ,
+ SInt24 ,UInt24 , Int24 ,
+ SInt32 ,UInt32 , Int32 ,
+#ifdef HAS64
+ Int64 ,
+#endif
+ IntTypeCnt} IntType;
+
+typedef enum {Float32,Float64,Float80,FloatDec,FloatCo,FloatTypeCnt} FloatType;
+
+extern LargeWord IntMasks[IntTypeCnt];
+extern LargeInt IntMins[IntTypeCnt];
+extern LargeInt IntMaxs[IntTypeCnt];
+
+extern Boolean FirstPassUnknown;
+extern Boolean SymbolQuestionable;
+extern Boolean UsesForwards;
+extern LongInt MomLocHandle;
+extern LongInt LocHandleCnt;
+extern Boolean BalanceTree;
+extern LongInt MomLocHandle;
+
+
+extern void AsmParsInit(void);
+
+
+extern Boolean SingleBit(LargeInt Inp, LargeInt *Erg);
+
+
+extern LargeInt ConstIntVal(char *Asc_O, IntType Typ, Boolean *Ok);
+
+extern Double ConstFloatVal(char *Asc_O, FloatType Typ, Boolean *Ok);
+
+extern void ConstStringVal(char *Asc, char *Erg, Boolean *OK);
+
+
+extern Boolean RangeCheck(LargeInt Wert, IntType Typ);
+
+extern Boolean FloatRangeCheck(Double Wert, FloatType Typ);
+
+
+extern Boolean IdentifySection(char *Name, LongInt *Erg);
+
+
+extern Boolean ExpandSymbol(char *Name);
+
+extern void EnterIntSymbol(char *Name_O, LargeInt Wert, Byte Typ, Boolean MayChange);
+
+extern void EnterExtSymbol(char *Name_O, LargeInt Wert, Byte Typ, Boolean MayChange);
+
+extern void EnterFloatSymbol(char *Name_O, Double Wert, Boolean MayChange);
+
+extern void EnterStringSymbol(char *Name_O, char *Wert, Boolean MayChange);
+
+extern Boolean GetIntSymbol(char *Name, LargeInt *Wert);
+
+extern Boolean GetFloatSymbol(char *Name, Double *Wert);
+
+extern Boolean GetStringSymbol(char *Name, char *Wert);
+
+extern void PrintSymbolList(void);
+
+extern void PrintDebSymbols(FILE *f);
+
+extern void PrintNoISymbols(FILE *f);
+
+extern void PrintSymbolTree(void);
+
+extern void ClearSymbolList(void);
+
+extern void ResetSymbolDefines(void);
+
+extern void PrintSymbolDepth(void);
+
+
+extern void SetSymbolSize(char *Name, ShortInt Size);
+
+extern ShortInt GetSymbolSize(char *Name);
+
+extern Boolean IsSymbolFloat(char *Name);
+
+extern Boolean IsSymbolString(char *Name);
+
+extern Boolean IsSymbolDefined(char *Name);
+
+extern Boolean IsSymbolUsed(char *Name);
+
+extern Boolean IsSymbolChangeable(char *Name);
+
+extern Integer GetSymbolType(char *Name);
+
+extern void EvalExpression(char *Asc_O, TempResult *Erg);
+
+extern LargeInt EvalIntExpression(char *Asc, IntType Typ, Boolean *OK);
+
+extern Double EvalFloatExpression(char *Asc, FloatType Typ, Boolean *OK);
+
+extern void EvalStringExpression(char *Asc, Boolean *OK, char *Result);
+
+
+extern Boolean PushSymbol(char *SymName_O, char *StackName_O);
+
+extern Boolean PopSymbol(char *SymName_O, char *StackName_O);
+
+extern void ClearStacks(void);
+
+
+extern void EnterFunction(char *FName, char *FDefinition, Byte NewCnt);
+
+extern PFunction FindFunction(char *Name);
+
+extern void PrintFunctionList(void);
+
+extern void ClearFunctionList(void);
+
+
+extern void AddDefSymbol(char *Name, TempResult *Value);
+
+extern void RemoveDefSymbol(char *Name);
+
+extern void CopyDefSymbols(void);
+
+
+extern void PrintCrossList(void);
+
+extern void ClearCrossList(void);
+
+
+extern LongInt GetSectionHandle(char *SName_O, Boolean AddEmpt, LongInt Parent);
+
+extern char *GetSectionName(LongInt Handle);
+
+extern void SetMomSection(LongInt Handle);
+
+extern void AddSectionUsage(LongInt Start, LongInt Length);
+
+extern void PrintSectionList(void);
+
+extern void PrintDebSections(FILE *f);
+
+extern void ClearSectionList(void);
+
+
+extern void SetFlag(Boolean *Flag, char *Name, Boolean Wert);
+
+
+extern LongInt GetLocHandle(void);
+
+extern void PushLocHandle(LongInt NewLoc);
+
+extern void PopLocHandle(void);
+
+extern void ClearLocStack(void);
+
+
+extern void AddRegDef(char *Orig, char *Repl);
+
+extern Boolean FindRegDef(char *Name, char **Erg);
+
+extern void TossRegDefs(LongInt Sect);
+
+extern void CleanupRegDefs(void);
+
+extern void ClearRegDefs(void);
+
+extern void PrintRegDefs(void);
+
+
+extern void ClearCodepages(void);
+
+extern void PrintCodepages(void);
+
+
+extern void asmpars_init(void);
+
diff --git a/asmrelocs.c b/asmrelocs.c
new file mode 100644
index 0000000..bb24e22
--- /dev/null
+++ b/asmrelocs.c
@@ -0,0 +1,133 @@
+/* asmrelocs.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung von Relokationslisten */
+/* */
+/* Historie: 25. 7.1999 Grundsteinlegung */
+/* 1. 8.1999 Merge-Funktion implementiert */
+/* 8. 8.1999 Reloc-Liste gespeichert */
+/* 15. 9.1999 fehlende Includes */
+/* Add in Merge */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmrelocs.h"
+
+/*---------------------------------------------------------------------------*/
+
+PRelocEntry LastRelocs = Nil;
+
+/*---------------------------------------------------------------------------*/
+
+ PRelocEntry MergeRelocs(PRelocEntry *list1, PRelocEntry *list2,
+ Boolean Add)
+BEGIN
+ PRelocEntry PRun1, PRun2, PPrev, PNext, PLast, PRes;
+
+ PRun1 = *list1; PLast = PRes = Nil;
+
+ /* ueber alle in Liste 1 */
+
+ while (PRun1 != Nil)
+ BEGIN
+ /* Uebereinstimmung suchen, die sich aufhebt */
+
+ PNext = PRun1->Next;
+ PRun2 = *list2; PPrev = Nil;
+ while (PRun2 != Nil)
+ if ((strcasecmp(PRun1->Ref, PRun2->Ref) == 0) AND ((PRun1->Add != PRun2->Add) != Add))
+ BEGIN
+ /* gefunden -> beide weg */
+
+ free(PRun1->Ref); free(PRun2->Ref);
+ if (PPrev == Nil) *list2 = PRun2->Next;
+ else PPrev->Next = PRun2->Next;
+ free(PRun2); free(PRun1); PRun1 = Nil;
+ break;
+ END
+ else
+ BEGIN
+ PPrev = PRun2; PRun2 = PRun2->Next;
+ END
+
+ /* ansonsten an Ergebnisliste anhaengen */
+
+ if (PRun1 != Nil)
+ if (PLast == Nil) PRes = PLast = PRun1;
+ else
+ BEGIN
+ PLast->Next = PRun1; PLast = PRun1;
+ END
+ PRun1 = PNext;
+ END
+
+ /* Reste aus Liste 2 nicht vergessen */
+
+ if (PLast == Nil) PRes = *list2;
+ else PLast->Next = *list2;
+
+ /* Quellisten jetzt leer */
+
+ *list1 = *list2 = Nil;
+
+ /* fertich */
+
+ return PRes;
+END
+
+ void InvertRelocs(PRelocEntry *erg, PRelocEntry *src)
+BEGIN
+ PRelocEntry SRun;
+
+ for (SRun = *src; SRun != Nil; SRun = SRun->Next)
+ SRun->Add = NOT (SRun->Add);
+
+ *erg = *src;
+END
+
+ void FreeRelocs(PRelocEntry *list)
+BEGIN
+ PRelocEntry Run;
+
+ while (*list != Nil)
+ BEGIN
+ Run = *list;
+ *list = (*list)->Next;
+ free(Run->Ref);
+ free(Run);
+ END
+END
+
+ PRelocEntry DupRelocs(PRelocEntry src)
+BEGIN
+ PRelocEntry First, Run, SRun, Neu;
+
+ First = Run = Nil;
+ for (SRun = src; SRun != Nil; SRun = SRun->Next)
+ BEGIN
+ Neu = (PRelocEntry) malloc(sizeof(TRelocEntry));
+ Neu->Next = Nil;
+ Neu->Ref = strdup(SRun->Ref);
+ Neu->Add = SRun->Add;
+ if (First == Nil) First = Neu;
+ else Run->Next = Neu;
+ Run = Neu;
+ END
+
+ return First;
+END
+
+ void SetRelocs(PRelocEntry List)
+BEGIN
+ if (LastRelocs != Nil)
+ BEGIN
+ WrError(1155);
+ FreeRelocs(&LastRelocs);
+ END
+ LastRelocs = List;
+END
diff --git a/asmrelocs.h b/asmrelocs.h
new file mode 100644
index 0000000..e808e61
--- /dev/null
+++ b/asmrelocs.h
@@ -0,0 +1,22 @@
+/* asmrelocs.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung von Relokationslisten */
+/* */
+/* Historie: 25. 7.1999 Grundsteinlegung */
+/* 8. 8.1999 Reloc-Liste gespeichert */
+/*****************************************************************************/
+
+extern PRelocEntry LastRelocs;
+
+extern PRelocEntry MergeRelocs(PRelocEntry *list1, PRelocEntry *list2,
+ Boolean Add);
+
+extern void InvertRelocs(PRelocEntry *erg, PRelocEntry *src);
+
+extern void FreeRelocs(PRelocEntry *list);
+
+extern PRelocEntry DupRelocs(PRelocEntry src);
+
+extern void SetRelocs(PRelocEntry List);
diff --git a/asmsub.c b/asmsub.c
new file mode 100644
index 0000000..2569d95
--- /dev/null
+++ b/asmsub.c
@@ -0,0 +1,1526 @@
+/* asmsub.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Unterfunktionen, vermischtes */
+/* */
+/* Historie: 4. 5.1996 Grundsteinlegung */
+/* 13. 8.1997 KillBlanks-Funktionen nach stringutil.c geschoben */
+/* 26. 6.1998 Fehlermeldung Codepage nicht gefunden */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 17. 8.1998 Unterfunktion zur Buchhaltung Adressbereiche */
+/* 1. 9.1998 FloatString behandelte Sonderwerte nicht korrekt */
+/* 13. 9.1998 Prozessorliste macht Zeilenvorschub nach 6 Namen */
+/* 14.10.1998 Fehlerzeilen mit > > > */
+/* 30. 1.1999 Formatstrings maschinenunabhaengig gemacht */
+/* 18. 4.1999 Ausgabeliste Sharefiles */
+/* 13. 7.1999 Fehlermeldungen relokatible Symbole */
+/* 13. 9.1999 I/O-Fehler 25 ignorieren */
+/* 5.11.1999 ExtendErrors ist jetzt ShortInt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "version.h"
+#include "endian.h"
+#include "stdhandl.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "as.rsc"
+#include "strutil.h"
+#include "stringlists.h"
+#include "chunks.h"
+#include "ioerrs.h"
+#include "asmdef.h"
+#include "asmpars.h"
+#include "asmdebug.h"
+#include "as.h"
+
+#include "asmsub.h"
+
+
+#ifdef __TURBOC__
+#ifdef __DPMI16__
+#define STKSIZE 40960
+#else
+#define STKSIZE 49152
+#endif
+#endif
+
+
+Word ErrorCount,WarnCount;
+static StringList CopyrightList, OutList, ShareOutList;
+
+static LongWord StartStack,MinStack,LowStack;
+
+/****************************************************************************/
+/* Modulinitialisierung */
+
+ void AsmSubInit(void)
+BEGIN
+ PageLength=60; PageWidth=0;
+ ErrorCount=0; WarnCount=0;
+END
+
+/****************************************************************************/
+/* neuen Prozessor definieren */
+
+ CPUVar AddCPU(char *NewName, TSwitchProc Switcher)
+BEGIN
+ PCPUDef Lauf,Neu;
+ char *p;
+
+ Neu=(PCPUDef) malloc(sizeof(TCPUDef));
+ Neu->Name=strdup(NewName);
+ /* kein UpString, weil noch nicht initialisiert ! */
+ for (p=Neu->Name; *p!='\0'; p++) *p=toupper(*p);
+ Neu->SwitchProc=Switcher;
+ Neu->Next=Nil;
+ Neu->Number=Neu->Orig=CPUCnt;
+
+ Lauf=FirstCPUDef;
+ if (Lauf==Nil) FirstCPUDef=Neu;
+ else
+ BEGIN
+ while (Lauf->Next!=Nil) Lauf=Lauf->Next;
+ Lauf->Next=Neu;
+ END
+
+ return CPUCnt++;
+END
+
+ Boolean AddCPUAlias(char *OrigName, char *AliasName)
+BEGIN
+ PCPUDef Lauf=FirstCPUDef,Neu;
+
+ while ((Lauf!=Nil) AND (strcmp(Lauf->Name,OrigName)!=0)) Lauf=Lauf->Next;
+
+ if (Lauf==Nil) return False;
+ else
+ BEGIN
+ Neu=(PCPUDef) malloc(sizeof(TCPUDef));
+ Neu->Next=Nil;
+ Neu->Name=strdup(AliasName);
+ Neu->Number=CPUCnt++;
+ Neu->Orig=Lauf->Orig;
+ Neu->SwitchProc=Lauf->SwitchProc;
+ while (Lauf->Next!=Nil) Lauf=Lauf->Next;
+ Lauf->Next=Neu;
+ return True;
+ END
+END
+
+ void PrintCPUList(TSwitchProc NxtProc)
+BEGIN
+ PCPUDef Lauf;
+ TSwitchProc Proc;
+ int cnt;
+
+ Lauf=FirstCPUDef; Proc=NullProc; cnt=0;
+ while (Lauf!=Nil)
+ BEGIN
+ if (Lauf->Number==Lauf->Orig)
+ BEGIN
+ if ((Lauf->SwitchProc!=Proc) OR (cnt==7))
+ BEGIN
+ Proc=Lauf->SwitchProc; printf("\n"); NxtProc(); cnt=0;
+ END
+ printf("%-10s",Lauf->Name); cnt++;
+ END
+ Lauf=Lauf->Next;
+ END
+ printf("\n"); NxtProc();
+END
+
+ void ClearCPUList(void)
+BEGIN
+ PCPUDef Save;
+
+ while (FirstCPUDef!=Nil)
+ BEGIN
+ Save=FirstCPUDef; FirstCPUDef=Save->Next;
+ free(Save->Name); free(Save);
+ END
+END
+
+/****************************************************************************/
+/* Copyrightlistenverwaltung */
+
+ void AddCopyright(char *NewLine)
+BEGIN
+ AddStringListLast(&CopyrightList,NewLine);
+END
+
+ void WriteCopyrights(TSwitchProc NxtProc)
+BEGIN
+ StringRecPtr Lauf;
+
+ if (NOT StringListEmpty(CopyrightList))
+ BEGIN
+ printf("%s\n",GetStringListFirst(CopyrightList,&Lauf)); NxtProc();
+ while (Lauf!=Nil)
+ BEGIN
+ printf("%s\n",GetStringListNext(&Lauf)); NxtProc();
+ END
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+/* ermittelt das erste/letzte Auftauchen eines Zeichens ausserhalb */
+/* "geschuetzten" Bereichen */
+
+#if 0
+ char *QuotPos(char *s, char Zeichen)
+BEGIN
+ register int Cnt=0;
+ register char *i;
+ register char ch,Cmp2,Cmp3;
+
+ for (i=s; (ch=*i)!='\0'; i++)
+ if (Cnt==0)
+ BEGIN
+ if (ch==Zeichen) return i;
+ else switch (ch)
+ BEGIN
+ case '"':
+ case '\'': Cmp2='\0'; Cmp3=ch; Cnt=1; break;
+ case '(': Cmp2='('; Cmp3=')'; Cnt=1; break;
+ case '[': Cmp2='['; Cmp3=']'; Cnt=1; break;
+ END
+ END
+ else
+ BEGIN
+ if (ch==Cmp2) Cnt++;
+ else if (ch==Cmp3) Cnt--;
+ END
+
+ return Nil;
+END
+#else
+ char *QuotPos(char *s, char Zeichen)
+BEGIN
+ register ShortInt Brack=0,AngBrack=0;
+ register char *i;
+ register LongWord Flag=0;
+ static Boolean First=True,Imp[256],Save;
+
+ if (First)
+ BEGIN
+ memset(Imp,False,256);
+ Imp['"']=Imp['\'']=Imp['(']=Imp[')']=Imp['[']=Imp[']']=True;
+ First=False;
+ END
+
+ Save=Imp[(unsigned char)Zeichen]; Imp[(unsigned char)Zeichen]=True;
+ for (i=s; *i!='\0'; i++)
+ if (Imp[(unsigned char)*i])
+ BEGIN
+ if (*i==Zeichen)
+ BEGIN
+ if ((AngBrack|Brack|Flag)==0)
+ { Imp[(unsigned char)Zeichen]=Save; return i;}
+ END
+ else switch(*i)
+ BEGIN
+ case '"': if (((Brack|AngBrack)==0) AND ((Flag&2)==0)) Flag^=1; break;
+ case '\'':if (((Brack|AngBrack)==0) AND ((Flag&1)==0)) Flag^=2; break;
+ case '(': if ((AngBrack|Flag)==0) Brack++; break;
+ case ')': if ((AngBrack|Flag)==0) Brack--; break;
+ case '[': if ((Brack|Flag)==0) AngBrack++; break;
+ case ']': if ((Brack|Flag)==0) AngBrack--; break;
+ END
+ END
+
+ Imp[(unsigned char)Zeichen]=Save; return Nil;
+END
+#endif
+ char *RQuotPos(char *s, char Zeichen)
+BEGIN
+ ShortInt Brack=0,AngBrack=0;
+ char *i;
+ Boolean Quot=False,Paren=False;
+
+ for (i=s+strlen(s)-1; i>=s; i--)
+ if (*i==Zeichen)
+ BEGIN
+ if ((AngBrack==0) AND (Brack==0) AND (NOT Paren) AND (NOT Quot)) return i;
+ END
+ else switch (*i)
+ BEGIN
+ case '"': if ((Brack==0) AND (AngBrack==0) AND (NOT Quot)) Paren=NOT Paren; break;
+ case '\'':if ((Brack==0) AND (AngBrack==0) AND (NOT Paren)) Quot=NOT Quot; break;
+ case ')': if ((AngBrack==0) AND (NOT Paren) AND (NOT Quot)) Brack++; break;
+ case '(': if ((AngBrack==0) AND (NOT Paren) AND (NOT Quot)) Brack--; break;
+ case ']': if ((Brack==0) AND (NOT Paren) AND (NOT Quot)) AngBrack++; break;
+ case '[': if ((Brack==0) AND (NOT Paren) AND (NOT Quot)) AngBrack--; break;
+ END
+
+ return Nil;
+END
+
+/*--------------------------------------------------------------------------*/
+/* ermittelt das erste Leerzeichen in einem String */
+
+ char *FirstBlank(char *s)
+BEGIN
+ char *h,*Min=Nil;
+
+ h=strchr(s,' ');
+ if (h!=Nil) if ((Min==Nil) OR (h<Min)) Min=h;
+ h=strchr(s,Char_HT);
+ if (h!=Nil) if ((Min==Nil) OR (h<Min)) Min=h;
+ return Min;
+END
+
+/*--------------------------------------------------------------------------*/
+/* einen String in zwei Teile zerlegen */
+
+ void SplitString(char *Source, char *Left, char *Right, char *Trenner)
+BEGIN
+ char Save;
+ LongInt slen=strlen(Source);
+
+ if ((Trenner==Nil) OR (Trenner>=Source+slen))
+ Trenner=Source+slen;
+ Save=(*Trenner); *Trenner='\0';
+ strcpy(Left,Source); *Trenner=Save;
+ if (Trenner>=Source+slen) *Right='\0';
+ else strcpy(Right,Trenner+1);
+END
+
+/*--------------------------------------------------------------------------*/
+/* verbesserte Grossbuchstabenfunktion */
+
+/* einen String in Grossbuchstaben umwandeln. Dabei Stringkonstanten in Ruhe */
+/* lassen */
+
+ void UpString(char *s)
+BEGIN
+ char *z;
+ int hypquot=0;
+
+ for (z=s; *z!='\0'; z++)
+ BEGIN
+ if ((*z=='\'') AND ((hypquot&2)==0)) hypquot^=1;
+ else if ((*z=='"') AND ((hypquot&1)==0)) hypquot^=2;
+ else if (hypquot==0) *z=UpCaseTable[(int)*z];
+ END
+END
+
+/****************************************************************************/
+
+ void TranslateString(char *s)
+BEGIN
+ char *z;
+
+ for (z=s; *z!='\0'; z++) *z=CharTransTable[((usint)(*z))&0xff];
+END
+
+ ShortInt StrCmp(char *s1, char *s2, LongInt Hand1, LongInt Hand2)
+BEGIN
+ int tmp;
+
+ tmp=(*s1)-(*s2);
+ if (tmp==0) tmp=strcmp(s1,s2);
+ if (tmp==0) tmp=Hand1-Hand2;
+ if (tmp<0) return -1;
+ if (tmp>0) return 1;
+ return 0;
+END
+
+/****************************************************************************/
+/* an einen Dateinamen eine Endung anhaengen */
+
+ void AddSuffix(char *s, char *Suff)
+BEGIN
+ char *p,*z,*Part;
+
+ p=Nil;
+ for (z=s; *z!='\0'; z++) if (*z=='\\') p=z;
+ Part=(p!=Nil)?(p):(s);
+ if (strchr(Part,'.')==Nil) strmaxcat(s,Suff,255);
+END
+
+
+/*--------------------------------------------------------------------------*/
+/* von einem Dateinamen die Endung loeschen */
+
+ void KillSuffix(char *s)
+BEGIN
+ char *p,*z,*Part;
+
+ p=Nil;
+ for (z=s; *z!='\0'; z++) if (*z=='\\') p=z;
+ Part=(p!=Nil)?(p):(s); Part=strchr(Part,'.');
+ if (Part!=Nil) *Part='\0';
+END
+
+/*--------------------------------------------------------------------------*/
+/* Pfadanteil (Laufwerk+Verzeichnis) von einem Dateinamen abspalten */
+
+ char *PathPart(char *Name)
+BEGIN
+ static String s;
+ char *p;
+
+ strmaxcpy(s,Name,255);
+
+ p=strrchr(Name,PATHSEP);
+#ifdef DRSEP
+ if (p==Nil) p=strrchr(Name,DRSEP);
+#endif
+
+ if (p==Nil) *s='\0'; else s[1]='\0';
+
+ return s;
+END
+
+/*--------------------------------------------------------------------------*/
+/* Namensanteil von einem Dateinamen abspalten */
+
+ char *NamePart(char *Name)
+BEGIN
+ char *p=strrchr(Name,PATHSEP);
+
+#ifdef DRSEP
+ if (p==Nil) p=strrchr(Name,DRSEP);
+#endif
+
+ return (p==Nil)?(Name):(p+1);
+END
+
+/****************************************************************************/
+/* eine Gleitkommazahl in einen String umwandeln */
+
+ char *FloatString(Double f)
+BEGIN
+#define MaxLen 18
+ static String s;
+ char *p,*d;
+ sint n,ExpVal,nzeroes;
+ Boolean WithE,OK;
+
+ /* 1. mit Maximallaenge wandeln, fuehrendes Vorzeichen weg */
+
+ sprintf(s,"%27.15e",f);
+ for (p=s; (*p==' ') OR (*p=='+'); p++);
+ if (p!=s) strcpy(s,p);
+
+ /* 2. Exponenten soweit als moeglich kuerzen, evtl. ganz streichen */
+
+ p=strchr(s,'e');
+ if (p==Nil) return s;
+ switch (*(++p))
+ BEGIN
+ case '+': strcpy(p,p+1); break;
+ case '-': p++; break;
+ END
+
+ while (*p=='0') strcpy(p,p+1);
+ WithE=(*p!='\0');
+ if (NOT WithE) s[strlen(s)-1]='\0';
+
+ /* 3. Nullen am Ende der Mantisse entfernen, Komma bleibt noch */
+
+ if (WithE) p=strchr(s,'e'); else p=s+strlen(s); p--;
+ while (*p=='0')
+ BEGIN
+ strcpy(p,p+1); p--;
+ END
+
+ /* 4. auf die gewuenschte Maximalstellenzahl begrenzen */
+
+ if (WithE) p=strchr(s,'e'); else p=s+strlen(s);
+ d=strchr(s,'.');
+ n=p-d-1;
+
+ /* 5. Maximallaenge ueberschritten ? */
+
+ if (strlen(s)>MaxLen) strcpy(d+(n-(strlen(s)-MaxLen)),d+n);
+
+ /* 6. Exponentenwert berechnen */
+
+ if (WithE)
+ BEGIN
+ p=strchr(s,'e');
+ ExpVal=ConstLongInt(p+1,&OK);
+ END
+ else
+ BEGIN
+ p=s+strlen(s);
+ ExpVal=0;
+ END
+
+ /* 7. soviel Platz, dass wir den Exponenten weglassen und evtl. Nullen
+ anhaengen koennen ? */
+
+ if (ExpVal>0)
+ BEGIN
+ nzeroes=ExpVal-(p-strchr(s,'.')-1); /* = Zahl von Nullen, die anzuhaengen waere */
+
+ /* 7a. nur Kommaverschiebung erforderlich. Exponenten loeschen und
+ evtl. auch Komma */
+
+ if (nzeroes<=0)
+ BEGIN
+ *p='\0';
+ d=strchr(s,'.'); strcpy(d,d+1);
+ if (nzeroes!=0)
+ BEGIN
+ memmove(s+strlen(s)+nzeroes+1,s+strlen(s)+nzeroes,-nzeroes);
+ s[strlen(s)-1+nzeroes]='.';
+ END
+ END
+
+ /* 7b. Es muessen Nullen angehaengt werden. Schauen, ob nach Loeschen von
+ Punkt und E-Teil genuegend Platz ist */
+
+ else
+ BEGIN
+ n=strlen(p)+1+(MaxLen-strlen(s)); /* = Anzahl freizubekommender Zeichen+Gutschrift */
+ if (n>=nzeroes)
+ BEGIN
+ *p='\0'; d=strchr(s,'.'); strcpy(d,d+1);
+ d=s+strlen(s);
+ for (n=0; n<nzeroes; n++) *(d++)='0'; *d='\0';
+ END
+ END
+ END
+
+ /* 8. soviel Platz, dass Exponent wegkann und die Zahl mit vielen Nullen
+ vorne geschrieben werden kann ? */
+
+ else if (ExpVal<0)
+ BEGIN
+ n=(-ExpVal)-(strlen(p)); /* = Verlaengerung nach Operation */
+ if (strlen(s)+n<=MaxLen)
+ BEGIN
+ *p='\0'; d=strchr(s,'.'); strcpy(d,d+1);
+ if (s[0]=='-') d=s+1; else d=s;
+ memmove(d-ExpVal+1,d,strlen(s)+1);
+ *(d++)='0'; *(d++)='.';
+ for (n=0; n<-ExpVal-1; n++) *(d++)='0';
+ END
+ END
+
+
+ /* 9. Ueberfluessiges Komma entfernen */
+
+ if (WithE)
+ BEGIN
+ p=strchr(s,'e'); if (p!=Nil) *p='E';
+ END
+ else p=s+strlen(s);
+ if ((p!=Nil) AND (*(p-1)=='.')) strcpy(p-1,p);
+
+ return s;
+END
+
+/****************************************************************************/
+/* Symbol in String wandeln */
+
+ void StrSym(TempResult *t, Boolean WithSystem, char *Dest)
+BEGIN
+ switch (t->Typ)
+ BEGIN
+ case TempInt:
+ strcpy(Dest,HexString(t->Contents.Int,1));
+ if (WithSystem)
+ switch (ConstMode)
+ BEGIN
+ case ConstModeIntel : strcat(Dest,"H"); break;
+ case ConstModeMoto : strprep(Dest,"$"); break;
+ case ConstModeC : strprep(Dest,"0x"); break;
+ END
+ break;
+ case TempFloat:
+ strcpy(Dest,FloatString(t->Contents.Float)); break;
+ case TempString:
+ strcpy(Dest,t->Contents.Ascii); break;
+ default: strcpy(Dest,"???");
+ END
+END
+
+/****************************************************************************/
+/* Listingzaehler zuruecksetzen */
+
+ void ResetPageCounter(void)
+BEGIN
+ int z;
+
+ for (z=0; z<=ChapMax; z++) PageCounter[z]=0;
+ LstCounter=0; ChapDepth=0;
+END
+
+/*--------------------------------------------------------------------------*/
+/* eine neue Seite im Listing beginnen */
+
+ void NewPage(ShortInt Level, Boolean WithFF)
+BEGIN
+ ShortInt z;
+ String Header,s;
+ char Save;
+
+ if (ListOn==0) return;
+
+ LstCounter=0;
+
+ if (ChapDepth<(Byte) Level)
+ BEGIN
+ memmove(PageCounter+(Level-ChapDepth),PageCounter,(ChapDepth+1)*sizeof(Word));
+ for (z=0; z<=Level-ChapDepth; PageCounter[z++]=1);
+ ChapDepth=Level;
+ END
+ for (z=0; z<=Level-1; PageCounter[z++]=1);
+ PageCounter[Level]++;
+
+ if (WithFF)
+ BEGIN
+ errno=0; fprintf(LstFile,"%c",Char_FF); ChkIO(10002);
+ END
+
+ sprintf(Header," AS V%s%s%s",Version,getmessage(Num_HeadingFileNameLab),NamePart(SourceFile));
+ if ((strcmp(CurrFileName,"INTERNAL")!=0) AND (strcmp(NamePart(CurrFileName),NamePart(SourceFile))!=0))
+ BEGIN
+ strmaxcat(Header,"(",255);
+ strmaxcat(Header,NamePart(CurrFileName),255);
+ strmaxcat(Header,")",255);
+ END
+ strmaxcat(Header,getmessage(Num_HeadingPageLab),255);
+
+ for (z=ChapDepth; z>=0; z--)
+ BEGIN
+ sprintf(s, IntegerFormat, PageCounter[z]);
+ strmaxcat(Header,s,255);
+ if (z!=0) strmaxcat(Header,".",255);
+ END
+
+ strmaxcat(Header," - ",255);
+ NLS_CurrDateString(s); strmaxcat(Header,s,255);
+ strmaxcat(Header," ",255);
+ NLS_CurrTimeString(False,s); strmaxcat(Header,s,255);
+
+ if (PageWidth!=0)
+ while (strlen(Header)>PageWidth)
+ BEGIN
+ Save=Header[PageWidth]; Header[PageWidth]='\0';
+ errno=0; fprintf(LstFile,"%s\n",Header); ChkIO(10002);
+ Header[PageWidth]=Save; strcpy(Header,Header+PageWidth);
+ END
+ errno=0; fprintf(LstFile,"%s\n",Header); ChkIO(10002);
+
+ if (PrtTitleString[0]!='\0')
+ BEGIN
+ errno=0; fprintf(LstFile,"%s\n",PrtTitleString); ChkIO(10002);
+ END
+
+ errno=0; fprintf(LstFile,"\n\n"); ChkIO(10002);
+END
+
+
+/*--------------------------------------------------------------------------*/
+/* eine Zeile ins Listing schieben */
+
+ void WrLstLine(char *Line)
+BEGIN
+ int LLength;
+ char bbuf[2500];
+ String LLine;
+ int blen=0,hlen,z,Start;
+
+ if (ListOn==0) return;
+
+ if (PageLength==0)
+ BEGIN
+ errno=0; fprintf(LstFile,"%s\n",Line); ChkIO(10002);
+ END
+ else
+ BEGIN
+ if ((PageWidth==0) OR ((strlen(Line)<<3)<PageWidth)) LLength=1;
+ else
+ BEGIN
+ blen=0;
+ for (z=0; z<strlen(Line); z++)
+ if (Line[z]==Char_HT)
+ BEGIN
+ memset(bbuf+blen,8-(blen&7),' ');
+ blen+=8-(blen&7);
+ END
+ else bbuf[blen++]=Line[z];
+ LLength=blen/PageWidth; if (blen%PageWidth!=0) LLength++;
+ END
+ if (LLength==1)
+ BEGIN
+ errno=0; fprintf(LstFile,"%s\n",Line); ChkIO(10002);
+ if ((++LstCounter)==PageLength) NewPage(0,True);
+ END
+ else
+ BEGIN
+ Start=0;
+ for (z=1; z<=LLength; z++)
+ BEGIN
+ hlen=PageWidth; if (blen-Start<hlen) hlen=blen-Start;
+ memcpy(LLine,bbuf+Start,hlen); LLine[hlen]='\0';
+ errno=0; fprintf(LstFile,"%s\n",LLine);
+ if ((++LstCounter)==PageLength) NewPage(0,True);
+ Start+=hlen;
+ END
+ END
+ END
+END
+
+/*****************************************************************************/
+/* Ausdruck in Spalte vor Listing */
+
+
+ void SetListLineVal(TempResult *t)
+BEGIN
+ StrSym(t,True,ListLine); strmaxprep(ListLine,"=",255);
+ if (strlen(ListLine)>14)
+ BEGIN
+ ListLine[12]='\0'; strmaxcat(ListLine,"..",255);
+ END
+END
+
+/****************************************************************************/
+/* einen Symbolnamen auf Gueltigkeit ueberpruefen */
+
+ Boolean ChkSymbName(char *sym)
+BEGIN
+ char *z;
+
+ if (*sym=='\0') return False;
+ if (NOT (isalpha((unsigned int) *sym) OR (*sym=='_') OR (*sym=='.'))) return False;
+ for (z=sym; *z!='\0'; z++)
+ if (NOT (isalnum((unsigned int) *z) OR (*z=='_') OR (*z=='.'))) return False;
+ return True;
+END
+
+ Boolean ChkMacSymbName(char *sym)
+BEGIN
+ char *z;
+
+ if (*sym=='\0') return False;
+ if (NOT isalpha((unsigned int) *sym)) return False;
+ for (z=sym; *z!='\0'; z++)
+ if (NOT isalnum((unsigned int) *z)) return False;
+ return True;
+END
+
+/****************************************************************************/
+/* Fehlerkanal offen ? */
+
+ static void ForceErrorOpen(void)
+BEGIN
+ if (NOT IsErrorOpen)
+ BEGIN
+ RewriteStandard(&ErrorFile,ErrorName); IsErrorOpen=True;
+ if (ErrorFile==Nil) ChkIO(10001);
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+/* eine Fehlermeldung mit Klartext ausgeben */
+
+ static void EmergencyStop(void)
+BEGIN
+ if ((IsErrorOpen) AND (ErrorFile!=Nil)) fclose(ErrorFile);
+ fclose(LstFile);
+ if (ShareMode!=0)
+ BEGIN
+ fclose(ShareFile); unlink(ShareName);
+ END
+ if (MacProOutput)
+ BEGIN
+ fclose(MacProFile); unlink(MacProName);
+ END
+ if (MacroOutput)
+ BEGIN
+ fclose(MacroFile); unlink(MacroName);
+ END
+ if (MakeDebug) fclose(Debug);
+ if (CodeOutput)
+ BEGIN
+ fclose(PrgFile); unlink(OutName);
+ END
+END
+
+ void WrErrorString(char *Message, char *Add, Boolean Warning, Boolean Fatal)
+BEGIN
+ String h,h2;
+ char *p;
+ FILE *errfile;
+
+ strcpy(h,"> > >");
+ strmaxcat(h,p=GetErrorPos(),255); free(p);
+ if (NOT Warning)
+ BEGIN
+ strmaxcat(h,getmessage(Num_ErrName),255);
+ strmaxcat(h,Add,255);
+ strmaxcat(h,": ",255);
+ ErrorCount++;
+ END
+ else
+ BEGIN
+ strmaxcat(h,getmessage(Num_WarnName),255);
+ strmaxcat(h,Add,255);
+ strmaxcat(h,": ",255);
+ WarnCount++;
+ END
+
+ if ((strcmp(LstName, "/dev/null") != 0) AND (NOT Fatal))
+ BEGIN
+ strmaxcpy(h2, h, 255); strmaxcat(h2, Message, 255); WrLstLine(h2);
+ if ((ExtendErrors > 0) AND (*ExtendError != '\0'))
+ BEGIN
+ sprintf(h2, "> > > %s", ExtendError); WrLstLine(h2);
+ END
+ if (ExtendErrors > 1)
+ BEGIN
+ sprintf(h2, "> > > %s", OneLine); WrLstLine(h2);
+ END
+ END
+
+ ForceErrorOpen();
+ if ((strcmp(LstName, "!1")!=0) OR (Fatal))
+ BEGIN
+ errfile = (ErrorFile == Nil) ? stdout : ErrorFile;
+ fprintf(errfile, "%s%s%s\n", h, Message, ClrEol);
+ if ((ExtendErrors > 0) AND (*ExtendError != '\0'))
+ fprintf(errfile, "> > > %s%s\n", ExtendError, ClrEol);
+ if (ExtendErrors > 1)
+ fprintf(errfile, "> > > %s%s\n", OneLine, ClrEol);
+ END
+ *ExtendError = '\0';
+
+ if (Fatal)
+ BEGIN
+ fprintf((ErrorFile==Nil)?stdout:ErrorFile,"%s\n",getmessage(Num_ErrMsgIsFatal));
+ EmergencyStop();
+ exit(3);
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+/* eine Fehlermeldung ueber Code ausgeben */
+
+ static void WrErrorNum(Word Num)
+BEGIN
+ String h;
+ char Add[11];
+ int msgno;
+
+ if ((NOT CodeOutput) AND (Num==1200)) return;
+
+ if ((SuppWarns) AND (Num<1000)) return;
+
+ switch (Num)
+ BEGIN
+ case 0: msgno=Num_ErrMsgUselessDisp; break;
+ case 10: msgno=Num_ErrMsgShortAddrPossible; break;
+ case 20: msgno=Num_ErrMsgShortJumpPossible; break;
+ case 30: msgno=Num_ErrMsgNoShareFile; break;
+ case 40: msgno=Num_ErrMsgBigDecFloat; break;
+ case 50: msgno=Num_ErrMsgPrivOrder; break;
+ case 60: msgno=Num_ErrMsgDistNull; break;
+ case 70: msgno=Num_ErrMsgWrongSegment; break;
+ case 75: msgno=Num_ErrMsgInAccSegment; break;
+ case 80: msgno=Num_ErrMsgPhaseErr; break;
+ case 90: msgno=Num_ErrMsgOverlap; break;
+ case 100: msgno=Num_ErrMsgNoCaseHit; break;
+ case 110: msgno=Num_ErrMsgInAccPage; break;
+ case 120: msgno=Num_ErrMsgRMustBeEven; break;
+ case 130: msgno=Num_ErrMsgObsolete; break;
+ case 140: msgno=Num_ErrMsgUnpredictable; break;
+ case 150: msgno=Num_ErrMsgAlphaNoSense; break;
+ case 160: msgno=Num_ErrMsgSenseless; break;
+ case 170: msgno=Num_ErrMsgRepassUnknown; break;
+ case 180: msgno=Num_ErrMsgAddrNotAligned; break;
+ case 190: msgno=Num_ErrMsgIOAddrNotAllowed; break;
+ case 200: msgno=Num_ErrMsgPipeline; break;
+ case 210: msgno=Num_ErrMsgDoubleAdrRegUse; break;
+ case 220: msgno=Num_ErrMsgNotBitAddressable; break;
+ case 230: msgno=Num_ErrMsgStackNotEmpty; break;
+ case 240: msgno=Num_ErrMsgNULCharacter; break;
+ case 250: msgno=Num_ErrMsgPageCrossing; break;
+ case 260: msgno=Num_ErrMsgWOverRange; break;
+ case 270: msgno=Num_ErrMsgNegDUP; break;
+ case 1000: msgno=Num_ErrMsgDoubleDef; break;
+ case 1010: msgno=Num_ErrMsgSymbolUndef; break;
+ case 1020: msgno=Num_ErrMsgInvSymName; break;
+ case 1090: msgno=Num_ErrMsgInvFormat; break;
+ case 1100: msgno=Num_ErrMsgUseLessAttr; break;
+ case 1105: msgno=Num_ErrMsgTooLongAttr; break;
+ case 1107: msgno=Num_ErrMsgUndefAttr; break;
+ case 1110: msgno=Num_ErrMsgWrongArgCnt; break;
+ case 1115: msgno=Num_ErrMsgWrongOptCnt; break;
+ case 1120: msgno=Num_ErrMsgOnlyImmAddr; break;
+ case 1130: msgno=Num_ErrMsgInvOpsize; break;
+ case 1131: msgno=Num_ErrMsgConfOpSizes; break;
+ case 1132: msgno=Num_ErrMsgUndefOpSizes; break;
+ case 1135: msgno=Num_ErrMsgInvOpType; break;
+ case 1140: msgno=Num_ErrMsgTooMuchArgs; break;
+ case 1150: msgno=Num_ErrMsgNoRelocs; break;
+ case 1155: msgno=Num_ErrMsgUnresRelocs; break;
+ case 1200: msgno=Num_ErrMsgUnknownOpcode; break;
+ case 1300: msgno=Num_ErrMsgBrackErr; break;
+ case 1310: msgno=Num_ErrMsgDivByZero; break;
+ case 1315: msgno=Num_ErrMsgUnderRange; break;
+ case 1320: msgno=Num_ErrMsgOverRange; break;
+ case 1325: msgno=Num_ErrMsgNotAligned; break;
+ case 1330: msgno=Num_ErrMsgDistTooBig; break;
+ case 1335: msgno=Num_ErrMsgInAccReg; break;
+ case 1340: msgno=Num_ErrMsgNoShortAddr; break;
+ case 1350: msgno=Num_ErrMsgInvAddrMode; break;
+ case 1351: msgno=Num_ErrMsgMustBeEven; break;
+ case 1355: msgno=Num_ErrMsgInvParAddrMode; break;
+ case 1360: msgno=Num_ErrMsgUndefCond; break;
+ case 1370: msgno=Num_ErrMsgJmpDistTooBig; break;
+ case 1375: msgno=Num_ErrMsgDistIsOdd; break;
+ case 1380: msgno=Num_ErrMsgInvShiftArg; break;
+ case 1390: msgno=Num_ErrMsgRange18; break;
+ case 1400: msgno=Num_ErrMsgShiftCntTooBig; break;
+ case 1410: msgno=Num_ErrMsgInvRegList; break;
+ case 1420: msgno=Num_ErrMsgInvCmpMode; break;
+ case 1430: msgno=Num_ErrMsgInvCPUType; break;
+ case 1440: msgno=Num_ErrMsgInvCtrlReg; break;
+ case 1445: msgno=Num_ErrMsgInvReg; break;
+ case 1450: msgno=Num_ErrMsgNoSaveFrame; break;
+ case 1460: msgno=Num_ErrMsgNoRestoreFrame; break;
+ case 1465: msgno=Num_ErrMsgUnknownMacArg; break;
+ case 1470: msgno=Num_ErrMsgMissEndif; break;
+ case 1480: msgno=Num_ErrMsgInvIfConst; break;
+ case 1483: msgno=Num_ErrMsgDoubleSection; break;
+ case 1484: msgno=Num_ErrMsgInvSection; break;
+ case 1485: msgno=Num_ErrMsgMissingEndSect; break;
+ case 1486: msgno=Num_ErrMsgWrongEndSect; break;
+ case 1487: msgno=Num_ErrMsgNotInSection; break;
+ case 1488: msgno=Num_ErrMsgUndefdForward; break;
+ case 1489: msgno=Num_ErrMsgContForward; break;
+ case 1490: msgno=Num_ErrMsgInvFuncArgCnt; break;
+ case 1495: msgno=Num_ErrMsgMissingLTORG; break;
+ case 1500: msgno= -1;
+ sprintf(h,"%s%s%s",getmessage(Num_ErrMsgNotOnThisCPU1),
+ MomCPUIdent,getmessage(Num_ErrMsgNotOnThisCPU2));
+ break;
+ case 1505: msgno= -1;
+ sprintf(h,"%s%s%s",getmessage(Num_ErrMsgNotOnThisCPU3),
+ MomCPUIdent,getmessage(Num_ErrMsgNotOnThisCPU2));
+ break;
+ case 1510: msgno=Num_ErrMsgInvBitPos; break;
+ case 1520: msgno=Num_ErrMsgOnlyOnOff; break;
+ case 1530: msgno=Num_ErrMsgStackEmpty; break;
+ case 1540: msgno=Num_ErrMsgNotOneBit; break;
+ case 1550: msgno=Num_ErrMsgMissingStruct; break;
+ case 1551: msgno=Num_ErrMsgOpenStruct; break;
+ case 1552: msgno=Num_ErrMsgWrongStruct; break;
+ case 1553: msgno=Num_ErrMsgPhaseDisallowed; break;
+ case 1554: msgno=Num_ErrMsgInvStructDir; break;
+ case 1600: msgno=Num_ErrMsgShortRead; break;
+ case 1610: msgno=Num_ErrMsgUnknownCodepage; break;
+ case 1700: msgno=Num_ErrMsgRomOffs063; break;
+ case 1710: msgno=Num_ErrMsgInvFCode; break;
+ case 1720: msgno=Num_ErrMsgInvFMask; break;
+ case 1730: msgno=Num_ErrMsgInvMMUReg; break;
+ case 1740: msgno=Num_ErrMsgLevel07; break;
+ case 1750: msgno=Num_ErrMsgInvBitMask; break;
+ case 1760: msgno=Num_ErrMsgInvRegPair; break;
+ case 1800: msgno=Num_ErrMsgOpenMacro; break;
+ case 1805: msgno=Num_ErrMsgEXITMOutsideMacro; break;
+ case 1810: msgno=Num_ErrMsgTooManyMacParams; break;
+ case 1815: msgno=Num_ErrMsgDoubleMacro; break;
+ case 1820: msgno=Num_ErrMsgFirstPassCalc; break;
+ case 1830: msgno=Num_ErrMsgTooManyNestedIfs; break;
+ case 1840: msgno=Num_ErrMsgMissingIf; break;
+ case 1850: msgno=Num_ErrMsgRekMacro; break;
+ case 1860: msgno=Num_ErrMsgUnknownFunc; break;
+ case 1870: msgno=Num_ErrMsgInvFuncArg; break;
+ case 1880: msgno=Num_ErrMsgFloatOverflow; break;
+ case 1890: msgno=Num_ErrMsgInvArgPair; break;
+ case 1900: msgno=Num_ErrMsgNotOnThisAddress; break;
+ case 1905: msgno=Num_ErrMsgNotFromThisAddress; break;
+ case 1910: msgno=Num_ErrMsgTargOnDiffPage; break;
+ case 1920: msgno=Num_ErrMsgCodeOverflow; break;
+ case 1925: msgno=Num_ErrMsgAdrOverflow; break;
+ case 1930: msgno=Num_ErrMsgMixDBDS; break;
+ case 1940: msgno=Num_ErrMsgNotInStruct; break;
+ case 1950: msgno=Num_ErrMsgParNotPossible; break;
+ case 1960: msgno=Num_ErrMsgInvSegment; break;
+ case 1961: msgno=Num_ErrMsgUnknownSegment; break;
+ case 1962: msgno=Num_ErrMsgUnknownSegReg; break;
+ case 1970: msgno=Num_ErrMsgInvString; break;
+ case 1980: msgno=Num_ErrMsgInvRegName; break;
+ case 1985: msgno=Num_ErrMsgInvArg; break;
+ case 1990: msgno=Num_ErrMsgNoIndir; break;
+ case 1995: msgno=Num_ErrMsgNotInThisSegment; break;
+ case 1996: msgno=Num_ErrMsgNotInMaxmode; break;
+ case 1997: msgno=Num_ErrMsgOnlyInMaxmode; break;
+ case 10001: msgno=Num_ErrMsgOpeningFile; break;
+ case 10002: msgno=Num_ErrMsgListWrError; break;
+ case 10003: msgno=Num_ErrMsgFileReadError; break;
+ case 10004: msgno=Num_ErrMsgFileWriteError; break;
+ case 10006: msgno=Num_ErrMsgHeapOvfl; break;
+ case 10007: msgno=Num_ErrMsgStackOvfl; break;
+ default : msgno= -1;
+ sprintf(h,"%s %d",getmessage(Num_ErrMsgIntError),(int) Num);
+ END
+ if (msgno!=-1) strmaxcpy(h,getmessage(msgno),255);
+
+ if (((Num==1910) OR (Num==1370)) AND (NOT Repass)) JmpErrors++;
+
+ if (NumericErrors) sprintf(Add,"#%d", (int)Num);
+ else *Add='\0';
+ WrErrorString(h,Add,Num<1000,Num>=10000);
+END
+
+ void WrError(Word Num)
+BEGIN
+ *ExtendError='\0'; WrErrorNum(Num);
+END
+
+ void WrXError(Word Num, char *Message)
+BEGIN
+ strmaxcpy(ExtendError,Message,255); WrErrorNum(Num);
+END
+
+/*--------------------------------------------------------------------------*/
+/* I/O-Fehler */
+
+ void ChkIO(Word ErrNo)
+BEGIN
+ int io;
+
+ io=errno; if ((io == 0) OR (io == 19) OR (io == 25)) return;
+
+ WrXError(ErrNo,GetErrorMsg(io));
+END
+
+/*--------------------------------------------------------------------------*/
+/* Bereichsfehler */
+
+ Boolean ChkRange(LargeInt Value, LargeInt Min, LargeInt Max)
+BEGIN
+ char s1[100],s2[100];
+
+ if (Value<Min)
+ BEGIN
+ strmaxcpy(s1,LargeString(Value),99);
+ strmaxcpy(s2,LargeString(Min),99);
+ strmaxcat(s1,"<",99); strmaxcat(s1,s2,99);
+ WrXError(1315,s1); return False;
+ END
+ else if (Value>Max)
+ BEGIN
+ strmaxcpy(s1,LargeString(Value),99);
+ strmaxcpy(s2,LargeString(Max),99);
+ strmaxcat(s1,">",99); strmaxcat(s1,s2,99);
+ WrXError(1320,s1); return False;
+ END
+ else return True;
+END
+
+/****************************************************************************/
+
+ LargeWord ProgCounter(void)
+BEGIN
+ return PCs[ActPC];
+END
+
+/*--------------------------------------------------------------------------*/
+/* aktuellen Programmzaehler mit Phasenverschiebung holen */
+
+ LargeWord EProgCounter(void)
+BEGIN
+ return PCs[ActPC]+Phases[ActPC];
+END
+
+
+/*--------------------------------------------------------------------------*/
+/* Granularitaet des aktuellen Segments holen */
+
+ Word Granularity(void)
+BEGIN
+ return Grans[ActPC];
+END
+
+/*--------------------------------------------------------------------------*/
+/* Linstingbreite des aktuellen Segments holen */
+
+ Word ListGran(void)
+BEGIN
+ return ListGrans[ActPC];
+END
+
+/*--------------------------------------------------------------------------*/
+/* pruefen, ob alle Symbole einer Formel im korrekten Adressraum lagen */
+
+ void ChkSpace(Byte Space)
+BEGIN
+ Byte Mask=0xff-(1<<Space);
+
+ if ((TypeFlag&Mask)!=0) WrError(70);
+END
+
+/****************************************************************************/
+/* eine Chunkliste im Listing ausgeben & Speicher loeschen */
+
+ void PrintChunk(ChunkList *NChunk)
+BEGIN
+ LargeWord NewMin,FMin;
+ Boolean Found;
+ Word p=0,z;
+ int BufferZ;
+ String BufferS;
+
+ NewMin=0; BufferZ=0; *BufferS='\0';
+
+ do
+ BEGIN
+ /* niedrigsten Start finden, der ueberhalb des letzten Endes liegt */
+ Found=False;
+#ifdef __STDC__
+ FMin=0xffffffffu;
+#else
+ FMin=0xffffffff;
+#endif
+ for (z=0; z<NChunk->RealLen; z++)
+ if (NChunk->Chunks[z].Start>=NewMin)
+ if (FMin>NChunk->Chunks[z].Start)
+ BEGIN
+ Found=True; FMin=NChunk->Chunks[z].Start; p=z;
+ END
+
+ if (Found)
+ BEGIN
+ strmaxcat(BufferS,HexString(NChunk->Chunks[p].Start,0),255);
+ if (NChunk->Chunks[p].Length!=1)
+ BEGIN
+ strmaxcat(BufferS,"-",255);
+ strmaxcat(BufferS,HexString(NChunk->Chunks[p].Start+NChunk->Chunks[p].Length-1,0),255);
+ END
+ strmaxcat(BufferS,Blanks(19-strlen(BufferS)%19),255);
+ if (++BufferZ==4)
+ BEGIN
+ WrLstLine(BufferS); *BufferS='\0'; BufferZ=0;
+ END
+ NewMin=NChunk->Chunks[p].Start+NChunk->Chunks[p].Length;
+ END
+ END
+ while (Found);
+
+ if (BufferZ!=0) WrLstLine(BufferS);
+END
+
+/*--------------------------------------------------------------------------*/
+/* Listen ausgeben */
+
+ void PrintUseList(void)
+BEGIN
+ int z,z2,l;
+ String s;
+
+ for (z=1; z<=PCMax; z++)
+ if (SegChunks[z].Chunks!=Nil)
+ BEGIN
+ sprintf(s," %s%s%s",getmessage(Num_ListSegListHead1),SegNames[z],
+ getmessage(Num_ListSegListHead2));
+ WrLstLine(s);
+ strcpy(s," ");
+ l=strlen(SegNames[z])+strlen(getmessage(Num_ListSegListHead1))+strlen(getmessage(Num_ListSegListHead2));
+ for (z2=0; z2<l; z2++) strmaxcat(s,"-",255);
+ WrLstLine(s);
+ WrLstLine("");
+ PrintChunk(SegChunks+z);
+ WrLstLine("");
+ END
+END
+
+ void ClearUseList(void)
+BEGIN
+ int z;
+
+ for (z=1; z<=PCMax; z++)
+ ClearChunk(SegChunks+z);
+END
+
+/****************************************************************************/
+/* Include-Pfadlistenverarbeitung */
+
+ static char *GetPath(char *Acc)
+BEGIN
+ char *p;
+ static String tmp;
+
+ p=strchr(Acc,DIRSEP);
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(tmp,Acc,255); Acc[0]='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(tmp,Acc,255); strcpy(Acc,p+1);
+ END
+ return tmp;
+END
+
+ void AddIncludeList(char *NewPath)
+BEGIN
+ String Test;
+
+ strmaxcpy(Test,IncludeList,255);
+ while (*Test!='\0')
+ if (strcmp(GetPath(Test),NewPath)==0) return;
+ if (*IncludeList!='\0') strmaxprep(IncludeList,SDIRSEP,255);
+ strmaxprep(IncludeList,NewPath,255);
+END
+
+
+ void RemoveIncludeList(char *RemPath)
+BEGIN
+ String Save;
+ char *Part;
+
+ strmaxcpy(IncludeList,Save,255); IncludeList[0]='\0';
+ while (Save[0]!='\0')
+ BEGIN
+ Part=GetPath(Save);
+ if (strcmp(Part,RemPath)!=0)
+ BEGIN
+ if (IncludeList[0]!='\0') strmaxcat(IncludeList,SDIRSEP,255);
+ strmaxcat(IncludeList,Part,255);
+ END
+ END
+END
+
+/****************************************************************************/
+/* Liste mit Ausgabedateien */
+
+ void ClearOutList(void)
+BEGIN
+ ClearStringList(&OutList);
+END
+
+ void AddToOutList(char *NewName)
+BEGIN
+ AddStringListLast(&OutList,NewName);
+END
+
+ void RemoveFromOutList(char *OldName)
+BEGIN
+ RemoveStringList(&OutList,OldName);
+END
+
+ char *GetFromOutList(void)
+BEGIN
+ return GetAndCutStringList(&OutList);
+END
+
+ void ClearShareOutList(void)
+BEGIN
+ ClearStringList(&ShareOutList);
+END
+
+ void AddToShareOutList(char *NewName)
+BEGIN
+ AddStringListLast(&ShareOutList,NewName);
+END
+
+ void RemoveFromShareOutList(char *OldName)
+BEGIN
+ RemoveStringList(&ShareOutList,OldName);
+END
+
+ char *GetFromShareOutList(void)
+BEGIN
+ return GetAndCutStringList(&ShareOutList);
+END
+
+/****************************************************************************/
+/* Tokenverarbeitung */
+
+ static Boolean CompressLine_NErl(char ch)
+BEGIN
+ return (((ch>='A') AND (ch<='Z')) OR ((ch>='a') AND (ch<='z')) OR ((ch>='0') AND (ch<='9')));
+END
+
+ void CompressLine(char *TokNam, Byte Num, char *Line)
+BEGIN
+ int z,e,tlen,llen;
+ Boolean SFound;
+
+ z=0; tlen=strlen(TokNam); llen=strlen(Line);
+ while (z<=llen-tlen)
+ BEGIN
+ e=z+strlen(TokNam);
+ SFound=(CaseSensitive) ? (strncmp(Line+z,TokNam,tlen)==0)
+ : (strncasecmp(Line+z,TokNam,tlen)==0);
+ if ( (SFound)
+ AND ((z==0) OR (NOT CompressLine_NErl(Line[z-1])))
+ AND ((e>=strlen(Line)) OR (NOT CompressLine_NErl(Line[e]))) )
+ BEGIN
+ strcpy(Line+z+1,Line+e); Line[z]=Num;
+ llen=strlen(Line);
+ END;
+ z++;
+ END
+END
+
+ void ExpandLine(char *TokNam, Byte Num, char *Line)
+BEGIN
+ char *z;
+
+ do
+ BEGIN
+ z=strchr(Line,Num);
+ if (z!=Nil)
+ BEGIN
+ strcpy(z,z+1);
+ strmaxins(Line,TokNam,z-Line,255);
+ END
+ END
+ while (z!=0);
+END
+
+ void KillCtrl(char *Line)
+BEGIN
+ char *z;
+
+ if (*(z=Line)=='\0') return;
+ do
+ BEGIN
+ if (*z=='\0');
+ else if (*z==Char_HT)
+ BEGIN
+ strcpy(z,z+1);
+ strprep(z,Blanks(8-((z-Line)%8)));
+ END
+ else if ((*z&0xe0)==0) *z=' ';
+ z++;
+ END
+ while (*z!='\0');
+END
+
+/****************************************************************************/
+/* Buchhaltung */
+
+ void BookKeeping(void)
+BEGIN
+ if (MakeUseList)
+ if (AddChunk(SegChunks+ActPC,ProgCounter(),CodeLen,ActPC==SegCode)) WrError(90);
+ if (DebugMode!=DebugNone)
+ BEGIN
+ AddSectionUsage(ProgCounter(),CodeLen);
+ AddLineInfo(InMacroFlag,CurrLine,CurrFileName,ActPC,PCs[ActPC],CodeLen);
+ END
+END
+
+/****************************************************************************/
+/* Differenz zwischen zwei Zeiten mit Jahresueberlauf berechnen */
+
+ long DTime(long t1, long t2)
+BEGIN
+ LongInt d;
+
+ d=t2-t1; if (d<0) d+=(24*360000);
+ return (d>0) ? d : -d;
+END
+
+/*--------------------------------------------------------------------------*/
+/* Zeit holen */
+
+#ifdef __MSDOS__
+
+#include <dos.h>
+
+ long GTime(void)
+BEGIN
+ static unsigned long *tick=MK_FP(0x40,0x6c);
+ double tmp=*tick;
+
+ return ((long) (tmp*5.4931641));
+END
+
+#elif __IBMC__
+
+#include <time.h>
+#define INCL_DOSDATETIME
+#include <os2.h>
+
+ long GTime(void)
+BEGINM
+ DATETIME dt;
+ struct tm ts;
+ DosGetDateTime(&dt);
+ memset(&ts,0,sizeof(ts));
+ ts.tm_year = dt.year-1900;
+ ts.tm_mon = dt.month-1;
+ ts.tm_mday = dt.day;
+ ts.tm_hour = dt.hours;
+ ts.tm_min = dt.minutes;
+ ts.tm_sec = dt.seconds;
+ return (mktime(&ts)*100)+(dt.hundredths);
+END
+
+#else
+
+#include <sys/time.h>
+
+ long GTime(void)
+BEGIN
+ struct timeval tv;
+
+ gettimeofday(&tv,Nil);
+ return (tv.tv_sec*100)+(tv.tv_usec/10000);
+END
+
+#endif
+/**
+{****************************************************************************}
+{ Heapfehler abfedern }
+
+ FUNCTION MyHeapError(Size:Word):Integer;
+ Far;
+ BEGIN
+ IF Size<>0 THEN WrError(10006);
+ MyHeapError:=1;
+END;
+**/
+/*-------------------------------------------------------------------------*/
+/* Stackfehler abfangen - bis auf DOS nur Dummies */
+
+#ifdef __TURBOC__
+#ifdef __DPMI16__
+#else
+unsigned _stklen=STKSIZE;
+unsigned _ovrbuffer=64*48;
+#endif
+#include <malloc.h>
+#endif
+
+ void ChkStack(void)
+BEGIN
+#ifdef __TURBOC__
+ LongWord avail=stackavail();
+ if (avail<MinStack) WrError(10007);
+ if (avail<LowStack) LowStack=avail;
+#endif
+END
+
+ void ResetStack(void)
+BEGIN
+#ifdef __TURBOC__
+ LowStack=stackavail();
+#endif
+END
+
+ LongWord StackRes(void)
+BEGIN
+#ifdef __TURBOC__
+ return LowStack-MinStack;
+#else
+ return 0;
+#endif
+END
+
+#ifdef CKMALLOC
+#undef malloc
+#undef realloc
+
+ void *ckmalloc(size_t s)
+BEGIN
+ void *tmp=malloc(s);
+ if (tmp==NULL) WrError(10006);
+ return tmp;
+END
+
+ void *ckrealloc(void *p, size_t s)
+BEGIN
+ void *tmp=realloc(p,s);
+ if (tmp==NULL) WrError(10006);
+ return tmp;
+END
+#endif
+
+ void asmsub_init(void)
+BEGIN
+ char *CMess=InfoMessCopyright;
+ Word z;
+ LongWord XORVal;
+
+#ifdef __TURBOC__
+#ifdef __MSDOS__
+#ifdef __DPMI16__
+ char *MemFlag,*p;
+ String MemVal,TempName;
+ unsigned long FileLen;
+#else
+ char *envval;
+ int ovrerg;
+#endif
+#endif
+#endif
+
+ for (z=0; z<strlen(CMess); z++)
+ BEGIN
+ XORVal=CMess[z];
+ XORVal=XORVal << (((z+1) % 4)*8);
+ Magic=Magic ^ XORVal;
+ END
+
+ InitStringList(&CopyrightList);
+ InitStringList(&OutList);
+ InitStringList(&ShareOutList);
+
+#ifdef __TURBOC__
+#ifdef __MSDOS__
+#ifdef __DPMI16__
+ /* Fuer DPMI evtl. Swapfile anlegen */
+
+ MemFlag=getenv("ASXSWAP");
+ if (MemFlag!=Nil)
+ BEGIN
+ strmaxcpy(MemVal,MemFlag,255);
+ p=strchr(MemVal,',');
+ if (p==Nil) strcpy(TempName,"ASX.TMP");
+ else
+ BEGIN
+ *p=Nil; strcpy(TempName,MemVal);
+ strcpy(MemVal,p+1);
+ END;
+ KillBlanks(TempName); KillBlanks(MemVal);
+ FileLen=strtol(MemFlag,&p,0);
+ if (*p!='\0')
+ BEGIN
+ fputs(getmessage(Num_ErrMsgInvSwapSize),stderr); exit(4);
+ END;
+ if (MEMinitSwapFile(TempName,FileLen << 20)!=RTM_OK)
+ BEGIN
+ fputs(getmessage(Num_ErrMsgSwapTooBig),stderr); exit(4);
+ END
+ END
+#else
+ /* Bei DOS Auslagerung Overlays in XMS/EMS versuchen */
+
+ envval=getenv("USEXMS");
+ if ((envval!=Nil) AND (toupper(*envval)=='N')) ovrerg=-1;
+ else ovrerg=_OvrInitExt(0,0);
+ if (ovrerg!=0)
+ BEGIN
+ envval=getenv("USEEMS");
+ if ((envval==Nil) OR (toupper(*envval)!='N')) _OvrInitEms(0,0,0);
+ END
+#endif
+#endif
+#endif
+
+#ifdef __TURBOC__
+ StartStack=stackavail(); LowStack=stackavail();
+ MinStack=StartStack-STKSIZE+0x800;
+#else
+ StartStack=LowStack=MinStack=0;
+#endif
+END
+
diff --git a/asmsub.h b/asmsub.h
new file mode 100644
index 0000000..6589e4e
--- /dev/null
+++ b/asmsub.h
@@ -0,0 +1,166 @@
+/* asmsub.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Unterfunktionen, vermischtes */
+/* */
+/* Historie: 4. 5. 1996 Grundsteinlegung */
+/* Historie: 13. 8.1997 KillBlanks-Funktionen nach stringutil.c geschoben */
+/* 17. 8.1998 Unterfunktion zur Buchhaltung Adressbereiche */
+/* 18. 4.1999 Ausgabeliste Sharefiles */
+/* */
+/*****************************************************************************/
+
+typedef void (*TSwitchProc)(
+#ifdef __PROTOS__
+void
+#endif
+);
+
+
+extern Word ErrorCount,WarnCount;
+
+
+extern void AsmSubInit(void);
+
+
+extern long GTime(void);
+
+
+extern CPUVar AddCPU(char *NewName, TSwitchProc Switcher);
+
+extern Boolean AddCPUAlias(char *OrigName, char *AliasName);
+
+extern void PrintCPUList(TSwitchProc NxtProc);
+
+extern void ClearCPUList(void);
+
+
+extern void UpString(char *s);
+
+extern char *QuotPos(char *s, char Zeichen);
+
+extern char *RQuotPos(char *s, char Zeichen);
+
+extern char *FirstBlank(char *s);
+
+extern void SplitString(char *Source, char *Left, char *Right, char *Trenner);
+
+extern void TranslateString(char *s);
+
+extern ShortInt StrCmp(char *s1, char *s2, LongInt Hand1, LongInt Hand2);
+
+/*#define Memo(s) ((*OpPart==*(s)) AND (strcmp(OpPart,(s))==0))*/
+#define Memo(s) (strcmp(OpPart,(s))==0)
+
+
+extern void AddSuffix(char *s, char *Suff);
+
+extern void KillSuffix(char *s);
+
+extern char *NamePart(char *Name);
+
+extern char *PathPart(char *Name);
+
+
+extern char *FloatString(Double f);
+
+extern void StrSym(TempResult *t, Boolean WithSystem, char *Dest);
+
+
+extern void ResetPageCounter(void);
+
+extern void NewPage(ShortInt Level, Boolean WithFF);
+
+extern void WrLstLine(char *Line);
+
+extern void SetListLineVal(TempResult *t);
+
+
+extern LargeWord ProgCounter(void);
+
+extern LargeWord EProgCounter(void);
+
+extern Word Granularity(void);
+
+extern Word ListGran(void);
+
+extern void ChkSpace(Byte Space);
+
+
+extern void PrintChunk(ChunkList *NChunk);
+
+extern void PrintUseList(void);
+
+extern void ClearUseList(void);
+
+
+extern void CompressLine(char *TokNam, Byte Num, char *Line);
+
+extern void ExpandLine(char *TokNam, Byte Num, char *Line);
+
+extern void KillCtrl(char *Line);
+
+
+extern void ChkStack(void);
+
+extern void ResetStack(void);
+
+extern LongWord StackRes(void);
+
+
+extern void AddCopyright(char *NewLine);
+
+extern void WriteCopyrights(TSwitchProc NxtProc);
+
+
+extern Boolean ChkSymbName(char *sym);
+
+extern Boolean ChkMacSymbName(char *sym);
+
+
+extern void WrErrorString(char *Message, char *Add, Boolean Warning, Boolean Fatal);
+
+
+extern void WrError(Word Num);
+
+extern void WrXError(Word Num, char *Message);
+
+extern Boolean ChkRange(LargeInt Value, LargeInt Min, LargeInt Max);
+
+
+extern void ChkIO(Word ErrNo);
+
+
+extern void AddIncludeList(char *NewPath);
+
+extern void RemoveIncludeList(char *RemPath);
+
+
+extern void ClearOutList(void);
+
+extern void AddToOutList(char *NewName);
+
+extern void RemoveFromOutList(char *OldName);
+
+extern char *GetFromOutList(void);
+
+
+extern void ClearShareOutList(void);
+
+extern void AddToShareOutList(char *NewName);
+
+extern void RemoveFromShareOutList(char *OldName);
+
+extern char *GetFromShareOutList(void);
+
+
+extern void BookKeeping(void);
+
+
+extern long DTime(long t1, long t2);
+
+
+
+
+extern void asmsub_init(void);
diff --git a/bincmp.c b/bincmp.c
new file mode 100644
index 0000000..1037ec8
--- /dev/null
+++ b/bincmp.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+
+int main(argc,argv)
+int argc;
+char **argv;
+{
+ FILE *f1,*f2;
+ unsigned char c1,c2;
+ long pos=0;
+
+ if (argc!=3)
+ {
+ fprintf(stderr,"calling convention: %s <file1> <file2>\n",argv[0]);
+ return 1;
+ }
+
+ f1=fopen(argv[1],"rb");
+ if (f1==NULL)
+ {
+ perror(argv[1]); return 2;
+ }
+ f2=fopen(argv[2],"rb");
+ if (f2==NULL)
+ {
+ perror(argv[2]); return 2;
+ }
+
+ while ((!feof(f1))&&(!feof(f2)))
+ {
+ fread(&c1,1,1,f1); fread(&c2,1,1,f2);
+ if (c1!=c2)
+ {
+ fprintf(stderr,"compare error at position %d\n",pos);
+ fclose(f1); fclose(f2); return 3;
+ }
+ pos++;
+ }
+
+ if (feof(f1)!=feof(f2))
+ {
+ fprintf(stderr,"files have different sizes\n");
+ fclose(f1); fclose(f2); return 4;
+ }
+
+ fclose(f1); fclose(f2); return 0;
+}
diff --git a/bpemu.c b/bpemu.c
new file mode 100644
index 0000000..3f35493
--- /dev/null
+++ b/bpemu.c
@@ -0,0 +1,239 @@
+
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Emulation einiger Borland-Pascal-Funktionen */
+/* */
+/* Historie: 20. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#include "strutil.h"
+#include "bpemu.h"
+
+#ifdef __MSDOS__
+#include <dos.h>
+#include <dir.h>
+#endif
+
+#if defined( __EMX__ ) || defined( __IBMC__ )
+#include <os2.h>
+#endif
+
+ char *FExpand(char *Src)
+BEGIN
+ static String CurrentDir;
+ String Copy;
+#ifdef DRSEP
+ String DrvPart;
+#if defined( __EMX__ ) || defined( __IBMC__ )
+ ULONG DrvNum,Dummy;
+#else
+ int DrvNum;
+#endif
+#endif
+ char *p,*p2;
+
+ strmaxcpy(Copy,Src,255);
+
+#ifdef DRSEP
+ p=strchr(Copy,DRSEP);
+ if (p!=Nil)
+ BEGIN
+ memcpy(DrvPart,Copy,p-Copy); DrvPart[p-Copy]='\0'; strcpy(Copy,p+1);
+ END
+ else *DrvPart='\0';
+#endif
+
+#ifdef __MSDOS__
+ if (*DrvPart=='\0')
+ BEGIN
+ DrvNum=getdisk(); *DrvPart=DrvNum+'A'; DrvPart[1]='\0'; DrvNum++;
+ END
+ else DrvNum=toupper(*DrvPart)-'@';
+ getcurdir(DrvNum,CurrentDir);
+#else
+#if defined( __EMX__ ) || defined( __IBMC__ )
+ if (*DrvPart=='\0')
+ BEGIN
+ DosQueryCurrentDisk(&DrvNum,&Dummy);
+ *DrvPart=DrvNum+'@'; DrvPart[1]='\0';
+ END
+ else DrvNum=toupper(*DrvPart)-'@';
+ Dummy=255; DosQueryCurrentDir(DrvNum,(PBYTE) CurrentDir,&Dummy);
+#else
+#ifdef _WIN32
+ getcwd(CurrentDir,255);
+ for (p=CurrentDir; *p!='\0'; p++)
+ if (*p=='/') *p='\\';
+#else
+ getcwd(CurrentDir,255);
+#endif
+#endif
+#endif
+
+ if (CurrentDir[strlen(CurrentDir)-1]!=PATHSEP) strmaxcat(CurrentDir,SPATHSEP,255);
+ if (*CurrentDir!=PATHSEP) strmaxprep(CurrentDir,SPATHSEP,255);
+
+ if (*Copy==PATHSEP)
+ BEGIN
+ strmaxcpy(CurrentDir,SPATHSEP,255); strcpy(Copy,Copy+1);
+ END
+
+#ifdef DRSEP
+ strmaxprep(CurrentDir,SDRSEP,255);
+ strmaxprep(CurrentDir,DrvPart,255);
+#endif
+
+ while((p=strchr(Copy,PATHSEP))!=Nil)
+ BEGIN
+ *p='\0';
+ if (strcmp(Copy,".")==0);
+ else if ((strcmp(Copy,"..")==0) AND (strlen(CurrentDir)>1))
+ BEGIN
+ CurrentDir[strlen(CurrentDir)-1]='\0';
+ p2=strrchr(CurrentDir,PATHSEP); p2[1]='\0';
+ END
+ else
+ BEGIN
+ strmaxcat(CurrentDir,Copy,255); strmaxcat(CurrentDir,SPATHSEP,255);
+ END
+ strcpy(Copy,p+1);
+ END
+
+ strmaxcat(CurrentDir,Copy,255);
+
+ return CurrentDir;
+END
+
+ char *FSearch(char *File, char *Path)
+BEGIN
+ static String Component;
+ char *p,*start,Save='\0';
+ FILE *Dummy;
+ Boolean OK;
+
+ Dummy=fopen(File,"r"); OK=(Dummy!=Nil);
+ if (OK)
+ BEGIN
+ fclose(Dummy);
+ strmaxcpy(Component,File,255); return Component;
+ END
+
+ start=Path;
+ do
+ BEGIN
+ if (*start=='\0') break;
+ p=strchr(start,DIRSEP);
+ if (p!=Nil)
+ BEGIN
+ Save=(*p); *p='\0';
+ END
+ strmaxcpy(Component,start,255);
+ strmaxcat(Component,SPATHSEP,255);
+ strmaxcat(Component,File,255);
+ if (p!=Nil) *p=Save;
+ Dummy=fopen(Component,"r"); OK=(Dummy!=Nil);
+ if (OK)
+ BEGIN
+ fclose(Dummy);
+ return Component;
+ END
+ start=p+1;
+ END
+ while (p!=Nil);
+
+ *Component='\0'; return Component;
+END
+
+ long FileSize(FILE *file)
+BEGIN
+ long Save=ftell(file),Size;
+
+ fseek(file,0,SEEK_END);
+ Size=ftell(file);
+ fseek(file,Save,SEEK_SET);
+ return Size;
+END
+
+ Byte Lo(Word inp)
+BEGIN
+ return (inp&0xff);
+END
+
+ Byte Hi(Word inp)
+BEGIN
+ return ((inp>>8)&0xff);
+END
+
+ Boolean Odd(int inp)
+BEGIN
+ return ((inp&1)==1);
+END
+
+ Boolean DirScan(char *Mask, charcallback callback)
+BEGIN
+ char Name[1024];
+
+#ifdef __MSDOS__
+ struct ffblk blk;
+ int res;
+ char *pos;
+
+ res=findfirst(Mask,&blk,FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_LABEL|FA_DIREC|FA_ARCH);
+ if (res<0) return False;
+ pos=strrchr(Mask,PATHSEP); if (pos==Nil) pos=strrchr(Mask,DRSEP);
+ if (pos==Nil) pos=Mask; else pos++;
+ memcpy(Name,Mask,pos-Mask);
+ while (res==0)
+ BEGIN
+ if ((blk.ff_attrib&(FA_LABEL|FA_DIREC))==0)
+ BEGIN
+ strcpy(Name+(pos-Mask),blk.ff_name);
+ callback(Name);
+ END
+ res=findnext(&blk);
+ END
+ return True;
+#else
+#if defined ( __EMX__ ) || defined ( __IBMC__ )
+ HDIR hdir=1;
+ FILEFINDBUF3 buf;
+ ULONG rescnt;
+ USHORT res;
+ char *pos;
+
+ rescnt=1; res=DosFindFirst(Mask,&hdir,0x16,&buf,sizeof(buf),&rescnt,1);
+ if (res!=0) return False;
+ pos=strrchr(Mask,PATHSEP); if (pos==Nil) pos=strrchr(Mask,DRSEP);
+ if (pos==Nil) pos=Mask; else pos++;
+ memcpy(Name,Mask,pos-Mask);
+ while (res==0)
+ BEGIN
+ strcpy(Name+(pos-Mask),buf.achName); callback(Name);
+ res=DosFindNext(hdir,&buf,sizeof(buf),&rescnt);
+ END
+ return True;
+#else
+ strmaxcpy(Name,Mask,255); callback(Name); return True;
+#endif
+#endif
+END
+
+ LongInt GetFileTime(char *Name)
+BEGIN
+ struct stat st;
+
+ if (stat(Name,&st)==-1) return 0;
+ else return st.st_mtime;
+END
+
+ void bpemu_init(void)
+BEGIN
+END
diff --git a/bpemu.h b/bpemu.h
new file mode 100644
index 0000000..11036b7
--- /dev/null
+++ b/bpemu.h
@@ -0,0 +1,33 @@
+/* bpemu.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Emulation einiger Borland-Pascal-Funktionen */
+/* */
+/* Historie: 20. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+typedef void (*charcallback)(
+#ifdef __PROTOS__
+char *Name
+#endif
+);
+
+extern char *FExpand(char *Src);
+
+extern char *FSearch(char *File, char *Path);
+
+extern long FileSize(FILE *file);
+
+extern Byte Lo(Word inp);
+
+extern Byte Hi(Word inp);
+
+extern Boolean Odd (int inp);
+
+extern Boolean DirScan(char *Mask, charcallback callback);
+
+extern LongInt GetFileTime(char *Name);
+
+extern void bpemu_init(void);
diff --git a/changelog b/changelog
new file mode 100644
index 0000000..9ace5a0
--- /dev/null
+++ b/changelog
@@ -0,0 +1,729 @@
+------------------------------------------------------------------------------
+v1.41r3 Aenderungen: (-->v1.41r4beta)
+
+11.3.1996
+
+- Bugfix : -l - Option funktionierte bei P2HEX nicht.
+- Erweiterung : P2HEX/P2BIN koennen Dateiinhalte auf andere Adressen
+ verschieben.
+- Erweiterung : P2HEX kann den Einsprungpunkt auch in Intel-Hex-Files
+ weitergeben.
+- Erweiterung : Kommentare in SHARED-Anweisungen werden in die Share-Datei
+ weitergegeben.
+- Aenderung : Als Kommentarzeichen wird fuer Share-Dateien im Pascal-Modus
+ (* ... *) anstelle { ... } verwendet. Dies erlaubt es,
+ die Dateien auch fuer Modula zu verwenden und sollte fuer
+ Pascal keine Nachteile mit sich bringen.
+
+18.3.1996
+
+- Bugfix : Kodierungsfehler im Z(3)80-Teil behoben:
+ - MTEST
+ - LD (IX/IY+n),r16
+ - MULTW/MULTUW/DIVUW [HL,]IX/IY/imm16
+ - LD r16,BC
+- Bugfix : Fehlermeldungen ueber fehlende/fehlerhafte Key-Datei kamen
+ in der englischen Version noch auf Deutsch.
+
+25.3.1996
+
+- Bugfix : Erwaehnung der -quiet sowie -alias -Optionen fehlte in der
+ Online-Hilfe
+- Erweiterung : 80C517 als Prozessortyp aufgenommen (+Register in STDDEF51.INC)
+
+ 9.4.1996
+
+- Erweiterung : MELPS-7700-Teil kennt jetzt auch die 7750er-Befehlssatzer-
+ weiterungen
+
+ 6.5.1996
+
+- Bugfix : VERSION-Variable stand noch auf 1.41r2
+
+13.5.1996
+
+- Erweiterung : MELPS-7700-Teil kennt jetzt auch die 7751er-Befehlssatzer-
+ weiterungen.
+
+- Bugfix : einige haarstraeubende Nichtinitialisierungen von Variablen
+ beseitigt, die in Zusammenhang mit der Definition von Symbolen
+ in der Kommandozeile auftreten koennen.
+
+28.5.1996
+
+- Bugfix : Der Z80-Teil hatte bei IX/IY-Displacements ein Byte zu frueh
+ auf laengere Offsets umgeschaltet.
+
+- Bugfix : Die \i und \h - Escapes funktionierten in Strings nicht.
+
+- Bugfix : Die Bereichseingrenzung fuer 24-Bit-Zahlen war nicht korrekt.
+
+29.5.1996
+
+- Bugfix : Der 68000-Teil schrieb Bloedsinn in die Code-Datei, wenn in
+ einer Zeile genau ein Byte Code erzeugt wurde.
+
+31.5.1996
+
+- Bugfix : Im MELPS-7700-Teil funktionierten eine Reihe von Befehlen nicht mehr,
+ wenn man den 7751er als Ziel-CPU einstellte.
+
+- Bugfix : Der SEL-Befehl des MCS-48-Teils gab bei einer falschen
+ Parameterzahl eine falsche Fehlermeldung aus.
+
+10.6.1996
+
+- Bugfix : bei P2HEX war die Bereichsueberpruefung fuer den
+ Datenadressbereich des DSK-Formats fehlerhaft
+
+- Bugfix : einige Abfragen auf I/O-Fehler bei P2HEX und P2BIN fehlten
+
+- Bugfix : der SFRB-Befehl gab einen falschen Wert im Listing aus
+
+- Bugfix : BIGENDIAN funktionierte nicht fuer die ganze 8051-Familie,
+ sondern nur fuer den 80C251
+
+- Bugfix : Bei 16-Bit-immediate-Werten im 8051-Modus war die
+ Bereichsabfrage nicht korrekt
+
+- Bugfix : Wurde im 8051-Modus bei registerindirekter Adressierung ein
+ fehlerhafter Registername angegeben, gab es keine Fehlermeldung
+
+- Bugfix : im 8051-Teil war die Benutzung von immediate-Operanden bei PUSH
+ nicht auf den 80C251 eingeschraenkt
+
+- Bugfix : PUSH/POP DRk beim 80251 erzeugte fehlerhafte Codes
+
+- Bugfix : bei 8051:ACALL/AJMP/ECALL/EJMP waren negative Adressen erlaubt
+
+- Bugfix : im 80251-Modus war JG undefiniert, dafuer lieferte JSLE einen
+ falschen Opcode
+
+- Bugfix : bei 80251: JMP wurden fuer sehr grosse Distanzen SJMPS erzeugt
+
+- Bugfix : der MCS-51-DJNZ-Befehl gab fuer Distanzueberschreitungen eine
+ ungenaue Fehlermeldung aus
+
+- Erweiterung : ueber die HAS64-Variable kann man jetzt abfragen, ob der
+ Parser mit 64 Bit arbeitet
+
+- Erweiterung : DQ kann jetzt auch 64-Bit-Integers ablegen
+
+------------------------------------------------------------------------------
+v1.41r4 Aenderungen: (-->v1.41r5beta)
+
+15.7.1996
+
+- Bugfix : lag beim XA ein Normier-/Schiebebefehl mit 32-Bit-Operanden-
+ laenge auf einer ungeraden Adresse, so dass bei vorangestelltem
+ Label ein NOP eingeflickt werden musste, so wurde ein falscher
+ Code erzeugt.
+
+- Bugfix : Im TLCS-900-Teil wurde ein Byte zu frueh auf laengere
+ Displacements beim Adressierungsmodus (reg+disp) umgeschaltet.
+
+ 5.8.1996
+
+- Bugfix : noch 1,2 Kleinigkeiten im XA-Teil beseitigt...
+
+12.8.1996
+
+- Bugfix : Der TLCS-900-Teil machte bei der Bearbeitung von 2-Operanden-
+ ALU-Befehlen (ADD,SUB,CMP...) auch weiter, wenn eine falschen
+ Anzahl von Parametern angegeben war.
+
+- Bugfix : Im TLCS-900-Teil konnten bei der Benutzung vorwaertsreferen-
+ zierter Symbole fuer Schiebeamplituden Fehler auftreten
+
+- Erweiterung : Um etwas kompatibler zum AS11 von Motorola zu werden, gibt es
+ jetzt im 68xx-Modus auch die Befehle FCC, FDB, FCB und RMB.
+
+19.8.1996
+
+- Bugfix : Im 65xx-Teil funktionierten die Angaben < bzw. > zur Er-
+ zwingung kurzer bzw. langer Adressen nicht korrekt
+
+- Bugfix : INC/INC A bzw. DEC/DEC A funktionierten beim MELPS/740 nicht
+
+26.8.1996
+
+- Bugfix : in PIC16C8x-Teil war die Adressbereichsbegrenzung nicht korrekt
+
+- Erweiterung : zusaetzlich M16C-Familie unterstuetzt
+
+ 9.9.1996
+
+- Erweiterung : zum M16C gibt es jetzt auch ein Includefile
+
+- Erweiterung : zusaetzlich COP8-Familie unterstuetzt
+
+- Bugfix : wurden im Zx80-Teil ADC oder SBC mit einer falschen
+ Operandenzahl benutzt, gab es eine falsche Fehlermeldung
+
+- Bugfix : wurden im Z380-Teil INA, INAW, OUTA, OUTAW mit einer Adresse
+ >2GByte benutzt, konnte es Kodierungsfehler geben
+
+- Erweiterung : zusaetzliche Befehle zur bedingten Assemblierung: IFB und IFNB
+
+- Erweiterung : neuer EXITM-Befehl, um eine Makroexpansion vorzeitig
+ abzubrechen
+
+- Bugfix : in den englische Fehlermeldungen geisterten noch einige
+ deutsche Woerter herum
+
+16.9.1996
+
+- Erweiterung : zusaetzlich MSP430 unterstuetzt
+
+- Erweiterung : mit LISTING NOSKIPPED bzw. LISTING PURECODE kann man jetzt
+ nicht assemblierte Teile aus dem Listing ausschliessen
+
+23.9.1996
+
+- Bugfix : im PowerPC-Teil gab es noch einige Big<->Little-Endian-
+ Verdrehungen
+
+4.10.1996
+
+- Erweiterung : zusaetzlich 78K0 unterstuetzt
+
+14.10.1996
+
+- Bugfix : wurde beim Wiederholungsfaktor von DC.x die schliessende
+ Klammer vergessen, so gab es unvorhersagbare Reaktionen
+ anstatt einer Fehlermeldung
+
+- Bugfix : die Attributabfrage bei PEA in 680x0-Teil war nicht korrekt
+
+- Bugfix : wurde beim 68xx ein inkorrektes Indexregister verwendet, so
+ wurde kein Fehler gemeldet, sondern absolute Adressierung
+ erzeugt
+
+- Bugfix : auf b endende Hex-Zahlen mit C-Syntax funktionierten im
+ RELAXED-Modus nicht
+
+- Bugfix : Prozessornamen COP87L48-->COP87L84 korrigiert
+
+- Bugfix : CBEQ beim 68HC08 erzeugte z.T. auch Code bei falschem
+ Adressierungsmodus
+
+- Bugfix : P2HEX/P2BIN arbeiteten nicht korrekt bei Adressen > 2GByte
+
+- Erweiterung : zusaetzlicher BINCLUDE-Befehl
+
+- Bugfix : explizit kurze Adressen beim 6809 funktionierten nicht,
+ wenn DPR<>0 war
+
+- Erweiterung : BIGENDIAN nun auch beim PowerPC
+
+28.10.1996
+
+- Bugfix : Beim 6804 war die Bereichsabfrage nicht korrekt (16 statt 12 Bit)
+
+- Bugfix : Bei DC.x fuer den 68HC12 waren die Bytes paarweise verdreht
+
+- Bugfix : Mit READ in Makros eingelesene Symbole wurden als lokal zum Makro definiert
+
+- Bugfix : Beim 8086 gab es keine Fehlermeldung, wenn die schliessende Klammer (])
+ eines Adressausdruckes fehlte
+
+- Bugfix : Beim 8086 wurde fuer Displacements von -128 versehentlich lange Adressierung
+ benutzt
+
+- Bugfix : INS/EXT beim V30/35 erzeugten auch Code , wenn der Adressierungsmodus ungueltig
+ war
+
+- Bugfix : wurde beim 8085 bei LDAX/STAX ein falsches Register benutzt, gab es eine unsinnige
+ Fehlermeldung
+
+- Bugfix : Beim 8086 gab es bei falschem Adressierungsmodus in einigen Faellen doppelte
+ Fehlermeldungen
+
+- Bugfix : Beim PowerPC waren bei MTSPR/MFSPR/MTDCR/MFDCR die 5-Bit-Komponenten der Register-
+ nummer verdreht
+
+- Bugfix : wurden beim 8086 8-Bit-immediate-Werte mit Vorwaertsreferenzen benutzt, so gab es
+ in einigen Faellen Fehler wegen Bereichsueberschreitungen
+
+5.11.1996
+
+- Erweiterung : DC.X funktioniert jetzt auch bei 68xx
+
+- Bugfix : wurde beim TLCS90 bei CALL, JMP oder RET eine ungueltige
+ Bedingung benutzt, gab es keine Fehlermeldung
+
+- Erweiterung : Funktionen TOLOWER, LOWSTRING
+
+
+11.11.1996 (alaaf...)
+
+- Bugfix : bei MELPS7751 als Ziel funktionierten einige Befehle nicht
+
+- Bugfix : wurde beim Z8 ein ungueltiges Register fuer indizierte Adressierung angegeben,
+ so gab es eine bloede Fehlermeldung
+
+19.12.1996
+
+- Bugfix : beim H8/300(H): wurde bei Logikanweisungen mit einem C am Ende
+ die Argumentzahl nicht kontrolliert
+
+- Bugfix : bei 32-bittiger Anzeige im Listing wurden keine Vornullen
+ ausgegeben
+
+- Bugfix : die relativen Sprungbefehle beim TMS370 erlaubten nur Adressen von
+ 0..255 als Argument
+
+- Bugfix : beim MELPS4500 war versehentlich das DATA-Segment gesperrt
+
+- Bugfix : beim 16C8x war Konstantenablage im Codesegment nur 12-bittig
+ zugelassen
+
+- Bugfix : bei einem REPT-Argument <1 erfolgte trotzdem ein Durchlauf
+
+- Aenderung : Fehlernummern fuer fatale Fehler wurden von Basis 2000 auf
+ Basis 10000 geschoben
+
+- Erweiterung : Konstantenablage ist jetzt auch im Codesegment zugelassen
+
+2.1.1997
+
+- Bugfix : beim M16C war die Abfrage auf ungueltige Adressierungsmodi
+ bei LDE/STE/INC/DEC/NOT/ROT/JMPS/ADJNZ nicht korrekt
+
+- Bugfix : beim MSP gab es keinen Abbruch bei ungueltiger Operandengroesse
+
+- Bugfix : beim MSP gab es keine Fehlermeldung wenn fuer BYTE ein
+ Float-Argument verwendet wurde
+
+- Bugfix : beim MSP wurde das nicht erlaubte Attribut bei RETI nicht
+ abgeprueft
+
+- Erweiterung : PADDING geht jetzt auch beim MSP
+
+- Bugfix : die automatische Laengenumschaltung fuer relative Spruenge
+ arbeitete beim H8/500 fehlerhaft
+
+- Bugfix : beim H8/500 gab es eine falsche Meldung bei absoluten
+ Adressen ausserhalb der aktuellen Seite
+
+- Bugfix : beim 78C1x war der erlaube Displacement-Bereich in Adressen
+ zu gross
+
+- Bugfix : Der SER-Befehl beim AVR erzeugte bisweilen keinen Code
+
+- Bugfix : Im 75K0-Teil wurden fuer Prozessoren >=75104 bisweilen
+ keine Steuerregister akzeptiert
+
+21.1.1997
+
+- Bugfix : wurde ein NEWPAGE-Befehl ohne Argument benutzt, kam
+ bisweilen keine Reaktion
+
+- Bugfix : bei bitbedingten Sprungbefehlen des XA, die auf einer
+ ungeraden Adresse mit vorangestelltem Label lagen, gab
+ es Kodierungsfehler
+
+- Bugfix : wurden mit dem POPU-Befehl des XA gleichzeitig Register
+ aus der unteren und oberen Haelfte geholt, war die Reihen-
+ folge der Einzelbefehle nicht spiegelbildlich zu PUSH/PUSHU
+
+- Bugfix : Der MUL-Befehl des 6805 wurde erst fuer den 68HC08 erlaubt
+
+- Bugfix : indizierte Adressierungsarten mit automatischem Inkrement/
+ Dekrement erzeugten ein falsches Postbyte
+
+------------------------------------------------------------------------------
+v1.41r5 Aenderungen: (-->v1.41r6beta)
+
+7.2.1997
+
+- Bugfix : Die BITPOS-Funktion arbeitete nicht korrekt.
+
+- Aenderung : Wird ein Makro in einem mit IF... ausgeschlossenen Teil
+ referiert, so erfolgt die (MACRO)-Anzeige im Listing
+ nicht mehr, als Zeichen, dass nicht expandiert wird.
+
+- Bugfix : Die meisten Include-Files arbeiteten im case-sensitiven
+ Modus nicht korrekt.
+
+- Bugfix : Im TMS-370-Teil waren alle 16-Bit-Teile von Instruktionen
+ verdreht (little statt big endian) abgelegt.
+
+- Bugfix : Im TMS-370-Teil wurde das #-Zeichen nicht immer akzeptiert.
+
+- Bugfix : Die DIVLU-Instruktion beim 166er war versehentlich als
+ DIVUL abgelegt.
+
+- Erweiterung : Zusaetzliche Prozessorfamilien: ST9, SC/MP und TMS7000
+
+13.3.1997
+
+- Bugfix : Bei grossen 8051-Programmen konnte es bei den Befehlen
+ CJNE, DJNZ, JNB, JB und JBC zu out-of-branch-Fehlern
+ kommen, obwohl das Ziel eigentlich innerhalb der Sprung-
+ weite lag.
+
+- Erweiterung : Zusaetzliche Prozessorfamilien: MCS-296, TMS9900
+
+17.3.1997
+
+- Erweiterung : neue Z8-Derivate
+
+- Erweiterung : Beruecksichtigung der Maskenfehler des 80C504
+
+24.3.1997
+
+- Bugfix : Die t-Option funktionierte verkehrtherum
+
+- Bugfix : bei grossen 8051-Programmen konnte es bei Vorwaersspruengen
+ Fehler ueber zu lange Sprungdistanzen geben
+
+- Bugfix : Wenn beim 680x0 die Adressierungsart d16(An) eine Vor-
+ waertsreferenz enthielt, gab es Fehler.
+
+1.4.1997
+
+- Erweiterung : Schreiben von Debug-Informationen moeglich
+
+- Erweiterung : Includefiles fuer Siemens SAB C501/2/4
+
+- Erweiterung : Includefile fuer 80C163/165 erweitert
+
+5.5.1997
+
+- Erweiterung : Sektionsinfo in Debug-Meldungen
+
+26.5.1997
+
+- Erweiterung : Stack-Verbrauch im Parser reduziert (zu Gunsten der OS/2-
+ Version)
+
+- Erweiterung : < > >> als Praefixe fuer MELPS-7700 zugelassen
+
+- Erweiterung : DB, DW... auch fuer MELPS-7700 zugelassen
+
+9.6.1997
+
+- Bugfix : BTST akzeptierte kein ueberfluessiges .B Attribut
+
+- Bugfix : der AVR-Teil ist jetzt den offiziellen Typen angepasst
+
+12.6.1997
+
+- Bugfix : Vorwaertsdeklarationen beim 68xx gaben noch Probleme bei
+ Befehlen, die nur kurze absolute Adressen kennen
+
+------------------------------------------------------------------------------
+v1.41r6 Aenderungen: (-->v1.41r7beta)
+
+28.7.1997
+
+- Bugfix : traten keine Fehler auf, so wurde eine alte Error-Log-Datei
+ nicht beseitigt
+
+- Erweiterung : Ueber die ARCHITECTURE-Variable kann jetzt die Zielplattform
+ von AS abgefragt werden
+
+- Aenderung : PADDING ist nur noch fuer die 680x0-Familie defaultmaessig
+ eingeschaltet
+
+11.8.1997
+
+- Erweiterung : Definition von Strukturen ueber STRUCT/ENDSTRUCT
+
+21.8.1997
+
+- Bugfix : beim MELPS7700 wurden fuer DEC abs8 und ICN abs8 gleiche
+ Opcodes erzeugt
+
+1.9.1997
+
+- Erweiterung : Unterstuetzung des Atmel HEX- und OBJ-Formates
+
+29.9.1997
+
+- Bugfix : Die Operandenreihenfolgen fuer Schiebe- und Immediate-Befehle
+ beim TMS9900 waren nicht korrekt, und einfache Integerzahlen
+ als Registerangaben waren nicht erlaubt.
+
+- Erweiterung : Unterstuetzung der 68040-Steuerregister fuer MOVEC
+
+9.10.1997
+
+- Bugfix : CALL beim 80C166 ergab nicht immer korrekte Bedingungs-Codes
+
+20.10.1997
+
+- Bugfix : DUP spielte bei Argumenten <=0 verrueckt
+
+- Erweiterung : STRLEN()-Funktion
+
+- Erweiterung : Registersymbole fuer Atmel AVR
+
+22.10.1997
+
+- Bugfix : Eine Reihe von Kodierungen im 80C251-Teil waren noch verkehrt
+
+27.10.1997
+
+- Erweiterung : P2BIN und P2HEX koennen jetzt optional die Quelldateien nach
+ Umwandlung loeschen
+
+- Erweiterung : P2BIN kann jetzt dem Image die Startadresse voranstellen
+
+- Erweiterung : Unterstuetzung der undokumentierten 6502-Befehle
+
+17.11.1997
+
+- Erweiterung : 68K-Teil kennt Motorola ColdFire
+
+20.11.1997
+
+- Bugfix : MOVBZ/MOVBS funktionierten in der Kombination 'rn,abs'
+ nicht
+
+3.12.1997
+
+- Bugfix : BINCLUDE arbeitete nicht korrekt, wenn nur der Offset
+ angegeben war
+
+12.1.1998
+
+- Bugfix : in REG166.INC war das CAPREL-Register fuer einige 80C16x-
+ Varianten falsch beschrieben
+
+- Bugfix : EXTP legte fuer 80C16x die Bits in einer falschen Reihenfolge
+ ab.
+
+26.1.1998
+
+- Erweiterung : Die Pseudo-Befehle BYT/FCB,ADR/FDB und FCC erlauben jetzt auch
+ den von DC.x her bekannten Wiederholungsfaktor.
+
+- Bugfix : MOVC beim 8051 gab keine Fehlermeldung bei einem ungueltigen
+ zweiten Parameter aus.
+
+16.1.1998
+
+- Bugfix : BINCLUDE, die zweite...
+
+13.4.1998
+
+- Bugfix : EQU/SET akzeptierten kein leeres Argument, um typenlose Symbole
+ zu definieren
+
+- Bugfix : LDD/STD beim AVR kamen nicht mit symbolischen Offsets zurecht
+
+- Erweiterung : 320C6x-Support
+
+
+....
+
+- Bugfix : Ungültige Bitadressen erzeugten z.T. beim 80C16x keine
+ Fehlermeldungen
+
+- Erweiterung : Registersymbole auch für 80C16x
+
+25.5.1998
+
+- Bugfix : TST ab 68020 funktionierte nicht mit Adreßregister
+
+2.6.1998
+
+- Bugfix : TST ab 68020 funktionierte nicht mit immediate/PC-relativ
+
+- Bugfix : Adressierungsart ([pc]) funktionierte im 68K-Teil nicht
+
+- Bugfix : MTCRF im PowerPC-Teil war nicht korrekt implementiert
+
+- Bugfix : DATA im AVR-Teil verschlampte letztes Argument (nur C-Version)
+
+- Bugfix : In STDDEF60.INC waren einige PPC403-Register falsch definiert
+
+- Bugfix : MOVE vom/zum CCR war als Byte-Operation kodiert
+
+............
+
+- Bugfix : DD und DQ legten Daten immer in Little-Endian ab, egal
+ von der Einstellung mit BIGENDIAN
+
+------------------------------------------------------------------------------
+v1.41r7 Aenderungen: (-->v1.41r8beta)
+
+2.7.1998
+
+- Erweiterung : String-Funktionen STRSUB und STRSTR
+
+- Erweiterung : CODEPAGE-Anweisung
+
+- Bugfix : Manual-Pages machten Probleme mit catman unter Solaris
+
+- Bugfix : Zeilen, die nur aus Label bzw. Kommentar bestanden, wurden
+ nicht in den Makroprozessoroutput übernommen
+
+- Bugfix : DEFINEs arbeiteten nicht korrekt
+
+- Erweiterung : neue Argumentvarianten für CHARSET
+
+21.8.1998
+
+- Bugfix : einige Bereichsmasken im Parser waren falsch gesetzt
+
+- Erweiterung : Backslash-Ausdrücke in Character/String-Konstanten jetzt
+ auch in hex oder oktal möglich
+
+- Bugfix : kurze 8051-Bitadressen wurden im 80251-Sourcemodus unnötig
+ in lange Adressen umgewandelt.
+
+- Aenderung : nicht mit XA-PSW-Bits kollidierende 51er-Flags haben jetzt
+ wieder die Originalnamen
+
+- Bugfix : Befehle mit genau 20 Argumenten gaben einen Crash
+
+- Erweiterung : RADIX-Befehl zur Festlegung des Default-Zahlensystems
+
+- Erweiterung : statt ELSEIF darf auch ELSE geschrieben werden
+
+- Bugfix : im Testprogramm T_FULL09 wurde an einigen Stellen ELSE statt
+ ELSEIF benutzt
+
+- Erweiterung : statt = darf auch == geschrieben werden
+
+24.9.1998 [Bld 3]
+
+- Bugfix : Fuer MOV dir8,Rm im 80251-Teil wurde ein falscher Code erzeugt
+ (Fehler im Manual!)
+
+- Erweiterung : i960-Unterstuetzung
+
+- Erweiterung : NEC uPD7720/25-Unterstützung
+
+- Bugfix : einige Kodierungsfehler im M16C-Teil behoben
+
+18.10.1998 [Bld 4]
+
+
+- Erweiterung : NEC uPD77230-Unterstützung
+
+- Erweiterung : BRANCHEXT fuer XA funktioniert jetzt auch für BR
+
+- Erweiterung : Fehlermeldungen mit > > > am Anfang
+
+- Bugfix : TRAPA für H8/300H nachgetragen
+
+- Bugfix : LDD/STD mit <Reg>+<Symbol> klappte nicht
+
+25.10.1998 [Bld 5]
+
+- Bugfix : direkt indizierte Adressierung mit 16-Bit-Displacement
+ ergab ein falsches Postbyte beim 68HC12
+
+10. 1.1999 [Bld 6]
+
+- Bugfix : bei X/Y-Indizierung wurde im 65xx-Teil das Indexregister
+ nicht sauber abgeprueft
+
+- Erweiterung : SYM53C8xx-Unterstützung
+
+- Erweiterung : i4004-Unterstützung
+
+- Bugfix : Der Adressbereich fuer die neueren 80C166-Derivate stand
+ noch auf 0-3ffffh statt 0-ffffffh
+
+- Bugfix : Für PIC16C64/84 ist zusätzlich der Adreßbereich von $2000
+ bis $2007 eingeschaltet. (oder ist das eine Erweiterung?
+ Ick wees nich...)
+
+- Bugfix : Wenn der vom einem Befehl erzeugte Code über eine Record-
+ Grenze im P-File hinausging, gab es eine fehlerhafte Folge-
+ adresse im neuen Record.
+
+- Bugfix : Wenn mit BINCLUDE Daten von mehr als 64K eingezogen wurden
+ (strenggenommen, wenn BINCLUDE zur Anlage eines neuen
+ Records in der P-Datei führte), gab es fehlerhafte Adressen
+ im Record, außerdem fehlte die Prüfung auf Segmentgrenzen-
+ überschreitung
+
+17. 1.1999 [Bld 7]
+
+- Erweiterung : Der 680x0-Teil legt die Länge äußerer Displacements jetzt
+ selber fest.
+
+27. 1.1999 [Bld 8]
+
+- Bugfix : Die implizite Erweiterung von Registern auf -paare klappte
+ nicht auf allen Zielplattformen (680x0)
+
+- Bugfix : SBCD wurde falsch kodiert (680x0)
+
+ 1. 2.1999 [Bld 9]
+
+- Bugfix : Weil einige Formatstrings nicht portabel waren, knallte
+ es bisweilen unter DOS/DPMI
+
+ 8. 2.1999 [Bld 10]
+
+- Bugfix : Eine Reihe von Kodierungsfehlern im M16C-Teil beseitigt
+
+19. 4.1999 [Bld 11]
+
+- Erweiterung : Befehle / Register PPC403-MMU
+
+- Erweiterung : National SC144xx-Support
+
+- Bugfix : Angabe von Symbol-Defines in der Kommandozeile, die nicht
+ einfache Konstanten sind, konnten zu Abstürzen führen
+
+- Erweiterung : Kommandozeilenoption, um CPU-Typ zu setzen
+
+- Erweiterung : In der Kommandozeile kann ein Key-File referenziert werden
+
+- Erweiterung : In der Kommandozeile kann die Zieldatei für Shared-Definitionen
+ gesetzt werden
+
+20. 4.1999 [Bld 11]
+
+- Bugfix : Parameterbereich B_RST für Ziel SC14xxx falsch
+
+ 2. 5.1999 [Bld 12]
+
+- Erweiterung : WRAPMODE-Befehl fuer Atmel AVR
+
+- Änderung : In Atmel-Debugfiles wird für jedes Wort eines Maschinenbefehls ein
+ Record geschrieben, nicht mehr nur für das erste
+
+ 6. 7.1999 [Bld 14]
+
+- Erweiterung : Unterstützung der TMS320C20x-Befehlsuntermenge
+
+- Erweiterung : hexadezimale Adressangaben für die Hilfsprogramm können jetzt
+ auch in C-Notation gemacht werden
+
+- Erweiterung : OUTRADIX-Befehl
+
+- Änderung : Syntax für 4004-Registerpaare ist jetzt R[02468ABCE]R[13579BDF]
+
+- Erweiterung : Unterstützung Fujitsu F²MC8L
+
+- Bugfix : FMOVE <ea>,FPm funktionierte mit <ea> = D1 nicht (680x0)
+
+- Bugfix : FSMOVE und FDMOVE fuer 68040 fehlten noch
+
+- Erweiterung : Kommandozeilenoption für P2HEX, um Minimalgröße S-Records zu
+ setzen
+
+- Bugfix : -l - Option in P2HEX funktionierte nicht
+
+15. 9.1999 [Bld 15]
+
+- Erweiterung : Fairchild ACE als Prozessorziel
+
+- Bugfix : Probleme mit dem NULL-Device und dem NLS-Support einiger Linux-
+ Distributionen behoben
+
+- Erweiterung : REG-Statement fuer PowerPCs
+
+- Bugfix : Registerpaarsyntax fuer 4004 korrigiert
+
+- Erweiterung : Minimalrecordlaenge fuer P2HEX
+
diff --git a/chardefs.h b/chardefs.h
new file mode 100644
index 0000000..2187923
--- /dev/null
+++ b/chardefs.h
@@ -0,0 +1,237 @@
+#ifndef _chardefs_h
+#define _chardefs_h
+
+#ifdef CHARSET_ISO8859_1
+#define CH_ae "\344"
+#define CH_ee "\353"
+#define CH_ie "\357"
+#define CH_oe "\366"
+#define CH_ue "\374"
+#define CH_Ae "\304"
+#define CH_Ee "\313"
+#define CH_Ie "\317"
+#define CH_Oe "\326"
+#define CH_Ue "\334"
+#define CH_sz "\337"
+#define CH_e2 "\262"
+#define CH_mu "\265"
+#define CH_agrave "\340"
+#define CH_Agrave "\300"
+#define CH_egrave "\350"
+#define CH_Egrave "\310"
+#define CH_igrave "\354"
+#define CH_Igrave "\314"
+#define CH_ograve "\362"
+#define CH_Ograve "\322"
+#define CH_ugrave "\371"
+#define CH_Ugrave "\331"
+#define CH_aacute "\341"
+#define CH_Aacute "\301"
+#define CH_eacute "\351"
+#define CH_Eacute "\311"
+#define CH_iacute "\355"
+#define CH_Iacute "\315"
+#define CH_oacute "\363"
+#define CH_Oacute "\323"
+#define CH_uacute "\372"
+#define CH_Uacute "\332"
+#define CH_acirc "\342"
+#define CH_Acirc "\302"
+#define CH_ecirc "\352"
+#define CH_Ecirc "\312"
+#define CH_icirc "\356"
+#define CH_Icirc "\316"
+#define CH_ocirc "\364"
+#define CH_Ocirc "\324"
+#define CH_ucirc "\373"
+#define CH_Ucirc "\333"
+#define CH_ccedil "\347"
+#define CH_Ccedil "\307"
+#define CH_ntilde "\361"
+#define CH_Ntilde "\321"
+#define CH_aring "\345"
+#define CH_Aring "\305"
+#define CH_aelig "\346"
+#define CH_Aelig "\306"
+#define CH_oslash "\370"
+#define CH_Oslash "\330"
+#define CH_iquest "\277"
+#define CH_iexcl "\241"
+#endif
+
+#ifdef CHARSET_IBM437
+#define CH_ae "\204"
+#define CH_ee "\211"
+#define CH_ie "\213"
+#define CH_oe "\224"
+#define CH_ue "\201"
+#define CH_Ae "\216"
+#define CH_Ee "Ee"
+#define CH_Ie "Ie"
+#define CH_Oe "\231"
+#define CH_Ue "\232"
+#define CH_sz "\341"
+#define CH_e2 "\375"
+#define CH_mu "\346"
+#define CH_agrave "\205"
+#define CH_Agrave "`A"
+#define CH_egrave "\212"
+#define CH_Egrave "`E"
+#define CH_igrave "\215"
+#define CH_Igrave "`I"
+#define CH_ograve "\225"
+#define CH_Ograve "`O"
+#define CH_ugrave "\227"
+#define CH_Ugrave "\`U"
+#define CH_aacute "\240"
+#define CH_Aacute "'A"
+#define CH_eacute "\202"
+#define CH_Eacute "\220"
+#define CH_iacute "\241"
+#define CH_Iacute "'I"
+#define CH_oacute "\242"
+#define CH_Oacute "'O"
+#define CH_uacute "\243"
+#define CH_Uacute "'U"
+#define CH_acirc "\203"
+#define CH_Acirc "^A"
+#define CH_ecirc "\210"
+#define CH_Ecirc "^E"
+#define CH_icirc "\214"
+#define CH_Icirc "^I"
+#define CH_ocirc "\223"
+#define CH_Ocirc "^O"
+#define CH_ucirc "\226"
+#define CH_Ucirc "\^U"
+#define CH_ccedil "\207"
+#define CH_Ccedil "\200"
+#define CH_ntilde "\244"
+#define CH_Ntilde "\245"
+#define CH_aring "\206"
+#define CH_Aring "\217"
+#define CH_aelig "\221"
+#define CH_Aelig "\222"
+#define CH_oslash "o"
+#define CH_Oslash "O"
+#define CH_iquest "\250"
+#define CH_iexcl "\255"
+#endif
+
+#ifdef CHARSET_IBM850
+#define CH_ae "\204"
+#define CH_ee "\211"
+#define CH_ie "\213"
+#define CH_oe "\224"
+#define CH_ue "\201"
+#define CH_Ae "\216"
+#define CH_Ee "\323"
+#define CH_Ie "\330"
+#define CH_Oe "\231"
+#define CH_Ue "\232"
+#define CH_sz "\341"
+#define CH_e2 "\375"
+#define CH_mu "\346"
+#define CH_agrave "\205"
+#define CH_Agrave "\267"
+#define CH_egrave "\212"
+#define CH_Egrave "\324"
+#define CH_igrave "\215"
+#define CH_Igrave "\336"
+#define CH_ograve "\225"
+#define CH_Ograve "\343"
+#define CH_ugrave "\227"
+#define CH_Ugrave "\353"
+#define CH_aacute "\240"
+#define CH_Aacute "\265"
+#define CH_eacute "\202"
+#define CH_Eacute "\220"
+#define CH_iacute "\241"
+#define CH_Iacute "\326"
+#define CH_oacute "\242"
+#define CH_Oacute "\340"
+#define CH_uacute "\243"
+#define CH_Uacute "\351"
+#define CH_acirc "\203"
+#define CH_Acirc "\266"
+#define CH_ecirc "\210"
+#define CH_Ecirc "\322"
+#define CH_icirc "\214"
+#define CH_Icirc "\327"
+#define CH_ocirc "\223"
+#define CH_Ocirc "\342"
+#define CH_ucirc "\226"
+#define CH_Ucirc "\352"
+#define CH_ccedil "\207"
+#define CH_Ccedil "\200"
+#define CH_ntilde "\244"
+#define CH_Ntilde "\245"
+#define CH_aring "\206"
+#define CH_Aring "\217"
+#define CH_aelig "\221"
+#define CH_Aelig "\222"
+#define CH_oslash "\233"
+#define CH_Oslash "\235"
+#define CH_iquest "\250"
+#define CH_iexcl "\255"
+#endif
+
+#ifdef CHARSET_ASCII7
+#define CH_ae "ae"
+#define CH_ee "ee"
+#define CH_ie "ie"
+#define CH_oe "oe"
+#define CH_ue "ue"
+#define CH_Ae "Ae"
+#define CH_Ee "Ee"
+#define CH_Ie "Ie"
+#define CH_Oe "Oe"
+#define CH_Ue "Ue"
+#define CH_sz "ss"
+#define CH_e2 "^2"
+#define CH_mu "u"
+#define CH_agrave "`a"
+#define CH_Agrave "`A"
+#define CH_egrave "`e"
+#define CH_Egrave "`E"
+#define CH_igrave "`i"
+#define CH_Igrave "`I"
+#define CH_ograve "`o"
+#define CH_Ograve "`O"
+#define CH_ugrave "`u"
+#define CH_Ugrave "`U"
+#define CH_aacute "'a"
+#define CH_Aacute "'A"
+#define CH_eacute "'e"
+#define CH_Eacute "'E"
+#define CH_iacute "'i"
+#define CH_Iacute "'I"
+#define CH_oacute "'o"
+#define CH_Oacute "'O"
+#define CH_uacute "'u"
+#define CH_Uacute "'U"
+#define CH_acirc "^a"
+#define CH_Acirc "^A"
+#define CH_ecirc "^e"
+#define CH_Ecirc "^E"
+#define CH_icirc "^i"
+#define CH_Icirc "^I"
+#define CH_ocirc "^o"
+#define CH_Ocirc "^O"
+#define CH_ucirc "^u"
+#define CH_Ucirc "^U"
+#define CH_ccedil "c"
+#define CH_Ccedil "C"
+#define CH_ntilde "~n"
+#define CH_Ntilde "~N"
+#define CH_aring "a"
+#define CH_Aring "A"
+#define CH_aelig "ae"
+#define CH_Aelig "AE"
+#define CH_oslash "o"
+#define CH_Oslash "O"
+#define CH_iquest "!"
+#define CH_iexcl "?"
+#endif
+
+#endif /* _chardefs_h */
+
diff --git a/chunks.c b/chunks.c
new file mode 100644
index 0000000..e92a9dc
--- /dev/null
+++ b/chunks.c
@@ -0,0 +1,228 @@
+/* chunks.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung von Adressbereichslisten */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* 16. 8.1998 Min/Max-Ausgabe */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include "strutil.h"
+
+#include "chunks.h"
+
+/*--------------------------------------------------------------------------*/
+/* eine Chunkliste initialisieren */
+
+ void InitChunk(ChunkList *NChunk)
+BEGIN
+ NChunk->RealLen=0;
+ NChunk->AllocLen=0;
+ NChunk->Chunks=Nil;
+END
+
+ void ClearChunk(ChunkList *NChunk)
+BEGIN
+ if (NChunk->AllocLen>0) free(NChunk->Chunks);
+ InitChunk(NChunk);
+END
+
+/*--------------------------------------------------------------------------*/
+/* eine Chunkliste um einen Eintrag erweitern */
+
+ static Boolean Overlap(LargeWord Start1, LargeWord Len1, LargeWord Start2, LargeWord Len2)
+BEGIN
+ return ((Start1==Start2)
+ OR ((Start2>Start1) AND (Start1+Len1>=Start2))
+ OR ((Start1>Start2) AND (Start2+Len2>=Start1)));
+END
+
+ static void SetChunk(OneChunk *NChunk, LargeWord Start1, LargeWord Len1,
+ LargeWord Start2, LargeWord Len2)
+BEGIN
+ NChunk->Start =min(Start1,Start2);
+ NChunk->Length=max(Start1+Len1-1,Start2+Len2-1)-NChunk->Start+1;
+END
+
+ static void IncChunk(ChunkList *NChunk)
+BEGIN
+ if (NChunk->RealLen+1>NChunk->AllocLen)
+ BEGIN
+ if (NChunk->RealLen==0)
+ NChunk->Chunks=(OneChunk *) malloc(sizeof(OneChunk));
+ else
+ NChunk->Chunks=(OneChunk *) realloc(NChunk->Chunks,sizeof(OneChunk)*(NChunk->RealLen+1));
+ NChunk->AllocLen=NChunk->RealLen+1;
+ END
+END
+
+ Boolean AddChunk(ChunkList *NChunk, LargeWord NewStart, LargeWord NewLen, Boolean Warn)
+BEGIN
+ Word z,f1=0,f2=0;
+ Boolean Found;
+ LongInt PartSum;
+ Boolean Result;
+
+ Result=False;
+
+ if (NewLen==0) return Result;
+
+ /* herausfinden, ob sich das neue Teil irgendwo mitanhaengen laesst */
+
+ Found=False;
+ for (z=0; z<NChunk->RealLen; z++)
+ if (Overlap(NewStart,NewLen,NChunk->Chunks[z].Start,NChunk->Chunks[z].Length))
+ BEGIN
+ Found=True; f1=z; break;
+ END
+
+ /* Fall 1: etwas gefunden : */
+
+ if (Found)
+ BEGIN
+ /* gefundene Chunk erweitern */
+
+ PartSum=NChunk->Chunks[f1].Length+NewLen;
+ SetChunk(NChunk->Chunks+f1,NewStart,NewLen,NChunk->Chunks[f1].Start,NChunk->Chunks[f1].Length);
+ if (Warn)
+ if (PartSum!=NChunk->Chunks[f1].Length) Result=True;
+
+ /* schauen, ob sukzessiv neue Chunks angebunden werden koennen */
+
+ do
+ BEGIN
+ Found=False;
+ for (z=1; z<NChunk->RealLen; z++)
+ if (z!=f1)
+ if (Overlap(NChunk->Chunks[z].Start,NChunk->Chunks[z].Length,NChunk->Chunks[f1].Start,NChunk->Chunks[f1].Length))
+ BEGIN
+ Found=True; f2=z; break;
+ END
+ if (Found)
+ BEGIN
+ SetChunk(NChunk->Chunks+f1,NChunk->Chunks[f1].Start,NChunk->Chunks[f1].Length,NChunk->Chunks[f2].Start,NChunk->Chunks[f2].Length);
+ NChunk->Chunks[f2]=NChunk->Chunks[--NChunk->RealLen];
+ END
+ END
+ while (Found);
+ END
+
+ /* ansonsten Feld erweitern und einschreiben */
+
+ else
+ BEGIN
+ IncChunk(NChunk);
+
+ NChunk->Chunks[NChunk->RealLen].Length=NewLen;
+ NChunk->Chunks[NChunk->RealLen].Start=NewStart;
+ NChunk->RealLen++;
+ END
+
+ return Result;
+END
+
+/*--------------------------------------------------------------------------*/
+/* Ein Stueck wieder austragen */
+
+ void DeleteChunk(ChunkList *NChunk, LargeWord DelStart, LargeWord DelLen)
+BEGIN
+ Word z;
+ LargeWord OStart;
+
+ if (DelLen==0) return;
+
+ z=0;
+ while (z<=NChunk->RealLen)
+ BEGIN
+ if (Overlap(DelStart,DelLen,NChunk->Chunks[z].Start,NChunk->Chunks[z].Length))
+ BEGIN
+ if (NChunk->Chunks[z].Start>=DelStart)
+ if (DelStart+DelLen>=NChunk->Chunks[z].Start+NChunk->Chunks[z].Length)
+ BEGIN
+ /* ganz loeschen */
+ NChunk->Chunks[z]=NChunk->Chunks[--NChunk->RealLen];
+ END
+ else
+ BEGIN
+ /* unten abschneiden */
+ OStart=NChunk->Chunks[z].Start; NChunk->Chunks[z].Start=DelStart+DelLen;
+ NChunk->Chunks[z].Start-=NChunk->Chunks[z].Start-OStart;
+ END
+ else
+ if (DelStart+DelLen>=NChunk->Chunks[z].Start+NChunk->Chunks[z].Length)
+ BEGIN
+ /* oben abschneiden */
+ NChunk->Chunks[z].Length=DelStart-NChunk->Chunks[z].Start;
+ /* wenn Laenge 0, ganz loeschen */
+ if (NChunk->Chunks[z].Length==0)
+ BEGIN
+ NChunk->Chunks[z]=NChunk->Chunks[--NChunk->RealLen];
+ END
+ END
+ else
+ BEGIN
+ /* teilen */
+ IncChunk(NChunk);
+ NChunk->Chunks[NChunk->RealLen].Start=DelStart+DelLen;
+ NChunk->Chunks[NChunk->RealLen].Length=NChunk->Chunks[z].Start+NChunk->Chunks[z].Length-NChunk->Chunks[NChunk->RealLen].Start;
+ NChunk->Chunks[z].Length=DelStart-NChunk->Chunks[z].Start;
+ END
+ END
+ z++;
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+/* Minimaladresse holen */
+
+ LargeWord ChunkMin(ChunkList *NChunk)
+BEGIN
+ LongInt z;
+ LargeWord t=(LargeWord) -1;
+
+ if (NChunk->RealLen==0) return 0;
+
+ for (z=0; z<NChunk->RealLen; z++)
+ if (NChunk->Chunks[z].Start<t) t=NChunk->Chunks[z].Start;
+
+ return t;
+END
+
+/*--------------------------------------------------------------------------*/
+/* Maximaladresse holen */
+
+ LargeWord ChunkMax(ChunkList *NChunk)
+BEGIN
+ LongInt z;
+ LargeWord t=(LargeWord) 0;
+
+ if (NChunk->RealLen==0) return 0;
+
+ for (z=0; z<NChunk->RealLen; z++)
+ if (NChunk->Chunks[z].Start+NChunk->Chunks[z].Length-1>t)
+ t=NChunk->Chunks[z].Start+NChunk->Chunks[z].Length-1;
+
+ return t;
+END
+
+/*--------------------------------------------------------------------------*/
+/* Menge holen */
+
+ LargeWord ChunkSum(ChunkList *NChunk)
+BEGIN
+ LongInt z;
+ LargeWord Sum=0;
+
+ for (z=0; z<NChunk->RealLen; z++)
+ Sum+=NChunk->Chunks[z].Length;
+
+ return Sum;
+END
+
+ void chunks_init(void)
+BEGIN
+END
diff --git a/chunks.h b/chunks.h
new file mode 100644
index 0000000..6027ad7
--- /dev/null
+++ b/chunks.h
@@ -0,0 +1,44 @@
+#ifndef _CHUNKS_H
+#define _CHUNKS_H
+
+/* chunks.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung von Adressbereichslisten */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* 16. 8.1998 Min/Max-Ausgabe */
+/* */
+/*****************************************************************************/
+
+typedef struct
+ {
+ LargeWord Start,Length;
+ } OneChunk;
+
+typedef struct
+ {
+ Word RealLen,AllocLen;
+ OneChunk *Chunks;
+ } ChunkList;
+
+
+extern Boolean AddChunk(ChunkList *NChunk, LargeWord NewStart, LargeWord NewLen, Boolean Warn);
+
+extern void DeleteChunk(ChunkList *NChunk, LargeWord DelStart, LargeWord DelLen);
+
+extern void InitChunk(ChunkList *NChunk);
+
+extern void ClearChunk(ChunkList *NChunk);
+
+extern LargeWord ChunkMin(ChunkList *NChunk);
+
+extern LargeWord ChunkMax(ChunkList *NChunk);
+
+extern LargeWord ChunkSum(ChunkList *NChunk);
+
+
+extern void chunks_init(void);
+
+#endif /* _CHUNKS_H */
diff --git a/cmdarg.c b/cmdarg.c
new file mode 100644
index 0000000..5ac02ee
--- /dev/null
+++ b/cmdarg.c
@@ -0,0 +1,222 @@
+/* cmdarg.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verarbeitung Kommandozeilenparameter */
+/* */
+/* Historie: 4. 5.1996 Grundsteinlegung */
+/* 1. 6.1996 Empty-Funktion */
+/* 17. 4.1999 Key-Files in Kommandozeile */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "strutil.h"
+#include "cmdarg.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "cmdarg.rsc"
+
+LongInt ParamCount; /* Kommandozeilenparameter */
+char **ParamStr;
+
+TMsgCat MsgCat;
+
+ static void ClrBlanks(char *tmp)
+BEGIN
+ int cnt;
+
+ for (cnt=0; isspace((unsigned int) tmp[cnt]); cnt++);
+ if (cnt>0) strcpy(tmp,tmp+cnt);
+END
+
+ Boolean ProcessedEmpty(CMDProcessed Processed)
+BEGIN
+ int z;
+
+ for (z=1; z<=ParamCount; z++)
+ if (Processed[z]) return False;
+ return True;
+END
+
+ static void ProcessFile(char *Name_O, CMDRec *Def, Integer Cnt, CMDErrCallback ErrProc);
+
+ static CMDResult ProcessParam(CMDRec *Def, Integer Cnt, char *O_Param,
+ char *O_Next, Boolean AllowLink,
+ CMDErrCallback ErrProc)
+BEGIN
+ int Start;
+ Boolean Negate;
+ int z,Search;
+ CMDResult TempRes;
+ String s,Param,Next;
+
+ strncpy(Param,O_Param,255);
+ strncpy(Next,O_Next,255);
+
+ if ((*Next == '-') OR (*Next == '+') OR (*Next == '@')) *Next = '\0';
+ if (*Param == '@')
+ BEGIN
+ if (AllowLink)
+ BEGIN
+ ProcessFile(Param + 1, Def, Cnt, ErrProc);
+ return CMDOK;
+ END
+ else
+ BEGIN
+ fprintf(stderr, "%s\n", catgetmessage(&MsgCat, Num_ErrMsgNoKeyInFile));
+ return CMDErr;
+ END
+ END
+ if ((*Param == '-') OR (*Param == '+'))
+ BEGIN
+ Negate=(*Param=='+'); Start=1;
+
+ if (Param[Start]=='#')
+ BEGIN
+ for (z=Start+1; z<strlen(Param); z++) Param[z]=toupper(Param[z]);
+ Start++;
+ END
+ else if (Param[Start]=='~')
+ BEGIN
+ for (z=Start+1; z<strlen(Param); z++) Param[z]=tolower(Param[z]);
+ Start++;
+ END
+
+ TempRes=CMDOK;
+
+ Search=0;
+ strncpy(s,Param+Start,255);
+ for (z=0; z<strlen(s); z++) s[z]=toupper(s[z]);
+ for (Search=0; Search<Cnt; Search++)
+ if ((strlen(Def[Search].Ident)>1) AND (strcmp(s,Def[Search].Ident)==0)) break;
+ if (Search<Cnt)
+ TempRes=Def[Search].Callback(Negate,Next);
+
+ else
+ for (z=Start; z<strlen(Param); z++)
+ if (TempRes!=CMDErr)
+ BEGIN
+ Search=0;
+ for (Search=0; Search<Cnt; Search++)
+ if ((strlen(Def[Search].Ident)==1) AND (Def[Search].Ident[0]==Param[z])) break;
+ if (Search>=Cnt) TempRes=CMDErr;
+ else
+ switch (Def[Search].Callback(Negate,Next))
+ BEGIN
+ case CMDErr: TempRes=CMDErr; break;
+ case CMDArg: TempRes=CMDArg; break;
+ case CMDOK: break;
+ case CMDFile: break; /** **/
+ END
+ END
+ return TempRes;
+ END
+ else return CMDFile;
+END
+
+ static void DecodeLine(CMDRec *Def, Integer Cnt, char *OneLine,
+ CMDErrCallback ErrProc)
+BEGIN
+ int z;
+ char *EnvStr[256],*start,*p;
+ int EnvCnt=0;
+
+ ClrBlanks(OneLine);
+ if ((*OneLine!='\0') AND (*OneLine!=';'))
+ BEGIN
+ start=OneLine;
+ while (*start!='\0')
+ BEGIN
+ EnvStr[EnvCnt++]=start;
+ p=strchr(start,' '); if (p==Nil) p=strchr(start, '\t');
+ if (p!=Nil)
+ BEGIN
+ *p='\0'; start=p+1;
+ while (isspace((unsigned int) *start)) start++;
+ END
+ else start+=strlen(start);
+ END
+ EnvStr[EnvCnt]=start;
+
+ for (z=0; z<EnvCnt; z++)
+ switch (ProcessParam(Def, Cnt, EnvStr[z], EnvStr[z+1], False, ErrProc))
+ BEGIN
+ case CMDErr:
+ case CMDFile: ErrProc(True,EnvStr[z]); break;
+ case CMDArg: z++; break;
+ case CMDOK: break;
+ END
+ END
+END
+
+ static void ProcessFile(char *Name_O, CMDRec *Def, Integer Cnt, CMDErrCallback ErrProc)
+BEGIN
+ FILE *KeyFile;
+ String Name, OneLine;
+
+ strmaxcpy(Name, Name_O, 255);
+ ClrBlanks(OneLine);
+
+ KeyFile=fopen(Name, "r");
+ if (KeyFile == Nil) ErrProc(True, catgetmessage(&MsgCat, Num_ErrMsgKeyFileNotFound));
+ while (NOT feof(KeyFile))
+ BEGIN
+ errno = 0; ReadLn(KeyFile, OneLine);
+ if ((errno != 0) AND (NOT feof(KeyFile)))
+ ErrProc(True, catgetmessage(&MsgCat, Num_ErrMsgKeyFileError));
+ DecodeLine(Def, Cnt, OneLine, ErrProc);
+ END
+ fclose(KeyFile);
+END
+
+ void ProcessCMD(CMDRec *Def, Integer Cnt, CMDProcessed Unprocessed,
+ char *EnvName, CMDErrCallback ErrProc)
+BEGIN
+ int z;
+ String OneLine;
+
+ if (getenv(EnvName)==Nil) OneLine[0]='\0';
+ else strncpy(OneLine,getenv(EnvName),255);
+
+ if (OneLine[0]=='@')
+ ProcessFile(OneLine + 1, Def, Cnt, ErrProc);
+ else DecodeLine(Def,Cnt,OneLine,ErrProc);
+
+ for (z=0; z<=ParamCount; Unprocessed[z++]=(z!=0));
+ for (z=1; z<=ParamCount; z++)
+ if (Unprocessed[z])
+ switch (ProcessParam(Def, Cnt, ParamStr[z], (z < ParamCount) ? ParamStr[z + 1] : "",
+ True, ErrProc))
+ BEGIN
+ case CMDErr: ErrProc(False,ParamStr[z]); break;
+ case CMDOK: Unprocessed[z]=False; break;
+ case CMDArg: Unprocessed[z]=Unprocessed[z+1]=False; break;
+ case CMDFile: break; /** **/
+ END
+END
+
+ char *GetEXEName(void)
+BEGIN
+ static String s;
+ char *pos;
+
+ strcpy(s,ParamStr[0]);
+ do
+ BEGIN
+ pos=strchr(s,'/');
+ if (pos!=Nil) strcpy(s,pos+1);
+ END
+ while (pos!=Nil);
+ pos=strchr(s,'.'); if (pos!=Nil) *pos='\0';
+ return s;
+END
+
+ void cmdarg_init(char *ProgPath)
+BEGIN
+ opencatalog(&MsgCat,"cmdarg.msg",ProgPath,MsgId1,MsgId2);
+END
+
diff --git a/cmdarg.h b/cmdarg.h
new file mode 100644
index 0000000..fe67d4a
--- /dev/null
+++ b/cmdarg.h
@@ -0,0 +1,46 @@
+/* cmdarg.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verarbeitung Kommandozeilenparameter */
+/* */
+/* Historie: 4. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+typedef enum {CMDErr,CMDFile,CMDOK,CMDArg} CMDResult;
+
+typedef CMDResult (*CMDCallback)(
+#ifdef __PROTOS__
+Boolean NegFlag, char *Arg
+#endif
+);
+
+typedef void (*CMDErrCallback)
+(
+#ifdef __PROTOS__
+Boolean InEnv, char *Arg
+#endif
+);
+
+typedef struct
+ {
+ char Ident[11];
+ CMDCallback Callback;
+ } CMDRec;
+
+#define MAXPARAM 256
+typedef Boolean CMDProcessed[MAXPARAM+1];
+
+extern LongInt ParamCount;
+extern char **ParamStr;
+
+
+extern Boolean ProcessedEmpty(CMDProcessed Processed);
+
+extern void ProcessCMD(CMDRec *Def, Integer Cnt, CMDProcessed Unprocessed,
+ char *EnvName, CMDErrCallback ErrProc);
+
+extern char *GetEXEName(void);
+
+extern void cmdarg_init(char *ProgPath);
diff --git a/cmdarg.res b/cmdarg.res
new file mode 100644
index 0000000..740a09a
--- /dev/null
+++ b/cmdarg.res
@@ -0,0 +1,24 @@
+;* decodecmd.res
+;*****************************************************************************
+;* AS-Portierung *
+;* *
+;* Definition der Fehlermeldungen, die beim Einlesen auftreten koennen *
+;* *
+;* Historie: 5. 5.1996 Grundsteinlegung *
+;* 18. 4.1999 Fehlermeldung Indirektion im Key-File *
+;* *
+;*****************************************************************************
+
+Include header.res
+
+Message ErrMsgKeyFileNotFound
+ "Key-Datei nicht gefunden"
+ "key file not found"
+
+Message ErrMsgKeyFileError
+ "Fehler beim Lesen der Key-Datei"
+ "error reading key file"
+
+Message ErrMsgNoKeyInFile
+ "Referenz auf Key-Datei in Key-Datei nicht erlaubt"
+ "no references to a key file from inside a key file"
diff --git a/code166.c b/code166.c
new file mode 100644
index 0000000..edf95af
--- /dev/null
+++ b/code166.c
@@ -0,0 +1,1697 @@
+/* code166.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegenerator Siemens 80C16x */
+/* */
+/* Historie: 11.11.1996 (alaaf) Grundsteinlegung */
+/* 9. 5.1998 Registersymbole */
+/* 3. 1.1999 ChkPC angepasst */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Word Code1,Code2;
+ } BaseOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } SimpOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } Condition;
+
+
+#define FixedOrderCount 10
+#define ConditionCount 20
+#define ALU2OrderCount 8
+#define ShiftOrderCount 5
+#define Bit2OrderCount 6
+#define LoopOrderCount 4
+#define DivOrderCount 4
+#define BJmpOrderCount 4
+#define MulOrderCount 3
+
+#define DPPCount 4
+static char *RegNames[6]={"DPP0","DPP1","DPP2","DPP3","CP","SP"};
+
+static CPUVar CPU80C166,CPU80C167;
+
+static BaseOrder *FixedOrders;
+static Condition *Conditions;
+static int TrueCond;
+static char **ALU2Orders;
+static SimpOrder *ShiftOrders;
+static SimpOrder *Bit2Orders;
+static SimpOrder *LoopOrders;
+static char **DivOrders;
+static char **BJmpOrders;
+static char **MulOrders;
+
+static SimpProc SaveInitProc;
+static LongInt DPPAssumes[DPPCount];
+static IntType MemInt,MemInt2;
+static Byte OpSize;
+
+static Boolean DPPChanged[DPPCount],N_DPPChanged[DPPCount];
+static Boolean SPChanged,CPChanged,N_SPChanged,N_CPChanged;
+
+static ShortInt ExtCounter;
+static enum {MemModeStd,MemModeNoCheck,MemModeZeroPage,MemModeFixedBank,MemModeFixedPage} MemMode;
+ /* normal EXTS Rn EXTP Rn EXTS nn EXTP nn */
+static Word MemPage;
+static Boolean ExtSFRs;
+
+/*-------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, CPUVar NMin, Word NCode1, Word NCode2)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].MinCPU=NMin;
+ FixedOrders[InstrZ].Code1=NCode1;
+ FixedOrders[InstrZ++].Code2=NCode2;
+END
+
+ static void AddShift(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ShiftOrderCount) exit(255);
+ ShiftOrders[InstrZ].Name=NName;
+ ShiftOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddBit2(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=Bit2OrderCount) exit(255);
+ Bit2Orders[InstrZ].Name=NName;
+ Bit2Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddLoop(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=LoopOrderCount) exit(255);
+ LoopOrders[InstrZ].Name=NName;
+ LoopOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddCondition(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ConditionCount) exit(255);
+ Conditions[InstrZ].Name=NName;
+ Conditions[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(BaseOrder *) malloc(FixedOrderCount*sizeof(BaseOrder)); InstrZ=0;
+ AddFixed("DISWDT",CPU80C166,0x5aa5,0xa5a5);
+ AddFixed("EINIT" ,CPU80C166,0x4ab5,0xb5b5);
+ AddFixed("IDLE" ,CPU80C166,0x7887,0x8787);
+ AddFixed("NOP" ,CPU80C166,0x00cc,0x0000);
+ AddFixed("PWRDN" ,CPU80C166,0x6897,0x9797);
+ AddFixed("RET" ,CPU80C166,0x00cb,0x0000);
+ AddFixed("RETI" ,CPU80C166,0x88fb,0x0000);
+ AddFixed("RETS" ,CPU80C166,0x00db,0x0000);
+ AddFixed("SRST" ,CPU80C166,0x48b7,0xb7b7);
+ AddFixed("SRVWDT",CPU80C166,0x58a7,0xa7a7);
+
+ Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCount); InstrZ=0;
+ TrueCond=InstrZ; AddCondition("UC" ,0x0); AddCondition("Z" ,0x2);
+ AddCondition("NZ" ,0x3); AddCondition("V" ,0x4);
+ AddCondition("NV" ,0x5); AddCondition("N" ,0x6);
+ AddCondition("NN" ,0x7); AddCondition("C" ,0x8);
+ AddCondition("NC" ,0x9); AddCondition("EQ" ,0x2);
+ AddCondition("NE" ,0x3); AddCondition("ULT",0x8);
+ AddCondition("ULE",0xf); AddCondition("UGE",0x9);
+ AddCondition("UGT",0xe); AddCondition("SLT",0xc);
+ AddCondition("SLE",0xb); AddCondition("SGE",0xd);
+ AddCondition("SGT",0xa); AddCondition("NET",0x1);
+
+ ALU2Orders=(char **) malloc(sizeof(char *)*ALU2OrderCount); InstrZ=0;
+ ALU2Orders[InstrZ++]="ADD" ; ALU2Orders[InstrZ++]="ADDC";
+ ALU2Orders[InstrZ++]="SUB" ; ALU2Orders[InstrZ++]="SUBC";
+ ALU2Orders[InstrZ++]="CMP" ; ALU2Orders[InstrZ++]="XOR" ;
+ ALU2Orders[InstrZ++]="AND" ; ALU2Orders[InstrZ++]="OR" ;
+
+ ShiftOrders=(SimpOrder *) malloc(sizeof(SimpOrder)*ShiftOrderCount); InstrZ=0;
+ AddShift("ASHR",0xac); AddShift("ROL" ,0x0c);
+ AddShift("ROR" ,0x2c); AddShift("SHL" ,0x4c);
+ AddShift("SHR" ,0x6c);
+
+ Bit2Orders=(SimpOrder *) malloc(sizeof(SimpOrder)*Bit2OrderCount); InstrZ=0;
+ AddBit2("BAND",0x6a); AddBit2("BCMP" ,0x2a);
+ AddBit2("BMOV",0x4a); AddBit2("BMOVN",0x3a);
+ AddBit2("BOR" ,0x5a); AddBit2("BXOR" ,0x7a);
+
+ LoopOrders=(SimpOrder *) malloc(sizeof(SimpOrder)*LoopOrderCount); InstrZ=0;
+ AddLoop("CMPD1",0xa0); AddLoop("CMPD2",0xb0);
+ AddLoop("CMPI1",0x80); AddLoop("CMPI2",0x90);
+
+ DivOrders=(char **) malloc(sizeof(char *)*DivOrderCount); InstrZ=0;
+ DivOrders[InstrZ++]="DIV"; DivOrders[InstrZ++]="DIVU";
+ DivOrders[InstrZ++]="DIVL"; DivOrders[InstrZ++]="DIVLU";
+
+ BJmpOrders=(char **) malloc(sizeof(char *)*BJmpOrderCount); InstrZ=0;
+ BJmpOrders[InstrZ++]="JB"; BJmpOrders[InstrZ++]="JNB";
+ BJmpOrders[InstrZ++]="JBC"; BJmpOrders[InstrZ++]="JNBS";
+
+ MulOrders=(char **) malloc(sizeof(char *)*MulOrderCount); InstrZ=0;
+ MulOrders[InstrZ++]="MUL"; MulOrders[InstrZ++]="MULU";
+ MulOrders[InstrZ++]="PRIOR";
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(Conditions);
+ free(ALU2Orders);
+ free(ShiftOrders);
+ free(Bit2Orders);
+ free(LoopOrders);
+ free(DivOrders);
+ free(BJmpOrders);
+ free(MulOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModImm 1
+#define MModImm (1 << ModImm)
+#define ModIReg 2
+#define MModIReg (1 << ModIReg)
+#define ModPreDec 3
+#define MModPreDec (1 << ModPreDec)
+#define ModPostInc 4
+#define MModPostInc (1 << ModPostInc)
+#define ModIndex 5
+#define MModIndex (1 << ModIndex)
+#define ModAbs 6
+#define MModAbs (1 << ModAbs)
+#define ModMReg 7
+#define MModMReg (1 << ModMReg)
+#define ModLAbs 8
+#define MModLAbs (1 << ModLAbs)
+
+static Byte AdrMode;
+static Byte AdrVals[2];
+static ShortInt AdrType;
+
+ static Boolean IsReg(char *Asc, Byte *Erg, Boolean WordWise)
+BEGIN
+ Boolean err;
+ char *s;
+
+ if (FindRegDef(Asc,&s)) Asc=s;
+
+ if ((strlen(Asc)<2) OR (toupper(*Asc)!='R')) return False;
+ else if ((strlen(Asc)>2) AND (toupper(Asc[1])=='L') AND (NOT WordWise))
+ BEGIN
+ *Erg=ConstLongInt(Asc+2,&err); *Erg<<=1;
+ return ((err) AND (*Erg<=15));
+ END
+ else if ((strlen(Asc)>2) AND (toupper(Asc[1])=='H') AND (NOT WordWise))
+ BEGIN
+ *Erg=ConstLongInt(Asc+2,&err); *Erg<<=1; (*Erg)++;
+ return ((err) AND (*Erg<=15));
+ END
+ else
+ BEGIN
+ *Erg=ConstLongInt(Asc+1,&err);
+ return ((err) AND (*Erg<=15));
+ END
+END
+
+ static Boolean IsRegM1(char *Asc, Byte *Erg, Boolean WordWise)
+BEGIN
+ char tmp;
+ int l;
+ Boolean b;
+
+ if (*Asc!='\0')
+ BEGIN
+ tmp=Asc[l=(strlen(Asc)-1)]; Asc[l]='\0';
+ b=IsReg(Asc,Erg,WordWise);
+ Asc[l]=tmp;
+ return b;
+ END
+ else return False;
+END
+
+ static LongInt SFRStart(void)
+BEGIN
+ return (ExtSFRs) ? 0xf000 : 0xfe00;
+END
+
+ static LongInt SFREnd(void)
+BEGIN
+ return (ExtSFRs) ? 0xf1de : 0xffde;
+END
+
+ static Boolean CalcPage(LongInt *Adr, Boolean DoAnyway)
+BEGIN
+ int z;
+ Word Bank;
+
+ switch (MemMode)
+ BEGIN
+ case MemModeStd:
+ z=0;
+ while ((z<=3) AND (((*Adr) >> 14)!=DPPAssumes[z])) z++;
+ if (z>3)
+ BEGIN
+ WrError(110); (*Adr)&=0xffff; return (DoAnyway);
+ END
+ else
+ BEGIN
+ *Adr=((*Adr) & 0x3fff)+(z << 14);
+ if (DPPChanged[z]) WrXError(200,RegNames[z]);
+ return True;
+ END
+ case MemModeZeroPage:
+ (*Adr)&=0x3fff;
+ return True;
+ case MemModeFixedPage:
+ Bank=(*Adr) >> 14; (*Adr)&=0x3fff;
+ if (Bank!=MemPage)
+ BEGIN
+ WrError(110); return (DoAnyway);
+ END
+ else return True;
+ case MemModeNoCheck:
+ (*Adr)&=0xffff;
+ return True;
+ case MemModeFixedBank:
+ Bank=(*Adr) >> 16; (*Adr)&=0xffff;
+ if (Bank!=MemPage)
+ BEGIN
+ WrError(110); return (DoAnyway);
+ END
+ else return True;
+ default:
+ return False;
+ END
+END
+
+ static void DecideAbsolute(Boolean InCode, LongInt DispAcc, Word Mask, Boolean Dest)
+BEGIN
+#define DPPAdr 0xfe00
+#define SPAdr 0xfe12
+#define CPAdr 0xfe10
+
+ int z;
+
+ if (InCode)
+ if (((EProgCounter() >> 16)==(DispAcc >> 16)) AND ((Mask & MModAbs)!=0))
+ BEGIN
+ AdrType=ModAbs; AdrCnt=2;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc);
+ END
+ else
+ BEGIN
+ AdrType=ModLAbs; AdrCnt=2; AdrMode=DispAcc >> 16;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc);
+ END
+ else if (((Mask & MModMReg)!=0) AND (DispAcc>=SFRStart()) AND (DispAcc<=SFREnd()) AND ((DispAcc&1)==0))
+ BEGIN
+ AdrType=ModMReg; AdrCnt=1; AdrVals[0]=(DispAcc-SFRStart()) >> 1;
+ END
+ else switch (MemMode)
+ BEGIN
+ case MemModeStd:
+ z=0;
+ while ((z<=3) AND ((DispAcc >> 14)!=DPPAssumes[z])) z++;
+ if (z>3)
+ BEGIN
+ WrError(110); z=(DispAcc >> 14) & 3;
+ END
+ AdrType=ModAbs; AdrCnt=2;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=(Hi(DispAcc) & 0x3f)+(z << 6);
+ if (DPPChanged[z]) WrXError(200,RegNames[z]);
+ break;
+ case MemModeZeroPage:
+ AdrType=ModAbs; AdrCnt=2;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc) & 0x3f;
+ break;
+ case MemModeFixedPage:
+ if ((DispAcc >> 14)!=MemPage) WrError(110);
+ AdrType=ModAbs; AdrCnt=2;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc) & 0x3f;
+ break;
+ case MemModeNoCheck:
+ AdrType=ModAbs; AdrCnt=2;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc);
+ break;
+ case MemModeFixedBank:
+ if ((DispAcc >> 16)!=MemPage) WrError(110);
+ AdrType=ModAbs; AdrCnt=2;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc);
+ break;
+ END
+
+ if ((AdrType!=ModNone) AND (Dest))
+ switch ((Word)DispAcc)
+ BEGIN
+ case SPAdr : N_SPChanged=True; break;
+ case CPAdr : N_CPChanged=True; break;
+ case DPPAdr :
+ case DPPAdr+1 : N_DPPChanged[0]=True; break;
+ case DPPAdr+2 :
+ case DPPAdr+3 : N_DPPChanged[1]=True; break;
+ case DPPAdr+4 :
+ case DPPAdr+5 : N_DPPChanged[2]=True; break;
+ case DPPAdr+6 :
+ case DPPAdr+7 : N_DPPChanged[3]=True; break;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask, Boolean InCode, Boolean Dest)
+BEGIN
+ LongInt HDisp,DispAcc;
+ char *PPos,*MPos;
+ String Part;
+ Boolean OK,NegFlag,NNegFlag;
+ Byte HReg;
+
+ AdrType=ModNone; AdrCnt=0;
+
+ /* immediate ? */
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ AdrVals[1]=0;
+ break;
+ case 1:
+ HDisp=EvalIntExpression(Asc+1,Int16,&OK);
+ AdrVals[0]=Lo(HDisp); AdrVals[1]=Hi(HDisp);
+ break;
+ END
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=OpSize+1;
+ END
+ END
+
+ /* Register ? */
+
+ else if (IsReg(Asc,&AdrMode,OpSize==1))
+ BEGIN
+ if ((Mask & MModReg)!=0) AdrType=ModReg;
+ else
+ BEGIN
+ AdrType=ModMReg; AdrVals[0]=0xf0+AdrMode; AdrCnt=1;
+ END
+ if (CPChanged) WrXError(200,RegNames[4]);
+ END
+
+ /* indirekt ? */
+
+ else if ((*Asc=='[') AND (Asc[strlen(Asc)-1]==']'))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+
+ /* Predekrement ? */
+
+ if ((strlen(Asc)>2) AND (*Asc=='-') AND (IsReg(Asc+1,&AdrMode,True)))
+ AdrType=ModPreDec;
+
+ /* Postinkrement ? */
+
+ else if ((strlen(Asc)>2) AND (Asc[strlen(Asc)-1]=='+') AND (IsRegM1(Asc,&AdrMode,True)))
+ AdrType=ModPostInc;
+
+ /* indiziert ? */
+
+ else
+ BEGIN
+ NegFlag=False; DispAcc=0; AdrMode=0xff;
+ while (*Asc!='\0')
+ BEGIN
+ MPos=QuotPos(Asc,'-'); PPos=QuotPos(Asc,'+');
+ if (((MPos<PPos) OR (PPos==Nil)) AND (MPos!=Nil))
+ BEGIN
+ PPos=MPos; NNegFlag=True;
+ END
+ else NNegFlag=False;
+ if (PPos==Nil)
+ BEGIN
+ strmaxcpy(Part,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *PPos='\0'; strmaxcpy(Part,Asc,255); strcpy(Asc,PPos+1);
+ END
+ if (IsReg(Part,&HReg,True))
+ if ((NegFlag) OR (AdrMode!=0xff)) WrError(1350); else AdrMode=HReg;
+ else
+ BEGIN
+ if (*Part=='#') strcpy(Part,Part+1);
+ HDisp=EvalIntExpression(Part,Int32,&OK);
+ if (OK)
+ if (NegFlag) DispAcc-=HDisp; else DispAcc+=HDisp;
+ END
+ NegFlag=NNegFlag;
+ END
+ if (AdrMode==0xff) DecideAbsolute(InCode,DispAcc,Mask,Dest);
+ else if (DispAcc==0) AdrType=ModIReg;
+ else if (DispAcc>0xffff) WrError(1320);
+ else if (DispAcc<-0x8000l) WrError(1315);
+ else
+ BEGIN
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc);
+ AdrType=ModIndex; AdrCnt=2;
+ END
+ END
+ END
+ else
+ BEGIN
+ DispAcc=EvalIntExpression(Asc,MemInt,&OK);
+ if (OK) DecideAbsolute(InCode,DispAcc,Mask,Dest);
+ END
+
+ if ((AdrType!=ModNone) AND (((1 << AdrType) & Mask)==0))
+ BEGIN
+ WrError(1350); AdrType=ModNone; AdrCnt=0;
+ END
+END
+
+ static int DecodeCondition(char *Name)
+BEGIN
+ int z;
+
+ NLS_UpString(Name);
+ for (z=0; z<ConditionCount; z++)
+ if (strcmp(Conditions[z].Name,Name)==0) break;
+ return z;
+END
+
+ static Boolean DecodeBitAddr(char *Asc, Word *Adr, Byte *Bit, Boolean MayBeOut)
+BEGIN
+ char *p;
+ Word LAdr;
+ Byte Reg;
+ Boolean OK;
+
+ p=QuotPos(Asc,'.');
+ if (p==Nil)
+ BEGIN
+ LAdr=EvalIntExpression(Asc,UInt16,&OK) & 0x1fff;
+ if (OK)
+ BEGIN
+ if ((NOT MayBeOut) AND ((LAdr >> 12)!=Ord(ExtSFRs)))
+ BEGIN
+ WrError(1335); return False;
+ END
+ *Adr=LAdr >> 4; *Bit=LAdr & 15;
+ if (NOT MayBeOut) *Adr=Lo(*Adr);
+ return True;
+ END
+ else return False;
+ END
+ else if (p==Asc)
+ BEGIN
+ WrError(1350); return False;
+ END
+ else
+ BEGIN
+ *p='\0';
+ if (IsReg(Asc,&Reg,True)) *Adr=0xf0+Reg;
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ LAdr=EvalIntExpression(Asc,UInt16,&OK); if (NOT OK) return False;
+ if (FirstPassUnknown) LAdr=0xfd00;
+ if ((LAdr&1)==1)
+ BEGIN
+ WrError(1325); return False;
+ END
+ if ((LAdr>=0xfd00) AND (LAdr<=0xfdfe)) *Adr=(LAdr-0xfd00)/2;
+ else if ((LAdr>=0xff00) AND (LAdr<=0xffde))
+ BEGIN
+ if ((ExtSFRs) AND (NOT MayBeOut))
+ BEGIN
+ WrError(1335); return False;
+ END
+ *Adr=0x80+((LAdr-0xff00)/2);
+ END
+ else if ((LAdr>=0xf100) AND (LAdr<=0xf1de))
+ BEGIN
+ if ((NOT ExtSFRs) AND (NOT MayBeOut))
+ BEGIN
+ WrError(1335); return False;
+ END
+ *Adr=0x80+((LAdr-0xf100)/2);
+ if (MayBeOut) (*Adr)+=0x100;
+ END
+ else
+ BEGIN
+ WrError(1320); return False;
+ END
+ END
+
+ *Bit=EvalIntExpression(p+1,UInt4,&OK);
+ return OK;
+ END
+END
+
+ static Word WordVal(void)
+BEGIN
+ return AdrVals[0]+(((Word)AdrVals[1]) << 8);
+END
+
+ static Boolean DecodePref(char *Asc, Byte *Erg)
+BEGIN
+ Boolean OK;
+
+ if (*Asc!='#')
+ BEGIN
+ WrError(1350); return False;
+ END
+ strcpy(Asc,Asc+1);
+ FirstPassUnknown=False;
+ *Erg=EvalIntExpression(Asc,UInt3,&OK);
+ if (FirstPassUnknown) *Erg=1;
+ if (NOT OK) return False;
+ if (*Erg<1) WrError(1315);
+ else if (*Erg>4) WrError(1320);
+ else
+ BEGIN
+ (*Erg)--; return True;
+ END
+ return False;
+END
+
+/*-------------------------------------------------------------------------*/
+
+#define ASSUME166Count 4
+static ASSUMERec ASSUME166s[ASSUME166Count]=
+ {{"DPP0", DPPAssumes+0, 0, 15, -1},
+ {"DPP1", DPPAssumes+1, 0, 15, -1},
+ {"DPP2", DPPAssumes+2, 0, 15, -1},
+ {"DPP3", DPPAssumes+3, 0, 15, -1}};
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Word Adr;
+ Byte Bit;
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME166s,ASSUME166Count);
+ return True;
+ END
+
+ if (Memo("BIT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeBitAddr(ArgStr[1],&Adr,&Bit,True))
+ BEGIN
+ PushLocHandle(-1);
+ EnterIntSymbol(LabPart,(Adr << 4)+Bit,SegNone,False);
+ PopLocHandle();
+ sprintf(ListLine,"=%02xH.%1x",Adr,Bit);
+ END
+ return True;
+ END
+
+ if (Memo("REG"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else AddRegDef(LabPart,ArgStr[1]);
+ return True;
+ END
+
+ return False;
+END
+
+ static Boolean BMemo(char *Name)
+BEGIN
+ int l;
+
+ if (strncmp(OpPart,Name,l=strlen(Name))!=0) return False;
+ switch (OpPart[l])
+ BEGIN
+ case '\0':
+ OpSize=1; return True;
+ case 'B':
+ if (OpPart[l+1]=='\0')
+ BEGIN
+ OpSize=0; return True;
+ END
+ else return False;
+ default:
+ return False;
+ END
+END
+
+ static void MakeCode_166(void)
+BEGIN
+ int z,Cond;
+ Word AdrWord;
+ Byte AdrBank,HReg;
+ Byte BOfs1,BOfs2;
+ Word BAdr1,BAdr2;
+ LongInt AdrLong;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False; OpSize=1;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* Pipeline-Flags weiterschalten */
+
+ SPChanged=N_SPChanged; N_SPChanged=False;
+ CPChanged=N_CPChanged; N_CPChanged=False;
+ for (z=0; z<DPPCount; z++)
+ BEGIN
+ DPPChanged[z]=N_DPPChanged[z];
+ N_DPPChanged[z]=False;
+ END
+
+ /* Praefixe herunterzaehlen */
+
+ if (ExtCounter>=0)
+ if (--ExtCounter<0)
+ BEGIN
+ MemMode=MemModeStd;
+ ExtSFRs=False;
+ END
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=Lo(FixedOrders[z].Code1);
+ BAsmCode[1]=Hi(FixedOrders[z].Code1);
+ if (FixedOrders[z].Code2!=0)
+ BEGIN
+ CodeLen=4;
+ BAsmCode[2]=Lo(FixedOrders[z].Code2);
+ BAsmCode[3]=Hi(FixedOrders[z].Code2);
+ if ((strncmp(OpPart,"RET",3)==0) AND (SPChanged)) WrXError(200,RegNames[5]);
+ END
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (BMemo("MOV"))
+ BEGIN
+ Cond=1-OpSize;
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModMReg+MModIReg+MModPreDec+MModPostInc+MModIndex+MModAbs,False,True);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModImm+MModIReg+MModPostInc+MModIndex+MModAbs,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0xf0+Cond;
+ BAsmCode[1]=(HReg << 4)+AdrMode;
+ break;
+ case ModImm:
+ if (WordVal()<=15)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe0+Cond;
+ BAsmCode[1]=(WordVal() << 4)+HReg;
+ END
+ else
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0xe6+Cond; BAsmCode[1]=HReg+0xf0;
+ memcpy(BAsmCode+2,AdrVals,2);
+ END
+ break;
+ case ModIReg:
+ CodeLen=2; BAsmCode[0]=0xa8+Cond;
+ BAsmCode[1]=(HReg << 4)+AdrMode;
+ break;
+ case ModPostInc:
+ CodeLen=2; BAsmCode[0]=0x98+Cond;
+ BAsmCode[1]=(HReg << 4)+AdrMode;
+ break;
+ case ModIndex:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xd4+(Cond << 5);
+ BAsmCode[1]=(HReg << 4)+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ case ModAbs:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xf2+Cond;
+ BAsmCode[1]=0xf0+HReg; memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ END
+ break;
+ case ModMReg:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModImm+MModMReg+((DPPAssumes[3]==3)?MModIReg:0)+MModAbs,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModImm:
+ CodeLen=4; BAsmCode[0]=0xe6+Cond;
+ memcpy(BAsmCode+2,AdrVals,2);
+ break;
+ case ModMReg: /* BAsmCode[1] sicher absolut darstellbar, da Rn vorher */
+ /* abgefangen wird! */
+ BAsmCode[0]=0xf6+Cond;
+ AdrLong=0xfe00+(((Word)BAsmCode[1]) << 1);
+ CalcPage(&AdrLong,True);
+ BAsmCode[2]=Lo(AdrLong);
+ BAsmCode[3]=Hi(AdrLong);
+ BAsmCode[1]=AdrVals[0];
+ CodeLen=4;
+ break;
+ case ModIReg:
+ CodeLen=4; BAsmCode[0]=0x94+(Cond << 5);
+ BAsmCode[2]=BAsmCode[1] << 1;
+ BAsmCode[3]=0xfe + (BAsmCode[1] >> 7); /* ANSI :-0 */
+ BAsmCode[1]=AdrMode;
+ break;
+ case ModAbs:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xf2+Cond;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ END
+ break;
+ case ModIReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModIReg+MModPostInc+MModAbs,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0xb8+Cond;
+ BAsmCode[1]=HReg+(AdrMode << 4);
+ break;
+ case ModIReg:
+ CodeLen=2; BAsmCode[0]=0xc8+Cond;
+ BAsmCode[1]=(HReg << 4)+AdrMode;
+ break;
+ case ModPostInc:
+ CodeLen=2; BAsmCode[0]=0xe8+Cond;
+ BAsmCode[1]=(HReg << 4)+AdrMode;
+ break;
+ case ModAbs:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0x84+(Cond << 5);
+ BAsmCode[1]=HReg; memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ END
+ break;
+ case ModPreDec:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0x88+Cond;
+ BAsmCode[1]=HReg+(AdrMode << 4);
+ break;
+ END
+ break;
+ case ModPostInc:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModIReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModIReg:
+ CodeLen=2; BAsmCode[0]=0xd8+Cond;
+ BAsmCode[1]=(HReg << 4)+AdrMode;
+ break;
+ END
+ break;
+ case ModIndex:
+ BAsmCode[1]=AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0xc4+(Cond << 5);
+ CodeLen=4; BAsmCode[1]+=AdrMode << 4;
+ break;
+ END
+ break;
+ case ModAbs:
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModIReg+MModMReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModIReg:
+ CodeLen=4; BAsmCode[0]=0x94+(Cond << 5);
+ BAsmCode[1]=AdrMode;
+ break;
+ case ModMReg:
+ CodeLen=4; BAsmCode[0]=0xf6+Cond;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MOVBS")) OR (Memo("MOVBZ")))
+ BEGIN
+ Cond=Ord(Memo("MOVBS")) << 4;
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OpSize=1;
+ DecodeAdr(ArgStr[1],MModReg+MModMReg+MModAbs,False,True);
+ OpSize=0;
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ HReg=AdrMode; DecodeAdr(ArgStr[2],MModReg+MModAbs,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0xc0+Cond;
+ BAsmCode[1]=HReg+(AdrMode << 4);
+ break;
+ case ModAbs:
+ CodeLen=4; BAsmCode[0]=0xc2+Cond;
+ BAsmCode[1]=0xf0+HReg;
+ memcpy(BAsmCode+2,AdrVals,2);
+ break;
+ END
+ break;
+ case ModMReg:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModAbs+MModMReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModMReg: /* BAsmCode[1] sicher absolut darstellbar, da Rn vorher */
+ /* abgefangen wird! */
+ BAsmCode[0]=0xc5+Cond;
+ AdrLong=0xfe00+(((Word)BAsmCode[1]) << 1);
+ CalcPage(&AdrLong,True);
+ BAsmCode[2]=Lo(AdrLong);
+ BAsmCode[3]=Hi(AdrLong);
+ BAsmCode[1]=AdrVals[0];
+ CodeLen=4;
+ break;
+ case ModAbs:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xc2+Cond;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ END
+ break;
+ case ModAbs:
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModMReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModMReg:
+ CodeLen=4; BAsmCode[0]=0xc5+Cond;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMReg,False,Memo("POP"));
+ switch (AdrType)
+ BEGIN
+ case ModMReg:
+ CodeLen=2; BAsmCode[0]=0xec+(Ord(Memo("POP")) << 4);
+ BAsmCode[1]=AdrVals[0];
+ if (SPChanged) WrXError(200,RegNames[5]);
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("SCXT"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMReg,False,True);
+ switch (AdrType)
+ BEGIN
+ case ModMReg:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModAbs+MModImm,False,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0xc6+(Ord(AdrType==ModAbs) << 4);
+ memcpy(BAsmCode+2,AdrVals,2);
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<ALU2OrderCount; z++)
+ if (BMemo(ALU2Orders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ Cond=(1-OpSize)+(z << 4);
+ DecodeAdr(ArgStr[1],MModReg+MModMReg+MModAbs,False,True);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModIReg+MModPostInc+MModAbs+MModImm,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=Cond;
+ BAsmCode[1]=(HReg << 4)+AdrMode;
+ break;
+ case ModIReg:
+ if (AdrMode>3) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x08+Cond;
+ BAsmCode[1]=(HReg << 4)+8+AdrMode;
+ END
+ break;
+ case ModPostInc:
+ if (AdrMode>3) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x08+Cond;
+ BAsmCode[1]=(HReg << 4)+12+AdrMode;
+ END
+ break;
+ case ModAbs:
+ CodeLen=4; BAsmCode[0]=0x02+Cond; BAsmCode[1]=0xf0+HReg;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ case ModImm:
+ if (WordVal()<=7)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x08+Cond;
+ BAsmCode[1]=(HReg << 4)+AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0x06+Cond; BAsmCode[1]=0xf0+HReg;
+ memcpy(BAsmCode+2,AdrVals,2);
+ END
+ break;
+ END
+ break;
+ case ModMReg:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModAbs+MModMReg+MModImm,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ CodeLen=4; BAsmCode[0]=0x02+Cond;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ case ModMReg: /* BAsmCode[1] sicher absolut darstellbar, da Rn vorher */
+ /* abgefangen wird! */
+ BAsmCode[0]=0x04+Cond;
+ AdrLong=0xfe00+(((Word)BAsmCode[1]) << 1);
+ CalcPage(&AdrLong,True);
+ BAsmCode[2]=Lo(AdrLong);
+ BAsmCode[3]=Hi(AdrLong);
+ BAsmCode[1]=AdrVals[0];
+ CodeLen=4;
+ break;
+ case ModImm:
+ CodeLen=4; BAsmCode[0]=0x06+Cond;
+ memcpy(BAsmCode+2,AdrVals,2);
+ break;
+ END
+ break;
+ case ModAbs:
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModMReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModMReg:
+ CodeLen=4; BAsmCode[0]=0x04+Cond; BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((BMemo("CPL")) OR (BMemo("NEG")))
+ BEGIN
+ Cond=0x81+((1-OpSize) << 5);
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg,False,True);
+ if (AdrType==ModReg)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=Cond+(Ord(BMemo("CPL")) << 4);
+ BAsmCode[1]=AdrMode << 4;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<DivOrderCount; z++)
+ if (Memo(DivOrders[z]))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg,False,False);
+ if (AdrType==ModReg)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x4b+(z << 4);
+ BAsmCode[1]=AdrMode*0x11;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<LoopOrderCount; z++)
+ if (Memo(LoopOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg,False,True);
+ if (AdrType==ModReg)
+ BEGIN
+ BAsmCode[1]=AdrMode;
+ DecodeAdr(ArgStr[2],MModAbs+MModImm,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ CodeLen=4; BAsmCode[0]=LoopOrders[z].Code+2; BAsmCode[1]+=0xf0;
+ memcpy(BAsmCode+2,AdrVals,2);
+ break;
+ case ModImm:
+ if (WordVal()<16)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=LoopOrders[z].Code;
+ BAsmCode[1]+=(WordVal() << 4);
+ END
+ else
+ BEGIN
+ CodeLen=4; BAsmCode[0]=LoopOrders[z].Code+6; BAsmCode[1]+=0xf0;
+ memcpy(BAsmCode+2,AdrVals,2);
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<MulOrderCount; z++)
+ if (Memo(MulOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0x0b+(z << 4);
+ BAsmCode[1]=(HReg << 4)+AdrMode;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Logik */
+
+ for (z=0; z<ShiftOrderCount; z++)
+ if (Memo(ShiftOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OpSize=1;
+ DecodeAdr(ArgStr[1],MModReg,False,True);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModImm,False,True);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=ShiftOrders[z].Code; BAsmCode[1]=AdrMode+(HReg << 4);
+ CodeLen=2;
+ break;
+ case ModImm:
+ if (WordVal()>15) WrError(1320);
+ else
+ BEGIN
+ BAsmCode[0]=ShiftOrders[z].Code+0x10;
+ BAsmCode[1]=(WordVal() << 4)+HReg;
+ CodeLen=2;
+ END
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Bit2OrderCount; z++)
+ if (Memo(Bit2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ if (DecodeBitAddr(ArgStr[1],&BAdr1,&BOfs1,False))
+ if (DecodeBitAddr(ArgStr[2],&BAdr2,&BOfs2,False))
+ BEGIN
+ CodeLen=4; BAsmCode[0]=Bit2Orders[z].Code;
+ BAsmCode[1]=BAdr2; BAsmCode[2]=BAdr1;
+ BAsmCode[3]=(BOfs2 << 4)+BOfs1;
+ END
+ return;
+ END
+
+ if ((Memo("BCLR")) OR (Memo("BSET")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeBitAddr(ArgStr[1],&BAdr1,&BOfs1,False))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=(BOfs1 << 4)+0x0e + Ord(Memo("BSET")); /* ANSI :-0 */
+ BAsmCode[1]=BAdr1;
+ END
+ return;
+ END
+
+ if ((Memo("BFLDH")) OR (Memo("BFLDL")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ strmaxcat(ArgStr[1],".0",255);
+ if (DecodeBitAddr(ArgStr[1],&BAdr1,&BOfs1,False))
+ BEGIN
+ OpSize=0; BAsmCode[1]=BAdr1;
+ DecodeAdr(ArgStr[2],MModImm,False,False);
+ if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[3],MModImm,False,False);
+ if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[3]=AdrVals[0];
+ CodeLen=4; BAsmCode[0]=0x0a;
+ if (Memo("BFLDH"))
+ BEGIN
+ BAdr1=BAsmCode[2]; BAsmCode[2]=BAsmCode[3]; BAsmCode[3]=BAdr1;
+ BAsmCode[0]+=0x10;
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /*Spruenge */
+
+ if (Memo("JMP"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ Cond=(ArgCnt==1) ? TrueCond : DecodeCondition(ArgStr[1]);
+ if (Cond>=ConditionCount) WrXError(1360,ArgStr[1]);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[ArgCnt],MModAbs+MModLAbs+MModIReg,True,False);
+ switch (AdrType)
+ BEGIN
+ case ModLAbs:
+ if (Cond!=TrueCond) WrXError(1360,ArgStr[1]);
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xfa; BAsmCode[1]=AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ END
+ break;
+ case ModAbs:
+ AdrLong=WordVal()-(EProgCounter()+2);
+ if ((AdrLong<=254) AND (AdrLong>=-256) AND ((AdrLong&1)==0))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x0d+(Conditions[Cond].Code << 4);
+ BAsmCode[1]=(AdrLong/2)&0xff;
+ END
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xea;
+ BAsmCode[1]=Conditions[Cond].Code << 4;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ END
+ break;
+ case ModIReg:
+ CodeLen=2; BAsmCode[0]=0x9c;
+ BAsmCode[1]=(Conditions[Cond].Code << 4)+AdrMode;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALL"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ Cond=(ArgCnt==1) ? TrueCond : DecodeCondition(ArgStr[1]);
+ if (Cond>=ConditionCount) WrXError(1360,ArgStr[1]);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[ArgCnt],MModAbs+MModLAbs+MModIReg,True,False);
+ switch (AdrType)
+ BEGIN
+ case ModLAbs:
+ if (Cond!=TrueCond) WrXError(1360,ArgStr[1]);
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xda; BAsmCode[1]=AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ END
+ break;
+ case ModAbs:
+ AdrLong=WordVal()-(EProgCounter()+2);
+ if ((AdrLong<=254) AND (AdrLong>=-256) AND ((AdrLong&1)==0) AND (Cond==TrueCond))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xbb;
+ BAsmCode[1]=(AdrLong/2) & 0xff;
+ END
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xca;
+ BAsmCode[1]=0x00+(Conditions[Cond].Code << 4);
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ END
+ break;
+ case ModIReg:
+ CodeLen=2; BAsmCode[0]=0xab;
+ BAsmCode[1]=(Conditions[Cond].Code << 4)+AdrMode;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("JMPR"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ Cond=(ArgCnt==1) ? TrueCond : DecodeCondition(ArgStr[1]);
+ if (Cond>=ConditionCount) WrXError(1360,ArgStr[1]);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[ArgCnt],MemInt,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((AdrLong&1)==1) WrError(1375);
+ else if ((NOT SymbolQuestionable) AND ((AdrLong>254) OR (AdrLong<-256))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x0d+(Conditions[Cond].Code << 4);
+ BAsmCode[1]=(AdrLong/2) & 0xff;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALLR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[ArgCnt],MemInt,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((AdrLong&1)==1) WrError(1375);
+ else if ((NOT SymbolQuestionable) AND ((AdrLong>254) OR (AdrLong<-256))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xbb;
+ BAsmCode[1]=(AdrLong/2) & 0xff;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JMPA")) OR (Memo("CALLA")))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ Cond=(ArgCnt==1) ? TrueCond : DecodeCondition(ArgStr[1]);
+ if (Cond>=ConditionCount) WrXError(1360,ArgStr[1]);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[ArgCnt],MemInt,&OK);
+ if (OK)
+ if ((AdrLong >> 16)!=(EProgCounter() >> 16)) WrError(1910);
+ else
+ BEGIN
+ CodeLen=4;
+ BAsmCode[0]=(Memo("JMPA")) ? 0xea : 0xca;
+ BAsmCode[1]=0x00+(Conditions[Cond].Code << 4);
+ BAsmCode[2]=Lo(AdrLong); BAsmCode[3]=Hi(AdrLong);
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JMPS")) OR (Memo("CALLS")))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],MemInt,&OK);
+ AdrWord=AdrLong & 0xffff; AdrBank=AdrLong >> 16;
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt16,&OK);
+ if (OK) AdrBank=EvalIntExpression(ArgStr[1],MemInt2,&OK); else AdrBank=0;
+ END
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ BAsmCode[0]=(Memo("JMPS")) ? 0xfa : 0xda;
+ BAsmCode[1]=AdrBank;
+ BAsmCode[2]=Lo(AdrWord); BAsmCode[3]=Hi(AdrWord);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JMPI")) OR (Memo("CALLI")))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ Cond=(ArgCnt==1) ? TrueCond : DecodeCondition(ArgStr[1]);
+ if (Cond>=ConditionCount) WrXError(1360,ArgStr[1]);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[ArgCnt],MModIReg,True,False);
+ switch (AdrType)
+ BEGIN
+ case ModIReg:
+ CodeLen=2;
+ BAsmCode[0]=(Memo("JMPI")) ? 0x9c : 0xab;
+ BAsmCode[1]=AdrMode+(Conditions[Cond].Code << 4);
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BJmpOrderCount; z++)
+ if (Memo(BJmpOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (DecodeBitAddr(ArgStr[1],&BAdr1,&BOfs1,False))
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[2],MemInt,&OK)-(EProgCounter()+4);
+ if (OK)
+ if ((AdrLong&1)==1) WrError(1375);
+ else if ((NOT SymbolQuestionable) AND ((AdrLong<-256) OR (AdrLong>254))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0x8a+(z << 4);
+ BAsmCode[1]=BAdr1;
+ BAsmCode[2]=(AdrLong/2) & 0xff;
+ BAsmCode[3]=BOfs1 << 4;
+ END
+ END
+ return;
+ END
+
+ if (Memo("PCALL"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModMReg:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModAbs,True,False);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ CodeLen=4; BAsmCode[0]=0xe2; memcpy(BAsmCode+2,AdrVals,2);
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("RETP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMReg,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModMReg:
+ BAsmCode[1]=AdrVals[0]; BAsmCode[0]=0xeb; CodeLen=2;
+ if (SPChanged) WrXError(200,RegNames[5]);
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("TRAP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1]+1,UInt7,&OK) << 1;
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x9b; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ /* spezielle Steuerbefehle */
+
+ if (Memo("ATOMIC"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU80C167) WrError(1500);
+ else if (DecodePref(ArgStr[1],&HReg))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xd1; BAsmCode[1]=HReg << 4;
+ END
+ return;
+ END
+
+ if (Memo("EXTR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU80C167) WrError(1500);
+ else if (DecodePref(ArgStr[1],&HReg))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xd1; BAsmCode[1]=0x80+(HReg << 4);
+ ExtCounter=HReg+1; ExtSFRs=True;
+ END
+ return;
+ END
+
+ if ((Memo("EXTP")) OR (Memo("EXTPR")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80C167) WrError(1500);
+ else if (DecodePref(ArgStr[2],&HReg))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModImm,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0xdc; BAsmCode[1]=0x40+(HReg << 4)+AdrMode;
+ if (Memo("EXTPR")) BAsmCode[1]+=0x80;
+ ExtCounter=HReg+1; MemMode=MemModeZeroPage;
+ break;
+ case ModImm:
+ CodeLen=4; BAsmCode[0]=0xd7; BAsmCode[1]=0x40+(HReg << 4);
+ if (Memo("EXTPR")) BAsmCode[1]+=0x80;
+ BAsmCode[2]=WordVal() & 0xff; BAsmCode[3]=(WordVal() >> 8) & 3;
+ ExtCounter=HReg+1; MemMode=MemModeFixedPage; MemPage=WordVal() & 0x3ff;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("EXTS")) OR (Memo("EXTSR")))
+ BEGIN
+ OpSize=0;
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80C167) WrError(1500);
+ else if (DecodePref(ArgStr[2],&HReg))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModImm,False,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0xdc; BAsmCode[1]=0x00+(HReg << 4)+AdrMode;
+ if (Memo("EXTSR")) BAsmCode[1]+=0x80;
+ ExtCounter=HReg+1; MemMode=MemModeNoCheck;
+ break;
+ case ModImm:
+ CodeLen=4; BAsmCode[0]=0xd7; BAsmCode[1]=0x00+(HReg << 4);
+ if (Memo("EXTSR")) BAsmCode[1]+=0x80;
+ BAsmCode[2]=AdrVals[0]; BAsmCode[3]=0;
+ ExtCounter=HReg+1; MemMode=MemModeFixedBank; MemPage=AdrVals[0];
+ break;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_166(void)
+BEGIN
+ int z;
+
+ SaveInitProc();
+ for (z=0; z<DPPCount; z++)
+ BEGIN
+ DPPAssumes[z]=z; N_DPPChanged[z]=False;
+ END
+ N_CPChanged=False; N_SPChanged=False;
+
+ MemMode=MemModeStd; ExtSFRs=False; ExtCounter=(-1);
+END
+
+ static Boolean IsDef_166(void)
+BEGIN
+ return (Memo("BIT")) OR (Memo("REG"));
+END
+
+ static void SwitchFrom_166(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_166(void)
+BEGIN
+ Byte z;
+
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+ OpSize=1;
+
+ PCSymbol="$"; HeaderID=0x4c; NOPCode=0xcc00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+
+ MakeCode=MakeCode_166; IsDef=IsDef_166;
+ SwitchFrom=SwitchFrom_166;
+
+ if (MomCPU==CPU80C166)
+ BEGIN
+ MemInt=UInt18; MemInt2=UInt2; ASSUME166s[0].Max=15;
+ SegLimits[SegCode] = 0x3ffffl;
+ END
+ else
+ BEGIN
+ MemInt=UInt24; MemInt2=UInt8; ASSUME166s[0].Max=1023;
+ SegLimits[SegCode] = 0xffffffl;
+ END
+ for (z=1; z<4; z++) ASSUME166s[z].Max=ASSUME166s[0].Max;
+
+ InitFields();
+END
+
+ void code166_init(void)
+BEGIN
+ CPU80C166=AddCPU("80C166",SwitchTo_166);
+ CPU80C167=AddCPU("80C167",SwitchTo_166);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_166;
+END
diff --git a/code166.h b/code166.h
new file mode 100644
index 0000000..1a74645
--- /dev/null
+++ b/code166.h
@@ -0,0 +1,11 @@
+/* code166.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegenerator Siemens 80C16x */
+/* */
+/* Historie: 11.11.1996 (alaaf) Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code166_init(void);
diff --git a/code16c5x.c b/code16c5x.c
new file mode 100644
index 0000000..cef9bc5
--- /dev/null
+++ b/code16c5x.c
@@ -0,0 +1,448 @@
+/* code16c5x.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS - Codegenerator fuer PIC16C5x */
+/* */
+/* Historie: 19.8.1996 Grundsteinlegung */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 17. 8.1998 RES mit Bookkeeping */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Byte DefaultDir;
+ } AriOrder;
+
+#define FixedOrderCnt 5
+#define LitOrderCnt 5
+#define AriOrderCnt 14
+#define BitOrderCnt 4
+#define FOrderCnt 2
+
+#define D_CPU16C54 0
+#define D_CPU16C55 1
+#define D_CPU16C56 2
+#define D_CPU16C57 3
+
+static FixedOrder *FixedOrders;
+static FixedOrder *LitOrders;
+static AriOrder *AriOrders;
+static FixedOrder *BitOrders;
+static FixedOrder *FOrders;
+
+static CPUVar CPU16C54,CPU16C55,CPU16C56,CPU16C57;
+
+/*-------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddLit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=LitOrderCnt) exit(255);
+ LitOrders[InstrZ].Name=NName;
+ LitOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddAri(char *NName, Word NCode, Byte NDef)
+BEGIN
+ if (InstrZ>=AriOrderCnt) exit(255);
+ AriOrders[InstrZ].Name=NName;
+ AriOrders[InstrZ].Code=NCode;
+ AriOrders[InstrZ++].DefaultDir=NDef;
+END
+
+ static void AddBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=BitOrderCnt) exit(255);
+ BitOrders[InstrZ].Name=NName;
+ BitOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddF(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FOrderCnt) exit(255);
+ FOrders[InstrZ].Name=NName;
+ FOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("CLRW" , 0x040);
+ AddFixed("NOP" , 0x000);
+ AddFixed("CLRWDT", 0x004);
+ AddFixed("OPTION", 0x002);
+ AddFixed("SLEEP" , 0x003);
+
+ LitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LitOrderCnt); InstrZ=0;
+ AddLit("ANDLW", 0xe00);
+ AddLit("IORLW", 0xd00);
+ AddLit("MOVLW", 0xc00);
+ AddLit("RETLW", 0x800);
+ AddLit("XORLW", 0xf00);
+
+ AriOrders=(AriOrder *) malloc(sizeof(AriOrder)*AriOrderCnt); InstrZ=0;
+ AddAri("ADDWF" , 0x1c0, 0);
+ AddAri("ANDWF" , 0x140, 0);
+ AddAri("COMF" , 0x240, 1);
+ AddAri("DECF" , 0x0c0, 1);
+ AddAri("DECFSZ", 0x2c0, 1);
+ AddAri("INCF" , 0x280, 1);
+ AddAri("INCFSZ", 0x3c0, 1);
+ AddAri("IORWF" , 0x100, 0);
+ AddAri("MOVF" , 0x200, 0);
+ AddAri("RLF" , 0x340, 1);
+ AddAri("RRF" , 0x300, 1);
+ AddAri("SUBWF" , 0x080, 0);
+ AddAri("SWAPF" , 0x380, 1);
+ AddAri("XORWF" , 0x180, 0);
+
+ BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCnt); InstrZ=0;
+ AddBit("BCF" , 0x400);
+ AddBit("BSF" , 0x500);
+ AddBit("BTFSC", 0x600);
+ AddBit("BTFSS", 0x700);
+
+ FOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FOrderCnt); InstrZ=0;
+ AddF("CLRF" , 0x060);
+ AddF("MOVWF", 0x020);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(LitOrders);
+ free(AriOrders);
+ free(BitOrders);
+ free(FOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Word ROMEnd(void)
+BEGIN
+ switch (MomCPU-CPU16C54)
+ BEGIN
+ case D_CPU16C54:
+ case D_CPU16C55: return 511;
+ case D_CPU16C56: return 1023;
+ case D_CPU16C57: return 2047;
+ default: return 0;
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Word Size;
+ Boolean ValOK;
+ int z;
+ TempResult t;
+ char *p;
+ LongInt MinV,MaxV;
+
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,0x1f);
+ return True;
+ END
+
+ if (Memo("RES"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("DATA"))
+ BEGIN
+ MaxV=(ActPC==SegCode)?4095:255; MinV=(-((MaxV+1) >> 1));
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ ValOK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (ValOK)
+ BEGIN
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ if ((FirstPassUnknown) AND (t.Typ==TempInt)) t.Contents.Int&=MaxV;
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (ChkRange(t.Contents.Int,MinV,MaxV))
+ if (ActPC==SegCode) WAsmCode[CodeLen++]=t.Contents.Int & MaxV;
+ else BAsmCode[CodeLen++]=t.Contents.Int & MaxV;
+ break;
+ case TempFloat:
+ WrError(1135); ValOK=False;
+ break;
+ case TempString:
+ for (p=t.Contents.Ascii; *p!='\0'; p++)
+ if (ActPC==SegCode)
+ WAsmCode[CodeLen++]=CharTransTable[((usint) *p)&0xff];
+ else
+ BAsmCode[CodeLen++]=CharTransTable[((usint) *p)&0xff];
+ break;
+ default:
+ ValOK=False;
+ END
+ END
+ if (NOT ValOK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("ZERO"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ if ((Size << 1)>MaxCodeLen) WrError(1920);
+ else
+ BEGIN
+ CodeLen=Size;
+ memset(WAsmCode,0,2*Size);
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_16C5X(void)
+BEGIN
+ Boolean OK;
+ Word AdrWord;
+ int z;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; WAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ /* nur ein Literal als Argument */
+
+ for (z=0; z<LitOrderCnt; z++)
+ if (Memo(LitOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]=LitOrders[z].Code+(AdrWord & 0xff);
+ END
+ END
+ return;
+ END
+
+ /* W-mit-f-Operationen */
+
+ for (z=0; z<AriOrderCnt; z++)
+ if (Memo(AriOrders[z].Name))
+ BEGIN
+ if ((ArgCnt==0) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegData);
+ WAsmCode[0]=AriOrders[z].Code+(AdrWord & 0x1f);
+ if (ArgCnt==1)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=AriOrders[z].DefaultDir << 5;
+ END
+ else if (strcasecmp(ArgStr[2],"W")==0) CodeLen=1;
+ else if (strcasecmp(ArgStr[2],"F")==0)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=0x20;
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt1,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=AdrWord << 5;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt3,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=BitOrders[z].Code+(AdrWord << 5);
+ ChkSpace(SegData);
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<FOrderCnt; z++)
+ if (Memo(FOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]=FOrders[z].Code+AdrWord;
+ ChkSpace(SegData);
+ END
+ END
+ return;
+ END
+
+ if (Memo("TRIS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ if (ChkRange(AdrWord,5,7))
+ BEGIN
+ CodeLen=1; WAsmCode[0]=0x000+AdrWord;
+ ChkSpace(SegData);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CALL")) OR (Memo("GOTO")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ if (AdrWord>ROMEnd()) WrError(1320);
+ else if ((Memo("CALL")) AND ((AdrWord & 0x100)!=0)) WrError(1905);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ if (((ProgCounter() ^ AdrWord) & 0x200)!=0)
+ WAsmCode[CodeLen++]=0x4a3+((AdrWord & 0x200) >> 1); /* BCF/BSF 3,5 */
+ if (((ProgCounter() ^ AdrWord) & 0x400)!=0)
+ WAsmCode[CodeLen++]=0x4c3+((AdrWord & 0x400) >> 2); /* BCF/BSF 3,6 */
+ if (Memo("CALL")) WAsmCode[CodeLen++]=0x900+(AdrWord & 0xff);
+ else WAsmCode[CodeLen++]=0xa00+(AdrWord & 0x1ff);
+ END
+ END
+ return;
+ END;
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_16C5X(void)
+BEGIN
+ return Memo("SFR");
+END
+
+ static void SwitchFrom_16C5X()
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_16C5X(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x71; NOPCode=0x000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)+(1<<SegData);
+ Grans[SegCode]=2; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ SegLimits[SegCode] = ROMEnd();
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegCode]=0;
+ SegLimits[SegData] = 0x1f;
+
+ MakeCode=MakeCode_16C5X; IsDef=IsDef_16C5X;
+ SwitchFrom=SwitchFrom_16C5X; InitFields();
+END
+
+ void code16c5x_init(void)
+BEGIN
+ CPU16C54=AddCPU("16C54",SwitchTo_16C5X);
+ CPU16C55=AddCPU("16C55",SwitchTo_16C5X);
+ CPU16C56=AddCPU("16C56",SwitchTo_16C5X);
+ CPU16C57=AddCPU("16C57",SwitchTo_16C5X);
+END
diff --git a/code16c5x.h b/code16c5x.h
new file mode 100644
index 0000000..2a39fe2
--- /dev/null
+++ b/code16c5x.h
@@ -0,0 +1,12 @@
+/* code16c5x.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS - Codegenerator fuer PIC16C5x */
+/* */
+/* Historie: 19.8.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code16c5x_init(void);
+
diff --git a/code16c8x.c b/code16c8x.c
new file mode 100644
index 0000000..cea59fd
--- /dev/null
+++ b/code16c8x.c
@@ -0,0 +1,472 @@
+/* code16c8x.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegenerator PIC16C8x */
+/* */
+/* Historie: 21.8.1996 Grundsteinlegung */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 18. 8.1998 Bookkeeping-Aufruf bei RES */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* Sonderadressbereich PIC16C84 */
+/* 2. 10.1999 ChkPC wurde nicht angebunden... */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "chunks.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Byte DefaultDir;
+ } AriOrder;
+
+#define D_CPU16C64 0
+#define D_CPU16C84 1
+
+#define FixedOrderCnt 7
+#define LitOrderCnt 7
+#define AriOrderCnt 14
+#define BitOrderCnt 4
+#define FOrderCnt 2
+
+static FixedOrder *FixedOrders;
+static FixedOrder *LitOrders;
+static AriOrder *AriOrders;
+static FixedOrder *BitOrders;
+static FixedOrder *FOrders;
+
+static CPUVar CPU16C64,CPU16C84;
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddLit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=LitOrderCnt) exit(255);
+ LitOrders[InstrZ].Name=NName;
+ LitOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddAri(char *NName, Word NCode, Byte NDir)
+BEGIN
+ if (InstrZ>=AriOrderCnt) exit(255);
+ AriOrders[InstrZ].Name=NName;
+ AriOrders[InstrZ].Code=NCode;
+ AriOrders[InstrZ++].DefaultDir=NDir;
+END
+
+ static void AddBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=BitOrderCnt) exit(255);
+ BitOrders[InstrZ].Name=NName;
+ BitOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddF(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FOrderCnt) exit(255);
+ FOrders[InstrZ].Name=NName;
+ FOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("CLRW" , 0x0100);
+ AddFixed("NOP" , 0x0000);
+ AddFixed("CLRWDT", 0x0064);
+ AddFixed("OPTION", 0x0062);
+ AddFixed("SLEEP" , 0x0063);
+ AddFixed("RETFIE", 0x0009);
+ AddFixed("RETURN", 0x0008);
+
+ LitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LitOrderCnt); InstrZ=0;
+ AddLit("ADDLW", 0x3e00);
+ AddLit("ANDLW", 0x3900);
+ AddLit("IORLW", 0x3800);
+ AddLit("MOVLW", 0x3000);
+ AddLit("RETLW", 0x3400);
+ AddLit("SUBLW", 0x3c00);
+ AddLit("XORLW", 0x3a00);
+
+ AriOrders=(AriOrder *) malloc(sizeof(AriOrder)*AriOrderCnt); InstrZ=0;
+ AddAri("ADDWF" , 0x0700, 0);
+ AddAri("ANDWF" , 0x0500, 0);
+ AddAri("COMF" , 0x0900, 1);
+ AddAri("DECF" , 0x0300, 1);
+ AddAri("DECFSZ", 0x0b00, 1);
+ AddAri("INCF" , 0x0a00, 1);
+ AddAri("INCFSZ", 0x0f00, 1);
+ AddAri("IORWF" , 0x0400, 0);
+ AddAri("MOVF" , 0x0800, 0);
+ AddAri("RLF" , 0x0d00, 1);
+ AddAri("RRF" , 0x0c00, 1);
+ AddAri("SUBWF" , 0x0200, 0);
+ AddAri("SWAPF" , 0x0e00, 1);
+ AddAri("XORWF" , 0x0600, 0);
+
+ BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCnt); InstrZ=0;
+ AddBit("BCF" , 0x1000);
+ AddBit("BSF" , 0x1400);
+ AddBit("BTFSC", 0x1800);
+ AddBit("BTFSS", 0x1c00);
+
+ FOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FOrderCnt); InstrZ=0;
+ AddF("CLRF" , 0x0180);
+ AddF("MOVWF", 0x0080);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(LitOrders);
+ free(AriOrders);
+ free(BitOrders);
+ free(FOrders);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Word ROMEnd(void)
+BEGIN
+ switch (MomCPU-CPU16C64)
+ BEGIN
+ case D_CPU16C64: return 0x7ff;
+ case D_CPU16C84: return 0x3ff;
+ default: return 0;
+ END
+END
+
+ static Word EvalFExpression(char *Asc, Boolean *OK)
+BEGIN
+ LongInt h;
+
+ h=EvalIntExpression(Asc,UInt9,OK);
+ if (*OK)
+ BEGIN
+ ChkSpace(SegData); return (h & 0x7f);
+ END
+ else return 0;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Word Size;
+ Boolean ValOK;
+ int z;
+ char *p;
+ TempResult t;
+ LongInt MinV,MaxV;
+
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,511);
+ return True;
+ END
+
+ if (Memo("RES"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("DATA"))
+ BEGIN
+ MaxV=(ActPC==SegCode)?16383:255; MinV=(-((MaxV+1) >> 1));
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ ValOK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (ValOK)
+ BEGIN
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ if ((FirstPassUnknown) AND (t.Typ==TempInt)) t.Contents.Int&=MaxV;
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (ChkRange(t.Contents.Int,MinV,MaxV))
+ if (ActPC==SegCode) WAsmCode[CodeLen++]=t.Contents.Int & MaxV;
+ else BAsmCode[CodeLen++]=t.Contents.Int & MaxV;
+ break;
+ case TempFloat:
+ WrError(1135); ValOK=False;
+ break;
+ case TempString:
+ for (p=t.Contents.Ascii; *p!='\0'; p++)
+ if (ActPC==SegCode)
+ WAsmCode[CodeLen++]=CharTransTable[((usint) *p)&0xff];
+ else
+ BAsmCode[CodeLen++]=CharTransTable[((usint) *p)&0xff];
+ break;
+ default:
+ ValOK=False;
+ END
+ END
+ if (NOT ValOK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("ZERO"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ if (Size << 1>MaxCodeLen) WrError(1920);
+ else
+ BEGIN
+ CodeLen=Size;
+ memset(WAsmCode,0,2*Size);
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_16c8x(void)
+BEGIN
+ Boolean OK;
+ Word AdrWord;
+ int z;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; WAsmCode[0]=FixedOrders[z].Code;
+ if (Memo("OPTION")) WrError(130);
+ END
+ return;
+ END
+
+ /* nur ein Literal als Argument */
+
+ for (z=0; z<LitOrderCnt; z++)
+ if (Memo(LitOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]=LitOrders[z].Code+(AdrWord & 0xff);
+ END
+ END
+ return;
+ END
+
+ /* W-mit-f-Operationen */
+
+ for (z=0; z<AriOrderCnt; z++)
+ if (Memo(AriOrders[z].Name))
+ BEGIN
+ if ((ArgCnt==0) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalFExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=AriOrders[z].Code+AdrWord;
+ if (ArgCnt==1)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=AriOrders[z].DefaultDir << 7;
+ END
+ else if (strcasecmp(ArgStr[2],"W")==0) CodeLen=1;
+ else if (strcasecmp(ArgStr[2],"F")==0)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=0x80;
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt1,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=AdrWord << 7;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt3,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=EvalFExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=BitOrders[z].Code+(AdrWord << 7);
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<FOrderCnt; z++)
+ if (Memo(FOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalFExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]=FOrders[z].Code+AdrWord;
+ END
+ END
+ return;
+ END
+
+ if (Memo("TRIS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrWord=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (FirstPassUnknown) AdrWord=5;
+ if (OK)
+ if (ChkRange(AdrWord,5,6))
+ BEGIN
+ CodeLen=1; WAsmCode[0]=0x0060+AdrWord;
+ ChkSpace(SegData); WrError(130);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CALL")) OR (Memo("GOTO")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if (AdrWord>ROMEnd()) WrError(1320);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ if (((ProgCounter() ^ AdrWord) & 0x800)!=0)
+ WAsmCode[CodeLen++]=0x118a+((AdrWord & 0x800) >> 1); /* BCF/BSF 10,3 */
+ if (((ProgCounter() ^ AdrWord) & 0x1000)!=0)
+ WAsmCode[CodeLen++]=0x120a+((AdrWord & 0x400) >> 2); /* BCF/BSF 10,4 */
+ if (Memo("CALL")) WAsmCode[CodeLen++]=0x2000+(AdrWord & 0x7ff);
+ else WAsmCode[CodeLen++]=0x2800+(AdrWord & 0x7ff);
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_16c8x(void)
+BEGIN
+ return (Memo("SFR"));
+END
+
+ static Boolean ChkPC_16c8x(LargeWord Addr)
+BEGIN
+
+ if ((ActPC == SegCode) AND (Addr > SegLimits[SegCode]))
+ BEGIN
+ return ((Addr >= 0x2000) AND (Addr <= 0x2007));
+ END
+ else return (Addr <= SegLimits[ActPC]);
+END
+
+ static void SwitchFrom_16c8x(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_16c8x(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x70; NOPCode=0x0000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)+(1<<SegData);
+ Grans[SegCode]=2; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ SegLimits[SegCode] = ROMEnd() + 0x300;
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
+ SegLimits[SegData] = 0x1ff;
+ ChkPC = ChkPC_16c8x;
+
+ MakeCode=MakeCode_16c8x; IsDef=IsDef_16c8x;
+ SwitchFrom=SwitchFrom_16c8x; InitFields();
+END
+
+ void code16c8x_init(void)
+BEGIN
+ CPU16C64=AddCPU("16C64",SwitchTo_16c8x);
+ CPU16C84=AddCPU("16C84",SwitchTo_16c8x);
+END
diff --git a/code16c8x.h b/code16c8x.h
new file mode 100644
index 0000000..80f1305
--- /dev/null
+++ b/code16c8x.h
@@ -0,0 +1,11 @@
+/* code16c8x.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegenerator PIC16C8x */
+/* */
+/* Historie: 21.8.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code16c8x_init(void);
diff --git a/code17c4x.c b/code17c4x.c
new file mode 100644
index 0000000..b2e0cdd
--- /dev/null
+++ b/code17c4x.c
@@ -0,0 +1,521 @@
+/* code17c4x.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator PIC17C4x */
+/* */
+/* Historie: 21.8.1996 Grundsteinlegung */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 18. 8.1998 Bookkeeping-Aufruf in RES */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word DefaultDir;
+ Word Code;
+ } AriOrder;
+
+#define FixedOrderCnt 5
+#define LittOrderCnt 8
+#define AriOrderCnt 23
+#define BitOrderCnt 5
+#define FOrderCnt 5
+
+
+/*---------------------------------------------------------------------------*/
+
+static FixedOrder *FixedOrders;
+static FixedOrder *LittOrders;
+static AriOrder *AriOrders;
+static FixedOrder *BitOrders;
+static FixedOrder *FOrders;
+
+static CPUVar CPU17C42;
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddLitt(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=LittOrderCnt) exit(255);
+ LittOrders[InstrZ].Name=NName;
+ LittOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddAri(char *NName, Word NDef, Word NCode)
+BEGIN
+ if (InstrZ>=AriOrderCnt) exit(255);
+ AriOrders[InstrZ].Name=NName;
+ AriOrders[InstrZ].Code=NCode;
+ AriOrders[InstrZ++].DefaultDir=NDef;
+END
+
+ static void AddBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=BitOrderCnt) exit(255);
+ BitOrders[InstrZ].Name=NName;
+ BitOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddF(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FOrderCnt) exit(255);
+ FOrders[InstrZ].Name=NName;
+ FOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("RETFIE", 0x0005);
+ AddFixed("RETURN", 0x0002);
+ AddFixed("CLRWDT", 0x0004);
+ AddFixed("NOP" , 0x0000);
+ AddFixed("SLEEP" , 0x0003);
+
+ LittOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LittOrderCnt); InstrZ=0;
+ AddLitt("MOVLB", 0xb800);
+ AddLitt("ADDLW", 0xb100);
+ AddLitt("ANDLW", 0xb500);
+ AddLitt("IORLW", 0xb300);
+ AddLitt("MOVLW", 0xb000);
+ AddLitt("SUBLW", 0xb200);
+ AddLitt("XORLW", 0xb400);
+ AddLitt("RETLW", 0xb600);
+
+ AriOrders=(AriOrder *) malloc(sizeof(AriOrder)*AriOrderCnt); InstrZ=0;
+ AddAri("ADDWF" , 0, 0x0e00);
+ AddAri("ADDWFC", 0, 0x1000);
+ AddAri("ANDWF" , 0, 0x0a00);
+ AddAri("CLRF" , 1, 0x2800);
+ AddAri("COMF" , 1, 0x1200);
+ AddAri("DAW" , 1, 0x2e00);
+ AddAri("DECF" , 1, 0x0600);
+ AddAri("INCF" , 1, 0x1400);
+ AddAri("IORWF" , 0, 0x0800);
+ AddAri("NEGW" , 1, 0x2c00);
+ AddAri("RLCF" , 1, 0x1a00);
+ AddAri("RLNCF" , 1, 0x2200);
+ AddAri("RRCF" , 1, 0x1800);
+ AddAri("RRNCF" , 1, 0x2000);
+ AddAri("SETF" , 1, 0x2a00);
+ AddAri("SUBWF" , 0, 0x0400);
+ AddAri("SUBWFB", 0, 0x0200);
+ AddAri("SWAPF" , 1, 0x1c00);
+ AddAri("XORWF" , 0, 0x0c00);
+ AddAri("DECFSZ", 1, 0x1600);
+ AddAri("DCFSNZ", 1, 0x2600);
+ AddAri("INCFSZ", 1, 0x1e00);
+ AddAri("INFSNZ", 1, 0x2400);
+
+ BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCnt); InstrZ=0;
+ AddBit("BCF" , 0x8800);
+ AddBit("BSF" , 0x8000);
+ AddBit("BTFSC", 0x9800);
+ AddBit("BTFSS", 0x9000);
+ AddBit("BTG" , 0x3800);
+
+ FOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FOrderCnt); InstrZ=0;
+ AddF("MOVWF" , 0x0100);
+ AddF("CPFSEQ", 0x3100);
+ AddF("CPFSGT", 0x3200);
+ AddF("CPFSLT", 0x3000);
+ AddF("TSTFSZ", 0x3300);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(LittOrders);
+ free(AriOrders);
+ free(BitOrders);
+ free(FOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Word Size;
+ Boolean ValOK;
+ int z,z2;
+ TempResult t;
+ LongInt MinV,MaxV;
+
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,0xff);
+ return True;
+ END
+
+ if (Memo("RES"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("DATA"))
+ BEGIN
+ MaxV=(ActPC==SegCode)?65535:255; MinV=(-((MaxV+1) >> 1));
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ ValOK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (ValOK)
+ BEGIN
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ if ((FirstPassUnknown) AND (t.Typ==TempInt)) t.Contents.Int&=MaxV;
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (ChkRange(t.Contents.Int,MinV,MaxV))
+ if (ActPC==SegCode) WAsmCode[CodeLen++]=t.Contents.Int;
+ else BAsmCode[CodeLen++]=t.Contents.Int;
+ break;
+ case TempFloat:
+ WrError(1135); ValOK=False;
+ break;
+ case TempString:
+ for (z2=0; z2<strlen(t.Contents.Ascii); z2++)
+ BEGIN
+ Size=CharTransTable[((usint) t.Contents.Ascii[z2])&0xff];
+ if (ActPC==SegData) BAsmCode[CodeLen++]=Size;
+ else if ((z2&1)==0) WAsmCode[CodeLen++]=Size;
+ else WAsmCode[CodeLen-1]+=Size<<8;
+ END
+ break;
+ default: ValOK=False;
+ END
+ END
+ if (NOT ValOK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("ZERO"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ if ((Size << 1)>MaxCodeLen) WrError(1920);
+ else
+ BEGIN
+ CodeLen=Size;
+ memset(WAsmCode,0,2*Size);
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_17c4x(void)
+BEGIN
+ Boolean OK;
+ Word AdrWord;
+ int z;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* kein Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; WAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ /* konstantes Argument */
+
+ for (z=0; z<LittOrderCnt; z++)
+ if (Memo(LittOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=LittOrders[z].Code+(AdrWord & 0xff); CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ /* W-mit-f-Operationen */
+
+ for (z=0; z<AriOrderCnt; z++)
+ if (Memo(AriOrders[z].Name))
+ BEGIN
+ if ((ArgCnt==0) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegData);
+ WAsmCode[0]=AriOrders[z].Code+(AdrWord & 0xff);
+ if (ArgCnt==1)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=AriOrders[z].DefaultDir << 8;
+ END
+ else if (strcasecmp(ArgStr[2],"W")==0) CodeLen=1;
+ else if (strcasecmp(ArgStr[2],"F")==0)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=0x100;
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt1,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=(AdrWord << 8);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Bitoperationen */
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt3,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=BitOrders[z].Code+(AdrWord << 8);
+ ChkSpace(SegData);
+ END
+ END
+ END
+ return;
+ END
+
+ /* Register als Operand */
+
+ for (z=0; z<FOrderCnt; z++)
+ if (Memo(FOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]=FOrders[z].Code+AdrWord;
+ ChkSpace(SegData);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MOVFP")) OR (Memo("MOVPF")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (Memo("MOVFP"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ END
+ AdrWord=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=Lo(WAsmCode[0])+(AdrWord << 8)+0x4000;
+ if (Memo("MOVFP")) WAsmCode[0]+=0x2000;
+ CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("TABLRD")) OR (Memo("TABLWT")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=Lo(EvalIntExpression(ArgStr[3],Int8,&OK));
+ if (OK)
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt1,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]+=AdrWord << 8;
+ AdrWord=EvalIntExpression(ArgStr[1],UInt1,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]+=0xa800+(AdrWord << 9);
+ if (Memo("TABLWT")) WAsmCode[0]+=0x400;
+ CodeLen=1;
+ END
+ END
+ END
+ END;
+ return;
+ END
+
+ if ((Memo("TLRD")) OR (Memo("TLWT")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=Lo(EvalIntExpression(ArgStr[2],Int8,&OK));
+ if (OK)
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt1,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]+=(AdrWord << 9)+0xa000;
+ if (Memo("TLWT")) WAsmCode[0]+=0x400;
+ CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CALL")) OR (Memo("GOTO")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ if (((ProgCounter() ^ AdrWord) & 0xe000)!=0) WrError(1910);
+ else
+ BEGIN
+ WAsmCode[0]=0xc000+(AdrWord & 0x1fff);
+ if (Memo("CALL")) WAsmCode[0]+=0x2000;
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("LCALL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=3;
+ WAsmCode[0]=0xb000+Hi(AdrWord);
+ WAsmCode[1]=0x0103;
+ WAsmCode[2]=0xb700+Lo(AdrWord);
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_17c4x(void)
+BEGIN
+ return Memo("SFR");
+END
+
+ static void SwitchFrom_17c4x(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_17c4x(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x72; NOPCode=0x0000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)+(1<<SegData);
+ Grans[SegCode]=2; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
+ SegLimits[SegData] = 0xff;
+
+ MakeCode=MakeCode_17c4x; IsDef=IsDef_17c4x;
+ SwitchFrom=SwitchFrom_17c4x; InitFields();
+END
+
+ void code17c4x_init(void)
+BEGIN
+ CPU17C42=AddCPU("17C42",SwitchTo_17c4x);
+END
diff --git a/code17c4x.h b/code17c4x.h
new file mode 100644
index 0000000..adf2b0d
--- /dev/null
+++ b/code17c4x.h
@@ -0,0 +1,11 @@
+/* code17c4x.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator PIC17C4x */
+/* */
+/* Historie: 21.8.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code17c4x_init(void);
diff --git a/code29k.c b/code29k.c
new file mode 100644
index 0000000..96f0f9c
--- /dev/null
+++ b/code29k.c
@@ -0,0 +1,887 @@
+/* code29k.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator AM29xxx-Familie */
+/* */
+/* Historie: 18.11.1996 Grundsteinlegung */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "stringlists.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ Boolean MustSup;
+ CPUVar MinCPU;
+ LongWord Code;
+ } StdOrder;
+
+typedef struct
+ {
+ char *Name;
+ Boolean HasReg,HasInd;
+ CPUVar MinCPU;
+ LongWord Code;
+ } JmpOrder;
+
+typedef struct
+ {
+ char *Name;
+ LongWord Code;
+ } SPReg;
+
+#define StdOrderCount 51
+#define NoImmOrderCount 22
+#define VecOrderCount 10
+#define JmpOrderCount 5
+#define FixedOrderCount 2
+#define MemOrderCount 7
+#define SPRegCount 28
+
+static StdOrder *StdOrders;
+static StdOrder *NoImmOrders;
+static StdOrder *VecOrders;
+static JmpOrder *JmpOrders;
+static StdOrder *FixedOrders;
+static StdOrder *MemOrders;
+static SPReg *SPRegs;
+
+
+static CPUVar CPU29000,CPU29240,CPU29243,CPU29245;
+static LongInt Reg_RBP;
+static StringList Emulations;
+static SimpProc SaveInitProc;
+
+/*-------------------------------------------------------------------------*/
+
+ static void AddStd(char *NName, CPUVar NMin, Boolean NSup, LongWord NCode)
+BEGIN
+ if (InstrZ>=StdOrderCount) exit(255);
+ StdOrders[InstrZ].Name=NName;
+ StdOrders[InstrZ].Code=NCode;
+ StdOrders[InstrZ].MustSup=NSup;
+ StdOrders[InstrZ++].MinCPU=NMin;
+END
+
+ static void AddNoImm(char *NName, CPUVar NMin, Boolean NSup, LongWord NCode)
+BEGIN
+ if (InstrZ>=NoImmOrderCount) exit(255);
+ NoImmOrders[InstrZ].Name=NName;
+ NoImmOrders[InstrZ].Code=NCode;
+ NoImmOrders[InstrZ].MustSup=NSup;
+ NoImmOrders[InstrZ++].MinCPU=NMin;
+END
+
+ static void AddVec(char *NName, CPUVar NMin, Boolean NSup, LongWord NCode)
+BEGIN
+ if (InstrZ>=VecOrderCount) exit(255);
+ VecOrders[InstrZ].Name=NName;
+ VecOrders[InstrZ].Code=NCode;
+ VecOrders[InstrZ].MustSup=NSup;
+ VecOrders[InstrZ++].MinCPU=NMin;
+END
+
+ static void AddJmp(char *NName, CPUVar NMin, Boolean NHas, Boolean NInd, LongWord NCode)
+BEGIN
+ if (InstrZ>=JmpOrderCount) exit(255);
+ JmpOrders[InstrZ].Name=NName;
+ JmpOrders[InstrZ].HasReg=NHas;
+ JmpOrders[InstrZ].HasInd=NInd;
+ JmpOrders[InstrZ].Code=NCode;
+ JmpOrders[InstrZ++].MinCPU=NMin;
+END
+
+ static void AddFixed(char *NName, CPUVar NMin, Boolean NSup, LongWord NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ].MustSup=NSup;
+ FixedOrders[InstrZ++].MinCPU=NMin;
+END
+
+ static void AddMem(char *NName, CPUVar NMin, Boolean NSup, LongWord NCode)
+BEGIN
+ if (InstrZ>=MemOrderCount) exit(255);
+ MemOrders[InstrZ].Name=NName;
+ MemOrders[InstrZ].Code=NCode;
+ MemOrders[InstrZ].MustSup=NSup;
+ MemOrders[InstrZ++].MinCPU=NMin;
+END
+
+ static void AddSP(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=SPRegCount) exit(255);
+ SPRegs[InstrZ].Name=NName;
+ SPRegs[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ StdOrders=(StdOrder *) malloc(sizeof(StdOrder)*StdOrderCount); InstrZ=0;
+ AddStd("ADD" ,CPU29245,False,0x14); AddStd("ADDC" ,CPU29245,False,0x1c);
+ AddStd("ADDCS" ,CPU29245,False,0x18); AddStd("ADDCU" ,CPU29245,False,0x1a);
+ AddStd("ADDS" ,CPU29245,False,0x10); AddStd("ADDU" ,CPU29245,False,0x12);
+ AddStd("AND" ,CPU29245,False,0x90); AddStd("ANDN" ,CPU29245,False,0x9c);
+ AddStd("CPBYTE" ,CPU29245,False,0x2e); AddStd("CPEQ" ,CPU29245,False,0x60);
+ AddStd("CPGE" ,CPU29245,False,0x4c); AddStd("CPGEU" ,CPU29245,False,0x4e);
+ AddStd("CPGT" ,CPU29245,False,0x48); AddStd("CPGTU" ,CPU29245,False,0x4a);
+ AddStd("CPLE" ,CPU29245,False,0x44); AddStd("CPLEU" ,CPU29245,False,0x46);
+ AddStd("CPLT" ,CPU29245,False,0x40); AddStd("CPLTU" ,CPU29245,False,0x42);
+ AddStd("CPNEQ" ,CPU29245,False,0x62); AddStd("DIV" ,CPU29245,False,0x6a);
+ AddStd("DIV0" ,CPU29245,False,0x68); AddStd("DIVL" ,CPU29245,False,0x6c);
+ AddStd("DIVREM" ,CPU29245,False,0x6e); AddStd("EXBYTE" ,CPU29245,False,0x0a);
+ AddStd("EXHW" ,CPU29245,False,0x7c); AddStd("EXTRACT",CPU29245,False,0x7a);
+ AddStd("INBYTE" ,CPU29245,False,0x0c); AddStd("INHW" ,CPU29245,False,0x78);
+ AddStd("MUL" ,CPU29245,False,0x64); AddStd("MULL" ,CPU29245,False,0x66);
+ AddStd("MULU" ,CPU29245,False,0x74); AddStd("NAND" ,CPU29245,False,0x9a);
+ AddStd("NOR" ,CPU29245,False,0x98); AddStd("OR" ,CPU29245,False,0x92);
+ AddStd("SLL" ,CPU29245,False,0x80); AddStd("SRA" ,CPU29245,False,0x86);
+ AddStd("SRL" ,CPU29245,False,0x82); AddStd("SUB" ,CPU29245,False,0x24);
+ AddStd("SUBC" ,CPU29245,False,0x2c); AddStd("SUBCS" ,CPU29245,False,0x28);
+ AddStd("SUBCU" ,CPU29245,False,0x2a); AddStd("SUBR" ,CPU29245,False,0x34);
+ AddStd("SUBRC" ,CPU29245,False,0x3c); AddStd("SUBRCS" ,CPU29245,False,0x38);
+ AddStd("SUBRCU" ,CPU29245,False,0x3a); AddStd("SUBRS" ,CPU29245,False,0x30);
+ AddStd("SUBRU" ,CPU29245,False,0x32); AddStd("SUBS" ,CPU29245,False,0x20);
+ AddStd("SUBU" ,CPU29245,False,0x22); AddStd("XNOR" ,CPU29245,False,0x96);
+ AddStd("XOR" ,CPU29245,False,0x94);
+
+ NoImmOrders=(StdOrder *) malloc(sizeof(StdOrder)*NoImmOrderCount); InstrZ=0;
+ AddNoImm("DADD" ,CPU29000,False,0xf1); AddNoImm("DDIV" ,CPU29000,False,0xf7);
+ AddNoImm("DEQ" ,CPU29000,False,0xeb); AddNoImm("DGE" ,CPU29000,False,0xef);
+ AddNoImm("DGT" ,CPU29000,False,0xed); AddNoImm("DIVIDE" ,CPU29000,False,0xe1);
+ AddNoImm("DIVIDU" ,CPU29000,False,0xe3); AddNoImm("DMUL" ,CPU29000,False,0xf5);
+ AddNoImm("DSUB" ,CPU29000,False,0xf3); AddNoImm("FADD" ,CPU29000,False,0xf0);
+ AddNoImm("FDIV" ,CPU29000,False,0xf6); AddNoImm("FDMUL" ,CPU29000,False,0xf9);
+ AddNoImm("FEQ" ,CPU29000,False,0xea); AddNoImm("FGE" ,CPU29000,False,0xee);
+ AddNoImm("FGT" ,CPU29000,False,0xec); AddNoImm("FMUL" ,CPU29000,False,0xf4);
+ AddNoImm("FSUB" ,CPU29000,False,0xf2); AddNoImm("MULTIPLU",CPU29243,False,0xe2);
+ AddNoImm("MULTIPLY",CPU29243,False,0xe0); AddNoImm("MULTM" ,CPU29243,False,0xde);
+ AddNoImm("MULTMU" ,CPU29243,False,0xdf); AddNoImm("SETIP" ,CPU29245,False,0x9e);
+
+ VecOrders=(StdOrder *) malloc(sizeof(StdOrder)*VecOrderCount); InstrZ=0;
+ AddVec("ASEQ" ,CPU29245,False,0x70); AddVec("ASGE" ,CPU29245,False,0x5c);
+ AddVec("ASGEU" ,CPU29245,False,0x5e); AddVec("ASGT" ,CPU29245,False,0x58);
+ AddVec("ASGTU" ,CPU29245,False,0x5a); AddVec("ASLE" ,CPU29245,False,0x54);
+ AddVec("ASLEU" ,CPU29245,False,0x56); AddVec("ASLT" ,CPU29245,False,0x50);
+ AddVec("ASLTU" ,CPU29245,False,0x52); AddVec("ASNEQ" ,CPU29245,False,0x72);
+
+ JmpOrders=(JmpOrder *) malloc(sizeof(JmpOrder)*JmpOrderCount); InstrZ=0;
+ AddJmp("CALL" ,CPU29245,True ,True ,0xa8); AddJmp("JMP" ,CPU29245,False,True ,0xa0);
+ AddJmp("JMPF" ,CPU29245,True ,True ,0xa4); AddJmp("JMPFDEC",CPU29245,True ,False,0xb4);
+ AddJmp("JMPT" ,CPU29245,True ,True ,0xac);
+
+ FixedOrders=(StdOrder *) malloc(sizeof(StdOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("HALT" ,CPU29245,True,0x89); AddFixed("IRET" ,CPU29245,True,0x88);
+
+ MemOrders=(StdOrder *) malloc(sizeof(StdOrder)*MemOrderCount); InstrZ=0;
+ AddMem("LOAD" ,CPU29245,False,0x16); AddMem("LOADL" ,CPU29245,False,0x06);
+ AddMem("LOADM" ,CPU29245,False,0x36); AddMem("LOADSET",CPU29245,False,0x26);
+ AddMem("STORE" ,CPU29245,False,0x1e); AddMem("STOREL" ,CPU29245,False,0x0e);
+ AddMem("STOREM" ,CPU29245,False,0x3e);
+
+ SPRegs=(SPReg *) malloc(sizeof(SPReg)*SPRegCount); InstrZ=0;
+ AddSP("VAB", 0);
+ AddSP("OPS", 1);
+ AddSP("CPS", 2);
+ AddSP("CFG", 3);
+ AddSP("CHA", 4);
+ AddSP("CHD", 5);
+ AddSP("CHC", 6);
+ AddSP("RBP", 7);
+ AddSP("TMC", 8);
+ AddSP("TMR", 9);
+ AddSP("PC0", 10);
+ AddSP("PC1", 11);
+ AddSP("PC2", 12);
+ AddSP("MMU", 13);
+ AddSP("LRU", 14);
+ AddSP("CIR", 29);
+ AddSP("CDR", 30);
+ AddSP("IPC", 128);
+ AddSP("IPA", 129);
+ AddSP("IPB", 130);
+ AddSP("Q", 131);
+ AddSP("ALU", 132);
+ AddSP("BP", 133);
+ AddSP("FC", 134);
+ AddSP("CR", 135);
+ AddSP("FPE", 160);
+ AddSP("INTE",161);
+ AddSP("FPS", 162);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(StdOrders);
+ free(NoImmOrders);
+ free(VecOrders);
+ free(JmpOrders);
+ free(FixedOrders);
+ free(MemOrders);
+ free(SPRegs);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void ChkSup(void)
+BEGIN
+ if (NOT SupAllowed) WrError(50);
+END
+
+ static Boolean IsSup(LongWord RegNo)
+BEGIN
+ return ((RegNo<0x80) OR (RegNo>=0xa0));
+END
+
+ static Boolean ChkCPU(CPUVar Min)
+BEGIN
+ if (MomCPU>=Min) return True;
+ else return (StringListPresent(Emulations,OpPart));
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodeReg(char *Asc, LongWord *Erg)
+BEGIN
+ Boolean io,OK;
+
+ if ((strlen(Asc)>=2) AND (toupper(*Asc)=='R'))
+ BEGIN
+ *Erg=ConstLongInt(Asc+1,&io);
+ OK=((io) AND (*Erg<=255));
+ END
+ else if ((strlen(Asc)>=3) AND (toupper(*Asc)=='G') AND (toupper(Asc[1])=='R'))
+ BEGIN
+ *Erg=ConstLongInt(Asc+2,&io);
+ OK=((io) AND (*Erg<=127));
+ END
+ else if ((strlen(Asc)>=3) AND (toupper(*Asc)=='L') AND (toupper(Asc[1])=='R'))
+ BEGIN
+ *Erg=ConstLongInt(Asc+2,&io);
+ OK=((io) AND (*Erg<=127));
+ *Erg+=128;
+ END
+ else OK=False;
+ if (OK)
+ if ((*Erg<127) AND (Odd(Reg_RBP >> ((*Erg) >> 4)))) ChkSup();
+ return OK;
+END
+
+ static Boolean DecodeSpReg(char *Asc_O, LongWord *Erg)
+BEGIN
+ int z;
+ String Asc;
+
+ strmaxcpy(Asc,Asc_O,255); NLS_UpString(Asc);
+ for (z=0; z<SPRegCount; z++)
+ if (strcmp(Asc,SPRegs[z].Name)==0)
+ BEGIN
+ *Erg=SPRegs[z].Code;
+ break;
+ END
+ return (z<SPRegCount);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME29KCount 1
+ static ASSUMERec ASSUME29Ks[ASSUME29KCount]=
+ {{"RBP", &Reg_RBP, 0, 0xff, 0x00000000}};
+
+ int z;
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME29Ks,ASSUME29KCount);
+ return True;
+ END
+
+ if (Memo("EMULATED"))
+ BEGIN
+ if (ArgCnt<1) WrError(1110);
+ else
+ for (z=1; z<=ArgCnt; z++)
+ BEGIN
+ NLS_UpString(ArgStr[z]);
+ if (NOT StringListPresent(Emulations,ArgStr[z]))
+ AddStringListLast(&Emulations,ArgStr[z]);
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_29K(void)
+BEGIN
+ int z,l;
+ LongWord Dest,Src1,Src2,Src3,AdrLong;
+ LongInt AdrInt;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* Nullanweisung */
+
+ if (Memo("") AND (*AttrPart=='\0') AND (ArgCnt==0)) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(True)) return;
+
+ /* Variante 1: Register <-- Register op Register/uimm8 */
+
+ for (z=0; z<StdOrderCount; z++)
+ if (Memo(StdOrders[z].Name))
+ BEGIN
+ if ((ArgCnt>3) OR (ArgCnt<2)) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ OK=True;
+ if (ArgCnt==2) Src1=Dest;
+ else OK=DecodeReg(ArgStr[2],&Src1);
+ if (NOT OK) WrXError(1445,ArgStr[2]);
+ else
+ BEGIN
+ if (DecodeReg(ArgStr[ArgCnt],&Src2))
+ BEGIN
+ OK=True; Src3=0;
+ END
+ else
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[ArgCnt],UInt8,&OK);
+ Src3=0x1000000;
+ END
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=(StdOrders[z].Code << 24)+Src3+(Dest << 16)+(Src1 << 8)+Src2;
+ if (StdOrders[z].MustSup) ChkSup();
+ END
+ END
+ END
+ return;
+ END
+
+ /* Variante 2: Register <-- Register op Register */
+
+ for (z=0; z<NoImmOrderCount; z++)
+ if (Memo(NoImmOrders[z].Name))
+ BEGIN
+ if ((ArgCnt>3) OR (ArgCnt<2)) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ OK=True;
+ if (ArgCnt==2) Src1=Dest;
+ else OK=DecodeReg(ArgStr[2],&Src1);
+ if (NOT OK) WrError(1445);
+ else if (NOT DecodeReg(ArgStr[ArgCnt],&Src2)) WrError(1445);
+ else
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=(NoImmOrders[z].Code << 24)+(Dest << 16)+(Src1 << 8)+Src2;
+ if (NoImmOrders[z].MustSup) ChkSup();
+ END
+ END
+ return;
+ END
+
+ /* Variante 3: Vektor <-- Register op Register/uimm8 */
+
+ for (z=0; z<VecOrderCount; z++)
+ if (Memo(VecOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Dest=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if (FirstPassUnknown) Dest=64;
+ if (OK)
+ if (NOT DecodeReg(ArgStr[2],&Src1)) WrError(1445);
+ else
+ BEGIN
+ if (DecodeReg(ArgStr[ArgCnt],&Src2))
+ BEGIN
+ OK=True; Src3=0;
+ END
+ else
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[ArgCnt],UInt8,&OK);
+ Src3=0x1000000;
+ END
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=(VecOrders[z].Code << 24)+Src3+(Dest << 16)+(Src1 << 8)+Src2;
+ if ((VecOrders[z].MustSup) OR (Dest<=63)) ChkSup();
+ END
+ END
+ END
+ return;
+ END
+
+ /* Variante 4: ohne Operanden */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=4; DAsmCode[0]=FixedOrders[z].Code << 24;
+ if (FixedOrders[z].MustSup) ChkSup();
+ END
+ return;
+ END
+
+ /* Variante 5 : [0], Speichersteuerwort, Register, Register/uimm8 */
+
+ for (z=0; z<MemOrderCount; z++)
+ if (Memo(MemOrders[z].Name))
+ BEGIN
+ if ((ArgCnt!=3) AND (ArgCnt!=4)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==3)
+ BEGIN
+ OK=True; AdrLong=0;
+ END
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (OK) OK=ChkRange(AdrLong,0,0);
+ END
+ if (OK)
+ BEGIN
+ Dest=EvalIntExpression(ArgStr[ArgCnt-2],UInt7,&OK);
+ if (OK)
+ if (DecodeReg(ArgStr[ArgCnt-1],&Src1))
+ BEGIN
+ if (DecodeReg(ArgStr[ArgCnt],&Src2))
+ BEGIN
+ OK=True; Src3=0;
+ END
+ else
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[ArgCnt],UInt8,&OK);
+ Src3=0x1000000;
+ END
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=(MemOrders[z].Code << 24)+Src3+(Dest << 16)+(Src1 << 8)+Src2;
+ if (MemOrders[z].MustSup) ChkSup();
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Sprungbefehle */
+
+ for (z=0; z<JmpOrderCount; z++)
+ BEGIN
+ l=strlen(JmpOrders[z].Name);
+ if ((strncmp(OpPart,JmpOrders[z].Name,l)==0) AND ((OpPart[l]=='\0') OR (OpPart[l]=='I')))
+ BEGIN
+ if (ArgCnt!=1+Ord(JmpOrders[z].HasReg)) WrError(1110);
+ else if (DecodeReg(ArgStr[ArgCnt],&Src1))
+ BEGIN
+ if (NOT JmpOrders[z].HasReg)
+ BEGIN
+ Dest=0; OK=True;
+ END
+ else OK=DecodeReg(ArgStr[1],&Dest);
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=((JmpOrders[z].Code+0x20) << 24)+(Dest << 8)+Src1;
+ END
+ END
+ else if (OpPart[l]=='I') WrError(1445);
+ else
+ BEGIN
+ if (NOT JmpOrders[z].HasReg)
+ BEGIN
+ Dest=0; OK=True;
+ END
+ else OK=DecodeReg(ArgStr[1],&Dest);
+ if (OK)
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[ArgCnt],Int32,&OK);
+ AdrInt=AdrLong-EProgCounter();
+ if (OK)
+ if ((AdrLong & 3)!=0) WrError(1325);
+ else if ((AdrInt<=0x1ffff) AND (AdrInt>=-0x20000))
+ BEGIN
+ CodeLen=4;
+ AdrLong-=EProgCounter();
+ DAsmCode[0]=(JmpOrders[z].Code << 24)
+ +((AdrLong & 0x3fc00) << 6)
+ +(Dest << 8)+((AdrLong & 0x3fc) >> 2);
+ END
+ else if ((NOT SymbolQuestionable) AND (AdrLong>0x3fffff)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=((JmpOrders[z].Code+1) << 24)
+ +((AdrLong & 0x3fc00) << 6)
+ +(Dest << 8)+((AdrLong & 0x3fc) >> 2);
+ END
+ END
+ END
+ return;
+ END
+ END
+
+ /* Sonderfaelle */
+
+ if (Memo("CLASS"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT ChkCPU(CPU29000)) WrError(1500);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrError(1445);
+ else if (NOT DecodeReg(ArgStr[2],&Src1)) WrError(1445);
+ else
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[3],UInt2,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=0xe6000000+(Dest << 16)+(Src1 << 8)+Src2;
+ END
+ END
+ return;
+ END
+
+ if (Memo("EMULATE"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Dest=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if (FirstPassUnknown) Dest=64;
+ if (OK)
+ if (NOT DecodeReg(ArgStr[2],&Src1)) WrError(1445);
+ else if (NOT DecodeReg(ArgStr[ArgCnt],&Src2)) WrError(1445);
+ else
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=0xd7000000+(Dest << 16)+(Src1 << 8)+Src2;
+ if (Dest<=63) ChkSup();
+ END
+ END
+ return;
+ END
+
+ if (Memo("SQRT"))
+ BEGIN
+ if ((ArgCnt!=3) AND (ArgCnt!=2)) WrError(1110);
+ else if (NOT ChkCPU(CPU29000)) WrError(1500);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrError(1445);
+ else
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ OK=True; Src1=Dest;
+ END
+ else OK=DecodeReg(ArgStr[2],&Src1);
+ if (NOT OK) WrError(1445);
+ else
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[ArgCnt],UInt2,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=0xe5000000+(Dest << 16)+(Src1 << 8)+Src2;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CLZ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrError(1445);
+ else
+ BEGIN
+ if (DecodeReg(ArgStr[2],&Src1))
+ BEGIN
+ OK=True; Src3=0;
+ END
+ else
+ BEGIN
+ Src1=EvalIntExpression(ArgStr[2],UInt8,&OK);
+ Src3=0x1000000;
+ END
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=0x08000000+Src3+(Dest << 16)+Src1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CONST"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrError(1445);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[2],Int32,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=((AdrLong & 0xff00) << 8)+(Dest << 8)+(AdrLong & 0xff);
+ AdrLong=AdrLong >> 16;
+ if (AdrLong==0xffff) DAsmCode[0]+=0x01000000;
+ else
+ BEGIN
+ DAsmCode[0]+=0x03000000;
+ if (AdrLong!=0)
+ BEGIN
+ CodeLen=8;
+ DAsmCode[1]=0x02000000+((AdrLong & 0xff00) << 16)+(Dest << 8)+(AdrLong & 0xff);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CONSTH")) OR (Memo("CONSTN")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrError(1445);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(ArgStr[2],Int32,&OK);
+ if (FirstPassUnknown) AdrLong&=0xffff;
+ if ((Memo("CONSTN")) AND ((AdrLong >> 16)==0xffff)) AdrLong&=0xffff;
+ if (ChkRange(AdrLong,0,0xffff))
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=0x1000000+((AdrLong & 0xff00) << 8)+(Dest << 8)+(AdrLong & 0xff);
+ if (Memo("CONSTH")) DAsmCode[0]+=0x1000000;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CONVERT"))
+ BEGIN
+ if (ArgCnt!=6) WrError(1110);
+ else if (NOT ChkCPU(CPU29000)) WrError(1500);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrError(1445);
+ else if (NOT DecodeReg(ArgStr[2],&Src1)) WrError(1445);
+ else
+ BEGIN
+ Src2=0;
+ Src2+=EvalIntExpression(ArgStr[3],UInt1,&OK) << 7;
+ if (OK)
+ BEGIN
+ Src2+=EvalIntExpression(ArgStr[4],UInt3,&OK) << 4;
+ if (OK)
+ BEGIN
+ Src2+=EvalIntExpression(ArgStr[5],UInt2,&OK) << 2;
+ if (OK)
+ BEGIN
+ Src2+=EvalIntExpression(ArgStr[6],UInt2,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=0xe4000000+(Dest << 16)+(Src1 << 8)+Src2;
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("EXHWS"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrError(1445);
+ else if (NOT DecodeReg(ArgStr[2],&Src1)) WrError(1445);
+ else
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=0x7e000000+(Dest << 16)+(Src1 << 8);
+ END
+ return;
+ END
+
+ if ((Memo("INV")) OR (Memo("IRETINV")))
+ BEGIN
+ if (ArgCnt>1) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ Src1=0; OK=True;
+ END
+ else Src1=EvalIntExpression(ArgStr[1],UInt2,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ DAsmCode[0]=Src1 << 16;
+ if (Memo("INV")) DAsmCode[0]+=0x9f000000;
+ else DAsmCode[0]+=0x8c000000;
+ ChkSup();
+ END
+ END
+ return;
+ END
+
+ if (Memo("MFSR"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrXError(1445,ArgStr[1]);
+ else if (NOT DecodeSpReg(ArgStr[2],&Src1)) WrXError(1440,ArgStr[2]);
+ else
+ BEGIN
+ DAsmCode[0]=0xc6000000+(Dest << 16)+(Src1 << 8);
+ CodeLen=4; if (IsSup(Src1)) ChkSup();
+ END
+ return;
+ END
+
+ if (Memo("MTSR"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeSpReg(ArgStr[1],&Dest)) WrXError(1440,ArgStr[1]);
+ else if (NOT DecodeReg(ArgStr[2],&Src1)) WrXError(1445,ArgStr[2]);
+ else
+ BEGIN
+ DAsmCode[0]=0xce000000+(Dest << 8)+Src1;
+ CodeLen=4; if (IsSup(Dest)) ChkSup();
+ END
+ return;
+ END
+
+ if (Memo("MTSRIM"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeSpReg(ArgStr[1],&Dest)) WrXError(1440,ArgStr[1]);
+ else
+ BEGIN
+ Src1=EvalIntExpression(ArgStr[2],UInt16,&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x04000000+((Src1 & 0xff00) << 8)+(Dest << 8)+Lo(Src1);
+ CodeLen=4; if (IsSup(Dest)) ChkSup();
+ END
+ END
+ return;
+ END
+
+ if (Memo("MFTLB"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrXError(1445,ArgStr[1]);
+ else if (NOT DecodeReg(ArgStr[2],&Src1)) WrXError(1445,ArgStr[2]);
+ else
+ BEGIN
+ DAsmCode[0]=0xb6000000+(Dest << 16)+(Src1 << 8);
+ CodeLen=4; ChkSup();
+ END
+ return;
+ END
+
+ if (Memo("MTTLB"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest)) WrXError(1445,ArgStr[1]);
+ else if (NOT DecodeReg(ArgStr[2],&Src1)) WrXError(1445,ArgStr[2]);
+ else
+ BEGIN
+ DAsmCode[0]=0xbe000000+(Dest << 8)+Src1;
+ CodeLen=4; ChkSup();
+ END
+ return;
+ END
+
+ /* unbekannter Befehl */
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_29K(void)
+BEGIN
+ SaveInitProc();
+ Reg_RBP=0; ClearStringList(&Emulations);
+END
+
+ static Boolean IsDef_29K(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_29K(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_29K(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeC; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x29; NOPCode=0x000000000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=4; SegInits[SegCode]=0;
+#ifdef __STDC__
+ SegLimits[SegCode] = 0xfffffffful;
+#else
+ SegLimits[SegCode] = 0xffffffffl;
+#endif
+
+ MakeCode=MakeCode_29K; IsDef=IsDef_29K;
+ AddONOFF("SUPMODE", &SupAllowed, SupAllowedName,False);
+
+ SwitchFrom=SwitchFrom_29K; InitFields();
+END
+
+ void code29k_init(void)
+BEGIN
+ CPU29245=AddCPU("AM29245",SwitchTo_29K);
+ CPU29243=AddCPU("AM29243",SwitchTo_29K);
+ CPU29240=AddCPU("AM29240",SwitchTo_29K);
+ CPU29000=AddCPU("AM29000",SwitchTo_29K);
+
+ Emulations=Nil;
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_29K;
+END
+
diff --git a/code29k.h b/code29k.h
new file mode 100644
index 0000000..d603faf
--- /dev/null
+++ b/code29k.h
@@ -0,0 +1,11 @@
+/* code29k.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator AM29xxx-Familie */
+/* */
+/* Historie: 18.11.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code29k_init(void);
diff --git a/code3201x.c b/code3201x.c
new file mode 100644
index 0000000..ee7f65d
--- /dev/null
+++ b/code3201x.c
@@ -0,0 +1,553 @@
+/* code3201x.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS3201x-Familie */
+/* */
+/* Historie: 28.11.1996 Grundsteinlegung */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 18. 8.1992 BookKeeping-Aufruf in RES */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Boolean Must1;
+ } AdrOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Word AllowShifts;
+ } AdrShiftOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Integer Min,Max;
+ Word Mask;
+ } ImmOrder;
+
+
+#define FixedOrderCnt 14
+#define JmpOrderCnt 11
+#define AdrOrderCnt 21
+#define AdrShiftOrderCnt 5
+#define ImmOrderCnt 3
+
+
+static Word AdrMode;
+static Boolean AdrOK;
+
+static CPUVar CPU32010,CPU32015;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *JmpOrders;
+static AdrOrder *AdrOrders;
+static AdrShiftOrder *AdrShiftOrders;
+static ImmOrder *ImmOrders;
+
+/*----------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddJmp(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=JmpOrderCnt) exit(255);
+ JmpOrders[InstrZ].Name=NName;
+ JmpOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddAdr(char *NName, Word NCode, Word NMust1)
+BEGIN
+ if (InstrZ>=AdrOrderCnt) exit(255);
+ AdrOrders[InstrZ].Name=NName;
+ AdrOrders[InstrZ].Code=NCode;
+ AdrOrders[InstrZ++].Must1=NMust1;
+END
+
+ static void AddAdrShift(char *NName, Word NCode, Word NAllow)
+BEGIN
+ if (InstrZ>=AdrShiftOrderCnt) exit(255);
+ AdrShiftOrders[InstrZ].Name=NName;
+ AdrShiftOrders[InstrZ].Code=NCode;
+ AdrShiftOrders[InstrZ++].AllowShifts=NAllow;
+END
+
+ static void AddImm(char *NName, Word NCode, Integer NMin, Integer NMax, Word NMask)
+BEGIN
+ if (InstrZ>=ImmOrderCnt) exit(255);
+ ImmOrders[InstrZ].Name=NName;
+ ImmOrders[InstrZ].Code=NCode;
+ ImmOrders[InstrZ].Min=NMin;
+ ImmOrders[InstrZ].Max=NMax;
+ ImmOrders[InstrZ++].Mask=NMask;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("ABS" , 0x7f88); AddFixed("APAC" , 0x7f8f);
+ AddFixed("CALA" , 0x7f8c); AddFixed("DINT" , 0x7f81);
+ AddFixed("EINT" , 0x7f82); AddFixed("NOP" , 0x7f80);
+ AddFixed("PAC" , 0x7f8e); AddFixed("POP" , 0x7f9d);
+ AddFixed("PUSH" , 0x7f9c); AddFixed("RET" , 0x7f8d);
+ AddFixed("ROVM" , 0x7f8a); AddFixed("SOVM" , 0x7f8b);
+ AddFixed("SPAC" , 0x7f90); AddFixed("ZAC" , 0x7f89);
+
+ JmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*JmpOrderCnt); InstrZ=0;
+ AddJmp("B" , 0xf900); AddJmp("BANZ" , 0xf400);
+ AddJmp("BGEZ" , 0xfd00); AddJmp("BGZ" , 0xfc00);
+ AddJmp("BIOZ" , 0xf600); AddJmp("BLEZ" , 0xfb00);
+ AddJmp("BLZ" , 0xfa00); AddJmp("BNZ" , 0xfe00);
+ AddJmp("BV" , 0xf500); AddJmp("BZ" , 0xff00);
+ AddJmp("CALL" , 0xf800);
+
+ AdrOrders=(AdrOrder *) malloc(sizeof(AdrOrder)*AdrOrderCnt); InstrZ=0;
+ AddAdr("ADDH" , 0x6000, False); AddAdr("ADDS" , 0x6100, False);
+ AddAdr("AND" , 0x7900, False); AddAdr("DMOV" , 0x6900, False);
+ AddAdr("LDP" , 0x6f00, False); AddAdr("LST" , 0x7b00, False);
+ AddAdr("LT" , 0x6a00, False); AddAdr("LTA" , 0x6c00, False);
+ AddAdr("LTD" , 0x6b00, False); AddAdr("MAR" , 0x6800, False);
+ AddAdr("MPY" , 0x6d00, False); AddAdr("OR" , 0x7a00, False);
+ AddAdr("SST" , 0x7c00, True ); AddAdr("SUBC" , 0x6400, False);
+ AddAdr("SUBH" , 0x6200, False); AddAdr("SUBS" , 0x6300, False);
+ AddAdr("TBLR" , 0x6700, False); AddAdr("TBLW" , 0x7d00, False);
+ AddAdr("XOR" , 0x7800, False); AddAdr("ZALH" , 0x6500, False);
+ AddAdr("ZALS" , 0x6600, False);
+
+ AdrShiftOrders=(AdrShiftOrder *) malloc(sizeof(AdrShiftOrder)*AdrShiftOrderCnt); InstrZ=0;
+ AddAdrShift("ADD" , 0x0000, 0xffff);
+ AddAdrShift("LAC" , 0x2000, 0xffff);
+ AddAdrShift("SACH" , 0x5800, 0x0013);
+ AddAdrShift("SACL" , 0x5000, 0x0001);
+ AddAdrShift("SUB" , 0x1000, 0xffff);
+
+ ImmOrders=(ImmOrder *) malloc(sizeof(ImmOrder)*ImmOrderCnt); InstrZ=0;
+ AddImm("LACK", 0x7e00, 0, 255, 0xff);
+ AddImm("LDPK", 0x6e00, 0, 1, 0x1);
+ AddImm("MPYK", 0x8000, -4096, 4095, 0x1fff);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(JmpOrders);
+ free(AdrOrders);
+ free(AdrShiftOrders);
+ free(ImmOrders);
+END
+
+/*----------------------------------------------------------------------------*/
+
+ static Word EvalARExpression(char *Asc, Boolean *OK)
+BEGIN
+ *OK=True;
+ if (strcasecmp(Asc,"AR0")==0) return 0;
+ if (strcasecmp(Asc,"AR1")==0) return 1;
+ return EvalIntExpression(Asc,UInt1,OK);
+END
+
+ static void DecodeAdr(char *Arg, int Aux, Boolean Must1)
+BEGIN
+ Byte h;
+ char *p;
+
+ AdrOK=False;
+
+ if ((strcmp(Arg,"*")==0) OR (strcmp(Arg,"*-")==0) OR (strcmp(Arg,"*+")==0))
+ BEGIN
+ AdrMode=0x88;
+ if (strlen(Arg)==2)
+ AdrMode+=(Arg[1]=='+') ? 0x20 : 0x10;
+ if (Aux<=ArgCnt)
+ BEGIN
+ h=EvalARExpression(ArgStr[Aux],&AdrOK);
+ if (AdrOK)
+ BEGIN
+ AdrMode&=0xf7; AdrMode+=h;
+ END
+ END
+ else AdrOK=True;
+ END
+ else if (Aux<=ArgCnt) WrError(1110);
+ else
+ BEGIN
+ h=0;
+ if ((strlen(Arg)>3) AND (strncasecmp(Arg,"DAT",3)==0))
+ BEGIN
+ AdrOK=True;
+ for (p=Arg+3; *p!='\0'; p++)
+ if ((*p>'9') OR (*p<'0')) AdrOK=False;
+ if (AdrOK) h=EvalIntExpression(Arg+3,UInt8,&AdrOK);
+ END
+ if (NOT AdrOK) h=EvalIntExpression(Arg,Int8,&AdrOK);
+ if (AdrOK)
+ if ((Must1) AND (h<0x80) AND (NOT FirstPassUnknown))
+ BEGIN
+ WrError(1315); AdrOK=False;
+ END
+ else
+ BEGIN
+ AdrMode=h & 0x7f; ChkSpace(SegData);
+ END
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Word Size;
+ int z,z2;
+ char *p;
+ TempResult t;
+ Boolean OK;
+
+ if (Memo("PORT"))
+ BEGIN
+ CodeEquate(SegIO,0,7);
+ return True;
+ END
+
+ if (Memo("RES"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("DATA"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ OK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (OK)
+ BEGIN
+ EvalExpression(ArgStr[z],&t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if ((t.Contents.Int<-32768) OR (t.Contents.Int>0xffff))
+ BEGIN
+ WrError(1320); OK=False;
+ END
+ else WAsmCode[CodeLen++]=t.Contents.Int;
+ break;
+ case TempFloat:
+ WrError(1135); OK=False;
+ break;
+ case TempString:
+ for (p=t.Contents.Ascii,z2=0; *p!='\0'; p++,z2++)
+ BEGIN
+ if ((z2&1)==0)
+ WAsmCode[CodeLen]=CharTransTable[((usint)*p)&0xff];
+ else
+ WAsmCode[CodeLen++]+=((Word) CharTransTable[((usint)*p)&0xff]) << 8;
+ END
+ if ((z2&1)==0) CodeLen++;
+ break;
+ default:
+ OK=False;
+ END
+ END
+ if (NOT OK) CodeLen=0;
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_3201X(void)
+BEGIN
+ Boolean OK,HasSh;
+ Word AdrWord;
+ LongInt AdrLong;
+ int z,Cnt;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* kein Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; WAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ for (z=0; z<JmpOrderCnt; z++)
+ if (Memo(JmpOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[1]=EvalIntExpression(ArgStr[1],UInt12,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=JmpOrders[z].Code;
+ END
+ END
+ return;
+ END
+
+ /* nur Adresse */
+
+ for (z=0; z<AdrOrderCnt; z++)
+ if (Memo(AdrOrders[z].Name))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],2,AdrOrders[z].Must1);
+ if (AdrOK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]=AdrOrders[z].Code+AdrMode;
+ END
+ END
+ return;
+ END
+
+ /* Adresse & schieben */
+
+ for (z=0; z<AdrShiftOrderCnt; z++)
+ if (Memo(AdrShiftOrders[z].Name))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>3)) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]=='*')
+ if (ArgCnt==2)
+ if (strncasecmp(ArgStr[2],"AR",2)==0)
+ BEGIN
+ HasSh=False; Cnt=2;
+ END
+ else
+ BEGIN
+ HasSh=True; Cnt=3;
+ END
+ else
+ BEGIN
+ HasSh=True; Cnt=3;
+ END
+ else
+ BEGIN
+ Cnt=3; HasSh=(ArgCnt==2);
+ END
+ DecodeAdr(ArgStr[1],Cnt,False);
+ if (AdrOK)
+ BEGIN
+ if (NOT HasSh)
+ BEGIN
+ OK=True; AdrWord=0;
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],Int4,&OK);
+ if ((OK) AND (FirstPassUnknown)) AdrWord=0;
+ END
+ if (OK)
+ if ((AdrShiftOrders[z].AllowShifts & (1 << AdrWord))==0) WrError(1380);
+ else
+ BEGIN
+ CodeLen=1; WAsmCode[0]=AdrShiftOrders[z].Code+AdrMode+(AdrWord << 8);
+ END
+ END
+ END
+ return;
+ END
+
+ /* Ein/Ausgabe */
+
+ if ((Memo("IN")) OR (Memo("OUT")))
+ BEGIN
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],3,False);
+ if (AdrOK)
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt3,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegIO);
+ CodeLen=1;
+ WAsmCode[0]=0x4000+AdrMode+(AdrWord << 8);
+ if (Memo("OUT")) WAsmCode[0]+=0x800;
+ END
+ END
+ END
+ return;
+ END
+
+ /* konstantes Argument */
+
+ for (z=0; z<ImmOrderCnt; z++)
+ if (Memo(ImmOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (OK)
+ BEGIN
+ if (FirstPassUnknown) AdrLong&=ImmOrders[z].Mask;
+ if (AdrLong<ImmOrders[z].Min) WrError(1315);
+ else if (AdrLong>ImmOrders[z].Max) WrError(1320);
+ else
+ BEGIN
+ CodeLen=1; WAsmCode[0]=ImmOrders[z].Code+(AdrLong & ImmOrders[z].Mask);
+ END
+ END
+ END
+ return;
+ END
+
+ /* mit Hilfsregistern */
+
+ if (Memo("LARP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalARExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]=0x6880+AdrWord;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LAR")) OR (Memo("SAR")))
+ BEGIN
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalARExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[2],3,False);
+ if (AdrOK)
+ BEGIN
+ CodeLen=1;
+ WAsmCode[0]=0x3000+AdrMode+(AdrWord << 8);
+ if (Memo("LAR")) WAsmCode[0]+=0x800;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("LARK"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalARExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1;
+ WAsmCode[0]=Lo(WAsmCode[0])+0x7000+(AdrWord << 8);
+ END
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_3201X(void)
+BEGIN
+ return (Memo("PORT"));
+END
+
+ static void SwitchFrom_3201X(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_3201X(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x74; NOPCode=0x7f80;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegIO);
+ Grans[SegCode]=2; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xfff;
+ Grans[SegData]=2; ListGrans[SegData]=2; SegInits[SegData]=0;
+ SegLimits[SegData] = (MomCPU==CPU32010) ? 0x8f : 0xff;
+ Grans[SegIO ]=2; ListGrans[SegIO ]=2; SegInits[SegIO ]=0;
+ SegLimits[SegIO ] = 7;
+
+ MakeCode=MakeCode_3201X; IsDef=IsDef_3201X;
+ SwitchFrom=SwitchFrom_3201X; InitFields();
+END
+
+ void code3201x_init(void)
+BEGIN
+ CPU32010=AddCPU("32010",SwitchTo_3201X);
+ CPU32015=AddCPU("32015",SwitchTo_3201X);
+END
diff --git a/code3201x.h b/code3201x.h
new file mode 100644
index 0000000..76d19aa
--- /dev/null
+++ b/code3201x.h
@@ -0,0 +1,11 @@
+/* code3201x.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS3201x-Familie */
+/* */
+/* Historie: 28.11.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code3201x_init(void);
diff --git a/code3202x.c b/code3202x.c
new file mode 100644
index 0000000..8e7fe9d
--- /dev/null
+++ b/code3202x.c
@@ -0,0 +1,1122 @@
+/*
+ * AS-Portierung
+ *
+ * AS-Codegeneratormodul fuer die Texas Instruments TMS320C2x-Familie
+ *
+ * (C) 1996 Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *
+ * 19.08.96: Erstellung
+ * 18.01.97: Anpassungen fuer Case-Sensitivitaet
+ * 7.07.1998 Fix Zugriffe auf CharTransTable wg. signed chars
+ * 18.08.1998 BookKeeping-Aufruf bei RES
+ * 9. 1.1999 ChkPC jetzt ueber SegLimits
+ */
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "endian.h"
+
+#include "code3202x.h"
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct {
+ char *name;
+ Word code;
+} cmd_fixed;
+typedef struct {
+ char *name;
+ Word code;
+ Boolean must1;
+} cmd_adr;
+typedef struct {
+ char *name;
+ Word code;
+ Word allow_shifts;
+} cmd_adr_shift;
+typedef struct {
+ char *name;
+ Word code;
+ Integer Min;
+ Integer Max;
+ Word mask;
+} cmd_imm;
+typedef struct {
+ char *name;
+ Word mode;
+} adr_mode_t;
+
+static cmd_fixed *cmd_fixed_order;
+#define cmd_fixed_cnt 38
+static cmd_fixed *cmd_jmp_order;
+#define cmd_jmp_cnt 17
+static cmd_adr *cmd_adr_order;
+#define cmd_adr_cnt 44
+static cmd_adr *cmd_adr_2ndadr_order;
+#define cmd_adr_2ndadr_cnt 5
+static cmd_adr_shift *cmd_adr_shift_order;
+#define cmd_adr_shift_cnt 7
+static cmd_imm *cmd_imm_order;
+#define cmd_imm_cnt 17
+static adr_mode_t *adr_modes;
+#define adr_mode_cnt 10
+
+static int instrz;
+
+static void addfixed(char *nname, Word ncode)
+{
+ if (instrz>=cmd_fixed_cnt) exit(255);
+ cmd_fixed_order[instrz].name=nname;
+ cmd_fixed_order[instrz++].code=ncode;
+}
+
+static void addjmp(char *nname, Word ncode)
+{
+ if (instrz>=cmd_jmp_cnt) exit(255);
+ cmd_jmp_order[instrz].name=nname;
+ cmd_jmp_order[instrz++].code=ncode;
+}
+
+static void addadr(char *nname, Word ncode, Boolean nmust1)
+{
+ if (instrz>=cmd_adr_cnt) exit(255);
+ cmd_adr_order[instrz].name=nname;
+ cmd_adr_order[instrz].code=ncode;
+ cmd_adr_order[instrz++].must1=nmust1;
+}
+
+static void add2ndadr(char *nname, Word ncode, Boolean nmust1)
+{
+ if (instrz>=cmd_adr_2ndadr_cnt) exit(255);
+ cmd_adr_2ndadr_order[instrz].name=nname;
+ cmd_adr_2ndadr_order[instrz].code=ncode;
+ cmd_adr_2ndadr_order[instrz++].must1=nmust1;
+}
+
+static void addshiftadr(char *nname, Word ncode, Word nallow)
+{
+ if (instrz>=cmd_adr_shift_cnt) exit(255);
+ cmd_adr_shift_order[instrz].name=nname;
+ cmd_adr_shift_order[instrz].code=ncode;
+ cmd_adr_shift_order[instrz++].allow_shifts=nallow;
+}
+
+static void addimm(char *nname, Word ncode, Integer nmin, Integer nmax,Word nmask)
+{
+ if (instrz>=cmd_imm_cnt) exit(255);
+ cmd_imm_order[instrz].name=nname;
+ cmd_imm_order[instrz].code=ncode;
+ cmd_imm_order[instrz].Min=nmin;
+ cmd_imm_order[instrz].Max=nmax;
+ cmd_imm_order[instrz++].mask=nmask;
+}
+
+static void addadrmode(char *nname, Word nmode)
+{
+ if (instrz>=adr_mode_cnt) exit(255);
+ adr_modes[instrz].name=nname;
+ adr_modes[instrz++].mode=nmode;
+}
+
+static void initfields(void)
+{
+ cmd_fixed_order=(cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_fixed_cnt); instrz=0;
+ addfixed("ABS", 0xce1b); addfixed("CMPL", 0xce27);
+ addfixed("NEG", 0xce23); addfixed("ROL", 0xce34);
+ addfixed("ROR", 0xce35); addfixed("SFL", 0xce18);
+ addfixed("SFR", 0xce19); addfixed("ZAC", 0xca00);
+ addfixed("APAC", 0xce15); addfixed("PAC", 0xce14);
+ addfixed("SPAC", 0xce16); addfixed("BACC", 0xce25);
+ addfixed("CALA", 0xce24); addfixed("RET", 0xce26);
+ addfixed("RFSM", 0xce36); addfixed("RTXM", 0xce20);
+ addfixed("RXF", 0xce0c); addfixed("SFSM", 0xce37);
+ addfixed("STXM", 0xce21); addfixed("SXF", 0xce0d);
+ addfixed("DINT", 0xce01); addfixed("EINT", 0xce00);
+ addfixed("IDLE", 0xce1f); addfixed("NOP", 0x5500);
+ addfixed("POP", 0xce1d); addfixed("PUSH", 0xce1c);
+ addfixed("RC", 0xce30); addfixed("RHM", 0xce38);
+ addfixed("ROVM", 0xce02); addfixed("RSXM", 0xce06);
+ addfixed("RTC", 0xce32); addfixed("SC", 0xce31);
+ addfixed("SHM", 0xce39); addfixed("SOVM", 0xce03);
+ addfixed("SSXM", 0xce07); addfixed("STC", 0xce33);
+ addfixed("TRAP", 0xce1e); addfixed(NULL, 0);
+
+ cmd_jmp_order=(cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_jmp_cnt); instrz=0;
+ addjmp("B", 0xff80); addjmp("BANZ", 0xfb80);
+ addjmp("BBNZ", 0xf980); addjmp("BBZ", 0xf880);
+ addjmp("BC", 0x5e80); addjmp("BGEZ", 0xf480);
+ addjmp("BGZ", 0xf180); addjmp("BIOZ", 0xfa80);
+ addjmp("BLEZ", 0xf280); addjmp("BLZ", 0xf380);
+ addjmp("BNC", 0x5f80); addjmp("BNV", 0xf780);
+ addjmp("BNZ", 0xf580); addjmp("BV", 0xf080);
+ addjmp("BZ", 0xf680); addjmp("CALL", 0xfe80);
+ addjmp(NULL, 0);
+
+ cmd_adr_order=(cmd_adr *) malloc(sizeof(cmd_adr)*cmd_adr_cnt); instrz=0;
+ addadr("ADDC", 0x4300, False); addadr("ADDH", 0x4800, False);
+ addadr("ADDS", 0x4900, False); addadr("ADDT", 0x4a00, False);
+ addadr("AND", 0x4e00, False); addadr("LACT", 0x4200, False);
+ addadr("OR", 0x4d00, False); addadr("SUBB", 0x4f00, False);
+ addadr("SUBC", 0x4700, False); addadr("SUBH", 0x4400, False);
+ addadr("SUBS", 0x4500, False); addadr("SUBT", 0x4600, False);
+ addadr("XOR", 0x4c00, False); addadr("ZALH", 0x4000, False);
+ addadr("ZALR", 0x7b00, False); addadr("ZALS", 0x4100, False);
+ addadr("LDP", 0x5200, False); addadr("MAR", 0x5500, False);
+ addadr("LPH", 0x5300, False); addadr("LT", 0x3c00, False);
+ addadr("LTA", 0x3d00, False); addadr("LTD", 0x3f00, False);
+ addadr("LTP", 0x3e00, False); addadr("LTS", 0x5b00, False);
+ addadr("MPY", 0x3800, False); addadr("MPYA", 0x3a00, False);
+ addadr("MPYS", 0x3b00, False); addadr("MPYU", 0xcf00, False);
+ addadr("SPH", 0x7d00, False); addadr("SPL", 0x7c00, False);
+ addadr("SQRA", 0x3900, False); addadr("SQRS", 0x5a00, False);
+ addadr("DMOV", 0x5600, False); addadr("TBLR", 0x5800, False);
+ addadr("TBLW", 0x5900, False); addadr("BITT", 0x5700, False);
+ addadr("LST", 0x5000, False); addadr("LST1", 0x5100, False);
+ addadr("POPD", 0x7a00, False); addadr("PSHD", 0x5400, False);
+ addadr("RPT", 0x4b00, False); addadr("SST", 0x7800, True);
+ addadr("SST1", 0x7900, True); addadr(NULL, 0, False);
+
+ cmd_adr_2ndadr_order=(cmd_adr *) malloc(sizeof(cmd_adr)*cmd_adr_2ndadr_cnt); instrz=0;
+ add2ndadr("BLKD", 0xfd00, False); add2ndadr("BLKP", 0xfc00, False);
+ add2ndadr("MAC", 0x5d00, False); add2ndadr("MACD", 0x5c00, False);
+ add2ndadr(NULL, 0, False);
+
+ cmd_adr_shift_order=(cmd_adr_shift *) malloc(sizeof(cmd_adr_shift)*cmd_adr_shift_cnt); instrz=0;
+ addshiftadr("ADD", 0x0000, 0xf); addshiftadr("LAC", 0x2000, 0xf);
+ addshiftadr("SACH", 0x6800, 0x7); addshiftadr("SACL", 0x6000, 0x7);
+ addshiftadr("SUB", 0x1000, 0xf); addshiftadr("BIT", 0x9000, 0xf);
+ addshiftadr(NULL, 0, 0);
+
+ cmd_imm_order=(cmd_imm *) malloc(sizeof(cmd_imm)*cmd_imm_cnt); instrz=0;
+ addimm("ADDK", 0xcc00, 0, 255, 0xff);
+ addimm("LACK", 0xca00, 0, 255, 0xff);
+ addimm("SUBK", 0xcd00, 0, 255, 0xff);
+ addimm("ADRK", 0x7e00, 0, 255, 0xff);
+ addimm("SBRK", 0x7f00, 0, 255, 0xff);
+ addimm("RPTK", 0xcb00, 0, 255, 0xff);
+ addimm("MPYK", 0xa000, -4096, 4095, 0x1fff);
+ addimm("SPM", 0xce08, 0, 3, 0x3);
+ addimm("CMPR", 0xce50, 0, 3, 0x3);
+ addimm("FORT", 0xce0e, 0, 1, 0x1);
+ addimm("ADLK", 0xd002, 0, 0x7fff, 0xffff);
+ addimm("ANDK", 0xd004, 0, 0x7fff, 0xffff);
+ addimm("LALK", 0xd001, 0, 0x7fff, 0xffff);
+ addimm("ORK", 0xd005, 0, 0x7fff, 0xffff);
+ addimm("SBLK", 0xd003, 0, 0x7fff, 0xffff);
+ addimm("XORK", 0xd006, 0, 0x7fff, 0xffff);
+ addimm(NULL, 0, 0, 0, 0);
+
+ adr_modes=(adr_mode_t *) malloc(sizeof(adr_mode_t)*adr_mode_cnt); instrz=0;
+ addadrmode( "*-", 0x90 ); addadrmode( "*+", 0xa0 );
+ addadrmode( "*BR0-", 0xc0 ); addadrmode( "*0-", 0xd0 );
+ addadrmode( "*AR0-", 0xd0 ); addadrmode( "*0+", 0xe0 );
+ addadrmode( "*AR0+", 0xe0 ); addadrmode( "*BR0+", 0xf0 );
+ addadrmode( "*", 0x80 ); addadrmode( NULL, 0);
+}
+
+static void deinitfields(void)
+{
+ free(cmd_fixed_order);
+ free(cmd_jmp_order);
+ free(cmd_adr_order);
+ free(cmd_adr_2ndadr_order);
+ free(cmd_adr_shift_order);
+ free(cmd_imm_order);
+ free(adr_modes);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static Word adr_mode;
+static Boolean adr_ok;
+
+static CPUVar cpu_32025, cpu_32026, cpu_32028;
+
+/* ---------------------------------------------------------------------- */
+
+static Word eval_ar_expression(char *asc, Boolean *ok)
+{
+ *ok = True;
+ if ((toupper(asc[0]) == 'A') && (toupper(asc[1]) == 'R') && (asc[2] >= '0') &&
+ (asc[2] <= '7') && (asc[3] == '\0'))
+ return asc[2] - '0';
+ return EvalIntExpression(asc, UInt3, ok);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void decode_adr(char *arg, int aux, Boolean must1)
+{
+ const adr_mode_t *am = adr_modes;
+ Byte h;
+
+ adr_ok = False;
+ while (am->name && strcasecmp(am->name, arg))
+ am++;
+ if (!am->name) {
+ if (aux <= ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ h = EvalIntExpression(arg, Int16, &adr_ok);
+ if (!adr_ok)
+ return;
+ if (must1 && (h >= 0x80) && (!FirstPassUnknown)) {
+ WrError(1315);
+ adr_ok = False;
+ return;
+ }
+ adr_mode = h & 0x7f;
+ ChkSpace(SegData);
+ return;
+ }
+ adr_mode = am->mode;
+ if (aux <= ArgCnt) {
+ h = eval_ar_expression(ArgStr[aux], &adr_ok);
+ if (adr_ok)
+ adr_mode |= 0x8 | h;
+ } else
+ adr_ok = True;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void pseudo_qxx(Integer num)
+{
+ int z;
+ Boolean ok;
+ double res;
+
+ if (!ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ for(z = 1; z <= ArgCnt; z++) {
+ res = ldexp(EvalFloatExpression(ArgStr[z], Float64, &ok), num);
+ if (!ok) {
+ CodeLen = 0;
+ return;
+ }
+ if ((res > 32767.49) || (res < -32768.49)) {
+ CodeLen = 0;
+ WrError(1320);
+ return;
+ }
+ WAsmCode[CodeLen++] = res;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void pseudo_lqxx(int num)
+{
+ int z;
+ Boolean ok;
+ double res;
+ LongInt resli;
+
+ if (!ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ for(z = 1; z <= ArgCnt; z++) {
+ res = ldexp(EvalFloatExpression(ArgStr[z], Float64, &ok), num);
+ if (!ok) {
+ CodeLen = 0;
+ return;
+ }
+ if ((res > 2147483647.49) || (res < -2147483647.49)) {
+ CodeLen = 0;
+ WrError(1320);
+ return;
+ }
+ resli = res;
+ WAsmCode[CodeLen++] = resli & 0xffff;
+ WAsmCode[CodeLen++] = resli >> 16;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void define_untyped_label(void)
+{
+ if (LabPart[0]) {
+ PushLocHandle(-1);
+ EnterIntSymbol(LabPart, EProgCounter(), SegNone, False);
+ PopLocHandle();
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_byte(Boolean *ok, int *adr, LongInt val)
+{
+ if ((val < -128) || (val > 0xff)) {
+ WrError(1320);
+ *ok = False;
+ return;
+ }
+ WAsmCode[(*adr)++] = val & 0xff;
+ CodeLen = *adr;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_word(Boolean *ok, int *adr, LongInt val)
+{
+ if ((val < -32768) || (val > 0xffff)) {
+ WrError(1320);
+ *ok = False;
+ return;
+ }
+ WAsmCode[(*adr)++] = val;
+ CodeLen = *adr;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_long(Boolean *ok, int *adr, LongInt val)
+{
+ WAsmCode[(*adr)++] = val & 0xffff;
+ WAsmCode[(*adr)++] = val >> 16;
+ CodeLen = *adr;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_byte_hilo(Boolean *ok, int *adr, LongInt val)
+{
+ if ((val < -128) || (val > 0xff)) {
+ WrError(1320);
+ *ok = False;
+ return;
+ }
+ if ((*adr) & 1)
+ WAsmCode[((*adr)++)/2] |= val & 0xff;
+ else
+ WAsmCode[((*adr)++)/2] = val << 8;
+ CodeLen = ((*adr)+1)/2;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_byte_lohi(Boolean *ok, int *adr, LongInt val)
+{
+ if ((val < -128) || (val > 0xff)) {
+ WrError(1320);
+ *ok = False;
+ return;
+ }
+ if ((*adr) & 1)
+ WAsmCode[((*adr)++)/2] |= val << 8;
+ else
+ WAsmCode[((*adr)++)/2] = val & 0xff;
+ CodeLen = ((*adr)+1)/2;
+}
+
+/* ---------------------------------------------------------------------- */
+
+typedef void (*tcallback)(
+#ifdef __PROTOS__
+Boolean *, int *, LongInt
+#endif
+);
+
+static void pseudo_store(tcallback callback)
+{
+ Boolean ok = True;
+ int adr = 0;
+ int z;
+ TempResult t;
+ unsigned char *cp;
+
+ if (!ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ define_untyped_label();
+ for(z = 1; z <= ArgCnt; z++) {
+ if (!ok)
+ return;
+ EvalExpression(ArgStr[z], &t);
+ switch(t.Typ) {
+ case TempInt:
+ callback(&ok, &adr, t.Contents.Int);
+ break;
+ case TempFloat:
+ WrError(1135);
+ return;
+ case TempString:
+ cp = (unsigned char *)t.Contents.Ascii;
+ while (*cp)
+ callback(&ok, &adr, CharTransTable[((usint)*cp++)&0xff]);
+ break;
+ default:
+ WrError(1135);
+ return;
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static Boolean decode_pseudo(void)
+{
+ Word size;
+ Boolean ok;
+ TempResult t;
+ int z,z2;
+ unsigned char *cp;
+ float flt;
+ double dbl, mant;
+ int exp;
+ long lmant;
+ Word w;
+
+ if (Memo("PORT")) {
+ CodeEquate(SegIO, 0, 15);
+ return True;
+ }
+
+ if (Memo("RES") || Memo("BSS")) {
+ if (ArgCnt != 1) {
+ WrError(1110);
+ return True;
+ }
+ if (Memo("BSS"))
+ define_untyped_label();
+ FirstPassUnknown = False;
+ size = EvalIntExpression(ArgStr[1], Int16, &ok);
+ if (FirstPassUnknown) {
+ WrError(1820);
+ return True;
+ }
+ if (!ok)
+ return True;
+ DontPrint = True;
+ CodeLen = size;
+ BookKeeping();
+ return True;
+ }
+
+ if(Memo("DATA")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ EvalExpression(ArgStr[z], &t);
+ switch(t.Typ) {
+ case TempInt:
+ if((t.Contents.Int < -32768) ||
+ (t.Contents.Int > 0xffff)) {
+ WrError(1320);
+ ok = False;
+ } else
+ WAsmCode[CodeLen++] = t.Contents.Int;
+ break;
+ default:
+ case TempFloat:
+ WrError(1135);
+ ok = False;
+ break;
+ case TempString:
+ z2 = 0;
+ cp = (unsigned char *)t.Contents.Ascii;
+ while (*cp) {
+ if (z2 & 1)
+ WAsmCode[CodeLen++] |=
+ (CharTransTable[((usint)*cp++)&0xff]
+ << 8);
+ else
+ WAsmCode[CodeLen] =
+ CharTransTable[((usint)*cp++)&0xff];
+ z2++;
+ }
+ if (z2 & 1)
+ CodeLen++;
+ break;
+ }
+ }
+ if (!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if(Memo("STRING")) {
+ pseudo_store(wr_code_byte_hilo);
+ return True;
+ }
+ if(Memo("RSTRING")) {
+ pseudo_store(wr_code_byte_lohi);
+ return True;
+ }
+ if(Memo("BYTE")) {
+ pseudo_store(wr_code_byte);
+ return True;
+ }
+ if(Memo("WORD")) {
+ pseudo_store(wr_code_word);
+ return True;
+ }
+ if(Memo("LONG")) {
+ pseudo_store(wr_code_long);
+ return True;
+ }
+
+ /* Qxx */
+
+ if((OpPart[0] == 'Q') && (OpPart[1] >= '0') && (OpPart[1] <= '9') &&
+ (OpPart[2] >= '0') && (OpPart[2] <= '9') && (OpPart[3] == '\0')) {
+ pseudo_qxx(10*(OpPart[1]-'0')+OpPart[2]-'0');
+ return True;
+ }
+
+ /* LQxx */
+
+ if((OpPart[0] == 'L') && (OpPart[1] == 'Q') && (OpPart[2] >= '0') &&
+ (OpPart[2] <= '9') && (OpPart[3] >= '0') && (OpPart[3] <= '9') &&
+ (OpPart[4] == '\0')) {
+ pseudo_lqxx(10*(OpPart[2]-'0')+OpPart[3]-'0');
+ return True;
+ }
+
+ /* Floating point definitions */
+
+ if(Memo("FLOAT")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ flt = EvalFloatExpression(ArgStr[z], Float32, &ok);
+ memcpy(WAsmCode+CodeLen, &flt, sizeof(float));
+ if (BigEndian) {
+ w = WAsmCode[CodeLen];
+ WAsmCode[CodeLen] = WAsmCode[CodeLen+1];
+ WAsmCode[CodeLen+1] = w;
+ }
+ CodeLen += sizeof(float)/2;
+ }
+ if(!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if(Memo("DOUBLE")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
+ memcpy(WAsmCode+CodeLen, &dbl, sizeof(dbl));
+ if (BigEndian) {
+ w = WAsmCode[CodeLen];
+ WAsmCode[CodeLen] = WAsmCode[CodeLen+3];
+ WAsmCode[CodeLen+3] = w;
+ w = WAsmCode[CodeLen+1];
+ WAsmCode[CodeLen+1] = WAsmCode[CodeLen+2];
+ WAsmCode[CodeLen+2] = w;
+ }
+ CodeLen += sizeof(dbl)/2;
+ }
+ if(!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if(Memo("EFLOAT")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
+ mant = frexp(dbl, &exp);
+ WAsmCode[CodeLen++] = ldexp(mant, 15);
+ WAsmCode[CodeLen++] = exp-1;
+ }
+ if(!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if(Memo("BFLOAT")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
+ mant = frexp(dbl, &exp);
+ lmant = ldexp(mant, 31);
+ WAsmCode[CodeLen++] = (lmant & 0xffff);
+ WAsmCode[CodeLen++] = (lmant >> 16);
+ WAsmCode[CodeLen++] = exp-1;
+ }
+ if(!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if(Memo("TFLOAT")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
+ mant = frexp(dbl, &exp);
+ mant = modf(ldexp(mant, 15), &dbl);
+ WAsmCode[CodeLen+3] = dbl;
+ mant = modf(ldexp(mant, 16), &dbl);
+ WAsmCode[CodeLen+2] = dbl;
+ mant = modf(ldexp(mant, 16), &dbl);
+ WAsmCode[CodeLen+1] = dbl;
+ mant = modf(ldexp(mant, 16), &dbl);
+ WAsmCode[CodeLen] = dbl;
+ CodeLen += 4;
+ WAsmCode[CodeLen++] = ((exp - 1) & 0xffff);
+ WAsmCode[CodeLen++] = ((exp - 1) >> 16);
+ }
+ if(!ok)
+ CodeLen = 0;
+ return True;
+ }
+ return False;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void make_code_3202x(void)
+{
+ Boolean ok;
+ Word adr_word;
+ LongInt adr_long;
+ const cmd_fixed *fo;
+ const cmd_adr *ao;
+ const cmd_adr_shift *aso;
+ const cmd_imm *io;
+
+ CodeLen = 0;
+ DontPrint = False;
+
+ /* zu ignorierendes */
+
+ if(Memo(""))
+ return;
+
+ /* Pseudoanweisungen */
+
+ if(decode_pseudo())
+ return;
+
+ /* prozessorspezifische Befehle */
+
+ if(Memo("CNFD")) {
+ if(ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ if(MomCPU == cpu_32026) {
+ WrError(1500);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = 0xce04;
+ return;
+ }
+
+ if(Memo("CNFP")) {
+ if(ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ if(MomCPU == cpu_32026) {
+ WrError(1500);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = 0xce05;
+ return;
+ }
+
+ if(Memo("CONF")) {
+ if(ArgCnt != 1) {
+ WrError(1110);
+ return;
+ }
+ if(MomCPU != cpu_32026) {
+ WrError(1500);
+ return;
+ }
+ WAsmCode[0] = 0xce3c|EvalIntExpression(ArgStr[1], UInt2, &ok);
+ if(ok)
+ CodeLen = 1;
+ return;
+ }
+
+ /* kein Argument */
+
+ for(fo = cmd_fixed_order; fo->name; fo++) {
+ if (Memo(fo->name)) {
+ if(ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = fo->code;
+ return;
+ }
+ }
+
+ /* Spruenge */
+
+ for(fo = cmd_jmp_order; fo->name; fo++) {
+ if (Memo(fo->name)) {
+ if((ArgCnt < 1) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ adr_mode = 0;
+ if(ArgCnt > 1) {
+ decode_adr(ArgStr[2], 3, False);
+ if(adr_mode < 0x80)
+ WrError(1350);
+ }
+ WAsmCode[1] = EvalIntExpression(ArgStr[1],
+ Int16, &ok);
+ if(ok) {
+ CodeLen = 2;
+ WAsmCode[0] = fo->code | (adr_mode & 0x7f);
+ }
+ return;
+ }
+ }
+
+ /* nur Adresse */
+
+ for(ao = cmd_adr_order; ao->name; ao++) {
+ if (Memo(ao->name)) {
+ if((ArgCnt < 1) || (ArgCnt > 2)) {
+ WrError(1110);
+ return;
+ }
+ decode_adr(ArgStr[1], 2, ao->must1);
+ if(adr_ok) {
+ CodeLen = 1;
+ WAsmCode[0] = ao->code | adr_mode;
+ }
+ return;
+ }
+ }
+
+ /* 2 Addressen */
+
+ for(ao = cmd_adr_2ndadr_order; ao->name; ao++) {
+ if (Memo(ao->name)) {
+ if((ArgCnt < 2) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ WAsmCode[1] = EvalIntExpression(ArgStr[1], Int16, &ok);
+ decode_adr(ArgStr[2], 3, ao->must1);
+ if(ok && adr_ok) {
+ CodeLen = 2;
+ WAsmCode[0] = ao->code | adr_mode;
+ }
+ return;
+ }
+ }
+
+ /* Adresse & schieben */
+
+ for(aso = cmd_adr_shift_order; aso->name; aso++) {
+ if (Memo(aso->name)) {
+ if((ArgCnt < 1) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ decode_adr(ArgStr[1], 3, False);
+ if(!adr_ok)
+ return;
+ if(ArgCnt < 2) {
+ ok = True;
+ adr_word = 0;
+ } else {
+ adr_word = EvalIntExpression(ArgStr[2], Int4,
+ &ok);
+ if (ok && FirstPassUnknown)
+ adr_word = 0;
+ }
+ if(!ok)
+ return;
+ if(aso->allow_shifts < adr_word) {
+ WrError(1380);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = aso->code | adr_mode | (adr_word << 8);
+ return;
+ }
+ }
+
+ /* Ein/Ausgabe */
+
+ if((Memo("IN")) || (Memo("OUT"))) {
+ if((ArgCnt < 2) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ decode_adr(ArgStr[1], 3, False);
+ if(!adr_ok)
+ return;
+ adr_word = EvalIntExpression(ArgStr[2], Int4, &ok);
+ if(!ok)
+ return;
+ ChkSpace(SegIO);
+ CodeLen = 1;
+ WAsmCode[0] = ((Memo("OUT")) ? 0xe000 : 0x8000) | adr_mode |
+ (adr_word << 8);
+ return;
+ }
+
+ /* konstantes Argument */
+
+ for(io = cmd_imm_order; io->name; io++) {
+ if (Memo(io->name)) {
+ if((ArgCnt < 1) || (ArgCnt > 2) ||
+ ((ArgCnt == 2) && (io->mask != 0xffff))) {
+ WrError(1110);
+ return;
+ }
+ adr_long = EvalIntExpression(ArgStr[1], Int32, &ok);
+ if(!ok)
+ return;
+ if(FirstPassUnknown)
+ adr_long &= io->mask;
+ if(io->mask == 0xffff) {
+ if(adr_long < -32768) {
+ WrError(1315);
+ return;
+ }
+ if(adr_long > 65535) {
+ WrError(1320);
+ return;
+ }
+ adr_word = 0;
+ ok = True;
+ if(ArgCnt == 2) {
+ adr_word = EvalIntExpression(ArgStr[2],
+ Int4,
+ &ok);
+ if(ok && FirstPassUnknown)
+ adr_word = 0;
+ }
+ if(!ok)
+ return;
+ CodeLen = 2;
+ WAsmCode[0] = io->code | (adr_word << 8);
+ WAsmCode[1] = adr_long;
+ return;
+ }
+ if(adr_long < io->Min) {
+ WrError(1315);
+ return;
+ }
+ if(adr_long > io->Max) {
+ WrError(1320);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = io->code | (adr_long & io->mask);
+ return;
+ }
+ }
+
+ /* mit Hilfsregistern */
+
+ if(Memo("LARP")) {
+ if(ArgCnt != 1) {
+ WrError(1110);
+ return;
+ }
+ adr_word = eval_ar_expression(ArgStr[1], &ok);
+ if(!ok)
+ return;
+ CodeLen = 1;
+ WAsmCode[0] = 0x5588 | adr_word;
+ return;
+ }
+
+ if((Memo("LAR")) OR (Memo("SAR"))) {
+ if((ArgCnt < 2) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ adr_word = eval_ar_expression(ArgStr[1], &ok);
+ if(!ok)
+ return;
+ decode_adr(ArgStr[2], 3, False);
+ if(!adr_ok)
+ return;
+ CodeLen = 1;
+ WAsmCode[0] = ((Memo("SAR")) ? 0x7000 : 0x3000) | adr_mode |
+ (adr_word << 8);
+ return;
+ }
+
+ if(Memo("LARK")) {
+ if(ArgCnt != 2) {
+ WrError(1110);
+ return;
+ }
+ adr_word = eval_ar_expression(ArgStr[1], &ok);
+ if(!ok)
+ return;
+ WAsmCode[0] = EvalIntExpression(ArgStr[2], Int8, &ok) & 0xff;
+ if(!ok)
+ return;
+ CodeLen = 1;
+ WAsmCode[0] |= 0xc000 | (adr_word << 8);
+ return;
+ }
+
+ if(Memo("LRLK")) {
+ if(ArgCnt != 2) {
+ WrError(1110);
+ return;
+ }
+ adr_word = eval_ar_expression(ArgStr[1], &ok);
+ if(!ok)
+ return;
+ WAsmCode[1] = EvalIntExpression(ArgStr[2], Int16, &ok);
+ if(!ok)
+ return;
+ CodeLen = 2;
+ WAsmCode[0] = 0xd000 | (adr_word << 8);
+ return;
+ }
+
+ if(Memo("LDPK")) {
+ if(ArgCnt != 1) {
+ WrError(1110);
+ return;
+ }
+ WAsmCode[0] = ConstIntVal(ArgStr[1], Int16, &ok);
+ if(ok && (!(WAsmCode[0] & (~0x1ff)))) { /* emulate Int9 */
+ CodeLen = 1;
+ WAsmCode[0] = (WAsmCode[0] & 0x1ff) | 0xc800;
+ return;
+ }
+ WAsmCode[0] = EvalIntExpression(ArgStr[1], Int16, &ok);
+ if(!ok)
+ return;
+ ChkSpace(SegData);
+ CodeLen = 1;
+ WAsmCode[0] = ((WAsmCode[0] >> 7) & 0x1ff) | 0xc800;
+ return;
+ }
+
+ if(Memo("NORM")) {
+ if((ArgCnt != 1)) {
+ WrError(1110);
+ return;
+ }
+ decode_adr(ArgStr[1], 2, False);
+ if(!adr_ok)
+ return;
+ if(adr_mode < 0x80) {
+ WrError(1350);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = 0xce82 | (adr_mode & 0x70);
+ return;
+ }
+
+ WrXError(1200, OpPart);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static Boolean is_def_3202x(void)
+{
+ static const char *defs[] = { "BSS", "PORT", "STRING", "RSTRING",
+ "BYTE", "WORD", "LONG", "FLOAT",
+ "DOUBLE", "EFLOAT", "BFLOAT",
+ "TFLOAT", NULL };
+ const char **cp = defs;
+
+ while(*cp) {
+ if (Memo(*cp))
+ return True;
+ cp++;
+ }
+ return False;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void switch_from_3202x(void)
+{
+ deinitfields();
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void switch_to_3202x(void)
+{
+ TurnWords = False;
+ ConstMode = ConstModeIntel;
+ SetIsOccupied = False;
+
+ PCSymbol = "$";
+ HeaderID = 0x75;
+ NOPCode = 0x5500;
+ DivideChars = ",";
+ HasAttrs = False;
+
+ ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegIO);
+ Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
+ SegLimits[SegCode] = 0xffff;
+ Grans[SegData] = 2; ListGrans[SegData] = 2; SegInits[SegData] = 0;
+ SegLimits[SegData] = 0xffff;
+ Grans[SegIO ] = 2; ListGrans[SegIO ] = 2; SegInits[SegIO ] = 0;
+ SegLimits[SegIO ] = 0xf;
+
+ MakeCode = make_code_3202x;
+ IsDef = is_def_3202x; SwitchFrom = switch_from_3202x;
+ initfields();
+}
+
+/* ---------------------------------------------------------------------- */
+
+void code3202x_init(void)
+{
+ cpu_32025 = AddCPU("320C25", switch_to_3202x);
+ cpu_32026 = AddCPU("320C26", switch_to_3202x);
+ cpu_32028 = AddCPU("320C28", switch_to_3202x);
+
+ AddCopyright("TMS320C2x-Generator (C) 1994/96 Thomas Sailer");
+}
diff --git a/code3202x.h b/code3202x.h
new file mode 100644
index 0000000..3b7929e
--- /dev/null
+++ b/code3202x.h
@@ -0,0 +1,9 @@
+/*
+ * AS-Portierung
+ *
+ * AS-Codegeneratormodul fuer die Texas Instruments TMS320C2x-Familie
+ *
+ * 19.08.96: Erstellung
+ */
+
+extern void code3202x_init(void);
diff --git a/code3203x.c b/code3203x.c
new file mode 100644
index 0000000..04be742
--- /dev/null
+++ b/code3203x.c
@@ -0,0 +1,1511 @@
+/* code3203x.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS320C3x-Familie */
+/* */
+/* Historie: 12.12.1996 Grundsteinlegung */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 18. 8.1998 BookKeeping-Aufruf in RES */
+/* 3. 1.1998 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "nls.h"
+#include "endian.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmcode.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+#define ConditionCount 28
+#define FixedOrderCount 3
+#define RotOrderCount 4
+#define StkOrderCount 4
+#define GenOrderCount 41
+#define ParOrderCount 8
+#define SingOrderCount 3
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } Condition;
+
+typedef struct
+ {
+ char *Name;
+ LongWord Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ int NameLen;
+ Boolean May1,May3;
+ Byte Code,Code3;
+ Boolean OnlyMem;
+ Boolean SwapOps;
+ Boolean ImmFloat;
+ Byte ParMask,Par3Mask;
+ Byte PCodes[8],P3Codes[8];
+ } GenOrder;
+
+typedef struct
+ {
+ char *Name;
+ LongWord Code;
+ Byte Mask;
+ } SingOrder;
+
+
+static CPUVar CPU32030,CPU32031;
+static SimpProc SaveInitProc;
+
+static Boolean NextPar,ThisPar;
+static Byte PrevARs,ARs;
+static char PrevOp[7];
+static int z2;
+static ShortInt PrevSrc1Mode,PrevSrc2Mode,PrevDestMode;
+static ShortInt CurrSrc1Mode,CurrSrc2Mode,CurrDestMode;
+static Word PrevSrc1Part,PrevSrc2Part,PrevDestPart;
+static Word CurrSrc1Part,CurrSrc2Part,CurrDestPart;
+
+static Condition *Conditions;
+static FixedOrder *FixedOrders;
+static char **RotOrders;
+static char **StkOrders;
+static GenOrder *GenOrders;
+static char **ParOrders;
+static SingOrder *SingOrders;
+
+static LongInt DPValue;
+
+/*-------------------------------------------------------------------------*/
+/* Befehlstabellenverwaltung */
+
+ static void AddCondition(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ConditionCount) exit(255);
+ Conditions[InstrZ].Name=NName;
+ Conditions[InstrZ++].Code=NCode;
+END
+
+ static void AddFixed(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddSing(char *NName, LongWord NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=SingOrderCount) exit(255);
+ SingOrders[InstrZ].Name=NName;
+ SingOrders[InstrZ].Code=NCode;
+ SingOrders[InstrZ++].Mask=NMask;
+END
+
+ static void AddGen(char *NName, Boolean NMay1, Boolean NMay3,
+ Byte NCode, Byte NCode3,
+ Boolean NOnly, Boolean NSwap, Boolean NImm,
+ Byte NMask1, Byte NMask3,
+ Byte C20, Byte C21, Byte C22, Byte C23, Byte C24,
+ Byte C25, Byte C26, Byte C27, Byte C30, Byte C31,
+ Byte C32, Byte C33, Byte C34, Byte C35, Byte C36,
+ Byte C37)
+BEGIN
+ if (InstrZ>=GenOrderCount) exit(255);
+ GenOrders[InstrZ].Name=NName;
+ GenOrders[InstrZ].NameLen=strlen(NName);
+ GenOrders[InstrZ].May1=NMay1; GenOrders[InstrZ].May3=NMay3;
+ GenOrders[InstrZ].Code=NCode; GenOrders[InstrZ].Code3=NCode3;
+ GenOrders[InstrZ].OnlyMem=NOnly; GenOrders[InstrZ].SwapOps=NSwap;
+ GenOrders[InstrZ].ImmFloat=NImm;
+ GenOrders[InstrZ].ParMask=NMask1; GenOrders[InstrZ].Par3Mask=NMask3;
+ GenOrders[InstrZ].PCodes[0]=C20; GenOrders[InstrZ].PCodes[1]=C21;
+ GenOrders[InstrZ].PCodes[2]=C22; GenOrders[InstrZ].PCodes[3]=C23;
+ GenOrders[InstrZ].PCodes[4]=C24; GenOrders[InstrZ].PCodes[5]=C25;
+ GenOrders[InstrZ].PCodes[6]=C26; GenOrders[InstrZ].PCodes[7]=C27;
+ GenOrders[InstrZ].P3Codes[0]=C30; GenOrders[InstrZ].P3Codes[1]=C31;
+ GenOrders[InstrZ].P3Codes[2]=C32; GenOrders[InstrZ].P3Codes[3]=C33;
+ GenOrders[InstrZ].P3Codes[4]=C34; GenOrders[InstrZ].P3Codes[5]=C35;
+ GenOrders[InstrZ].P3Codes[6]=C36; GenOrders[InstrZ++].P3Codes[7]=C37;
+END
+
+ static void InitFields(void)
+BEGIN
+ Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCount); InstrZ=0;
+ AddCondition("U" ,0x00); AddCondition("LO" ,0x01);
+ AddCondition("LS" ,0x02); AddCondition("HI" ,0x03);
+ AddCondition("HS" ,0x04); AddCondition("EQ" ,0x05);
+ AddCondition("NE" ,0x06); AddCondition("LT" ,0x07);
+ AddCondition("LE" ,0x08); AddCondition("GT" ,0x09);
+ AddCondition("GE" ,0x0a); AddCondition("Z" ,0x05);
+ AddCondition("NZ" ,0x06); AddCondition("P" ,0x09);
+ AddCondition("N" ,0x07); AddCondition("NN" ,0x0a);
+ AddCondition("NV" ,0x0c); AddCondition("V" ,0x0d);
+ AddCondition("NUF",0x0e); AddCondition("UF" ,0x0f);
+ AddCondition("NC" ,0x04); AddCondition("C" ,0x01);
+ AddCondition("NLV",0x10); AddCondition("LV" ,0x11);
+ AddCondition("NLUF",0x12);AddCondition("LUF",0x13);
+ AddCondition("ZUF",0x14); AddCondition("" ,0x00);
+
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("IDLE",0x06000000); AddFixed("SIGI",0x16000000);
+ AddFixed("SWI" ,0x66000000);
+
+ RotOrders=(char **) malloc(sizeof(char *)*RotOrderCount); InstrZ=0;
+ RotOrders[InstrZ++]="ROL"; RotOrders[InstrZ++]="ROLC";
+ RotOrders[InstrZ++]="ROR"; RotOrders[InstrZ++]="RORC";
+
+ StkOrders=(char **) malloc(sizeof(char *)*StkOrderCount); InstrZ=0;
+ StkOrders[InstrZ++]="POP"; StkOrders[InstrZ++]="POPF";
+ StkOrders[InstrZ++]="PUSH"; StkOrders[InstrZ++]="PUSHF";
+
+ GenOrders=(GenOrder *) malloc(sizeof(GenOrder)*GenOrderCount); InstrZ=0;
+/* Name May3 Cd3 Swap PM1 PCodes3 */
+/* May1 Cd1 OMem ImmF PM3 PCodes1 */
+ AddGen("ABSF" ,True ,False,0x00,0xff,False,False,True , 4, 0,
+ 0xff,0xff,0x04,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("ABSI" ,True ,False,0x01,0xff,False,False,False, 8, 0,
+ 0xff,0xff,0xff,0x05,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("ADDC" ,False,True ,0x02,0x00,False,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("ADDF" ,False,True ,0x03,0x01,False,False,True , 0, 4,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0x06,0xff,0xff,0xff,0xff,0xff);
+ AddGen("ADDI" ,False,True ,0x04,0x02,False,False,False, 0, 8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x07,0xff,0xff,0xff,0xff);
+ AddGen("AND" ,False,True ,0x05,0x03,False,False,False, 0, 8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x08,0xff,0xff,0xff,0xff);
+ AddGen("ANDN" ,False,True ,0x06,0x04,False,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("ASH" ,False,True ,0x07,0x05,False,False,False, 0, 8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x09,0xff,0xff,0xff,0xff);
+ AddGen("CMPF" ,False,True ,0x08,0x06,False,False,True , 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("CMPI" ,False,True ,0x09,0x07,False,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("FIX" ,True ,False,0x0a,0xff,False,False,True , 8, 0,
+ 0xff,0xff,0xff,0x0a,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("FLOAT",True ,False,0x0b,0xff,False,False,False, 4, 0,
+ 0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("LDE" ,False,False,0x0d,0xff,False,False,True , 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("LDF" ,False,False,0x0e,0xff,False,False,True , 5, 0,
+ 0x02,0xff,0x0c,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("LDFI" ,False,False,0x0f,0xff,True ,False,True , 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("LDI" ,False,False,0x10,0xff,False,False,False,10, 0,
+ 0xff,0x03,0xff,0x0d,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("LDII" ,False,False,0x11,0xff,True ,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("LDM" ,False,False,0x12,0xff,False,False,True , 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("LSH" ,False,True ,0x13,0x08,False,False,False, 0, 8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x0e,0xff,0xff,0xff,0xff);
+ AddGen("MPYF" ,False,True ,0x14,0x09,False,False,True , 0,52,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0x0f,0xff,0x00,0x01,0xff,0xff);
+ AddGen("MPYI" ,False,True ,0x15,0x0a,False,False,False, 0,200,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x10,0xff,0xff,0x02,0x03);
+ AddGen("NEGB" ,True ,False,0x16,0xff,False,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("NEGF" ,True ,False,0x17,0xff,False,False,True , 4, 0,
+ 0xff,0xff,0x11,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("NEGI" ,True ,False,0x18,0xff,False,False,False, 8, 0,
+ 0xff,0xff,0xff,0x12,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("NORM" ,True ,False,0x1a,0xff,False,False,True , 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("NOT" ,True ,False,0x1b,0xff,False,False,False, 8, 0,
+ 0xff,0xff,0xff,0x13,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("OR" ,False,True ,0x20,0x0b,False,False,False, 0, 8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x14,0xff,0xff,0xff,0xff);
+ AddGen("RND" ,True ,False,0x22,0xff,False,False,True , 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("STF" ,False,False,0x28,0xff,True ,True ,True , 4, 0,
+ 0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("STFI" ,False,False,0x29,0xff,True ,True ,True , 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("STI" ,False,False,0x2a,0xff,True ,True ,False, 8, 0,
+ 0xff,0xff,0xff,0x01,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("STII" ,False,False,0x2b,0xff,True ,True ,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("SUBB" ,False,True ,0x2d,0x0c,False,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("SUBC" ,False,False,0x2e,0xff,False,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("SUBF" ,False,True ,0x2f,0x0d,False,False,True , 0, 4,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0x15,0xff,0xff,0xff,0xff,0xff);
+ AddGen("SUBI" ,False,True ,0x30,0x0e,False,False,False, 0, 8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x16,0xff,0xff,0xff,0xff);
+ AddGen("SUBRB",False,False,0x31,0xff,False,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("SUBRF",False,False,0x32,0xff,False,False,True , 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("SUBRI",False,False,0x33,0xff,False,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("TSTB" ,False,True ,0x34,0x0f,False,False,False, 0, 0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+ AddGen("XOR" ,False,True ,0x35,0x10,False,False,False, 0, 8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x17,0xff,0xff,0xff,0xff);
+
+ ParOrders=(char **) malloc(sizeof(char *)*ParOrderCount); InstrZ=0;
+ ParOrders[InstrZ++]="LDF"; ParOrders[InstrZ++]="LDI";
+ ParOrders[InstrZ++]="STF"; ParOrders[InstrZ++]="STI";
+ ParOrders[InstrZ++]="ADDF3"; ParOrders[InstrZ++]="SUBF3";
+ ParOrders[InstrZ++]="ADDI3"; ParOrders[InstrZ++]="SUBI3";
+
+ SingOrders=(SingOrder *) malloc(sizeof(SingOrder)*SingOrderCount); InstrZ=0;
+ AddSing("IACK",0x1b000000,6);
+ AddSing("NOP" ,0x0c800000,5);
+ AddSing("RPTS",0x139b0000,15);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(Conditions);
+ free(FixedOrders);
+ free(RotOrders);
+ free(StkOrders);
+ free(GenOrders);
+ free(ParOrders);
+ free(SingOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Gleitkommawandler */
+
+ static void SplitExt(Double Inp, LongInt *Expo, LongWord *Mant)
+BEGIN
+ Byte Field[8];
+ Boolean Sign;
+ int z;
+
+ Double_2_ieee8(Inp,Field,False);
+ Sign=(Field[7]>0x7f);
+ *Expo=(((LongWord) Field[7]&0x7f)<<4)+(Field[6]>>4);
+ *Mant=Field[6]&0x0f; if (*Expo!=0) *Mant|=0x10;
+ for (z=5; z>2; z--) *Mant=((*Mant)<<8)|Field[z];
+ *Mant=((*Mant)<<3)+(Field[2]>>5);
+ *Expo-=0x3ff;
+ if (Sign) *Mant=0xffffffff-(*Mant);
+ *Mant=(*Mant)^0x80000000;
+END
+
+ static Boolean ExtToShort(Double Inp, Word *Erg)
+BEGIN
+ LongInt Expo;
+ LongWord Mant;
+
+ if (Inp==0) *Erg=0x8000;
+ else
+ BEGIN
+ SplitExt(Inp,&Expo,&Mant);
+ if (abs(Expo)>7)
+ BEGIN
+ WrError((Expo>0)?1320:1315);
+ return False;
+ END
+ *Erg=((Expo << 12) & 0xf000) | ((Mant >> 20) & 0xfff);
+ END
+ return True;
+END
+
+ static Boolean ExtToSingle(Double Inp, LongWord *Erg)
+BEGIN
+ LongInt Expo;
+ LongWord Mant;
+
+ if (Inp==0) *Erg=0x80000000;
+ else
+ BEGIN
+ SplitExt(Inp,&Expo,&Mant);
+ if (abs(Expo)>127)
+ BEGIN
+ WrError((Expo>0)?1320:1315);
+ return False;
+ END
+ *Erg=((Expo << 24) & 0xff000000)+(Mant >> 8);
+ END
+ return True;
+END
+
+ static Boolean ExtToExt(Double Inp, LongWord *ErgL, LongWord *ErgH)
+BEGIN
+ LongInt Exp;
+
+ if (Inp==0)
+ BEGIN
+ *ErgH=0x80; *ErgL=0x00000000;
+ END
+ else
+ BEGIN
+ SplitExt(Inp,&Exp,ErgL);
+ if (abs(Exp)>127)
+ BEGIN
+ WrError((Exp>0)?1320:1315);
+ return False;
+ END
+ *ErgH=Exp&0xff;
+ END
+ return True;
+END
+
+/*-------------------------------------------------------------------------*/
+/* Adressparser */
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModDir 1
+#define MModDir (1 << ModDir)
+#define ModInd 2
+#define MModInd (1 << ModInd)
+#define ModImm 3
+#define MModImm (1 << ModImm)
+
+static ShortInt AdrMode;
+static LongInt AdrPart;
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg)
+BEGIN
+#define RegCnt 12
+#define RegStart 0x10
+ static char *Regs[RegCnt]=
+ {"DP","IR0","IR1","BK","SP","ST","IE","IF","IOF","RS","RE","RC"};
+ Boolean Err;
+
+ if ((toupper(*Asc)=='R') AND (strlen(Asc)<=3) AND (strlen(Asc)>=2))
+ BEGIN
+ *Erg=ConstLongInt(Asc+1,&Err);
+ if ((Err) AND (*Erg<=0x1b)) return True;
+ END
+
+ if ((strlen(Asc)==3) AND (toupper(*Asc)=='A') AND (toupper(Asc[1])=='R') AND (Asc[2]>='0') AND (Asc[2]<='7'))
+ BEGIN
+ *Erg=Asc[2]-'0'+8; return True;
+ END
+
+ *Erg=0;
+ while ((*Erg<RegCnt) AND (strcasecmp(Regs[*Erg],Asc)!=0)) (*Erg)++;
+ if (*Erg<RegCnt)
+ BEGIN
+ *Erg+=RegStart; return True;
+ END
+
+ return False;
+END
+
+ static void ChkAdr(Byte Erl)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Erl & (1 << AdrMode))==0))
+ BEGIN
+ AdrMode=ModNone; WrError(1350);
+ END
+END
+
+ static void DecodeAdr(char *Asc, Byte Erl, Boolean ImmFloat)
+BEGIN
+ Byte HReg;
+ Integer Disp;
+ char *p;
+ int l;
+ Double f;
+ Word fi;
+ LongInt AdrLong;
+ Boolean BitRev,Circ;
+ String NDisp;
+ Boolean OK;
+ enum {ModBase,ModAdd,ModSub,ModPreInc,ModPreDec,ModPostInc,ModPostDec} Mode;
+
+ KillBlanks(Asc);
+
+ AdrMode=ModNone;
+
+ /* I. Register? */
+
+ if (DecodeReg(Asc,&HReg))
+ BEGIN
+ AdrMode=ModReg; AdrPart=HReg; ChkAdr(Erl); return;
+ END
+
+ /* II. indirekt ? */
+
+ if (*Asc=='*')
+ BEGIN
+ /* II.1. Erkennungszeichen entfernen */
+
+ strcpy(Asc,Asc+1);
+
+ /* II.2. Extrawuerste erledigen */
+
+ BitRev=False; Circ=False;
+ if (toupper(Asc[strlen(Asc)-1])=='B')
+ BEGIN
+ BitRev=True; Asc[strlen(Asc)-1]='\0';
+ END
+ else if (Asc[strlen(Asc)-1]=='%')
+ BEGIN
+ Circ=True; Asc[strlen(Asc)-1]='\0';
+ END
+
+ /* II.3. Displacement entfernen und auswerten:
+ 0..255-->Displacement
+ -1,-2 -->IR0,IR1
+ -3 -->Default */
+
+ p=QuotPos(Asc,'(');
+ if (p!=Nil)
+ BEGIN
+ if (Asc[strlen(Asc)-1]!=')')
+ BEGIN
+ WrError(1350); return;
+ END
+ *p='\0'; strmaxcpy(NDisp,p+1,255); NDisp[strlen(NDisp)-1]='\0';
+ if (strcasecmp(NDisp,"IR0")==0) Disp=(-1);
+ else if (strcasecmp(NDisp,"IR1")==0) Disp=(-2);
+ else
+ BEGIN
+ Disp=EvalIntExpression(NDisp,UInt8,&OK);
+ if (NOT OK) return;
+ END
+ END
+ else Disp=(-3);
+
+ /* II.4. Addieren/Subtrahieren mit/ohne Update? */
+
+ l=strlen(Asc);
+ if (*Asc=='-')
+ BEGIN
+ if (Asc[1]=='-')
+ BEGIN
+ Mode=ModPreDec; strcpy(Asc,Asc+2);
+ END
+ else
+ BEGIN
+ Mode=ModSub; strcpy(Asc,Asc+1);
+ END
+ END
+ else if (*Asc=='+')
+ BEGIN
+ if (Asc[1]=='+')
+ BEGIN
+ Mode=ModPreInc; strcpy(Asc,Asc+2);
+ END
+ else
+ BEGIN
+ Mode=ModAdd; strcpy(Asc,Asc+1);
+ END
+ END
+ else if (Asc[l-1]=='-')
+ BEGIN
+ if (Asc[l-2]=='-')
+ BEGIN
+ Mode=ModPostDec; Asc[l-2]='\0';
+ END
+ else
+ BEGIN
+ WrError(1350); return;
+ END
+ END
+ else if (Asc[l-1]=='+')
+ BEGIN
+ if (Asc[l-2]=='+')
+ BEGIN
+ Mode=ModPostInc; Asc[l-2]='\0';
+ END
+ else
+ BEGIN
+ WrError(1350); return;
+ END
+ END
+ else Mode=ModBase;
+
+ /* II.5. Rest muss Basisregister sein */
+
+ if ((NOT DecodeReg(Asc,&HReg)) OR (HReg<8) OR (HReg>15))
+ BEGIN
+ WrError(1350); return;
+ END
+ HReg-=8;
+ if ((ARs & (1l << HReg))==0) ARs+=1l << HReg;
+ else WrXError(210,Asc);
+
+ /* II.6. Default-Displacement explizit machen */
+
+ if (Disp==-3)
+ Disp=(Mode==ModBase) ? 0 : 1;
+
+ /* II.7. Entscheidungsbaum */
+
+ switch (Mode)
+ BEGIN
+ case ModBase:
+ case ModAdd:
+ if ((Circ) OR (BitRev)) WrError(1350);
+ else
+ BEGIN
+ switch (Disp)
+ BEGIN
+ case -2: AdrPart=0x8000; break;
+ case -1: AdrPart=0x4000; break;
+ case 0: AdrPart=0xc000; break;
+ default: AdrPart=Disp;
+ END
+ AdrPart+=((Word)HReg) << 8; AdrMode=ModInd;
+ END
+ break;
+ case ModSub:
+ if ((Circ) OR (BitRev)) WrError(1350);
+ else
+ BEGIN
+ switch (Disp)
+ BEGIN
+ case -2: AdrPart=0x8800; break;
+ case -1: AdrPart=0x4800; break;
+ case 0: AdrPart=0xc000; break;
+ default: AdrPart=0x0800+Disp;
+ END
+ AdrPart+=((Word)HReg) << 8; AdrMode=ModInd;
+ END
+ break;
+ case ModPreInc:
+ if ((Circ) OR (BitRev)) WrError(1350);
+ else
+ BEGIN
+ switch (Disp)
+ BEGIN
+ case -2: AdrPart=0x9000; break;
+ case -1: AdrPart=0x5000; break;
+ default: AdrPart=0x1000+Disp;
+ END
+ AdrPart+=((Word)HReg) << 8; AdrMode=ModInd;
+ END
+ break;
+ case ModPreDec:
+ if ((Circ) OR (BitRev)) WrError(1350);
+ else
+ BEGIN
+ switch (Disp)
+ BEGIN
+ case -2: AdrPart=0x9800; break;
+ case -1: AdrPart=0x5800; break;
+ default: AdrPart=0x1800+Disp;
+ END
+ AdrPart+=((Word)HReg) << 8; AdrMode=ModInd;
+ END
+ break;
+ case ModPostInc:
+ if (BitRev)
+ BEGIN
+ if (Disp!=-1) WrError(1350);
+ else
+ BEGIN
+ AdrPart=0xc800+(((Word)HReg) << 8); AdrMode=ModInd;
+ END
+ END
+ else
+ BEGIN
+ switch (Disp)
+ BEGIN
+ case -2: AdrPart=0xa000; break;
+ case -1: AdrPart=0x6000; break;
+ default: AdrPart=0x2000+Disp;
+ END
+ if (Circ) AdrPart+=0x1000;
+ AdrPart+=((Word)HReg) << 8; AdrMode=ModInd;
+ END
+ break;
+ case ModPostDec:
+ if (BitRev) WrError(1350);
+ else
+ BEGIN
+ switch (Disp)
+ BEGIN
+ case -2: AdrPart=0xa800; break;
+ case -1: AdrPart=0x6800; break;
+ default: AdrPart=0x2800+Disp; break;
+ END
+ if (Circ) AdrPart+=0x1000;
+ AdrPart+=((Word)HReg) << 8; AdrMode=ModInd;
+ END
+ break;
+ END
+
+ ChkAdr(Erl); return;
+ END
+
+ /* III. absolut */
+
+ if (*Asc=='@')
+ BEGIN
+ AdrLong=EvalIntExpression(Asc+1,UInt24,&OK);
+ if (OK)
+ BEGIN
+ if ((DPValue!=-1) AND ((AdrLong >> 16)!=DPValue)) WrError(110);
+ AdrMode=ModDir; AdrPart=AdrLong & 0xffff;
+ END
+ ChkAdr(Erl); return;
+ END
+
+ /* IV. immediate */
+
+ if (ImmFloat)
+ BEGIN
+ f=EvalFloatExpression(Asc,Float64,&OK);
+ if (OK)
+ if (ExtToShort(f,&fi))
+ BEGIN
+ AdrPart=fi; AdrMode=ModImm;
+ END
+ END
+ else
+ BEGIN
+ AdrPart=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrPart&=0xffff; AdrMode=ModImm;
+ END
+ END
+
+ ChkAdr(Erl);
+END
+
+ static Word EffPart(Byte Mode, Word Part)
+BEGIN
+ switch (Mode)
+ BEGIN
+ case ModReg: return Lo(Part);
+ case ModInd: return Hi(Part);
+ default: WrError(10000); return 0;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/* Code-Erzeugung */
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME3203Count 1
+ static ASSUMERec ASSUME3203s[ASSUME3203Count]=
+ {{"DP", &DPValue, -1, 0xff, 0x100}};
+
+ Boolean OK;
+ int z,z2;
+ LongInt Size;
+ Double f;
+ TempResult t;
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME3203s,ASSUME3203Count);
+ return True;
+ END
+
+ if (Memo("SINGLE"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ OK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (OK)
+ BEGIN
+ f=EvalFloatExpression(ArgStr[z],Float64,&OK);
+ if (OK)
+ OK=OK AND ExtToSingle(f,DAsmCode+(CodeLen++));
+ END
+ if (NOT OK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("EXTENDED"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ OK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (OK)
+ BEGIN
+ f=EvalFloatExpression(ArgStr[z],Float64,&OK);
+ if (OK)
+ OK=OK AND ExtToExt(f,DAsmCode+CodeLen+1,DAsmCode+CodeLen);
+ CodeLen+=2;
+ END
+ if (NOT OK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("WORD"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ OK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (OK) DAsmCode[CodeLen++]=EvalIntExpression(ArgStr[z],Int32,&OK);
+ if (NOT OK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("DATA"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ OK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (OK)
+ BEGIN
+ EvalExpression(ArgStr[z],&t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+#ifdef HAS64
+ if (NOT RangeCheck(t.Contents.Int,Int32))
+ BEGIN
+ OK=False; WrError(1320);
+ END
+ else
+#endif
+ DAsmCode[CodeLen++]=t.Contents.Int;
+ break;
+ case TempFloat:
+ if (NOT ExtToSingle(t.Contents.Float,DAsmCode+(CodeLen++))) OK=False;
+ break;
+ case TempString:
+ for (z2=0; z2<strlen(t.Contents.Ascii); z2++)
+ BEGIN
+ if ((z2 & 3)==0) DAsmCode[CodeLen++]=0;
+ DAsmCode[CodeLen-1]+=
+ (((LongWord)CharTransTable[((usint)t.Contents.Ascii[z2])&0xff])) << (8*(3-(z2 & 3)));
+ END
+ break;
+ case TempNone:
+ OK=False;
+ END
+ END
+ if (NOT OK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("BSS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void JudgePar(GenOrder *Prim, int Sec, Byte *ErgMode, Byte *ErgCode)
+BEGIN
+ if (Sec>3) *ErgMode=3;
+ else if (Prim->May3) *ErgMode=1;
+ else *ErgMode=2;
+ if (*ErgMode==2) *ErgCode=Prim->PCodes[Sec];
+ else *ErgCode=Prim->P3Codes[Sec];
+END
+
+ static LongWord EvalAdrExpression(char *Asc, Boolean *OK)
+BEGIN
+ if (*Asc=='@') strcpy(Asc,Asc+1);
+ return EvalIntExpression(Asc,UInt24,OK);
+END
+
+ static void SwapMode(ShortInt *M1, ShortInt *M2)
+BEGIN
+ AdrMode=(*M1); *M1=(*M2); *M2=AdrMode;
+END
+
+ static void SwapPart(Word *P1, Word *P2)
+BEGIN
+ AdrPart=(*P1); *P1=(*P2); *P2=AdrPart;
+END
+
+ static void MakeCode_3203X(void)
+BEGIN
+ Boolean OK,Is3;
+ Byte HReg,HReg2,Sum;
+ int z,z3,l;
+ LongInt AdrLong,DFlag,Disp;
+ String HOp,Form;
+
+ CodeLen=0; DontPrint=False;
+
+ ThisPar=(strcmp(LabPart,"||")==0);
+ if ((strlen(OpPart)>2) AND (strncmp(OpPart,"||",2)==0))
+ BEGIN
+ ThisPar=True; strcpy(OpPart,OpPart+2);
+ END
+ if ((NOT NextPar) AND (ThisPar))
+ BEGIN
+ WrError(1950); return;
+ END
+ ARs=0;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else
+ BEGIN
+ DAsmCode[0]=FixedOrders[z].Code; CodeLen=1;
+ END
+ NextPar=False; return;
+ END
+
+ /* Arithmetik/Logik */
+
+ for (z=0; z<GenOrderCount; z++)
+ if ((strncmp(OpPart,GenOrders[z].Name,GenOrders[z].NameLen)==0)
+ AND ((OpPart[GenOrders[z].NameLen]=='\0') OR (OpPart[GenOrders[z].NameLen]=='3')))
+ BEGIN
+ NextPar=False;
+ /* Argumentzahl abgleichen */
+ if (ArgCnt==1)
+ if (GenOrders[z].May1)
+ BEGIN
+ ArgCnt=2; strcpy(ArgStr[2],ArgStr[1]);
+ END
+ else
+ BEGIN
+ WrError(1110); return;
+ END
+ if ((ArgCnt==3) AND (OpPart[strlen(OpPart)-1]!='3')) strcat(OpPart,"3");
+ Is3=(OpPart[strlen(OpPart)-1]=='3');
+ if ((GenOrders[z].SwapOps) AND (NOT Is3))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ END
+ if ((Is3) AND (ArgCnt==2))
+ BEGIN
+ ArgCnt=3; strcpy(ArgStr[3],ArgStr[2]);
+ END
+ if ((ArgCnt<2) OR (ArgCnt>3) OR ((Is3) AND (NOT GenOrders[z].May3)))
+ BEGIN
+ WrError(1110); return;
+ END
+ /* Argumente parsen */
+ if (Is3)
+ BEGIN
+ if (Memo("TSTB3"))
+ BEGIN
+ CurrDestMode=ModReg; CurrDestPart=0;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[3],MModReg,GenOrders[z].ImmFloat);
+ if (AdrMode==ModNone) return;
+ CurrDestMode=AdrMode; CurrDestPart=AdrPart;
+ END
+ DecodeAdr(ArgStr[2],MModReg+MModInd,GenOrders[z].ImmFloat);
+ if (AdrMode==ModNone) return;
+ if ((AdrMode==ModInd) AND ((AdrPart & 0xe000)==0) AND (Lo(AdrPart)!=1))
+ BEGIN
+ WrError(1350); return;
+ END
+ CurrSrc2Mode=AdrMode; CurrSrc2Part=AdrPart;
+ DecodeAdr(ArgStr[1],MModReg+MModInd,GenOrders[z].ImmFloat);
+ if (AdrMode==ModNone) return;
+ if ((AdrMode==ModInd) AND ((AdrPart & 0xe000)==0) AND (Lo(AdrPart)!=1))
+ BEGIN
+ WrError(1350); return;
+ END
+ CurrSrc1Mode=AdrMode; CurrSrc1Part=AdrPart;
+ END
+ else /* NOT Is3 */
+ BEGIN
+ DecodeAdr(ArgStr[1],MModDir+MModInd+((GenOrders[z].OnlyMem)?0:MModReg+MModImm),GenOrders[z].ImmFloat);
+ if (AdrMode==ModNone) return;
+ CurrSrc1Mode=AdrMode; CurrSrc1Part=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg+MModInd,GenOrders[z].ImmFloat);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ CurrDestMode=AdrMode; CurrDestPart=AdrPart;
+ CurrSrc2Mode=CurrSrc1Mode; CurrSrc2Part=CurrSrc1Part;
+ break;
+ case ModInd:
+ if (((strcmp(OpPart,"TSTB")!=0) AND (strcmp(OpPart,"CMPI")!=0) AND (strcmp(OpPart,"CMPF")!=0))
+ OR ((CurrSrc1Mode==ModDir) OR (CurrSrc1Mode==ModImm))
+ OR ((CurrSrc1Mode==ModInd) AND ((CurrSrc1Part & 0xe000)==0) AND (Lo(CurrSrc1Part)!=1))
+ OR (((AdrPart & 0xe000)==0) AND (Lo(AdrPart)!=1)))
+ BEGIN
+ WrError(1350); return;
+ END
+ else
+ BEGIN
+ Is3=True; CurrDestMode=ModReg; CurrDestPart=0;
+ CurrSrc2Mode=AdrMode; CurrSrc2Part=AdrPart;
+ END
+ break;
+ case ModNone:
+ return;
+ END
+ END
+ /* auswerten: parallel... */
+ if (ThisPar)
+ BEGIN
+ /* in Standardreihenfolge suchen */
+ if (PrevOp[strlen(PrevOp)-1]=='3') HReg=GenOrders[z2].Par3Mask;
+ else HReg=GenOrders[z2].ParMask;
+ z3=0;
+ while ((z3<ParOrderCount) AND ((NOT Odd(HReg)) OR (strcmp(ParOrders[z3],OpPart)!=0)))
+ BEGIN
+ z3++; HReg>>=1;
+ END
+ if (z3<ParOrderCount) JudgePar(GenOrders+z2,z3,&HReg,&HReg2);
+ /* in gedrehter Reihenfolge suchen */
+ else
+ BEGIN
+ if (OpPart[strlen(OpPart)-1]=='3') HReg=GenOrders[z].Par3Mask;
+ else HReg=GenOrders[z].ParMask;
+ z3=0;
+ while ((z3<ParOrderCount) AND ((NOT Odd(HReg)) OR (strcmp(ParOrders[z3],PrevOp)!=0)))
+ BEGIN
+ z3++; HReg>>=1;
+ END
+ if (z3<ParOrderCount)
+ BEGIN
+ JudgePar(GenOrders+z,z3,&HReg,&HReg2);
+ SwapMode(&CurrDestMode,&PrevDestMode);
+ SwapMode(&CurrSrc1Mode,&PrevSrc1Mode);
+ SwapMode(&CurrSrc2Mode,&PrevSrc2Mode);
+ SwapPart(&CurrDestPart,&PrevDestPart);
+ SwapPart(&CurrSrc1Part,&PrevSrc1Part);
+ SwapPart(&CurrSrc2Part,&PrevSrc2Part);
+ END
+ else
+ BEGIN
+ WrError(1950); return;
+ END
+ END
+ /* mehrfache Registernutzung ? */
+ for (z3=0; z3<8; z3++)
+ if ((ARs & PrevARs & (1l << z3))!=0)
+ BEGIN
+ sprintf(Form,"AR%d",z3); WrXError(210,Form);
+ END
+ /* 3 Basisfaelle */
+ switch (HReg)
+ BEGIN
+ case 1:
+ if ((strcmp(PrevOp,"LSH3")==0) OR (strcmp(PrevOp,"ASH3")==0) OR (strcmp(PrevOp,"SUBF3")==0) OR (strcmp(PrevOp,"SUBI3")==0))
+ BEGIN
+ SwapMode(&PrevSrc1Mode,&PrevSrc2Mode);
+ SwapPart(&PrevSrc1Part,&PrevSrc2Part);
+ END
+ if ((PrevDestPart>7) OR (CurrDestPart>7))
+ BEGIN
+ WrError(1445); return;
+ END
+ /* Bei Addition und Multiplikation Kommutativitaet nutzen */
+ if ((PrevSrc2Mode==ModInd) AND (PrevSrc1Mode==ModReg)
+ AND ((strncmp(PrevOp,"ADD",3)==0) OR (strncmp(PrevOp,"MPY",3)==0)
+ OR (strncmp(PrevOp,"AND",3)==0) OR (strncmp(PrevOp,"XOR",3)==0)
+ OR (strncmp(PrevOp,"OR",2)==0)))
+ BEGIN
+ SwapMode(&PrevSrc1Mode,&PrevSrc2Mode);
+ SwapPart(&PrevSrc1Part,&PrevSrc2Part);
+ END
+ if ((PrevSrc2Mode!=ModReg) OR (PrevSrc2Part>7)
+ OR (PrevSrc1Mode!=ModInd) OR (CurrSrc1Mode!=ModInd))
+ BEGIN
+ WrError(1355); return;
+ END
+ RetractWords(1);
+ DAsmCode[0]=0xc0000000+(((LongWord)HReg2) << 25)
+ +(((LongWord)PrevDestPart) << 22)
+ +(((LongWord)PrevSrc2Part) << 19)
+ +(((LongWord)CurrDestPart) << 16)
+ +(CurrSrc1Part & 0xff00)+Hi(PrevSrc1Part);
+ CodeLen=1; NextPar=False;
+ break;
+ case 2:
+ if ((PrevDestPart>7) OR (CurrDestPart>7))
+ BEGIN
+ WrError(1445); return;
+ END
+ if ((PrevSrc1Mode!=ModInd) OR (CurrSrc1Mode!=ModInd))
+ BEGIN
+ WrError(1355); return;
+ END
+ RetractWords(1);
+ DAsmCode[0]=0xc0000000+(((LongWord)HReg2) << 25)
+ +(((LongWord)PrevDestPart) << 22)
+ +(CurrSrc1Part & 0xff00)+Hi(PrevSrc1Part);
+ if ((strcmp(PrevOp,OpPart)==0) AND (*OpPart=='L'))
+ BEGIN
+ DAsmCode[0]+=((LongWord)CurrDestPart) << 19;
+ if (PrevDestPart==CurrDestPart) WrError(140);
+ END
+ else
+ DAsmCode[0]+=((LongWord)CurrDestPart) << 16;
+ CodeLen=1; NextPar=False;
+ break;
+ case 3:
+ if ((PrevDestPart>1) OR (CurrDestPart<2) OR (CurrDestPart>3))
+ BEGIN
+ WrError(1445); return;
+ END
+ Sum=0;
+ if (PrevSrc1Mode==ModInd) Sum++;
+ if (PrevSrc2Mode==ModInd) Sum++;
+ if (CurrSrc1Mode==ModInd) Sum++;
+ if (CurrSrc2Mode==ModInd) Sum++;
+ if (Sum!=2)
+ BEGIN
+ WrError(1355); return;
+ END
+ RetractWords(1);
+ DAsmCode[0]=0x80000000+(((LongWord)HReg2) << 26)
+ +(((LongWord)PrevDestPart & 1) << 23)
+ +(((LongWord)CurrDestPart & 1) << 22);
+ CodeLen=1;
+ if (CurrSrc2Mode==ModReg)
+ if (CurrSrc1Mode==ModReg)
+ BEGIN
+ DAsmCode[0]+=((LongWord)0x00000000)
+ +(((LongWord)CurrSrc2Part) << 19)
+ +(((LongWord)CurrSrc1Part) << 16)
+ +(PrevSrc2Part & 0xff00)+Hi(PrevSrc1Part);
+ END
+ else
+ BEGIN
+ DAsmCode[0]+=((LongWord)0x03000000)
+ +(((LongWord)CurrSrc2Part) << 16)
+ +Hi(CurrSrc1Part);
+ if (PrevSrc1Mode==ModReg)
+ DAsmCode[0]+=(((LongWord)PrevSrc1Part) << 19)+(PrevSrc2Part & 0xff00);
+ else
+ DAsmCode[0]+=(((LongWord)PrevSrc2Part) << 19)+(PrevSrc1Part & 0xff00);
+ END
+ else
+ if (CurrSrc1Mode==ModReg)
+ BEGIN
+ DAsmCode[0]+=((LongWord)0x01000000)
+ +(((LongWord)CurrSrc1Part) << 16)
+ +Hi(CurrSrc2Part);
+ if (PrevSrc1Mode==ModReg)
+ DAsmCode[0]+=(((LongWord)PrevSrc1Part) << 19)+(PrevSrc2Part & 0xff00);
+ else
+ DAsmCode[0]+=(((LongWord)PrevSrc2Part) << 19)+(PrevSrc1Part & 0xff00);
+ END
+ else
+ BEGIN
+ DAsmCode[0]+=((LongWord)0x02000000)
+ +(((LongWord)PrevSrc2Part) << 19)
+ +(((LongWord)PrevSrc1Part) << 16)
+ +(CurrSrc2Part & 0xff00)+Hi(CurrSrc1Part);
+ END
+ break;
+ END
+ END
+ /* ...sequentiell */
+ else
+ BEGIN
+ PrevSrc1Mode=CurrSrc1Mode; PrevSrc1Part=CurrSrc1Part;
+ PrevSrc2Mode=CurrSrc2Mode; PrevSrc2Part=CurrSrc2Part;
+ PrevDestMode=CurrDestMode; PrevDestPart=CurrDestPart;
+ strcpy(PrevOp,OpPart); PrevARs=ARs; z2=z;
+ if (Is3)
+ DAsmCode[0]=0x20000000+(((LongWord)GenOrders[z].Code3) << 23)
+ +(((LongWord)CurrDestPart) << 16)
+ +(((LongWord)CurrSrc2Mode) << 20)+(EffPart(CurrSrc2Mode,CurrSrc2Part) << 8)
+ +(((LongWord)CurrSrc1Mode) << 21)+EffPart(CurrSrc1Mode,CurrSrc1Part);
+ else
+ DAsmCode[0]=0x00000000+(((LongWord)GenOrders[z].Code) << 23)
+ +(((LongWord)CurrSrc1Mode) << 21)+CurrSrc1Part
+ +(((LongWord)CurrDestPart) << 16);
+ CodeLen=1; NextPar=True;
+ END
+ return;
+ END
+
+ for (z=0; z<RotOrderCount; z++)
+ if (Memo(RotOrders[z]))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else if (NOT DecodeReg(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0]=0x11e00000+(((LongWord)z) << 23)+(((LongWord)HReg) << 16);
+ CodeLen=1;
+ END
+ NextPar=False; return;
+ END
+
+ for (z=0; z<StkOrderCount; z++)
+ if (Memo(StkOrders[z]))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else if (NOT DecodeReg(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0]=0x0e200000+(((LongWord)z) << 23)+(((LongWord)HReg) << 16);
+ CodeLen=1;
+ END
+ NextPar=False; return;
+ END
+
+ /* Datentransfer */
+
+ if ((strncmp(OpPart,"LDI",3)==0) OR (strncmp(OpPart,"LDF",3)==0))
+ BEGIN
+ strcpy(HOp,OpPart); strcpy(OpPart,OpPart+3);
+ for (z=0; z<ConditionCount; z++)
+ if (Memo(Conditions[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[1],MModReg+MModDir+MModInd+MModImm,HOp[2]=='F');
+ if (AdrMode!=ModNone)
+ BEGIN
+ DAsmCode[0]=0x40000000+(((LongWord)HReg) << 16)
+ +(((LongWord)Conditions[z].Code) << 23)
+ +(((LongWord)AdrMode) << 21)+AdrPart;
+ if (HOp[2]=='I') DAsmCode[0]+=0x10000000;
+ CodeLen=1;
+ END
+ END
+ END
+ NextPar=False; return;
+ END
+ WrXError(1200,HOp); NextPar=False; return;
+ END
+
+ /* Sonderfall NOP auch ohne Argumente */
+
+ if ((Memo("NOP")) AND (ArgCnt==0))
+ BEGIN
+ CodeLen=1; DAsmCode[0]=NOPCode; return;
+ END
+
+ /* Sonderfaelle */
+
+ for (z=0; z<SingOrderCount; z++)
+ if (Memo(SingOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],SingOrders[z].Mask,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ DAsmCode[0]=SingOrders[z].Code+(((LongWord)AdrMode) << 21)+AdrPart;
+ CodeLen=1;
+ END
+ END;
+ NextPar=False; return;
+ END
+
+ if (Memo("LDP"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else if ((ArgCnt==2) AND (strcasecmp(ArgStr[2],"DP")!=0)) WrError(1350);
+ else
+ BEGIN
+ AdrLong=EvalAdrExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x08700000+(AdrLong >> 16);
+ CodeLen=1;
+ END
+ END
+ NextPar=False; return;
+ END
+
+ /* Schleifen */
+
+ if (Memo("RPTB"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else
+ BEGIN
+ AdrLong=EvalAdrExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x64000000+AdrLong;
+ CodeLen=1;
+ END
+ END
+ NextPar=False; return;
+ END
+
+ /* Spruenge */
+
+ if ((Memo("BR")) OR (Memo("BRD")) OR (Memo("CALL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else
+ BEGIN
+ AdrLong=EvalAdrExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x60000000+AdrLong;
+ if (Memo("BRD")) DAsmCode[0]+=0x01000000;
+ else if (Memo("CALL")) DAsmCode[0]+=0x02000000;
+ CodeLen=1;
+ END
+ END
+ NextPar=False; return;
+ END
+
+ if (*OpPart=='B')
+ BEGIN
+ strcpy(HOp,OpPart);
+ strcpy(OpPart,OpPart+1);
+ l=strlen(OpPart);
+ if ((l>=1) AND (OpPart[l-1]=='D'))
+ BEGIN
+ OpPart[l-1]='\0'; DFlag=1l << 21;
+ Disp=3;
+ END
+ else
+ BEGIN
+ DFlag=0; Disp=1;
+ END
+ for (z=0; z<ConditionCount; z++)
+ if (Memo(Conditions[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else if (DecodeReg(ArgStr[1],&HReg))
+ BEGIN
+ DAsmCode[0]=0x68000000+(((LongWord)Conditions[z].Code) << 16)+DFlag+HReg;
+ CodeLen=1;
+ END
+ else
+ BEGIN
+ AdrLong=EvalAdrExpression(ArgStr[1],&OK)-(EProgCounter()+Disp);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrLong>0x7fffl) OR (AdrLong<-0x8000l))) WrError(1370);
+ else
+ BEGIN
+ DAsmCode[0]=0x6a000000+(((LongWord)Conditions[z].Code) << 16)+DFlag+(AdrLong & 0xffff);
+ CodeLen=1;
+ END
+ END
+ NextPar=False; return;
+ END
+ WrXError(1200,HOp); NextPar=False; return;
+ END
+
+ if (strncmp(OpPart,"CALL",4)==0)
+ BEGIN
+ strcpy(HOp,OpPart); strcpy(OpPart,OpPart+4);
+ for (z=0; z<ConditionCount; z++)
+ if (Memo(Conditions[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else if (DecodeReg(ArgStr[1],&HReg))
+ BEGIN
+ DAsmCode[0]=0x70000000+(((LongWord)Conditions[z].Code) << 16)+HReg;
+ CodeLen=1;
+ END
+ else
+ BEGIN
+ AdrLong=EvalAdrExpression(ArgStr[1],&OK)-(EProgCounter()+1);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrLong>0x7fffl) OR (AdrLong<-0x8000l))) WrError(1370);
+ else
+ BEGIN
+ DAsmCode[0]=0x72000000+(((LongWord)Conditions[z].Code) << 16)+(AdrLong & 0xffff);
+ CodeLen=1;
+ END
+ END
+ NextPar=False; return;
+ END
+ WrXError(1200,HOp); NextPar=False; return;
+ END
+
+ if (strncmp(OpPart,"DB",2)==0)
+ BEGIN
+ strcpy(HOp,OpPart);
+ strcpy(OpPart,OpPart+2);
+ l=strlen(OpPart);
+ if ((l>=1) AND (OpPart[l-1]=='D'))
+ BEGIN
+ OpPart[l-1]='\0'; DFlag=1l << 21;
+ Disp=3;
+ END
+ else
+ BEGIN
+ DFlag=0; Disp=1;
+ END
+ for (z=0; z<ConditionCount; z++)
+ if (Memo(Conditions[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else if (NOT DecodeReg(ArgStr[1],&HReg2)) WrError(1350);
+ else if ((HReg2<8) OR (HReg2>15)) WrError(1350);
+ else
+ BEGIN
+ HReg2-=8;
+ if (DecodeReg(ArgStr[2],&HReg))
+ BEGIN
+ DAsmCode[0]=0x6c000000
+ +(((LongWord)Conditions[z].Code) << 16)
+ +DFlag
+ +(((LongWord)HReg2) << 22)
+ +HReg;
+ CodeLen=1;
+ END
+ else
+ BEGIN
+ AdrLong=EvalAdrExpression(ArgStr[2],&OK)-(EProgCounter()+Disp);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrLong>0x7fffl) OR (AdrLong<-0x8000l))) WrError(1370);
+ else
+ BEGIN
+ DAsmCode[0]=0x6e000000
+ +(((LongWord)Conditions[z].Code) << 16)
+ +DFlag
+ +(((LongWord)HReg2) << 22)
+ +(AdrLong & 0xffff);
+ CodeLen=1;
+ END
+ END
+ END
+ NextPar=False; return;
+ END
+ WrXError(1200,HOp); NextPar=False; return;
+ END
+
+ if ((strncmp(OpPart,"RETI",4)==0) OR (strncmp(OpPart,"RETS",4)==0))
+ BEGIN
+ DFlag=(OpPart[3]=='S')?(1l << 23):(0);
+ strcpy(HOp,OpPart); strcpy(OpPart,OpPart+4);
+ for (z=0; z<ConditionCount; z++)
+ if (Memo(Conditions[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else
+ BEGIN
+ DAsmCode[0]=0x78000000+DFlag+(((LongWord)Conditions[z].Code) << 16);
+ CodeLen=1;
+ END
+ NextPar=False; return;
+ END
+ WrXError(1200,HOp); NextPar=False; return;
+ END
+
+ if (strncmp(OpPart,"TRAP",4)==0)
+ BEGIN
+ strcpy(HOp,OpPart); strcpy(OpPart,OpPart+4);
+ for (z=0; z<ConditionCount; z++)
+ if (Memo(Conditions[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (ThisPar) WrError(1950);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[1],UInt4,&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x74000000+HReg+(((LongWord)Conditions[z].Code) << 16);
+ CodeLen=1;
+ END
+ END
+ NextPar=False; return;
+ END
+ WrXError(1200,HOp); NextPar=False; return;
+ END
+
+ WrXError(1200,OpPart); NextPar=False;
+END
+
+ static void InitCode_3203x(void)
+BEGIN
+ SaveInitProc();
+ DPValue=0;
+END
+
+ static Boolean IsDef_3203X(void)
+BEGIN
+ return (strcmp(LabPart,"||")==0);
+END
+
+ static void SwitchFrom_3203X(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_3203X(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x76; NOPCode=0x0c800000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=4; ListGrans[SegCode]=4; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffffffl;
+
+ MakeCode=MakeCode_3203X; IsDef=IsDef_3203X;
+ SwitchFrom=SwitchFrom_3203X; InitFields(); NextPar=False;
+END
+
+ void code3203x_init(void)
+BEGIN
+ CPU32030=AddCPU("320C30",SwitchTo_3203X);
+ CPU32031=AddCPU("320C31",SwitchTo_3203X);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_3203x;
+END
diff --git a/code3203x.h b/code3203x.h
new file mode 100644
index 0000000..c90dd29
--- /dev/null
+++ b/code3203x.h
@@ -0,0 +1,11 @@
+/* code3203x.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS320C3x-Familie */
+/* */
+/* Historie: 12.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code3203x_init(void);
diff --git a/code3205x.c b/code3205x.c
new file mode 100644
index 0000000..4032aff
--- /dev/null
+++ b/code3205x.c
@@ -0,0 +1,1852 @@
+/*
+ * AS-Portierung
+ *
+ * AS-Codegeneratormodul fuer die Texas Instruments TMS320C5x-Familie
+ *
+ * (C) 1996 Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *
+ * 20.08.96: Erstellung
+ * 7.07.1998 Fix Zugriffe auf CharTransTable wg. signed chars
+ * 18.08.1998 BookKeeping-Aufruf in RES
+ * 9. 1.1999 ChkPC jetzt ueber SegLimits
+ * 30. 5.1999 Erweiterung auf C203 abgeschlossen, Hashtabelle fuer
+ * Prozessorbefehle erledigt
+ */
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "codepseudo.h"
+#include "endian.h"
+
+#include "code3202x.h"
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct {
+ char *name;
+ CPUVar mincpu;
+ Word code;
+} cmd_fixed;
+typedef struct {
+ char *name;
+ CPUVar mincpu;
+ Word code;
+ Boolean cond;
+} cmd_jmp;
+typedef struct {
+ char *name;
+ CPUVar mincpu;
+ Word mode;
+} adr_mode_t;
+typedef struct {
+ char *name;
+ CPUVar mincpu;
+ Word codeand;
+ Word codeor;
+ Byte iszl;
+ Byte isc;
+ Byte isv;
+ Byte istp;
+} condition;
+typedef struct {
+ char *name;
+ CPUVar mincpu;
+ Word code;
+} bit_table_t;
+
+static cmd_fixed *cmd_fixed_order;
+#define cmd_fixed_cnt 45
+static cmd_fixed *cmd_adr_order;
+#define cmd_adr_cnt 32
+static cmd_jmp *cmd_jmp_order;
+#define cmd_jmp_cnt 11
+static cmd_fixed *cmd_plu_order;
+#define cmd_plu_cnt 7
+static adr_mode_t *adr_modes;
+#define adr_mode_cnt 10
+static condition *cond_tab;
+#define cond_cnt 15
+static bit_table_t *bit_table;
+#define bit_cnt 9
+
+static Word adr_mode;
+static Boolean adr_ok;
+
+static CPUVar cpu_320203;
+static CPUVar cpu_32050;
+static CPUVar cpu_32051;
+static CPUVar cpu_32053;
+
+static PInstTable InstTable;
+
+/* ---------------------------------------------------------------------- */
+
+static Word eval_ar_expression(char *asc, Boolean *ok)
+{
+ *ok = True;
+
+ if ((toupper(asc[0]) == 'A') && (toupper(asc[1]) == 'R') && (asc[2] >= '0') &&
+ (asc[2] <= '7') && (asc[3] <= '\0'))
+ return asc[2] - '0';
+ return EvalIntExpression(asc, UInt3, ok);
+}
+
+/* ---------------------------------------------------------------------- */
+
+ static Boolean decode_adr(char *arg, int aux, Boolean must1)
+{
+ Word h;
+ adr_mode_t *am = adr_modes;
+
+ /* Annahme: nicht gefunden */
+
+ adr_ok = False;
+
+ /* Adressierungsmodus suchen */
+
+ while (am->name && strcasecmp(am->name, arg))
+ am++;
+
+ /* nicht gefunden: dann absolut */
+
+ if (!am->name)
+ BEGIN
+ /* ARn-Register darf dann nicht vorhanden sein */
+ if (aux <= ArgCnt)
+ BEGIN
+ WrError(1110); return FALSE;
+ END
+
+ /* Adresse berechnen */
+ h = EvalIntExpression(arg, Int16, &adr_ok);
+ if (!adr_ok) return FALSE;
+
+ /* Adresslage pruefen */
+ if (must1 && (h >= 0x80) && (!FirstPassUnknown))
+ BEGIN
+ WrError(1315);
+ adr_ok = False;
+ return FALSE;
+ END
+
+ /* nur untere 7 Bit gespeichert */
+ adr_mode = h & 0x7f;
+ ChkSpace(SegData);
+ END
+
+ /* ansonsten evtl. noch Adressregister dazu */
+
+ else
+ BEGIN
+ /* auf dieser CPU nicht erlaubter Modus ? */
+
+ if (am->mincpu > MomCPU)
+ BEGIN
+ WrError(1505); return FALSE;
+ END
+
+ adr_mode = am->mode;
+ if (aux <= ArgCnt)
+ BEGIN
+ h = eval_ar_expression(ArgStr[aux], &adr_ok);
+ if (adr_ok) adr_mode |= 0x8 | h;
+ END
+ else
+ adr_ok = True;
+ END
+
+ return adr_ok;
+END
+
+/* ---------------------------------------------------------------------- */
+
+static Word decode_cond(int argp)
+{
+ condition *cndp;
+ Byte cntzl = 0, cntc = 0, cntv = 0, cnttp = 0;
+ Word ret = 0x300;
+
+ while(argp <= ArgCnt) {
+ for(cndp = cond_tab;
+ cndp->name && strcasecmp(cndp->name, ArgStr[argp]); cndp++);
+ if (!cndp->name) {
+ WrError(1360);
+ return ret;
+ }
+ ret &= cndp->codeand;
+ ret |= cndp->codeor;
+ cntzl += cndp->iszl;
+ cntc += cndp->isc;
+ cntv += cndp->isv;
+ cnttp += cndp->istp;
+ argp++;
+ }
+ if ((cnttp > 1) || (cntzl > 1) || (cntv > 1) || (cntc > 1))
+ WrXError(1200, ArgStr[argp]); /* invalid condition */
+ return ret;
+}
+
+/* ---------------------------------------------------------------------- */
+
+ static Word DecodeShift(char *arg, Boolean *ok)
+BEGIN
+ Word Shift;
+
+ FirstPassUnknown = False;
+ Shift = EvalIntExpression(arg, UInt5, ok);
+ if (*ok)
+ BEGIN
+ if (FirstPassUnknown) Shift &= 15;
+ *ok = ChkRange(Shift, 0, 16);
+ END
+ return Shift;
+END
+
+/* ---------------------------------------------------------------------- */
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ cmd_fixed *fo = cmd_fixed_order + Index;
+
+ if (ArgCnt != 0)
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ if (fo->mincpu > MomCPU)
+ BEGIN
+ WrError(1500);
+ return;
+ END
+
+ CodeLen = 1;
+ WAsmCode[0] = fo->code;
+END
+
+ static void DecodeCmdAdr(Word Index)
+BEGIN
+ cmd_fixed *fo = cmd_adr_order + Index;
+
+ if ((ArgCnt < 1) OR (ArgCnt > 2))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ if (MomCPU < fo->mincpu)
+ BEGIN
+ WrError(1500);
+ return;
+ END
+
+ decode_adr(ArgStr[1], 2, False);
+ if (adr_ok)
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = fo->code | adr_mode;
+ END
+END
+
+ static void DecodeCmdJmp(Word Index)
+BEGIN
+ cmd_jmp *jo = cmd_jmp_order + Index;
+ Boolean ok;
+
+ if (MomCPU < jo->mincpu)
+ BEGIN
+ WrError(1500);
+ return;
+ END
+
+ if ((ArgCnt < 1) || ((ArgCnt > 3) && (!jo->cond)))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ adr_mode = 0;
+ if (jo->cond)
+ adr_mode = decode_cond(2);
+ else if (ArgCnt > 1)
+ BEGIN
+ decode_adr(ArgStr[2], 3, False);
+ if (adr_mode < 0x80)
+ BEGIN
+ WrError(1350);
+ return;
+ END
+ adr_mode &= 0x7f;
+ END
+
+ WAsmCode[1] = EvalIntExpression(ArgStr[1], Int16, &ok);
+ if (!ok) return;
+
+ CodeLen = 2;
+ WAsmCode[0] = jo->code | adr_mode;
+END
+
+ static void DecodeCmdPlu(Word Index)
+BEGIN
+ Boolean ok;
+
+ cmd_fixed *fo = cmd_plu_order + Index;
+
+ if (MomCPU < fo->mincpu) WrError(1500);
+ else if (*ArgStr[1] == '#')
+ BEGIN
+ if ((ArgCnt < 2) OR (ArgCnt > 3)) WrError(1110);
+ else
+ BEGIN
+ decode_adr(ArgStr[2], 3, False);
+ WAsmCode[1] = EvalIntExpression(ArgStr[1] + 1, Int16, &ok);
+ if ((ok) AND (adr_ok))
+ BEGIN
+ CodeLen = 2;
+ WAsmCode[0] = fo->code | 0x0400 | adr_mode;
+ END
+ END
+ END
+ else if (strlen(OpPart) == 4) WrError(1120);
+ else
+ BEGIN
+ if ((ArgCnt < 1) OR (ArgCnt > 2)) WrError(1110);
+ else
+ BEGIN
+ decode_adr(ArgStr[1], 2, False);
+ if (adr_ok)
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = fo->code | adr_mode;
+ END
+ END
+ END
+END
+
+ static void DecodeADDSUB(Word Index)
+BEGIN
+ Word Shift;
+ LongInt adr_long;
+ Boolean ok;
+
+ if ((ArgCnt < 1) || (ArgCnt > 3)) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1] == '#')
+ BEGIN
+ if (ArgCnt > 2) WrError(1110);
+ else
+ BEGIN
+ ok = True;
+ if (ArgCnt == 1) Shift = 0;
+ else Shift = EvalIntExpression(ArgStr[2], UInt4, &adr_ok);
+ if (ok)
+ BEGIN
+ adr_long = EvalIntExpression(ArgStr[1] + 1, UInt16, &ok);
+ if (ok)
+ if ((Shift == 0) && (Hi(adr_long) == 0))
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = (Index << 9) | 0xb800 | (adr_long & 0xff);
+ END
+ else
+ BEGIN
+ CodeLen = 2;
+ WAsmCode[0] = ((Index << 4) + 0xbf90) | (Shift & 0xf);
+ WAsmCode[1] = adr_long;
+ END
+ END
+ END
+ END
+ else
+ BEGIN
+ decode_adr(ArgStr[1], 3, False);
+ if (adr_ok)
+ BEGIN
+ ok = True;
+ if (ArgCnt >= 2)
+ Shift = DecodeShift(ArgStr[2], &ok);
+ else
+ Shift = 0;
+ if (ok)
+ BEGIN
+ CodeLen = 1;
+ if (Shift == 16)
+ WAsmCode[0] = ((Index << 10) | 0x6100) | adr_mode;
+ else
+ WAsmCode[0] = ((Index << 12) | 0x2000) | ((Shift & 0xf) << 8) | adr_mode;
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeADRSBRK(Word Index)
+BEGIN
+ Word adr_word;
+ Boolean ok;
+
+ if (ArgCnt != 1)
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ if (*ArgStr[1] != '#')
+ BEGIN
+ WrError(1120); /*invalid parameter*/
+ return;
+ END
+
+ adr_word = EvalIntExpression(ArgStr[1] + 1, UInt8, &ok);
+ if (ok)
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = (Index << 10)| 0x7800 | (adr_word & 0xff);
+ END
+END
+
+ static void DecodeLogic(Word Index)
+BEGIN
+ Boolean adr_ok, ok;
+ Word Shift;
+
+ if ((ArgCnt != 1) AND (ArgCnt != 2))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ if (*ArgStr[1] == '#')
+ BEGIN
+ WAsmCode[1] = EvalIntExpression((ArgStr[1])+1, UInt16, &ok);
+ Shift = 0;
+ adr_ok = True;
+ if (ArgCnt >= 2)
+ Shift = DecodeShift(ArgStr[2], &adr_ok);
+ if ((ok) AND (adr_ok))
+ BEGIN
+ CodeLen = 2;
+ if (Shift >= 16)
+ WAsmCode[0] = 0xbe80 | Lo(Index);
+ else
+ WAsmCode[0] = 0xbfa0 + ((Index & 3) << 4) + (Shift & 0xf);
+ END
+ END
+ else
+ BEGIN
+ if (decode_adr(ArgStr[1], 2, False))
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = (Index & 0xff00) | adr_mode;
+ END
+ END
+END
+
+ static void DecodeBIT(Word Index)
+BEGIN
+ Word bit;
+ Boolean ok;
+
+ if ((ArgCnt < 2) || (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ bit = EvalIntExpression(ArgStr[2], UInt4, &ok);
+
+ decode_adr(ArgStr[1], 3, False);
+
+ if ((adr_ok) AND (ok))
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0x4000 | adr_mode | ((bit & 0xf) << 8);
+ END
+END
+
+ static void DecodeBLDD(Word Index)
+BEGIN
+ Boolean ok;
+
+ if ((ArgCnt < 2) || (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ if (!strcasecmp(ArgStr[1], "BMAR"))
+ BEGIN
+ if (MomCPU < cpu_32050) WrError(1500);
+ else
+ BEGIN
+ decode_adr(ArgStr[2], 3, False);
+ if (!adr_ok) return;
+ CodeLen = 1;
+ WAsmCode[0] = 0xac00 | adr_mode;
+ END
+ return;
+ END
+
+ if (!strcasecmp(ArgStr[2], "BMAR"))
+ BEGIN
+ if (MomCPU < cpu_32050) WrError(1500);
+ else
+ BEGIN
+ decode_adr(ArgStr[1], 3, False);
+ if (!adr_ok) return;
+ CodeLen = 1;
+ WAsmCode[0] = 0xad00 | adr_mode;
+ END
+ return;
+ END
+
+ if (*ArgStr[1] == '#')
+ BEGIN
+ WAsmCode[1] = EvalIntExpression((ArgStr[1])+1, Int16, &ok);
+ decode_adr(ArgStr[2], 3, False);
+ if ((!adr_ok) || (!ok)) return;
+ CodeLen = 2;
+ WAsmCode[0] = 0xa800 | adr_mode;
+ return;
+ END
+
+ if (*ArgStr[2] == '#')
+ BEGIN
+ WAsmCode[1] = EvalIntExpression((ArgStr[2])+1, Int16, &ok);
+ decode_adr(ArgStr[1], 3, False);
+ if ((!adr_ok) || (!ok)) return;
+ CodeLen = 2;
+ WAsmCode[0] = 0xa900 | adr_mode;
+ return;
+ END
+
+ WrError(1350); /* invalid addr mode */
+END
+
+ static void DecodeBLPD(Word Index)
+BEGIN
+ Boolean ok;
+
+ if ((ArgCnt < 2) || (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ if (!strcasecmp(ArgStr[1], "BMAR"))
+ BEGIN
+ if (MomCPU < cpu_32050) WrError(1500);
+ else
+ BEGIN
+ decode_adr(ArgStr[2], 3, False);
+ if (!adr_ok) return;
+ CodeLen = 1;
+ WAsmCode[0] = 0xa400 | adr_mode;
+ END
+ return;
+ END
+
+ if (*ArgStr[1] == '#')
+ BEGIN
+ WAsmCode[1] = EvalIntExpression((ArgStr[1])+1, Int16, &ok);
+ decode_adr(ArgStr[2], 3, False);
+ if ((!adr_ok) || (!ok)) return;
+ CodeLen = 2;
+ WAsmCode[0] = 0xa500 | adr_mode;
+ return;
+ END
+
+ WrError(1350); /* invalid addressing mode */
+END
+
+ static void DecodeCLRSETC(Word Index)
+BEGIN
+ bit_table_t *bitp;
+
+ if (ArgCnt != 1)
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ WAsmCode[0] = Index; NLS_UpString(ArgStr[1]);
+
+ for(bitp = bit_table; bitp->name; bitp++)
+ if (!strcmp(ArgStr[1], bitp->name))
+ BEGIN
+ if (bitp->mincpu > MomCPU) WrError(1500);
+ else
+ BEGIN
+ WAsmCode[0] |= bitp->code;
+ CodeLen = 1;
+ END
+ return;
+ END
+
+ WrXError(1445, ArgStr[1]); /* invalid instruction */
+END
+
+ static void DecodeCMPRSPM(Word Index)
+BEGIN
+ Boolean ok;
+
+ if (ArgCnt != 1)
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ WAsmCode[0] = Index | (EvalIntExpression(ArgStr[1], UInt2, &ok) & 3);
+ if (!ok) return;
+ CodeLen = 1;
+END
+
+ static void DecodeIO(Word Index)
+BEGIN
+ Boolean ok;
+
+ if ((ArgCnt < 2) || (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ decode_adr(ArgStr[1],3,False);
+ if (!adr_ok) return;
+
+ WAsmCode[1] = EvalIntExpression(ArgStr[2], UInt16, &ok);
+ if (!ok) return;
+ ChkSpace(SegIO);
+
+ CodeLen = 2;
+ WAsmCode[0] = Index | adr_mode;
+END
+
+ static void DecodeINTR(Word Index)
+BEGIN
+ Boolean ok;
+
+ if (ArgCnt != 1)
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ WAsmCode[0] = EvalIntExpression(ArgStr[1], UInt5, &ok) | 0xbe60;
+ if (!ok) return;
+ CodeLen = 1;
+END
+
+ static void DecodeLACC(Word Index)
+BEGIN
+ Boolean ok;
+ LongWord adr_long;
+ Word Shift;
+
+ if ((ArgCnt < 1) || (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ if (*ArgStr[1] == '#')
+ BEGIN
+ if (ArgCnt > 2) WrError(1110);
+ else
+ BEGIN
+ adr_long = EvalIntExpression(ArgStr[1] + 1, Int16, &ok);
+ if (ok)
+ BEGIN
+ Shift = 0;
+ adr_ok = True;
+ if (ArgCnt > 1)
+ Shift = EvalIntExpression(ArgStr[2], UInt4, &adr_ok);
+ if (adr_ok)
+ BEGIN
+ CodeLen = 2;
+ WAsmCode[0] = 0xbf80 | (Shift & 0xf);
+ WAsmCode[1] = adr_long;
+ END
+ END
+ END
+ END
+ else
+ BEGIN
+ decode_adr(ArgStr[1], 3, False);
+ if (adr_ok)
+ BEGIN
+ Shift = 0; ok = True;
+ if (ArgCnt >= 2)
+ Shift = DecodeShift(ArgStr[2], &ok);
+ if (ok)
+ BEGIN
+ CodeLen = 1;
+ if (Shift >= 16)
+ WAsmCode[0] = 0x6a00 | adr_mode;
+ else
+ WAsmCode[0] = 0x1000 | ((Shift & 0xf) << 8) | adr_mode;
+ END
+ END
+ END
+END
+
+ static void DecodeLACL(Word Index)
+BEGIN
+ Boolean ok;
+
+ if (*ArgStr[1] == '#')
+ BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0] = EvalIntExpression(ArgStr[1] + 1, UInt8, &ok);
+ if (!ok) return;
+ CodeLen = 1;
+ WAsmCode[0] |= 0xb900;
+ END
+ END
+ else
+ BEGIN
+ if ((ArgCnt < 1) OR (ArgCnt > 2)) WrError(1110);
+ else
+ BEGIN
+ decode_adr(ArgStr[1], 2, False);
+ if (adr_ok)
+ BEGIN
+ WAsmCode[0] = 0x6900 | adr_mode;
+ CodeLen = 1;
+ END
+ END
+ END
+END
+
+ static void DecodeLAR(Word Index)
+BEGIN
+ Word Reg;
+ LongWord adr_long;
+ Boolean ok;
+
+ if ((ArgCnt < 2) || (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ Reg = eval_ar_expression(ArgStr[1], &ok);
+ if (!ok) return;
+
+ if (*ArgStr[2] == '#')
+ BEGIN
+ if (ArgCnt > 2) WrError(1110);
+ adr_long = EvalIntExpression(ArgStr[2] + 1, Int16,
+ &adr_ok) & 0xffff;
+ if (adr_ok)
+ if (adr_long > 255)
+ BEGIN
+ CodeLen = 2;
+ WAsmCode[0] = 0xbf08 | (Reg & 7);
+ WAsmCode[1] = adr_long;
+ END
+ else
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0xb000 | ((Reg & 7) << 8) | (adr_long & 0xff);
+ END
+ END
+ else
+ BEGIN
+ decode_adr(ArgStr[2], 3, False);
+ if (adr_ok)
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0x0000 | ((Reg & 7) << 8) | adr_mode;
+ END
+ END
+END
+
+ static void DecodeLDP(Word Index)
+BEGIN
+ Word konst;
+ Boolean ok;
+
+ if (*ArgStr[1] == '#')
+ BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ konst = EvalIntExpression(ArgStr[1] + 1, UInt9, &ok);
+ if (ok)
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = (konst & 0x1ff) | 0xbc00;
+ END
+ END
+ END
+ else
+ BEGIN
+ if ((ArgCnt != 1) AND (ArgCnt != 2)) WrError(1110);
+ else
+ BEGIN
+ decode_adr(ArgStr[1], 2, False);
+ if (adr_ok)
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0x0d00 | adr_mode;
+ END
+ END
+ END
+END
+
+ static void DecodeLSST(Word Index)
+BEGIN
+ Word konst;
+ Boolean ok;
+
+ if ((ArgCnt < 2) || (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ if (*ArgStr[1] != '#')
+ BEGIN
+ WrError(1120); /* invalid instruction */
+ END
+
+ konst = EvalIntExpression(ArgStr[1] + 1, UInt1, &ok);
+ decode_adr(ArgStr[2], 3, Index);
+ if ((ok) AND (adr_ok))
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0x0e00 | (Index << 15) | ((konst & 1) << 8) | adr_mode;
+ END
+END
+
+ static void DecodeMAC(Word Index)
+BEGIN
+ Boolean ok;
+
+ if ((ArgCnt < 2) OR (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ WAsmCode[1] = EvalIntExpression(ArgStr[1], Int16, &ok);
+ ChkSpace(SegCode);
+
+ decode_adr(ArgStr[2], 3, False);
+
+ if ((adr_ok) AND (ok))
+ BEGIN
+ CodeLen = 2;
+ WAsmCode[0] = 0xa200 | (Index << 8) | adr_mode;
+ END
+END
+
+ static void DecodeMPY(Word Index)
+BEGIN
+ LongInt Imm;
+ Boolean ok;
+
+ if (*ArgStr[1] == '#')
+ BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown = FALSE;
+ Imm = EvalIntExpression(ArgStr[1] + 1, SInt16, &ok);
+ if (FirstPassUnknown) Imm &= 0xfff;
+ if (ok)
+ if ((Imm < -4096) || (Imm > 4095))
+ BEGIN
+ if (MomCPU < cpu_32050) WrError(1500);
+ else
+ BEGIN
+ CodeLen = 2; /* What does that mean? */
+ WAsmCode[0] = 0xbe80;
+ WAsmCode[1] = Imm;
+ END
+ END
+ else
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0xc000 | (Imm & 0x1fff);
+ END
+ END
+ END
+ else
+ BEGIN
+ if ((ArgCnt < 1) OR (ArgCnt > 2)) WrError(1110);
+ else
+ BEGIN
+ decode_adr(ArgStr[1], 2, Index);
+ if (adr_ok)
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0x5400 | adr_mode;
+ END
+ END
+ END
+END
+
+ static void DecodeNORM(Word Index)
+BEGIN
+ if ((ArgCnt < 1) || (ArgCnt > 2))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ decode_adr(ArgStr[1], 2, False);
+ if (adr_ok)
+ if (adr_mode < 0x80) WrError(1350);
+ else
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0xa080 | (adr_mode & 0x7f);
+ END
+END
+
+ static void DecodeRETC(Word Index)
+BEGIN
+ if (ArgCnt < 1) WrError(1110);
+ else if ((Memo("RETCD")) AND (MomCPU < cpu_32050)) WrError(1500);
+ else
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0xec00 | (Index << 12) | decode_cond(1);
+ END
+END
+
+ static void DecodeRPT(Word Index)
+BEGIN
+ Word Imm;
+ Boolean ok;
+
+ if (*ArgStr[1] == '#')
+ BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ Imm = EvalIntExpression(ArgStr[1] + 1, (MomCPU >= cpu_32050) ? UInt16 : UInt8, &ok);
+ if (ok)
+ if (Imm > 255)
+ BEGIN
+ CodeLen = 2;
+ WAsmCode[0] = 0xbec4;
+ WAsmCode[1] = Imm;
+ END
+ else
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0xbb00 | (Imm & 0xff);
+ END
+ END
+ END
+ else
+ BEGIN
+ if ((ArgCnt != 1) AND (ArgCnt != 2)) WrError(1110);
+ else
+ BEGIN
+ decode_adr(ArgStr[1], 2, False);
+ if (adr_ok)
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0x0b00 | adr_mode;
+ END
+ END
+ END
+END
+
+ static void DecodeSAC(Word Index)
+BEGIN
+ Boolean ok;
+ Word Shift;
+
+ if ((ArgCnt < 1) || (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ ok = True;
+ Shift = 0;
+ if (ArgCnt >= 2)
+ Shift = EvalIntExpression(ArgStr[2], UInt3, &ok);
+
+ decode_adr(ArgStr[1], 3, False);
+
+ if ((adr_ok) AND (ok))
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = (Index << 11) | 0x9000 | adr_mode | ((Shift & 7) << 8);
+ END
+END
+
+ static void DecodeSAR(Word Index)
+BEGIN
+ Word Reg;
+ Boolean ok;
+
+ if ((ArgCnt < 2) || (ArgCnt > 3))
+ BEGIN
+ WrError(1110);
+ return;
+ END
+
+ Reg = eval_ar_expression(ArgStr[1], &ok);
+ decode_adr(ArgStr[2], 3, False);
+
+ if ((adr_ok) AND (ok))
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0x8000 | ((Reg & 7) << 8) | adr_mode;
+ END
+END
+
+ static void DecodeBSAR(Word Index)
+BEGIN
+ Word Shift;
+ Boolean ok;
+
+ if (ArgCnt != 1) WrError(1110);
+ else if (MomCPU < cpu_32050) WrError(1500);
+ else
+ BEGIN
+ FirstPassUnknown = False;
+ Shift = EvalIntExpression(ArgStr[1], UInt5, &ok);
+ if (FirstPassUnknown) Shift = 1;
+ if (ok)
+ if (ChkRange(Shift, 1, 16))
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0xbfe0 | ((Shift - 1) & 0xf);
+ END
+ END
+END
+
+ static void DecodeLSAMM(Word Index)
+BEGIN
+ if ((ArgCnt < 1) OR (ArgCnt > 2)) WrError(1110);
+ else if (MomCPU < cpu_32050) WrError(1500);
+ else
+ BEGIN
+ decode_adr(ArgStr[1], 2, True);
+ if (adr_ok)
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = 0x0800 | (Index << 15) | adr_mode;
+ END
+ END
+END
+
+ static void DecodeLSMMR(Word Index)
+BEGIN
+ Boolean ok;
+
+ if ((ArgCnt < 2) OR (ArgCnt > 3)) WrError(1110);
+ else if (MomCPU < cpu_32050) WrError(1500);
+ else if (ArgStr[2][0] != '#') WrError(1120);
+ else
+ BEGIN
+ WAsmCode[1] = EvalIntExpression(ArgStr[2] + 1, Int16, &ok);
+ decode_adr(ArgStr[1], 3, True);
+ if ((adr_ok) AND (ok))
+ BEGIN
+ CodeLen = 2;
+ WAsmCode[0] = 0x0900 | (Index << 15) | adr_mode;
+ END
+ END
+END
+
+ static void DecodeRPTB(Word Index)
+BEGIN
+ Boolean ok;
+
+ if (ArgCnt != 1) WrError(1110);
+ else if (MomCPU < cpu_32050) WrError(1500);
+ else
+ BEGIN
+ WAsmCode[1] = EvalIntExpression(ArgStr[1], Int16, &ok);
+ if (ok)
+ BEGIN
+ CodeLen = 2;
+ WAsmCode[0] = 0xbec6;
+ END
+ END
+END
+
+ static void DecodeRPTZ(Word Index)
+BEGIN
+ Boolean ok;
+
+ if (ArgCnt != 1) WrError(1110);
+ else if (MomCPU < cpu_32050) WrError(1500);
+ else if (*ArgStr[1] != '#') WrError(1120);
+ else
+ BEGIN
+ WAsmCode[1] = EvalIntExpression(ArgStr[1] + 1, Int16, &ok);
+ if (ok)
+ BEGIN
+ CodeLen = 2;
+ WAsmCode[0] = 0xbec5;
+ END
+ END
+END
+
+ static void DecodeXC(Word Index)
+BEGIN
+ Word Mode;
+ Boolean ok;
+
+ if (ArgCnt < 2) WrError(1110);
+ else if (MomCPU < cpu_32050) WrError(1500);
+ else
+ BEGIN
+ FirstPassUnknown = False;
+ Mode = EvalIntExpression(ArgStr[1], UInt2, &ok);
+ if (ok)
+ if ((Mode != 1) && (Mode != 2) && (!FirstPassUnknown)) WrError(1315);
+ else
+ BEGIN
+ CodeLen = 1;
+ WAsmCode[0] = (0xd400 + (Mode << 12)) | decode_cond(2);
+ END
+ END
+END
+
+/* ---------------------------------------------------------------------- */
+
+static int instrz;
+
+static void addfixed(char *nname, CPUVar mincpu, Word ncode)
+{
+ if (instrz>=cmd_fixed_cnt) exit(255);
+ cmd_fixed_order[instrz].name = nname;
+ cmd_fixed_order[instrz].mincpu = mincpu;
+ cmd_fixed_order[instrz].code = ncode;
+ AddInstTable(InstTable, nname, instrz++, DecodeFixed);
+}
+
+static void addadr(char *nname, CPUVar mincpu, Word ncode)
+{
+ if (instrz>=cmd_adr_cnt) exit(255);
+ cmd_adr_order[instrz].name = nname;
+ cmd_adr_order[instrz].mincpu = mincpu;
+ cmd_adr_order[instrz].code = ncode;
+ AddInstTable(InstTable, nname, instrz++, DecodeCmdAdr);
+}
+
+static void addjmp(char *nname, CPUVar mincpu, Word ncode, Boolean ncond)
+{
+ if (instrz>=cmd_jmp_cnt) exit(255);
+ cmd_jmp_order[instrz].name = nname;
+ cmd_jmp_order[instrz].mincpu = mincpu;
+ cmd_jmp_order[instrz].code = ncode;
+ cmd_jmp_order[instrz].cond = ncond;
+ AddInstTable(InstTable, nname, instrz++, DecodeCmdJmp);
+}
+
+static void addplu(char *nname, CPUVar mincpu, Word ncode)
+{
+ if (instrz>=cmd_plu_cnt) exit(255);
+ cmd_plu_order[instrz].name = nname;
+ cmd_plu_order[instrz].mincpu = mincpu;
+ cmd_plu_order[instrz].code = ncode;
+ AddInstTable(InstTable, nname, instrz++, DecodeCmdPlu);
+}
+
+static void addadrmode(char *nname, CPUVar mincpu, Word nmode)
+{
+ if (instrz>=adr_mode_cnt) exit(255);
+ adr_modes[instrz].name = nname;
+ adr_modes[instrz].mincpu = mincpu;
+ adr_modes[instrz++].mode= nmode;
+}
+
+static void addcond(char *nname, CPUVar mincpu, Word ncodeand, Word ncodeor, Byte niszl,
+ Byte nisc, Byte nisv, Byte nistp)
+{
+ if (instrz>=cond_cnt) exit(255);
+ cond_tab[instrz].name = nname;
+ cond_tab[instrz].mincpu = mincpu;
+ cond_tab[instrz].codeand = ncodeand;
+ cond_tab[instrz].codeor = ncodeor;
+ cond_tab[instrz].iszl = niszl;
+ cond_tab[instrz].isc = nisc;
+ cond_tab[instrz].isv = nisv;
+ cond_tab[instrz++].istp = nistp;
+}
+
+static void addbit(char *nname, CPUVar mincpu, Word ncode)
+{
+ if (instrz>=bit_cnt) exit(255);
+ bit_table[instrz].name = nname;
+ bit_table[instrz].mincpu = mincpu;
+ bit_table[instrz++].code = ncode;
+}
+
+static void initfields(void)
+{
+ InstTable = CreateInstTable(203);
+
+ cmd_fixed_order=(cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_fixed_cnt); instrz = 0;
+ addfixed("ABS", cpu_320203, 0xbe00); addfixed("ADCB", cpu_32050 , 0xbe11);
+ addfixed("ADDB", cpu_32050 , 0xbe10); addfixed("ANDB", cpu_32050 , 0xbe12);
+ addfixed("CMPL", cpu_320203, 0xbe01); addfixed("CRGT", cpu_32050 , 0xbe1b);
+ addfixed("CRLT", cpu_32050 , 0xbe1c); addfixed("EXAR", cpu_32050 , 0xbe1d);
+ addfixed("LACB", cpu_32050 , 0xbe1f); addfixed("NEG", cpu_320203, 0xbe02);
+ addfixed("ORB", cpu_32050 , 0xbe13); addfixed("ROL", cpu_320203, 0xbe0c);
+ addfixed("ROLB", cpu_32050 , 0xbe14); addfixed("ROR", cpu_320203, 0xbe0d);
+ addfixed("RORB", cpu_32050 , 0xbe15); addfixed("SACB", cpu_32050 , 0xbe1e);
+ addfixed("SATH", cpu_32050 , 0xbe5a); addfixed("SATL", cpu_32050 , 0xbe5b);
+ addfixed("SBB", cpu_32050 , 0xbe18); addfixed("SBBB", cpu_32050 , 0xbe19);
+ addfixed("SFL", cpu_320203, 0xbe09); addfixed("SFLB", cpu_32050 , 0xbe16);
+ addfixed("SFR", cpu_320203, 0xbe0a); addfixed("SFRB", cpu_32050 , 0xbe17);
+ addfixed("XORB", cpu_32050 , 0xbe1a); addfixed("ZAP", cpu_32050 , 0xbe59);
+ addfixed("APAC", cpu_320203, 0xbe04); addfixed("PAC", cpu_320203, 0xbe03);
+ addfixed("SPAC", cpu_320203, 0xbe05); addfixed("ZPR", cpu_32050 , 0xbe58);
+ addfixed("BACC", cpu_320203, 0xbe20); addfixed("BACCD", cpu_32050 , 0xbe21);
+ addfixed("CALA", cpu_320203, 0xbe30); addfixed("CALAD", cpu_32050 , 0xbe3d);
+ addfixed("NMI", cpu_320203, 0xbe52); addfixed("RET", cpu_320203, 0xef00);
+ addfixed("RETD", cpu_32050 , 0xff00); addfixed("RETE", cpu_32050 , 0xbe3a);
+ addfixed("RETI", cpu_32050 , 0xbe38); addfixed("TRAP", cpu_320203, 0xbe51);
+ addfixed("IDLE", cpu_320203, 0xbe22); addfixed("NOP", cpu_320203, 0x8b00);
+ addfixed("POP", cpu_320203, 0xbe32); addfixed("PUSH", cpu_320203, 0xbe3c);
+ addfixed("IDLE2", cpu_32050 , 0xbe23);
+
+ cmd_adr_order = (cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_adr_cnt); instrz = 0;
+ addadr("ADDC", cpu_320203, 0x6000); addadr("ADDS", cpu_320203, 0x6200);
+ addadr("ADDT", cpu_320203, 0x6300); addadr("LACT", cpu_320203, 0x6b00);
+ addadr("SUBB", cpu_320203, 0x6400); addadr("SUBC", cpu_320203, 0x0a00);
+ addadr("SUBS", cpu_320203, 0x6600); addadr("SUBT", cpu_320203, 0x6700);
+ addadr("ZALR", cpu_320203, 0x6800); addadr("MAR", cpu_320203, 0x8b00);
+ addadr("LPH", cpu_320203, 0x7500); addadr("LT", cpu_320203, 0x7300);
+ addadr("LTA", cpu_320203, 0x7000); addadr("LTD", cpu_320203, 0x7200);
+ addadr("LTP", cpu_320203, 0x7100); addadr("LTS", cpu_320203, 0x7400);
+ addadr("MADD", cpu_32050 , 0xab00); addadr("MADS", cpu_32050 , 0xaa00);
+ addadr("MPYA", cpu_320203, 0x5000); addadr("MPYS", cpu_320203, 0x5100);
+ addadr("MPYU", cpu_320203, 0x5500); addadr("SPH", cpu_320203, 0x8d00);
+ addadr("SPL", cpu_320203, 0x8c00); addadr("SQRA", cpu_320203, 0x5200);
+ addadr("SQRS", cpu_320203, 0x5300); addadr("BLDP", cpu_32050 , 0x5700);
+ addadr("DMOV", cpu_320203, 0x7700); addadr("TBLR", cpu_320203, 0xa600);
+ addadr("TBLW", cpu_320203, 0xa700); addadr("BITT", cpu_320203, 0x6f00);
+ addadr("POPD", cpu_320203, 0x8a00); addadr("PSHD", cpu_320203, 0x7600);
+
+ cmd_jmp_order=(cmd_jmp *) malloc(sizeof(cmd_jmp)*cmd_jmp_cnt); instrz=0;
+ addjmp("B", cpu_320203, 0x7980, False);
+ addjmp("BD", cpu_32050 , 0x7d80, False);
+ addjmp("BANZ", cpu_320203, 0x7b80, False);
+ addjmp("BANZD", cpu_32050 , 0x7f80, False);
+ addjmp("BCND", cpu_320203, 0xe000, True);
+ addjmp("BCNDD", cpu_32050 , 0xf000, True);
+ addjmp("CALL", cpu_320203, 0x7a80, False);
+ addjmp("CALLD", cpu_32050 , 0x7e80, False);
+ addjmp("CC", cpu_320203, 0xe800, True);
+ addjmp("CCD", cpu_32050 , 0xf800, True);
+
+ cmd_plu_order=(cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_plu_cnt); instrz=0;
+ addplu("APL", cpu_32050 , 0x5a00); addplu("CPL", cpu_32050 , 0x5b00);
+ addplu("OPL", cpu_32050 , 0x5900); addplu("SPLK", cpu_320203, 0xaa00);
+ addplu("XPL", cpu_32050 , 0x5800);
+
+ adr_modes=(adr_mode_t *) malloc(sizeof(adr_mode_t)*adr_mode_cnt); instrz=0;
+ addadrmode( "*-", cpu_320203, 0x90 ); addadrmode( "*+", cpu_320203, 0xa0 );
+ addadrmode( "*BR0-", cpu_320203, 0xc0 ); addadrmode( "*0-", cpu_320203, 0xd0 );
+ addadrmode( "*AR0-", cpu_32050 , 0xd0 ); addadrmode( "*0+", cpu_320203, 0xe0 );
+ addadrmode( "*AR0+", cpu_32050 , 0xe0 ); addadrmode( "*BR0+", cpu_320203, 0xf0 );
+ addadrmode( "*", cpu_320203, 0x80 ); addadrmode( NULL, cpu_32050 , 0);
+
+ cond_tab=(condition *) malloc(sizeof(condition)*cond_cnt); instrz=0;
+ addcond("EQ", cpu_32050 , 0xf33, 0x088, 1, 0, 0, 0);
+ addcond("NEQ", cpu_32050 , 0xf33, 0x008, 1, 0, 0, 0);
+ addcond("LT", cpu_32050 , 0xf33, 0x044, 1, 0, 0, 0);
+ addcond("LEQ", cpu_32050 , 0xf33, 0x0cc, 1, 0, 0, 0);
+ addcond("GT", cpu_32050 , 0xf33, 0x004, 1, 0, 0, 0);
+ addcond("GEQ", cpu_32050 , 0xf33, 0x08c, 1, 0, 0, 0);
+ addcond("NC", cpu_32050 , 0xfee, 0x001, 0, 1, 0, 0);
+ addcond("C", cpu_32050 , 0xfee, 0x011, 0, 1, 0, 0);
+ addcond("NOV", cpu_32050 , 0xfdd, 0x002, 0, 0, 1, 0);
+ addcond("OV", cpu_32050 , 0xfdd, 0x022, 0, 0, 1, 0);
+ addcond("BIO", cpu_32050 , 0x0ff, 0x000, 0, 0, 0, 1);
+ addcond("NTC", cpu_32050 , 0x0ff, 0x200, 0, 0, 0, 1);
+ addcond("TC", cpu_32050 , 0x0ff, 0x100, 0, 0, 0, 1);
+ addcond("UNC", cpu_32050 , 0x0ff, 0x300, 0, 0, 0, 1);
+ addcond(NULL, cpu_32050 , 0xfff, 0x000, 0, 0, 0, 0);
+
+ bit_table=(bit_table_t *) malloc(sizeof(bit_table_t)*bit_cnt); instrz=0;
+ addbit("OVM", cpu_320203, 0xbe42 ); addbit("SXM", cpu_320203, 0xbe46 );
+ addbit("HM", cpu_32050 , 0xbe48 ); addbit("TC", cpu_320203, 0xbe4a );
+ addbit("C", cpu_320203, 0xbe4e ); addbit("XF", cpu_320203, 0xbe4c );
+ addbit("CNF", cpu_320203, 0xbe44 ); addbit("INTM", cpu_320203, 0xbe40 );
+ addbit(NULL, cpu_32050 , 0 );
+
+ AddInstTable(InstTable, "ADD" , 0, DecodeADDSUB);
+ AddInstTable(InstTable, "SUB" , 1, DecodeADDSUB);
+ AddInstTable(InstTable, "ADRK" , 0, DecodeADRSBRK);
+ AddInstTable(InstTable, "SBRK" , 1, DecodeADRSBRK);
+ AddInstTable(InstTable, "AND" , 0x6e01, DecodeLogic);
+ AddInstTable(InstTable, "OR" , 0x6d02, DecodeLogic);
+ AddInstTable(InstTable, "XOR" , 0x6c03, DecodeLogic);
+ AddInstTable(InstTable, "BIT" , 0, DecodeBIT);
+ AddInstTable(InstTable, "BLDD" , 0, DecodeBLDD);
+ AddInstTable(InstTable, "BLPD" , 0, DecodeBLPD);
+ AddInstTable(InstTable, "CLRC" , 0, DecodeCLRSETC);
+ AddInstTable(InstTable, "SETC" , 1, DecodeCLRSETC);
+ AddInstTable(InstTable, "CMPR" , 0xbf44, DecodeCMPRSPM);
+ AddInstTable(InstTable, "SPM" , 0xbf00, DecodeCMPRSPM);
+ AddInstTable(InstTable, "IN" , 0xaf00, DecodeIO);
+ AddInstTable(InstTable, "OUT" , 0x0c00, DecodeIO);
+ AddInstTable(InstTable, "INTR" , 0, DecodeINTR);
+ AddInstTable(InstTable, "LACC" , 0, DecodeLACC);
+ AddInstTable(InstTable, "LACL" , 0, DecodeLACL);
+ AddInstTable(InstTable, "LAR" , 0, DecodeLAR);
+ AddInstTable(InstTable, "LDP" , 0, DecodeLDP);
+ AddInstTable(InstTable, "SST" , 1, DecodeLSST);
+ AddInstTable(InstTable, "LST" , 0, DecodeLSST);
+ AddInstTable(InstTable, "MAC" , 0, DecodeMAC);
+ AddInstTable(InstTable, "MACD" , 1, DecodeMAC);
+ AddInstTable(InstTable, "MPY" , 0, DecodeMPY);
+ AddInstTable(InstTable, "NORM" , 0, DecodeNORM);
+ AddInstTable(InstTable, "RETC" , 0, DecodeRETC);
+ AddInstTable(InstTable, "RETCD", 1, DecodeRETC);
+ AddInstTable(InstTable, "RPT" , 0, DecodeRPT);
+ AddInstTable(InstTable, "SACL" , 0, DecodeSAC);
+ AddInstTable(InstTable, "SACH" , 1, DecodeSAC);
+ AddInstTable(InstTable, "SAR" , 0, DecodeSAR);
+ AddInstTable(InstTable, "BSAR" , 0, DecodeBSAR);
+ AddInstTable(InstTable, "LAMM" , 0, DecodeLSAMM);
+ AddInstTable(InstTable, "SAMM" , 1, DecodeLSAMM);
+ AddInstTable(InstTable, "LMMR" , 1, DecodeLSMMR);
+ AddInstTable(InstTable, "SMMR" , 0, DecodeLSMMR);
+ AddInstTable(InstTable, "RPTB" , 0, DecodeRPTB);
+ AddInstTable(InstTable, "RPTZ" , 0, DecodeRPTZ);
+ AddInstTable(InstTable, "XC" , 0, DecodeXC);
+}
+
+static void deinitfields(void)
+{
+ DestroyInstTable(InstTable);
+ free(cmd_fixed_order);
+ free(cmd_adr_order);
+ free(cmd_jmp_order);
+ free(cmd_plu_order);
+ free(adr_modes);
+ free(cond_tab);
+ free(bit_table);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void pseudo_qxx(Integer num)
+{
+ int z;
+ Boolean ok;
+ double res;
+
+ if (!ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ for(z = 1; z <= ArgCnt; z++) {
+ res = ldexp(EvalFloatExpression(ArgStr[z], Float64, &ok), num);
+ if (!ok) {
+ CodeLen = 0;
+ return;
+ }
+ if ((res > 32767.49) || (res < -32768.49)) {
+ CodeLen = 0;
+ WrError(1320);
+ return;
+ }
+ WAsmCode[CodeLen++] = res;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void pseudo_lqxx(Integer num)
+{
+ int z;
+ Boolean ok;
+ double res;
+ LongInt resli;
+
+ if (!ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ for(z = 1; z <= ArgCnt; z++) {
+ res = ldexp(EvalFloatExpression(ArgStr[z], Float64, &ok), num);
+ if (!ok) {
+ CodeLen = 0;
+ return;
+ }
+ if ((res > 2147483647.49) || (res < -2147483647.49)) {
+ CodeLen = 0;
+ WrError(1320);
+ return;
+ }
+ resli = res;
+ WAsmCode[CodeLen++] = resli & 0xffff;
+ WAsmCode[CodeLen++] = resli >> 16;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void define_untyped_label(void)
+{
+ if (LabPart[0]) {
+ PushLocHandle(-1);
+ EnterIntSymbol(LabPart, EProgCounter(), SegNone, False);
+ PopLocHandle();
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_byte(Boolean *ok, int *adr, LongInt val)
+{
+ if ((val < -128) || (val > 0xff)) {
+ WrError(1320);
+ *ok = False;
+ return;
+ }
+ WAsmCode[(*adr)++] = val & 0xff;
+ CodeLen = *adr;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_word(Boolean *ok, int *adr, LongInt val)
+{
+ if ((val < -32768) || (val > 0xffff)) {
+ WrError(1320);
+ *ok = False;
+ return;
+ }
+ WAsmCode[(*adr)++] = val;
+ CodeLen = *adr;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_long(Boolean *ok, int *adr, LongInt val)
+{
+ WAsmCode[(*adr)++] = val & 0xffff;
+ WAsmCode[(*adr)++] = val >> 16;
+ CodeLen = *adr;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_byte_hilo(Boolean *ok, int *adr, LongInt val)
+{
+ if ((val < -128) || (val > 0xff)) {
+ WrError(1320);
+ *ok = False;
+ return;
+ }
+ if ((*adr) & 1)
+ WAsmCode[((*adr)++)/2] |= val & 0xff;
+ else
+ WAsmCode[((*adr)++)/2] = val << 8;
+ CodeLen = ((*adr)+1)/2;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void wr_code_byte_lohi(Boolean *ok, int *adr, LongInt val)
+{
+ if ((val < -128) || (val > 0xff)) {
+ WrError(1320);
+ *ok = False;
+ return;
+ }
+ if ((*adr) & 1)
+ WAsmCode[((*adr)++)/2] |= val << 8;
+ else
+ WAsmCode[((*adr)++)/2] = val & 0xff;
+ CodeLen = ((*adr)+1)/2;
+}
+
+/* ---------------------------------------------------------------------- */
+
+typedef void (*tcallback)(
+#ifdef __PROTOS__
+Boolean *, int *, LongInt
+#endif
+);
+
+static void pseudo_store(tcallback callback)
+{
+ Boolean ok = True;
+ int adr = 0;
+ int z;
+ TempResult t;
+ unsigned char *cp;
+
+ if (!ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ define_untyped_label();
+ for(z = 1; z <= ArgCnt; z++) {
+ if (!ok)
+ return;
+ EvalExpression(ArgStr[z], &t);
+ switch(t.Typ) {
+ case TempInt:
+ callback(&ok, &adr, t.Contents.Int);
+ break;
+ case TempFloat:
+ WrError(1135);
+ return;
+ case TempString:
+ cp = (unsigned char *)t.Contents.Ascii;
+ while (*cp)
+ callback(&ok, &adr, CharTransTable[((usint)*cp++)&0xff]);
+ break;
+ default:
+ WrError(1135);
+ return;
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static Boolean decode_pseudo(void)
+{
+ Word size;
+ Boolean ok;
+ TempResult t;
+ int z,z2;
+ unsigned char *cp;
+ float flt;
+ double dbl, mant;
+ int exp;
+ long lmant;
+ Word w;
+
+ if (Memo("PORT")) {
+ CodeEquate(SegIO,0,65535);
+ return True;
+ }
+
+ if (Memo("RES") || Memo("BSS")) {
+ if (ArgCnt != 1) {
+ WrError(1110);
+ return True;
+ }
+ if (Memo("BSS"))
+ define_untyped_label();
+ FirstPassUnknown = False;
+ size = EvalIntExpression(ArgStr[1], Int16, &ok);
+ if (FirstPassUnknown) {
+ WrError(1820);
+ return True;
+ }
+ if (!ok)
+ return True;
+ DontPrint = True;
+ CodeLen = size;
+ BookKeeping();
+ return True;
+ }
+
+ if (Memo("DATA")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ EvalExpression(ArgStr[z], &t);
+ switch(t.Typ) {
+ case TempInt:
+ if ((t.Contents.Int < -32768) ||
+ (t.Contents.Int > 0xffff)) {
+ WrError(1320);
+ ok = False;
+ } else
+ WAsmCode[CodeLen++] = t.Contents.Int;
+ break;
+ default:
+ case TempFloat:
+ WrError(1135);
+ ok = False;
+ break;
+ case TempString:
+ z2 = 0;
+ cp = (unsigned char *)t.Contents.Ascii;
+ while (*cp) {
+ if (z2 & 1)
+ WAsmCode[CodeLen++] |=
+ (CharTransTable[((usint)*cp++)&0xff]
+ << 8);
+ else
+ WAsmCode[CodeLen] =
+ CharTransTable[((usint)*cp++)&0xff];
+ z2++;
+ }
+ if (z2 & 1)
+ CodeLen++;
+ break;
+ }
+ }
+ if (!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if (Memo("STRING")) {
+ pseudo_store(wr_code_byte_hilo);
+ return True;
+ }
+ if (Memo("RSTRING")) {
+ pseudo_store(wr_code_byte_lohi);
+ return True;
+ }
+ if (Memo("BYTE")) {
+ pseudo_store(wr_code_byte);
+ return True;
+ }
+ if (Memo("WORD")) {
+ pseudo_store(wr_code_word);
+ return True;
+ }
+ if (Memo("LONG")) {
+ pseudo_store(wr_code_long);
+ return True;
+ }
+
+ /* Qxx */
+
+ if ((OpPart[0] == 'Q') && (OpPart[1] >= '0') && (OpPart[1] <= '9') &&
+ (OpPart[2] >= '0') && (OpPart[2] <= '9') && (OpPart[3] == '\0')) {
+ pseudo_qxx(10*(OpPart[1]-'0')+OpPart[2]-'0');
+ return True;
+ }
+
+ /* LQxx */
+
+ if ((OpPart[0] == 'L') && (OpPart[1] == 'Q') && (OpPart[2] >= '0') &&
+ (OpPart[2] <= '9') && (OpPart[3] >= '0') && (OpPart[3] <= '9') &&
+ (OpPart[4] == '\0')) {
+ pseudo_lqxx(10*(OpPart[2]-'0')+OpPart[3]-'0');
+ return True;
+ }
+
+ /* Floating point definitions */
+
+ if (Memo("FLOAT")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ flt = EvalFloatExpression(ArgStr[z], Float32, &ok);
+ memcpy(WAsmCode+CodeLen, &flt, sizeof(float));
+ if (BigEndian) {
+ w = WAsmCode[CodeLen];
+ WAsmCode[CodeLen] = WAsmCode[CodeLen+1];
+ WAsmCode[CodeLen+1] = w;
+ }
+ CodeLen += sizeof(float)/2;
+ }
+ if (!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if (Memo("DOUBLE")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
+ memcpy(WAsmCode+CodeLen, &dbl, sizeof(dbl));
+ if (BigEndian) {
+ w = WAsmCode[CodeLen];
+ WAsmCode[CodeLen] = WAsmCode[CodeLen+3];
+ WAsmCode[CodeLen+3] = w;
+ w = WAsmCode[CodeLen+1];
+ WAsmCode[CodeLen+1] = WAsmCode[CodeLen+2];
+ WAsmCode[CodeLen+2] = w;
+ }
+ CodeLen += sizeof(dbl)/2;
+ }
+ if (!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if (Memo("EFLOAT")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
+ mant = frexp(dbl, &exp);
+ WAsmCode[CodeLen++] = ldexp(mant, 15);
+ WAsmCode[CodeLen++] = exp-1;
+ }
+ if (!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if (Memo("BFLOAT")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
+ mant = frexp(dbl, &exp);
+ lmant = ldexp(mant, 31);
+ WAsmCode[CodeLen++] = (lmant & 0xffff);
+ WAsmCode[CodeLen++] = (lmant >> 16);
+ WAsmCode[CodeLen++] = exp-1;
+ }
+ if (!ok)
+ CodeLen = 0;
+ return True;
+ }
+
+ if (Memo("TFLOAT")) {
+ if (!ArgCnt) {
+ WrError(1110);
+ return True;
+ }
+ define_untyped_label();
+ ok = True;
+ for(z = 1; (z <= ArgCnt) && ok; z++) {
+ dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
+ mant = frexp(dbl, &exp);
+ mant = modf(ldexp(mant, 15), &dbl);
+ WAsmCode[CodeLen+3] = dbl;
+ mant = modf(ldexp(mant, 16), &dbl);
+ WAsmCode[CodeLen+2] = dbl;
+ mant = modf(ldexp(mant, 16), &dbl);
+ WAsmCode[CodeLen+1] = dbl;
+ mant = modf(ldexp(mant, 16), &dbl);
+ WAsmCode[CodeLen] = dbl;
+ CodeLen += 4;
+ WAsmCode[CodeLen++] = ((exp - 1) & 0xffff);
+ WAsmCode[CodeLen++] = ((exp - 1) >> 16);
+ }
+ if (!ok)
+ CodeLen = 0;
+ return True;
+ }
+ return False;
+}
+
+/* ---------------------------------------------------------------------- */
+
+ static void make_code_3205x(void)
+BEGIN
+ CodeLen = 0;
+ DontPrint = False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (decode_pseudo()) return;
+
+ /* per Hash-Tabelle */
+
+ if (NOT LookupInstTable(InstTable, OpPart)) WrXError(1200, OpPart);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static Boolean is_def_3205x(void)
+{
+ static const char *defs[] = { "BSS", "PORT", "STRING", "RSTRING",
+ "BYTE", "WORD", "LONG", "FLOAT",
+ "DOUBLE", "EFLOAT", "BFLOAT",
+ "TFLOAT", NULL };
+ const char **cp = defs;
+
+ while(*cp) {
+ if (Memo(*cp))
+ return True;
+ cp++;
+ }
+ return False;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void switch_from_3205x(void)
+{
+ deinitfields();
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void switch_to_3205x(void)
+{
+ TurnWords = False;
+ ConstMode = ConstModeIntel;
+ SetIsOccupied = False;
+
+ PCSymbol = "$";
+ HeaderID = 0x77;
+ NOPCode = 0x8b00;
+ DivideChars = ",";
+ HasAttrs = False;
+
+ ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegIO);
+ Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
+ SegLimits[SegCode] = 0xffff;
+ Grans[SegData] = 2; ListGrans[SegData] = 2; SegInits[SegData] = 0;
+ SegLimits[SegData] = 0xffff;
+ Grans[SegIO ] = 2; ListGrans[SegIO ] = 2; SegInits[SegIO ] = 0;
+ SegLimits[SegIO ] = 0xffff;
+
+ MakeCode = make_code_3205x;
+ IsDef = is_def_3205x; SwitchFrom = switch_from_3205x;
+ initfields();
+}
+
+/* ---------------------------------------------------------------------- */
+
+void code3205x_init(void)
+{
+ cpu_320203 = AddCPU("320C203", switch_to_3205x);
+ cpu_32050 = AddCPU("320C50", switch_to_3205x);
+ cpu_32051 = AddCPU("320C51", switch_to_3205x);
+ cpu_32053 = AddCPU("320C53", switch_to_3205x);
+
+ AddCopyright("TMS320C5x-Generator (C) 1995/96 Thomas Sailer");
+}
diff --git a/code3205x.h b/code3205x.h
new file mode 100644
index 0000000..aa1ec7f
--- /dev/null
+++ b/code3205x.h
@@ -0,0 +1,9 @@
+/*
+ * AS-Portierung
+ *
+ * AS-Codegeneratormodul fuer die Texas Instruments TMS320C5x-Familie
+ *
+ * 19.08.96: Erstellung
+ */
+
+extern void code3205x_init(void);
diff --git a/code3206x.c b/code3206x.c
new file mode 100644
index 0000000..de0be1b
--- /dev/null
+++ b/code3206x.c
@@ -0,0 +1,2313 @@
+/* code3206x.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS320C6x */
+/* */
+/* Historie: 24. 2.1997 Grundsteinlegung */
+/* 22. 5.1998 Schoenheitsoperatioenen fuer K&R-Compiler */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* 23. 1.1999 DecodeCtrlReg jetzt mit unsigned-Ergebnis */
+/* 30. 1.1999 Formate maschinenunabhaengig gemacht */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "strutil.h"
+#include "bpemu.h"
+#include "nls.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmcode.h"
+#include "codepseudo.h"
+#include "asmitree.h"
+
+/*---------------------------------------------------------------------------*/
+
+typedef enum {NoUnit,L1,L2,S1,S2,M1,M2,D1,D2,LastUnit,UnitCnt} TUnit;
+
+typedef struct
+ {
+ LongInt OpCode;
+ LongInt SrcMask,SrcMask2,DestMask;
+ Byte CrossUsed; /* Bit 0 -->X1 benutzt, Bit 1 -->X2 benutzt */
+ Byte AddrUsed; /* Bit 0 -->Addr1 benutzt, Bit 1 -->Addr2 benutzt
+ Bit 2 -->LdSt1 benutzt, Bit 3 -->LdSt2 benutzt */
+ Byte LongUsed; /* Bit 0 -->lange Quelle, Bit 1-->langes Ziel */
+ Boolean StoreUsed,LongSrc,LongDest;
+ TUnit U;
+ } InstrRec;
+
+typedef struct
+ {
+ char *Name;
+ LongInt Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ LongInt Code;
+ LongInt Scale;
+ } MemOrder;
+
+typedef struct
+ {
+ char *Name;
+ LongInt Code;
+ Boolean DSign,SSign1,SSign2;
+ Boolean MayImm;
+ } MulOrder;
+
+typedef struct
+ {
+ char *Name;
+ LongInt Code;
+ Boolean Rd,Wr;
+ } CtrlReg;
+
+static char *UnitNames[UnitCnt]={" ","L1","L2","S1","S2","M1","M2","D1","D2"," "};
+#define MaxParCnt 8
+#define FirstUnit L1
+
+#define LinAddCnt 6
+#define CmpCnt 5
+#define MemCnt 8
+#define MulCnt 20
+#define CtrlCnt 13
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModLReg 1
+#define MModLReg (1 << ModLReg)
+#define ModImm 2
+#define MModImm (1 << ModImm)
+
+static ShortInt AdrMode;
+
+static CPUVar CPU32060;
+
+static Boolean ThisPar,ThisCross,ThisStore;
+static Byte ThisAddr,ThisLong;
+static LongInt ThisSrc,ThisSrc2,ThisDest;
+static LongInt Condition;
+static TUnit ThisUnit;
+static LongWord UnitFlag,ThisInst;
+static Integer ParCnt;
+static LongWord PacketAddr;
+
+static InstrRec ParRecs[MaxParCnt];
+
+FixedOrder *LinAddOrders;
+FixedOrder *CmpOrders;
+MemOrder *MemOrders;
+MulOrder *MulOrders;
+CtrlReg *CtrlRegs;
+PInstTable InstTable;
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean CheckOpt(char *Asc)
+BEGIN
+ Boolean Flag,erg=True;
+ int l=strlen(Asc);
+
+ if (strcmp(Asc,"||")==0) ThisPar=True;
+ else if ((*Asc=='[') AND (Asc[l-1]==']'))
+ BEGIN
+ Asc++; Asc[l-2]='\0'; l-=2;
+ if (*Asc=='!')
+ BEGIN
+ Asc++; l--; Condition=1;
+ END
+ else Condition=0;
+ Flag=True;
+ if (l!=2) Flag=False;
+ else if (toupper(*Asc)=='A')
+ if ((Asc[1]>='1') AND (Asc[1]<='2')) Condition+=(Asc[1]-'0'+3) << 1;
+ else Flag=False;
+ else if (toupper(*Asc)=='B')
+ if ((Asc[1]>='0') AND (Asc[1]<='2')) Condition+=(Asc[1]-'0'+1) << 1;
+ else Flag=False;
+ if (NOT Flag) WrXError(1445,Asc); erg=Flag;
+ END
+ else erg=False;
+
+ return erg;
+END
+
+ static Boolean ReiterateOpPart(void)
+BEGIN
+ char *p;
+ int z;
+
+ if (NOT CheckOpt(OpPart)) return False;
+
+ if (ArgCnt<1)
+ BEGIN
+ WrError(1210); return False;
+ END
+ p=FirstBlank(ArgStr[1]);
+ if (p==Nil)
+ BEGIN
+ strcpy(OpPart,ArgStr[1]);
+ for (z=2; z<=ArgCnt; z++) strcpy(ArgStr[z-1],ArgStr[z]);
+ ArgCnt--;
+ END
+ else
+ BEGIN
+ *p='\0'; strcpy(OpPart,ArgStr[1]); strcpy(ArgStr[1],p+1);
+ KillPrefBlanks(ArgStr[1]);
+ END
+ NLS_UpString(OpPart);
+ p=strchr(OpPart,'.');
+ if (p==Nil) *AttrPart='\0';
+ else
+ BEGIN
+ strcpy(AttrPart,p+1);
+ *p='\0';
+ END;
+ return True;
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void AddSrc(LongWord Reg)
+BEGIN
+ LongWord Mask=1 << Reg;
+
+ if ((ThisSrc & Mask)==0) ThisSrc|=Mask;
+ else ThisSrc2|=Mask;
+END
+
+ static void AddLSrc(LongWord Reg)
+BEGIN
+ AddSrc(Reg); AddSrc(Reg+1);
+ ThisLong|=1;
+END
+
+ static void AddDest(LongWord Reg)
+BEGIN
+ ThisDest|=(1 << Reg);
+END
+
+ static void AddLDest(LongWord Reg)
+BEGIN
+ ThisDest|=(3 << Reg);
+ ThisLong|=2;
+END
+
+ static LongInt FindReg(LongInt Mask)
+BEGIN
+ int z;
+
+ for (z=0; z<32; z++)
+ BEGIN
+ if ((Mask&1)!=0) break;
+ Mask=Mask >> 1;
+ END
+ return z;
+END
+
+ static char *RegName(LongInt Num)
+BEGIN
+ static char s[5];
+
+ Num&=31;
+ sprintf(s, "%c%ld", 'A' + (Num >> 4), (long) (Num & 15));
+ return s;
+END
+
+ static Boolean DecodeSReg(char *Asc, LongWord *Reg, Boolean Quarrel)
+BEGIN
+ char *end;
+ Byte RVal;
+ Boolean TFlag;
+
+ TFlag=True;
+ if (toupper(*Asc)=='A') *Reg=0;
+ else if (toupper(*Asc)=='B') *Reg=16;
+ else TFlag=False;
+ if (TFlag)
+ BEGIN
+ RVal=strtol(Asc+1,&end,10);
+ if (*end!='\0') TFlag=False;
+ else if (RVal>15) TFlag=False;
+ else *Reg+=RVal;
+ END
+ if ((NOT TFlag) AND (Quarrel)) WrXError(1445,Asc);
+ return TFlag;
+END
+
+ static Boolean DecodeReg(char *Asc, LongWord *Reg, Boolean *PFlag, Boolean Quarrel)
+BEGIN
+ char *p;
+ LongWord NextReg;
+
+ p=strchr(Asc,':');
+ if (p==0)
+ BEGIN
+ *PFlag=False; return DecodeSReg(Asc,Reg,Quarrel);
+ END
+ else
+ BEGIN
+ *PFlag=True; *p='\0';
+ if (NOT DecodeSReg(Asc,&NextReg,Quarrel)) return False;
+ else if (NOT DecodeSReg(p+1,Reg,Quarrel)) return False;
+ else if ((Odd(*Reg)) OR (NextReg!=(*Reg)+1) OR ((((*Reg) ^ NextReg) & 0x10)!=0))
+ BEGIN
+ if (Quarrel) WrXError(1760,Asc); return False;
+ END
+ else return True;
+ END
+END
+
+ static Boolean DecodeCtrlReg(char *Asc, LongWord *Erg, Boolean Write)
+BEGIN
+ int z;
+
+ for (z=0; z<CtrlCnt; z++)
+ if (strcasecmp(Asc,CtrlRegs[z].Name)==0)
+ BEGIN
+ *Erg=CtrlRegs[z].Code;
+ return (Write AND CtrlRegs[z].Wr) OR ((NOT Write) AND CtrlRegs[z].Rd);
+ END
+ return False;
+END
+
+/* Was bedeutet das r-Feld im Adressoperanden mit kurzem Offset ???
+ und wie ist das genau mit der Skalierung gemeint ??? */
+
+ static Boolean DecodeMem(char *Asc, LongWord *Erg, LongWord Scale)
+BEGIN
+ String RegPart,DispPart;
+ LongInt DispAcc,Mode;
+ LongWord BaseReg,IndReg;
+ int l;
+ char Counter;
+ char *p;
+ Boolean OK;
+
+ /* das muss da sein */
+
+ if (*Asc!='*')
+ BEGIN
+ WrError(1350); return False;
+ END;
+ Asc++;
+
+ /* teilen */
+
+ p=strchr(Asc,'['); Counter=']';
+ if (p==Nil)
+ BEGIN
+ p=strchr(Asc,'('); Counter=')';
+ END
+ if (p!=Nil)
+ BEGIN
+ if (Asc[strlen(Asc)-1]!=Counter)
+ BEGIN
+ WrError(1350); return False;
+ END
+ Asc[strlen(Asc)-1]='\0'; *p='\0';
+ strmaxcpy(RegPart,Asc,255); strmaxcpy(DispPart,p+1,255);
+ END
+ else
+ BEGIN
+ strcpy(RegPart,Asc); *DispPart='\0';
+ END
+
+ /* Registerfeld entschluesseln */
+
+ l=strlen(RegPart);
+ Mode=1; /* Default ist *+R */
+ if (*RegPart=='+')
+ BEGIN
+ strcpy(RegPart,RegPart+1); Mode=1;
+ if (*RegPart=='+')
+ BEGIN
+ strcpy(RegPart,RegPart+1); Mode=9;
+ END
+ END
+ else if (*RegPart=='-')
+ BEGIN
+ strcpy(RegPart,RegPart+1); Mode=0;
+ if (*RegPart=='-')
+ BEGIN
+ strcpy(RegPart,RegPart+1); Mode=8;
+ END
+ END
+ else if (RegPart[l-1]=='+')
+ BEGIN
+ if (RegPart[l-2]!='+')
+ BEGIN
+ WrError(1350); return False;
+ END
+ RegPart[l-2]='\0'; Mode=11;
+ END
+ else if (RegPart[l-1]=='-')
+ BEGIN
+ if (RegPart[l-2]!='-')
+ BEGIN
+ WrError(1350); return False;
+ END
+ RegPart[l-2]='\0'; Mode=10;
+ END
+ if (NOT DecodeSReg(RegPart,&BaseReg,False))
+ BEGIN
+ WrXError(1445,RegPart); return False;
+ END
+ AddSrc(BaseReg);
+
+ /* kein Offsetfeld ? --> Skalierungsgroesse bei Autoinkrement/De-
+ krement, sonst 0 */
+
+ if (*DispPart=='\0')
+ DispAcc=(Mode<2) ? 0 : Scale;
+
+ /* Register als Offsetfeld? Dann Bit 2 in Modus setzen */
+
+ else if (DecodeSReg(DispPart,&IndReg,False))
+ BEGIN
+ if ((IndReg ^ BaseReg)>15)
+ BEGIN
+ WrError(1350); return False;
+ END
+ Mode+=4; AddSrc(DispAcc=IndReg);
+ END
+
+ /* ansonsten normaler Offset */
+
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ DispAcc=EvalIntExpression(DispPart,UInt15,&OK);
+ if (NOT OK) return False;
+ if (FirstPassUnknown) DispAcc&=7;
+ if (Counter==']') DispAcc*=Scale;
+ END
+
+ /* Benutzung des Adressierers markieren */
+
+ ThisAddr|=(BaseReg>15) ? 2 : 1;
+
+ /* Wenn Offset>31, muessen wir Variante 2 benutzen */
+
+ if (((Mode & 4)==0) AND (DispAcc>31))
+ if ((BaseReg<0x1e) OR (Mode!=1)) WrError(1350);
+ else
+ BEGIN
+ *Erg=((DispAcc & 0x7fff) << 8)+((BaseReg & 1) << 7)+12;
+ return True;
+ END
+
+ else
+ BEGIN
+ *Erg=(BaseReg << 18)+((DispAcc & 0x1f) << 13)+(Mode << 9)
+ +((BaseReg & 0x10) << 3)+4;
+ return True;
+ END
+
+ return False;
+END
+
+ static Boolean DecodeAdr(char *Asc, Byte Mask, Boolean Signed, LongWord *AdrVal)
+BEGIN
+ Boolean OK;
+
+ AdrMode=ModNone;
+
+ if (DecodeReg(Asc,AdrVal,&OK,False))
+ BEGIN
+ AdrMode=(OK) ? ModLReg : ModReg;
+ END
+ else
+ BEGIN
+ if (Signed) *AdrVal=EvalIntExpression(Asc,SInt5,&OK) & 0x1f;
+ else *AdrVal=EvalIntExpression(Asc,UInt5,&OK);
+ if (OK) AdrMode=ModImm;
+ END
+
+ if ((AdrMode!=ModNone) AND (((1 << AdrMode) AND Mask)==0))
+ BEGIN
+ WrError(1350); AdrMode=ModNone; return False;
+ END
+ else return True;
+END
+
+ static Boolean ChkUnit(LongWord Reg, TUnit U1, TUnit U2)
+BEGIN
+ UnitFlag=Ord(Reg>15);
+ if (ThisUnit==NoUnit)
+ BEGIN
+ ThisUnit=(Reg>15) ? U2 : U1;
+ return True;
+ END
+ else if (((ThisUnit==U1) AND (Reg<16)) OR ((ThisUnit==U2) AND (Reg>15))) return True;
+ else
+ BEGIN
+ WrError(1107); return False;
+ END
+END
+
+ static TUnit UnitCode(char c)
+BEGIN
+ switch (c)
+ BEGIN
+ case 'L': return L1;
+ case 'S': return S1;
+ case 'D': return D1;
+ case 'M': return M1;
+ default: return NoUnit;
+ END
+END
+
+ static Boolean UnitUsed(TUnit TestUnit)
+BEGIN
+ Integer z;
+
+ for (z=0; z<ParCnt; z++)
+ if (ParRecs[z].U==TestUnit) return True;
+
+ return False;
+END
+
+ static Boolean IsCross(LongWord Reg)
+BEGIN
+ return (Reg >> 4)!=UnitFlag;
+END
+
+ static void SetCross(LongWord Reg)
+BEGIN
+ ThisCross=((Reg >> 4)!=UnitFlag);
+END
+
+ static Boolean DecideUnit(LongWord Reg, char *Units)
+BEGIN
+ Integer z;
+ TUnit TestUnit;
+
+ if (ThisUnit==NoUnit)
+ BEGIN
+ z=0;
+ while ((Units[z]!='\0') AND (ThisUnit==NoUnit))
+ BEGIN
+ TestUnit=UnitCode(Units[z]);
+ if (Reg>=16) TestUnit++;
+ if (NOT UnitUsed(TestUnit)) ThisUnit=TestUnit;
+ z++;
+ END
+ if (ThisUnit==NoUnit)
+ BEGIN
+ ThisUnit=UnitCode(*Units);
+ if (Reg>16) TestUnit++;
+ END
+ END
+ UnitFlag=(ThisUnit-FirstUnit) & 1;
+ if (IsCross(Reg))
+ BEGIN
+ WrError(1107); return False;
+ END
+ else return True;
+END
+
+ static void SwapReg(LongWord *r1, LongWord *r2)
+BEGIN
+ LongWord tmp;
+
+ tmp=(*r1); *r1=(*r2); *r2=tmp;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+
+ static Boolean CodeL(LongWord OpCode,LongWord Dest,LongWord Src1,LongWord Src2)
+BEGIN
+ ThisInst=0x18+(OpCode << 5)+(UnitFlag << 1)+(Ord(ThisCross) << 12)
+ +(Dest << 23)+(Src2 << 18)+(Src1 << 13);
+ return True;
+END
+
+ static Boolean CodeM(LongWord OpCode, LongWord Dest, LongWord Src1, LongWord Src2)
+BEGIN
+ ThisInst=0x00+(OpCode << 7)+(UnitFlag << 1)+(Ord(ThisCross) << 12)
+ +(Dest << 23)+(Src2 << 18)+(Src1 << 13);
+ return True;
+END
+
+ static Boolean CodeS(LongWord OpCode, LongWord Dest, LongWord Src1, LongWord Src2)
+BEGIN
+ ThisInst=0x20+(OpCode << 6)+(UnitFlag << 1)+(Ord(ThisCross) << 12)
+ +(Dest << 23)+(Src2 << 18)+(Src1 << 13);
+ return True;
+END
+
+ static Boolean CodeD(LongWord OpCode, LongWord Dest, LongWord Src1, LongWord Src2)
+BEGIN
+ ThisInst=0x40+(OpCode << 7)+(UnitFlag << 1)
+ +(Dest << 23)+(Src2 << 18)+(Src1 << 13);
+ return True;
+END
+
+/*-------------------------------------------------------------------------*/
+
+static Boolean __erg;
+
+ static void DecodeIDLE(Word Index)
+BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if ((ThisCross) OR (ThisUnit!=NoUnit)) WrError(1107);
+ else
+ BEGIN
+ ThisInst=0x0001e000; __erg=True;
+ END
+END
+
+ static void DecodeNOP(Word Index)
+BEGIN
+ LongInt Count;
+ Boolean OK;
+
+ if ((ArgCnt!=0) AND (ArgCnt!=1)) WrError(1110);
+ else if ((ThisCross) OR (ThisUnit!=NoUnit)) WrError(1107);
+ else
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ OK=True; Count=0;
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Count=EvalIntExpression(ArgStr[1],UInt4,&OK);
+ if (FirstPassUnknown) Count=0; else Count--;
+ OK=ChkRange(Count,0,8);
+ END
+ if (OK)
+ BEGIN
+ ThisInst=Count << 13; __erg=True;
+ END
+ END
+END
+
+ static void DecodeMul(Word Index)
+BEGIN
+ LongWord DReg,S1Reg,S2Reg;
+ MulOrder *POrder=MulOrders+Index;
+
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[3],MModReg,POrder->DSign,&DReg))
+ if (ChkUnit(DReg,M1,M2))
+ BEGIN
+ if (DecodeAdr(ArgStr[2],MModReg,POrder->SSign2,&S2Reg))
+ BEGIN
+ AddSrc(S2Reg);
+ DecodeAdr(ArgStr[1],(POrder->MayImm?MModImm:0)+MModReg,
+ POrder->SSign1,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((ThisCross) AND (NOT IsCross(S2Reg)) AND (NOT IsCross(S1Reg))) WrError(1350);
+ else if ((IsCross(S2Reg)) AND (IsCross(S1Reg))) WrError(1350);
+ else
+ BEGIN
+ if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
+ SetCross(S2Reg);
+ AddSrc(S1Reg);
+ __erg=CodeM(POrder->Code,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ if (Memo("MPY")) __erg=CodeM(POrder->Code-1,DReg,S1Reg,S2Reg);
+ else __erg=CodeM(POrder->Code+3,DReg,S1Reg,S2Reg);
+ break;
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeMemO(Word Index)
+BEGIN
+ LongWord DReg,S1Reg;
+ MemOrder *POrder=MemOrders+Index;
+ Boolean OK,IsStore;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ IsStore=(*OpPart)=='S';
+ if (IsStore)
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ ThisStore=True;
+ END
+ if (DecodeAdr(ArgStr[2],MModReg,False,&DReg))
+ BEGIN
+ if (IsStore) AddSrc(DReg);
+ ThisAddr|=(DReg>15) ? 8 : 4;
+ /* Zielregister 4 Takte verzoegert, nicht als Dest eintragen */
+ OK=DecodeMem(ArgStr[1],&S1Reg,POrder->Scale);
+ if (OK)
+ if ((S1Reg & 8)==0) OK=ChkUnit((S1Reg >> 18) & 31,D1,D2);
+ else OK=ChkUnit(0x1e,D1,D2);
+ if (OK)
+ BEGIN
+ ThisInst=S1Reg+(DReg << 23)+(POrder->Code << 4)
+ +((DReg & 16) >> 3);
+ __erg=True;
+ END
+ END;
+ END
+END
+
+ static void DecodeSTP(Word Index)
+BEGIN
+ LongWord S2Reg;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (ChkUnit(0x10,S1,S2))
+ BEGIN
+ if (DecodeAdr(ArgStr[1],MModReg,False,&S2Reg))
+ if ((ThisCross) OR (S2Reg<16)) WrError(1110);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ __erg=CodeS(0x0c,0,0,S2Reg);
+ END
+ END
+END
+
+ static void DecodeABS(Word Index)
+BEGIN
+ Boolean DPFlag,S1Flag;
+ LongWord DReg,S1Reg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (DecodeReg(ArgStr[2],&DReg,&DPFlag,True))
+ if (ChkUnit(DReg,L1,L2))
+ if (DecodeReg(ArgStr[1],&S1Reg,&S1Flag,True))
+ if (DPFlag!=S1Flag) WrError(1350);
+ else if ((ThisCross) AND ((S1Reg >> 4)==UnitFlag)) WrError(1350);
+ else
+ BEGIN
+ SetCross(S1Reg);
+ if (DPFlag) __erg=CodeL(0x38,DReg,0,S1Reg);
+ else __erg=CodeL(0x1a,DReg,0,S1Reg);
+ if (DPFlag) AddLSrc(S1Reg); else AddSrc(S1Reg);
+ if (DPFlag) AddLDest(DReg); else AddDest(DReg);
+ END
+END
+
+ static void DecodeADD(Word Index)
+BEGIN
+ LongWord S1Reg,S2Reg,DReg;
+ Boolean OK;
+
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
+ UnitFlag=DReg >> 4;
+ switch (AdrMode)
+ BEGIN
+ case ModLReg: /* ADD ?,?,long */
+ AddLDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModLReg+MModImm,True,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg: /* ADD int,?,long */
+ AddSrc(S1Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModLReg,True,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg: /* ADD int,int,long */
+ if (ChkUnit(DReg,L1,L2))
+ if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
+ SetCross(S2Reg);
+ __erg=CodeL(0x23,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModLReg:/* ADD int,long,long */
+ if (ChkUnit(DReg,L1,L2))
+ if (IsCross(S2Reg)) WrError(1350);
+ else if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ SetCross(S1Reg);
+ __erg=CodeL(0x21,DReg,S1Reg,S2Reg);
+ END
+ break;
+ END
+ break;
+ case ModLReg: /* ADD long,?,long */
+ AddLSrc(S1Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg: /* ADD long,int,long */
+ if (ChkUnit(DReg,L1,L2))
+ if (IsCross(S1Reg)) WrError(1350);
+ else if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ SetCross(S2Reg);
+ __erg=CodeL(0x21,DReg,S2Reg,S1Reg);
+ END
+ break;
+ case ModImm: /* ADD long,imm,long */
+ if (ChkUnit(DReg,L1,L2))
+ if (IsCross(S1Reg)) WrError(1350);
+ else if (ThisCross) WrError(1350);
+ else __erg=CodeL(0x20,DReg,S2Reg,S1Reg);
+ break;
+ END
+ break;
+ case ModImm: /* ADD imm,?,long */
+ if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
+ BEGIN /* ADD imm,long,long */
+ if (ChkUnit(DReg,L1,L2))
+ if (IsCross(S2Reg)) WrError(1350);
+ else if (ThisCross) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ __erg=CodeL(0x20,DReg,S1Reg,S2Reg);
+ END
+ END
+ break;
+ END
+ break;
+ case ModReg: /* ADD ?,?,int */
+ AddDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg: /* ADD int,?,int */
+ AddSrc(S1Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg: /* ADD int,int,int */
+ AddSrc(S2Reg);
+ if (((DReg^S1Reg)>15) AND ((DReg^S2Reg)>15)) WrError(1350);
+ else if ((ThisCross) AND ((DReg^S1Reg)<16) AND ((DReg^S2Reg)<15)) WrError(1350);
+ else
+ BEGIN
+ if ((S1Reg^DReg)>15) SwapReg(&S1Reg,&S2Reg);
+ OK=DecideUnit(DReg,((S2Reg^DReg)>15) ? "LS" : "LSD");
+ if (OK)
+ BEGIN
+ switch (ThisUnit)
+ BEGIN
+ case L1: case L2: __erg=CodeL(0x03,DReg,S1Reg,S2Reg); break; /* ADD.Lx int,int,int */
+ case S1: case S2: __erg=CodeS(0x07,DReg,S1Reg,S2Reg); break; /* ADD.Sx int,int,int */
+ case D1: case D2: __erg=CodeD(0x10,DReg,S1Reg,S2Reg); break; /* ADD.Dx int,int,int */
+ default: WrError(20000);
+ END
+ END
+ END
+ break;
+ case ModImm: /* ADD int,imm,int */
+ if ((ThisCross) AND ((S1Reg^DReg)<16)) WrError(1350);
+ else
+ BEGIN
+ SetCross(S1Reg);
+ if (DecideUnit(DReg,"LS"))
+ switch (ThisUnit)
+ BEGIN
+ case L1: case L2: __erg=CodeL(0x02,DReg,S2Reg,S1Reg); break;
+ case S1: case S2: __erg=CodeS(0x06,DReg,S2Reg,S1Reg); break;
+ default: WrError(20000);
+ END
+ END
+ break;
+ END
+ break;
+ case ModImm: /* ADD imm,?,int */
+ if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
+ BEGIN
+ AddSrc(S2Reg);
+ if ((ThisCross) AND ((S2Reg^DReg)<16)) WrError(1350);
+ else
+ BEGIN
+ SetCross(S2Reg);
+ if (DecideUnit(DReg,"LS"))
+ switch (ThisUnit)
+ BEGIN
+ case L1: case L2: __erg=CodeL(0x02,DReg,S1Reg,S2Reg); break;
+ case S1: case S2: __erg=CodeS(0x06,DReg,S1Reg,S2Reg); break;
+ default: WrError(20000);
+ END
+ END
+ END
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeADDU(Word Index)
+BEGIN
+ LongWord DReg,S1Reg,S2Reg;
+
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[3],MModReg+MModLReg,False,&DReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg: /* ADDU ?,?,int */
+ if (ChkUnit(DReg,D1,D2))
+ BEGIN
+ AddDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModImm,False,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg: /* ADDU int,?,int */
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S1Reg);
+ if (DecodeAdr(ArgStr[2],MModImm,False,&S2Reg))
+ __erg=CodeD(0x12,DReg,S2Reg,S1Reg);
+ END
+ break;
+ case ModImm: /* ADDU imm,?,int */
+ if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
+ if (IsCross(S2Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ __erg=CodeD(0x12,DReg,S1Reg,S2Reg);
+ END
+ break;
+ END
+ END
+ break;
+ case ModLReg: /* ADDU ?,?,long */
+ if (ChkUnit(DReg,L1,L2))
+ BEGIN
+ AddLDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModLReg,False,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg: /* ADDU int,?,long */
+ AddSrc(S1Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModLReg,False,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg: /* ADDU int,int,long */
+ if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
+ else if ((ThisCross) AND (((S1Reg^DReg)<16) AND ((S2Reg^DReg)<16))) WrError(1350);
+ else
+ BEGIN
+ if ((S1Reg^DReg)>15) SwapReg(&S1Reg,&S2Reg);
+ SetCross(S2Reg);
+ __erg=CodeL(0x2b,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModLReg: /* ADDU int,long,long */
+ if (IsCross(S2Reg)) WrError(1350);
+ else if ((ThisCross) AND ((S1Reg^DReg)<16)) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ SetCross(S1Reg);
+ __erg=CodeL(0x29,DReg,S1Reg,S2Reg);
+ END
+ break;
+ END
+ break;
+ case ModLReg:
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S1Reg);
+ if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
+ if ((ThisCross) AND ((S2Reg^DReg)<16)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg); SetCross(S2Reg);
+ __erg=CodeL(0x29,DReg,S2Reg,S1Reg);
+ END
+ END
+ break;
+ END
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeSUB(Word Index)
+BEGIN
+ LongWord DReg,S1Reg,S2Reg;
+ Boolean OK;
+
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddSrc(S1Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((ThisCross) AND ((S1Reg^DReg)<16) AND ((S2Reg^DReg)<16)) WrError(1350);
+ else if (((S1Reg^DReg)>15) AND ((S2Reg^DReg)>15)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ ThisCross=((S1Reg^DReg)>15) OR ((S2Reg^DReg)>15);
+ if ((S1Reg^DReg)>15) OK=DecideUnit(DReg,"L");
+ else if ((S2Reg^DReg)>15) OK=DecideUnit(DReg,"LS");
+ else OK=DecideUnit(DReg,"LSD");
+ if (OK)
+ switch (ThisUnit)
+ BEGIN
+ case L1: case L2:
+ if ((S1Reg^DReg)>15) __erg=CodeL(0x17,DReg,S1Reg,S2Reg);
+ else __erg=CodeL(0x07,DReg,S1Reg,S2Reg);
+ break;
+ case S1: case S2:
+ __erg=CodeS(0x17,DReg,S1Reg,S2Reg);
+ break;
+ case D1: case D2:
+ __erg=CodeD(0x11,DReg,S2Reg,S1Reg);
+ break;
+ default:
+ WrError(20000);
+ END
+ END
+ break;
+ case ModImm:
+ if (ChkUnit(DReg,D1,D2))
+ if ((ThisCross) OR ((S1Reg^DReg)>15)) WrError(1350);
+ else __erg=CodeD(0x13,DReg,S2Reg,S1Reg);
+ break;
+ END
+ break;
+ case ModImm:
+ if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
+ if ((ThisCross) AND ((S2Reg^DReg)<16)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ if (DecideUnit(DReg,"LS"))
+ switch (ThisUnit)
+ BEGIN
+ case L1: case L2: __erg=CodeL(0x06,DReg,S1Reg,S2Reg); break;
+ case S1: case S2: __erg=CodeS(0x16,DReg,S1Reg,S2Reg); break;
+ default: WrError(20000);
+ END
+ END
+ break;
+ END
+ break;
+ case ModLReg:
+ AddLDest(DReg);
+ if (ChkUnit(DReg,L1,L2))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModImm+MModReg,True,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
+ if ((ThisCross) OR (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ __erg=CodeL(0x24,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModReg:
+ AddSrc(S1Reg);
+ if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ ThisCross=(IsCross(S1Reg)) OR (IsCross(S2Reg));
+ if (IsCross(S1Reg)) __erg=CodeL(0x37,DReg,S1Reg,S2Reg);
+ else __erg=CodeL(0x47,DReg,S1Reg,S2Reg);
+ END
+ break;
+ END
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeSUBU(Word Index)
+BEGIN
+ LongWord S1Reg,S2Reg,DReg;
+
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ if ((DecodeAdr(ArgStr[3],MModLReg,False,&DReg)) AND (ChkUnit(DReg,L1,L2)))
+ BEGIN
+ AddLDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModReg,False,&S1Reg))
+ BEGIN
+ AddSrc(S1Reg);
+ if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ ThisCross=IsCross(S1Reg) OR IsCross(S2Reg);
+ if (IsCross(S1Reg)) __erg=CodeL(0x3f,DReg,S1Reg,S2Reg);
+ else __erg=CodeL(0x2f,DReg,S1Reg,S2Reg);
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeSUBC(Word Index)
+BEGIN
+ LongWord DReg,S1Reg,S2Reg;
+
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ if ((DecodeAdr(ArgStr[3],MModReg,False,&DReg)) AND (ChkUnit(DReg,L1,L2)))
+ BEGIN
+ AddLDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModReg,False,&S1Reg))
+ BEGIN
+ if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg); SetCross(S2Reg);
+ __erg=CodeL(0x4b,DReg,S1Reg,S2Reg);
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeLinAdd(Word Index)
+BEGIN
+ LongWord DReg,S1Reg,S2Reg;
+ FixedOrder *POrder=LinAddOrders+Index;
+
+ if (ArgCnt!=3) WrError(1110);
+ else if (ThisCross) WrError(1350);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
+ if (ChkUnit(DReg,D1,D2))
+ BEGIN
+ AddDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModReg,True,&S2Reg))
+ if (IsCross(S2Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S1Reg);
+ __erg=CodeD(POrder->Code,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ __erg=CodeD(POrder->Code+2,DReg,S1Reg,S2Reg);
+ break;
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeADDK(Word Index)
+BEGIN
+ LongInt Value;
+ LongWord DReg;
+ Boolean OK;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[2],MModReg,False,&DReg))
+ if (ChkUnit(DReg,S1,S2))
+ BEGIN
+ AddDest(DReg);
+ Value=EvalIntExpression(ArgStr[1],SInt16,&OK);
+ if (OK)
+ BEGIN
+ ThisInst=0x50+(UnitFlag << 1)+((Value & 0xffff) << 7)+(DReg << 23);
+ __erg=True;
+ END
+ END
+ END
+END
+
+ static void DecodeADD2_SUB2(Word Index)
+BEGIN
+ LongWord DReg,S1Reg,S2Reg;
+ Boolean OK;
+
+ Index=(Index<<5)+1;
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
+ if (ChkUnit(DReg,S1,S2))
+ BEGIN
+ AddDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModReg,True,&S1Reg))
+ BEGIN
+ AddSrc(S1Reg);
+ if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ OK=True; AddSrc(S2Reg);
+ if (IsCross(S1Reg))
+ if (Index>1)
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else SwapReg(&S1Reg,&S2Reg);
+ if (OK)
+ BEGIN
+ SetCross(S2Reg);
+ __erg=CodeS(Index,DReg,S1Reg,S2Reg);
+ END
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeLogic(Word Index)
+BEGIN
+ LongWord S1Reg,S2Reg,DReg;
+ LongWord Code1,Code2;
+ Boolean OK,WithImm;
+
+ Code1=Lo(Index); Code2=Hi(Index);
+
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
+ BEGIN
+ AddDest(DReg);
+ DecodeAdr(ArgStr[1],MModImm+MModReg,True,&S1Reg); WithImm=False;
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ OK=DecodeAdr(ArgStr[2],MModReg,True,&S2Reg);
+ if (OK) AddSrc(S2Reg);
+ WithImm=True;
+ break;
+ case ModReg:
+ AddSrc(S1Reg);
+ OK=DecodeAdr(ArgStr[2],MModImm+MModReg,True,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ SwapReg(&S1Reg,&S2Reg); WithImm=True;
+ break;
+ case ModReg:
+ AddSrc(S2Reg); WithImm=False;
+ break;
+ default:
+ OK=False;
+ END
+ break;
+ default:
+ OK=False;
+ END
+ if (OK)
+ if (DecideUnit(DReg,"LS"))
+ if ((NOT WithImm) AND (IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
+ else if ((ThisCross) AND (NOT IsCross(S2Reg)) AND ((WithImm) OR (NOT IsCross(S1Reg)))) WrError(1350);
+ else
+ BEGIN
+ if ((NOT WithImm) AND (IsCross(S1Reg))) SwapReg(&S1Reg,&S2Reg);
+ SetCross(S2Reg);
+ switch (ThisUnit)
+ BEGIN
+ case L1: case L2:
+ __erg=CodeL(Code1-Ord(WithImm),DReg,S1Reg,S2Reg); break;
+ case S1: case S2:
+ __erg=CodeS(Code1-Ord(WithImm),DReg,S1Reg,S2Reg); break;
+ default:
+ WrError(20000);
+ END
+ END
+ END
+ END
+END
+
+ static Boolean DecodeInst(void)
+BEGIN
+ Boolean OK,erg;
+ LongInt Dist;
+ int z;
+ LongWord DReg,S1Reg,S2Reg,HReg;
+ LongWord Code1;
+ Boolean WithImm,HasSign;
+
+ erg=__erg=False;
+
+ /* ueber Tabelle: */
+
+ if (LookupInstTable(InstTable,OpPart)) return __erg;
+
+ /* jetzt geht's los... */
+
+ if ((Memo("CLR") OR (Memo("EXT")) OR (Memo("EXTU")) OR (Memo("SET"))))
+ BEGIN
+ if ((ArgCnt!=3) AND (ArgCnt!=4)) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[ArgCnt],MModReg,Memo("EXT"),&DReg))
+ if (ChkUnit(DReg,S1,S2))
+ BEGIN
+ AddDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModReg,Memo("EXT"),&S2Reg))
+ BEGIN
+ AddSrc(S2Reg);
+ if (ArgCnt==3)
+ BEGIN
+ if (DecodeAdr(ArgStr[2],MModReg,False,&S1Reg))
+ if (IsCross(S1Reg)) WrError(1350);
+ else if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ SetCross(S2Reg);
+ if (Memo("CLR")) erg=CodeS(0x3f,DReg,S1Reg,S2Reg);
+ else if (Memo("EXTU")) erg=CodeS(0x2b,DReg,S1Reg,S2Reg);
+ else if (Memo("SET")) erg=CodeS(0x3b,DReg,S1Reg,S2Reg);
+ else erg=CodeS(0x2f,DReg,S1Reg,S2Reg);
+ END
+ END
+ else if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ S1Reg=EvalIntExpression(ArgStr[2],UInt5,&OK);
+ if (OK)
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[3],UInt5,&OK);
+ if (OK)
+ BEGIN
+ ThisInst=(DReg << 23)+(S2Reg << 18)+(S1Reg << 13)+
+ (HReg << 8)+(UnitFlag << 1);
+ if (Memo("CLR")) ThisInst+=0xc8;
+ else if (Memo("SET")) ThisInst+=0x88;
+ else if (Memo("EXT")) ThisInst+=0x48;
+ else ThisInst+=0x08;
+ erg=True;
+ END
+ END
+ END
+ END
+ END
+ END
+ return erg;
+ END
+
+ for (z=0; z<CmpCnt; z++)
+ if (Memo(CmpOrders[z].Name))
+ BEGIN
+ WithImm=OpPart[strlen(OpPart)-1]!='U';
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[3],MModReg,False,&DReg))
+ if (ChkUnit(DReg,L1,L2))
+ BEGIN
+ AddDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModImm,WithImm,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddSrc(S1Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModLReg,WithImm,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
+ else if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
+ SetCross(S2Reg);
+ erg=CodeL(CmpOrders[z].Code+3,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModLReg:
+ if (IsCross(S2Reg)) WrError(1350);
+ else if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg); SetCross(S1Reg);
+ erg=CodeL(CmpOrders[z].Code+1,DReg,S1Reg,S2Reg);
+ END
+ break;
+ END
+ break;
+ case ModImm:
+ DecodeAdr(ArgStr[2],MModReg+MModLReg,WithImm,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg); SetCross(S2Reg);
+ erg=CodeL(CmpOrders[z].Code+2,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModLReg:
+ if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ erg=CodeL(CmpOrders[z].Code,DReg,S1Reg,S2Reg);
+ END
+ break;
+ END
+ break;
+ END
+ END
+ END
+ return erg;
+ END
+
+ if (Memo("LMBD"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[3],MModReg,False,&DReg))
+ if (ChkUnit(DReg,L1,L2))
+ BEGIN
+ AddDest(DReg);
+ if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ SetCross(S2Reg);
+ if (DecodeAdr(ArgStr[1],MModImm+MModReg,False,&S1Reg))
+ BEGIN
+ if (AdrMode==ModReg) AddSrc(S1Reg);
+ erg=CodeL(0x6a+Ord(AdrMode==ModImm),DReg,S1Reg,S2Reg);
+ END
+ END
+ END
+ END
+ return erg;
+ END
+
+ if (Memo("NORM"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[2],MModReg,False,&DReg))
+ if (ChkUnit(DReg,L1,L2))
+ BEGIN
+ AddDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModLReg,True,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ SetCross(S2Reg); AddSrc(S2Reg);
+ erg=CodeL(0x63,DReg,0,S2Reg);
+ END
+ break;
+ case ModLReg:
+ if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ erg=CodeL(0x60,DReg,0,S2Reg);
+ END
+ break;
+ END
+ END
+ END
+ return erg;
+ END
+
+ if (Memo("SADD"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ if ((DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg)) AND (ChkUnit(DReg,L1,L2)))
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddSrc(S1Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
+ SetCross(S2Reg);
+ erg=CodeL(0x13,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
+ else
+ BEGIN
+ SetCross(S1Reg);
+ erg=CodeL(0x12,DReg,S2Reg,S1Reg);
+ END
+ break;
+ END
+ break;
+ case ModImm:
+ if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ SetCross(S2Reg);
+ erg=CodeL(0x12,DReg,S1Reg,S2Reg);
+ END
+ break;
+ END
+ break;
+ case ModLReg:
+ AddLDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModLReg+MModImm,True,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddSrc(S1Reg);
+ if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg); SetCross(S1Reg);
+ erg=CodeL(0x31,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModLReg:
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S1Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg); SetCross(S2Reg);
+ erg=CodeL(0x31,DReg,S2Reg,S1Reg);
+ END
+ break;
+ case ModImm:
+ erg=CodeL(0x30,DReg,S2Reg,S1Reg);
+ break;
+ END
+ END
+ break;
+ case ModImm:
+ if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
+ if (IsCross(S2Reg)) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ erg=CodeL(0x30,DReg,S1Reg,S2Reg);
+ END
+ break;
+ END
+ break;
+ END
+ END
+ return erg;
+ END
+
+ if (Memo("SAT"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[2],MModReg,True,&DReg))
+ if (ChkUnit(DReg,L1,L2))
+ BEGIN
+ AddDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModLReg,True,&S2Reg))
+ if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg); erg=CodeL(0x40,DReg,0,S2Reg);
+ END
+ END
+ END
+ return erg;
+ END
+
+ if (Memo("MVC"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((ThisUnit!=NoUnit) AND (ThisUnit!=S2)) WrError(1350);
+ else
+ BEGIN
+ z=0; ThisUnit=S2; UnitFlag=1;
+ if (DecodeCtrlReg(ArgStr[1],&S2Reg,False)) z=2;
+ else if (DecodeCtrlReg(ArgStr[2],&DReg,True)) z=1;
+ else WrXError(1440,ArgStr[1]);
+ if (z>0)
+ BEGIN
+ if (DecodeAdr(ArgStr[z],MModReg,False,&S1Reg))
+ if ((ThisCross) AND ((z==2) OR (IsCross(S1Reg)))) WrError(1350);
+ else
+ BEGIN
+ if (z==1)
+ BEGIN
+ S2Reg=S1Reg;
+ AddSrc(S2Reg); SetCross(S2Reg);
+ END
+ else
+ BEGIN
+ DReg=S1Reg; AddDest(DReg);
+ END
+ erg=CodeS(0x0d+z,DReg,0,S2Reg);
+ END
+ END
+ END
+ return erg;
+ END
+
+ if ((Memo("MVK")) OR (Memo("MVKH")) OR (Memo("MVKLH")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[2],MModReg,True,&DReg))
+ if (ChkUnit(DReg,S1,S2))
+ BEGIN
+ S1Reg=EvalIntExpression(ArgStr[1],Memo("MVKLH")?Int16:Int32,&OK);
+ if (OK)
+ BEGIN
+ AddDest(DReg);
+ if (Memo("MVKH")) S1Reg=S1Reg >> 16;
+ ThisInst=(DReg << 23)+((S1Reg & 0xffff) << 7)+(UnitFlag << 1);
+ ThisInst+=Memo("MVK") ? 0x28 : 0x68;
+ erg=True;
+ END
+ END
+ END
+ return True;
+ END
+
+ if (Memo("SHL"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
+ if ((AdrMode!=ModNone) AND (ChkUnit(DReg,S1,S2)))
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModReg,True,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg);
+ SetCross(S2Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S1Reg);
+ erg=CodeS(0x33,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ erg=CodeS(0x32,DReg,S1Reg,S2Reg);
+ break;
+ END
+ END
+ break;
+ case ModLReg:
+ AddLDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModLReg,True,&S2Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg); SetCross(S2Reg);
+ DecodeAdr(ArgStr[2],MModImm+MModReg,False,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S1Reg);
+ erg=CodeS(0x13,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ erg=CodeS(0x12,DReg,S1Reg,S2Reg);
+ break;
+ END
+ END
+ break;
+ case ModLReg:
+ if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ DecodeAdr(ArgStr[2],MModImm+MModReg,False,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S1Reg);
+ erg=CodeS(0x31,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ erg=CodeS(0x30,DReg,S1Reg,S2Reg);
+ break;
+ END
+ END
+ break;
+ END
+ break;
+ END
+ END
+ return erg;
+ END
+
+ if ((Memo("SHR")) OR (Memo("SHRU")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ HasSign=Memo("SHR"); z=Ord(HasSign) << 4;
+ DecodeAdr(ArgStr[3],MModReg+MModLReg,HasSign,&DReg);
+ if ((AdrMode!=ModNone) AND (ChkUnit(DReg,S1,S2)))
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModReg,HasSign,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg); SetCross(S2Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S1Reg);
+ erg=CodeS(0x27+z,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ erg=CodeS(0x26+z,DReg,S1Reg,S2Reg);
+ break;
+ END
+ END
+ break;
+ case ModLReg:
+ AddLDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModLReg,HasSign,&S2Reg))
+ if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S1Reg);
+ erg=CodeS(0x25+z,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ erg=CodeS(0x24+z,DReg,S1Reg,S2Reg);
+ break;
+ END
+ END
+ break;
+ END
+ END
+ return erg;
+ END
+
+ if (Memo("SSHL"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
+ if (ChkUnit(DReg,S1,S2))
+ BEGIN
+ AddDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModReg,True,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg); SetCross(S2Reg);
+ DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (IsCross(S1Reg)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S1Reg);
+ erg=CodeS(0x23,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ erg=CodeS(0x22,DReg,S1Reg,S2Reg);
+ break;
+ END
+ END
+ END
+ END
+ return erg;
+ END
+
+ if (Memo("SSUB"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
+ if ((AdrMode!=ModNone) AND (ChkUnit(DReg,L1,L2)))
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddDest(DReg);
+ DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ AddSrc(S1Reg);
+ if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
+ else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
+ else if (IsCross(S1Reg))
+ BEGIN
+ ThisCross=True;
+ erg=CodeL(0x1f,DReg,S1Reg,S2Reg);
+ END
+ else
+ BEGIN
+ SetCross(S2Reg);
+ erg=CodeL(0x0f,DReg,S1Reg,S2Reg);
+ END
+ break;
+ case ModImm:
+ if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
+ if ((ThisCross) AND (NOT IsCross(S2Reg)<16)) WrError(1350);
+ else
+ BEGIN
+ AddSrc(S2Reg); SetCross(S2Reg);
+ erg=CodeL(0x0e,DReg,S1Reg,S2Reg);
+ END
+ break;
+ END
+ break;
+ case ModLReg:
+ AddLDest(DReg);
+ if (DecodeAdr(ArgStr[1],MModImm,True,&S1Reg))
+ BEGIN
+ if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
+ if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
+ else
+ BEGIN
+ AddLSrc(S2Reg);
+ erg=CodeL(0x2c,DReg,S1Reg,S2Reg);
+ END
+ END
+ break;
+ END
+ END;
+ return erg;
+ END
+
+ /* Spruenge */
+
+ /* Wie zum Henker unterscheiden sich B IRP und B NRP ???
+ Kann TI keine ordentlichen Handbuecher mehr schreiben ? */
+
+ if (Memo("B"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1350);
+ else if (ThisCross) WrError(1350);
+ else if ((ThisUnit!=NoUnit) AND (ThisUnit!=S1) AND (ThisUnit!=S2)) WrError(1350);
+ else
+ BEGIN
+ OK=True; S2Reg=0; WithImm=False; Code1=0;
+ if (strcasecmp(ArgStr[1],"IRP")==0) Code1=0x03;
+ else if (strcasecmp(ArgStr[1],"NRP")==0) Code1=0x03; /* !!! */
+ else if (DecodeReg(ArgStr[1],&S2Reg,&OK,False))
+ BEGIN
+ if (OK) WrError(1350); OK=NOT OK;
+ Code1=0x0d;
+ END
+ else WithImm=True;
+ if (OK)
+ if (WithImm)
+ BEGIN
+ if (ThisUnit==NoUnit)
+ ThisUnit=(UnitUsed(S1)) ? S2 : S1;
+ UnitFlag=Ord(ThisUnit==S2);
+ Dist=EvalIntExpression(ArgStr[1],Int32,&OK)-PacketAddr;
+ if (OK)
+ if ((Dist & 3)!=0) WrError(1325);
+ else if ((NOT SymbolQuestionable) AND ((Dist>0x3fffff) OR (Dist<-0x400000))) WrError(1370);
+ else
+ BEGIN
+ ThisInst=0x50+((Dist & 0x007ffffc) << 5)+(UnitFlag << 1);
+ erg=True;
+ END
+ END
+ else
+ BEGIN
+ if (ChkUnit(0x10,S1,S2)) erg=CodeS(Code1,0,0,S2Reg);
+ END
+ END
+ return erg;
+ END
+
+ WrXError(1200,OpPart);
+
+ return erg;
+END
+
+ static void ChkPacket(void)
+BEGIN
+ LongWord EndAddr,Mask;
+ LongInt z,z1,z2;
+ Integer RegReads[32];
+ char TestUnit[4];
+
+ /* nicht ueber 8er-Grenze */
+
+ EndAddr=PacketAddr+((ParCnt << 2)-1);
+ if ((PacketAddr >> 5)!=(EndAddr >> 5)) WrError(2000);
+
+ /* doppelte Units,Crosspaths,Adressierer,Zielregister */
+
+ for (z1=0; z1<ParCnt; z1++)
+ for (z2=z1+1; z2<ParCnt; z2++)
+ if ((ParRecs[z1].OpCode >> 28)==(ParRecs[z2].OpCode >> 28))
+ BEGIN
+ /* doppelte Units */
+ if ((ParRecs[z1].U!=NoUnit) AND (ParRecs[z1].U==ParRecs[z2].U))
+ WrXError(2001,UnitNames[ParRecs[z1].U]);
+
+ /* Crosspaths */
+ z=ParRecs[z1].CrossUsed & ParRecs[z2].CrossUsed;
+ if (z!=0)
+ BEGIN
+ *TestUnit=z+'0'; TestUnit[1]='X'; TestUnit[2]='\0';
+ WrXError(2001,TestUnit);
+ END
+
+ z=ParRecs[z1].AddrUsed & ParRecs[z2].AddrUsed;
+ /* Adressgeneratoren */
+ if ((z & 1)==1) WrXError(2001,"Addr. A");
+ if ((z & 2)==2) WrXError(2001,"Addr. B");
+ /* Hauptspeicherpfade */
+ if ((z & 4)==4) WrXError(2001,"LdSt. A");
+ if ((z & 8)==8) WrXError(2001,"LdSt. B");
+
+ /* ueberlappende Zielregister */
+ z=ParRecs[z1].DestMask & ParRecs[z2].DestMask;
+ if (z!=0) WrXError(2006,RegName(FindReg(z)));
+
+ if ((ParRecs[z1].U & 1)==(ParRecs[z2].U & 1))
+ BEGIN
+ TestUnit[0]=ParRecs[z1].U-NoUnit-1+'A';
+ TestUnit[1]='\0';
+
+ /* mehrere Long-Reads */
+ if ((ParRecs[z1].LongSrc) AND (ParRecs[z2].LongSrc))
+ WrXError(2002,TestUnit);
+
+ /* mehrere Long-Writes */
+ if ((ParRecs[z1].LongDest) AND (ParRecs[z2].LongDest))
+ WrXError(2003,TestUnit);
+
+ /* Long-Read mit Store */
+ if ((ParRecs[z1].StoreUsed) AND (ParRecs[z2].LongSrc))
+ WrXError(2004,TestUnit);
+ if ((ParRecs[z2].StoreUsed) AND (ParRecs[z1].LongSrc))
+ WrXError(2004,TestUnit);
+ END
+ END
+
+ for (z2=0; z2<32; RegReads[z2++]=0);
+ for (z1=0; z1<ParCnt; z1++)
+ BEGIN
+ Mask=1;
+ for (z2=0; z2<32; z2++)
+ BEGIN
+ if ((ParRecs[z1].SrcMask & Mask)!=0) RegReads[z2]++;
+ if ((ParRecs[z1].SrcMask2 & Mask)!=0) RegReads[z2]++;
+ Mask=Mask << 1;
+ END
+ END
+
+ /* Register mehr als 4mal gelesen */
+
+ for (z1=0; z1<32; z1++)
+ if (RegReads[z1]>4) WrXError(2005,RegName(z1));
+END
+
+ static void MakeCode_3206X(void)
+BEGIN
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if ((*OpPart=='\0') AND (*LabPart=='\0')) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* Flags zuruecksetzen */
+
+ ThisPar=False; Condition=0;
+
+ /* Optionen aus Label holen */
+
+ if (*LabPart!='\0')
+ if ((strcmp(LabPart,"||")==0) OR (*LabPart=='['))
+ if (NOT CheckOpt(LabPart)) return;
+
+ /* eventuell falsche Mnemonics verwerten */
+
+ if (strcmp(OpPart,"||")==0)
+ if (NOT ReiterateOpPart()) return;
+ if (*OpPart=='[')
+ if (NOT ReiterateOpPart()) return;
+
+ if (Memo("")) return;
+
+ /* Attribut auswerten */
+
+ ThisUnit=NoUnit; ThisCross=False;
+ if (*AttrPart!='\0')
+ BEGIN
+ if (toupper(AttrPart[strlen(AttrPart)-1])=='X')
+ BEGIN
+ ThisCross=True;
+ AttrPart[strlen(AttrPart)-1]='\0';
+ END
+ if (*AttrPart=='\0') ThisUnit=NoUnit;
+ else
+ for (; ThisUnit!=LastUnit; ThisUnit++)
+ if (strcasecmp(AttrPart,UnitNames[ThisUnit])==0) break;
+ if (ThisUnit==LastUnit)
+ BEGIN
+ WrError(1107); return;
+ END
+ if (((ThisUnit==D1) OR (ThisUnit==D2)) AND (ThisCross))
+ BEGIN
+ WrError(1350); return;
+ END
+ END
+
+ /* falls nicht parallel, vorherigen Stack durchpruefen und verwerfen */
+
+ if ((NOT ThisPar) AND (ParCnt>0))
+ BEGIN
+ ChkPacket();
+ ParCnt=0; PacketAddr=EProgCounter();
+ END
+
+ /* dekodieren */
+
+ ThisSrc=0; ThisSrc2=0; ThisDest=0;
+ ThisAddr=0; ThisStore=False; ThisLong=0;
+ if (NOT DecodeInst()) return;
+
+ /* einsortieren */
+
+ ParRecs[ParCnt].OpCode=(Condition << 28)+ThisInst;
+ ParRecs[ParCnt].U=ThisUnit;
+ if (ThisCross)
+ switch (ThisUnit)
+ BEGIN
+ case L1: case S1: case M1: case D1: ParRecs[ParCnt].CrossUsed=1; break;
+ default: ParRecs[ParCnt].CrossUsed=2;
+ END
+ else ParRecs[ParCnt].CrossUsed=0;
+ ParRecs[ParCnt].AddrUsed=ThisAddr;
+ ParRecs[ParCnt].SrcMask=ThisSrc;
+ ParRecs[ParCnt].SrcMask2=ThisSrc2;
+ ParRecs[ParCnt].DestMask=ThisDest;
+ ParRecs[ParCnt].LongSrc=(ThisLong & 1)==1;
+ ParRecs[ParCnt].LongDest=(ThisLong & 2)==2;
+ ParRecs[ParCnt].StoreUsed=ThisStore;
+ ParCnt++;
+
+ /* wenn mehr als eine Instruktion, Ressourcenkonflikte abklopfen und
+ vorherige Instruktion zuruecknehmen */
+
+ if (ParCnt>1)
+ BEGIN
+ RetractWords(4);
+ DAsmCode[CodeLen >> 2]=ParRecs[ParCnt-2].OpCode | 1;
+ CodeLen+=4;
+ END
+
+ /* aktuelle Instruktion auswerfen: fuer letzte kein Parallelflag setzen */
+
+ DAsmCode[CodeLen >> 2]=ParRecs[ParCnt-1].OpCode;
+ CodeLen+=4;
+END
+
+/*-------------------------------------------------------------------------*/
+
+static int InstrZ;
+
+
+ static void AddLinAdd(char *NName, LongInt NCode)
+BEGIN
+ if (InstrZ>=LinAddCnt) exit(255);
+ LinAddOrders[InstrZ].Name=NName;
+ LinAddOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeLinAdd);
+END
+
+ static void AddCmp(char *NName, LongInt NCode)
+BEGIN
+ if (InstrZ>=CmpCnt) exit(255);
+ CmpOrders[InstrZ].Name=NName;
+ CmpOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddMem(char *NName, LongInt NCode, LongInt NScale)
+BEGIN
+ if (InstrZ>=MemCnt) exit(255);
+ MemOrders[InstrZ].Name=NName;
+ MemOrders[InstrZ].Code=NCode;
+ MemOrders[InstrZ].Scale=NScale;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeMemO);
+END
+
+ static void AddMul(char *NName, LongInt NCode,
+ Boolean NDSign,Boolean NSSign1,Boolean NSSign2, Boolean NMay)
+BEGIN
+ if (InstrZ>=MulCnt) exit(255);
+ MulOrders[InstrZ].Name=NName;
+ MulOrders[InstrZ].Code=NCode;
+ MulOrders[InstrZ].DSign=NDSign;
+ MulOrders[InstrZ].SSign1=NSSign1;
+ MulOrders[InstrZ].SSign2=NSSign2;
+ MulOrders[InstrZ].MayImm=NMay;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeMul);
+END
+
+ static void AddCtrl(char *NName, LongInt NCode,
+ Boolean NWr, Boolean NRd)
+BEGIN
+ if (InstrZ>=CtrlCnt) exit(255);
+ CtrlRegs[InstrZ].Name=NName;
+ CtrlRegs[InstrZ].Code=NCode;
+ CtrlRegs[InstrZ].Wr=NWr;
+ CtrlRegs[InstrZ++].Rd=NRd;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(203);
+
+ AddInstTable(InstTable,"IDLE",0,DecodeIDLE);
+ AddInstTable(InstTable,"NOP",0,DecodeNOP);
+ AddInstTable(InstTable,"STP",0,DecodeSTP);
+ AddInstTable(InstTable,"ABS",0,DecodeABS);
+ AddInstTable(InstTable,"ADD",0,DecodeADD);
+ AddInstTable(InstTable,"ADDU",0,DecodeADDU);
+ AddInstTable(InstTable,"SUB",0,DecodeSUB);
+ AddInstTable(InstTable,"SUBU",0,DecodeSUBU);
+ AddInstTable(InstTable,"SUBC",0,DecodeSUBC);
+ AddInstTable(InstTable,"ADDK",0,DecodeADDK);
+ AddInstTable(InstTable,"ADD2",0,DecodeADD2_SUB2);
+ AddInstTable(InstTable,"SUB2",1,DecodeADD2_SUB2);
+ AddInstTable(InstTable,"AND",0x1f79,DecodeLogic);
+ AddInstTable(InstTable,"OR",0x1b7f,DecodeLogic);
+ AddInstTable(InstTable,"XOR",0x0b6f,DecodeLogic);
+
+ LinAddOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LinAddCnt); InstrZ=0;
+ AddLinAdd("ADDAB",0x30); AddLinAdd("ADDAH",0x34); AddLinAdd("ADDAW",0x38);
+ AddLinAdd("SUBAB",0x31); AddLinAdd("SUBAH",0x35); AddLinAdd("SUBAW",0x39);
+
+ CmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*CmpCnt); InstrZ=0;
+ AddCmp("CMPEQ",0x50); AddCmp("CMPGT",0x44); AddCmp("CMPGTU",0x4c);
+ AddCmp("CMPLT",0x54); AddCmp("CMPLTU",0x5c);
+
+ MemOrders=(MemOrder *) malloc(sizeof(MemOrder)*MemCnt); InstrZ=0;
+ AddMem("LDB",2,1); AddMem("LDH",4,2); AddMem("LDW",6,4);
+ AddMem("LDBU",1,1); AddMem("LDHU",0,2); AddMem("STB",3,1);
+ AddMem("STH",5,2); AddMem("STW",7,4);
+
+ MulOrders=(MulOrder *) malloc(sizeof(MulOrder)*MulCnt); InstrZ=0;
+ AddMul("MPY" ,0x19,True ,True ,True ,True );
+ AddMul("MPYU" ,0x1f,False,False,False,False);
+ AddMul("MPYUS" ,0x1d,True ,False,True ,False);
+ AddMul("MPYSU" ,0x1b,True ,True ,False,True );
+ AddMul("MPYH" ,0x01,True ,True ,True ,False);
+ AddMul("MPYHU" ,0x07,False,False,False,False);
+ AddMul("MPYHUS" ,0x05,True ,False,True ,False);
+ AddMul("MPYHSU" ,0x03,True ,True ,False,False);
+ AddMul("MPYHL" ,0x09,True ,True ,True ,False);
+ AddMul("MPYHLU" ,0x0f,False,False,False,False);
+ AddMul("MPYHULS",0x0d,True ,False,True ,False);
+ AddMul("MPYHSLU",0x0b,True ,True ,False,False);
+ AddMul("MPYLH" ,0x11,True ,True ,True ,False);
+ AddMul("MPYLHU" ,0x17,False,False,False,False);
+ AddMul("MPYLUHS",0x15,True ,False,True ,False);
+ AddMul("MPYLSHU",0x13,True ,True ,False,False);
+ AddMul("SMPY" ,0x1a,True ,True ,True ,False);
+ AddMul("SMPYHL" ,0x0a,True ,True ,True ,False);
+ AddMul("SMPYLH" ,0x12,True ,True ,True ,False);
+ AddMul("SMPYH" ,0x02,True ,True ,True ,False);
+
+ CtrlRegs=(CtrlReg *) malloc(sizeof(CtrlReg)*CtrlCnt); InstrZ=0;
+ AddCtrl("AMR" , 0,True ,True );
+ AddCtrl("CSR" , 1,True ,True );
+ AddCtrl("IFR" , 2,False,True );
+ AddCtrl("ISR" , 2,True ,False);
+ AddCtrl("ICR" , 3,True ,False);
+ AddCtrl("IER" , 4,True ,True );
+ AddCtrl("ISTP" , 5,True ,True );
+ AddCtrl("IRP" , 6,True ,True );
+ AddCtrl("NRP" , 7,True ,True );
+ AddCtrl("IN" , 8,False,True );
+ AddCtrl("OUT" , 9,True ,True );
+ AddCtrl("PCE1" ,16,False,True );
+ AddCtrl("PDATA_O",15,True ,True );
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(LinAddOrders);
+ free(CmpOrders);
+ free(MemOrders);
+ free(MulOrders);
+ free(CtrlRegs);
+END
+
+/*------------------------------------------------------------------------*/
+
+ static Boolean IsDef_3206X(void)
+BEGIN
+ return (strcmp(LabPart,"||")==0) OR (*LabPart=='[');
+END
+
+ static void SwitchFrom_3206X(void)
+BEGIN
+ if (ParCnt>1) ChkPacket();
+ DeinitFields();
+END
+
+ static void SwitchTo_3206X(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x47; NOPCode=0x00000000;
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+ SetIsOccupied=True;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=4; SegInits[SegCode]=0;
+#ifdef __STDC__
+ SegLimits[SegCode] = 0xfffffffful;
+#else
+ SegLimits[SegCode] = 0xffffffffl;
+#endif
+
+ MakeCode=MakeCode_3206X; IsDef=IsDef_3206X;
+ SwitchFrom=SwitchFrom_3206X; InitFields();
+
+ ParCnt=0; PacketAddr=0;
+END
+
+ void code3206x_init(void)
+BEGIN
+ CPU32060=AddCPU("32060",SwitchTo_3206X);
+END
diff --git a/code3206x.h b/code3206x.h
new file mode 100644
index 0000000..f9e65ee
--- /dev/null
+++ b/code3206x.h
@@ -0,0 +1,12 @@
+/* code3206x.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS320C6x-Familie */
+/* */
+/* Historie: 24.2.1998 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code3206x_init(void);
+
diff --git a/code370.c b/code370.c
new file mode 100644
index 0000000..bafe0bd
--- /dev/null
+++ b/code370.c
@@ -0,0 +1,1117 @@
+/* code370.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 370-Familie */
+/* */
+/* Historie: 10.12.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+
+#define ModNone (-1)
+#define ModAccA 0
+#define MModAccA (1 << ModAccA) /* A */
+#define ModAccB 1
+#define MModAccB (1 << ModAccB) /* B */
+#define ModReg 2
+#define MModReg (1 << ModReg) /* Rn */
+#define ModPort 3
+#define MModPort (1 << ModPort) /* Pn */
+#define ModAbs 4
+#define MModAbs (1 << ModAbs) /* nnnn */
+#define ModBRel 5
+#define MModBRel (1 << ModBRel) /* nnnn(B) */
+#define ModSPRel 6
+#define MModSPRel (1 << ModSPRel) /* nn(SP) */
+#define ModIReg 7
+#define MModIReg (1 << ModIReg) /* @Rn */
+#define ModRegRel 8
+#define MModRegRel (1 << ModRegRel) /* nn(Rn) */
+#define ModImm 9
+#define MModImm (1 << ModImm) /* #nn */
+#define ModImmBRel 10
+#define MModImmBRel (1 << ModImmBRel) /* #nnnn(B) */
+#define ModImmRegRel 11
+#define MModImmRegRel (1 << ModImmRegRel) /* #nn(Rm) */
+
+#define FixedOrderCount 12
+#define Rel8OrderCount 18
+#define ALU1OrderCount 7
+#define ALU2OrderCount 5
+#define JmpOrderCount 4
+#define ABRegOrderCount 14
+#define BitOrderCount 5
+
+
+static CPUVar CPU37010,CPU37020,CPU37030,CPU37040,CPU37050;
+
+static Byte OpSize;
+static ShortInt AdrType;
+static Byte AdrVals[2];
+static Boolean AddrRel;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *Rel8Orders;
+static FixedOrder *ALU1Orders;
+static FixedOrder *ALU2Orders;
+static FixedOrder *JmpOrders;
+static FixedOrder *ABRegOrders;
+static FixedOrder *BitOrders;
+
+/****************************************************************************/
+
+ static void InitFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitRel8(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Rel8OrderCount) exit(255);
+ Rel8Orders[InstrZ].Name=NName;
+ Rel8Orders[InstrZ++].Code=NCode;
+END
+
+ static void InitALU1(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ALU1OrderCount) exit(255);
+ ALU1Orders[InstrZ].Name=NName;
+ ALU1Orders[InstrZ++].Code=NCode;
+END
+
+ static void InitALU2(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ALU2OrderCount) exit(255);
+ ALU2Orders[InstrZ].Name=NName;
+ ALU2Orders[InstrZ++].Code=NCode;
+END
+
+ static void InitJmp(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=JmpOrderCount) exit(255);
+ JmpOrders[InstrZ].Name=NName;
+ JmpOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitABReg(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ABRegOrderCount) exit(255);
+ ABRegOrders[InstrZ].Name=NName;
+ ABRegOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=BitOrderCount) exit(255);
+ BitOrders[InstrZ].Name=NName;
+ BitOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ InitFixed("CLRC" ,0x00b0); InitFixed("DINT" ,0xf000);
+ InitFixed("EINT" ,0xf00c); InitFixed("EINTH",0xf004);
+ InitFixed("EINTL",0xf008); InitFixed("IDLE" ,0x00f6);
+ InitFixed("LDSP" ,0x00fd); InitFixed("NOP" ,0x00ff);
+ InitFixed("RTI" ,0x00fa); InitFixed("RTS" ,0x00f9);
+ InitFixed("SETC" ,0x00f8); InitFixed("STSP" ,0x00fe);
+
+ Rel8Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Rel8OrderCount); InstrZ=0;
+ InitRel8("JMP",0x00); InitRel8("JC" ,0x03); InitRel8("JEQ",0x02);
+ InitRel8("JG" ,0x0e); InitRel8("JGE",0x0d); InitRel8("JHS",0x0b);
+ InitRel8("JL" ,0x09); InitRel8("JLE",0x0a); InitRel8("JLO",0x0f);
+ InitRel8("JN" ,0x01); InitRel8("JNC",0x07); InitRel8("JNE",0x06);
+ InitRel8("JNV",0x0c); InitRel8("JNZ",0x06); InitRel8("JP" ,0x04);
+ InitRel8("JPZ",0x05); InitRel8("JV" ,0x08); InitRel8("JZ" ,0x02);
+
+ ALU1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU1OrderCount); InstrZ=0;
+ InitALU1("ADC", 9); InitALU1("ADD", 8);
+ InitALU1("DAC",14); InitALU1("DSB",15);
+ InitALU1("SBB",11); InitALU1("SUB",10); InitALU1("MPY",12);
+
+ ALU2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU2OrderCount); InstrZ=0;
+ InitALU2("AND" , 3); InitALU2("BTJO", 6);
+ InitALU2("BTJZ", 7); InitALU2("OR" , 4); InitALU2("XOR", 5);
+
+ JmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*JmpOrderCount); InstrZ=0;
+ InitJmp("BR" ,12); InitJmp("CALL" ,14);
+ InitJmp("JMPL", 9); InitJmp("CALLR",15);
+
+ ABRegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ABRegOrderCount); InstrZ=0;
+ InitABReg("CLR" , 5); InitABReg("COMPL",11); InitABReg("DEC" , 2);
+ InitABReg("INC" , 3); InitABReg("INV" , 4); InitABReg("POP" , 9);
+ InitABReg("PUSH" , 8); InitABReg("RL" ,14); InitABReg("RLC" ,15);
+ InitABReg("RR" ,12); InitABReg("RRC" ,13); InitABReg("SWAP" , 7);
+ InitABReg("XCHB" , 6); InitABReg("DJNZ" ,10);
+
+ BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCount); InstrZ=0;
+ InitBit("CMPBIT", 5); InitBit("JBIT0" , 7); InitBit("JBIT1" , 6);
+ InitBit("SBIT0" , 3); InitBit("SBIT1" , 4);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(Rel8Orders);
+ free(ALU1Orders);
+ free(ALU2Orders);
+ free(JmpOrders);
+ free(ABRegOrders);
+ free(BitOrders);
+END
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrType!=-1) AND ((Mask & (1 << AdrType))==0))
+ BEGIN
+ WrError(1350); AdrType=ModNone; AdrCnt=0;
+ END
+END
+
+ static char *HasDisp(char *Asc)
+BEGIN
+ char *p;
+ int Lev;
+
+ if (Asc[strlen(Asc)-1]==')')
+ BEGIN
+ p=Asc+strlen(Asc)-2; Lev=0;
+ while ((p>=Asc) AND (Lev!=-1))
+ BEGIN
+ switch (*p)
+ BEGIN
+ case '(': Lev--; break;
+ case ')': Lev++; break;
+ END
+ if (Lev!=-1) p--;
+ END
+ if (p<Asc)
+ BEGIN
+ WrXError(1300,Asc); return Nil;
+ END
+ END
+ else p=Nil;
+
+ return p;
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ Integer HVal;
+ char *p;
+ Boolean OK;
+
+ AdrType=ModNone; AdrCnt=0;
+
+ if (strcasecmp(Asc,"A")==0)
+ BEGIN
+ if ((Mask & MModAccA)!=0) AdrType=ModAccA;
+ else if ((Mask & MModReg)!=0)
+ BEGIN
+ AdrCnt=1; AdrVals[0]=0; AdrType=ModReg;
+ END
+ else
+ BEGIN
+ AdrCnt=2; AdrVals[0]=0; AdrVals[1]=0; AdrType=ModAbs;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if (strcasecmp(Asc,"B")==0)
+ BEGIN
+ if ((Mask & MModAccB)!=0) AdrType=ModAccB;
+ else if ((Mask & MModReg)!=0)
+ BEGIN
+ AdrCnt=1; AdrVals[0]=1; AdrType=ModReg;
+ END
+ else
+ BEGIN
+ AdrCnt=2; AdrVals[0]=0; AdrVals[1]=1; AdrType=ModAbs;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if (*Asc=='#')
+ BEGIN
+ strcpy(Asc,Asc+1);
+ p=HasDisp(Asc);
+ if (p==Nil)
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc,Int8,&OK);
+ break;
+ case 1:
+ HVal=EvalIntExpression(Asc,Int16,&OK);
+ AdrVals[0]=Hi(HVal); AdrVals[1]=Lo(HVal);
+ break;
+ END
+ if (OK)
+ BEGIN
+ AdrCnt=1+OpSize; AdrType=ModImm;
+ END
+ END
+ else
+ BEGIN
+ *p='\0'; FirstPassUnknown=False;
+ HVal=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ *p='(';
+ if (strcasecmp(p,"(B)")==0)
+ BEGIN
+ AdrVals[0]=Hi(HVal); AdrVals[1]=Lo(HVal);
+ AdrCnt=2; AdrType=ModImmBRel;
+ END
+ else
+ BEGIN
+ if (FirstPassUnknown) HVal&=127;
+ if (ChkRange(HVal,-128,127))
+ BEGIN
+ AdrVals[0]=HVal & 0xff; AdrCnt=1;
+ AdrVals[1]=EvalIntExpression(Asc,UInt8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=2; AdrType=ModImmRegRel;
+ END
+ END
+ END
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if (*Asc=='@')
+ BEGIN
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrType=ModIReg;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ p=HasDisp(Asc);
+
+ if (p==Nil)
+ BEGIN
+ HVal=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ if (((Mask & MModReg)!=0) AND (Hi(HVal)==0))
+ BEGIN
+ AdrVals[0]=Lo(HVal); AdrCnt=1; AdrType=ModReg;
+ END
+ else if (((Mask & MModPort)!=0) AND (Hi(HVal)==0x10))
+ BEGIN
+ AdrVals[0]=Lo(HVal); AdrCnt=1; AdrType=ModPort;
+ END
+ else
+ BEGIN
+ if (AddrRel) HVal-=EProgCounter()+3;
+ AdrVals[0]=Hi(HVal); AdrVals[1]=Lo(HVal); AdrCnt=2;
+ AdrType=ModAbs;
+ END
+ ChkAdr(Mask); return;
+ END
+ else
+ BEGIN
+ *(p++)='\0';
+ FirstPassUnknown=False;
+ HVal=EvalIntExpression(Asc,Int16,&OK);
+ if (FirstPassUnknown) HVal&=0x7f;
+ if (OK)
+ BEGIN
+ p[strlen(p)-1]='\0';
+ if (strcasecmp(p,"B")==0)
+ BEGIN
+ if (AddrRel) HVal-=EProgCounter()+3;
+ AdrVals[0]=Hi(HVal); AdrVals[1]=Lo(HVal); AdrCnt=2;
+ AdrType=ModBRel;
+ END
+ else if (strcasecmp(p,"SP")==0)
+ BEGIN
+ if (AddrRel) HVal-=EProgCounter()+3;
+ if (HVal>127) WrError(1320);
+ else if (HVal<-128) WrError(1315);
+ else
+ BEGIN
+ AdrVals[0]=HVal & 0xff; AdrCnt=1; AdrType=ModSPRel;
+ END
+ END
+ else
+ if (HVal>127) WrError(1320);
+ else if (HVal<-128) WrError(1315);
+ else
+ BEGIN
+ AdrVals[0]=HVal & 0xff;
+ AdrVals[1]=EvalIntExpression(p,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=2; AdrType=ModRegRel;
+ END
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Boolean OK;
+ Byte Bit;
+ Word Adr;
+
+ if (Memo("DBIT"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Bit=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ if ((strcasecmp(ArgStr[2],"A")==0) OR (strcasecmp(ArgStr[2],"B")==0))
+ BEGIN
+ Adr=(*ArgStr[2])-'A'; OK=True;
+ END
+ else Adr=EvalIntExpression(ArgStr[2],Int16,&OK);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ PushLocHandle(-1);
+ EnterIntSymbol(LabPart,(((LongInt)Bit) << 16)+Adr,SegNone,False);
+ sprintf(ListLine,"=%s:%c",HexString(Adr,0),Bit+'0');
+ PopLocHandle();
+ END
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void PutCode(Word Code)
+BEGIN
+ if (Hi(Code)==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=Code;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=Hi(Code); BAsmCode[1]=Lo(Code);
+ END
+END
+
+ static void MakeCode_370(void)
+BEGIN
+ int z;
+ Integer AdrInt;
+ LongInt Bit;
+ Boolean OK,Rela;
+
+ CodeLen=0; DontPrint=False; OpSize=0; AddrRel=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(True)) return;
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else PutCode(FixedOrders[z].Code);
+ return;
+ END
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModAccB+MModReg+MModPort+MModAbs+MModIReg+MModBRel
+ +MModSPRel+MModRegRel+MModAccA);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ DecodeAdr(ArgStr[1],MModReg+MModAbs+MModIReg+MModBRel+MModRegRel
+ +MModSPRel+MModAccB+MModPort+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x12; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0x8a; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0x9a; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModBRel:
+ BAsmCode[0]=0xaa; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ break;
+ case ModRegRel:
+ BAsmCode[0]=0xf4; BAsmCode[1]=0xea;
+ memcpy(BAsmCode+2,AdrVals,2); CodeLen=4;
+ break;
+ case ModSPRel:
+ BAsmCode[0]=0xf1; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0x62; CodeLen=1;
+ break;
+ case ModPort:
+ BAsmCode[0]=0x80; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x22; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModAccB:
+ DecodeAdr(ArgStr[1],MModAccA+MModReg+MModPort+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0xc0; CodeLen=1;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x32; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModPort:
+ BAsmCode[0]=0x91; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x52; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModReg:
+ BAsmCode[1]=BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB+MModReg+MModPort+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0xd0; CodeLen=2;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0xd1; CodeLen=2;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x42; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModPort:
+ BAsmCode[0]=0xa2; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x72; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ case ModPort:
+ BAsmCode[1]=BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB+MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0x21; CodeLen=2;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0x51; CodeLen=2;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x71; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0xf7; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ case ModAbs:
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[1],MModAccA);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x8b; CodeLen=3;
+ END
+ break;
+ case ModIReg:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModAccA);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x9b; CodeLen=2;
+ END
+ break;
+ case ModBRel:
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[1],MModAccA);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xab; CodeLen=3;
+ END
+ break;
+ case ModSPRel:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModAccA);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xf2; CodeLen=2;
+ END
+ break;
+ case ModRegRel:
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[1],MModAccA);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xf4; BAsmCode[1]=0xeb; CodeLen=4;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOVW"))
+ BEGIN
+ OpSize=1;
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrType!=ModNone)
+ BEGIN
+ z=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg+MModImm+MModImmBRel+MModImmRegRel);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x98; BAsmCode[1]=AdrVals[0]; BAsmCode[2]=z;
+ CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x88; memcpy(BAsmCode+1,AdrVals,2);
+ BAsmCode[3]=z; CodeLen=4;
+ break;
+ case ModImmBRel:
+ BAsmCode[0]=0xa8; memcpy(BAsmCode+1,AdrVals,2);
+ BAsmCode[3]=z; CodeLen=4;
+ break;
+ case ModImmRegRel:
+ BAsmCode[0]=0xf4; BAsmCode[1]=0xe8;
+ memcpy(BAsmCode+2,AdrVals,2); BAsmCode[4]=z;
+ CodeLen=5;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Rel8OrderCount; z++)
+ if (Memo(Rel8Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt>127) OR (AdrInt<-128))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=Rel8Orders[z].Code; BAsmCode[1]=AdrInt & 0xff;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CMP"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModAccA+MModAccB+MModReg);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ DecodeAdr(ArgStr[1],MModAbs+MModIReg+MModBRel+MModRegRel+MModSPRel+MModAccB+MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ BAsmCode[0]=0x8d; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0x9d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModBRel:
+ BAsmCode[0]=0xad; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ break;
+ case ModRegRel:
+ BAsmCode[0]=0xf4; BAsmCode[1]=0xed;
+ memcpy(BAsmCode+2,AdrVals,2); CodeLen=4;
+ break;
+ case ModSPRel:
+ BAsmCode[0]=0xf3; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0x6d; CodeLen=1;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x1d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x2d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModAccB:
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x3d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x5d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModReg:
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x4d; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x7d; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ALU1OrderCount; z++)
+ if (Memo(ALU1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModAccA+MModAccB+MModReg);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ DecodeAdr(ArgStr[1],MModAccB+MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccB:
+ CodeLen=1; BAsmCode[0]=0x60+ALU1Orders[z].Code;
+ break;
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0x10+ALU1Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x20+ALU1Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModAccB:
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0x30+ALU1Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x50+ALU1Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModReg:
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=3; BAsmCode[0]=0x40+ALU1Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ break;
+ case ModImm:
+ CodeLen=3; BAsmCode[0]=0x70+ALU1Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ALU2OrderCount; z++)
+ if (Memo(ALU2Orders[z].Name))
+ BEGIN
+ Rela=((Memo("BTJO")) OR (Memo("BTJZ")));
+ if (((Rela) AND (ArgCnt!=3))
+ OR ((NOT Rela) AND (ArgCnt!=2))) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModAccA+MModAccB+MModReg+MModPort);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ DecodeAdr(ArgStr[1],MModAccB+MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccB:
+ BAsmCode[0]=0x60+ALU2Orders[z].Code; CodeLen=1;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x10+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x20+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModAccB:
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x30+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x50+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModReg:
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x40+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x70+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ case ModPort:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0x80+ALU2Orders[z].Code; CodeLen=2;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0x90+ALU2Orders[z].Code; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0xa0+ALU2Orders[z].Code; BAsmCode[2]=BAsmCode[1];
+ BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ END
+ if ((CodeLen!=0) AND (Rela))
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[3],UInt16,&OK)-(EProgCounter()+CodeLen+1);
+ if (NOT OK) CodeLen=0;
+ else if ((NOT SymbolQuestionable) AND ((AdrInt>127) OR (AdrInt<-128)))
+ BEGIN
+ WrError(1370); CodeLen=0;
+ END
+ else BAsmCode[CodeLen++]=AdrInt & 0xff;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<JmpOrderCount; z++)
+ if (Memo(JmpOrders[z].Name))
+ BEGIN
+ AddrRel=(Memo("CALLR") OR Memo("JMPL"));
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAbs+MModIReg+MModBRel+MModRegRel);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ CodeLen=3; BAsmCode[0]=0x80+JmpOrders[z].Code; memcpy(BAsmCode+1,AdrVals,2);
+ break;
+ case ModIReg:
+ CodeLen=2; BAsmCode[0]=0x90+JmpOrders[z].Code; BAsmCode[1]=AdrVals[0];
+ break;
+ case ModBRel:
+ CodeLen=3; BAsmCode[0]=0xa0+JmpOrders[z].Code; memcpy(BAsmCode+1,AdrVals,2);
+ break;
+ case ModRegRel:
+ CodeLen=4; BAsmCode[0]=0xf4; BAsmCode[1]=0xe0+JmpOrders[z].Code;
+ memcpy(BAsmCode+2,AdrVals,2);
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ABRegOrderCount; z++)
+ if (Memo(ABRegOrders[z].Name))
+ BEGIN
+ if (((NOT Memo("DJNZ")) AND (ArgCnt!=1))
+ OR (( Memo("DJNZ")) AND (ArgCnt!=2))) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"ST")==0)
+ BEGIN
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ BAsmCode[0]=0xf3+ABRegOrders[z].Code; CodeLen=1;
+ END
+ else WrError(1350);
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB+MModReg);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0xb0+ABRegOrders[z].Code; CodeLen=1;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0xc0+ABRegOrders[z].Code; CodeLen=1;
+ break;
+ case ModReg:
+ BAsmCode[0]=0xd0+ABRegOrders[z].Code; BAsmCode[CodeLen+1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ if ((Memo("DJNZ")) AND (CodeLen!=0))
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int16,&OK)-(EProgCounter()+CodeLen+1);
+ if (NOT OK) CodeLen=0;
+ else if ((NOT FirstPassUnknown) AND ((AdrInt>127) OR (AdrInt<-128)))
+ BEGIN
+ WrError(1370); CodeLen=0;
+ END
+ else BAsmCode[CodeLen++]=AdrInt & 0xff;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitOrderCount; z++)
+ if (Memo(BitOrders[z].Name))
+ BEGIN
+ Rela=((Memo("JBIT0")) OR (Memo("JBIT1")));
+ if (((Rela) AND (ArgCnt!=2))
+ OR ((NOT Rela) AND (ArgCnt!=1))) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Bit=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (OK)
+ BEGIN
+ if (FirstPassUnknown) Bit&=0x000710ff;
+ BAsmCode[1]=1 << ((Bit >> 16) & 7);
+ BAsmCode[2]=Lo(Bit);
+ switch (Hi(Bit))
+ BEGIN
+ case 0:
+ BAsmCode[0]=0x70+BitOrders[z].Code; CodeLen=3;
+ break;
+ case 16:
+ BAsmCode[0]=0xa0+BitOrders[z].Code; CodeLen=3;
+ break;
+ default:
+ WrError(1350);
+ END
+ if ((CodeLen!=0) AND (Rela))
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int16,&OK)-(EProgCounter()+CodeLen+1);
+ if (NOT OK) CodeLen=0;
+ else if ((NOT FirstPassUnknown) AND ((AdrInt>127) OR (AdrInt<-128)))
+ BEGIN
+ WrError(1370); CodeLen=0;
+ END
+ else BAsmCode[CodeLen++]=AdrInt & 0xff;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("DIV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModAccA);
+ if (AdrType!=ModNone)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xf4; BAsmCode[1]=0xf8;
+ BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("INCW"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x70; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDST"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xf0;
+ BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if (Memo("TRAP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=EvalIntExpression(ArgStr[1],Int4,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xef-BAsmCode[0]; CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("TST"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0xb0; CodeLen=1;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0xc6; CodeLen=1;
+ break;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_370(void)
+BEGIN
+ return (Memo("DBIT"));
+END
+
+ static void InternSymbol_370(char *Asc, TempResult*Erg)
+BEGIN
+ Boolean err;
+ String h;
+
+ Erg->Typ=TempNone;
+ if ((strlen(Asc)<2) OR ((toupper(*Asc)!='R') AND (toupper(*Asc)!='P'))) return;
+
+ strcpy(h,Asc+1);
+ if ((*h=='0') AND (strlen(h)>1)) *h='$';
+ Erg->Contents.Int=ConstLongInt(h,&err);
+ if ((NOT err) OR (Erg->Contents.Int<0) OR (Erg->Contents.Int>255)) return;
+
+ Erg->Typ=TempInt; if (toupper(*Asc)=='P') Erg->Contents.Int+=0x1000;
+END
+
+ static void SwitchFrom_370(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_370(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x49; NOPCode=0xff;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_370; IsDef=IsDef_370;
+ SwitchFrom=SwitchFrom_370; InternSymbol=InternSymbol_370;
+
+ InitFields();
+END
+
+ void code370_init(void)
+BEGIN
+ CPU37010=AddCPU("370C010" ,SwitchTo_370);
+ CPU37020=AddCPU("370C020" ,SwitchTo_370);
+ CPU37030=AddCPU("370C030" ,SwitchTo_370);
+ CPU37040=AddCPU("370C040" ,SwitchTo_370);
+ CPU37050=AddCPU("370C050" ,SwitchTo_370);
+END
diff --git a/code370.h b/code370.h
new file mode 100644
index 0000000..50cdbab
--- /dev/null
+++ b/code370.h
@@ -0,0 +1,11 @@
+/* code370h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 370-Familie */
+/* */
+/* Historie: 10.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code370_init(void);
diff --git a/code4004.c b/code4004.c
new file mode 100644
index 0000000..d3f799c
--- /dev/null
+++ b/code4004.c
@@ -0,0 +1,503 @@
+/* code4004.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Intel 4004 */
+/* */
+/* Historie: 1. 2.1998 Grundsteinlegung */
+/* 3. 3.1998 weitere Fixed-Befehle hinzugefuegt */
+/* 28.11.1998 LookupInstTable ;-) */
+/* JCN FIM... */
+/* 29.11.1998 HeaderId symbolisch holen */
+/* 3.12.1998 DATA schrieb 16-Bit-Ints statt 8 Bit */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* 23. 1.1999 / / entfernt */
+/* 2. 7.1999 Zus. Befehlsvarianten, andere Registersyntax */
+/* 8. 9.1999 REG fehlte */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "headids.h"
+
+/*---------------------------------------------------------------------------*/
+/* Variablen */
+
+#define FixedOrderCnt 35
+#define OneRegOrderCnt 1
+#define OneRRegOrderCnt 3
+#define AccRegOrderCnt 4
+#define Imm4OrderCnt 2
+
+typedef struct
+ {
+ Byte Code;
+ } FixedOrder;
+
+static CPUVar CPU4004/*,CPU4040*/;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *OneRegOrders;
+static FixedOrder *OneRRegOrders;
+static FixedOrder *AccRegOrders;
+static FixedOrder *Imm4Orders;
+static PInstTable InstTable;
+
+/*---------------------------------------------------------------------------*/
+/* Parser */
+
+ static Byte RegVal(char Inp)
+BEGIN
+ if ((Inp >='0') AND (Inp <= '9')) return Inp - '0';
+ else if ((Inp >='A') AND (Inp <= 'F')) return Inp - 'A' + 10;
+ else return 0xff;
+END
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg)
+BEGIN
+ char *s;
+
+ if (FindRegDef(Asc,&s)) Asc=s;
+
+ if ((strlen(Asc) != 2) OR (toupper(*Asc)!='R')) return False;
+ else
+ BEGIN
+ *Erg = RegVal(toupper(Asc[1]));
+ return (*Erg != 0xff);
+ END
+END
+
+ static Boolean DecodeRReg(char *Asc, Byte *Erg)
+BEGIN
+ Byte h;
+ char *s;
+
+ if (FindRegDef(Asc,&s)) Asc = s;
+
+ if ((strlen(Asc) != 4) OR (toupper(*Asc) != 'R') OR (toupper(Asc[2]) != 'R')) return False;
+ else
+ BEGIN
+ *Erg = RegVal(toupper(Asc[1]));
+ h = RegVal(toupper(Asc[3]));
+ return ((*Erg != 0xff) AND (h != 0xff) AND (h == (*Erg) + 1) AND (Odd(h)));
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+/* Hilfsdekoder */
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *Instr=FixedOrders+Index;
+
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=Instr->Code; CodeLen=1;
+ END
+END
+
+ static void DecodeOneReg(Word Index)
+BEGIN
+ FixedOrder *Instr=OneRegOrders+Index;
+ Byte Erg;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Erg)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ BAsmCode[0]=Instr->Code+Erg; CodeLen=1;
+ END
+END
+
+ static void DecodeOneRReg(Word Index)
+BEGIN
+ FixedOrder *Instr=OneRRegOrders+Index;
+ Byte Erg;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeRReg(ArgStr[1],&Erg)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ BAsmCode[0]=Instr->Code+Erg; CodeLen=1;
+ END
+END
+
+ static void DecodeAccReg(Word Index)
+BEGIN
+ FixedOrder *Instr=AccRegOrders+Index;
+ Byte Erg;
+
+ if ((ArgCnt != 2) AND (ArgCnt != 1)) WrError(1110);
+ else if ((ArgCnt == 2) AND (strcasecmp(ArgStr[1], "A") != 0)) WrError(1350);
+ else if (NOT DecodeReg(ArgStr[ArgCnt], &Erg)) WrXError(1445, ArgStr[ArgCnt]);
+ else
+ BEGIN
+ BAsmCode[0] = Instr->Code + Erg; CodeLen = 1;
+ END
+END
+
+ static void DecodeImm4(Word Index)
+BEGIN
+ FixedOrder *Instr=Imm4Orders+Index;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=EvalIntExpression(ArgStr[1],UInt4,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]+=Instr->Code; CodeLen=1;
+ END
+ END
+END
+
+ static void DecodeFullJmp(Word Index)
+BEGIN
+ Word Adr;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Adr=EvalIntExpression(ArgStr[1],UInt12,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x40+(Index << 4)+Hi(Adr);
+ BAsmCode[1]=Lo(Adr);
+ CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeISZ(Word Index)
+BEGIN
+ Word Adr;
+ Boolean OK;
+ Byte Erg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Erg)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Adr=EvalIntExpression(ArgStr[2],UInt12,&OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND (Hi(EProgCounter()+1)!=Hi(Adr))) WrError(1910);
+ else
+ BEGIN
+ BAsmCode[0]=0x70+Erg; BAsmCode[1]=Lo(Adr); CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeJCN(Word Index)
+BEGIN
+ Word AdrInt;
+ Boolean OK;
+
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0] = 0x10;
+ if (strcasecmp(ArgStr[1], "Z") == 0) BAsmCode[0] += 4;
+ else if (strcasecmp(ArgStr[1], "NZ") == 0) BAsmCode[0] += 12;
+ else if (strcasecmp(ArgStr[1], "C") == 0) BAsmCode[0] += 2;
+ else if (strcasecmp(ArgStr[1], "NC") == 0) BAsmCode[0] += 10;
+ else if (strcasecmp(ArgStr[1], "T") == 0) BAsmCode[0] += 1;
+ else if (strcasecmp(ArgStr[1], "NT") == 0) BAsmCode[0] += 9;
+ if (BAsmCode[0] == 0x10) WrXError(1360, ArgStr[1]);
+ else
+ BEGIN
+ AdrInt = EvalIntExpression(ArgStr[2], UInt12, &OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND (Hi(EProgCounter() + 2) != Hi(AdrInt))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[1] = Lo(AdrInt);
+ CodeLen = 2;
+ END
+ END
+ END
+END
+
+ static void DecodeFIM(Word Index)
+BEGIN
+ Boolean OK;
+
+ if (ArgCnt != 2) WrError(1110);
+ else if (NOT DecodeRReg(ArgStr[1], BAsmCode)) WrXError(1445, ArgStr[1]);
+ else
+ BEGIN
+ BAsmCode[1] = EvalIntExpression(ArgStr[2], Int8, &OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0] |= 0x20;
+ CodeLen = 2;
+ END
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Boolean ValOK;
+ Word Size;
+ int z, z2;
+ TempResult t;
+ char Ch;
+
+ if (Memo("DS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("DATA"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ ValOK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (ValOK)
+ BEGIN
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ if ((t.Typ==TempInt) AND (FirstPassUnknown))
+ if (ActPC==SegData) t.Contents.Int&=7; else t.Contents.Int&=127;
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (ActPC==SegCode)
+ BEGIN
+ if (NOT RangeCheck(t.Contents.Int,Int8))
+ BEGIN
+ WrError(1320); ValOK=False;
+ END
+ else BAsmCode[CodeLen++]=t.Contents.Int & 0xff;
+ END
+ else
+ BEGIN
+ if (NOT RangeCheck(t.Contents.Int,Int4))
+ BEGIN
+ WrError(1320); ValOK=False;
+ END
+ else BAsmCode[CodeLen++]=t.Contents.Int & 0x0f;
+ END
+ break;
+ case TempFloat:
+ WrError(1135); ValOK=False;
+ break;
+ case TempString:
+ for (z2=0; z2<strlen(t.Contents.Ascii); z2++)
+ BEGIN
+ Ch=CharTransTable[((usint) t.Contents.Ascii[z2])&0xff];
+ if (ActPC==SegCode)
+ BAsmCode[CodeLen++]=Ch;
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=Ch >> 4;
+ BAsmCode[CodeLen++]=Ch & 15;
+ END
+ END
+ break;
+ default:
+ ValOK=False;
+ END
+ END
+ if (NOT ValOK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("REG"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else AddRegDef(LabPart,ArgStr[1]);
+ return True;
+ END
+
+ return False;
+END
+
+/*---------------------------------------------------------------------------*/
+/* Codetabellenverwaltung */
+
+static int InstrZ;
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
+END
+
+ static void AddOneReg(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=OneRegOrderCnt) exit(255);
+ OneRegOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeOneReg);
+END
+
+ static void AddOneRReg(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=OneRRegOrderCnt) exit(255);
+ OneRRegOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeOneRReg);
+END
+
+ static void AddAccReg(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=AccRegOrderCnt) exit(255);
+ AccRegOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeAccReg);
+END
+
+ static void AddImm4(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=Imm4OrderCnt) exit(255);
+ Imm4Orders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeImm4);
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(101);
+
+ InstrZ=0; FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt);
+ AddFixed("NOP" ,0x00); AddFixed("WRM" ,0xe0);
+ AddFixed("WMP" ,0xe1); AddFixed("WRR" ,0xe2);
+ AddFixed("WPM" ,0xe3); AddFixed("WR0" ,0xe4);
+ AddFixed("WR1" ,0xe5); AddFixed("WR2" ,0xe6);
+ AddFixed("WR3" ,0xe7); AddFixed("SBM" ,0xe8);
+ AddFixed("RDM" ,0xe9); AddFixed("RDR" ,0xea);
+ AddFixed("ADM" ,0xeb); AddFixed("RD0" ,0xec);
+ AddFixed("RD1" ,0xed); AddFixed("RD2" ,0xee);
+ AddFixed("RD3" ,0xef); AddFixed("CLB" ,0xf0);
+ AddFixed("CLC" ,0xf1); AddFixed("IAC" ,0xf2);
+ AddFixed("CMC" ,0xf3); AddFixed("CMA" ,0xf4);
+ AddFixed("RAL" ,0xf5); AddFixed("RAR" ,0xf6);
+ AddFixed("TCC" ,0xf7); AddFixed("DAC" ,0xf8);
+ AddFixed("TCS" ,0xf9); AddFixed("STC" ,0xfa);
+ AddFixed("DAA" ,0xfb); AddFixed("KBP" ,0xfc);
+ AddFixed("DCL" ,0xfd); AddFixed("AD0" ,0xec);
+ AddFixed("AD1" ,0xed); AddFixed("AD2" ,0xee);
+ AddFixed("AD3" ,0xef);
+
+ InstrZ=0; OneRegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*OneRegOrderCnt);
+ AddOneReg("INC" ,0x60);
+
+ InstrZ=0; OneRRegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*OneRRegOrderCnt);
+ AddOneRReg("SRC" ,0x21);
+ AddOneRReg("FIN" ,0x30);
+ AddOneRReg("JIN" ,0x31);
+
+ InstrZ=0; AccRegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*AccRegOrderCnt);
+ AddAccReg("ADD" ,0x80); AddAccReg("SUB" ,0x90);
+ AddAccReg("LD" ,0xa0); AddAccReg("XCH" ,0xb0);
+
+ InstrZ=0; Imm4Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Imm4OrderCnt);
+ AddImm4("BBL" ,0xc0); AddImm4("LDM" ,0xd0);
+
+ AddInstTable(InstTable,"JCN", 0, DecodeJCN);
+ AddInstTable(InstTable,"JCM", 0, DecodeJCN);
+ AddInstTable(InstTable,"JUN", 0, DecodeFullJmp);
+ AddInstTable(InstTable,"JMS", 1, DecodeFullJmp);
+ AddInstTable(InstTable,"ISZ", 0, DecodeISZ);
+ AddInstTable(InstTable,"FIM", 0, DecodeFIM);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+ free(OneRegOrders);
+ free(OneRRegOrders);
+ free(AccRegOrders);
+ free(Imm4Orders);
+END
+
+/*---------------------------------------------------------------------------*/
+/* Callbacks */
+
+ static void MakeCode_4004(void)
+BEGIN
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* der Rest */
+
+ if (NOT LookupInstTable(InstTable, OpPart)) WrXError(1200, OpPart);
+END
+
+ static Boolean IsDef_4004(void)
+BEGIN
+ return Memo("REG");
+END
+
+ static void SwitchFrom_4004(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_4004(void)
+BEGIN
+ PFamilyDescr FoundDescr;
+
+ FoundDescr=FindFamilyByName("4004/4040");
+
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=FoundDescr->Id; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData);
+ Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
+ SegLimits[SegCode] = 0xfff;
+ Grans[SegData ]=1; ListGrans[SegData ]=1; SegInits[SegData ]=0;
+ SegLimits[SegData] = 0xff;
+
+ MakeCode=MakeCode_4004; IsDef=IsDef_4004;
+ SwitchFrom=SwitchFrom_4004;
+
+ InitFields();
+END
+
+/*---------------------------------------------------------------------------*/
+/* Initialisierung */
+
+ void code4004_init(void)
+BEGIN
+ CPU4004=AddCPU("4004",SwitchTo_4004);
+#if 0
+ CPU4040=AddCPU("4040",SwitchTo_4004);
+#endif
+END
diff --git a/code4004.h b/code4004.h
new file mode 100644
index 0000000..82c3530
--- /dev/null
+++ b/code4004.h
@@ -0,0 +1,11 @@
+/* code4004.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Intel 4004/4040 */
+/* */
+/* Historie: 1.2.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code4004_init(void);
diff --git a/code4500.c b/code4500.c
new file mode 100644
index 0000000..0a95939
--- /dev/null
+++ b/code4500.c
@@ -0,0 +1,397 @@
+/* code4500.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator MELPS-4500 */
+/* */
+/* Historie: 31.12.1996 (23.44!!) Grundsteinlegung */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 18. 8.1998 BookKeeping-Aufruf bei RES */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ IntType Max;
+ } ConstOrder;
+
+
+#define FixedOrderCount 79
+#define ConstOrderCount 12
+
+
+static CPUVar CPU4500;
+
+static FixedOrder *FixedOrders;
+static ConstOrder *ConstOrders;
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddConst(char *NName, Word NCode, IntType NMax)
+BEGIN
+ if (InstrZ>=ConstOrderCount) exit(255);
+ ConstOrders[InstrZ].Name=NName;
+ ConstOrders[InstrZ].Code=NCode;
+ ConstOrders[InstrZ++].Max=NMax;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("AM" ,0x00a); AddFixed("AMC" ,0x00b); AddFixed("AND" ,0x018);
+ AddFixed("CLD" ,0x011); AddFixed("CMA" ,0x01c); AddFixed("DEY" ,0x017);
+ AddFixed("DI" ,0x004); AddFixed("EI" ,0x005); AddFixed("IAP0",0x260);
+ AddFixed("IAP1",0x261); AddFixed("IAP2",0x262); AddFixed("IAP3",0x263);
+ AddFixed("IAP4",0x264); AddFixed("INY" ,0x013); AddFixed("NOP" ,0x000);
+ AddFixed("OR" ,0x019); AddFixed("OP0A",0x220); AddFixed("OP1A",0x221);
+ AddFixed("POF" ,0x002); AddFixed("POF2",0x008); AddFixed("RAR" ,0x01d);
+ AddFixed("RC" ,0x006); AddFixed("RC3" ,0x2ac); AddFixed("RC4" ,0x2ae);
+ AddFixed("RD" ,0x014); AddFixed("RT" ,0x044); AddFixed("RTI" ,0x046);
+ AddFixed("RTS" ,0x045); AddFixed("SC" ,0x007); AddFixed("SC3" ,0x2ad);
+ AddFixed("SC4" ,0x2af); AddFixed("SD" ,0x015); AddFixed("SEAM",0x026);
+ AddFixed("SNZ0",0x038); AddFixed("SNZP",0x003); AddFixed("SNZT1",0x280);
+ AddFixed("SNZT2",0x281); AddFixed("SNZT3",0x282); AddFixed("SPCR",0x299);
+ AddFixed("STCR",0x298); AddFixed("SZC" ,0x02f); AddFixed("T1R1",0x2ab);
+ AddFixed("T3AB",0x232); AddFixed("TAB" ,0x01e); AddFixed("TAB3",0x272);
+ AddFixed("TABE",0x02a); AddFixed("TAD" ,0x051); AddFixed("TAI1",0x253);
+ AddFixed("TAL1",0x24a); AddFixed("TAMR",0x252); AddFixed("TASP",0x050);
+ AddFixed("TAV1",0x054); AddFixed("TAW1",0x24b); AddFixed("TAW2",0x24c);
+ AddFixed("TAW3",0x24d); AddFixed("TAX" ,0x052); AddFixed("TAY" ,0x01f);
+ AddFixed("TAZ" ,0x053); AddFixed("TBA" ,0x00e); AddFixed("TC1A",0x2a8);
+ AddFixed("TC2A",0x2a9); AddFixed("TDA" ,0x029); AddFixed("TEAB",0x01a);
+ AddFixed("TI1A",0x217); AddFixed("TL1A",0x20a); AddFixed("TL2A",0x20b);
+ AddFixed("TL3A",0x20c); AddFixed("TLCA",0x20d); AddFixed("TMRA",0x216);
+ AddFixed("TPTA",0x2a5); AddFixed("TPAA",0x2aa); AddFixed("TR1A",0x2a6);
+ AddFixed("TR1AB",0x23f); AddFixed("TV1A",0x03f); AddFixed("TW1A",0x20e);
+ AddFixed("TW2A",0x20f); AddFixed("TW3A",0x210); AddFixed("TYA" ,0x00c);
+ AddFixed("WRST",0x2a0);
+
+ ConstOrders=(ConstOrder *) malloc(sizeof(ConstOrder)*ConstOrderCount); InstrZ=0;
+ AddConst("A" ,0x060,UInt4); AddConst("LA" ,0x070,UInt4);
+ AddConst("LZ" ,0x048,UInt2); AddConst("RB" ,0x04c,UInt2);
+ AddConst("SB" ,0x05c,UInt2); AddConst("SZB" ,0x020,UInt2);
+ AddConst("TABP",0x080,UInt6); AddConst("TAM" ,0x2c0,UInt4);
+ AddConst("TMA" ,0x2b0,UInt4); AddConst("XAM" ,0x2d0,UInt4);
+ AddConst("XAMD",0x2f0,UInt4); AddConst("XAMI",0x2e0,UInt4);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(ConstOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Boolean ValOK;
+ Word Size,z,z2;
+ TempResult t;
+ char Ch;
+
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,415);
+ return True;
+ END
+
+ if (Memo("RES"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("DATA"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ ValOK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (ValOK)
+ BEGIN
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ if ((t.Typ==TempInt) AND (FirstPassUnknown))
+ if (ActPC==SegData) t.Contents.Int&=7; else t.Contents.Int&=511;
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (ActPC==SegCode)
+ BEGIN
+ if (NOT RangeCheck(t.Contents.Int,Int10))
+ BEGIN
+ WrError(1320); ValOK=False;
+ END
+ else WAsmCode[CodeLen++]=t.Contents.Int & 0x3ff;
+ END
+ else
+ BEGIN
+ if (NOT RangeCheck(t.Contents.Int,Int4))
+ BEGIN
+ WrError(1320); ValOK=False;
+ END
+ else BAsmCode[CodeLen++]=t.Contents.Int & 0x0f;
+ END
+ break;
+ case TempFloat:
+ WrError(1135); ValOK=False;
+ break;
+ case TempString:
+ for (z2=0; z2<strlen(t.Contents.Ascii); z2++)
+ BEGIN
+ Ch=CharTransTable[((usint) t.Contents.Ascii[z2])&0xff];
+ if (ActPC==SegCode)
+ WAsmCode[CodeLen++]=Ch;
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=Ch >> 4;
+ BAsmCode[CodeLen++]=Ch & 15;
+ END
+ END
+ break;
+ default:
+ ValOK=False;
+ END
+ END
+ if (NOT ValOK) CodeLen=0;
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_4500(void)
+BEGIN
+ int z;
+ Word AdrWord;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; WAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ if (Memo("SZD"))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x024; WAsmCode[1]=0x02b;
+ END
+ return;
+ END
+
+ for (z=0; z<ConstOrderCount; z++)
+ if (Memo(ConstOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[1],ConstOrders[z].Max,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; WAsmCode[0]+=ConstOrders[z].Code;
+ END
+ END
+ return;
+ END
+
+ if (Memo("SEA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[1]=EvalIntExpression(ArgStr[1],UInt4,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; WAsmCode[1]+=0x070; WAsmCode[0]=0x025;
+ END
+ END
+ return;
+ END
+
+ if (Memo("B"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt13,&OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((EProgCounter() >> 7)!=(AdrWord >> 7))) WrError(1910);
+ else
+ BEGIN
+ CodeLen=1; WAsmCode[0]=0x180+(AdrWord&0x7f);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BL")) OR (Memo("BML")))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1) AdrWord=EvalIntExpression(ArgStr[1],UInt13,&OK);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt6,&OK) << 7;
+ if (OK) AdrWord+=EvalIntExpression(ArgStr[2],UInt7,&OK);
+ END;
+ if (OK)
+ BEGIN
+ CodeLen=2;
+ WAsmCode[1]=0x200+(AdrWord & 0x7f)+((AdrWord >> 12) << 7);
+ WAsmCode[0]=0x0c0+(Ord(Memo("BL")) << 5)+((AdrWord >> 7) & 0x1f);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BLA")) OR (Memo("BMLA")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt6,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2;
+ WAsmCode[1]=0x200+(AdrWord & 0x0f)+((AdrWord & 0x30) << 2);
+ WAsmCode[0]=0x010+(Ord(Memo("BMLA")) << 5);
+ END
+ END
+ return;
+ END
+
+ if (Memo("BM"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt13,&OK);
+ if (OK)
+ if ((AdrWord >> 7)!=2) WrError(1905);
+ else
+ BEGIN
+ CodeLen=1;
+ WAsmCode[0]=0x100+(AdrWord & 0x7f);
+ END
+ END
+ return;
+ END
+
+ if (Memo("LXY"))
+ BEGIN
+ if ((ArgCnt==0) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1) AdrWord=EvalIntExpression(ArgStr[1],Int8,&OK);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int4,&OK) << 4;
+ if (OK) AdrWord+=EvalIntExpression(ArgStr[2],Int4,&OK);
+ END
+ if (OK)
+ BEGIN
+ CodeLen=1;
+ WAsmCode[0]=0x300+AdrWord;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_4500(void)
+BEGIN
+ return (Memo("SFR"));
+END
+
+ static void SwitchFrom_4500(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_4500(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x12; NOPCode=0x000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData);
+ Grans[SegCode ]=2; ListGrans[SegCode ]=2; SegInits[SegCode ]=0;
+ SegLimits[SegCode] = 0x1fff;
+ Grans[SegData ]=1; ListGrans[SegData ]=1; SegInits[SegData ]=0;
+ SegLimits[SegData] = 415;
+
+ MakeCode=MakeCode_4500; IsDef=IsDef_4500;
+ SwitchFrom=SwitchFrom_4500;
+
+ InitFields();
+END
+
+ void code4500_init(void)
+BEGIN
+ CPU4500=AddCPU("MELPS4500" ,SwitchTo_4500);
+END
diff --git a/code4500.h b/code4500.h
new file mode 100644
index 0000000..30bda94
--- /dev/null
+++ b/code4500.h
@@ -0,0 +1,11 @@
+/* code4500.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator MELPS-4500 */
+/* */
+/* Historie: 31.12.1996 (23.44!!) Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code4500_init(void);
diff --git a/code47c00.c b/code47c00.c
new file mode 100644
index 0000000..14b289e
--- /dev/null
+++ b/code47c00.c
@@ -0,0 +1,1126 @@
+/* code47c00.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Toshiba TLCS-47(0(A)) */
+/* */
+/* Historie: 30.12.1996 Grundsteinlegung */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } FixedOrder;
+
+#define FixedOrderCnt 3
+#define BitOrderCnt 4
+
+
+#define ModNone (-1)
+#define ModAcc 0
+#define MModAcc (1 << ModAcc)
+#define ModL 1
+#define MModL (1 << ModL)
+#define ModH 2
+#define MModH (1 << ModH)
+#define ModHL 3
+#define MModHL (1 << ModHL)
+#define ModIHL 4
+#define MModIHL (1 << ModIHL)
+#define ModAbs 5
+#define MModAbs (1 << ModAbs)
+#define ModPort 6
+#define MModPort (1 << ModPort)
+#define ModImm 7
+#define MModImm (1 << ModImm)
+#define ModSAbs 8
+#define MModSAbs (1 << ModSAbs)
+
+static CPUVar CPU47C00,CPU470C00,CPU470AC00;
+static ShortInt AdrType,OpSize;
+static Byte AdrVal;
+static LongInt DMBAssume;
+static SimpProc SaveInitProc;
+
+static FixedOrder *FixedOrders;
+static char **BitOrders;
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("RET" , 0x2a);
+ AddFixed("RETI", 0x2b);
+ AddFixed("NOP" , 0x00);
+
+ BitOrders=(char **) malloc(sizeof(char *)*BitOrderCnt); InstrZ=0;
+ BitOrders[InstrZ++]="SET";
+ BitOrders[InstrZ++]="CLR";
+ BitOrders[InstrZ++]="TEST";
+ BitOrders[InstrZ++]="TESTP";
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(BitOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Word RAMEnd(void)
+BEGIN
+ if (MomCPU==CPU47C00) return 0xff;
+ else if (MomCPU==CPU470C00) return 0x1ff;
+ else return 0x3ff;
+END
+
+ static Word ROMEnd(void)
+BEGIN
+ if (MomCPU==CPU47C00) return 0xfff;
+ else if (MomCPU==CPU470C00) return 0x1fff;
+ else return 0x3fff;
+END
+
+ static Word PortEnd(void)
+BEGIN
+ if (MomCPU==CPU47C00) return 0x0f;
+ else return 0x1f;
+END
+
+ static void SetOpSize(ShortInt NewSize)
+BEGIN
+ if (OpSize==-1) OpSize=NewSize;
+ else if (OpSize!=NewSize)
+ BEGIN
+ WrError(1131); AdrType=ModNone;
+ END
+END
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrType!=ModNone) AND (((1 << AdrType) & Mask)==0))
+ BEGIN
+ WrError(1350); AdrType=ModNone;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ static char *RegNames[ModIHL+1]={"A","L","H","HL","@HL"};
+
+ Byte z;
+ Word AdrWord;
+ Boolean OK;
+
+ AdrType=ModNone;
+
+ for (z=0; z<=ModIHL; z++)
+ if (strcasecmp(Asc,RegNames[z])==0)
+ BEGIN
+ AdrType=z;
+ if (z!=ModIHL) SetOpSize(Ord(z==ModHL));
+ ChkAdr(Mask); return;
+ END
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1132); break;
+ case 2:
+ AdrVal=EvalIntExpression(Asc+1,UInt2,&OK) & 3;
+ if (OK) AdrType=ModImm;
+ break;
+ case 0:
+ AdrVal=EvalIntExpression(Asc+1,Int4,&OK) & 15;
+ if (OK) AdrType=ModImm;
+ break;
+ case 1:
+ AdrVal=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK) AdrType=ModImm;
+ break;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if (*Asc=='%')
+ BEGIN
+ AdrVal=EvalIntExpression(Asc+1,Int5,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModPort; ChkSpace(SegIO);
+ END
+ ChkAdr(Mask); return;
+ END
+
+ FirstPassUnknown=False;
+ AdrWord=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegData);
+
+ if (FirstPassUnknown) AdrWord&=RAMEnd();
+ else if (Hi(AdrWord)!=DMBAssume) WrError(110);
+
+ AdrVal=Lo(AdrWord);
+ if (FirstPassUnknown) AdrVal&=15;
+
+ if (((Mask & MModSAbs)!=0) AND (AdrVal<16))
+ AdrType=ModSAbs;
+ else AdrType=ModAbs;
+ END
+
+ ChkAdr(Mask);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME47Count 1
+static ASSUMERec ASSUME47s[ASSUME47Count]=
+ {{"DMB", &DMBAssume, 0, 3, 4}};
+
+ if (Memo("PORT"))
+ BEGIN
+ CodeEquate(SegIO,0,0x1f);
+ return True;
+ END
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME47s,ASSUME47Count);
+ return True;
+ END
+
+ return False;
+END
+
+ static void ChkCPU(Byte Mask)
+BEGIN
+ Byte NMask=(1 << (MomCPU-CPU47C00));
+
+ /* Don't ask me why, but NetBSD/Sun3 doesn't like writing
+ everything in one formula when using -O3 :-( */
+
+ if ((Mask & NMask)==0)
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+ static Boolean DualOp(char *s1, char *s2)
+BEGIN
+ return (((strcasecmp(ArgStr[1],s1)==0) AND (strcasecmp(ArgStr[2],s2)==0))
+ OR ((strcasecmp(ArgStr[2],s1)==0) AND (strcasecmp(ArgStr[1],s2)==0)));
+END
+
+ static void MakeCode_47C00(void)
+BEGIN
+ Boolean OK;
+ Word AdrWord;
+ int z;
+ Byte HReg;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodeIntelPseudo(False)) return;
+
+ if (DecodePseudo()) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("LD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"DMB")==0)
+ BEGIN
+ SetOpSize(2); DecodeAdr(ArgStr[2],MModImm+MModIHL);
+ switch (AdrType)
+ BEGIN
+ case ModIHL:
+ CodeLen=3; BAsmCode[0]=0x03; BAsmCode[1]=0x3a; BAsmCode[2]=0xe9;
+ ChkCPU(4);
+ break;
+ case ModImm:
+ CodeLen=3; BAsmCode[0]=0x03;
+ BAsmCode[1]=0x2c; BAsmCode[2]=0x09+(AdrVal << 4);
+ ChkCPU(4);
+ break;
+ END
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModHL+MModH+MModL);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModIHL+MModAbs+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModIHL:
+ CodeLen=1; BAsmCode[0]=0x0c;
+ break;
+ case ModAbs:
+ CodeLen=2; BAsmCode[0]=0x3c; BAsmCode[1]=AdrVal;
+ break;
+ case ModImm:
+ CodeLen=1; BAsmCode[0]=0x40+AdrVal;
+ break;
+ END
+ break;
+ case ModHL:
+ DecodeAdr(ArgStr[2],MModAbs+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ if ((AdrVal & 3)!=0) WrError(1325);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x28; BAsmCode[1]=AdrVal;
+ END
+ break;
+ case ModImm:
+ CodeLen=2;
+ BAsmCode[0]=0xc0+(AdrVal >> 4);
+ BAsmCode[1]=0xe0+(AdrVal & 15);
+ break;
+ END
+ break;
+ case ModH:
+ case ModL:
+ BAsmCode[0]=0xc0+(Ord(AdrType==ModL) << 5);
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1; BAsmCode[0]+=AdrVal;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDL"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"A")!=0) OR (strcasecmp(ArgStr[2],"@DC")!=0)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x33;
+ END
+ return;
+ END
+
+ if (Memo("LDH"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"A")!=0) OR (strcasecmp(ArgStr[2],"@DC+")!=0)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x32;
+ END
+ return;
+ END
+
+ if (Memo("ST"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"DMB")==0)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModIHL);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x03; BAsmCode[1]=0x3a; BAsmCode[2]=0x69;
+ ChkCPU(4);
+ END
+ END
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[1],MModImm+MModAcc);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ if (strcasecmp(ArgStr[2],"@HL+")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x1a;
+ END
+ else if (strcasecmp(ArgStr[2],"@HL-")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x1b;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModAbs+MModIHL);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ CodeLen=2; BAsmCode[0]=0x3f; BAsmCode[1]=AdrVal;
+ break;
+ case ModIHL:
+ CodeLen=1; BAsmCode[0]=0x0f;
+ break;
+ END
+ END
+ break;
+ case ModImm:
+ HReg=AdrVal;
+ if (strcasecmp(ArgStr[2],"@HL+")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xf0+HReg;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModSAbs);
+ if (AdrType!=ModNone)
+ if (AdrVal>0x0f) WrError(1320);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x2d;
+ BAsmCode[1]=(HReg << 4)+AdrVal;
+ END
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"A")==0) AND (strcasecmp(ArgStr[2],"DMB")==0))
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x03; BAsmCode[1]=0x3a; BAsmCode[2]=0xa9;
+ ChkCPU(4);
+ END
+ else if ((strcasecmp(ArgStr[1],"DMB")==0) AND (strcasecmp(ArgStr[2],"A")==0))
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x03; BAsmCode[1]=0x3a; BAsmCode[2]=0x29;
+ ChkCPU(4);
+ END
+ else if ((strcasecmp(ArgStr[1],"A")==0) AND (strcasecmp(ArgStr[2],"SPW13")==0))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x3a; BAsmCode[1]=0x84;
+ ChkCPU(4);
+ END
+ else if ((strcasecmp(ArgStr[1],"STK13")==0) AND (strcasecmp(ArgStr[2],"A")==0))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x3a; BAsmCode[1]=0x04;
+ ChkCPU(4);
+ END
+ else if (strcasecmp(ArgStr[2],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModH+MModL);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x10+Ord(AdrType==ModL);
+ END
+ END
+ return;
+ END
+
+ if (Memo("XCH"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (DualOp("A","EIR"))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x13;
+ END
+ else if (DualOp("A","@HL"))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x0d;
+ END
+ else if (DualOp("A","H"))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x30;
+ END
+ else if (DualOp("A","L"))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x31;
+ END
+ else
+ BEGIN
+ if ((strcasecmp(ArgStr[1],"A")!=0) AND (strcasecmp(ArgStr[1],"HL")!=0))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ END
+ if ((strcasecmp(ArgStr[1],"A")!=0) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModAbs);
+ if (AdrType!=ModNone)
+ if ((strcasecmp(ArgStr[1],"HL")==0) AND ((AdrVal & 3)!=0)) WrError(1325);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x29+(0x14*Ord(strcasecmp(ArgStr[1],"A")==0));
+ BAsmCode[1]=AdrVal;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("IN"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModPort);
+ if (AdrType!=ModNone)
+ BEGIN
+ HReg=AdrVal;
+ DecodeAdr(ArgStr[2],MModAcc+MModIHL);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ CodeLen=2; BAsmCode[0]=0x3a;
+ BAsmCode[1]=(HReg & 0x0f)+(((HReg & 0x10) ^ 0x10) << 1);
+ break;
+ case ModIHL:
+ CodeLen=2; BAsmCode[0]=0x3a;
+ BAsmCode[1]=0x40+(HReg & 0x0f)+(((HReg & 0x10) ^ 0x10) << 1);
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("OUT"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModPort);
+ if (AdrType!=ModNone)
+ BEGIN
+ HReg=AdrVal; OpSize=0;
+ DecodeAdr(ArgStr[1],MModAcc+MModIHL+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ CodeLen=2; BAsmCode[0]=0x3a;
+ BAsmCode[1]=0x80+((HReg & 0x10) << 1)+((HReg & 0x0f) ^ 4);
+ break;
+ case ModIHL:
+ CodeLen=2; BAsmCode[0]=0x3a;
+ BAsmCode[1]=0xc0+((HReg & 0x10) << 1)+((HReg & 0x0f) ^ 4);
+ break;
+ case ModImm:
+ if (HReg>0x0f) WrError(1110);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x2c;
+ BAsmCode[1]=(AdrVal << 4)+HReg;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("OUTB"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"@HL")!=0) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x12;
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ if (Memo("CMPR"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModSAbs+MModH+MModL);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModIHL+MModAbs+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModIHL:
+ CodeLen=1; BAsmCode[0]=0x16;
+ break;
+ case ModAbs:
+ CodeLen=2; BAsmCode[0]=0x3e; BAsmCode[1]=AdrVal;
+ break;
+ case ModImm:
+ CodeLen=1; BAsmCode[0]=0xd0+AdrVal;
+ break;
+ END
+ break;
+ case ModSAbs:
+ OpSize=0; HReg=AdrVal; DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x2e;
+ BAsmCode[1]=(AdrVal << 4)+HReg;
+ END
+ break;
+ case ModH:
+ case ModL:
+ HReg=AdrType;
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x38;
+ BAsmCode[1]=0x90+(Ord(HReg==ModH) << 6)+AdrVal;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("ADD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModIHL+MModSAbs+MModL+MModH);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModIHL+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModIHL:
+ CodeLen=1; BAsmCode[0]=0x17;
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x38; BAsmCode[1]=AdrVal;
+ break;
+ END
+ break;
+ case ModIHL:
+ OpSize=0; DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x38; BAsmCode[1]=0x40+AdrVal;
+ END
+ break;
+ case ModSAbs:
+ HReg=AdrVal; OpSize=0; DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x2f; BAsmCode[1]=(AdrVal << 4)+HReg;
+ END
+ break;
+ case ModH:
+ case ModL:
+ HReg=Ord(AdrType==ModH); DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x38; BAsmCode[1]=0x80+(HReg << 6)+AdrVal;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("ADDC"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"A")!=0) OR (strcasecmp(ArgStr[2],"@HL")!=0)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x15;
+ END
+ return;
+ END
+
+ if (Memo("SUBRC"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"A")!=0) OR (strcasecmp(ArgStr[2],"@HL")!=0)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x14;
+ END
+ return;
+ END
+
+ if (Memo("SUBR"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ HReg=AdrVal;
+ DecodeAdr(ArgStr[1],MModAcc+MModIHL);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ CodeLen=2; BAsmCode[0]=0x38; BAsmCode[1]=0x10+HReg;
+ break;
+ case ModIHL:
+ CodeLen=2; BAsmCode[0]=0x38; BAsmCode[1]=0x50+HReg;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INC")) OR (Memo("DEC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ HReg=Ord(Memo("DEC"));
+ DecodeAdr(ArgStr[1],MModAcc+MModIHL+MModL);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ CodeLen=1; BAsmCode[0]=0x08+HReg;
+ break;
+ case ModL:
+ CodeLen=1; BAsmCode[0]=0x18+HReg;
+ break;
+ case ModIHL:
+ CodeLen=1; BAsmCode[0]=0x0a+HReg;
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Logik */
+
+ if ((Memo("AND")) OR (Memo("OR")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ HReg=Ord(Memo("OR"));
+ DecodeAdr(ArgStr[1],MModAcc+MModIHL);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModImm+MModIHL);
+ switch (AdrType)
+ BEGIN
+ case ModIHL:
+ CodeLen=1; BAsmCode[0]=0x1e - HReg; /* ANSI :-0 */
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x38; BAsmCode[1]=0x30-(HReg << 4)+AdrVal;
+ break;
+ END
+ break;
+ case ModIHL:
+ SetOpSize(0); DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x38; BAsmCode[1]=0x70-(HReg << 4)+AdrVal;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("XOR"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"A")!=0) OR (strcasecmp(ArgStr[2],"@HL")!=0)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x1f;
+ END
+ return;
+ END
+
+ if ((Memo("ROLC")) OR (Memo("RORC")))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ HReg=1; OK=True;
+ END
+ else HReg=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x05+(Ord(Memo("RORC")) << 1);
+ for (z=1; z<HReg; z++) BAsmCode[z]=BAsmCode[0];
+ CodeLen=HReg;
+ if (HReg>=4) WrError(160);
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z]))
+ BEGIN
+ if (ArgCnt==1)
+ if (strcasecmp(ArgStr[1],"@L")==0)
+ BEGIN
+ if (Memo("TESTP")) WrError(1350);
+ else
+ BEGIN
+ if (z==2) z=3; CodeLen=1; BAsmCode[0]=0x34+z;
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"CF")==0)
+ BEGIN
+ if (z<2) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=10-2*z;
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"ZF")==0)
+ BEGIN
+ if (z!=3) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x0e;
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"GF")==0)
+ BEGIN
+ if (z==2) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=(z==3) ? 1 : 3-z;
+ ChkCPU(1);
+ END
+ END
+ else if ((strcasecmp(ArgStr[1],"DMB")==0) OR (strcasecmp(ArgStr[1],"DMB0")==0))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x3b; BAsmCode[1]=0x39+(z << 6);
+ ChkCPU(1 << (1+Ord(strcasecmp(ArgStr[1],"DMB0")==0)));
+ END
+ else if (strcasecmp(ArgStr[1],"DMB1")==0)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=3; BAsmCode[1]=0x3b;
+ BAsmCode[2]=0x19+(z << 6);
+ ChkCPU(4);
+ END
+ else if (strcasecmp(ArgStr[1],"STK13")==0)
+ BEGIN
+ if (z>1) WrError(1350);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=3-z; BAsmCode[1]=0x3a; BAsmCode[2]=0x84;
+ ChkCPU(4);
+ END
+ END
+ else WrError(1350);
+ else if (ArgCnt==2)
+ if (strcasecmp(ArgStr[1],"IL")==0)
+ BEGIN
+ if (z!=1) WrError(1350);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[2],UInt6,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x36; BAsmCode[1]=0xc0+HReg;
+ END
+ END
+ END
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[2],UInt2,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModIHL+MModPort+MModSAbs);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ if (z!=2) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x5c+HReg;
+ END
+ break;
+ case ModIHL:
+ if (z==3) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x50+HReg+(z << 2);
+ END
+ break;
+ case ModPort:
+ if (AdrVal>15) WrError(1320);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x3b;
+ BAsmCode[1]=(z << 6)+(HReg << 4)+AdrVal;
+ END
+ break;
+ case ModSAbs:
+ CodeLen=2; BAsmCode[0]=0x39;
+ BAsmCode[1]=(z << 6)+(HReg << 4)+AdrVal;
+ break;
+ END
+ END
+ END
+ else WrError(1110);
+ return;
+ END
+
+ if ((Memo("EICLR")) OR (Memo("DICLR")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"IL")!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],UInt6,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x36;
+ BAsmCode[1]+=0x40*(1+Ord(Memo("DICLR")));
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if (Memo("BSS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrWord >> 6)!=((EProgCounter()+1) >> 6))) WrError(1910);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ CodeLen=1; BAsmCode[0]=0x80+(AdrWord & 0x3f);
+ END
+ END
+ return;
+ END
+
+ if (Memo("BS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if (((NOT SymbolQuestionable) AND (AdrWord >> 12)!=((EProgCounter()+2) >> 12))) WrError(1910);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ CodeLen=2; BAsmCode[0]=0x60+(Hi(AdrWord) & 15);
+ BAsmCode[1]=Lo(AdrWord);
+ END
+ END
+ return;
+ END
+
+ if (Memo("BSL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if (AdrWord>ROMEnd()) WrError(1320);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ CodeLen=3;
+ switch (AdrWord >> 12)
+ BEGIN
+ case 0: BAsmCode[0]=0x02; break;
+ case 1: BAsmCode[0]=0x03; break;
+ case 2: BAsmCode[0]=0x1c; break;
+ case 3: BAsmCode[0]=0x01; break;
+ END
+ BAsmCode[1]=0x60+(Hi(AdrWord) & 0x0f); BAsmCode[2]=Lo(AdrWord);
+ END
+ END
+ return;
+ END
+
+ if (Memo("B"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if (AdrWord>ROMEnd()) WrError(1320);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ if ((AdrWord >> 6)==((EProgCounter()+1) >> 6))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x80+(AdrWord & 0x3f);
+ END
+ else if ((AdrWord >> 12)==((EProgCounter()+2) >> 12))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x60+(Hi(AdrWord) & 0x0f);
+ BAsmCode[1]=Lo(AdrWord);
+ END
+ else
+ BEGIN
+ CodeLen=3;
+ switch (AdrWord >> 12)
+ BEGIN
+ case 0: BAsmCode[0]=0x02; break;
+ case 1: BAsmCode[0]=0x03; break;
+ case 2: BAsmCode[0]=0x1c; break;
+ case 3: BAsmCode[0]=0x01; break;
+ END
+ BAsmCode[1]=0x60+(Hi(AdrWord) & 0x0f); BAsmCode[2]=Lo(AdrWord);
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALLS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ if (AdrWord==0x86) AdrWord=0x06;
+ if ((AdrWord & 0xff87)!=6) WrError(1135);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=(AdrWord >> 3)+0x70;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND (((AdrWord ^ EProgCounter()) & 0x3800)!=0)) WrError(1910);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ CodeLen=2; BAsmCode[0]=0x20+(Hi(AdrWord) & 7);
+ BAsmCode[1]=Lo(AdrWord);
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_47C00(void)
+BEGIN
+ return (Memo("PORT"));
+END
+
+ static void SwitchFrom_47C00(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_47C00(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=True;
+
+ PCSymbol="$"; HeaderID=0x55; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegIO);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = ROMEnd();
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
+ SegLimits[SegData] = RAMEnd();
+ Grans[SegIO ]=1; ListGrans[SegIO ]=1; SegInits[SegIO ]=0;
+ SegLimits[SegIO ] = PortEnd();
+
+ MakeCode=MakeCode_47C00; IsDef=IsDef_47C00;
+ SwitchFrom=SwitchFrom_47C00; InitFields();
+END
+
+ static void InitCode_47C00(void)
+BEGIN
+ SaveInitProc();
+
+ DMBAssume=0;
+END
+
+ void code47c00_init(void)
+BEGIN
+ CPU47C00=AddCPU("47C00",SwitchTo_47C00);
+ CPU470C00=AddCPU("470C00",SwitchTo_47C00);
+ CPU470AC00=AddCPU("470AC00",SwitchTo_47C00);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_47C00;
+END
diff --git a/code47c00.h b/code47c00.h
new file mode 100644
index 0000000..4c3d0e1
--- /dev/null
+++ b/code47c00.h
@@ -0,0 +1,11 @@
+/* code47c00.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Toshiba TLCS-47(0(A)) */
+/* */
+/* Historie: 30.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code47c00_init(void);
diff --git a/code48.c b/code48.c
new file mode 100644
index 0000000..e34135b
--- /dev/null
+++ b/code48.c
@@ -0,0 +1,998 @@
+/* code48.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul MCS-48-Familie */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "stringlists.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ Byte May2X;
+ Byte UPIFlag;
+ } CondOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } AccOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ Boolean Is22;
+ Boolean IsNUPI;
+ } SelOrder;
+
+#define ModImm 0
+#define ModReg 1
+#define ModInd 2
+#define ModAcc 3
+#define ModNone (-1)
+
+#define ClrCplCnt 4
+#define CondOrderCnt 22
+#define AccOrderCnt 6
+#define SelOrderCnt 6
+
+#define D_CPU8021 0
+#define D_CPU8022 1
+#define D_CPU8039 2
+#define D_CPU8048 3
+#define D_CPU80C39 4
+#define D_CPU80C48 5
+#define D_CPU8041 6
+#define D_CPU8042 7
+
+static ShortInt AdrMode;
+static Byte AdrVal;
+static CPUVar CPU8021,CPU8022,CPU8039,CPU8048,CPU80C39,CPU80C48,CPU8041,CPU8042;
+
+static char **ClrCplVals;
+static Byte *ClrCplCodes;
+static CondOrder *CondOrders;
+static AccOrder *AccOrders;
+static SelOrder *SelOrders;
+
+/****************************************************************************/
+
+ static void AddAcc(char *Name, Byte Code)
+BEGIN
+ if (InstrZ==AccOrderCnt) exit(255);
+ AccOrders[InstrZ].Name=Name;
+ AccOrders[InstrZ++].Code=Code;
+END
+
+ static void AddCond(char *Name, Byte Code, Byte May2X, Byte UPIFlag)
+BEGIN
+ if (InstrZ==CondOrderCnt) exit(255);
+ CondOrders[InstrZ].Name=Name;
+ CondOrders[InstrZ].Code=Code;
+ CondOrders[InstrZ].May2X=May2X;
+ CondOrders[InstrZ++].UPIFlag=UPIFlag;
+END
+
+ static void AddSel(char *Name, Byte Code, Byte Is22, Byte IsNUPI)
+BEGIN
+ if (InstrZ==SelOrderCnt) exit(255);
+ SelOrders[InstrZ].Name=Name;
+ SelOrders[InstrZ].Code=Code;
+ SelOrders[InstrZ].Is22=Is22;
+ SelOrders[InstrZ++].IsNUPI=IsNUPI;
+END
+
+ static void InitFields(void)
+BEGIN
+ ClrCplVals=(char **) malloc(sizeof(char *)*ClrCplCnt);
+ ClrCplCodes=(Byte *) malloc(sizeof(Byte)*ClrCplCnt);
+ ClrCplVals[0]="A"; ClrCplVals[1]="C"; ClrCplVals[2]="F0"; ClrCplVals[3]="F1";
+ ClrCplCodes[0]=0x27; ClrCplCodes[1]=0x97; ClrCplCodes[2]=0x85; ClrCplCodes[3]=0xa5;
+
+ CondOrders=(CondOrder *) malloc(sizeof(CondOrder)*CondOrderCnt); InstrZ=0;
+ AddCond("JTF" ,0x16, 2, 3); AddCond("JNI" ,0x86, 0, 2);
+ AddCond("JC" ,0xf6, 2, 3); AddCond("JNC" ,0xe6, 2, 3);
+ AddCond("JZ" ,0xc6, 2, 3); AddCond("JNZ" ,0x96, 2, 3);
+ AddCond("JT0" ,0x36, 1, 3); AddCond("JNT0" ,0x26, 1, 3);
+ AddCond("JT1" ,0x56, 2, 3); AddCond("JNT1" ,0x46, 2, 3);
+ AddCond("JF0" ,0xb6, 0, 3); AddCond("JF1" ,0x76, 0, 3);
+ AddCond("JNIBF",0xd6, 2, 1); AddCond("JOBF" ,0x86, 2, 1);
+ AddCond("JB0" ,0x12, 0, 3); AddCond("JB1" ,0x32, 0, 3);
+ AddCond("JB2" ,0x52, 0, 3); AddCond("JB3" ,0x72, 0, 3);
+ AddCond("JB4" ,0x92, 0, 3); AddCond("JB5" ,0xb2, 0, 3);
+ AddCond("JB6" ,0xd2, 0, 3); AddCond("JB7" ,0xf2, 0, 3);
+
+ AccOrders=(AccOrder *) malloc(sizeof(AccOrder)*AccOrderCnt); InstrZ=0;
+ AddAcc("DA" ,0x57);
+ AddAcc("RL" ,0xe7);
+ AddAcc("RLC" ,0xf7);
+ AddAcc("RR" ,0x77);
+ AddAcc("RRC" ,0x67);
+ AddAcc("SWAP",0x47);
+
+ SelOrders=(SelOrder *) malloc(sizeof(SelOrder)*SelOrderCnt); InstrZ=0;
+ AddSel("MB0" ,0xe5, False, True );
+ AddSel("MB1" ,0xf5, False, True );
+ AddSel("RB0" ,0xc5, False, False);
+ AddSel("RB1" ,0xd5, False, False);
+ AddSel("AN0" ,0x95, True , False);
+ AddSel("AN1" ,0x85, True , False);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(ClrCplVals);
+ free(ClrCplCodes);
+ free(CondOrders);
+ free(AccOrders);
+ free(SelOrders);
+END
+
+/****************************************************************************/
+
+ static void DecodeAdr(char *Asc_O)
+BEGIN
+ Boolean OK;
+ String Asc;
+
+ strmaxcpy(Asc,Asc_O,255);
+ AdrMode=ModNone;
+
+ if (*Asc=='\0') return;
+
+ if (strcasecmp(Asc,"A")==0) AdrMode=ModAcc;
+
+ else if (*Asc=='#')
+ BEGIN
+ AdrVal=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrMode=ModImm; BAsmCode[1]=AdrVal;
+ END
+ END
+
+ else if ((strlen(Asc)==2) AND (toupper(*Asc)=='R'))
+ BEGIN
+ if ((Asc[1]>='0') AND (Asc[1]<='7'))
+ BEGIN
+ AdrMode=ModReg; AdrVal=Asc[1]-'0';
+ END
+ END
+
+ else if ((strlen(Asc)==3) AND (*Asc=='@') AND (toupper(Asc[1])=='R'))
+ BEGIN
+ if ((Asc[2]>='0') AND (Asc[2]<='1'))
+ BEGIN
+ AdrMode=ModInd; AdrVal=Asc[2]-'0';
+ END
+ END
+END
+
+ static void ChkN802X(void)
+BEGIN
+ if (CodeLen==0) return;
+ if ((MomCPU==CPU8021) OR (MomCPU==CPU8022))
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+ static void Chk802X(void)
+BEGIN
+ if (CodeLen==0) return;
+ if ((MomCPU!=CPU8021) AND (MomCPU!=CPU8022))
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+ static void ChkNUPI(void)
+BEGIN
+ if (CodeLen==0) return;
+ if ((MomCPU==CPU8041) OR (MomCPU==CPU8042))
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+ static void ChkUPI(void)
+BEGIN
+ if (CodeLen==0) return;
+ if ((MomCPU!=CPU8041) AND (MomCPU!=CPU8042))
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+ static void ChkExt(void)
+BEGIN
+ if (CodeLen==0) return;
+ if ((MomCPU==CPU8039) OR (MomCPU==CPU80C39))
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ void MakeCode_48(void)
+BEGIN
+ Boolean OK;
+ Word AdrWord;
+ int z;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ if ((Memo("ADD")) OR (Memo("ADDC")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1135);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ if ((AdrMode==ModNone) OR (AdrMode==ModAcc)) WrError(1350);
+ else
+ BEGIN
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x03;
+ break;
+ case ModReg:
+ CodeLen=1; BAsmCode[0]=0x68+AdrVal;
+ break;
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0x60+AdrVal;
+ break;
+ END
+ if (strlen(OpPart)==4) BAsmCode[0]+=0x10;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("ANL")) OR (Memo("ORL")) OR (Memo("XRL")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")==0)
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ if ((AdrMode==-1) OR (AdrMode==ModAcc)) WrError(1350);
+ else
+ BEGIN
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x43;
+ break;
+ case ModReg:
+ CodeLen=1; BAsmCode[0]=0x48+AdrVal;
+ break;
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0x40+AdrVal;
+ break;
+ END
+ if (Memo("ANL")) BAsmCode[0]+=0x10;
+ else if (Memo("XRL")) BAsmCode[0]+=0x90;
+ END
+ END
+ else if ((strcasecmp(ArgStr[1],"BUS")==0) OR (strcmp(ArgStr[1],"P1")==0) OR (strcmp(ArgStr[1],"P2")==0))
+ BEGIN
+ if (Memo("XRL")) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ if (AdrMode!=ModImm) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x88;
+ if (toupper(*ArgStr[1])=='P') BAsmCode[0]+=ArgStr[1][1]-'0';
+ if (Memo("ANL")) BAsmCode[0]+=0x10;
+ if (strcasecmp(ArgStr[1],"BUS")==0)
+ BEGIN
+ ChkExt(); ChkNUPI();
+ END
+ ChkN802X();
+ END
+ END
+ END
+ else WrError(1350);
+ return;
+ END
+
+ if ((Memo("CALL")) OR (Memo("JMP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if ((EProgCounter()&0x7fe)==0x7fe) WrError(1900);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if (AdrWord>0xfff) WrError(1320);
+ else
+ BEGIN
+ if ((EProgCounter()&0x800)!=(AdrWord&0x800))
+ BEGIN
+ BAsmCode[0]=0xe5+((AdrWord&0x800)>>7); CodeLen=1;
+ END
+ BAsmCode[CodeLen+1]=AdrWord&0xff;
+ BAsmCode[CodeLen]=0x04+((AdrWord&0x700)>>3);
+ if (Memo("CALL")) BAsmCode[CodeLen]+=0x10;
+ CodeLen+=2; ChkSpace(SegCode);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CLR")) OR (Memo("CPL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ z=0; OK=False; NLS_UpString(ArgStr[1]);
+ do
+ BEGIN
+ if (strcmp(ClrCplVals[z],ArgStr[1])==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=ClrCplCodes[z]; OK=True;
+ if (*ArgStr[1]=='F') ChkN802X();
+ END
+ z++;
+ END
+ while ((z<ClrCplCnt) AND (CodeLen!=1));
+ if (NOT OK) WrError(1135);
+ else if (Memo("CPL")) BAsmCode[0]+=0x10;
+ END
+ return;
+ END
+
+ for (z=0; z<AccOrderCnt; z++)
+ if (Memo(AccOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=AccOrders[z].Code;
+ END
+ return;
+ END
+
+ if (Memo("DEC"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ CodeLen=1; BAsmCode[0]=0x07;
+ break;
+ case ModReg:
+ CodeLen=1; BAsmCode[0]=0xc8+AdrVal;
+ ChkN802X();
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("DIS")) OR (Memo("EN")))
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ if (strcmp(ArgStr[1],"I")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x05;
+ END
+ else if (strcmp(ArgStr[1],"TCNTI")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x25;
+ END
+ else if ((Memo("EN")) AND (strcmp(ArgStr[1],"DMA")==0))
+ BEGIN
+ BAsmCode[0]=0xe5; CodeLen=1; ChkUPI();
+ END
+ else if ((Memo("EN")) AND (strcmp(ArgStr[1],"FLAGS")==0))
+ BEGIN
+ BAsmCode[0]=0xf5; CodeLen=1; ChkUPI();
+ END
+ else WrError(1350);
+ if (CodeLen!=0)
+ BEGIN
+ if (Memo("DIS")) BAsmCode[0]+=0x10;
+ if (MomCPU==CPU8021)
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("DJNZ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ if (AdrMode!=ModReg) WrError(1350);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],Int16,&OK);
+ if (OK)
+ BEGIN
+ if (((EProgCounter()+1)&0xff00)!=(AdrWord&0xff00)) WrError(1910);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrVal; BAsmCode[1]=AdrWord&0xff;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("ENT0"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CLK")!=0) WrError(1135);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x75;
+ ChkN802X(); ChkNUPI();
+ END
+ return;
+ END
+
+ if (Memo("INC"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ CodeLen=1; BAsmCode[0]=0x17;
+ break;
+ case ModReg:
+ CodeLen=1; BAsmCode[0]=0x18+AdrVal;
+ break;
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0x10+AdrVal;
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ return;
+ END
+
+ if (Memo("IN"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else if (strcasecmp(ArgStr[2],"DBB")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x22; ChkUPI();
+ END
+ else if ((strlen(ArgStr[2])!=2) OR (toupper(*ArgStr[2])!='P')) WrError(1350);
+ else switch (ArgStr[2][1])
+ BEGIN
+ case '0':
+ case '1':
+ case '2':
+ CodeLen=1; BAsmCode[0]=0x08+ArgStr[2][1]-'0';
+ if (ArgStr[2][1]=='0') Chk802X();
+ break;
+ default:
+ WrError(1350);
+ END
+ return;
+ END
+
+ if (Memo("INS"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else if (strcasecmp(ArgStr[2],"BUS")!=0) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x08; ChkExt(); ChkNUPI();
+ END
+ return;
+ END
+
+ if (Memo("JMPP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"@A")!=0) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xb3;
+ END
+ return;
+ END
+
+ for (z=0; z<CondOrderCnt; z++)
+ if (Memo(CondOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt12,&OK);
+ if (NOT OK);
+ else if (((EProgCounter()+1)&0xff00)!=(AdrWord&0xff00)) WrError(1910);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=CondOrders[z].Code; BAsmCode[1]=AdrWord&0xff;
+ ChkSpace(SegCode);
+ if (CondOrders[z].May2X==0) ChkN802X();
+ else if ((CondOrders[z].May2X==1) AND (MomCPU==CPU8021))
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+ if (CondOrders[z].UPIFlag==1) ChkUPI();
+ else if (CondOrders[z].UPIFlag==2) ChkNUPI();
+ END
+ END
+ return;
+ END
+
+ if (Memo("JB"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrVal=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],UInt12,&OK);
+ if (NOT OK);
+ else if (((EProgCounter()+1)&0xff00)!=(AdrWord&0xff00)) WrError(1910);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x12+(AdrVal<<5);
+ BAsmCode[1]=AdrWord&0xff;
+ ChkN802X();
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")==0)
+ BEGIN
+ if (strcasecmp(ArgStr[2],"T")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x42;
+ END
+ else if (strcasecmp(ArgStr[2],"PSW")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xc7; ChkN802X();
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ CodeLen=1; BAsmCode[0]=0xf8+AdrVal;
+ break;
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0xf0+AdrVal;
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x23;
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"A")==0)
+ BEGIN
+ if (strcasecmp(ArgStr[1],"STS")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x90; ChkUPI();
+ END
+ else if (strcasecmp(ArgStr[1],"T")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x62;
+ END
+ else if (strcasecmp(ArgStr[1],"PSW")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xd7; ChkN802X();
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ CodeLen=1; BAsmCode[0]=0xa8+AdrVal;
+ break;
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0xa0+AdrVal;
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ END
+ else if (*ArgStr[2]=='#')
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2]+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0xb8+AdrVal; BAsmCode[1]=AdrWord;
+ break;
+ case ModInd:
+ CodeLen=2; BAsmCode[0]=0xb0+AdrVal; BAsmCode[1]=AdrWord;
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ END
+ else WrError(1135);
+ return;
+ END
+
+ if ((Memo("ANLD")) OR (Memo("ORLD")) OR (Memo("MOVD")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OK=False;
+ if ((Memo("MOVD")) AND (strcasecmp(ArgStr[1],"A")==0))
+ BEGIN
+ strcpy(ArgStr[1],ArgStr[2]); strmaxcpy(ArgStr[2],"A",255); OK=True;
+ END
+ if (strcasecmp(ArgStr[2],"A")!=0) WrError(1350);
+ else if ((strlen(ArgStr[1])!=2) OR (toupper(*ArgStr[1])!='P')) WrError(1350);
+ else if ((ArgStr[1][1]<'4') OR (ArgStr[1][1]>'7')) WrError(1320);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x0c+ArgStr[1][1]-'4';
+ if (Memo("ANLD")) BAsmCode[0]+=0x90;
+ else if (Memo("ORLD")) BAsmCode[0]+=0x80;
+ else if (NOT OK) BAsmCode[0]+=0x30;
+ ChkN802X();
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MOVP")) OR (Memo("MOVP3")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"A")!=0) OR (strcasecmp(ArgStr[2],"@A")!=0)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xa3;
+ if (Memo("MOVP3")) BAsmCode[0]+=0x40;
+ ChkN802X();
+ END
+ return;
+ END
+
+ if (Memo("MOVX"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OK=False;
+ if (strcasecmp(ArgStr[2],"A")==0)
+ BEGIN
+ strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"A",255); OK=True;
+ END
+ if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ if (AdrMode!=ModInd) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x80+AdrVal;
+ if (OK) BAsmCode[0]+=0x10;
+ ChkN802X(); ChkNUPI();
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("NOP"))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x00;
+ END
+ return;
+ END
+
+ if (Memo("OUT"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"DBB")!=0) WrError(1350);
+ else if (strcasecmp(ArgStr[2],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x02; CodeLen=1; ChkUPI();
+ END
+ return;
+ END
+
+ if (Memo("OUTL"))
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ if (strcasecmp(ArgStr[2],"A")!=0) WrError(1350);
+ else if (strcmp(ArgStr[1],"BUS")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x02;
+ ChkN802X(); ChkExt(); ChkNUPI();
+ END
+ else if (strcmp(ArgStr[1],"P0")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x90;
+ END
+ else if ((strcmp(ArgStr[1],"P1")==0) OR (strcmp(ArgStr[1],"P2")==0))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x38+ArgStr[1][1]-'0';
+ END
+ else WrError(1350);
+ END
+ return;
+ END
+
+ if ((Memo("RET")) OR (Memo("RETR")))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x83;
+ if (strlen(OpPart)==4)
+ BEGIN
+ BAsmCode[0]+=0x10; ChkN802X();
+ END
+ END
+ return;
+ END
+
+ if (Memo("SEL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU==CPU8021) WrError(1500);
+ else
+ BEGIN
+ OK=False; NLS_UpString(ArgStr[1]);
+ for (z=0; z<SelOrderCnt; z++)
+ if (strcmp(ArgStr[1],SelOrders[z].Name)==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=SelOrders[z].Code; OK=True;
+ if ((SelOrders[z].Is22) AND (MomCPU!=CPU8022))
+ BEGIN
+ CodeLen=0; WrError(1500);
+ END
+ if (SelOrders[z].IsNUPI) ChkNUPI();
+ END
+ if (NOT OK) WrError(1350);
+ END
+ return;
+ END
+
+ if (Memo("STOP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"TCNT")!=0) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x65;
+ END
+ return;
+ END
+
+ if (Memo("STRT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ if (strcmp(ArgStr[1],"CNT")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x45;
+ END
+ else if (strcmp(ArgStr[1],"T")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x55;
+ END
+ else WrError(1350);
+ END
+ return;
+ END
+
+ if (Memo("XCH"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (strcasecmp(ArgStr[2],"A")==0)
+ BEGIN
+ strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"A",255);
+ END
+ if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ CodeLen=1; BAsmCode[0]=0x28+AdrVal;
+ break;
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0x20+AdrVal;
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("XCHD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (strcasecmp(ArgStr[2],"A")==0)
+ BEGIN
+ strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"A",255);
+ END
+ if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ if (AdrMode!=ModInd) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x30+AdrVal;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("RAD"))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU!=CPU8022) WrError(1500);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x80;
+ END
+ return;
+ END
+
+ if (Memo("RETI"))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU!=CPU8022) WrError(1500);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x93;
+ END
+ return;
+ END
+
+ if (Memo("IDL"))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if ((MomCPU!=CPU80C39) AND (MomCPU!=CPU80C48)) WrError(1500);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x01;
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_48(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_48(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_48(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x21; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegIData)|(1<<SegXData);
+ Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
+ switch (MomCPU-CPU8021)
+ BEGIN
+ case D_CPU8041: SegLimits[SegCode] = 0x3ff; break;
+ case D_CPU8042: SegLimits[SegCode] = 0x7ff; break;
+ default : SegLimits[SegCode] = 0xfff; break;
+ END
+ Grans[SegIData]=1; ListGrans[SegIData]=1; SegInits[SegIData]=0x20;
+ SegLimits[SegIData] = 0xff;
+ Grans[SegXData]=1; ListGrans[SegXData]=1; SegInits[SegXData]=0;
+ SegLimits[SegXData] = 0xff;
+
+ MakeCode=MakeCode_48; IsDef=IsDef_48;
+ SwitchFrom=SwitchFrom_48; InitFields();
+END
+
+ void code48_init(void)
+BEGIN
+ CPU8021 =AddCPU("8021" ,SwitchTo_48);
+ CPU8022 =AddCPU("8022" ,SwitchTo_48);
+ CPU8039 =AddCPU("8039" ,SwitchTo_48);
+ CPU8048 =AddCPU("8048" ,SwitchTo_48);
+ CPU80C39=AddCPU("80C39",SwitchTo_48);
+ CPU80C48=AddCPU("80C48",SwitchTo_48);
+ CPU8041 =AddCPU("8041" ,SwitchTo_48);
+ CPU8042 =AddCPU("8042" ,SwitchTo_48);
+END
diff --git a/code48.h b/code48.h
new file mode 100644
index 0000000..6f2799e
--- /dev/null
+++ b/code48.h
@@ -0,0 +1,11 @@
+/* code48.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul MCS-48-Familie */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code48_init(void);
diff --git a/code51.c b/code51.c
new file mode 100644
index 0000000..a04c158
--- /dev/null
+++ b/code51.c
@@ -0,0 +1,2304 @@
+/* code51.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator fuer MCS-51/252 Prozessoren */
+/* */
+/* Historie: 5. 6.1996 Grundsteinlegung */
+/* 9. 8.1998 kurze 8051-Bitadressen wurden im 80251-Sourcemodus */
+/* immer lang gemacht */
+/* 24. 8.1998 Kodierung fuer MOV dir8,Rm war falsch (Fehler im */
+/* Manual!) */
+/* 2. 1.1998 ChkPC-Routine entfernt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+#include "asmitree.h"
+
+/*-------------------------------------------------------------------------*/
+/* Daten */
+
+typedef struct
+ {
+ CPUVar MinCPU;
+ Word Code;
+ } FixedOrder;
+
+#define ModNone (-1)
+#define ModReg 1
+#define MModReg (1<<ModReg)
+#define ModIReg8 2
+#define MModIReg8 (1<<ModIReg8)
+#define ModIReg 3
+#define MModIReg (1<<ModIReg)
+#define ModInd 5
+#define MModInd (1<<ModInd)
+#define ModImm 7
+#define MModImm (1<<ModImm)
+#define ModImmEx 8
+#define MModImmEx (1<<ModImmEx)
+#define ModDir8 9
+#define MModDir8 (1<<ModDir8)
+#define ModDir16 10
+#define MModDir16 (1<<ModDir16)
+#define ModAcc 11
+#define MModAcc (1<<ModAcc)
+#define ModBit51 12
+#define MModBit51 (1<<ModBit51)
+#define ModBit251 13
+#define MModBit251 (1<<ModBit251)
+
+#define MMod51 (MModReg+MModIReg8+MModImm+MModAcc+MModDir8)
+#define MMod251 (MModIReg+MModInd+MModImmEx+MModDir16)
+
+#define AccOrderCnt 6
+#define FixedOrderCnt 5
+#define CondOrderCnt 13
+#define BCondOrderCnt 3
+
+#define AccReg 11
+
+
+static FixedOrder *FixedOrders;
+static FixedOrder *AccOrders;
+static FixedOrder *CondOrders;
+static FixedOrder *BCondOrders;
+static PInstTable InstTable;
+
+static Byte AdrVals[5];
+static Byte AdrPart,AdrSize;
+static ShortInt AdrMode,OpSize;
+static Boolean MinOneIs0;
+
+static Boolean SrcMode,BigEndian;
+
+static SimpProc SaveInitProc;
+static CPUVar CPU87C750,CPU8051,CPU8052,CPU80C320,
+ CPU80501,CPU80502,CPU80504,CPU80515,CPU80517,
+ CPU80251;
+
+/*-------------------------------------------------------------------------*/
+/* Adressparser */
+
+ static void SetOpSize(ShortInt NewSize)
+BEGIN
+ if (OpSize==-1) OpSize=NewSize;
+ else if (OpSize!=NewSize)
+ BEGIN
+ WrError(1131); AdrMode=ModNone; AdrCnt=0;
+ END
+END
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg,Byte *Size)
+BEGIN
+ static Byte Masks[3]={0,1,3};
+
+ char *Start;
+ int alen=strlen(Asc);
+ Boolean IO;
+
+ if (strcasecmp(Asc,"DPX")==0)
+ BEGIN
+ *Erg=14; *Size=2; return True;
+ END
+
+ if (strcasecmp(Asc,"SPX")==0)
+ BEGIN
+ *Erg=15; *Size=2; return True;
+ END
+
+ if ((alen>=2) AND (toupper(*Asc)=='R'))
+ BEGIN
+ Start=Asc+1; *Size=0;
+ END
+ else if ((MomCPU>=CPU80251) AND (alen>=3) AND (toupper(*Asc)=='W') AND (toupper(Asc[1])=='R'))
+ BEGIN
+ Start=Asc+2; *Size=1;
+ END
+ else if ((MomCPU>=CPU80251) AND (alen>=3) AND (toupper(*Asc)=='D') AND (toupper(Asc[1])=='R'))
+ BEGIN
+ Start=Asc+2; *Size=2;
+ END
+ else return False;
+
+ *Erg=ConstLongInt(Start,&IO);
+ if (NOT IO) return False;
+ else if (((*Erg) & Masks[*Size])!=0) return False;
+ else
+ BEGIN
+ (*Erg) >>= (*Size);
+ switch (*Size)
+ BEGIN
+ case 0: return (((*Erg)<8) OR ((MomCPU>=CPU80251) AND ((*Erg)<16)));
+ case 1: return ((*Erg)<16);
+ case 2: return (((*Erg)<8) OR ((*Erg)==14) OR ((*Erg)==15));
+ default: return False;
+ END
+ END
+END
+
+ static void ChkMask(Word Mask, Word ExtMask)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ if ((ExtMask & (1 << AdrMode))==0) WrError(1350); else WrError(1505);
+ AdrCnt=0; AdrMode=ModNone;
+ END
+END
+
+ static void DecodeAdr(char *Asc_O, Word Mask)
+BEGIN
+ Boolean OK,FirstFlag;
+ Byte HSize;
+ Word H16;
+ int SegType;
+ char *PPos,*MPos,*DispPos,Save='\0';
+ LongWord H32;
+ String Asc,Part;
+ Word ExtMask;
+
+ strmaxcpy(Asc,Asc_O,255);
+
+ AdrMode=ModNone; AdrCnt=0;
+
+ ExtMask=MMod251 & Mask;
+ if (MomCPU<CPU80251) Mask &= MMod51;
+
+ if (*Asc=='\0') return;
+
+ if (strcasecmp(Asc,"A")==0)
+ BEGIN
+ if ((Mask & MModAcc)==0)
+ BEGIN
+ AdrMode=ModReg; AdrPart=AccReg;
+ END
+ else AdrMode=ModAcc;
+ SetOpSize(0);
+ ChkMask(Mask,ExtMask); return;
+ END
+
+ if (*Asc=='#')
+ BEGIN
+ if ((OpSize==-1) AND (MinOneIs0)) OpSize=0;
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1132);
+ break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrMode=ModImm; AdrCnt=1;
+ END
+ break;
+ case 1:
+ H16=EvalIntExpression(Asc+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=Hi(H16); AdrVals[1]=Lo(H16);
+ AdrMode=ModImm; AdrCnt=2;
+ END
+ break;
+ case 2:
+ FirstPassUnknown=False;
+ H32=EvalIntExpression(Asc+1,Int32,&OK);
+ if (FirstPassUnknown) H32 &= 0xffff;
+ if (OK)
+ BEGIN
+ AdrVals[1] = H32 & 0xff;
+ AdrVals[0] = (H32 >> 8) & 0xff;
+ H32 >>= 16;
+ if (H32==0) AdrMode=ModImm;
+ else if ((H32==1) OR (H32==0xffff)) AdrMode=ModImmEx;
+ else WrError(1132);
+ if (AdrMode!=ModNone) AdrCnt=2;
+ END
+ break;
+ END
+ ChkMask(Mask,ExtMask); return;
+ END
+
+ if (DecodeReg(Asc,&AdrPart,&HSize))
+ BEGIN
+ if ((MomCPU>=CPU80251) AND ((Mask & MModReg)==0))
+ if ((HSize==0) AND (AdrPart==AccReg)) AdrMode=ModAcc;
+ else AdrMode=ModReg;
+ else AdrMode=ModReg;
+ SetOpSize(HSize);
+ ChkMask(Mask,ExtMask); return;
+ END
+
+ if (*Asc=='@')
+ BEGIN
+ PPos=strchr(Asc,'+'); MPos=strchr(Asc,'-');
+ if ((MPos!=Nil) AND ((MPos<PPos) OR (PPos==Nil))) PPos=MPos;
+ if (PPos!=Nil)
+ BEGIN
+ Save=(*PPos); *PPos='\0';
+ END
+ if (DecodeReg(Asc+1,&AdrPart,&HSize))
+ BEGIN
+ if (PPos==Nil)
+ BEGIN
+ H32=0; OK=True;
+ END
+ else
+ BEGIN
+ *PPos=Save; DispPos=PPos; if (*DispPos=='+') DispPos++;
+ H32=EvalIntExpression(DispPos,SInt16,&OK);
+ END
+ if (OK)
+ switch (HSize)
+ BEGIN
+ case 0:
+ if ((AdrPart>1) OR (H32!=0)) WrError(1350);
+ else AdrMode=ModIReg8;
+ break;
+ case 1:
+ if (H32==0)
+ BEGIN
+ AdrMode=ModIReg; AdrSize=0;
+ END
+ else
+ BEGIN
+ AdrMode=ModInd; AdrSize=0;
+ AdrVals[1] = H32 & 0xff;
+ AdrVals[0] = (H32 >> 8) & 0xff;
+ AdrCnt=2;
+ END
+ break;
+ case 2:
+ if (H32==0)
+ BEGIN
+ AdrMode=ModIReg; AdrSize=2;
+ END
+ else
+ BEGIN
+ AdrMode=ModInd; AdrSize=2;
+ AdrVals[1] = H32 & 0xff;
+ AdrVals[0] = (H32 >> 8) & 0xff;
+ AdrCnt=2;
+ END
+ break;
+ END
+ END
+ else WrError(1350);
+ if (PPos!=Nil) *PPos=Save;
+ ChkMask(Mask,ExtMask); return;
+ END
+
+ FirstFlag=False;
+ SegType=(-1); PPos=QuotPos(Asc,':');
+ if (PPos!=Nil)
+ if (MomCPU<CPU80251)
+ BEGIN
+ WrError(1350); return;
+ END
+ else
+ BEGIN
+ SplitString(Asc,Part,Asc,PPos);
+ if (strcasecmp(Part,"S")==0) SegType=(-2);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ SegType=EvalIntExpression(Asc,UInt8,&OK);
+ if (NOT OK) return;
+ if (FirstPassUnknown) FirstFlag=True;
+ END
+ END
+
+ FirstPassUnknown=False;
+ switch (SegType)
+ BEGIN
+ case -2:
+ H32=EvalIntExpression(Asc,UInt9,&OK);
+ ChkSpace(SegIO);
+ if (FirstPassUnknown) H32=(H32 & 0xff) | 0x80;
+ break;
+ case -1:
+ H32=EvalIntExpression(Asc,UInt24,&OK);
+ default:
+ H32=EvalIntExpression(Asc,UInt16,&OK);
+ END
+ if (FirstPassUnknown) FirstFlag=True;
+
+ if ((SegType==-2) OR ((SegType==-1) AND ((TypeFlag & (1 << SegIO))!=0)))
+ BEGIN
+ if (ChkRange(H32,0x80,0xff))
+ BEGIN
+ AdrMode=ModDir8; AdrVals[0]=H32 & 0xff; AdrCnt=1;
+ END
+ END
+
+ else
+ BEGIN
+ if (SegType>=0) H32 += ((LongWord)SegType) << 16;
+ if (FirstFlag)
+ if ((MomCPU<CPU80251) OR ((Mask & ModDir16)==0)) H32 &= 0xff;
+ else H32 &= 0xffff;
+ if (((H32<128) OR ((H32<256) AND (MomCPU<CPU80251))) AND ((Mask & MModDir8)!=0))
+ BEGIN
+ if (MomCPU<CPU80251) ChkSpace(SegData);
+ AdrMode=ModDir8; AdrVals[0]=H32 &0xff; AdrCnt=1;
+ END
+ else if ((MomCPU<CPU80251) OR (H32>0xffff)) WrError(1925);
+ else
+ BEGIN
+ AdrMode=ModDir16; AdrCnt=2;
+ AdrVals[1] = H32 & 0xff;
+ AdrVals[0] = (H32 >> 8) & 0xff;
+ END
+ END
+
+ ChkMask(Mask,ExtMask);
+END
+
+ static ShortInt DecodeBitAdr(char *Asc, LongInt *Erg, Boolean MayShorten)
+BEGIN
+ Boolean OK;
+ char *PPos,Save;
+
+ if (MomCPU<CPU80251)
+ BEGIN
+ *Erg=EvalIntExpression(Asc,UInt8,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegBData);
+ return ModBit51;
+ END
+ else return ModNone;
+ END
+ else
+ BEGIN
+ PPos=RQuotPos(Asc,'.');
+ if (PPos==Nil)
+ BEGIN
+ FirstPassUnknown=False;
+ *Erg=EvalIntExpression(Asc,Int32,&OK);
+ if (FirstPassUnknown) (*Erg)&=0x070000ff;
+#ifdef __STDC__
+ if (((*Erg)&0xf8ffff00u)!=0)
+#else
+ if (((*Erg)&0xf8ffff00)!=0)
+#endif
+ BEGIN
+ WrError(1510); OK=False;
+ END
+ END
+ else
+ BEGIN
+ Save=(*PPos); *PPos='\0'; DecodeAdr(Asc,MModDir8); *PPos=Save;
+ if (AdrMode==ModNone) OK=False;
+ else
+ BEGIN
+ *Erg=EvalIntExpression(PPos+1,UInt3,&OK)<<24;
+ if (OK) (*Erg)+=AdrVals[0];
+ END
+ END
+ if (NOT OK) return ModNone;
+ else if (MayShorten)
+ if (((*Erg)&0x87)==0x80)
+ BEGIN
+ *Erg=((*Erg)&0xf8)+((*Erg)>>24); return ModBit51;
+ END
+ else if (((*Erg)&0xf0)==0x20)
+ BEGIN
+ *Erg=(((*Erg)&0x0f)<<3)+((*Erg)>>24); return ModBit51;
+ END
+ else return ModBit251;
+ else return ModBit251;
+ END
+END
+
+ static Boolean Chk504(LongInt Adr)
+BEGIN
+ return ((MomCPU==CPU80504) AND ((Adr & 0x7ff)==0x7fe));
+END
+
+ static Boolean NeedsPrefix(Word Opcode)
+BEGIN
+ return (((Opcode&0x0f)>=6) AND ((SrcMode!=0)!=((Hi(Opcode)!=0)!=0)));
+END
+
+ static void PutCode(Word Opcode)
+BEGIN
+ if (((Opcode&0x0f)<6) OR ((SrcMode!=0)!=((Hi(Opcode)==0)!=0)))
+ BEGIN
+ BAsmCode[0]=Lo(Opcode); CodeLen=1;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xa5; BAsmCode[1]=Lo(Opcode); CodeLen=2;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/* Einzelfaelle */
+
+ static void DecodeMOV(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Byte HSize,HReg;
+ Integer AdrInt;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"C")==0) OR (strcasecmp(ArgStr[1],"CY")==0))
+ BEGIN
+ switch (DecodeBitAdr(ArgStr[2],&AdrLong,True))
+ BEGIN
+ case ModBit51:
+ PutCode(0xa2);
+ BAsmCode[CodeLen] = AdrLong & 0xff;
+ CodeLen++;
+ break;
+ case ModBit251:
+ PutCode(0x1a9);
+ BAsmCode[CodeLen ] = 0xa0 +(AdrLong >> 24);
+ BAsmCode[CodeLen+1] = AdrLong & 0xff;
+ CodeLen+=2;
+ break;
+ END
+ END
+ else if ((strcasecmp(ArgStr[2],"C")==0) OR (strcasecmp(ArgStr[2],"CY")==0))
+ BEGIN
+ switch (DecodeBitAdr(ArgStr[1],&AdrLong,True))
+ BEGIN
+ case ModBit51:
+ PutCode(0x92);
+ BAsmCode[CodeLen] = AdrLong & 0xff;
+ CodeLen++;
+ break;
+ case ModBit251:
+ PutCode(0x1a9);
+ BAsmCode[CodeLen ] = 0x90 + (AdrLong >> 24);
+ BAsmCode[CodeLen+1] = AdrLong & 0xff;
+ CodeLen+=2;
+ break;
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"DPTR")==0)
+ BEGIN
+ SetOpSize(1); DecodeAdr(ArgStr[2],MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ PutCode(0x90);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ END
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModReg+MModIReg8+MModIReg+MModInd+MModDir8+MModDir16);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModReg+MModIReg8+MModIReg+MModInd+MModDir8+MModDir16+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((AdrPart<8) AND (NOT SrcMode)) PutCode(0xe8+AdrPart);
+ else if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ PutCode(0x17c);
+ BAsmCode[CodeLen++] = (AccReg << 4) + AdrPart;
+ END
+ break;
+ case ModIReg8:
+ PutCode(0xe6+AdrPart);
+ break;
+ case ModIReg:
+ PutCode(0x17e);
+ BAsmCode[CodeLen++] = (AdrPart << 4) + 0x09 + AdrSize;
+ BAsmCode[CodeLen++] = (AccReg << 4);
+ break;
+ case ModInd:
+ PutCode(0x109+(AdrSize << 4));
+ BAsmCode[CodeLen++] = (AccReg << 4) + AdrPart;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ case ModDir8:
+ PutCode(0xe5);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ case ModDir16:
+ PutCode(0x17e);
+ BAsmCode[CodeLen++] = (AccReg << 4) + 0x03;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ case ModImm:
+ PutCode(0x74);
+ BAsmCode[CodeLen++]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg+MModIReg8+MModIReg+MModInd+MModDir8+MModDir16+MModImm+MModImmEx);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((OpSize==0) AND (AdrPart==AccReg) AND (HReg<8)) PutCode(0xf8+HReg);
+ else if ((OpSize==0) AND (HReg==AccReg) AND (AdrPart<8)) PutCode(0xe8+AdrPart);
+ else if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ PutCode(0x17c+OpSize);
+ if (OpSize==2) BAsmCode[CodeLen-1]++;
+ BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
+ END
+ break;
+ case ModIReg8:
+ if ((OpSize!=0) OR (HReg!=AccReg)) WrError(1350);
+ else PutCode(0xe6+AdrPart);
+ break;
+ case ModIReg:
+ if (OpSize==0)
+ BEGIN
+ PutCode(0x17e);
+ BAsmCode[CodeLen++] = (AdrPart << 4) + 0x09 + AdrSize;
+ BAsmCode[CodeLen++] = HReg << 4;
+ END
+ else if (OpSize==1)
+ BEGIN
+ PutCode(0x10b);
+ BAsmCode[CodeLen++] = (AdrPart << 4) + 0x08 + AdrSize;
+ BAsmCode[CodeLen++] = HReg << 4;
+ END
+ else WrError(1350);
+ break;
+ case ModInd:
+ if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x109+(AdrSize << 4)+(OpSize << 6));
+ BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ break;
+ case ModDir8:
+ if ((OpSize==0) AND (HReg==AccReg))
+ BEGIN
+ PutCode(0xe5);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ else if ((OpSize==0) AND (HReg<8) AND (NOT SrcMode))
+ BEGIN
+ PutCode(0xa8+HReg);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ else if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ PutCode(0x17e);
+ BAsmCode[CodeLen++] = 0x01 + (HReg << 4) + (OpSize << 2);
+ if (OpSize==2) BAsmCode[CodeLen-1]+=4;
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ break;
+ case ModDir16:
+ PutCode(0x17e);
+ BAsmCode[CodeLen++] = 0x03 + (HReg << 4) + (OpSize << 2);
+ if (OpSize==2) BAsmCode[CodeLen-1]+=4;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ case ModImm:
+ if ((OpSize==0) AND (HReg==AccReg))
+ BEGIN
+ PutCode(0x74);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ else if ((OpSize==0) AND (HReg<8) AND (NOT SrcMode))
+ BEGIN
+ PutCode(0x78+HReg);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ else if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ PutCode(0x17e);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ break;
+ case ModImmEx:
+ PutCode(0x17e);
+ BAsmCode[CodeLen++]=0x0c + (HReg << 4);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ END
+ break;
+ case ModIReg8:
+ SetOpSize(0); HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModAcc+MModDir8+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ PutCode(0xf6+HReg);
+ break;
+ case ModDir8:
+ PutCode(0xa6+HReg);
+ BAsmCode[CodeLen++]=AdrVals[0];
+ break;
+ case ModImm:
+ PutCode(0x76+HReg);
+ BAsmCode[CodeLen++]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModIReg:
+ HReg=AdrPart; HSize=AdrSize;
+ DecodeAdr(ArgStr[2],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize==0)
+ BEGIN
+ PutCode(0x17a);
+ BAsmCode[CodeLen++] = (HReg << 4) + 0x09 + HSize;
+ BAsmCode[CodeLen++] = AdrPart << 4;
+ END
+ else if (OpSize==1)
+ BEGIN
+ PutCode(0x11b);
+ BAsmCode[CodeLen++] = (HReg << 4) + 0x08 + HSize;
+ BAsmCode[CodeLen++] = AdrPart << 4;
+ END
+ else WrError(1350);
+ END
+ break;
+ case ModInd:
+ HReg=AdrPart; HSize=AdrSize;
+ AdrInt=(((Word)AdrVals[0])<<8)+AdrVals[1];
+ DecodeAdr(ArgStr[2],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x119 + (HSize << 4) + (OpSize << 6));
+ BAsmCode[CodeLen++] = (AdrPart << 4) + HReg;
+ BAsmCode[CodeLen++] = Hi(AdrInt);
+ BAsmCode[CodeLen++] = Lo(AdrInt);
+ END
+ END
+ break;
+ case ModDir8:
+ MinOneIs0=True; HReg=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModReg+MModIReg8+MModDir8+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((OpSize==0) AND (AdrPart==AccReg))
+ BEGIN
+ PutCode(0xf5);
+ BAsmCode[CodeLen++] = HReg;
+ END
+ else if ((OpSize==0) AND (AdrPart<8) AND (NOT SrcMode))
+ BEGIN
+ PutCode(0x88+AdrPart);
+ BAsmCode[CodeLen++] = HReg;
+ END
+ else if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ PutCode(0x17a);
+ BAsmCode[CodeLen++] = 0x01 + (AdrPart << 4) + (OpSize << 2);
+ if (OpSize==2) BAsmCode[CodeLen-1]+=4;
+ BAsmCode[CodeLen++] = HReg;
+ END
+ break;
+ case ModIReg8:
+ PutCode(0x86+AdrPart);
+ BAsmCode[CodeLen++] = HReg;
+ break;
+ case ModDir8:
+ PutCode(0x85);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ BAsmCode[CodeLen++] = HReg;
+ break;
+ case ModImm:
+ PutCode(0x75);
+ BAsmCode[CodeLen++] = HReg;
+ BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ END
+ break;
+ case ModDir16:
+ AdrInt=(((Word)AdrVals[0]) << 8) + AdrVals[1];
+ DecodeAdr(ArgStr[2],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ PutCode(0x17a);
+ BAsmCode[CodeLen++]=0x03 + (AdrPart << 4) + (OpSize << 2);
+ if (OpSize==2) BAsmCode[CodeLen-1]+=4;
+ BAsmCode[CodeLen++] = Hi(AdrInt);
+ BAsmCode[CodeLen++] = Lo(AdrInt);
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeLogic(Word Index)
+BEGIN
+ Boolean InvFlag;
+ Byte HReg;
+ LongInt AdrLong;
+ int z;
+
+ /* Index: ORL=0 ANL=1 XRL=2 */
+
+ if (ArgCnt!=2) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"C")==0) OR (strcasecmp(ArgStr[1],"CY")==0))
+ BEGIN
+ if (Index==2) WrError(1350);
+ else
+ BEGIN
+ HReg=Index << 4;
+ InvFlag=(*ArgStr[2]=='/');
+ if (InvFlag) strcpy(ArgStr[2],ArgStr[2]+1);
+ switch (DecodeBitAdr(ArgStr[2],&AdrLong,True))
+ BEGIN
+ case ModBit51:
+ PutCode((InvFlag) ? 0xa0+HReg : 0x72+HReg);
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ break;
+ case ModBit251:
+ PutCode(0x1a9);
+ BAsmCode[CodeLen++] = ((InvFlag) ? 0xe0 : 0x70) + HReg + (AdrLong >>24);
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ break;
+ END
+ END
+ END
+ else
+ BEGIN
+ z=(Index << 4)+0x40;
+ DecodeAdr(ArgStr[1],MModAcc+MModReg+MModDir8);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModReg+MModIReg8+MModIReg+MModDir8+MModDir16+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((AdrPart<8) AND (NOT SrcMode)) PutCode(z+8+AdrPart);
+ else
+ BEGIN
+ PutCode(z+0x10c);
+ BAsmCode[CodeLen++] = AdrPart + (AccReg << 4);
+ END
+ break;
+ case ModIReg8:
+ PutCode(z+6+AdrPart);
+ break;
+ case ModIReg:
+ PutCode(z+0x10e);
+ BAsmCode[CodeLen++] = 0x09 + AdrSize + (AdrPart << 4);
+ BAsmCode[CodeLen++] = AccReg << 4;
+ break;
+ case ModDir8:
+ PutCode(z+0x05);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ case ModDir16:
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = 0x03 + (AccReg << 4);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ case ModImm:
+ PutCode(z+0x04);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ END
+ break;
+ case ModReg:
+ if (MomCPU<CPU80251) WrError(1350);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg+MModIReg8+MModIReg+MModDir8+MModDir16+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(z+0x10c+OpSize);
+ BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
+ END
+ break;
+ case ModIReg8:
+ if ((OpSize!=0) OR (HReg!=AccReg)) WrError(1350);
+ else PutCode(z+0x06+AdrPart);
+ break;
+ case ModIReg:
+ if (OpSize!=0) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = 0x09 + AdrSize + (AdrPart << 4);
+ BAsmCode[CodeLen++] = HReg << 4;
+ END
+ break;
+ case ModDir8:
+ if ((OpSize==0) AND (HReg==AccReg))
+ BEGIN
+ PutCode(0x05+z);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ else if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2) + 1;
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ break;
+ case ModDir16:
+ if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2) + 3;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ break;
+ case ModImm:
+ if ((OpSize==0) AND (HReg==AccReg))
+ BEGIN
+ PutCode(0x04+z);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ else if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ break;
+ END
+ END
+ break;
+ case ModDir8:
+ HReg=AdrVals[0]; SetOpSize(0);
+ DecodeAdr(ArgStr[2],MModAcc+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ PutCode(z+0x02);
+ BAsmCode[CodeLen++] = HReg;
+ break;
+ case ModImm:
+ PutCode(z+0x03);
+ BAsmCode[CodeLen++] = HReg;
+ BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeMOVC(Word Index)
+BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ if (strcasecmp(ArgStr[2],"@A+DPTR")==0) PutCode(0x93);
+ else if (strcasecmp(ArgStr[2],"@A+PC")==0) PutCode(0x83);
+ else WrError(1350);
+ break;
+ END
+ END
+END
+
+ static void DecodeMOVH(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80251) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize!=2) WrError(1350);
+ else
+ BEGIN
+ HReg=AdrPart; OpSize--;
+ DecodeAdr(ArgStr[2],MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ PutCode(0x17a);
+ BAsmCode[CodeLen++] = 0x0c + (HReg << 4);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ END
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeMOVZS(Word Index)
+BEGIN
+ Byte HReg;
+ int z;
+
+ z=Ord(Memo("MOVS")) << 4;
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80251) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize!=1) WrError(1350);
+ else
+ BEGIN
+ HReg=AdrPart; OpSize--;
+ DecodeAdr(ArgStr[2],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ PutCode(0x10a+z);
+ BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
+ break;
+ END
+ END
+ break;
+ END
+ END
+ return;
+END
+
+ static void DecodeMOVX(Word Index)
+BEGIN
+ int z;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ z=0;
+ if ((strcasecmp(ArgStr[2],"A")==0) OR ((MomCPU>=CPU80251) AND (strcasecmp(ArgStr[2],"R11")==0)))
+ BEGIN
+ z=0x10; strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"A",255);
+ END
+ if ((strcasecmp(ArgStr[1],"A")!=0) AND ((MomCPU<CPU80251) OR (strcasecmp(ArgStr[2],"R11")==0))) WrError(1350);
+ else if (strcasecmp(ArgStr[2],"@DPTR")==0) PutCode(0xe0+z);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModIReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModIReg8:
+ PutCode(0xe2+AdrPart+z);
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeStack(Word Index)
+BEGIN
+ int z;
+
+ /* Index: PUSH=0 POP=1 PUSHW=2 */
+
+ z=(Index&1) << 4;
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]=='#') SetOpSize(Ord(Index==2));
+ if (z==0x10) DecodeAdr(ArgStr[1],MModDir8+MModReg);
+ else DecodeAdr(ArgStr[1],MModDir8+MModReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModDir8:
+ PutCode(0xc0+z);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ case ModReg:
+ if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ PutCode(0x1ca+z);
+ BAsmCode[CodeLen++] = 0x08 + (AdrPart << 4) + OpSize + (Ord(OpSize == 2));
+ END
+ break;
+ case ModImm:
+ if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ PutCode(0x1ca);
+ BAsmCode[CodeLen++] = 0x02 + (OpSize << 2);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeXCH(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModReg+MModIReg8+MModDir8);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModReg+MModIReg8+MModDir8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (AdrPart>7) WrError(1350);
+ else PutCode(0xc8+AdrPart);
+ break;
+ case ModIReg8:
+ PutCode(0xc6+AdrPart);
+ break;
+ case ModDir8:
+ PutCode(0xc5);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ END
+ break;
+ case ModReg:
+ if ((OpSize!=0) OR (AdrPart>7)) WrError(1350);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ PutCode(0xc8+HReg);
+ break;
+ END
+ END
+ break;
+ case ModIReg8:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ PutCode(0xc6+HReg);
+ break;
+ END
+ break;
+ case ModDir8:
+ HReg=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ PutCode(0xc5);
+ BAsmCode[CodeLen++] = HReg;
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeXCHD(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModIReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModIReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModIReg8:
+ PutCode(0xd6+AdrPart);
+ break;
+ END
+ break;
+ case ModIReg8:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ PutCode(0xd6+HReg);
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeABranch(Word Index)
+BEGIN
+ Boolean OK;
+ LongInt AdrLong;
+
+ /* Index: AJMP=0 ACALL=1 */
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int24,&OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND (((EProgCounter()+2) >> 11)!=(AdrLong >> 11))) WrError(1910);
+ else if (Chk504(EProgCounter())) WrError(1900);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ PutCode(0x01 + (Index << 4) + ((Hi(AdrLong) & 7) << 5));
+ BAsmCode[CodeLen++]=Lo(AdrLong);
+ END
+ END
+END
+
+ static void DecodeLBranch(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ /* Index: LJMP=0 LCALL=1 */
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU8051) WrError(1500);
+ else if (*ArgStr[1]=='@')
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIReg);
+ switch (AdrMode)
+ BEGIN
+ case ModIReg:
+ if (AdrSize!=0) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x189 + (Index << 4));
+ BAsmCode[CodeLen++] = 0x04 + (AdrPart << 4);
+ END
+ break;
+ END
+ END
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int24,&OK);
+ if (OK)
+ if ((MomCPU>=CPU80251) AND (((EProgCounter()+3) >> 16)!=(AdrLong >> 16))) WrError(1910);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ PutCode(0x02 + (Index << 4));
+ BAsmCode[CodeLen++] = (AdrLong >> 8) & 0xff;
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ END
+END
+
+ static void DecodeEBranch(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ /* Index: AJMP=0 ACALL=1 */
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU80251) WrError(1500);
+ else if (*ArgStr[1]=='@')
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIReg);
+ switch (AdrMode)
+ BEGIN
+ case ModIReg:
+ if (AdrSize!=2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x189 + (Index << 4));
+ BAsmCode[CodeLen++] = 0x08 + (AdrPart << 4);
+ END
+ break;
+ END
+ END
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+ PutCode(0x18a + (Index << 4));
+ BAsmCode[CodeLen++] = (AdrLong >> 16) & 0xff;
+ BAsmCode[CodeLen++] = (AdrLong >> 8) & 0xff;
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ END
+END
+
+ static void DecodeJMP(Word Index)
+BEGIN
+ LongInt AdrLong,Dist;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"@A+DPTR")==0) PutCode(0x73);
+ else if (*ArgStr[1]=='@')
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIReg);
+ switch (AdrMode)
+ BEGIN
+ case ModIReg:
+ PutCode(0x189);
+ BAsmCode[CodeLen++] = 0x04 + (AdrSize << 1) + (AdrPart << 4);
+ break;
+ END
+ END
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ Dist=AdrLong-(EProgCounter()+2);
+ if ((Dist<=127) AND (Dist>=-128))
+ BEGIN
+ PutCode(0x80);
+ BAsmCode[CodeLen++] = Dist & 0xff;
+ END
+ else if ((NOT Chk504(EProgCounter())) AND ((AdrLong >> 11)==((EProgCounter()+2) >> 11)))
+ BEGIN
+ PutCode(0x01 + ((Hi(AdrLong) & 7) << 5));
+ BAsmCode[CodeLen++] = Lo(AdrLong);
+ END
+ else if (MomCPU<CPU8051) WrError(1910);
+ else if (((EProgCounter()+3) >> 16)==(AdrLong >> 16))
+ BEGIN
+ PutCode(0x02);
+ BAsmCode[CodeLen++] = Hi(AdrLong);
+ BAsmCode[CodeLen++] = Lo(AdrLong);
+ END
+ else if (MomCPU<CPU80251) WrError(1910);
+ else
+ BEGIN
+ PutCode(0x18a);
+ BAsmCode[CodeLen++] =(AdrLong >> 16) & 0xff;
+ BAsmCode[CodeLen++] =(AdrLong >> 8) & 0xff;
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ END
+ END
+END
+
+ static void DecodeCALL(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]=='@')
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIReg);
+ switch (AdrMode)
+ BEGIN
+ case ModIReg:
+ PutCode(0x199);
+ BAsmCode[CodeLen++] = 0x04 + (AdrSize << 1) + (AdrPart << 4);
+ break;
+ END
+ END
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ if ((NOT Chk504(EProgCounter())) AND ((AdrLong >> 11)==((EProgCounter()+2) >> 11)))
+ BEGIN
+ PutCode(0x11 + ((Hi(AdrLong) & 7) << 5));
+ BAsmCode[CodeLen++] = Lo(AdrLong);
+ END
+ else if (MomCPU<CPU8051) WrError(1910);
+ else if ((AdrLong >> 16)!=((EProgCounter()+3) >> 16)) WrError(1910);
+ else
+ BEGIN
+ PutCode(0x12);
+ BAsmCode[CodeLen++] = Hi(AdrLong);
+ BAsmCode[CodeLen++] = Lo(AdrLong);
+ END
+ END
+ END
+END
+
+ static void DecodeDJNZ(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK,Questionable;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[2],UInt24,&OK);
+ Questionable=SymbolQuestionable;
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModDir8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((OpSize!=0) OR (AdrPart>7)) WrError(1350);
+ else
+ BEGIN
+ AdrLong-=EProgCounter()+2+Ord(NeedsPrefix(0xd8+AdrPart));
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT Questionable)) WrError(1370);
+ else
+ BEGIN
+ PutCode(0xd8+AdrPart);
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ END
+ break;
+ case ModDir8:
+ AdrLong-=EProgCounter()+3+Ord(NeedsPrefix(0xd5));
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT Questionable)) WrError(1370);
+ else
+ BEGIN
+ PutCode(0xd5);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ BAsmCode[CodeLen++] = Lo(AdrLong);
+ END
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeCJNE(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK,Questionable;
+ Byte HReg;
+
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[3],UInt24,&OK);
+ Questionable=SymbolQuestionable;
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModIReg8+MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModDir8+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModDir8:
+ AdrLong-=EProgCounter()+3+Ord(NeedsPrefix(0xb5));
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT Questionable)) WrError(1370);
+ else
+ BEGIN
+ PutCode(0xb5);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ break;
+ case ModImm:
+ AdrLong-=EProgCounter()+3+Ord(NeedsPrefix(0xb5));
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT Questionable)) WrError(1370);
+ else
+ BEGIN
+ PutCode(0xb4);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ break;
+ END
+ break;
+ case ModReg:
+ if ((OpSize!=0) OR (AdrPart>7)) WrError(1350);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ AdrLong-=EProgCounter()+3+Ord(NeedsPrefix(0xb8+HReg));
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT Questionable)) WrError(1370);
+ else
+ BEGIN
+ PutCode(0xb8+HReg);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ break;
+ END
+ END
+ break;
+ case ModIReg8:
+ HReg=AdrPart; SetOpSize(0);
+ DecodeAdr(ArgStr[2],MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ AdrLong-=EProgCounter()+3+Ord(NeedsPrefix(0xb6+HReg));
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT Questionable)) WrError(1370);
+ else
+ BEGIN
+ PutCode(0xb6+HReg);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ break;
+ END
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeADD(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModImm+MModDir8+MModDir16+MModIReg8+MModIReg+MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ PutCode(0x24); BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ case ModDir8:
+ PutCode(0x25); BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ case ModDir16:
+ PutCode(0x12e);
+ BAsmCode[CodeLen++] = (AccReg << 4) + 3;
+ memcpy(BAsmCode+CodeLen,AdrVals,2);
+ CodeLen+=2;
+ break;
+ case ModIReg8:
+ PutCode(0x26+AdrPart);
+ break;
+ case ModIReg:
+ PutCode(0x12e);
+ BAsmCode[CodeLen++] = 0x09 + AdrSize + (AdrPart << 4);
+ BAsmCode[CodeLen++] = AccReg << 4;
+ break;
+ case ModReg:
+ if ((AdrPart<8) AND (NOT SrcMode)) PutCode(0x28+AdrPart);
+ else if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ PutCode(0x12c);
+ BAsmCode[CodeLen++] = AdrPart + (AccReg << 4);
+ END;
+ break;
+ END
+ break;
+ case ModReg:
+ if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModImm+MModReg+MModDir8+MModDir16+MModIReg8+MModIReg);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ if ((OpSize==0) AND (HReg==AccReg))
+ BEGIN
+ PutCode(0x24);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ else
+ BEGIN
+ PutCode(0x12e);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ break;
+ case ModReg:
+ PutCode(0x12c+OpSize);
+ if (OpSize==2) BAsmCode[CodeLen-1]++;
+ BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
+ break;
+ case ModDir8:
+ if (OpSize==2) WrError(1350);
+ else if ((OpSize==0) AND (HReg==AccReg))
+ BEGIN
+ PutCode(0x25);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ else
+ BEGIN
+ PutCode(0x12e);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2) + 1;
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ break;
+ case ModDir16:
+ if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x12e);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2) + 3;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ break;
+ case ModIReg8:
+ if ((OpSize!=0) OR (HReg!=AccReg)) WrError(1350);
+ else PutCode(0x26+AdrPart);
+ break;
+ case ModIReg:
+ if (OpSize!=0) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x12e);
+ BAsmCode[CodeLen++] = 0x09 + AdrSize + (AdrPart << 4);
+ BAsmCode[CodeLen++] = HReg << 4;
+ END
+ break;
+ END
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeSUBCMP(Word Index)
+BEGIN
+ int z;
+ Byte HReg;
+
+ /* Index: SUB=0 CMP=1 */
+
+ z=0x90+(Index<<5);
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80251) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ HReg=AdrPart;
+ if (Memo("CMP"))
+ DecodeAdr(ArgStr[2],MModImm+MModImmEx+MModReg+MModDir8+MModDir16+MModIReg);
+ else
+ DecodeAdr(ArgStr[2],MModImm+MModReg+MModDir8+MModDir16+MModIReg);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ case ModImmEx:
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = (HReg << 4) + 0x0c;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ case ModReg:
+ PutCode(0x10c + z + OpSize);
+ if (OpSize==2) BAsmCode[CodeLen-1]++;
+ BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
+ break;
+ case ModDir8:
+ if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2) + 1;
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ break;
+ case ModDir16:
+ if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = (HReg << 4) + (OpSize << 2) + 3;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ break;
+ case ModIReg:
+ if (OpSize!=0) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = 0x09 + AdrSize + (AdrPart << 4);
+ BAsmCode[CodeLen++] = HReg << 4;
+ END
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeADDCSUBB(Word Index)
+BEGIN
+ Byte HReg;
+
+ /* Index: ADDC=0 SUBB=1 */
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ HReg=0x30+(Index*0x60);
+ DecodeAdr(ArgStr[2],MModReg+MModIReg8+MModDir8+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (AdrPart>7) WrError(1350);
+ else PutCode(HReg+0x08+AdrPart);
+ break;
+ case ModIReg8:
+ PutCode(HReg+0x06+AdrPart);
+ break;
+ case ModDir8:
+ PutCode(HReg+0x05);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ case ModImm:
+ PutCode(HReg+0x04);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeINCDEC(Word Index)
+BEGIN
+ Byte HReg;
+ int z;
+ Boolean OK;
+
+ /* Index: INC=0 DEC=1 */
+
+ if (ArgCnt==1) strmaxcpy(ArgStr[++ArgCnt],"#1",255);
+ z=Index << 4;
+ if (ArgCnt!=2) WrError(1110);
+ else if (*ArgStr[2]!='#') WrError(1350);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ HReg=EvalIntExpression(ArgStr[2]+1,UInt3,&OK);
+ if (FirstPassUnknown) HReg=1;
+ if (OK)
+ BEGIN
+ OK=True;
+ if (HReg==1) HReg=0;
+ else if (HReg==2) HReg=1;
+ else if (HReg==4) HReg=2;
+ else OK=False;
+ if (NOT OK) WrError(1320);
+ else if (strcasecmp(ArgStr[1],"DPTR")==0)
+ BEGIN
+ if (Index==1) WrError(1350);
+ else if (HReg!=0) WrError(1320);
+ else PutCode(0xa3);
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModReg+MModDir8+MModIReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ if (HReg==0) PutCode(0x04+z);
+ else if (MomCPU<CPU80251) WrError(1320);
+ else
+ BEGIN
+ PutCode(0x10b+z);
+ BAsmCode[CodeLen++] = (AccReg << 4) + HReg;
+ END
+ break;
+ case ModReg:
+ if ((OpSize==0) AND (AdrPart==AccReg) AND (HReg==0)) PutCode(0x04+z);
+ else if ((AdrPart<8) AND (OpSize==0) AND (HReg==0) AND (NOT SrcMode)) PutCode(0x08+z+AdrPart);
+ else if (MomCPU<CPU80251) WrError(1505);
+ else
+ BEGIN
+ PutCode(0x10b+z);
+ BAsmCode[CodeLen++] = (AdrPart << 4) + (OpSize << 2) + HReg;
+ if (OpSize==2) BAsmCode[CodeLen-1]+=4;
+ END
+ break;
+ case ModDir8:
+ if (HReg!=0) WrError(1320);
+ else
+ BEGIN
+ PutCode(0x05+z);
+ BAsmCode[CodeLen++] = AdrVals[0];
+ END
+ break;
+ case ModIReg8:
+ if (HReg!=0) WrError(1320);
+ else PutCode(0x06+z+AdrPart);
+ break;
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeMULDIV(Word Index)
+BEGIN
+ int z;
+ Byte HReg;
+
+ /* Index: DIV=0 MUL=1 */
+
+ z=Index << 5;
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (ArgCnt==1)
+ BEGIN
+ if (strcasecmp(ArgStr[1],"AB")!=0) WrError(1350);
+ else PutCode(0x84+z);
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (MomCPU<CPU80251) WrError(1505);
+ else if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x18c+z+OpSize);
+ BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
+ END
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeBits(Word Index)
+BEGIN
+ LongInt AdrLong;
+ int z;
+
+ /* Index: CPL=0 CLR=1 SETB=2 */
+
+ z=Index<<4;
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")==0)
+ BEGIN
+ if (Memo("SETB")) WrError(1350);
+ else PutCode(0xf4-z);
+ END
+ else if ((strcasecmp(ArgStr[1],"C")==0) OR (strcasecmp(ArgStr[1],"CY")==0))
+ PutCode(0xb3+z);
+ else
+ switch (DecodeBitAdr(ArgStr[1],&AdrLong,True))
+ BEGIN
+ case ModBit51:
+ PutCode(0xb2+z);
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ break;
+ case ModBit251:
+ PutCode(0x1a9);
+ BAsmCode[CodeLen++] = 0xb0 + z + (AdrLong >> 24);
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ break;
+ END
+END
+
+ static void DecodeShift(Word Index)
+BEGIN
+ int z;
+
+ /* Index: SRA=0 SRL=1 SLL=3 */
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU80251) WrError(1500);
+ else
+ BEGIN
+ z=Index<<4;
+ DecodeAdr(ArgStr[1],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize==2) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x10e + z);
+ BAsmCode[CodeLen++] = (AdrPart << 4) + (OpSize << 2);
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeCond(Word Index)
+BEGIN
+ FixedOrder *FixedZ=CondOrders+Index;
+ LongInt AdrLong;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<FixedZ->MinCPU) WrError(1500);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ AdrLong-=EProgCounter()+2+Ord(NeedsPrefix(FixedZ->Code));
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ PutCode(FixedZ->Code);
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ END
+ END
+END
+
+ static void DecodeBCond(Word Index)
+BEGIN
+ FixedOrder *FixedZ=BCondOrders+Index;
+ LongInt AdrLong,BitLong;
+ Boolean OK,Questionable;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[2],UInt24,&OK);
+ Questionable=SymbolQuestionable;
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+ switch (DecodeBitAdr(ArgStr[1],&BitLong,True))
+ BEGIN
+ case ModBit51:
+ AdrLong-=EProgCounter()+3+Ord(NeedsPrefix(FixedZ->Code));
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT Questionable)) WrError(1370);
+ else
+ BEGIN
+ PutCode(FixedZ->Code);
+ BAsmCode[CodeLen++] = BitLong & 0xff;
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ break;
+ case ModBit251:
+ AdrLong-=EProgCounter()+4+Ord(NeedsPrefix(0x1a9));
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT Questionable)) WrError(1370);
+ else
+ BEGIN
+ PutCode(0x1a9);
+ BAsmCode[CodeLen++] = FixedZ->Code+(BitLong >> 24);
+ BAsmCode[CodeLen++] = BitLong & 0xff;
+ BAsmCode[CodeLen++] = AdrLong & 0xff;
+ END
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeAcc(Word Index)
+BEGIN
+ FixedOrder *FixedZ=AccOrders+Index;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<FixedZ->MinCPU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ PutCode(FixedZ->Code);
+ break;
+ END
+ END;
+END
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *FixedZ=FixedOrders+Index;
+
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<FixedZ->MinCPU) WrError(1500);
+ else PutCode(FixedZ->Code);
+END
+
+
+ static void DecodeSFR(Word Index)
+BEGIN
+ Word AdrByte;
+ Boolean OK;
+ int z,DSeg;
+ String s;
+
+ FirstPassUnknown=False;
+ if (ArgCnt!=1) WrError(1110);
+ else if ((Memo("SFRB")) AND (MomCPU>=CPU80251)) WrError(1500);
+ else
+ BEGIN
+ if (MomCPU>=CPU80251) AdrByte=EvalIntExpression(ArgStr[1],UInt9,&OK);
+ else AdrByte=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ PushLocHandle(-1);
+ DSeg=(MomCPU>=CPU80251)?(SegIO):(SegData);
+ EnterIntSymbol(LabPart,AdrByte,DSeg,False);
+ if (MakeUseList)
+ if (AddChunk(SegChunks+DSeg,AdrByte,1,False)) WrError(90);
+ if (Memo("SFRB"))
+ BEGIN
+ if (AdrByte>0x7f)
+ BEGIN
+ if ((AdrByte & 7)!=0) WrError(220);
+ END
+ else
+ BEGIN
+ if ((AdrByte & 0xe0)!=0x20) WrError(220);
+ AdrByte=(AdrByte-0x20) << 3;
+ END
+ for (z=0; z<8; z++)
+ BEGIN
+ sprintf(s,"%s.%c",LabPart,z+'0');
+ EnterIntSymbol(s,AdrByte+z,SegBData,False);
+ END
+ if (MakeUseList)
+ if (AddChunk(SegChunks+SegBData,AdrByte,8,False)) WrError(90);
+ sprintf(ListLine,"=%sH-",HexString(AdrByte,2));
+ strmaxcat(ListLine,HexString(AdrByte+7,2),255);
+ strmaxcat(ListLine,"H",255);
+ END
+ else sprintf(ListLine,"=%sH",HexString(AdrByte,2));
+ PopLocHandle();
+ END
+ END
+END
+
+ static void DecodeBIT(Word Index)
+BEGIN
+ LongInt AdrLong;
+
+ if (MomCPU>=CPU80251)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeBitAdr(ArgStr[1],&AdrLong,False)==ModBit251)
+ BEGIN
+ EnterIntSymbol(LabPart,AdrLong,SegNone,False);
+ sprintf(ListLine,"=%sH.%s",HexString(AdrLong&0xff,2),HexString(AdrLong>>24,1));
+ END
+ END
+ else CodeEquate(SegBData,0,0xff);
+END
+
+ static void DecodePORT(Word Index)
+BEGIN
+ if (MomCPU<CPU80251) WrError(1500);
+ else CodeEquate(SegIO,0,0x1ff);
+END
+
+/*-------------------------------------------------------------------------*/
+/* dynamische Codetabellenverwaltung */
+
+ static void AddFixed(char *NName, Word NCode, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ].MinCPU=NCPU;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
+END
+
+ static void AddAcc(char *NName, Word NCode, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=AccOrderCnt) exit(255);
+ AccOrders[InstrZ].Code=NCode;
+ AccOrders[InstrZ].MinCPU=NCPU;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeAcc);
+END
+
+ static void AddCond(char *NName, Word NCode, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=CondOrderCnt) exit(255);
+ CondOrders[InstrZ].Code=NCode;
+ CondOrders[InstrZ].MinCPU=NCPU;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeCond);
+END
+
+ static void AddBCond(char *NName, Word NCode, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=BCondOrderCnt) exit(255);
+ BCondOrders[InstrZ].Code=NCode;
+ BCondOrders[InstrZ].MinCPU=NCPU;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeBCond);
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(203);
+ AddInstTable(InstTable,"MOV" , 0,DecodeMOV);
+ AddInstTable(InstTable,"ANL" , 1,DecodeLogic);
+ AddInstTable(InstTable,"ORL" , 0,DecodeLogic);
+ AddInstTable(InstTable,"XRL" , 2,DecodeLogic);
+ AddInstTable(InstTable,"MOVC" , 0,DecodeMOVC);
+ AddInstTable(InstTable,"MOVH" , 0,DecodeMOVH);
+ AddInstTable(InstTable,"MOVZ" , 0,DecodeMOVZS);
+ AddInstTable(InstTable,"MOVS" , 0,DecodeMOVZS);
+ AddInstTable(InstTable,"MOVX" , 0,DecodeMOVX);
+ AddInstTable(InstTable,"POP" , 1,DecodeStack);
+ AddInstTable(InstTable,"PUSH" , 0,DecodeStack);
+ AddInstTable(InstTable,"PUSHW", 2,DecodeStack);
+ AddInstTable(InstTable,"XCH" , 0,DecodeXCH);
+ AddInstTable(InstTable,"XCHD" , 0,DecodeXCHD);
+ AddInstTable(InstTable,"AJMP" , 0,DecodeABranch);
+ AddInstTable(InstTable,"ACALL", 1,DecodeABranch);
+ AddInstTable(InstTable,"LJMP" , 0,DecodeLBranch);
+ AddInstTable(InstTable,"LCALL", 1,DecodeLBranch);
+ AddInstTable(InstTable,"EJMP" , 0,DecodeEBranch);
+ AddInstTable(InstTable,"ECALL", 1,DecodeEBranch);
+ AddInstTable(InstTable,"JMP" , 0,DecodeJMP);
+ AddInstTable(InstTable,"CALL" , 0,DecodeCALL);
+ AddInstTable(InstTable,"DJNZ" , 0,DecodeDJNZ);
+ AddInstTable(InstTable,"CJNE" , 0,DecodeCJNE);
+ AddInstTable(InstTable,"ADD" , 0,DecodeADD);
+ AddInstTable(InstTable,"SUB" , 0,DecodeSUBCMP);
+ AddInstTable(InstTable,"CMP" , 1,DecodeSUBCMP);
+ AddInstTable(InstTable,"ADDC" , 0,DecodeADDCSUBB);
+ AddInstTable(InstTable,"SUBB" , 1,DecodeADDCSUBB);
+ AddInstTable(InstTable,"INC" , 0,DecodeINCDEC);
+ AddInstTable(InstTable,"DEC" , 1,DecodeINCDEC);
+ AddInstTable(InstTable,"MUL" , 1,DecodeMULDIV);
+ AddInstTable(InstTable,"DIV" , 0,DecodeMULDIV);
+ AddInstTable(InstTable,"CLR" , 1,DecodeBits);
+ AddInstTable(InstTable,"CPL" , 0,DecodeBits);
+ AddInstTable(InstTable,"SETB" , 2,DecodeBits);
+ AddInstTable(InstTable,"SRA" , 0,DecodeShift);
+ AddInstTable(InstTable,"SRL" , 1,DecodeShift);
+ AddInstTable(InstTable,"SLL" , 3,DecodeShift);
+ AddInstTable(InstTable,"SFR" , 0,DecodeSFR);
+ AddInstTable(InstTable,"SFRB" , 1,DecodeSFR);
+ AddInstTable(InstTable,"BIT" , 0,DecodeBIT);
+ AddInstTable(InstTable,"PORT" , 0,DecodePORT);
+
+ FixedOrders=(FixedOrder *) malloc(FixedOrderCnt*sizeof(FixedOrder));
+ InstrZ=0;
+ AddFixed("NOP" ,0x0000,CPU87C750);
+ AddFixed("RET" ,0x0022,CPU87C750);
+ AddFixed("RETI",0x0032,CPU87C750);
+ AddFixed("ERET",0x01aa,CPU80251);
+ AddFixed("TRAP",0x01b9,CPU80251);
+
+ AccOrders=(FixedOrder *) malloc(AccOrderCnt*sizeof(FixedOrder));
+ InstrZ=0;
+ AddAcc("DA" ,0x00d4,CPU87C750);
+ AddAcc("RL" ,0x0023,CPU87C750);
+ AddAcc("RLC" ,0x0033,CPU87C750);
+ AddAcc("RR" ,0x0003,CPU87C750);
+ AddAcc("RRC" ,0x0013,CPU87C750);
+ AddAcc("SWAP",0x00c4,CPU87C750);
+
+ CondOrders=(FixedOrder *) malloc(CondOrderCnt*sizeof(FixedOrder));
+ InstrZ=0;
+ AddCond("JC" ,0x0040,CPU87C750);
+ AddCond("JE" ,0x0168,CPU80251);
+ AddCond("JG" ,0x0138,CPU80251);
+ AddCond("JLE" ,0x0128,CPU80251);
+ AddCond("JNC" ,0x0050,CPU87C750);
+ AddCond("JNE" ,0x0178,CPU80251);
+ AddCond("JNZ" ,0x0070,CPU87C750);
+ AddCond("JSG" ,0x0118,CPU80251);
+ AddCond("JSGE",0x0158,CPU80251);
+ AddCond("JSL" ,0x0148,CPU80251);
+ AddCond("JSLE",0x0108,CPU80251);
+ AddCond("JZ" ,0x0060,CPU87C750);
+ AddCond("SJMP",0x0080,CPU87C750);
+
+ BCondOrders=(FixedOrder *) malloc(BCondOrderCnt*sizeof(FixedOrder));
+ InstrZ=0;
+ AddBCond("JB" ,0x0020,CPU87C750);
+ AddBCond("JBC",0x0010,CPU87C750);
+ AddBCond("JNB",0x0030,CPU87C750);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+ free(AccOrders);
+ free(CondOrders);
+ free(BCondOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Instruktionsdecoder */
+
+ static Boolean DecodePseudo(void)
+BEGIN
+
+ return False;
+END
+
+ static void MakeCode_51(void)
+BEGIN
+ CodeLen=0; DontPrint=False; OpSize=(-1); MinOneIs0=False;
+
+ /* zu ignorierendes */
+
+ if (*OpPart=='\0') return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(BigEndian)) return;
+
+ /* suchen */
+
+ if (NOT LookupInstTable(InstTable,OpPart)) WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_51(void)
+BEGIN
+ switch (*OpPart)
+ BEGIN
+ case 'B': return Memo("BIT");
+ case 'S': if (Memo("SFR")) return True;
+ if (MomCPU>=CPU80251) return False;
+ return Memo("SFRB");
+ case 'P': if (MomCPU>=CPU80251) return Memo("PORT");
+ else return False;
+ default : return False;
+ END
+END
+
+ static void InitPass_51(void)
+BEGIN
+ SaveInitProc();
+ SetFlag(&SrcMode,SrcModeName,False);
+ SetFlag(&BigEndian,BigEndianName,False);
+END
+
+ static void SwitchFrom_51(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_51(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x31; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ if (MomCPU>=CPU80251)
+ BEGIN
+ ValidSegs=(1<<SegCode)|(1<<SegIO);
+ Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
+ SegLimits[SegCode ] = 0xffffffl;
+ Grans[SegIO ]=1; ListGrans[SegIO ]=1; SegInits[SegIO ]=0;
+ SegLimits[SegIO ] = 0x1ff;
+ END
+ else
+ BEGIN
+ ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegIData)|(1<<SegXData)|(1<<SegBData);
+ Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
+ SegLimits[SegCode ] = (MomCPU == CPU87C750) ? 0x7ff : 0xffff;
+ Grans[SegData ]=1; ListGrans[SegData ]=1; SegInits[SegData ]=0x30;
+ SegLimits[SegData ] = 0xff;
+ Grans[SegIData]=1; ListGrans[SegIData]=1; SegInits[SegIData]=0x80;
+ SegLimits[SegIData] = 0xff;
+ Grans[SegXData]=1; ListGrans[SegXData]=1; SegInits[SegXData]=0;
+ SegLimits[SegXData] = 0xffff;
+ Grans[SegBData]=1; ListGrans[SegBData]=1; SegInits[SegBData]=0;
+ SegLimits[SegBData] = 0xff;
+ END
+
+ MakeCode=MakeCode_51; IsDef=IsDef_51;
+
+ InitFields(); SwitchFrom=SwitchFrom_51;
+ AddONOFF("SRCMODE" , &SrcMode , SrcModeName , False);
+ AddONOFF("BIGENDIAN", &BigEndian, BigEndianName, False);
+END
+
+
+ void code51_init(void)
+BEGIN
+ CPU87C750 =AddCPU("87C750",SwitchTo_51);
+ CPU8051 =AddCPU("8051" ,SwitchTo_51);
+ CPU8052 =AddCPU("8052" ,SwitchTo_51);
+ CPU80C320 =AddCPU("80C320",SwitchTo_51);
+ CPU80501 =AddCPU("80C501",SwitchTo_51);
+ CPU80502 =AddCPU("80C502",SwitchTo_51);
+ CPU80504 =AddCPU("80C504",SwitchTo_51);
+ CPU80515 =AddCPU("80515" ,SwitchTo_51);
+ CPU80517 =AddCPU("80517" ,SwitchTo_51);
+ CPU80251 =AddCPU("80C251",SwitchTo_51);
+
+ SaveInitProc=InitPassProc;
+ InitPassProc=InitPass_51;
+END
diff --git a/code51.h b/code51.h
new file mode 100644
index 0000000..e71049f
--- /dev/null
+++ b/code51.h
@@ -0,0 +1,11 @@
+/* code51.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator fuer MCS-51/252 Prozessoren */
+/* */
+/* Historie: 5. 6.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code51_init(void);
diff --git a/code53c8xx.c b/code53c8xx.c
new file mode 100644
index 0000000..e5808e6
--- /dev/null
+++ b/code53c8xx.c
@@ -0,0 +1,1055 @@
+/* code53c8xx.c */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Codegenerator SYM53C8xx */
+/* */
+/* Historie: 30. 9.1998 angelegt */
+/* 3.10.1998 erste Befehle (NOP JUMP CALL RETURN INT INTFLY) */
+/* 4.10.1998 CHMOV CLEAR SET DISCONNECT LOAD STORE */
+/* 7.10.1998 MOVE begonnen */
+/* 15.11.1998 SELECT/RESELECT, WAIT */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "headids.h"
+#include "strutil.h"
+
+/*---------------------------------------------------------------------------*/
+
+#define RegCnt 69
+
+typedef struct
+ {
+ char *Name;
+ LongWord Code;
+ Word Mask;
+ } TReg, *PReg;
+
+static CPUVar CPU53C810, CPU53C860, CPU53C815, CPU53C825, CPU53C875,
+ CPU53C895;
+
+#define M_53C810 0x0001
+#define M_53C860 0x0002
+#define M_53C815 0x0004
+#define M_53C825 0x0008
+#define M_53C875 0x0010
+#define M_53C895 0x0020
+
+static PInstTable InstTable;
+static PReg Regs;
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean IsInToken(char Inp)
+BEGIN
+ return ((Inp == '_') OR (isalnum(((usint) Inp) & 0xff)));
+END
+
+ static void GetToken(char *Src, char *Dest)
+BEGIN
+ char *p, *start, Save;
+
+ /* Anfang suchen */
+
+ for (p = Src; isspace(*p); p++)
+ if (*p == '\0') break;
+ if (*p == '\0')
+ BEGIN
+ *Dest = *Src = '\0'; return;
+ END
+ start = p;
+
+ /* geklammerter Ausdruck ? */
+
+ if (*p == '(')
+ BEGIN
+ p = QuotPos(p, ')');
+ if (p == Nil)
+ BEGIN
+ strcpy(Dest, start); *Src = '\0';
+ END
+ else
+ BEGIN
+ Save = p[1]; p[1] = '\0';
+ strcpy(Dest, start);
+ p[1] = Save; strcpy(Src, p + 1);
+ END
+ END
+
+ /* Spezialtoken ? */
+
+ else if (NOT IsInToken(*p))
+ BEGIN
+ *Dest = *p; Dest[1] = '\0';
+ strcpy(Src, p + 1);
+ END
+
+ /* Wort ? */
+
+ else
+ BEGIN
+ for (; IsInToken(*p); p++)
+ if (*p == '\0') break;
+ Save = *p; *p = '\0';
+ strcpy(Dest, start);
+ *p = Save; strcpy(Src, p);
+ END
+END
+
+#if 0
+ static void GetRToken(char *Src, char *Dest)
+BEGIN
+ char *p;
+
+ KillPostBlanks(Src);
+
+ p = Src + strlen(Src) - 1;
+
+ /* geklammerter Ausdruck ? */
+
+ if (*p == ')')
+ BEGIN
+ p = RQuotPos(p, ')');
+ if (p == Nil)
+ BEGIN
+ strcpy(Dest, Src); *Src = '\0';
+ END
+ else
+ BEGIN
+ strcpy(Dest, p); *p = '\0';
+ END
+ END
+
+ /* Spezieltoken ? */
+
+ else if (NOT IsInToken(*p))
+ BEGIN
+ *Dest = *p; Dest[1] = '\0';
+ *p = '\0';
+ END
+
+ else
+ BEGIN
+ for (; IsInToken(*p); p--)
+ if (p <= Src) break;
+ if (NOT IsInToken(*p)) p++;
+ strcpy(Dest, p); *p = '\0';
+ END
+END
+#endif
+
+ static Boolean DecodePhase(char *Name, LongWord *Result)
+BEGIN
+ *Result = 8;
+ if (strcasecmp(Name, "DATA_OUT") == 0) *Result = 0;
+ else if (strcasecmp(Name, "DATA_IN") == 0) *Result = 1;
+ else if (strcasecmp(Name, "COMMAND") == 0) *Result = 2;
+ else if (strcasecmp(Name, "STATUS") == 0) *Result = 3;
+ else if (strcasecmp(Name, "RES4") == 0) *Result = 4;
+ else if (strcasecmp(Name, "RES5") == 0) *Result = 5;
+ else if (strcasecmp(Name, "MESSAGE_OUT") == 0) *Result = 6;
+ else if (strcasecmp(Name, "MESSAGE_IN") == 0) *Result = 7;
+ return (*Result < 8);
+END
+
+ static Boolean DecodeReg(char *Name, LongWord *Result)
+BEGIN
+ int z;
+ Integer Mask = 1 << (MomCPU - CPU53C810);
+ PReg Reg;
+
+ for (z = 0, Reg = Regs; z < RegCnt; z++, Reg++)
+ if ((strcasecmp(Reg->Name, Name) == 0) AND (Mask & Reg->Mask))
+ BEGIN
+ *Result = Reg->Code; return True;
+ END
+
+ return False;
+END
+
+ static Boolean Err(int Num, char *Msg)
+BEGIN
+ WrXError(Num, Msg);
+ return False;
+END
+
+ static Boolean DecodeCond(char *Src, LongWord *Dest)
+BEGIN
+ String Tok;
+ Boolean PhaseATNUsed, DataUsed, CarryUsed, MaskUsed;
+ LongWord Tmp;
+ Boolean OK;
+
+ /* IF/WHEN/Nix-Unterscheidung - TRUE fuer Nix setzen */
+
+ GetToken(Src, Tok);
+ if (*Tok == '\0')
+ BEGIN
+ *Dest |= 0x00080000;
+ return True;
+ END
+
+ if (strcasecmp(Tok, "WHEN") == 0)
+ *Dest |= 0x00010000;
+ else if (strcasecmp(Tok, "IF") != 0)
+ return Err(1135, Tok);
+
+ /* Negierung? */
+
+ GetToken(Src, Tok);
+ if (strcasecmp(Tok, "NOT") == 0) GetToken(Src, Tok);
+ else *Dest |= 0x00080000;
+
+ /* Bedingungen durchgehen */
+
+ PhaseATNUsed = DataUsed = MaskUsed = CarryUsed = False;
+ do
+ BEGIN
+ if (strcasecmp(Tok, "ATN") == 0)
+ BEGIN
+ if (PhaseATNUsed) return Err(1350, "2 x ATN/Phase");
+ if (CarryUsed) return Err(1350, "Carry + ATN/Phase");
+ if ((*Dest & 0x00010000) != 0) return Err(1350, "WHEN + ATN");
+ PhaseATNUsed = True; *Dest |= 0x00020000;
+ END
+ else if (DecodePhase(Tok, &Tmp))
+ BEGIN
+ if (PhaseATNUsed) return Err(1350, "2 x ATN/Phase");
+ if (CarryUsed) return Err(1350, "Carry + ATN/Phase");
+ PhaseATNUsed = True; *Dest |= 0x00020000 + (Tmp << 24);
+ END
+ else if (strcasecmp(Tok, "CARRY") == 0)
+ BEGIN
+ if (CarryUsed) return Err(1350, "2 x Carry");
+ if ((PhaseATNUsed) OR (DataUsed)) return Err(1350, "Carry + ...");
+ CarryUsed = True; *Dest |= 0x00200000;
+ END
+ else if (strcasecmp(Tok, "MASK") == 0)
+ BEGIN
+ if (CarryUsed) return Err(1350, "Carry + Data");
+ if (MaskUsed) return Err(1350, "2 x Mask");
+ if (NOT DataUsed) return Err(1350, "Mask + !Data");
+ GetToken(Src, Tok);
+ Tmp = EvalIntExpression(Tok, UInt8, &OK);
+ if (!OK) return False;
+ MaskUsed = True; *Dest |= (Tmp << 8);
+ END
+ else
+ BEGIN
+ if (CarryUsed) return Err(1350, "Carry + Data");
+ if (DataUsed) return Err(1350, "2 x Data");
+ Tmp = EvalIntExpression(Tok, UInt8, &OK);
+ if (!OK) return False;
+ DataUsed = True; *Dest |= 0x00040000 + Tmp;
+ END
+ GetToken(Src, Tok);
+ if (*Tok != '\0')
+ BEGIN
+ if (strcasecmp(Tok, "AND") != 0) return Err(1350, Tok);
+ GetToken(Src, Tok);
+ END
+ END
+ while (*Tok != '\0');
+
+ return True;
+END
+
+typedef enum {NONE, SFBR, REGISTER, IMM8} CompType;
+
+ CompType DecodeComp(char *Inp, LongWord *Outp)
+BEGIN
+ Boolean OK;
+
+ if (strcasecmp(Inp, "SFBR") == 0) return SFBR;
+ else if (DecodeReg(Inp, Outp)) return REGISTER;
+ else
+ BEGIN
+ *Outp = EvalIntExpression(Inp, Int8, &OK) & 0xff;
+ return (OK) ? IMM8 : NONE;
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+static int InstrZ;
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ if (ArgCnt != 0) WrError(1110);
+ else
+ BEGIN
+ DAsmCode[0] = ((LongWord) Index) << 24;
+ DAsmCode[1] = 0x00000000;
+ CodeLen = 8;
+ END
+END
+
+ static void DecodeJmps(Word Index)
+BEGIN
+ LongWord Buf;
+ LongInt Adr;
+ int l;
+ Boolean OK;
+
+ if (ArgCnt == 0)
+ if (Memo("INTFLY"))
+ BEGIN
+ ArgCnt = 1; strcpy(ArgStr[1], "0");
+ END
+ else if (Memo("RETURN"))
+ BEGIN
+ ArgCnt = 1; *ArgStr[1] = '\0';
+ END
+ if ((ArgCnt != 2) AND (ArgCnt!= 1)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt == 1)
+ if (Memo("RETURN")) strcpy(ArgStr[2], ArgStr[1]);
+ else *ArgStr[2] = '\0';
+ Buf = 0;
+ if (Memo("RETURN")) Adr = 0;
+ else
+ BEGIN
+ l = strlen(ArgStr[1]);
+ if ((strncasecmp(ArgStr[1], "REL(", 4) == 0) AND (ArgStr[1][l - 1] == ')'))
+ BEGIN
+ if (*OpPart == 'I')
+ BEGIN
+ WrError(1350); OK = False;
+ END
+ Buf |= 0x00800000;
+ strcpy(ArgStr[1], ArgStr[1] + 4); ArgStr[1][l - 5] = '\0';
+ END
+ Adr = EvalIntExpression(ArgStr[1], UInt32, &OK);
+ if ((OK) AND (Buf != 0))
+ BEGIN
+ Adr -= EProgCounter() + 8;
+ if ((NOT SymbolQuestionable) AND ((Adr > 0x7fffff) OR (Adr < -0x800000)))
+ BEGIN
+ WrError(1370); OK = False;
+ END
+ END
+ END
+ if ((OK) AND (DecodeCond(ArgStr[2], &Buf)))
+ BEGIN
+ DAsmCode[0] = 0x80000000 + (((LongWord) Index) << 27) + Buf;
+ if (Memo("INTFLY")) DAsmCode[0] |= 0x00100000;
+ DAsmCode[1] = Adr;
+ CodeLen = 8;
+ END
+ END
+END
+
+ static void DecodeCHMOV(Word Index)
+BEGIN
+ String Token;
+ char *Adr = Nil;
+ LongWord Phase;
+ Boolean OK;
+
+ if ((MomCPU != CPU53C825) AND (MomCPU != CPU53C875) AND (MomCPU != CPU53C895)) WrError(1500);
+ else if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else
+ BEGIN
+ GetToken(ArgStr[ArgCnt], Token);
+ if (strcasecmp(Token, "WITH") == 0) DAsmCode[0] = 0x08000000;
+ else if (strcasecmp(Token, "WHEN") == 0) DAsmCode[0] = 0x00000000;
+ else
+ BEGIN
+ WrXError(1350, Token); return;
+ END
+ KillBlanks(ArgStr[ArgCnt]);
+ if (NOT DecodePhase(ArgStr[ArgCnt], &Phase)) WrXError(1350, ArgStr[ArgCnt]);
+ else
+ BEGIN
+ DAsmCode[0] |= Phase << 24;
+ OK = False;
+ if (ArgCnt == 2)
+ BEGIN
+ GetToken(ArgStr[1], Token);
+ if (strcasecmp(Token, "FROM") != 0) WrError(1350);
+ else
+ BEGIN
+ Adr = ArgStr[1];
+ DAsmCode[0] |= 0x10000000;
+ OK = True;
+ END
+ END
+ else
+ BEGIN
+ Phase = EvalIntExpression(ArgStr[1], UInt24, &OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0] |= Phase;
+ if (strncasecmp(ArgStr[2],"PTR", 3) == 0)
+ BEGIN
+ strcpy(ArgStr[2], ArgStr[2] + 4);
+ DAsmCode[0] |= 0x20000000;
+ END
+ Adr = ArgStr[2];
+ END
+ END
+ if (OK)
+ BEGIN
+ KillPrefBlanks(Adr);
+ DAsmCode[1] = EvalIntExpression(Adr, UInt32, &OK);
+ if (OK) CodeLen = 8;
+ END
+ END
+ END
+END
+
+ static void DecodeFlags(Word Index)
+BEGIN
+ Boolean OK;
+ String Token;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ OK = True;
+ DAsmCode[0] = ((LongWord) Index) << 24;
+ DAsmCode[1] = 0;
+ while ((OK) AND (*ArgStr[1] != '\0'))
+ BEGIN
+ GetToken(ArgStr[1], Token);
+ if (strcasecmp(Token, "ACK") == 0) DAsmCode[0] |= 0x00000040;
+ else if (strcasecmp(Token, "ATN") == 0) DAsmCode[0] |= 0x00000008;
+ else if (strcasecmp(Token, "TARGET") == 0) DAsmCode[0] |= 0x00000200;
+ else if (strcasecmp(Token, "CARRY") == 0) DAsmCode[0] |= 0x00000400;
+ else
+ BEGIN
+ OK = False; WrXError(1350, Token);
+ END
+ if ((OK) AND (*ArgStr[1] != '\0'))
+ BEGIN
+ GetToken(ArgStr[1], Token);
+ if (strcasecmp(Token, "AND") != 0)
+ BEGIN
+ OK = False; WrXError(1350, Token);
+ END
+ END
+ END
+ if (OK) CodeLen = 8;
+ END
+END
+
+ static void DecodeRegTrans(Word Index)
+BEGIN
+ LongWord Reg, Cnt;
+ Boolean OK;
+
+ if (ArgCnt != 3) WrError(1110);
+ else if (MomCPU == CPU53C815) WrError(1500);
+ else if (NOT DecodeReg(ArgStr[1], &Reg)) WrXError(1445, ArgStr[1]);
+ else
+ BEGIN
+ FirstPassUnknown = False;
+ Cnt = EvalIntExpression(ArgStr[2], UInt3, &OK);
+ if (FirstPassUnknown) Cnt = 1;
+ if ((OK) AND (ChkRange(Cnt, 1, 4)))
+ BEGIN
+ DAsmCode[0] = 0xe0000000 + (((LongInt) Index) << 24) + (Reg << 16) + Cnt;
+ if ((strncasecmp(ArgStr[3], "DSAREL(", 7) == 0)
+ AND (ArgStr[3][strlen(ArgStr[3]) - 1] == ')'))
+ BEGIN
+ DAsmCode[0] |= 0x10000000;
+ DAsmCode[1] = EvalIntExpression(ArgStr[3] + 6, SInt24, &OK) & 0xffffff;
+ END
+ else DAsmCode[1] = EvalIntExpression(ArgStr[3], UInt32, &OK);
+ if (OK) CodeLen = 8;
+ END
+ END
+END
+
+ static void DecodeMOVE(Word Index)
+BEGIN
+ Boolean WithCarry, BigCPU;
+ String Token;
+ LongWord Tmp, DReg , AriOp = 0xff, ImmVal = 0x100;
+ String Parts[8];
+ Boolean OK;
+
+ BigCPU = (MomCPU == CPU53C825) OR (MomCPU == CPU53C875) OR (MomCPU == CPU53C895);
+
+ if ((ArgCnt > 3) OR (ArgCnt < 1)) WrError(1110);
+ else if (ArgCnt == 1) /* MOVE Register */
+ BEGIN
+ ArgCnt = 0;
+ do
+ BEGIN
+ GetToken(ArgStr[1], Parts[ArgCnt++]);
+ END
+ while ((*ArgStr[1] != '\0') AND (ArgCnt < 8));
+ if ((ArgCnt > 1) AND (strcasecmp(Parts[ArgCnt - 1], "CARRY") == 0) AND (strcasecmp(Parts[ArgCnt - 1], "TO") == 0))
+ BEGIN
+ WithCarry = True; ArgCnt -= 2;
+ END
+ else WithCarry = False;
+ DAsmCode[0] = 0x40000000;
+ DAsmCode[1] = 0;
+ if (ArgCnt == 3)
+ BEGIN
+ if (WithCarry) WrError(1350);
+ else if (strcasecmp(Parts[1], "TO") == 0) /* MOVE */
+ BEGIN
+ switch (DecodeComp(Parts[0], &ImmVal))
+ BEGIN
+ case SFBR:
+ switch (DecodeComp(Parts[2], &ImmVal))
+ BEGIN
+ case SFBR:
+ ImmVal = 8;
+ case REGISTER: /* --> 0x00 OR SFBR to reg */
+ DAsmCode[0] += 0x2a000000 + (ImmVal << 16);
+ CodeLen = 8;
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ case REGISTER:
+ DReg = ImmVal;
+ switch (DecodeComp(Parts[2], &ImmVal))
+ BEGIN
+ case SFBR: /* --> 0x00 OR reg to SFBR */
+ DAsmCode[0] += 0x32000000 + (DReg << 16);
+ CodeLen = 8;
+ break;
+ case REGISTER:
+ if (ImmVal != DReg) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0] += 0x3a000000 + (DReg << 16);
+ CodeLen = 8;
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ case IMM8:
+ switch (DecodeComp(Parts[2], &DReg))
+ BEGIN
+ case SFBR:
+ DReg = 8;
+ case REGISTER: /* --> imm to reg */
+ DAsmCode[0] += 0x38000000 + (DReg << 16) + (ImmVal << 8);
+ CodeLen = 8;
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ default:
+ WrError(1350);
+ break;
+ END
+ END /* ... TO ... */
+ else if ((strcasecmp(Parts[1], "SHL") == 0) OR (strcasecmp(Parts[1], "SHR") == 0))
+ BEGIN
+ AriOp = 1 + (Ord(toupper(Parts[1][2]) == 'R') << 2);
+ switch (DecodeComp(Parts[0], &DReg))
+ BEGIN
+ case SFBR:
+ switch (DecodeComp(Parts[2], &DReg))
+ BEGIN
+ case SFBR:
+ DReg = 8;
+ case REGISTER:
+ DAsmCode[0] += 0x28000000 + (AriOp << 24) + (DReg << 16);
+ CodeLen = 8;
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ case REGISTER:
+ ImmVal = DReg;
+ switch (DecodeComp(Parts[2], &DReg))
+ BEGIN
+ case SFBR:
+ DAsmCode[0] += 0x30000000 + (AriOp << 24) + (ImmVal << 16);
+ CodeLen = 8;
+ break;
+ case REGISTER:
+ if (DReg != ImmVal) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0] += 0x38000000 + (AriOp << 24) + (ImmVal << 16);
+ CodeLen = 8;
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ END /* ... SHx ... */
+ END /* ArgCnt == 3 */
+ else if (ArgCnt == 5)
+ BEGIN
+ if (strcasecmp(Parts[3], "TO") != 0) WrError(1350);
+ else
+ BEGIN
+ if (strcasecmp(Parts[1], "XOR") == 0) AriOp = 3;
+ else if (strcasecmp(Parts[1], "OR") == 0) AriOp = 2;
+ else if (strcasecmp(Parts[1], "AND") == 0) AriOp = 4;
+ else if (strcmp(Parts[1], "+") == 0) AriOp = 6;
+ if (WithCarry) AriOp = (AriOp == 6) ? 7 : 0xff;
+ if (AriOp == 0xff) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0] |= (AriOp << 24);
+ switch (DecodeComp(Parts[0], &ImmVal))
+ BEGIN
+ case SFBR:
+ switch (DecodeComp(Parts[2], &ImmVal))
+ BEGIN
+ case SFBR:
+ switch (DecodeComp(Parts[4], &ImmVal))
+ BEGIN
+ case SFBR:
+ ImmVal = 8;
+ case REGISTER:
+ if (NOT BigCPU) WrError(1500);
+ else
+ BEGIN
+ DAsmCode[0] |= 0x28800000 + (ImmVal << 16);
+ CodeLen = 8;
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ case IMM8:
+ switch (DecodeComp(Parts[4], &DReg))
+ BEGIN
+ case SFBR:
+ DReg = 8;
+ case REGISTER:
+ DAsmCode[0] |= 0x28000000 + (DReg << 16) + (ImmVal << 8);
+ CodeLen = 8;
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ case REGISTER:
+ DAsmCode[0] |= ImmVal << 16;
+ DReg = ImmVal;
+ switch (DecodeComp(Parts[2], &ImmVal))
+ BEGIN
+ case SFBR:
+ switch (DecodeComp(Parts[4], &ImmVal))
+ BEGIN
+ case SFBR:
+ if (NOT BigCPU) WrError(1500);
+ else
+ BEGIN
+ DAsmCode[0] |= 0x30800000;
+ CodeLen = 8;
+ END
+ break;
+ case REGISTER:
+ if (DReg != ImmVal) WrError(1350);
+ else if (NOT BigCPU) WrError(1500);
+ else
+ BEGIN
+ DAsmCode[0] |= 0x38800000;
+ CodeLen = 8;
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ case IMM8:
+ DAsmCode[0] |= (ImmVal << 8);
+ switch (DecodeComp(Parts[4], &Tmp))
+ BEGIN
+ case SFBR:
+ DAsmCode[0] |= 0x30000000;
+ CodeLen = 8;
+ break;
+ case REGISTER:
+ if (DReg != Tmp) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0] |= 0x38000000;
+ CodeLen = 8;
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ END
+ END /* ArgCnt == 5 */
+ else WrError(1350);
+ END
+ else if (ArgCnt == 2)
+ BEGIN
+ GetToken(ArgStr[1], Token);
+ if (strcasecmp(Token, "FROM") != 0) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0] = 0x00000000;
+ DAsmCode[1] = EvalIntExpression(ArgStr[1], Int32, &OK);
+ if (OK)
+ BEGIN
+ GetToken(ArgStr[2], Token);
+ OK = True;
+ if (strcasecmp(Token, "WHEN") == 0) DAsmCode[0] |= 0x08000000;
+ else if (strcasecmp(Token, "WITH") != 0) OK = False;
+ if (NOT OK) WrError(1350);
+ else
+ BEGIN
+ KillBlanks(ArgStr[2]);
+ if (NOT DecodePhase(ArgStr[2], &ImmVal)) WrXError(1350, ArgStr[2]);
+ else
+ BEGIN
+ DAsmCode[0] |= ImmVal << 24;
+ CodeLen = 8;
+ END
+ END
+ END
+ END
+ END
+ else if (ArgCnt == 3)
+ BEGIN
+ if (strncasecmp(ArgStr[1], "MEMORY", 6) == 0)
+ BEGIN
+ strcpy(ArgStr[1], ArgStr[1] + 7);
+ if (strncasecmp(ArgStr[1], "NO FLUSH", 8) == 0)
+ BEGIN
+ DAsmCode[0] = 0xc1000000;
+ strcpy(ArgStr[1], ArgStr[1] + 9);
+ END
+ else DAsmCode[0] = 0xc0000000;
+ DAsmCode[0] |= EvalIntExpression(ArgStr[1], UInt24, &OK);
+ if (OK)
+ BEGIN
+ DAsmCode[1] = EvalIntExpression(ArgStr[2], Int32, &OK);
+ if (OK)
+ BEGIN
+ DAsmCode[2] = EvalIntExpression(ArgStr[3], Int32, &OK);
+ if (OK) CodeLen = 12;
+ END
+ END
+ END
+ else
+ BEGIN
+ DAsmCode[0] = EvalIntExpression(ArgStr[1], UInt24, &OK);
+ if (OK)
+ BEGIN
+ GetToken(ArgStr[3], Token);
+ OK = True;
+ if (strcasecmp(Token, "WHEN") == 0) DAsmCode[0] |= 0x08000000;
+ else if (strcasecmp(Token, "WITH") != 0) OK = False;
+ if (NOT OK) WrError(1350);
+ else
+ BEGIN
+ KillBlanks(ArgStr[3]);
+ if (NOT DecodePhase(ArgStr[3], &ImmVal)) WrXError(1350, ArgStr[2]);
+ else
+ BEGIN
+ DAsmCode[0] |= ImmVal << 24;
+ if (strncasecmp(ArgStr[2], "PTR", 3) == 0)
+ BEGIN
+ strcpy(ArgStr[2], ArgStr[2] + 4);
+ DAsmCode[0] |= 0x20000000;
+ END
+ DAsmCode[1] = EvalIntExpression(ArgStr[2], UInt32, &OK);
+ if (OK) CodeLen = 8;
+ END
+ END
+ END
+ END
+ END
+ else WrError(1110);
+END
+
+ static void DecodeSELECT(Word MayATN)
+BEGIN
+ Boolean OK;
+ LongInt Dist;
+ int l;
+
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DAsmCode[0] = 0x40000000; OK = True;
+ if (strncasecmp(ArgStr[1], "ATN ", 4) == 0)
+ BEGIN
+ strcpy(ArgStr[1], ArgStr[1] + 4); KillPrefBlanks(ArgStr[1]);
+ if (NOT MayATN) OK = False;
+ else DAsmCode[0] |= 0x01000000;
+ END
+ if (NOT OK) WrError(1350);
+ else
+ BEGIN
+ if (strncasecmp(ArgStr[1], "FROM ", 5) == 0)
+ BEGIN
+ strcpy(ArgStr[1], ArgStr[1] + 5); KillPrefBlanks(ArgStr[1]);
+ DAsmCode[0] |= 0x02000000 + EvalIntExpression(ArgStr[1], UInt24, &OK);
+ END
+ else DAsmCode[0] |= EvalIntExpression(ArgStr[1], UInt4, &OK) << 16;
+ if (OK)
+ BEGIN
+ l = strlen(ArgStr[2]);
+ if ((strncasecmp(ArgStr[2], "REL(", 4) == 0) AND (ArgStr[2][l - 1] == ')'))
+ BEGIN
+ DAsmCode[0] |= 0x04000000; ArgStr[2][l - 1] = '\0';
+ Dist = EvalIntExpression(ArgStr[2] + 4, UInt32, &OK) - (EProgCounter() + 8);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Dist > 0x7fffff) OR (Dist < -0x800000))) WrError(1370);
+ else DAsmCode[1] = Dist & 0xffffff;
+ END
+ else DAsmCode[1] = EvalIntExpression(ArgStr[2], UInt32, &OK);
+ if (OK) CodeLen = 8;
+ END
+ END
+ END
+END
+
+ static void DecodeWAIT(Word Index)
+BEGIN
+ String Token;
+ int l;
+ Boolean OK;
+ LongInt Dist;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ GetToken(ArgStr[1], Token); KillPrefBlanks(ArgStr[1]);
+ if (strcasecmp(Token, "DISCONNECT") == 0)
+ BEGIN
+ if (*ArgStr[1] != '\0') WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0] = 0x48000000;
+ DAsmCode[1] = 0;
+ CodeLen = 8;
+ END
+ END
+ else if ((strcasecmp(Token, "RESELECT") == 0) OR (strcasecmp(Token, "SELECT") == 0))
+ BEGIN
+ l = strlen(ArgStr[1]);
+ if ((strncasecmp(ArgStr[1], "REL(", 4) == 0) AND (ArgStr[1][l - 1] == ')'))
+ BEGIN
+ ArgStr[1][l - 1] = '\0';
+ DAsmCode[0] = 0x54000000;
+ Dist = EvalIntExpression(ArgStr[1] + 4, UInt32, &OK) - (EProgCounter() + 8);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Dist > 0x7fffff) OR (Dist < -0x800000))) WrError(1370);
+ else DAsmCode[1] = Dist & 0xffffff;
+ END
+ else
+ BEGIN
+ DAsmCode[0] = 0x50000000;
+ DAsmCode[1] = EvalIntExpression(ArgStr[1], UInt32, &OK);
+ END
+ if (OK)
+ BEGIN
+ if (toupper(*Token) == 'S') DAsmCode[0] |= 0x00000200;
+ CodeLen = 8;
+ END
+ END
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+static int InstrZ;
+
+ static void AddReg(char *NName, LargeWord Adr, Word Mask)
+BEGIN
+ if (InstrZ >= RegCnt) exit(255);
+ Regs[InstrZ].Name = NName;
+ Regs[InstrZ].Code = Adr;
+ Regs[InstrZ++].Mask = Mask;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable = CreateInstTable(51);
+ AddInstTable(InstTable, "NOP" , 0x80, DecodeFixed);
+ AddInstTable(InstTable, "DISCONNECT" , 0x48, DecodeFixed);
+ AddInstTable(InstTable, "JUMP" , 0, DecodeJmps);
+ AddInstTable(InstTable, "CALL" , 1, DecodeJmps);
+ AddInstTable(InstTable, "RETURN" , 2, DecodeJmps);
+ AddInstTable(InstTable, "INT" , 3, DecodeJmps);
+ AddInstTable(InstTable, "INTFLY" , 3, DecodeJmps);
+ AddInstTable(InstTable, "CHMOV" , 0, DecodeCHMOV);
+ AddInstTable(InstTable, "CLEAR" , 0x60, DecodeFlags);
+ AddInstTable(InstTable, "SET" , 0x58, DecodeFlags);
+ AddInstTable(InstTable, "LOAD" , 1, DecodeRegTrans);
+ AddInstTable(InstTable, "STORE" , 0, DecodeRegTrans);
+ AddInstTable(InstTable, "MOVE" , 0, DecodeMOVE);
+ AddInstTable(InstTable, "RESELECT", 0, DecodeSELECT);
+ AddInstTable(InstTable, "SELECT" , 1, DecodeSELECT);
+ AddInstTable(InstTable, "WAIT" , 0, DecodeWAIT);
+
+ Regs = (PReg) malloc(sizeof(TReg) * RegCnt); InstrZ = 0;
+ AddReg("SCNTL0" , 0x00, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SCNTL1" , 0x01, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SCNTL2" , 0x02, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SCNTL3" , 0x03, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SCID" , 0x04, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SXFER" , 0x05, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SDID" , 0x06, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("GPREG" , 0x07, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SFBR" , 0x08, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SOCL" , 0x09, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SSID" , 0x0a, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SBCL" , 0x0b, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DSTAT" , 0x0c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SSTAT0" , 0x0d, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SSTAT1" , 0x0e, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SSTAT2" , 0x0f, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DSA" , 0x10, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("ISTAT" , 0x14, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("CTEST0" , 0x18, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("CTEST1" , 0x19, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("CTEST2" , 0x1a, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("CTEST3" , 0x1b, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("TEMP" , 0x1c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DFIFO" , 0x20, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("CTEST4" , 0x21, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("CTEST5" , 0x22, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("CTEST6" , 0x23, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DBC" , 0x24, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DCMD" , 0x27, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DNAD" , 0x28, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DSP" , 0x2c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DSPS" , 0x30, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SCRATCHA" , 0x34, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DMODE" , 0x38, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DIEN" , 0x39, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SBR" , 0x3a, M_53C810 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("DWT" , 0x3a, M_53C815 );
+ AddReg("DCNTL" , 0x3b, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("ADDER" , 0x3c, M_53C810 + M_53C825 + M_53C860 + M_53C895);
+ AddReg("SIEN0" , 0x40, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SIEN1" , 0x41, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SIST0" , 0x42, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SIST1" , 0x43, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SLPAR" , 0x44, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SWIDE" , 0x45, M_53C825 + M_53C875 + M_53C895);
+ AddReg("MACNTL" , 0x46, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("GPCNTL" , 0x47, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("STIME0" , 0x48, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("STIME1" , 0x49, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("RESPID" , 0x4a, M_53C810 + M_53C815 + M_53C825 + M_53C860 );
+ AddReg("RESPID0" , 0x4a, M_53C875 + M_53C895);
+ AddReg("RESPID1" , 0x4b, M_53C875 + M_53C895);
+ AddReg("STEST0" , 0x4c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("STEST1" , 0x4d, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("STEST2" , 0x4e, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("STEST3" , 0x4f, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SIDL" , 0x50, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("STEST4" , 0x52, + M_53C895);
+ AddReg("SODL" , 0x54, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SBDL" , 0x58, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SCRATCHB" , 0x5c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
+ AddReg("SCRATCHC" , 0x60, M_53C875 + M_53C895);
+ AddReg("SCRATCHD" , 0x64, M_53C875 + M_53C895);
+ AddReg("SCRATCHE" , 0x68, M_53C875 + M_53C895);
+ AddReg("SCRATCHF" , 0x6c, M_53C875 + M_53C895);
+ AddReg("SCRATCHG" , 0x70, M_53C875 + M_53C895);
+ AddReg("SCRATCHH" , 0x74, M_53C875 + M_53C895);
+ AddReg("SCRATCHI" , 0x78, M_53C875 + M_53C895);
+ AddReg("SCRATCHJ" , 0x7c, M_53C875 + M_53C895);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(Regs);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void MakeCode_53c8xx(void)
+BEGIN
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ if (NOT LookupInstTable(InstTable,OpPart)) WrXError(1200, OpPart);
+END
+
+ static Boolean IsDef_53c8xx(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_53c8xx(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_53c8xx(void)
+BEGIN
+ PFamilyDescr FoundDescr;
+
+ FoundDescr=FindFamilyByName("SYM53C8xx");
+
+ TurnWords=False; ConstMode=ConstModeC; SetIsOccupied=True;
+ PCSymbol="$"; HeaderID=FoundDescr->Id; NOPCode=0;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode ]=1; ListGrans[SegCode ]=4; SegInits[SegCode ]=0;
+#ifdef __STDC__
+ SegLimits[SegCode] = 0xfffffffful;
+#else
+ SegLimits[SegCode] = 0xffffffffl;
+#endif
+
+ MakeCode=MakeCode_53c8xx; IsDef=IsDef_53c8xx;
+ SwitchFrom=SwitchFrom_53c8xx;
+
+ InitFields();
+END
+
+/*---------------------------------------------------------------------------*/
+
+ void code53c8xx_init(void)
+BEGIN
+ CPU53C810 = AddCPU("SYM53C810", SwitchTo_53c8xx);
+ CPU53C860 = AddCPU("SYM53C860", SwitchTo_53c8xx);
+ CPU53C815 = AddCPU("SYM53C815", SwitchTo_53c8xx);
+ CPU53C825 = AddCPU("SYM53C825", SwitchTo_53c8xx);
+ CPU53C875 = AddCPU("SYM53C875", SwitchTo_53c8xx);
+ CPU53C895 = AddCPU("SYM53C895", SwitchTo_53c8xx);
+END
diff --git a/code53c8xx.h b/code53c8xx.h
new file mode 100644
index 0000000..185d0a7
--- /dev/null
+++ b/code53c8xx.h
@@ -0,0 +1,11 @@
+/* code53c8xx.h */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Codegenerator SYM53C8xx */
+/* */
+/* Historie: 30. 9.1998 angelegt */
+/* */
+/*****************************************************************************/
+
+extern void code53c8xx_init(void);
diff --git a/code56k.c b/code56k.c
new file mode 100644
index 0000000..07b7415
--- /dev/null
+++ b/code56k.c
@@ -0,0 +1,2566 @@
+/* code56k.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegeneratormodul fuer die DSP56K-Familie */
+/* */
+/* Historie: 10. 6.1996 Grundsteinlegung */
+/* 7. 6.1998 563xx-Erweiterungen fertiggestellt */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 18. 8.1998 BookKeeping-Aufruf bei RES */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+#include "code56k.h"
+
+typedef struct
+ {
+ char *Name;
+ LongWord Code;
+ CPUVar MinCPU;
+ } FixedOrder;
+
+typedef enum {ParAB,ParABShl1,ParABShl2,ParXYAB,ParABXYnAB,ParABBA,ParXYnAB,ParMul,ParFixAB} ParTyp;
+typedef struct
+ {
+ char *Name;
+ ParTyp Typ;
+ Byte Code;
+ } ParOrder;
+
+#define FixedOrderCnt 14
+
+#define ParOrderCnt 31
+
+#define BitOrderCnt 4
+static char *BitOrders[BitOrderCnt]={"BCLR","BSET","BCHG","BTST"};
+
+#define BitJmpOrderCnt 4
+static char *BitJmpOrders[BitJmpOrderCnt]={"JCLR","JSET","JSCLR","JSSET"};
+
+#define BitBrOrderCnt 4
+static char *BitBrOrders[BitBrOrderCnt]={"BRCLR","BRSET","BSCLR","BSSET"};
+
+#define ImmMacOrderCnt 4
+static char *ImmMacOrders[ImmMacOrderCnt]={"MPYI","MPYRI","MACI","MACRI"};
+
+static Byte MacTable[4][4]={{0,2,5,4},{2,0xff,6,7},{5,6,1,3},{4,7,3,0xff}};
+
+static Byte Mac4Table[4][4]={{0,13,10,4},{5,1,14,11},{2,6,8,15},{12,3,7,9}};
+
+static Byte Mac2Table[4]={1,3,2,0};
+
+#define ModNone (-1)
+#define ModImm 0
+#define MModImm (1 << ModImm)
+#define ModAbs 1
+#define MModAbs (1 << ModAbs)
+#define ModIReg 2
+#define MModIReg (1 << ModIReg)
+#define ModPreDec 3
+#define MModPreDec (1 << ModPreDec)
+#define ModPostDec 4
+#define MModPostDec (1 << ModPostDec)
+#define ModPostInc 5
+#define MModPostInc (1 << ModPostInc)
+#define ModIndex 6
+#define MModIndex (1 << ModIndex)
+#define ModModDec 7
+#define MModModDec (1 << ModModDec)
+#define ModModInc 8
+#define MModModInc (1 << ModModInc)
+#define ModDisp 9
+#define MModDisp (1 << ModDisp)
+
+#define MModNoExt (MModIReg+MModPreDec+MModPostDec+MModPostInc+MModIndex+MModModDec+MModModInc)
+#define MModNoImm (MModAbs+MModNoExt)
+#define MModAll (MModNoImm+MModImm)
+
+#define SegLData (SegYData+1)
+
+#define MSegCode (1 << SegCode)
+#define MSegXData (1 << SegXData)
+#define MSegYData (1 << SegYData)
+#define MSegLData (1 << SegLData)
+
+static CPUVar CPU56000,CPU56002,CPU56300;
+static IntType AdrInt;
+static LargeWord MemLimit;
+static ShortInt AdrType;
+static LongInt AdrMode;
+static LongInt AdrVal;
+static Byte AdrSeg;
+
+static FixedOrder *FixedOrders;
+static ParOrder *ParOrders;
+
+/*----------------------------------------------------------------------------------------------*/
+
+ static void AddFixed(char *Name, LongWord Code, CPUVar NMin)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+
+ FixedOrders[InstrZ].Name=Name;
+ FixedOrders[InstrZ].Code=Code;
+ FixedOrders[InstrZ++].MinCPU=NMin;
+END
+
+ static void AddPar(char *Name, ParTyp Typ, LongWord Code)
+BEGIN
+ if (InstrZ>=ParOrderCnt) exit(255);
+
+ ParOrders[InstrZ].Name=Name;
+ ParOrders[InstrZ].Typ=Typ;
+ ParOrders[InstrZ++].Code=Code;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("NOP" , 0x000000, CPU56000);
+ AddFixed("ENDDO" , 0x00008c, CPU56000);
+ AddFixed("ILLEGAL", 0x000005, CPU56000);
+ AddFixed("RESET" , 0x000084, CPU56000);
+ AddFixed("RTI" , 0x000004, CPU56000);
+ AddFixed("RTS" , 0x00000c, CPU56000);
+ AddFixed("STOP" , 0x000087, CPU56000);
+ AddFixed("SWI" , 0x000006, CPU56000);
+ AddFixed("WAIT" , 0x000086, CPU56000);
+ AddFixed("DEBUG" , 0x000200, CPU56300);
+ AddFixed("PFLUSH" , 0x000003, CPU56300);
+ AddFixed("PFLUSHUN",0x000001, CPU56300);
+ AddFixed("PFREE" , 0x000002, CPU56300);
+ AddFixed("TRAP" , 0x000006, CPU56300);
+
+ ParOrders=(ParOrder *) malloc(sizeof(ParOrder)*ParOrderCnt); InstrZ=0;
+ AddPar("ABS" ,ParAB, 0x26);
+ AddPar("ASL" ,ParABShl1, 0x32);
+ AddPar("ASR" ,ParABShl1, 0x22);
+ AddPar("CLR" ,ParAB, 0x13);
+ AddPar("LSL" ,ParABShl2, 0x33);
+ AddPar("LSR" ,ParABShl2, 0x23);
+ AddPar("NEG" ,ParAB, 0x36);
+ AddPar("NOT" ,ParAB, 0x17);
+ AddPar("RND" ,ParAB, 0x11);
+ AddPar("ROL" ,ParAB, 0x37);
+ AddPar("ROR" ,ParAB, 0x27);
+ AddPar("TST" ,ParAB, 0x03);
+ AddPar("ADC" ,ParXYAB, 0x21);
+ AddPar("SBC" ,ParXYAB, 0x25);
+ AddPar("ADD" ,ParABXYnAB,0x00);
+ AddPar("CMP" ,ParABXYnAB,0x05);
+ AddPar("CMPM",ParABXYnAB,0x07);
+ AddPar("SUB" ,ParABXYnAB,0x04);
+ AddPar("ADDL",ParABBA, 0x12);
+ AddPar("ADDR",ParABBA, 0x02);
+ AddPar("SUBL",ParABBA, 0x16);
+ AddPar("SUBR",ParABBA, 0x06);
+ AddPar("AND" ,ParXYnAB, 0x46);
+ AddPar("EOR" ,ParXYnAB, 0x43);
+ AddPar("OR" ,ParXYnAB, 0x42);
+ AddPar("MAC" ,ParMul, 0x82);
+ AddPar("MACR",ParMul, 0x83);
+ AddPar("MPY" ,ParMul, 0x80);
+ AddPar("MPYR",ParMul, 0x81);
+ AddPar("MAX" ,ParFixAB, 0x1d);
+ AddPar("MAXM",ParFixAB, 0x15);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(ParOrders);
+END
+
+/*----------------------------------------------------------------------------------------------*/
+
+ static void SplitArg(char *Orig, char *LDest, char *RDest)
+BEGIN
+ char *p,*str;
+
+ str=strdup(Orig);
+ p=QuotPos(str,',');
+ if (p==Nil)
+ BEGIN
+ *RDest='\0'; strcpy(LDest,str);
+ END
+ else
+ BEGIN
+ *p='\0';
+ strcpy(LDest,str); strcpy(RDest,p+1);
+ END
+ free(str);
+END
+
+ static void ChkMask(Word Erl, Byte ErlSeg)
+BEGIN
+ if ((AdrType!=ModNone) AND ((Erl & (1 << AdrType))==0))
+ BEGIN
+ WrError(1350); AdrCnt=0; AdrType=ModNone;
+ END
+ if ((AdrSeg!=SegNone) AND ((ErlSeg & (1 << AdrSeg))==0))
+ BEGIN
+ WrError(1960); AdrCnt=0; AdrType=ModNone;
+ END
+END
+
+ static void CutSize(char *Asc, Byte *ShortMode)
+BEGIN
+ switch (*Asc)
+ BEGIN
+ case '>':
+ strcpy(Asc,Asc+1); *ShortMode=2;
+ break;
+ case '<':
+ strcpy(Asc,Asc+1); *ShortMode=1;
+ break;
+ default:
+ *ShortMode=0;
+ END
+END
+
+ static Boolean DecodeReg(char *Asc, LongInt *Erg)
+BEGIN
+#define RegCount 12
+ static char *RegNames[RegCount]=
+ {"X0","X1","Y0","Y1","A0","B0","A2","B2","A1","B1","A","B"};
+ Word z;
+
+ for (z=0; z<RegCount; z++)
+ if (strcasecmp(Asc,RegNames[z])==0)
+ BEGIN
+ *Erg=z+4; return True;
+ END
+ if ((strlen(Asc)==2) AND (Asc[1]>='0') AND (Asc[1]<='7'))
+ switch (toupper(*Asc))
+ BEGIN
+ case 'R':
+ *Erg=16+Asc[1]-'0'; return True;
+ case 'N':
+ *Erg=24+Asc[1]-'0'; return True;
+ END
+ return False;
+END
+
+ static Boolean DecodeALUReg(char *Asc, LongInt *Erg,
+ Boolean MayX, Boolean MayY, Boolean MayAcc)
+BEGIN
+ Boolean Result=False;
+
+ if (NOT DecodeReg(Asc,Erg)) return Result;
+ switch (*Erg)
+ BEGIN
+ case 4:
+ case 5:
+ if (MayX)
+ BEGIN
+ Result=True; (*Erg)-=4;
+ END
+ break;
+ case 6:
+ case 7:
+ if (MayY)
+ BEGIN
+ Result=True; (*Erg)-=6;
+ END
+ break;
+ case 14:
+ case 15:
+ if (MayAcc)
+ BEGIN
+ Result=True;
+ if ((MayX) OR (MayY)) (*Erg)-=12; else (*Erg)-=14;
+ END
+ break;
+ END
+
+ return Result;
+END
+
+ static Boolean DecodeLReg(char *Asc, LongInt *Erg)
+BEGIN
+#undef RegCount
+#define RegCount 8
+ static char *RegNames[RegCount]=
+ {"A10","B10","X","Y","A","B","AB","BA"};
+ Word z;
+
+ for (z=0; z<RegCount; z++)
+ if (strcasecmp(Asc,RegNames[z])==0)
+ BEGIN
+ *Erg=z; return True;
+ END
+
+ return False;
+END
+
+ static Boolean DecodeXYABReg(char *Asc, LongInt *Erg)
+BEGIN
+#undef RegCount
+#define RegCount 8
+ static char *RegNames[RegCount]=
+ {"B","A","X","Y","X0","Y0","X1","Y1"};
+ Word z;
+
+ for (z=0; z<RegCount; z++)
+ if (strcasecmp(Asc,RegNames[z])==0)
+ BEGIN
+ *Erg=z; return True;
+ END
+
+ return False;
+END
+
+ static Boolean DecodeXYAB0Reg(char *Asc, LongInt *Erg)
+BEGIN
+#undef RegCount
+#define RegCount 6
+ static char *RegNames[RegCount]=
+ {"A0","B0","X0","Y0","X1","Y1"};
+ Word z;
+
+ for (z=0; z<RegCount; z++)
+ if (strcasecmp(Asc,RegNames[z])==0)
+ BEGIN
+ *Erg=z+2; return True;
+ END
+
+ return False;
+END
+
+ static Boolean DecodeXYAB1Reg(char *Asc, LongInt *Erg)
+BEGIN
+#undef RegCount
+#define RegCount 6
+ static char *RegNames[RegCount]=
+ {"A1","B1","X0","Y0","X1","Y1"};
+ Word z;
+
+ for (z=0; z<RegCount; z++)
+ if (strcasecmp(Asc,RegNames[z])==0)
+ BEGIN
+ *Erg=z+2; return True;
+ END
+
+ return False;
+END
+
+ static Boolean DecodePCReg(char *Asc, LongInt *Erg)
+BEGIN
+#undef RegCount
+#define RegCount 8 /** vvvv ab 56300 ? */
+ static char *RegNames[RegCount]={"SZ","SR","OMR","SP","SSH","SSL","LA","LC"};
+ Word z;
+
+ for (z=0; z<RegCount; z++)
+ if (strcasecmp(Asc,RegNames[z])==0)
+ BEGIN
+ (*Erg)=z; return True;
+ END
+
+ return False;
+END
+
+ static Boolean DecodeAddReg(char *Asc, LongInt *Erg)
+BEGIN
+ if ((strlen(Asc)==2) AND (toupper(*Asc)=='M') AND (Asc[1]>='0') AND (Asc[1]<='7'))
+ BEGIN
+ *Erg=Asc[1]-'0'; return True;
+ END
+ /* >=56300 ? */
+ if (strcasecmp(Asc,"EP")==0)
+ BEGIN
+ *Erg=0x0a; return True;
+ END
+ if (strcasecmp(Asc,"VBA")==0)
+ BEGIN
+ *Erg=0x10; return True;
+ END
+ if (strcasecmp(Asc,"SC")==0)
+ BEGIN
+ *Erg=0x11; return True;
+ END
+
+ return False;
+END
+
+ static Boolean DecodeGeneralReg(char *Asc, LongInt *Erg)
+BEGIN
+ if (DecodeReg(Asc,Erg)) return True;
+ if (DecodePCReg(Asc,Erg))
+ BEGIN
+ (*Erg)+=0x38; return True;
+ END
+ if (DecodeAddReg(Asc,Erg))
+ BEGIN
+ (*Erg)+=0x20; return True;
+ END
+ return False;
+END
+
+ static Boolean DecodeCtrlReg(char *Asc, LongInt *Erg)
+BEGIN
+ if (DecodeAddReg(Asc,Erg)) return True;
+ if (DecodePCReg(Asc,Erg))
+ BEGIN
+ (*Erg)+=0x18; return True;
+ END
+ return False;
+END
+
+ static Boolean DecodeControlReg(char *Asc, LongInt *Erg)
+BEGIN
+ Boolean Result=True;
+
+ if (strcasecmp(Asc,"MR")==0) *Erg=0;
+ else if (strcasecmp(Asc,"CCR")==0) *Erg=1;
+ else if ((strcasecmp(Asc,"OMR")==0) OR (strcasecmp(Asc,"COM")==0)) *Erg=2;
+ else if ((strcasecmp(Asc,"EOM")==0) AND (MomCPU>=CPU56000)) *Erg=3;
+ else Result=False;
+
+ return Result;
+END
+
+ static void DecodeAdr(char *Asc_O, Word Erl, Byte ErlSeg)
+BEGIN
+ static char *ModMasks[ModModInc+1]=
+ {"","","(Rx)","-(Rx)","(Rx)-","(Rx)+","(Rx+Nx)","(Rx)-Nx","(Rx)+Nx"};
+ static Byte ModCodes[ModModInc+1]=
+ {0,0,4,7,2,3,5,0,1};
+#define SegCount 4
+ static char SegNames[SegCount]={'P','X','Y','L'};
+ static Byte SegVals[SegCount]={SegCode,SegXData,SegYData,SegLData};
+ int z,l;
+ Boolean OK;
+ Byte OrdVal;
+ String Asc;
+ char *pp,*np,save;
+
+ AdrType=ModNone; AdrCnt=0; strmaxcpy(Asc,Asc_O,255);
+
+ /* Adressierungsmodi vom 56300 abschneiden */
+
+ if ((MomCPU<CPU56300) AND ((Erl & MModDisp)!=0)) Erl-=MModDisp;
+
+ /* Defaultsegment herausfinden */
+
+ if ((ErlSeg & MSegXData)!=0) AdrSeg=SegXData;
+ else if ((ErlSeg & MSegYData)!=0) AdrSeg=SegYData;
+ else if ((ErlSeg & MSegCode)!=0) AdrSeg=SegCode;
+ else AdrSeg=SegNone;
+
+ /* Zielsegment vorgegeben ? */
+
+ for (z=0; z<SegCount; z++)
+ if ((toupper(*Asc)==SegNames[z]) AND (Asc[1]==':'))
+ BEGIN
+ AdrSeg=SegVals[z]; strcpy(Asc,Asc+2);
+ END
+
+ /* Adressausdruecke abklopfen: dazu mit Referenzstring vergleichen */
+
+ for (z=ModIReg; z<=ModModInc; z++)
+ if (strlen(Asc)==strlen(ModMasks[z]))
+ BEGIN
+ AdrMode=0xffff;
+ for (l=0; l<=strlen(Asc); l++)
+ if (ModMasks[z][l]=='x')
+ BEGIN
+ OrdVal=Asc[l]-'0';
+ if (OrdVal>7) break;
+ else if (AdrMode==0xffff) AdrMode=OrdVal;
+ else if (AdrMode!=OrdVal)
+ BEGIN
+ WrError(1760); ChkMask(Erl,ErlSeg); return;
+ END
+ END
+ else if (ModMasks[z][l]!=toupper(Asc[l])) break;
+ if (l>strlen(Asc))
+ BEGIN
+ AdrType=z; AdrMode+=ModCodes[z] << 3;
+ ChkMask(Erl,ErlSeg); return;
+ END
+ END
+
+ /* immediate ? */
+
+ if (*Asc=='#')
+ BEGIN
+ AdrVal=EvalIntExpression(Asc+1,Int24,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=1; AdrMode=0x34;
+ ChkMask(Erl,ErlSeg); return;
+ END
+ END
+
+ /* Register mit Displacement bei 56300 */
+
+ if (IsIndirect(Asc))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ pp=strchr(Asc,'+'); np=strchr(Asc,'-');
+ if ((pp==Nil) OR ((np!=Nil) AND (np<pp))) pp=np;
+ if (pp!=0)
+ BEGIN
+ save=*pp; *pp='\0';
+ if ((DecodeGeneralReg(Asc,&AdrMode)) AND (AdrMode>=16) AND (AdrMode<=23))
+ BEGIN
+ *pp=save;
+ AdrMode-=16; FirstPassUnknown=False;
+ AdrVal=EvalIntExpression(pp,Int24,&OK);
+ if (OK)
+ BEGIN
+ if (FirstPassUnknown) AdrVal&=63;
+ AdrType=ModDisp;
+ END
+ ChkMask(Erl,ErlSeg); return;
+ END
+ *pp=save;
+ END
+ END
+
+ /* dann absolut */
+
+ AdrVal=EvalIntExpression(Asc,AdrInt,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModAbs; AdrMode=0x30; AdrCnt=1;
+ if ((AdrSeg & ((1<<SegCode)|(1<<SegXData)|(1<<SegYData)))!=0) ChkSpace(AdrSeg);
+ ChkMask(Erl,ErlSeg); return;
+ END
+END
+
+ static Boolean DecodeOpPair(char *Left, char *Right, Byte WorkSeg,
+ LongInt *Dir, LongInt *Reg1, LongInt *Reg2,
+ LongInt *AType, LongInt *AMode, LongInt *ACnt,
+ LongInt *AVal)
+BEGIN
+ Boolean Result=False;
+
+ if (DecodeALUReg(Left,Reg1,WorkSeg==SegXData,WorkSeg==SegYData,True))
+ BEGIN
+ if (DecodeALUReg(Right,Reg2,WorkSeg==SegXData,WorkSeg==SegYData,True))
+ BEGIN
+ *Dir=2; Result=True;
+ END
+ else
+ BEGIN
+ *Dir=0; *Reg2=(-1);
+ DecodeAdr(Right,MModNoImm,1 << WorkSeg);
+ if (AdrType!=ModNone)
+ BEGIN
+ *AType=AdrType; *AMode=AdrMode; *ACnt=AdrCnt; *AVal=AdrVal;
+ Result=True;
+ END
+ END
+ END
+ else if (DecodeALUReg(Right,Reg1,WorkSeg==SegXData,WorkSeg==SegYData,True))
+ BEGIN
+ *Dir=1; *Reg2=(-1);
+ DecodeAdr(Left,MModAll,1 << WorkSeg);
+ if (AdrType!=ModNone)
+ BEGIN
+ *AType=AdrType; *AMode=AdrMode; *ACnt=AdrCnt; *AVal=AdrVal;
+ Result=True;
+ END
+ END
+
+ return Result;
+END
+
+ static LongInt TurnXY(LongInt Inp)
+BEGIN
+ switch (Inp)
+ BEGIN
+ case 4:
+ case 7:
+ return Inp-4;
+ case 5:
+ case 6:
+ return 7-Inp;
+ default: /* wird nie erreicht */
+ return 0;
+ END
+END
+
+ static Boolean DecodeTFR(char *Asc, LongInt *Erg)
+BEGIN
+ LongInt Part1,Part2;
+ String Left,Right;
+
+ SplitArg(Asc,Left,Right);
+ if (NOT DecodeALUReg(Right,&Part2,False,False,True)) return False;
+ if (NOT DecodeReg(Left,&Part1)) return False;
+ if ((Part1<4) OR ((Part1>7) AND (Part1<14)) OR (Part1>15)) return False;
+ if (Part1>13)
+ if (((Part1 ^ Part2) & 1)==0) return False;
+ else Part1=0;
+ else Part1=TurnXY(Part1)+4;
+ *Erg=(Part1 << 1)+Part2;
+ return True;
+END
+
+ static Boolean DecodeRR(char *Asc, LongInt *Erg)
+BEGIN
+ LongInt Part1,Part2;
+ String Left,Right;
+
+ SplitArg(Asc,Left,Right);
+ if (NOT DecodeGeneralReg(Right,&Part2)) return False;
+ if ((Part2<16) OR (Part2>23)) return False;
+ if (NOT DecodeGeneralReg(Left,&Part1)) return False;
+ if ((Part1<16) OR (Part1>23)) return False;
+ *Erg=(Part2 & 7)+((Part1 & 7) << 8);
+ return True;
+END
+
+ static Boolean DecodeCondition(char *Asc, Word *Erg)
+BEGIN
+#define CondCount 18
+ static char *CondNames[CondCount]=
+ {"CC","GE","NE","PL","NN","EC","LC","GT","CS","LT","EQ","MI",
+ "NR","ES","LS","LE","HS","LO"};
+ Boolean Result;
+
+ (*Erg)=0;
+ while ((*Erg<CondCount) AND (strcasecmp(CondNames[*Erg],Asc)!=0)) (*Erg)++;
+ if (*Erg==CondCount-1) *Erg=8;
+ Result=(*Erg<CondCount);
+ *Erg&=15;
+ return Result;
+END
+
+ static Boolean DecodeMOVE_0(void)
+BEGIN
+ DAsmCode[0]=0x200000; CodeLen=1;
+ return True;
+END
+
+ static Boolean DecodeMOVE_1(int Start)
+BEGIN
+ String Left,Right;
+ LongInt RegErg,RegErg2,IsY,MixErg,l;
+ char c;
+ Word Condition;
+ Boolean Result=False;
+ Byte SegMask;
+
+ if (strncasecmp(ArgStr[Start],"IF",2)==0)
+ BEGIN
+ l=strlen(ArgStr[Start]);
+ if (strcasecmp(ArgStr[Start]+l-2,".U")==0)
+ BEGIN
+ RegErg=0x1000; l-=2;
+ END
+ else RegErg=0;
+ c=ArgStr[Start][l]; ArgStr[Start][l]='\0';
+ if (DecodeCondition(ArgStr[Start]+2,&Condition))
+ if (MomCPU<CPU56300) WrError(1505);
+ else
+ BEGIN
+ DAsmCode[0]=0x202000+(Condition << 8)+RegErg;
+ CodeLen=1;
+ return True;
+ END
+ ArgStr[Start][l]=c;
+ END
+
+ SplitArg(ArgStr[Start],Left,Right);
+
+ /* 1. Register-Update */
+
+ if (*Right=='\0')
+ BEGIN
+ DecodeAdr(Left,MModPostDec+MModPostInc+MModModDec+MModModInc,0);
+ if (AdrType!=ModNone)
+ BEGIN
+ Result=True;
+ DAsmCode[0]=0x204000+(AdrMode << 8);
+ CodeLen=1;
+ END
+ return Result;
+ END
+
+ /* 2. Ziel ist Register */
+
+ if (DecodeReg(Right,&RegErg))
+ BEGIN
+ AdrSeg=SegNone;
+ if (DecodeReg(Left,&RegErg2))
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x200000 + (RegErg << 8) + (RegErg2 << 13);
+ CodeLen=1;
+ END
+ else
+ BEGIN
+ /* A und B gehen auch als L:..., in L-Zweig zwingen! */
+ SegMask=MSegXData+MSegYData;
+ if ((RegErg==14) OR (RegErg==15)) SegMask|=MSegLData;
+ DecodeAdr(Left,MModAll+MModDisp,SegMask);
+ if (AdrSeg!=SegLData)
+ BEGIN
+ IsY=Ord(AdrSeg==SegYData);
+ MixErg = ((RegErg & 0x18) << 17) + (IsY << 19) + ((RegErg & 7) << 16);
+ if (AdrType==ModDisp)
+ if ((AdrVal<63) AND (AdrVal>-64) AND (RegErg<=15))
+ BEGIN
+ DAsmCode[0]=0x020090+((AdrVal & 1) << 6)+((AdrVal & 0x7e) << 10)
+ +(AdrMode << 8)+(IsY << 5)+RegErg;
+ CodeLen=1;
+ END
+ else
+ BEGIN
+ DAsmCode[0]=0x0a70c0+(AdrMode << 8)+(IsY << 16)+RegErg;
+ DAsmCode[1]=AdrVal;
+ CodeLen=2;
+ END
+#ifdef __STDC__
+ else if ((AdrType==ModImm) AND ((AdrVal & 0xffffff00u)==0))
+#else
+ else if ((AdrType==ModImm) AND ((AdrVal & 0xffffff00)==0))
+#endif
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x200000 + (RegErg << 16) + ((AdrVal & 0xff) << 8);
+ CodeLen=1;
+ END
+ else if ((AdrType==ModAbs) AND (AdrVal<=63) AND (AdrVal>=0))
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x408000 + MixErg + (AdrVal << 8);
+ CodeLen=1;
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x40c000 + MixErg + (AdrMode << 8);
+ DAsmCode[1] = AdrVal;
+ CodeLen=1+AdrCnt;
+ END
+ END
+ END
+ if (AdrSeg!=SegLData) return Result;
+ END
+
+ /* 3. Quelle ist Register */
+
+ if (DecodeReg(Left,&RegErg))
+ BEGIN
+ /* A und B gehen auch als L:..., in L-Zweig zwingen! */
+ SegMask=MSegXData+MSegYData;
+ if ((RegErg==14) OR (RegErg==15)) SegMask|=MSegLData;
+ DecodeAdr(Right,MModNoImm+MModDisp,SegMask);
+ if (AdrSeg!=SegLData)
+ BEGIN
+ IsY=Ord(AdrSeg==SegYData);
+ MixErg=((RegErg & 0x18) << 17) + (IsY << 19) + ((RegErg & 7) << 16);
+ if (AdrType==ModDisp)
+ if ((AdrVal<63) AND (AdrVal>-64) AND (RegErg<=15))
+ BEGIN
+ DAsmCode[0]=0x020080+((AdrVal & 1) << 6)+((AdrVal & 0x7e) << 10)
+ +(AdrMode << 8)+(IsY << 5)+RegErg;
+ CodeLen=1;
+ END
+ else
+ BEGIN
+ DAsmCode[0]=0x0a7080+(AdrMode << 8)+(IsY << 16)+RegErg;
+ DAsmCode[1]=AdrVal;
+ CodeLen=2;
+ END
+ else if ((AdrType==ModAbs) AND (AdrVal<=63) AND (AdrVal>=0))
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x400000 + MixErg + (AdrVal << 8);
+ CodeLen=1;
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x404000 + MixErg + (AdrMode << 8);
+ DAsmCode[1] = AdrVal;
+ CodeLen=1+AdrCnt;
+ END
+ return Result;
+ END
+ END
+
+ /* 4. Ziel ist langes Register */
+
+ if (DecodeLReg(Right,&RegErg))
+ BEGIN
+ DecodeAdr(Left,MModNoImm,MSegLData);
+ MixErg=((RegErg & 4) << 17) + ((RegErg & 3) << 16);
+ if ((AdrType==ModAbs) AND (AdrVal<=63) AND (AdrVal>=0))
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x408000 + MixErg + (AdrVal << 8);
+ CodeLen=1;
+ END
+ else
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x40c000 + MixErg + (AdrMode << 8);
+ DAsmCode[1] = AdrVal;
+ CodeLen=1+AdrCnt;
+ END
+ return Result;
+ END
+
+ /* 5. Quelle ist langes Register */
+
+ if (DecodeLReg(Left,&RegErg))
+ BEGIN
+ DecodeAdr(Right,MModNoImm,MSegLData);
+ MixErg=((RegErg & 4) << 17)+((RegErg & 3) << 16);
+ if ((AdrType==ModAbs) AND (AdrVal<=63) AND (AdrVal>=0))
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x400000 + MixErg + (AdrVal << 8);
+ CodeLen=1;
+ END
+ else
+ BEGIN
+ Result=True;
+ DAsmCode[0] = 0x404000 + MixErg + (AdrMode << 8);
+ DAsmCode[1] = AdrVal;
+ CodeLen=1+AdrCnt;
+ END
+ return Result;
+ END
+
+ WrError(1350); return Result;
+END
+
+ static Boolean DecodeMOVE_2(int Start)
+BEGIN
+ String Left1,Right1,Left2,Right2;
+ LongInt RegErg,Reg1L,Reg1R,Reg2L,Reg2R;
+ LongInt Mode1,Mode2,Dir1,Dir2,Type1,Type2,Cnt1,Cnt2,Val1,Val2;
+ Boolean Result=False;
+
+ SplitArg(ArgStr[Start],Left1,Right1);
+ SplitArg(ArgStr[Start+1],Left2,Right2);
+
+ /* 1. Spezialfall X auf rechter Seite ? */
+
+ if (strcasecmp(Left2,"X0")==0)
+ BEGIN
+ if (NOT DecodeALUReg(Right2,&RegErg,False,False,True)) WrError(1350);
+ else if (strcmp(Left1,Right2)!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(Right1,MModNoImm,MSegXData);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1+AdrCnt;
+ DAsmCode[0] = 0x080000 + (RegErg << 16) + (AdrMode << 8);
+ DAsmCode[1] = AdrVal;
+ Result=True;
+ END
+ END
+ return Result;
+ END
+
+ /* 2. Spezialfall Y auf linker Seite ? */
+
+ if (strcasecmp(Left1,"Y0")==0)
+ BEGIN
+ if (NOT DecodeALUReg(Right1,&RegErg,False,False,True)) WrError(1350);
+ else if (strcmp(Left2,Right1)!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(Right2,MModNoImm,MSegYData);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1+AdrCnt;
+ DAsmCode[0] = 0x088000 + (RegErg << 16) + (AdrMode << 8);
+ DAsmCode[1] = AdrVal;
+ Result=True;
+ END
+ END
+ return Result;
+ END
+
+ /* der Rest..... */
+
+ if ((DecodeOpPair(Left1,Right1,SegXData,&Dir1,&Reg1L,&Reg1R,&Type1,&Mode1,&Cnt1,&Val1))
+ AND (DecodeOpPair(Left2,Right2,SegYData,&Dir2,&Reg2L,&Reg2R,&Type2,&Mode2,&Cnt2,&Val2)))
+ BEGIN
+ if ((Reg1R==-1) AND (Reg2R==-1))
+ BEGIN
+ if ((Mode1 >> 3<1) OR (Mode1 >> 3>4) OR (Mode2 >> 3<1) OR (Mode2 >> 3>4)) WrError(1350);
+ else if (((Mode1 ^ Mode2) & 4)==0) WrError(1760);
+ else
+ BEGIN
+ DAsmCode[0] = 0x800000 + (Dir2 << 22) + (Dir1 << 15) +
+ (Reg1L << 18) + (Reg2L << 16) + ((Mode1 & 0x1f) << 8)+
+ ((Mode2 & 3) << 13) + ((Mode2 & 24) << 17);
+ CodeLen=1; Result=True;
+ END
+ END
+ else if (Reg1R==-1)
+ BEGIN
+ if ((Reg2L<2) OR (Reg2R>1)) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0] = 0x100000 + (Reg1L << 18) + ((Reg2L-2) << 17) + (Reg2R << 16) +
+ (Dir1 << 15) + (Mode1 << 8);
+ DAsmCode[1] = Val1;
+ CodeLen=1+Cnt1; Result=True;
+ END
+ END
+ else if (Reg2R==-1)
+ BEGIN
+ if ((Reg1L<2) OR (Reg1R>1)) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0] = 0x104000 + (Reg2L << 16) + ((Reg1L-2) << 19) + (Reg1R << 18) +
+ (Dir2 << 15) + (Mode2 << 8);
+ DAsmCode[1] = Val2;
+ CodeLen=1+Cnt2; Result=True;
+ END
+ END
+ else WrError(1350);
+ return Result;
+ END
+
+ WrError(1350); return Result;
+END
+
+ static Boolean DecodeMOVE(int Start)
+BEGIN
+ switch (ArgCnt-Start+1)
+ BEGIN
+ case 0: return DecodeMOVE_0();
+ case 1: return DecodeMOVE_1(Start);
+ case 2: return DecodeMOVE_2(Start);
+ default:
+ WrError(1110);
+ return False;
+ END
+END
+
+ static Boolean DecodeMix(char *Asc, Word *Erg)
+BEGIN
+ if (strcmp(Asc,"SS")==0) *Erg=0;
+ else if (strcmp(Asc,"SU")==0) *Erg=0x100;
+ else if (strcmp(Asc,"UU")==0) *Erg=0x140;
+ else return False;
+ return True;
+END
+
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Boolean OK;
+ int BCount;
+ Word AdrWord,z,z2;
+/* Byte Segment;*/
+ TempResult t;
+ LongInt HInt;
+
+
+ if (Memo("XSFR"))
+ BEGIN
+ CodeEquate(SegXData,0,MemLimit);
+ return True;
+ END
+
+ if (Memo("YSFR"))
+ BEGIN
+ CodeEquate(SegYData,0,MemLimit);
+ return True;
+ END
+
+ if (Memo("DS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrWord=EvalIntExpression(ArgStr[1],AdrInt,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ CodeLen=AdrWord; DontPrint=True;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("DC"))
+ BEGIN
+ if (ArgCnt<1) WrError(1110);
+ else
+ BEGIN
+ OK=True;
+ for (z=1 ; z<=ArgCnt; z++)
+ if (OK)
+ BEGIN
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (FirstPassUnknown) t.Contents.Int&=0xffffff;
+ if (NOT RangeCheck(t.Contents.Int,Int24))
+ BEGIN
+ WrError(1320); OK=False;
+ END
+ else
+ BEGIN
+ DAsmCode[CodeLen++]=t.Contents.Int & 0xffffff;
+ END
+ break;
+ case TempString:
+ BCount=2; DAsmCode[CodeLen]=0;
+ for (z2=0; z2<strlen(t.Contents.Ascii); z2++)
+ BEGIN
+ HInt=t.Contents.Ascii[z2];
+ HInt=CharTransTable[((usint) HInt)&0xff];
+ HInt<<=(BCount*8);
+ DAsmCode[CodeLen]|=HInt;
+ if (--BCount<0)
+ BEGIN
+ BCount=2; DAsmCode[++CodeLen]=0;
+ END
+ END
+ if (BCount!=2) CodeLen++;
+ break;
+ default:
+ WrError(1135); OK=False;
+ END
+ END
+ END
+ if (NOT OK) CodeLen=0;
+ return True;
+ END
+
+ return False;
+END
+
+static int ErrCode;
+static char *ErrString;
+
+ static void SetError(int Code)
+BEGIN
+ ErrCode=Code; ErrString="";
+END
+
+ static void SetXError(int Code, char *Ext)
+BEGIN
+ ErrCode=Code; ErrString=Ext;
+END
+
+ static void PrError(void)
+BEGIN
+ if (*ErrString!='\0') WrXError(ErrCode,ErrString);
+ else if (ErrCode!=0) WrError(ErrCode);
+END
+
+ static void MakeCode_56K(void)
+BEGIN
+ int z;
+ LongInt AddVal,h=0,h2,Reg1,Reg2,Reg3;
+ LongInt HVal,HCnt,HMode,HSeg,Dist;
+ LargeInt LAddVal;
+ Word Condition;
+ Boolean OK,DontAdd;
+ String Left,Mid,Right;
+ Byte Size;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<FixedOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ CodeLen=1; DAsmCode[0]=FixedOrders[z].Code;
+ END;
+ return;
+ END
+
+ /* ALU */
+
+ for (z=0; z<ParOrderCnt; z++)
+ if (Memo(ParOrders[z].Name))
+ BEGIN
+ if (DecodeMOVE(2))
+ BEGIN
+ ErrCode=0; ErrString=""; DontAdd=False;
+ switch (ParOrders[z].Typ)
+ BEGIN
+ case ParAB:
+ if (NOT DecodeALUReg(ArgStr[1],&Reg1,False,False,True)) SetXError(1445,ArgStr[1]);
+ else h=Reg1 << 3;
+ break;
+ case ParFixAB:
+ if (strcasecmp(ArgStr[1],"A,B")!=0) SetError(1760);
+ else h=0;
+ break;
+ case ParABShl1:
+ if (strchr(ArgStr[1],',')==Nil)
+ BEGIN
+ if (NOT DecodeALUReg(ArgStr[1],&Reg1,False,False,True)) SetXError(1445,ArgStr[1]);
+ else h=Reg1 << 3;
+ END
+ else if (ArgCnt!=1) SetError(1950);
+ else if (MomCPU<CPU56300) SetError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if (strchr(Right,',')==Nil) strcpy(Mid,Right);
+ else SplitArg(Right,Mid,Right);
+ if (NOT DecodeALUReg(Right,&Reg1,False,False,True)) SetXError(1445,Right);
+ else if (NOT DecodeALUReg(Mid,&Reg2,False,False,True)) SetXError(1445,Mid);
+ else if (*Left=='#')
+ BEGIN
+ AddVal=EvalIntExpression(Left+1,UInt6,&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x0c1c00+((ParOrders[z].Code & 0x10) << 4)+(Reg2 << 7)+
+ (AddVal << 1)+Reg1;
+ CodeLen=1; DontAdd=True;
+ END
+ END
+ else if (NOT DecodeXYAB1Reg(Left,&Reg3)) SetXError(1445,Left);
+ else
+ BEGIN
+ DAsmCode[0]=0x0c1e60-((ParOrders[z].Code & 0x10) << 2)+(Reg2 << 4)+
+ (Reg3 << 1)+Reg1;
+ CodeLen=1; DontAdd=True;
+ END
+ END
+ break;
+ case ParABShl2:
+ if (strchr(ArgStr[1],',')==Nil)
+ BEGIN
+ if (NOT DecodeALUReg(ArgStr[1],&Reg1,False,False,True)) SetXError(1445,ArgStr[1]);
+ else h=Reg1 << 3;
+ END
+ else if (ArgCnt!=1) SetError(1950);
+ else if (MomCPU<CPU56300) SetError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if (NOT DecodeALUReg(Right,&Reg1,False,False,True)) SetXError(1445,Right);
+ else if (*Left=='#')
+ BEGIN
+ AddVal=EvalIntExpression(Left+1,UInt5,&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x0c1e80+((0x33-ParOrders[z].Code) << 2)+
+ (AddVal << 1)+Reg1;
+ CodeLen=1; DontAdd=True;
+ END
+ END
+ else if (NOT DecodeXYAB1Reg(Left,&Reg3)) SetXError(1445,Left);
+ else
+ BEGIN
+ DAsmCode[0]=0x0c1e10+((0x33-ParOrders[z].Code) << 1)+
+ (Reg3 << 1)+Reg1;
+ CodeLen=1; DontAdd=True;
+ END
+ END
+ break;
+ case ParXYAB:
+ SplitArg(ArgStr[1],Left,Right);
+ if (NOT DecodeALUReg(Right,&Reg2,False,False,True)) SetXError(1445,Right);
+ else if (NOT DecodeLReg(Left,&Reg1)) SetXError(1445,Left);
+ else if ((Reg1<2) OR (Reg1>3)) SetXError(1445,Left);
+ else h=(Reg2 << 3) + ((Reg1-2) << 4);
+ break;
+ case ParABXYnAB:
+ SplitArg(ArgStr[1],Left,Right);
+ if (NOT DecodeALUReg(Right,&Reg2,False,False,True)) SetXError(1445,Right);
+ else if (*Left=='#')
+ BEGIN
+ if (Memo("CMPM")) SetError(1350);
+ else if (MomCPU<CPU56300) SetError(1500);
+ else if (ArgCnt!=1) SetError(1950);
+ else
+ BEGIN
+ AddVal=EvalIntExpression(Left+1,Int24,&OK);
+ if (NOT OK) SetError(-1);
+ else if ((AddVal>=0) AND (AddVal<=63))
+ BEGIN
+ DAsmCode[0]=0x014000+(AddVal << 8); h=0x80+(Reg2 << 3);
+ END
+ else
+ BEGIN
+ DAsmCode[0]=0x014000; h=0xc0+(Reg2 << 3);
+ DAsmCode[1]=AddVal & 0xffffff; CodeLen=2;
+ END
+ END
+ END
+ else
+ if (NOT DecodeXYABReg(Left,&Reg1)) SetXError(1445,Left);
+ else if ((Reg1 ^ Reg2)==1) SetError(1760);
+ else if ((Memo("CMPM")) AND ((Reg1 &6)==2)) SetXError(1445,Left);
+ else
+ BEGIN
+ if (Reg1<2) Reg1=Ord(NOT Memo("CMPM"));
+ h=(Reg2 << 3) + (Reg1 << 4);
+ END
+ break;
+ case ParABBA:
+ if (strcasecmp(ArgStr[1],"B,A")==0) h=0;
+ else if (strcasecmp(ArgStr[1],"A,B")==0) h=8;
+ else SetXError(1760,ArgStr[1]);
+ break;
+ case ParXYnAB:
+ SplitArg(ArgStr[1],Left,Right);
+ if (NOT DecodeALUReg(Right,&Reg2,False,False,True)) SetXError(1445,Right);
+ else if (*Left=='#')
+ BEGIN
+ if (MomCPU<CPU56300) SetError(1500);
+ else if (ArgCnt!=1) SetError(1950);
+ else
+ BEGIN
+ AddVal=EvalIntExpression(Left+1,Int24,&OK);
+ if (NOT OK) SetError(-1);
+ else if ((AddVal>=0) AND (AddVal<=63))
+ BEGIN
+ DAsmCode[0]=0x014080+(AddVal << 8)+(Reg2 << 3)+(ParOrders[z].Code&7);
+ CodeLen=1;
+ DontAdd=True;
+ END
+ else
+ BEGIN
+ DAsmCode[0]=0x0140c0+(Reg2 << 3)+(ParOrders[z].Code&7);
+ DAsmCode[1]=AddVal & 0xffffff; CodeLen=2;
+ DontAdd=True;
+ END
+ END
+ END
+ else
+ if (NOT DecodeReg(Left,&Reg1)) SetXError(1445,Left);
+ else if ((Reg1<4) OR (Reg1>7)) SetXError(1445,Left);
+ else h=(Reg2 << 3) + (TurnXY(Reg1) << 4);
+ break;
+ case ParMul:
+ SplitArg(ArgStr[1],Left,Mid); SplitArg(Mid,Mid,Right); h=0;
+ if (*Left=='-')
+ BEGIN
+ strcpy(Left,Left+1); h+=4;
+ END
+ else if (*Left=='+') strcpy(Left,Left+1);
+ if (NOT DecodeALUReg(Right,&Reg3,False,False,True)) SetXError(1445,Right);
+ else if (NOT DecodeReg(Left,&Reg1)) SetXError(1445,Left);
+ else if ((Reg1<4) OR (Reg1>7)) SetXError(1445,Left);
+ else if (*Mid=='#')
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AddVal=EvalIntExpression(Mid+1,UInt24,&OK);
+ if (FirstPassUnknown) AddVal=1;
+ if ((NOT (SingleBit(AddVal,&LAddVal))) OR (LAddVal>22)) WrError(1540);
+ else
+ BEGIN
+ LAddVal=23-LAddVal;
+ DAsmCode[0]=0x010040+(LAddVal << 8)+(Mac2Table[Reg1 & 3] << 4)
+ +(Reg3 << 3);
+ CodeLen=1;
+ END
+ END
+ END
+
+ else if (NOT DecodeReg(Mid,&Reg2)) SetXError(1445,Mid);
+ else if ((Reg2<4) OR (Reg2>7)) SetXError(1445,Mid);
+ else if (MacTable[Reg1-4][Reg2-4]==0xff) SetError(1760);
+ else h+=(Reg3 << 3) + (MacTable[Reg1-4][Reg2-4] << 4);
+ break;
+ END
+ if (ErrCode==0)
+ BEGIN
+ if (NOT DontAdd) DAsmCode[0]+=ParOrders[z].Code+h;
+ END
+ else
+ BEGIN
+ if (ErrCode>0) PrError(); CodeLen=0;
+ END
+ END
+ return;
+ END
+
+ if (Memo("DIV"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if ((*Left=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg2,False,False,True)) WrError(1350);
+ else if (NOT DecodeReg(Left,&Reg1)) WrError(1350);
+ else if ((Reg1<4) OR (Reg1>7)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x018040 + (Reg2 << 3) + (TurnXY(Reg1) << 4);
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ImmMacOrderCnt; z++)
+ if (Memo(ImmMacOrders[z]))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Mid); SplitArg(Mid,Mid,Right);
+ h=0;
+ switch (*Left)
+ BEGIN
+ case '-':
+ h=4;
+ case '+':
+ strcpy(Left,Left+1);
+ END
+ if ((*Mid=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg1,False,False,True)) WrXError(1445,Right);
+ else if (NOT DecodeXYABReg(Mid,&Reg2)) WrXError(1445,Mid);
+ else if ((Reg2<4) OR (Reg2>7)) WrXError(1445,Mid);
+ else if (*Left!='#') WrError(1120);
+ else
+ BEGIN
+ DAsmCode[1]=EvalIntExpression(Left+1,Int24,&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x0141c0+z+h+(Reg1 << 3)+((Reg2 & 3) << 4);
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((strncmp(OpPart,"DMAC",4)==0) AND (DecodeMix(OpPart+4,&Condition)))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Mid); SplitArg(Mid,Mid,Right);
+ if (*Left=='-')
+ BEGIN
+ strcpy(Left,Left+1); Condition+=16;
+ END
+ else if (*Left=='+') strcpy(Left,Left+1);
+ if ((*Mid=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg1,False,False,True)) WrXError(1445,Right);
+ else if (NOT DecodeXYAB1Reg(Mid,&Reg2)) WrXError(1445,Mid);
+ else if (Reg2<4) WrXError(1445,Mid);
+ else if (NOT DecodeXYAB1Reg(Left,&Reg3)) WrXError(1445,Left);
+ else if (Reg3<4) WrXError(1445,Left);
+ else
+ BEGIN
+ DAsmCode[0]=0x012480+Condition+(Reg1 << 5)+Mac4Table[Reg3-4][Reg2-4];
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (((strncmp(OpPart,"MAC",3)==0) OR (strncmp(OpPart,"MPY",3)==0))
+ AND (DecodeMix(OpPart+3,&Condition)))
+ BEGIN
+ if (Condition==0) WrXError(1200,OpPart);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ if (OpPart[1]=='A') Condition-=0x100;
+ SplitArg(ArgStr[1],Left,Mid); SplitArg(Mid,Mid,Right);
+ if (*Left=='-')
+ BEGIN
+ strcpy(Left,Left+1); Condition+=16;
+ END
+ else if (*Left=='+') strcpy(Left,Left+1);
+ if ((*Mid=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg1,False,False,True)) WrXError(1445,Right);
+ else if (NOT DecodeXYAB1Reg(Mid,&Reg2)) WrXError(1445,Mid);
+ else if (Reg2<4) WrXError(1445,Mid);
+ else if (NOT DecodeXYAB1Reg(Left,&Reg3)) WrXError(1445,Left);
+ else if (Reg3<4) WrXError(1445,Left);
+ else
+ BEGIN
+ DAsmCode[0]=0x012680+Condition+(Reg1 << 5)+Mac4Table[Reg3-4][Reg2-4];
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INC")) OR (Memo("DEC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56002) WrError(1500);
+ else if (NOT DecodeALUReg(ArgStr[1],&Reg1,False,False,True)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ DAsmCode[0]=0x000008+(Ord(Memo("DEC")) << 1)+Reg1;
+ CodeLen=1;
+ END
+ return;
+ END
+
+ if ((Memo("ANDI")) OR (Memo("ORI")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if ((*Left=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (NOT DecodeControlReg(Right,&Reg1)) WrError(1350);
+ else if (*Left!='#') WrError(1120);
+ else
+ BEGIN
+ h=EvalIntExpression(Left+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x0000b8 + ((h & 0xff) << 8) + (Ord(Memo("ORI")) << 6) + Reg1;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("NORM"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if ((*Left=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg2,False,False,True)) WrError(1350);
+ else if (NOT DecodeReg(Left,&Reg1)) WrError(1350);
+ else if ((Reg1<16) OR (Reg1>23)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x01d815 + ((Reg1 & 7) << 8) + (Reg2 << 3);
+ END
+ END
+ return;
+ END
+
+ if (Memo("NORMF"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if (*Right=='\0') WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg2,False,False,True)) WrXError(1445,Right);
+ else if (NOT DecodeXYAB1Reg(Left,&Reg1)) WrXError(1445,Left);
+ else
+ BEGIN
+ CodeLen=1; DAsmCode[0]=0x0c1e20+Reg2+(Reg1 << 1);
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z]))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Reg2=((z & 1) << 5) + (((LongInt) z >> 1) << 16);
+ SplitArg(ArgStr[1],Left,Right);
+ if ((*Left=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (*Left!='#') WrError(1120);
+ else
+ BEGIN
+ h=EvalIntExpression(Left+1,Int8,&OK);
+ if (FirstPassUnknown) h&=15;
+ if (OK)
+ if ((h<0) OR (h>23)) WrError(1320);
+ else if (DecodeGeneralReg(Right,&Reg1))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x0ac040 + h +(Reg1 << 8) + Reg2;
+ END
+ else
+ BEGIN
+ DecodeAdr(Right,MModNoImm,MSegXData+MSegYData);
+ Reg3=Ord(AdrSeg==SegYData) << 6;
+ if ((AdrType==ModAbs) AND (AdrVal<=63) AND (AdrVal>=0))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x0a0000 + h + (AdrVal << 8) + Reg3 + Reg2;
+ END
+ else if ((AdrType==ModAbs) AND (AdrVal>=MemLimit-0x3f) AND (AdrVal<=MemLimit))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x0a8000 + h + ((AdrVal & 0x3f) << 8) + Reg3 + Reg2;
+ END
+ else if ((AdrType==ModAbs) AND (MomCPU>=CPU56300) AND (AdrVal>=MemLimit-0x7f) AND (AdrVal<=MemLimit-0x40))
+ BEGIN
+ Reg2=((z & 1) << 5) + (((LongInt) z >> 1) << 14);
+ CodeLen=1;
+ DAsmCode[0] = 0x010000 + h + ((AdrVal & 0x3f) << 8) + Reg3 + Reg2;
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1+AdrCnt;
+ DAsmCode[0] = 0x0a4000 + h + (AdrMode << 8) + Reg3 + Reg2;
+ DAsmCode[1] = AdrVal;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("EXTRACT")) OR (Memo("EXTRACTU")))
+ BEGIN
+ z=Ord(Memo("EXTRACTU")) << 7;
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Mid); SplitArg(Mid,Mid,Right);
+ if ((*Mid=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg1,False,False,True)) WrXError(1445,Right);
+ else if (NOT DecodeALUReg(Mid,&Reg2,False,False,True)) WrXError(1445,Mid);
+ else if (*Left=='#')
+ BEGIN
+ DAsmCode[1]=EvalIntExpression(Left+1,Int24,&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x0c1800+z+Reg1+(Reg2 << 4); CodeLen=2;
+ END
+ END
+ else if (NOT DecodeXYAB1Reg(Left,&Reg3)) WrXError(1445,Left);
+ else
+ BEGIN
+ DAsmCode[0]=0x0c1a00+z+Reg1+(Reg2 << 4)+(Reg3 << 1);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("INSERT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Mid); SplitArg(Mid,Mid,Right);
+ if ((*Mid=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg1,False,False,True)) WrXError(1445,Right);
+ else if (NOT DecodeXYAB0Reg(Mid,&Reg2)) WrXError(1445,Mid);
+ else if (*Left=='#')
+ BEGIN
+ DAsmCode[1]=EvalIntExpression(Left+1,Int24,&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x0c1900+Reg1+(Reg2 << 4); CodeLen=2;
+ END
+ END
+ else if (NOT DecodeXYAB1Reg(Left,&Reg3)) WrXError(1445,Left);
+ else
+ BEGIN
+ DAsmCode[0]=0x0c1b00+Reg1+(Reg2 << 4)+(Reg3 << 1);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("MERGE"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if (*Right=='\0') WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg1,False,False,True)) WrXError(1445,Right);
+ else if (NOT DecodeXYAB1Reg(Left,&Reg2)) WrXError(1445,Left);
+ else
+ BEGIN
+ DAsmCode[0]=0x0c1b80+Reg1+(Reg2 << 1);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CLB"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if (*Right=='\0') WrError(1110);
+ else if (NOT DecodeALUReg(Left,&Reg1,False,False,True)) WrXError(1445,Left);
+ else if (NOT DecodeALUReg(Right,&Reg2,False,False,True)) WrXError(1445,Right);
+ else
+ BEGIN
+ DAsmCode[0]=0x0c1e00+Reg2+(Reg1 << 1);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CMPU"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if (*Right=='\0') WrError(1110);
+ else if (NOT DecodeALUReg(Right,&Reg1,False,False,True)) WrXError(1445,Right);
+ else if (NOT DecodeXYABReg(Left,&Reg2)) WrXError(1445,Left);
+ else if ((Reg1 ^ Reg2)==1) WrError(1760);
+ else if ((Reg2 & 6)==2) WrXError(1445,Left);
+ else
+ BEGIN
+ if (Reg2<2) Reg2=0;
+ DAsmCode[0]=0x0c1ff0+(Reg2 << 1)+Reg1;
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("MOVE"))
+ BEGIN
+ DecodeMOVE(1);
+ return;
+ END
+
+ if (Memo("MOVEC"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if (*Right=='\0') WrError(1110);
+ else if (DecodeCtrlReg(Left,&Reg1))
+ if (DecodeGeneralReg(Right,&Reg2))
+ BEGIN
+ DAsmCode[0]=0x0440a0+(Reg2 << 8)+Reg1; CodeLen=1;
+ END
+ else
+ BEGIN
+ DecodeAdr(Right,MModNoImm,MSegXData+MSegYData);
+ Reg3=(Ord(AdrSeg==SegYData)) << 6;
+ if ((AdrType==ModAbs) AND (AdrVal<=63))
+ BEGIN
+ DAsmCode[0]=0x050020+(AdrVal << 8)+Reg3+Reg1; CodeLen=1;
+ END
+ else
+ BEGIN
+ DAsmCode[0]=0x054020+(AdrMode << 8)+Reg3+Reg1;
+ DAsmCode[1]=AdrVal; CodeLen=1+AdrCnt;
+ END
+ END
+ else if (NOT DecodeCtrlReg(Right,&Reg1)) WrXError(1440,Right);
+ else
+ if (DecodeGeneralReg(Left,&Reg2))
+ BEGIN
+ DAsmCode[0]=0x04c0a0+(Reg2 << 8)+Reg1; CodeLen=1;
+ END
+ else
+ BEGIN
+ DecodeAdr(Left,MModAll,MSegXData+MSegYData);
+ Reg3=(Ord(AdrSeg==SegYData)) << 6;
+ if ((AdrType==ModAbs) AND (AdrVal<=63))
+ BEGIN
+ DAsmCode[0]=0x058020+(AdrVal << 8)+Reg3+Reg1; CodeLen=1;
+ END
+ else if ((AdrType==ModImm) AND (AdrVal<=255))
+ BEGIN
+ DAsmCode[0]=0x0500a0+(AdrVal << 8)+Reg1; CodeLen=1;
+ END
+ else
+ BEGIN
+ DAsmCode[0]=0x05c020+(AdrMode << 8)+Reg3+Reg1;
+ DAsmCode[1]=AdrVal; CodeLen=1+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOVEM"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if ((*Left=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (DecodeGeneralReg(Left,&Reg1))
+ BEGIN
+ DecodeAdr(Right,MModNoImm,MSegCode);
+ if ((AdrType==ModAbs) AND (AdrVal>=0) AND (AdrVal<=63))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x070000 + Reg1 + (AdrVal << 8);
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1+AdrCnt;
+ DAsmCode[1] = AdrVal;
+ DAsmCode[0] = 0x074080 + Reg1 + (AdrMode << 8);
+ END
+ END
+ else if (NOT DecodeGeneralReg(Right,&Reg2)) WrXError(1445,Right);
+ else
+ BEGIN
+ DecodeAdr(Left,MModNoImm,MSegCode);
+ if ((AdrType==ModAbs) AND (AdrVal>=0) AND (AdrVal<=63))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x078000 + Reg2 + (AdrVal << 8);
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ CodeLen = 1+AdrCnt;
+ DAsmCode[1] = AdrVal;
+ DAsmCode[0] = 0x07c080 + Reg2 + (AdrMode << 8);
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOVEP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if ((*Left=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (DecodeGeneralReg(Left,&Reg1))
+ BEGIN
+ DecodeAdr(Right,MModAbs,MSegXData+MSegYData);
+ if (AdrType!=ModNone)
+ if ((AdrVal<=MemLimit) AND (AdrVal>=MemLimit-0x3f))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x08c000 + (Ord(AdrSeg==SegYData) << 16) +
+ (AdrVal & 0x3f) + (Reg1 << 8);
+ END
+ else if ((MomCPU>=CPU56300) AND (AdrVal<=MemLimit-0x40) AND (AdrVal>=MemLimit-0x7f))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x04c000+(Ord(AdrSeg==SegYData) << 5)+
+ (Ord(AdrSeg==SegXData) << 7)+
+ (AdrVal & 0x1f)+((AdrVal & 0x20) << 1)+(Reg1 << 8);
+ END
+ else WrError(1315);
+ END
+ else if (DecodeGeneralReg(Right,&Reg2))
+ BEGIN
+ DecodeAdr(Left,MModAbs,MSegXData+MSegYData);
+ if (AdrType!=ModNone)
+ if ((AdrVal<=MemLimit) AND (AdrVal>=MemLimit-0x3f))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x084000 + (Ord(AdrSeg==SegYData) << 16) +
+ (AdrVal & 0x3f) + (Reg2 << 8);
+ END
+ else if ((MomCPU>=CPU56300) AND (AdrVal<=MemLimit-0x40) AND (AdrVal>=MemLimit-0x7f))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x044000+(Ord(AdrSeg==SegYData) << 5)+
+ (Ord(AdrSeg==SegXData) << 7)+
+ (AdrVal & 0x1f)+((AdrVal & 0x20) << 1)+(Reg2 << 8);
+ END
+ else WrError(1315);
+ END
+ else
+ BEGIN
+ DecodeAdr(Left,MModAll,MSegXData+MSegYData+MSegCode);
+ if ((AdrType==ModAbs) AND (AdrSeg!=SegCode) AND (AdrVal>=MemLimit-0x3f) AND (AdrVal<=MemLimit))
+ BEGIN
+ HVal=AdrVal & 0x3f; HSeg=AdrSeg;
+ DecodeAdr(Right,MModNoImm,MSegXData+MSegYData+MSegCode);
+ if (AdrType!=ModNone)
+ if (AdrSeg==SegCode)
+ BEGIN
+ CodeLen=1+AdrCnt;
+ DAsmCode[1] = AdrVal;
+ DAsmCode[0] = 0x084040 + HVal + (AdrMode << 8) +
+ (Ord(HSeg==SegYData) << 16);
+ END
+ else
+ BEGIN
+ CodeLen=1+AdrCnt;
+ DAsmCode[1] = AdrVal;
+ DAsmCode[0] = 0x084080 + HVal + (AdrMode << 8) +
+ (Ord(HSeg==SegYData) << 16) +
+ (Ord(AdrSeg==SegYData) << 6);
+ END
+ END
+ else if ((AdrType==ModAbs) AND (MomCPU>=CPU56300) AND (AdrSeg!=SegCode) AND (AdrVal>=MemLimit-0x7f) AND (AdrVal<=MemLimit-0x40))
+ BEGIN
+ HVal=AdrVal & 0x3f; HSeg=AdrSeg;
+ DecodeAdr(Right,MModNoImm,MSegXData+MSegYData+MSegCode);
+ if (AdrType!=ModNone)
+ if (AdrSeg==SegCode)
+ BEGIN
+ CodeLen=1+AdrCnt;
+ DAsmCode[1] = AdrVal;
+ DAsmCode[0] = 0x008000 + HVal + (AdrMode << 8) +
+ (Ord(HSeg==SegYData) << 6);
+ END
+ else
+ BEGIN
+ CodeLen=1+AdrCnt;
+ DAsmCode[1] = AdrVal;
+ DAsmCode[0] = 0x070000 + HVal + (AdrMode << 8) +
+ (Ord(HSeg==SegYData) << 7) +
+ (Ord(HSeg==SegXData) << 14) +
+ (Ord(AdrSeg==SegYData) << 6);
+ END
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ HVal=AdrVal; HCnt=AdrCnt; HMode=AdrMode; HSeg=AdrSeg;
+ DecodeAdr(Right,MModAbs,MSegXData+MSegYData);
+ if (AdrType!=ModNone)
+ if ((AdrVal>=MemLimit-0x3f) AND (AdrVal<=MemLimit))
+ BEGIN
+ if (HSeg==SegCode)
+ BEGIN
+ CodeLen=1+HCnt;
+ DAsmCode[1] = HVal;
+ DAsmCode[0] = 0x08c040 + (AdrVal & 0x3f) + (HMode << 8) +
+ (Ord(AdrSeg==SegYData) << 16);
+ END
+ else
+ BEGIN
+ CodeLen=1+HCnt;
+ DAsmCode[1] = HVal;
+ DAsmCode[0] = 0x08c080 + (((Word)AdrVal) & 0x3f) + (HMode << 8) +
+ (Ord(AdrSeg==SegYData) << 16) +
+ (Ord(HSeg==SegYData) << 6);
+ END
+ END
+ else if ((MomCPU>=CPU56300) AND (AdrVal>=MemLimit-0x7f) AND (AdrVal<=MemLimit-0x40))
+ BEGIN
+ if (HSeg==SegCode)
+ BEGIN
+ CodeLen=1+HCnt;
+ DAsmCode[1] = HVal;
+ DAsmCode[0] = 0x00c000 + (AdrVal & 0x3f) + (HMode << 8) +
+ (Ord(AdrSeg==SegYData) << 6);
+ END
+ else
+ BEGIN
+ CodeLen=1+HCnt;
+ DAsmCode[1] = HVal;
+ DAsmCode[0] = 0x078000 + (((Word)AdrVal) & 0x3f) + (HMode << 8) +
+ (Ord(AdrSeg==SegYData) << 7) +
+ (Ord(AdrSeg==SegXData) << 14) +
+ (Ord(HSeg==SegYData) << 6);
+ END
+ END
+ else WrError(1315);
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("TFR"))
+ BEGIN
+ if (ArgCnt<1) WrError(1110);
+ else if (DecodeMOVE(2))
+ if (DecodeTFR(ArgStr[1],&Reg1))
+ BEGIN
+ DAsmCode[0] += 0x01 + (Reg1 << 3);
+ END
+ else
+ BEGIN
+ WrError(1350); CodeLen=0;
+ END
+ return;
+ END
+
+ if ((*OpPart=='T') AND (DecodeCondition(OpPart+1,&Condition)))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if (DecodeTFR(ArgStr[1],&Reg1))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x020000+(Condition << 12)+(Reg1 << 3);
+ END
+ else if (NOT DecodeRR(ArgStr[2],&Reg2)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x030000+(Condition << 12)+(Reg1 << 3)+Reg2;
+ END
+ END
+ else if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeRR(ArgStr[1],&Reg1)) WrError(1350);
+ else
+ BEGIN
+ DAsmCode[0]=0x020800+(Condition << 12)+Reg1;
+ CodeLen=1;
+ END
+ return;
+ END
+
+ for (z=0; z<BitBrOrderCnt; z++)
+ if (Memo(BitBrOrders[z]))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ h=(z & 1) << 5;
+ h2=(((LongInt) z) & 2) << 15;
+ SplitArg(ArgStr[1],Left,Right); SplitArg(Right,Mid,Right);
+ if ((*Left=='\0') OR (*Right=='\0') OR (*Mid=='\0')) WrError(1110);
+ else if (*Left!='#') WrError(1120);
+ else
+ BEGIN
+ AddVal=EvalIntExpression(Left+1,Int8,&OK);
+ if (FirstPassUnknown) AddVal&=15;
+ if (OK)
+ if ((AddVal<0) OR (AddVal>23)) WrError(1320);
+ else if (DecodeGeneralReg(Mid,&Reg1))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x0cc080+AddVal+(Reg1 << 8)+h+h2;
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ DecodeAdr(Mid,MModNoImm,MSegXData+MSegYData);
+ Reg3=Ord(AdrSeg==SegYData) << 6;
+ if ((AdrType==ModAbs) AND (FirstPassUnknown)) AdrVal&=0x3f;
+ if ((AdrType==ModAbs) AND (AdrVal<=63) AND (AdrVal>=0))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x0c8080+AddVal+(AdrVal << 8)+Reg3+h+h2;
+ END
+ else if ((AdrType==ModAbs) AND (AdrVal>=MemLimit-0x3f) AND (AdrVal<=MemLimit))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x0cc000+AddVal+((AdrVal & 0x3f) << 8)+Reg3+h+h2;
+ END
+ else if ((AdrType==ModAbs) AND (AdrVal>=MemLimit-0x7f) AND (AdrVal<=MemLimit-0x40))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x048000+AddVal+((AdrVal & 0x3f) << 8)+Reg3+h+(h2 >> 9);
+ END
+ else if (AdrType==ModAbs) WrError(1350);
+ else if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x0c8000+AddVal+(AdrMode << 8)+Reg3+h+h2;
+ END
+ END
+ END
+ if (CodeLen==1)
+ BEGIN
+ Dist=EvalIntExpression(Right,AdrInt,&OK)-(EProgCounter()+2);
+ if (OK)
+ BEGIN
+ DAsmCode[1]=Dist & 0xffffff; CodeLen=2;
+ END
+ else CodeLen=0;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BRA")) OR (Memo("BSR")))
+ BEGIN
+ z=Memo("BRA") ? 0x40 : 0;
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else if (DecodeReg(ArgStr[1],&Reg1))
+ BEGIN
+ if ((Reg1<16) OR (Reg1>23)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Reg1-=16;
+ DAsmCode[0]=0x0d1880+(Reg1 << 8)+z;
+ CodeLen=1;
+ END
+ END
+ else
+ BEGIN
+ CutSize(ArgStr[1],&Size);
+ Dist=EvalIntExpression(ArgStr[1],AdrInt,&OK)-(EProgCounter()+1);
+ if (Size==0)
+ Size=((Dist>-256) AND (Dist<255)) ? 1 : 2;
+ switch (Size)
+ BEGIN
+ case 1:
+ if ((NOT SymbolQuestionable) AND ((Dist<-256) OR (Dist>255))) WrError(1370);
+ else
+ BEGIN
+ Dist&=0x1ff;
+ DAsmCode[0]=0x050800+(z << 4)+((Dist & 0x1e0) << 1)+(Dist & 0x1f);
+ CodeLen=1;
+ END
+ break;
+ case 2:
+ Dist--;
+ DAsmCode[0]=0x0d1080+z;
+ DAsmCode[1]=Dist & 0xffffff;
+ CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((*OpPart=='B') AND (DecodeCondition(OpPart+1,&Condition)))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else if (DecodeReg(ArgStr[1],&Reg1))
+ BEGIN
+ if ((Reg1<16) OR (Reg1>23)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Reg1-=16;
+ DAsmCode[0]=0x0d1840+(Reg1 << 8)+Condition;
+ CodeLen=1;
+ END
+ END
+ else
+ BEGIN
+ CutSize(ArgStr[1],&Size);
+ Dist=EvalIntExpression(ArgStr[1],AdrInt,&OK)-(EProgCounter()+1);
+ if (Size==0)
+ Size=((Dist>-256) AND (Dist<255)) ? 1 : 2;
+ switch (Size)
+ BEGIN
+ case 1:
+ if ((NOT SymbolQuestionable) AND ((Dist<-256) OR (Dist>255))) WrError(1370);
+ else
+ BEGIN
+ Dist&=0x1ff;
+ DAsmCode[0]=0x050400+(Condition << 12)+((Dist & 0x1e0) << 1)+(Dist & 0x1f);
+ CodeLen=1;
+ END
+ break;
+ case 2:
+ Dist--;
+ DAsmCode[0]=0x0d1040+Condition;
+ DAsmCode[1]=Dist & 0xffffff;
+ CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((strncmp(OpPart,"BS",2)==0) AND (DecodeCondition(OpPart+2,&Condition)))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else if (DecodeReg(ArgStr[1],&Reg1))
+ BEGIN
+ if ((Reg1<16) OR (Reg1>23)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Reg1-=16;
+ DAsmCode[0]=0x0d1800+(Reg1 << 8)+Condition;
+ CodeLen=1;
+ END
+ END
+ else
+ BEGIN
+ CutSize(ArgStr[1],&Size);
+ Dist=EvalIntExpression(ArgStr[1],AdrInt,&OK)-(EProgCounter()+1);
+ if (Size==0)
+ Size=((Dist>-256) AND (Dist<255)) ? 1 : 2;
+ switch (Size)
+ BEGIN
+ case 1:
+ if ((NOT SymbolQuestionable) AND ((Dist<-256) OR (Dist>255))) WrError(1370);
+ else
+ BEGIN
+ Dist&=0x1ff;
+ DAsmCode[0]=0x050000+(Condition << 12)+((Dist & 0x1e0) << 1)+(Dist & 0x1f);
+ CodeLen=1;
+ END
+ break;
+ case 2:
+ Dist--;
+ DAsmCode[0]=0x0d1000+Condition;
+ DAsmCode[1]=Dist & 0xffffff;
+ CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LUA")) OR (Memo("LEA")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if ((*Left=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (NOT DecodeReg(Right,&Reg1)) WrXError(1445,Right);
+ else if (Reg1>31) WrXError(1445,Right);
+ else
+ BEGIN
+ DecodeAdr(Left,MModModInc+MModModDec+MModPostInc+MModPostDec+MModDisp,MSegXData);
+ if (AdrType==ModDisp)
+ BEGIN
+ if (ChkRange(AdrVal,-64,63))
+ BEGIN
+ AdrVal&=0x7f;
+ DAsmCode[0]=0x040000+(Reg1-16)+(AdrMode << 8)+
+ ((AdrVal & 0x0f) << 4)+
+ ((AdrVal & 0x70) << 7);
+ CodeLen=1;
+ END
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0]=0x044000+(AdrMode << 8)+Reg1;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("LRA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Right);
+ if (*Right=='\0') WrError(1110);
+ else if (NOT DecodeGeneralReg(Right,&Reg1)) WrXError(1445,Right);
+ else if (Reg1>0x1f) WrXError(1445,Right);
+ else if (DecodeGeneralReg(Left,&Reg2))
+ BEGIN
+ if ((Reg2<16) OR (Reg2>23)) WrXError(1445,Left);
+ else
+ BEGIN
+ DAsmCode[0]=0x04c000+((Reg2 & 7) << 8)+Reg1;
+ CodeLen=1;
+ END
+ END
+ else
+ BEGIN
+ DAsmCode[1]=EvalIntExpression(Left,AdrInt,&OK)-(EProgCounter()+2);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=0x044040+Reg1;
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("PLOCK"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModNoImm,MSegCode);
+ if (AdrType!=ModNone)
+ BEGIN
+ DAsmCode[0]=0x0ac081+(AdrMode << 8); DAsmCode[1]=AdrVal;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PLOCKR")) OR (Memo("PUNLOCKR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ DAsmCode[1]=(EvalIntExpression(ArgStr[1],AdrInt,&OK)-(EProgCounter()+2)) & 0xffffff;
+ if (OK)
+ BEGIN /* ANSI :-O */
+ DAsmCode[0]=0x00000e + Ord(Memo("PUNLOCKR")); CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if ((Memo("JMP")) OR (Memo("JSR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AddVal=Ord(Memo("JSR")) << 16;
+ DecodeAdr(ArgStr[1],MModNoImm,MSegCode);
+ if (AdrType==ModAbs)
+ if ((AdrVal & 0xfff000)==0)
+ BEGIN
+ CodeLen=1; DAsmCode[0] = 0x0c0000 + AddVal + (AdrVal & 0xfff);
+ END
+ else
+ BEGIN
+ CodeLen=2; DAsmCode[0] = 0x0af080 + AddVal;
+ DAsmCode[1] = AdrVal;
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1; DAsmCode[0] = 0x0ac080 + AddVal + (AdrMode << 8);
+ END
+ END
+ return;
+ END
+
+ if ((*OpPart=='J') AND (DecodeCondition(OpPart+1,&Condition)))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModNoImm,MSegCode);
+ if (AdrType==ModAbs)
+ if ((AdrVal & 0xfff000)==0)
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x0e0000 + (Condition << 12) + (AdrVal & 0xfff);
+ END
+ else
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0] = 0x0af0a0 + Condition;
+ DAsmCode[1] = AdrVal;
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x0ac0a0 + Condition + (AdrMode << 8);
+ END
+ END
+ return;
+ END
+
+ if ((strncmp(OpPart,"JS",2)==0) AND (DecodeCondition(OpPart+2,&Condition)))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModNoImm,MSegCode);
+ if (AdrType==ModAbs)
+ if ((AdrVal & 0xfff000)==0)
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x0f0000 + (Condition << 12) + (AdrVal & 0xfff);
+ END
+ else
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0] = 0x0bf0a0 + Condition;
+ DAsmCode[1] = AdrVal;
+ END
+ else if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x0bc0a0 + Condition + (AdrMode << 8);
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitJmpOrderCnt; z++)
+ if (Memo(BitJmpOrders[z]))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ SplitArg(ArgStr[1],Left,Mid); SplitArg(Mid,Mid,Right);
+ if ((*Left=='\0') OR (*Mid=='\0') OR (*Right=='\0')) WrError(1110);
+ else if (*Left!='#') WrError(1120);
+ else
+ BEGIN
+ DAsmCode[1]=EvalIntExpression(Right,AdrInt,&OK);
+ if (OK)
+ BEGIN
+ h=EvalIntExpression(Left+1,Int8,&OK);
+ if (FirstPassUnknown) h&=15;
+ if (OK)
+ if ((h<0) OR (h>23)) WrError(1320);
+ else
+ BEGIN
+ Reg2=((z & 1) << 5) + (((LongInt)(z >> 1)) << 16);
+ if (DecodeGeneralReg(Mid,&Reg1))
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0] = 0x0ac000 + h + Reg2 + (Reg1 << 8);
+ END
+ else
+ BEGIN
+ DecodeAdr(Mid,MModNoImm,MSegXData+MSegYData);
+ Reg3=Ord(AdrSeg==SegYData) << 6;
+ if (AdrType==ModAbs)
+ if ((AdrVal>=0) AND (AdrVal<=63))
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0] = 0x0a0080 + h + Reg2 + Reg3 + (AdrVal << 8);
+ END
+ else if ((AdrVal>=MemLimit-0x3f) AND (AdrVal<=MemLimit))
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0] = 0x0a8080 + h + Reg2 + Reg3 + ((AdrVal & 0x3f) << 8);
+ END
+ else if ((MomCPU>=CPU56300) AND (AdrVal>=MemLimit-0x7f) AND (AdrVal<=MemLimit-0x40))
+ BEGIN
+ CodeLen=2;
+ Reg2=((z & 1) << 5) + (((LongInt)(z >> 1)) << 14);
+ DAsmCode[0] = 0x018080 + h + Reg2 + Reg3 + ((AdrVal & 0x3f) << 8);
+ END
+ else WrError(1320);
+ else
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0] = 0x0a4080 + h + Reg2 + Reg3 + (AdrMode << 8);
+ END
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("DO")) OR (Memo("DOR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ z=Ord(Memo("DOR"));
+ SplitArg(ArgStr[1],Left,Right);
+ if ((*Left=='\0') OR (*Right=='\0')) WrError(1110);
+ else
+ BEGIN
+ DAsmCode[1]=EvalIntExpression(Right,AdrInt,&OK)-1;
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+ if (strcasecmp(Left,"FOREVER")==0)
+ BEGIN
+ if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ DAsmCode[0]=0x000203-z;
+ CodeLen=2;
+ END
+ END
+ else if (DecodeGeneralReg(Left,&Reg1))
+ BEGIN
+ if (Reg1==0x3c) WrXError(1445,Left); /* kein SSH!! */
+ else
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0]=0x06c000+(Reg1 << 8)+(z << 4);
+ END
+ END
+ else if (*Left=='#')
+ BEGIN
+ Reg1=EvalIntExpression(Left+1,UInt12,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0]=0x060080+(Reg1 >> 8)+((Reg1 & 0xff) << 8)+(z << 4);
+ END
+ END
+ else
+ BEGIN
+ DecodeAdr(Left,MModNoImm,MSegXData+MSegYData);
+ if (AdrType==ModAbs)
+ if ((AdrVal<0) OR (AdrVal>63)) WrError(1320);
+ else
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0]=0x060000+(AdrVal << 8)+(Ord(AdrSeg==SegYData) << 6)+(z << 4);
+ END
+ else
+ BEGIN
+ CodeLen=2;
+ DAsmCode[0]=0x064000+(AdrMode << 8)+(Ord(AdrSeg==SegYData) << 6)+(z << 4);
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((strncmp(OpPart,"BRK",3)==0) AND (DecodeCondition(OpPart+3,&Condition)))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ DAsmCode[0]=0x00000210+Condition;
+ CodeLen=1;
+ END
+ return;
+ END
+
+ if ((strncmp(OpPart,"TRAP",4)==0) AND (DecodeCondition(OpPart+4,&Condition)))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ DAsmCode[0]=0x000010+Condition;
+ CodeLen=1;
+ END
+ return;
+ END
+
+ if ((strncmp(OpPart,"DEBUG",5)==0) AND (DecodeCondition(OpPart+5,&Condition)))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<CPU56300) WrError(1500);
+ else
+ BEGIN
+ DAsmCode[0]=0x00000300+Condition;
+ CodeLen=1;
+ END
+ return;
+ END
+
+ if (Memo("REP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeGeneralReg(ArgStr[1],&Reg1))
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x06c020 + (Reg1 << 8);
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAll,MSegXData+MSegYData);
+ if (AdrType==ModImm)
+ if ((AdrVal<0) OR (AdrVal>0xfff)) WrError(1320);
+ else
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x0600a0 + (AdrVal >> 8) + ((AdrVal & 0xff) << 8);
+ END
+ else if (AdrType==ModAbs)
+ if ((AdrVal<0) OR (AdrVal>63)) WrError(1320);
+ else
+ BEGIN
+ CodeLen=1;
+ DAsmCode[0] = 0x060020 + (AdrVal << 8) + (Ord(AdrSeg==SegYData) << 6);
+ END
+ else
+ BEGIN
+ CodeLen=1+AdrCnt;
+ DAsmCode[1] = AdrVal;
+ DAsmCode[0] = 0x064020 + (AdrMode << 8) + (Ord(AdrSeg==SegYData) << 6);
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_56K(void)
+BEGIN
+ return ((Memo("XSFR")) OR (Memo("YSFR")));
+END
+
+ static void SwitchFrom_56K(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_56K(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x09; NOPCode=0x000000;
+ DivideChars=" \009"; HasAttrs=False;
+
+ if (MomCPU==CPU56300)
+ BEGIN
+ AdrInt=UInt24; MemLimit=0xffffffl;
+ END
+ else
+ BEGIN
+ AdrInt=UInt16; MemLimit=0xffff;
+ END
+
+ ValidSegs=(1<<SegCode)|(1<<SegXData)|(1<<SegYData);
+ Grans[SegCode ]=4; ListGrans[SegCode ]=4; SegInits[SegCode ]=0;
+ SegLimits[SegCode ] = MemLimit;
+ Grans[SegXData]=4; ListGrans[SegXData]=4; SegInits[SegXData]=0;
+ SegLimits[SegXData] = MemLimit;
+ Grans[SegYData]=4; ListGrans[SegYData]=4; SegInits[SegYData]=0;
+ SegLimits[SegYData] = MemLimit;
+
+ MakeCode=MakeCode_56K; IsDef=IsDef_56K;
+ SwitchFrom=SwitchFrom_56K; InitFields();
+END
+
+ void code56k_init(void)
+BEGIN
+ CPU56000=AddCPU("56000",SwitchTo_56K);
+ CPU56002=AddCPU("56002",SwitchTo_56K);
+ CPU56300=AddCPU("56300",SwitchTo_56K);
+END
+
diff --git a/code56k.h b/code56k.h
new file mode 100644
index 0000000..cbc2656
--- /dev/null
+++ b/code56k.h
@@ -0,0 +1,11 @@
+/* code56k.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegeneratormodul fuer die DSP56K-Familie */
+/* */
+/* Historie: 10. 6.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code56k_init(void);
diff --git a/code601.c b/code601.c
new file mode 100644
index 0000000..001444e
--- /dev/null
+++ b/code601.c
@@ -0,0 +1,2017 @@
+/* code601.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator PowerPC-Familie */
+/* */
+/* Historie: 17.10.1996 Grundsteinlegung */
+/* 30. 8.1998 Umstellung auf 32-Bit-Zugriffe */
+/* Header-ID per Abfrage */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* 9. 3.1999 MMU-Instruktionen */
+/* 10. 3.1999 PPC403-MMU-Befehle */
+/* 28. 3.1999 PPC403GB auf GC korrigiert (erst der hat eine MMU) */
+/* 8. 9.1999 REG-Befehl nachgeruestet */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "endian.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+#include "headids.h"
+
+typedef struct
+ {
+ char *Name;
+ LongWord Code;
+ Byte CPUMask;
+ } BaseOrder;
+
+#define FixedOrderCount 8
+#define Reg1OrderCount 4
+#define FReg1OrderCount 2
+#define CReg1OrderCount 1
+#define CBit1OrderCount 4
+#define Reg2OrderCount 29
+#define CReg2OrderCount 2
+#define FReg2OrderCount 14
+#define Reg2BOrderCount 2
+#define Reg2SwapOrderCount 6
+#define NoDestOrderCount 10
+#define Reg3OrderCount 91
+#define CReg3OrderCount 8
+#define FReg3OrderCount 10
+#define Reg3SwapOrderCount 49
+#define MixedOrderCount 8
+#define FReg4OrderCount 16
+#define RegDispOrderCount 16
+#define FRegDispOrderCount 8
+#define Reg2ImmOrderCount 12
+#define Imm16OrderCount 7
+#define Imm16SwapOrderCount 6
+
+static BaseOrder *FixedOrders;
+static BaseOrder *Reg1Orders;
+static BaseOrder *CReg1Orders;
+static BaseOrder *CBit1Orders;
+static BaseOrder *FReg1Orders;
+static BaseOrder *Reg2Orders;
+static BaseOrder *CReg2Orders;
+static BaseOrder *FReg2Orders;
+static BaseOrder *Reg2BOrders;
+static BaseOrder *Reg2SwapOrders;
+static BaseOrder *NoDestOrders;
+static BaseOrder *Reg3Orders;
+static BaseOrder *CReg3Orders;
+static BaseOrder *FReg3Orders;
+static BaseOrder *Reg3SwapOrders;
+static BaseOrder *MixedOrders;
+static BaseOrder *FReg4Orders;
+static BaseOrder *RegDispOrders;
+static BaseOrder *FRegDispOrders;
+static BaseOrder *Reg2ImmOrders;
+static BaseOrder *Imm16Orders;
+static BaseOrder *Imm16SwapOrders;
+
+static SimpProc SaveInitProc;
+static Boolean BigEnd;
+
+static CPUVar CPU403, CPU403C, CPU505, CPU601, CPU6000;
+
+#define M_403 0x01
+#define M_403C 0x02
+#define M_505 0x04
+#define M_601 0x08
+#define M_6000 0x10
+
+/*-------------------------------------------------------------------------*/
+/*
+ PROCEDURE EnterByte(b:Byte);
+ BEGIN
+ if Odd(CodeLen)
+ BEGIN
+ BAsmCode[CodeLen]:=BAsmCode[CodeLen-1];
+ BAsmCode[CodeLen-1]:=b;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]:=b;
+ END;
+ Inc(CodeLen);
+END;
+*/
+/*-------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName1, char *NName2, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddReg1(char *NName1, char *NName2, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=Reg1OrderCount) exit(255);
+ Reg1Orders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ Reg1Orders[InstrZ].Code=NCode;
+ Reg1Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddCReg1(char *NName1, char *NName2, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=CReg1OrderCount) exit(255);
+ CReg1Orders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ CReg1Orders[InstrZ].Code=NCode;
+ CReg1Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddCBit1(char *NName1, char *NName2, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=CBit1OrderCount) exit(255);
+ CBit1Orders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ CBit1Orders[InstrZ].Code=NCode;
+ CBit1Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddFReg1(char *NName1, char *NName2, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=FReg1OrderCount) exit(255);
+ FReg1Orders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ FReg1Orders[InstrZ].Code=NCode;
+ FReg1Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddSReg2(char *NName, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=Reg2OrderCount) exit(255);
+ if (NName==Nil) exit(255);
+ Reg2Orders[InstrZ].Name=NName;
+ Reg2Orders[InstrZ].Code=NCode;
+ Reg2Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddReg2(char *NName1, char *NName2, LongInt NCode, Byte NMask, Boolean WithOE, Boolean WithFL)
+BEGIN
+ String NName;
+
+ strcpy(NName,(MomCPU==CPU6000)?NName2:NName1);
+ AddSReg2(strdup(NName),NCode,NMask);
+ if (WithOE)
+ BEGIN
+ strcat(NName,"O");
+ AddSReg2(strdup(NName),NCode | 0x400,NMask);
+ NName[strlen(NName)-1]='\0';
+ END
+ if (WithFL)
+ BEGIN
+ strcat(NName,".");
+ AddSReg2(strdup(NName),NCode | 0x001,NMask);
+ NName[strlen(NName)-1]='\0';
+ if (WithOE)
+ BEGIN
+ strcat(NName,"O.");
+ AddSReg2(strdup(NName),NCode | 0x401,NMask);
+ END
+ END
+END
+
+ static void AddCReg2(char *NName1, char *NName2, LongWord NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=CReg2OrderCount) exit(255);
+ CReg2Orders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ CReg2Orders[InstrZ].Code=NCode;
+ CReg2Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddSFReg2(char *NName, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=FReg2OrderCount) exit(255);
+ if (NName==Nil) exit(255);
+ FReg2Orders[InstrZ].Name=NName;
+ FReg2Orders[InstrZ].Code=NCode;
+ FReg2Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddFReg2(char *NName1, char *NName2, LongInt NCode, Byte NMask, Boolean WithFL)
+BEGIN
+ String NName;
+
+ strcpy(NName,(MomCPU==CPU6000)?NName2:NName1);
+ AddSFReg2(strdup(NName),NCode,NMask);
+ if (WithFL)
+ BEGIN
+ strcat(NName,".");
+ AddSFReg2(strdup(NName),NCode | 0x001,NMask);
+ END
+END
+
+ static void AddReg2B(char *NName1, char *NName2, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=Reg2BOrderCount) exit(255);
+ Reg2BOrders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ Reg2BOrders[InstrZ].Code=NCode;
+ Reg2BOrders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddSReg2Swap(char *NName, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=Reg2SwapOrderCount) exit(255);
+ if (NName==Nil) exit(255);
+ Reg2SwapOrders[InstrZ].Name=NName;
+ Reg2SwapOrders[InstrZ].Code=NCode;
+ Reg2SwapOrders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddReg2Swap(char *NName1, char *NName2, LongInt NCode, Byte NMask, Boolean WithOE, Boolean WithFL)
+BEGIN
+ String NName;
+
+ strcpy(NName,(MomCPU==CPU6000)?NName2:NName1);
+ AddSReg2Swap(strdup(NName),NCode,NMask);
+ if (WithOE)
+ BEGIN
+ strcat(NName,"O");
+ AddSReg2Swap(strdup(NName),NCode | 0x400,NMask);
+ NName[strlen(NName)-1]='\0';
+ END
+ if (WithFL)
+ BEGIN
+ strcat(NName,".");
+ AddSReg2Swap(strdup(NName),NCode | 0x001,NMask);
+ NName[strlen(NName)-1]='\0';
+ if (WithOE)
+ BEGIN
+ strcat(NName,"O.");
+ AddSReg2Swap(strdup(NName),NCode | 0x401,NMask);
+ END
+ END
+END
+
+ static void AddNoDest(char *NName1, char *NName2, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=NoDestOrderCount) exit(255);
+ NoDestOrders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ NoDestOrders[InstrZ].Code=NCode;
+ NoDestOrders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddSReg3(char *NName, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=Reg3OrderCount) exit(255);
+ if (NName==Nil) exit(255);
+ Reg3Orders[InstrZ].Name=NName;
+ Reg3Orders[InstrZ].Code=NCode;
+ Reg3Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddReg3(char *NName1, char *NName2, LongInt NCode, Byte NMask, Boolean WithOE, Boolean WithFL)
+BEGIN
+ String NName;
+
+ strcpy(NName,(MomCPU==CPU6000)?NName2:NName1);
+ AddSReg3(strdup(NName),NCode,NMask);
+ if (WithOE)
+ BEGIN
+ strcat(NName,"O");
+ AddSReg3(strdup(NName),NCode | 0x400,NMask);
+ NName[strlen(NName)-1]='\0';
+ END
+ if (WithFL)
+ BEGIN
+ strcat(NName,".");
+ AddSReg3(strdup(NName),NCode | 0x001,NMask);
+ NName[strlen(NName)-1]='\0';
+ if (WithOE)
+ BEGIN
+ strcat(NName,"O.");
+ AddSReg3(strdup(NName),NCode | 0x401,NMask);
+ END
+ END
+END
+
+ static void AddCReg3(char *NName, LongWord NCode, CPUVar NMask)
+BEGIN
+ if (InstrZ>=CReg3OrderCount) exit(255);
+ CReg3Orders[InstrZ].Name=NName;
+ CReg3Orders[InstrZ].Code=NCode;
+ CReg3Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddSFReg3(char *NName, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=FReg3OrderCount) exit(255);
+ if (NName==Nil) exit(255);
+ FReg3Orders[InstrZ].Name=NName;
+ FReg3Orders[InstrZ].Code=NCode;
+ FReg3Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddFReg3(char *NName1, char *NName2, LongInt NCode, Byte NMask, Boolean WithFL)
+BEGIN
+ String NName;
+
+ strcpy(NName,(MomCPU==CPU6000)?NName2:NName1);
+ AddSFReg3(strdup(NName),NCode,NMask);
+ if (WithFL)
+ BEGIN
+ strcat(NName,".");
+ AddSFReg3(strdup(NName),NCode | 0x001,NMask);
+ END
+END
+
+ static void AddSReg3Swap(char *NName, LongInt NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=Reg3SwapOrderCount) exit(255);
+ if (NName==Nil) exit(255);
+ Reg3SwapOrders[InstrZ].Name=NName;
+ Reg3SwapOrders[InstrZ].Code=NCode;
+ Reg3SwapOrders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddReg3Swap(char *NName1, char *NName2, LongInt NCode, Byte NMask, Boolean WithFL)
+BEGIN
+ String NName;
+
+ strcpy(NName,(MomCPU==CPU6000)?NName2:NName1);
+ AddSReg3Swap(strdup(NName),NCode,NMask);
+ if (WithFL)
+ BEGIN
+ strcat(NName,".");
+ AddSReg3Swap(strdup(NName),NCode | 0x001,NMask);
+ END
+END
+
+ static void AddMixed(char *NName1, char *NName2, LongWord NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=MixedOrderCount) exit(255);
+ MixedOrders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ MixedOrders[InstrZ].Code=NCode;
+ MixedOrders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddSFReg4(char *NName, LongWord NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=FReg4OrderCount) exit(255);
+ if (NName==Nil) exit(255);
+ FReg4Orders[InstrZ].Name=NName;
+ FReg4Orders[InstrZ].Code=NCode;
+ FReg4Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddFReg4(char *NName1, char *NName2, LongWord NCode, Byte NMask, Boolean WithFL)
+BEGIN
+ String NName;
+
+ strcpy(NName,(MomCPU==CPU6000)?NName2:NName1);
+ AddSFReg4(strdup(NName),NCode,NMask);
+ if (WithFL)
+ BEGIN
+ strcat(NName,".");
+ AddSFReg4(strdup(NName),NCode | 0x001,NMask);
+ END
+END
+
+ static void AddRegDisp(char *NName1, char *NName2, LongWord NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=RegDispOrderCount) exit(255);
+ RegDispOrders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ RegDispOrders[InstrZ].Code=NCode;
+ RegDispOrders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddFRegDisp(char *NName1, char *NName2, LongWord NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=FRegDispOrderCount) exit(255);
+ FRegDispOrders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ FRegDispOrders[InstrZ].Code=NCode;
+ FRegDispOrders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddSReg2Imm(char *NName, LongWord NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=Reg2ImmOrderCount) exit(255);
+ if (NName==Nil) exit(255);
+ Reg2ImmOrders[InstrZ].Name=NName;
+ Reg2ImmOrders[InstrZ].Code=NCode;
+ Reg2ImmOrders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddReg2Imm(char *NName1, char *NName2, LongWord NCode, Byte NMask, Boolean WithFL)
+BEGIN
+ String NName;
+
+ strcpy(NName,(MomCPU==CPU6000)?NName2:NName1);
+ AddSReg2Imm(strdup(NName),NCode,NMask);
+ if (WithFL)
+ BEGIN
+ strcat(NName,".");
+ AddSReg2Imm(strdup(NName),NCode | 0x001,NMask);
+ END
+END
+
+ static void AddImm16(char *NName1, char *NName2, LongWord NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=Imm16OrderCount) exit(255);
+ Imm16Orders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ Imm16Orders[InstrZ].Code=NCode;
+ Imm16Orders[InstrZ++].CPUMask=NMask;
+END
+
+ static void AddImm16Swap(char *NName1, char *NName2, LongWord NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=Imm16SwapOrderCount) exit(255);
+ Imm16SwapOrders[InstrZ].Name=(MomCPU==CPU6000)?NName2:NName1;
+ Imm16SwapOrders[InstrZ].Code=NCode;
+ Imm16SwapOrders[InstrZ++].CPUMask=NMask;
+END
+
+#ifdef __STDC__
+#define T1 1lu
+#define T3 3lu
+#define T4 4lu
+#define T7 7lu
+#define T8 8lu
+#define T9 9lu
+#define T10 10lu
+#define T11 11lu
+#define T12 12lu
+#define T13 13lu
+#define T14 14lu
+#define T15 15lu
+#define T16 16lu
+#define T17 17lu
+#define T18 18lu
+#define T19 19lu
+#define T20 20lu
+#define T21 21lu
+#define T22 22lu
+#define T23 23lu
+#define T24 24lu
+#define T25 25lu
+#define T26 26lu
+#define T27 27lu
+#define T28 28lu
+#define T29 29lu
+#define T31 31lu
+#define T32 32lu
+#define T33 33lu
+#define T34 34lu
+#define T35 35lu
+#define T36 36lu
+#define T37 37lu
+#define T38 38lu
+#define T39 39lu
+#define T40 40lu
+#define T41 41lu
+#define T42 42lu
+#define T43 43lu
+#define T44 44lu
+#define T45 45lu
+#define T46 46lu
+#define T47 47lu
+#define T48 48lu
+#define T49 49lu
+#define T50 50lu
+#define T51 51lu
+#define T52 52lu
+#define T53 53lu
+#define T54 54lu
+#define T55 55lu
+#define T59 59lu
+#define T63 63lu
+#else
+#define T1 1l
+#define T3 3l
+#define T4 4l
+#define T7 7l
+#define T8 8l
+#define T9 9l
+#define T10 10l
+#define T11 11l
+#define T12 12l
+#define T13 13l
+#define T14 14l
+#define T15 15l
+#define T16 16l
+#define T17 17l
+#define T18 18l
+#define T19 19l
+#define T20 20l
+#define T21 21l
+#define T22 22l
+#define T23 23l
+#define T24 24l
+#define T25 25l
+#define T26 26l
+#define T27 27l
+#define T28 28l
+#define T29 29l
+#define T31 31l
+#define T32 32l
+#define T33 33l
+#define T34 34l
+#define T35 35l
+#define T36 36l
+#define T37 37l
+#define T38 38l
+#define T39 39l
+#define T40 40l
+#define T41 41l
+#define T42 42l
+#define T43 43l
+#define T44 44l
+#define T45 45l
+#define T46 46l
+#define T47 47l
+#define T48 48l
+#define T49 49l
+#define T50 50l
+#define T51 51l
+#define T52 52l
+#define T53 53l
+#define T54 54l
+#define T55 55l
+#define T59 59l
+#define T63 63l
+#endif
+
+ static void InitFields(void)
+BEGIN
+ /* --> 0 0 0 */
+
+ FixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("EIEIO" ,"EIEIO" ,(T31 << 26)+(854 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddFixed("ISYNC" ,"ICS" ,(T19 << 26)+(150 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddFixed("RFI" ,"RFI" ,(T19 << 26)+( 50 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddFixed("SC" ,"SVCA" ,(T17 << 26)+( 1 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddFixed("SYNC" ,"DCS" ,(T31 << 26)+(598 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddFixed("RFCI" ,"RFCI" ,(T19 << 26)+( 51 << 1), M_403 | M_403C );
+ AddFixed("TLBIA" ,"TLBIA" ,(T31 << 26)+(370 << 1), M_403C );
+ AddFixed("TLBSYNC","TLBSYNC",(T31 << 26)+(566 << 1), M_403C );
+
+ /* D --> D 0 0 */
+
+ Reg1Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*Reg1OrderCount); InstrZ=0;
+ AddReg1("MFCR" ,"MFCR" ,(T31 << 26)+( 19 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddReg1("MFMSR" ,"MFMSR" ,(T31 << 26)+( 83 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddReg1("MTMSR" ,"MTMSR" ,(T31 << 26)+(146 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddReg1("WRTEE" ,"WRTEE" ,(T31 << 26)+(131 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+
+ /* crD --> D 0 0 */
+
+ CReg1Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*CReg1OrderCount); InstrZ=0;
+ AddCReg1("MCRXR" ,"MCRXR" ,(T31 << 26)+(512 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+
+ /* crbD --> D 0 0 */
+
+ CBit1Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*CBit1OrderCount); InstrZ=0;
+ AddCBit1("MTFSB0" ,"MTFSB0" ,(T63 << 26)+( 70 << 1) , M_601 | M_6000);
+ AddCBit1("MTFSB0.","MTFSB0.",(T63 << 26)+( 70 << 1)+1, M_601 | M_6000);
+ AddCBit1("MTFSB1" ,"MTFSB1" ,(T63 << 26)+( 38 << 1) , M_601 | M_6000);
+ AddCBit1("MTFSB1.","MTFSB1.",(T63 << 26)+( 38 << 1)+1, M_601 | M_6000);
+
+ /* frD --> D 0 0 */
+
+ FReg1Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*FReg1OrderCount); InstrZ=0;
+ AddFReg1("MFFS" ,"MFFS" ,(T63 << 26)+(583 << 1) , M_601 | M_6000);
+ AddFReg1("MFFS." ,"MFFS." ,(T63 << 26)+(583 << 1)+1, M_601 | M_6000);
+
+ /* D,A --> D A 0 */
+
+ Reg2Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*Reg2OrderCount); InstrZ=0;
+ AddReg2("ABS" ,"ABS" ,(T31 << 26)+(360 << 1), M_6000,True ,True );
+ AddReg2("ADDME" ,"AME" ,(T31 << 26)+(234 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg2("ADDZE" ,"AZE" ,(T31 << 26)+(202 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg2("CLCS" ,"CLCS" ,(T31 << 26)+(531 << 1), M_6000,False,False);
+ AddReg2("NABS" ,"NABS" ,(T31 << 26)+(488 << 1), M_6000,True ,True );
+ AddReg2("NEG" ,"NEG" ,(T31 << 26)+(104 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg2("SUBFME","SFME" ,(T31 << 26)+(232 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg2("SUBFZE","SFZE" ,(T31 << 26)+(200 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+
+ /* cD,cS --> D S 0 */
+
+ CReg2Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*CReg2OrderCount); InstrZ=0;
+ AddCReg2("MCRF" ,"MCRF" ,(T19 << 26)+( 0 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddCReg2("MCRFS" ,"MCRFS" ,(T63 << 26)+( 64 << 1), M_601 | M_6000);
+
+ /* fD,fB --> D 0 B */
+
+ FReg2Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*FReg2OrderCount); InstrZ=0;
+ AddFReg2("FABS" ,"FABS" ,(T63 << 26)+(264 << 1), M_601 | M_6000,True );
+ AddFReg2("FCTIW" ,"FCTIW" ,(T63 << 26)+( 14 << 1), M_601 | M_6000,True );
+ AddFReg2("FCTIWZ","FCTIWZ",(T63 << 26)+( 15 << 1), M_601 | M_6000,True );
+ AddFReg2("FMR" ,"FMR" ,(T63 << 26)+( 72 << 1), M_601 | M_6000,True );
+ AddFReg2("FNABS" ,"FNABS" ,(T63 << 26)+(136 << 1), M_601 | M_6000,True );
+ AddFReg2("FNEG" ,"FNEG" ,(T63 << 26)+( 40 << 1), M_601 | M_6000,True );
+ AddFReg2("FRSP" ,"FRSP" ,(T63 << 26)+( 12 << 1), M_601 | M_6000,True );
+
+ /* D,B --> D 0 B */
+
+ Reg2BOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*Reg2BOrderCount); InstrZ=0;
+ AddReg2B("MFSRIN","MFSRIN",(T31 << 26)+(659 << 1), M_601 | M_6000);
+ AddReg2B("MTSRIN","MTSRI" ,(T31 << 26)+(242 << 1), M_601 | M_6000);
+
+ /* A,S --> S A 0 */
+
+ Reg2SwapOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*Reg2SwapOrderCount); InstrZ=0;
+ AddReg2Swap("CNTLZW","CNTLZ" ,(T31 << 26)+( 26 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,True );
+ AddReg2Swap("EXTSB ","EXTSB" ,(T31 << 26)+(954 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,True );
+ AddReg2Swap("EXTSH ","EXTS" ,(T31 << 26)+(922 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,True );
+
+ /* A,B --> 0 A B */
+
+ NoDestOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*NoDestOrderCount); InstrZ=0;
+ AddNoDest("DCBF" ,"DCBF" ,(T31 << 26)+( 86 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddNoDest("DCBI" ,"DCBI" ,(T31 << 26)+( 470 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddNoDest("DCBST" ,"DCBST" ,(T31 << 26)+( 54 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddNoDest("DCBT" ,"DCBT" ,(T31 << 26)+( 278 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddNoDest("DCBTST","DCBTST",(T31 << 26)+( 246 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddNoDest("DCBZ" ,"DCLZ" ,(T31 << 26)+(1014 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddNoDest("DCCCI" ,"DCCCI" ,(T31 << 26)+( 454 << 1), M_403 | M_403C );
+ AddNoDest("ICBI" ,"ICBI" ,(T31 << 26)+( 982 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddNoDest("ICBT" ,"ICBT" ,(T31 << 26)+( 262 << 1), M_403 | M_403C );
+ AddNoDest("ICCCI" ,"ICCCI" ,(T31 << 26)+( 966 << 1), M_403 | M_403C );
+
+ /* D,A,B --> D A B */
+
+ Reg3Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*Reg3OrderCount); InstrZ=0;
+ AddReg3("ADD" ,"CAX" ,(T31 << 26)+(266 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True, True );
+ AddReg3("ADDC" ,"A" ,(T31 << 26)+( 10 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("ADDE" ,"AE" ,(T31 << 26)+(138 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("DIV" ,"DIV" ,(T31 << 26)+(331 << 1), M_6000,True ,True );
+ AddReg3("DIVS" ,"DIVS" ,(T31 << 26)+(363 << 1), M_6000,True ,True );
+ AddReg3("DIVW" ,"DIVW" ,(T31 << 26)+(491 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("DIVWU" ,"DIVWU" ,(T31 << 26)+(459 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("DOZ" ,"DOZ" ,(T31 << 26)+(264 << 1), M_6000,True ,True );
+ AddReg3("ECIWX" ,"ECIWX" ,(T31 << 26)+(310 << 1), M_6000,False,False);
+ AddReg3("LBZUX" ,"LBZUX" ,(T31 << 26)+(119 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LBZX" ,"LBZX" ,(T31 << 26)+( 87 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LHAUX" ,"LHAUX" ,(T31 << 26)+(375 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LHAX" ,"LHAX" ,(T31 << 26)+(343 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LHBRX" ,"LHBRX" ,(T31 << 26)+(790 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LHZUX" ,"LHZUX" ,(T31 << 26)+(311 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LHZX" ,"LHZX" ,(T31 << 26)+(279 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LSCBX" ,"LSCBX" ,(T31 << 26)+(277 << 1), M_6000,False,True );
+ AddReg3("LSWX" ,"LSX" ,(T31 << 26)+(533 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LWARX" ,"LWARX" ,(T31 << 26)+( 20 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LWBRX" ,"LBRX" ,(T31 << 26)+(534 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LWZUX" ,"LUX" ,(T31 << 26)+( 55 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("LWZX" ,"LX" ,(T31 << 26)+( 23 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("MUL" ,"MUL" ,(T31 << 26)+(107 << 1), M_6000,True ,True );
+ AddReg3("MULHW" ,"MULHW" ,(T31 << 26)+( 75 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,True );
+ AddReg3("MULHWU","MULHWU",(T31 << 26)+( 11 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,True );
+ AddReg3("MULLW" ,"MULS" ,(T31 << 26)+(235 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("STBUX" ,"STBUX" ,(T31 << 26)+(247 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("STBX" ,"STBX" ,(T31 << 26)+(215 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("STHBRX","STHBRX",(T31 << 26)+(918 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("STHUX" ,"STHUX" ,(T31 << 26)+(439 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("STHX" ,"STHX" ,(T31 << 26)+(407 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("STSWX" ,"STSX" ,(T31 << 26)+(661 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("STWBRX","STBRX" ,(T31 << 26)+(662 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("STWCX.","STWCX.",(T31 << 26)+(150 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("STWUX" ,"STUX" ,(T31 << 26)+(183 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("STWX" ,"STX" ,(T31 << 26)+(151 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,False,False);
+ AddReg3("SUBF" ,"SUBF" ,(T31 << 26)+( 40 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("SUB" ,"SUB" ,(T31 << 26)+( 40 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("SUBFC" ,"SF" ,(T31 << 26)+( 8 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("SUBC" ,"SUBC" ,(T31 << 26)+( 8 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("SUBFE" ,"SFE" ,(T31 << 26)+(136 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True ,True );
+ AddReg3("TLBSX" ,"TLBSX" ,(T31 << 26)+(914 << 1), M_403C ,False,True );
+
+ /* cD,cA,cB --> D A B */
+
+ CReg3Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*CReg3OrderCount); InstrZ=0;
+ AddCReg3("CRAND" ,(T19 << 26)+(257 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddCReg3("CRANDC" ,(T19 << 26)+(129 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddCReg3("CREQV" ,(T19 << 26)+(289 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddCReg3("CRNAND" ,(T19 << 26)+(225 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddCReg3("CRNOR" ,(T19 << 26)+( 33 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddCReg3("CROR" ,(T19 << 26)+(449 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddCReg3("CRORC" ,(T19 << 26)+(417 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddCReg3("CRXOR" ,(T19 << 26)+(193 << 1), M_403 | M_403C | M_505 | M_601 | M_6000);
+
+ /* fD,fA,fB --> D A B */
+
+ FReg3Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*FReg3OrderCount); InstrZ=0;
+ AddFReg3("FADD" ,"FA" ,(T63 << 26)+(21 << 1), M_601 | M_6000,True );
+ AddFReg3("FADDS" ,"FADDS" ,(T59 << 26)+(21 << 1), M_601 | M_6000,True );
+ AddFReg3("FDIV" ,"FD" ,(T63 << 26)+(18 << 1), M_601 | M_6000,True );
+ AddFReg3("FDIVS" ,"FDIVS" ,(T59 << 26)+(18 << 1), M_601 | M_6000,True );
+ AddFReg3("FSUB" ,"FS" ,(T63 << 26)+(20 << 1), M_601 | M_6000,True );
+
+ /* A,S,B --> S A B */
+
+ Reg3SwapOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*Reg3SwapOrderCount); InstrZ=0;
+ AddReg3Swap("AND" ,"AND" ,(T31 << 26)+( 28 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("ANDC" ,"ANDC" ,(T31 << 26)+( 60 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("ECOWX" ,"ECOWX" ,(T31 << 26)+( 438 << 1), M_601 | M_6000,False);
+ AddReg3Swap("EQV" ,"EQV" ,(T31 << 26)+( 284 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("MASKG" ,"MASKG" ,(T31 << 26)+( 29 << 1), M_6000,True );
+ AddReg3Swap("MASKIR","MASKIR",(T31 << 26)+( 541 << 1), M_6000,True );
+ AddReg3Swap("NAND" ,"NAND" ,(T31 << 26)+( 476 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("NOR" ,"NOR" ,(T31 << 26)+( 124 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("OR" ,"OR" ,(T31 << 26)+( 444 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("ORC" ,"ORC" ,(T31 << 26)+( 412 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("RRIB" ,"RRIB" ,(T31 << 26)+( 537 << 1), M_6000,True );
+ AddReg3Swap("SLE" ,"SLE" ,(T31 << 26)+( 153 << 1), M_6000,True );
+ AddReg3Swap("SLEQ" ,"SLEQ" ,(T31 << 26)+( 217 << 1), M_6000,True );
+ AddReg3Swap("SLLQ" ,"SLLQ" ,(T31 << 26)+( 216 << 1), M_6000,True );
+ AddReg3Swap("SLQ" ,"SLQ" ,(T31 << 26)+( 152 << 1), M_6000,True );
+ AddReg3Swap("SLW" ,"SL" ,(T31 << 26)+( 24 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("SRAQ" ,"SRAQ" ,(T31 << 26)+( 920 << 1), M_6000,True );
+ AddReg3Swap("SRAW" ,"SRA" ,(T31 << 26)+( 792 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("SRE" ,"SRE" ,(T31 << 26)+( 665 << 1), M_6000,True );
+ AddReg3Swap("SREA" ,"SREA" ,(T31 << 26)+( 921 << 1), M_6000,True );
+ AddReg3Swap("SREQ" ,"SREQ" ,(T31 << 26)+( 729 << 1), M_6000,True );
+ AddReg3Swap("SRLQ" ,"SRLQ" ,(T31 << 26)+( 728 << 1), M_6000,True );
+ AddReg3Swap("SRQ" ,"SRQ" ,(T31 << 26)+( 664 << 1), M_6000,True );
+ AddReg3Swap("SRW" ,"SR" ,(T31 << 26)+( 536 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+ AddReg3Swap("XOR" ,"XOR" ,(T31 << 26)+( 316 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True );
+
+ /* fD,A,B --> D A B */
+
+ MixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*MixedOrderCount); InstrZ=0;
+ AddMixed("LFDUX" ,"LFDUX" ,(T31 << 26)+(631 << 1), M_601 | M_6000);
+ AddMixed("LFDX" ,"LFDX" ,(T31 << 26)+(599 << 1), M_601 | M_6000);
+ AddMixed("LFSUX" ,"LFSUX" ,(T31 << 26)+(567 << 1), M_601 | M_6000);
+ AddMixed("LFSX" ,"LFSX" ,(T31 << 26)+(535 << 1), M_601 | M_6000);
+ AddMixed("STFDUX","STFDUX",(T31 << 26)+(759 << 1), M_601 | M_6000);
+ AddMixed("STFDX" ,"STFDX" ,(T31 << 26)+(727 << 1), M_601 | M_6000);
+ AddMixed("STFSUX","STFSUX",(T31 << 26)+(695 << 1), M_601 | M_6000);
+ AddMixed("STFSX" ,"STFSX" ,(T31 << 26)+(663 << 1), M_601 | M_6000);
+
+ /* fD,fA,fC,fB --> D A B C */
+
+ FReg4Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*FReg4OrderCount); InstrZ=0;
+ AddFReg4("FMADD" ,"FMA" ,(T63 << 26)+(29 << 1), M_601 | M_6000,True );
+ AddFReg4("FMADDS" ,"FMADDS" ,(T59 << 26)+(29 << 1), M_601 | M_6000,True );
+ AddFReg4("FMSUB" ,"FMS" ,(T63 << 26)+(28 << 1), M_601 | M_6000,True );
+ AddFReg4("FMSUBS" ,"FMSUBS" ,(T59 << 26)+(28 << 1), M_601 | M_6000,True );
+ AddFReg4("FNMADD" ,"FNMA" ,(T63 << 26)+(31 << 1), M_601 | M_6000,True );
+ AddFReg4("FNMADDS","FNMADDS",(T59 << 26)+(31 << 1), M_601 | M_6000,True );
+ AddFReg4("FNMSUB" ,"FNMS" ,(T63 << 26)+(30 << 1), M_601 | M_6000,True );
+ AddFReg4("FNMSUBS","FNMSUBS",(T59 << 26)+(30 << 1), M_601 | M_6000,True );
+
+ /* D,d(A) --> D A d */
+
+ RegDispOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*RegDispOrderCount); InstrZ=0;
+ AddRegDisp("LBZ" ,"LBZ" ,(T34 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("LBZU" ,"LBZU" ,(T35 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("LHA" ,"LHA" ,(T42 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("LHAU" ,"LHAU" ,(T43 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("LHZ" ,"LHZ" ,(T40 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("LHZU" ,"LHZU" ,(T41 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("LMW" ,"LM" ,(T46 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("LWZ" ,"L" ,(T32 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("LWZU" ,"LU" ,(T33 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("STB" ,"STB" ,(T38 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("STBU" ,"STBU" ,(T39 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("STH" ,"STH" ,(T44 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("STHU" ,"STHU" ,(T45 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("STMW" ,"STM" ,(T47 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("STW" ,"ST" ,(T36 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddRegDisp("STWU" ,"STU" ,(T37 << 26), M_403 | M_403C | M_505 | M_601 | M_6000);
+
+ /* fD,d(A) --> D A d */
+
+ FRegDispOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FRegDispOrderCount); InstrZ=0;
+ AddFRegDisp("LFD" ,"LFD" ,(T50 << 26), M_601 | M_6000);
+ AddFRegDisp("LFDU" ,"LFDU" ,(T51 << 26), M_601 | M_6000);
+ AddFRegDisp("LFS" ,"LFS" ,(T48 << 26), M_601 | M_6000);
+ AddFRegDisp("LFSU" ,"LFSU" ,(T49 << 26), M_601 | M_6000);
+ AddFRegDisp("STFD" ,"STFD" ,(T54 << 26), M_601 | M_6000);
+ AddFRegDisp("STFDU" ,"STFDU" ,(T55 << 26), M_601 | M_6000);
+ AddFRegDisp("STFS" ,"STFS" ,(T52 << 26), M_601 | M_6000);
+ AddFRegDisp("STFSU" ,"STFSU" ,(T53 << 26), M_601 | M_6000);
+
+ /* A,S,Imm5 --> S A Imm */
+
+ Reg2ImmOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*Reg2ImmOrderCount); InstrZ=0;
+ AddReg2Imm("SLIQ" ,"SLIQ" ,(T31 << 26)+(184 << 1), M_6000,True);
+ AddReg2Imm("SLLIQ" ,"SLLIQ" ,(T31 << 26)+(248 << 1), M_6000,True);
+ AddReg2Imm("SRAIQ" ,"SRAIQ" ,(T31 << 26)+(952 << 1), M_6000,True);
+ AddReg2Imm("SRAWI" ,"SRAI" ,(T31 << 26)+(824 << 1), M_403 | M_403C | M_505 | M_601 | M_6000,True);
+ AddReg2Imm("SRIQ" ,"SRIQ" ,(T31 << 26)+(696 << 1), M_6000,True);
+ AddReg2Imm("SRLIQ" ,"SRLIQ" ,(T31 << 26)+(760 << 1), M_6000,True);
+
+ /* D,A,Imm --> D A Imm */
+
+ Imm16Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*Imm16OrderCount); InstrZ=0;
+ AddImm16("ADDI" ,"CAL" ,T14 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16("ADDIC" ,"AI" ,T12 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16("ADDIC." ,"AI." ,T13 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16("ADDIS" ,"CAU" ,T15 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16("DOZI" ,"DOZI" , T9 << 26, M_6000);
+ AddImm16("MULLI" ,"MULI" , T7 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16("SUBFIC" ,"SFI" , T8 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+
+ /* A,S,Imm --> S A Imm */
+
+ Imm16SwapOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*Imm16SwapOrderCount); InstrZ=0;
+ AddImm16Swap("ANDI." ,"ANDIL." ,T28 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16Swap("ANDIS." ,"ANDIU." ,T29 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16Swap("ORI" ,"ORIL" ,T24 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16Swap("ORIS" ,"ORIU" ,T25 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16Swap("XORI" ,"XORIL" ,T26 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+ AddImm16Swap("XORIS" ,"XORIU" ,T27 << 26, M_403 | M_403C | M_505 | M_601 | M_6000);
+END
+
+ static void DeinitNames(BaseOrder *Orders, int OrderCount)
+BEGIN
+ int z;
+
+ for (z=0; z<OrderCount; free(Orders[z++].Name));
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(Reg1Orders);
+ free(FReg1Orders);
+ free(CReg1Orders);
+ free(CBit1Orders);
+ DeinitNames(Reg2Orders,Reg2OrderCount); free(Reg2Orders);
+ free(CReg2Orders);
+ DeinitNames(FReg2Orders,FReg2OrderCount); free(FReg2Orders);
+ free(Reg2BOrders);
+ DeinitNames(Reg2SwapOrders,Reg2SwapOrderCount); free(Reg2SwapOrders);
+ free(NoDestOrders);
+ DeinitNames(Reg3Orders,Reg3OrderCount); free(Reg3Orders);
+ free(CReg3Orders);
+ DeinitNames(FReg3Orders,FReg3OrderCount); free(FReg3Orders);
+ DeinitNames(Reg3SwapOrders,Reg3SwapOrderCount); free(Reg3SwapOrders);
+ free(MixedOrders);
+ DeinitNames(FReg4Orders,FReg4OrderCount); free(FReg4Orders);
+ free(RegDispOrders);
+ free(FRegDispOrders);
+ DeinitNames(Reg2ImmOrders,Reg2ImmOrderCount); free(Reg2ImmOrders);
+ free(Imm16Orders);
+ free(Imm16SwapOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void PutCode(LongWord Code)
+BEGIN
+#if 0
+ memcpy(BAsmCode,&Code,4);
+ if (NOT BigEndian) DSwap((void *)BAsmCode,4);
+#endif
+ DAsmCode[0]=Code;
+END
+
+ static void IncCode(LongWord Code)
+BEGIN
+#if 0
+ BAsmCode[0]+=(Code >> 24) & 0xff;
+ BAsmCode[1]+=(Code >> 16) & 0xff;
+ BAsmCode[2]+=(Code >> 8) & 0xff;
+ BAsmCode[3]+=(Code ) & 0xff;
+#endif
+ DAsmCode[0]+=Code;
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodeGenReg(char *Asc, LongWord *Erg)
+BEGIN
+ Boolean io;
+ char *s;
+
+ if (FindRegDef(Asc, &s)) Asc = s;
+
+ if ((strlen(Asc) < 2) OR (toupper(*Asc) != 'R')) return False;
+ else
+ BEGIN
+ *Erg = ConstLongInt(Asc+1,&io);
+ return ((io) AND (*Erg <= 31));
+ END
+END
+
+ static Boolean DecodeFPReg(char *Asc, LongWord *Erg)
+BEGIN
+ Boolean io;
+ char *s;
+
+ if (FindRegDef(Asc, &s)) Asc = s;
+
+ if ((strlen(Asc)<3) OR (toupper(*Asc)!='F') OR (toupper(Asc[1])!='R')) return False;
+ else
+ BEGIN
+ *Erg=ConstLongInt(Asc+2,&io);
+ return ((io) AND (*Erg<=31));
+ END
+END
+
+ static Boolean DecodeCondReg(char *Asc, LongWord *Erg)
+BEGIN
+ Boolean OK;
+
+ *Erg=EvalIntExpression(Asc,UInt3,&OK) << 2;
+ return ((OK) AND (*Erg<=31));
+END
+
+ static Boolean DecodeCondBit(char *Asc, LongWord *Erg)
+BEGIN
+ Boolean OK;
+
+ *Erg=EvalIntExpression(Asc,UInt5,&OK);
+ return ((OK) AND (*Erg<=31));
+END
+
+ static Boolean DecodeRegDisp(char *Asc, LongWord *Erg)
+BEGIN
+ char *p;
+ int l=strlen(Asc);
+ LongInt Disp;
+ Boolean OK;
+
+ if (Asc[l-1]!=')') return False; Asc[l-1]='\0'; l--;
+ p=Asc+l-1; while ((p>=Asc) AND (*p!='(')) p--;
+ if (p<Asc) return False;
+ if (NOT DecodeGenReg(p+1,Erg)) return False;
+ *p='\0';
+ Disp=EvalIntExpression(Asc,Int16,&OK); if (NOT OK) return False;
+ *Erg=(*Erg << 16)+(Disp & 0xffff); return True;
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean Convert6000(char *Name1, char *Name2)
+BEGIN
+ if (NOT Memo(Name1)) return True;
+ if (MomCPU==CPU6000)
+ BEGIN
+ strmaxcpy(OpPart,Name2,255);
+ return True;
+ END
+ else
+ BEGIN
+ WrError(1200); return False;
+ END
+END
+
+ static Boolean PMemo(char *Name)
+BEGIN
+ String tmp;
+
+ if (Memo(Name)) return True;
+
+ strmaxcpy(tmp,Name,255); strmaxcat(tmp,".",255);
+ return (Memo(tmp));
+END
+
+ static void IncPoint(void)
+BEGIN
+ if (OpPart[strlen(OpPart)-1]=='.') IncCode(1);
+END
+
+ static void ChkSup(void)
+BEGIN
+ if (NOT SupAllowed) WrError(50);
+END
+
+ static Boolean ChkCPU(Byte Mask)
+BEGIN
+ return (((Mask >> (MomCPU-CPU403))&1)==1);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ if (Memo("REG"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else AddRegDef(LabPart,ArgStr[1]);
+ return True;
+ END
+
+ return False;
+END
+
+ static void SwapCode(LongWord *Code)
+BEGIN
+ *Code=((*Code & 0x1f) << 5) | ((*Code >> 5) & 0x1f);
+END
+
+ static void MakeCode_601(void)
+BEGIN
+ int z;
+ Integer Imm;
+ LongWord Dest,Src1,Src2,Src3;
+ LongInt Dist;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* Nullanweisung */
+
+ if ((Memo("")) AND (*AttrPart=='\0') AND (ArgCnt==0)) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(BigEnd)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (NOT ChkCPU(FixedOrders[z].CPUMask)) WrXError(1500,OpPart);
+ else
+ BEGIN
+ CodeLen=4; PutCode(FixedOrders[z].Code);
+ if (Memo("RFI")) ChkSup();
+ END
+ return;
+ END
+
+ /* ein Register */
+
+ for (z=0; z<Reg1OrderCount; z++)
+ if Memo(Reg1Orders[z].Name)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT ChkCPU(Reg1Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(Reg1Orders[z].Code+(Dest << 21));
+ if (Memo("MTMSR")) ChkSup();
+ END
+ return;
+ END
+
+ /* ein Steuerregister */
+
+ for (z=1; z<CReg1OrderCount; z++)
+ if (Memo(CReg1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT ChkCPU(CReg1Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeCondReg(ArgStr[1],&Dest)) WrError(1350);
+ else if ((Dest & 3)!=0) WrError(1351);
+ else
+ BEGIN
+ CodeLen=4; PutCode(CReg1Orders[z].Code+(Dest << 21));
+ END
+ return;
+ END
+
+ /* ein Steuerregisterbit */
+
+ for (z=0; z<CBit1OrderCount; z++)
+ if (Memo(CBit1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT ChkCPU(CBit1Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeCondBit(ArgStr[1],&Dest)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(CBit1Orders[z].Code+(Dest << 21));
+ END
+ return;
+ END
+
+ /* ein Gleitkommaregister */
+
+ for (z=0; z<FReg1OrderCount; z++)
+ if (Memo(FReg1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT ChkCPU(FReg1Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeFPReg(ArgStr[1],&Dest)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(FReg1Orders[z].Code+(Dest << 21));
+ END
+ return;
+ END
+
+ /* 1/2 Integer-Register */
+
+ for (z=0; z<Reg2OrderCount; z++)
+ if (Memo(Reg2Orders[z].Name))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ ArgCnt=2; strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT ChkCPU(Reg2Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(Reg2Orders[z].Code+(Dest << 21)+(Src1 << 16));
+ END
+ return;
+ END
+
+ /* 2 Bedingungs-Bits */
+
+ for (z=0; z<CReg2OrderCount; z++)
+ if Memo(CReg2Orders[z].Name)
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT ChkCPU(CReg2Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeCondReg(ArgStr[1],&Dest)) WrError(1350);
+ else if ((Dest & 3)!=0) WrError(1351);
+ else if (NOT DecodeCondReg(ArgStr[2],&Src1)) WrError(1350);
+ else if ((Src1 & 3)!=0) WrError(1351);
+ else
+ BEGIN
+ CodeLen=4; PutCode(CReg2Orders[z].Code+(Dest << 21)+(Src1 << 16));
+ END
+ return;
+ END
+
+ /* 1/2 Float-Register */
+
+ for (z=0; z<FReg2OrderCount; z++)
+ if Memo(FReg2Orders[z].Name)
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ ArgCnt=2; strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT ChkCPU(FReg2Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeFPReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeFPReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(FReg2Orders[z].Code+(Dest << 21)+(Src1 << 11));
+ END
+ return;
+ END
+
+ /* 1/2 Integer-Register, Quelle in B */
+
+ for (z=0; z<Reg2BOrderCount; z++)
+ if Memo(Reg2BOrders[z].Name)
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ ArgCnt=2; strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT ChkCPU(Reg2BOrders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(Reg2BOrders[z].Code+(Dest << 21)+(Src1 << 11));
+ ChkSup();
+ END
+ return;
+ END
+
+ /* 1/2 Integer-Register, getauscht */
+
+ for (z=0; z<Reg2SwapOrderCount; z++)
+ if (Memo(Reg2SwapOrders[z].Name))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ ArgCnt=2; strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT ChkCPU(Reg2SwapOrders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(Reg2SwapOrders[z].Code+(Dest << 16)+(Src1 << 21));
+ END
+ return;
+ END
+
+ /* 2 Integer-Register, kein Ziel */
+
+ for (z=0; z<NoDestOrderCount; z++)
+ if (Memo(NoDestOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT ChkCPU(NoDestOrders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Src1)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src2)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(NoDestOrders[z].Code+(Src1 << 16)+(Src2 << 11));
+ END
+ return;
+ END
+
+ /* 2/3 Integer-Register */
+
+ for (z=0; z<Reg3OrderCount; z++)
+ if (Memo(Reg3Orders[z].Name))
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ ArgCnt=3; strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT ChkCPU(Reg3Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[3],&Src2)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(Reg3Orders[z].Code+(Dest << 21)+(Src1 << 16)+(Src2 << 11));
+ END
+ return;
+ END
+
+ /* 2/3 Bedingungs-Bits */
+
+ for (z=0; z<CReg3OrderCount; z++)
+ if (Memo(CReg3Orders[z].Name))
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ ArgCnt=3; strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT ChkCPU(CReg3Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeCondBit(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeCondBit(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeCondBit(ArgStr[3],&Src2)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(CReg3Orders[z].Code+(Dest << 21)+(Src1 << 16)+(Src2 << 11));
+ END
+ return;
+ END
+
+ /* 2/3 Float-Register */
+
+ for (z=0; z<FReg3OrderCount; z++)
+ if (Memo(FReg3Orders[z].Name))
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ ArgCnt=3; strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT ChkCPU(FReg3Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeFPReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeFPReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeFPReg(ArgStr[3],&Src2)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(FReg3Orders[z].Code+(Dest << 21)+(Src1 << 16)+(Src2 << 11));
+ END
+ return;
+ END
+
+ /* 2/3 Integer-Register, Ziel & Quelle 1 getauscht */
+
+ for (z=0; z<Reg3SwapOrderCount; z++)
+ if (Memo(Reg3SwapOrders[z].Name))
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ ArgCnt=3; strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT ChkCPU(Reg3SwapOrders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[3],&Src2)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(Reg3SwapOrders[z].Code+(Dest << 16)+(Src1 << 21)+(Src2 << 11));
+ END
+ return;
+ END
+
+ /* 1 Float und 2 Integer-Register */
+
+ for (z=0; z<MixedOrderCount; z++)
+ if (Memo(MixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT ChkCPU(MixedOrders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeFPReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[3],&Src2)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4; PutCode(MixedOrders[z].Code+(Dest << 21)+(Src1 << 16)+(Src2 << 11));
+ END
+ return;
+ END
+
+ /* 3/4 Float-Register */
+
+ for (z=0; z<FReg4OrderCount; z++)
+ if (Memo(FReg4Orders[z].Name))
+ BEGIN
+ if (ArgCnt==3)
+ BEGIN
+ ArgCnt=4; strcpy(ArgStr[4],ArgStr[3]);
+ strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=4) WrError(1110);
+ else if (NOT ChkCPU(FReg4Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeFPReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeFPReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeFPReg(ArgStr[3],&Src3)) WrError(1350);
+ else if (NOT DecodeFPReg(ArgStr[4],&Src2)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=4;
+ PutCode(FReg4Orders[z].Code+(Dest << 21)+(Src1 << 16)+(Src2 << 11)+(Src3 << 6));
+ END
+ return;
+ END
+
+ /* Register mit indiziertem Speicheroperandem */
+
+ for (z=0; z<RegDispOrderCount; z++)
+ if (Memo(RegDispOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeRegDisp(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ PutCode(RegDispOrders[z].Code+(Dest << 21)+Src1); CodeLen=4;
+ END
+ return;
+ END
+
+ /* Gleitkommaregister mit indiziertem Speicheroperandem */
+
+ for (z=0; z<FRegDispOrderCount; z++)
+ if (Memo(FRegDispOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeFPReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeRegDisp(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ PutCode(FRegDispOrders[z].Code+(Dest << 21)+Src1); CodeLen=4;
+ END
+ return;
+ END
+
+ /* 2 verdrehte Register mit immediate */
+
+ for (z=0; z<Reg2ImmOrderCount; z++)
+ if (Memo(Reg2ImmOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT ChkCPU(Reg2ImmOrders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[3],UInt5,&OK);
+ if (OK)
+ BEGIN
+ PutCode(Reg2ImmOrders[z].Code+(Src1 << 21)+(Dest << 16)+(Src2 << 11));
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ /* 2 Register+immediate */
+
+ for (z=0; z<Imm16OrderCount; z++)
+ if (Memo(Imm16Orders[z].Name))
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ ArgCnt=3; strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT ChkCPU(Imm16Orders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ Imm=EvalIntExpression(ArgStr[3],Int16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4; PutCode(Imm16Orders[z].Code+(Dest << 21)+(Src1 << 16)+(Imm & 0xffff));
+ END
+ END
+ return;
+ END
+
+ /* 2 Register+immediate, Ziel & Quelle 1 getauscht */
+
+ for (z=0; z<Imm16SwapOrderCount; z++)
+ if (Memo(Imm16SwapOrders[z].Name))
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ ArgCnt=3; strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]);
+ END
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT ChkCPU(Imm16SwapOrders[z].CPUMask)) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ Imm=EvalIntExpression(ArgStr[3],Int16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4; PutCode(Imm16SwapOrders[z].Code+(Dest << 16)+(Src1 << 21)+(Imm & 0xffff));
+ END
+ END
+ return;
+ END
+
+ /* Ausreisser... */
+
+ if (NOT Convert6000("FM","FMUL")) return;
+ if (NOT Convert6000("FM.","FMUL.")) return;
+
+ if ((PMemo("FMUL")) OR (PMemo("FMULS")))
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]); ArgCnt=3;
+ END
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT DecodeFPReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeFPReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeFPReg(ArgStr[3],&Src2)) WrError(1350);
+ else
+ BEGIN
+ PutCode((T59 << 26)+(25 << 1)+(Dest << 21)+(Src1 << 16)+(Src2 << 6));
+ if (PMemo("FMUL")) IncCode(T4 << 26);
+ IncPoint();
+ CodeLen=4;
+ END
+ return;
+ END
+
+ if (NOT Convert6000("LSI","LSWI")) return;
+ if (NOT Convert6000("STSI","STSWI")) return;
+
+ if ((Memo("LSWI")) OR (Memo("STSWI")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[3],UInt5,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T31 << 26)+(597 << 1)+(Dest << 21)+(Src1 << 16)+(Src2 << 11));
+ if (Memo("STSWI")) IncCode(128 << 1);
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MFSPR")) OR (Memo("MTSPR")))
+ BEGIN
+ if (Memo("MTSPR"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else
+ BEGIN
+ Src1=EvalIntExpression(ArgStr[2],UInt10,&OK);
+ if (OK)
+ BEGIN
+ SwapCode(&Src1);
+ PutCode((T31 << 26)+(Dest << 21)+(Src1 << 11));
+ IncCode((Memo("MFSPR") ? 339 : 467) << 1);
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MFDCR")) OR (Memo("MTDCR")))
+ BEGIN
+ if (Memo("MTDCR"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU>=CPU505) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else
+ BEGIN
+ Src1=EvalIntExpression(ArgStr[2],UInt10,&OK);
+ if (OK)
+ BEGIN
+ SwapCode(&Src1);
+ PutCode((T31 << 26)+(Dest << 21)+(Src1 << 11));
+ IncCode((Memo("MFDCR") ? 323 : 451) << 1);
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MFSR")) OR (Memo("MTSR")))
+ BEGIN
+ if (Memo("MTSR"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else
+ BEGIN
+ Src1=EvalIntExpression(ArgStr[2],UInt4,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T31 << 26)+(Dest << 21)+(Src1 << 16));
+ IncCode((Memo("MFSR") ? 595 : 210) << 1);
+ CodeLen=4; ChkSup();
+ END
+ END
+ return;
+ END
+
+ if (Memo("MTCRF"))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[ArgCnt],&Src1)) WrError(1350);
+ else
+ BEGIN
+ OK=True;
+ if (ArgCnt==1) Dest=0xff;
+ else Dest=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T31 << 26)+(Src1 << 21)+(Dest << 12)+(144 << 1));
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if (PMemo("MTFSF"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeFPReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ Dest=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T63 << 26)+(Dest << 17)+(Src1 << 11)+(711 << 1));
+ IncPoint();
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if (PMemo("MTFSFI"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeCondReg(ArgStr[1],&Dest)) WrError(1350);
+ else if ((Dest & 3)!=0) WrError(1351);
+ else
+ BEGIN
+ Src1=EvalIntExpression(ArgStr[2],UInt4,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T63 << 26)+(Dest << 21)+(Src1 << 12)+(134 << 1));
+ IncPoint();
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if (PMemo("RLMI"))
+ BEGIN
+ if (ArgCnt!=5) WrError(1110);
+ else if (MomCPU<CPU6000) WrXError(1500,OpPart);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[3],&Src2)) WrError(1350);
+ else
+ BEGIN
+ Src3=EvalIntExpression(ArgStr[4],UInt5,&OK);
+ if (OK)
+ BEGIN
+ Imm=EvalIntExpression(ArgStr[5],UInt5,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T22 << 26)+(Src1 << 21)+(Dest << 16)
+ +(Src2 << 11)+(Src3 << 6)+(Imm << 1));
+ IncPoint();
+ CodeLen=4;
+ END
+ END
+ END
+ return;
+ END
+
+ if (NOT Convert6000("RLNM","RLWNM")) return;
+ if (NOT Convert6000("RLNM.","RLWNM.")) return;
+
+ if (PMemo("RLWNM"))
+ BEGIN
+ if (ArgCnt!=5) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[3],&Src2)) WrError(1350);
+ else
+ BEGIN
+ Src3=EvalIntExpression(ArgStr[4],UInt5,&OK);
+ if (OK)
+ BEGIN
+ Imm=EvalIntExpression(ArgStr[5],UInt5,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T23 << 26)+(Src1 << 21)+(Dest << 16)
+ +(Src2 << 11)+(Src3 << 6)+(Imm << 1));
+ IncPoint();
+ CodeLen=4;
+ END
+ END
+ END
+ return;
+ END
+
+ if (NOT Convert6000("RLIMI","RLWIMI")) return;
+ if (NOT Convert6000("RLIMI.","RLWIMI.")) return;
+ if (NOT Convert6000("RLINM","RLWINM")) return;
+ if (NOT Convert6000("RLINM.","RLWINM.")) return;
+
+ if ((PMemo("RLWIMI")) OR (PMemo("RLWINM")))
+ BEGIN
+ if (ArgCnt!=5) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[1],&Dest)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[3],UInt5,&OK);
+ if (OK)
+ BEGIN
+ Src3=EvalIntExpression(ArgStr[4],UInt5,&OK);
+ if (OK)
+ BEGIN
+ Imm=EvalIntExpression(ArgStr[5],UInt5,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T20 << 26)+(Dest << 16)+(Src1 << 21)
+ +(Src2 << 11)+(Src3 << 6)+(Imm << 1));
+ if (PMemo("RLWINM")) IncCode(T1 << 26);
+ IncPoint();
+ CodeLen=4;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (NOT Convert6000("TLBI","TLBIE")) return;
+
+ if (Memo("TLBIE"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[1],&Src1)) WrError(1350);
+ else
+ BEGIN
+ PutCode((T31 << 26)+(Src1 << 11)+(306 << 1));
+ CodeLen=4; ChkSup();
+ END
+ return;
+ END
+
+ if (NOT Convert6000("T","TW")) return;
+
+ if (Memo("TW"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[3],&Src2)) WrError(1350);
+ else
+ BEGIN
+ Dest=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T31 << 26)+(Dest << 21)+(Src1 << 16)+(Src2 << 11)+(4 << 1));
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if (NOT Convert6000("TI","TWI")) return;
+
+ if (Memo("TWI"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[2],&Src1)) WrError(1350);
+ else
+ BEGIN
+ Imm=EvalIntExpression(ArgStr[3],Int16,&OK);
+ if (OK)
+ BEGIN
+ Dest=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T3 << 26)+(Dest << 21)+(Src1 << 16)+(Imm & 0xffff));
+ CodeLen=4;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("WRTEEI"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU>=CPU505) WrXError(1500,OpPart);
+ else
+ BEGIN
+ Src1=EvalIntExpression(ArgStr[1],UInt1,&OK) << 15;
+ if (OK)
+ BEGIN
+ PutCode((T31 << 26)+Src1+(163 << 1));
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ /* Vergleiche */
+
+ if ((Memo("CMP")) OR (Memo("CMPL")))
+ BEGIN
+ if (ArgCnt==3)
+ BEGIN
+ strcpy(ArgStr[4],ArgStr[3]); strcpy(ArgStr[3],ArgStr[2]); strmaxcpy(ArgStr[2],"0",255); ArgCnt=4;
+ END
+ if (ArgCnt!=4) WrError(1110);
+ else if (NOT DecodeGenReg(ArgStr[4],&Src2)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[3],&Src1)) WrError(1350);
+ else if (NOT DecodeCondReg(ArgStr[1],&Dest)) WrError(1350);
+ else if ((Dest & 3)!=0) WrError(1351);
+ else
+ BEGIN
+ Src3=EvalIntExpression(ArgStr[2],UInt1,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T31 << 26)+(Dest << 21)+(Src3 << 21)+(Src1 << 16)
+ +(Src2 << 11));
+ if (Memo("CMPL")) IncCode(32 << 1);
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("FCMPO")) OR (Memo("FCMPU")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT DecodeFPReg(ArgStr[3],&Src2)) WrError(1350);
+ else if (NOT DecodeFPReg(ArgStr[2],&Src1)) WrError(1350);
+ else if (NOT DecodeCondReg(ArgStr[1],&Dest)) WrError(1350);
+ else if ((Dest & 3)!=0) WrError(1351);
+ else
+ BEGIN
+ PutCode((T63 << 26)+(Dest << 21)+(Src1 << 16)+(Src2 << 11));
+ if (Memo("FCMPO")) IncCode(32 << 1);
+ CodeLen=4;
+ END
+ return;
+ END
+
+ if ((Memo("CMPI")) OR (Memo("CMPLI")))
+ BEGIN
+ if (ArgCnt==3)
+ BEGIN
+ strcpy(ArgStr[4],ArgStr[3]); strcpy(ArgStr[3],ArgStr[2]); strmaxcpy(ArgStr[2],"0",255); ArgCnt=4;
+ END
+ if (ArgCnt!=4) WrError(1110);
+ else
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[4],Int16,&OK);
+ if (OK)
+ if (NOT DecodeGenReg(ArgStr[3],&Src1)) WrError(1350);
+ else if (NOT DecodeCondReg(ArgStr[1],&Dest)) WrError(1350);
+ else if ((Dest & 3)!=0) WrError(1351);
+ else
+ BEGIN
+ Src3=EvalIntExpression(ArgStr[2],UInt1,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T10 << 26)+(Dest << 21)+(Src3 << 21)
+ +(Src1 << 16)+(Src2 & 0xffff));
+ if (Memo("CMPI")) IncCode(T1 << 26);
+ CodeLen=4;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if ((Memo("B")) OR (Memo("BL")) OR (Memo("BA")) OR (Memo("BLA")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Dist=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (OK)
+ BEGIN
+ if ((Memo("B")) OR (Memo("BL"))) Dist-=EProgCounter();
+ if ((NOT SymbolQuestionable) AND (Dist>0x1ffffff)) WrError(1320);
+ else if ((NOT SymbolQuestionable) AND (Dist<-0x2000000l)) WrError(1315);
+ else if ((Dist & 3)!=0) WrError(1375);
+ else
+ BEGIN
+ PutCode((T18 << 26)+(Dist & 0x03fffffc));
+ if ((Memo("BA")) OR (Memo("BLA"))) IncCode(2);
+ if ((Memo("BL")) OR (Memo("BLA"))) IncCode(1);
+ CodeLen=4;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BC")) OR (Memo("BCL")) OR (Memo("BCA")) OR (Memo("BCLA")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ Src1=EvalIntExpression(ArgStr[1],UInt5,&OK); /* BO */
+ if (OK)
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[2],UInt5,&OK); /* BI */
+ if (OK)
+ BEGIN
+ Dist=EvalIntExpression(ArgStr[3],Int32,&OK); /* ADR */
+ if (OK)
+ BEGIN
+ if ((Memo("BC")) OR (Memo("BCL"))) Dist-=EProgCounter();
+ if ((NOT SymbolQuestionable) AND (Dist>0x7fff)) WrError(1320);
+ else if ((NOT SymbolQuestionable) AND (Dist<-0x8000l)) WrError(1315);
+ else if ((Dist & 3)!=0) WrError(1375);
+ else
+ BEGIN
+ PutCode((T16 << 26)+(Src1 << 21)+(Src2 << 16)+(Dist & 0xfffc));
+ if ((Memo("BCA")) OR (Memo("BCLA"))) IncCode(2);
+ if ((Memo("BCL")) OR (Memo("BCLA"))) IncCode(1);
+ CodeLen=4;
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (NOT Convert6000("BCC","BCCTR")) return;
+ if (NOT Convert6000("BCCL","BCCTRL")) return;
+ if (NOT Convert6000("BCR","BCLR")) return;
+ if (NOT Convert6000("BCRL","BCLRL")) return;
+
+ if ((Memo("BCCTR")) OR (Memo("BCCTRL")) OR (Memo("BCLR")) OR (Memo("BCLRL")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ Src1=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (OK)
+ BEGIN
+ Src2=EvalIntExpression(ArgStr[2],UInt5,&OK);
+ if (OK)
+ BEGIN
+ PutCode((T19 << 26)+(Src1 << 21)+(Src2 << 16));
+ if ((Memo("BCCTR")) OR (Memo("BCCTRL")))
+ IncCode(528 << 1);
+ else
+ IncCode(16 << 1);
+ if ((Memo("BCCTRL")) OR (Memo("BCLRL"))) IncCode(1);
+ CodeLen=4;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("TLBRE")) OR (Memo("TLBWE")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (MomCPU != CPU403C) WrError(1500);
+ else if (NOT DecodeGenReg(ArgStr[1], &Src1)) WrError(1350);
+ else if (NOT DecodeGenReg(ArgStr[2], &Src2)) WrError(1350);
+ else
+ BEGIN
+ Src3 = EvalIntExpression(ArgStr[3], UInt1, &OK);
+ if (OK)
+ BEGIN
+ PutCode((T31 << 26) + (Src1 << 21) + (Src2 << 16) +
+ (Src3 << 11) + (946 << 1));
+ if (Memo("TLBWE")) IncCode(32 << 1);
+ CodeLen = 4;
+ END
+ END
+ return;
+ END
+
+ /* unbekannter Befehl */
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_601(void)
+BEGIN
+ return Memo("REG");
+END
+
+ static void InitPass_601(void)
+BEGIN
+ SaveInitProc();
+ SetFlag(&BigEnd,BigEndianName,False);
+END
+
+ static void InternSymbol_601(char *Asc, TempResult *Erg)
+BEGIN
+ int l=strlen(Asc);
+
+ Erg->Typ=TempNone;
+ if ((l==3) OR (l==4))
+ if ((toupper(*Asc)=='C') AND (toupper(Asc[1])=='R'))
+ if ((Asc[l-1]>='0') AND (Asc[l-1]<='7'))
+ if ((l==3) != ((toupper(Asc[2])=='F') OR (toupper(Asc[3])=='B')))
+ BEGIN
+ Erg->Typ=TempInt; Erg->Contents.Int=Asc[l-1]-'0';
+ END
+END
+
+ static void SwitchFrom_601(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_601(void)
+BEGIN
+ PFamilyDescr FoundDscr;
+
+ TurnWords=True; ConstMode=ConstModeC; SetIsOccupied=False;
+
+ FoundDscr=FindFamilyByName("MPC601"); if (FoundDscr==Nil) exit(255);
+
+ PCSymbol="*"; HeaderID=FoundDscr->Id; NOPCode=0x000000000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=4; SegInits[SegCode]=0;
+#ifdef __STDC__
+ SegLimits[SegCode] = 0xfffffffful;
+#else
+ SegLimits[SegCode] = 0xffffffffl;
+#endif
+
+ MakeCode=MakeCode_601; IsDef=IsDef_601;
+ SwitchFrom=SwitchFrom_601; InternSymbol=InternSymbol_601;
+ AddONOFF("SUPMODE", &SupAllowed, SupAllowedName,False);
+ AddONOFF("BIGENDIAN", &BigEnd, BigEndianName, False);
+
+ InitFields();
+END
+
+
+ void code601_init(void)
+BEGIN
+ CPU403 =AddCPU("PPC403", SwitchTo_601);
+ CPU403C =AddCPU("PPC403GC", SwitchTo_601);
+ CPU505 =AddCPU("MPC505", SwitchTo_601);
+ CPU601 =AddCPU("MPC601", SwitchTo_601);
+ CPU6000 =AddCPU("RS6000", SwitchTo_601);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitPass_601;
+END
+
diff --git a/code601.h b/code601.h
new file mode 100644
index 0000000..de350b9
--- /dev/null
+++ b/code601.h
@@ -0,0 +1,11 @@
+/* code601.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator PowerPC-Familie */
+/* */
+/* Historie: 17.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code601_init(void);
diff --git a/code65.c b/code65.c
new file mode 100644
index 0000000..69ccc93
--- /dev/null
+++ b/code65.c
@@ -0,0 +1,736 @@
+/* code65.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 65xx/MELPS740 */
+/* */
+/* Historie: 17. 8.1996 Grundsteinlegung */
+/* 17.11.1998 ungueltiges Register wurde bei Indizierung nicht ab- */
+/* gefangen */
+/* 2. 1.1999 ChkPC umgestellt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmpars.h"
+#include "asmsub.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+/*---------------------------------------------------------------------------*/
+
+#define ModZA 0 /* aa */
+#define ModA 1 /* aabb */
+#define ModZIX 2 /* aa,X */
+#define ModIX 3 /* aabb,X */
+#define ModZIY 4 /* aa,Y */
+#define ModIY 5 /* aabb,Y */
+#define ModIndX 6 /* (aa,X) */
+#define ModIndY 7 /* (aa),Y */
+#define ModInd16 8 /* (aabb) */
+#define ModImm 9 /* #aa */
+#define ModAcc 10 /* A */
+#define ModNone 11 /* */
+#define ModInd8 12 /* (aa) */
+#define ModSpec 13 /* \aabb */
+
+typedef struct
+ {
+ char *Name;
+ Byte CPUFlag;
+ Byte Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Integer Codes[ModSpec+1];
+ } NormOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte CPUFlag;
+ Byte Code;
+ } CondOrder;
+
+#define FixedOrderCount 37
+#define NormOrderCount 51
+#define CondOrderCount 9
+
+
+static Boolean CLI_SEI_Flag,ADC_SBC_Flag;
+
+static FixedOrder *FixedOrders;
+static NormOrder *NormOrders;
+static CondOrder *CondOrders;
+
+static SimpProc SaveInitProc;
+static CPUVar CPU6502,CPU65SC02,CPU65C02,CPUM740,CPU6502U;
+static LongInt SpecPage;
+
+static ShortInt ErgMode;
+static Byte AdrVals[2];
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Byte NFlag, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].CPUFlag=NFlag;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddNorm(char *NName, Word ZACode, Word ACode, Word ZIXCode,
+ Word IXCode, Word ZIYCode, Word IYCode, Word IndXCode,
+ Word IndYCode, Word Ind16Code, Word ImmCode, Word AccCode,
+ Word NoneCode, Word Ind8Code, Word SpecCode)
+BEGIN
+ if (InstrZ>=NormOrderCount) exit(255);
+ NormOrders[InstrZ].Name=NName;
+ NormOrders[InstrZ].Codes[ModZA]=ZACode;
+ NormOrders[InstrZ].Codes[ModA]=ACode;
+ NormOrders[InstrZ].Codes[ModZIX]=ZIXCode;
+ NormOrders[InstrZ].Codes[ModIX]=IXCode;
+ NormOrders[InstrZ].Codes[ModZIY]=ZIYCode;
+ NormOrders[InstrZ].Codes[ModIY]=IYCode;
+ NormOrders[InstrZ].Codes[ModIndX]=IndXCode;
+ NormOrders[InstrZ].Codes[ModIndY]=IndYCode;
+ NormOrders[InstrZ].Codes[ModInd16]=Ind16Code;
+ NormOrders[InstrZ].Codes[ModImm]=ImmCode;
+ NormOrders[InstrZ].Codes[ModAcc]=AccCode;
+ NormOrders[InstrZ].Codes[ModNone]=NoneCode;
+ NormOrders[InstrZ].Codes[ModInd8]=Ind8Code;
+ NormOrders[InstrZ++].Codes[ModSpec]=SpecCode;
+END
+
+ static void AddCond(char *NName, Byte NFlag, Byte NCode)
+BEGIN
+ if (InstrZ>=CondOrderCount) exit(255);
+ CondOrders[InstrZ].Name=NName;
+ CondOrders[InstrZ].CPUFlag=NFlag;
+ CondOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ Boolean Is740=(MomCPU==CPUM740);
+
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("RTS", 31, 0x60); AddFixed("RTI", 31, 0x40);
+ AddFixed("TAX", 31, 0xaa); AddFixed("TXA", 31, 0x8a);
+ AddFixed("TAY", 31, 0xa8); AddFixed("TYA", 31, 0x98);
+ AddFixed("TXS", 31, 0x9a); AddFixed("TSX", 31, 0xba);
+ AddFixed("DEX", 31, 0xca); AddFixed("DEY", 31, 0x88);
+ AddFixed("INX", 31, 0xe8); AddFixed("INY", 31, 0xc8);
+ AddFixed("PHA", 31, 0x48); AddFixed("PLA", 31, 0x68);
+ AddFixed("PHP", 31, 0x08); AddFixed("PLP", 31, 0x28);
+ AddFixed("PHX", 6, 0xda); AddFixed("PLX", 6, 0xfa);
+ AddFixed("PHY", 6, 0x5a); AddFixed("PLY", 6, 0x7a);
+ AddFixed("BRK", 31, 0x00); AddFixed("STP", 8, 0x42);
+ AddFixed("SLW", 8, 0xc2); AddFixed("FST", 8, 0xe2);
+ AddFixed("WIT", 8, 0xc2); AddFixed("CLI", 31, 0x58);
+ AddFixed("SEI", 31, 0x78); AddFixed("CLC", 31, 0x18);
+ AddFixed("SEC", 31, 0x38); AddFixed("CLD", 31, 0xd8);
+ AddFixed("SED", 31, 0xf8); AddFixed("CLV", 31, 0xb8);
+ AddFixed("CLT", 8, 0x12); AddFixed("SET", 8, 0x32);
+ AddFixed("JAM", 16, 0x02); AddFixed("CRS", 16, 0x02);
+ AddFixed("KIL", 16, 0x02);
+
+
+ NormOrders=(NormOrder *) malloc(sizeof(NormOrder)*NormOrderCount); InstrZ=0;
+ /* ZA A ZIX IX ZIY IY @X @Y (n16) imm ACC NON (n8) spec */
+ AddNorm("NOP",0x1004,0x100c,0x1014,0x101c, -1, -1, -1, -1, -1,0x1080, -1,0x1fea, -1, -1);
+ AddNorm("LDA",0x1fa5,0x1fad,0x1fb5,0x1fbd, -1,0x1fb9,0x1fa1,0x1fb1, -1,0x1fa9, -1, -1,0x06b2, -1);
+ AddNorm("LDX",0x1fa6,0x1fae, -1, -1,0x1fb6,0x1fbe, -1, -1, -1,0x1fa2, -1, -1, -1, -1);
+ AddNorm("LDY",0x1fa4,0x1fac,0x1fb4,0x1fbc, -1, -1, -1, -1, -1,0x1fa0, -1, -1, -1, -1);
+ AddNorm("STA",0x1f85,0x1f8d,0x1f95,0x1f9d, -1,0x1f99,0x1f81,0x1f91, -1, -1, -1, -1,0x0692, -1);
+ AddNorm("STX",0x1f86,0x1f8e, -1, -1,0x1f96, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("STY",0x1f84,0x1f8c,0x1f94, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("STZ",0x0664,0x069c,0x0674,0x069e, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("ADC",0x1f65,0x1f6d,0x1f75,0x1f7d, -1,0x1f79,0x1f61,0x1f71, -1,0x1f69, -1, -1,0x0672, -1);
+ AddNorm("SBC",0x1fe5,0x1fed,0x1ff5,0x1ffd, -1,0x1ff9,0x1fe1,0x1ff1, -1,0x1fe9, -1, -1,0x06f2, -1);
+ AddNorm("MUL", -1, -1,0x0862, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("DIV", -1, -1,0x08e2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("AND",0x1f25,0x1f2d,0x1f35,0x1f3d, -1,0x1f39,0x1f21,0x1f31, -1,0x1f29, -1, -1,0x0632, -1);
+ AddNorm("ORA",0x1f05,0x1f0d,0x1f15,0x1f1d, -1,0x1f19,0x1f01,0x1f11, -1,0x1f09, -1, -1,0x0612, -1);
+ AddNorm("EOR",0x1f45,0x1f4d,0x1f55,0x1f5d, -1,0x1f59,0x1f41,0x1f51, -1,0x1f49, -1, -1,0x0652, -1);
+ AddNorm("COM",0x0844, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("BIT",0x1f24,0x1f2c,0x0634,0x063c, -1, -1, -1, -1, -1,0x0689, -1, -1, -1, -1);
+ AddNorm("TST",0x0864, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("ASL",0x1f06,0x1f0e,0x1f16,0x1f1e, -1, -1, -1, -1, -1, -1,0x1f0a,0x1f0a, -1, -1);
+ AddNorm("LSR",0x1f46,0x1f4e,0x1f56,0x1f5e, -1, -1, -1, -1, -1, -1,0x1f4a,0x1f4a, -1, -1);
+ AddNorm("ROL",0x1f26,0x1f2e,0x1f36,0x1f3e, -1, -1, -1, -1, -1, -1,0x1f2a,0x1f2a, -1, -1);
+ AddNorm("ROR",0x1f66,0x1f6e,0x1f76,0x1f7e, -1, -1, -1, -1, -1, -1,0x1f6a,0x1f6a, -1, -1);
+ AddNorm("RRF",0x0882, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("TSB",0x0604,0x060c, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("TRB",0x0614,0x061c, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("INC",0x1fe6,0x1fee,0x1ff6,0x1ffe, -1, -1, -1, -1, -1, -1,(Is740)?0x0e3a:0x0e1a,
+ (Is740)?0x0e3a:0x0e1a,
+ -1, -1);
+ AddNorm("DEC",0x1fc6,0x1fce,0x1fd6,0x1fde, -1, -1, -1, -1, -1, -1,(Is740)?0x0e1a:0x0e3a,
+ (Is740)?0x0e1a:0x0e3a,
+ -1, -1);
+ AddNorm("CMP",0x1fc5,0x1fcd,0x1fd5,0x1fdd, -1,0x1fd9,0x1fc1,0x1fd1, -1,0x1fc9, -1, -1,0x06d2, -1);
+ AddNorm("CPX",0x1fe4,0x1fec, -1, -1, -1, -1, -1, -1, -1,0x1fe0, -1, -1, -1, -1);
+ AddNorm("CPY",0x1fc4,0x1fcc, -1, -1, -1, -1, -1, -1, -1,0x1fc0, -1, -1, -1, -1);
+ AddNorm("JMP", -1,0x1f4c, -1, -1, -1, -1,0x067c, -1,0x1f6c, -1, -1, -1,0x08b2, -1);
+ AddNorm("JSR", -1,0x1f20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0x0802,0x0822);
+ AddNorm("SLO",0x1007,0x100f,0x1017,0x101f, -1,0x101b,0x1003,0x1013, -1, -1, -1, -1, -1, -1);
+ AddNorm("ANC", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x100b, -1, -1, -1, -1);
+ AddNorm("RLA",0x1027,0x102f,0x1037,0x103f, -1,0x103b,0x1023,0x1033, -1, -1, -1, -1, -1, -1);
+ AddNorm("SRE",0x1047,0x104f,0x1057,0x105f, -1,0x105b,0x1043,0x1053, -1, -1, -1, -1, -1, -1);
+ AddNorm("ASR", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x104b, -1, -1, -1, -1);
+ AddNorm("RRA",0x1067,0x106f,0x1077,0x107f, -1,0x107b,0x1063,0x1073, -1, -1, -1, -1, -1, -1);
+ AddNorm("ARR", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x106b, -1, -1, -1, -1);
+ AddNorm("SAX",0x1087,0x108f, -1, -1,0x1097, -1,0x1083, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("ANE", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x108b, -1, -1, -1, -1);
+ AddNorm("SHA", -1, -1, -1,0x1093, -1,0x109f, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("SHS", -1, -1, -1, -1, -1,0x109b, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("SHY", -1, -1, -1, -1, -1,0x109c, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("SHX", -1, -1, -1,0x109e, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("LAX",0x10a7,0x10af, -1, -1,0x10b7,0x10bf,0x10a3,0x10b3, -1, -1, -1, -1, -1, -1);
+ AddNorm("LXA", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x10ab, -1, -1, -1, -1);
+ AddNorm("LAE", -1, -1, -1, -1, -1,0x10bb, -1, -1, -1, -1, -1, -1, -1, -1);
+ AddNorm("DCP",0x10c7,0x10cf,0x10d7,0x10df, -1,0x10db,0x10c3,0x10d3, -1, -1, -1, -1, -1, -1);
+ AddNorm("SBX", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x10cb, -1, -1, -1, -1);
+ AddNorm("ISB",0x10e7,0x10ef,0x10f7,0x10ff, -1,0x10fb,0x10e3,0x10f3, -1, -1, -1, -1, -1, -1);
+
+ CondOrders=(CondOrder *) malloc(sizeof(CondOrder)*CondOrderCount); InstrZ=0;
+ AddCond("BEQ", 31, 0xf0);
+ AddCond("BNE", 31, 0xd0);
+ AddCond("BPL", 31, 0x10);
+ AddCond("BMI", 31, 0x30);
+ AddCond("BCC", 31, 0x90);
+ AddCond("BCS", 31, 0xb0);
+ AddCond("BVC", 31, 0x50);
+ AddCond("BVS", 31, 0x70);
+ AddCond("BRA", 14, 0x80);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(NormOrders);
+ free(CondOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void ChkZero(char *Asc, Byte *erg)
+BEGIN
+ if ((strlen(Asc)>1) AND ((*Asc=='<') OR (*Asc=='>')))
+ BEGIN
+ *erg=Ord(*Asc=='<')+1; strcpy(Asc,Asc+1);
+ END
+ else *erg=0;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME740Count 1
+ static ASSUMERec ASSUME740s[ASSUME740Count]=
+ {{"SP", &SpecPage, 0, 0xff, -1}};
+
+ if (Memo("ASSUME"))
+ BEGIN
+ if (MomCPU!=CPUM740) WrError(1500);
+ else CodeASSUME(ASSUME740s,ASSUME740Count);
+ return True;
+ END
+
+ return False;
+END
+
+ static void ChkFlags(void)
+BEGIN
+ /* Spezialflags ? */
+
+ CLI_SEI_Flag=(Memo("CLI") OR Memo("SEI"));
+ ADC_SBC_Flag=(Memo("ADC") OR Memo("SBC"));
+END
+
+ static Boolean CPUAllowed(Byte Flag)
+BEGIN
+ return (((Flag >> (MomCPU-CPU6502))&1)==1);
+END
+
+ static void InsNOP(void)
+BEGIN
+ memmove(BAsmCode,BAsmCode+1,CodeLen);
+ CodeLen++; BAsmCode[0]=NOPCode;
+END
+
+ static Boolean IsAllowed(Word Val)
+BEGIN
+ return (CPUAllowed(Hi(Val)) AND (Val!=0xffff));
+END
+
+ static void ChkZeroMode(ShortInt Mode)
+BEGIN
+ int OrderZ;
+
+ for (OrderZ=0; OrderZ<NormOrderCount; OrderZ++)
+ if (Memo(NormOrders[OrderZ].Name))
+ BEGIN
+ if (IsAllowed(NormOrders[OrderZ].Codes[Mode]))
+ BEGIN
+ ErgMode=Mode; AdrCnt--;
+ END
+ return;
+ END
+END
+
+ static void MakeCode_65(void)
+BEGIN
+ Word OrderZ;
+ Byte AdrByte;
+ Integer AdrInt;
+ Word AdrWord;
+ String s1;
+ Boolean ValOK,b;
+ Byte ZeroMode;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) { ChkFlags(); return; }
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) { ChkFlags(); return; }
+
+ if (DecodeMotoPseudo(False)) { ChkFlags(); return; }
+
+ /* Anweisungen ohne Argument */
+
+ for (OrderZ=0; OrderZ<FixedOrderCount; OrderZ++)
+ if (Memo(FixedOrders[OrderZ].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (NOT CPUAllowed(FixedOrders[OrderZ].CPUFlag)) WrError(1500);
+ else
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=FixedOrders[OrderZ].Code;
+ if (Memo("BRK")) BAsmCode[CodeLen++]=NOPCode;
+ else if (MomCPU==CPUM740)
+ BEGIN
+ if (Memo("PLP")) BAsmCode[CodeLen++]=NOPCode;
+ if ((ADC_SBC_Flag) AND (Memo("SEC") OR Memo("CLC") OR Memo("CLD"))) InsNOP();
+ END
+ END
+ ChkFlags(); return;
+ END
+
+ if ((Memo("SEB")) OR (Memo("CLB")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU!=CPUM740) WrError(1500);
+ else
+ BEGIN
+ AdrByte=EvalIntExpression(ArgStr[1],UInt3,&ValOK);
+ if (ValOK)
+ BEGIN
+ BAsmCode[0]=0x0b+(AdrByte << 5)+(Ord(Memo("CLB")) << 4);
+ if (strcasecmp(ArgStr[2],"A")==0) CodeLen=1;
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ CodeLen=2; BAsmCode[0]+=4;
+ END
+ END
+ END
+ END
+ ChkFlags(); return;
+ END
+
+ if ((Memo("BBC")) OR (Memo("BBS")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (MomCPU!=CPUM740) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[0]=EvalIntExpression(ArgStr[1],UInt3,&ValOK);
+ if (ValOK)
+ BEGIN
+ BAsmCode[0]=(BAsmCode[0] << 5)+(Ord(Memo("BBC")) << 4)+3;
+ b=(strcasecmp(ArgStr[2],"A")!=0);
+ if (NOT b) ValOK=True;
+ else
+ BEGIN
+ BAsmCode[0]+=4;
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],UInt8,&ValOK);
+ END
+ if (ValOK)
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[3],Int16,&ValOK)-(EProgCounter()+2+Ord(b)+Ord(CLI_SEI_Flag));
+ if (ValOK)
+ if (((AdrInt>127) OR (AdrInt<-128)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2+Ord(b);
+ BAsmCode[CodeLen-1]=AdrInt & 0xff;
+ if (CLI_SEI_Flag) InsNOP();
+ END
+ END
+ END
+ END
+ ChkFlags(); return;
+ END
+
+ if (((strlen(OpPart)==4)
+ AND (OpPart[3]>='0') AND (OpPart[3]<='7')
+ AND ((strncmp(OpPart,"BBR",3)==0) OR (strncmp(OpPart,"BBS",3)==0))))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU!=CPU65C02) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1],UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ BAsmCode[0]=((OpPart[3]-'0') << 4)+(Ord(OpPart[2]=='S') << 7)+15;
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&ValOK)-(EProgCounter()+3);
+ if (ValOK)
+ if (((AdrInt>127) OR (AdrInt<-128)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=3;
+ BAsmCode[2]=AdrInt & 0xff;
+ END
+ END
+ END
+ ChkFlags(); return;
+ END
+
+ if (((strlen(OpPart)==4)
+ AND (OpPart[3]>='0') AND (OpPart[3]<='7')
+ AND ((strncmp(OpPart,"RMB",3)==0) OR (strncmp(OpPart,"SMB",3)==0))))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU!=CPU65C02) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1],UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ BAsmCode[0]=((OpPart[3]-'0') << 4)+(Ord(*OpPart=='S') << 7)+7;
+ CodeLen=2;
+ END
+ END
+ ChkFlags(); return;
+ END
+
+ if (Memo("LDM"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU!=CPUM740) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[0]=0x3c;
+ BAsmCode[2]=EvalIntExpression(ArgStr[2],UInt8,&ValOK);
+ if (ValOK)
+ if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1]+1,Int8,&ValOK);
+ if (ValOK) CodeLen=3;
+ END
+ END
+ ChkFlags(); return;
+ END
+
+ /* normale Anweisungen: Adressausdruck parsen */
+
+ ErgMode=(-1);
+
+ if (ArgCnt==0)
+ BEGIN
+ AdrCnt=0; ErgMode=ModNone;
+ END
+
+ else if (ArgCnt==1)
+ BEGIN
+ /* 1. Akkuadressierung */
+
+ if (strcasecmp(ArgStr[1],"A")==0)
+ BEGIN
+ AdrCnt=0; ErgMode=ModAcc;
+ END
+
+ /* 2. immediate ? */
+
+ else if (*ArgStr[1]=='#')
+ BEGIN
+ AdrVals[0]=EvalIntExpression(ArgStr[1]+1,Int8,&ValOK);
+ if (ValOK)
+ BEGIN
+ ErgMode=ModImm; AdrCnt=1;
+ END
+ END
+
+ /* 3. Special Page ? */
+
+ else if (*ArgStr[1]=='\\')
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1]+1,UInt16,&ValOK);
+ if (ValOK)
+ if (Hi(AdrWord)!=SpecPage) WrError(1315);
+ else
+ BEGIN
+ ErgMode=ModSpec; AdrVals[0]=Lo(AdrWord); AdrCnt=1;
+ END
+ END
+
+ /* 4. X-indirekt ? */
+
+ else if ((strlen(ArgStr[1])>=5) AND (strcasecmp(ArgStr[1]+strlen(ArgStr[1])-3,",X)")==0))
+ BEGIN
+ if (*ArgStr[1]!='(') WrError(1350);
+ else
+ BEGIN
+ strmaxcpy(s1,ArgStr[1]+1,255); s1[strlen(s1)-3]='\0';
+ ChkZero(s1,&ZeroMode);
+ if (Memo("JMP"))
+ BEGIN
+ AdrWord=EvalIntExpression(s1,UInt16,&ValOK);
+ if (ValOK)
+ BEGIN
+ AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord);
+ ErgMode=ModIndX; AdrCnt=2;
+ END
+ END
+ else
+ BEGIN
+ AdrVals[0]=EvalIntExpression(s1,UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ ErgMode=ModIndX; AdrCnt=1;
+ END
+ END
+ END
+ END
+
+ else
+ BEGIN
+ /* 5. indirekt absolut ? */
+
+ if (IsIndirect(ArgStr[1]))
+ BEGIN
+ strcpy(s1,ArgStr[1]+1); s1[strlen(s1)-1]='\0';
+ ChkZero(s1,&ZeroMode);
+ if (ZeroMode==2)
+ BEGIN
+ AdrVals[0]=EvalIntExpression(s1,UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ ErgMode=ModInd8; AdrCnt=1;
+ END
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(s1,UInt16,&ValOK);
+ if (ValOK)
+ BEGIN
+ ErgMode=ModInd16; AdrCnt=2;
+ AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord);
+ if ((ZeroMode==0) AND (AdrVals[1]==0)) ChkZeroMode(ModInd8);
+ END
+ END
+ END
+
+ /* 6. absolut */
+
+ else
+ BEGIN
+ ChkZero(ArgStr[1],&ZeroMode);
+ if (ZeroMode==2)
+ BEGIN
+ AdrVals[0]=EvalIntExpression(ArgStr[1],UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ ErgMode=ModZA; AdrCnt=1;
+ END
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt16,&ValOK);
+ if (ValOK)
+ BEGIN
+ ErgMode=ModA; AdrCnt=2;
+ AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord);
+ if ((ZeroMode==0) AND (AdrVals[1]==0)) ChkZeroMode(ModZA);
+ END
+ END
+ END
+ END
+ END
+
+ else if (ArgCnt==2)
+ BEGIN
+ /* 7. Y-indirekt ? */
+
+ if ((IsIndirect(ArgStr[1])) AND (strcasecmp(ArgStr[2],"Y")==0))
+ BEGIN
+ strcpy(s1,ArgStr[1]+1); s1[strlen(s1)-1]='\0';
+ ChkZero(s1,&ZeroMode);
+ AdrVals[0]=EvalIntExpression(s1,UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ ErgMode=ModIndY; AdrCnt=1;
+ END
+ END
+
+ /* 8. X,Y-indiziert ? */
+
+ else
+ BEGIN
+ strcpy(s1,ArgStr[1]);
+ ChkZero(s1,&ZeroMode);
+ if (ZeroMode==2)
+ BEGIN
+ AdrVals[0]=EvalIntExpression(s1,UInt8,&ValOK);
+ if (ValOK)
+ BEGIN
+ AdrCnt=1;
+ if (strcasecmp(ArgStr[2],"X")==0) ErgMode=ModZIX;
+ else if (strcasecmp(ArgStr[2],"Y")==0) ErgMode=ModZIY;
+ else WrXError(1445,ArgStr[2]);
+ END
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(s1,Int16,&ValOK);
+ if (ValOK)
+ BEGIN
+ AdrCnt=2;
+ AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord);
+ if (strcasecmp(ArgStr[2],"X")==0) ErgMode=ModIX;
+ else if (strcasecmp(ArgStr[2],"Y")==0) ErgMode=ModIY;
+ else WrXError(1445,ArgStr[2]);
+ if (ErgMode != -1)
+ BEGIN
+ if ((AdrVals[1]==0) AND (ZeroMode==0))
+ ChkZeroMode((strcasecmp(ArgStr[2],"X")==0)?ModZIX:ModZIY);
+ END
+ END
+ END
+ END
+ END
+
+ else
+ BEGIN
+ WrError(1110);
+ ChkFlags(); return;
+ END;
+
+ /* in Tabelle nach Opcode suchen */
+
+ for (OrderZ=0; OrderZ<NormOrderCount; OrderZ++)
+ if (Memo(NormOrders[OrderZ].Name))
+ BEGIN
+ if ((ErgMode==-1)) WrError(1350);
+ else
+ BEGIN
+ if (NormOrders[OrderZ].Codes[ErgMode]==-1)
+ BEGIN
+ if (ErgMode==ModZA) ErgMode=ModA;
+ if (ErgMode==ModZIX) ErgMode=ModIX;
+ if (ErgMode==ModZIY) ErgMode=ModIY;
+ if (ErgMode==ModInd8) ErgMode=ModInd16;
+ AdrVals[AdrCnt++]=0;
+ END
+ if (NormOrders[OrderZ].Codes[ErgMode]==-1) WrError(1350);
+ else if (NOT CPUAllowed(Hi(NormOrders[OrderZ].Codes[ErgMode]))) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[0]=Lo(NormOrders[OrderZ].Codes[ErgMode]);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=AdrCnt+1;
+ if ((ErgMode==ModInd16) AND (MomCPU!=CPU65C02) AND (BAsmCode[1]==0xff))
+ BEGIN
+ WrError(1900); CodeLen=0;
+ END
+ END
+ END
+ ChkFlags(); return;
+ END
+
+ /* relativer Sprung ? */
+
+ if (ErgMode==ModZA)
+ BEGIN
+ ErgMode=ModA; AdrVals[1]=0;
+ END
+ if (ErgMode==ModA)
+ for (OrderZ=0; OrderZ<CondOrderCount; OrderZ++)
+ if (Memo(CondOrders[OrderZ].Name))
+ BEGIN
+ AdrInt=(((Integer)AdrVals[1])<<8)+AdrVals[0];
+ AdrInt-=EProgCounter()+2;
+ if (NOT CPUAllowed(CondOrders[OrderZ].CPUFlag)) WrError(1500);
+ else if (((AdrInt>127) OR (AdrInt<-128)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=CondOrders[OrderZ].Code; BAsmCode[1]=AdrInt & 0xff;
+ CodeLen=2;
+ END
+ ChkFlags(); return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_65(void)
+BEGIN
+ SaveInitProc();
+ CLI_SEI_Flag=False;
+ ADC_SBC_Flag=False;
+END
+
+ static Boolean IsDef_65(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_65(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_65(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=(MomCPU==CPUM740);
+
+ PCSymbol="*"; HeaderID=0x11; NOPCode=0xea;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_65; IsDef=IsDef_65;
+ SwitchFrom=SwitchFrom_65; InitFields();
+END
+
+ void code65_init(void)
+BEGIN
+ CPU6502 =AddCPU("6502" ,SwitchTo_65);
+ CPU65SC02=AddCPU("65SC02" ,SwitchTo_65);
+ CPU65C02 =AddCPU("65C02" ,SwitchTo_65);
+ CPUM740 =AddCPU("MELPS740" ,SwitchTo_65);
+ CPU6502U =AddCPU("6502UNDOC",SwitchTo_65);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_65;
+END
diff --git a/code65.h b/code65.h
new file mode 100644
index 0000000..a4cea18
--- /dev/null
+++ b/code65.h
@@ -0,0 +1,11 @@
+/* code65.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 65xx/MELPS740 */
+/* */
+/* Historie: 17.8.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code65_init(void);
diff --git a/code68.c b/code68.c
new file mode 100644
index 0000000..6f679d6
--- /dev/null
+++ b/code68.c
@@ -0,0 +1,847 @@
+/* code68.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator fuer 68xx Prozessoren */
+/* */
+/* Historie: 13. 8.1996 Grundsteinlegung */
+/* 2. 1.1998 ChkPC ersetzt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmpars.h"
+#include "asmsub.h"
+#include "codepseudo.h"
+#include "codevars.h"
+#include "asmitree.h"
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU,MaxCPU;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } BaseOrder;
+
+typedef struct
+ {
+ char *Name;
+ Boolean MayImm;
+ Byte Code;
+ } ALU8Order;
+
+typedef struct
+ {
+ Boolean MayImm;
+ CPUVar MinCPU; /* Shift andere ,Y */
+ Byte PageShift; /* 0 : nix Pg 2 */
+ Byte Code; /* 1 : Pg 3 Pg 4 */
+ } ALU16Order; /* 2 : nix Pg 4 */
+ /* 3 : Pg 2 Pg 3 */
+
+
+#define ModNone (-1)
+#define ModAcc 0
+#define MModAcc (1<<ModAcc)
+#define ModDir 1
+#define MModDir (1<<ModDir)
+#define ModExt 2
+#define MModExt (1<<ModExt)
+#define ModInd 3
+#define MModInd (1<<ModInd)
+#define ModImm 4
+#define MModImm (1<<ModImm)
+
+#define Page2Prefix 0x18
+#define Page3Prefix 0x1a
+#define Page4Prefix 0xcd
+
+#define FixedOrderCnt 45
+#define RelOrderCnt 19
+#define ALU8OrderCnt 11
+#define ALU16OrderCnt 13
+#define Sing8OrderCnt 12
+#define Bit63OrderCnt 4
+
+
+static ShortInt OpSize;
+static Byte PrefCnt; /* Anzahl Befehlspraefixe */
+static ShortInt AdrMode; /* Ergebnisadressmodus */
+static Byte AdrPart; /* Adressierungsmodusbits im Opcode */
+static Byte AdrVals[4]; /* Adressargument */
+
+static FixedOrder *FixedOrders;
+static BaseOrder *RelOrders;
+static ALU8Order *ALU8Orders;
+static ALU16Order *ALU16Orders;
+static BaseOrder *Bit63Orders;
+static BaseOrder *Sing8Orders;
+static PInstTable InstTable;
+
+static CPUVar CPU6800,CPU6301,CPU6811;
+
+/*---------------------------------------------------------------------------*/
+
+ static void DecodeAdr(int StartInd, int StopInd, Byte Erl)
+BEGIN
+ String Asc;
+ Boolean OK,ErrOcc;
+ Word AdrWord;
+ Byte Bit8;
+
+ AdrMode=ModNone; AdrPart=0; strmaxcpy(Asc,ArgStr[StartInd],255); ErrOcc=False;
+
+ /* eine Komponente ? */
+
+ if (StartInd==StopInd)
+ BEGIN
+
+ /* Akkumulatoren ? */
+
+ if (strcasecmp(Asc,"A")==0)
+ BEGIN
+ if ((MModAcc & Erl)!=0) AdrMode=ModAcc;
+ END
+ else if (strcasecmp(Asc,"B")==0)
+ BEGIN
+ if ((MModAcc & Erl)!=0)
+ BEGIN
+ AdrMode=ModAcc; AdrPart=1;
+ END
+ END
+
+ /* immediate ? */
+
+ else if ((strlen(Asc)>1) AND (*Asc=='#'))
+ BEGIN
+ if ((MModImm & Erl)!=0)
+ BEGIN
+ if (OpSize==1)
+ BEGIN
+ AdrWord=EvalIntExpression(Asc+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrMode=ModImm;
+ AdrVals[AdrCnt++]=Hi(AdrWord); AdrVals[AdrCnt++]=Lo(AdrWord);
+ END
+ else ErrOcc=True;
+ END
+ else
+ BEGIN
+ AdrVals[AdrCnt]=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrMode=ModImm; AdrCnt++;
+ END
+ else ErrOcc=True;
+ END
+ END
+ END
+
+ /* absolut ? */
+
+ else
+ BEGIN
+ Bit8=0;
+ if (*Asc=='<')
+ BEGIN
+ Bit8=2; strcpy(Asc,Asc+1);
+ END
+ else if (*Asc=='>')
+ BEGIN
+ Bit8=1; strcpy(Asc,Asc+1);
+ END
+ if ((Bit8==2) OR ((MModExt & Erl)==0))
+ AdrWord=EvalIntExpression(Asc,Int8,&OK);
+ else
+ AdrWord=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ if (((MModDir & Erl)!=0) AND (Bit8!=1) AND ((Bit8==2) OR ((MModExt & Erl)==0) OR (Hi(AdrWord)==0)))
+ BEGIN
+ if (Hi(AdrWord)!=0)
+ BEGIN
+ WrError(1340); ErrOcc=True;
+ END
+ else
+ BEGIN
+ AdrMode=ModDir; AdrPart=1;
+ AdrVals[AdrCnt++]=Lo(AdrWord);
+ END
+ END
+ else if ((MModExt & Erl)!=0)
+ BEGIN
+ AdrMode=ModExt; AdrPart=3;
+ AdrVals[AdrCnt++]=Hi(AdrWord); AdrVals[AdrCnt++]=Lo(AdrWord);
+ END
+ END
+ else ErrOcc=True;
+ END
+ END
+
+ /* zwei Komponenten ? */
+
+ else if (StartInd+1==StopInd)
+ BEGIN
+
+ /* indiziert ? */
+
+ if (((strcasecmp(ArgStr[StopInd],"X")==0) OR (strcasecmp(ArgStr[StopInd],"Y")==0)))
+ BEGIN
+ if ((MModInd & Erl)!=0)
+ BEGIN
+ AdrWord=EvalIntExpression(Asc,Int8,&OK);
+ if (OK)
+ if ((MomCPU<CPU6811) AND (strcasecmp(ArgStr[StartInd+1],"Y")==0))
+ BEGIN
+ WrError(1505); ErrOcc=True;
+ END
+ else
+ BEGIN
+ AdrVals[AdrCnt++]=Lo(AdrWord);
+ AdrMode=ModInd; AdrPart=2;
+ if (strcasecmp(ArgStr[StartInd+1],"Y")==0)
+ BEGIN
+ BAsmCode[PrefCnt++]=0x18;
+ END
+ END
+ else ErrOcc=True;
+ END
+ END
+ else
+ BEGIN
+ WrXError(1445,ArgStr[StopInd]); ErrOcc=True;
+ END
+
+ END
+ else
+ BEGIN
+ WrError(1110); ErrOcc=True;
+ END
+
+ if ((NOT ErrOcc) AND (AdrMode==ModNone)) WrError(1350);
+END
+
+ static void AddPrefix(Byte Prefix)
+BEGIN
+ BAsmCode[PrefCnt++]=Prefix;
+END
+
+ static void Try2Split(int Src)
+BEGIN
+ Integer z;
+ char *p;
+
+ KillPrefBlanks(ArgStr[Src]); KillPostBlanks(ArgStr[Src]);
+ p=ArgStr[Src]+strlen(ArgStr[Src])-1;
+ while ((p>ArgStr[Src]) AND (NOT isspace((unsigned int) *p))) p--;
+ if (p>ArgStr[Src])
+ BEGIN
+ for (z=ArgCnt; z>=Src; z--) strcpy(ArgStr[z+1],ArgStr[z]); ArgCnt++;
+ strcpy(ArgStr[Src+1],p+1); *p='\0';
+ KillPostBlanks(ArgStr[Src]); KillPrefBlanks(ArgStr[Src+1]);
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *forder=FixedOrders+Index;
+
+ if (ArgCnt!=0) WrError(1110);
+ else if ((MomCPU<forder->MinCPU) OR (MomCPU>forder->MaxCPU)) WrError(1500);
+ else if (Hi(forder->Code)!=0)
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=Hi(forder->Code);
+ BAsmCode[1]=Lo(forder->Code);
+ END
+ else
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=Lo(forder->Code);
+ END
+END
+
+ static void DecodeRel(Word Index)
+BEGIN
+ BaseOrder *forder=RelOrders+Index;
+ Integer AdrInt;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrInt-=EProgCounter()+2;
+ if (((AdrInt<-128) OR (AdrInt>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=forder->Code; BAsmCode[1]=Lo(AdrInt);
+ END
+ END
+ END
+END
+
+ static void DecodeALU16(Word Index)
+BEGIN
+ ALU16Order *forder=ALU16Orders+Index;
+
+ OpSize=1;
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (MomCPU<forder->MinCPU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(1,ArgCnt,(forder->MayImm?MModImm:0)+MModInd+MModExt+MModDir);
+ if (AdrMode!=ModNone)
+ BEGIN
+ switch (forder->PageShift)
+ BEGIN
+ case 1:
+ if (PrefCnt==1) BAsmCode[PrefCnt-1]=Page4Prefix;
+ else AddPrefix(Page3Prefix);
+ break;
+ case 2:
+ if (PrefCnt==1) BAsmCode[PrefCnt-1]=Page4Prefix;
+ break;
+ case 3:
+ if (PrefCnt==0) AddPrefix((AdrMode==ModInd)?Page3Prefix:Page2Prefix);
+ break;
+ END
+ BAsmCode[PrefCnt]=forder->Code+(AdrPart << 4);
+ CodeLen=PrefCnt+1+AdrCnt;
+ memcpy(BAsmCode+1+PrefCnt,AdrVals,AdrCnt);
+ END
+ END
+END
+
+ static void DecodeBit63(Word Index)
+BEGIN
+ BaseOrder *forder=Bit63Orders+Index;
+
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else if (MomCPU!=CPU6301) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(1,1,MModImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ DecodeAdr(2,ArgCnt,MModDir+MModInd);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[PrefCnt]=forder->Code;
+ if (AdrMode==ModDir) BAsmCode[PrefCnt]+=0x10;
+ CodeLen=PrefCnt+1+AdrCnt;
+ memcpy(BAsmCode+1+PrefCnt,AdrVals,AdrCnt);
+ END
+ END
+ END
+END
+
+ static void DecodeJMP(Word Index)
+BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(1,ArgCnt,MModExt+MModInd);
+ if (AdrMode!=ModImm)
+ BEGIN
+ CodeLen=PrefCnt+1+AdrCnt;
+ BAsmCode[PrefCnt]=0x4e + (AdrPart << 4);
+ memcpy(BAsmCode+1+PrefCnt,AdrVals,AdrCnt);
+ END
+ END
+END
+
+ static void DecodeJSR(Word Index)
+BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(1,ArgCnt,MModDir+MModExt+MModInd);
+ if (AdrMode!=ModImm)
+ BEGIN
+ CodeLen=PrefCnt+1+AdrCnt;
+ BAsmCode[PrefCnt]=0x8d+(AdrPart << 4);
+ memcpy(BAsmCode+1+PrefCnt,AdrVals,AdrCnt);
+ END
+ END
+END
+
+ static void DecodeBRxx(Word Index)
+BEGIN
+ Boolean OK;
+ Byte Mask;
+ Integer AdrInt;
+
+ if (ArgCnt==1)
+ BEGIN
+ Try2Split(1); Try2Split(1);
+ END
+ else if (ArgCnt==2)
+ BEGIN
+ Try2Split(ArgCnt); Try2Split(2);
+ END
+ if ((ArgCnt<3) OR (ArgCnt>4)) WrError(1110);
+ else if (MomCPU<CPU6811) WrError(1500);
+ else
+ BEGIN
+ if (*ArgStr[ArgCnt-1]=='#') strcpy(ArgStr[ArgCnt-1],ArgStr[ArgCnt-1]+1);
+ Mask=EvalIntExpression(ArgStr[ArgCnt-1],Int8,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(1,ArgCnt-2,MModDir+MModInd);
+ if (AdrMode!=ModNone)
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[ArgCnt],Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrInt-=EProgCounter()+3+PrefCnt+AdrCnt;
+ if ((AdrInt<-128) OR (AdrInt>127)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=PrefCnt+3+AdrCnt;
+ BAsmCode[PrefCnt]=0x12+Index;
+ if (AdrMode==ModInd) BAsmCode[PrefCnt]+=12;
+ memcpy(BAsmCode+PrefCnt+1,AdrVals,AdrCnt);
+ BAsmCode[PrefCnt+1+AdrCnt]=Mask;
+ BAsmCode[PrefCnt+2+AdrCnt]=Lo(AdrInt);
+ END
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeBxx(Word Index)
+BEGIN
+ Byte Mask;
+ Boolean OK;
+ int z;
+
+ if (MomCPU==CPU6301)
+ BEGIN
+ strcpy(ArgStr[ArgCnt+1],ArgStr[1]);
+ for (z=1; z<=ArgCnt-1; z++) strcpy(ArgStr[z],ArgStr[z+1]);
+ strcpy(ArgStr[ArgCnt],ArgStr[ArgCnt+1]);
+ END
+ if ((ArgCnt>=1) AND (ArgCnt<=2)) Try2Split(ArgCnt);
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else if (MomCPU<CPU6301) WrError(1500);
+ else
+ BEGIN
+ if (*ArgStr[ArgCnt]=='#') strcpy(ArgStr[ArgCnt],ArgStr[ArgCnt]+1);
+ Mask=EvalIntExpression(ArgStr[ArgCnt],Int8,&OK);
+ if ((OK) AND (MomCPU==CPU6301))
+ if (Mask>7)
+ BEGIN
+ WrError(1320); OK=False;
+ END
+ else
+ BEGIN
+ Mask=1 << Mask;
+ if (Index==1) Mask=0xff-Mask;
+ END
+ if (OK)
+ BEGIN
+ DecodeAdr(1,ArgCnt-1,MModDir+MModInd);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CodeLen=PrefCnt+2+AdrCnt;
+ if (MomCPU==CPU6301)
+ BEGIN
+ BAsmCode[PrefCnt]=0x62-Index;
+ if (AdrMode==ModDir) BAsmCode[PrefCnt]+=0x10;
+ BAsmCode[1+PrefCnt]=Mask;
+ memcpy(BAsmCode+2+PrefCnt,AdrVals,AdrCnt);
+ END
+ else
+ BEGIN
+ BAsmCode[PrefCnt]=0x14+Index;
+ if (AdrMode==ModInd) BAsmCode[PrefCnt]+=8;
+ memcpy(BAsmCode+1+PrefCnt,AdrVals,AdrCnt);
+ BAsmCode[1+PrefCnt+AdrCnt]=Mask;
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeBTxx(Word Index)
+BEGIN
+ Boolean OK;
+ Byte AdrByte;
+
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else if (MomCPU!=CPU6301) WrError(1500);
+ else
+ BEGIN
+ AdrByte=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ if (AdrByte>7) WrError(1320);
+ else
+ BEGIN
+ DecodeAdr(2,ArgCnt,MModDir+MModInd);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CodeLen=PrefCnt+2+AdrCnt;
+ BAsmCode[1+PrefCnt]=1 << AdrByte;
+ memcpy(BAsmCode+2+PrefCnt,AdrVals,AdrCnt);
+ BAsmCode[PrefCnt]=0x65;
+ BAsmCode[PrefCnt]+=Index;
+ if (AdrMode==ModDir) BAsmCode[PrefCnt]+=0x10;
+ END
+ END
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, CPUVar NMin, CPUVar NMax, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].MinCPU=NMin;
+ FixedOrders[InstrZ].MaxCPU=NMax;
+ FixedOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
+END
+
+ static void AddRel(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeRel);
+END
+
+ static void AddALU8(char *NName, Boolean NMay, Byte NCode)
+BEGIN
+ if (InstrZ>=ALU8OrderCnt) exit(255);
+
+ ALU8Orders[InstrZ].Name=NName;
+ ALU8Orders[InstrZ].MayImm=NMay;
+ ALU8Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU16(char *NName, Boolean NMay, CPUVar NMin, Byte NShift, Byte NCode)
+BEGIN
+ if (InstrZ>=ALU16OrderCnt) exit(255);
+
+ ALU16Orders[InstrZ].MayImm=NMay;
+ ALU16Orders[InstrZ].MinCPU=NMin;
+ ALU16Orders[InstrZ].PageShift=NShift;
+ ALU16Orders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeALU16);
+END
+
+ static void AddSing8(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=Sing8OrderCnt) exit(255);
+
+ Sing8Orders[InstrZ].Name=NName;
+ Sing8Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddBit63(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=Bit63OrderCnt) exit(255);
+
+ Bit63Orders[InstrZ].Name=NName;
+ Bit63Orders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeBit63);
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(201);
+ AddInstTable(InstTable,"JMP",0,DecodeJMP);
+ AddInstTable(InstTable,"JSR",0,DecodeJSR);
+ AddInstTable(InstTable,"BRCLR",1,DecodeBRxx);
+ AddInstTable(InstTable,"BRSET",0,DecodeBRxx);
+ AddInstTable(InstTable,"BCLR",1,DecodeBxx);
+ AddInstTable(InstTable,"BSET",0,DecodeBxx);
+ AddInstTable(InstTable,"BTST",6,DecodeBTxx);
+ AddInstTable(InstTable,"BTGL",0,DecodeBTxx);
+
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("ABA" ,CPU6800, CPU6811, 0x001b); AddFixed("ABX" ,CPU6301, CPU6811, 0x003a);
+ AddFixed("ABY" ,CPU6811, CPU6811, 0x183a); AddFixed("ASLD" ,CPU6301, CPU6811, 0x0005);
+ AddFixed("CBA" ,CPU6800, CPU6811, 0x0011); AddFixed("CLC" ,CPU6800, CPU6811, 0x000c);
+ AddFixed("CLI" ,CPU6800, CPU6811, 0x000e); AddFixed("CLV" ,CPU6800, CPU6811, 0x000a);
+ AddFixed("DAA" ,CPU6800, CPU6811, 0x0019); AddFixed("DES" ,CPU6800, CPU6811, 0x0034);
+ AddFixed("DEX" ,CPU6800, CPU6811, 0x0009); AddFixed("DEY" ,CPU6811, CPU6811, 0x1809);
+ AddFixed("FDIV" ,CPU6811, CPU6811, 0x0003); AddFixed("IDIV" ,CPU6811, CPU6811, 0x0002);
+ AddFixed("INS" ,CPU6800, CPU6811, 0x0031); AddFixed("INX" ,CPU6800, CPU6811, 0x0008);
+ AddFixed("INY" ,CPU6811, CPU6811, 0x1808); AddFixed("LSLD" ,CPU6301, CPU6811, 0x0005);
+ AddFixed("LSRD" ,CPU6301, CPU6811, 0x0004); AddFixed("MUL" ,CPU6301, CPU6811, 0x003d);
+ AddFixed("NOP" ,CPU6800, CPU6811, 0x0001); AddFixed("PSHX" ,CPU6301, CPU6811, 0x003c);
+ AddFixed("PSHY" ,CPU6811, CPU6811, 0x183c); AddFixed("PULX" ,CPU6301, CPU6811, 0x0038);
+ AddFixed("PULY" ,CPU6811, CPU6811, 0x1838); AddFixed("RTI" ,CPU6800, CPU6811, 0x003b);
+ AddFixed("RTS" ,CPU6800, CPU6811, 0x0039); AddFixed("SBA" ,CPU6800, CPU6811, 0x0010);
+ AddFixed("SEC" ,CPU6800, CPU6811, 0x000d); AddFixed("SEI" ,CPU6800, CPU6811, 0x000f);
+ AddFixed("SEV" ,CPU6800, CPU6811, 0x000b); AddFixed("SLP" ,CPU6301, CPU6301, 0x001a);
+ AddFixed("STOP" ,CPU6811, CPU6811, 0x00cf); AddFixed("SWI" ,CPU6800, CPU6811, 0x003f);
+ AddFixed("TAB" ,CPU6800, CPU6811, 0x0016); AddFixed("TAP" ,CPU6800, CPU6811, 0x0006);
+ AddFixed("TBA" ,CPU6800, CPU6811, 0x0017); AddFixed("TPA" ,CPU6800, CPU6811, 0x0007);
+ AddFixed("TSX" ,CPU6800, CPU6811, 0x0030); AddFixed("TSY" ,CPU6811, CPU6811, 0x1830);
+ AddFixed("TXS" ,CPU6800, CPU6811, 0x0035); AddFixed("TYS" ,CPU6811, CPU6811, 0x1835);
+ AddFixed("WAI" ,CPU6800, CPU6811, 0x003e); AddFixed("XGDX" ,CPU6811, CPU6811, 0x008f);
+ AddFixed("XGDY" ,CPU6811, CPU6811, 0x188f);
+
+ RelOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("BCC", 0x24); AddRel("BCS", 0x25);
+ AddRel("BEQ", 0x27); AddRel("BGE", 0x2c);
+ AddRel("BGT", 0x2e); AddRel("BHI", 0x22);
+ AddRel("BHS", 0x24); AddRel("BLE", 0x2f);
+ AddRel("BLO", 0x25); AddRel("BLS", 0x23);
+ AddRel("BLT", 0x2d); AddRel("BMI", 0x2b);
+ AddRel("BNE", 0x26); AddRel("BPL", 0x2a);
+ AddRel("BRA", 0x20); AddRel("BRN", 0x21);
+ AddRel("BSR", 0x8d); AddRel("BVC", 0x28);
+ AddRel("BVS", 0x29);
+
+ ALU8Orders=(ALU8Order *) malloc(sizeof(ALU8Order)*ALU8OrderCnt); InstrZ=0;
+ AddALU8("ADC",True , 0x89);
+ AddALU8("ADD",True , 0x8b);
+ AddALU8("AND",True , 0x84);
+ AddALU8("BIT",True , 0x85);
+ AddALU8("CMP",True , 0x81);
+ AddALU8("EOR",True , 0x88);
+ AddALU8("LDA",True , 0x86);
+ AddALU8("ORA",True , 0x8a);
+ AddALU8("SBC",True , 0x82);
+ AddALU8("STA",False, 0x87);
+ AddALU8("SUB",True , 0x80);
+
+ ALU16Orders=(ALU16Order *) malloc(sizeof(ALU16Order)*ALU16OrderCnt); InstrZ=0;
+ AddALU16("ADDD", True , CPU6301, 0, 0xc3);
+ AddALU16("CPD" , True , CPU6811, 1, 0x83);
+ AddALU16("CPX" , True , CPU6800, 2, 0x8c);
+ AddALU16("CPY" , True , CPU6811, 3, 0x8c);
+ AddALU16("LDD" , True , CPU6301, 0, 0xcc);
+ AddALU16("LDS" , True , CPU6800, 0, 0x8e);
+ AddALU16("LDX" , True , CPU6800, 2, 0xce);
+ AddALU16("LDY" , True , CPU6811, 3, 0xce);
+ AddALU16("STD" , False, CPU6301, 0, 0xcd);
+ AddALU16("STS" , False, CPU6800, 0, 0x8f);
+ AddALU16("STX" , False, CPU6800, 2, 0xcf);
+ AddALU16("STY" , False, CPU6811, 3, 0xcf);
+ AddALU16("SUBD", True , CPU6301, 0, 0x83);
+
+ Sing8Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*Sing8OrderCnt); InstrZ=0;
+ AddSing8("ASL", 0x48);
+ AddSing8("ASR", 0x47);
+ AddSing8("CLR", 0x4f);
+ AddSing8("COM", 0x43);
+ AddSing8("DEC", 0x4a);
+ AddSing8("INC", 0x4c);
+ AddSing8("LSL", 0x48);
+ AddSing8("LSR", 0x44);
+ AddSing8("NEG", 0x40);
+ AddSing8("ROL", 0x49);
+ AddSing8("ROR", 0x46);
+ AddSing8("TST", 0x4d);
+
+ Bit63Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*Bit63OrderCnt); InstrZ=0;
+ AddBit63("AIM", 0x61); AddBit63("EIM", 0x65);
+ AddBit63("OIM", 0x62); AddBit63("TIM", 0x6b);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+ free(RelOrders);
+ free(ALU8Orders);
+ free(ALU16Orders);
+ free(Sing8Orders);
+ free(Bit63Orders);
+END
+
+ static Boolean SplitAcc(char *Op)
+BEGIN
+ char Ch;
+ Integer z;
+ int OpLen=strlen(Op),OpPartLen=strlen(OpPart);
+
+ Ch=OpPart[OpPartLen-1];
+ if ((OpLen+1==OpPartLen) AND
+ (strncmp(OpPart,Op,OpLen)==0) AND
+ ((Ch=='A') OR (Ch=='B')))
+ BEGIN
+ for (z=ArgCnt; z>=1; z--) strcpy(ArgStr[z+1],ArgStr[z]);
+ ArgStr[1][0]=Ch; ArgStr[1][1]='\0';
+ OpPart[OpPartLen-1]='\0'; ArgCnt++;
+ END
+ return (Memo(Op));
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void MakeCode_68(void)
+BEGIN
+ int z;
+
+ CodeLen=0; DontPrint=False; PrefCnt=0; AdrCnt=0; OpSize=0;
+
+ /* Operandengroesse festlegen */
+
+ if (*AttrPart!='\0')
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B':OpSize=0; break;
+ case 'W':OpSize=1; break;
+ case 'L':OpSize=2; break;
+ case 'Q':OpSize=3; break;
+ case 'S':OpSize=4; break;
+ case 'D':OpSize=5; break;
+ case 'X':OpSize=6; break;
+ case 'P':OpSize=7; break;
+ default:
+ WrError(1107); return;
+ END
+
+ /* zu ignorierendes */
+
+ if (*OpPart=='\0') return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeMotoPseudo(True)) return;
+ if (DecodeMoto16Pseudo(OpSize,True)) return;
+
+ /* gehashtes */
+
+ if (LookupInstTable(InstTable,OpPart)) return;
+
+ /* Anweisungen ohne Argument */
+
+ /* Sonderfall : XGDX hat anderen Code bei 6301 !!!! */
+
+ if ((MomCPU==CPU6301) AND (Memo("XGDX")))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x18;
+ END
+ return;
+ END
+
+ for (z=0; z<ALU8OrderCnt; z++)
+ if (SplitAcc(ALU8Orders[z].Name))
+ BEGIN
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(2,ArgCnt,((ALU8Orders[z].MayImm)?MModImm:0)+MModInd+MModExt+MModDir);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[PrefCnt]=
+ ALU8Orders[z].Code+(AdrPart << 4);
+ DecodeAdr(1,1,1);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[PrefCnt]+=AdrPart << 6;
+ CodeLen=PrefCnt+1+AdrCnt;
+ memcpy(BAsmCode+1+PrefCnt,AdrVals,AdrCnt);
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Sing8OrderCnt; z++)
+ if (SplitAcc(Sing8Orders[z].Name))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(1,ArgCnt,MModAcc+MModExt+MModInd);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CodeLen=PrefCnt+1+AdrCnt;
+ BAsmCode[PrefCnt]=Sing8Orders[z].Code+(AdrPart << 4);
+ memcpy(BAsmCode+1+PrefCnt,AdrVals,AdrCnt);
+ END
+ END
+ return;
+ END
+
+ if ((SplitAcc("PSH")) OR (SplitAcc("PUL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(1,1,MModAcc);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x32+AdrPart;
+ if (Memo("PSH")) BAsmCode[0]+=4;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_68(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_68()
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_68(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x61; NOPCode=0x01;
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_68; IsDef=IsDef_68;
+ SwitchFrom=SwitchFrom_68; InitFields();
+ AddMoto16PseudoONOFF();
+
+ SetFlag(&DoPadding,DoPaddingName,False);
+END
+
+ void code68_init(void)
+BEGIN
+ CPU6800=AddCPU("6800",SwitchTo_68);
+ CPU6301=AddCPU("6301",SwitchTo_68);
+ CPU6811=AddCPU("6811",SwitchTo_68);
+END
diff --git a/code68.h b/code68.h
new file mode 100644
index 0000000..865ea61
--- /dev/null
+++ b/code68.h
@@ -0,0 +1,11 @@
+/* code68.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator fuer 68xx-Prozessoren */
+/* */
+/* Historie: 13.8.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code68_init(void);
diff --git a/code6804.c b/code6804.c
new file mode 100644
index 0000000..966ff33
--- /dev/null
+++ b/code6804.c
@@ -0,0 +1,451 @@
+/* code6804.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codeenerator Motorola/ST 6804 */
+/* */
+/* Historie: 17.10.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ LongInt Code;
+ } BaseOrder;
+
+#define FixedOrderCnt 19
+#define RelOrderCnt 6
+#define ALUOrderCnt 4
+
+#define ModNone (-1)
+#define ModInd 0
+#define MModInd (1 << ModInd)
+#define ModDir 1
+#define MModDir (1 << ModDir)
+#define ModImm 2
+#define MModImm (1 << ModImm)
+
+static ShortInt AdrMode;
+static Byte AdrVal;
+
+static CPUVar CPU6804;
+
+static BaseOrder *FixedOrders;
+static BaseOrder *RelOrders;
+static BaseOrder *ALUOrders;
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, LongInt NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRel(char *NName, LongInt NCode)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU(char *NName, LongInt NCode)
+BEGIN
+ if (InstrZ>=ALUOrderCnt) exit(255);
+ ALUOrders[InstrZ].Name=NName;
+ ALUOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("CLRA", 0x00fbff);
+ AddFixed("CLRX", 0xb08000);
+ AddFixed("CLRY", 0xb08100);
+ AddFixed("COMA", 0x0000b4);
+ AddFixed("ROLA", 0x0000b5);
+ AddFixed("ASLA", 0x00faff);
+ AddFixed("INCA", 0x00feff);
+ AddFixed("INCX", 0x0000a8);
+ AddFixed("INCY", 0x0000a9);
+ AddFixed("DECA", 0x00ffff);
+ AddFixed("DECX", 0x0000b8);
+ AddFixed("DECY", 0x0000b9);
+ AddFixed("TAX" , 0x0000bc);
+ AddFixed("TAY" , 0x0000bd);
+ AddFixed("TXA" , 0x0000ac);
+ AddFixed("TYA" , 0x0000ad);
+ AddFixed("RTS" , 0x0000b3);
+ AddFixed("RTI" , 0x0000b2);
+ AddFixed("NOP" , 0x000020);
+
+ RelOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("BCC", 0x40);
+ AddRel("BHS", 0x40);
+ AddRel("BCS", 0x60);
+ AddRel("BLO", 0x60);
+ AddRel("BNE", 0x00);
+ AddRel("BEQ", 0x20);
+
+ ALUOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*ALUOrderCnt); InstrZ=0;
+ AddALU("ADD", 0x02);
+ AddALU("SUB", 0x03);
+ AddALU("CMP", 0x04);
+ AddALU("AND", 0x05);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(RelOrders);
+ free(ALUOrders);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void ChkAdr(Boolean MayImm)
+BEGIN
+ if ((AdrMode==ModImm) AND (NOT MayImm))
+ BEGIN
+ WrError(1350); AdrMode=ModNone;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Boolean MayImm)
+BEGIN
+ Boolean OK;
+
+ AdrMode=ModNone;
+
+ if (strcasecmp(Asc,"(X)")==0)
+ BEGIN
+ AdrMode=ModInd; AdrVal=0x00; ChkAdr(MayImm); return;
+ END
+ if (strcasecmp(Asc,"(Y)")==0)
+ BEGIN
+ AdrMode=ModInd; AdrVal=0x10; ChkAdr(MayImm); return;
+ END
+
+ if (*Asc=='#')
+ BEGIN
+ AdrVal=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK) AdrMode=ModImm; ChkAdr(MayImm); return;
+ END
+
+ AdrVal=EvalIntExpression(Asc,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrMode=ModDir; ChkAdr(MayImm); return;
+ END
+
+ ChkAdr(MayImm);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,0xff);
+ return True;
+ END
+
+ return False;
+END
+
+ static Boolean IsShort(Byte Adr)
+BEGIN
+ return ((Adr & 0xfc)==0x80);
+END
+
+ static void MakeCode_6804(void)
+BEGIN
+ int z;
+ Integer AdrInt;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeMotoPseudo(True)) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if Memo(FixedOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ if ((FixedOrders[z].Code >> 16)!=0) CodeLen=3;
+ else CodeLen=1+Ord(Hi(FixedOrders[z].Code)!=0);
+ if (CodeLen==3) BAsmCode[0]=FixedOrders[z].Code >> 16;
+ if (CodeLen>=2) BAsmCode[CodeLen-2]=Hi(FixedOrders[z].Code);
+ BAsmCode[CodeLen-1]=Lo(FixedOrders[z].Code);
+ END
+ return;
+ END
+
+ /* relative/absolute Spruenge */
+
+ for (z=0; z<RelOrderCnt; z++)
+ if Memo(RelOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK)-(EProgCounter()+1);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-16) OR (AdrInt>15))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=RelOrders[z].Code+(AdrInt & 0x1f);
+ ChkSpace(SegCode);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JSR")) OR (Memo("JMP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt12,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; BAsmCode[1]=Lo(AdrInt);
+ BAsmCode[0]=0x80+(Ord(Memo("JMP")) << 4)+(Hi(AdrInt) & 15);
+ ChkSpace(SegCode);
+ END
+ END
+ return;
+ END
+
+ /* AKKU-Operationen */
+
+ for (z=0; z<ALUOrderCnt; z++)
+ if (Memo(ALUOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],True);
+ switch (AdrMode)
+ BEGIN
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0xe0+AdrVal+ALUOrders[z].Code;
+ break;
+ case ModDir:
+ CodeLen=2; BAsmCode[0]=0xf8+ALUOrders[z].Code; BAsmCode[1]=AdrVal;
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0xe8+ALUOrders[z].Code; BAsmCode[1]=AdrVal;
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if ((Memo("LDA")) OR (Memo("STA")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Memo("LDA"));
+ AdrInt=Ord(Memo("STA"));
+ switch (AdrMode)
+ BEGIN
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0xe0+AdrInt+AdrVal;
+ break;
+ case ModDir:
+ if (IsShort(AdrVal))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xac+(AdrInt << 4)+(AdrVal & 3);
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xf8+AdrInt; BAsmCode[1]=AdrVal;
+ END
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0xe8+AdrInt; BAsmCode[1]=AdrVal;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDXI")) OR (Memo("LDYI")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[1]+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xb0;
+ BAsmCode[1]=0x80+Ord(Memo("LDYI"));
+ END
+ END
+ return;
+ END
+
+ if (Memo("MVI"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*ArgStr[2]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegData);
+ BAsmCode[2]=EvalIntExpression(ArgStr[2]+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xb0; CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Read/Modify/Write-Operationen */
+
+ if ((Memo("INC")) OR (Memo("DEC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],False);
+ AdrInt=Ord(Memo("DEC"));
+ switch (AdrMode)
+ BEGIN
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0xe6+AdrInt+AdrVal;
+ break;
+ case ModDir:
+ if (IsShort(AdrVal))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xa8+(AdrInt << 4)+(AdrVal & 3);
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xfe + AdrInt; /* ANSI :-O */
+ BAsmCode[1]=AdrVal;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Bitbefehle */
+
+ if ((Memo("BSET")) OR (Memo("BCLR")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrVal=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xd0+(Ord(Memo("BSET")) << 3)+AdrVal;
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; ChkSpace(SegData);
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BRSET")) OR (Memo("BRCLR")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ AdrVal=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xc0+(Ord(Memo("BRSET")) << 3)+AdrVal;
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegData);
+ AdrInt=EvalIntExpression(ArgStr[3],Int16,&OK)-(EProgCounter()+3);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode); BAsmCode[2]=AdrInt & 0xff; CodeLen=3;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_6804(void)
+BEGIN
+ return (Memo("SFR"));
+END
+
+ static void SwitchFrom_6804(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_6804(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="PC"; HeaderID=0x64; NOPCode=0x20;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xfff;
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
+ SegLimits[SegData] = 0xff;
+
+ MakeCode=MakeCode_6804; IsDef=IsDef_6804;
+ SwitchFrom=SwitchFrom_6804; InitFields();
+END
+
+ void code6804_init(void)
+BEGIN
+ CPU6804=AddCPU("6804",SwitchTo_6804);
+END
diff --git a/code6804.h b/code6804.h
new file mode 100644
index 0000000..144f3dc
--- /dev/null
+++ b/code6804.h
@@ -0,0 +1,11 @@
+/* code6804.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codeenerator Motorola/ST 6804 */
+/* */
+/* Historie: 17.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code6804_init(void);
diff --git a/code6805.c b/code6805.c
new file mode 100644
index 0000000..1da6c30
--- /dev/null
+++ b/code6805.c
@@ -0,0 +1,786 @@
+/* code6805.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 68(HC)05/08 */
+/* */
+/* Historie: 9.10.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+
+#include "asmdef.h"
+#include "asmpars.h"
+#include "asmsub.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Byte Code;
+ } BaseOrder;
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Byte Code;
+ Word Mask;
+ ShortInt Size;
+ } ALUOrder;
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Byte Code;
+ Word Mask;
+ } RMWOrder;
+
+#define FixedOrderCnt 52
+#define RelOrderCnt 23
+#define ALUOrderCnt 19
+#define RMWOrderCnt 12
+
+#define ModNone (-1)
+#define ModImm 0
+#define MModImm (1 << ModImm)
+#define ModDir 1
+#define MModDir (1 << ModDir)
+#define ModExt 2
+#define MModExt (1 << ModExt)
+#define ModIx2 3
+#define MModIx2 (1 << ModIx2)
+#define ModIx1 4
+#define MModIx1 (1 << ModIx1)
+#define ModIx 5
+#define MModIx (1 << ModIx)
+#define ModSP2 6
+#define MModSP2 (1 << ModSP2)
+#define ModSP1 7
+#define MModSP1 (1 << ModSP1)
+#define ModIxP 8
+#define MModIxP (1 << ModIxP)
+#define MMod05 (MModImm+MModDir+MModExt+MModIx2+MModIx1+MModIx)
+#define MMod08 (MModSP2+MModSP1+MModIxP)
+
+static ShortInt AdrMode,OpSize;
+static Byte AdrVals[2];
+
+static CPUVar CPU6805,CPU6808;
+
+static BaseOrder *FixedOrders;
+static BaseOrder *RelOrders;
+static RMWOrder *RMWOrders;
+static ALUOrder *ALUOrders;
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, CPUVar NMin, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].MinCPU=NMin;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRel(char *NName, CPUVar NMin, Byte NCode)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ].MinCPU=NMin;
+ RelOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU(char *NName, CPUVar NMin, Byte NCode, Word NMask, ShortInt NSize)
+BEGIN
+ if (InstrZ>=ALUOrderCnt) exit(255);
+ ALUOrders[InstrZ].Name=NName;
+ ALUOrders[InstrZ].MinCPU=NMin;
+ ALUOrders[InstrZ].Code=NCode;
+ ALUOrders[InstrZ].Mask=NMask;
+ ALUOrders[InstrZ++].Size=NSize;
+END
+
+ static void AddRMW(char *NName, CPUVar NMin, Byte NCode ,Word NMask)
+BEGIN
+ if (InstrZ>=RMWOrderCnt) exit(255);
+ RMWOrders[InstrZ].Name=NName;
+ RMWOrders[InstrZ].MinCPU=NMin;
+ RMWOrders[InstrZ].Code=NCode;
+ RMWOrders[InstrZ++].Mask=NMask;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("RTI" ,CPU6805,0x80); AddFixed("RTS" ,CPU6805,0x81);
+ AddFixed("SWI" ,CPU6805,0x83); AddFixed("TAX" ,CPU6805,0x97);
+ AddFixed("CLC" ,CPU6805,0x98); AddFixed("SEC" ,CPU6805,0x99);
+ AddFixed("CLI" ,CPU6805,0x9a); AddFixed("SEI" ,CPU6805,0x9b);
+ AddFixed("RSP" ,CPU6805,0x9c); AddFixed("NOP" ,CPU6805,0x9d);
+ AddFixed("TXA" ,CPU6805,0x9f); AddFixed("NEGA",CPU6805,0x40);
+ AddFixed("NEGX",CPU6805,0x50); AddFixed("COMA",CPU6805,0x43);
+ AddFixed("COMX",CPU6805,0x53); AddFixed("LSRA",CPU6805,0x44);
+ AddFixed("LSRX",CPU6805,0x54); AddFixed("RORA",CPU6805,0x46);
+ AddFixed("RORX",CPU6805,0x56); AddFixed("ASRA",CPU6805,0x47);
+ AddFixed("ASRX",CPU6805,0x57); AddFixed("ASLA",CPU6805,0x48);
+ AddFixed("ASLX",CPU6805,0x58); AddFixed("LSLA",CPU6805,0x48);
+ AddFixed("LSLX",CPU6805,0x58); AddFixed("ROLA",CPU6805,0x49);
+ AddFixed("ROLX",CPU6805,0x59); AddFixed("DECA",CPU6805,0x4a);
+ AddFixed("DECX",CPU6805,0x5a); AddFixed("INCA",CPU6805,0x4c);
+ AddFixed("INCX",CPU6805,0x5c); AddFixed("TSTA",CPU6805,0x4d);
+ AddFixed("TSTX",CPU6805,0x5d); AddFixed("CLRA",CPU6805,0x4f);
+ AddFixed("CLRX",CPU6805,0x5f); AddFixed("CLRH",CPU6808,0x8c);
+ AddFixed("DAA" ,CPU6808,0x72); AddFixed("DIV" ,CPU6808,0x52);
+ AddFixed("MUL" ,CPU6805,0x42); AddFixed("NSA" ,CPU6808,0x62);
+ AddFixed("PSHA",CPU6808,0x87); AddFixed("PSHH",CPU6808,0x8b);
+ AddFixed("PSHX",CPU6808,0x89); AddFixed("PULA",CPU6808,0x86);
+ AddFixed("PULH",CPU6808,0x8a); AddFixed("PULX",CPU6808,0x88);
+ AddFixed("STOP",CPU6805,0x8e); AddFixed("TAP" ,CPU6808,0x84);
+ AddFixed("TPA" ,CPU6808,0x85); AddFixed("TSX" ,CPU6808,0x95);
+ AddFixed("TXS" ,CPU6808,0x94); AddFixed("WAIT",CPU6805,0x8f);
+
+ RelOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("BRA" ,CPU6805,0x20); AddRel("BRN" ,CPU6805,0x21);
+ AddRel("BHI" ,CPU6805,0x22); AddRel("BLS" ,CPU6805,0x23);
+ AddRel("BCC" ,CPU6805,0x24); AddRel("BCS" ,CPU6805,0x25);
+ AddRel("BNE" ,CPU6805,0x26); AddRel("BEQ" ,CPU6805,0x27);
+ AddRel("BHCC",CPU6805,0x28); AddRel("BHCS",CPU6805,0x29);
+ AddRel("BPL" ,CPU6805,0x2a); AddRel("BMI" ,CPU6805,0x2b);
+ AddRel("BMC" ,CPU6805,0x2c); AddRel("BMS" ,CPU6805,0x2d);
+ AddRel("BIL" ,CPU6805,0x2e); AddRel("BIH" ,CPU6805,0x2f);
+ AddRel("BSR" ,CPU6805,0xad); AddRel("BGE" ,CPU6808,0x90);
+ AddRel("BGT" ,CPU6808,0x92); AddRel("BHS" ,CPU6805,0x24);
+ AddRel("BLE" ,CPU6808,0x93); AddRel("BLO" ,CPU6805,0x25);
+ AddRel("BLT" ,CPU6808,0x91);
+
+ ALUOrders=(ALUOrder *) malloc(sizeof(ALUOrder)*ALUOrderCnt); InstrZ=0;
+ AddALU("SUB" ,CPU6805,0x00,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("CMP" ,CPU6805,0x01,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("SBC" ,CPU6805,0x02,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("CPX" ,CPU6805,0x03,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("AND" ,CPU6805,0x04,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("BIT" ,CPU6805,0x05,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("LDA" ,CPU6805,0x06,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("STA" ,CPU6805,0x07, MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("EOR" ,CPU6805,0x08,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("ADC" ,CPU6805,0x09,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("ORA" ,CPU6805,0x0a,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("ADD" ,CPU6805,0x0b,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("JMP" ,CPU6805,0x0c, MModDir+MModExt+MModIx+MModIx1+MModIx2 ,-1);
+ AddALU("JSR" ,CPU6805,0x0d, MModDir+MModExt+MModIx+MModIx1+MModIx2 ,-1);
+ AddALU("LDX" ,CPU6805,0x0e,MModImm+MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("STX" ,CPU6805,0x0f, MModDir+MModExt+MModIx+MModIx1+MModIx2+MModSP1+MModSP2,0);
+ AddALU("CPHX",CPU6808,0xc5,MModImm+MModDir ,1);
+ AddALU("LDHX",CPU6808,0xa5,MModImm+MModDir ,1);
+ AddALU("STHX",CPU6808,0x85, MModDir ,1);
+
+ RMWOrders=(RMWOrder *) malloc(sizeof(RMWOrder)*RMWOrderCnt); InstrZ=0;
+ AddRMW("NEG",CPU6805,0x00,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("COM",CPU6805,0x03,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("LSR",CPU6805,0x04,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("ROR",CPU6805,0x06,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("ASR",CPU6805,0x07,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("ASL",CPU6805,0x08,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("LSL",CPU6805,0x08,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("ROL",CPU6805,0x09,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("DEC",CPU6805,0x0a,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("INC",CPU6805,0x0c,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("TST",CPU6805,0x0d,MModDir+ MModIx+MModIx1+ MModSP1 );
+ AddRMW("CLR",CPU6805,0x0f,MModDir+ MModIx+MModIx1+ MModSP1 );
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(RelOrders);
+ free(ALUOrders);
+ free(RMWOrders);
+END
+
+/*--------------------------------------------------------------------------*/
+
+
+ static void ChkZero(char *s, char *serg, Byte *Erg)
+BEGIN
+ if (*s=='<')
+ BEGIN
+ strcpy(serg,s+1); *Erg=2;
+ END
+ else if (*s=='>')
+ BEGIN
+ strcpy(serg,s+1); *Erg=1;
+ END
+ else
+ BEGIN
+ strcpy(serg,s); *Erg=0;
+ END
+END
+
+ static void ChkAdr(Word Mask, Word Mask08)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ WrError( (((1 << AdrMode) AND Mask08)==0) ? 1350 : 1505);
+ AdrMode=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(Byte Start, Byte Stop, Word Mask)
+BEGIN
+ Boolean OK;
+ Word AdrWord,Mask08;
+ Byte ZeroMode;
+ String s;
+ ShortInt tmode1,tmode2;
+
+ AdrMode=ModNone; AdrCnt=0;
+
+ Mask08=Mask & MMod08;
+ if (MomCPU==CPU6805) Mask&=MMod05;
+
+ if (Stop-Start==1)
+ BEGIN
+ if (strcasecmp(ArgStr[Stop],"X")==0)
+ BEGIN
+ tmode1=ModIx1; tmode2=ModIx2;
+ END
+ else if (strcasecmp(ArgStr[Stop],"SP")==0)
+ BEGIN
+ tmode1=ModSP1; tmode2=ModSP2;
+ if (MomCPU<CPU6808)
+ BEGIN
+ WrXError(1445,ArgStr[Stop]); ChkAdr(Mask,Mask08); return;
+ END
+ END
+ else
+ BEGIN
+ WrXError(1445,ArgStr[Stop]); ChkAdr(Mask,Mask08); return;
+ END
+
+ ChkZero(ArgStr[Start],s,&ZeroMode);
+ FirstPassUnknown=False;
+ AdrWord=EvalIntExpression(s,(ZeroMode==2)?Int8:Int16,&OK);
+
+ if (OK)
+ BEGIN
+ if ((ZeroMode==0) AND (AdrWord==0) AND (Mask AND MModIx!=0) AND (tmode1==ModIx1)) AdrMode=ModIx;
+
+ else if (((Mask AND (1 << tmode2))==0) OR (ZeroMode==2) OR ((ZeroMode==0) AND (Hi(AdrWord)==0)))
+ BEGIN
+ if (FirstPassUnknown) AdrWord&=0xff;
+ if (Hi(AdrWord)!=0) WrError(1340);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]=Lo(AdrWord); AdrMode=tmode1;
+ END
+ END
+
+ else
+ BEGIN
+ AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ AdrCnt=2; AdrMode=tmode2;
+ END
+ END
+ END
+
+ else if (Stop==Start)
+ BEGIN
+ /* Postinkrement */
+
+ if (strcasecmp(ArgStr[Start],"X+")==0)
+ BEGIN
+ AdrMode=ModIxP; ChkAdr(Mask,Mask08); return;
+ END
+
+ /* X-indirekt */
+
+ if (strcasecmp(ArgStr[Start],"X")==0)
+ BEGIN
+ AdrMode=ModIx; ChkAdr(Mask,Mask08); return;
+ END
+
+ /* immediate */
+
+ if (*ArgStr[Start]=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1132); break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(ArgStr[Start]+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrMode=ModImm;
+ END
+ break;
+ case 1:
+ AdrWord=EvalIntExpression(ArgStr[Start]+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ AdrCnt=2; AdrMode=ModImm;
+ END
+ break;
+ END
+ ChkAdr(Mask,Mask08); return;
+ END
+
+ /* absolut */
+
+ ChkZero(ArgStr[Start],s,&ZeroMode);
+ FirstPassUnknown=False;
+ AdrWord=EvalIntExpression(s,(ZeroMode==2)?UInt8:UInt16,&OK);
+
+ if (OK)
+ BEGIN
+ if (((Mask & MModExt)==0) OR (ZeroMode==2) OR ((ZeroMode==0) AND (Hi(AdrWord)==0)))
+ BEGIN
+ if (FirstPassUnknown) AdrWord&=0xff;
+ if (Hi(AdrWord)!=0) WrError(1340);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]=Lo(AdrWord); AdrMode=ModDir;
+ END
+ END
+ else
+ BEGIN
+ AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ AdrCnt=2; AdrMode=ModExt;
+ END
+ ChkAdr(Mask,Mask08); return;
+ END
+ END
+
+ else WrError(1110);
+
+
+ ChkAdr(Mask,Mask08);
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void MakeCode_6805(void)
+BEGIN
+ int z;
+ Integer AdrInt;
+ Boolean OK;
+ char ch;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeMotoPseudo(True)) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<FixedOrders[z].MinCPU) WrXError(1500,OpPart);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU6808) WrXError(1500,OpPart);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(1,1,MModImm+MModDir+MModIxP);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[1]=AdrVals[0]; DecodeAdr(2,2,MModDir);
+ if (AdrMode==ModDir)
+ BEGIN
+ BAsmCode[0]=0x6e; BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ END
+ break;
+ case ModDir:
+ BAsmCode[1]=AdrVals[0]; DecodeAdr(2,2,MModDir+MModIxP);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0]=0x4e; BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModIxP:
+ BAsmCode[0]=0x5e; CodeLen=2;
+ break;
+ END
+ break;
+ case ModIxP:
+ DecodeAdr(2,2,MModDir);
+ if (AdrMode==ModDir)
+ BEGIN
+ BAsmCode[0]=0x7e; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ /* relative Spruenge */
+
+ for (z=0; z<RelOrderCnt; z++)
+ if Memo(RelOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<RelOrders[z].MinCPU) WrXError(1500,OpPart);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=RelOrders[z].Code; BAsmCode[1]=Lo(AdrInt);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CBEQA")) OR (Memo("CBEQX")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU6808) WrXError(1500,OpPart);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(1,1,MModImm);
+ if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[1]=AdrVals[0];
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+3);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x41+(Ord(Memo("CBEQX")) << 4);
+ BAsmCode[2]=AdrInt & 0xff;
+ CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CBEQ"))
+ BEGIN
+ if (MomCPU<CPU6808) WrXError(1500,OpPart);
+ else if (ArgCnt==2)
+ BEGIN
+ DecodeAdr(1,1,MModDir+MModIxP);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0]=0x31; BAsmCode[1]=AdrVals[0]; z=3;
+ break;
+ case ModIxP:
+ BAsmCode[0]=0x71; z=2;
+ break;
+ END;
+ if (AdrMode!=ModNone)
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+z);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[z-1]=AdrInt & 0xff; CodeLen=z;
+ END
+ END
+ END
+ else if (ArgCnt==3)
+ BEGIN
+ OK=True;
+ if (strcasecmp(ArgStr[2],"X+")==0) z=3;
+ else if (strcasecmp(ArgStr[2],"SP")==0)
+ BEGIN
+ BAsmCode[0]=0x9e; z=4;
+ END
+ else
+ BEGIN
+ WrXError(1445,ArgStr[2]); OK=False;
+ END
+ if (OK)
+ BEGIN
+ BAsmCode[z-3]=0x61;
+ BAsmCode[z-2]=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if (OK)
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[3],UInt16,&OK)-(EProgCounter()+z);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[z-1]=AdrInt & 0xff; CodeLen=z;
+ END
+ END
+ END
+ END
+ else WrError(1110);
+ return;
+ END
+
+ if ((Memo("DBNZA")) OR (Memo("DBNZX")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU6808) WrXError(1500,OpPart);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x4b+(Ord(Memo("DBNZX")) << 4);
+ BAsmCode[1]=AdrInt & 0xff;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if (Memo("DBNZ"))
+ BEGIN
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else if (MomCPU<CPU6808) WrXError(1500,OpPart);
+ else
+ BEGIN
+ DecodeAdr(1,ArgCnt-1,MModDir+MModIx+MModIx1+MModSP1);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0]=0x3b; BAsmCode[1]=AdrVals[0]; z=3;
+ break;
+ case ModIx:
+ BAsmCode[0]=0x7b; z=2;
+ break;
+ case ModIx1:
+ BAsmCode[0]=0x6b; BAsmCode[1]=AdrVals[0]; z=3;
+ break;
+ case ModSP1:
+ BAsmCode[0]=0x9e; BAsmCode[1]=0x6b; BAsmCode[2]=AdrVals[0]; z=4;
+ break;
+ END
+ if (AdrMode!=ModNone)
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[ArgCnt],UInt16,&OK)-(EProgCounter()+z);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[z-1]=AdrInt & 0xff; CodeLen=z;
+ END
+ END
+ END
+ return;
+ END
+
+ /* ALU-Operationen */
+
+ for (z=0; z<ALUOrderCnt; z++)
+ if Memo(ALUOrders[z].Name)
+ BEGIN
+ if (MomCPU<ALUOrders[z].MinCPU) WrXError(1500,OpPart);
+ else
+ BEGIN
+ OpSize=ALUOrders[z].Size;
+ DecodeAdr(1,ArgCnt,ALUOrders[z].Mask);
+ if (AdrMode!=ModNone)
+ BEGIN
+ switch (AdrMode)
+ BEGIN
+ case ModImm :
+ BAsmCode[0]=0xa0+ALUOrders[z].Code; CodeLen=1;
+ break;
+ case ModDir :
+ BAsmCode[0]=0xb0+ALUOrders[z].Code; CodeLen=1;
+ break;
+ case ModExt :
+ BAsmCode[0]=0xc0+ALUOrders[z].Code; CodeLen=1;
+ break;
+ case ModIx :
+ BAsmCode[0]=0xf0+ALUOrders[z].Code; CodeLen=1;
+ break;
+ case ModIx1 :
+ BAsmCode[0]=0xe0+ALUOrders[z].Code; CodeLen=1;
+ break;
+ case ModIx2 :
+ BAsmCode[0]=0xd0+ALUOrders[z].Code; CodeLen=1;
+ break;
+ case ModSP1 :
+ BAsmCode[0]=0x9e; BAsmCode[1]=0xe0+ALUOrders[z].Code; CodeLen=2;
+ break;
+ case ModSP2 :
+ BAsmCode[0]=0x9e; BAsmCode[1]=0xd0+ALUOrders[z].Code; CodeLen=2;
+ break;
+ END
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt); CodeLen+=AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("AIX")) OR (Memo("AIS")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU6808) WrXError(1500,OpPart);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1]+1,SInt8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xa7+(Ord(Memo("AIX")) << 3); CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ /* Read/Modify/Write-Operationen */
+
+ for (z=0; z<RMWOrderCnt; z++)
+ if Memo(RMWOrders[z].Name)
+ BEGIN
+ if (MomCPU<RMWOrders[z].MinCPU) WrXError(1500,OpPart);
+ else
+ BEGIN
+ DecodeAdr(1,ArgCnt,RMWOrders[z].Mask);
+ if (AdrMode!=ModNone)
+ BEGIN
+ switch (AdrMode)
+ BEGIN
+ case ModDir :
+ BAsmCode[0]=0x30+RMWOrders[z].Code; CodeLen=1;
+ break;
+ case ModIx :
+ BAsmCode[0]=0x70+RMWOrders[z].Code; CodeLen=1;
+ break;
+ case ModIx1 :
+ BAsmCode[0]=0x60+RMWOrders[z].Code; CodeLen=1;
+ break;
+ case ModSP1 :
+ BAsmCode[0]=0x9e; BAsmCode[1]=0x60+RMWOrders[z].Code; CodeLen=2;
+ break;
+ END
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt); CodeLen+=AdrCnt;
+ END
+ END
+ return;
+ END
+
+ ch=OpPart[strlen(OpPart)-1];
+ if ((ch>='0') AND (ch<='7'))
+ BEGIN
+ for (z=ArgCnt; z>=1; z--) strcpy(ArgStr[z+1],ArgStr[z]);
+ *ArgStr[1]=ch; ArgStr[1][1]='\0'; ArgCnt++;
+ OpPart[strlen(OpPart)-1]='\0';
+ END
+
+ if ((Memo("BSET")) OR (Memo("BCLR")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x10+(BAsmCode[0] << 1)+Ord(Memo("BCLR"));
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BRSET")) OR (Memo("BRCLR")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[3],UInt16,&OK)-(EProgCounter()+3);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=(BAsmCode[0] << 1)+Ord(Memo("BRCLR"));
+ BAsmCode[2]=Lo(AdrInt);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_6805(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_6805(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_6805(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x62; NOPCode=0x9d;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0x1fff;
+
+ MakeCode=MakeCode_6805; IsDef=IsDef_6805;
+ SwitchFrom=SwitchFrom_6805; InitFields();
+END
+
+ void code6805_init(void)
+BEGIN
+ CPU6805=AddCPU("6805",SwitchTo_6805);
+ CPU6808=AddCPU("68HC08",SwitchTo_6805);
+END
diff --git a/code6805.h b/code6805.h
new file mode 100644
index 0000000..7e19fd5
--- /dev/null
+++ b/code6805.h
@@ -0,0 +1,11 @@
+/* code6805.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 68(HC)05/08 */
+/* */
+/* Historie: 9.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code6805_init(void);
diff --git a/code6809.c b/code6809.c
new file mode 100644
index 0000000..36b3311
--- /dev/null
+++ b/code6809.c
@@ -0,0 +1,1318 @@
+/* code6809.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 6809/6309 */
+/* */
+/* Historie: 10.10.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "bpemu.h"
+
+#include "asmdef.h"
+#include "asmpars.h"
+#include "asmsub.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ CPUVar MinCPU;
+ } BaseOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Boolean Inv;
+ CPUVar MinCPU;
+ } FlagOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code8;
+ Word Code16;
+ CPUVar MinCPU;
+ } RelOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Byte Op16;
+ Boolean MayImm;
+ CPUVar MinCPU;
+ } ALUOrder;
+
+#define ModNone (-1)
+#define ModImm 1
+#define ModDir 2
+#define ModInd 3
+#define ModExt 4
+
+#define FixedOrderCnt 73
+#define RelOrderCnt 19
+#define ALUOrderCnt 65
+#define ALU2OrderCnt 8
+#define RMWOrderCnt 13
+#define FlagOrderCnt 3
+#define LEAOrderCnt 4
+#define ImmOrderCnt 4
+#define StackOrderCnt 4
+#define BitOrderCnt 8
+
+#define StackRegCnt 11
+static char StackRegNames[StackRegCnt][4]=
+ {"CCR","A","B","DPR","X","Y","S/U","PC","CC","DP","S"};
+static Byte StackRegCodes[StackRegCnt]=
+ { 0, 1, 2, 3, 4, 5, 6, 7, 0, 3, 6};
+
+static char *FlagChars="CVZNIHFE";
+
+static ShortInt AdrMode;
+static Byte AdrVals[5];
+static Byte OpSize;
+static Boolean ExtFlag;
+static LongInt DPRValue;
+
+static BaseOrder *FixedOrders;
+static RelOrder *RelOrders;
+static ALUOrder *ALUOrders;
+static char **ALU2Orders;
+static BaseOrder *RMWOrders;
+static FlagOrder *FlagOrders;
+static BaseOrder *LEAOrders;
+static BaseOrder *ImmOrders;
+static BaseOrder *StackOrders;
+static char **BitOrders;
+
+static SimpProc SaveInitProc;
+
+static CPUVar CPU6809,CPU6309;
+
+/*-------------------------------------------------------------------------*/
+/* Erzeugung/Aufloesung Codetabellen*/
+
+ static void AddFixed(char *NName, Word NCode, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ++].MinCPU=NCPU;
+END
+
+ static void AddRel(char *NName, Word NCode8, Word NCode16)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ].Code8=NCode8;
+ RelOrders[InstrZ++].Code16=NCode16;
+END
+
+ static void AddALU(char *NName, Word NCode, Byte NSize, Boolean NImm, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=ALUOrderCnt) exit(255);
+ ALUOrders[InstrZ].Name=NName;
+ ALUOrders[InstrZ].Code=NCode;
+ ALUOrders[InstrZ].Op16=NSize;
+ ALUOrders[InstrZ].MayImm=NImm;
+ ALUOrders[InstrZ++].MinCPU=NCPU;
+END
+
+ static void AddRMW(char *NName, Word NCode, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=RMWOrderCnt) exit(255);
+ RMWOrders[InstrZ].Name=NName;
+ RMWOrders[InstrZ].Code=NCode;
+ RMWOrders[InstrZ++].MinCPU=NCPU;
+END
+
+ static void AddFlag(char *NName, Word NCode, Boolean NInv, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=FlagOrderCnt) exit(255);
+ FlagOrders[InstrZ].Name=NName;
+ FlagOrders[InstrZ].Code=NCode;
+ FlagOrders[InstrZ].Inv=NInv;
+ FlagOrders[InstrZ++].MinCPU=NCPU;
+END
+
+ static void AddLEA(char *NName, Word NCode, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=LEAOrderCnt) exit(255);
+ LEAOrders[InstrZ].Name=NName;
+ LEAOrders[InstrZ].Code=NCode;
+ LEAOrders[InstrZ++].MinCPU=NCPU;
+END
+
+ static void AddImm(char *NName, Word NCode, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=ImmOrderCnt) exit(255);
+ ImmOrders[InstrZ].Name=NName;
+ ImmOrders[InstrZ].Code=NCode;
+ ImmOrders[InstrZ++].MinCPU=NCPU;
+END
+
+ static void AddStack(char *NName, Word NCode, CPUVar NCPU)
+BEGIN
+ if (InstrZ>=StackOrderCnt) exit(255);
+ StackOrders[InstrZ].Name=NName;
+ StackOrders[InstrZ].Code=NCode;
+ StackOrders[InstrZ++].MinCPU=NCPU;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("NOP" ,0x0012,CPU6809); AddFixed("SYNC" ,0x0013,CPU6809);
+ AddFixed("DAA" ,0x0019,CPU6809); AddFixed("SEX" ,0x001d,CPU6809);
+ AddFixed("RTS" ,0x0039,CPU6809); AddFixed("ABX" ,0x003a,CPU6809);
+ AddFixed("RTI" ,0x003b,CPU6809); AddFixed("MUL" ,0x003d,CPU6809);
+ AddFixed("SWI2" ,0x103f,CPU6809); AddFixed("SWI3" ,0x113f,CPU6809);
+ AddFixed("NEGA" ,0x0040,CPU6809); AddFixed("COMA" ,0x0043,CPU6809);
+ AddFixed("LSRA" ,0x0044,CPU6809); AddFixed("RORA" ,0x0046,CPU6809);
+ AddFixed("ASRA" ,0x0047,CPU6809); AddFixed("ASLA" ,0x0048,CPU6809);
+ AddFixed("LSLA" ,0x0048,CPU6809); AddFixed("ROLA" ,0x0049,CPU6809);
+ AddFixed("DECA" ,0x004a,CPU6809); AddFixed("INCA" ,0x004c,CPU6809);
+ AddFixed("TSTA" ,0x004d,CPU6809); AddFixed("CLRA" ,0x004f,CPU6809);
+ AddFixed("NEGB" ,0x0050,CPU6809); AddFixed("COMB" ,0x0053,CPU6809);
+ AddFixed("LSRB" ,0x0054,CPU6809); AddFixed("RORB" ,0x0056,CPU6809);
+ AddFixed("ASRB" ,0x0057,CPU6809); AddFixed("ASLB" ,0x0058,CPU6809);
+ AddFixed("LSLB" ,0x0058,CPU6809); AddFixed("ROLB" ,0x0059,CPU6809);
+ AddFixed("DECB" ,0x005a,CPU6809); AddFixed("INCB" ,0x005c,CPU6809);
+ AddFixed("TSTB" ,0x005d,CPU6809); AddFixed("CLRB" ,0x005f,CPU6809);
+ AddFixed("PSHSW",0x1038,CPU6309); AddFixed("PULSW",0x1039,CPU6309);
+ AddFixed("PSHUW",0x103a,CPU6309); AddFixed("PULUW",0x103b,CPU6309);
+ AddFixed("SEXW" ,0x0014,CPU6309); AddFixed("NEGD" ,0x1040,CPU6309);
+ AddFixed("COMD" ,0x1043,CPU6309); AddFixed("LSRD" ,0x1044,CPU6309);
+ AddFixed("RORD" ,0x1046,CPU6309); AddFixed("ASRD" ,0x1047,CPU6309);
+ AddFixed("ASLD" ,0x1048,CPU6309); AddFixed("LSLD" ,0x1048,CPU6309);
+ AddFixed("ROLD" ,0x1049,CPU6309); AddFixed("DECD" ,0x104a,CPU6309);
+ AddFixed("INCD" ,0x104c,CPU6309); AddFixed("TSTD" ,0x104d,CPU6309);
+ AddFixed("CLRD" ,0x104f,CPU6309); AddFixed("COMW" ,0x1053,CPU6309);
+ AddFixed("LSRW" ,0x1054,CPU6309); AddFixed("RORW" ,0x1056,CPU6309);
+ AddFixed("ROLW" ,0x1059,CPU6309); AddFixed("DECW" ,0x105a,CPU6309);
+ AddFixed("INCW" ,0x105c,CPU6309); AddFixed("TSTW" ,0x105d,CPU6309);
+ AddFixed("CLRW" ,0x105f,CPU6309); AddFixed("COME" ,0x1143,CPU6309);
+ AddFixed("DECE" ,0x114a,CPU6309); AddFixed("INCE" ,0x114c,CPU6309);
+ AddFixed("TSTE" ,0x114d,CPU6309); AddFixed("CLRE" ,0x114f,CPU6309);
+ AddFixed("COMF" ,0x1153,CPU6309); AddFixed("DECF" ,0x115a,CPU6309);
+ AddFixed("INCF" ,0x115c,CPU6309); AddFixed("TSTF" ,0x115d,CPU6309);
+ AddFixed("CLRF" ,0x115f,CPU6309); AddFixed("CLRS" ,0x1fd4,CPU6309);
+ AddFixed("CLRV" ,0x1fd7,CPU6309); AddFixed("CLRX" ,0x1fd1,CPU6309);
+ AddFixed("CLRY" ,0x1fd2,CPU6309);
+
+ RelOrders=(RelOrder *) malloc(sizeof(RelOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("BRA",0x0020,0x0016); AddRel("BRN",0x0021,0x1021);
+ AddRel("BHI",0x0022,0x1022); AddRel("BLS",0x0023,0x1023);
+ AddRel("BHS",0x0024,0x1024); AddRel("BCC",0x0024,0x1024);
+ AddRel("BLO",0x0025,0x1025); AddRel("BCS",0x0025,0x1025);
+ AddRel("BNE",0x0026,0x1026); AddRel("BEQ",0x0027,0x1027);
+ AddRel("BVC",0x0028,0x1028); AddRel("BVS",0x0029,0x1029);
+ AddRel("BPL",0x002a,0x102a); AddRel("BMI",0x002b,0x102b);
+ AddRel("BGE",0x002c,0x102c); AddRel("BLT",0x002d,0x102d);
+ AddRel("BGT",0x002e,0x102e); AddRel("BLE",0x002f,0x102f);
+ AddRel("BSR",0x008d,0x0017);
+
+ ALUOrders=(ALUOrder *) malloc(sizeof(ALUOrder)*ALUOrderCnt); InstrZ=0;
+ AddALU("LDA" ,0x0086,0,True ,CPU6809);
+ AddALU("STA" ,0x0087,0,False,CPU6809);
+ AddALU("CMPA",0x0081,0,True ,CPU6809);
+ AddALU("ADDA",0x008b,0,True ,CPU6809);
+ AddALU("ADCA",0x0089,0,True ,CPU6809);
+ AddALU("SUBA",0x0080,0,True ,CPU6809);
+ AddALU("SBCA",0x0082,0,True ,CPU6809);
+ AddALU("ANDA",0x0084,0,True ,CPU6809);
+ AddALU("ORA" ,0x008a,0,True ,CPU6809);
+ AddALU("EORA",0x0088,0,True ,CPU6809);
+ AddALU("BITA",0x0085,0,True ,CPU6809);
+
+ AddALU("LDB" ,0x00c6,0,True ,CPU6809);
+ AddALU("STB" ,0x00c7,0,False,CPU6809);
+ AddALU("CMPB",0x00c1,0,True ,CPU6809);
+ AddALU("ADDB",0x00cb,0,True ,CPU6809);
+ AddALU("ADCB",0x00c9,0,True ,CPU6809);
+ AddALU("SUBB",0x00c0,0,True ,CPU6809);
+ AddALU("SBCB",0x00c2,0,True ,CPU6809);
+ AddALU("ANDB",0x00c4,0,True ,CPU6809);
+ AddALU("ORB" ,0x00ca,0,True ,CPU6809);
+ AddALU("EORB",0x00c8,0,True ,CPU6809);
+ AddALU("BITB",0x00c5,0,True ,CPU6809);
+
+ AddALU("LDD" ,0x00cc,1,True ,CPU6809);
+ AddALU("STD" ,0x00cd,1,False,CPU6809);
+ AddALU("CMPD",0x1083,1,True ,CPU6809);
+ AddALU("ADDD",0x00c3,1,True ,CPU6809);
+ AddALU("ADCD",0x1089,1,True ,CPU6309);
+ AddALU("SUBD",0x0083,1,True ,CPU6809);
+ AddALU("SBCD",0x1082,1,True ,CPU6309);
+ AddALU("MULD",0x118f,1,True ,CPU6309);
+ AddALU("DIVD",0x118d,1,True ,CPU6309);
+ AddALU("ANDD",0x1084,1,True ,CPU6309);
+ AddALU("ORD" ,0x108a,1,True ,CPU6309);
+ AddALU("EORD",0x1088,1,True ,CPU6309);
+ AddALU("BITD",0x1085,1,True ,CPU6309);
+
+ AddALU("LDW" ,0x1086,1,True ,CPU6309);
+ AddALU("STW" ,0x1087,1,False,CPU6309);
+ AddALU("CMPW",0x1081,1,True ,CPU6309);
+ AddALU("ADDW",0x108b,1,True ,CPU6309);
+ AddALU("SUBW",0x1080,1,True ,CPU6309);
+
+ AddALU("STQ" ,0x10cd,1,True ,CPU6309);
+ AddALU("DIVQ",0x118e,1,True ,CPU6309);
+
+ AddALU("LDE" ,0x1186,0,True ,CPU6309);
+ AddALU("STE" ,0x1187,0,False,CPU6309);
+ AddALU("CMPE",0x1181,0,True ,CPU6309);
+ AddALU("ADDE",0x118b,0,True ,CPU6309);
+ AddALU("SUBE",0x1180,0,True ,CPU6309);
+
+ AddALU("LDF" ,0x11c6,0,True ,CPU6309);
+ AddALU("STF" ,0x11c7,0,False,CPU6309);
+ AddALU("CMPF",0x11c1,0,True ,CPU6309);
+ AddALU("ADDF",0x11cb,0,True ,CPU6309);
+ AddALU("SUBF",0x11c0,0,True ,CPU6309);
+
+ AddALU("LDX" ,0x008e,1,True ,CPU6809);
+ AddALU("STX" ,0x008f,1,False,CPU6809);
+ AddALU("CMPX",0x008c,1,True ,CPU6809);
+
+ AddALU("LDY" ,0x108e,1,True ,CPU6809);
+ AddALU("STY" ,0x108f,1,False,CPU6809);
+ AddALU("CMPY",0x108c,1,True ,CPU6809);
+
+ AddALU("LDU" ,0x00ce,1,True ,CPU6809);
+ AddALU("STU" ,0x00cf,1,False,CPU6809);
+ AddALU("CMPU",0x1183,1,True ,CPU6809);
+
+ AddALU("LDS" ,0x10ce,1,True ,CPU6809);
+ AddALU("STS" ,0x10cf,1,False,CPU6809);
+ AddALU("CMPS",0x118c,1,True ,CPU6809);
+
+ AddALU("JSR" ,0x008d,1,False,CPU6809);
+
+ ALU2Orders=(char **) malloc(sizeof(char *)*ALU2OrderCnt);
+ ALU2Orders[0]="ADD"; ALU2Orders[1]="ADC";
+ ALU2Orders[2]="SUB"; ALU2Orders[3]="SBC";
+ ALU2Orders[4]="AND"; ALU2Orders[5]="OR" ;
+ ALU2Orders[6]="EOR"; ALU2Orders[7]="CMP";
+
+ RMWOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*RMWOrderCnt); InstrZ=0;
+ AddRMW("NEG",0x00,CPU6809);
+ AddRMW("COM",0x03,CPU6809);
+ AddRMW("LSR",0x04,CPU6809);
+ AddRMW("ROR",0x06,CPU6809);
+ AddRMW("ASR",0x07,CPU6809);
+ AddRMW("ASL",0x08,CPU6809);
+ AddRMW("LSL",0x08,CPU6809);
+ AddRMW("ROL",0x09,CPU6809);
+ AddRMW("DEC",0x0a,CPU6809);
+ AddRMW("INC",0x0c,CPU6809);
+ AddRMW("TST",0x0d,CPU6809);
+ AddRMW("JMP",0x0e,CPU6809);
+ AddRMW("CLR",0x0f,CPU6809);
+
+ FlagOrders=(FlagOrder *) malloc(sizeof(FlagOrder)*FlagOrderCnt); InstrZ=0;
+ AddFlag("CWAI" ,0x3c,True ,CPU6809);
+ AddFlag("ANDCC",0x1c,True ,CPU6809);
+ AddFlag("ORCC" ,0x1a,False,CPU6809);
+
+ LEAOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*LEAOrderCnt); InstrZ=0;
+ AddLEA("LEAX",0x30,CPU6809);
+ AddLEA("LEAY",0x31,CPU6809);
+ AddLEA("LEAS",0x32,CPU6809);
+ AddLEA("LEAU",0x33,CPU6809);
+
+ ImmOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*ImmOrderCnt); InstrZ=0;
+ AddImm("AIM",0x02,CPU6309);
+ AddImm("OIM",0x01,CPU6309);
+ AddImm("EIM",0x05,CPU6309);
+ AddImm("TIM",0x0b,CPU6309);
+
+ StackOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*StackOrderCnt); InstrZ=0;
+ AddStack("PSHS",0x34,CPU6809);
+ AddStack("PULS",0x35,CPU6809);
+ AddStack("PSHU",0x36,CPU6809);
+ AddStack("PULU",0x37,CPU6809);
+
+ BitOrders=(char **) malloc(sizeof(char *)*BitOrderCnt);
+ BitOrders[0]="BAND"; BitOrders[1]="BIAND";
+ BitOrders[2]="BOR"; BitOrders[3]="BIOR" ;
+ BitOrders[4]="BEOR"; BitOrders[5]="BIEOR";
+ BitOrders[6]="LDBT"; BitOrders[7]="STBT" ;
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(RelOrders);
+ free(ALUOrders);
+ free(ALU2Orders);
+ free(RMWOrders);
+ free(FlagOrders);
+ free(LEAOrders);
+ free(ImmOrders);
+ free(StackOrders);
+ free(BitOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+
+
+ static Boolean CodeReg(char *ChIn, Byte *erg)
+BEGIN
+ static char Regs[5]="XYUS",*p;
+
+ if (strlen(ChIn)!=1) return False;
+ else
+ BEGIN
+ p=strchr(Regs,toupper(*ChIn));
+ if (p==Nil) return False;
+ *erg=p-Regs; return True;
+ END
+END
+
+ static void ChkZero(char *s, Byte *Erg)
+BEGIN
+ if (*s=='>')
+ BEGIN
+ strcpy(s,s+1); *Erg=1;
+ END
+ else if (*s=='<')
+ BEGIN
+ strcpy(s,s+1); *Erg=2;
+ if (*s=='<')
+ BEGIN
+ strcpy(s,s+1); *Erg=3;
+ END
+ END
+ else *Erg=0;
+END
+
+ static Boolean MayShort(Integer Arg)
+BEGIN
+ return ((Arg>=-128) AND (Arg<127));
+END
+
+ static void DecodeAdr(void)
+BEGIN
+ String Asc,LAsc,temp;
+ LongInt AdrLong;
+ Word AdrWord;
+ Boolean IndFlag,OK;
+ Byte EReg,ZeroMode;
+ char *p;
+ Integer AdrInt;
+
+ AdrMode=ModNone; AdrCnt=0;
+ strmaxcpy(Asc,ArgStr[1],255); strmaxcpy(LAsc,ArgStr[ArgCnt],255);
+
+ /* immediate */
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case 2:
+ AdrLong=EvalIntExpression(Asc+1,Int32,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=Lo(AdrLong >> 24);
+ AdrVals[1]=Lo(AdrLong >> 16);
+ AdrVals[2]=Lo(AdrLong >> 8);
+ AdrVals[3]=Lo(AdrLong);
+ AdrCnt=4;
+ END
+ break;
+ case 1:
+ AdrWord=EvalIntExpression(Asc+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ AdrCnt=2;
+ END
+ break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK) AdrCnt=1;
+ break;
+ END
+ if (OK) AdrMode=ModImm;
+ return;
+ END
+
+ /* indirekter Ausdruck ? */
+
+ if ((*Asc=='[') AND (Asc[strlen(Asc)-1]==']'))
+ BEGIN
+ IndFlag=True; strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ ArgCnt=0;
+ while (*Asc!='\0')
+ BEGIN
+ ArgCnt++;
+ p=QuotPos(Asc,',');
+ if (p!=Nil)
+ BEGIN
+ *p='\0'; strmaxcpy(ArgStr[ArgCnt],Asc,255); strcpy(Asc,p+1);
+ END
+ else
+ BEGIN
+ strmaxcpy(ArgStr[ArgCnt],Asc,255); *Asc='\0';
+ END
+ END
+ strmaxcpy(Asc,ArgStr[1],255); strmaxcpy(LAsc,ArgStr[ArgCnt],255);
+ END
+ else IndFlag=False;
+
+ /* Predekrement ? */
+
+ if ((ArgCnt>=1) AND (ArgCnt<=2) AND (strlen(LAsc)==2) AND (*LAsc=='-') AND (CodeReg(LAsc+1,&EReg)))
+ BEGIN
+ if ((ArgCnt==2) AND (*Asc!='\0')) WrError(1350);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]=0x82+(EReg << 5)+(Ord(IndFlag) << 4);
+ AdrMode=ModInd;
+ END
+ return;
+ END
+
+ if ((ArgCnt>=1) AND (ArgCnt<=2) AND (strlen(LAsc)==3) AND (strncmp(LAsc,"--",2)==0) AND (CodeReg(LAsc+2,&EReg)))
+ BEGIN
+ if ((ArgCnt==2) AND (*Asc!='\0')) WrError(1350);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]=0x83+(EReg << 5)+(Ord(IndFlag) << 4);
+ AdrMode=ModInd;
+ END
+ return;
+ END
+
+ if ((ArgCnt>=1) AND (ArgCnt<=2) AND (strcasecmp(LAsc,"--W")==0))
+ BEGIN
+ if ((ArgCnt==2) AND (*Asc!='\0')) WrError(1350);
+ else if (MomCPU<CPU6309) WrError(1505);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]=0xef+Ord(IndFlag);
+ AdrMode=ModInd;
+ END
+ return;
+ END
+
+ /* Postinkrement ? */
+
+ if ((ArgCnt>=1) AND (ArgCnt<=2) AND (strlen(LAsc)==2) AND (LAsc[1]=='+'))
+ BEGIN
+ temp[0]=(*LAsc); temp[1]='\0';
+ if (CodeReg(temp,&EReg))
+ BEGIN
+ if ((ArgCnt==2) AND (*Asc!='\0')) WrError(1350);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]=0x80+(EReg << 5)+(Ord(IndFlag) << 4);
+ AdrMode=ModInd;
+ END
+ return;
+ END
+ END
+
+ if ((ArgCnt>=1) AND (ArgCnt<=2) AND (strlen(LAsc)==3) AND (strncmp(LAsc+1,"++",2)==0))
+ BEGIN
+ temp[0]=(*LAsc); temp[1]='\0';
+ if (CodeReg(temp,&EReg))
+ BEGIN
+ if ((ArgCnt==2) AND (*Asc!='\0')) WrError(1350);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]=0x81+(EReg << 5)+(Ord(IndFlag) << 4);
+ AdrMode=ModInd;
+ END
+ return;
+ END
+ END
+
+ if ((ArgCnt>=1) AND (ArgCnt<=2) AND (strcasecmp(LAsc,"W++")==0))
+ BEGIN
+ if ((ArgCnt==2) AND (*Asc!='\0')) WrError(1350);
+ else if (MomCPU<CPU6309) WrError(1505);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]=0xcf+Ord(IndFlag);
+ AdrMode=ModInd;
+ END
+ return;
+ END
+
+ /* 16-Bit-Register (mit Index) ? */
+
+ if ((ArgCnt<=2) AND (ArgCnt>=1) AND (CodeReg(LAsc,&EReg)))
+ BEGIN
+ AdrVals[0]=(EReg << 5)+(Ord(IndFlag) << 4);
+
+ /* nur 16-Bit-Register */
+
+ if (ArgCnt==1)
+ BEGIN
+ AdrCnt=1; AdrVals[0]+=0x84;
+ AdrMode=ModInd; return;
+ END
+
+ /* mit Index */
+
+ if (strcasecmp(Asc,"A")==0)
+ BEGIN
+ AdrCnt=1; AdrVals[0]+=0x86;
+ AdrMode=ModInd; return;
+ END
+ if (strcasecmp(Asc,"B")==0)
+ BEGIN
+ AdrCnt=1; AdrVals[0]+=0x85;
+ AdrMode=ModInd; return;
+ END
+ if (strcasecmp(Asc,"D")==0)
+ BEGIN
+ AdrCnt=1; AdrVals[0]+=0x8b;
+ AdrMode=ModInd; return;
+ END
+ if ((strcasecmp(Asc,"E")==0) AND (MomCPU>=CPU6309))
+ BEGIN
+ if (EReg!=0) WrError(1350);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]+=0x87; AdrMode=ModInd;
+ END
+ return;
+ END
+ if ((strcasecmp(Asc,"F")==0) AND (MomCPU>=CPU6309))
+ BEGIN
+ if (EReg!=0) WrError(1350);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]+=0x8a; AdrMode=ModInd;
+ END
+ return;
+ END
+ if ((strcasecmp(Asc,"W")==0) AND (MomCPU>=CPU6309))
+ BEGIN
+ if (EReg!=0) WrError(1350);
+ else
+ BEGIN
+ AdrCnt=1; AdrVals[0]+=0x8e; AdrMode=ModInd;
+ END
+ return;
+ END
+
+ /* Displacement auswerten */
+
+ ChkZero(Asc,&ZeroMode);
+ if (ZeroMode>1)
+ BEGIN
+ AdrInt=EvalIntExpression(Asc,Int8,&OK);
+ if ((FirstPassUnknown) AND (ZeroMode==3)) AdrInt&=0x0f;
+ END
+ else
+ AdrInt=EvalIntExpression(Asc,Int16,&OK);
+
+ /* Displacement 0 ? */
+
+ if ((ZeroMode==0) AND (AdrInt==0))
+ BEGIN
+ AdrCnt=1; AdrVals[0]+=0x84;
+ AdrMode=ModInd; return;
+ END
+
+ /* 5-Bit-Displacement */
+
+ else if ((ZeroMode==3) OR ((ZeroMode==0) AND (NOT IndFlag) AND (AdrInt>=-16) AND (AdrInt<=15)))
+ BEGIN
+ if ((AdrInt<-16) OR (AdrInt>15)) WrError(1340);
+ else if (IndFlag) WrError(1350);
+ else
+ BEGIN
+ AdrMode=ModInd;
+ AdrCnt=1; AdrVals[0]+=AdrInt & 0x1f;
+ END
+ return;
+ END
+
+ /* 8-Bit-Displacement */
+
+ else if ((ZeroMode==2) OR ((ZeroMode==0) AND (MayShort(AdrInt))))
+ BEGIN
+ if (NOT MayShort(AdrInt)) WrError(1340);
+ else
+ BEGIN
+ AdrMode=ModInd;
+ AdrCnt=2; AdrVals[0]+=0x88; AdrVals[1]=Lo(AdrInt);
+ END;
+ return;
+ END
+
+ /* 16-Bit-Displacement */
+
+ else
+ BEGIN
+ AdrMode=ModInd;
+ AdrCnt=3; AdrVals[0]+=0x89;
+ AdrVals[1]=Hi(AdrInt); AdrVals[2]=Lo(AdrInt);
+ return;
+ END
+ END
+
+ if ((ArgCnt<=2) AND (ArgCnt>=1) AND (MomCPU>=CPU6309) AND (strcasecmp(ArgStr[ArgCnt],"W")==0))
+ BEGIN
+ AdrVals[0]=0x8f+Ord(IndFlag);
+
+ /* nur W-Register */
+
+ if (ArgCnt==1)
+ BEGIN
+ AdrCnt=1; AdrMode=ModInd; return;
+ END
+
+ /* Displacement auswerten */
+ ChkZero(Asc,&ZeroMode);
+ AdrInt=EvalIntExpression(Asc,Int16,&OK);
+
+ /* Displacement 0 ? */
+
+ if ((ZeroMode==0) AND (AdrInt==0))
+ BEGIN
+ AdrCnt=1; AdrMode=ModInd; return;
+ END
+
+ /* 16-Bit-Displacement */
+
+ else
+ BEGIN
+ AdrMode=ModInd;
+ AdrCnt=3; AdrVals[0]+=0x20;
+ AdrVals[1]=Hi(AdrInt); AdrVals[2]=Lo(AdrInt);
+ return;
+ END
+ END
+
+ /* PC-relativ ? */
+
+ if ((ArgCnt==2) AND ((strcasecmp(ArgStr[2],"PCR")==0) OR (strcasecmp(ArgStr[2],"PC")==0)))
+ BEGIN
+ AdrVals[0]=Ord(IndFlag) << 4;
+ ChkZero(Asc,&ZeroMode);
+ AdrInt=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrInt-=EProgCounter()+3+Ord(ExtFlag);
+
+ if (ZeroMode==3) WrError(1350);
+
+ else if ((ZeroMode==2) OR ((ZeroMode==0) AND MayShort(AdrInt)))
+ BEGIN
+ if (NOT MayShort(AdrInt)) WrError(1320);
+ else
+ BEGIN
+ AdrCnt=2; AdrVals[0]+=0x8c;
+ AdrVals[1]=Lo(AdrInt);
+ AdrMode=ModInd;
+ END
+ END
+
+ else
+ BEGIN
+ AdrInt--;
+ AdrCnt=3; AdrVals[0]+=0x8d;
+ AdrVals[1]=Hi(AdrInt); AdrVals[2]=Lo(AdrInt);
+ AdrMode=ModInd;
+ END
+ END
+ return;
+ END
+
+ if (ArgCnt==1)
+ BEGIN
+ ChkZero(Asc,&ZeroMode);
+ FirstPassUnknown=False;
+ AdrInt=EvalIntExpression(Asc,Int16,&OK);
+ if ((FirstPassUnknown) AND (ZeroMode==2))
+ AdrInt=(AdrInt & 0xff)| (DPRValue << 8);
+
+ if (OK)
+ BEGIN
+ if (ZeroMode==3) WrError(1350);
+
+ else if ((ZeroMode==2) OR ((ZeroMode==0) AND (Hi(AdrInt)==DPRValue) AND (NOT IndFlag)))
+ BEGIN
+ if (IndFlag) WrError(1990);
+ else if (Hi(AdrInt)!=DPRValue) WrError(1340);
+ else
+ BEGIN
+ AdrCnt=1; AdrMode=ModDir; AdrVals[0]=Lo(AdrInt);
+ END
+ END
+
+ else
+ BEGIN
+ if (IndFlag)
+ BEGIN
+ AdrMode=ModInd; AdrCnt=3; AdrVals[0]=0x9f;
+ AdrVals[1]=Hi(AdrInt); AdrVals[2]=Lo(AdrInt);
+ END
+ else
+ BEGIN
+ AdrMode=ModExt; AdrCnt=2;
+ AdrVals[0]=Hi(AdrInt); AdrVals[1]=Lo(AdrInt);
+ END
+ END
+ END
+ return;
+ END
+
+ if (AdrMode==ModNone) WrError(1350);
+END
+
+ static Boolean CodeCPUReg(char *Asc, Byte *Erg)
+BEGIN
+#define RegCnt 18
+ static char *RegNames[RegCnt]={"D","X","Y","U","S","SP","PC","W","V","A","B","CCR","DPR","CC","DP","Z","E","F"};
+ static Byte RegVals[RegCnt] ={0 ,1 ,2 ,3 ,4 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,10 ,11 ,13 ,14 ,15 };
+
+ int z;
+ String Asc_N;
+
+ strmaxcpy(Asc_N,Asc,255); NLS_UpString(Asc_N); Asc=Asc_N;
+
+ for (z=0; z<RegCnt; z++)
+ if (strcmp(Asc,RegNames[z])==0)
+ if (((RegVals[z] & 6)==6) AND (MomCPU<CPU6309)) WrError(1505);
+ else
+ BEGIN
+ *Erg=RegVals[z]; return True;
+ END
+ return False;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME09Count 1
+static ASSUMERec ASSUME09s[ASSUME09Count]=
+ {{"DPR", &DPRValue, 0, 0xff, 0x100}};
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME09s,ASSUME09Count);
+ return True;
+ END
+
+ return False;
+END
+
+ static void SplitPM(char *s, int *Erg)
+BEGIN
+ int l=strlen(s);
+
+ if (l==0) *Erg=0;
+ else if (s[l-1]=='+')
+ BEGIN
+ s[l-1]='\0'; *Erg=1;
+ END
+ else if (s[l-1]=='-')
+ BEGIN
+ s[l-1]='\0'; *Erg=(-1);
+ END
+ else *Erg=0;
+END
+
+ static Boolean SplitBit(char *Asc, int *Erg)
+BEGIN
+ char *p;
+ Boolean OK;
+
+ p=QuotPos(Asc,'.');
+ if (p==Nil)
+ BEGIN
+ WrError(1510); return False;
+ END
+ *Erg=EvalIntExpression(p+1,UInt3,&OK);
+ if (NOT OK) return False;
+ *p='\0';
+ return True;
+END
+
+ static void MakeCode_6809(void)
+BEGIN
+ char *p;
+ int z,z2,z3;
+ Integer AdrInt;
+ Boolean LongFlag,OK,Extent;
+
+ CodeLen=0; DontPrint=False; OpSize=0; ExtFlag=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeMotoPseudo(True)) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if Memo(FixedOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<FixedOrders[z].MinCPU) WrError(1500);
+ else if (Hi(FixedOrders[z].Code)==0)
+ BEGIN
+ BAsmCode[0]=Lo(FixedOrders[z].Code); CodeLen=1;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=Hi(FixedOrders[z].Code);
+ BAsmCode[1]=Lo(FixedOrders[z].Code); CodeLen=2;
+ END
+ return;
+ END;
+
+ /* Specials... */
+
+ if (Memo("SWI"))
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ BAsmCode[0]=0x3f; CodeLen=1;
+ END
+ else if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"2")==0)
+ BEGIN
+ BAsmCode[0]=0x10; BAsmCode[1]=0x3f; CodeLen=2;
+ END
+ else if (strcasecmp(ArgStr[1],"3")==0)
+ BEGIN
+ BAsmCode[0]=0x11; BAsmCode[1]=0x3f; CodeLen=2;
+ END
+ else WrError(1135);
+ return;
+ END
+
+ /* relative Spruenge */
+
+ for (z=0; z<RelOrderCnt; z++)
+ if ((Memo(RelOrders[z].Name)) OR ((*OpPart=='L') AND (strcmp(OpPart+1,RelOrders[z].Name)==0)))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ LongFlag=(*OpPart=='L'); ExtFlag=(LongFlag) AND (Hi(RelOrders[z].Code16)!=0);
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ BEGIN
+ AdrInt-=EProgCounter()+2+Ord(LongFlag)+Ord(ExtFlag);
+ if ((NOT SymbolQuestionable) AND (NOT LongFlag) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=1+Ord(ExtFlag);
+ if (LongFlag)
+ if (ExtFlag)
+ BEGIN
+ BAsmCode[0]=Hi(RelOrders[z].Code16); BAsmCode[1]=Lo(RelOrders[z].Code16);
+ END
+ else BAsmCode[0]=Lo(RelOrders[z].Code16);
+ else BAsmCode[0]=Lo(RelOrders[z].Code8);
+ if (LongFlag)
+ BEGIN
+ BAsmCode[CodeLen]=Hi(AdrInt); BAsmCode[CodeLen+1]=Lo(AdrInt);
+ CodeLen+=2;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=Lo(AdrInt);
+ CodeLen++;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* ALU-Operationen */
+
+ for (z=0; z<ALUOrderCnt; z++)
+ if Memo(ALUOrders[z].Name)
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (MomCPU<ALUOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ OpSize=ALUOrders[z].Op16; ExtFlag=(Hi(ALUOrders[z].Code)!=0);
+ DecodeAdr();
+ if (AdrMode!=ModNone)
+ if ((NOT ALUOrders[z].MayImm) AND (AdrMode==ModImm)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=Ord(ExtFlag)+1+AdrCnt;
+ if (ExtFlag) BAsmCode[0]=Hi(ALUOrders[z].Code);
+ BAsmCode[Ord(ExtFlag)]=Lo(ALUOrders[z].Code)+((AdrMode-1) << 4);
+ memcpy(BAsmCode+1+Ord(ExtFlag),AdrVals,AdrCnt);
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDQ"))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (MomCPU<CPU6309) WrError(1500);
+ else
+ BEGIN
+ OpSize=2;
+ DecodeAdr();
+ if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[0]=0xcd; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x10; BAsmCode[1]=0xcc+((AdrMode-1) << 4);
+ CodeLen=2+AdrCnt;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ END
+ END
+ return;
+ END
+
+ /* Read-Modify-Write-Operationen */
+
+ for (z=0; z<RMWOrderCnt; z++)
+ if Memo(RMWOrders[z].Name)
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (MomCPU<RMWOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr();
+ if (AdrMode!=ModNone)
+ if (AdrMode==ModImm) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1+AdrCnt;
+ switch (AdrMode)
+ BEGIN
+ case ModDir:BAsmCode[0]=RMWOrders[z].Code; break;
+ case ModInd:BAsmCode[0]=RMWOrders[z].Code+0x60; break;
+ case ModExt:BAsmCode[0]=RMWOrders[z].Code+0x70; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ END
+ END
+ return;
+ END
+
+ /* Anweisungen mit Flag-Operand */
+
+ for (z=0; z<FlagOrderCnt; z++)
+ if (Memo(FlagOrders[z].Name))
+ BEGIN
+ if (ArgCnt<1) WrError(1110);
+ else
+ BEGIN
+ OK=True;
+ if (FlagOrders[z].Inv) BAsmCode[1]=0xff; else BAsmCode[1]=0x00;
+ for (z2=1; z2<=ArgCnt; z2++)
+ if (OK)
+ BEGIN
+ p=(strlen(ArgStr[z2])==1)?strchr(FlagChars,toupper(*ArgStr[z2])):Nil;
+ if (p!=Nil)
+ BEGIN
+ z3=p-FlagChars;
+ if (FlagOrders[z].Inv) BAsmCode[1]&=(0xff^(1 << z3));
+ else BAsmCode[1]|=(1 << z3);
+ END
+ else if (*ArgStr[z2]!='#')
+ BEGIN
+ WrError(1120); OK=False;
+ END
+ else
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[z2]+1,Int8,&OK);
+ if (OK)
+ if (FlagOrders[z].Inv) BAsmCode[1]&=BAsmCode[2];
+ else BAsmCode[1]|=BAsmCode[2];
+ END
+ END
+ if (OK)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=FlagOrders[z].Code;
+ END
+ END
+ return;
+ END
+
+ /* Bit-Befehle */
+
+ for (z=0; z<ImmOrderCnt; z++)
+ if (Memo(ImmOrders[z].Name))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
+ else if (MomCPU<ImmOrders[z].MinCPU) WrError(1500);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1]+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ for (z2=1; z2<ArgCnt; z2++) strcpy(ArgStr[z2],ArgStr[z2+1]);
+ ArgCnt--; DecodeAdr();
+ if (AdrMode==ModImm) WrError(1350);
+ else
+ BEGIN
+ switch (AdrMode)
+ BEGIN
+ case ModDir:BAsmCode[0]=ImmOrders[z].Code; break;
+ case ModExt:BAsmCode[0]=ImmOrders[z].Code+0x70; break;
+ case ModInd:BAsmCode[0]=ImmOrders[z].Code+0x60; break;
+ END
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU6309) WrError(1500);
+ else
+ if (SplitBit(ArgStr[1],&z2))
+ if (SplitBit(ArgStr[2],&z3))
+ if (NOT CodeCPUReg(ArgStr[1],BAsmCode+2)) WrError(1980);
+ else if ((BAsmCode[2]<8) OR (BAsmCode[2]>11)) WrError(1980);
+ else
+ BEGIN
+ strcpy(ArgStr[1],ArgStr[2]); ArgCnt=1; DecodeAdr();
+ if (AdrMode!=ModDir) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[2]-=7;
+ if (BAsmCode[2]==3) BAsmCode[2]=0;
+ BAsmCode[0]=0x11; BAsmCode[1]=0x30+z;
+ BAsmCode[2]=(BAsmCode[2] << 6)+(z3 << 3)+z2;
+ BAsmCode[3]=AdrVals[0];
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ /* Register-Register-Operationen */
+
+ if ((Memo("TFR")) OR (Memo("TFM")) OR (Memo("EXG")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ SplitPM(ArgStr[1],&z2); SplitPM(ArgStr[2],&z3);
+ if ((z2!=0) OR (z3!=0))
+ BEGIN
+ if (Memo("EXG")) WrError(1350);
+ else if (NOT CodeCPUReg(ArgStr[1],BAsmCode+3)) WrError(1980);
+ else if (NOT CodeCPUReg(ArgStr[2],BAsmCode+2)) WrError(1980);
+ else if ((BAsmCode[2]<1) OR (BAsmCode[2]>4)) WrError(1980);
+ else if ((BAsmCode[3]<1) OR (BAsmCode[3]>4)) WrError(1980);
+ else
+ BEGIN
+ BAsmCode[0]=0x11; BAsmCode[1]=0;
+ BAsmCode[2]+=BAsmCode[3] << 4;
+ if ((z2==1) AND (z3==1)) BAsmCode[1]=0x38;
+ else if ((z2==-1) AND (z3==-1)) BAsmCode[1]=0x39;
+ else if ((z2== 1) AND (z3== 0)) BAsmCode[1]=0x3a;
+ else if ((z2== 0) AND (z3== 1)) BAsmCode[1]=0x3b;
+ if (BAsmCode[1]==0) WrError(1350); else CodeLen=3;
+ END
+ END
+ else if (Memo("TFM")) WrError(1350);
+ else if (NOT CodeCPUReg(ArgStr[1],BAsmCode+2)) WrError(1980);
+ else if (NOT CodeCPUReg(ArgStr[2],BAsmCode+1)) WrError(1980);
+ else if ((BAsmCode[1]!=13) AND (BAsmCode[2]!=13) AND /* Z-Register mit allen kompatibel */
+ (((BAsmCode[1] ^ BAsmCode[2]) & 0x08)!=0)) WrError(1131);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x1e + Ord(Memo("TFR"));
+ BAsmCode[1]+=BAsmCode[2] << 4;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ALU2OrderCnt; z++)
+ if ((strncmp(OpPart,ALU2Orders[z],strlen(ALU2Orders[z]))==0) AND ((OpPart[strlen(OpPart)]=='\0') OR (OpPart[strlen(OpPart)-1]=='R')))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT CodeCPUReg(ArgStr[1],BAsmCode+3)) WrError(1980);
+ else if (NOT CodeCPUReg(ArgStr[2],BAsmCode+2)) WrError(1980);
+ else if ((BAsmCode[1]!=13) AND (BAsmCode[2]!=13) AND /* Z-Register mit allen kompatibel */
+ (((BAsmCode[2] ^ BAsmCode[3]) & 0x08)!=0)) WrError(1131);
+ else
+ BEGIN
+ CodeLen=3;
+ BAsmCode[0]=0x10;
+ BAsmCode[1]=0x30+z;
+ BAsmCode[2]+=BAsmCode[3] << 4;
+ END
+ return;
+ END
+
+ /* Berechnung effektiver Adressen */
+
+ for (z=0; z<LEAOrderCnt; z++)
+ if Memo(LEAOrders[z].Name)
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr();
+ if (AdrMode!=ModNone)
+ if (AdrMode!=ModInd) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1+AdrCnt;
+ BAsmCode[0]=LEAOrders[z].Code;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ END;
+ END;
+ return;
+ END
+
+ /* Push/Pull */
+
+ for (z=0; z<StackOrderCnt; z++)
+ if Memo(StackOrders[z].Name)
+ BEGIN
+ BAsmCode[1]=0; OK=True; Extent=False;
+ /* S oder U einsetzen, entsprechend Opcode */
+ *StackRegNames[StackRegCnt-1]=
+ OpPart[strlen(OpPart)-1] ^ Ord('S') ^ Ord('U');
+ for (z2=1; z2<=ArgCnt; z2++)
+ if (OK)
+ BEGIN
+ if (strcasecmp(ArgStr[z2],"W")==0)
+ BEGIN
+ if (MomCPU<CPU6309)
+ BEGIN
+ WrError(1500); OK=False;
+ END
+ else if (ArgCnt!=1)
+ BEGIN
+ WrError(1335); OK=False;
+ END
+ else Extent=True;
+ END
+ else
+ BEGIN
+ for (z3=0; z3<StackRegCnt; z3++)
+ if (strcasecmp(ArgStr[z2],StackRegNames[z3])==0)
+ BEGIN
+ BAsmCode[1]|=(1 << StackRegCodes[z3]);
+ break;
+ END
+ if (z3>=StackRegCnt)
+ if (strcasecmp(ArgStr[z2],"ALL")==0) BAsmCode[1]=0xff;
+ else if (*ArgStr[z2]!='#') OK=False;
+ else
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[z2]+1,Int8,&OK);
+ if (OK) BAsmCode[1]|=BAsmCode[2];
+ END
+ END
+ END
+ if (OK)
+ if (Extent)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x10; BAsmCode[1]=StackOrders[z].Code+4;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=StackOrders[z].Code;
+ END
+ else WrError(1980);
+ return;
+ END
+
+ if ((Memo("BITMD")) OR (Memo("LDMD")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU6309) WrError(1500);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[1]+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x11;
+ BAsmCode[1]=0x3c+Ord(Memo("LDMD"));
+ CodeLen=3;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_6809()
+BEGIN
+ SaveInitProc();
+ DPRValue=0;
+END
+
+ static Boolean IsDef_6809(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_6809(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_6809(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x63; NOPCode=0x9d;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_6809; IsDef=IsDef_6809;
+
+ SwitchFrom=SwitchFrom_6809; InitFields();
+END
+
+ void code6809_init(void)
+BEGIN
+ CPU6809=AddCPU("6809",SwitchTo_6809);
+ CPU6309=AddCPU("6309",SwitchTo_6809);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_6809;
+END
diff --git a/code6809.h b/code6809.h
new file mode 100644
index 0000000..b5c3e2f
--- /dev/null
+++ b/code6809.h
@@ -0,0 +1,11 @@
+/* code6809.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 6809/6309 */
+/* */
+/* Historie: 10.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code6809_init(void);
diff --git a/code6812.c b/code6812.c
new file mode 100644
index 0000000..99117ef
--- /dev/null
+++ b/code6812.c
@@ -0,0 +1,1143 @@
+/* code6812.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul CPU12 */
+/* */
+/* Historie: 13.10.1996 Grundsteinlegung */
+/* 25.10.1998 dir. 16-Bit-Modus von ...11 auf ...10 korrigiert */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmpars.h"
+#include "asmsub.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Boolean MayImm,MayDir,MayExt;
+ ShortInt ThisOpSize;
+ } GenOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Boolean MayDir;
+ } JmpOrder;
+
+
+#define ModNone (-1)
+#define ModImm 0
+#define MModImm (1 << ModImm)
+#define ModDir 1
+#define MModDir (1 << ModDir)
+#define ModExt 2
+#define MModExt (1 << ModExt)
+#define ModIdx 3
+#define MModIdx (1 << ModIdx)
+#define ModIdx1 4
+#define MModIdx1 (1 << ModIdx1)
+#define ModIdx2 5
+#define MModIdx2 (1 << ModIdx2)
+#define ModDIdx 6
+#define MModDIdx (1 << ModDIdx)
+#define ModIIdx2 7
+#define MModIIdx2 (1 << ModIIdx2)
+
+#define MModAllIdx (MModIdx | MModIdx1 | MModIdx2 | MModDIdx | MModIIdx2)
+
+#define FixedOrderCount 87
+#define BranchOrderCount 20
+#define GenOrderCount 56
+#define LoopOrderCount 6
+#define LEAOrderCount 3
+#define JmpOrderCount 2
+
+static ShortInt OpSize;
+static ShortInt AdrMode;
+static ShortInt ExPos;
+static Byte AdrVals[4];
+static CPUVar CPU6812;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *BranchOrders;
+static GenOrder *GenOrders;
+static FixedOrder *LoopOrders;
+static FixedOrder *LEAOrders;
+static JmpOrder *JmpOrders;
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddBranch(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=BranchOrderCount) exit(255);
+ BranchOrders[InstrZ].Name=NName;
+ BranchOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddGen(char *NName, Word NCode,
+ Boolean NMayI, Boolean NMayD, Boolean NMayE,
+ ShortInt NSize)
+BEGIN
+ if (InstrZ>=GenOrderCount) exit(255);
+ GenOrders[InstrZ].Name=NName;
+ GenOrders[InstrZ].Code=NCode;
+ GenOrders[InstrZ].MayImm=NMayI;
+ GenOrders[InstrZ].MayDir=NMayD;
+ GenOrders[InstrZ].MayExt=NMayE;
+ GenOrders[InstrZ++].ThisOpSize=NSize;
+END
+
+ static void AddLoop(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=LoopOrderCount) exit(255);
+ LoopOrders[InstrZ].Name=NName;
+ LoopOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddLEA(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=LEAOrderCount) exit(255);
+ LEAOrders[InstrZ].Name=NName;
+ LEAOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddJmp(char *NName, Word NCode, Boolean NDir)
+BEGIN
+ if (InstrZ>=JmpOrderCount) exit(255);
+ JmpOrders[InstrZ].Name=NName;
+ JmpOrders[InstrZ].Code=NCode;
+ JmpOrders[InstrZ++].MayDir=NDir;
+END
+
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(FixedOrderCount*sizeof(FixedOrder)); InstrZ=0;
+ AddFixed("ABA" ,0x1806); AddFixed("ABX" ,0x1ae5);
+ AddFixed("ABY" ,0x19ed); AddFixed("ASLA" ,0x0048);
+ AddFixed("ASLB" ,0x0058); AddFixed("ASLD" ,0x0059);
+ AddFixed("ASRA" ,0x0047); AddFixed("ASRB" ,0x0057);
+ AddFixed("BGND" ,0x0000); AddFixed("CBA" ,0x1817);
+ AddFixed("CLC" ,0x10fe); AddFixed("CLI" ,0x10ef);
+ AddFixed("CLRA" ,0x0087); AddFixed("CLRB" ,0x00c7);
+ AddFixed("CLV" ,0x10fd); AddFixed("COMA" ,0x0041);
+ AddFixed("COMB" ,0x0051); AddFixed("DAA" ,0x1807);
+ AddFixed("DECA" ,0x0043); AddFixed("DECB" ,0x0053);
+ AddFixed("DES" ,0x1b9f); AddFixed("DEX" ,0x0009);
+ AddFixed("DEY" ,0x0003); AddFixed("EDIV" ,0x0011);
+ AddFixed("EDIVS",0x1814); AddFixed("EMUL" ,0x0013);
+ AddFixed("EMULS",0x1813); AddFixed("FDIV" ,0x1811);
+ AddFixed("IDIV" ,0x1810); AddFixed("IDIVS",0x1815);
+ AddFixed("INCA" ,0x0042); AddFixed("INCB" ,0x0052);
+ AddFixed("INS" ,0x1b81); AddFixed("INX" ,0x0008);
+ AddFixed("INY" ,0x0002); AddFixed("LSLA" ,0x0048);
+ AddFixed("LSLB" ,0x0058); AddFixed("LSLD" ,0x0059);
+ AddFixed("LSRA" ,0x0044); AddFixed("LSRB" ,0x0054);
+ AddFixed("LSRD" ,0x0049); AddFixed("MEM" ,0x0001);
+ AddFixed("MUL" ,0x0012); AddFixed("NEGA" ,0x0040);
+ AddFixed("NEGB" ,0x0050); AddFixed("NOP" ,0x00a7);
+ AddFixed("PSHA" ,0x0036); AddFixed("PSHB" ,0x0037);
+ AddFixed("PSHC" ,0x0039); AddFixed("PSHD" ,0x003b);
+ AddFixed("PSHX" ,0x0034); AddFixed("PSHY" ,0x0035);
+ AddFixed("PULA" ,0x0032); AddFixed("PULB" ,0x0033);
+ AddFixed("PULC" ,0x0038); AddFixed("PULD" ,0x003a);
+ AddFixed("PULX" ,0x0030); AddFixed("PULY" ,0x0031);
+ AddFixed("REV" ,0x183a); AddFixed("REVW" ,0x183b);
+ AddFixed("ROLA" ,0x0045); AddFixed("ROLB" ,0x0055);
+ AddFixed("RORA" ,0x0046); AddFixed("RORB" ,0x0056);
+ AddFixed("RTC" ,0x000a); AddFixed("RTI" ,0x000b);
+ AddFixed("RTS" ,0x003d); AddFixed("SBA" ,0x1816);
+ AddFixed("SEC" ,0x1401); AddFixed("SEI" ,0x1410);
+ AddFixed("SEV" ,0x1402); AddFixed("STOP" ,0x183e);
+ AddFixed("SWI" ,0x003f); AddFixed("TAB" ,0x180e);
+ AddFixed("TAP" ,0xb702); AddFixed("TBA" ,0x180f);
+ AddFixed("TPA" ,0xb720); AddFixed("TSTA" ,0x0097);
+ AddFixed("TSTB" ,0x00d7); AddFixed("TSX" ,0xb775);
+ AddFixed("TSY" ,0xb776); AddFixed("TXS" ,0xb757);
+ AddFixed("TYS" ,0xb767); AddFixed("WAI" ,0x003e);
+ AddFixed("WAV" ,0x183c); AddFixed("XGDX" ,0xb7c5);
+ AddFixed("XGDY" ,0xb7c6);
+
+ BranchOrders=(FixedOrder *) malloc(BranchOrderCount*sizeof(FixedOrder)); InstrZ=0;
+ AddBranch("BGT",0x2e); AddBranch("BGE",0x2c);
+ AddBranch("BEQ",0x27); AddBranch("BLE",0x2f);
+ AddBranch("BLT",0x2d); AddBranch("BHI",0x22);
+ AddBranch("BHS",0x24); AddBranch("BCC",0x24);
+ AddBranch("BNE",0x26); AddBranch("BLS",0x23);
+ AddBranch("BLO",0x25); AddBranch("BCS",0x25);
+ AddBranch("BMI",0x2b); AddBranch("BVS",0x29);
+ AddBranch("BRA",0x20); AddBranch("BPL",0x2a);
+ AddBranch("BGT",0x2e); AddBranch("BRN",0x21);
+ AddBranch("BVC",0x28); AddBranch("BSR",0x07);
+
+ GenOrders=(GenOrder *) malloc(sizeof(GenOrder)*GenOrderCount); InstrZ=0;
+ AddGen("ADCA" ,0x0089,True ,True ,True , 0);
+ AddGen("ADCB" ,0x00c9,True ,True ,True , 0);
+ AddGen("ADDA" ,0x008b,True ,True ,True , 0);
+ AddGen("ADDB" ,0x00cb,True ,True ,True , 0);
+ AddGen("ADDD" ,0x00c3,True ,True ,True , 1);
+ AddGen("ANDA" ,0x0084,True ,True ,True , 0);
+ AddGen("ANDB" ,0x00c4,True ,True ,True , 0);
+ AddGen("ASL" ,0x0048,False,False,True ,-1);
+ AddGen("ASR" ,0x0047,False,False,True ,-1);
+ AddGen("BITA" ,0x0085,True ,True ,True , 0);
+ AddGen("BITB" ,0x00c5,True ,True ,True , 0);
+ AddGen("CLR" ,0x0049,False,False,True ,-1);
+ AddGen("CMPA" ,0x0081,True ,True ,True , 0);
+ AddGen("CMPB" ,0x00c1,True ,True ,True , 0);
+ AddGen("COM" ,0x0041,False,False,True ,-1);
+ AddGen("CPD" ,0x008c,True ,True ,True , 1);
+ AddGen("CPS" ,0x008f,True ,True ,True , 1);
+ AddGen("CPX" ,0x008e,True ,True ,True , 1);
+ AddGen("CPY" ,0x008d,True ,True ,True , 1);
+ AddGen("DEC" ,0x0043,False,False,True ,-1);
+ AddGen("EMAXD",0x18fa,False,False,False,-1);
+ AddGen("EMAXM",0x18fe,False,False,False,-1);
+ AddGen("EMIND",0x18fb,False,False,False,-1);
+ AddGen("EMINM",0x18ff,False,False,False,-1);
+ AddGen("EORA" ,0x0088,True ,True ,True , 0);
+ AddGen("EORB" ,0x00c8,True ,True ,True , 0);
+ AddGen("INC" ,0x0042,False,False,True ,-1);
+ AddGen("LDAA" ,0x0086,True ,True ,True , 0);
+ AddGen("LDAB" ,0x00c6,True ,True ,True , 0);
+ AddGen("LDD" ,0x00cc,True ,True ,True , 1);
+ AddGen("LDS" ,0x00cf,True ,True ,True , 1);
+ AddGen("LDX" ,0x00ce,True ,True ,True , 1);
+ AddGen("LDY" ,0x00cd,True ,True ,True , 1);
+ AddGen("LSL" ,0x0048,False,False,True ,-1);
+ AddGen("LSR" ,0x0044,False,False,True ,-1);
+ AddGen("MAXA" ,0x18f8,False,False,False,-1);
+ AddGen("MAXM" ,0x18fc,False,False,False,-1);
+ AddGen("MINA" ,0x18f9,False,False,False,-1);
+ AddGen("MINM" ,0x18fd,False,False,False,-1);
+ AddGen("NEG" ,0x0040,False,False,True ,-1);
+ AddGen("ORAA" ,0x008a,True ,True ,True , 0);
+ AddGen("ORAB" ,0x00ca,True ,True ,True , 0);
+ AddGen("ROL" ,0x0045,False,False,True ,-1);
+ AddGen("ROR" ,0x0046,False,False,True ,-1);
+ AddGen("SBCA" ,0x0082,True ,True ,True , 0);
+ AddGen("SBCB" ,0x00c2,True ,True ,True , 0);
+ AddGen("STAA" ,0x004a,False,True ,True , 0);
+ AddGen("STAB" ,0x004b,False,True ,True , 0);
+ AddGen("STD" ,0x004c,False,True ,True ,-1);
+ AddGen("STS" ,0x004f,False,True ,True ,-1);
+ AddGen("STX" ,0x004e,False,True ,True ,-1);
+ AddGen("STY" ,0x004d,False,True ,True ,-1);
+ AddGen("SUBA" ,0x0080,True ,True ,True , 0);
+ AddGen("SUBB" ,0x00c0,True ,True ,True , 0);
+ AddGen("SUBD" ,0x0083,True ,True ,True , 1);
+ AddGen("TST" ,0x00c7,False,False,True ,-1);
+
+ LoopOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LoopOrderCount); InstrZ=0;
+ AddLoop("DBEQ",0x00); AddLoop("DBNE",0x20);
+ AddLoop("IBEQ",0x80); AddLoop("IBNE",0xa0);
+ AddLoop("TBEQ",0x40); AddLoop("TBNE",0x60);
+
+ LEAOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LEAOrderCount); InstrZ=0;
+ AddLEA("LEAS",0x1b);
+ AddLEA("LEAX",0x1a);
+ AddLEA("LEAY",0x19);
+
+ JmpOrders=(JmpOrder *) malloc(sizeof(JmpOrder)*JmpOrderCount); InstrZ=0;
+ AddJmp("JMP",0x06,False);
+ AddJmp("JSR",0x16,True);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(BranchOrders);
+ free(GenOrders);
+ free(LoopOrders);
+ free(LEAOrders);
+ free(JmpOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+#define PCReg 3
+
+ static Boolean DecodeReg16(char *Asc, Byte *Erg)
+BEGIN
+ *Erg=0xff;
+ if (strcasecmp(Asc,"X")==0) *Erg=0;
+ else if (strcasecmp(Asc,"Y")==0) *Erg=1;
+ else if (strcasecmp(Asc,"SP")==0) *Erg=2;
+ else if (strcasecmp(Asc,"PC")==0) *Erg=PCReg;
+ return (*Erg!=0xff);
+END
+
+ static Boolean ValidReg(char *Asc_o)
+BEGIN
+ Byte Dummy;
+ String Asc;
+ int l=strlen(Asc_o);
+
+ strmaxcpy(Asc,Asc_o,255);
+
+ if ((*Asc=='-') OR (*Asc=='+')) strcpy(Asc,Asc+1);
+ else if ((Asc[l-1]=='-') OR (Asc[l-1]=='+')) Asc[l-1]='\0';
+ return DecodeReg16(Asc,&Dummy);
+END
+
+ static Boolean DecodeReg8(char *Asc, Byte *Erg)
+BEGIN
+ *Erg=0xff;
+ if (strcasecmp(Asc,"A")==0) *Erg=0;
+ else if (strcasecmp(Asc,"B")==0) *Erg=1;
+ else if (strcasecmp(Asc,"D")==0) *Erg=2;
+ return (*Erg!=0xff);
+END
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg)
+BEGIN
+ if (DecodeReg8(Asc,Erg))
+ BEGIN
+ if (*Erg==2) *Erg=4; return True;
+ END
+ else if (DecodeReg16(Asc,Erg))
+ BEGIN
+ *Erg+=5; return (*Erg!=PCReg);
+ END
+ else if (strcasecmp(Asc,"CCR")==0)
+ BEGIN
+ *Erg=2; return True;
+ END
+ else return False;
+END
+
+ static void CutShort(char *Asc, Integer *ShortMode)
+BEGIN
+ if (*Asc=='>')
+ BEGIN
+ *ShortMode=1;
+ strcpy(Asc,Asc+1);
+ END
+ else if (*Asc=='<')
+ BEGIN
+ *ShortMode=2;
+ strcpy(Asc,Asc+1);
+ if (*Asc=='<')
+ BEGIN
+ *ShortMode=3;
+ strcpy(Asc,Asc+1);
+ END
+ END
+ else *ShortMode=0;
+END
+
+ static Boolean DistFits(Byte Reg, Integer Dist, Integer Offs, LongInt Min, LongInt Max)
+BEGIN
+ if (Reg==PCReg) Dist-=Offs;
+ return (((Dist>=Min) AND (Dist<=Max)) OR ((Reg==PCReg) AND SymbolQuestionable));
+END
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrMode!=ModNone) AND (((1 << AdrMode) & Mask)==0))
+ BEGIN
+ AdrMode=ModNone; AdrCnt=0; WrError(1350);
+ END
+END
+
+ static void DecodeAdr(int Start, int Stop, Word Mask)
+BEGIN
+ Integer AdrWord,ShortMode;
+ int l;
+ char *p;
+ Boolean OK;
+ Boolean DecFlag,AutoFlag,PostFlag;
+
+ AdrMode=ModNone; AdrCnt=0;
+
+ if (Stop-Start==0)
+ BEGIN
+
+ /* immediate */
+
+ if (*ArgStr[Start]=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case -1:WrError(1132); break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(ArgStr[Start]+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrMode=ModImm;
+ END
+ break;
+ case 1:
+ AdrWord=EvalIntExpression(ArgStr[Start]+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=AdrWord >> 8; AdrVals[1]=AdrWord & 0xff;
+ AdrCnt=2; AdrMode=ModImm;
+ END
+ break;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* indirekt */
+
+ if ((*ArgStr[Start]=='[') AND (ArgStr[Start][strlen(ArgStr[Start])-1]==']'))
+ BEGIN
+ strcpy(ArgStr[Start],ArgStr[Start]+1);
+ ArgStr[Start][strlen(ArgStr[Start])-1]='\0';
+ p=QuotPos(ArgStr[Start],','); if (p!=Nil) *p='\0';
+ if (p==Nil) WrError(1350);
+ else if (NOT DecodeReg16(p+1,AdrVals))
+ WrXError(1445,p+1);
+ else if (strcasecmp(ArgStr[Start],"D")==0)
+ BEGIN
+ AdrVals[0]=(AdrVals[0] << 3) | 0xe7;
+ AdrCnt=1; AdrMode=ModDIdx;
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[Start],Int16,&OK);
+ if (OK)
+ BEGIN
+ if (AdrVals[0]==PCReg) AdrWord-=EProgCounter()+ExPos+3;
+ AdrVals[0]=(AdrVals[0] << 3) | 0xe3;
+ AdrVals[1]=AdrWord >> 8;
+ AdrVals[2]=AdrWord & 0xff;
+ AdrCnt=3; AdrMode=ModIIdx2;
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* dann absolut */
+
+ CutShort(ArgStr[Start],&ShortMode);
+
+ if ((ShortMode==2) OR ((ShortMode==0) AND ((Mask & MModExt)==0)))
+ AdrWord=EvalIntExpression(ArgStr[Start],UInt8,&OK);
+ else
+ AdrWord=EvalIntExpression(ArgStr[Start],UInt16,&OK);
+
+ if (OK)
+ if ((ShortMode!=1) AND ((AdrWord & 0xff00)==0) AND ((Mask & MModDir)!=0))
+ BEGIN
+ AdrMode=ModDir; AdrVals[0]=AdrWord & 0xff; AdrCnt=1;
+ END
+ else
+ BEGIN
+ AdrMode=ModExt;
+ AdrVals[0]=(AdrWord >> 8) & 0xff; AdrVals[1]=AdrWord & 0xff;
+ AdrCnt=2;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ else if (Stop-Start==1)
+ BEGIN
+
+ /* Autoin/-dekrement abspalten */
+
+ l=strlen(ArgStr[Stop]);
+ if ((*ArgStr[Stop]=='-') OR (*ArgStr[Stop]=='+'))
+ BEGIN
+ DecFlag=(*ArgStr[Stop]=='-');
+ AutoFlag=True; PostFlag=False; strcpy(ArgStr[Stop],ArgStr[Stop]+1);
+ END
+ else if ((ArgStr[Stop][l-1]=='-') OR (ArgStr[Stop][l-1]=='+'))
+ BEGIN
+ DecFlag=(ArgStr[Stop][l-1]=='-');
+ AutoFlag=True; PostFlag=True; ArgStr[Stop][l-1]='\0';
+ END
+ else AutoFlag=DecFlag=PostFlag=False;
+
+ if (AutoFlag)
+ BEGIN
+ if (NOT DecodeReg16(ArgStr[Stop],AdrVals)) WrXError(1445,ArgStr[Stop]);
+ else if (AdrVals[0]==PCReg) WrXError(1445,ArgStr[Stop]);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrWord=EvalIntExpression(ArgStr[Start],SInt8,&OK);
+ if (FirstPassUnknown) AdrWord=1;
+ if (AdrWord==0)
+ BEGIN
+ AdrVals[0]=0; AdrCnt=1; AdrMode=ModIdx;
+ END
+ else if (AdrWord>8) WrError(1320);
+ else if (AdrWord<-8) WrError(1315);
+ else
+ BEGIN
+ if (AdrWord<0)
+ BEGIN
+ DecFlag=NOT DecFlag; AdrWord=(-AdrWord);
+ END
+ if (DecFlag) AdrWord=8-AdrWord; else AdrWord--;
+ AdrVals[0]=(AdrVals[0] << 6)+0x20+(Ord(PostFlag) << 4)+(Ord(DecFlag) << 3)+(AdrWord & 7);
+ AdrCnt=1; AdrMode=ModIdx;
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+
+ else
+ BEGIN
+ if (NOT DecodeReg16(ArgStr[Stop],AdrVals)) WrXError(1445,ArgStr[Stop]);
+ else if (DecodeReg8(ArgStr[Start],AdrVals+1))
+ BEGIN
+ AdrVals[0]=(AdrVals[0] << 3)+AdrVals[1]+0xe4;
+ AdrCnt=1; AdrMode=ModIdx;
+ END
+ else
+ BEGIN
+ CutShort(ArgStr[Start],&ShortMode);
+ AdrWord=EvalIntExpression(ArgStr[Start],Int16,&OK);
+ if (AdrVals[0]==PCReg) AdrWord-=EProgCounter()+ExPos;
+ if (OK)
+ if ((ShortMode!=1) AND (ShortMode!=2) AND ((Mask & MModIdx)!=0) AND (DistFits(AdrVals[0],AdrWord,1,-16,15)))
+ BEGIN
+ if (AdrVals[0]==PCReg) AdrWord--;
+ AdrVals[0]=(AdrVals[0] << 6)+(AdrWord & 0x1f);
+ AdrCnt=1; AdrMode=ModIdx;
+ END
+ else if ((ShortMode!=1) AND (ShortMode!=3) AND ((Mask & MModIdx1)!=0) AND DistFits(AdrVals[0],AdrWord,2,-256,255))
+ BEGIN
+ if (AdrVals[0]==PCReg) AdrWord-=2;
+ AdrVals[0]=0xe0+(AdrVals[0] << 3)+((AdrWord >> 8) & 1);
+ AdrVals[1]=AdrWord & 0xff;
+ AdrCnt=2; AdrMode=ModIdx1;
+ END
+ else
+ BEGIN
+ if (AdrVals[0]==PCReg) AdrWord-=3;
+ AdrVals[0]=0xe2+(AdrVals[0] << 3);
+ AdrVals[1]=(AdrWord >> 8) & 0xff;
+ AdrVals[2]=AdrWord & 0xff;
+ AdrCnt=3; AdrMode=ModIdx2;
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+ END
+
+ else WrError(1350);
+
+ ChkAdr(Mask);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void Try2Split(int Src)
+BEGIN
+ char *p;
+ int z;
+
+ KillPrefBlanks(ArgStr[Src]); KillPostBlanks(ArgStr[Src]);
+ p=ArgStr[Src]+strlen(ArgStr[Src])-1;
+ while ((p>=ArgStr[Src]) AND (NOT isspace(((unsigned int) *p)&0xff))) p--;
+ if (p>=ArgStr[Src])
+ BEGIN
+ for (z=ArgCnt; z>=Src; z--) strcpy(ArgStr[z+1],ArgStr[z]); ArgCnt++;
+ *p='\0'; strcpy(ArgStr[Src+1],p+1);
+ KillPostBlanks(ArgStr[Src]); KillPrefBlanks(ArgStr[Src+1]);
+ END
+END
+
+ static void MakeCode_6812(void)
+BEGIN
+ int z;
+ LongInt Address;
+ Byte HReg,HCnt;
+ Boolean OK;
+ Word Mask;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1);
+
+ /* Operandengroesse festlegen */
+
+ if (*AttrPart!='\0')
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B':OpSize=0; break;
+ case 'W':OpSize=1; break;
+ case 'L':OpSize=2; break;
+ case 'Q':OpSize=3; break;
+ case 'S':OpSize=4; break;
+ case 'D':OpSize=5; break;
+ case 'X':OpSize=6; break;
+ case 'P':OpSize=7; break;
+ default:
+ WrError(1107); return;
+ END
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeMotoPseudo(True)) return;
+ if (DecodeMoto16Pseudo(OpSize,True)) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if Memo(FixedOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ CodeLen=1+Ord(Hi(FixedOrders[z].Code)!=0);
+ if (CodeLen==2) BAsmCode[0]=Hi(FixedOrders[z].Code);
+ BAsmCode[CodeLen-1]=Lo(FixedOrders[z].Code);
+ END
+ return;
+ END
+
+ /* einfacher Adressoperand */
+
+ for (z=0; z<GenOrderCount; z++)
+ if Memo(GenOrders[z].Name)
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ ExPos=1+Ord(Hi(GenOrders[z].Code)!=0); OpSize=GenOrders[z].ThisOpSize;
+ Mask=MModAllIdx;
+ if (GenOrders[z].MayImm) Mask+=MModImm;
+ if (GenOrders[z].MayDir) Mask+=MModDir;
+ if (GenOrders[z].MayExt) Mask+=MModExt;
+ DecodeAdr(1,ArgCnt,Mask);
+ if (AdrMode!=ModNone)
+ if (Hi(GenOrders[z].Code)==0)
+ BEGIN
+ BAsmCode[0]=GenOrders[z].Code; CodeLen=1;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=Hi(GenOrders[z].Code);
+ BAsmCode[1]=Lo(GenOrders[z].Code); CodeLen=2;
+ END;
+ switch (AdrMode)
+ BEGIN
+ case ModImm: break;
+ case ModDir: BAsmCode[CodeLen-1]+=0x10; break;
+ case ModIdx:
+ case ModIdx1:
+ case ModIdx2:
+ case ModDIdx:
+ case ModIIdx2: BAsmCode[CodeLen-1]+=0x20; break;
+ case ModExt: BAsmCode[CodeLen-1]+=0x30; break;
+ END
+ if (AdrMode!=ModNone)
+ BEGIN
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<LEAOrderCount; z++)
+ if (Memo(LEAOrders[z].Name))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ ExPos=1;
+ DecodeAdr(1,ArgCnt,MModIdx+MModIdx1+MModIdx2);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=LEAOrders[z].Code;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("TBL")) OR (Memo("ETBL")))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ ExPos=2;
+ DecodeAdr(1,ArgCnt,MModIdx);
+ if (AdrMode==ModIdx)
+ BEGIN
+ BAsmCode[0]=0x18;
+ BAsmCode[1]=0x3d+(Ord(Memo("ETBL")) << 1);
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if (Memo("EMACS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ Address=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x18;
+ BAsmCode[1]=0x12;
+ BAsmCode[2]=(Address >> 8) & 0xff;
+ BAsmCode[3]=Address & 0xff;
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ /* Transfer */
+
+ if ((Memo("TFR")) OR (Memo("EXG")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (NOT DecodeReg(ArgStr[2],BAsmCode+1)) WrXError(1445,ArgStr[2]);
+ else if (NOT DecodeReg(ArgStr[1],&HReg)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ BAsmCode[0]=0xb7;
+ BAsmCode[1]+=(Ord(Memo("EXG")) << 7)+(HReg << 4);
+ CodeLen=2;
+ END
+ return;
+ END
+
+ if (Memo("SEX"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (NOT DecodeReg(ArgStr[2],BAsmCode+1)) WrXError(1445,ArgStr[2]);
+ else if (BAsmCode[1]<4) WrXError(1445,ArgStr[2]);
+ else if (NOT DecodeReg(ArgStr[1],&HReg)) WrXError(1445,ArgStr[1]);
+ else if (HReg>3) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ BAsmCode[0]=0xb7;
+ BAsmCode[1]+=(Ord(Memo("EXG")) << 7)+(HReg << 4);
+ CodeLen=2;
+ END
+ return;
+ END
+
+ if ((Memo("MOVB")) OR (Memo("MOVW")))
+ BEGIN
+ switch (ArgCnt)
+ BEGIN
+ case 1:Try2Split(1); break;
+ case 2:Try2Split(1); if (ArgCnt==2) Try2Split(2); break;
+ case 3:Try2Split(2); break;
+ END
+ if ((ArgCnt<2) OR (ArgCnt>4)) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ if (ArgCnt==2) HReg=2;
+ else if (ArgCnt==4) HReg=3;
+ else if (ValidReg(ArgStr[2])) HReg=3;
+ else HReg=2;
+ OpSize=Ord(Memo("MOVW")); ExPos=2;
+ BAsmCode[0]=0x18; BAsmCode[1]=Ord(Memo("MOVB")) << 3;
+ DecodeAdr(1,HReg-1,MModImm+MModExt+MModIdx);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ memmove(AdrVals+2,AdrVals,AdrCnt); HCnt=AdrCnt;
+ ExPos=4+2*OpSize; DecodeAdr(HReg,ArgCnt,MModExt+MModIdx);
+ switch (AdrMode)
+ BEGIN
+ case ModExt:
+ BAsmCode[1]+=3;
+ memcpy(BAsmCode+2,AdrVals+2,HCnt);
+ memcpy(BAsmCode+2+HCnt,AdrVals,AdrCnt);
+ CodeLen=2+HCnt+AdrCnt;
+ break;
+ case ModIdx:
+ BAsmCode[2]=AdrVals[0];
+ memcpy(BAsmCode+3,AdrVals+2,HCnt);
+ CodeLen=3+HCnt;
+ break;
+ END
+ break;
+ case ModExt:
+ memmove(AdrVals+2,AdrVals,AdrCnt); HCnt=AdrCnt;
+ ExPos=6; DecodeAdr(HReg,ArgCnt,MModExt+MModIdx);
+ switch (AdrMode)
+ BEGIN
+ case ModExt:
+ BAsmCode[1]+=4;
+ memcpy(BAsmCode+2,AdrVals+2,HCnt);
+ memcpy(BAsmCode+2+HCnt,AdrVals,AdrCnt);
+ CodeLen=2+HCnt+AdrCnt;
+ break;
+ case ModIdx:
+ BAsmCode[1]+=1;
+ BAsmCode[2]=AdrVals[0];
+ memcpy(BAsmCode+3,AdrVals+2,HCnt);
+ CodeLen=3+HCnt;
+ break;
+ END;
+ break;
+ case ModIdx:
+ HCnt=AdrVals[0];
+ ExPos=4; DecodeAdr(HReg,ArgCnt,MModExt+MModIdx);
+ switch (AdrMode)
+ BEGIN
+ case ModExt:
+ BAsmCode[1]+=5;
+ BAsmCode[2]=HCnt;
+ memcpy(BAsmCode+3,AdrVals,AdrCnt);
+ CodeLen=3+AdrCnt;
+ break;
+ case ModIdx:
+ BAsmCode[1]+=2;
+ BAsmCode[2]=HCnt;
+ BAsmCode[3]=AdrVals[0];
+ CodeLen=4;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Logik */
+
+ if ((Memo("ANDCC")) OR (Memo("ORCC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(1,1,MModImm);
+ if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[0]=0x10+(Ord(Memo("ORCC")) << 2);
+ BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BSET")) OR (Memo("BCLR")))
+ BEGIN
+ if ((ArgCnt==1) OR (ArgCnt==2)) Try2Split(ArgCnt);
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ if (*ArgStr[ArgCnt]=='#') strcpy(ArgStr[ArgCnt],ArgStr[ArgCnt]+1);
+ HReg=EvalIntExpression(ArgStr[ArgCnt],UInt8,&OK);
+ if (OK)
+ BEGIN
+ ExPos=2; /* wg. Masken-Postbyte */
+ DecodeAdr(1,ArgCnt-1,MModDir+MModExt+MModIdx+MModIdx1+MModIdx2);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x0c+Ord(Memo("BCLR"));
+ switch (AdrMode)
+ BEGIN
+ case ModDir: BAsmCode[0]+=0x40; break;
+ case ModExt: BAsmCode[0]+=0x10; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=HReg;
+ CodeLen=2+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ for (z=0; z<BranchOrderCount; z++)
+ if Memo(BranchOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ Address=EvalIntExpression(ArgStr[1],UInt16,&OK)-EProgCounter()-2;
+ if (OK)
+ if (((Address<-128) OR (Address>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=BranchOrders[z].Code; BAsmCode[1]=Address & 0xff; CodeLen=2;
+ END
+ END
+ return;
+ END
+ else if ((*OpPart=='L') AND (strcmp(OpPart+1,BranchOrders[z].Name)==0))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ Address=EvalIntExpression(ArgStr[1],UInt16,&OK)-EProgCounter()-4;
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x18;
+ BAsmCode[1]=BranchOrders[z].Code;
+ BAsmCode[2]=(Address >> 8) & 0xff;
+ BAsmCode[3]=Address & 0xff;
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<LoopOrderCount; z++)
+ if Memo(LoopOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ if (DecodeReg8(ArgStr[1],&HReg))
+ BEGIN
+ OK=True; if (HReg==2) HReg=4;
+ END
+ else if (DecodeReg16(ArgStr[1],&HReg))
+ BEGIN
+ OK=(HReg!=PCReg); HReg+=5;
+ END
+ else OK=False;
+ if (NOT OK) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Address=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+3);
+ if (OK)
+ if (((Address<-256) OR (Address>255)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x04;
+ BAsmCode[1]=LoopOrders[z].Code+HReg+((Address >> 4) & 0x10);
+ BAsmCode[2]=Address & 0xff;
+ CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<JmpOrderCount; z++)
+ if (Memo(JmpOrders[z].Name))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ Mask=MModAllIdx+MModExt; if (JmpOrders[z].MayDir) Mask+=MModDir;
+ ExPos=1; DecodeAdr(1,ArgCnt,Mask);
+ if (AdrMode!=ModNone)
+ BEGIN
+ switch (AdrMode)
+ BEGIN
+ case ModExt: BAsmCode[0]=JmpOrders[z].Code; break;
+ case ModDir: BAsmCode[0]=JmpOrders[z].Code+1; break;
+ case ModIdx:
+ case ModIdx1:
+ case ModIdx2:
+ case ModDIdx:
+ case ModIIdx2: BAsmCode[0]=JmpOrders[z].Code-1; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALL"))
+ BEGIN
+ if (ArgCnt<1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (*ArgStr[1]=='[')
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ ExPos=1; DecodeAdr(1,1,MModDIdx+MModIIdx2);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x4b;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ END
+ END
+ else
+ BEGIN
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[ArgCnt],UInt8,&OK);
+ if (OK)
+ BEGIN
+ ExPos=2; /* wg. Seiten-Byte eins mehr */
+ DecodeAdr(1,ArgCnt-1,MModExt+MModIdx+MModIdx1+MModIdx2);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x4a+Ord(AdrMode!=ModExt);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=HReg;
+ CodeLen=2+AdrCnt;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BRSET")) OR (Memo("BRCLR")))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ Try2Split(1); Try2Split(1);
+ END
+ else if (ArgCnt==2)
+ BEGIN
+ Try2Split(ArgCnt); Try2Split(2);
+ END
+ if ((ArgCnt<3) OR (ArgCnt>4)) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ if (*ArgStr[ArgCnt-1]=='#') strcpy(ArgStr[ArgCnt-1],ArgStr[ArgCnt-1]+1);
+ HReg=EvalIntExpression(ArgStr[ArgCnt-1],UInt8,&OK);
+ if (OK)
+ BEGIN
+ Address=EvalIntExpression(ArgStr[ArgCnt],UInt16,&OK)-EProgCounter();
+ if (OK)
+ BEGIN
+ ExPos=3; /* Opcode, Maske+Distanz */
+ DecodeAdr(1,ArgCnt-2,MModDir+MModExt+MModIdx+MModIdx1+MModIdx2);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x0e + Ord(Memo("BRCLR")); /* ANSI :-O */
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ switch (AdrMode)
+ BEGIN
+ case ModDir: BAsmCode[0]+=0x40; break;
+ case ModExt: BAsmCode[0]+=0x10; break;
+ END
+ BAsmCode[1+AdrCnt]=HReg;
+ Address-=3+AdrCnt;
+ if (((Address<-128) OR (Address>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[2+AdrCnt]=Address & 0xff;
+ CodeLen=3+AdrCnt;
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("TRAP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ if (*ArgStr[1]=='#') strcpy(ArgStr[1],ArgStr[1]+1);
+ BAsmCode[1]=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if (FirstPassUnknown) BAsmCode[1]=0x30;
+ if (OK)
+ if ((BAsmCode[1]<0x30) OR ((BAsmCode[1]>0x39) AND (BAsmCode[1]<0x40))) WrError(1320);
+ else
+ BEGIN
+ BAsmCode[0]=0x18; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_6812(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_6812(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_6812(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x66; NOPCode=0xa7;
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_6812; IsDef=IsDef_6812;
+ SwitchFrom=SwitchFrom_6812; InitFields();
+ AddMoto16PseudoONOFF();
+
+ SetFlag(&DoPadding,DoPaddingName,False);
+END
+
+ void code6812_init(void)
+BEGIN
+ CPU6812=AddCPU("68HC12",SwitchTo_6812);
+END
diff --git a/code6812.h b/code6812.h
new file mode 100644
index 0000000..130fea0
--- /dev/null
+++ b/code6812.h
@@ -0,0 +1,11 @@
+/* code6812.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul CPU12 */
+/* */
+/* Historie: 13.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code6812_init(void);
diff --git a/code6816.c b/code6816.c
new file mode 100644
index 0000000..6fbc5e4
--- /dev/null
+++ b/code6816.c
@@ -0,0 +1,1073 @@
+/* code6816.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul CPU16 */
+/* */
+/* Historie: 15.10.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ ShortInt Size;
+ Word Code,ExtCode;
+ Byte AdrMask,ExtShift;
+ } GenOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code1,Code2;
+ } EmuOrder;
+
+#define FixedOrderCnt 140
+#define RelOrderCnt 18
+#define LRelOrderCnt 3
+#define GenOrderCnt 66
+#define AuxOrderCnt 12
+#define ImmOrderCnt 4
+#define ExtOrderCnt 3
+#define EmuOrderCnt 6
+#define RegCnt 7
+
+#define ModNone (-1)
+#define ModDisp8 0
+#define MModDisp8 (1 << ModDisp8)
+#define ModDisp16 1
+#define MModDisp16 (1 << ModDisp16)
+#define ModDispE 2
+#define MModDispE (1 << ModDispE)
+#define ModAbs 3
+#define MModAbs (1 << ModAbs)
+#define ModImm 4
+#define MModImm (1 << ModImm)
+#define ModImmExt 5
+#define MModImmExt (1 << ModImmExt)
+#define ModDisp20 ModDisp16
+#define MModDisp20 MModDisp16
+#define ModAbs20 ModAbs
+#define MModAbs20 MModAbs
+
+static ShortInt OpSize;
+static ShortInt AdrMode;
+static Byte AdrPart;
+static Byte AdrVals[4];
+
+static LongInt Reg_EK;
+static SimpProc SaveInitProc;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *RelOrders;
+static FixedOrder *LRelOrders;
+static GenOrder *GenOrders;
+static FixedOrder *AuxOrders;
+static FixedOrder *ImmOrders;
+static FixedOrder *ExtOrders;
+static EmuOrder *EmuOrders;
+static char **Regs;
+
+static CPUVar CPU6816;
+
+/*-------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRel(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddLRel(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=LRelOrderCnt) exit(255);
+ LRelOrders[InstrZ].Name=NName;
+ LRelOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddGen(char *NName, ShortInt NSize, Word NCode,
+ Word NExtCode, Byte NShift, Byte NMask)
+BEGIN
+ if (InstrZ>=GenOrderCnt) exit(255);
+ GenOrders[InstrZ].Name=NName;
+ GenOrders[InstrZ].Code=NCode;
+ GenOrders[InstrZ].ExtCode=NExtCode;
+ GenOrders[InstrZ].Size=NSize;
+ GenOrders[InstrZ].AdrMask=NMask;
+ GenOrders[InstrZ++].ExtShift=NShift;
+END
+
+ static void AddAux(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=AuxOrderCnt) exit(255);
+ AuxOrders[InstrZ].Name=NName;
+ AuxOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddImm(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ImmOrderCnt) exit(255);
+ ImmOrders[InstrZ].Name=NName;
+ ImmOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddExt(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ExtOrderCnt) exit(255);
+ ExtOrders[InstrZ].Name=NName;
+ ExtOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddEmu(char *NName, Word NCode1, Word NCode2)
+BEGIN
+ if (InstrZ>=EmuOrderCnt) exit(255);
+ EmuOrders[InstrZ].Name=NName;
+ EmuOrders[InstrZ].Code1=NCode1;
+ EmuOrders[InstrZ++].Code2=NCode2;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("ABA" ,0x370b); AddFixed("ABX" ,0x374f);
+ AddFixed("ABY" ,0x375f); AddFixed("ABZ" ,0x376f);
+ AddFixed("ACE" ,0x3722); AddFixed("ACED" ,0x3723);
+ AddFixed("ADE" ,0x2778); AddFixed("ADX" ,0x37cd);
+ AddFixed("ADY" ,0x37dd); AddFixed("ADZ" ,0x37ed);
+ AddFixed("AEX" ,0x374d); AddFixed("AEY" ,0x375d);
+ AddFixed("AEZ" ,0x376d); AddFixed("ASLA" ,0x3704);
+ AddFixed("ASLB" ,0x3714); AddFixed("ASLD" ,0x27f4);
+ AddFixed("ASLE" ,0x2774); AddFixed("ASLM" ,0x27b6);
+ AddFixed("LSLB" ,0x3714); AddFixed("LSLD" ,0x27f4);
+ AddFixed("LSLE" ,0x2774); AddFixed("LSLA" ,0x3704);
+ AddFixed("ASRA" ,0x370d); AddFixed("ASRB" ,0x371d);
+ AddFixed("ASRD" ,0x27fd); AddFixed("ASRE" ,0x277d);
+ AddFixed("ASRM" ,0x27ba); AddFixed("BGND" ,0x37a6);
+ AddFixed("CBA" ,0x371b); AddFixed("CLRA" ,0x3705);
+ AddFixed("CLRB" ,0x3715); AddFixed("CLRD" ,0x27f5);
+ AddFixed("CLRE" ,0x2775); AddFixed("CLRM" ,0x27b7);
+ AddFixed("COMA" ,0x3700); AddFixed("COMB" ,0x3710);
+ AddFixed("COMD" ,0x27f0); AddFixed("COME" ,0x2770);
+ AddFixed("DAA" ,0x3721); AddFixed("DECA" ,0x3701);
+ AddFixed("DECB" ,0x3711); AddFixed("EDIV" ,0x3728);
+ AddFixed("EDIVS" ,0x3729); AddFixed("EMUL" ,0x3725);
+ AddFixed("EMULS" ,0x3726); AddFixed("FDIV" ,0x372b);
+ AddFixed("FMULS" ,0x3727); AddFixed("IDIV" ,0x372a);
+ AddFixed("INCA" ,0x3703); AddFixed("INCB" ,0x3713);
+ AddFixed("LPSTOP",0x27f1); AddFixed("LSRA" ,0x370f);
+ AddFixed("LSRB" ,0x371f); AddFixed("LSRD" ,0x27ff);
+ AddFixed("LSRE" ,0x277f); AddFixed("MUL" ,0x3724);
+ AddFixed("NEGA" ,0x3702); AddFixed("NEGB" ,0x3712);
+ AddFixed("NEGD" ,0x27f2); AddFixed("NEGE" ,0x2772);
+ AddFixed("NOP" ,0x274c); AddFixed("PSHA" ,0x3708);
+ AddFixed("PSHB" ,0x3718); AddFixed("PSHMAC",0x27b8);
+ AddFixed("PULA" ,0x3709); AddFixed("PULB" ,0x3719);
+ AddFixed("PULMAC",0x27b9); AddFixed("ROLA" ,0x370c);
+ AddFixed("ROLB" ,0x371c); AddFixed("ROLD" ,0x27fc);
+ AddFixed("ROLE" ,0x277c); AddFixed("RORA" ,0x370e);
+ AddFixed("RORB" ,0x371e); AddFixed("RORD" ,0x27fe);
+ AddFixed("RORE" ,0x277e); AddFixed("RTI" ,0x2777);
+ AddFixed("RTS" ,0x27f7); AddFixed("SBA" ,0x370a);
+ AddFixed("SDE" ,0x2779); AddFixed("SWI" ,0x3720);
+ AddFixed("SXT" ,0x27f8); AddFixed("TAB" ,0x3717);
+ AddFixed("TAP" ,0x37fd); AddFixed("TBA" ,0x3707);
+ AddFixed("TBEK" ,0x27fa); AddFixed("TBSK" ,0x379f);
+ AddFixed("TBXK" ,0x379c); AddFixed("TBYK" ,0x379d);
+ AddFixed("TBZK" ,0x379e); AddFixed("TDE" ,0x277b);
+ AddFixed("TDMSK" ,0x372f); AddFixed("TDP" ,0x372d);
+ AddFixed("TED" ,0x27fb); AddFixed("TEDM" ,0x27b1);
+ AddFixed("TEKB" ,0x27bb); AddFixed("TEM" ,0x27b2);
+ AddFixed("TMER" ,0x27b4); AddFixed("TMET" ,0x27b5);
+ AddFixed("TMXED" ,0x27b3); AddFixed("TPA" ,0x37fc);
+ AddFixed("TPD" ,0x372c); AddFixed("TSKB" ,0x37af);
+ AddFixed("TSTA" ,0x3706); AddFixed("TSTB" ,0x3716);
+ AddFixed("TSTD" ,0x27f6); AddFixed("TSTE" ,0x2776);
+ AddFixed("TSX" ,0x274f); AddFixed("TSY" ,0x275f);
+ AddFixed("TSZ" ,0x276f); AddFixed("TXKB" ,0x37ac);
+ AddFixed("TXS" ,0x374e); AddFixed("TXY" ,0x275c);
+ AddFixed("TXZ" ,0x276c); AddFixed("TYKB" ,0x37ad);
+ AddFixed("TYS" ,0x375e); AddFixed("TYX" ,0x274d);
+ AddFixed("TYZ" ,0x276d); AddFixed("TZKB" ,0x37ae);
+ AddFixed("TZS" ,0x376e); AddFixed("TZX" ,0x274e);
+ AddFixed("TZY" ,0x275e); AddFixed("WAI" ,0x27f3);
+ AddFixed("XGAB" ,0x371a); AddFixed("XGDE" ,0x277a);
+ AddFixed("XGDX" ,0x37cc); AddFixed("XGDY" ,0x37dc);
+ AddFixed("XGDZ" ,0x37ec); AddFixed("XGEX" ,0x374c);
+ AddFixed("XGEY" ,0x375c); AddFixed("XGEZ" ,0x376c);
+ AddFixed("DES" ,0x3fff); AddFixed("INS" ,0x3f01);
+ AddFixed("DEX" ,0x3cff); AddFixed("INX" ,0x3c01);
+ AddFixed("DEY" ,0x3dff); AddFixed("INY" ,0x3d01);
+ AddFixed("PSHX" ,0x3404); AddFixed("PULX" ,0x3510);
+ AddFixed("PSHY" ,0x3408); AddFixed("PULY" ,0x3508);
+
+ RelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("BCC", 4); AddRel("BCS", 5); AddRel("BEQ", 7);
+ AddRel("BGE",12); AddRel("BGT",14); AddRel("BHI", 2);
+ AddRel("BLE",15); AddRel("BLS", 3); AddRel("BLT",13);
+ AddRel("BMI",11); AddRel("BNE", 6); AddRel("BPL",10);
+ AddRel("BRA", 0); AddRel("BRN", 1); AddRel("BVC", 8);
+ AddRel("BVS", 9); AddRel("BHS", 4); AddRel("BLO", 5);
+
+ LRelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LRelOrderCnt); InstrZ=0;
+ AddLRel("LBEV",0x3791); AddLRel("LBMV",0x3790); AddLRel("LBSR",0x27f9);
+
+ GenOrders=(GenOrder *) malloc(sizeof(GenOrder)*GenOrderCnt); InstrZ=0;
+ AddGen("ADCA",0,0x43,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ADCB",0,0xc3,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ADCD",1,0x83,0xffff,0x20,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ADCE",1,0x03,0xffff,0x20, MModImm+ MModDisp16+MModAbs );
+ AddGen("ADDA",0,0x41,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ADDB",0,0xc1,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ADDD",1,0x81, 0xfc,0x20,MModDisp8+MModImm+MModImmExt+MModDisp16+MModAbs+MModDispE);
+ AddGen("ADDE",1,0x01, 0x7c,0x20, MModImm+MModImmExt+MModDisp16+MModAbs );
+ AddGen("ANDA",0,0x46,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ANDB",0,0xc6,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ANDD",1,0x86,0xffff,0x20,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ANDE",1,0x06,0xffff,0x20, MModImm+ MModDisp16+MModAbs );
+ AddGen("ASL" ,0,0x04,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("ASLW",0,0x04,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("LSL" ,0,0x04,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("LSLW",0,0x04,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("ASR" ,0,0x0d,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("ASRW",0,0x0d,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("BITA",0,0x49,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("BITB",0,0xc9,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("CLR" ,0,0x05,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("CLRW",0,0x05,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("CMPA",0,0x48,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("CMPB",0,0xc8,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("COM" ,0,0x00,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("COMW",0,0x00,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("CPD" ,1,0x88,0xffff,0x20,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("CPE" ,1,0x08,0xffff,0x20, MModImm+ MModDisp16+MModAbs );
+ AddGen("DEC" ,0,0x01,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("DECW",0,0x01,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("EORA",0,0x44,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("EORB",0,0xc4,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("EORD",1,0x84,0xffff,0x20,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("EORE",1,0x04,0xffff,0x20, MModImm+ MModDisp16+MModAbs );
+ AddGen("INC" ,0,0x03,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("INCW",0,0x03,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("LDAA",0,0x45,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("LDAB",0,0xc5,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("LDD" ,1,0x85,0xffff,0x20,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("LDE" ,1,0x05,0xffff,0x20, MModImm+ MModDisp16+MModAbs );
+ AddGen("LSR" ,0,0x0f,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("LSRW",0,0x0f,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("NEG" ,0,0x02,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("NEGW",0,0x02,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("ORAA",0,0x47,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ORAB",0,0xc7,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ORD" ,1,0x87,0xffff,0x20,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("ORE" ,1,0x07,0xffff,0x20, MModImm+ MModDisp16+MModAbs );
+ AddGen("ROL" ,0,0x0c,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("ROLW",0,0x0c,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("ROR" ,0,0x0e,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("RORW",0,0x0e,0xffff,0x10, MModDisp16+MModAbs );
+ AddGen("SBCA",0,0x42,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("SBCB",0,0xc2,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("SBCD",1,0x82,0xffff,0x20,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("SBCE",1,0x02,0xffff,0x20, MModImm+ MModDisp16+MModAbs );
+ AddGen("STAA",0,0x4a,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs+MModDispE);
+ AddGen("STAB",0,0xca,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs+MModDispE);
+ AddGen("STD" ,1,0x8a,0xffff,0x20,MModDisp8+ MModDisp16+MModAbs+MModDispE);
+ AddGen("STE" ,1,0x0a,0xffff,0x20, MModDisp16+MModAbs );
+ AddGen("SUBA",0,0x40,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("SUBB",0,0xc0,0xffff,0x00,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("SUBD",1,0x80,0xffff,0x20,MModDisp8+MModImm+ MModDisp16+MModAbs+MModDispE);
+ AddGen("SUBE",1,0x00,0xffff,0x20, MModImm+ MModDisp16+MModAbs );
+ AddGen("TST" ,0,0x06,0xffff,0x00,MModDisp8+ MModDisp16+MModAbs );
+ AddGen("TSTW",0,0x06,0xffff,0x10, MModDisp16+MModAbs );
+
+ AuxOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*AuxOrderCnt); InstrZ=0;
+ AddAux("CPS",0x4f); AddAux("CPX",0x4c); AddAux("CPY",0x4d); AddAux("CPZ",0x4e);
+ AddAux("LDS",0xcf); AddAux("LDX",0xcc); AddAux("LDY",0xcd); AddAux("LDZ",0xce);
+ AddAux("STS",0x8f); AddAux("STX",0x8c); AddAux("STY",0x8d); AddAux("STZ",0x8e);
+
+ ImmOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ImmOrderCnt); InstrZ=0;
+ AddImm("AIS",0x3f); AddImm("AIX",0x3c); AddImm("AIY",0x3d); AddImm("AIZ",0x3e);
+
+ ExtOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ExtOrderCnt); InstrZ=0;
+ AddExt("LDED",0x2771); AddExt("LDHI",0x27b0);AddExt("STED",0x2773);
+
+ EmuOrders=(EmuOrder *) malloc(sizeof(EmuOrder)*EmuOrderCnt); InstrZ=0;
+ AddEmu("CLC",0x373a,0xfeff); AddEmu("CLI",0x373a,0xff1f); AddEmu("CLV",0x373a,0xfdff);
+ AddEmu("SEC",0x373b,0x0100); AddEmu("SEI",0x373b,0x00e0); AddEmu("SEV",0x373b,0x0200);
+
+ Regs=(char **) malloc(sizeof(char *)*RegCnt);
+ Regs[0]="D"; Regs[1]="E"; Regs[2]="X"; Regs[3]="Y";
+ Regs[4]="Z"; Regs[5]="K"; Regs[6]="CCR";
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(RelOrders);
+ free(LRelOrders);
+ free(GenOrders);
+ free(AuxOrders);
+ free(ImmOrders);
+ free(ExtOrders);
+ free(EmuOrders);
+ free(Regs);
+END
+
+/*-------------------------------------------------------------------------*/
+
+typedef enum {ShortDisp,LongDisp,NoDisp} DispType;
+
+ static void ChkAdr(Byte Mask)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Mask AND (1 << AdrMode))==0))
+ BEGIN
+ WrError(1350);
+ AdrMode=ModNone; AdrCnt=0;
+ END
+END
+
+ static void SplitSize(char *Asc, DispType *Erg)
+BEGIN
+ if (strlen(Asc)<1) *Erg=NoDisp;
+ else if (*Asc=='>') *Erg=LongDisp;
+ else if (*Asc=='<') *Erg=ShortDisp;
+ else *Erg=NoDisp;
+END
+
+ static void DecodeAdr(int Start, int Stop, Boolean LongAdr, Byte Mask)
+BEGIN
+ Integer V16;
+ LongInt V32;
+ Boolean OK;
+ String s;
+ DispType Size;
+
+ AdrMode=ModNone; AdrCnt=0;
+
+ Stop-=Start-1;
+ if (Stop<1)
+ BEGIN
+ WrError(1110); return;
+ END
+
+ /* immediate ? */
+
+ if (*ArgStr[Start]=='#')
+ BEGIN
+ strmaxcpy(s,ArgStr[Start]+1,255); SplitSize(s,&Size);
+ switch (OpSize)
+ BEGIN
+ case -1: WrError(1132); break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(s,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrMode=ModImm;
+ END
+ break;
+ case 1:
+ V16=EvalIntExpression(s,(Size==ShortDisp)?SInt8:Int16,&OK);
+ if ((Size==NoDisp) AND (V16>=-128) AND (V16<=127) AND ((Mask & MModImmExt)!=0))
+ Size=ShortDisp;
+ if (OK)
+ if (Size==ShortDisp)
+ BEGIN
+ AdrVals[0]=Lo(V16);
+ AdrCnt=1; AdrMode=ModImmExt;
+ END
+ else
+ BEGIN
+ AdrVals[0]=Hi(V16);
+ AdrVals[1]=Lo(V16);
+ AdrCnt=2; AdrMode=ModImm;
+ END
+ break;
+ case 2:
+ V32=EvalIntExpression(s,Int32,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=(V32 >> 24) & 0xff;
+ AdrVals[1]=(V32 >> 16) & 0xff;
+ AdrVals[2]=(V32 >> 8) & 0xff;
+ AdrVals[3]=V32 & 0xff;
+ AdrCnt=4; AdrMode=ModImm;
+ END
+ break;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* zusammengesetzt ? */
+
+ if (Stop==2)
+ BEGIN
+ AdrPart=0xff;
+ if (strcasecmp(ArgStr[Start+1],"X")==0) AdrPart=0x00;
+ else if (strcasecmp(ArgStr[Start+1],"Y")==0) AdrPart=0x10;
+ else if (strcasecmp(ArgStr[Start+1],"Z")==0) AdrPart=0x20;
+ else WrXError(1445,ArgStr[Start+1]);
+ if (AdrPart!=0xff)
+ if (strcasecmp(ArgStr[Start],"E")==0) AdrMode=ModDispE;
+ else
+ BEGIN
+ SplitSize(ArgStr[Start],&Size);
+ if (Size==ShortDisp)
+ V32=EvalIntExpression(ArgStr[Start],UInt8,&OK);
+ else if (LongAdr)
+ V32=EvalIntExpression(ArgStr[Start],SInt20,&OK);
+ else
+ V32=EvalIntExpression(ArgStr[Start],SInt16,&OK);
+ if (OK)
+ BEGIN
+ if (Size==NoDisp)
+ if ((V32>=0) AND (V32<=255) AND ((Mask & MModDisp8)!=0)) Size=ShortDisp;
+ if (Size==ShortDisp)
+ BEGIN
+ AdrVals[0]=V32 & 0xff;
+ AdrCnt=1; AdrMode=ModDisp8;
+ END
+ else if (LongAdr)
+ BEGIN
+ AdrVals[0]=(V32 >> 16) & 0x0f;
+ AdrVals[1]=(V32 >> 8) & 0xff;
+ AdrVals[2]=V32 & 0xff;
+ AdrCnt=3; AdrMode=ModDisp16;
+ END
+ else
+ BEGIN
+ AdrVals[0]=(V32 >> 8) & 0xff;
+ AdrVals[1]=V32 & 0xff;
+ AdrCnt=2; AdrMode=ModDisp16;
+ END
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* absolut ? */
+
+ else
+ BEGIN
+ SplitSize(ArgStr[Start],&Size);
+ V32=EvalIntExpression(ArgStr[Start],UInt20,&OK);
+ if (OK)
+ if (LongAdr)
+ BEGIN
+ AdrVals[0]=(V32 >> 16) & 0xff;
+ AdrVals[1]=(V32 >> 8) & 0xff;
+ AdrVals[2]=V32 & 0xff;
+ AdrMode=ModAbs; AdrCnt=3;
+ END
+ else
+ BEGIN
+ if ((V32 >> 16)!=Reg_EK) WrError(110);
+ AdrVals[0]=(V32 >> 8) & 0xff;
+ AdrVals[1]=V32 & 0xff;
+ AdrMode=ModAbs; AdrCnt=2;
+ END
+ ChkAdr(Mask); return;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME6816Count 1
+ static ASSUMERec ASSUME6816s[ASSUME6816Count]=
+ {{"EK" , &Reg_EK , 0 , 0xff , 0x100}};
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME6816s,ASSUME6816Count);
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_6816(void)
+BEGIN
+ int z,z2;
+ Boolean OK;
+ Byte Mask;
+ LongInt AdrLong;
+
+ CodeLen=0; DontPrint=False; AdrCnt=0; OpSize=(-1);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeMotoPseudo(True)) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if Memo(FixedOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=Hi(FixedOrders[z].Code); BAsmCode[1]=Lo(FixedOrders[z].Code);
+ CodeLen=2;
+ END
+ return;
+ END
+
+ for (z=0; z<EmuOrderCnt; z++)
+ if Memo(EmuOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=Hi(EmuOrders[z].Code1); BAsmCode[1]=Lo(EmuOrders[z].Code1);
+ BAsmCode[2]=Hi(EmuOrders[z].Code2); BAsmCode[3]=Lo(EmuOrders[z].Code2);
+ CodeLen=4;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ for (z=0; z<AuxOrderCnt; z++)
+ if (Memo(AuxOrders[z].Name))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ OpSize=1;
+ DecodeAdr(1,ArgCnt,False,(*OpPart=='S'?0:MModImm)+MModDisp8+MModDisp16+MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModDisp8:
+ BAsmCode[0]=AuxOrders[z].Code+AdrPart;
+ BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModDisp16:
+ BAsmCode[0]=0x17;
+ BAsmCode[1]=AuxOrders[z].Code+AdrPart;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0x17;
+ BAsmCode[1]=AuxOrders[z].Code+0x30;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x37; BAsmCode[1]=AuxOrders[z].Code+0x30;
+ if (*OpPart=='L') BAsmCode[1]-=0x40;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ExtOrderCnt; z++)
+ if (Memo(ExtOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(1,1,False,MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModAbs:
+ BAsmCode[0]=Hi(ExtOrders[z].Code); BAsmCode[1]=Lo(ExtOrders[z].Code);
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PSHM")) OR (Memo("PULM")))
+ BEGIN
+ if (ArgCnt<1) WrError(1110);
+ else
+ BEGIN
+ OK=True; Mask=0;
+ for (z=1; z<=ArgCnt; z++)
+ if (OK)
+ BEGIN
+ z2=0; NLS_UpString(ArgStr[z]);
+ while ((z2<RegCnt) AND (strcmp(ArgStr[z],Regs[z2])!=0)) z2++;
+ if (z2>=RegCnt)
+ BEGIN
+ WrXError(1445,ArgStr[z]); OK=False;
+ END
+ else if (Memo("PSHM")) Mask+=(1 << z2);
+ else Mask+=(1 << (RegCnt-1-z2));
+ END
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x34+Ord(Memo("PULM")); BAsmCode[1]=Mask;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MOVB")) OR (Memo("MOVW")))
+ BEGIN
+ z=Ord(Memo("MOVW"));
+ if (ArgCnt==2)
+ BEGIN
+ DecodeAdr(1,1,False,MModAbs);
+ if (AdrMode==ModAbs)
+ BEGIN
+ memcpy(BAsmCode+2,AdrVals,2);
+ DecodeAdr(2,2,False,MModAbs);
+ if (AdrMode==ModAbs)
+ BEGIN
+ memcpy(BAsmCode+4,AdrVals,2);
+ BAsmCode[0]=0x37; BAsmCode[1]=0xfe + z; /* ANSI :-0 */
+ CodeLen=6;
+ END
+ END
+ END
+ else if (ArgCnt!=3) WrError(1110);
+ else if (strcasecmp(ArgStr[2],"X")==0)
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1],SInt8,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(3,3,False,MModAbs);
+ if (AdrMode==ModAbs)
+ BEGIN
+ memcpy(BAsmCode+2,AdrVals,2);
+ BAsmCode[0]=0x30+z;
+ CodeLen=4;
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[3],"X")==0)
+ BEGIN
+ BAsmCode[3]=EvalIntExpression(ArgStr[2],SInt8,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(1,1,False,MModAbs);
+ if (AdrMode==ModAbs)
+ BEGIN
+ memcpy(BAsmCode+1,AdrVals,2);
+ BAsmCode[0]=0x32+z;
+ CodeLen=4;
+ END
+ END
+ END
+ else WrError(1350);
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<GenOrderCnt; z++)
+ if (Memo(GenOrders[z].Name))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ OpSize=GenOrders[z].Size;
+ DecodeAdr(1,ArgCnt,False,GenOrders[z].AdrMask);
+ switch (AdrMode)
+ BEGIN
+ case ModDisp8:
+ BAsmCode[0]=GenOrders[z].Code+AdrPart;
+ BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModDisp16:
+ BAsmCode[0]=0x17+GenOrders[z].ExtShift;
+ BAsmCode[1]=GenOrders[z].Code+(OpSize << 6)+AdrPart;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ case ModDispE:
+ BAsmCode[0]=0x27; BAsmCode[1]=GenOrders[z].Code+AdrPart;
+ CodeLen=2;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0x17+GenOrders[z].ExtShift;
+ BAsmCode[1]=GenOrders[z].Code+(OpSize << 6)+0x30;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ case ModImm:
+ if (OpSize==0)
+ BEGIN
+ BAsmCode[0]=GenOrders[z].Code+0x30;
+ BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x37; BAsmCode[1]=GenOrders[z].Code+0x30;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ END
+ break;
+ case ModImmExt:
+ BAsmCode[0]=GenOrders[z].ExtCode;
+ BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ImmOrderCnt; z++)
+ if (Memo(ImmOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(1,1,False,MModImm+MModImmExt);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0]=0x37; BAsmCode[1]=ImmOrders[z].Code;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ case ModImmExt:
+ BAsmCode[0]=ImmOrders[z].Code; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("ANDP")) OR (Memo("ORP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(1,1,False,MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0]=0x37; BAsmCode[1]=0x3a+Ord(Memo("ORP"));
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MAC")) OR (Memo("RMAC")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ z=EvalIntExpression(ArgStr[1],UInt4,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],UInt4,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[1]+=(z << 4);
+ BAsmCode[0]=0x7b+(Ord(Memo("RMAC")) << 7);
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Bitoperationen */
+
+ if ((Memo("BCLR")) OR (Memo("BSET")))
+ BEGIN
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else
+ BEGIN
+ OpSize=0; z=Ord(Memo("BSET"));
+ DecodeAdr(ArgCnt,ArgCnt,False,MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ Mask=AdrVals[0];
+ DecodeAdr(1,ArgCnt-1,False,MModDisp8+MModDisp16+MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModDisp8:
+ BAsmCode[0]=0x17; BAsmCode[1]=0x08+z+AdrPart;
+ BAsmCode[2]=Mask; BAsmCode[3]=AdrVals[0];
+ CodeLen=4;
+ break;
+ case ModDisp16:
+ BAsmCode[0]=0x08+z+AdrPart; BAsmCode[1]=Mask;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0x38+z; BAsmCode[1]=Mask;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BCLRW")) OR (Memo("BSETW")))
+ BEGIN
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else
+ BEGIN
+ OpSize=1; z=Ord(Memo("BSETW"));
+ DecodeAdr(ArgCnt,ArgCnt,False,MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ DecodeAdr(1,ArgCnt-1,False,MModDisp16+MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModDisp16:
+ BAsmCode[0]=0x27; BAsmCode[1]=0x08+z+AdrPart;
+ memcpy(BAsmCode+4,AdrVals,AdrCnt);
+ CodeLen=4+AdrCnt;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0x27; BAsmCode[1]=0x38+z;
+ memcpy(BAsmCode+4,AdrVals,AdrCnt);
+ CodeLen=4+AdrCnt;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BRCLR")) OR (Memo("BRSET")))
+ BEGIN
+ if ((ArgCnt<3) OR (ArgCnt>4)) WrError(1110);
+ else
+ BEGIN
+ z=Ord(Memo("BRSET"));
+ OpSize=0; DecodeAdr(ArgCnt-1,ArgCnt-1,False,MModImm);
+ if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[1]=AdrVals[0];
+ AdrLong=EvalIntExpression(ArgStr[ArgCnt],UInt20,&OK)-EProgCounter()-6;
+ if (OK)
+ BEGIN
+ OK=SymbolQuestionable;
+ DecodeAdr(1,ArgCnt-2,False,MModDisp8+MModDisp16+MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModDisp8:
+ if ((AdrLong>=-128) AND (AdrLong<127))
+ BEGIN
+ BAsmCode[0]=0xcb-(z << 6)+AdrPart;
+ BAsmCode[2]=AdrVals[0];
+ BAsmCode[3]=AdrLong & 0xff;
+ CodeLen=4;
+ END
+ else if ((NOT OK) AND ((AdrLong<-0x8000l) OR (AdrLong>0x7fffl))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x0a+AdrPart+z;
+ BAsmCode[2]=0;
+ BAsmCode[3]=AdrVals[0];
+ BAsmCode[4]=(AdrLong >> 8) & 0xff;
+ BAsmCode[5]=AdrLong & 0xff;
+ CodeLen=6;
+ END
+ break;
+ case ModDisp16:
+ if ((NOT OK) AND ((AdrLong<-0x8000l) OR (AdrLong>0x7fffl))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x0a+AdrPart+z;
+ memcpy(BAsmCode+2,AdrVals,2);
+ BAsmCode[4]=(AdrLong >> 8) & 0xff;
+ BAsmCode[5]=AdrLong & 0xff;
+ CodeLen=6;
+ END
+ break;
+ case ModAbs:
+ if ((NOT OK) AND ((AdrLong<-0x8000l) OR (AdrLong>0x7fffl))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x3a+z;
+ memcpy(BAsmCode+2,AdrVals,2);
+ BAsmCode[4]=(AdrLong >> 8) & 0xff;
+ BAsmCode[5]=AdrLong & 0xff;
+ CodeLen=6;
+ END
+ break;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if ((Memo("JMP")) OR (Memo("JSR")))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ OpSize=1;
+ DecodeAdr(1,ArgCnt,True,MModAbs20+MModDisp20);
+ switch (AdrMode)
+ BEGIN
+ case ModAbs20:
+ BAsmCode[0]=0x7a+(Ord(Memo("JSR")) << 7);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ break;
+ case ModDisp20:
+ BAsmCode[0]=(Memo("JMP"))?0x4b:0x89;
+ BAsmCode[0]+=AdrPart;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<RelOrderCnt; z++)
+ if ((Memo(RelOrders[z].Name)) OR ((*OpPart=='L') AND (strcmp(OpPart+1,RelOrders[z].Name)==0)))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK)-EProgCounter()-6;
+ if ((AdrLong&1)==1) WrError(1325);
+ else if (*OpPart=='L')
+ if ((NOT SymbolQuestionable) AND ((AdrLong>0x7fffl) OR (AdrLong<-0x8000l))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x37; BAsmCode[1]=RelOrders[z].Code+0x80;
+ BAsmCode[2]=(AdrLong >> 8) & 0xff;
+ BAsmCode[3]=AdrLong & 0xff;
+ CodeLen=4;
+ END
+ else
+ if ((NOT SymbolQuestionable) AND ((AdrLong>0x7fl) OR (AdrLong<-0x80l))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0xb0+RelOrders[z].Code;
+ BAsmCode[1]=AdrLong & 0xff;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<LRelOrderCnt; z++)
+ if (Memo(LRelOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK)-EProgCounter()-6;
+ if ((AdrLong&1)==1) WrError(1325);
+ else if ((NOT SymbolQuestionable) AND ((AdrLong>0x7fffl) OR (AdrLong<-0x8000l))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=Hi(LRelOrders[z].Code); BAsmCode[1]=Lo(LRelOrders[z].Code);
+ BAsmCode[2]=(AdrLong >> 8) & 0xff;
+ BAsmCode[3]=AdrLong & 0xff;
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if (Memo("BSR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK)-EProgCounter()-6;
+ if ((AdrLong&1)==1) WrError(1325);
+ else if ((NOT SymbolQuestionable) AND ((AdrLong>0x7fl) OR (AdrLong<-0x80l))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x36;
+ BAsmCode[1]=AdrLong & 0xff;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_6816(void)
+BEGIN
+ SaveInitProc();
+ Reg_EK=0;
+END
+
+ static Boolean IsDef_6816(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_6816(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_6816(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x65; NOPCode=0x274c;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xfffffl;
+
+ MakeCode=MakeCode_6816; IsDef=IsDef_6816;
+ SwitchFrom=SwitchFrom_6816;
+
+ InitFields();
+END
+
+ void code6816_init(void)
+BEGIN
+ CPU6816=AddCPU("68HC16",SwitchTo_6816);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_6816;
+END
diff --git a/code6816.h b/code6816.h
new file mode 100644
index 0000000..a046349
--- /dev/null
+++ b/code6816.h
@@ -0,0 +1,11 @@
+/* code6816.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul CPU16 */
+/* */
+/* Historie: 15.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code6816_init(void);
diff --git a/code68k.c b/code68k.c
new file mode 100644
index 0000000..260c7d3
--- /dev/null
+++ b/code68k.c
@@ -0,0 +1,4428 @@
+/* code68k.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 680x0-Familie */
+/* */
+/* Historie: 9. 9.1996 Grundsteinlegung */
+/* 14.11.1997 Coldfire-Erweiterungen */
+/* 31. 5.1998 68040-Erweiterungen */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* 17. 1.1999 automatische Laengenanpassung OutDisp */
+/* 23. 1.1999 Einen String an sich selber anzuhaengen, ist keine */
+/* gute Idee gewesen :-) */
+/* 25. 1.1999 falscher Code fuer SBCD korrigiert */
+/* 5. 7.1999 bei FMOVE FPreg, <ea> war die Modusmaske Humbug... */
+/* FSMOVE/FDMOVE fuer 68040 fehlten noch */
+/* 9. 7.1999 In der Bitfeld-Dekodierung war bei der Portierung */
+/* ein call-by-reference verlorengegangen */
+/* 3.11.1999 ...in SplitBitField auch! */
+/* 4.11.1999 FSMOVE/DMOVE auch mit FPn als Quelle */
+/* F(S/D)(ADD/SUB/MUL/DIV) */
+/* FMOVEM statt FMOVE fpcr<->ea erlaubt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "endian.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+#include "asmitree.h"
+
+
+typedef struct
+ {
+ Word Code;
+ Boolean MustSup;
+ Word CPUMask;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ CPUVar FirstCPU,LastCPU;
+ } CtReg;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ Boolean Dya;
+ CPUVar MinCPU;
+ } FPUOp;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } FPUCond;
+
+#define FixedOrderCnt 10
+#define CtRegCnt 29
+#define CondCnt 20
+#define FPUOpCnt 43
+#define FPUCondCnt 26
+#define PMMUCondCnt 16
+#define PMMURegCnt 13
+
+#define PMMUAvailName "HASPMMU" /* PMMU-Befehle erlaubt */
+#define FullPMMUName "FULLPMMU" /* voller PMMU-Befehlssatz */
+
+#define Mdata 1 /* Adressierungsmasken */
+#define Madr 2
+#define Madri 4
+#define Mpost 8
+#define Mpre 16
+#define Mdadri 32
+#define Maix 64
+#define Mpc 128
+#define Mpcidx 256
+#define Mabs 512
+#define Mimm 1024
+#define Mfpn 2048
+#define Mfpcr 4096
+
+static Byte OpSize;
+static ShortInt RelPos;
+static Boolean PMMUAvail; /* PMMU-Befehle erlaubt? */
+static Boolean FullPMMU; /* voller PMMU-Befehlssatz? */
+static Byte AdrNum; /* Adressierungsnummer */
+static Word AdrMode; /* Adressierungsmodus */
+static Word AdrVals[10]; /* die Worte selber */
+
+static FixedOrder *FixedOrders;
+static CtReg *CtRegs;
+static char **CondNams;
+static Byte *CondVals;
+static FPUOp *FPUOps;
+static FPUCond *FPUConds;
+static char **PMMUConds;
+static char **PMMURegNames;
+static Byte *PMMURegSizes;
+static Word *PMMURegCodes;
+static PInstTable InstTable,FInstTable,CInstTable;
+
+static SimpProc SaveInitProc;
+
+static CPUVar CPU68008,CPU68000,CPU68010,CPU68012,
+ CPUCOLD,
+ CPU68332,CPU68340,CPU68360,
+ CPU68020,CPU68030,CPU68040;
+
+static Word Masks[14]={0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096};
+static Byte FSizeCodes[8]={6,4,0,7,1,5,2,3};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBSTRCNT
+static int strcnt=0;
+
+ static int strccmp(const char *s1, const char *s2)
+BEGIN
+ strcnt++;
+ return strcmp(s1,s2);
+END
+
+#undef Memo
+#define strcmp(s1,s2) strccmp(s1,s2)
+#define Memo(s1) (strccmp(s1,OpPart)==0)
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Unterroutinen */
+
+#define CopyAdrVals(Dest) memcpy(Dest,AdrVals,AdrCnt)
+
+ static void ACheckCPU(CPUVar MinCPU)
+BEGIN
+ if (MomCPU<MinCPU)
+ BEGIN
+ WrError(1505); AdrNum=0; AdrCnt=0;
+ END
+END
+
+ static void CheckCPU(CPUVar Level)
+BEGIN
+ if (MomCPU<Level)
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+ static void Check020(void)
+BEGIN
+ if (MomCPU!=CPU68020)
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+ static void Check32(void)
+BEGIN
+ if ((MomCPU<CPU68332) OR (MomCPU>CPU68360))
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+ static void CheckSup(void)
+BEGIN
+ if (NOT SupAllowed) WrError(50);
+END
+
+ static Boolean CheckColdSize(void)
+BEGIN
+ if ((OpSize>2) OR ((MomCPU==CPUCOLD) AND (OpSize<2)))
+ BEGIN
+ WrError(1130); return False;
+ END
+ else return True;
+END
+
+/*-------------------------------------------------------------------------*/
+/* Adressparser */
+
+typedef enum {PC,AReg,Index,indir,Disp,None} CompType;
+typedef struct
+ {
+ String Name;
+ CompType Art;
+ Word ANummer,INummer;
+ Boolean Long;
+ Word Scale;
+ Word Size;
+ LongInt Wert;
+ } AdrComp;
+
+ static Boolean ValReg(char Ch)
+BEGIN
+ return ((Ch>='0') AND (Ch<='7'));
+END
+
+ static Boolean CodeReg(char *s, Word *Erg)
+BEGIN
+ Boolean Result=True;
+
+ if (strcasecmp(s,"SP")==0) *Erg=15;
+ else if (ValReg(s[1]))
+ if (toupper(*s)=='D') *Erg=s[1]-'0';
+ else if (toupper(*s)=='A') *Erg=s[1]-'0'+8;
+ else Result=False;
+ else Result=False;
+
+ return Result;
+END
+
+ static Boolean CodeRegPair(char *Asc, Word *Erg1, Word *Erg2)
+BEGIN
+ if (strlen(Asc)!=5) return False;
+ if (toupper(*Asc)!='D') return False;
+ if (Asc[2]!=':') return False;
+ if (toupper(Asc[3])!='D') return False;
+ if (NOT (ValReg(Asc[1]) AND ValReg(Asc[4]))) return False;
+
+ *Erg1=Asc[1]-'0'; *Erg2=Asc[4]-'0';
+
+ return True;
+END
+
+ static Boolean CodeIndRegPair(char *Asc, Word *Erg1, Word *Erg2)
+BEGIN
+ if (strlen(Asc)!=9) return False;
+ if (*Asc!='(') return False;
+ if ((toupper(Asc[1])!='D') AND (toupper(Asc[1])!='A')) return False;
+ if (Asc[3]!=')') return False;
+ if (Asc[4]!=':') return False;
+ if (Asc[5]!='(') return False;
+ if ((toupper(Asc[6])!='D') AND (toupper(Asc[6])!='A')) return False;
+ if (Asc[8]!=')') return False;
+ if (NOT (ValReg(Asc[2]) AND ValReg(Asc[7]))) return False;
+
+ *Erg1=Asc[2]-'0'; if (toupper(Asc[1])=='A') *Erg1+=8;
+ *Erg2=Asc[7]-'0'; if (toupper(Asc[6])=='A') *Erg2+=8;
+
+ return True;
+END
+
+ static Boolean CodeCache(char *Asc, Word *Erg)
+BEGIN
+ if (strcasecmp(Asc,"IC")==0) *Erg=2;
+ else if (strcasecmp(Asc,"DC")==0) *Erg=1;
+ else if (strcasecmp(Asc,"IC/DC")==0) *Erg=3;
+ else if (strcasecmp(Asc,"DC/IC")==0) *Erg=3;
+ else return False;
+ return True;
+END
+
+ static Boolean DecodeCtrlReg(char *Asc, Word *Erg)
+BEGIN
+ Byte z;
+ String Asc_N;
+ CtReg *Reg;
+
+ strmaxcpy(Asc_N,Asc,255); NLS_UpString(Asc_N); Asc=Asc_N;
+
+ for (z=0,Reg=CtRegs; z<CtRegCnt; z++,Reg++)
+ if (strcmp(Reg->Name,Asc)==0) break;
+ if (z>=CtRegCnt) return False;
+ if ((MomCPU<Reg->FirstCPU) OR (MomCPU>Reg->LastCPU)) return False;
+ *Erg=Reg->Code; return True;
+END
+
+ static int FindICondition(char *Name)
+BEGIN
+ int i;
+
+ for (i=0; i<CondCnt; i++)
+ if (strcmp(Name,CondNams[i])==0) break;
+
+ return i;
+END
+
+ static Boolean OneField(char *Asc, Word *Erg, Boolean Ab1)
+BEGIN
+ Boolean ValOK;
+
+ if ((strlen(Asc)==2) AND (toupper(*Asc)=='D') AND (ValReg(Asc[1])))
+ BEGIN
+ *Erg=0x20+(Asc[1]-'0'); return True;
+ END
+ else
+ BEGIN
+ *Erg=EvalIntExpression(Asc,Int8,&ValOK);
+ if ((Ab1) AND (*Erg==32)) *Erg=0;
+ return ((ValOK) AND (*Erg<32));
+ END
+END
+
+ static Boolean SplitBitField(char *Arg, Word *Erg)
+BEGIN
+ char *p;
+ Word OfsVal;
+ String Desc;
+
+ p = strchr(Arg, '{');
+ if (p == Nil) return False;
+ *p = '\0'; strcpy(Desc, p + 1);
+ if (Desc[strlen(Desc) - 1] != '}') return False;
+ Desc[strlen(Desc) - 1] = '\0';
+
+ p = strchr(Desc, ':');
+ if (p == Nil) return False;
+ *p = '\0';
+ if (NOT OneField(Desc, &OfsVal, False)) return False;
+ if (NOT OneField(p + 1, Erg, True)) return False;
+ *Erg += OfsVal << 6;
+ return True;
+END
+
+ static Boolean ClassComp(AdrComp *C)
+BEGIN
+ char sh[10];
+
+ if ((*C->Name=='[') AND (C->Name[strlen(C->Name)-1]==']'))
+ BEGIN
+ C->Art=indir; return True;
+ END
+
+ if (strcasecmp(C->Name,"PC")==0)
+ BEGIN
+ C->Art=PC; return True;
+ END
+
+ sh[0]=C->Name[0]; sh[1]=C->Name[1]; sh[2]='\0';
+ if (CodeReg(sh,&C->ANummer))
+ BEGIN
+ if ((C->ANummer>7) AND (strlen(C->Name)==2))
+ BEGIN
+ C->Art=AReg; C->ANummer-=8; return True;
+ END
+ else
+ BEGIN
+ if ((strlen(C->Name)>3) AND (C->Name[2]=='.'))
+ BEGIN
+ switch (toupper(C->Name[3]))
+ BEGIN
+ case 'L': C->Long=True; break;
+ case 'W': C->Long=False; break;
+ default: return False;
+ END
+ strcpy(C->Name+2,C->Name+4);
+ END
+ else C->Long=(MomCPU==CPUCOLD);
+ if ((strlen(C->Name)>3) AND (C->Name[2]=='*'))
+ BEGIN
+ switch (C->Name[3])
+ BEGIN
+ case '1': C->Scale=0; break;
+ case '2': C->Scale=1; break;
+ case '4': C->Scale=2; break;
+ case '8': if (MomCPU==CPUCOLD) return False;
+ C->Scale=3; break;
+ default: return False;
+ END
+ strcpy(C->Name+2,C->Name+4);
+ END
+ else C->Scale=0;
+ C->INummer=C->ANummer; C->Art=Index; return True;
+ END
+ END
+
+ C->Art=Disp;
+ if (C->Name[strlen(C->Name)-2]=='.')
+ BEGIN
+ switch (toupper(C->Name[strlen(C->Name)-1]))
+ BEGIN
+ case 'L': C->Size=2; break;
+ case 'W': C->Size=1; break;
+ default: return False;
+ END
+ C->Name[strlen(C->Name)-2]='\0';
+ END
+ else C->Size=1;
+ C->Art=Disp;
+ return True;
+END
+
+ static void ChkAdr(Word Erl)
+BEGIN
+ if ((Erl & Masks[AdrNum])==0)
+ BEGIN
+ WrError(1350); AdrNum=0;
+ END
+END
+
+ static Boolean IsShortAdr(LongInt Adr)
+BEGIN
+ Word WHi=(Adr>>16)&0xffff,WLo=Adr&0xffff;
+
+ return ((WHi==0 ) AND (WLo<=0x7fff))
+ OR ((WHi==0xffff) AND (WLo>=0x8000));
+END
+
+ static Boolean IsDisp8(LongInt Disp)
+BEGIN
+ return ((Disp>=-128) AND (Disp<=127));
+END
+
+ static Boolean IsDisp16(LongInt Disp)
+BEGIN
+ if (Disp<-32768) return False;
+ if (Disp>32767) return False;
+ return True;
+END
+
+ static void ChkEven(LongInt Adr)
+BEGIN
+ if ((MomCPU<=CPU68340) AND (Odd(Adr))) WrError(180);
+END
+
+ static void DecodeAdr(char *Asc_O, Word Erl)
+BEGIN
+ Byte l,i;
+ char *p;
+ Word rerg;
+ Byte lklamm,rklamm,lastrklamm;
+ Boolean doklamm;
+
+ AdrComp AdrComps[3],OneComp;
+ Byte CompCnt;
+ String OutDisp;
+ ShortInt OutDispLen;
+ Boolean PreInd;
+
+#ifdef HAS64
+ QuadInt QVal;
+#endif
+ LongInt HVal;
+ Integer HVal16;
+ ShortInt HVal8;
+ Double DVal;
+ Boolean ValOK;
+ Word SwapField[6];
+ String Asc;
+ char CReg[10];
+
+ strmaxcpy(Asc,Asc_O,255); KillBlanks(Asc);
+ l=strlen(Asc);
+ AdrNum=0; AdrCnt=0;
+
+ /* immediate : */
+
+ if (*Asc=='#')
+ BEGIN
+ strcpy(Asc,Asc+1);
+ AdrNum=11;
+ AdrMode=0x3c;
+ switch (OpSize)
+ BEGIN
+ case 0:
+ AdrCnt=2;
+ HVal8=EvalIntExpression(Asc,Int8,&ValOK);
+ if (ValOK) AdrVals[0]=(Word)((Byte) HVal8);
+ break;
+ case 1:
+ AdrCnt=2;
+ HVal16=EvalIntExpression(Asc,Int16,&ValOK);
+ if (ValOK) AdrVals[0]=(Word) HVal16;
+ break;
+ case 2:
+ AdrCnt=4;
+ HVal=EvalIntExpression(Asc,Int32,&ValOK);
+ if (ValOK)
+ BEGIN
+ AdrVals[0]=HVal >> 16;
+ AdrVals[1]=HVal & 0xffff;
+ END
+ break;
+#ifdef HAS64
+ case 3:
+ AdrCnt=8;
+ QVal=EvalIntExpression(Asc,Int64,&ValOK);
+ if (ValOK)
+ BEGIN
+ AdrVals[0]=(QVal >> 48) & 0xffff;
+ AdrVals[1]=(QVal >> 32) & 0xffff;
+ AdrVals[2]=(QVal >> 16) & 0xffff;
+ AdrVals[3]=(QVal ) & 0xffff;
+ END
+ break;
+#endif
+ case 4:
+ AdrCnt=4;
+ DVal=EvalFloatExpression(Asc,Float32,&ValOK);
+ if (ValOK)
+ BEGIN
+ Double_2_ieee4(DVal,(Byte *) SwapField,BigEndian);
+ if (BigEndian) DWSwap((Byte *) SwapField,4);
+ AdrVals[0]=SwapField[1];
+ AdrVals[1]=SwapField[0];
+ END
+ break;
+ case 5:
+ AdrCnt=8;
+ DVal=EvalFloatExpression(Asc,Float64,&ValOK);
+ if (ValOK)
+ BEGIN
+ Double_2_ieee8(DVal,(Byte *) SwapField,BigEndian);
+ if (BigEndian) QWSwap((Byte *) SwapField,8);
+ AdrVals[0]=SwapField[3];
+ AdrVals[1]=SwapField[2];
+ AdrVals[2]=SwapField[1];
+ AdrVals[3]=SwapField[0];
+ END
+ break;
+ case 6:
+ AdrCnt=12;
+ DVal=EvalFloatExpression(Asc,Float64,&ValOK);
+ if (ValOK)
+ BEGIN
+ Double_2_ieee10(DVal,(Byte *) SwapField,False);
+ if (BigEndian) WSwap((Byte *) SwapField,10);
+ AdrVals[0]=SwapField[4];
+ AdrVals[1]=0;
+ AdrVals[2]=SwapField[3];
+ AdrVals[3]=SwapField[2];
+ AdrVals[4]=SwapField[1];
+ AdrVals[5]=SwapField[0];
+ END
+ break;
+ case 7:
+ AdrCnt=12;
+ DVal=EvalFloatExpression(Asc,Float64,&ValOK);
+ if (ValOK)
+ BEGIN
+ ConvertDec(DVal,SwapField);
+ AdrVals[0]=SwapField[5];
+ AdrVals[1]=SwapField[4];
+ AdrVals[2]=SwapField[3];
+ AdrVals[3]=SwapField[2];
+ AdrVals[4]=SwapField[1];
+ AdrVals[5]=SwapField[0];
+ END
+ break;
+ END
+ ChkAdr(Erl); return;
+ END
+
+ /* CPU-Register direkt: */
+
+ if (CodeReg(Asc,&AdrMode))
+ BEGIN
+ AdrCnt=0; AdrNum=(AdrMode >> 3)+1; ChkAdr(Erl); return;
+ END
+
+ /* Gleitkommaregister direkt: */
+
+ if (strncasecmp(Asc,"FP",2)==0)
+ BEGIN
+ if ((strlen(Asc)==3) AND (ValReg(Asc[2])))
+ BEGIN
+ AdrMode=Asc[2]-'0'; AdrCnt=0; AdrNum=12; ChkAdr(Erl); return;
+ END;
+ if (strcasecmp(Asc,"FPCR")==0)
+ BEGIN
+ AdrMode=4; AdrNum=13; ChkAdr(Erl); return;
+ END
+ if (strcasecmp(Asc,"FPSR")==0)
+ BEGIN
+ AdrMode=2; AdrNum=13; ChkAdr(Erl); return;
+ END
+ if (strcasecmp(Asc,"FPIAR")==0)
+ BEGIN
+ AdrMode=1; AdrNum=13; ChkAdr(Erl); return;
+ END
+ END
+
+ /* Adressregister indirekt mit Predekrement: */
+
+ if ((l==5) AND (*Asc=='-') AND (Asc[1]=='(') AND (Asc[4]==')'))
+ BEGIN
+ strcpy(CReg,Asc+2); CReg[2]='\0';
+ if (CodeReg(CReg,&rerg))
+ if (rerg>7)
+ BEGIN
+ AdrMode=rerg+24; AdrCnt=0; AdrNum=5; ChkAdr(Erl); return;
+ END
+ END
+
+ /* Adressregister indirekt mit Postinkrement */
+
+ if ((l==5) AND (*Asc=='(') AND (Asc[3]==')') AND (Asc[4]=='+'))
+ BEGIN
+ strcpy(CReg,Asc+1); CReg[2]='\0';
+ if (CodeReg(CReg,&rerg))
+ if (rerg>7)
+ BEGIN
+ AdrMode=rerg+16; AdrCnt=0; AdrNum=4; ChkAdr(Erl); return;
+ END
+ END
+
+ /* Unterscheidung direkt<->indirekt: */
+
+ lklamm=0; rklamm=0; lastrklamm=0; doklamm=True;
+ for (p=Asc; *p!='\0'; p++)
+ BEGIN
+ if (*p=='[') doklamm=False;
+ if (*p==']') doklamm=True;
+ if (doklamm)
+ if (*p=='(') lklamm++;
+ else if (*p==')')
+ BEGIN
+ rklamm++; lastrklamm=p-Asc;
+ END
+ END
+
+ if ((lklamm==1) AND (rklamm==1) AND (lastrklamm==strlen(Asc)-1))
+ BEGIN
+
+ /* aeusseres Displacement abspalten, Klammern loeschen: */
+
+ p=strchr(Asc,'('); *p='\0'; strmaxcpy(OutDisp,Asc,255); strcpy(Asc,p+1);
+ if ((strlen(OutDisp)>2) AND (OutDisp[strlen(OutDisp)-2]=='.'))
+ BEGIN
+ switch (toupper(OutDisp[strlen(OutDisp)-1]))
+ BEGIN
+ case 'B': OutDispLen=0; break;
+ case 'W': OutDispLen=1; break;
+ case 'L': OutDispLen=2; break;
+ default:
+ WrError(1130); return;
+ END
+ OutDisp[strlen(OutDisp)-2]='\0';
+ END
+ else OutDispLen=-1;
+ Asc[strlen(Asc)-1]='\0';
+
+ /* in Komponenten zerteilen: */
+
+ CompCnt=0;
+ do
+ BEGIN
+ doklamm=True;
+ p=Asc;
+ do
+ BEGIN
+ if (*p=='[') doklamm=False;
+ else if (*p==']') doklamm=True;
+ p++;
+ END
+ while (((NOT doklamm) OR (*p!=',')) AND (*p!='\0'));
+ if (*p=='\0')
+ BEGIN
+ strcpy(AdrComps[CompCnt].Name,Asc); *Asc='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strcpy(AdrComps[CompCnt].Name,Asc); strcpy(Asc,p+1);
+ END
+ if (NOT ClassComp(AdrComps+CompCnt))
+ BEGIN
+ WrError(1350); return;
+ END
+ if ((CompCnt==1) AND (AdrComps[CompCnt].Art==AReg))
+ BEGIN
+ AdrComps[CompCnt].Art=Index;
+ AdrComps[CompCnt].INummer=AdrComps[CompCnt].ANummer+8;
+ AdrComps[CompCnt].Long=False;
+ AdrComps[CompCnt].Scale=0;
+ END
+ if ((AdrComps[CompCnt].Art==Disp) OR ((AdrComps[CompCnt].Art!=Index) AND (CompCnt!=0)))
+ BEGIN
+ WrError(1350); return;
+ END
+ CompCnt++;
+ END
+ while (*Asc!='\0');
+ if ((CompCnt>2) OR ((AdrComps[0].Art==Index) AND (CompCnt!=1)))
+ BEGIN
+ WrError(1350); return;
+ END
+
+ /* 1. Variante (An....), d(An....) */
+
+ if (AdrComps[0].Art==AReg)
+ BEGIN
+
+ /* 1.1. Variante (An), d(An) */
+
+ if (CompCnt==1)
+ BEGIN
+
+ /* 1.1.1. Variante (An) */
+
+ if ((*OutDisp=='\0') AND ((Madri & Erl)!=0))
+ BEGIN
+ AdrMode=0x10+AdrComps[0].ANummer; AdrNum=3; AdrCnt=0;
+ ChkAdr(Erl); return;
+ END
+
+ /* 1.1.2. Variante d(An) */
+
+ else
+ BEGIN
+ if ((OutDispLen < 0) OR (OutDispLen >= 2))
+ HVal = EvalIntExpression(OutDisp, SInt32, &ValOK);
+ else
+ HVal = EvalIntExpression(OutDisp, SInt16, &ValOK);
+ if (NOT ValOK)
+ BEGIN
+ WrError(1350); return;
+ END
+ if ((ValOK) AND (HVal==0) AND ((Madri & Erl)!=0) AND (OutDispLen==-1))
+ BEGIN
+ AdrMode=0x10+AdrComps[0].ANummer; AdrNum=3; AdrCnt=0;
+ ChkAdr(Erl); return;
+ END
+ if (OutDispLen == -1)
+ OutDispLen = (IsDisp16(HVal)) ? 1 : 2;
+ switch (OutDispLen)
+ BEGIN
+ case 1: /* d16(An) */
+ AdrMode=0x28+AdrComps[0].ANummer; AdrNum=6;
+ AdrCnt=2; AdrVals[0]=HVal&0xffff;
+ ChkAdr(Erl); return;
+ case 2: /* d32(An) */
+ AdrMode=0x30+AdrComps[0].ANummer; AdrNum=7;
+ AdrCnt=6; AdrVals[0]=0x0170;
+ AdrVals[1]=(HVal >> 16) & 0xffff; AdrVals[2]=HVal & 0xffff;
+ ACheckCPU(CPU68332); ChkAdr(Erl); return;
+ END
+ END
+ END
+
+ /* 1.2. Variante d(An,Xi) */
+
+ else
+ BEGIN
+ AdrVals[0]=(AdrComps[1].INummer << 12)+(Ord(AdrComps[1].Long) << 11)+(AdrComps[1].Scale << 9);
+ AdrMode=0x30+AdrComps[0].ANummer;
+ switch (OutDispLen)
+ BEGIN
+ case 0:
+ HVal = EvalIntExpression(OutDisp, SInt8, &ValOK);
+ break;
+ case 1:
+ HVal = EvalIntExpression(OutDisp, SInt16, &ValOK);
+ break;
+ default:
+ HVal = EvalIntExpression(OutDisp, SInt32, &ValOK);
+ END
+ if (ValOK)
+ BEGIN
+ if (OutDispLen == -1)
+ BEGIN
+ if (IsDisp8(HVal)) OutDispLen = 0;
+ else if (IsDisp16(HVal)) OutDispLen = 1;
+ else OutDispLen = 2;
+ END
+ switch (OutDispLen)
+ BEGIN
+ case 0:
+ AdrNum=7; AdrCnt=2; AdrVals[0]+=(HVal & 0xff);
+ if (AdrComps[1].Scale!=0) ACheckCPU(CPUCOLD);
+ ChkAdr(Erl); return;
+ case 1:
+ AdrNum=7; AdrCnt=4;
+ AdrVals[0]+=0x120; AdrVals[1]=HVal & 0xffff;
+ ACheckCPU(CPU68332);
+ ChkAdr(Erl); return;
+ case 2:
+ AdrNum=7; AdrCnt=6; AdrVals[0]+=0x130;
+ AdrVals[1]=HVal >> 16; AdrVals[2]=HVal & 0xffff;
+ ACheckCPU(CPU68332);
+ ChkAdr(Erl); return;
+ END
+ END
+ END
+ END
+
+ /* 2. Variante d(PC....) */
+
+ else if (AdrComps[0].Art==PC)
+ BEGIN
+
+ /* 2.1. Variante d(PC) */
+
+ if (CompCnt==1)
+ BEGIN
+ HVal=EvalIntExpression(OutDisp,Int32,&ValOK)-(EProgCounter()+RelPos);
+ if (NOT ValOK)
+ BEGIN
+ WrError(1350); return;
+ END
+ if (OutDispLen < 0)
+ OutDispLen = (IsDisp16(HVal)) ? 1 : 2;
+ switch (OutDispLen)
+ BEGIN
+ case 1:
+ AdrMode=0x3a;
+ if (NOT IsDisp16(HVal))
+ BEGIN
+ WrError(1330); return;
+ END
+ AdrNum=8; AdrCnt=2; AdrVals[0]=HVal & 0xffff;
+ ChkAdr(Erl); return;
+ case 2:
+ AdrMode=0x3b;
+ AdrNum=9; AdrCnt=6; AdrVals[0]=0x170;
+ AdrVals[1]=HVal >> 16; AdrVals[2]=HVal & 0xffff;
+ ACheckCPU(CPU68332); ChkAdr(Erl); return;
+ END
+ END
+
+ /* 2.2. Variante d(PC,Xi) */
+
+ else
+ BEGIN
+ AdrVals[0]=(AdrComps[1].INummer << 12)+(Ord(AdrComps[1].Long) << 11)+(AdrComps[1].Scale << 9);
+ HVal=EvalIntExpression(OutDisp,Int32,&ValOK)-(EProgCounter()+RelPos);
+ if (NOT ValOK)
+ BEGIN
+ WrError(1350); return;
+ END;
+ if (OutDispLen < 0)
+ BEGIN
+ if (IsDisp8(HVal)) OutDispLen = 0;
+ else if (IsDisp16(HVal)) OutDispLen = 1;
+ else OutDispLen = 2;
+ END
+ AdrMode=0x3b;
+ switch (OutDispLen)
+ BEGIN
+ case 0:
+ if (NOT IsDisp8(HVal))
+ BEGIN
+ WrError(1330); return;
+ END
+ AdrVals[0]+=(HVal & 0xff); AdrCnt=2; AdrNum=9;
+ if (AdrComps[1].Scale!=0) ACheckCPU(CPUCOLD);
+ ChkAdr(Erl); return;
+ case 1:
+ if (NOT IsDisp16(HVal))
+ BEGIN
+ WrError(1330); return;
+ END
+ AdrVals[0]+=0x120; AdrCnt=4; AdrNum=9;
+ AdrVals[1]=HVal & 0xffff;
+ ACheckCPU(CPU68332);
+ ChkAdr(Erl); return;
+ case 2:
+ AdrVals[0]=AdrVals[0]+0x120; AdrCnt=6; AdrNum=9;
+ AdrVals[1]=HVal >> 16; AdrVals[2]=HVal & 0xffff;
+ ACheckCPU(CPU68332);
+ ChkAdr(Erl); return;
+ END
+ END
+ END
+
+ /* 3. Variante (Xi), d(Xi) */
+
+ else if (AdrComps[0].Art==Index)
+ BEGIN
+ AdrVals[0]=(AdrComps[0].INummer << 12)+(Ord(AdrComps[0].Long) << 11)+(AdrComps[0].Scale << 9)+0x180;
+ AdrMode=0x30;
+ if (*OutDisp=='\0')
+ BEGIN
+ AdrVals[0]=AdrVals[0]+0x0010; AdrCnt=2;
+ AdrNum=7; ACheckCPU(CPU68332); ChkAdr(Erl); return;
+ END
+ else
+ BEGIN
+ if (OutDispLen != 1)
+ HVal = EvalIntExpression(OutDisp,SInt32,&ValOK);
+ else
+ HVal = EvalIntExpression(OutDisp,SInt16,&ValOK);
+ if (ValOK)
+ BEGIN
+ if (OutDispLen == -1)
+ BEGIN
+ if (IsDisp16(HVal)) OutDispLen = 1;
+ else OutDispLen = 2;
+ END
+ switch (OutDispLen)
+ BEGIN
+ case 0:
+ case 1:
+ AdrVals[0]=AdrVals[0]+0x0020; AdrVals[1]=HVal & 0xffff;
+ AdrNum=7; AdrCnt=4; ACheckCPU(CPU68332);
+ ChkAdr(Erl); return;
+ case 2:
+ AdrVals[0]=AdrVals[0]+0x0030; AdrNum=7; AdrCnt=6;
+ AdrVals[1]=HVal >> 16; AdrVals[2]=HVal & 0xffff;
+ ACheckCPU(CPU68332);
+ ChkAdr(Erl); return;
+ END
+ END
+ END
+ END
+
+ /* 4. Variante indirekt: */
+
+ else if (AdrComps[0].Art==indir)
+ BEGIN
+
+ /* erst ab 68020 erlaubt */
+
+ if (MomCPU<CPU68020)
+ BEGIN
+ WrError(1505); return;
+ END
+
+ /* Unterscheidung Vor- <---> Nachindizierung: */
+
+ if (CompCnt==2)
+ BEGIN
+ PreInd=False;
+ AdrComps[2]=AdrComps[1];
+ END
+ else
+ BEGIN
+ PreInd=True;
+ AdrComps[2].Art=None;
+ END
+
+ /* indirektes Argument herauskopieren: */
+
+ strcpy(Asc,AdrComps[0].Name+1);
+ Asc[strlen(Asc)-1]='\0';
+
+ /* Felder loeschen: */
+
+ for (i=0; i<2; AdrComps[i++].Art=None);
+
+ /* indirekten Ausdruck auseinanderfieseln: */
+
+ do
+ BEGIN
+
+ /* abschneiden & klassifizieren: */
+
+ p=strchr(Asc,',');
+ if (p==Nil)
+ BEGIN
+ strcpy(OneComp.Name,Asc); *Asc='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strcpy(OneComp.Name,Asc); strcpy(Asc,p+1);
+ END
+ if (NOT ClassComp(&OneComp))
+ BEGIN
+ WrError(1350); return;
+ END
+
+ /* passend einsortieren: */
+
+ if ((AdrComps[1].Art!=None) AND (OneComp.Art==AReg))
+ BEGIN
+ OneComp.Art=Index; OneComp.INummer=OneComp.ANummer+8;
+ OneComp.Long=False; OneComp.Scale=0;
+ END
+ switch (OneComp.Art)
+ BEGIN
+ case Disp : i=0; break;
+ case AReg :
+ case PC : i=1; break;
+ case Index : i=2; break;
+ default : i=(-1);
+ END
+ if (AdrComps[i].Art!=None)
+ BEGIN
+ WrError(1350); return;
+ END
+ else AdrComps[i]=OneComp;
+ END
+ while (*Asc!='\0');
+
+ /* Vor-oder Nachindizierung? */
+
+ AdrVals[0]=0x100+(Ord(PreInd) << 2);
+
+ /* Indexregister eintragen */
+
+ if (AdrComps[2].Art==None) AdrVals[0]+=0x40;
+ else AdrVals[0]+=(AdrComps[2].INummer << 12)+(Ord(AdrComps[2].Long) << 11)+(AdrComps[2].Scale << 9);
+
+ /* 4.1 Variante d([...PC...]...) */
+
+ if (AdrComps[1].Art==PC)
+ BEGIN
+ if (AdrComps[0].Art==None) HVal=0;
+ else HVal=EvalIntExpression(AdrComps[0].Name,Int32,&ValOK);
+ HVal-=EProgCounter()+RelPos;
+ if (NOT ValOK) return;
+ AdrMode=0x3b;
+ switch (AdrComps[0].Size)
+ BEGIN
+ case 1:
+ if (NOT IsDisp16(HVal))
+ BEGIN
+ WrError(1330); return;
+ END
+ AdrVals[1]=HVal & 0xffff; AdrVals[0]+=0x20; AdrNum=7; AdrCnt=4;
+ break;
+ case 2:
+ AdrVals[1]=HVal >> 16; AdrVals[2]=HVal & 0xffff;
+ AdrVals[0]+=0x30; AdrNum=7; AdrCnt=6;
+ break;
+ END
+ END
+
+ /* 4.2 Variante d([...An...]...) */
+
+ else
+ BEGIN
+ if (AdrComps[1].Art==None)
+ BEGIN
+ AdrMode=0x30; AdrVals[0]+=0x80;
+ END
+ else AdrMode=0x30+AdrComps[1].ANummer;
+
+ if (AdrComps[0].Art==None)
+ BEGIN
+ AdrNum=7; AdrCnt=2; AdrVals[0]+=0x10;
+ END
+ else switch (AdrComps[0].Size)
+ BEGIN
+ case 1:
+ HVal16=EvalIntExpression(AdrComps[0].Name,Int16,&ValOK);
+ if (NOT ValOK) return;
+ AdrNum=7; AdrVals[1]=HVal16; AdrCnt=4; AdrVals[0]+=0x20;
+ break;
+ case 2:
+ HVal=EvalIntExpression(AdrComps[0].Name,Int32,&ValOK);
+ if (NOT ValOK) return;
+ AdrNum=7; AdrCnt=6; AdrVals[0]+=0x30;
+ AdrVals[1]=HVal >> 16; AdrVals[2]=HVal & 0xffff;
+ break;
+ END
+ END
+
+ /* aeusseres Displacement: */
+
+ if (OutDispLen == 1)
+ HVal = EvalIntExpression(OutDisp, SInt16, &ValOK);
+ else
+ HVal = EvalIntExpression(OutDisp, SInt32, &ValOK);
+ if (NOT ValOK)
+ BEGIN
+ AdrNum=0; AdrCnt=0; return;
+ END;
+ if (OutDispLen == -1)
+ BEGIN
+ if (IsDisp16(HVal)) OutDispLen = 1;
+ else OutDispLen = 2;
+ END
+ if (*OutDisp=='\0')
+ BEGIN
+ AdrVals[0]++; ChkAdr(Erl); return;
+ END
+ else switch (OutDispLen)
+ BEGIN
+ case 0:
+ case 1:
+ AdrVals[AdrCnt >> 1]=HVal & 0xffff; AdrCnt+=2; AdrVals[0]+=2;
+ break;
+ case 2:
+ AdrVals[(AdrCnt >> 1) ]=HVal >> 16;
+ AdrVals[(AdrCnt >> 1)+1]=HVal & 0xffff;
+ AdrCnt+=4; AdrVals[0]+=3;
+ break;
+ END
+
+ ChkAdr(Erl); return;
+
+ END
+
+ END
+
+ /* absolut: */
+
+ else
+ BEGIN
+ AdrCnt=0;
+ if (strcasecmp(Asc+strlen(Asc)-2,".W")==0)
+ BEGIN
+ AdrCnt=2; Asc[strlen(Asc)-2]='\0';
+ END
+ else if (strcasecmp(Asc+strlen(Asc)-2,".L")==0)
+ BEGIN
+ AdrCnt=4; Asc[strlen(Asc)-2]='\0';
+ END
+
+ FirstPassUnknown=False;
+ HVal=EvalIntExpression(Asc,Int32,&ValOK);
+ if ((NOT FirstPassUnknown) AND (OpSize>0)) ChkEven(HVal);
+ HVal16=HVal;
+
+ if (ValOK)
+ BEGIN
+ if (AdrCnt==0) AdrCnt=(IsShortAdr(HVal))?2:4;
+ AdrNum=10;
+
+ if (AdrCnt==2)
+ BEGIN
+ if (NOT IsShortAdr(HVal))
+ BEGIN
+ WrError(1340); AdrNum=0;
+ END
+ else
+ BEGIN
+ AdrMode=0x38; AdrVals[0]=HVal16;
+ END
+ END
+ else
+ BEGIN
+ AdrMode=0x39; AdrVals[0]=HVal >> 16; AdrVals[1]=HVal & 0xffff;
+ END
+ END
+ END
+
+ ChkAdr(Erl);
+END
+
+ static Byte OneReg(char *Asc)
+BEGIN
+ if (strlen(Asc)!=2) return 16;
+ if ((toupper(*Asc)!='A') AND (toupper(*Asc)!='D')) return 16;
+ if (NOT ValReg(Asc[1])) return 16;
+ return Asc[1]-'0'+((toupper(*Asc)=='D')?0:8);
+END
+
+ static Boolean DecodeRegList(char *Asc_o, Word *Erg)
+BEGIN
+ static Word Masks[16]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
+ Byte h,h2,z;
+ char *p;
+ String Asc,s;
+
+ *Erg=0; strmaxcpy(Asc,Asc_o,255);
+ do
+ BEGIN
+ p=strchr(Asc,'/');
+ if (p==Nil)
+ BEGIN
+ strcpy(s,Asc); *Asc='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strcpy(s,Asc); strcpy(Asc,p+1);
+ END
+ if (*Asc=='/') strcpy(Asc,Asc+1);
+ p=strchr(s,'-');
+ if (p==Nil)
+ BEGIN
+ if ((h=OneReg(s))==16) return False;
+ *Erg|=Masks[h];
+ END
+ else
+ BEGIN
+ *p='\0';
+ if ((h=OneReg(s))==16) return False;
+ if ((h2=OneReg(p+1))==16) return False;
+ for (z=h; z<=h2; *Erg|=Masks[z++]);
+ END
+ END
+ while (*Asc!='\0');
+ return True;
+END
+
+/*-------------------------------------------------------------------------*/
+/* Dekodierroutinen: Integer-Einheit */
+
+/* 0=MOVE 1=MOVEA */
+
+ static void DecodeMOVE(Word Index)
+BEGIN
+ int z;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"USP")==0)
+ BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Madr);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x4e68 | (AdrMode & 7); CheckSup();
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"USP")==0)
+ BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madr);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x4e60 | (AdrMode & 7); CheckSup();
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"SR")==0)
+ BEGIN
+ if (OpSize!=1) WrError(1130);
+ else
+ BEGIN
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[2],Mdata);
+ else DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; WAsmCode[0]=0x40c0 | AdrMode;
+ CopyAdrVals(WAsmCode+1);
+ if (MomCPU>=CPU68010) CheckSup();
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"CCR")==0)
+ BEGIN
+ if ((*AttrPart!='\0') AND (OpSize>1)) WrError(1130);
+ else
+ BEGIN
+ OpSize=0;
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[2],Mdata);
+ else DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; WAsmCode[0]=0x42c0 | AdrMode;
+ CopyAdrVals(WAsmCode+1); CheckCPU(CPU68010);
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"SR")==0)
+ BEGIN
+ if (OpSize!=1) WrError(1130);
+ else
+ BEGIN
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[1],Mdata+Mimm);
+ else DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; WAsmCode[0]=0x46c0 | AdrMode;
+ CopyAdrVals(WAsmCode+1); CheckSup();
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"CCR")==0)
+ BEGIN
+ if ((*AttrPart!='\0') AND (OpSize>1)) WrError(1130);
+ else
+ BEGIN
+ OpSize=0;
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[1],Mdata+Mimm);
+ else DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; WAsmCode[0]=0x44c0 | AdrMode;
+ CopyAdrVals(WAsmCode+1);
+ END
+ END
+ END
+ else
+ BEGIN
+ if (OpSize>2) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ z=AdrCnt; CodeLen=2+z; CopyAdrVals(WAsmCode+1);
+ if (OpSize==0) WAsmCode[0]=0x1000;
+ else if (OpSize==1) WAsmCode[0]=0x3000;
+ else WAsmCode[0]=0x2000;
+ WAsmCode[0]|=AdrMode;
+ DecodeAdr(ArgStr[2],Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrMode!=0)
+ if ((MomCPU==CPUCOLD) AND (z>0) AND (AdrCnt>0)) WrError(1350);
+ else
+ BEGIN
+ AdrMode=((AdrMode & 7) << 3) | (AdrMode >> 3);
+ WAsmCode[0]|=AdrMode << 6;
+ CopyAdrVals(WAsmCode+(CodeLen >> 1));
+ CodeLen+=AdrCnt;
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeLEA(Word Index)
+BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Madr);
+ if (AdrNum!=0)
+ BEGIN
+ OpSize=0;
+ WAsmCode[0]=0x41c0 | ((AdrMode & 7) << 9);
+ DecodeAdr(ArgStr[1],Madri+Mdadri+Maix+Mpc+Mpcidx+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=AdrMode; CodeLen=2+AdrCnt;
+ CopyAdrVals(WAsmCode+1);
+ END
+ END
+ END
+END
+
+/* 0=ASR 1=ASL 2=LSR 3=LSL 4=ROXR 5=ROXL 6=ROR 7=ROL */
+
+ static void DecodeShift(Word Index)
+BEGIN
+ Boolean ValOK;
+ Byte HVal8;
+ Word LFlag=(Index>>2), Op=Index&3;
+
+ if (ArgCnt==1)
+ BEGIN
+ strcpy(ArgStr[2],ArgStr[1]); strcpy(ArgStr[1],"#1");
+ ArgCnt=2;
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if ((*OpPart=='R') AND (MomCPU==CPUCOLD)) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum==1)
+ BEGIN
+ if (CheckColdSize())
+ BEGIN
+ WAsmCode[0]=0xe000 | AdrMode | (Op << 3) | (OpSize << 6) | (LFlag << 8);
+ OpSize=1;
+ DecodeAdr(ArgStr[1],Mdata+Mimm);
+ if ((AdrNum==1) OR ((AdrNum==11) AND (Lo(AdrVals[0])>=1) AND (Lo(AdrVals[0])<=8)))
+ BEGIN
+ CodeLen=2;
+ WAsmCode[0] |= (AdrNum==1) ? 0x20|(AdrMode<<9) : ((AdrVals[0] & 7) << 9);
+ END
+ else WrError(1380);
+ END
+ END
+ else if (AdrNum!=0)
+ if (MomCPU==CPUCOLD) WrError(1350);
+ else
+ BEGIN
+ if (OpSize!=1) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0xe0c0 | AdrMode | (Op << 9) | (LFlag << 8);
+ CopyAdrVals(WAsmCode+1);
+ if (*ArgStr[1]=='#') strcpy(ArgStr[1],ArgStr[1]+1);
+ HVal8=EvalIntExpression(ArgStr[1],Int8,&ValOK);
+ if ((ValOK) AND (HVal8==1)) CodeLen=2+AdrCnt;
+ else WrError(1390);
+ END
+ END
+ END
+END
+
+/* ADDQ=0 SUBQ=1 */
+
+ static void DecodeADDQSUBQ(Word Index)
+BEGIN
+ Byte HVal8;
+ Boolean ValOK;
+
+ if (CheckColdSize())
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x5000 | AdrMode | (OpSize << 6) | (Index << 8);
+ CopyAdrVals(WAsmCode+1);
+ if (*ArgStr[1]=='#') strcpy(ArgStr[1],ArgStr[1]+1);
+ FirstPassUnknown=False;
+ HVal8=EvalIntExpression(ArgStr[1],UInt4,&ValOK);
+ if (FirstPassUnknown) HVal8=1;
+ if ((ValOK) AND (HVal8>=1) AND (HVal8<=8))
+ BEGIN
+ CodeLen=2+AdrCnt;
+ WAsmCode[0]|=(((Word) HVal8 & 7) << 9);
+ END
+ else WrError(1390);
+ END
+ END
+END
+
+/* 0=ADDX 1=SUBX */
+
+ static void DecodeADDXSUBX(Word Index)
+BEGIN
+ if (CheckColdSize())
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Mpre);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x9100 | (OpSize << 6) OR (AdrMode & 7) | (Index << 14);
+ if (AdrNum==5) WAsmCode[0]|=8;
+ DecodeAdr(ArgStr[2],Masks[AdrNum]);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2;
+ WAsmCode[0]|= (AdrMode & 7) << 9;
+ END
+ END
+ END
+END
+
+ static void DecodeCMPM(Word Index)
+BEGIN
+ if (OpSize>2) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mpost);
+ if (AdrNum==4)
+ BEGIN
+ WAsmCode[0]=0xb108 | (OpSize << 6) | (AdrMode & 7);
+ DecodeAdr(ArgStr[2],Mpost);
+ if (AdrNum==4)
+ BEGIN
+ WAsmCode[0]|=(AdrMode & 7) << 9;
+ CodeLen=2;
+ END
+ END
+ END
+END
+
+/* 0=SUB 1=CMP 2=ADD +4=..I +8=..A */
+
+ static void DecodeADDSUBCMP(Word Index)
+BEGIN
+ Word Op=Index&3;
+
+ if (CheckColdSize())
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum==2) /* ADDA ? */
+ if (OpSize==0) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0x90c0 | ((AdrMode & 7) << 9) | (Op << 13);
+ if (OpSize==2) WAsmCode[0]|=0x100;
+ DecodeAdr(ArgStr[1],Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=AdrMode; CodeLen=2+AdrCnt;
+ CopyAdrVals(WAsmCode+1);
+ END
+ END
+ else if (AdrNum==1) /* ADD <EA>,Dn ? */
+ BEGIN
+ WAsmCode[0]=0x9000 | (OpSize << 6) | (AdrMode << 9) | (Op << 13);
+ DecodeAdr(ArgStr[1],Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; CopyAdrVals(WAsmCode+1);
+ WAsmCode[0]|=AdrMode;
+ END
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Mimm);
+ if (AdrNum==11) /* ADDI ? */
+ BEGIN
+ if (Op==1) Op=8;
+ WAsmCode[0]=0x400 | (OpSize << 6) | (Op << 8);
+ CodeLen=2+AdrCnt;
+ CopyAdrVals(WAsmCode+1);
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[2],Mdata);
+ else DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=AdrMode;
+ CopyAdrVals(WAsmCode+(CodeLen >> 1));
+ CodeLen+=AdrCnt;
+ END
+ else CodeLen=0;
+ END
+ else if (AdrNum!=0) /* ADD Dn,<EA> ? */
+ BEGIN
+ if (Op==1) WrError(1420);
+ else
+ BEGIN
+ WAsmCode[0]=0x9100 | (OpSize << 6) | (AdrMode << 9) | (Op << 13);
+ DecodeAdr(ArgStr[2],Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; CopyAdrVals(WAsmCode+1);
+ WAsmCode[0]|=AdrMode;
+ END
+ END
+ END
+ END
+ END
+END
+
+/* 0=OR 1=AND +4=..I */
+
+ static void DecodeANDOR(Word Index)
+BEGIN
+ Word Op=Index&3;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckColdSize())
+ BEGIN
+ if ((strcasecmp(ArgStr[2],"CCR")!=0) AND (strcasecmp(ArgStr[2],"SR")!=0))
+ DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (strcasecmp(ArgStr[2],"CCR")==0) /* AND #...,CCR */
+ BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=0)) WrError(1130);
+ else if ((MomCPU==CPU68008) OR (MomCPU==CPUCOLD)) WrError(1500);
+ else
+ BEGIN
+ WAsmCode[0] = 0x003c | (Op << 9);
+ OpSize=0; DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=4; WAsmCode[1]=AdrVals[0];
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"SR")==0) /* AND #...,SR */
+ BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=1)) WrError(1130);
+ else if ((MomCPU==CPU68008) OR (MomCPU==CPUCOLD)) WrError(1500);
+ else
+ BEGIN
+ WAsmCode[0] = 0x007c | (Op << 9);
+ OpSize=1; DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=4; WAsmCode[1]=AdrVals[0]; CheckSup();
+ END
+ END
+ END
+ else if (AdrNum==1) /* AND <EA>,Dn */
+ BEGIN
+ WAsmCode[0]=0x8000 | (OpSize << 6) | (AdrMode << 9) | (Op << 14);
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=AdrMode;
+ CodeLen=2+AdrCnt; CopyAdrVals(WAsmCode+1);
+ END
+ END
+ else if (AdrNum!=0) /* AND ...,<EA> */
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Mimm);
+ if (AdrNum==11) /* AND #..,<EA> */
+ BEGIN
+ WAsmCode[0]=(OpSize << 6) | (Op << 9);
+ CodeLen=2+AdrCnt;
+ CopyAdrVals(WAsmCode+1);
+ DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=AdrMode;
+ CopyAdrVals(WAsmCode+(CodeLen >> 1));
+ CodeLen+=AdrCnt;
+ END
+ else CodeLen=0;
+ END
+ else if (AdrNum!=0) /* AND Dn,<EA> ? */
+ BEGIN
+ WAsmCode[0]=0x8100 | (OpSize << 6) | (AdrMode << 9) | (Op << 14);
+ DecodeAdr(ArgStr[2],Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; CopyAdrVals(WAsmCode+1);
+ WAsmCode[0]|=AdrMode;
+ END
+ END
+ END
+ END
+END
+
+/* 0=EOR 4=EORI */
+
+ static void DecodeEOR(Word Index)
+BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[2],"CCR")==0)
+ BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=0)) WrError(1130);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ WAsmCode[0]=0xa3c; OpSize=0;
+ DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=4; WAsmCode[1]=AdrVals[0];
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"SR")==0)
+ BEGIN
+ if (OpSize!=1) WrError(1130);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ WAsmCode[0]=0xa7c;
+ DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=4; WAsmCode[1]=AdrVals[0]; CheckSup();
+ CheckCPU(CPU68000);
+ END
+ END
+ END
+ else if (CheckColdSize())
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Mimm);
+ if (AdrNum==1)
+ BEGIN
+ WAsmCode[0]=0xb100 | (AdrMode << 9) | (OpSize << 6);
+ DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; CopyAdrVals(WAsmCode+1);
+ WAsmCode[0]|=AdrMode;
+ END
+ END
+ else if (AdrNum==11)
+ BEGIN
+ WAsmCode[0]=0x0a00 | (OpSize << 6);
+ CopyAdrVals(WAsmCode+1); CodeLen=2+AdrCnt;
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[2],Mdata);
+ else DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CopyAdrVals(WAsmCode+(CodeLen >> 1));
+ CodeLen+=AdrCnt;
+ WAsmCode[0]|=AdrMode;
+ END
+ else CodeLen=0;
+ END
+ END
+END
+
+ static void DecodePEA(Word Index)
+BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ OpSize=0;
+ DecodeAdr(ArgStr[1],Madri+Mdadri+Maix+Mpc+Mpcidx+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt;
+ WAsmCode[0]=0x4840 | AdrMode;
+ CopyAdrVals(WAsmCode+1);
+ END
+ END
+END
+
+/* 0=CLR 1=TST */
+
+ static void DecodeCLRTST(Word Index)
+BEGIN
+ Word w1;
+
+ if (OpSize>2) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ w1=Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs;
+ if ((Index==1) AND (OpSize>0) AND (MomCPU>=CPU68332))
+ w1+=Madr+Mpc+Mpcidx+Mimm;
+ DecodeAdr(ArgStr[1],w1);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt;
+ WAsmCode[0]=0x4200 | (Index << 11) | (OpSize << 6) | AdrMode;
+ CopyAdrVals(WAsmCode+1);
+ END
+ END
+END
+
+/* 0=JSR 1=JMP */
+
+ static void DecodeJSRJMP(Word Index)
+BEGIN
+ if (*AttrPart!='\0') WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri+Mdadri+Maix+Mpc+Mpcidx+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt;
+ WAsmCode[0]=0x4e80 | (Index << 6) | AdrMode;
+ CopyAdrVals(WAsmCode+1);
+ END
+ END
+END
+
+/* 0=TAS 1=NBCD */
+
+ static void DecodeNBCDTAS(Word Index)
+BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=0)) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ OpSize=0;
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt;
+ WAsmCode[0]=(Index==1) ? 0x4800 : 0x4ac0;
+ WAsmCode[0]|=AdrMode;
+ CopyAdrVals(WAsmCode+1);
+ END
+ END
+END
+
+/* 0=NEGX 2=NEG 3=NOT */
+
+ static void DecodeNEGNOT(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckColdSize())
+ BEGIN
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[1],Mdata);
+ else DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt;
+ WAsmCode[0]=0x4000 | (Index << 9) | (OpSize << 6) | AdrMode;
+ CopyAdrVals(WAsmCode+1);
+ END
+ END
+END
+
+ static void DecodeSWAP(Word Index)
+BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x4840 | AdrMode;
+ END
+ END
+END
+
+ static void DecodeUNLK(Word Index)
+BEGIN
+ if (*AttrPart!='\0') WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madr);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x4e58 | AdrMode;
+ END
+ END
+END
+
+ static void DecodeEXT(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if ((OpSize==0) OR (OpSize>2)) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata);
+ if (AdrNum==1)
+ BEGIN
+ WAsmCode[0]=0x4880 | AdrMode | (((Word)OpSize-1) << 6);
+ CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeWDDATA(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU!=CPUCOLD) WrError(1500);
+ else if (OpSize>2) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf400+(OpSize << 6)+AdrMode;
+ CopyAdrVals(WAsmCode+1); CodeLen=2+AdrCnt;
+ CheckSup();
+ END
+ END
+END
+
+ static void DecodeWDEBUG(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU!=CPUCOLD) WrError(1500);
+ else if (CheckColdSize())
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri+Mdadri);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xfbc0+AdrMode; WAsmCode[1]=0x0003;
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt;
+ CheckSup();
+ END
+ END
+END
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *FixedZ=FixedOrders+Index;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=0) WrError(1110);
+ else if ((FixedZ->CPUMask &(1 << (MomCPU-CPU68008)))==0) WrError(1500);
+ else
+ BEGIN
+ CodeLen=2; WAsmCode[0]=FixedZ->Code;
+ if (FixedZ->MustSup) CheckSup();
+ END
+END
+
+ static void DecodeMOVEM(Word Index)
+BEGIN
+ int z;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if ((OpSize<1) OR (OpSize>2)) WrError(1130);
+ else if ((MomCPU==CPUCOLD) AND (OpSize==1)) WrError(1130);
+ else
+ BEGIN
+ if (DecodeRegList(ArgStr[2],WAsmCode+1))
+ BEGIN
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[1],Madri+Mdadri);
+ else DecodeAdr(ArgStr[1],Madri+Mpost+Mdadri+Maix+Mpc+Mpcidx+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x4c80 | AdrMode | ((OpSize-1) << 6);
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ END
+ END
+ else if (DecodeRegList(ArgStr[1],WAsmCode+1))
+ BEGIN
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[2],Madri+Mdadri);
+ else DecodeAdr(ArgStr[2],Madri+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x4880 | AdrMode | ((OpSize-1) << 6);
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ if (AdrNum==5)
+ BEGIN
+ WAsmCode[9]=WAsmCode[1]; WAsmCode[1]=0;
+ for (z=0; z<16; z++)
+ BEGIN
+ WAsmCode[1]=WAsmCode[1] << 1;
+ if ((WAsmCode[9]&1)==1) WAsmCode[1]++;
+ WAsmCode[9]=WAsmCode[9] >> 1;
+ END
+ END
+ END
+ END
+ else WrError(1410);
+ END
+END
+
+ static void DecodeMOVEQ(Word Index)
+BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x7000 | (AdrMode << 9);
+ OpSize=0;
+ DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2; WAsmCode[0]|=AdrVals[0];
+ END
+ END
+ END
+END
+
+ static void DecodeSTOP(Word Index)
+BEGIN
+ Word HVal;
+ Boolean ValOK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ HVal=EvalIntExpression(ArgStr[1]+1,Int16,&ValOK);
+ if (ValOK)
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0x4e72; WAsmCode[1]=HVal; CheckSup();
+ END
+ END
+END
+
+ static void DecodeLPSTOP(Word Index)
+BEGIN
+ Word HVal;
+ Boolean ValOK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ HVal=EvalIntExpression(ArgStr[1]+1,Int16,&ValOK);
+ if (ValOK)
+ BEGIN
+ CodeLen=6;
+ WAsmCode[0]=0xf800;
+ WAsmCode[1]=0x01c0;
+ WAsmCode[2]=HVal;
+ CheckSup(); Check32();
+ END
+ END
+END
+
+ static void DecodeTRAP(Word Index)
+BEGIN
+ Byte HVal8;
+ Boolean ValOK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ HVal8=EvalIntExpression(ArgStr[1]+1,Int4,&ValOK);
+ if (ValOK)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x4e40+(HVal8 & 15);
+ END
+ END
+END
+
+ static void DecodeBKPT(Word Index)
+BEGIN
+ Byte HVal8;
+ Boolean ValOK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ HVal8=EvalIntExpression(ArgStr[1]+1,UInt3,&ValOK);
+ if (ValOK)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x4848+(HVal8 & 7);
+ CheckCPU(CPU68010);
+ END
+ END
+END
+
+ static void DecodeRTD(Word Index)
+BEGIN
+ Word HVal;
+ Boolean ValOK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ HVal=EvalIntExpression(ArgStr[1]+1,Int16,&ValOK);
+ if (ValOK)
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0x4e74; WAsmCode[1]=HVal;
+ CheckCPU(CPU68010);
+ END
+ END
+END
+
+ static void DecodeEXG(Word Index)
+BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Madr);
+ if (AdrNum==1)
+ BEGIN
+ WAsmCode[0]=0xc100 | (AdrMode << 9);
+ DecodeAdr(ArgStr[2],Mdata+Madr);
+ if (AdrNum==1)
+ BEGIN
+ WAsmCode[0]|=0x40 | AdrMode; CodeLen=2;
+ END
+ else if (AdrNum==2)
+ BEGIN
+ WAsmCode[0]|=0x88 | (AdrMode & 7); CodeLen=2;
+ END
+ END
+ else if (AdrNum==2)
+ BEGIN
+ WAsmCode[0]=0xc100 | (AdrMode & 7);
+ DecodeAdr(ArgStr[2],Mdata+Madr);
+ if (AdrNum==1)
+ BEGIN
+ WAsmCode[0]|=0x88 OR (AdrMode << 9); CodeLen=2;
+ END
+ else
+ BEGIN
+ WAsmCode[0]|=0x48 | ((AdrMode & 7) << 9); CodeLen=2;
+ END
+ END
+ END
+END
+
+ static void DecodeMOVE16(Word Index)
+BEGIN
+ Word z,z2,w1,w2;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mpost+Madri+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ w1=AdrNum; z=AdrMode & 7;
+ if ((w1==10) AND (AdrCnt==2))
+ BEGIN
+ AdrVals[1]=AdrVals[0];
+ AdrVals[0]=0-(AdrVals[1] >> 15);
+ END
+ DecodeAdr(ArgStr[2],Mpost+Madri+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ w2=AdrNum; z2=AdrMode & 7;
+ if ((w2==10) AND (AdrCnt==2))
+ BEGIN
+ AdrVals[1]=AdrVals[0];
+ AdrVals[0]=0-(AdrVals[1] >> 15);
+ END
+ if ((w1==4) AND (w2==4))
+ BEGIN
+ WAsmCode[0]=0xf620+z;
+ WAsmCode[1]=0x8000+(z2 << 12);
+ CodeLen=4;
+ END
+ else
+ BEGIN
+ WAsmCode[1]=AdrVals[0]; WAsmCode[2]=AdrVals[1];
+ CodeLen=6;
+ if ((w1==4) AND (w2==10)) WAsmCode[0]=0xf600+z;
+ else if ((w1==10) AND (w2==4)) WAsmCode[0]=0xf608+z2;
+ else if ((w1==3) AND (w2==10)) WAsmCode[0]=0xf610+z;
+ else if ((w1==10) AND (w2==3)) WAsmCode[0]=0xf618+z2;
+ else
+ BEGIN
+ WrError(1350); CodeLen=0;
+ END
+ END
+ if (CodeLen>0) CheckCPU(CPU68040);
+ END
+ END
+ END
+END
+
+ static void DecodeCacheAll(Word Index)
+BEGIN
+ Word w1;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (NOT CodeCache(ArgStr[1],&w1)) WrXError(1440,ArgStr[1]);
+ else
+ BEGIN
+ WAsmCode[0]=0xf418+(w1 << 6)+(Index << 5);
+ CodeLen=2;
+ CheckCPU(CPU68040); CheckSup();
+ END
+END
+
+ static void DecodeCache(Word Index)
+BEGIN
+ Word w1;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT CodeCache(ArgStr[1],&w1)) WrXError(1440,ArgStr[1]);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Madri);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf400+(w1 << 6)+(Index << 3)+(AdrMode & 7);
+ CodeLen=2;
+ CheckCPU(CPU68040); CheckSup();
+ END
+ END
+END
+
+ static void DecodeDIVL(Word Index)
+BEGIN
+ Word w1,w2;
+
+ if (*AttrPart=='\0') OpSize=2;
+ if (ArgCnt!=2) WrError(1110);
+ else if (OpSize!=2) WrError(1130);
+ else if (NOT CodeRegPair(ArgStr[2],&w1,&w2)) WrXError(1760, ArgStr[2]);
+ else
+ BEGIN
+ RelPos=4;
+ WAsmCode[1]=w1|(w2 << 12)|(Index << 11);
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x4c40+AdrMode;
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt;
+ CheckCPU(CPU68332);
+ END
+ END
+END
+
+ static void DecodeASBCD(Word Index)
+BEGIN
+ if ((OpSize!=0) AND (*AttrPart!='\0')) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ OpSize=0;
+ DecodeAdr(ArgStr[1],Mdata+Mpre);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x8100 | (AdrMode & 7) | (Index << 14);
+ if (AdrNum==5) WAsmCode[0]|=8;
+ DecodeAdr(ArgStr[2],Masks[AdrNum]);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2;
+ WAsmCode[0]|=(AdrMode & 7) << 9;
+ END
+ END
+ END
+END
+
+ static void DecodeCHK(Word Index)
+BEGIN
+ if (OpSize!=1) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x4180 | AdrMode; CodeLen=2+AdrCnt;
+ CopyAdrVals(WAsmCode+1);
+ DecodeAdr(ArgStr[2],Mdata);
+ if (AdrNum==1) WAsmCode[0]|=WAsmCode[0] | (AdrMode << 9);
+ else CodeLen=0;
+ END
+ END
+END
+
+ static void DecodeLINK(Word Index)
+BEGIN
+ if ((*AttrPart=='\0') AND (MomCPU==CPUCOLD)) OpSize=1;
+ if ((OpSize<1) OR (OpSize>2)) WrError(1130);
+ else if ((OpSize==2) AND (MomCPU<CPU68332)) WrError(1500);
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madr);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=(OpSize==1) ? 0x4e50 : 0x4808;
+ WAsmCode[0]+=AdrMode & 7;
+ DecodeAdr(ArgStr[2],Mimm);
+ if (AdrNum==11)
+ BEGIN
+ CodeLen=2+AdrCnt; memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ END
+ END
+ END
+END
+
+ static void DecodeMOVEP(Word Index)
+BEGIN
+ if ((OpSize==0) OR (OpSize>2)) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Mdadri);
+ if (AdrNum==1)
+ BEGIN
+ WAsmCode[0]=0x188 | ((OpSize-1) << 6) | (AdrMode << 9);
+ DecodeAdr(ArgStr[2],Mdadri);
+ if (AdrNum==6)
+ BEGIN
+ WAsmCode[0]|=AdrMode & 7;
+ CodeLen=4; WAsmCode[1]=AdrVals[0];
+ END
+ END
+ else if (AdrNum==6)
+ BEGIN
+ WAsmCode[0]=0x108 | ((OpSize-1) << 6) | (AdrMode & 7);
+ WAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],Mdata);
+ if (AdrNum==1)
+ BEGIN
+ WAsmCode[0]|=(AdrMode & 7) << 9;
+ CodeLen=4;
+ END
+ END
+ END
+END
+
+ static void DecodeMOVEC(Word Index)
+BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ BEGIN
+ if (DecodeCtrlReg(ArgStr[1],WAsmCode+1))
+ BEGIN
+ DecodeAdr(ArgStr[2],Mdata+Madr);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0x4e7a;
+ WAsmCode[1]|=AdrMode << 12; CheckSup();
+ END
+ END
+ else if (DecodeCtrlReg(ArgStr[2],WAsmCode+1))
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Madr);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0x4e7b;
+ WAsmCode[1]|=AdrMode << 12; CheckSup();
+ END
+ END
+ else WrError(1440);
+ END
+END
+
+ static void DecodeMOVES(Word Index)
+BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (OpSize>2) WrError(1130);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if ((AdrNum==1) OR (AdrNum==2))
+ BEGIN
+ WAsmCode[1]=0x800 | (AdrMode << 12);
+ DecodeAdr(ArgStr[2],Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xe00 | AdrMode | (OpSize << 6); CodeLen=4+AdrCnt;
+ CopyAdrVals(WAsmCode+2); CheckSup();
+ CheckCPU(CPU68010);
+ END
+ END
+ else if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xe00 | AdrMode | (OpSize << 6);
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ DecodeAdr(ArgStr[2],Mdata+Madr);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[1]=AdrMode << 12;
+ CheckSup();
+ CheckCPU(CPU68010);
+ END
+ else CodeLen=0;
+ END
+ END
+END
+
+ static void DecodeCALLM(Word Index)
+BEGIN
+ if (*AttrPart!='\0') WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OpSize=0;
+ DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[1]=AdrVals[0]; RelPos=4;
+ DecodeAdr(ArgStr[2],Madri+Mdadri+Maix+Mpc+Mpcidx+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x06c0+AdrMode;
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt;
+ CheckCPU(CPU68020); Check020();
+ END
+ END
+ END
+END
+
+ static void DecodeCAS(Word Index)
+BEGIN
+ if (OpSize>2) WrError(1130);
+ else if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[1]=AdrMode;
+ DecodeAdr(ArgStr[2],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ RelPos=4;
+ WAsmCode[1]+=(((Word)AdrMode) << 6);
+ DecodeAdr(ArgStr[3],Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x08c0+AdrMode+(((Word)OpSize+1) << 9);
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt;
+ CheckCPU(CPU68020);
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeCAS2(Word Index)
+BEGIN
+ Word w1,w2;
+
+ if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else if (ArgCnt!=3) WrError(1110);
+ else if (NOT CodeRegPair(ArgStr[1],WAsmCode+1,WAsmCode+2)) WrXError(1760, ArgStr[1]);
+ else if (NOT CodeRegPair(ArgStr[2],&w1,&w2)) WrXError(1760, ArgStr[2]);
+ else
+ BEGIN
+ WAsmCode[1]+=(w1 << 6);
+ WAsmCode[2]+=(w2 << 6);
+ if (NOT CodeIndRegPair(ArgStr[3],&w1,&w2)) WrXError(1760, ArgStr[3]);
+ else
+ BEGIN
+ WAsmCode[1]+=(w1 << 12);
+ WAsmCode[2]+=(w2 << 12);
+ WAsmCode[0]=0x0cfc+(((Word)OpSize-1) << 9);
+ CodeLen=6;
+ CheckCPU(CPU68020);
+ END
+ END
+END
+
+ static void DecodeCMPCHK2(Word Index)
+BEGIN
+ if (OpSize>2) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Mdata+Madr);
+ if (AdrNum!=0)
+ BEGIN
+ RelPos=4;
+ WAsmCode[1]=(((Word)AdrMode) << 12) | (Index << 11);
+ DecodeAdr(ArgStr[1],Madri+Mdadri+Maix+Mpc+Mpcidx+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x00c0+(((Word)OpSize) << 9)+AdrMode;
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt;
+ CheckCPU(CPU68332);
+ END
+ END
+ END
+END
+
+ static void DecodeEXTB(Word Index)
+BEGIN
+ if ((OpSize!=2) AND (*AttrPart!='\0')) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x49c0+AdrMode; CodeLen=2;
+ CheckCPU(CPU68332);
+ END
+ END
+END
+
+ static void DecodePACK(Word Index)
+BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Mpre);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=(0x8140+(Index<<6)) | (AdrMode & 7);
+ if (AdrNum==5) WAsmCode[0]+=8;
+ DecodeAdr(ArgStr[2],Masks[AdrNum]);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=((AdrMode & 7) << 9);
+ DecodeAdr(ArgStr[3],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[1]=AdrVals[0]; CodeLen=4;
+ CheckCPU(CPU68020);
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeRTM(Word Index)
+BEGIN
+ if (*AttrPart!='\0') WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Madr);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x06c0+AdrMode; CodeLen=2;
+ CheckCPU(CPU68020); Check020();
+ END
+ END
+END
+
+ static void DecodeTBL(Word Index)
+BEGIN
+ char *p;
+ Word w2,Mode;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (OpSize>2) WrError(1130);
+ else if (MomCPU<CPU68332) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ Mode=AdrMode;
+ p=strchr(ArgStr[1],':');
+ if (p==0)
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri+Mdadri+Maix+Mabs+Mpc+Mpcidx);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf800+AdrMode;
+ WAsmCode[1]=0x0100+(OpSize << 6)+(Mode << 12)+(Index << 10);
+ memcpy(WAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=4+AdrCnt; Check32();
+ END
+ END
+ else
+ BEGIN
+ strcpy(ArgStr[3],p+1); *p='\0';
+ DecodeAdr(ArgStr[1],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ w2=AdrMode;
+ DecodeAdr(ArgStr[3],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf800+w2;
+ WAsmCode[1]=0x0000+(OpSize << 6)+(Mode << 12)+AdrMode;
+ if (OpPart[3]=='S') WAsmCode[1]+=0x0800;
+ if (OpPart[strlen(OpPart)-1]=='N') WAsmCode[1]+=0x0400;
+ CodeLen=4; Check32();
+ END
+ END
+ END
+ END
+ END
+END
+
+/* 0=BTST 1=BCHG 2=BCLR 3=BSET */
+
+ static void DecodeBits(Word Index)
+BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (*AttrPart=='\0') OpSize=0;
+ if (Index!=0) DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ else DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs);
+ if (*AttrPart=='\0') OpSize=(AdrNum==1) ? 2 : 0;
+ if (AdrNum!=0)
+ BEGIN
+ if (((AdrNum==1) AND (OpSize!=2)) OR ((AdrNum!=1) AND (OpSize!=0))) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=AdrMode+(Index << 6);
+ CodeLen=2+AdrCnt; CopyAdrVals(WAsmCode+1);
+ OpSize=0;
+ DecodeAdr(ArgStr[1],Mdata+Mimm);
+ if (AdrNum==1)
+ BEGIN
+ WAsmCode[0]|=0x100 | (AdrMode << 9);
+ END
+ else if (AdrNum==11)
+ BEGIN
+ memmove(WAsmCode+2,WAsmCode+1,CodeLen-2); WAsmCode[1]=AdrVals[0];
+ WAsmCode[0]|=0x800;
+ CodeLen+=2;
+ if ((AdrVals[0]>31)
+ OR (((WAsmCode[0] & 0x38)!=0) AND (AdrVals[0]>7)))
+ BEGIN
+ CodeLen=0; WrError(1510);
+ END
+ END
+ else CodeLen=0;
+ END
+ END
+ END
+END
+
+/* 0=BFTST 1=BFCHG 2=BFCLR 3=BFSET */
+
+ static void DecodeFBits(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else if (NOT SplitBitField(ArgStr[1],WAsmCode+1)) WrError(1750);
+ else
+ BEGIN
+ RelPos=4;
+ OpSize=0;
+ if (Memo("BFTST")) DecodeAdr(ArgStr[1],Mdata+Madri+Mdadri+Maix+Mpc+Mpcidx+Mabs);
+ else DecodeAdr(ArgStr[1],Mdata+Madri+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xe8c0 | AdrMode | (Index << 10);
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt;
+ CheckCPU(CPU68020);
+ END
+ END
+END
+
+/* 0=BFEXTU 1=BFEXTS 2=BFFFO */
+
+ static void DecodeEBits(Word Index)
+BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else if (NOT SplitBitField(ArgStr[1],WAsmCode+1)) WrError(1750);
+ else
+ BEGIN
+ RelPos=4;
+ OpSize=0;
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xe9c0+AdrMode+(Index << 9); CopyAdrVals(WAsmCode+2);
+ CodeLen=4+AdrCnt;
+ DecodeAdr(ArgStr[2],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[1]|=AdrMode << 12;
+ CheckCPU(CPU68020);
+ END
+ else CodeLen=0;
+ END
+ END
+END
+
+ static void DecodeBFINS(Word Index)
+BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else if (NOT SplitBitField(ArgStr[2],WAsmCode+1)) WrError(1750);
+ else
+ BEGIN
+ OpSize=0;
+ DecodeAdr(ArgStr[2],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xefc0+AdrMode; CopyAdrVals(WAsmCode+2);
+ CodeLen=4+AdrCnt;
+ DecodeAdr(ArgStr[1],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[1]|=AdrMode << 12;
+ CheckCPU(CPU68020);
+ END
+ else CodeLen=0;
+ END
+ END
+END
+
+static Word CondIndex;
+ static void DecodeCondition(Word Index)
+BEGIN
+ CondIndex=Index;
+END
+
+/*-------------------------------------------------------------------------*/
+/* Dekodierroutinen Gleitkommaeinheit */
+
+ static void DecodeFPUOp(Word Index)
+BEGIN
+ FPUOp *Op=FPUOps+Index;
+
+ if ((ArgCnt==1) AND (NOT Op->Dya))
+ BEGIN
+ strcpy(ArgStr[2],ArgStr[1]); ArgCnt=2;
+ END
+ if (*AttrPart=='\0') OpSize=6;
+ if (OpSize==3) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Mfpn);
+ if (AdrNum==12)
+ BEGIN
+ WAsmCode[0]=0xf200;
+ WAsmCode[1]=Op->Code | (AdrMode << 7);
+ RelPos=4;
+ DecodeAdr(ArgStr[1],((OpSize<=2) OR (OpSize==4))?
+ Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm+Mfpn:
+ Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm+Mfpn);
+ if (AdrNum==12)
+ BEGIN
+ WAsmCode[1]|=AdrMode << 10;
+ if (OpSize==6) CodeLen=4; else WrError(1130);
+ CheckCPU(Op->MinCPU);
+ END
+ else if (AdrNum!=0)
+ BEGIN
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ WAsmCode[0]|=AdrMode;
+ WAsmCode[1]|=0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
+ CheckCPU(Op->MinCPU);
+ END
+ END
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/* Dekodierroutinen Pseudoinstruktionen: */
+
+ static void PutByte(Byte b)
+BEGIN
+ if (((CodeLen&1)==1) AND (NOT BigEndian))
+ BEGIN
+ BAsmCode[CodeLen]=BAsmCode[CodeLen-1];
+ BAsmCode[CodeLen-1]=b;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=b;
+ END
+ CodeLen++;
+END
+
+ static void DecodeSTR(Word Index)
+BEGIN
+ int l,z;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if ((l=strlen(ArgStr[1]))<2) WrError(1135);
+ else if (*ArgStr[1]!='\'') WrError(1135);
+ else if (ArgStr[1][l-1]!='\'') WrError(1135);
+ else
+ BEGIN
+ PutByte(l-2);
+ for (z=1; z<l-1; z++)
+ PutByte(CharTransTable[((usint) ArgStr[1][z])&0xff]);
+ if ((Odd(CodeLen)) AND (DoPadding)) PutByte(0);
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/* Codetabellenverwaltung */
+
+ static void AddFixed(char *NName, Word NCode, Boolean NSup, Word NMask)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ].MustSup=NSup;
+ FixedOrders[InstrZ].CPUMask=NMask;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
+END
+
+ static void AddCtReg(char *NName, Word NCode, CPUVar NFirst, CPUVar NLast)
+BEGIN
+ if (InstrZ>=CtRegCnt) exit(255);
+ CtRegs[InstrZ].Name=NName;
+ CtRegs[InstrZ].Code=NCode;
+ CtRegs[InstrZ].FirstCPU=NFirst;
+ CtRegs[InstrZ++].LastCPU=NLast;
+END
+
+ static void AddCond(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=CondCnt) exit(255);
+ AddInstTable(CInstTable,NName,NCode,DecodeCondition);
+ CondNams[InstrZ]=NName;
+ CondVals[InstrZ++]=NCode;
+END
+
+ static void AddFPUOp(char *NName, Byte NCode, Boolean NDya, CPUVar NMin)
+BEGIN
+ if (InstrZ >= FPUOpCnt) exit(255);
+ FPUOps[InstrZ].Name = NName;
+ FPUOps[InstrZ].Code = NCode;
+ FPUOps[InstrZ].Dya = NDya;
+ FPUOps[InstrZ].MinCPU = NMin;
+ AddInstTable(FInstTable, NName, InstrZ++, DecodeFPUOp);
+END
+
+ static void AddFPUCond(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=FPUCondCnt) exit(255);
+ FPUConds[InstrZ].Name=NName;
+ FPUConds[InstrZ++].Code=NCode;
+END
+
+ static void AddPMMUCond(char *NName)
+BEGIN
+ if (InstrZ>=PMMUCondCnt) exit(255);
+ PMMUConds[InstrZ++]=NName;
+END
+
+ static void AddPMMUReg(char *Name, Byte Size, Word Code)
+BEGIN
+ if (InstrZ>=PMMURegCnt) exit(255);
+ PMMURegNames[InstrZ]=Name;
+ PMMURegSizes[InstrZ]=Size;
+ PMMURegCodes[InstrZ++]=Code;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(201);
+ FInstTable=CreateInstTable(201);
+ CInstTable=CreateInstTable(47);
+
+ AddInstTable(InstTable,"MOVE" ,0,DecodeMOVE);
+ AddInstTable(InstTable,"MOVEA" ,1,DecodeMOVE);
+ AddInstTable(InstTable,"LEA" ,0,DecodeLEA);
+ AddInstTable(InstTable,"ASR" ,0,DecodeShift);
+ AddInstTable(InstTable,"ASL" ,4,DecodeShift);
+ AddInstTable(InstTable,"LSR" ,1,DecodeShift);
+ AddInstTable(InstTable,"LSL" ,5,DecodeShift);
+ AddInstTable(InstTable,"ROXR" ,2,DecodeShift);
+ AddInstTable(InstTable,"ROXL" ,6,DecodeShift);
+ AddInstTable(InstTable,"ROR" ,3,DecodeShift);
+ AddInstTable(InstTable,"ROL" ,7,DecodeShift);
+ AddInstTable(InstTable,"ADDQ" ,0,DecodeADDQSUBQ);
+ AddInstTable(InstTable,"SUBQ" ,1,DecodeADDQSUBQ);
+ AddInstTable(InstTable,"ADDX" ,0,DecodeADDXSUBX);
+ AddInstTable(InstTable,"SUBX" ,1,DecodeADDXSUBX);
+ AddInstTable(InstTable,"CMPM" ,0,DecodeCMPM);
+ AddInstTable(InstTable,"SUB" ,0,DecodeADDSUBCMP);
+ AddInstTable(InstTable,"CMP" ,1,DecodeADDSUBCMP);
+ AddInstTable(InstTable,"ADD" ,2,DecodeADDSUBCMP);
+ AddInstTable(InstTable,"SUBI" ,4,DecodeADDSUBCMP);
+ AddInstTable(InstTable,"CMPI" ,5,DecodeADDSUBCMP);
+ AddInstTable(InstTable,"ADDI" ,6,DecodeADDSUBCMP);
+ AddInstTable(InstTable,"SUBA" ,8,DecodeADDSUBCMP);
+ AddInstTable(InstTable,"CMPA" ,9,DecodeADDSUBCMP);
+ AddInstTable(InstTable,"ADDA" ,10,DecodeADDSUBCMP);
+ AddInstTable(InstTable,"AND" ,1,DecodeANDOR);
+ AddInstTable(InstTable,"OR" ,0,DecodeANDOR);
+ AddInstTable(InstTable,"ANDI" ,5,DecodeANDOR);
+ AddInstTable(InstTable,"ORI" ,4,DecodeANDOR);
+ AddInstTable(InstTable,"EOR" ,0,DecodeEOR);
+ AddInstTable(InstTable,"EORI" ,4,DecodeEOR);
+ AddInstTable(InstTable,"PEA" ,0,DecodePEA);
+ AddInstTable(InstTable,"CLR" ,0,DecodeCLRTST);
+ AddInstTable(InstTable,"TST" ,1,DecodeCLRTST);
+ AddInstTable(InstTable,"JSR" ,0,DecodeJSRJMP);
+ AddInstTable(InstTable,"JMP" ,1,DecodeJSRJMP);
+ AddInstTable(InstTable,"TAS" ,0,DecodeNBCDTAS);
+ AddInstTable(InstTable,"NBCD" ,1,DecodeNBCDTAS);
+ AddInstTable(InstTable,"NEGX" ,0,DecodeNEGNOT);
+ AddInstTable(InstTable,"NEG" ,2,DecodeNEGNOT);
+ AddInstTable(InstTable,"NOT" ,3,DecodeNEGNOT);
+ AddInstTable(InstTable,"SWAP" ,0,DecodeSWAP);
+ AddInstTable(InstTable,"UNLK" ,0,DecodeUNLK);
+ AddInstTable(InstTable,"EXT" ,0,DecodeEXT);
+ AddInstTable(InstTable,"WDDATA" ,0,DecodeWDDATA);
+ AddInstTable(InstTable,"WDEBUG" ,0,DecodeWDEBUG);
+ AddInstTable(InstTable,"MOVEM" ,0,DecodeMOVEM);
+ AddInstTable(InstTable,"MOVEQ" ,0,DecodeMOVEQ);
+ AddInstTable(InstTable,"STOP" ,0,DecodeSTOP);
+ AddInstTable(InstTable,"LPSTOP" ,0,DecodeLPSTOP);
+ AddInstTable(InstTable,"TRAP" ,0,DecodeTRAP);
+ AddInstTable(InstTable,"BKPT" ,0,DecodeBKPT);
+ AddInstTable(InstTable,"RTD" ,0,DecodeRTD);
+ AddInstTable(InstTable,"EXG" ,0,DecodeEXG);
+ AddInstTable(InstTable,"MOVE16" ,0,DecodeMOVE16);
+ AddInstTable(InstTable,"DIVUL" ,0,DecodeDIVL);
+ AddInstTable(InstTable,"DIVSL" ,1,DecodeDIVL);
+ AddInstTable(InstTable,"ABCD" ,1,DecodeASBCD);
+ AddInstTable(InstTable,"SBCD" ,0,DecodeASBCD);
+ AddInstTable(InstTable,"CHK" ,0,DecodeCHK);
+ AddInstTable(InstTable,"LINK" ,0,DecodeLINK);
+ AddInstTable(InstTable,"MOVEP" ,0,DecodeMOVEP);
+ AddInstTable(InstTable,"MOVEC" ,0,DecodeMOVEC);
+ AddInstTable(InstTable,"MOVES" ,0,DecodeMOVES);
+ AddInstTable(InstTable,"CALLM" ,0,DecodeCALLM);
+ AddInstTable(InstTable,"CAS" ,0,DecodeCAS);
+ AddInstTable(InstTable,"CAS2" ,0,DecodeCAS2);
+ AddInstTable(InstTable,"CMP2" ,0,DecodeCMPCHK2);
+ AddInstTable(InstTable,"CHK2" ,1,DecodeCMPCHK2);
+ AddInstTable(InstTable,"EXTB" ,0,DecodeEXTB);
+ AddInstTable(InstTable,"PACK" ,0,DecodePACK);
+ AddInstTable(InstTable,"UNPK" ,1,DecodePACK);
+ AddInstTable(InstTable,"RTM" ,0,DecodeRTM);
+ AddInstTable(InstTable,"TBLU" ,0,DecodeTBL);
+ AddInstTable(InstTable,"TBLUN" ,1,DecodeTBL);
+ AddInstTable(InstTable,"TBLS" ,2,DecodeTBL);
+ AddInstTable(InstTable,"TBLSN" ,3,DecodeTBL);
+ AddInstTable(InstTable,"BTST" ,0,DecodeBits);
+ AddInstTable(InstTable,"BSET" ,3,DecodeBits);
+ AddInstTable(InstTable,"BCLR" ,2,DecodeBits);
+ AddInstTable(InstTable,"BCHG" ,1,DecodeBits);
+ AddInstTable(InstTable,"BFTST" ,0,DecodeFBits);
+ AddInstTable(InstTable,"BFSET" ,3,DecodeFBits);
+ AddInstTable(InstTable,"BFCLR" ,2,DecodeFBits);
+ AddInstTable(InstTable,"BFCHG" ,1,DecodeFBits);
+ AddInstTable(InstTable,"BFEXTU" ,0,DecodeEBits);
+ AddInstTable(InstTable,"BFEXTS" ,1,DecodeEBits);
+ AddInstTable(InstTable,"BFFFO" ,2,DecodeEBits);
+ AddInstTable(InstTable,"BFINS" ,0,DecodeBFINS);
+ AddInstTable(InstTable,"CINVA" ,0,DecodeCacheAll);
+ AddInstTable(InstTable,"CPUSHA" ,1,DecodeCacheAll);
+ AddInstTable(InstTable,"CINVL" ,1,DecodeCache);
+ AddInstTable(InstTable,"CPUSHL" ,5,DecodeCache);
+ AddInstTable(InstTable,"CINVP" ,2,DecodeCache);
+ AddInstTable(InstTable,"CPUSHP" ,6,DecodeCache);
+ AddInstTable(InstTable,"STR" ,0,DecodeSTR);
+
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("NOP" ,0x4e71,False,0x07ff);
+ AddFixed("RESET" ,0x4e70,False,0x07ef);
+ AddFixed("ILLEGAL",0x4afc,False,0x07ff);
+ AddFixed("TRAPV" ,0x4e76,False,0x07ef);
+ AddFixed("RTE" ,0x4e73,True ,0x07ff);
+ AddFixed("RTR" ,0x4e77,False,0x07ef);
+ AddFixed("RTS" ,0x4e75,False,0x07ff);
+ AddFixed("BGND" ,0x4afa,False,0x00e0);
+ AddFixed("HALT" ,0x4ac8,True ,0x0010);
+ AddFixed("PULSE" ,0x4acc,True ,0x0010);
+
+ CtRegs=(CtReg *) malloc(sizeof(CtReg)*CtRegCnt); InstrZ=0;
+ AddCtReg("SFC" ,0x000, CPU68010, CPU68040);
+ AddCtReg("DFC" ,0x001, CPU68010, CPU68040);
+ AddCtReg("CACR" ,0x002, CPU68020, CPU68040);
+ AddCtReg("TC" ,0x003, CPU68040, CPU68040);
+ AddCtReg("ITT0" ,0x004, CPU68040, CPU68040);
+ AddCtReg("ITT1" ,0x005, CPU68040, CPU68040);
+ AddCtReg("DTT0" ,0x006, CPU68040, CPU68040);
+ AddCtReg("DTT1" ,0x007, CPU68040, CPU68040);
+ AddCtReg("USP" ,0x800, CPU68010, CPU68040);
+ AddCtReg("VBR" ,0x801, CPU68010, CPU68040);
+ AddCtReg("CAAR" ,0x802, CPU68020, CPU68030);
+ AddCtReg("MSP" ,0x803, CPU68020, CPU68040);
+ AddCtReg("ISP" ,0x804, CPU68020, CPU68040);
+ AddCtReg("MMUSR",0x805, CPU68040, CPU68040);
+ AddCtReg("URP" ,0x806, CPU68040, CPU68040);
+ AddCtReg("SRP" ,0x807, CPU68040, CPU68040);
+ AddCtReg("IACR0",0x004, CPU68040, CPU68040);
+ AddCtReg("IACR1",0x005, CPU68040, CPU68040);
+ AddCtReg("DACR0",0x006, CPU68040, CPU68040);
+ AddCtReg("DACR1",0x007, CPU68040, CPU68040);
+ AddCtReg("TCR" ,0x003, CPUCOLD , CPUCOLD );
+ AddCtReg("ACR2" ,0x004, CPUCOLD , CPUCOLD );
+ AddCtReg("ACR3" ,0x005, CPUCOLD , CPUCOLD );
+ AddCtReg("ACR0" ,0x006, CPUCOLD , CPUCOLD );
+ AddCtReg("ACR1" ,0x007, CPUCOLD , CPUCOLD );
+ AddCtReg("ROMBAR",0xc00,CPUCOLD , CPUCOLD );
+ AddCtReg("RAMBAR0",0xc04,CPUCOLD, CPUCOLD );
+ AddCtReg("RAMBAR1",0xc05,CPUCOLD, CPUCOLD );
+ AddCtReg("MBAR" ,0xc0f, CPUCOLD , CPUCOLD );
+
+ CondNams=(char **) malloc(sizeof(char *)*CondCnt);
+ CondVals=(Byte *) malloc(sizeof(Byte)*CondCnt); InstrZ=0;
+ AddCond("T" , 0); AddCond("F" , 1); AddCond("HI", 2); AddCond("LS", 3);
+ AddCond("CC", 4); AddCond("CS", 5); AddCond("NE", 6); AddCond("EQ", 7);
+ AddCond("VC", 8); AddCond("VS", 9); AddCond("PL",10); AddCond("MI",11);
+ AddCond("GE",12); AddCond("LT",13); AddCond("GT",14); AddCond("LE",15);
+ AddCond("HS", 4); AddCond("LO", 5); AddCond("RA", 0); AddCond("SR", 1);
+
+ FPUOps=(FPUOp *) malloc(sizeof(FPUOp)*FPUOpCnt); InstrZ=0;
+ AddFPUOp("INT" ,0x01, False, CPU68000); AddFPUOp("SINH" ,0x02, False, CPU68000);
+ AddFPUOp("INTRZ" ,0x03, False, CPU68000); AddFPUOp("SQRT" ,0x04, False, CPU68000);
+ AddFPUOp("LOGNP1",0x06, False, CPU68000); AddFPUOp("ETOXM1",0x08, False, CPU68000);
+ AddFPUOp("TANH" ,0x09, False, CPU68000); AddFPUOp("ATAN" ,0x0a, False, CPU68000);
+ AddFPUOp("ASIN" ,0x0c, False, CPU68000); AddFPUOp("ATANH" ,0x0d, False, CPU68000);
+ AddFPUOp("SIN" ,0x0e, False, CPU68000); AddFPUOp("TAN" ,0x0f, False, CPU68000);
+ AddFPUOp("ETOX" ,0x10, False, CPU68000); AddFPUOp("TWOTOX",0x11, False, CPU68000);
+ AddFPUOp("TENTOX",0x12, False, CPU68000); AddFPUOp("LOGN" ,0x14, False, CPU68000);
+ AddFPUOp("LOG10" ,0x15, False, CPU68000); AddFPUOp("LOG2" ,0x16, False, CPU68000);
+ AddFPUOp("ABS" ,0x18, False, CPU68000); AddFPUOp("COSH" ,0x19, False, CPU68000);
+ AddFPUOp("NEG" ,0x1a, False, CPU68000); AddFPUOp("ACOS" ,0x1c, False, CPU68000);
+ AddFPUOp("COS" ,0x1d, False, CPU68000); AddFPUOp("GETEXP",0x1e, False, CPU68000);
+ AddFPUOp("GETMAN",0x1f, False, CPU68000); AddFPUOp("DIV" ,0x20, True , CPU68000);
+ AddFPUOp("SDIV" ,0x60, False, CPU68040); AddFPUOp("DDIV" ,0x64, True , CPU68040);
+ AddFPUOp("MOD" ,0x21, True , CPU68000); AddFPUOp("ADD" ,0x22, True , CPU68000);
+ AddFPUOp("SADD" ,0x62, True , CPU68040); AddFPUOp("DADD" ,0x66, True , CPU68040);
+ AddFPUOp("MUL" ,0x23, True , CPU68000); AddFPUOp("SMUL" ,0x63, True , CPU68040);
+ AddFPUOp("DMUL" ,0x67, True , CPU68040); AddFPUOp("SGLDIV",0x24, True , CPU68000);
+ AddFPUOp("REM" ,0x25, True , CPU68000); AddFPUOp("SCALE" ,0x26, True , CPU68000);
+ AddFPUOp("SGLMUL",0x27, True , CPU68000); AddFPUOp("SUB" ,0x28, True , CPU68000);
+ AddFPUOp("SSUB" ,0x68, True , CPU68040); AddFPUOp("DSUB" ,0x6c, True , CPU68040);
+ AddFPUOp("CMP" ,0x38, True , CPU68000);
+
+ FPUConds=(FPUCond *) malloc(sizeof(FPUCond)*FPUCondCnt); InstrZ=0;
+ AddFPUCond("EQ" , 0x01); AddFPUCond("NE" , 0x0e);
+ AddFPUCond("GT" , 0x12); AddFPUCond("NGT" , 0x1d);
+ AddFPUCond("GE" , 0x13); AddFPUCond("NGE" , 0x1c);
+ AddFPUCond("LT" , 0x14); AddFPUCond("NLT" , 0x1b);
+ AddFPUCond("LE" , 0x15); AddFPUCond("NLE" , 0x1a);
+ AddFPUCond("GL" , 0x16); AddFPUCond("NGL" , 0x19);
+ AddFPUCond("GLE" , 0x17); AddFPUCond("NGLE", 0x18);
+ AddFPUCond("OGT" , 0x02); AddFPUCond("ULE" , 0x0d);
+ AddFPUCond("OGE" , 0x03); AddFPUCond("ULT" , 0x0c);
+ AddFPUCond("OLT" , 0x04); AddFPUCond("UGE" , 0x0b);
+ AddFPUCond("OLE" , 0x05); AddFPUCond("UGT" , 0x0a);
+ AddFPUCond("OGL" , 0x06); AddFPUCond("UEQ" , 0x09);
+ AddFPUCond("OR" , 0x07); AddFPUCond("UN" , 0x08);
+
+ PMMUConds=(char **) malloc(sizeof(char *)*PMMUCondCnt); InstrZ=0;
+ AddPMMUCond("BS"); AddPMMUCond("BC"); AddPMMUCond("LS"); AddPMMUCond("LC");
+ AddPMMUCond("SS"); AddPMMUCond("SC"); AddPMMUCond("AS"); AddPMMUCond("AC");
+ AddPMMUCond("WS"); AddPMMUCond("WC"); AddPMMUCond("IS"); AddPMMUCond("IC");
+ AddPMMUCond("GS"); AddPMMUCond("GC"); AddPMMUCond("CS"); AddPMMUCond("CC");
+
+ PMMURegNames=(char **) malloc(sizeof(char *)*PMMURegCnt);
+ PMMURegSizes=(Byte *) malloc(sizeof(Byte)*PMMURegCnt);
+ PMMURegCodes=(Word *) malloc(sizeof(Word)*PMMURegCnt); InstrZ=0;
+ AddPMMUReg("TC" ,2,16); AddPMMUReg("DRP" ,3,17);
+ AddPMMUReg("SRP" ,3,18); AddPMMUReg("CRP" ,3,19);
+ AddPMMUReg("CAL" ,0,20); AddPMMUReg("VAL" ,0,21);
+ AddPMMUReg("SCC" ,0,22); AddPMMUReg("AC" ,1,23);
+ AddPMMUReg("PSR" ,1,24); AddPMMUReg("PCSR" ,1,25);
+ AddPMMUReg("TT0" ,2, 2); AddPMMUReg("TT1" ,2, 3);
+ AddPMMUReg("MMUSR",1,24);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable); DestroyInstTable(FInstTable);
+ DestroyInstTable(CInstTable);
+ free(FixedOrders);
+ free(CtRegs);
+ free(CondNams); free(CondVals);
+ free(FPUOps);
+ free(FPUConds);
+ free(PMMUConds);
+ free(PMMURegNames); free(PMMURegSizes); free(PMMURegCodes);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+/*-------------------------------------------------------------------------*/
+
+
+ static Boolean DecodeOneFPReg(char *Asc, Byte * h)
+BEGIN
+ if ((strlen(Asc)==3) AND (strncasecmp(Asc,"FP",2)==0) AND ValReg(Asc[2]))
+ BEGIN
+ *h=Asc[2]-'0'; return True;
+ END
+ else return False;
+END
+
+ static void DecodeFRegList(char *Asc_o, Byte *Typ, Byte *Erg)
+BEGIN
+ String s,Asc;
+ Word hw;
+ Byte h2,h3,z;
+ char *h1;
+
+ strmaxcpy(Asc,Asc_o,255);
+ *Typ=0; if (*Asc=='\0') return;
+
+ if ((strlen(Asc)==2) AND (*Asc=='D') AND ValReg(Asc[1]))
+ BEGIN
+ *Typ = 1; *Erg = (Asc[1]-'0') << 4; return;
+ END;
+
+ hw=0;
+ do
+ BEGIN
+ h1=strchr(Asc,'/');
+ if (h1==Nil)
+ BEGIN
+ strcpy(s,Asc); *Asc='\0';
+ END
+ else
+ BEGIN
+ *h1='\0'; strcpy(s,Asc); strcpy(Asc,h1+1);
+ END
+ if (strcasecmp(s,"FPCR")==0) hw|=0x400;
+ else if (strcasecmp(s,"FPSR")==0) hw|=0x200;
+ else if (strcasecmp(s,"FPIAR")==0) hw|=0x100;
+ else
+ BEGIN
+ h1=strchr(s,'-');
+ if (h1==Nil)
+ BEGIN
+ if (NOT DecodeOneFPReg(s,&h2)) return;
+ hw|=(1 << (7-h2));
+ END
+ else
+ BEGIN
+ *h1='\0';
+ if (NOT DecodeOneFPReg(s,&h2)) return;
+ if (NOT DecodeOneFPReg(h1+1,&h3)) return;
+ for (z=h2; z<=h3; z++) hw|=(1 << (7-z));
+ END
+ END
+ END
+ while (*Asc!='\0');
+ if (Hi(hw)==0)
+ BEGIN
+ *Typ=2; *Erg=Lo(hw);
+ END
+ else if (Lo(hw)==0)
+ BEGIN
+ *Typ=3; *Erg=Hi(hw);
+ END
+END
+
+ static void GenerateMovem(Byte z1, Byte z2)
+BEGIN
+ Byte hz2,z;
+
+ if (AdrNum==0) return;
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ WAsmCode[0]=0xf200 | AdrMode;
+ switch (z1)
+ BEGIN
+ case 1:
+ case 2:
+ WAsmCode[1]|=0xc000;
+ if (z1==1) WAsmCode[1]|=0x800;
+ if (AdrNum!=5) WAsmCode[1]|=0x1000;
+ if ((AdrNum==5) AND (z1==2))
+ BEGIN
+ hz2=z2; z2=0;
+ for (z=0; z<8; z++)
+ BEGIN
+ z2=z2 << 1; if ((hz2&1)==1) z2|=1;
+ hz2=hz2 >> 1;
+ END
+ END
+ WAsmCode[1]|=z2;
+ break;
+ case 3:
+ WAsmCode[1]|=0x8000 | (((Word)z2) << 10);
+ END
+END
+
+ static void DecodeFPUOrders(void)
+BEGIN
+ Byte z,z1,z2;
+ char *p;
+ String sk;
+ LongInt HVal;
+ Integer HVal16;
+ Boolean ValOK;
+ Word Mask;
+
+ if (LookupInstTable(FInstTable,OpPart)) return;
+
+ if (Memo("SAVE"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; WAsmCode[0]=0xf300 | AdrMode;
+ CopyAdrVals(WAsmCode+1); CheckSup();
+ END
+ END
+ return;
+ END
+
+ if (Memo("RESTORE"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri+Mpost+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; WAsmCode[0]=0xf340 | AdrMode;
+ CopyAdrVals(WAsmCode+1); CheckSup();
+ END
+ END
+ return;
+ END
+
+ if (Memo("NOP"))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0xf280; WAsmCode[1]=0;
+ END
+ return;
+ END
+
+ if (Memo("MOVE"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (OpSize==3) WrError(1130);
+ else
+ BEGIN
+ p=strchr(AttrPart,'{');
+ if (p!=0) /* k-Faktor abspalten */
+ BEGIN
+ strcpy(sk,p); *p='\0';
+ END
+ else *sk='\0';
+ DecodeAdr(ArgStr[2],Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Maix+Mabs+Mfpn+Mfpcr);
+ if (AdrNum==12) /* FMOVE.x <ea>/FPm,FPn ? */
+ BEGIN
+ WAsmCode[0]=0xf200; WAsmCode[1]=AdrMode << 7;
+ RelPos=4;
+ if (*AttrPart=='\0') OpSize=6;
+ DecodeAdr(ArgStr[1],((OpSize<=2) OR (OpSize==4))?
+ Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm+Mfpn:
+ Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm+Mfpn);
+ if (AdrNum==12) /* FMOVE.X FPm,FPn ? */
+ BEGIN
+ WAsmCode[1]|=AdrMode << 10;
+ if (OpSize==6) CodeLen=4; else WrError(1130);
+ END
+ else if (AdrNum!=0) /* FMOVE.x <ea>,FPn ? */
+ BEGIN
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ WAsmCode[0]|=AdrMode;
+ WAsmCode[1]|=0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
+ END
+ END
+ else if (AdrNum==13) /* FMOVE.L <ea>,FPcr ? */
+ BEGIN
+ if ((OpSize!=2) AND (*AttrPart!='\0')) WrError(1130);
+ else
+ BEGIN
+ RelPos=4;
+ WAsmCode[0]=0xf200; WAsmCode[1]=0x8000 | (AdrMode << 10);
+ DecodeAdr(ArgStr[1],(AdrMode==1)?
+ Mdata+Madr+Madri+Mpost+Mpre+Mdadri+Mpc+Mpcidx+Mabs+Mimm:
+ Mdata+Madri+Mpost+Mpre+Mdadri+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=AdrMode; CodeLen=4+AdrCnt;
+ CopyAdrVals(WAsmCode+2);
+ END
+ END
+ END
+ else if (AdrNum!=0) /* FMOVE.x ????,<ea> ? */
+ BEGIN
+ WAsmCode[0]=0xf200 | AdrMode;
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ DecodeAdr(ArgStr[1], (AdrNum == 2) ? Mfpcr : Mfpn + Mfpcr);
+ if (AdrNum==12) /* FMOVE.x FPn,<ea> ? */
+ BEGIN
+ if (*AttrPart=='\0') OpSize=6;
+ WAsmCode[1]=0x6000 | (((Word)FSizeCodes[OpSize]) << 10) | (AdrMode << 7);
+ if (OpSize==7)
+ if (strlen(sk)>2)
+ BEGIN
+ OpSize=0; strcpy(sk,sk+1); sk[strlen(sk)-1]='\0';
+ DecodeAdr(sk,Mdata+Mimm);
+ if (AdrNum==1) WAsmCode[1]|=(AdrMode << 4) | 0x1000;
+ else if (AdrNum==11) WAsmCode[1]|=(AdrVals[0] & 127);
+ else CodeLen=0;
+ END
+ else WAsmCode[1]|=17;
+ END
+ else if (AdrNum==13) /* FMOVE.L FPcr,<ea> ? */
+ BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=2))
+ BEGIN
+ WrError(1130); CodeLen=0;
+ END
+ else
+ BEGIN
+ WAsmCode[1]=0xa000 | (AdrMode << 10);
+ if ((AdrMode!=1) AND ((WAsmCode[0] & 0x38)==8))
+ BEGIN
+ WrError(1350); CodeLen=0;
+ END
+ END
+ END
+ else CodeLen=0;
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOVECR"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((*AttrPart!='\0') AND (OpSize!=6)) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Mfpn);
+ if (AdrNum==12)
+ BEGIN
+ WAsmCode[0]=0xf200; WAsmCode[1]=0x5c00 | (AdrMode << 7);
+ OpSize=0;
+ DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum==11)
+ if (AdrVals[0]>63) WrError(1700);
+ else
+ BEGIN
+ CodeLen=4;
+ WAsmCode[1]|=AdrVals[0];
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("TST"))
+ BEGIN
+ if (*AttrPart=='\0') OpSize=6;
+ else if (OpSize==3) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ RelPos=4;
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm+Mfpn);
+ if (AdrNum==12)
+ BEGIN
+ WAsmCode[0]=0xf200; WAsmCode[1]=0x3a | (AdrMode << 10);
+ CodeLen=4;
+ END
+ else if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf200 | AdrMode;
+ WAsmCode[1]=0x403a | (((Word)FSizeCodes[OpSize]) << 10);
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ END
+ END
+ return;
+ END
+
+ if (Memo("SINCOS"))
+ BEGIN
+ if (*AttrPart=='\0') OpSize=6;
+ if (OpSize==3) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ p=strrchr(ArgStr[2],':');
+ if (p!=Nil)
+ BEGIN
+ *p='\0'; strcpy(sk,ArgStr[2]); strcpy(ArgStr[2],p+1);
+ END
+ else *sk='\0';
+ DecodeAdr(sk,Mfpn);
+ if (AdrNum==12)
+ BEGIN
+ WAsmCode[1]=AdrMode | 0x30;
+ DecodeAdr(ArgStr[2],Mfpn);
+ if (AdrNum==12)
+ BEGIN
+ WAsmCode[1]|=(AdrMode << 7);
+ RelPos=4;
+ DecodeAdr(ArgStr[1],((OpSize<=2) OR (OpSize==4))?
+ Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm+Mfpn:
+ Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm+Mfpn);
+ if (AdrNum==12)
+ BEGIN
+ WAsmCode[0]=0xf200; WAsmCode[1]|=(AdrMode << 10);
+ CodeLen=4;
+ END
+ else if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf200 | AdrMode;
+ WAsmCode[1]|=0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (*OpPart=='B')
+ BEGIN
+ for (z=0; z<FPUCondCnt; z++)
+ if (strcmp(OpPart+1,FPUConds[z].Name)==0) break;
+ if (z>=FPUCondCnt) WrError(1360);
+ else
+ BEGIN
+ if ((OpSize!=1) AND (OpSize!=2) AND (OpSize!=6)) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ HVal=EvalIntExpression(ArgStr[1],Int32,&ValOK)-(EProgCounter()+2);
+ HVal16=HVal;
+
+ if (OpSize==1)
+ BEGIN
+ OpSize=(IsDisp16(HVal))?2:6;
+ END
+
+ if (OpSize==2)
+ BEGIN
+ if ((NOT IsDisp16(HVal)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0xf280 | FPUConds[z].Code;
+ WAsmCode[1]=HVal16;
+ END
+ END
+ else
+ BEGIN
+ CodeLen=6; WAsmCode[0]=0xf2c0 | FPUConds[z].Code;
+ WAsmCode[2]=HVal & 0xffff; WAsmCode[1]=HVal >> 16;
+ if ((IsDisp16(HVal)) AND (PassNo>1) AND (*AttrPart=='\0'))
+ BEGIN
+ WrError(20); WAsmCode[0]^=0x40;
+ CodeLen-=2; WAsmCode[1]=WAsmCode[2]; StopfZahl++;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (strncmp(OpPart,"DB",2)==0)
+ BEGIN
+ for (z=0; z<FPUCondCnt; z++)
+ if (strcmp(OpPart+2,FPUConds[z].Name)==0) break;
+ if (z>=FPUCondCnt) WrError(1360);
+ else
+ BEGIN
+ if ((OpSize!=1) AND (*AttrPart!='\0')) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf248 | AdrMode; WAsmCode[1]=FPUConds[z].Code;
+ HVal=EvalIntExpression(ArgStr[2],Int32,&ValOK)-(EProgCounter()+4);
+ if (ValOK)
+ BEGIN
+ HVal16=HVal; WAsmCode[2]=HVal16;
+ if ((NOT IsDisp16(HVal)) AND (NOT SymbolQuestionable)) WrError(1370); else CodeLen=6;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("DMOVE")) OR (Memo("SMOVE")))
+ BEGIN
+ if (ArgCnt != 2) WrError(1110);
+ else if (MomCPU < CPU68040) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2], Mfpn);
+ if (AdrNum == 12)
+ BEGIN
+ WAsmCode[0] = 0xf200;
+ WAsmCode[1] = 0x0040 | AdrMode << 7;
+ if (*OpPart == 'D') WAsmCode[1] |= 4;
+ RelPos = 4;
+ if (*AttrPart == '\0') OpSize = 6;
+ Mask = Mfpn+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm;
+ if ((OpSize <= 2) OR (OpSize == 4))
+ Mask |= Mdata;
+ DecodeAdr(ArgStr[1], Mask);
+ if (AdrNum == 12)
+ BEGIN
+ CodeLen = 4;
+ WAsmCode[1] |= (AdrMode << 10);
+ END
+ else if (AdrNum != 0)
+ BEGIN
+ CodeLen = 4 + AdrCnt; CopyAdrVals(WAsmCode + 2);
+ WAsmCode[0] |= AdrMode;
+ WAsmCode[1] |= 0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
+ END
+ END
+ END
+ return;
+ END
+
+ if (*OpPart=='S')
+ BEGIN
+ for (z=0; z<FPUCondCnt; z++)
+ if (strcmp(OpPart+1,FPUConds[z].Name)==0) break;
+ if (z>=FPUCondCnt) WrError(1360);
+ else
+ BEGIN
+ if ((OpSize!=0) AND (*AttrPart!='\0')) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=4+AdrCnt; WAsmCode[0]=0xf240 | AdrMode;
+ WAsmCode[1]=FPUConds[z].Code; CopyAdrVals(WAsmCode+2);
+ END
+ END
+ END
+ return;
+ END
+
+ if (strncmp(OpPart,"TRAP",4)==0)
+ BEGIN
+ for (z=0; z<FPUCondCnt; z++)
+ if (strcmp(OpPart+4,FPUConds[z].Name)==0) break;
+ if (z>=FPUCondCnt) WrError(1360);
+ else
+ BEGIN
+ if (*AttrPart=='\0') OpSize=0;
+ if (OpSize>2) WrError(1130);
+ else if (((OpSize==0) AND (ArgCnt!=0)) OR ((OpSize!=0) AND (ArgCnt!=1))) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=0xf278; WAsmCode[1]=FPUConds[z].Code;
+ if (OpSize==0)
+ BEGIN
+ WAsmCode[0]|=4; CodeLen=4;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=(OpSize+1);
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOVEM"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeFRegList(ArgStr[2], &z1, &z2);
+ if (z1 != 0)
+ BEGIN
+ if ((*AttrPart != '\0')
+ AND (((z1 < 3) AND (OpSize != 6))
+ OR ((z1 == 3) AND (OpSize != 2))))
+ WrError(1130);
+ else
+ BEGIN
+ RelPos = 4;
+ Mask = Madri + Mpost + Mdadri + Maix + Mpc + Mpcidx + Mabs + Mimm;
+ if (z1 == 3) /* Steuerregister auch Predekrement */
+ BEGIN
+ Mask |= Mpre;
+ if ((z2 == 4) | (z2 == 2) | (z2 == 1)) /* nur ein Register */
+ Mask |= Mdata;
+ if (z2 == 1) /* nur FPIAR */
+ Mask |= Madr;
+ END
+ DecodeAdr(ArgStr[1], Mask);
+ WAsmCode[1] = 0; GenerateMovem(z1, z2);
+ END
+ END
+ else
+ BEGIN
+ DecodeFRegList(ArgStr[1],&z1,&z2);
+ if (z1!=0)
+ BEGIN
+ if ((*AttrPart!='\0') AND (((z1<3) AND (OpSize!=6)) OR ((z1==3) AND (OpSize!=2))))
+ WrError(1130);
+ else
+ BEGIN
+ Mask = Madri + Mpost + Mdadri + Maix + Mabs;
+ if (z1 == 3) /* Steuerregister auch Postinkrement */
+ BEGIN
+ Mask |= Mpre;
+ if ((z2 == 4) | (z2 == 2) | (z2 == 1)) /* nur ein Register */
+ Mask |= Mdata;
+ if (z2 == 1) /* nur FPIAR */
+ Mask |= Madr;
+ END
+ DecodeAdr(ArgStr[2], Mask);
+ WAsmCode[1] = 0x2000; GenerateMovem(z1, z2);
+ END
+ END
+ else WrError(1410);
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+/*-------------------------------------------------------------------------*/
+
+
+ static Boolean DecodeFC(char *Asc, Word *erg)
+BEGIN
+ Boolean OK;
+ Word Val;
+ String Asc_N;
+
+ strmaxcpy(Asc_N,Asc,255); NLS_UpString(Asc_N); Asc=Asc_N;
+
+ if (strcmp(Asc,"SFC")==0)
+ BEGIN
+ *erg=0; return True;
+ END
+
+ if (strcmp(Asc,"DFC")==0)
+ BEGIN
+ *erg=1; return True;
+ END
+
+ if ((strlen(Asc)==2) AND (*Asc=='D') AND ValReg(Asc[1]))
+ BEGIN
+ *erg=Asc[2]-'0'+8; return True;
+ END
+
+ if (*Asc=='#')
+ BEGIN
+ Val=EvalIntExpression(Asc+1,Int4,&OK);
+ if (OK) *erg=Val+16; return OK;
+ END
+
+ return False;
+END
+
+ static Boolean DecodePMMUReg(char *Asc, Word *erg, Byte *Size)
+BEGIN
+ Byte z;
+
+ if ((strlen(Asc)==4) AND (strncasecmp(Asc,"BAD",3)==0) AND ValReg(Asc[3]))
+ BEGIN
+ *Size=1;
+ *erg=0x7000+((Asc[3]-'0') << 2); return True;
+ END
+ if ((strlen(Asc)==4) AND (strncasecmp(Asc,"BAC",3)==0) AND ValReg(Asc[3]))
+ BEGIN
+ *Size=1;
+ *erg=0x7400+((Asc[3]-'0') << 2); return True;
+ END
+
+ for (z=0; z<PMMURegCnt; z++)
+ if (strcasecmp(Asc,PMMURegNames[z])==0) break;
+ if (z<PMMURegCnt)
+ BEGIN
+ *Size=PMMURegSizes[z];
+ *erg=PMMURegCodes[z] << 10;
+ END
+ return (z<PMMURegCnt);
+END
+
+ static void DecodePMMUOrders(void)
+BEGIN
+ Byte z;
+ Word Mask;
+ LongInt HVal;
+ Integer HVal16;
+ Boolean ValOK;
+
+ if (Memo("SAVE"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else if (NOT FullPMMU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; WAsmCode[0]=0xf100 | AdrMode;
+ CopyAdrVals(WAsmCode+1); CheckSup();
+ END
+ END
+ return;
+ END
+
+ if (Memo("RESTORE"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else if (NOT FullPMMU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=2+AdrCnt; WAsmCode[0]=0xf140 | AdrMode;
+ CopyAdrVals(WAsmCode+1); CheckSup();
+ END
+ END
+ return;
+ END
+
+ if (Memo("FLUSHA"))
+ BEGIN
+ if (*AttrPart!='\0') WrError(1130);
+ else if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ if (MomCPU>=CPU68040)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0xf518;
+ END
+ else
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0xf000; WAsmCode[1]=0x2400;
+ END
+ CheckSup();
+ END
+ return;
+ END
+
+ if (Memo("FLUSHAN"))
+ BEGIN
+ if (*AttrPart!='\0') WrError(1130);
+ else if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0xf510;
+ CheckCPU(CPU68040); CheckSup();
+ END
+ return;
+ END
+
+ if ((Memo("FLUSH")) OR (Memo("FLUSHS")))
+ BEGIN
+ if (*AttrPart!='\0') WrError(1130);
+ else if (MomCPU>=CPU68040)
+ BEGIN
+ if (Memo("FLUSHS")) WrError(1500);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf508+(AdrMode & 7);
+ CodeLen=2;
+ CheckSup();
+ END
+ END
+ END
+ else if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
+ else if ((Memo("FLUSHS")) AND (NOT FullPMMU)) WrError(1500);
+ else if (NOT DecodeFC(ArgStr[1],WAsmCode+1)) WrError(1710);
+ else
+ BEGIN
+ OpSize=0;
+ DecodeAdr(ArgStr[2],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ if (AdrVals[0]>15) WrError(1720);
+ else
+ BEGIN
+ WAsmCode[1]|=(AdrVals[0] << 5) | 0x3000;
+ if (Memo("FLUSHS")) WAsmCode[1]|=0x400;
+ WAsmCode[0]=0xf000; CodeLen=4; CheckSup();
+ if (ArgCnt==3)
+ BEGIN
+ WAsmCode[1]|=0x800;
+ DecodeAdr(ArgStr[3],Madri+Mdadri+Maix+Mabs);
+ if (AdrNum==0) CodeLen=0;
+ else
+ BEGIN
+ WAsmCode[0]|=AdrMode; CodeLen+=AdrCnt;
+ CopyAdrVals(WAsmCode+2);
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("FLUSHN"))
+ BEGIN
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf500+(AdrMode & 7);
+ CodeLen=2;
+ CheckCPU(CPU68040); CheckSup();
+ END
+ END
+ return;
+ END
+
+ if (Memo("FLUSHR"))
+ BEGIN
+ if (*AttrPart=='\0') OpSize=3;
+ if (OpSize!=3) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (NOT FullPMMU) WrError(1500);
+ else
+ BEGIN
+ RelPos=4;
+ DecodeAdr(ArgStr[1],Madri+Mpre+Mpost+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf000 | AdrMode; WAsmCode[1]=0xa000;
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt; CheckSup();
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LOADR")) OR (Memo("LOADW")))
+ BEGIN
+ if (*AttrPart!='\0') WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeFC(ArgStr[1],WAsmCode+1)) WrError(1710);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Madri+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf000 | AdrMode; WAsmCode[1]|=0x2000;
+ if (Memo("LOADR")) WAsmCode[1]|=0x200;
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2); CheckSup();
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MOVE")) OR (Memo("MOVEFD")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (DecodePMMUReg(ArgStr[1],WAsmCode+1,&z))
+ BEGIN
+ WAsmCode[1]|=0x200;
+ if (*AttrPart=='\0') OpSize=z;
+ if (OpSize!=z) WrError(1130);
+ else
+ BEGIN
+ Mask=Madri+Mdadri+Maix+Mabs;
+ if (FullPMMU)
+ BEGIN
+ Mask*=Mpost+Mpre;
+ if (z!=3) Mask+=Mdata+Madr;
+ END
+ DecodeAdr(ArgStr[2],Mask);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf000 | AdrMode;
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ CheckSup();
+ END
+ END
+ END
+ else if (DecodePMMUReg(ArgStr[2],WAsmCode+1,&z))
+ BEGIN
+ if (*AttrPart=='\0') OpSize=z;
+ if (OpSize!=z) WrError(1130);
+ else
+ BEGIN
+ RelPos=4;
+ Mask=Madri+Mdadri+Maix+Mabs;
+ if (FullPMMU)
+ BEGIN
+ Mask+=Mpost+Mpre+Mpc+Mpcidx+Mimm;
+ if (z!=3) Mask+=Mdata+Madr;
+ END
+ DecodeAdr(ArgStr[1],Mask);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf000 | AdrMode;
+ CodeLen=4+AdrCnt; CopyAdrVals(WAsmCode+2);
+ if (Memo("MOVEFD")) WAsmCode[1]+=0x100;
+ CheckSup();
+ END
+ END
+ END
+ else WrError(1730);
+ END
+ return;
+ END
+
+ if ((Memo("TESTR")) OR (Memo("TESTW")))
+ BEGIN
+ if (*AttrPart!='\0') WrError(1130);
+ else if (MomCPU>=CPU68040)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madri);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf548+(AdrMode & 7)+(Ord(Memo("TESTR")) << 5);
+ CodeLen=2;
+ CheckSup();
+ END
+ END
+ END
+ else if ((ArgCnt>4) OR (ArgCnt<3)) WrError(1110);
+ else
+ BEGIN
+ if (NOT DecodeFC(ArgStr[1],WAsmCode+1)) WrError(1710);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Madri+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf000 | AdrMode; CodeLen=4+AdrCnt;
+ WAsmCode[1]|=0x8000;
+ CopyAdrVals(WAsmCode+2);
+ if (Memo("TESTR")) WAsmCode[1]|=0x200;
+ DecodeAdr(ArgStr[3],Mimm);
+ if (AdrNum!=0)
+ if (AdrVals[0]>7)
+ BEGIN
+ WrError(1740); CodeLen=0;
+ END
+ else
+ BEGIN
+ WAsmCode[1]|=AdrVals[0] << 10;
+ if (ArgCnt==4)
+ BEGIN
+ DecodeAdr(ArgStr[4],Madr);
+ if (AdrNum==0) CodeLen=0; else WAsmCode[1]|=AdrMode << 5;
+ CheckSup();
+ END
+ END
+ else CodeLen=0;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("VALID"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT FullPMMU) WrError(1500);
+ else if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],Madri+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf000 | AdrMode;
+ WAsmCode[1]=0x2800; CodeLen=4+AdrCnt;
+ CopyAdrVals(WAsmCode+1);
+ if (strcasecmp(ArgStr[1],"VAL")==0);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Madr);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[1]|=0x400 | (AdrMode & 7);
+ END
+ else CodeLen=0;
+ END
+ END
+ END
+ return;
+ END
+
+ if (*OpPart=='B')
+ BEGIN
+ for (z=0; z<PMMUCondCnt; z++)
+ if (strcmp(OpPart+1,PMMUConds[z])==0) break;
+ if (z==PMMUCondCnt) WrError(1360);
+ else
+ BEGIN
+ if ((OpSize!=1) AND (OpSize!=2) AND (OpSize!=6)) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (NOT FullPMMU) WrError(1500);
+ else
+ BEGIN
+
+ HVal=EvalIntExpression(ArgStr[1],Int32,&ValOK)-(EProgCounter()+2);
+ HVal16=HVal;
+
+ if (OpSize==1) OpSize=(IsDisp16(HVal))?2:6;
+
+ if (OpSize==2)
+ BEGIN
+ if ((NOT IsDisp16(HVal)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0xf080 | z;
+ WAsmCode[1]=HVal16; CheckSup();
+ END
+ END
+ else
+ BEGIN
+ CodeLen=6; WAsmCode[0]=0xf0c0 | z;
+ WAsmCode[2]=HVal & 0xffff; WAsmCode[1]=HVal >> 16;
+ CheckSup();
+ END
+ END
+ END
+ return;
+ END;
+
+ if (strncmp(OpPart,"DB",2)==0)
+ BEGIN
+ for (z=0; z<PMMUCondCnt; z++)
+ if (strcmp(OpPart+2,PMMUConds[z])==0) break;
+ if (z==PMMUCondCnt) WrError(1360);
+ else
+ BEGIN
+ if ((OpSize!=1) AND (*AttrPart!='\0')) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT FullPMMU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0xf048 | AdrMode; WAsmCode[1]=z;
+ HVal=EvalIntExpression(ArgStr[2],Int32,&ValOK)-(EProgCounter()+4);
+ if (ValOK)
+ BEGIN
+ HVal16=HVal; WAsmCode[2]=HVal16;
+ if ((NOT IsDisp16(HVal)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else CodeLen=6;
+ CheckSup();
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (*OpPart=='S')
+ BEGIN
+ for (z=0; z<PMMUCondCnt; z++)
+ if (strcmp(OpPart+1,PMMUConds[z])==0) break;
+ if (z==PMMUCondCnt) WrError(1360);
+ else
+ BEGIN
+ if ((OpSize!=0) AND (*AttrPart!='\0')) WrError(1130);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (NOT FullPMMU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ CodeLen=4+AdrCnt; WAsmCode[0]=0xf040 | AdrMode;
+ WAsmCode[1]=z; CopyAdrVals(WAsmCode+2); CheckSup();
+ END
+ END
+ END
+ return;
+ END
+
+ if (strncmp(OpPart,"TRAP",4)==0)
+ BEGIN
+ for (z=0; z<PMMUCondCnt; z++)
+ if (strcmp(OpPart+4,PMMUConds[z])==0) break;
+ if (z==PMMUCondCnt) WrError(1360);
+ else
+ BEGIN
+ if (*AttrPart=='\0') OpSize=0;
+ if (OpSize>2) WrError(1130);
+ else if (((OpSize==0) AND (ArgCnt!=0)) OR ((OpSize!=0) AND (ArgCnt!=1))) WrError(1110);
+ else if (NOT FullPMMU) WrError(1500);
+ else
+ BEGIN
+ WAsmCode[0]=0xf078; WAsmCode[1]=z;
+ if (OpSize==0)
+ BEGIN
+ WAsmCode[0]|=4; CodeLen=4; CheckSup();
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=(OpSize+1);
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt; CheckSup();
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ WrError(1200);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void MakeCode_68K(void)
+BEGIN
+ Boolean ValOK;
+ LongInt HVal;
+ Integer i,HVal16;
+ ShortInt HVal8;
+ Word w1,w2;
+
+ CodeLen=0;
+ OpSize=(MomCPU==CPUCOLD) ? 2 : 1;
+ DontPrint=False; RelPos=2;
+
+ if (*AttrPart!='\0')
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B': OpSize=0; break;
+ case 'W': OpSize=1; break;
+ case 'L': OpSize=2; break;
+ case 'Q': OpSize=3; break;
+ case 'S': OpSize=4; break;
+ case 'D': OpSize=5; break;
+ case 'X': OpSize=6; break;
+ case 'P': OpSize=7; break;
+ default: WrError(1107); return;
+ END
+
+ /* Nullanweisung */
+
+ if ((*OpPart=='\0') AND (*AttrPart=='\0') AND (ArgCnt==0)) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodeMoto16Pseudo(OpSize,True)) return;
+
+ if (DecodePseudo()) return;
+
+ /* Befehlszaehler ungerade ? */
+
+ if (Odd(EProgCounter())) WrError(180);
+
+ /* Befehlserweiterungen */
+
+ if ((*OpPart=='F') AND (FPUAvail))
+ BEGIN
+ strcpy(OpPart,OpPart+1);
+ DecodeFPUOrders();
+ return;
+ END
+
+ if ((*OpPart=='P') AND (NOT Memo("PEA")) AND (PMMUAvail))
+ BEGIN
+ strcpy(OpPart,OpPart+1);
+ DecodePMMUOrders();
+ return;
+ END
+
+ /* vermischtes */
+
+ if (LookupInstTable(InstTable,OpPart)) return;
+
+ /* Anweisungen mit konstantem Argument */
+
+ /* zwei Operanden */
+
+ if ((strncmp(OpPart,"MUL",3)==0) OR (strncmp(OpPart,"DIV",3)==0))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((MomCPU==CPUCOLD) AND (*OpPart=='D')) WrError(1500);
+ else if (OpSize==1)
+ BEGIN
+ DecodeAdr(ArgStr[2],Mdata);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x80c0 | (AdrMode << 9);
+ if (strncmp(OpPart,"MUL",3)==0) WAsmCode[0]|=0x4000;
+ if (OpPart[3]=='S') WAsmCode[0]|=0x100;
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]|=AdrMode;
+ CodeLen=2+AdrCnt; CopyAdrVals(WAsmCode+1);
+ END
+ END
+ END
+ else if (OpSize==2)
+ BEGIN
+ if (strchr(ArgStr[2],':')==Nil)
+ BEGIN
+ strcpy(ArgStr[3], ArgStr[2]);
+ strcat(ArgStr[2], ":");
+ strcat(ArgStr[2], ArgStr[3]);
+ END
+ if (NOT CodeRegPair(ArgStr[2],&w1,&w2)) WrXError(1760, ArgStr[2]);
+ else
+ BEGIN
+ WAsmCode[1]=w1+(w2 << 12); RelPos=4;
+ if (w1!=w2) WAsmCode[1]|=0x400;
+ if (OpPart[3]=='S') WAsmCode[1]|=0x800;
+ DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mpc+Mpcidx+Mabs+Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x4c00+AdrMode;
+ if (strncmp(OpPart,"DIV",3)==0) WAsmCode[0]|=0x40;
+ CopyAdrVals(WAsmCode+2); CodeLen=4+AdrCnt;
+ CheckCPU((w1!=w2) ? CPU68332 : CPUCOLD);
+ END
+ END
+ END
+ else WrError(1130);
+ return;
+ END
+
+ /* bedingte Befehle */
+
+ if ((strlen(OpPart)<=3) AND (*OpPart=='B'))
+ BEGIN
+ /* .W, .S, .L, .X erlaubt */
+
+ if ((OpSize!=1) AND (OpSize!=2) AND (OpSize!=4) AND (OpSize!=6))
+ WrError(1130);
+
+ /* nur ein Operand erlaubt */
+
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+
+ /* Bedingung finden, evtl. meckern */
+
+ if (NOT LookupInstTable(CInstTable,OpPart+1)) WrError(1360);
+ else
+ BEGIN
+
+ /* Zieladresse ermitteln, zum Programmzaehler relativieren */
+
+ HVal=EvalIntExpression(ArgStr[1],Int32,&ValOK);
+ HVal=HVal-(EProgCounter()+2);
+
+ /* Bei Automatik Groesse festlegen */
+
+ if (OpSize==1)
+ BEGIN
+ if (IsDisp8(HVal)) OpSize=4;
+ else if (IsDisp16(HVal)) OpSize=2;
+ else OpSize=6;
+ END
+
+ if (ValOK)
+ BEGIN
+
+ /* 16 Bit ? */
+
+ if (OpSize==2)
+ BEGIN
+
+ /* zu weit ? */
+
+ HVal16=HVal;
+ if ((NOT IsDisp16(HVal)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+
+ /* Code erzeugen */
+
+ CodeLen=4; WAsmCode[0]=0x6000 | (CondIndex << 8);
+ WAsmCode[1]=HVal16;
+ END
+ END
+
+ /* 8 Bit ? */
+
+ else if (OpSize==4)
+ BEGIN
+
+ /* zu weit ? */
+
+ HVal8=HVal;
+ if ((NOT IsDisp8(HVal)) AND (NOT SymbolQuestionable)) WrError(1370);
+
+ /* Code erzeugen */
+ else
+ BEGIN
+ CodeLen=2;
+ if (HVal8!=0)
+ BEGIN
+ WAsmCode[0]=0x6000 | (CondIndex << 8) | ((Byte)HVal8);
+ END
+ else
+ BEGIN
+ WAsmCode[0]=NOPCode;
+ if ((NOT Repass) AND (*AttrPart!='\0')) WrError(60);
+ END
+ END
+ END
+
+ /* 32 Bit ? */
+
+ else
+ BEGIN
+ CodeLen=6; WAsmCode[0]=0x60ff | (CondIndex << 8);
+ WAsmCode[1]=HVal >> 16; WAsmCode[2]=HVal & 0xffff;
+ CheckCPU(CPU68332);
+ END
+ END
+ END
+ return;
+ END
+ END
+
+ if ((strlen(OpPart)<=3) AND (*OpPart=='S'))
+ BEGIN
+ if ((*AttrPart!='\0') AND (OpSize!=0)) WrError(1130);
+ else if (ArgCnt!=1) WrError(1130);
+ else
+ BEGIN
+ i=FindICondition(OpPart+1);
+ if (i>=CondCnt-2) WrError(1360);
+ else
+ BEGIN
+ OpSize=0;
+ if (MomCPU==CPUCOLD) DecodeAdr(ArgStr[1],Mdata);
+ else DecodeAdr(ArgStr[1],Mdata+Madri+Mpost+Mpre+Mdadri+Maix+Mabs);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]=0x50c0 | (CondVals[i] << 8) | AdrMode;
+ CodeLen=2+AdrCnt; CopyAdrVals(WAsmCode+1);
+ END
+ END
+ END
+ return;
+ END
+
+ if ((strlen(OpPart)<=4) AND (strncmp(OpPart,"DB",2)==0))
+ BEGIN
+ if (OpSize!=1) WrError(1130);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU==CPUCOLD) WrError(1500);
+ else
+ BEGIN
+ i=FindICondition(OpPart+2);
+ if (i==18) i=1;
+ if (i>=CondCnt-1) WrError(1360);
+ else
+ BEGIN
+ HVal=EvalIntExpression(ArgStr[2],Int32,&ValOK);
+ if (ValOK)
+ BEGIN
+ HVal-=(EProgCounter()+2); HVal16=HVal;
+ if ((NOT IsDisp16(HVal)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0x50c8 | (CondVals[i] << 8);
+ WAsmCode[1]=HVal16;
+ DecodeAdr(ArgStr[1],Mdata);
+ if (AdrNum==1) WAsmCode[0]|=AdrMode;
+ else CodeLen=0;
+ END
+ END
+ END
+ return;
+ END
+ END
+
+ if ((strlen(OpPart)<=6) AND (strncmp(OpPart,"TRAP",4)==0))
+ BEGIN
+ if (*AttrPart=='\0') OpSize=0;
+ i=(OpSize==0) ? 0 : 1;
+ if (OpSize>2) WrError(1130);
+ else if (ArgCnt!=i) WrError(1110);
+ else
+ BEGIN
+ i=FindICondition(OpPart+4);
+ if ((i==18) OR (i>=CondCnt-2)) WrError(1360);
+ else if ((MomCPU==CPUCOLD) AND (i!=1)) WrError(1500);
+ else
+ BEGIN
+ WAsmCode[0]=0x50f8+(i << 8);
+ if (OpSize==0)
+ BEGIN
+ WAsmCode[0]+=4; CodeLen=2;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],Mimm);
+ if (AdrNum!=0)
+ BEGIN
+ WAsmCode[0]+=OpSize+1;
+ CopyAdrVals(WAsmCode+1); CodeLen=2+AdrCnt;
+ END
+ END
+ CheckCPU(CPUCOLD);
+ END
+ END
+ return;
+ END
+
+ /* unbekannter Befehl */
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_68K(void)
+BEGIN
+ SaveInitProc();
+ SetFlag(&PMMUAvail,PMMUAvailName,False);
+ SetFlag(&FullPMMU,FullPMMUName,True);
+END
+
+ static Boolean IsDef_68K(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_68K(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_68K(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x01; NOPCode=0x4e71;
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+#ifdef __STDC__
+ SegLimits[SegCode] = 0xfffffffful;
+#else
+ SegLimits[SegCode] = 0xffffffffl;
+#endif
+
+ MakeCode=MakeCode_68K; IsDef=IsDef_68K;
+
+ SwitchFrom=SwitchFrom_68K; InitFields();
+ AddONOFF("PMMU" , &PMMUAvail , PMMUAvailName, False);
+ AddONOFF("FULLPMMU", &FullPMMU , FullPMMUName , False);
+ AddONOFF("FPU" , &FPUAvail , FPUAvailName , False);
+ AddONOFF("SUPMODE" , &SupAllowed, SupAllowedName,False);
+ AddMoto16PseudoONOFF();
+
+ SetFlag(&FullPMMU,FullPMMUName,MomCPU<=CPU68020);
+ SetFlag(&DoPadding,DoPaddingName,True);
+END
+
+#ifdef DEBSTRCNT
+ static void wrstrcnt(void)
+BEGIN
+ printf("\n%d comps\n",strcnt);
+END
+#endif
+
+ void code68k_init(void)
+BEGIN
+ CPU68008=AddCPU("68008",SwitchTo_68K);
+ CPU68000=AddCPU("68000",SwitchTo_68K);
+ CPU68010=AddCPU("68010",SwitchTo_68K);
+ CPU68012=AddCPU("68012",SwitchTo_68K);
+ CPUCOLD =AddCPU("MCF5200",SwitchTo_68K);
+ CPU68332=AddCPU("68332",SwitchTo_68K);
+ CPU68340=AddCPU("68340",SwitchTo_68K);
+ CPU68360=AddCPU("68360",SwitchTo_68K);
+ CPU68020=AddCPU("68020",SwitchTo_68K);
+ CPU68030=AddCPU("68030",SwitchTo_68K);
+ CPU68040=AddCPU("68040",SwitchTo_68K);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_68K;
+#ifdef DEBSTRCNT
+ atexit(wrstrcnt);
+#endif
+END
+
diff --git a/code68k.h b/code68k.h
new file mode 100644
index 0000000..961bb56
--- /dev/null
+++ b/code68k.h
@@ -0,0 +1,11 @@
+/* code68k.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 680x0-Familie */
+/* */
+/* Historie: 9. 9.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code68k_init(void);
diff --git a/code7000.c b/code7000.c
new file mode 100644
index 0000000..dfdb423
--- /dev/null
+++ b/code7000.c
@@ -0,0 +1,1315 @@
+/* code7000.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator SH7x00 */
+/* */
+/* Historie: 25.12.1996 Grundsteinlegung */
+/* 12. 4.1998 SH7700-Erweiterungen */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+#define FixedOrderCount 13
+#define OneRegOrderCount 22
+#define TwoRegOrderCount 20
+#define MulRegOrderCount 3
+#define BWOrderCount 3
+#define LogOrderCount 4
+
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModIReg 1
+#define MModIReg (1 << ModIReg)
+#define ModPreDec 2
+#define MModPreDec (1 << ModPreDec)
+#define ModPostInc 3
+#define MModPostInc (1 << ModPostInc)
+#define ModIndReg 4
+#define MModIndReg (1 << ModIndReg)
+#define ModR0Base 5
+#define MModR0Base (1 << ModR0Base)
+#define ModGBRBase 6
+#define MModGBRBase (1 << ModGBRBase)
+#define ModGBRR0 7
+#define MModGBRR0 (1 << ModGBRR0)
+#define ModPCRel 8
+#define MModPCRel (1 << ModPCRel)
+#define ModImm 9
+#define MModImm (1 << ModImm)
+
+
+#define CompLiteralsName "COMPRESSEDLITERALS"
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Boolean Priv;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Boolean Priv;
+ Word Code;
+ ShortInt DefSize;
+ } TwoRegOrder;
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Word Code;
+ } FixedMinOrder;
+
+ typedef struct _TLiteral
+ {
+ struct _TLiteral *Next;
+ LongInt Value,FCount;
+ Boolean Is32,IsForward;
+ Integer PassNo;
+ LongInt DefSection;
+ } *PLiteral,TLiteral;
+
+static ShortInt OpSize; /* Groesse=8*(2^OpSize) */
+static ShortInt AdrMode; /* Ergebnisadressmodus */
+static Word AdrPart; /* Adressierungsmodusbits im Opcode */
+
+static PLiteral FirstLiteral;
+static LongInt ForwardCount;
+static SimpProc SaveInitProc;
+
+static CPUVar CPU7000,CPU7600,CPU7700;
+
+static FixedOrder *FixedOrders;
+static FixedMinOrder *OneRegOrders;
+static TwoRegOrder *TwoRegOrders;
+static FixedMinOrder *MulRegOrders;
+static FixedOrder *BWOrders;
+static char **LogOrders;
+
+static Boolean CurrDelayed,PrevDelayed,CompLiterals;
+static LongInt DelayedAdr;
+
+/*-------------------------------------------------------------------------*/
+/* dynamische Belegung/Freigabe Codetabellen */
+
+ static void AddFixed(char *NName, Word NCode, Boolean NPriv, CPUVar NMin)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].Priv=NPriv;
+ FixedOrders[InstrZ].MinCPU=NMin;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddOneReg(char *NName, Word NCode, CPUVar NMin)
+BEGIN
+ if (InstrZ>=OneRegOrderCount) exit(255);
+ OneRegOrders[InstrZ].Name=NName;
+ OneRegOrders[InstrZ].Code=NCode;
+ OneRegOrders[InstrZ++].MinCPU=NMin;
+END
+
+ static void AddTwoReg(char *NName, Word NCode, Boolean NPriv, CPUVar NMin, ShortInt NDef)
+BEGIN
+ if (InstrZ>=TwoRegOrderCount) exit(255);
+ TwoRegOrders[InstrZ].Name=NName;
+ TwoRegOrders[InstrZ].Priv=NPriv;
+ TwoRegOrders[InstrZ].DefSize=NDef;
+ TwoRegOrders[InstrZ].MinCPU=NMin;
+ TwoRegOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddMulReg(char *NName, Word NCode, CPUVar NMin)
+BEGIN
+ if (InstrZ>=MulRegOrderCount) exit(255);
+ MulRegOrders[InstrZ].Name=NName;
+ MulRegOrders[InstrZ].Code=NCode;
+ MulRegOrders[InstrZ++].MinCPU=NMin;
+END
+
+ static void AddBW(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=BWOrderCount) exit(255);
+ BWOrders[InstrZ].Name=NName;
+ BWOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("CLRT" ,0x0008,False,CPU7000);
+ AddFixed("CLRMAC",0x0028,False,CPU7000);
+ AddFixed("NOP" ,0x0009,False,CPU7000);
+ AddFixed("RTE" ,0x002b,False,CPU7000);
+ AddFixed("SETT" ,0x0018,False,CPU7000);
+ AddFixed("SLEEP" ,0x001b,False,CPU7000);
+ AddFixed("RTS" ,0x000b,False,CPU7000);
+ AddFixed("DIV0U" ,0x0019,False,CPU7000);
+ AddFixed("BRK" ,0x0000,True ,CPU7000);
+ AddFixed("RTB" ,0x0001,True ,CPU7000);
+ AddFixed("CLRS" ,0x0048,False,CPU7700);
+ AddFixed("SETS" ,0x0058,False,CPU7700);
+ AddFixed("LDTLB" ,0x0038,True ,CPU7700);
+
+ OneRegOrders=(FixedMinOrder *) malloc(sizeof(FixedMinOrder)*OneRegOrderCount); InstrZ=0;
+ AddOneReg("MOVT" ,0x0029,CPU7000); AddOneReg("CMP/PZ",0x4011,CPU7000);
+ AddOneReg("CMP/PL",0x4015,CPU7000); AddOneReg("ROTL" ,0x4004,CPU7000);
+ AddOneReg("ROTR" ,0x4005,CPU7000); AddOneReg("ROTCL" ,0x4024,CPU7000);
+ AddOneReg("ROTCR" ,0x4025,CPU7000); AddOneReg("SHAL" ,0x4020,CPU7000);
+ AddOneReg("SHAR" ,0x4021,CPU7000); AddOneReg("SHLL" ,0x4000,CPU7000);
+ AddOneReg("SHLR" ,0x4001,CPU7000); AddOneReg("SHLL2" ,0x4008,CPU7000);
+ AddOneReg("SHLR2" ,0x4009,CPU7000); AddOneReg("SHLL8" ,0x4018,CPU7000);
+ AddOneReg("SHLR8" ,0x4019,CPU7000); AddOneReg("SHLL16",0x4028,CPU7000);
+ AddOneReg("SHLR16",0x4029,CPU7000); AddOneReg("LDBR" ,0x0021,CPU7000);
+ AddOneReg("STBR" ,0x0020,CPU7000); AddOneReg("DT" ,0x4010,CPU7600);
+ AddOneReg("BRAF" ,0x0032,CPU7600); AddOneReg("BSRF" ,0x0003,CPU7600);
+
+ TwoRegOrders=(TwoRegOrder *) malloc(sizeof(TwoRegOrder)*TwoRegOrderCount); InstrZ=0;
+ AddTwoReg("XTRCT" ,0x200d,False,CPU7000,2);
+ AddTwoReg("ADDC" ,0x300e,False,CPU7000,2);
+ AddTwoReg("ADDV" ,0x300f,False,CPU7000,2);
+ AddTwoReg("CMP/HS",0x3002,False,CPU7000,2);
+ AddTwoReg("CMP/GE",0x3003,False,CPU7000,2);
+ AddTwoReg("CMP/HI",0x3006,False,CPU7000,2);
+ AddTwoReg("CMP/GT",0x3007,False,CPU7000,2);
+ AddTwoReg("CMP/STR",0x200c,False,CPU7000,2);
+ AddTwoReg("DIV1" ,0x3004,False,CPU7000,2);
+ AddTwoReg("DIV0S" ,0x2007,False,CPU7000,-1);
+ AddTwoReg("MULS" ,0x200f,False,CPU7000,1);
+ AddTwoReg("MULU" ,0x200e,False,CPU7000,1);
+ AddTwoReg("NEG" ,0x600b,False,CPU7000,2);
+ AddTwoReg("NEGC" ,0x600a,False,CPU7000,2);
+ AddTwoReg("SUB" ,0x3008,False,CPU7000,2);
+ AddTwoReg("SUBC" ,0x300a,False,CPU7000,2);
+ AddTwoReg("SUBV" ,0x300b,False,CPU7000,2);
+ AddTwoReg("NOT" ,0x6007,False,CPU7000,2);
+ AddTwoReg("SHAD" ,0x400c,False,CPU7700,2);
+ AddTwoReg("SHLD" ,0x400d,False,CPU7700,2);
+
+ MulRegOrders=(FixedMinOrder *) malloc(sizeof(FixedMinOrder)*MulRegOrderCount); InstrZ=0;
+ AddMulReg("MUL" ,0x0007,CPU7600);
+ AddMulReg("DMULU" ,0x3005,CPU7600);
+ AddMulReg("DMULS" ,0x300d,CPU7600);
+
+ BWOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BWOrderCount); InstrZ=0;
+ AddBW("SWAP",0x6008); AddBW("EXTS",0x600e); AddBW("EXTU",0x600c);
+
+ LogOrders=(char **) malloc(sizeof(char *)*LogOrderCount); InstrZ=0;
+ LogOrders[InstrZ++]="TST"; LogOrders[InstrZ++]="AND";
+ LogOrders[InstrZ++]="XOR"; LogOrders[InstrZ++]="OR" ;
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(OneRegOrders);
+ free(TwoRegOrders);
+ free(MulRegOrders);
+ free(BWOrders);
+ free(LogOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+/* die PC-relative Adresse: direkt nach verzoegerten Spruengen = Sprungziel+2 */
+
+ static LongInt PCRelAdr(void)
+BEGIN
+ if (PrevDelayed) return DelayedAdr+2;
+ else return EProgCounter()+4;
+END
+
+ static void ChkDelayed(void)
+BEGIN
+ if (PrevDelayed) WrError(200);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Adressparsing */
+
+ static char *LiteralName(PLiteral Lit)
+BEGIN
+ String Tmp;
+ static String Result;
+
+ if (Lit->IsForward) sprintf(Tmp,"F_%s",HexString(Lit->FCount,8));
+ else if (Lit->Is32) sprintf(Tmp,"L_%s",HexString(Lit->Value,8));
+ else sprintf(Tmp,"W_%s",HexString(Lit->Value,4));
+ sprintf(Result,"LITERAL_%s_%s",Tmp,HexString(Lit->PassNo,0));
+ return Result;
+END
+/*
+ static void PrintLiterals(void)
+BEGIN
+ PLiteral Lauf;
+
+ WrLstLine("LiteralList");
+ Lauf=FirstLiteral;
+ while (Lauf!=Nil)
+ BEGIN
+ WrLstLine(LiteralName(Lauf)); Lauf=Lauf->Next;
+ END
+END
+*/
+ static void SetOpSize(ShortInt Size)
+BEGIN
+ if (OpSize==-1) OpSize=Size;
+ else if (Size!=OpSize)
+ BEGIN
+ WrError(1131); AdrMode=ModNone;
+ END
+END
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg)
+BEGIN
+ Boolean Err;
+
+ if (strcasecmp(Asc,"SP")==0)
+ BEGIN
+ *Erg=15; return True;
+ END
+ else if ((strlen(Asc)<2) OR (strlen(Asc)>3) OR (toupper(*Asc)!='R')) return False;
+ else
+ BEGIN
+ *Erg=ConstLongInt(Asc+1,&Err);
+ return (Err AND (*Erg<=15));
+ END
+END
+
+ static Boolean DecodeCtrlReg(char *Asc, Byte *Erg)
+BEGIN
+ CPUVar MinCPU=CPU7000;
+
+ *Erg=0xff;
+ if (strcasecmp(Asc,"SR")==0) *Erg=0;
+ else if (strcasecmp(Asc,"GBR")==0) *Erg=1;
+ else if (strcasecmp(Asc,"VBR")==0) *Erg=2;
+ else if (strcasecmp(Asc,"SSR")==0)
+ BEGIN
+ *Erg=3; MinCPU=CPU7700;
+ END
+ else if (strcasecmp(Asc,"SPC")==0)
+ BEGIN
+ *Erg=4; MinCPU=CPU7700;
+ END
+ else if ((strlen(Asc)==7) AND (toupper(*Asc)=='R')
+ AND (strcasecmp(Asc+2,"_BANK")==0)
+ AND (Asc[1]>='0') AND (Asc[1]<='7'))
+ BEGIN
+ *Erg=Asc[1]-'0'+8; MinCPU=CPU7700;
+ END
+ if ((*Erg==0xff) OR (MomCPU<MinCPU))
+ BEGIN
+ WrXError(1440,Asc); return False;
+ END
+ else return True;
+END
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ WrError(1350); AdrMode=ModNone;
+ END
+END
+
+ static LongInt ExtOp(LongInt Inp, Byte Src, Boolean Signed)
+BEGIN
+ switch (Src)
+ BEGIN
+ case 0: Inp&=0xff; break;
+ case 1: Inp&=0xffff; break;
+ END
+ if (Signed)
+ BEGIN
+ if (Src<1)
+ if ((Inp & 0x80)==0x80) Inp+=0xff00;
+ if (Src<2)
+ if ((Inp & 0x8000)==0x8000) Inp+=0xffff0000;
+ END
+ return Inp;
+END
+
+ static LongInt OpMask(ShortInt OpSize)
+BEGIN
+ switch (OpSize)
+ BEGIN
+ case 0: return 0xff;
+ case 1: return 0xffff;
+ case 2: return 0xffffffff;
+ default: return 0;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask, Boolean Signed)
+BEGIN
+#define RegNone (-1)
+#define RegPC (-2)
+#define RegGBR (-3)
+
+ Byte p,HReg;
+ char *pos;
+ ShortInt BaseReg,IndReg,DOpSize;
+ LongInt DispAcc;
+ String AdrStr,LStr;
+ Boolean OK,FirstFlag,NIs32,Critical,Found,LDef;
+ PLiteral Lauf,Last;
+
+ AdrMode=ModNone;
+
+ if (DecodeReg(Asc,&HReg))
+ BEGIN
+ AdrPart=HReg; AdrMode=ModReg; ChkAdr(Mask); return;
+ END
+
+ if (*Asc=='@')
+ BEGIN
+ strcpy(Asc,Asc+1);
+ if (IsIndirect(Asc))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ BaseReg=RegNone; IndReg=RegNone;
+ DispAcc=0; FirstFlag=False; OK=True;
+ while ((*Asc!='\0') AND (OK))
+ BEGIN
+ pos=QuotPos(Asc,',');
+ if (pos==Nil)
+ BEGIN
+ strmaxcpy(AdrStr,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *pos='\0'; strmaxcpy(AdrStr,Asc,255); strcpy(Asc,pos+1);
+ END
+ if (strcasecmp(AdrStr,"PC")==0)
+ if (BaseReg==RegNone) BaseReg=RegPC;
+ else
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else if (strcasecmp(AdrStr,"GBR")==0)
+ if (BaseReg==RegNone) BaseReg=RegGBR;
+ else
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else if (DecodeReg(AdrStr,&HReg))
+ if (IndReg==RegNone) IndReg=HReg;
+ else if ((BaseReg==RegNone) AND (HReg==0)) BaseReg=0;
+ else if ((IndReg==0) AND (BaseReg==RegNone))
+ BEGIN
+ BaseReg=0; IndReg=HReg;
+ END
+ else
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ DispAcc+=EvalIntExpression(AdrStr,Int32,&OK);
+ if (FirstPassUnknown) FirstFlag=True;
+ END
+ END
+ if (FirstFlag) DispAcc=0;
+ if ((OK) AND ((DispAcc & ((1 << OpSize)-1))!=0))
+ BEGIN
+ WrError(1325); OK=False;
+ END
+ else if ((OK) AND (DispAcc<0))
+ BEGIN
+ WrXError(1315,"Disp<0"); OK=False;
+ END
+ else DispAcc=DispAcc >> OpSize;
+ if (OK)
+ BEGIN
+ switch (BaseReg)
+ BEGIN
+ case 0:
+ if ((IndReg<0) OR (DispAcc!=0)) WrError(1350);
+ else
+ BEGIN
+ AdrMode=ModR0Base; AdrPart=IndReg;
+ END
+ break;
+ case RegGBR:
+ if ((IndReg==0) AND (DispAcc==0)) AdrMode=ModGBRR0;
+ else if (IndReg!=RegNone) WrError(1350);
+ else if (DispAcc>255) WrError(1320);
+ else
+ BEGIN
+ AdrMode=ModGBRBase; AdrPart=DispAcc;
+ END
+ break;
+ case RegNone:
+ if (IndReg==RegNone) WrError(1350);
+ else if (DispAcc>15) WrError(1320);
+ else
+ BEGIN
+ AdrMode=ModIndReg; AdrPart=(IndReg << 4)+DispAcc;
+ END
+ break;
+ case RegPC:
+ if (IndReg!=RegNone) WrError(1350);
+ else if (DispAcc>255) WrError(1320);
+ else
+ BEGIN
+ AdrMode=ModPCRel; AdrPart=DispAcc;
+ END
+ break;
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+ else
+ BEGIN
+ if (DecodeReg(Asc,&HReg))
+ BEGIN
+ AdrPart=HReg; AdrMode=ModIReg;
+ END
+ else if ((strlen(Asc)>1) AND (*Asc=='-') AND (DecodeReg(Asc+1,&HReg)))
+ BEGIN
+ AdrPart=HReg; AdrMode=ModPreDec;
+ END
+ else if ((strlen(Asc)>1) AND (Asc[strlen(Asc)-1]=='+'))
+ BEGIN
+ strmaxcpy(AdrStr,Asc,255); AdrStr[strlen(AdrStr)-1]='\0';
+ if (DecodeReg(AdrStr,&HReg))
+ BEGIN
+ AdrPart=HReg; AdrMode=ModPostInc;
+ END
+ else WrError(1350);
+ END
+ else WrError(1350);
+ ChkAdr(Mask); return;
+ END
+ END
+
+ if (*Asc=='#')
+ BEGIN
+ FirstPassUnknown=False;
+ switch (OpSize)
+ BEGIN
+ case 0: DispAcc=EvalIntExpression(Asc+1,Int8,&OK); break;
+ case 1: DispAcc=EvalIntExpression(Asc+1,Int16,&OK); break;
+ case 2: DispAcc=EvalIntExpression(Asc+1,Int32,&OK); break;
+ default: DispAcc=0; OK=True;
+ END
+ Critical=FirstPassUnknown OR UsesForwards;
+ if (OK)
+ BEGIN
+ /* minimale Groesse optimieren */
+ DOpSize=(OpSize==0) ? 0 : Ord(Critical);
+ while (((ExtOp(DispAcc,DOpSize,Signed) ^ DispAcc) & OpMask(OpSize))!=0) DOpSize++;
+ if (DOpSize==0)
+ BEGIN
+ AdrPart=DispAcc & 0xff;
+ AdrMode=ModImm;
+ END
+ else if ((Mask & MModPCRel)!=0)
+ BEGIN
+ /* Literalgroesse ermitteln */
+ NIs32=(DOpSize==2);
+ if (NOT NIs32) DispAcc&=0xffff;
+ /* Literale sektionsspezifisch */
+ strcpy(AdrStr,"[PARENT0]");
+ /* schon vorhanden ? */
+ Lauf=FirstLiteral; p=0; OK=False; Last=Nil; Found=False;
+ while ((Lauf!=Nil) AND (NOT Found))
+ BEGIN
+ Last=Lauf;
+ if ((NOT Critical) AND (NOT Lauf->IsForward)
+ AND (Lauf->DefSection==MomSectionHandle))
+ if (((Lauf->Is32==NIs32) AND (DispAcc==Lauf->Value))
+ OR ((Lauf->Is32) AND (NOT NIs32) AND (DispAcc==(Lauf->Value >> 16)))) Found=True;
+ else if ((Lauf->Is32) AND (NOT NIs32) AND (DispAcc==(Lauf->Value & 0xffff)))
+ BEGIN
+ Found=True; p=2;
+ END
+ if (NOT Found) Lauf=Lauf->Next;
+ END
+ /* nein - erzeugen */
+ if (NOT Found)
+ BEGIN
+ Lauf=(PLiteral) malloc(sizeof(TLiteral));
+ Lauf->Is32=NIs32; Lauf->Value=DispAcc;
+ Lauf->IsForward=Critical;
+ if (Critical) Lauf->FCount=ForwardCount++;
+ Lauf->Next=Nil; Lauf->PassNo=1; Lauf->DefSection=MomSectionHandle;
+ do
+ BEGIN
+ sprintf(LStr,"%s%s",LiteralName(Lauf),AdrStr);
+ LDef=IsSymbolDefined(LStr);
+ if (LDef) Lauf->PassNo++;
+ END
+ while (LDef);
+ if (Last==Nil) FirstLiteral=Lauf; else Last->Next=Lauf;
+ END
+ /* Distanz abfragen - im naechsten Pass... */
+ FirstPassUnknown=False;
+ sprintf(LStr,"%s%s",LiteralName(Lauf),AdrStr);
+ DispAcc=EvalIntExpression(LStr,Int32,&OK)+p;
+ if (OK)
+ BEGIN
+ if (FirstPassUnknown)
+ DispAcc=0;
+ else if (NIs32)
+ DispAcc=(DispAcc-(PCRelAdr() & 0xfffffffc)) >> 2;
+ else
+ DispAcc=(DispAcc-PCRelAdr()) >> 1;
+ if (DispAcc<0)
+ BEGIN
+ WrXError(1315,"Disp<0"); OK=False;
+ END
+ else if ((DispAcc>255) AND (NOT SymbolQuestionable)) WrError(1330);
+ else
+ BEGIN
+ AdrMode=ModPCRel; AdrPart=DispAcc; OpSize=Ord(NIs32)+1;
+ END
+ END
+ END
+ else WrError(1350);
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* absolut ueber PC-relativ abwickeln */
+
+ if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ DispAcc=EvalIntExpression(Asc,Int32,&OK);
+ if (FirstPassUnknown) DispAcc=0;
+ else if (OpSize==2) DispAcc-=(PCRelAdr() & 0xfffffffc);
+ else DispAcc-=PCRelAdr();
+ if (DispAcc<0) WrXError(1315,"Disp<0");
+ else if ((DispAcc & ((1 << OpSize)-1))!=0) WrError(1325);
+ else
+ BEGIN
+ DispAcc=DispAcc >> OpSize;
+ if (DispAcc>255) WrError(1320);
+ else
+ BEGIN
+ AdrMode=ModPCRel; AdrPart=DispAcc;
+ END
+ END
+ END
+
+ ChkAdr(Mask);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void LTORG_16(void)
+BEGIN
+ PLiteral Lauf;
+
+ Lauf=FirstLiteral;
+ while (Lauf!=Nil)
+ BEGIN
+ if ((NOT Lauf->Is32) AND (Lauf->DefSection==MomSectionHandle))
+ BEGIN
+ WAsmCode[CodeLen >> 1]=Lauf->Value;
+ EnterIntSymbol(LiteralName(Lauf),EProgCounter()+CodeLen,SegCode,False);
+ Lauf->PassNo=(-1);
+ CodeLen+=2;
+ END
+ Lauf=Lauf->Next;
+ END
+END
+
+ static void LTORG_32(void)
+BEGIN
+ PLiteral Lauf,EqLauf;
+
+ Lauf=FirstLiteral;
+ while (Lauf!=Nil)
+ BEGIN
+ if ((Lauf->Is32) AND (Lauf->DefSection==MomSectionHandle) AND (Lauf->PassNo>=0))
+ BEGIN
+ if (((EProgCounter()+CodeLen) & 2)!=0)
+ BEGIN
+ WAsmCode[CodeLen >> 1]=0; CodeLen+=2;
+ END
+ WAsmCode[CodeLen >> 1]=(Lauf->Value >> 16);
+ WAsmCode[(CodeLen >> 1)+1]=(Lauf->Value & 0xffff);
+ EnterIntSymbol(LiteralName(Lauf),EProgCounter()+CodeLen,SegCode,False);
+ Lauf->PassNo=(-1);
+ if (CompLiterals)
+ BEGIN
+ EqLauf=Lauf->Next;
+ while (EqLauf!=Nil)
+ BEGIN
+ if ((EqLauf->Is32) AND (EqLauf->PassNo>=0) AND
+ (EqLauf->DefSection==MomSectionHandle) AND
+ (EqLauf->Value==Lauf->Value))
+ BEGIN
+ EnterIntSymbol(LiteralName(EqLauf),EProgCounter()+CodeLen,SegCode,False);
+ EqLauf->PassNo=(-1);
+ END
+ EqLauf=EqLauf->Next;
+ END
+ END
+ CodeLen+=4;
+ END
+ Lauf=Lauf->Next;
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ PLiteral Lauf,Tmp,Last;
+
+ /* ab hier (und weiter in der Hauptroutine) stehen die Befehle,
+ die Code erzeugen, deshalb wird der Merker fuer verzoegerte
+ Spruenge hier weiter geschaltet. */
+
+ PrevDelayed=CurrDelayed; CurrDelayed=False;
+
+ if (Memo("LTORG"))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ if ((EProgCounter() & 3)==0)
+ BEGIN
+ LTORG_32(); LTORG_16();
+ END
+ else
+ BEGIN
+ LTORG_16(); LTORG_32();
+ END
+ Lauf=FirstLiteral; Last=Nil;
+ while (Lauf!=Nil)
+ BEGIN
+ if ((Lauf->DefSection==MomSectionHandle) AND (Lauf->PassNo<0))
+ BEGIN
+ Tmp=Lauf->Next;
+ if (Last==Nil) FirstLiteral=Tmp; else Last->Next=Tmp;
+ free(Lauf); Lauf=Tmp;
+ END
+ else
+ BEGIN
+ Last=Lauf; Lauf=Lauf->Next;
+ END
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void SetCode(Word Code)
+BEGIN
+ CodeLen=2; WAsmCode[0]=Code;
+END
+
+ static void MakeCode_7000(void)
+BEGIN
+ int z;
+ LongInt AdrLong;
+ Boolean OK;
+ Byte HReg;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* Attribut verwursten */
+
+ if (*AttrPart!='\0')
+ BEGIN
+ if (strlen(AttrPart)!=1)
+ BEGIN
+ WrError(1105); return;
+ END
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B': SetOpSize(0); break;
+ case 'W': SetOpSize(1); break;
+ case 'L': SetOpSize(2); break;
+ case 'Q': SetOpSize(3); break;
+ case 'S': SetOpSize(4); break;
+ case 'D': SetOpSize(5); break;
+ case 'X': SetOpSize(6); break;
+ case 'P': SetOpSize(7); break;
+ default:
+ WrError(1107); return;
+ END
+ END
+
+ if (DecodeMoto16Pseudo(OpSize,True)) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (MomCPU<FixedOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ SetCode(FixedOrders[z].Code);
+ if ((NOT SupAllowed) AND (FixedOrders[z].Priv)) WrError(50);
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("MOV"))
+ BEGIN
+ if (OpSize==-1) SetOpSize(2);
+ if (ArgCnt!=2) WrError(1110);
+ else if (OpSize>2) WrError(1130);
+ else if (DecodeReg(ArgStr[1],&HReg))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+MModIReg+MModPreDec+MModIndReg+MModR0Base+MModGBRBase,True);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize!=2) WrError(1130);
+ else SetCode(0x6003+(HReg << 4)+(AdrPart << 8));
+ break;
+ case ModIReg:
+ SetCode(0x2000+(HReg << 4)+(AdrPart << 8)+OpSize);
+ break;
+ case ModPreDec:
+ SetCode(0x2004+(HReg << 4)+(AdrPart << 8)+OpSize);
+ break;
+ case ModIndReg:
+ if (OpSize==2)
+ SetCode(0x1000+(HReg << 4)+(AdrPart & 15)+((AdrPart & 0xf0) << 4));
+ else if (HReg!=0) WrError(1350);
+ else SetCode(0x8000+AdrPart+(((Word)OpSize) << 8));
+ break;
+ case ModR0Base:
+ SetCode(0x0004+(AdrPart << 8)+(HReg << 4)+OpSize);
+ break;
+ case ModGBRBase:
+ if (HReg!=0) WrError(1350);
+ else SetCode(0xc000+AdrPart+(((Word)OpSize) << 8));
+ break;
+ END
+ END
+ else if (DecodeReg(ArgStr[2],&HReg))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModImm+MModPCRel+MModIReg+MModPostInc+MModIndReg+MModR0Base+MModGBRBase,True);
+ switch (AdrMode)
+ BEGIN
+ case ModIReg:
+ SetCode(0x6000+(AdrPart << 4)+(((Word)HReg) << 8)+OpSize);
+ break;
+ case ModPostInc:
+ SetCode(0x6004+(AdrPart << 4)+(((Word)HReg) << 8)+OpSize);
+ break;
+ case ModIndReg:
+ if (OpSize==2)
+ SetCode(0x5000+(((Word)HReg) << 8)+AdrPart);
+ else if (HReg!=0) WrError(1350);
+ else SetCode(0x8400+AdrPart+(((Word)OpSize) << 8));
+ break;
+ case ModR0Base:
+ SetCode(0x000c+(AdrPart << 4)+(((Word)HReg) << 8)+OpSize);
+ break;
+ case ModGBRBase:
+ if (HReg!=0) WrError(1350);
+ else SetCode(0xc400+AdrPart+(((Word)OpSize) << 8));
+ break;
+ case ModPCRel:
+ if (OpSize==0) WrError(1350);
+ else SetCode(0x9000+(((Word)OpSize-1) << 14)+(((Word)HReg) << 8)+AdrPart);
+ break;
+ case ModImm:
+ SetCode(0xe000+(((Word)HReg) << 8)+AdrPart);
+ break;
+ END
+ END
+ else WrError(1350);
+ return;
+ END
+
+ if (Memo("MOVA"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[2],&HReg)) WrError(1350);
+ else if (HReg!=0) WrError(1350);
+ else
+ BEGIN
+ SetOpSize(2);
+ DecodeAdr(ArgStr[1],MModPCRel,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0xc700+AdrPart;
+ END
+ END
+ return;
+ END
+
+ if (Memo("PREF"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIReg,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x0083+(AdrPart << 8);
+ END;
+ END;
+ return;
+ END
+
+ if ((Memo("LDC")) OR (Memo("STC")))
+ BEGIN
+ if (OpSize==-1) SetOpSize(2);
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (Memo("LDC"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ END
+ if (DecodeCtrlReg(ArgStr[1],&HReg))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+((Memo("LDC"))?MModPostInc:MModPreDec),False);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (Memo("LDC")) SetCode(0x400e + (AdrPart << 8)+(HReg << 4)); /* ANSI :-0 */
+ else SetCode(0x0002+(AdrPart << 8)+(HReg << 4));
+ break;
+ case ModPostInc:
+ SetCode(0x4007+(AdrPart << 8)+(HReg << 4));
+ break;
+ case ModPreDec:
+ SetCode(0x4003+(AdrPart << 8)+(HReg << 4));
+ break;
+ END
+ if ((AdrMode!=ModNone) AND (NOT SupAllowed)) WrError(50);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDS")) OR (Memo("STS")))
+ BEGIN
+ if (OpSize==-1) SetOpSize(2);
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (Memo("LDS"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ END
+ if (strcasecmp(ArgStr[1],"MACH")==0) HReg=0;
+ else if (strcasecmp(ArgStr[1],"MACL")==0) HReg=1;
+ else if (strcasecmp(ArgStr[1],"PR")==0) HReg=2;
+ else
+ BEGIN
+ WrError(1440); HReg=0xff;
+ END
+ if (HReg<0xff)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+((Memo("LDS"))?MModPostInc:MModPreDec),False);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (Memo("LDS")) SetCode(0x400a+(AdrPart << 8)+(HReg << 4));
+ else SetCode(0x000a+(AdrPart << 8)+(HReg << 4));
+ break;
+ case ModPostInc:
+ SetCode(0x4006+(AdrPart << 8)+(HReg << 4));
+ break;
+ case ModPreDec:
+ SetCode(0x4002+(AdrPart << 8)+(HReg << 4));
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ /* nur ein Register als Argument */
+
+ for (z=0; z<OneRegOrderCount; z++)
+ if (Memo(OneRegOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (MomCPU<OneRegOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg,False);
+ if (AdrMode!=ModNone)
+ SetCode(OneRegOrders[z].Code+(AdrPart << 8));
+ if ((NOT SupAllowed) AND ((Memo("STBR")) OR (Memo("LDBR")))) WrError(50);
+ if (*OpPart=='B')
+ BEGIN
+ CurrDelayed=True; DelayedAdr=0x7fffffff;
+ ChkDelayed();
+ END
+ END
+ return;
+ END
+
+ if (Memo("TAS"))
+ BEGIN
+ if (OpSize==-1) SetOpSize(0);
+ if (ArgCnt!=1) WrError(1110);
+ else if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIReg,False);
+ if (AdrMode!=ModNone) SetCode(0x401b+(AdrPart << 8));
+ END
+ return;
+ END
+
+ /* zwei Register */
+
+ for (z=0; z<TwoRegOrderCount; z++)
+ if (Memo(TwoRegOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((*AttrPart!='\0') AND (OpSize!=TwoRegOrders[z].DefSize)) WrError(1100);
+ else if (MomCPU<TwoRegOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ WAsmCode[0]=TwoRegOrders[z].Code+(AdrPart << 4);
+ DecodeAdr(ArgStr[2],MModReg,False);
+ if (AdrMode!=ModNone) SetCode(WAsmCode[0]+(((Word)AdrPart) << 8));
+ if ((NOT SupAllowed) AND (TwoRegOrders[z].Priv)) WrError(50);
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<MulRegOrderCount; z++)
+ if (Memo(MulRegOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<MulRegOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ if (*AttrPart=='\0') OpSize=2;
+ if (OpSize!=2) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ WAsmCode[0]=MulRegOrders[z].Code+(AdrPart << 4);
+ DecodeAdr(ArgStr[2],MModReg,False);
+ if (AdrMode!=ModNone) SetCode(WAsmCode[0]+(((Word)AdrPart) << 8));
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BWOrderCount; z++)
+ if (Memo(BWOrders[z].Name))
+ BEGIN
+ if (OpSize==-1) SetOpSize(1);
+ if (ArgCnt!=2) WrError(1110);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ WAsmCode[0]=BWOrders[z].Code+OpSize+(AdrPart << 4);
+ DecodeAdr(ArgStr[2],MModReg,False);
+ if (AdrMode!=ModNone) SetCode(WAsmCode[0]+(((Word)AdrPart) << 8));
+ END
+ END
+ return;
+ END
+
+ if (Memo("MAC"))
+ BEGIN
+ if (OpSize==-1) SetOpSize(1);
+ if (ArgCnt!=2) WrError(1110);
+ else if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else if ((OpSize==2) AND (MomCPU<CPU7600)) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModPostInc,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ WAsmCode[0]=0x000f+(AdrPart << 4)+(((Word)2-OpSize) << 14);
+ DecodeAdr(ArgStr[2],MModPostInc,False);
+ if (AdrMode!=ModNone) SetCode(WAsmCode[0]+(((Word)AdrPart) << 8));
+ END
+ END
+ return;
+ END
+
+ if (Memo("ADD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ HReg=AdrPart; OpSize=2;
+ DecodeAdr(ArgStr[1],MModReg+MModImm,True);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ SetCode(0x300c+(((Word)HReg) << 8)+(AdrPart << 4));
+ break;
+ case ModImm:
+ SetCode(0x7000+AdrPart+(((Word)HReg) << 8));
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CMP/EQ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ HReg=AdrPart; OpSize=2; DecodeAdr(ArgStr[1],MModReg+MModImm,True);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ SetCode(0x3000+(((Word)HReg) << 8)+(AdrPart << 4));
+ break;
+ case ModImm:
+ if (HReg!=0) WrError(1350);
+ else SetCode(0x8800+AdrPart);
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<LogOrderCount; z++)
+ if (Memo(LogOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+MModGBRR0,False);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ OpSize=2;
+ HReg=AdrPart; DecodeAdr(ArgStr[1],MModReg+MModImm,False);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ SetCode(0x2008+z+(((Word)HReg) << 8)+(AdrPart << 4));
+ break;
+ case ModImm:
+ if (HReg!=0) WrError(1350);
+ else SetCode(0xc800+(z << 8)+AdrPart);
+ break;
+ END
+ END
+ break;
+ case ModGBRR0:
+ DecodeAdr(ArgStr[1],MModImm,False);
+ if (AdrMode!=ModNone)
+ SetCode(0xcc00+(z << 8)+AdrPart);
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Miszellaneen.. */
+
+ if (Memo("TRAPA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ OpSize=0;
+ DecodeAdr(ArgStr[1],MModImm,False);
+ if (AdrMode==ModImm) SetCode(0xc300+AdrPart);
+ ChkDelayed();
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if ((Memo("BF")) OR (Memo("BT"))
+ OR (Memo("BF/S")) OR (Memo("BT/S")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1110);
+ else if ((strlen(OpPart)==4) AND (MomCPU<CPU7600)) WrError(1500);
+ else
+ BEGIN
+ DelayedAdr=EvalIntExpression(ArgStr[1],Int32,&OK);
+ AdrLong=DelayedAdr-(EProgCounter()+4);
+ if (OK)
+ if (Odd(AdrLong)) WrError(1375);
+ else if (((AdrLong<-256) OR (AdrLong>254)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ WAsmCode[0]=0x8900+((AdrLong >> 1) & 0xff);
+ if (OpPart[1]=='F') WAsmCode[0]+=0x200;
+ if (strlen(OpPart)==4)
+ BEGIN
+ WAsmCode[0]+=0x400; CurrDelayed=True;
+ END
+ CodeLen=2;
+ ChkDelayed();
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BRA")) OR (Memo("BSR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1110);
+ else
+ BEGIN
+ DelayedAdr=EvalIntExpression(ArgStr[1],Int32,&OK);
+ AdrLong=DelayedAdr-(EProgCounter()+4);
+ if (OK)
+ if (Odd(AdrLong)) WrError(1375);
+ else if (((AdrLong<-4096) OR (AdrLong>4094)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ WAsmCode[0]=0xa000+((AdrLong >> 1) & 0xfff);
+ if (Memo("BSR")) WAsmCode[0]+=0x1000;
+ CodeLen=2;
+ CurrDelayed=True; ChkDelayed();
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JSR")) OR (Memo("JMP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIReg,False);
+ if (AdrMode!=ModNone)
+ BEGIN
+ SetCode(0x400b+(AdrPart << 8)+(Ord(Memo("JMP")) << 5));
+ CurrDelayed=True; DelayedAdr=0x7fffffff;
+ ChkDelayed();
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_7000(void)
+BEGIN
+ SaveInitProc();
+ FirstLiteral=Nil; ForwardCount=0;
+END
+
+ static Boolean IsDef_7000(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_7000(void)
+BEGIN
+ DeinitFields();
+ if (FirstLiteral!=Nil) WrError(1495);
+ ClearONOFF();
+END
+
+ static void SwitchTo_7000(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x6c; NOPCode=0x0009;
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+#ifdef __STDC__
+ SegLimits[SegCode] = 0xfffffffful;
+#else
+ SegLimits[SegCode] = 0xffffffffl;
+#endif
+
+ MakeCode=MakeCode_7000; IsDef=IsDef_7000;
+ SwitchFrom=SwitchFrom_7000; InitFields();
+ AddONOFF("SUPMODE", &SupAllowed, SupAllowedName ,False);
+ AddONOFF("COMPLITERALS", &CompLiterals, CompLiteralsName,False);
+ AddMoto16PseudoONOFF();
+
+ CurrDelayed=False; PrevDelayed=False;
+
+ SetFlag(&DoPadding,DoPaddingName,False);
+END
+
+ void code7000_init(void)
+BEGIN
+ CPU7000=AddCPU("SH7000",SwitchTo_7000);
+ CPU7600=AddCPU("SH7600",SwitchTo_7000);
+ CPU7700=AddCPU("SH7700",SwitchTo_7000);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_7000;
+ FirstLiteral=Nil;
+END
diff --git a/code7000.h b/code7000.h
new file mode 100644
index 0000000..17ce9cd
--- /dev/null
+++ b/code7000.h
@@ -0,0 +1,11 @@
+/* code7000.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator SH7x00 */
+/* */
+/* Historie: 25.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code7000_init(void);
diff --git a/code75k0.c b/code75k0.c
new file mode 100644
index 0000000..7c58414
--- /dev/null
+++ b/code75k0.c
@@ -0,0 +1,1436 @@
+/* code75k0.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator NEC 75K0 */
+/* */
+/* Historie: 31.12.1996 Grundsteinlegung */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+#define ModNone (-1)
+#define ModReg4 0
+#define MModReg4 (1 << ModReg4)
+#define ModReg8 1
+#define MModReg8 (1 << ModReg8)
+#define ModImm 2
+#define MModImm (1 << ModImm)
+#define ModInd 3
+#define MModInd (1 << ModInd)
+#define ModAbs 4
+#define MModAbs (1 << ModAbs)
+
+#define FixedOrderCount 6
+#define AriOrderCount 3
+#define LogOrderCount 3
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+
+static SimpProc SaveInitProc;
+
+static FixedOrder *FixedOrders;
+static char **AriOrders;
+static char **LogOrders;
+
+static LongInt MBSValue,MBEValue;
+static Boolean MinOneIs0;
+static CPUVar
+ CPU75402,CPU75004,CPU75006,CPU75008,
+ CPU75268,CPU75304,CPU75306,CPU75308,
+ CPU75312,CPU75316,CPU75328,CPU75104,
+ CPU75106,CPU75108,CPU75112,CPU75116,
+ CPU75206,CPU75208,CPU75212,CPU75216,
+ CPU75512,CPU75516;
+static Word ROMEnd;
+
+static ShortInt OpSize;
+static Byte AdrPart;
+static ShortInt AdrMode;
+
+/*-------------------------------------------------------------------------*/
+/* dynamische Codetabellenverwaltung */
+
+ static void AddFixed(char *NewName, Word NewCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NewName;
+ FixedOrders[InstrZ++].Code=NewCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ Boolean Err;
+
+ ROMEnd=ConstLongInt(MomCPUName+3,&Err);
+ if (ROMEnd>2) ROMEnd%=10;
+ ROMEnd=(ROMEnd << 10)-1;
+
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("RET" ,0x00ee);
+ AddFixed("RETS",0x00e0);
+ AddFixed("RETI",0x00ef);
+ AddFixed("HALT",0xa39d);
+ AddFixed("STOP",0xb39d);
+ AddFixed("NOP" ,0x0060);
+
+ AriOrders=(char **) malloc(sizeof(char *)*AriOrderCount); InstrZ=0;
+ AriOrders[InstrZ++]="ADDC";
+ AriOrders[InstrZ++]="SUBS";
+ AriOrders[InstrZ++]="SUBC";
+
+ LogOrders=(char **) malloc(sizeof(char *)*LogOrderCount); InstrZ=0;
+ LogOrders[InstrZ++]="AND";
+ LogOrders[InstrZ++]="OR";
+ LogOrders[InstrZ++]="XOR";
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(AriOrders);
+ free(LogOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Untermengen von Befehlssatz abpruefen */
+
+ static void CheckCPU(CPUVar MinCPU)
+BEGIN
+ if (MomCPU<MinCPU)
+ BEGIN
+ WrError(1500); CodeLen=0;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/* Adressausdruck parsen */
+
+ static Boolean SetOpSize(ShortInt NewSize)
+BEGIN
+ if (OpSize==-1) OpSize=NewSize;
+ else if (NewSize!=OpSize)
+ BEGIN
+ WrError(1131); return False;
+ END
+ return True;
+END
+
+ static void ChkDataPage(Word Adr)
+BEGIN
+ switch (MBEValue)
+ BEGIN
+ case 0: if ((Adr>0x7f) AND (Adr<0xf80)) WrError(110); break;
+ case 1: if (Hi(Adr)!=MBSValue) WrError(110); break;
+ END
+END
+
+ static void ChkAdr(Byte Mask)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ WrError(1350); AdrMode=ModNone;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Byte Mask)
+BEGIN
+ static char *RegNames="XAHLDEBC";
+
+ char *p;
+ int pos;
+ Boolean OK;
+ String s;
+
+ AdrMode=ModNone;
+
+ /* Register ? */
+
+ memcpy(s,Asc,2); s[2]='\0'; NLS_UpString(s);
+ p=strstr(RegNames,s);
+
+ if (p!=Nil)
+ BEGIN
+ pos=p-RegNames;
+
+ /* 8-Bit-Register ? */
+
+ if (strlen(Asc)==1)
+ BEGIN
+ AdrPart=pos ^ 1;
+ if (SetOpSize(0))
+ if ((AdrPart>4) AND (MomCPU<CPU75004)) WrError(1505);
+ else AdrMode=ModReg4;
+ ChkAdr(Mask); return;
+ END
+
+ /* 16-Bit-Register ? */
+
+ if ((strlen(Asc)==2) AND (NOT Odd(pos)))
+ BEGIN
+ AdrPart=pos;
+ if (SetOpSize(1))
+ if ((AdrPart>2) AND (MomCPU<CPU75004)) WrError(1505);
+ else AdrMode=ModReg8;
+ ChkAdr(Mask); return;
+ END
+
+ /* 16-Bit-Schattenregister ? */
+
+ if ((strlen(Asc)==3) AND ((Asc[2]=='\'') OR (Asc[2]=='`')) AND (NOT Odd(pos)))
+ BEGIN
+ AdrPart=pos+1;
+ if (SetOpSize(1))
+ if (MomCPU<CPU75104) WrError(1505); else AdrMode=ModReg8;
+ ChkAdr(Mask); return;
+ END
+ END
+
+ /* immediate? */
+
+ if (*Asc=='#')
+ BEGIN
+ if ((OpSize==-1) AND (MinOneIs0)) OpSize=0;
+ FirstPassUnknown=False;
+ switch (OpSize)
+ BEGIN
+ case -1: WrError(1132); break;
+ case 0: AdrPart=EvalIntExpression(Asc+1,Int4,&OK) & 15; break;
+ case 1: AdrPart=EvalIntExpression(Asc+1,Int8,&OK); break;
+ END;
+ if (OK) AdrMode=ModImm;
+ ChkAdr(Mask); return;
+ END
+
+ /* indirekt ? */
+
+ if (*Asc=='@')
+ BEGIN
+ strmaxcpy(s,Asc+1,255);
+ if (strcasecmp(s,"HL")==0) AdrPart=1;
+ else if (strcasecmp(s,"HL+")==0) AdrPart=2;
+ else if (strcasecmp(s,"HL-")==0) AdrPart=3;
+ else if (strcasecmp(s,"DE")==0) AdrPart=4;
+ else if (strcasecmp(s,"DL")==0) AdrPart=5;
+ else AdrPart=0;
+ if (AdrPart!=0)
+ BEGIN
+ if ((MomCPU<CPU75004) AND (AdrPart!=1)) WrError(1505);
+ else if ((MomCPU<CPU75104) AND ((AdrPart==2) OR (AdrPart==3))) WrError(1505);
+ else AdrMode=ModInd;
+ ChkAdr(Mask); return;
+ END
+ END
+
+ /* absolut */
+
+ FirstPassUnknown=False;
+ pos=EvalIntExpression(Asc,UInt12,&OK);
+ if (OK)
+ BEGIN
+ AdrPart=Lo(pos); AdrMode=ModAbs;
+ ChkSpace(SegData);
+ if (NOT FirstPassUnknown) ChkDataPage(pos);
+ END
+
+ ChkAdr(Mask);
+END
+
+static String BName;
+
+ static Boolean DecodeBitAddr(char *Asc, Word *Erg)
+BEGIN
+ char *p;
+ int Num;
+ Boolean OK;
+ Word Adr;
+ String bpart;
+
+ p=QuotPos(Asc,'.');
+ if (p==Nil)
+ BEGIN
+ *Erg=EvalIntExpression(Asc,Int16,&OK);
+ if (Hi(*Erg)!=0) ChkDataPage(((*Erg >> 4) & 0xf00)+Lo(*Erg));
+ return OK;
+ END
+
+ *p='\0';
+ strmaxcpy(bpart,p+1,255);
+
+ if (strcasecmp(bpart,"@L")==0)
+ BEGIN
+ FirstPassUnknown=False;
+ Adr=EvalIntExpression(Asc,UInt12,&OK);
+ if (FirstPassUnknown) Adr=(Adr & 0xffc) | 0xfc0;
+ if (OK)
+ BEGIN
+ ChkSpace(SegData);
+ if ((Adr & 3)!=0) WrError(1325);
+ else if (Adr<0xfc0) WrError(1315);
+ else if (MomCPU<CPU75004) WrError(1505);
+ else
+ BEGIN
+ *Erg=0x40+((Adr & 0x3c) >> 2);
+ sprintf(BName,"%sH.@L",HexString(Adr,3));
+ return True;
+ END
+ END
+ END
+ else
+ BEGIN
+ Num=EvalIntExpression(bpart,UInt2,&OK);
+ if (OK)
+ if (strncasecmp(Asc,"@H",2)==0)
+ BEGIN
+ Adr=EvalIntExpression(Asc+2,UInt4,&OK);
+ if (OK)
+ if (MomCPU<CPU75004) WrError(1505);
+ else
+ BEGIN
+ *Erg=(Num << 4)+Adr;
+ sprintf(BName,"@H%s.%c",HexString(Adr,1),Num+'0');
+ return True;
+ END
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Adr=EvalIntExpression(Asc,UInt12,&OK);
+ if (FirstPassUnknown) Adr=(Adr | 0xff0);
+ if (OK)
+ BEGIN
+ ChkSpace(SegData);
+ if ((Adr>=0xfb0) AND (Adr<0xfc0))
+ *Erg=0x80+(Num << 4)+(Adr & 15);
+ else if (Adr>=0xff0)
+ *Erg=0xc0+(Num << 4)+(Adr & 15);
+ else
+ *Erg=0x400+(((Word)Num) << 8)+Lo(Adr)+(Hi(Adr) << 12);
+ sprintf(BName,"%sH.%c",HexString(Adr,3),'0'+Num);
+ return True;
+ END
+ END
+ END
+ return False;
+END
+
+ static Boolean DecodeIntName(char *Asc, Byte *Erg)
+BEGIN
+ Word HErg;
+ Byte LPart;
+ String Asc_N;
+
+ strmaxcpy(Asc_N,Asc,255); NLS_UpString(Asc_N); Asc=Asc_N;
+
+ if (MomCPU<=CPU75402) LPart=0;
+ else if (MomCPU<CPU75004) LPart=1;
+ else if (MomCPU<CPU75104) LPart=2;
+ else LPart=3;
+ if (strcmp(Asc,"IEBT")==0) HErg=0x000;
+ else if (strcmp(Asc,"IEW")==0) HErg=0x102;
+ else if (strcmp(Asc,"IETPG")==0) HErg=0x203;
+ else if (strcmp(Asc,"IET0")==0) HErg=0x104;
+ else if (strcmp(Asc,"IECSI")==0) HErg=0x005;
+ else if (strcmp(Asc,"IECSIO")==0) HErg=0x205;
+ else if (strcmp(Asc,"IE0")==0) HErg=0x006;
+ else if (strcmp(Asc,"IE2")==0) HErg=0x007;
+ else if (strcmp(Asc,"IE4")==0) HErg=0x120;
+ else if (strcmp(Asc,"IEKS")==0) HErg=0x123;
+ else if (strcmp(Asc,"IET1")==0) HErg=0x224;
+ else if (strcmp(Asc,"IE1")==0) HErg=0x126;
+ else if (strcmp(Asc,"IE3")==0) HErg=0x227;
+ else HErg=0xfff;
+ if (HErg==0xfff) return False;
+ else if (Hi(HErg)>LPart) return False;
+ else
+ BEGIN
+ *Erg=Lo(HErg); return True;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME75Count 2
+ static ASSUMERec ASSUME75s[ASSUME75Count]=
+ {{"MBS", &MBSValue, 0, 0x0f, 0x10},
+ {"MBE", &MBEValue, 0, 0x01, 0x01}};
+
+ Word BErg;
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME75s,ASSUME75Count);
+ if ((MomCPU==CPU75402) AND (MBEValue!=0))
+ BEGIN
+ MBEValue=0; WrError(1440);
+ END
+ return True;
+ END
+
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,0xfff);
+ return True;
+ END
+
+ if (Memo("BIT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ if (DecodeBitAddr(ArgStr[1],&BErg))
+ if (NOT FirstPassUnknown)
+ BEGIN
+ PushLocHandle(-1);
+ EnterIntSymbol(LabPart,BErg,SegNone,False);
+ sprintf(ListLine,"=%s",BName);
+ PopLocHandle();
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void PutCode(Word Code)
+BEGIN
+ BAsmCode[0]=Lo(Code);
+ if (Hi(Code)==0) CodeLen=1;
+ else
+ BEGIN
+ BAsmCode[1]=Hi(Code); CodeLen=2;
+ END
+END
+
+ static void MakeCode_75K0(void)
+BEGIN
+ Integer AdrInt,Dist;
+ int z;
+ Byte HReg;
+ Word BVal;
+ Boolean OK,BrRel,BrLong;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1); MinOneIs0=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(True)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else PutCode(FixedOrders[z].Code);
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg4+MModReg8+MModInd+MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg4+MModInd+MModAbs+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (HReg==0)
+ BEGIN
+ PutCode(0x7899+(((Word)AdrPart) << 8)); CheckCPU(CPU75004);
+ END
+ else if (AdrPart==0)
+ BEGIN
+ PutCode(0x7099+(((Word)HReg) << 8)); CheckCPU(CPU75004);
+ END
+ else WrError(1350);
+ break;
+ case ModInd:
+ if (HReg!=0) WrError(1350);
+ else PutCode(0xe0+AdrPart);
+ break;
+ case ModAbs:
+ if (HReg!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xa3; BAsmCode[1]=AdrPart; CodeLen=2;
+ END
+ break;
+ case ModImm:
+ if (HReg==0) PutCode(0x70+AdrPart);
+ else
+ BEGIN
+ PutCode(0x089a+(((Word)AdrPart) << 12)+(((Word)HReg) << 8));
+ CheckCPU(CPU75004);
+ END
+ break;
+ END
+ break;
+ case ModReg8:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg8+MModAbs+MModInd+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (HReg==0)
+ BEGIN
+ PutCode(0x58aa+(((Word)AdrPart) << 8)); CheckCPU(CPU75004);
+ END
+ else if (AdrPart==0)
+ BEGIN
+ PutCode(0x50aa+(((Word)HReg) << 8)); CheckCPU(CPU75004);
+ END
+ else WrError(1350);
+ break;
+ case ModAbs:
+ if (HReg!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xa2; BAsmCode[1]=AdrPart; CodeLen=2;
+ if ((NOT FirstPassUnknown) AND (Odd(AdrPart))) WrError(180);
+ END
+ break;
+ case ModInd:
+ if ((HReg!=0) OR (AdrPart!=1)) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x18aa); CheckCPU(CPU75004);
+ END
+ break;
+ case ModImm:
+ if (Odd(HReg)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x89+HReg; BAsmCode[1]=AdrPart; CodeLen=2;
+ END
+ break;
+ END
+ break;
+ case ModInd:
+ if (AdrPart!=1) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg4+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ PutCode(0xe8); CheckCPU(CPU75004);
+ END
+ break;
+ case ModReg8:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x10aa); CheckCPU(CPU75004);
+ END
+ break;
+ END
+ END
+ break;
+ case ModAbs:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg4+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x93; BAsmCode[1]=HReg; CodeLen=2;
+ END
+ break;
+ case ModReg8:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x92; BAsmCode[1]=HReg; CodeLen=2;
+ if ((NOT FirstPassUnknown) AND (Odd(HReg))) WrError(180);
+ END
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("XCH"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg4+MModReg8+MModAbs+MModInd);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg4+MModAbs+MModInd);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (HReg==0) PutCode(0xd8+AdrPart);
+ else if (AdrPart==0) PutCode(0xd8+HReg);
+ else WrError(1350);
+ break;
+ case ModAbs:
+ if (HReg!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xb3; BAsmCode[1]=AdrPart; CodeLen=2;
+ END
+ break;
+ case ModInd:
+ if (HReg!=0) WrError(1350);
+ else PutCode(0xe8+AdrPart);
+ break;
+ END
+ break;
+ case ModReg8:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg8+MModAbs+MModInd);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (HReg==0)
+ BEGIN
+ PutCode(0x40aa+(((Word)AdrPart) << 8)); CheckCPU(CPU75004);
+ END
+ else if (AdrPart==0)
+ BEGIN
+ PutCode(0x40aa+(((Word)HReg) << 8)); CheckCPU(CPU75004);
+ END
+ else WrError(1350);
+ break;
+ case ModAbs:
+ if (HReg!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xb2; BAsmCode[1]=AdrPart; CodeLen=2;
+ if ((FirstPassUnknown) AND (Odd(AdrPart))) WrError(180);
+ END
+ break;
+ case ModInd:
+ if ((AdrPart!=1) OR (HReg!=0)) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x11aa); CheckCPU(CPU75004);
+ END
+ break;
+ END
+ break;
+ case ModAbs:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg4+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xb3; BAsmCode[1]=HReg; CodeLen=2;
+ END
+ break;
+ case ModReg8:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xb2; BAsmCode[1]=HReg; CodeLen=2;
+ if ((FirstPassUnknown) AND (Odd(HReg))) WrError(180);
+ END
+ break;
+ END
+ break;
+ case ModInd:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg4+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (AdrPart!=0) WrError(1350);
+ else PutCode(0xe8+HReg);
+ break;
+ case ModReg8:
+ if ((AdrPart!=0) OR (HReg!=1)) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x11aa); CheckCPU(CPU75004);
+ END;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOVT"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"XA")!=0) WrError(1350);
+ else if (strcasecmp(ArgStr[2],"@PCDE")==0)
+ BEGIN
+ PutCode(0xd4); CheckCPU(CPU75004);
+ END
+ else if (strcasecmp(ArgStr[2],"@PCXA")==0) PutCode(0xd0);
+ else WrError(1350);
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ OK=Memo("PUSH");
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"BS")==0)
+ BEGIN
+ PutCode(0x0699+(Ord(OK) << 8)); CheckCPU(CPU75004);
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (Odd(AdrPart)) WrError(1350);
+ else PutCode(0x48+Ord(OK)+AdrPart);
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("IN")) OR (Memo("OUT")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ z=Ord(Memo("IN"));
+ if (z>0)
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[3]);
+ END
+ if (strncasecmp(ArgStr[1],"PORT",4)!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=0xf0+EvalIntExpression(ArgStr[1]+4,UInt4,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg8+MModReg4);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x93+(z << 4); CodeLen=2;
+ END
+ break;
+ case ModReg8:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x92+(z << 4); CodeLen=2;
+ CheckCPU(CPU75004);
+ END
+ break;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ if (Memo("ADDS"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg4+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModImm+MModInd);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ PutCode(0x60+AdrPart); break;
+ case ModInd:
+ if (AdrPart==1) PutCode(0xd2); else WrError(1350);
+ break;
+ END
+ END
+ break;
+ case ModReg8:
+ if (AdrPart==0)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg8+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ PutCode(0xc8aa+(((Word)AdrPart) << 8));
+ CheckCPU(CPU75104);
+ break;
+ case ModImm:
+ BAsmCode[0]=0xb9; BAsmCode[1]=AdrPart;
+ CodeLen=2;
+ CheckCPU(CPU75104);
+ break;
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"XA")!=0) WrError(1350);
+ else
+ BEGIN
+ PutCode(0xc0aa+(((Word)AdrPart) << 8));
+ CheckCPU(CPU75104);
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<AriOrderCount; z++)
+ if (Memo(AriOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg4+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModInd);
+ switch (AdrMode)
+ BEGIN
+ case ModInd:
+ if (AdrPart==1)
+ BEGIN
+ BAsmCode[0]=0xa8;
+ if (z==0) BAsmCode[0]++;
+ if (z==2) BAsmCode[0]+=0x10;
+ CodeLen=1;
+ if (NOT Memo("ADDC")) CheckCPU(CPU75004);
+ END
+ else WrError(1350);
+ break;
+ END
+ END
+ break;
+ case ModReg8:
+ if (AdrPart==0)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ PutCode(0xc8aa+((z+1) << 12)+(((Word)AdrPart) << 8));
+ CheckCPU(CPU75104);
+ break;
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"XA")!=0) WrError(1350);
+ else
+ BEGIN
+ PutCode(0xc0aa+((z+1) << 12)+(((Word)AdrPart) << 8));
+ CheckCPU(CPU75104);
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<LogOrderCount; z++)
+ if (Memo(LogOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg4+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModImm+MModInd);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ PutCode(0x2099+(((Word)AdrPart & 15) << 8)+((z+1) << 12));
+ CheckCPU(CPU75004);
+ break;
+ case ModInd:
+ if (AdrPart==1) PutCode(0x80+((z+1) << 4)); else WrError(1350);
+ break;
+ END
+ END
+ break;
+ case ModReg8:
+ if (AdrPart==0)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ PutCode(0x88aa+(((Word)AdrPart) << 8)+((z+1) << 12));
+ CheckCPU(CPU75104);
+ break;
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"XA")!=0) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x80aa+(((Word)AdrPart) << 8)+((z+1) << 12));
+ CheckCPU(CPU75104);
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("INCS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg4+MModReg8+MModInd+MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ PutCode(0xc0+AdrPart);
+ break;
+ case ModReg8:
+ if ((AdrPart<1) OR (Odd(AdrPart))) WrError(1350);
+ else
+ BEGIN
+ PutCode(0x88+AdrPart); CheckCPU(CPU75104);
+ END
+ break;
+ case ModInd:
+ if (AdrPart==1)
+ BEGIN
+ PutCode(0x0299); CheckCPU(CPU75004);
+ END
+ else WrError(1350);
+ break;
+ case ModAbs:
+ BAsmCode[0]=0x82; BAsmCode[1]=AdrPart; CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("DECS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg4+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ PutCode(0xc8+AdrPart);
+ break;
+ case ModReg8:
+ PutCode(0x68aa+(((Word)AdrPart) << 8));
+ CheckCPU(CPU75104);
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("SKE"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg4+MModReg8+MModInd);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModImm+MModInd+MModReg4);
+ switch (AdrMode)
+ BEGIN
+ case ModReg4:
+ if (HReg==0)
+ BEGIN
+ PutCode(0x0899+(((Word)AdrPart) << 8)); CheckCPU(CPU75004);
+ END
+ else if (AdrPart==0)
+ BEGIN
+ PutCode(0x0899+(((Word)HReg) << 8)); CheckCPU(CPU75004);
+ END
+ else WrError(1350);
+ break;
+ case ModImm:
+ BAsmCode[0]=0x9a; BAsmCode[1]=(AdrPart << 4)+HReg;
+ CodeLen=2;
+ break;
+ case ModInd:
+ if ((AdrPart==1) AND (HReg==0)) PutCode(0x80);
+ else WrError(1350);
+ break;
+ END
+ break;
+ case ModReg8:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModInd+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (HReg==0)
+ BEGIN
+ PutCode(0x48aa+(((Word)AdrPart) << 8)); CheckCPU(CPU75104);
+ END
+ else if (AdrPart==0)
+ BEGIN
+ PutCode(0x48aa+(((Word)HReg) << 8)); CheckCPU(CPU75104);
+ END
+ else WrError(1350);
+ break;
+ case ModInd:
+ if (AdrPart==1)
+ BEGIN
+ PutCode(0x19aa); CheckCPU(CPU75104);
+ END
+ else WrError(1350);
+ break;
+ END
+ break;
+ case ModInd:
+ if (AdrPart!=1) WrError(1350);
+ else
+ BEGIN
+ MinOneIs0=True;
+ DecodeAdr(ArgStr[2],MModImm+MModReg4+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ PutCode(0x6099+(((Word)AdrPart) << 8)); CheckCPU(CPU75004);
+ break;
+ case ModReg4:
+ if (AdrPart==0) PutCode(0x80); else WrError(1350);
+ break;
+ case ModReg8:
+ if (AdrPart==0)
+ BEGIN
+ PutCode(0x19aa); CheckCPU(CPU75004);
+ END
+ else WrError(1350);
+ break;
+ END
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("RORC")) OR (Memo("NOT")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else if (Memo("RORC")) PutCode(0x98);
+ else PutCode(0x5f99);
+ return;
+ END
+
+ /* Bitoperationen */
+
+ if (Memo("MOV1"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OK=True;
+ if (strcasecmp(ArgStr[1],"CY")==0) z=0xbd;
+ else if (strcasecmp(ArgStr[2],"CY")==0) z=0x9b;
+ else OK=False;
+ if (NOT OK) WrError(1350);
+ else if (DecodeBitAddr(ArgStr[((z >> 2) & 3)-1],&BVal))
+ if (Hi(BVal)!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=z; BAsmCode[1]=BVal; CodeLen=2;
+ CheckCPU(CPU75104);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("SET1")) OR (Memo("CLR1")))
+ BEGIN
+ OK=Memo("SET1");
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CY")==0) PutCode(0xe6+Ord(OK));
+ else if (DecodeBitAddr(ArgStr[1],&BVal))
+ if (Hi(BVal)!=0)
+ BEGIN
+ BAsmCode[0]=0x84+Ord(OK)+(Hi(BVal & 0x300) << 4);
+ BAsmCode[1]=Lo(BVal); CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x9c+Ord(OK); BAsmCode[1]=BVal; CodeLen=2;
+ END
+ return;
+ END
+
+ if ((Memo("SKT")) OR (Memo("SKF")))
+ BEGIN
+ OK=Memo("SKT");
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CY")==0)
+ if (Memo("SKT")) PutCode(0xd7);
+ else WrError(1350);
+ else if (DecodeBitAddr(ArgStr[1],&BVal))
+ if (Hi(BVal)!=0)
+ BEGIN
+ BAsmCode[0]=0x86+Ord(OK)+(Hi(BVal & 0x300) << 4);
+ BAsmCode[1]=Lo(BVal); CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xbe + Ord(OK); /* ANSI :-0 */
+ BAsmCode[1]=BVal; CodeLen=2;
+ END
+ return;
+ END
+
+ if (Memo("NOT1"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CY")!=0) WrError(1350);
+ else PutCode(0xd6);
+ return;
+ END
+
+ if (Memo("SKTCLR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeBitAddr(ArgStr[1],&BVal))
+ if (Hi(BVal)!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x9f; BAsmCode[1]=BVal; CodeLen=2;
+ END
+ return;
+ END
+
+ if (OpPart[strlen(OpPart)-1]=='1')
+ for (z=0; z<LogOrderCount; z++)
+ if (strncmp(LogOrders[z],OpPart,strlen(LogOrders[z]))==0)
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CY")!=0) WrError(1350);
+ else if (DecodeBitAddr(ArgStr[2],&BVal))
+ if (Hi(BVal)!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xac+((z & 1) << 1)+((z & 2) << 3);
+ BAsmCode[1]=BVal; CodeLen=2;
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if (Memo("BR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"PCDE")==0)
+ BEGIN
+ PutCode(0x0499); CheckCPU(CPU75004);
+ END
+ else if (strcasecmp(ArgStr[1],"PCXA")==0)
+ BEGIN
+ BAsmCode[0]=0x99; BAsmCode[1]=0x00; CodeLen=2;
+ CheckCPU(CPU75104);
+ END
+ else
+ BEGIN
+ BrRel=False; BrLong=False;
+ if (*ArgStr[1]=='$')
+ BEGIN
+ BrRel=True; strcpy(ArgStr[1],ArgStr[1]+1);
+ END
+ else if (*ArgStr[1]=='!')
+ BEGIN
+ BrLong=True; strcpy(ArgStr[1],ArgStr[1]+1);
+ END
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ BEGIN
+ Dist=AdrInt-EProgCounter();
+ if ((BrRel) OR ((Dist<=16) AND (Dist>=-15) AND (Dist!=0)))
+ BEGIN
+ if (Dist>0)
+ BEGIN
+ Dist--;
+ if ((Dist>15) AND (NOT SymbolQuestionable)) WrError(1370);
+ else PutCode(0x00+Dist);
+ END
+ else
+ BEGIN
+ if ((Dist<-15) AND (NOT SymbolQuestionable)) WrError(1370);
+ else PutCode(0xf0+15+Dist);
+ END
+ END
+ else if ((NOT BrLong) AND ((AdrInt >> 12)==(EProgCounter() >> 12)) AND ((EProgCounter() & 0xfff)<0xffe))
+ BEGIN
+ BAsmCode[0]=0x50+((AdrInt >> 8) & 15);
+ BAsmCode[1]=Lo(AdrInt);
+ CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xab;
+ BAsmCode[1]=Hi(AdrInt & 0x3fff);
+ BAsmCode[2]=Lo(AdrInt);
+ CodeLen=3;
+ CheckCPU(CPU75004);
+ END
+ ChkSpace(SegCode);
+ END
+ END
+ return;
+ END
+
+ if (Memo("BRCB"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ if ((AdrInt >> 12)!=(EProgCounter() >> 12)) WrError(1910);
+ else if ((EProgCounter() & 0xfff)>=0xffe) WrError(1905);
+ else
+ BEGIN
+ BAsmCode[0]=0x50+((AdrInt >> 8) & 15);
+ BAsmCode[1]=Lo(AdrInt);
+ CodeLen=2;
+ ChkSpace(SegCode);
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]=='!')
+ BEGIN
+ strcpy(ArgStr[1],ArgStr[1]+1); BrLong=True;
+ END
+ else BrLong=False;
+ FirstPassUnknown=False;
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (FirstPassUnknown) AdrInt&=0x7ff;
+ if (OK)
+ BEGIN
+ if ((BrLong) OR (AdrInt>0x7ff))
+ BEGIN
+ BAsmCode[0]=0xab;
+ BAsmCode[1]=0x40+Hi(AdrInt & 0x3fff);
+ BAsmCode[2]=Lo(AdrInt);
+ CodeLen=3;
+ CheckCPU(CPU75004);
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x40+Hi(AdrInt & 0x7ff);
+ BAsmCode[1]=Lo(AdrInt);
+ CodeLen=2;
+ END
+ ChkSpace(SegCode);
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALLF"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]=='!') strcpy(ArgStr[1],ArgStr[1]+1);
+ AdrInt=EvalIntExpression(ArgStr[1],UInt11,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x40+Hi(AdrInt);
+ BAsmCode[1]=Lo(AdrInt);
+ CodeLen=2;
+ ChkSpace(SegCode);
+ END
+ END
+ return;
+ END
+
+ if (Memo("GETI"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=EvalIntExpression(ArgStr[1],UInt6,&OK);
+ CodeLen=Ord(OK);
+ CheckCPU(CPU75004);
+ END
+ return;
+ END
+
+ /* Steueranweisungen */
+
+ if ((Memo("EI")) OR (Memo("DI")))
+ BEGIN
+ OK=Memo("EI");
+ if (ArgCnt==0) PutCode(0xb29c+Ord(OK));
+ else if (ArgCnt!=1) WrError(1110);
+ else if (DecodeIntName(ArgStr[1],&HReg)) PutCode(0x989c+Ord(OK)+(((Word)HReg) << 8));
+ else WrError(1440);
+ return;
+ END
+
+ if (Memo("SEL"))
+ BEGIN
+ BAsmCode[0]=0x99;
+ if (ArgCnt!=1) WrError(1110);
+ else if (strncasecmp(ArgStr[1],"RB",2)==0)
+ BEGIN
+ BAsmCode[1]=0x20+EvalIntExpression(ArgStr[1]+2,UInt2,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; CheckCPU(CPU75104);
+ END
+ END
+ else if (strncasecmp(ArgStr[1],"MB",2)==0)
+ BEGIN
+ BAsmCode[1]=0x10+EvalIntExpression(ArgStr[1]+2,UInt4,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; CheckCPU(CPU75004);
+ END
+ END
+ else WrError(1350);
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_75K0(void)
+BEGIN
+ SaveInitProc();
+ MBSValue=0; MBEValue=0;
+END
+
+ static Boolean IsDef_75K0(void)
+BEGIN
+ return ((Memo("SFR")) OR (Memo("BIT")));
+END
+
+ static void SwitchFrom_75K0(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_75K0(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="PC"; HeaderID=0x7b; NOPCode=0x60;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
+ SegLimits[SegData] = 0xfff;
+
+ MakeCode=MakeCode_75K0; IsDef=IsDef_75K0;
+ SwitchFrom=SwitchFrom_75K0; InitFields();
+ SegLimits[SegCode] = ROMEnd;
+END
+
+ void code75k0_init(void)
+BEGIN
+ CPU75402=AddCPU("75402",SwitchTo_75K0);
+ CPU75004=AddCPU("75004",SwitchTo_75K0);
+ CPU75006=AddCPU("75006",SwitchTo_75K0);
+ CPU75008=AddCPU("75008",SwitchTo_75K0);
+ CPU75268=AddCPU("75268",SwitchTo_75K0);
+ CPU75304=AddCPU("75304",SwitchTo_75K0);
+ CPU75306=AddCPU("75306",SwitchTo_75K0);
+ CPU75308=AddCPU("75308",SwitchTo_75K0);
+ CPU75312=AddCPU("75312",SwitchTo_75K0);
+ CPU75316=AddCPU("75316",SwitchTo_75K0);
+ CPU75328=AddCPU("75328",SwitchTo_75K0);
+ CPU75104=AddCPU("75104",SwitchTo_75K0);
+ CPU75106=AddCPU("75106",SwitchTo_75K0);
+ CPU75108=AddCPU("75108",SwitchTo_75K0);
+ CPU75112=AddCPU("75112",SwitchTo_75K0);
+ CPU75116=AddCPU("75116",SwitchTo_75K0);
+ CPU75206=AddCPU("75206",SwitchTo_75K0);
+ CPU75208=AddCPU("75208",SwitchTo_75K0);
+ CPU75212=AddCPU("75212",SwitchTo_75K0);
+ CPU75216=AddCPU("75216",SwitchTo_75K0);
+ CPU75512=AddCPU("75512",SwitchTo_75K0);
+ CPU75516=AddCPU("75516",SwitchTo_75K0);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_75K0;
+END
+
diff --git a/code75k0.h b/code75k0.h
new file mode 100644
index 0000000..e2757a7
--- /dev/null
+++ b/code75k0.h
@@ -0,0 +1,11 @@
+/* code75k0.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator NEC 75K0 */
+/* */
+/* Historie: 31.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code75k0_init(void);
diff --git a/code7700.c b/code7700.c
new file mode 100644
index 0000000..b7fb20b
--- /dev/null
+++ b/code7700.c
@@ -0,0 +1,1304 @@
+/* code7700.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegeneratormodul MELPS-7700 */
+/* */
+/* Historie: 5.11.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+#include "code7700.h"
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Byte Allowed;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ ShortInt Disp8,Disp16;
+ } RelOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } AccOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte ACode,MCode;
+ } RMWOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte CodeImm,CodeAbs8,CodeAbs16,CodeIdxX8,CodeIdxX16,
+ CodeIdxY8,CodeIdxY16;
+ } XYOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Byte Allowed;
+ } MulDivOrder;
+
+#define ModNone (-1)
+#define ModImm 0
+#define MModImm (1l << ModImm)
+#define ModAbs8 1
+#define MModAbs8 (1l << ModAbs8)
+#define ModAbs16 2
+#define MModAbs16 (1l << ModAbs16)
+#define ModAbs24 3
+#define MModAbs24 (1l << ModAbs24)
+#define ModIdxX8 4
+#define MModIdxX8 (1l << ModIdxX8)
+#define ModIdxX16 5
+#define MModIdxX16 (1l << ModIdxX16)
+#define ModIdxX24 6
+#define MModIdxX24 (1l << ModIdxX24)
+#define ModIdxY8 7
+#define MModIdxY8 (1l << ModIdxY8)
+#define ModIdxY16 8
+#define MModIdxY16 (1l << ModIdxY16)
+#define ModIdxY24 9
+#define MModIdxY24 (1l << ModIdxY24)
+#define ModInd8 10
+#define MModInd8 (1l << ModInd8)
+#define ModInd16 11
+#define MModInd16 (1l << ModInd16)
+#define ModInd24 12
+#define MModInd24 (1l << ModInd24)
+#define ModIndX8 13
+#define MModIndX8 (1l << ModIndX8)
+#define ModIndX16 14
+#define MModIndX16 (1l << ModIndX16)
+#define ModIndX24 15
+#define MModIndX24 (1l << ModIndX24)
+#define ModIndY8 16
+#define MModIndY8 (1l << ModIndY8)
+#define ModIndY16 17
+#define MModIndY16 (1l << ModIndY16)
+#define ModIndY24 18
+#define MModIndY24 (1l << ModIndY24)
+#define ModIdxS8 19
+#define MModIdxS8 (1l << ModIdxS8)
+#define ModIndS8 20
+#define MModIndS8 (1l << ModIndS8)
+
+#define FixedOrderCnt 64
+
+#define RelOrderCnt 13
+
+#define AccOrderCnt 9
+
+#define RMWOrderCnt 6
+
+#define Imm8OrderCnt 5
+
+#define XYOrderCnt 6
+
+#define MulDivOrderCnt 4
+
+#define PushRegCnt 8
+static char *PushRegs[PushRegCnt]={"A","B","X","Y","DPR","DT","PG","PS"};
+
+#define PrefAccB 0x42
+
+static LongInt Reg_PG,Reg_DT,Reg_X,Reg_M,Reg_DPR,BankReg;
+
+static Boolean WordSize;
+static Byte AdrVals[3];
+static ShortInt AdrType;
+static Boolean LFlag;
+
+static FixedOrder *FixedOrders;
+static RelOrder *RelOrders;
+static AccOrder *AccOrders;
+static RMWOrder *RMWOrders;
+static FixedOrder *Imm8Orders;
+static XYOrder *XYOrders;
+static MulDivOrder *MulDivOrders;
+
+static SimpProc SaveInitProc;
+
+static CPUVar CPU65816,CPUM7700,CPUM7750,CPUM7751;
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode, Byte NAllowed)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ++].Allowed=NAllowed;
+END
+
+ static void AddRel(char *NName, Word NCode, ShortInt NDisp8, ShortInt NDisp16)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ].Code=NCode;
+ RelOrders[InstrZ].Disp8=NDisp8;
+ RelOrders[InstrZ++].Disp16=NDisp16;
+END
+
+ static void AddAcc(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=AccOrderCnt) exit(255);
+ AccOrders[InstrZ].Name=NName;
+ AccOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRMW(char *NName, Byte NACode, Byte NMCode)
+BEGIN
+ if (InstrZ>=RMWOrderCnt) exit(255);
+ RMWOrders[InstrZ].Name=NName;
+ RMWOrders[InstrZ].MCode=NMCode;
+ RMWOrders[InstrZ++].ACode=NACode;
+END
+
+ static void AddImm8(char *NName, Word NCode, Byte NAllowed)
+BEGIN
+ if (InstrZ>=Imm8OrderCnt) exit(255);
+ Imm8Orders[InstrZ].Name=NName;
+ Imm8Orders[InstrZ].Code=NCode;
+ Imm8Orders[InstrZ++].Allowed=NAllowed;
+END
+
+ static void AddXY(char *NName, Byte NCodeImm, Byte NCodeAbs8, Byte NCodeAbs16,
+ Byte NCodeIdxX8, Byte NCodeIdxX16, Byte NCodeIdxY8,
+ Byte NCodeIdxY16)
+BEGIN
+ if (InstrZ>=XYOrderCnt) exit(255);
+ XYOrders[InstrZ].Name=NName;
+ XYOrders[InstrZ].CodeImm=NCodeImm;
+ XYOrders[InstrZ].CodeAbs8=NCodeAbs8;
+ XYOrders[InstrZ].CodeAbs16=NCodeAbs16;
+ XYOrders[InstrZ].CodeIdxX8=NCodeIdxX8;
+ XYOrders[InstrZ].CodeIdxX16=NCodeIdxX16;
+ XYOrders[InstrZ].CodeIdxY8=NCodeIdxY8;
+ XYOrders[InstrZ++].CodeIdxY16=NCodeIdxY16;
+END
+
+ static void AddMulDiv(char *NName, Word NCode, Byte NAllowed)
+BEGIN
+ if (InstrZ>=MulDivOrderCnt) exit(255);
+ MulDivOrders[InstrZ].Name=NName;
+ MulDivOrders[InstrZ].Code=NCode;
+ MulDivOrders[InstrZ++].Allowed=NAllowed;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("CLC",0x0018,15); AddFixed("CLI",0x0058,15);
+ AddFixed("CLM",0x00d8,14); AddFixed("CLV",0x00b8,15);
+ AddFixed("DEX",0x00ca,15); AddFixed("DEY",0x0088,15);
+ AddFixed("INX",0x00e8,15); AddFixed("INY",0x00c8,15);
+ AddFixed("NOP",0x00ea,15); AddFixed("PHA",0x0048,15);
+ AddFixed("PHD",0x000b,15); AddFixed("PHG",0x004b,14);
+ AddFixed("PHP",0x0008,15); AddFixed("PHT",0x008b,14);
+ AddFixed("PHX",0x00da,15); AddFixed("PHY",0x005a,15);
+ AddFixed("PLA",0x0068,15); AddFixed("PLD",0x002b,15);
+ AddFixed("PLP",0x0028,15); AddFixed("PLT",0x00ab,14);
+ AddFixed("PLX",0x00fa,15); AddFixed("PLY",0x007a,15);
+ AddFixed("RTI",0x0040,15); AddFixed("RTL",0x006b,15);
+ AddFixed("RTS",0x0060,15); AddFixed("SEC",0x0038,15);
+ AddFixed("SEI",0x0078,15); AddFixed("SEM",0x00f8,14);
+ AddFixed("STP",0x00db,15); AddFixed("TAD",0x005b,15);
+ AddFixed("TAS",0x001b,15); AddFixed("TAX",0x00aa,15);
+ AddFixed("TAY",0x00a8,15); AddFixed("TBD",0x425b,14);
+ AddFixed("TBS",0x421b,14); AddFixed("TBX",0x42aa,14);
+ AddFixed("TBY",0x42a8,14); AddFixed("TDA",0x007b,15);
+ AddFixed("TDB",0x427b,14); AddFixed("TSA",0x003b,15);
+ AddFixed("TSX",0x00ba,15); AddFixed("TXA",0x008a,15);
+ AddFixed("TXB",0x428a,14); AddFixed("TXS",0x009a,15);
+ AddFixed("TXY",0x009b,15); AddFixed("TYA",0x0098,15);
+ AddFixed("TYB",0x4298,15); AddFixed("TYX",0x00bb,15);
+ AddFixed("WIT",0x00cb,14); AddFixed("XAB",0x8928,14);
+ AddFixed("COP",0x0002, 1); AddFixed("CLD",0x00d8, 1);
+ AddFixed("SED",0x00f8, 1); AddFixed("TCS",0x001b,15);
+ AddFixed("TSC",0x003b,15); AddFixed("TCD",0x005b,15);
+ AddFixed("TDC",0x007b,15); AddFixed("PHK",0x004b, 1);
+ AddFixed("WAI",0x00cb, 1); AddFixed("XBA",0x00eb, 1);
+ AddFixed("SWA",0x00eb, 1); AddFixed("XCE",0x00fb, 1);
+ AddFixed("DEA",(MomCPU>=CPUM7700) ? 0x001a : 0x003a,15);
+ AddFixed("INA",(MomCPU>=CPUM7700) ? 0x003a : 0x001a,15);
+
+ RelOrders=(RelOrder *) malloc(sizeof(RelOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("BCC" ,0x0090, 2,-1);
+ AddRel("BLT" ,0x0090, 2,-1);
+ AddRel("BCS" ,0x00b0, 2,-1);
+ AddRel("BGE" ,0x00b0, 2,-1);
+ AddRel("BEQ" ,0x00f0, 2,-1);
+ AddRel("BMI" ,0x0030, 2,-1);
+ AddRel("BNE" ,0x00d0, 2,-1);
+ AddRel("BPL" ,0x0010, 2,-1);
+ AddRel("BRA" ,0x8280, 2, 3);
+ AddRel("BVC" ,0x0050, 2,-1);
+ AddRel("BVS" ,0x0070, 2,-1);
+ AddRel("BRL" ,0x8200,-1, 3);
+ AddRel("BRAL",0x8200,-1, 3);
+
+ AccOrders=(AccOrder *) malloc(sizeof(AccOrder)*AccOrderCnt); InstrZ=0;
+ AddAcc("ADC",0x60);
+ AddAcc("AND",0x20);
+ AddAcc("CMP",0xc0);
+ AddAcc("CPA",0xc0);
+ AddAcc("EOR",0x40);
+ AddAcc("LDA",0xa0);
+ AddAcc("ORA",0x00);
+ AddAcc("SBC",0xe0);
+ AddAcc("STA",0x80);
+
+ RMWOrders=(RMWOrder *) malloc(sizeof(RMWOrder)*RMWOrderCnt); InstrZ=0;
+ AddRMW("ASL",0x0a,0x06);
+ AddRMW("DEC",(MomCPU>=CPUM7700)?0x1a:0x3a,0xc6);
+ AddRMW("ROL",0x2a,0x26);
+ AddRMW("INC",(MomCPU>=CPUM7700)?0x3a:0x1a,0xe6);
+ AddRMW("LSR",0x4a,0x46);
+ AddRMW("ROR",0x6a,0x66);
+
+ Imm8Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Imm8OrderCnt); InstrZ=0;
+ AddImm8("CLP",0x00c2,15);
+ AddImm8("REP",0x00c2,15);
+ AddImm8("LDT",0x89c2,14);
+ AddImm8("SEP",0x00e2,15);
+ AddImm8("RMPA",0x89e2,8);
+
+ XYOrders=(XYOrder *) malloc(sizeof(XYOrder)*XYOrderCnt); InstrZ=0;
+ AddXY("CPX",0xe0,0xe4,0xec,0xff,0xff,0xff,0xff);
+ AddXY("CPY",0xc0,0xc4,0xcc,0xff,0xff,0xff,0xff);
+ AddXY("LDX",0xa2,0xa6,0xae,0xff,0xff,0xb6,0xbe);
+ AddXY("LDY",0xa0,0xa4,0xac,0xb4,0xbc,0xff,0xff);
+ AddXY("STX",0xff,0x86,0x8e,0xff,0xff,0x96,0xff);
+ AddXY("STY",0xff,0x84,0x8c,0x94,0xff,0xff,0xff);
+
+ MulDivOrders=(MulDivOrder *) malloc(sizeof(MulDivOrder)*MulDivOrderCnt); InstrZ=0;
+ AddMulDiv("MPY",0x0000,14); AddMulDiv("MPYS",0x0080,12);
+ AddMulDiv("DIV",0x0020,14); AddMulDiv("DIVS",0x00a0,12); /*???*/
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(RelOrders);
+ free(AccOrders);
+ free(RMWOrders);
+ free(Imm8Orders);
+ free(XYOrders);
+ free(MulDivOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void ChkAdr(LongWord Mask)
+BEGIN
+ if (AdrType!=ModNone)
+ if ((Mask & (1l << ((LongWord)AdrType)))==0)
+ BEGIN
+ AdrType=ModNone; AdrCnt=0; WrError(1350);
+ END
+END
+
+
+ static void CodeDisp(char *Asc, LongInt Start, LongWord Mask)
+BEGIN
+ Boolean OK;
+ LongInt Adr;
+ ShortInt DType;
+ int l=strlen(Asc);
+
+ if ((l>1) AND (*Asc=='<'))
+ BEGIN
+ Asc++; DType=0;
+ END
+ else if ((l>1) AND (*Asc=='>'))
+ if ((l>2) AND (Asc[1]=='>'))
+ BEGIN
+ Asc+=2; DType=2;
+ END
+ else
+ BEGIN
+ Asc++; DType=1;
+ END
+ else DType=(-1);
+
+ Adr=EvalIntExpression(Asc,UInt24,&OK);
+
+ if (NOT OK) return;
+
+ if (DType==-1)
+ BEGIN
+ if ((((Mask & (1l << Start)))!=0) AND (Adr>=Reg_DPR) AND (Adr<Reg_DPR+0x100)) DType=0;
+ else if ((((Mask & (2l << Start)))!=0) AND ((Adr >> 16)==BankReg)) DType=1;
+ else DType=2;
+ END
+
+ if ((Mask & (1l << (Start+DType)))==0) WrError(1350);
+ else switch (DType)
+ BEGIN
+ case 0:
+ if ((FirstPassUnknown) OR (ChkRange(Adr,Reg_DPR,Reg_DPR+0xff)))
+ BEGIN
+ AdrCnt=1; AdrType=Start;
+ AdrVals[0]=Lo(Adr-Reg_DPR);
+ END;
+ break;
+ case 1:
+ if ((NOT FirstPassUnknown) AND ((Adr >> 16)!=BankReg)) WrError(1320);
+ else
+ BEGIN
+ AdrCnt=2; AdrType=Start+1;
+ AdrVals[0]=Lo(Adr); AdrVals[1]=Hi(Adr);
+ END
+ break;
+ case 2:
+ AdrCnt=3; AdrType=Start+2;
+ AdrVals[0]=Lo(Adr); AdrVals[1]=Hi(Adr); AdrVals[2]=Adr >> 16;
+ break;
+ END
+END
+
+ static void SplitArg(char *Src, String *HStr, Integer *HCnt)
+BEGIN
+ char *p;
+
+ strcpy(Src,Src+1); Src[strlen(Src)-1]='\0';
+ p=QuotPos(Src,',');
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(HStr[0],Src,255); *HCnt=1;
+ END
+ else
+ BEGIN
+ *p='\0';
+ strmaxcpy(HStr[0],Src,255);
+ strmaxcpy(HStr[1],p+1,255);
+ *p=',';
+ *HCnt=2;
+ END
+END
+
+ static void DecodeAdr(Integer Start, LongWord Mask)
+BEGIN
+ Word AdrWord;
+ Boolean OK;
+ Integer HCnt;
+ String HStr[2];
+
+ AdrType=ModNone; AdrCnt=0; BankReg=Reg_DT;
+
+ /* I. 1 Parameter */
+
+ if (Start==ArgCnt)
+ BEGIN
+ /* I.1. immediate */
+
+ if (*ArgStr[Start]=='#')
+ BEGIN
+ if (WordSize)
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[Start]+1,Int16,&OK);
+ AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord);
+ END
+ else AdrVals[0]=EvalIntExpression(ArgStr[Start]+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1+Ord(WordSize); AdrType=ModImm;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* I.2. indirekt */
+
+ if (IsIndirect(ArgStr[Start]))
+ BEGIN
+ SplitArg(ArgStr[Start],HStr,&HCnt);
+
+ /* I.2.i. einfach indirekt */
+
+ if (HCnt==1)
+ BEGIN
+ CodeDisp(HStr[0],ModInd8,Mask); ChkAdr(Mask); return;
+ END
+
+ /* I.2.ii indirekt mit Vorindizierung */
+
+ else if (strcasecmp(HStr[1],"X")==0)
+ BEGIN
+ CodeDisp(HStr[0],ModIndX8,Mask); ChkAdr(Mask); return;
+ END
+
+ else
+ BEGIN
+ WrError(1350); ChkAdr(Mask); return;
+ END
+ END
+
+ /* I.3. absolut */
+
+ else
+ BEGIN
+ CodeDisp(ArgStr[Start],ModAbs8,Mask); ChkAdr(Mask); return;
+ END
+ END
+
+ /* II. 2 Parameter */
+
+ else if (Start+1==ArgCnt)
+ BEGIN
+ /* II.1 indirekt mit Nachindizierung */
+
+ if (IsIndirect(ArgStr[Start]))
+ BEGIN
+ if (strcasecmp(ArgStr[Start+1],"Y")!=0) WrError(1350);
+ else
+ BEGIN
+ SplitArg(ArgStr[Start],HStr,&HCnt);
+
+ /* II.1.i. (d),Y */
+
+ if (HCnt==1)
+ BEGIN
+ CodeDisp(HStr[0],ModIndY8,Mask); ChkAdr(Mask); return;
+ END
+
+ /* II.1.ii. (d,S),Y */
+
+ else if (strcasecmp(HStr[1],"S")==0)
+ BEGIN
+ AdrVals[0]=EvalIntExpression(HStr[0],Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModIndS8; AdrCnt=1;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ else WrError(1350);
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* II.2. einfach indiziert */
+
+ else
+ BEGIN
+ /* II.2.i. d,X */
+
+ if (strcasecmp(ArgStr[Start+1],"X")==0)
+ BEGIN
+ CodeDisp(ArgStr[Start],ModIdxX8,Mask); ChkAdr(Mask); return;
+ END
+
+ /* II.2.ii. d,Y */
+
+ else if (strcasecmp(ArgStr[Start+1],"Y")==0)
+ BEGIN
+ CodeDisp(ArgStr[Start],ModIdxY8,Mask); ChkAdr(Mask); return;
+ END
+
+ /* II.2.iii. d,S */
+
+ else if (strcasecmp(ArgStr[Start+1],"S")==0)
+ BEGIN
+ AdrVals[0]=EvalIntExpression(ArgStr[Start],Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModIdxS8; AdrCnt=1;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ else WrError(1350);
+ END
+ END
+
+ else WrError(1110);
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME7700Count 5
+static ASSUMERec ASSUME7700s[ASSUME7700Count]=
+ {{"PG" , &Reg_PG , 0, 0xff, 0x100},
+ {"DT" , &Reg_DT , 0, 0xff, 0x100},
+ {"X" , &Reg_X , 0, 1, -1},
+ {"M" , &Reg_M , 0, 1, -1},
+ {"DPR", &Reg_DPR, 0,0xffff,0x10000}};
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME7700s,ASSUME7700Count);
+ return True;
+ END
+
+ return False;
+END
+
+ static Boolean LMemo(char *s)
+BEGIN
+ String tmp;
+
+ if (Memo(s))
+ BEGIN
+ LFlag=False; return True;
+ END
+ else
+ BEGIN
+ strmaxcpy(tmp,s,255); strmaxcat(tmp,"L",255);
+ if (Memo(tmp))
+ BEGIN
+ LFlag=True; return True;
+ END
+ else return False;
+ END
+END
+
+ static void MakeCode_7700(void)
+BEGIN
+ int z;
+ Integer Start;
+ LongInt AdrLong,Mask;
+ Boolean OK,Rel;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeMotoPseudo(False)) return;
+ if (DecodeIntelPseudo(False)) return;
+
+ /* ohne Argument */
+
+ if (Memo("BRK"))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x00; BAsmCode[1]=NOPCode;
+ END
+ return;
+ END
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (((FixedOrders[z].Allowed >> (MomCPU-CPU65816))&1)==0) WrError(1500);
+ else
+ BEGIN
+ CodeLen=1+Ord(Hi(FixedOrders[z].Code)!=0);
+ if (CodeLen==2) BAsmCode[0]=Hi(FixedOrders[z].Code);
+ BAsmCode[CodeLen-1]=Lo(FixedOrders[z].Code);
+ END
+ return;
+ END
+
+ if ((Memo("PHB")) OR (Memo("PLB")))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ if (MomCPU>=CPUM7700)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=PrefAccB; BAsmCode[1]=0x48;
+ END
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x8b;
+ END;
+ if (Memo("PLB")) BAsmCode[CodeLen-1]+=0x20;
+ END
+ return;
+ END
+
+ /* relative Adressierung */
+
+ for (z=0; z<RelOrderCnt; z++)
+ if (Memo(RelOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]=='#') strcpy(ArgStr[1],ArgStr[1]+1);
+ AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (OK)
+ BEGIN
+ OK=RelOrders[z].Disp8==-1;
+ if (OK) AdrLong-=EProgCounter()+RelOrders[z].Disp16;
+ else
+ BEGIN
+ AdrLong-=EProgCounter()+RelOrders[z].Disp8;
+ if (((AdrLong>127) OR (AdrLong<-128)) AND (NOT SymbolQuestionable) AND (RelOrders[z].Disp16!=-1))
+ BEGIN
+ OK=True; AdrLong-=RelOrders[z].Disp16-RelOrders[z].Disp8;
+ END
+ END
+ if (OK) /* d16 */
+ if (((AdrLong<-32768) OR (AdrLong>32767)) AND (NOT SymbolQuestionable)) WrError(1330);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=Hi(RelOrders[z].Code);
+ BAsmCode[1]=Lo(AdrLong); BAsmCode[2]=Hi(AdrLong);
+ END
+ else /* d8 */
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=Lo(RelOrders[z].Code);
+ BAsmCode[1]=Lo(AdrLong);
+ END
+ END
+ END
+ return;
+ END
+
+ /* mit Akku */
+
+ for (z=0; z<AccOrderCnt; z++)
+ if (LMemo(AccOrders[z].Name))
+ BEGIN
+ if ((ArgCnt==0) OR (ArgCnt>3)) WrError(1110);
+ else
+ BEGIN
+ WordSize=(Reg_M==0);
+ if (strcasecmp(ArgStr[1],"A")==0) Start=2;
+ else if (strcasecmp(ArgStr[1],"B")==0)
+ BEGIN
+ Start=2; BAsmCode[0]=PrefAccB; CodeLen++;
+ if (MomCPU==CPU65816)
+ BEGIN
+ WrError(1505); return;
+ END
+ END
+ else Start=1;
+ Mask=MModAbs8+MModAbs16+MModAbs24+
+ MModIdxX8+MModIdxX16+MModIdxX24+
+ MModIdxY16+
+ MModInd8+MModIndX8+MModIndY8+
+ MModIdxS8+MModIndS8;
+ if (NOT LMemo("STA")) Mask+=MModImm;
+ DecodeAdr(Start,Mask);
+ if (AdrType!=ModNone)
+ if ((LFlag) AND (AdrType!=ModInd8) AND (AdrType!=ModIndY8)) WrError(1350);
+ else
+ BEGIN
+ switch (AdrType)
+ BEGIN
+ case ModImm : BAsmCode[CodeLen]=AccOrders[z].Code+0x09; break;
+ case ModAbs8 : BAsmCode[CodeLen]=AccOrders[z].Code+0x05; break;
+ case ModAbs16 : BAsmCode[CodeLen]=AccOrders[z].Code+0x0d; break;
+ case ModAbs24 : BAsmCode[CodeLen]=AccOrders[z].Code+0x0f; break;
+ case ModIdxX8 : BAsmCode[CodeLen]=AccOrders[z].Code+0x15; break;
+ case ModIdxX16 : BAsmCode[CodeLen]=AccOrders[z].Code+0x1d; break;
+ case ModIdxX24 : BAsmCode[CodeLen]=AccOrders[z].Code+0x1f; break;
+ case ModIdxY16 : BAsmCode[CodeLen]=AccOrders[z].Code+0x19; break;
+ case ModInd8 : if (LFlag) BAsmCode[CodeLen]=AccOrders[z].Code+0x07;
+ else BAsmCode[CodeLen]=AccOrders[z].Code+0x12; break;
+ case ModIndX8 : BAsmCode[CodeLen]=AccOrders[z].Code+0x01; break;
+ case ModIndY8 : if (LFlag) BAsmCode[CodeLen]=AccOrders[z].Code+0x17;
+ else BAsmCode[CodeLen]=AccOrders[z].Code+0x11; break;
+ case ModIdxS8 : BAsmCode[CodeLen]=AccOrders[z].Code+0x03; break;
+ case ModIndS8 : BAsmCode[CodeLen]=AccOrders[z].Code+0x13; break;
+ END
+ memcpy(BAsmCode+CodeLen+1,AdrVals,AdrCnt); CodeLen+=1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("EXTS")) OR (Memo("EXTZ")))
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ strmaxcpy(ArgStr[1],"A",255); ArgCnt=1;
+ END
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPUM7750) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[1]=0x8b+(Ord(Memo("EXTZ")) << 5);
+ BAsmCode[0]=0;
+ if (strcasecmp(ArgStr[1],"A")==0) BAsmCode[0]=0x89;
+ else if (strcasecmp(ArgStr[1],"B")==0) BAsmCode[0]=0x42;
+ else WrError(1350);
+ if (BAsmCode[0]!=0) CodeLen=2;
+ END
+ return;
+ END
+
+ for (z=0; z<RMWOrderCnt; z++)
+ if (Memo(RMWOrders[z].Name))
+ BEGIN
+ if ((ArgCnt==0) OR ((ArgCnt==1) AND (strcasecmp(ArgStr[1],"A")==0)))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=RMWOrders[z].ACode;
+ END
+ else if ((ArgCnt==1) AND (strcasecmp(ArgStr[1],"B")==0))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=PrefAccB; BAsmCode[1]=RMWOrders[z].ACode;
+ if (MomCPU==CPU65816)
+ BEGIN
+ WrError(1505); return;
+ END
+ END
+ else if (ArgCnt>2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(1,MModAbs8+MModAbs16+MModIdxX8+MModIdxX16);
+ if (AdrType!=ModNone)
+ BEGIN
+ switch (AdrType)
+ BEGIN
+ case ModAbs8 : BAsmCode[0]=RMWOrders[z].MCode; break;
+ case ModAbs16 : BAsmCode[0]=RMWOrders[z].MCode+8; break;
+ case ModIdxX8 : BAsmCode[0]=RMWOrders[z].MCode+16; break;
+ case ModIdxX16 : BAsmCode[0]=RMWOrders[z].MCode+24; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if (Memo("ASR"))
+ BEGIN
+ if (MomCPU<CPUM7750) WrError(1500);
+ else if ((ArgCnt==0) OR ((ArgCnt==1) AND (strcasecmp(ArgStr[1],"A")==0)))
+ BEGIN
+ BAsmCode[0]=0x89; BAsmCode[1]=0x08; CodeLen=2;
+ END
+ else if ((ArgCnt==1) AND (strcasecmp(ArgStr[1],"B")==0))
+ BEGIN
+ BAsmCode[0]=0x42; BAsmCode[1]=0x08; CodeLen=2;
+ END
+ else if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(1,MModAbs8+MModIdxX8+MModAbs16+MModIdxX16);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x89;
+ switch (AdrType)
+ BEGIN
+ case ModAbs8:BAsmCode[1]=0x06; break;
+ case ModIdxX8:BAsmCode[1]=0x16; break;
+ case ModAbs16:BAsmCode[1]=0x0e; break;
+ case ModIdxX16:BAsmCode[1]=0x1e; break;
+ END
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BBC")) OR (Memo("BBS")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (MomCPU<CPUM7700) WrError(1500);
+ else
+ BEGIN
+ WordSize=(Reg_M==0);
+ ArgCnt=2; DecodeAdr(2,MModAbs8+MModAbs16);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x24;
+ if (Memo("BBC")) BAsmCode[0]+=0x10;
+ if (AdrType==ModAbs16) BAsmCode[0]+=8;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ ArgCnt=1; DecodeAdr(1,MModImm);
+ if (AdrType==ModNone) CodeLen=0;
+ else
+ BEGIN
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt); CodeLen+=AdrCnt;
+ AdrLong=EvalIntExpression(ArgStr[3],UInt24,&OK)-(EProgCounter()+CodeLen+1);
+ if (NOT OK) CodeLen=0;
+ else if ((NOT SymbolQuestionable) AND ((AdrLong<-128) OR (AdrLong>127)))
+ BEGIN
+ WrError(1370); CodeLen=0;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=Lo(AdrLong); CodeLen++;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("BIT"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if (MomCPU!=CPU65816) WrError(1500);
+ else
+ BEGIN
+ WordSize=False;
+ DecodeAdr(1,MModAbs8+MModAbs16+MModIdxX8+MModIdxX16+MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ switch (AdrType)
+ BEGIN
+ case ModAbs8:BAsmCode[0]=0x24; break;
+ case ModAbs16:BAsmCode[0]=0x2c; break;
+ case ModIdxX8:BAsmCode[0]=0x34; break;
+ case ModIdxX16:BAsmCode[0]=0x3c; break;
+ case ModImm:BAsmCode[0]=0x89; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CLB")) OR (Memo("SEB")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPUM7700) WrError(1500);
+ else
+ BEGIN
+ WordSize=(Reg_M==0);
+ DecodeAdr(2,MModAbs8+MModAbs16);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x04;
+ if (Memo("CLB")) BAsmCode[0]+=0x10;
+ if (AdrType==ModAbs16) BAsmCode[0]+=8;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ ArgCnt=1; DecodeAdr(1,MModImm);
+ if (AdrType==ModNone) CodeLen=0;
+ else
+ BEGIN
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt); CodeLen+=AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("TSB")) OR (Memo("TRB")))
+ BEGIN
+ if (MomCPU==CPU65816)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(1,MModAbs8+MModAbs16);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x04;
+ if (Memo("TRB")) BAsmCode[0]+=0x10;
+ if (AdrType==ModAbs16) BAsmCode[0]+=8;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ END
+ END
+ END
+ else if (Memo("TRB")) WrError(1500);
+ else if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x42; BAsmCode[1]=0x3b;
+ END
+ return;
+ END
+
+ for (z=0; z<Imm8OrderCnt; z++)
+ if (Memo(Imm8Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (((Imm8Orders[z].Allowed >> (MomCPU-CPU65816))&1)==0) WrError(1500);
+ else
+ BEGIN
+ WordSize=False;
+ DecodeAdr(1,MModImm);
+ if (AdrType==ModImm)
+ BEGIN
+ CodeLen=1+Ord(Hi(Imm8Orders[z].Code)!=0);
+ if (CodeLen==2) BAsmCode[0]=Hi(Imm8Orders[z].Code);
+ BAsmCode[CodeLen-1]=Lo(Imm8Orders[z].Code);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt); CodeLen+=AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if (Memo("RLA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ WordSize=(Reg_M==0);
+ DecodeAdr(1,MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0x89; BAsmCode[1]=0x49;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<XYOrderCnt; z++)
+ if (Memo(XYOrders[z].Name))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ WordSize=(Reg_X==0); Mask=0;
+ if (XYOrders[z].CodeImm !=0xff) Mask+=MModImm;
+ if (XYOrders[z].CodeAbs8 !=0xff) Mask+=MModAbs8;
+ if (XYOrders[z].CodeAbs16 !=0xff) Mask+=MModAbs16;
+ if (XYOrders[z].CodeIdxX8 !=0xff) Mask+=MModIdxX8;
+ if (XYOrders[z].CodeIdxX16!=0xff) Mask+=MModIdxX16;
+ if (XYOrders[z].CodeIdxY8 !=0xff) Mask+=MModIdxY8;
+ if (XYOrders[z].CodeIdxY16!=0xff) Mask+=MModIdxY16;
+ DecodeAdr(1,Mask);
+ if (AdrType!=ModNone)
+ BEGIN
+ switch (AdrType)
+ BEGIN
+ case ModImm :BAsmCode[0]=XYOrders[z].CodeImm; break;
+ case ModAbs8 :BAsmCode[0]=XYOrders[z].CodeAbs8; break;
+ case ModAbs16 :BAsmCode[0]=XYOrders[z].CodeAbs16; break;
+ case ModIdxX8 :BAsmCode[0]=XYOrders[z].CodeIdxX8; break;
+ case ModIdxY8 :BAsmCode[0]=XYOrders[z].CodeIdxY8; break;
+ case ModIdxX16:BAsmCode[0]=XYOrders[z].CodeIdxX16; break;
+ case ModIdxY16:BAsmCode[0]=XYOrders[z].CodeIdxY16; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<MulDivOrderCnt; z++)
+ if (LMemo(MulDivOrders[z].Name))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (((MulDivOrders[z].Allowed >> (MomCPU-CPU65816))&1)==0) WrError(1500);
+ else
+ BEGIN
+ WordSize=(Reg_M==0);
+ DecodeAdr(1,MModImm+MModAbs8+MModAbs16+MModAbs24+MModIdxX8+MModIdxX16+
+ MModIdxX24+MModIdxY16+MModInd8+MModIndX8+MModIndY8+
+ MModIdxS8+MModIndS8);
+ if (AdrType!=ModNone)
+ if ((LFlag) AND (AdrType!=ModInd8) AND (AdrType!=ModIndY8)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x89;
+ switch (AdrType)
+ BEGIN
+ case ModImm : BAsmCode[1]=0x09; break;
+ case ModAbs8 : BAsmCode[1]=0x05; break;
+ case ModAbs16 : BAsmCode[1]=0x0d; break;
+ case ModAbs24 : BAsmCode[1]=0x0f; break;
+ case ModIdxX8 : BAsmCode[1]=0x15; break;
+ case ModIdxX16 : BAsmCode[1]=0x1d; break;
+ case ModIdxX24 : BAsmCode[1]=0x1f; break;
+ case ModIdxY16 : BAsmCode[1]=0x19; break;
+ case ModInd8 : BAsmCode[1]=(LFlag) ? 0x07 : 0x12; break;
+ case ModIndX8 : BAsmCode[1]=0x01; break;
+ case ModIndY8 : BAsmCode[1]=(LFlag) ? 0x17 : 0x11; break;
+ case ModIdxS8 : BAsmCode[1]=0x03; break;
+ case ModIndS8 : BAsmCode[1]=0x13; break;
+ END
+ BAsmCode[1]+=MulDivOrders[z].Code;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JML")) OR (Memo("JSL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4;
+ BAsmCode[0]=(Memo("JSL")) ? 0x22 : 0x5c;
+ BAsmCode[1]=AdrLong >> 16;
+ BAsmCode[2]=Hi(AdrLong);
+ BAsmCode[3]=Lo(AdrLong);
+ END
+ END
+ return;
+ END
+
+ if ((LMemo("JMP")) OR (LMemo("JSR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ BankReg=Reg_PG;
+ Mask=MModAbs24+MModIndX16;
+ if (NOT LFlag) Mask+=MModAbs16;
+ DecodeAdr(1,Mask+((LMemo("JSR"))?0:MModInd16));
+ if (AdrType!=ModNone)
+ BEGIN
+ switch (AdrType)
+ BEGIN
+ case ModAbs16:
+ BAsmCode[0]=(LMemo("JSR")) ? 0x20 : 0x4c; break;
+ case ModAbs24:
+ BAsmCode[0]=(LMemo("JSR")) ? 0x22 : 0x5c; break;
+ case ModIndX16:
+ BAsmCode[0]=(LMemo("JSR")) ? 0xfc : 0x7c; break;
+ case ModInd16:
+ BAsmCode[0]=(LFlag) ? 0xdc : 0x6c; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDM"))
+ BEGIN
+ if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
+ else if (MomCPU<CPUM7700) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(2,MModAbs8+MModAbs16+MModIdxX8+MModIdxX16);
+ if (AdrType!=ModNone)
+ BEGIN
+ switch (AdrType)
+ BEGIN
+ case ModAbs8 : BAsmCode[0]=0x64; break;
+ case ModAbs16 : BAsmCode[0]=0x9c; break;
+ case ModIdxX8 : BAsmCode[0]=0x74; break;
+ case ModIdxX16: BAsmCode[0]=0x9e; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ WordSize=(Reg_M==0);
+ ArgCnt=1; DecodeAdr(1,MModImm);
+ if (AdrType==ModNone) CodeLen=0;
+ else
+ BEGIN
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt); CodeLen+=AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("STZ"))
+ BEGIN
+ if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
+ else if (MomCPU!=CPU65816) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(1,MModAbs8+MModAbs16+MModIdxX8+MModIdxX16);
+ if (AdrType!=ModNone)
+ BEGIN
+ switch (AdrType)
+ BEGIN
+ case ModAbs8 : BAsmCode[0]=0x64; break;
+ case ModAbs16 : BAsmCode[0]=0x9c; break;
+ case ModIdxX8 : BAsmCode[0]=0x74; break;
+ case ModIdxX16: BAsmCode[0]=0x9e; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MVN")) OR (Memo("MVP")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (OK)
+ BEGIN
+ Mask=EvalIntExpression(ArgStr[2],Int32,&OK);
+ if (OK)
+ if (((Mask & 0xff000000)!=0) OR ((AdrLong & 0xff000000)!=0)) WrError(1320);
+ else
+ BEGIN
+ BAsmCode[0]=(Memo("MVN")) ? 0x54 : 0x44;
+ BAsmCode[1]=AdrLong >> 16;
+ BAsmCode[2]=Mask >> 16;
+ CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PSH")) OR (Memo("PUL")))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else if (MomCPU<CPUM7700) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[0]=0xeb+(Ord(Memo("PUL")) << 4);
+ BAsmCode[1]=0; OK=True;
+ z=1;
+ while ((z<=ArgCnt) AND (OK))
+ BEGIN
+ if (*ArgStr[z]=='#')
+ BAsmCode[1]|=EvalIntExpression(ArgStr[z]+1,Int8,&OK);
+ else
+ BEGIN
+ Start=0;
+ while ((Start<PushRegCnt) AND (strcasecmp(PushRegs[Start],ArgStr[z])!=0)) Start++;
+ OK=(Start<PushRegCnt);
+ if (OK) BAsmCode[1]|=1l << Start;
+ else WrXError(1980,ArgStr[z]);
+ END
+ z++;
+ END
+ if (OK) CodeLen=2;
+ END
+ return;
+ END
+
+ if (Memo("PEA"))
+ BEGIN
+ WordSize=True;
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(1,MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1+AdrCnt; BAsmCode[0]=0xf4;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ END
+ END
+ return;
+ END
+
+ if (Memo("PEI"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]=='#') strcpy(ArgStr[1],ArgStr[1]+1);
+ DecodeAdr(1,MModAbs8);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1+AdrCnt; BAsmCode[0]=0xd4;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ END
+ END
+ return;
+ END
+
+ if (Memo("PER"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Rel=True;
+ if (*ArgStr[1]=='#')
+ BEGIN
+ strcpy(ArgStr[1],ArgStr[1]+1); Rel=False;
+ END
+ BAsmCode[0]=0x62;
+ if (Rel)
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((AdrLong<-32768) OR (AdrLong>32767)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[1]=AdrLong & 0xff;
+ BAsmCode[2]=(AdrLong >> 8) & 0xff;
+ END
+ END
+ else
+ BEGIN
+ z=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=3; BAsmCode[1]=Lo(z); BAsmCode[2]=Hi(z);
+ END
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_7700(void)
+BEGIN
+ SaveInitProc();
+ Reg_PG=0;
+ Reg_DT=0;
+ Reg_X=0;
+ Reg_M=0;
+ Reg_DPR=0;
+END
+
+ static Boolean IsDef_7700(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_7700(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_7700(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x19; NOPCode=0xea;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1 << SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffffffl;
+
+ MakeCode=MakeCode_7700; IsDef=IsDef_7700;
+ SwitchFrom=SwitchFrom_7700; InitFields();
+END
+
+
+ void code7700_init(void)
+BEGIN
+ CPU65816=AddCPU("65816" ,SwitchTo_7700);
+ CPUM7700=AddCPU("MELPS7700",SwitchTo_7700);
+ CPUM7750=AddCPU("MELPS7750",SwitchTo_7700);
+ CPUM7751=AddCPU("MELPS7751",SwitchTo_7700);
+
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_7700;
+END
diff --git a/code7700.h b/code7700.h
new file mode 100644
index 0000000..8796a10
--- /dev/null
+++ b/code7700.h
@@ -0,0 +1,11 @@
+/* code7700.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegeneratormodul MELPS-7700 */
+/* */
+/* Historie: 5.11.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code7700_init(void);
diff --git a/code7720.c b/code7720.c
new file mode 100644
index 0000000..e22b8ec
--- /dev/null
+++ b/code7720.c
@@ -0,0 +1,587 @@
+/* code7720.c */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Codegenerator NEC uPD772x */
+/* */
+/* Historie: 30. 8.1998 Grundsteinlegung */
+/* 31. 8.1998 RET-Anweisung */
+/* 2. 9.1998 Verallgemeinerung auf 77C25 */
+/* 5. 9.1998 Pseudo-Anweisungen */
+/* 11. 9.1998 ROMData-Segment angelegt */
+/* 24. 9.1998 Korrekturen fuer DOS-Compiler */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+#include "strutil.h"
+#include "nls.h"
+#include "bpemu.h"
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmcode.h"
+#include "asmitree.h"
+#include "headids.h"
+
+/*---------------------------------------------------------------------------*/
+
+#define JmpOrderCnt 36
+#define ALU2OrderCnt 8
+#define ALU1OrderCnt 7
+
+#define DestRegCnt 16
+#define SrcRegCnt 16
+#define ALUSrcRegCnt 4
+
+typedef struct
+ {
+ LongWord Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ LongWord Code;
+ } TReg;
+
+typedef enum {MoveField,ALUField,DPLField,DPHField,RPField,RetField} OpComps;
+
+static CPUVar CPU7720,CPU7725;
+
+static LongWord ActCode;
+static Boolean InOp;
+static Byte UsedOpFields;
+
+static Byte TypePos,ImmValPos,AddrPos,ALUPos,DPLPos,AccPos,ALUSrcPos;
+static IntType MemInt;
+static Word ROMEnd,DROMEnd,RAMEnd;
+
+static FixedOrder *JmpOrders,*ALU2Orders,*ALU1Orders;
+
+static TReg *DestRegs,*SrcRegs,*ALUSrcRegs;
+
+static PInstTable InstTable, OpTable;
+
+/*---------------------------------------------------------------------------*/
+/* Hilfsroutinen */
+
+ static Boolean DecodeReg(char *Asc, LongWord *Code, TReg *Regs, int Cnt)
+BEGIN
+ int z;
+
+ for (z=0; z<Cnt; z++)
+ if (strcasecmp(Asc,Regs[z].Name)==0) break;
+
+ if (z<Cnt) *Code=Regs[z].Code;
+ return z<Cnt;
+END
+
+ static Boolean ChkOpPresent(OpComps Comp)
+BEGIN
+ if ((UsedOpFields&(1l<<Comp))!=0)
+ BEGIN
+ WrError(1355); return False;
+ END
+ else
+ BEGIN
+ UsedOpFields|=1l<<Comp; return True;
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+/* Dekoder */
+
+ static void DecodeJmp(Word Index)
+BEGIN
+ Word Dest;
+ Boolean OK;
+ FixedOrder *Op=JmpOrders+Index;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Dest=EvalIntExpression(ArgStr[1],MemInt,&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=(2l<<TypePos)+(Op->Code<<13)+(Dest<<AddrPos);
+ CodeLen=1;
+ END
+ END
+END
+
+ static void DecodeDATA(Word Index)
+BEGIN
+ LongInt MinV,MaxV,Trans;
+ TempResult t;
+ int z,z2,Pos,Max;
+ Boolean OK;
+
+ if (ActPC==SegCode) MaxV=(MomCPU>=CPU7725) ? 16777215 : 8388607;
+ else MaxV=65535;
+ MinV=(-((MaxV+1) >> 1));
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ OK=True; z=1;
+ while ((OK) & (z<=ArgCnt))
+ BEGIN
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ if ((FirstPassUnknown) AND (t.Typ==TempInt)) t.Contents.Int&=MaxV;
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (ChkRange(t.Contents.Int,MinV,MaxV))
+ if (ActPC==SegCode) DAsmCode[CodeLen++]=t.Contents.Int;
+ else WAsmCode[CodeLen++]=t.Contents.Int;
+ break;
+ case TempFloat:
+ WrError(1135); OK=False;
+ break;
+ case TempString:
+ Max=((ActPC==SegCode) AND (MomCPU>=CPU7725)) ? 3 : 2; Pos=0;
+ for (z2=0; z2<strlen(t.Contents.Ascii); z2++)
+ BEGIN
+ Trans=CharTransTable[((usint) t.Contents.Ascii[z2])&0xff];
+ if (ActPC==SegCode)
+ DAsmCode[CodeLen]=(Pos==0) ? Trans : (DAsmCode[CodeLen]<<8)|Trans;
+ else
+ WAsmCode[CodeLen]=(Pos==0) ? Trans : (WAsmCode[CodeLen]<<8)|Trans;
+ if (++Pos==Max)
+ BEGIN
+ Pos=0; CodeLen++;
+ END
+ END
+ if (Pos!=0) CodeLen++;
+ break;
+ case TempNone:
+ OK=False;
+ END
+ z++;
+ END
+ END
+END
+
+ static void DecodeRES(Word Index)
+BEGIN
+ Word Size;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+END
+
+ static void DecodeALU2(Word Index)
+BEGIN
+ LongWord Acc=0xff,Src;
+ FixedOrder *Op=ALU2Orders+Index;
+ char ch;
+
+ if (NOT ChkOpPresent(ALUField)) return;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[2],&Src,ALUSrcRegs,ALUSrcRegCnt)) WrXError(1445,ArgStr[2]);
+ else
+ BEGIN
+ if ((strlen(ArgStr[1])==4) AND (strncasecmp(ArgStr[1],"ACC",3)==0))
+ BEGIN
+ ch=toupper(ArgStr[1][3]);
+ if ((ch>='A') AND (ch<='B')) Acc=ch-'A';
+ END
+ if (Acc==0xff) WrXError(1445,ArgStr[1]);
+ else ActCode|=(Op->Code<<ALUPos)+(Acc<<AccPos)+(Src<<ALUSrcPos);
+ END
+END
+
+ static void DecodeALU1(Word Index)
+BEGIN
+ LongWord Acc=0xff;
+ FixedOrder *Op=ALU1Orders+Index;
+ char ch;
+
+ if (NOT ChkOpPresent(ALUField)) return;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if ((strlen(ArgStr[1])==4) AND (strncasecmp(ArgStr[1],"ACC",3)==0))
+ BEGIN
+ ch=toupper(ArgStr[1][3]);
+ if ((ch>='A') AND (ch<='B')) Acc=ch-'A';
+ END
+ if (Acc==0xff) WrXError(1445,ArgStr[1]);
+ else ActCode|=(Op->Code<<ALUPos)+(Acc<<AccPos);
+ END
+END
+
+ static void DecodeNOP(Word Index)
+BEGIN
+ if (NOT ChkOpPresent(ALUField)) return;
+END
+
+ static void DecodeDPL(Word Index)
+BEGIN
+ if (NOT ChkOpPresent(DPLField)) return;
+
+ if (ArgCnt!=0) WrError(1110);
+ else ActCode|=(((LongWord)Index)<<DPLPos);
+END
+
+ static void DecodeDPH(Word Index)
+BEGIN
+ if (NOT ChkOpPresent(DPHField)) return;
+
+ if (ArgCnt!=0) WrError(1110);
+ else ActCode|=(((LongWord)Index)<<9);
+END
+
+ static void DecodeRP(Word Index)
+BEGIN
+ if (NOT ChkOpPresent(RPField)) return;
+
+ if (ArgCnt!=0) WrError(1110);
+ else ActCode|=(((LongWord)Index)<<8);
+END
+
+ static void DecodeRET(Word Index)
+BEGIN
+ if (NOT ChkOpPresent(RetField)) return;
+
+ if (ArgCnt!=0) WrError(1110);
+ else ActCode|=(1l<<TypePos);
+END
+
+ static void DecodeLDI(Word Index)
+BEGIN
+ LongWord Value;
+ LongWord Reg;
+ Boolean OK;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Reg,DestRegs,DestRegCnt)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Value=EvalIntExpression(ArgStr[2],Int16,&OK);
+ if (OK)
+ BEGIN
+ DAsmCode[0]=(3l<<TypePos)+Reg+(Value<<ImmValPos);
+ CodeLen=1;
+ END
+ END
+END
+
+ static void DecodeOP(Word Index)
+BEGIN
+ char *p;
+ int z;
+
+ UsedOpFields=0; ActCode=0;
+
+ if (ArgCnt>1)
+ BEGIN
+ p=FirstBlank(ArgStr[1]);
+ if (p!=NULL)
+ BEGIN
+ *p='\0'; strmaxcpy(OpPart,ArgStr[1],255);
+ NLS_UpString(OpPart);
+ strcpy(ArgStr[1],p+1); KillPrefBlanks(ArgStr[1]);
+ END
+ else
+ BEGIN
+ strmaxcpy(OpPart,ArgStr[1],255);
+ for (z=1; z<ArgCnt; z++)
+ strcpy(ArgStr[z],ArgStr[z+1]);
+ ArgCnt--;
+ END
+ if (NOT LookupInstTable(OpTable,OpPart)) WrXError(1200,OpPart);
+ END
+
+ DAsmCode[0]=ActCode; CodeLen=1;
+END
+
+ static void DecodeMOV(Word Index)
+BEGIN
+ LongWord Dest,Src;
+
+ if (NOT ChkOpPresent(MoveField)) return;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Dest,DestRegs,DestRegCnt)) WrXError(1445,ArgStr[1]);
+ else if (NOT DecodeReg(ArgStr[2],&Src,SrcRegs,SrcRegCnt)) WrXError(1445,ArgStr[2]);
+ else ActCode|=Dest+(Src<<4);
+END
+
+/*---------------------------------------------------------------------------*/
+/* Tabellenverwaltung */
+
+static int InstrZ;
+
+ static void AddJmp(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=JmpOrderCnt) exit(255);
+ if ((MomCPU<CPU7725) AND (Odd(NCode))) return;
+ JmpOrders[InstrZ].Code=(MomCPU==CPU7725) ? NCode : NCode>>1;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeJmp);
+END
+
+ static void AddALU2(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=ALU2OrderCnt) exit(255);
+ ALU2Orders[InstrZ].Code=NCode;
+ AddInstTable(OpTable, NName, InstrZ++, DecodeALU2);
+END
+
+ static void AddALU1(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=ALU1OrderCnt) exit(255);
+ ALU1Orders[InstrZ].Code=NCode;
+ AddInstTable(OpTable, NName, InstrZ++, DecodeALU1);
+END
+
+ static void AddDestReg(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=DestRegCnt) exit(255);
+ DestRegs[InstrZ].Name=NName;
+ DestRegs[InstrZ++].Code=NCode;
+END
+
+ static void AddSrcReg(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=SrcRegCnt) exit(255);
+ SrcRegs[InstrZ].Name=NName;
+ SrcRegs[InstrZ++].Code=NCode;
+END
+
+ static void AddALUSrcReg(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=ALUSrcRegCnt) exit(255);
+ ALUSrcRegs[InstrZ].Name=NName;
+ ALUSrcRegs[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(101);
+ OpTable=CreateInstTable(79);
+
+ AddInstTable(InstTable,"LDI",0,DecodeLDI);
+ AddInstTable(InstTable,"LD",0,DecodeLDI);
+ AddInstTable(InstTable,"OP",0,DecodeOP);
+ AddInstTable(InstTable,"DATA",0,DecodeDATA);
+ AddInstTable(InstTable,"RES",0,DecodeRES);
+ AddInstTable(OpTable,"MOV",0,DecodeMOV);
+ AddInstTable(OpTable,"NOP",0,DecodeNOP);
+ AddInstTable(OpTable,"DPNOP",0,DecodeDPL);
+ AddInstTable(OpTable,"DPINC",1,DecodeDPL);
+ AddInstTable(OpTable,"DPDEC",2,DecodeDPL);
+ AddInstTable(OpTable,"DPCLR",3,DecodeDPL);
+ AddInstTable(OpTable,"M0",0,DecodeDPH);
+ AddInstTable(OpTable,"M1",1,DecodeDPH);
+ AddInstTable(OpTable,"M2",2,DecodeDPH);
+ AddInstTable(OpTable,"M3",3,DecodeDPH);
+ AddInstTable(OpTable,"M4",4,DecodeDPH);
+ AddInstTable(OpTable,"M5",5,DecodeDPH);
+ AddInstTable(OpTable,"M6",6,DecodeDPH);
+ AddInstTable(OpTable,"M7",7,DecodeDPH);
+ if (MomCPU>=CPU7725)
+ BEGIN
+ AddInstTable(OpTable,"M8",8,DecodeDPH);
+ AddInstTable(OpTable,"M9",9,DecodeDPH);
+ AddInstTable(OpTable,"MA",10,DecodeDPH);
+ AddInstTable(OpTable,"MB",11,DecodeDPH);
+ AddInstTable(OpTable,"MC",12,DecodeDPH);
+ AddInstTable(OpTable,"MD",13,DecodeDPH);
+ AddInstTable(OpTable,"ME",14,DecodeDPH);
+ AddInstTable(OpTable,"MF",15,DecodeDPH);
+ END
+ AddInstTable(OpTable,"RPNOP",0,DecodeRP);
+ AddInstTable(OpTable,"RPDEC",1,DecodeRP);
+ AddInstTable(OpTable,"RET",1,DecodeRET);
+
+ JmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*JmpOrderCnt); InstrZ=0;
+ AddJmp("JMP" , 0x100); AddJmp("CALL" , 0x140);
+ AddJmp("JNCA" , 0x080); AddJmp("JCA" , 0x082);
+ AddJmp("JNCB" , 0x084); AddJmp("JCB" , 0x086);
+ AddJmp("JNZA" , 0x088); AddJmp("JZA" , 0x08a);
+ AddJmp("JNZB" , 0x08c); AddJmp("JZB" , 0x08e);
+ AddJmp("JNOVA0", 0x090); AddJmp("JOVA0" , 0x092);
+ AddJmp("JNOVB0", 0x094); AddJmp("JOVB0" , 0x096);
+ AddJmp("JNOVA1", 0x098); AddJmp("JOVA1" , 0x09a);
+ AddJmp("JNOVB1", 0x09c); AddJmp("JOVB1" , 0x09e);
+ AddJmp("JNSA0" , 0x0a0); AddJmp("JSA0" , 0x0a2);
+ AddJmp("JNSB0" , 0x0a4); AddJmp("JSB0" , 0x0a6);
+ AddJmp("JNSA1" , 0x0a8); AddJmp("JSA1" , 0x0aa);
+ AddJmp("JNSB1" , 0x0ac); AddJmp("JSB1" , 0x0ae);
+ AddJmp("JDPL0" , 0x0b0); AddJmp("JDPLF" , 0x0b2);
+ AddJmp("JNSIAK", 0x0b4); AddJmp("JSIAK" , 0x0b6);
+ AddJmp("JNSOAK", 0x0b8); AddJmp("JSOAK" , 0x0ba);
+ AddJmp("JNRQM" , 0x0bc); AddJmp("JRQM" , 0x0be);
+ AddJmp("JDPLN0", 0x0b1); AddJmp("JDPLNF" , 0x0b3);
+
+ ALU2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU2OrderCnt); InstrZ=0;
+ AddALU2("OR" , 1); AddALU2("AND" , 2); AddALU2("XOR" , 3);
+ AddALU2("SUB" , 4); AddALU2("ADD" , 5); AddALU2("SBB" , 6);
+ AddALU2("ADC" , 7); AddALU2("CMP" ,10);
+
+ ALU1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU1OrderCnt); InstrZ=0;
+ AddALU1("DEC" , 8); AddALU1("INC" , 9); AddALU1("SHR1",11);
+ AddALU1("SHL1",12); AddALU1("SHL2",13); AddALU1("SHL4",14);
+ AddALU1("XCHG",15);
+
+ DestRegs=(TReg *) malloc(sizeof(TReg)*DestRegCnt); InstrZ=0;
+ AddDestReg("@NON", 0); AddDestReg("@A" , 1);
+ AddDestReg("@B" , 2); AddDestReg("@TR" , 3);
+ AddDestReg("@DP" , 4); AddDestReg("@RP" , 5);
+ AddDestReg("@DR" , 6); AddDestReg("@SR" , 7);
+ AddDestReg("@SOL", 8); AddDestReg("@SOM", 9);
+ AddDestReg("@K" , 10); AddDestReg("@KLR", 11);
+ AddDestReg("@KLM", 12); AddDestReg("@L" , 13);
+ AddDestReg((MomCPU==CPU7725)?"@TRB":"",14);
+ AddDestReg("@MEM", 15);
+
+
+ SrcRegs=(TReg *) malloc(sizeof(TReg)*SrcRegCnt); InstrZ=0;
+ AddSrcReg("NON" , 0); AddSrcReg("A" , 1);
+ AddSrcReg("B" , 2); AddSrcReg("TR" , 3);
+ AddSrcReg("DP" , 4); AddSrcReg("RP" , 5);
+ AddSrcReg("RO" , 6); AddSrcReg("SGN" , 7);
+ AddSrcReg("DR" , 8); AddSrcReg("DRNF", 9);
+ AddSrcReg("SR" , 10); AddSrcReg("SIM" , 11);
+ AddSrcReg("SIL" , 12); AddSrcReg("K" , 13);
+ AddSrcReg("L" , 14); AddSrcReg("MEM" , 15);
+
+ ALUSrcRegs=(TReg *) malloc(sizeof(TReg)*ALUSrcRegCnt); InstrZ=0;
+ AddALUSrcReg("RAM", 0); AddALUSrcReg("IDB", 1);
+ AddALUSrcReg("M" , 2); AddALUSrcReg("N" , 3);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ DestroyInstTable(OpTable);
+ free(JmpOrders);
+ free(ALU2Orders);
+ free(ALU1Orders);
+ free(DestRegs);
+ free(SrcRegs);
+ free(ALUSrcRegs);
+END
+
+/*---------------------------------------------------------------------------*/
+/* Callbacks */
+
+ static void MakeCode_7720(void)
+BEGIN
+ Boolean NextOp;
+
+ /* Nullanweisung */
+
+ if ((Memo("")) AND (*AttrPart=='\0') AND (ArgCnt==0)) return;
+
+ /* direkte Anweisungen */
+
+ NextOp=Memo("OP");
+ if (LookupInstTable(InstTable,OpPart))
+ BEGIN
+ InOp=NextOp; return;
+ END
+
+ /* wenn eine parallele Op-Anweisung offen ist, noch deren Komponenten testen */
+
+ if ((InOp) AND (LookupInstTable(OpTable,OpPart)))
+ BEGIN
+ RetractWords(1);
+ DAsmCode[0]=ActCode; CodeLen=1;
+ return;
+ END
+
+ /* Hae??? */
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_7720(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_7720(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_7720(void)
+BEGIN
+ PFamilyDescr FoundDescr;
+
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ if (MomCPU==CPU7725)
+ BEGIN
+ FoundDescr=FindFamilyByName("7725");
+ MemInt=UInt11;
+ ROMEnd=0x7ff; DROMEnd=0x3ff; RAMEnd=0xff;
+ TypePos=22;
+ ImmValPos=6;
+ AddrPos=2;
+ ALUPos=16;
+ DPLPos=13;
+ AccPos=15;
+ ALUSrcPos=20;
+ END
+ else
+ BEGIN
+ FoundDescr=FindFamilyByName("7720");
+ MemInt=UInt9;
+ ROMEnd=0x1ff; DROMEnd=0x1ff; RAMEnd=0x7f;
+ TypePos=21;
+ ImmValPos=5;
+ AddrPos=4;
+ ALUPos=15;
+ DPLPos=12;
+ AccPos=14;
+ ALUSrcPos=19;
+ END
+
+ PCSymbol="$"; HeaderID=FoundDescr->Id; NOPCode=0x000000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1l<<SegCode)|(1l<<SegData)|(1l<<SegRData);
+ Grans[SegCode ]=4; ListGrans[SegCode ]=4; SegInits[SegCode ]=0;
+ SegLimits[SegCode ] = ROMEnd;
+ Grans[SegData ]=2; ListGrans[SegData ]=2; SegInits[SegData ]=0;
+ SegLimits[SegData ] = RAMEnd;
+ Grans[SegRData]=2; ListGrans[SegRData]=2; SegInits[SegRData]=0;
+ SegLimits[SegRData] = DROMEnd;
+
+ MakeCode=MakeCode_7720; IsDef=IsDef_7720;
+ SwitchFrom=SwitchFrom_7720;
+
+ InOp=False; UsedOpFields=0; ActCode=0;
+ InitFields();
+END
+
+/*---------------------------------------------------------------------------*/
+/* Initialisierung */
+
+ void code7720_init(void)
+BEGIN
+ CPU7720=AddCPU("7720",SwitchTo_7720);
+ CPU7725=AddCPU("7725",SwitchTo_7720);
+END
diff --git a/code7720.h b/code7720.h
new file mode 100644
index 0000000..939c243
--- /dev/null
+++ b/code7720.h
@@ -0,0 +1,11 @@
+/* code7720.h */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Codegenerator NEC uPD7720 */
+/* */
+/* Historie: 30. 8.1998 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code7720_init(void);
diff --git a/code77230.c b/code77230.c
new file mode 100644
index 0000000..566d8c3
--- /dev/null
+++ b/code77230.c
@@ -0,0 +1,1024 @@
+/* code77230.c */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Codegenerator NEC uPD77230 */
+/* */
+/* Historie: 13. 9.1998 Grundsteinlegung */
+/* 14. 9.1998 LDI/Destregs getestet */
+/* 16. 9.1998 das instruktionelle Kleingemuese begonnen */
+/* 19. 9.1998 restliche CPU-Instruktionen */
+/* 27. 9.1998 DW-Anweisung */
+/* 28. 9.1998 String-Argument fuer DW */
+/* DS */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Includes */
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "strutil.h"
+#include "nls.h"
+#include "endian.h"
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "headids.h"
+
+/*---------------------------------------------------------------------------*/
+/* Definitionen */
+
+#define SrcRegCnt 32
+#define DestRegCnt 32
+#define ALUSrcRegCnt 4
+
+#define JmpOrderCnt 32
+#define ALU1OrderCnt 15
+#define ALU2OrderCnt 10
+
+#define CaseCnt 17
+
+typedef struct
+ {
+ LongWord Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ LongWord Code;
+ } Register;
+
+enum {InstrLDI, InstrBranch,
+ InstrALU, InstrMove,
+ InstrM0, InstrM1, InstrDP0, InstrDP1,
+ InstrEA, InstrRP, InstrFC, InstrLC,
+ InstrBASE0, InstrBASE1, InstrRPC,
+ InstrP2, InstrP3, InstrEM, InstrBM,
+ InstrL, InstrRW, InstrWT, InstrNF, InstrWI,
+ InstrFIS, InstrFD, InstrSHV, InstrRPS, InstrNAL, InstrCnt};
+
+static LongWord CaseMasks[CaseCnt]=
+ {(1l<<InstrLDI),
+ (1l<<InstrBranch)|(1l<<InstrMove),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrM0)|(1l<<InstrM1)|(1l<<InstrDP0)|(1l<<InstrDP1),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrEA)|(1l<<InstrDP0)|(1l<<InstrDP1),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrRP)|(1l<<InstrM0)|(1l<<InstrDP0)|(1l<<InstrFC),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrRP)|(1l<<InstrM1)|(1l<<InstrDP1)|(1l<<InstrFC),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrRP)|(1l<<InstrM0)|(1l<<InstrM1)|(1l<<InstrL)|(1l<<InstrFC),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrBASE0)|(1l<<InstrBASE1)|(1l<<InstrFC),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrRPC)|(1l<<InstrL)|(1l<<InstrFC),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrP3)|(1l<<InstrP2)|(1l<<InstrEM)|(1l<<InstrBM)|(1l<<InstrL)|(1l<<InstrFC),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrRW)|(1l<<InstrL)|(1l<<InstrFC),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrWT)|(1l<<InstrL)|(1l<<InstrFC),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrNF)|(1l<<InstrWI)|(1l<<InstrL)|(1l<<InstrFC),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrFIS)|(1l<<InstrFD)|(1l<<InstrL),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrSHV),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrRPS),
+ (1l<<InstrALU)|(1l<<InstrMove)|(1l<<InstrNAL)
+ };
+
+static CPUVar CPU77230;
+static LongWord InstrMask;
+static Boolean Error;
+static LongWord *InstrComps,*InstrDefs;
+
+static PInstTable InstTable;
+static Register *SrcRegs,*ALUSrcRegs,*DestRegs;
+static FixedOrder *JmpOrders,*ALU1Orders,*ALU2Orders;
+
+/*---------------------------------------------------------------------------*/
+/* Hilfsroutinen */
+
+static int DiscCnt,SplittedArg;
+static char *DiscPtr;
+
+ static Boolean SplitArgs(int Count)
+BEGIN
+ char *p,*p1,*p2;
+
+ SplittedArg=DiscCnt=Count;
+
+ if (Count==0)
+ BEGIN
+ if (ArgCnt>0)
+ BEGIN
+ DiscPtr=ArgStr[1]-1;
+ SplittedArg=1;
+ END
+ else DiscPtr=Nil;
+ return True;
+ END
+
+ if (ArgCnt<Count)
+ BEGIN
+ WrError(1110); Error=True; return False;
+ END
+
+ for (p=ArgStr[SplittedArg]; isspace(((usint)*p)&0xff); p++);
+ p1=QuotPos(p,' ');
+ p2=QuotPos(p,'\t');
+ if ((p1==Nil) OR ((p2!=Nil) AND (p2<p1))) DiscPtr=p2;
+ else DiscPtr=p1;
+ if (DiscPtr!=Nil) *(DiscPtr)='\0';
+
+ return True;
+END
+
+ static void DiscardArgs(void)
+BEGIN
+ char *p,*p2;
+ int z;
+ Boolean Eaten;
+
+ if (DiscPtr!=Nil)
+ BEGIN
+ for (p=DiscPtr+1; isspace(((usint)*p)&0xff); p++)
+ if (*p=='\0') break;
+ for (p2=p; NOT isspace(((usint)*p2)&0xff); p2++)
+ if (*p2=='\0') break;
+ Eaten=(*p2=='\0'); *p2='\0';
+ strcpy(OpPart,p); NLS_UpString(OpPart);
+ if (Eaten)
+ BEGIN
+ for (z=1; z<ArgCnt; z++)
+ strcpy(ArgStr[z],ArgStr[z+1]);
+ ArgCnt--;
+ END
+ else
+ BEGIN
+ if (p2!=Nil)
+ for (p2++; isspace(((usint)*p2)&0xff); p2++);
+ strcpy(ArgStr[SplittedArg],p2);
+ END
+ END
+ else *OpPart='\0';
+ if (DiscCnt>0)
+ BEGIN
+ for (z=0; z<=ArgCnt-DiscCnt; z++)
+ strcpy(ArgStr[z+1],ArgStr[z+DiscCnt]);
+ ArgCnt-=DiscCnt-1;
+ END
+END
+
+ static void AddComp(int Index, LongWord Value)
+BEGIN
+ if ((InstrMask&(1l<<Index))!=0)
+ BEGIN
+ WrError(1355); Error=True;
+ END
+ else
+ BEGIN
+ InstrMask|=(1l<<Index); InstrComps[Index]=Value;
+ END;
+END
+
+ static Boolean DecodeReg(char *Asc, LongWord *Erg, Register *Regs, int Cnt)
+BEGIN
+ int z;
+
+ for (z=0; z<Cnt; z++)
+ if (strcasecmp(Asc,Regs[z].Name)==0)
+ BEGIN
+ *Erg=Regs[z].Code; return True;
+ END
+ return False;
+END
+
+/*---------------------------------------------------------------------------*/
+/* Dekoder fuer Routinen */
+
+ static void DecodeJmp(Word Index)
+BEGIN
+ FixedOrder *Op=JmpOrders+Index;
+ int acnt=(Memo("RET")) ? 0 : 1;
+ LongWord Adr;
+
+ if (NOT SplitArgs(acnt)) return;
+ if (acnt==0)
+ BEGIN
+ Adr=0; Error=True;
+ END
+ else Adr=EvalIntExpression(ArgStr[1],UInt13,&Error);
+ Error=NOT Error;
+ if (NOT Error) AddComp(InstrBranch,Op->Code+(Adr << 5));
+ DiscardArgs();
+END
+
+ static void DecodeMOV(Word Index)
+BEGIN
+ LongWord DReg,SReg;
+
+ if (NOT SplitArgs(2)) return;
+ if (NOT DecodeReg(ArgStr[1],&DReg,DestRegs,DestRegCnt))
+ BEGIN
+ WrXError(1445,ArgStr[1]); Error=True;
+ END
+ else if (NOT DecodeReg(ArgStr[2],&SReg,SrcRegs,SrcRegCnt))
+ BEGIN
+ WrXError(1445,ArgStr[2]); Error=True;
+ END
+ else AddComp(InstrMove,(SReg<<5)+DReg);
+ DiscardArgs();
+END
+
+ static void DecodeLDI(Word Index)
+BEGIN
+ LongWord DReg,Src=0;
+
+ if (NOT SplitArgs(2)) return;
+ if (NOT DecodeReg(ArgStr[1],&DReg,DestRegs,DestRegCnt))
+ BEGIN
+ WrXError(1445,ArgStr[1]); Error=True;
+ END
+ else Src=EvalIntExpression(ArgStr[2],Int24,&Error);
+ Error=NOT Error;
+ if (NOT Error) AddComp(InstrLDI,(Src<<5)+DReg);
+ DiscardArgs();
+END
+
+ static void DecodeNOP(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrALU,0);
+ DiscardArgs();
+END
+
+ static void DecodeALU1(Word Index)
+BEGIN
+ FixedOrder *Op=ALU1Orders+Index;
+ LongWord DReg;
+
+ if (NOT SplitArgs(1)) return;
+ if ((NOT DecodeReg(ArgStr[1],&DReg,DestRegs,DestRegCnt))
+ OR (DReg<16) OR (DReg>23))
+ BEGIN
+ WrXError(1445,ArgStr[1]); Error=True;
+ END
+ else AddComp(InstrALU,(Op->Code<<17)+(DReg&7));
+ DiscardArgs();
+END
+
+ static void DecodeALU2(Word Index)
+BEGIN
+ FixedOrder *Op=ALU2Orders+Index;
+ LongWord DReg,SReg;
+
+ if (NOT SplitArgs(2)) return;
+ if ((NOT DecodeReg(ArgStr[1],&DReg,DestRegs,DestRegCnt))
+ OR (DReg<16) OR (DReg>23))
+ BEGIN
+ WrXError(1445,ArgStr[1]); Error=True;
+ END
+ else if (NOT DecodeReg(ArgStr[2],&SReg,ALUSrcRegs,ALUSrcRegCnt))
+ BEGIN
+ WrXError(1445,ArgStr[2]); Error=True;
+ END
+ else AddComp(InstrALU,(Op->Code<<17)+(SReg<<3)+(DReg&7));
+ DiscardArgs();
+END
+
+ static void DecodeM0(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrM0,Index);
+ DiscardArgs();
+END
+
+ static void DecodeM1(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrM1,Index);
+ DiscardArgs();
+END
+
+ static void DecodeDP0(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrDP0,Index);
+ DiscardArgs();
+END
+
+ static void DecodeDP1(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrDP1,Index);
+ DiscardArgs();
+END
+
+ static void DecodeEA(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrEA,Index);
+ DiscardArgs();
+END
+
+ static void DecodeFC(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrFC,Index);
+ DiscardArgs();
+END
+
+ static void DecodeRP(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrRP,Index);
+ DiscardArgs();
+END
+
+ static void DecodeL(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrL,Index);
+ DiscardArgs();
+END
+
+ static void DecodeBASE(Word Index)
+BEGIN
+ LongWord Value;
+
+ if (NOT SplitArgs(1)) return;
+ Value=EvalIntExpression(ArgStr[1],UInt3,&Error); Error=NOT Error;
+ if (NOT Error) AddComp(Index,Value);
+ DiscardArgs();
+END
+
+ static void DecodeRPC(Word Index)
+BEGIN
+ LongWord Value;
+
+ if (NOT SplitArgs(1)) return;
+ FirstPassUnknown=False;
+ Value=EvalIntExpression(ArgStr[1],UInt4,&Error);
+ if (FirstPassUnknown) Value&=7;
+ if (Value>9) Error=True; else Error=NOT Error;
+ if (NOT Error) AddComp(InstrRPC,Value);
+ DiscardArgs();
+END
+
+ static void DecodeP2(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrP2,Index);
+ DiscardArgs();
+END
+
+ static void DecodeP3(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrP3,Index);
+ DiscardArgs();
+END
+
+ static void DecodeBM(Word Index)
+BEGIN
+ /* Wenn EM-Feld schon da war, muss es EI gewesen sein */
+
+ if (NOT SplitArgs(0)) return;
+ if ((InstrMask&(1<<InstrEM))!=0)
+ BEGIN
+ Error=(InstrComps[InstrEM]==0);
+ if (Error) WrError(1355);
+ else AddComp(InstrBM,Index);
+ END
+ else AddComp(InstrBM,Index);
+ DiscardArgs();
+END
+
+ static void DecodeEM(Word Index)
+BEGIN
+ /* Wenn BM-Feld schon da war, muss es EI sein */
+
+ if (NOT SplitArgs(0)) return;
+ if ((InstrMask&(1<<InstrBM))!=0)
+ BEGIN
+ Error=(Index==0);
+ if (Error) WrError(1355);
+ else AddComp(InstrEM,Index);
+ END
+ else
+ BEGIN
+ AddComp(InstrEM,Index);
+ if (Index==0) InstrComps[InstrBM]=3;
+ END
+ DiscardArgs();
+END
+
+ static void DecodeRW(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrRW,Index);
+ DiscardArgs();
+END
+
+ static void DecodeWT(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrWT,Index);
+ DiscardArgs();
+END
+
+ static void DecodeNF(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrNF,Index);
+ DiscardArgs();
+END
+
+ static void DecodeWI(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrWI,Index);
+ DiscardArgs();
+END
+
+ static void DecodeFIS(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrFIS,Index);
+ DiscardArgs();
+END
+
+ static void DecodeFD(Word Index)
+BEGIN
+ if (NOT SplitArgs(0)) return;
+ AddComp(InstrFD,Index);
+ DiscardArgs();
+END
+
+ static void DecodeSHV(Word Index)
+BEGIN
+ LongWord Value;
+
+ if (NOT SplitArgs(1)) return;
+ FirstPassUnknown=False;
+ Value=EvalIntExpression(ArgStr[1],UInt6,&Error);
+ if (FirstPassUnknown) Value&=31;
+ if (Value>46) Error=True; else Error=NOT Error;
+ if (NOT Error) AddComp(InstrSHV,(Index<<6)+Value);
+ DiscardArgs();
+END
+
+ static void DecodeRPS(Word Index)
+BEGIN
+ LongWord Value;
+
+ if (NOT SplitArgs(1)) return;
+ Value=EvalIntExpression(ArgStr[1],UInt9,&Error);
+ Error=NOT Error;
+ if (NOT Error) AddComp(InstrRPS,Value);
+ DiscardArgs();
+END
+
+ static void DecodeNAL(Word Index)
+BEGIN
+ LongWord Value;
+
+ if (NOT SplitArgs(1)) return;
+ FirstPassUnknown=False;
+ Value=EvalIntExpression(ArgStr[1],UInt13,&Error);
+ if (FirstPassUnknown) Value=(Value&0x1ff)|(EProgCounter()&0x1e00);
+ Error=NOT Error;
+ if (NOT Error)
+ if ((NOT SymbolQuestionable) AND ((Value^EProgCounter())&0x1e00)) WrError(1910);
+ else AddComp(InstrNAL,Value&0x1ff);
+ DiscardArgs();
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ int z;
+ Boolean OK;
+ TempResult t;
+ LongWord temp;
+ LongInt sign,mant,expo,Size;
+ char *cp;
+
+ if (Memo("DW"))
+ BEGIN
+ if (ArgCnt<1) WrError(1110);
+ else
+ BEGIN
+ z=1; OK=True;
+ while ((OK) AND (z<=ArgCnt))
+ BEGIN
+ FirstPassUnknown=FALSE;
+ EvalExpression(ArgStr[z],&t);
+ switch(t.Typ)
+ BEGIN
+ case TempInt:
+ if (NOT RangeCheck(t.Contents.Int,Int32))
+ BEGIN
+ WrError(1320); OK=False; break;
+ END
+ DAsmCode[CodeLen++]=t.Contents.Int;
+ break;
+ case TempFloat:
+ if (NOT FloatRangeCheck(t.Contents.Float,Float32))
+ BEGIN
+ WrError(1320); OK=False; break;
+ END
+ Double_2_ieee4(t.Contents.Float,(Byte*) &temp,BigEndian);
+ sign=(temp>>31)&1;
+ expo=(temp>>23)&255;
+ mant=temp&0x7fffff;
+ if ((mant==0) AND (expo==0))
+ DAsmCode[CodeLen++]=0x80000000;
+ else
+ BEGIN
+ if (expo>0)
+ BEGIN
+ mant|=0x800000;
+ expo-=127;
+ END
+ else expo-=126;
+ if (mant>=0x800000)
+ BEGIN
+ mant=mant>>1; expo+=1;
+ END
+ if (sign==1) mant=((mant^0xffffff)+1);
+ DAsmCode[CodeLen++]=((expo&0xff)<<24)|(mant&0xffffff);
+ END
+ break;
+ case TempString:
+ for (z=0,cp=t.Contents.Ascii; *cp!='\0'; cp++,z++)
+ BEGIN
+ DAsmCode[CodeLen]=(DAsmCode[CodeLen]<<8)+CharTransTable[((usint)*cp)&0xff];
+ if ((z&3)==3) CodeLen++;
+ END
+ if ((z&3)!=0) DAsmCode[CodeLen++]=(DAsmCode[CodeLen])<<((4-(z&3))<<3);
+ break;
+ default:
+ OK=False;
+ END
+ z++;
+ END
+ if (NOT OK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("DS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ return FALSE;
+END
+
+/*---------------------------------------------------------------------------*/
+/* Codetabellenverwaltung */
+
+static int InstrZ;
+
+ static void AddJmp(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=JmpOrderCnt) exit(255);
+ JmpOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeJmp);
+END
+
+ static void AddALU1(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=ALU1OrderCnt) exit(255);
+ ALU1Orders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeALU1);
+END
+
+ static void AddALU2(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=ALU2OrderCnt) exit(255);
+ ALU2Orders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeALU2);
+END
+
+ static void AddSrcReg(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=SrcRegCnt) exit(255);
+ SrcRegs[InstrZ].Name=NName;
+ SrcRegs[InstrZ++].Code=NCode;
+END
+
+ static void AddALUSrcReg(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=ALUSrcRegCnt) exit(255);
+ ALUSrcRegs[InstrZ].Name=NName;
+ ALUSrcRegs[InstrZ++].Code=NCode;
+END
+
+ static void AddDestReg(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=DestRegCnt) exit(255);
+ DestRegs[InstrZ].Name=NName;
+ DestRegs[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(201);
+
+ AddInstTable(InstTable,"MOV",0,DecodeMOV);
+ AddInstTable(InstTable,"LDI",0,DecodeLDI);
+ AddInstTable(InstTable,"NOP",0,DecodeNOP);
+
+ AddInstTable(InstTable,"SPCBP0",1,DecodeM0);
+ AddInstTable(InstTable,"SPCIX0",2,DecodeM0);
+ AddInstTable(InstTable,"SPCBI0",3,DecodeM0);
+
+ AddInstTable(InstTable,"SPCBP1",1,DecodeM1);
+ AddInstTable(InstTable,"SPCIX1",2,DecodeM1);
+ AddInstTable(InstTable,"SPCBI1",3,DecodeM1);
+
+ AddInstTable(InstTable,"INCBP0",1,DecodeDP0);
+ AddInstTable(InstTable,"DECBP0",2,DecodeDP0);
+ AddInstTable(InstTable,"CLRBP0",3,DecodeDP0);
+ AddInstTable(InstTable,"STIX0" ,4,DecodeDP0);
+ AddInstTable(InstTable,"INCIX0",5,DecodeDP0);
+ AddInstTable(InstTable,"DECIX0",6,DecodeDP0);
+ AddInstTable(InstTable,"CLRIX0",7,DecodeDP0);
+
+ AddInstTable(InstTable,"INCBP1",1,DecodeDP1);
+ AddInstTable(InstTable,"DECBP1",2,DecodeDP1);
+ AddInstTable(InstTable,"CLRBP1",3,DecodeDP1);
+ AddInstTable(InstTable,"STIX1" ,4,DecodeDP1);
+ AddInstTable(InstTable,"INCIX1",5,DecodeDP1);
+ AddInstTable(InstTable,"DECIX1",6,DecodeDP1);
+ AddInstTable(InstTable,"CLRIX1",7,DecodeDP1);
+
+ AddInstTable(InstTable,"INCAR" ,1,DecodeEA);
+ AddInstTable(InstTable,"DECAR" ,2,DecodeEA);
+
+ AddInstTable(InstTable,"XCHPSW",1,DecodeFC);
+
+ AddInstTable(InstTable,"INCRP" ,1,DecodeRP);
+ AddInstTable(InstTable,"DECRP" ,2,DecodeRP);
+ AddInstTable(InstTable,"INCBRP",3,DecodeRP);
+
+ AddInstTable(InstTable,"DECLC" ,1,DecodeL);
+
+ AddInstTable(InstTable,"MCNBP0",InstrBASE0,DecodeBASE);
+ AddInstTable(InstTable,"MCNBP1",InstrBASE1,DecodeBASE);
+
+ AddInstTable(InstTable,"BITRP" ,0,DecodeRPC);
+
+ AddInstTable(InstTable,"CLRP2" ,0,DecodeP2);
+ AddInstTable(InstTable,"SETP2" ,1,DecodeP2);
+
+ AddInstTable(InstTable,"CLRP3" ,0,DecodeP3);
+ AddInstTable(InstTable,"SETP3" ,1,DecodeP3);
+
+ AddInstTable(InstTable,"DI" ,0,DecodeEM);
+ AddInstTable(InstTable,"EI" ,1,DecodeEM);
+ AddInstTable(InstTable,"CLRBM" ,1,DecodeBM);
+ AddInstTable(InstTable,"SETBM" ,2,DecodeBM);
+
+ AddInstTable(InstTable,"RD" ,1,DecodeRW);
+ AddInstTable(InstTable,"WR" ,2,DecodeRW);
+
+ AddInstTable(InstTable,"WRBORD",1,DecodeWT);
+ AddInstTable(InstTable,"WRBL24",2,DecodeWT);
+ AddInstTable(InstTable,"WRBL23",3,DecodeWT);
+ AddInstTable(InstTable,"WRBEL8",4,DecodeWT);
+ AddInstTable(InstTable,"WRBL8E",5,DecodeWT);
+ AddInstTable(InstTable,"WRBXCH",6,DecodeWT);
+ AddInstTable(InstTable,"WRBBRV",7,DecodeWT);
+
+ AddInstTable(InstTable,"TRNORM",2,DecodeNF);
+ AddInstTable(InstTable,"RDNORM",4,DecodeNF);
+ AddInstTable(InstTable,"FLTFIX",6,DecodeNF);
+ AddInstTable(InstTable,"FIXMA" ,7,DecodeNF);
+
+ AddInstTable(InstTable,"BWRL24",1,DecodeWI);
+ AddInstTable(InstTable,"BWRORD",2,DecodeWI);
+
+ AddInstTable(InstTable,"SPCPSW0",1,DecodeFIS);
+ AddInstTable(InstTable,"SPCPSW1",2,DecodeFIS);
+ AddInstTable(InstTable,"CLRPSW0",4,DecodeFIS);
+ AddInstTable(InstTable,"CLRPSW1",5,DecodeFIS);
+ AddInstTable(InstTable,"CLRPSW" ,6,DecodeFIS);
+
+ AddInstTable(InstTable,"SPIE",1,DecodeFD);
+ AddInstTable(InstTable,"IESP",2,DecodeFD);
+
+ AddInstTable(InstTable,"SETSVL",0,DecodeSHV);
+ AddInstTable(InstTable,"SETSVR",1,DecodeSHV);
+
+ AddInstTable(InstTable,"SPCRA",0,DecodeRPS);
+ AddInstTable(InstTable,"JBLK" ,0,DecodeNAL);
+
+ JmpOrders=(FixedOrder*) malloc(sizeof(FixedOrder)*JmpOrderCnt); InstrZ=0;
+ AddJmp("JMP" ,0x00); AddJmp("CALL" ,0x01); AddJmp("RET" ,0x02);
+ AddJmp("JNZRP" ,0x03); AddJmp("JZ0" ,0x04); AddJmp("JNZ0" ,0x05);
+ AddJmp("JZ1" ,0x06); AddJmp("JNZ1" ,0x07); AddJmp("JC0" ,0x08);
+ AddJmp("JNC0" ,0x09); AddJmp("JC1" ,0x0a); AddJmp("JNC1" ,0x0b);
+ AddJmp("JS0" ,0x0c); AddJmp("JNS0" ,0x0d); AddJmp("JS1" ,0x0e);
+ AddJmp("JNS1" ,0x0f); AddJmp("JV0" ,0x10); AddJmp("JNV0" ,0x11);
+ AddJmp("JV1" ,0x12); AddJmp("JNV1" ,0x13); AddJmp("JEV0" ,0x14);
+ AddJmp("JEV1" ,0x15); AddJmp("JNFSI" ,0x16); AddJmp("JNESO" ,0x17);
+ AddJmp("JIP0" ,0x18); AddJmp("JIP1" ,0x19); AddJmp("JNZIX0",0x1a);
+ AddJmp("JNZIX1",0x1b); AddJmp("JNZBP0",0x1c); AddJmp("JNZBP1",0x1d);
+ AddJmp("JRDY" ,0x1e); AddJmp("JRQM" ,0x1f);
+
+ ALU1Orders=(FixedOrder*) malloc(sizeof(FixedOrder)*ALU1OrderCnt); InstrZ=0;
+ AddALU1("INC" ,0x01); AddALU1("DEC" ,0x02); AddALU1("ABS" ,0x03);
+ AddALU1("NOT" ,0x04); AddALU1("NEG" ,0x05); AddALU1("SHLC" ,0x06);
+ AddALU1("SHRC" ,0x07); AddALU1("ROL" ,0x08); AddALU1("ROR" ,0x09);
+ AddALU1("SHLM" ,0x0a); AddALU1("SHRM" ,0x0b); AddALU1("SHRAM",0x0c);
+ AddALU1("CLR" ,0x0d); AddALU1("NORM" ,0x0e); AddALU1("CVT" ,0x0f);
+
+ ALU2Orders=(FixedOrder*) malloc(sizeof(FixedOrder)*ALU2OrderCnt); InstrZ=0;
+ AddALU2("ADD" ,0x10); AddALU2("SUB" ,0x11); AddALU2("ADDC" ,0x12);
+ AddALU2("SUBC" ,0x13); AddALU2("CMP" ,0x14); AddALU2("AND" ,0x15);
+ AddALU2("OR" ,0x16); AddALU2("XOR" ,0x17); AddALU2("ADDF" ,0x18);
+ AddALU2("SUBF" ,0x19);
+
+ SrcRegs=(Register*) malloc(sizeof(Register)*SrcRegCnt); InstrZ=0;
+ AddSrcReg("NON" ,0x00); AddSrcReg("RP" ,0x01); AddSrcReg("PSW0" ,0x02);
+ AddSrcReg("PSW1",0x03); AddSrcReg("SVR" ,0x04); AddSrcReg("SR" ,0x05);
+ AddSrcReg("LC" ,0x06); AddSrcReg("STX" ,0x07); AddSrcReg("M" ,0x08);
+ AddSrcReg("ML" ,0x09); AddSrcReg("ROM" ,0x0a); AddSrcReg("TR" ,0x0b);
+ AddSrcReg("AR" ,0x0c); AddSrcReg("SI" ,0x0d); AddSrcReg("DR" ,0x0e);
+ AddSrcReg("DRS" ,0x0f); AddSrcReg("WR0" ,0x10); AddSrcReg("WR1" ,0x11);
+ AddSrcReg("WR2" ,0x12); AddSrcReg("WR3" ,0x13); AddSrcReg("WR4" ,0x14);
+ AddSrcReg("WR5" ,0x15); AddSrcReg("WR6" ,0x16); AddSrcReg("WR7" ,0x17);
+ AddSrcReg("RAM0",0x18); AddSrcReg("RAM1",0x19); AddSrcReg("BP0" ,0x1a);
+ AddSrcReg("BP1" ,0x1b); AddSrcReg("IX0" ,0x1c); AddSrcReg("IX1" ,0x1d);
+ AddSrcReg("K" ,0x1e); AddSrcReg("L" ,0x1f);
+
+ ALUSrcRegs=(Register*) malloc(sizeof(Register)*ALUSrcRegCnt); InstrZ=0;
+ AddALUSrcReg("IB" ,0x00); AddALUSrcReg("M" ,0x01);
+ AddALUSrcReg("RAM0",0x02); AddALUSrcReg("RAM1",0x03);
+
+ DestRegs=(Register*) malloc(sizeof(Register)*DestRegCnt); InstrZ=0;
+ AddDestReg("NON" ,0x00); AddDestReg("RP" ,0x01); AddDestReg("PSW0" ,0x02);
+ AddDestReg("PSW1",0x03); AddDestReg("SVR" ,0x04); AddDestReg("SR" ,0x05);
+ AddDestReg("LC" ,0x06); AddDestReg("STK" ,0x07); AddDestReg("LKR0" ,0x08);
+ AddDestReg("KLR1",0x09); AddDestReg("TRE" ,0x0a); AddDestReg("TR" ,0x0b);
+ AddDestReg("AR" ,0x0c); AddDestReg("SO" ,0x0d); AddDestReg("DR" ,0x0e);
+ AddDestReg("DRS" ,0x0f); AddDestReg("WR0" ,0x10); AddDestReg("WR1" ,0x11);
+ AddDestReg("WR2" ,0x12); AddDestReg("WR3" ,0x13); AddDestReg("WR4" ,0x14);
+ AddDestReg("WR5" ,0x15); AddDestReg("WR6" ,0x16); AddDestReg("WR7" ,0x17);
+ AddDestReg("RAM0",0x18); AddDestReg("RAM1",0x19); AddDestReg("BP0" ,0x1a);
+ AddDestReg("BP1" ,0x1b); AddDestReg("IX0" ,0x1c); AddDestReg("IX1" ,0x1d);
+ AddDestReg("K" ,0x1e); AddDestReg("L" ,0x1f);
+
+ InstrComps=(LongWord*) malloc(sizeof(LongWord)*InstrCnt);
+ InstrDefs=(LongWord*) malloc(sizeof(LongWord)*InstrCnt);
+ for (InstrZ=0; InstrZ<InstrCnt; InstrDefs[InstrZ++]=0xffffffff);
+ InstrDefs[InstrALU]=0;
+ InstrDefs[InstrMove]=0;
+ InstrDefs[InstrBM]=0;
+ InstrDefs[InstrEM]=0;
+ InstrDefs[InstrDP0]=0;
+ InstrDefs[InstrDP1]=0;
+ InstrDefs[InstrEA]=0;
+ InstrDefs[InstrFC]=0;
+ InstrDefs[InstrFD]=0;
+ InstrDefs[InstrFIS]=0;
+ InstrDefs[InstrL]=0;
+ InstrDefs[InstrM0]=0;
+ InstrDefs[InstrM1]=0;
+ InstrDefs[InstrNF]=0;
+ InstrDefs[InstrRP]=0;
+ InstrDefs[InstrRW]=0;
+ InstrDefs[InstrWI]=0;
+ InstrDefs[InstrWT]=0;
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+
+ free(SrcRegs); free(ALUSrcRegs); free(DestRegs);
+
+ free(JmpOrders); free(ALU1Orders); free(ALU2Orders);
+
+ free(InstrComps); free(InstrDefs);
+END
+
+/*---------------------------------------------------------------------------*/
+/* Callbacks */
+
+ static void MakeCode_77230(void)
+BEGIN
+ int z,z2;
+ LongWord Diff;
+
+ /* Nullanweisung */
+
+ if ((Memo("")) AND (*AttrPart=='\0') AND (ArgCnt==0)) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* solange dekodieren, bis keine Operanden mehr da oder Fehler */
+
+ Error=False; InstrMask=0;
+ memset(InstrComps,0,sizeof(LongWord)*InstrCnt);
+ do
+ BEGIN
+ if (NOT LookupInstTable(InstTable,OpPart))
+ BEGIN
+ WrXError(1200,OpPart); Error=True;
+ END
+ END
+ while ((NOT Error) AND (*OpPart!='\0'));
+
+ /* passende Verknuepfung suchen */
+
+ if (NOT Error)
+ BEGIN
+ for (z=0; z<CaseCnt; z++)
+ BEGIN
+ /* Bits ermitteln, die nur in einer Maske vorhanden sind */
+
+ Diff=InstrMask^CaseMasks[z];
+
+ /* Fall nur möglich, wenn Bits im aktuellen Fall gesetzt sind, die
+ der Fall nicht hat */
+
+ if ((Diff&InstrMask)==0)
+ BEGIN
+ /* ist irgendein Feld unbenutzt, fuer das wir keinen Default haben? */
+
+ for (z2=0; z2<InstrCnt; z2++)
+ if (((Diff&(1l<<z2))!=0) AND (InstrDefs[z2]==-1)) break;
+ if (z2==InstrCnt) break;
+ END
+ END
+
+ switch (z)
+ BEGIN
+ case 0: /* nur LDI */
+ DAsmCode[0]=0xe0000000+InstrComps[InstrLDI];
+ CodeLen=1;
+ break;
+ case 1: /* JMP+MOV */
+ DAsmCode[0]=0xd0000000+(InstrComps[InstrBranch]<<10)
+ +InstrComps[InstrMove];
+ CodeLen=1;
+ break;
+ case 2: /* ALU+MOV+M0+M1+DP0+DP1 */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrDP1]<<15)+(InstrComps[InstrDP0]<<18)
+ +(InstrComps[InstrM1]<<21)+(InstrComps[InstrM0]<<23);
+ CodeLen=1;
+ break;
+ case 3: /* ALU+MOV+EA+DP0+DP1 */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrDP1]<<15)+(InstrComps[InstrDP0]<<18)
+ +(InstrComps[InstrEA]<<21)+0x02000000;
+ CodeLen=1;
+ break;
+ case 4: /* ALU+MOV+RP+M0+DP0+FC */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrRP]<<21)+(InstrComps[InstrFC]<<15)
+ +(InstrComps[InstrM0]<<19)+(InstrComps[InstrDP0]<<16)
+ +0x02800000;
+ CodeLen=1;
+ break;
+ case 5: /* ALU+MOV+RP+M1+DP1+FC */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrRP]<<21)+(InstrComps[InstrFC]<<15)
+ +(InstrComps[InstrM1]<<19)+(InstrComps[InstrDP1]<<16)
+ +0x03000000;
+ CodeLen=1;
+ break;
+ case 6: /* ALU+MOV+RP+M0+M1+L+FC */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrRP]<<21)+(InstrComps[InstrL]<<16)
+ +(InstrComps[InstrM0]<<19)+(InstrComps[InstrM1]<<17)
+ +(InstrComps[InstrFC]<<15)+0x03800000;
+ CodeLen=1;
+ break;
+ case 7: /* ALU+MOV+BASE0+BASE1+FC */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrBASE0]<<19)+(InstrComps[InstrBASE1]<<16)
+ +(InstrComps[InstrFC]<<15)+0x04000000;
+ CodeLen=1;
+ break;
+ case 8: /* ALU+MOV+RPC+L+FC */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrRPC]<<18)+(InstrComps[InstrL]<<16)
+ +(InstrComps[InstrFC]<<15)+0x04400000;
+ CodeLen=1;
+ break;
+ case 9: /* ALU+MOV+P2+P3+EM+BM+L+FC */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrP2]<<20)+(InstrComps[InstrP3]<<21)
+ +(InstrComps[InstrEM]<<19)+(InstrComps[InstrBM]<<17)
+ +(InstrComps[InstrL]<<16)+(InstrComps[InstrFC]<<15)
+ +0x04800000;
+ CodeLen=1;
+ break;
+ case 10: /* ALU+MOV+RW+L+FC */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrRW]<<20)+(InstrComps[InstrL]<<16)
+ +(InstrComps[InstrFC]<<15)+0x04c00000;
+ CodeLen=1;
+ break;
+ case 11: /* ALU+MOV+WT+L+FC */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrWT]<<19)+(InstrComps[InstrL]<<16)
+ +(InstrComps[InstrFC]<<15)+0x05000000;
+ CodeLen=1;
+ break;
+ case 12: /* ALU+MOV+NF+WI+L+FC */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrNF]<<19)+(InstrComps[InstrWI]<<17)
+ +(InstrComps[InstrL]<<16)+(InstrComps[InstrFC]<<15)
+ +0x05400000;
+ CodeLen=1;
+ break;
+ case 13: /* ALU+MOV+FIS+FD+L */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrFIS]<<19)+(InstrComps[InstrFD]<<17)
+ +(InstrComps[InstrL]<<16)+0x05800000;
+ CodeLen=1;
+ break;
+ case 14: /* ALU+MOV+SHV */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrSHV]<<15)+0x05c00000;
+ CodeLen=1;
+ break;
+ case 15: /* ALU+MOV+RPS */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrRPS]<<15)+0x06000000;
+ CodeLen=1;
+ break;
+ case 16: /* ALU+MOV+NAL */
+ DAsmCode[0]=(InstrComps[InstrALU]<<10)+InstrComps[InstrMove]
+ +(InstrComps[InstrNAL]<<15)+0x07000000;
+ CodeLen=1;
+ break;
+ default:
+ WrError(1355);
+ END
+ END
+END
+
+ static Boolean IsDef_77230(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_77230(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_77230(void)
+BEGIN
+ PFamilyDescr FoundDescr;
+
+ FoundDescr=FindFamilyByName("77230");
+
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+ PCSymbol="$"; HeaderID=FoundDescr->Id; NOPCode=0x00000000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegXData)|(1<<SegYData)|(1<<SegRData);
+ Grans[SegCode ]=4; ListGrans[SegCode ]=4; SegInits[SegCode ]=0;
+ SegLimits[SegCode ] = 0x1fff;
+ Grans[SegXData]=4; ListGrans[SegXData]=4; SegInits[SegXData]=0;
+ SegLimits[SegXData] = 0x1ff;
+ Grans[SegYData]=4; ListGrans[SegYData]=4; SegInits[SegYData]=0;
+ SegLimits[SegYData] = 0x1ff;
+ Grans[SegRData]=4; ListGrans[SegRData]=4; SegInits[SegRData]=0;
+ SegLimits[SegRData] = 0x3ff;
+
+ MakeCode=MakeCode_77230; IsDef=IsDef_77230;
+ SwitchFrom=SwitchFrom_77230;
+
+ InitFields();
+END
+
+/*---------------------------------------------------------------------------*/
+/* Initialisierung */
+
+ void code77230_init(void)
+BEGIN
+ CPU77230=AddCPU("77230",SwitchTo_77230);
+END
diff --git a/code77230.h b/code77230.h
new file mode 100644
index 0000000..244c02a
--- /dev/null
+++ b/code77230.h
@@ -0,0 +1,11 @@
+/* code77230.h */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Codegenerator NEC uPD77230 */
+/* */
+/* Historie: 13. 9.1998 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code77230_init(void);
diff --git a/code78c10.c b/code78c10.c
new file mode 100644
index 0000000..67afa96
--- /dev/null
+++ b/code78c10.c
@@ -0,0 +1,978 @@
+/* code78c10.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator NEC uPD78(C)1x */
+/* */
+/* Historie: 29.12.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } SReg;
+
+#define FixedOrderCnt 23
+#define ALUOrderCnt 15
+#define AbsOrderCnt 10
+#define Reg2OrderCnt 10
+#define WorkOrderCnt 4
+#define EAOrderCnt 4
+#define SRegCnt 28
+
+
+static LongInt WorkArea;
+
+static SimpProc SaveInitProc;
+
+static CPUVar CPU7810,CPU78C10;
+
+static FixedOrder *FixedOrders;
+static Byte *ALUOrderCodes;
+static char **ALUOrderImmOps,**ALUOrderRegOps,**ALUOrderEAOps;
+static FixedOrder *AbsOrders;
+static FixedOrder *Reg2Orders;
+static FixedOrder *WorkOrders;
+static FixedOrder *EAOrders;
+static SReg *SRegs;
+
+/*--------------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddSReg(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=SRegCnt) exit(255);
+ SRegs[InstrZ].Name=NName;
+ SRegs[InstrZ++].Code=NCode;
+END
+
+ static void AddALU(Byte NCode, char *NName1, char *NName2, char *NName3)
+BEGIN
+ if (InstrZ>=ALUOrderCnt) exit(255);
+ ALUOrderCodes[InstrZ]=NCode;
+ ALUOrderImmOps[InstrZ]=NName1;
+ ALUOrderRegOps[InstrZ]=NName2;
+ ALUOrderEAOps[InstrZ++]=NName3;
+END
+
+ static void AddAbs(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=AbsOrderCnt) exit(255);
+ AbsOrders[InstrZ].Name=NName;
+ AbsOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddReg2(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Reg2OrderCnt) exit(255);
+ Reg2Orders[InstrZ].Name=NName;
+ Reg2Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddWork(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=WorkOrderCnt) exit(255);
+ WorkOrders[InstrZ].Name=NName;
+ WorkOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddEA(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=EAOrderCnt) exit(255);
+ EAOrders[InstrZ].Name=NName;
+ EAOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("EXX" , 0x0011); AddFixed("EXA" , 0x0010);
+ AddFixed("EXH" , 0x0050); AddFixed("BLOCK", 0x0031);
+ AddFixed("TABLE", 0x48a8); AddFixed("DAA" , 0x0061);
+ AddFixed("STC" , 0x482b); AddFixed("CLC" , 0x482a);
+ AddFixed("NEGA" , 0x483a); AddFixed("RLD" , 0x4838);
+ AddFixed("RRD" , 0x4839); AddFixed("JB" , 0x0021);
+ AddFixed("JEA" , 0x4828); AddFixed("CALB" , 0x4829);
+ AddFixed("SOFTI", 0x0072); AddFixed("RET" , 0x00b8);
+ AddFixed("RETS" , 0x00b9); AddFixed("RETI" , 0x0062);
+ AddFixed("NOP" , 0x0000); AddFixed("EI" , 0x00aa);
+ AddFixed("DI" , 0x00ba); AddFixed("HLT" , 0x483b);
+ AddFixed("STOP" , 0x48bb);
+
+ SRegs=(SReg *) malloc(sizeof(SReg)*SRegCnt); InstrZ=0;
+ AddSReg("PA" , 0x00); AddSReg("PB" , 0x01);
+ AddSReg("PC" , 0x02); AddSReg("PD" , 0x03);
+ AddSReg("PF" , 0x05); AddSReg("MKH" , 0x06);
+ AddSReg("MKL" , 0x07); AddSReg("ANM" , 0x08);
+ AddSReg("SMH" , 0x09); AddSReg("SML" , 0x0a);
+ AddSReg("EOM" , 0x0b); AddSReg("ETNM", 0x0c);
+ AddSReg("TMM" , 0x0d); AddSReg("MM" , 0x10);
+ AddSReg("MCC" , 0x11); AddSReg("MA" , 0x12);
+ AddSReg("MB" , 0x13); AddSReg("MC" , 0x14);
+ AddSReg("MF" , 0x17); AddSReg("TXB" , 0x18);
+ AddSReg("RXB" , 0x19); AddSReg("TM0" , 0x1a);
+ AddSReg("TM1" , 0x1b); AddSReg("CR0" , 0x20);
+ AddSReg("CR1" , 0x21); AddSReg("CR2" , 0x22);
+ AddSReg("CR3" , 0x23); AddSReg("ZCM" , 0x28);
+
+ ALUOrderCodes=(Byte *) malloc(sizeof(Byte)*ALUOrderCnt);
+ ALUOrderImmOps=(char **) malloc(sizeof(char *)*ALUOrderCnt);
+ ALUOrderRegOps=(char **) malloc(sizeof(char *)*ALUOrderCnt);
+ ALUOrderEAOps=(char **) malloc(sizeof(char *)*ALUOrderCnt); InstrZ=0;
+ AddALU(10,"ACI" ,"ADC" ,"DADC" );
+ AddALU( 4,"ADINC","ADDNC","DADDNC");
+ AddALU( 8,"ADI" ,"ADD" ,"DADD" );
+ AddALU( 1,"ANI" ,"ANA" ,"DAN" );
+ AddALU(15,"EQI" ,"EQA" ,"DEQ" );
+ AddALU( 5,"GTI" ,"GTA" ,"DGT" );
+ AddALU( 7,"LTI" ,"LTA" ,"DLT" );
+ AddALU(13,"NEI" ,"NEA" ,"DNE" );
+ AddALU(11,"OFFI" ,"OFFA" ,"DOFF" );
+ AddALU( 9,"ONI" ,"ONA" ,"DON" );
+ AddALU( 3,"ORI" ,"ORA" ,"DOR" );
+ AddALU(14,"SBI" ,"SBB" ,"DSBB" );
+ AddALU( 6,"SUINB","SUBNB","DSUBNB");
+ AddALU(12,"SUI" ,"SUB" ,"DSUB" );
+ AddALU( 2,"XRI" ,"XRA" ,"DXR" );
+
+ AbsOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*AbsOrderCnt); InstrZ=0;
+ AddAbs("CALL", 0x0040); AddAbs("JMP" , 0x0054);
+ AddAbs("LBCD", 0x701f); AddAbs("LDED", 0x702f);
+ AddAbs("LHLD", 0x703f); AddAbs("LSPD", 0x700f);
+ AddAbs("SBCD", 0x701e); AddAbs("SDED", 0x702e);
+ AddAbs("SHLD", 0x703e); AddAbs("SSPD", 0x700e);
+
+ Reg2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Reg2OrderCnt); InstrZ=0;
+ AddReg2("DCR" , 0x0050); AddReg2("DIV" , 0x483c);
+ AddReg2("INR" , 0x0040); AddReg2("MUL" , 0x482c);
+ AddReg2("RLL" , 0x4834); AddReg2("RLR" , 0x4830);
+ AddReg2("SLL" , 0x4824); AddReg2("SLR" , 0x4820);
+ AddReg2("SLLC", 0x4804); AddReg2("SLRC", 0x4800);
+
+ WorkOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*WorkOrderCnt); InstrZ=0;
+ AddWork("DCRW", 0x33); AddWork("INRW", 0x20);
+ AddWork("LDAW", 0x01); AddWork("STAW", 0x63);
+
+ EAOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*EAOrderCnt); InstrZ=0;
+ AddEA("DRLL", 0x48b4); AddEA("DRLR", 0x48b0);
+ AddEA("DSLL", 0x48a4); AddEA("DSLR", 0x48a0);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(ALUOrderCodes); free(ALUOrderImmOps); free(ALUOrderRegOps); free(ALUOrderEAOps);
+ free(AbsOrders);
+ free(Reg2Orders);
+ free(WorkOrders);
+ free(EAOrders);
+ free(SRegs);
+END
+
+/*--------------------------------------------------------------------------------*/
+
+ static Boolean Decode_r(char *Asc, ShortInt *Erg)
+BEGIN
+ static char *Names="VABCDEHL";
+ char *p;
+
+ if (strlen(Asc)!=1) return False;
+ p=strchr(Names,toupper(*Asc));
+ if (p==Nil) return False;
+ *Erg=p-Names; return True;;
+END
+
+ static Boolean Decode_r1(char *Asc, ShortInt *Erg)
+BEGIN
+ if (strcasecmp(Asc,"EAL")==0) *Erg=1;
+ else if (strcasecmp(Asc,"EAH")==0) *Erg=0;
+ else
+ BEGIN
+ if (NOT Decode_r(Asc,Erg)) return False;
+ return (*Erg>1);
+ END
+ return True;
+END
+
+ static Boolean Decode_r2(char *Asc, ShortInt *Erg)
+BEGIN
+ if (NOT Decode_r(Asc,Erg)) return False;
+ return ((*Erg>0) AND (*Erg<4));
+END
+
+ static Boolean Decode_rp2(char *Asc, ShortInt *Erg)
+BEGIN
+#define RegCnt 5
+ static char *Regs[RegCnt]={"SP","B","D","H","EA"};
+
+ for (*Erg=0; *Erg<RegCnt; (*Erg)++)
+ if (strcasecmp(Asc,Regs[*Erg])==0) break;
+ return (*Erg<RegCnt);
+END
+
+ static Boolean Decode_rp(char *Asc, ShortInt *Erg)
+BEGIN
+ if (NOT Decode_rp2(Asc,Erg)) return False;
+ return (*Erg<4);
+END
+
+ static Boolean Decode_rp1(char *Asc, ShortInt *Erg)
+BEGIN
+ if (strcasecmp(Asc,"VA")==0) *Erg=0;
+ else
+ BEGIN
+ if (NOT Decode_rp2(Asc,Erg)) return False;
+ return (*Erg!=0);
+ END
+ return True;
+END
+
+ static Boolean Decode_rp3(char *Asc, ShortInt *Erg)
+BEGIN
+ if (NOT Decode_rp2(Asc,Erg)) return False;
+ return ((*Erg<4) AND (*Erg>0));
+END
+
+ static Boolean Decode_rpa2(char *Asc, ShortInt *Erg, ShortInt *Disp)
+BEGIN
+#define OpCnt 13
+ static char *OpNames[OpCnt]={"B","D","H","D+","H+","D-","H-",
+ "H+A","A+H","H+B","B+H","H+EA","EA+H"};
+ static Byte OpCodes[OpCnt]={1,2,3,4,5,6,7,12,12,13,13,14,14};
+
+ int z;
+ char *p,*pm;
+ Boolean OK;
+
+ for (z=0; z<OpCnt; z++)
+ if (strcasecmp(Asc,OpNames[z])==0)
+ BEGIN
+ *Erg=OpCodes[z]; return True;
+ END
+
+ p=QuotPos(Asc,'+'); pm=QuotPos(Asc,'-');
+ if ((p==Nil) OR ((pm!=Nil) AND (pm<p))) p=pm;
+ if (p==Nil) return False;
+
+ if (p==Asc+1)
+ switch (toupper(*Asc))
+ BEGIN
+ case 'H': *Erg=15; break;
+ case 'D': *Erg=11; break;
+ default: return False;
+ END
+ else return False;
+ *Disp=EvalIntExpression(p,SInt8,&OK);
+ return OK;
+END
+
+ static Boolean Decode_rpa(char *Asc, ShortInt *Erg)
+BEGIN
+ ShortInt Dummy;
+
+ if (NOT Decode_rpa2(Asc,Erg,&Dummy)) return False;
+ return (*Erg<=7);
+END
+
+ static Boolean Decode_rpa1(char *Asc, ShortInt *Erg)
+BEGIN
+ ShortInt Dummy;
+
+ if (NOT Decode_rpa2(Asc,Erg,&Dummy)) return False;
+ return (*Erg<=3);
+END
+
+ static Boolean Decode_rpa3(char *Asc, ShortInt *Erg, ShortInt *Disp)
+BEGIN
+ if (strcasecmp(Asc,"D++")==0) *Erg=4;
+ else if (strcasecmp(Asc,"H++")==0) *Erg=5;
+ else
+ BEGIN
+ if (NOT Decode_rpa2(Asc,Erg,Disp)) return False;
+ return ((*Erg==2) OR (*Erg==3) OR (*Erg>=8));
+ END
+ return True;
+END
+
+ static Boolean Decode_f(char *Asc, ShortInt *Erg)
+BEGIN
+#define FlagCnt 3
+ static char *Flags[FlagCnt]={"CY","HC","Z"};
+
+ for (*Erg=0; *Erg<FlagCnt; (*Erg)++)
+ if (strcasecmp(Flags[*Erg],Asc)==0) break;
+ *Erg+=2; return (*Erg<=4);
+END
+
+ static Boolean Decode_sr0(char *Asc, ShortInt *Erg)
+BEGIN
+ int z;
+
+ for (z=0; z<SRegCnt; z++)
+ if (strcasecmp(Asc,SRegs[z].Name)==0) break;
+ if ((z==SRegCnt-1) AND (MomCPU==CPU7810))
+ BEGIN
+ WrError(1440); return False;
+ END
+ if (z<SRegCnt)
+ BEGIN
+ *Erg=SRegs[z].Code; return True;
+ END
+ else return False;
+END
+
+ static Boolean Decode_sr1(char *Asc, ShortInt *Erg)
+BEGIN
+ if (NOT Decode_sr0(Asc,Erg)) return False;
+ return (((*Erg>=0) AND (*Erg<=9)) OR (*Erg==11) OR (*Erg==13) OR (*Erg==25) OR ((*Erg>=32) AND (*Erg<=35)));
+END
+
+ static Boolean Decode_sr(char *Asc, ShortInt *Erg)
+BEGIN
+ if (NOT Decode_sr0(Asc,Erg)) return False;
+ return (((*Erg>=0) AND (*Erg<=24)) OR (*Erg==26) OR (*Erg==27) OR (*Erg==40));
+END
+
+ static Boolean Decode_sr2(char *Asc, ShortInt *Erg)
+BEGIN
+ if (NOT Decode_sr0(Asc,Erg)) return False;
+ return (((*Erg>=0) AND (*Erg<=9)) OR (*Erg==11) OR (*Erg==13));
+END
+
+ static Boolean Decode_sr3(char *Asc, ShortInt *Erg)
+BEGIN
+ if (strcasecmp(Asc,"ETM0")==0) *Erg=0;
+ else if (strcasecmp(Asc,"ETM1")==0) *Erg=1;
+ else return False;
+ return True;
+END
+
+ static Boolean Decode_sr4(char *Asc, ShortInt *Erg)
+BEGIN
+ if (strcasecmp(Asc,"ECNT")==0) *Erg=0;
+ else if (strcasecmp(Asc,"ECPT")==0) *Erg=1;
+ else return False;
+ return True;
+END
+
+ static Boolean Decode_irf(char *Asc, ShortInt *Erg)
+BEGIN
+#undef FlagCnt
+#define FlagCnt 18
+ static char *FlagNames[FlagCnt]=
+ {"NMI" ,"FT0" ,"FT1" ,"F1" ,"F2" ,"FE0" ,
+ "FE1" ,"FEIN","FAD" ,"FSR" ,"FST" ,"ER" ,
+ "OV" ,"AN4" ,"AN5" ,"AN6" ,"AN7" ,"SB" };
+ static ShortInt FlagCodes[FlagCnt]=
+ {0,1,2,3,4,5,6,7,8,9,10,11,12,16,17,18,19,20};
+
+ for (*Erg=0; *Erg<FlagCnt; (*Erg)++)
+ if (strcasecmp(FlagNames[*Erg],Asc)==0) break;
+ if (*Erg>=FlagCnt) return False;
+ *Erg=FlagCodes[*Erg];
+ return True;
+END
+
+ static Boolean Decode_wa(char *Asc, Byte *Erg)
+BEGIN
+ Word Adr;
+ Boolean OK;
+
+ FirstPassUnknown=False;
+ Adr=EvalIntExpression(Asc,Int16,&OK); if (NOT OK) return False;
+ if ((FirstPassUnknown) AND (Hi(Adr)!=WorkArea)) WrError(110);
+ *Erg=Lo(Adr);
+ return True;
+END
+
+ static Boolean HasDisp(ShortInt Mode)
+BEGIN
+ return ((Mode & 11)==11);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME78C10Count 1
+static ASSUMERec ASSUME78C10s[ASSUME78C10Count]=
+ {{"V" , &WorkArea, 0, 0xff, 0x100}};
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME78C10s,ASSUME78C10Count);
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_78C10(void)
+BEGIN
+ int z;
+ Integer AdrInt;
+ ShortInt HVal8,HReg;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if ((Memo("STOP")) AND (MomCPU==CPU7810)) WrError(1500);
+ else
+ BEGIN
+ CodeLen=0;
+ if (Hi(FixedOrders[z].Code)!=0) BAsmCode[CodeLen++]=Hi(FixedOrders[z].Code);
+ BAsmCode[CodeLen++]=Lo(FixedOrders[z].Code);
+ END
+ return;
+ END
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")==0)
+ if (Decode_sr1(ArgStr[2],&HReg))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x4c;
+ BAsmCode[1]=0xc0+HReg;
+ END
+ else if (Decode_r1(ArgStr[2],&HReg))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x08+HReg;
+ END
+ else WrError(1350);
+ else if (strcasecmp(ArgStr[2],"A")==0)
+ if (Decode_sr(ArgStr[1],&HReg))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x4d;
+ BAsmCode[1]=0xc0+HReg;
+ END
+ else if (Decode_r1(ArgStr[1],&HReg))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x18+HReg;
+ END
+ else WrError(1350);
+ else if (Decode_r(ArgStr[1],&HReg))
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0x70; BAsmCode[1]=0x68+HReg;
+ BAsmCode[2]=Lo(AdrInt); BAsmCode[3]=Hi(AdrInt);
+ END
+ END
+ else if (Decode_r(ArgStr[2],&HReg))
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0x70; BAsmCode[1]=0x78+HReg;
+ BAsmCode[2]=Lo(AdrInt); BAsmCode[3]=Hi(AdrInt);
+ END
+ END
+ else WrError(1350);
+ return;
+ END
+
+ if (Memo("MVI"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ if (Decode_r(ArgStr[1],&HReg))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x68+HReg;
+ END
+ else if (Decode_sr2(ArgStr[1],&HReg))
+ BEGIN
+ CodeLen=3; BAsmCode[2]=BAsmCode[1]; BAsmCode[0]=0x64;
+ BAsmCode[1]=(HReg & 7)+((HReg & 8) << 4);
+ END
+ else WrError(1350);
+ END
+ return;
+ END
+
+ if (Memo("MVIW"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (Decode_wa(ArgStr[1],BAsmCode+1))
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x71;
+ END
+ END
+ return;
+ END
+
+ if (Memo("MVIX"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT Decode_rpa1(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x48+HReg; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDAX")) OR (Memo("STAX")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT Decode_rpa2(ArgStr[1],&HReg,(ShortInt *) BAsmCode+1)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1+Ord(HasDisp(HReg));
+ BAsmCode[0]=0x28+(Ord(Memo("STAX")) << 4)+((HReg & 8) << 4)+(HReg & 7);
+ END
+ return;
+ END
+
+ if ((Memo("LDEAX")) OR (Memo("STEAX")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT Decode_rpa3(ArgStr[1],&HReg,(ShortInt *) BAsmCode+2)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2+Ord(HasDisp(HReg)); BAsmCode[0]=0x48;
+ BAsmCode[1]=0x80+(Ord(Memo("STEAX")) << 4)+HReg;
+ END
+ return;
+ END
+
+ if (Memo("LXI"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT Decode_rp2(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x04+(HReg << 4);
+ BAsmCode[1]=Lo(AdrInt); BAsmCode[2]=Hi(AdrInt);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT Decode_rp1(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=0xa0+(Ord(Memo("PUSH")) << 4)+HReg;
+ END
+ return;
+ END
+
+ if (Memo("DMOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (strcasecmp(ArgStr[1],"EA")!=0)
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ OK=True;
+ END
+ else OK=False;
+ if (strcasecmp(ArgStr[1],"EA")!=0) WrError(1350);
+ else if (Decode_rp3(ArgStr[2],&HReg))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xa4+HReg;
+ if (OK) BAsmCode[0]+=0x10;
+ END
+ else if (((OK) AND (Decode_sr3(ArgStr[2],&HReg)))
+ OR ((NOT OK) AND (Decode_sr4(ArgStr[2],&HReg))))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x48; BAsmCode[1]=0xc0+HReg;
+ if (OK) BAsmCode[1]+=0x12;
+ END
+ else WrError(1350);
+ END
+ return;
+ END
+
+ for (z=0; z<ALUOrderCnt; z++)
+ if (Memo(ALUOrderImmOps[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ HVal8=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ if (strcasecmp(ArgStr[1],"A")==0)
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x06+((ALUOrderCodes[z] & 14) << 3)+(ALUOrderCodes[z] & 1);
+ BAsmCode[1]=HVal8;
+ END
+ else if (Decode_r(ArgStr[1],&HReg))
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x74; BAsmCode[2]=HVal8;
+ BAsmCode[1]=HReg+(ALUOrderCodes[z] << 3);
+ END
+ else if (Decode_sr2(ArgStr[1],&HReg))
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x64; BAsmCode[2]=HVal8;
+ BAsmCode[1]=(HReg & 7)+(ALUOrderCodes[z] << 3)+((HReg & 8) << 4);
+ END
+ else WrError(1350);
+ END
+ return;
+ END
+ else if (Memo(ALUOrderRegOps[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (strcasecmp(ArgStr[1],"A")!=0)
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ OK=False;
+ END
+ else OK=True;
+ if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else if (NOT Decode_r(ArgStr[2],&HReg)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x60;
+ BAsmCode[1]=(ALUOrderCodes[z] << 3)+HReg;
+ if ((OK) OR (Memo("ONA")) OR (Memo("OFFA")))
+ BAsmCode[1]+=0x80;
+ END
+ END
+ return;
+ END
+ else if ((OpPart[strlen(OpPart)-1]=='W') AND (strncmp(ALUOrderRegOps[z],OpPart,strlen(ALUOrderRegOps[z]))==0))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (Decode_wa(ArgStr[1],BAsmCode+2))
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x74;
+ BAsmCode[1]=0x80+(ALUOrderCodes[z] << 3);
+ END
+ return;
+ END
+ else if ((OpPart[strlen(OpPart)-1]=='X') AND (strncmp(ALUOrderRegOps[z],OpPart,strlen(ALUOrderRegOps[z]))==0))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT Decode_rpa(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x70;
+ BAsmCode[1]=0x80+(ALUOrderCodes[z] << 3)+HReg;
+ END
+ return;
+ END
+ else if (Memo(ALUOrderEAOps[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"EA")!=0) WrError(1350);
+ else if (NOT Decode_rp3(ArgStr[2],&HReg)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x74;
+ BAsmCode[1]=0x84+(ALUOrderCodes[z] << 3)+HReg;
+ END
+ return;
+ END
+ else if (((OpPart[strlen(OpPart)-1]=='W') AND (strncmp(ALUOrderImmOps[z],OpPart,strlen(ALUOrderImmOps[z]))==0)) AND (Odd(ALUOrderCodes[z])))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (Decode_wa(ArgStr[1],BAsmCode+1))
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=3;
+ BAsmCode[0]=0x05+((ALUOrderCodes[z] >> 1) << 4);
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<AbsOrderCnt; z++)
+ if (Memo(AbsOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=0;
+ if (Hi(AbsOrders[z].Code)!=0) BAsmCode[CodeLen++]=Hi(AbsOrders[z].Code);
+ BAsmCode[CodeLen++]=Lo(AbsOrders[z].Code);
+ BAsmCode[CodeLen++]=Lo(AdrInt);
+ BAsmCode[CodeLen++]=Hi(AdrInt);
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Reg2OrderCnt; z++)
+ if (Memo(Reg2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT Decode_r2(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=0;
+ if (Hi(Reg2Orders[z].Code)!=0) BAsmCode[CodeLen++]=Hi(Reg2Orders[z].Code);
+ BAsmCode[CodeLen++]=Lo(Reg2Orders[z].Code)+HReg;
+ END
+ return;
+ END
+
+ for (z=0; z<WorkOrderCnt; z++)
+ if (Memo(WorkOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (Decode_wa(ArgStr[1],BAsmCode+1))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=WorkOrders[z].Code;
+ END
+ return;
+ END
+
+ if ((Memo("DCX")) OR (Memo("INX")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"EA")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xa8+Ord(Memo("DCX"));
+ END
+ else if (Decode_rp(ArgStr[1],&HReg))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x02+Ord(Memo("DCX"))+(HReg << 4);
+ END
+ else WrError(1350);
+ return;
+ END
+
+ if ((Memo("EADD")) OR (Memo("ESUB")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"EA")!=0) WrError(1350);
+ else if (NOT Decode_r2(ArgStr[2],&HReg)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x70;
+ BAsmCode[1]=0x40+(Ord(Memo("ESUB")) << 5)+HReg;
+ END
+ return;
+ END
+
+ if ((Memo("JR")) OR (Memo("JRE")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK)-(EProgCounter()+1+Ord(Memo("JRE")));
+ if (OK)
+ if (Memo("JR"))
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-32) OR (AdrInt>31))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xc0+(AdrInt & 0x3f);
+ END
+ else
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-256) OR (AdrInt>255))) WrError(1370);
+ else
+ BEGIN
+ if ((AdrInt>=-32) AND (AdrInt<=31)) WrError(20);
+ CodeLen=2; BAsmCode[0]=0x4e + (Hi(AdrInt) & 1); /* ANSI :-O */
+ BAsmCode[1]=Lo(AdrInt);
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALF"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if ((NOT FirstPassUnknown) AND ((AdrInt >> 11)!=1)) WrError(1905);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=Hi(AdrInt)+0x70; BAsmCode[1]=Lo(AdrInt);
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if ((NOT FirstPassUnknown) AND ((AdrInt & 0xffc1)!=0x80)) WrError(1905);
+ else
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=0x80+((AdrInt & 0x3f) >> 1);
+ END
+ END
+ return;
+ END
+
+ if (Memo("BIT"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ if (Decode_wa(ArgStr[2],BAsmCode+1))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x58+HReg;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<EAOrderCnt; z++)
+ if (Memo(EAOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"EA")!=0) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=Hi(EAOrders[z].Code); BAsmCode[1]=Lo(EAOrders[z].Code);
+ END
+ return;
+ END
+
+ if ((Memo("SK")) OR (Memo("SKN")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT Decode_f(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x48;
+ BAsmCode[1]=0x08+(Ord(Memo("SKN")) << 4)+HReg;
+ END
+ return;
+ END
+
+ if ((Memo("SKIT")) OR (Memo("SKINT")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT Decode_irf(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x48;
+ BAsmCode[1]=0x40+(Ord(Memo("SKINT")) << 5)+HReg;
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_78C10(void)
+BEGIN
+ SaveInitProc();
+ WorkArea=0x100;
+END
+
+ static Boolean IsDef_78C10(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_78C10(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_78C10(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x7a; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_78C10; IsDef=IsDef_78C10;
+ SwitchFrom=SwitchFrom_78C10; InitFields();
+END
+
+ void code78c10_init(void)
+BEGIN
+ CPU7810 =AddCPU("7810" ,SwitchTo_78C10);
+ CPU78C10=AddCPU("78C10",SwitchTo_78C10);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_78C10;
+END
diff --git a/code78c10.h b/code78c10.h
new file mode 100644
index 0000000..e2d1f99
--- /dev/null
+++ b/code78c10.h
@@ -0,0 +1,11 @@
+/* code78c10.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator NEC uPD78(C)1x */
+/* */
+/* Historie: 29.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code78c10_init(void);
diff --git a/code78k0.c b/code78k0.c
new file mode 100644
index 0000000..3a03e94
--- /dev/null
+++ b/code78k0.c
@@ -0,0 +1,1228 @@
+/* code78k0.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 78K0-Familie */
+/* */
+/* Historie: 1.12.1996 Grundsteinlegung */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+#define ModNone (-1)
+#define ModReg8 0
+#define MModReg8 (1 << ModReg8)
+#define ModReg16 1
+#define MModReg16 (1 << ModReg16)
+#define ModImm 2
+#define MModImm (1 << ModImm)
+#define ModShort 3
+#define MModShort (1 << ModShort)
+#define ModSFR 4
+#define MModSFR (1 << ModSFR)
+#define ModAbs 5
+#define MModAbs (1 << ModAbs)
+#define ModIReg 6
+#define MModIReg (1 << ModIReg)
+#define ModIndex 7
+#define MModIndex (1 << ModIndex)
+#define ModDisp 8
+#define MModDisp (1 << ModDisp)
+
+#define AccReg 1
+#define AccReg16 0
+
+#define FixedOrderCount 11
+#define AriOrderCount 8
+#define Ari16OrderCount 3
+#define ShiftOrderCount 4
+#define Bit2OrderCount 3
+#define RelOrderCount 4
+#define BRelOrderCount 3
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+static FixedOrder *FixedOrders;
+static char **AriOrders;
+static char **Ari16Orders;
+static char **ShiftOrders;
+static char **Bit2Orders;
+static char **RelOrders;
+static char **BRelOrders;
+
+static Byte OpSize,AdrPart;
+static Byte AdrVals[2];
+static ShortInt AdrMode;
+
+static CPUVar CPU78070;
+
+
+/*-------------------------------------------------------------------------*/
+/* dynamische Codetabellenverwaltung */
+
+ static void AddFixed(char *NewName, Word NewCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NewName;
+ FixedOrders[InstrZ++].Code=NewCode;
+END
+
+ static void AddAri(char *NewName)
+BEGIN
+ if (InstrZ>=AriOrderCount) exit(255);
+ AriOrders[InstrZ++]=NewName;
+END
+
+ static void AddAri16(char *NewName)
+BEGIN
+ if (InstrZ>=Ari16OrderCount) exit(255);
+ Ari16Orders[InstrZ++]=NewName;
+END
+
+ static void AddShift(char *NewName)
+BEGIN
+ if (InstrZ>=ShiftOrderCount) exit(255);
+ ShiftOrders[InstrZ++]=NewName;
+END
+
+ static void AddBit2(char *NewName)
+BEGIN
+ if (InstrZ>=Bit2OrderCount) exit(255);
+ Bit2Orders[InstrZ++]=NewName;
+END
+
+ static void AddRel(char *NewName)
+BEGIN
+ if (InstrZ>=RelOrderCount) exit(255);
+ RelOrders[InstrZ++]=NewName;
+END
+
+ static void AddBRel(char *NewName)
+BEGIN
+ if (InstrZ>=BRelOrderCount) exit(255);
+ BRelOrders[InstrZ++]=NewName;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("BRK" ,0x00bf);
+ AddFixed("RET" ,0x00af);
+ AddFixed("RETB" ,0x009f);
+ AddFixed("RETI" ,0x008f);
+ AddFixed("HALT" ,0x7110);
+ AddFixed("STOP" ,0x7100);
+ AddFixed("NOP" ,0x0000);
+ AddFixed("EI" ,0x7a1e);
+ AddFixed("DI" ,0x7b1e);
+ AddFixed("ADJBA",0x6180);
+ AddFixed("ADJBS",0x6190);
+
+ AriOrders=(char **) malloc(sizeof(char *)*AriOrderCount); InstrZ=0;
+ AddAri("ADD" ); AddAri("SUB" ); AddAri("ADDC"); AddAri("SUBC");
+ AddAri("CMP" ); AddAri("AND" ); AddAri("OR" ); AddAri("XOR" );
+
+ Ari16Orders=(char **) malloc(sizeof(char *)*Ari16OrderCount); InstrZ=0;
+ AddAri16("ADDW"); AddAri16("SUBW"); AddAri16("CMPW");
+
+ ShiftOrders=(char **) malloc(sizeof(char *)*ShiftOrderCount); InstrZ=0;
+ AddShift("ROR"); AddShift("RORC"); AddShift("ROL"); AddShift("ROLC");
+
+ Bit2Orders=(char **) malloc(sizeof(char *)*Bit2OrderCount); InstrZ=0;
+ AddBit2("AND1"); AddBit2("OR1"); AddBit2("XOR1");
+
+ RelOrders=(char **) malloc(sizeof(char *)*RelOrderCount); InstrZ=0;
+ AddRel("BC"); AddRel("BNC"); AddRel("BZ"); AddRel("BNZ");
+
+ BRelOrders=(char **) malloc(sizeof(char *)*BRelOrderCount); InstrZ=0;
+ AddBRel("BTCLR"); AddBRel("BT"); AddBRel("BF");
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(AriOrders);
+ free(Ari16Orders);
+ free(ShiftOrders);
+ free(Bit2Orders);
+ free(RelOrders);
+ free(BRelOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Adressausdruck parsen */
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ WrError(1350);
+ AdrMode=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ static char *RegNames[8]={"X","A","C","B","E","D","L","H"};
+
+ Word AdrWord;
+ int z;
+ Boolean OK,LongFlag;
+
+ AdrMode=ModNone; AdrCnt=0;
+
+ /* Register */
+
+ for (z=0; z<8; z++)
+ if (strcasecmp(Asc,RegNames[z])==0)
+ BEGIN
+ AdrMode=ModReg8; AdrPart=z; ChkAdr(Mask); return;
+ END
+
+ if (toupper(*Asc)=='R')
+ if ((strlen(Asc)==2) AND (Asc[1]>='0') AND (Asc[1]<='7'))
+ BEGIN
+ AdrMode=ModReg8; AdrPart=Asc[1]-'0'; ChkAdr(Mask); return;
+ END
+ else if ((strlen(Asc)==3) AND (toupper(Asc[1])=='P') AND (Asc[2]>='0') AND (Asc[2]<='3'))
+ BEGIN
+ AdrMode=ModReg16; AdrPart=Asc[2]-'0'; ChkAdr(Mask); return;
+ END
+
+ if (strlen(Asc)==2)
+ for (z=0; z<4; z++)
+ if ((toupper(*Asc)==*RegNames[(z<<1)+1]) AND (toupper(Asc[1])==*RegNames[z<<1]))
+ BEGIN
+ AdrMode=ModReg16; AdrPart=z; ChkAdr(Mask); return;
+ END
+
+ /* immediate */
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ break;
+ case 1:
+ AdrWord=EvalIntExpression(Asc+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord);
+ END
+ break;
+ END
+ if (OK)
+ BEGIN
+ AdrMode=ModImm; AdrCnt=OpSize+1;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* indirekt */
+
+ if ((*Asc=='[') AND (Asc[strlen(Asc)-1]==']'))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+
+ if ((strcasecmp(Asc,"DE")==0) OR (strcasecmp(Asc,"RP2")==0))
+ BEGIN
+ AdrMode=ModIReg; AdrPart=0;
+ END
+ else if ((strncasecmp(Asc,"HL",2)!=0) AND (strncasecmp(Asc,"RP3",3)!=0)) WrXError(1445,Asc);
+ else
+ BEGIN
+ strcpy(Asc,Asc+2); if (*Asc=='3') strcpy(Asc,Asc+1);
+ if ((strcasecmp(Asc,"+B")==0) OR (strcasecmp(Asc,"+R3")==0))
+ BEGIN
+ AdrMode=ModIndex; AdrPart=1;
+ END
+ else if ((strcasecmp(Asc,"+C")==0) OR (strcasecmp(Asc,"+R2")==0))
+ BEGIN
+ AdrMode=ModIndex; AdrPart=0;
+ END
+ else
+ BEGIN
+ AdrVals[0]=EvalIntExpression(Asc,UInt8,&OK);
+ if (OK)
+ if (AdrVals[0]==0)
+ BEGIN
+ AdrMode=ModIReg; AdrPart=1;
+ END
+ else
+ BEGIN
+ AdrMode=ModDisp; AdrCnt=1;
+ END;
+ END
+ END
+
+ ChkAdr(Mask); return;
+ END
+
+ /* erzwungen lang ? */
+
+ if (*Asc=='!')
+ BEGIN
+ LongFlag=True; strcpy(Asc,Asc+1);
+ END
+ else LongFlag=False;
+
+ /* -->absolut */
+
+ FirstPassUnknown=True;
+ AdrWord=EvalIntExpression(Asc,UInt16,&OK);
+ if (FirstPassUnknown)
+ BEGIN
+ AdrWord&=0xffffe;
+ if ((Mask & MModAbs)==0)
+ AdrWord=(AdrWord | 0xff00) & 0xff1f;
+ END
+ if (OK)
+ if ((NOT LongFlag) AND ((Mask & MModShort)!=0) AND (AdrWord>=0xfe20) AND (AdrWord<=0xff1f))
+ BEGIN
+ AdrMode=ModShort; AdrCnt=1; AdrVals[0]=Lo(AdrWord);
+ END
+ else if ((NOT LongFlag) AND ((Mask & MModSFR)!=0) AND (((AdrWord>=0xff00) AND (AdrWord<=0xffcf)) OR (AdrWord>=0xffe0)))
+ BEGIN
+ AdrMode=ModSFR; AdrCnt=1; AdrVals[0]=Lo(AdrWord);
+ END
+ else
+ BEGIN
+ AdrMode=ModAbs; AdrCnt=2; AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord);
+ END
+
+ ChkAdr(Mask);
+END
+
+ static void ChkEven(void)
+BEGIN
+ if ((AdrMode==ModAbs) OR (AdrMode==ModShort) OR (AdrMode==ModSFR))
+ if ((AdrVals[0]&1)==1) WrError(180);
+END
+
+ static Boolean DecodeBitAdr(char *Asc, Byte *Erg)
+BEGIN
+ char *p;
+ Boolean OK;
+
+ p=RQuotPos(Asc,'.');
+ if (p==Nil)
+ BEGIN
+ WrError(1510); return False;
+ END
+
+ *p='\0';
+ *Erg=EvalIntExpression(p+1,UInt3,&OK) << 4;
+ if (NOT OK) return False;
+
+ DecodeAdr(Asc,MModShort+MModSFR+MModIReg+MModReg8);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart!=AccReg)
+ BEGIN
+ WrError(1350); return False;
+ END
+ else
+ BEGIN
+ *Erg+=0x88; return True;
+ END
+ case ModShort:
+ return True;
+ case ModSFR:
+ *Erg+=0x08; return True;
+ case ModIReg:
+ if (AdrPart==0)
+ BEGIN
+ WrError(1350); return False;
+ END
+ else
+ BEGIN
+ *Erg+=0x80; return True;
+ END
+ default:
+ return False;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void MakeCode_78K0(void)
+BEGIN
+ int z;
+ Byte HReg;
+ Word AdrWord;
+ Integer AdrInt;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False; OpSize=0;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (Hi(FixedOrders[z].Code)==0) CodeLen=1;
+ else
+ BEGIN
+ BAsmCode[0]=Hi(FixedOrders[z].Code); CodeLen=2;
+ END
+ BAsmCode[CodeLen-1]=Lo(FixedOrders[z].Code);
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModShort+MModSFR+MModAbs+MModIReg+MModIndex+MModDisp);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModImm+MModReg8+((HReg==AccReg)?MModShort+MModSFR+MModAbs+MModIReg+MModIndex+MModDisp:0));
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if ((HReg==AccReg)==(AdrPart==AccReg)) WrError(1350);
+ else if (HReg==AccReg)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x60+AdrPart;
+ END
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x70+HReg;
+ END
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0xa0+HReg; BAsmCode[1]=AdrVals[0];
+ break;
+ case ModShort:
+ CodeLen=2; BAsmCode[0]=0xf0; BAsmCode[1]=AdrVals[0];
+ break;
+ case ModSFR:
+ CodeLen=2; BAsmCode[0]=0xf4; BAsmCode[1]=AdrVals[0];
+ break;
+ case ModAbs:
+ CodeLen=3; BAsmCode[0]=0xfe; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ break;
+ case ModIReg:
+ CodeLen=1; BAsmCode[0]=0x85+(AdrPart << 1);
+ break;
+ case ModIndex:
+ CodeLen=1; BAsmCode[0]=0xaa+AdrPart;
+ break;
+ case ModDisp:
+ CodeLen=2; BAsmCode[0]=0xae; BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModShort:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModReg8+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart!=AccReg) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xf2; CodeLen=2;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0x11; BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ case ModSFR:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModReg8+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart!=AccReg) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xf6; CodeLen=2;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0x13; BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ case ModAbs:
+ memcpy(BAsmCode+1,AdrVals,2);
+ DecodeAdr(ArgStr[2],MModReg8);
+ if (AdrMode==ModReg8)
+ if (AdrPart!=AccReg) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x9e; CodeLen=3;
+ END
+ break;
+ case ModIReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg8);
+ if (AdrMode==ModReg8)
+ if (AdrPart!=AccReg) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x95+(AdrPart << 1); CodeLen=1;
+ END
+ break;
+ case ModIndex:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg8);
+ if (AdrMode==ModReg8)
+ if (AdrPart!=AccReg) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xba+HReg; CodeLen=1;
+ END
+ break;
+ case ModDisp:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModReg8);
+ if (AdrMode==ModReg8)
+ if (AdrPart!=AccReg) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xbe; CodeLen=2;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("XCH"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if ((strcasecmp(ArgStr[2],"A")==0) OR (strcasecmp(ArgStr[2],"RP1")==0))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ DecodeAdr(ArgStr[1],MModReg8);
+ if (AdrMode!=ModNone)
+ if (AdrPart!=AccReg) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg8+MModShort+MModSFR+MModAbs+MModIReg+MModIndex+MModDisp);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart==AccReg) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x30+AdrPart; CodeLen=1;
+ END
+ break;
+ case ModShort:
+ BAsmCode[0]=0x83; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModSFR:
+ BAsmCode[0]=0x93; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0xce; memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=3;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0x05+(AdrPart << 1); CodeLen=1;
+ break;
+ case ModIndex:
+ BAsmCode[0]=0x31; BAsmCode[1]=0x8a+AdrPart; CodeLen=2;
+ break;
+ case ModDisp:
+ BAsmCode[0]=0xde; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOVW"))
+ BEGIN
+ OpSize=1;
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16+MModShort+MModSFR+MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg16+MModImm+((HReg==AccReg16)?MModShort+MModSFR+MModAbs:0));
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if ((HReg==AccReg16)==(AdrPart==AccReg16)) WrError(1350);
+ else if (HReg==AccReg16)
+ BEGIN
+ BAsmCode[0]=0xc0+(AdrPart << 1); CodeLen=1;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xd0+(HReg << 1); CodeLen=1;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0x10+(HReg << 1); memcpy(BAsmCode+1,AdrVals,2);
+ CodeLen=3;
+ break;
+ case ModShort:
+ BAsmCode[0]=0x89; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ ChkEven();
+ break;
+ case ModSFR:
+ BAsmCode[0]=0xa9; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ ChkEven();
+ break;
+ case ModAbs:
+ BAsmCode[0]=0x02; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ ChkEven();
+ break;
+ END
+ break;
+ case ModShort:
+ ChkEven();
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModReg16+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (AdrPart!=AccReg16) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x99; CodeLen=2;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xee; memcpy(BAsmCode+2,AdrVals,2); CodeLen=4;
+ break;
+ END
+ break;
+ case ModSFR:
+ ChkEven();
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModReg16+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (AdrPart!=AccReg16) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xb9; CodeLen=2;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xfe; memcpy(BAsmCode+2,AdrVals,2); CodeLen=4;
+ break;
+ END
+ break;
+ case ModAbs:
+ ChkEven();
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModReg16);
+ if (AdrMode==ModReg16)
+ if (AdrPart!=AccReg16) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x03; CodeLen=3;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("XCHW"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16);
+ if (AdrMode==ModReg16)
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg16);
+ if (AdrMode==ModReg16)
+ if ((HReg==AccReg16)==(AdrPart==AccReg16)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=(HReg==AccReg16) ? 0xe0+(AdrPart << 1) : 0xe0+(HReg << 1);
+ CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ z=Ord(Memo("POP"));
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"PSW")==0)
+ BEGIN
+ BAsmCode[0]=0x22+z; CodeLen=1;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16);
+ if (AdrMode==ModReg16)
+ BEGIN
+ BAsmCode[0]=0xb1-z+(AdrPart << 1); CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<AriOrderCount; z++)
+ if (Memo(AriOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModShort);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg8+((HReg==AccReg)?(MModImm+MModShort+MModAbs+MModIReg+MModIndex+MModDisp):0));
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart==AccReg)
+ BEGIN
+ BAsmCode[0]=0x61; BAsmCode[1]=(z << 4)+HReg; CodeLen=2;
+ END
+ else if (HReg==AccReg)
+ BEGIN
+ BAsmCode[0]=0x61; BAsmCode[1]=0x08+(z << 4)+AdrPart; CodeLen=2;
+ END
+ else WrError(1350);
+ break;
+ case ModImm:
+ BAsmCode[0]=(z << 4)+0x0d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModShort:
+ BAsmCode[0]=(z << 4)+0x0e; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModAbs:
+ BAsmCode[0]=(z << 4)+0x08; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ break;
+ case ModIReg:
+ if (AdrPart==0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=(z << 4)+0x0f; CodeLen=2;
+ END
+ break;
+ case ModIndex:
+ BAsmCode[0]=0x31; BAsmCode[1]=(z << 4)+0x0a+AdrPart; CodeLen=2;
+ break;
+ case ModDisp:
+ BAsmCode[0]=(z << 4)+0x09; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModShort:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[0]=(z << 4)+0x88; BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Ari16OrderCount; z++)
+ if (Memo(Ari16Orders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OpSize=1;
+ DecodeAdr(ArgStr[1],MModReg16);
+ if (AdrMode==ModReg16)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[0]=0xca+(z << 4); memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("MULU"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8);
+ if (AdrMode==ModReg8)
+ if (AdrPart!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x31; BAsmCode[1]=0x88; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if (Memo("DIVUW"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8);
+ if (AdrMode==ModReg8)
+ if (AdrPart!=2) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x31; BAsmCode[1]=0x82; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INC")) OR (Memo("DEC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ z=Ord(Memo("DEC")) << 4;
+ DecodeAdr(ArgStr[1],MModReg8+MModShort);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ BAsmCode[0]=0x40+AdrPart+z; CodeLen=1;
+ break;
+ case ModShort:
+ BAsmCode[0]=0x81+z; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INCW")) OR (Memo("DECW")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16);
+ if (AdrMode==ModReg16)
+ BEGIN
+ BAsmCode[0]=0x80+(Ord(Memo("DECW")) << 4)+(AdrPart << 1);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ShiftOrderCount; z++)
+ if (Memo(ShiftOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8);
+ if (AdrMode==ModReg8)
+ if (AdrPart!=AccReg) WrError(1350);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[2],UInt1,&OK);
+ if (OK)
+ if (HReg!=1) WrError(1315);
+ else
+ BEGIN
+ BAsmCode[0]=0x24+z; CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("ROL4")) OR (Memo("ROR4")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIReg);
+ if (AdrMode==ModIReg)
+ if (AdrPart==0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x31; BAsmCode[1]=0x80+(Ord(Memo("ROR4")) << 4);
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ /* Bitoperationen */
+
+ if (Memo("MOV1"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (strcasecmp(ArgStr[2],"CY")==0)
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ z=1;
+ END
+ else z=4;
+ if (strcasecmp(ArgStr[1],"CY")!=0) WrError(1110);
+ else if (DecodeBitAdr(ArgStr[2],&HReg))
+ BEGIN
+ BAsmCode[0]=0x61+(Ord((HReg & 0x88)!=0x88) << 4);
+ BAsmCode[1]=z+HReg;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Bit2OrderCount; z++)
+ if (Memo(Bit2Orders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CY")!=0) WrError(1110);
+ else if (DecodeBitAdr(ArgStr[2],&HReg))
+ BEGIN
+ BAsmCode[0]=0x61+(Ord((HReg & 0x88)!=0x88) << 4);
+ BAsmCode[1]=z+5+HReg;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ return;
+ END
+
+ if ((Memo("SET1")) OR (Memo("CLR1")))
+ BEGIN
+ z=Ord(Memo("CLR1"));
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CY")==0)
+ BEGIN
+ BAsmCode[0]=0x20+z; CodeLen=1;
+ END
+ else if (DecodeBitAdr(ArgStr[1],&HReg))
+ if ((HReg & 0x88)==0)
+ BEGIN
+ BAsmCode[0]=0x0a+z+(HReg & 0x70);
+ BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x61+(Ord((HReg & 0x88)!=0x88) << 4);
+ BAsmCode[1]=HReg+2+z;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ return;
+ END
+
+ if (Memo("NOT1"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CY")!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x01;
+ CodeLen=1;
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if (Memo("CALL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAbs);
+ if (AdrMode==ModAbs)
+ BEGIN
+ BAsmCode[0]=0x9a; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALLF"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]=='!') strcpy(ArgStr[1],ArgStr[1]+1);
+ AdrWord=EvalIntExpression(ArgStr[1],UInt11,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x0c+(Hi(AdrWord) << 4);
+ BAsmCode[1]=Lo(AdrWord);
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALLT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if ((*ArgStr[1]!='[') OR (ArgStr[1][strlen(ArgStr[1])-1]!=']')) WrError(1350);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ ArgStr[1][strlen(ArgStr[1])-1]='\0';
+ AdrWord=EvalIntExpression(ArgStr[1]+1,UInt6,&OK);
+ if (FirstPassUnknown) AdrWord&=0xfffe;
+ if (OK)
+ if (Odd(AdrWord)) WrError(1325);
+ else
+ BEGIN
+ BAsmCode[0]=0xc1+(AdrWord & 0x3e);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("BR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if ((strcasecmp(ArgStr[1],"AX")==0) OR (strcasecmp(ArgStr[1],"RP0")==0))
+ BEGIN
+ BAsmCode[0]=0x31; BAsmCode[1]=0x98; CodeLen=2;
+ END
+ else
+ BEGIN
+ if (*ArgStr[1]=='!')
+ BEGIN
+ strcpy(ArgStr[1],ArgStr[1]+1); HReg=1;
+ END
+ else if (*ArgStr[1]=='$')
+ BEGIN
+ strcpy(ArgStr[1],ArgStr[1]+1); HReg=2;
+ END
+ else HReg=0;
+ AdrWord=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ BEGIN
+ if (HReg==0)
+ BEGIN
+ AdrInt=AdrWord-(EProgCounter()-2);
+ HReg=((AdrInt>=-128) AND (AdrInt<127)) ? 2 : 1;
+ END
+ switch (HReg)
+ BEGIN
+ case 1:
+ BAsmCode[0]=0x9b; BAsmCode[1]=Lo(AdrWord); BAsmCode[2]=Hi(AdrWord);
+ CodeLen=3;
+ break;
+ case 2:
+ AdrInt=AdrWord-(EProgCounter()+2);
+ if (((AdrInt<-128) OR (AdrInt>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0xfa; BAsmCode[1]=AdrInt & 0xff; CodeLen=2;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<RelOrderCount; z++)
+ if (Memo(RelOrders[z]))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]=='$') strcpy(ArgStr[1],ArgStr[1]+1);
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if (((AdrInt<-128) OR (AdrInt>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x8b+(z << 4); BAsmCode[1]=AdrInt & 0xff;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BRelOrderCount; z++)
+ if (Memo(BRelOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (DecodeBitAdr(ArgStr[1],&HReg))
+ BEGIN
+ if ((z==1) AND ((HReg & 0x88)==0))
+ BEGIN
+ BAsmCode[0]=0x8c+HReg; BAsmCode[1]=AdrVals[0]; HReg=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x31;
+ switch (HReg & 0x88)
+ BEGIN
+ case 0x00:
+ BAsmCode[1]=0x00; break;
+ case 0x08:
+ BAsmCode[1]=0x04; break;
+ case 0x80:
+ BAsmCode[1]=0x84; break;
+ case 0x88:
+ BAsmCode[1]=0x0c; break;
+ END
+ BAsmCode[1]+=(HReg & 0x70)+z+1;
+ BAsmCode[2]=AdrVals[0];
+ HReg=2+AdrCnt;
+ END
+ if (*ArgStr[2]=='$') strcpy(ArgStr[2],ArgStr[2]+1);
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+HReg+1);
+ if (OK)
+ if (((AdrInt<-128) OR (AdrInt>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[HReg]=AdrInt & 0xff;
+ CodeLen=HReg+1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("DBNZ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModShort);
+ if ((AdrMode==ModReg8) AND ((AdrPart & 6)!=2)) WrError(1350);
+ else if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=(AdrMode==ModReg8) ? 0x88+AdrPart : 0x04;
+ BAsmCode[1]=AdrVals[0];
+ if (*ArgStr[2]=='$') strcpy(ArgStr[2],ArgStr[2]+1);
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+AdrCnt+2);
+ if (OK)
+ if (((AdrInt<-128) OR (AdrInt>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[AdrCnt+1]=AdrInt & 0xff;
+ CodeLen=AdrCnt+2;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Steueranweisungen */
+
+ if (Memo("SEL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1350);
+ else if ((strlen(ArgStr[1])!=3) OR (strncasecmp(ArgStr[1],"RB",2)!=0)) WrError(1350);
+ else
+ BEGIN
+ HReg=ArgStr[1][2]-'0';
+ if (ChkRange(HReg,0,3))
+ BEGIN
+ BAsmCode[0]=0x61;
+ BAsmCode[1]=0xd0+((HReg & 1) << 3)+((HReg & 2) << 4);
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_78K0(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_78K0(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_78K0(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="PC"; HeaderID=0x7c; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_78K0; IsDef=IsDef_78K0;
+ SwitchFrom=SwitchFrom_78K0; InitFields();
+END
+
+ void code78k0_init(void)
+BEGIN
+ CPU78070=AddCPU("78070",SwitchTo_78K0);
+END
+
+
+
diff --git a/code78k0.h b/code78k0.h
new file mode 100644
index 0000000..59bba22
--- /dev/null
+++ b/code78k0.h
@@ -0,0 +1,11 @@
+/* code78k0.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 78K0-Familie */
+/* */
+/* Historie: 1.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code78k0_init(void);
diff --git a/code8008.c b/code8008.c
new file mode 100644
index 0000000..77c4399
--- /dev/null
+++ b/code8008.c
@@ -0,0 +1,356 @@
+/* code8008.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Intel 8008 */
+/* */
+/* Historie: 3.12.1998 Grundsteinlegung */
+/* 4.12.1998 FixedOrders begonnen */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "headids.h"
+
+/*---------------------------------------------------------------------------*/
+/* Variablen */
+
+typedef struct
+ {
+ Byte Code;
+ } FixedOrder;
+
+#define FixedOrderCnt 10
+#define ImmOrderCnt 10
+#define JmpOrderCnt 10
+
+static CPUVar CPU8008;
+static PInstTable InstTable;
+
+static FixedOrder *FixedOrders, *ImmOrders, *JmpOrders;
+
+static char *RegNames = "ABCDEHLM";
+
+/*---------------------------------------------------------------------------*/
+/* Parser */
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg)
+BEGIN
+ char *p;
+
+ if (strlen(Asc) != 2) return False;
+
+ p = strchr(RegNames, toupper(*Asc));
+ if (p != NULL) *Erg = p - RegNames;
+ return (p!= NULL);
+END
+
+/*---------------------------------------------------------------------------*/
+/* Hilfsdekoder */
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ if (ArgCnt != 0) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0] = FixedOrders[Index].Code;
+ CodeLen = 1;
+ END
+END
+
+ static void DecodeImm(Word Index)
+BEGIN
+ Boolean OK;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[1] = EvalIntExpression(ArgStr[1], Int8, &OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0] = ImmOrders[Index].Code;
+ CodeLen = 2;
+ END
+ END
+END
+
+ static void DecodeJmp(Word Index)
+BEGIN
+ Boolean OK;
+ Word AdrWord;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ AdrWord = EvalIntExpression(ArgStr[1], UInt14, &OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0] = JmpOrders[Index].Code;
+ BAsmCode[1] = Lo(AdrWord);
+ BAsmCode[2] = Hi(AdrWord) & 0x3f;
+ CodeLen = 3;
+ ChkSpace(SegCode);
+ END
+ END
+END
+
+ static void DecodeRST(Word Index)
+BEGIN
+ Boolean OK;
+ Word AdrWord;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown = False;
+ AdrWord = EvalIntExpression(ArgStr[1], UInt14, &OK);
+ if (FirstPassUnknown) AdrWord &= 0x38;
+ if (OK)
+ if (ChkRange(AdrWord, 0, 0x38))
+ if ((AdrWord & 7) != 0) WrError(1325);
+ else
+ BEGIN
+ BAsmCode[0] = AdrWord + 0x05;
+ CodeLen = 1;
+ ChkSpace(SegCode);
+ END
+ END
+END
+
+ static void DecodeINP(Word Index)
+BEGIN
+ Boolean OK;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0] = 0x41 + (EvalIntExpression(ArgStr[1], UInt3, &OK) << 1);
+ if (OK)
+ BEGIN
+ CodeLen = 1;
+ ChkSpace(SegIO);
+ END
+ END
+END
+
+ static void DecodeOUT(Word Index)
+BEGIN
+ Boolean OK;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0] = 0x41 + (EvalIntExpression(ArgStr[1], UInt3, &OK) << 1);
+ if (OK)
+ BEGIN
+ CodeLen = 1;
+ ChkSpace(SegIO);
+ END
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+/*---------------------------------------------------------------------------*/
+/* Codetabellenverwaltung */
+
+static int InstrZ;
+static char *FlagNames = "CZSP";
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ >= FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Code = NCode;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
+END
+
+ static void AddFixeds(char *NName, Byte NCode, int Pos)
+BEGIN
+ char Memo[10], *p;
+ int z;
+
+ strcpy(Memo, NName); p = strchr(Memo, '*');
+ for (z = 0; z < 8; z++)
+ BEGIN
+ *p = RegNames[z];
+ AddFixed(Memo, NCode + (z << Pos));
+ END
+END
+
+ static void AddImm(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ >= ImmOrderCnt) exit(255);
+ ImmOrders[InstrZ].Code = NCode;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeImm);
+END
+
+ static void AddImms(char *NName, Byte NCode, int Pos)
+BEGIN
+ char Memo[10], *p;
+ int z;
+
+ strcpy(Memo, NName); p = strchr(Memo, '*');
+ for (z = 0; z < 8; z++)
+ BEGIN
+ *p = RegNames[z];
+ AddImm(Memo, NCode + (z << Pos));
+ END
+END
+
+ static void AddJmp(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ >= JmpOrderCnt) exit(255);
+ JmpOrders[InstrZ].Code = NCode;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeJmp);
+END
+
+ static void AddJmps(char *NName, Byte NCode, int Pos)
+BEGIN
+ char Memo[10], *p;
+ int z;
+
+ strcpy(Memo, NName); p = strchr(Memo, '*');
+ for (z = 0; z < 4; z++)
+ BEGIN
+ *p = FlagNames[z];
+ AddJmp(Memo, NCode + (z << Pos));
+ END
+END
+
+ static void InitFields(void)
+BEGIN
+ SetDynamicInstTable(InstTable=CreateInstTable(401));
+
+ FixedOrders = (FixedOrder*) malloc(sizeof(FixedOrder) * FixedOrderCnt); InstrZ = 0;
+ AddFixeds("L*A", 0xc0, 3); AddFixeds("L*B", 0xc1, 3);
+ AddFixeds("L*C", 0xc2, 3); AddFixeds("L*D", 0xc3, 3);
+ AddFixeds("L*E", 0xc4, 3); AddFixeds("L*H", 0xc5, 3);
+ AddFixeds("L*L", 0xc6, 3); AddFixeds("L*M", 0xc7, 3);
+
+ AddFixeds("IN*", 0x00, 3);
+ AddFixeds("DC*", 0x01, 3);
+ AddFixeds("AD*", 0x80, 0);
+ AddFixeds("AC*", 0x88, 0);
+ AddFixeds("SU*", 0x90, 0);
+ AddFixeds("SB*", 0x98, 0);
+ AddFixeds("NR*", 0xa0, 0);
+ AddFixeds("XR*", 0xa8, 0);
+ AddFixeds("OR*", 0xb0, 0);
+ AddFixeds("CP*", 0xb8, 0);
+ AddFixed ("RLC", 0x02);
+ AddFixed ("RRC", 0x0a);
+ AddFixed ("RAL", 0x12);
+ AddFixed ("RAR", 0x1a);
+
+ AddFixed("RET", 0x07);
+ AddFixed("RFC", 0x03); AddFixed("RFZ", 0x0b);
+ AddFixed("RFS", 0x13); AddFixed("RFP", 0x1b);
+ AddFixed("RTC", 0x23); AddFixed("RTZ", 0x2b);
+ AddFixed("RTS", 0x33); AddFixed("RTP", 0x3b);
+ AddFixed("HLT", 0x00);
+
+ ImmOrders = (FixedOrder*) malloc(sizeof(FixedOrder) * ImmOrderCnt); InstrZ = 0;
+ AddImms("L*I", 0x06, 3);
+ AddImm ("ADI", 0x04);
+ AddImm ("ACI", 0x0c);
+ AddImm ("SUI", 0x14);
+ AddImm ("SBI", 0x1c);
+ AddImm ("NDI", 0x24);
+ AddImm ("XRI", 0x2c);
+ AddImm ("ORI", 0x34);
+ AddImm ("CPI", 0x3c);
+
+ JmpOrders = (FixedOrder*) malloc(sizeof(FixedOrder) * JmpOrderCnt); InstrZ = 0;
+ AddJmp ("JMP", 0x44);
+ AddJmps("JF*", 0x40, 3);
+ AddJmps("JT*", 0x60, 3);
+ AddJmp ("CAL", 0x46);
+ AddJmps("CF*", 0x42, 3);
+ AddJmps("CT*", 0x62, 3);
+
+ AddInstTable(InstTable, "RST", 0, DecodeRST);
+ AddInstTable(InstTable, "INP", 0, DecodeINP);
+ AddInstTable(InstTable, "OUT", 0, DecodeOUT);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+ free(ImmOrders);
+ free(JmpOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+/* Callbacks */
+
+ static void MakeCode_8008(void)
+BEGIN
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* der Rest */
+
+ if (NOT LookupInstTable(InstTable, OpPart)) WrXError(1200, OpPart);
+END
+
+ static Boolean IsDef_8008(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_8008(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_8008(void)
+BEGIN
+ PFamilyDescr FoundDescr;
+
+ FoundDescr=FindFamilyByName("8008");
+
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=FoundDescr->Id; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegIO);
+ Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
+ SegLimits[SegCode] = 0x3fff;
+ Grans[SegIO ]=1; ListGrans[SegIO ]=1; SegInits[SegIO ]=0;
+ SegLimits[SegIO] = 7;
+
+ MakeCode=MakeCode_8008; IsDef=IsDef_8008;
+ SwitchFrom=SwitchFrom_8008;
+
+ InitFields();
+END
+
+/*---------------------------------------------------------------------------*/
+/* Initialisierung */
+
+ void code8008_init(void)
+BEGIN
+ CPU8008=AddCPU("8008",SwitchTo_8008);
+END
diff --git a/code8008.h b/code8008.h
new file mode 100644
index 0000000..6d4b694
--- /dev/null
+++ b/code8008.h
@@ -0,0 +1,11 @@
+/* code8008.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Intel 8008 */
+/* */
+/* Historie: 3.12.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code8008_init(void);
diff --git a/code85.c b/code85.c
new file mode 100644
index 0000000..aa1e25d
--- /dev/null
+++ b/code85.c
@@ -0,0 +1,423 @@
+/* code85.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 8080/8085 */
+/* */
+/* Historie: 24.10.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+/*--------------------------------------------------------------------------------------------------*/
+
+typedef struct
+ {
+ char *Name;
+ Boolean May80;
+ Byte Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } BaseOrder;
+
+#define FixedOrderCnt 27
+#define Op16OrderCnt 22
+#define Op8OrderCnt 10
+#define ALUOrderCnt 8
+
+static FixedOrder *FixedOrders;
+static BaseOrder *Op16Orders;
+static BaseOrder *Op8Orders;
+static BaseOrder *ALUOrders;
+
+static CPUVar CPU8080,CPU8085;
+
+/*--------------------------------------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Boolean NMay, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].May80=NMay;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddOp16(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=Op16OrderCnt) exit(255);
+ Op16Orders[InstrZ].Name=NName;
+ Op16Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddOp8(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=Op8OrderCnt) exit(255);
+ Op8Orders[InstrZ].Name=NName;
+ Op8Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ALUOrderCnt) exit(255);
+ ALUOrders[InstrZ].Name=NName;
+ ALUOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("XCHG", True , 0xeb); AddFixed("XTHL", True , 0xe3);
+ AddFixed("SPHL", True , 0xf9); AddFixed("PCHL", True , 0xe9);
+ AddFixed("RET" , True , 0xc9); AddFixed("RC" , True , 0xd8);
+ AddFixed("RNC" , True , 0xd0); AddFixed("RZ" , True , 0xc8);
+ AddFixed("RNZ" , True , 0xc0); AddFixed("RP" , True , 0xf0);
+ AddFixed("RM" , True , 0xf8); AddFixed("RPE" , True , 0xe8);
+ AddFixed("RPO" , True , 0xe0); AddFixed("RLC" , True , 0x07);
+ AddFixed("RRC" , True , 0x0f); AddFixed("RAL" , True , 0x17);
+ AddFixed("RAR" , True , 0x1f); AddFixed("CMA" , True , 0x2f);
+ AddFixed("STC" , True , 0x37); AddFixed("CMC" , True , 0x3f);
+ AddFixed("DAA" , True , 0x27); AddFixed("EI" , True , 0xfb);
+ AddFixed("DI" , True , 0xf3); AddFixed("NOP" , True , 0x00);
+ AddFixed("HLT" , True , 0x76); AddFixed("RIM" , False, 0x20);
+ AddFixed("SIM" , False, 0x30);
+
+ Op16Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*Op16OrderCnt); InstrZ=0;
+ AddOp16("STA" , 0x32); AddOp16("LDA" , 0x3a);
+ AddOp16("SHLD", 0x22); AddOp16("LHLD", 0x2a);
+ AddOp16("JMP" , 0xc3); AddOp16("JC" , 0xda);
+ AddOp16("JNC" , 0xd2); AddOp16("JZ" , 0xca);
+ AddOp16("JNZ" , 0xc2); AddOp16("JP" , 0xf2);
+ AddOp16("JM" , 0xfa); AddOp16("JPE" , 0xea);
+ AddOp16("JPO" , 0xe2); AddOp16("CALL", 0xcd);
+ AddOp16("CC" , 0xdc); AddOp16("CNC" , 0xd4);
+ AddOp16("CZ" , 0xcc); AddOp16("CNZ" , 0xc4);
+ AddOp16("CP" , 0xf4); AddOp16("CM" , 0xfc);
+ AddOp16("CPE" , 0xec); AddOp16("CPO" , 0xe4);
+
+ Op8Orders=(BaseOrder *) malloc(sizeof(BaseOrder)*Op8OrderCnt); InstrZ=0;
+ AddOp8("IN" , 0xdb); AddOp8("OUT" , 0xd3);
+ AddOp8("ADI" , 0xc6); AddOp8("ACI" , 0xce);
+ AddOp8("SUI" , 0xd6); AddOp8("SBI" , 0xde);
+ AddOp8("ANI" , 0xe6); AddOp8("XRI" , 0xee);
+ AddOp8("ORI" , 0xf6); AddOp8("CPI" , 0xfe);
+
+ ALUOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*ALUOrderCnt); InstrZ=0;
+ AddALU("ADD" , 0x80); AddALU("ADC" , 0x88);
+ AddALU("SUB" , 0x90); AddALU("SBB" , 0x98);
+ AddALU("ANA" , 0xa0); AddALU("XRA" , 0xa8);
+ AddALU("ORA" , 0xb0); AddALU("CMP" , 0xb8);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(Op16Orders);
+ free(Op8Orders);
+ free(ALUOrders);
+END
+
+/*--------------------------------------------------------------------------------------------------------*/
+
+ static Boolean DecodeReg8(char *Asc, Byte *Erg)
+BEGIN
+ static char *RegNames="BCDEHLMA";
+ char *p;
+
+ if (strlen(Asc)!=1) return False;
+ else
+ BEGIN
+ p=strchr(RegNames,toupper(*Asc));
+ if (p==0) return False;
+ else
+ BEGIN
+ *Erg=p-RegNames; return True;
+ END
+ END
+END
+
+ static Boolean DecodeReg16(char *Asc, Byte *Erg)
+BEGIN
+ static char *RegNames[4]={"B","D","H","SP"};
+
+ for (*Erg=0; (*Erg)<4; (*Erg)++)
+ if (strcasecmp(Asc,RegNames[*Erg])==0) break;
+
+ return ((*Erg)<4);
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ if (Memo("PORT"))
+ BEGIN
+ CodeEquate(SegIO,0,0xff);
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_85(void)
+BEGIN
+ Boolean OK;
+ Word AdrWord;
+ Byte AdrByte;
+ int z;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* Anweisungen ohne Operanden */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if ((MomCPU<CPU8085) AND (NOT FixedOrders[z].May80)) WrError(1500);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ /* ein 16-Bit-Operand */
+
+ for (z=0; z<Op16OrderCnt; z++)
+ if (Memo(Op16Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=Op16Orders[z].Code;
+ BAsmCode[1]=Lo(AdrWord); BAsmCode[2]=Hi(AdrWord);
+ ChkSpace(SegCode);
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Op8OrderCnt; z++)
+ if (Memo(Op8Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrByte=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=Op8Orders[z].Code; BAsmCode[1]=AdrByte;
+ if (z<2) ChkSpace(SegIO);
+ END
+ END
+ return;
+ END
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg8(ArgStr[1],&AdrByte)) WrError(1980);
+ else if (NOT DecodeReg8(ArgStr[2],BAsmCode+0)) WrError(1980);
+ else
+ BEGIN
+ BAsmCode[0]+=0x40+(AdrByte << 3);
+ if (BAsmCode[0]==0x76) WrError(1760); else CodeLen=1;
+ END
+ return;
+ END
+
+ if (Memo("MVI"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ if (NOT DecodeReg8(ArgStr[1],&AdrByte)) WrError(1980);
+ else
+ BEGIN
+ BAsmCode[0]=0x06+(AdrByte << 3); CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if (Memo("LXI"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],Int16,&OK);
+ if (OK)
+ if (NOT DecodeReg16(ArgStr[1],&AdrByte)) WrError(1980);
+ else
+ BEGIN
+ BAsmCode[0]=0x01+(AdrByte << 4);
+ BAsmCode[1]=Lo(AdrWord); BAsmCode[2]=Hi(AdrWord);
+ CodeLen=3;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDAX")) OR (Memo("STAX")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg16(ArgStr[1],&AdrByte)) WrError(1980);
+ else switch (AdrByte)
+ BEGIN
+ case 3: /* SP */
+ WrError(1135); break;
+ case 2: /* H --> MOV A,M oder M,A */
+ CodeLen=1;
+ BAsmCode[0]=(Memo("LDAX")) ? 0x7e : 0x77;
+ break;
+ default:
+ CodeLen=1;
+ BAsmCode[0]=0x02+(AdrByte << 4);
+ if (Memo("LDAX")) BAsmCode[0]+=8;
+ break;
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if (strcasecmp(ArgStr[1],"PSW")==0) strmaxcpy(ArgStr[1],"SP",255);
+ if (NOT DecodeReg16(ArgStr[1],&AdrByte)) WrError(1980);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xc1+(AdrByte << 4);
+ if (Memo("PUSH")) BAsmCode[0]+=4;
+ END
+ END
+ return;
+ END
+
+ if (Memo("RST"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrByte=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xc7+(AdrByte << 3);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INR")) OR (Memo("DCR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg8(ArgStr[1],&AdrByte)) WrError(1980);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x04+(AdrByte << 3);
+ if (Memo("DCR")) BAsmCode[0]++;
+ END
+ return;
+ END
+
+ if ((Memo("INX")) OR (Memo("DCX")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg16(ArgStr[1],&AdrByte)) WrError(1980);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x03+(AdrByte << 4);
+ if (Memo("DCX")) BAsmCode[0]+=8;
+ END
+ return;
+ END
+
+ if (Memo("DAD"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg16(ArgStr[1],&AdrByte)) WrError(1980);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x09+(AdrByte << 4);
+ END
+ return;
+ END
+
+ for (z=0; z<ALUOrderCnt; z++)
+ if (Memo(ALUOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg8(ArgStr[1],&AdrByte)) WrError(1980);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=ALUOrders[z].Code+AdrByte;
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_85(void)
+BEGIN
+ return (Memo("PORT"));
+END
+
+ static void SwitchFrom_85(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_85(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x41; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegIO);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+ Grans[SegIO ]=1; ListGrans[SegIO ]=1; SegInits[SegIO ]=0;
+ SegLimits[SegIO ] = 0xff;
+
+ MakeCode=MakeCode_85; IsDef=IsDef_85;
+ SwitchFrom=SwitchFrom_85; InitFields();
+END
+
+ void code85_init(void)
+BEGIN
+ CPU8080=AddCPU("8080",SwitchTo_85);
+ CPU8085=AddCPU("8085",SwitchTo_85);
+END
diff --git a/code85.h b/code85.h
new file mode 100644
index 0000000..44b0fe3
--- /dev/null
+++ b/code85.h
@@ -0,0 +1,11 @@
+/* code85.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 8080/8085 */
+/* */
+/* Historie: 24.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code85_init(void);
diff --git a/code86.c b/code86.c
new file mode 100644
index 0000000..9c5ffe6
--- /dev/null
+++ b/code86.c
@@ -0,0 +1,2600 @@
+/* code86.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 8086/V-Serie */
+/* */
+/* Historie: */
+/* 2. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+#include "asmitree.h"
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Word Code;
+ Byte Add;
+ } AddOrder;
+
+
+#define FixedOrderCnt 41
+#define FPUFixedOrderCnt 29
+#define StringOrderCnt 14
+#define ReptOrderCnt 7
+#define RelOrderCnt 36
+#define ModRegOrderCnt 4
+#define ShiftOrderCnt 8
+#define Reg16OrderCnt 3
+#define FPUStOrderCnt 2
+#define FPU16OrderCnt 5
+#define MulOrderCnt 4
+#define Bit1OrderCnt 4
+
+#define SegRegCnt 3
+static char *SegRegNames[SegRegCnt+1]={"ES","CS","SS","DS"};
+static Byte SegRegPrefixes[SegRegCnt+1]={0x26,0x2e,0x36,0x3e};
+
+#define TypeNone (-1)
+#define TypeReg8 0
+#define TypeReg16 1
+#define TypeRegSeg 2
+#define TypeMem 3
+#define TypeImm 4
+#define TypeFReg 5
+
+static ShortInt AdrType;
+static Byte AdrMode;
+static Byte AdrVals[6];
+static ShortInt OpSize;
+static Boolean UnknownFlag;
+
+static Boolean NoSegCheck;
+
+static Byte Prefixes[6];
+static Byte PrefixLen;
+
+static Byte SegAssumes[SegRegCnt+1];
+
+static SimpProc SaveInitProc;
+
+static CPUVar CPU8086,CPU80186,CPUV30,CPUV35;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *FPUFixedOrders;
+static FixedOrder *FPUStOrders;
+static FixedOrder *FPU16Orders;
+static FixedOrder *StringOrders;
+static FixedOrder *ReptOrders;
+static FixedOrder *RelOrders;
+static FixedOrder *ModRegOrders;
+static FixedOrder *ShiftOrders;
+static AddOrder *Reg16Orders;
+static char **MulOrders;
+static char **Bit1Orders;
+static PInstTable InstTable;
+
+/*------------------------------------------------------------------------------------*/
+
+ static void PutCode(Word Code)
+BEGIN
+ if (Hi(Code)!=0) BAsmCode[CodeLen++]=Hi(Code);
+ BAsmCode[CodeLen++]=Lo(Code);
+END
+
+ static void MoveAdr(int Dest)
+BEGIN
+ memcpy(BAsmCode+CodeLen+Dest,AdrVals,AdrCnt);
+END
+
+ static Byte Sgn(Byte inp)
+BEGIN
+ return (inp>127) ? 0xff : 0;
+END
+
+ static void AddPrefix(Byte Prefix)
+BEGIN
+ Prefixes[PrefixLen++]=Prefix;
+END
+
+ static void AddPrefixes(void)
+BEGIN
+ if ((CodeLen!=0) AND (PrefixLen!=0))
+ BEGIN
+ memmove(BAsmCode+PrefixLen,BAsmCode,CodeLen);
+ memcpy(BAsmCode,Prefixes,PrefixLen);
+ CodeLen+=PrefixLen;
+ END
+END
+
+ static Boolean AbleToSign(Word Arg)
+BEGIN
+ return ((Arg<=0x7f) OR (Arg>=0xff80));
+END
+
+ static Boolean MinOneIs0(void)
+BEGIN
+ if ((UnknownFlag) AND (OpSize==-1))
+ BEGIN
+ OpSize=0; return True;
+ END
+ else return False;
+END
+
+ static void ChkOpSize(ShortInt NewSize)
+BEGIN
+ if (OpSize==-1) OpSize=NewSize;
+ else if (OpSize!=NewSize)
+ BEGIN
+ AdrType=TypeNone; WrError(1131);
+ END
+END
+
+ static void ChkSingleSpace(Byte Seg, Byte EffSeg, Byte MomSegment)
+BEGIN
+ Byte z;
+
+ /* liegt Operand im zu pruefenden Segment? nein-->vergessen */
+
+ if ((MomSegment & (1 << Seg))==0) return;
+
+ /* zeigt bish. benutztes Segmentregister auf dieses Segment? ja-->ok */
+
+ if (EffSeg==Seg) return;
+
+ /* falls schon ein Override gesetzt wurde, nur warnen */
+
+ if (PrefixLen>0) WrError(70);
+
+ /* ansonsten ein passendes Segment suchen und warnen, falls keines da */
+
+ else
+ BEGIN
+ z=0;
+ while ((z<=SegRegCnt) AND (SegAssumes[z]!=Seg)) z++;
+ if (z>SegRegCnt) WrXError(75,SegNames[Seg]);
+ else AddPrefix(SegRegPrefixes[z]);
+ END
+END
+
+ static void ChkSpaces(ShortInt SegBuffer, Byte MomSegment)
+BEGIN
+ Byte EffSeg;
+
+ if (NoSegCheck) return;
+
+ /* in welches Segment geht das benutzte Segmentregister ? */
+
+ EffSeg=SegAssumes[SegBuffer];
+
+ /* Zieloperand in Code-/Datensegment ? */
+
+ ChkSingleSpace(SegCode,EffSeg,MomSegment);
+ ChkSingleSpace(SegXData,EffSeg,MomSegment);
+ ChkSingleSpace(SegData,EffSeg,MomSegment);
+END
+
+ static void DecodeAdr(char *Asc)
+BEGIN
+#define RegCnt 7
+ static char *Reg16Names[RegCnt+1]=
+ {"AX","CX","DX","BX","SP","BP","SI","DI"};
+ static char *Reg8Names[RegCnt+1]=
+ {"AL","CL","DL","BL","AH","CH","DH","BH"};
+ static Byte RMCodes[8]={11,12,21,22,1,2,20,10};
+
+ int RegZ,z;
+ Boolean IsImm;
+ ShortInt IndexBuf,BaseBuf;
+ Byte SumBuf;
+ LongInt DispAcc,DispSum;
+ char *p,*p1,*p2;
+ Boolean HasAdr;
+ Boolean OK,OldNegFlag,NegFlag;
+ String AdrPart,AddPart;
+ ShortInt SegBuffer;
+ Byte MomSegment;
+ ShortInt FoundSize;
+
+ AdrType=TypeNone; AdrCnt=0;
+ SegBuffer=(-1); MomSegment=0;
+
+ for (RegZ=0; RegZ<=RegCnt; RegZ++)
+ BEGIN
+ if (strcasecmp(Asc,Reg16Names[RegZ])==0)
+ BEGIN
+ AdrType=TypeReg16; AdrMode=RegZ;
+ ChkOpSize(1);
+ return;
+ END
+ if (strcasecmp(Asc,Reg8Names[RegZ])==0)
+ BEGIN
+ AdrType=TypeReg8; AdrMode=RegZ;
+ ChkOpSize(0);
+ return;
+ END
+ END
+
+ for (RegZ=0; RegZ<=SegRegCnt; RegZ++)
+ if (strcasecmp(Asc,SegRegNames[RegZ])==0)
+ BEGIN
+ AdrType=TypeRegSeg; AdrMode=RegZ;
+ ChkOpSize(1);
+ return;
+ END
+
+ if (FPUAvail)
+ BEGIN
+ if (strcasecmp(Asc,"ST")==0)
+ BEGIN
+ AdrType=TypeFReg; AdrMode=0;
+ ChkOpSize(4);
+ return;
+ END
+
+ if ((strlen(Asc)>4) AND (strncasecmp(Asc,"ST(",3)==0) AND (Asc[strlen(Asc)-1]==')'))
+ BEGIN
+ Asc[strlen(Asc)-1]='\0';
+ AdrMode=EvalIntExpression(Asc+3,UInt3,&OK);
+ if (OK)
+ BEGIN
+ AdrType=TypeFReg;
+ ChkOpSize(4);
+ END
+ return;
+ END
+ END
+
+ IsImm=True;
+ IndexBuf=0; BaseBuf=0;
+ DispAcc=0; FoundSize=(-1);
+
+ if (strncasecmp(Asc,"WORD PTR",8)==0)
+ BEGIN
+ strcpy(Asc,Asc+8); FoundSize=1; IsImm=False;
+ KillBlanks(Asc);
+ END
+ else if (strncasecmp(Asc,"BYTE PTR",8)==0)
+ BEGIN
+ strcpy(Asc,Asc+8); FoundSize=0; IsImm=False;
+ KillBlanks(Asc);
+ END
+ else if (strncasecmp(Asc,"DWORD PTR",9)==0)
+ BEGIN
+ strcpy(Asc,Asc+9); FoundSize=2; IsImm=False;
+ KillBlanks(Asc);
+ END
+ else if (strncasecmp(Asc,"QWORD PTR",9)==0)
+ BEGIN
+ strcpy(Asc,Asc+9); FoundSize=3; IsImm=False;
+ KillBlanks(Asc);
+ END
+ else if (strncasecmp(Asc,"TBYTE PTR",9)==0)
+ BEGIN
+ strcpy(Asc,Asc+9); FoundSize=4; IsImm=False;
+ KillBlanks(Asc);
+ END
+
+ if ((strlen(Asc)>2) AND (Asc[2]==':'))
+ BEGIN
+ strncpy(AddPart,Asc,2); AddPart[2]='\0';
+ for (z=0; z<=SegRegCnt; z++)
+ if (strcasecmp(AddPart,SegRegNames[z])==0)
+ BEGIN
+ strcpy(Asc,Asc+3); SegBuffer=z;
+ AddPrefix(SegRegPrefixes[SegBuffer]);
+ END
+ END
+
+ do
+ BEGIN
+ p=QuotPos(Asc,'['); HasAdr=(p!=Nil);
+
+
+ if (p!=Asc)
+ BEGIN
+ FirstPassUnknown=False; if (p!=Nil) *p='\0';
+ DispAcc+=EvalIntExpression(Asc,Int16,&OK);
+ if (NOT OK) return;
+ UnknownFlag=UnknownFlag OR FirstPassUnknown;
+ MomSegment|=TypeFlag;
+ if (FoundSize==-1) FoundSize=SizeFlag;
+ if (p==Nil) *Asc='\0';
+ else
+ BEGIN
+ *p='['; strcpy(Asc,p);
+ END
+ END
+
+ if (HasAdr)
+ BEGIN
+ IsImm=False;
+
+ p=RQuotPos(Asc,']'); if (p==Nil)
+ BEGIN
+ WrError(1300); return;
+ END
+
+ *p='\0'; strmaxcpy(AdrPart,Asc+1,255); strcpy(Asc,p+1);
+ OldNegFlag=False;
+
+ do
+ BEGIN
+ NegFlag=False;
+ p1=QuotPos(AdrPart,'+'); p2=QuotPos(AdrPart,'-');
+ if (((p1>p2) OR (p1==Nil)) AND (p2!=Nil))
+ BEGIN
+ p=p2; NegFlag=True;
+ END
+ else p=p1;
+
+ if (p==Nil)
+ BEGIN
+ strcpy(AddPart,AdrPart); *AdrPart='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strcpy(AddPart,AdrPart); strcpy(AdrPart,p+1);
+ END
+
+ if (strcasecmp(AddPart,"BX")==0)
+ BEGIN
+ if ((OldNegFlag) OR (BaseBuf!=0)) return; else BaseBuf=1;
+ END
+ else if (strcasecmp(AddPart,"BP")==0)
+ BEGIN
+ if ((OldNegFlag) OR (BaseBuf!=0)) return; else BaseBuf=2;
+ END
+ else if (strcasecmp(AddPart,"SI")==0)
+ BEGIN
+ if ((OldNegFlag) OR (IndexBuf!=0)) return; else IndexBuf=1;
+ END
+ else if (strcasecmp(AddPart,"DI")==0)
+ BEGIN
+ if ((OldNegFlag) OR (IndexBuf!=0)) return; else IndexBuf=2;
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ DispSum=EvalIntExpression(AddPart,Int16,&OK);
+ if (NOT OK) return;
+ UnknownFlag=UnknownFlag OR FirstPassUnknown;
+ if (OldNegFlag) DispAcc-=DispSum; else DispAcc+=DispSum;
+ MomSegment|=TypeFlag;
+ if (FoundSize==-1) FoundSize=SizeFlag;
+ END
+ OldNegFlag=NegFlag;
+ END
+ while (*AdrPart!='\0');
+ END
+ END
+ while (*Asc!='\0');
+
+ SumBuf=BaseBuf*10+IndexBuf;
+
+ /* welches Segment effektiv benutzt ? */
+
+ if (SegBuffer==-1) SegBuffer=(BaseBuf==2) ? 2 : 3;
+
+ /* nur Displacement */
+
+ if (SumBuf==0)
+
+ /* immediate */
+
+ if (IsImm)
+ BEGIN
+ if (((UnknownFlag) AND (OpSize==0)) OR (MinOneIs0())) DispAcc&=0xff;
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1132); break;
+ case 0:
+ if ((DispAcc<-128) OR (DispAcc>255)) WrError(1320);
+ else
+ BEGIN
+ AdrType=TypeImm; AdrVals[0]=DispAcc & 0xff; AdrCnt=1;
+ END
+ break;
+ case 1:
+ AdrType=TypeImm;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc); AdrCnt=2;
+ break;
+ END
+ END
+
+ /* absolut */
+
+ else
+ BEGIN
+ AdrType=TypeMem; AdrMode=0x06;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc); AdrCnt=2;
+ if (FoundSize!=-1) ChkOpSize(FoundSize);
+ ChkSpaces(SegBuffer,MomSegment);
+ END
+
+ /* kombiniert */
+
+ else
+ BEGIN
+ AdrType=TypeMem;
+ for (z=0; z<8; z++)
+ if (SumBuf==RMCodes[z]) AdrMode=z;
+ if (DispAcc==0)
+ BEGIN
+ if (SumBuf==20)
+ BEGIN
+ AdrMode+=0x40; AdrVals[0]=0; AdrCnt=1;
+ END
+ END
+ else if (AbleToSign(DispAcc))
+ BEGIN
+ AdrMode+=0x40;
+ AdrVals[0]=DispAcc & 0xff; AdrCnt=1;
+ END
+ else
+ BEGIN
+ AdrMode+=0x80;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc); AdrCnt=2;
+ END
+ ChkSpaces(SegBuffer,MomSegment);
+ if (FoundSize!=-1) ChkOpSize(FoundSize);
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void DecodeMOV(Word Index)
+BEGIN
+ Byte AdrByte;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ AdrByte=AdrMode;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen++]=0x8a+OpSize;
+ BAsmCode[CodeLen++]=0xc0+(AdrByte << 3)+AdrMode;
+ break;
+ case TypeMem:
+ if ((AdrByte==0) AND (AdrMode==6))
+ BEGIN
+ BAsmCode[CodeLen]=0xa0+OpSize;
+ MoveAdr(1);
+ CodeLen+=1+AdrCnt;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x8a+OpSize;
+ BAsmCode[CodeLen++]=AdrMode+(AdrByte << 3);
+ MoveAdr(0); CodeLen+=AdrCnt;
+ END
+ break;
+ case TypeRegSeg:
+ if (OpSize==0) WrError(1131);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x8c;
+ BAsmCode[CodeLen++]=0xc0+(AdrMode << 3)+AdrByte;
+ END
+ break;
+ case TypeImm:
+ BAsmCode[CodeLen++]=0xb0+(OpSize << 3)+AdrByte;
+ MoveAdr(0); CodeLen+=AdrCnt;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen+1]=AdrMode;
+ MoveAdr(2); AdrByte=AdrCnt;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ if ((AdrMode==0) AND (BAsmCode[CodeLen+1]==6))
+ BEGIN
+ BAsmCode[CodeLen]=0xa2+OpSize;
+ memmove(BAsmCode+CodeLen+1,BAsmCode+CodeLen+2,AdrByte);
+ CodeLen+=1+AdrByte;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0x88+OpSize;
+ BAsmCode[CodeLen+1]+=AdrMode << 3;
+ CodeLen+=2+AdrByte;
+ END
+ break;
+ case TypeRegSeg:
+ BAsmCode[CodeLen]=0x8c;
+ BAsmCode[CodeLen+1]+=AdrMode << 3;
+ CodeLen+=2+AdrByte;
+ break;
+ case TypeImm:
+ BAsmCode[CodeLen]=0xc6+OpSize;
+ MoveAdr(2+AdrByte);
+ CodeLen+=2+AdrByte+AdrCnt;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ case TypeRegSeg:
+ BAsmCode[CodeLen+1]=AdrMode << 3;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg16:
+ BAsmCode[CodeLen++]=0x8e;
+ BAsmCode[CodeLen++]+=0xc0+AdrMode;
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen]=0x8e;
+ BAsmCode[CodeLen+1]+=AdrMode;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeINCDEC(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg16:
+ BAsmCode[CodeLen]=0x40+AdrMode+Index;
+ CodeLen++;
+ break;
+ case TypeReg8:
+ BAsmCode[CodeLen]=0xfe;
+ BAsmCode[CodeLen+1]=0xc0+AdrMode+Index;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ MinOneIs0();
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xfe + OpSize; /* ANSI :-0 */
+ BAsmCode[CodeLen+1]=AdrMode+Index;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeINT(Word Index)
+BEGIN
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[CodeLen+1]=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ if (BAsmCode[1]==3) BAsmCode[CodeLen++]=0xcc;
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xcd; CodeLen+=2;
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeINOUT(Word Index)
+BEGIN
+ Boolean OK;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (Index!=0)
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ if (AdrMode!=0) WrError(1350);
+ else if (strcasecmp(ArgStr[2],"DX")==0)
+ BAsmCode[CodeLen++]=0xec+OpSize+Index;
+ else
+ BEGIN
+ BAsmCode[CodeLen+1]=EvalIntExpression(ArgStr[2],UInt8,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegIO);
+ BAsmCode[CodeLen]=0xe4+OpSize+Index;
+ CodeLen+=2;
+ END
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeCALLJMP(Word Index)
+BEGIN
+ Byte AdrByte;
+ Word AdrWord;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if (strncmp(ArgStr[1],"SHORT ",6)==0)
+ BEGIN
+ AdrByte=2; strcpy(ArgStr[1],ArgStr[1]+6); KillPrefBlanks(ArgStr[1]);
+ END
+ else if ((strncmp(ArgStr[1],"LONG ",5)==0) OR (strncmp(ArgStr[1],"NEAR ",5)==0))
+ BEGIN
+ AdrByte=1; strcpy(ArgStr[1],ArgStr[1]+5); KillPrefBlanks(ArgStr[1]);
+ END
+ else AdrByte=0;
+ OK=True;
+ if (Index==0)
+ if (AdrByte==2)
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else AdrByte=1;
+
+ if (OK)
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg16:
+ BAsmCode[0]=0xff;
+ BAsmCode[1]=0xd0+AdrMode+(Index<<4);
+ CodeLen=2;
+ break;
+ case TypeMem:
+ BAsmCode[0]=0xff;
+ BAsmCode[1]=AdrMode+0x10+(Index<<4);
+ MoveAdr(2);
+ CodeLen=2+AdrCnt;
+ break;
+ case TypeImm:
+ ChkSpace(SegCode);
+ AdrWord=(((Word) AdrVals[1]) << 8)+AdrVals[0];
+ if ((AdrByte==2) OR ((AdrByte==0) AND (AbleToSign(AdrWord-EProgCounter()-2))))
+ BEGIN
+ AdrWord-=EProgCounter()+2;
+ if (NOT AbleToSign(AdrWord)) WrError(1330);
+ else
+ BEGIN
+ BAsmCode[0]=0xeb;
+ BAsmCode[1]=Lo(AdrWord);
+ CodeLen=2;
+ END
+ END
+ else
+ BEGIN
+ AdrWord-=EProgCounter()+3;
+ ChkSpace(SegCode);
+ BAsmCode[0]=0xe8+Index;
+ BAsmCode[1]=Lo(AdrWord);
+ BAsmCode[2]=Hi(AdrWord);
+ CodeLen=3;
+ AdrWord++;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodePUSHPOP(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg16:
+ BAsmCode[CodeLen]=0x50+AdrMode+(Index<<3);
+ CodeLen++;
+ break;
+ case TypeRegSeg:
+ BAsmCode[CodeLen]=0x06+(AdrMode << 3)+Index;
+ CodeLen++;
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen]=0x8f; BAsmCode[CodeLen+1]=AdrMode;
+ if (Index==0)
+ BEGIN
+ BAsmCode[CodeLen]+=0x70;
+ BAsmCode[CodeLen+1]+=0x30;
+ END
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ break;
+ case TypeImm:
+ if (MomCPU<CPU80186) WrError(1500);
+ else if (Index==1) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0x68;
+ BAsmCode[CodeLen+1]=AdrVals[0];
+ if (Sgn(AdrVals[0])==AdrVals[1])
+ BEGIN
+ BAsmCode[CodeLen]+=2; CodeLen+=2;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen+2]=AdrVals[1]; CodeLen+=3;
+ END
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeNOTNEG(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ MinOneIs0();
+ BAsmCode[CodeLen]=0xf6+OpSize;
+ BAsmCode[CodeLen+1]=0x10+Index;
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen+1]+=0xc0+AdrMode;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ BAsmCode[CodeLen+1]+=AdrMode;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeRET(Word Index)
+BEGIN
+ Word AdrWord;
+ Boolean OK;
+
+ if (ArgCnt>1) WrError(1110);
+ else if (ArgCnt==0)
+ BAsmCode[CodeLen++]=0xc3+Index;
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[CodeLen++]=0xc2+Index;
+ BAsmCode[CodeLen++]=Lo(AdrWord);
+ BAsmCode[CodeLen++]=Hi(AdrWord);
+ END
+ END
+END
+
+ static void DecodeTEST(Word Index)
+BEGIN
+ Byte AdrByte;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen+1]=(AdrMode << 3);
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen+1]+=0xc0+AdrMode;
+ BAsmCode[CodeLen]=0x84+OpSize;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen+1]+=AdrMode;
+ BAsmCode[CodeLen]=0x84+OpSize;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ break;
+ case TypeImm:
+ if (((BAsmCode[CodeLen+1] >> 3) & 7)==0)
+ BEGIN
+ BAsmCode[CodeLen]=0xa8+OpSize;
+ MoveAdr(1);
+ CodeLen+=1+AdrCnt;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=OpSize+0xf6;
+ BAsmCode[CodeLen+1]=(BAsmCode[CodeLen+1] >> 3)+0xc0;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen+1]=AdrMode;
+ AdrByte=AdrCnt; MoveAdr(2);
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen]=0x84+OpSize;
+ BAsmCode[CodeLen+1]+=(AdrMode << 3);
+ CodeLen+=2+AdrByte;
+ break;
+ case TypeImm:
+ BAsmCode[CodeLen]=OpSize+0xf6;
+ MoveAdr(2+AdrByte);
+ CodeLen+=2+AdrCnt+AdrByte;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeXCHG(Word Index)
+BEGIN
+ Byte AdrByte;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ AdrByte=AdrMode;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ if ((OpSize==1) AND ((AdrMode==0) OR (AdrByte==0)))
+ BEGIN
+ BAsmCode[CodeLen]=0x90+AdrMode+AdrByte;
+ CodeLen++;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0x86+OpSize;
+ BAsmCode[CodeLen+1]=AdrMode+0xc0+(AdrByte << 3);
+ CodeLen+=2;
+ END
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen]=0x86+OpSize;
+ BAsmCode[CodeLen+1]=AdrMode+(AdrByte << 3);
+ MoveAdr(2);
+ CodeLen+=AdrCnt+2;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen+1]=AdrMode;
+ MoveAdr(2); AdrByte=AdrCnt;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen]=0x86+OpSize;
+ BAsmCode[CodeLen+1]+=(AdrMode << 3);
+ CodeLen+=AdrByte+2;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeCALLJMPF(Word Index)
+BEGIN
+ char *p;
+ Word AdrWord;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ p=QuotPos(ArgStr[1],':');
+ if (p==Nil)
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ BAsmCode[CodeLen]=0xff;
+ BAsmCode[CodeLen+1]=AdrMode+0x18+Index;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ else
+ BEGIN
+ *p='\0';
+ AdrWord=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[CodeLen+3]=Lo(AdrWord);
+ BAsmCode[CodeLen+4]=Hi(AdrWord);
+ AdrWord=EvalIntExpression(p+1,UInt16,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[CodeLen+1]=Lo(AdrWord);
+ BAsmCode[CodeLen+2]=Hi(AdrWord);
+ BAsmCode[CodeLen]=0x9a+Index;
+ CodeLen+=5;
+ END
+ END
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeENTER(Word Index)
+BEGIN
+ Word AdrWord;
+ Boolean OK;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80186) WrError(1500);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[CodeLen+1]=Lo(AdrWord);
+ BAsmCode[CodeLen+2]=Hi(AdrWord);
+ BAsmCode[CodeLen+3]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[CodeLen]=0xc8; CodeLen+=4;
+ END
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *FixedZ=FixedOrders+Index;
+
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<FixedZ->MinCPU) WrError(1500);
+ else PutCode(FixedZ->Code);
+ AddPrefixes();
+END
+
+ static void DecodeALU2(Word Index)
+BEGIN
+ Byte AdrByte;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen+1]=AdrMode << 3;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen+1]+=0xc0+AdrMode;
+ BAsmCode[CodeLen]=(Index << 3)+2+OpSize;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen+1]+=AdrMode;
+ BAsmCode[CodeLen]=(Index << 3)+2+OpSize;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ break;
+ case TypeImm:
+ if (((BAsmCode[CodeLen+1] >> 3) & 7)==0)
+ BEGIN
+ BAsmCode[CodeLen]=(Index << 3)+4+OpSize;
+ MoveAdr(1);
+ CodeLen+=1+AdrCnt;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=OpSize+0x80;
+ if ((OpSize==1) AND (Sgn(AdrVals[0])==AdrVals[1]))
+ BEGIN
+ AdrCnt=1; BAsmCode[CodeLen]+=2;
+ END
+ BAsmCode[CodeLen+1]=(BAsmCode[CodeLen+1] >> 3)+0xc0+(Index << 3);
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen+1]=AdrMode;
+ AdrByte=AdrCnt; MoveAdr(2);
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen]=(Index << 3)+OpSize;
+ BAsmCode[CodeLen+1]+=(AdrMode << 3);
+ CodeLen+=2+AdrByte;
+ break;
+ case TypeImm:
+ BAsmCode[CodeLen]=OpSize+0x80;
+ if ((OpSize==1) AND (Sgn(AdrVals[0])==AdrVals[1]))
+ BEGIN
+ AdrCnt=1; BAsmCode[CodeLen]+=2;
+ END
+ BAsmCode[CodeLen+1]+=(Index << 3);
+ MoveAdr(2+AdrByte);
+ CodeLen+=2+AdrCnt+AdrByte;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes();
+END
+
+ static void DecodeRel(Word Index)
+BEGIN
+ FixedOrder *RelZ=RelOrders+Index;
+ Word AdrWord;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<RelZ->MinCPU) WrError(1500);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+ AdrWord-=EProgCounter()+2;
+ if (Hi(RelZ->Code)!=0) AdrWord--;
+ if ((AdrWord>=0x80) AND (AdrWord<0xff80) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ PutCode(RelZ->Code); BAsmCode[CodeLen++]=Lo(AdrWord);
+ END
+ END
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].MinCPU=NMin;
+ FixedOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
+END
+
+ static void AddFPUFixed(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=FPUFixedOrderCnt) exit(255);
+ FPUFixedOrders[InstrZ].Name=NName;
+ FPUFixedOrders[InstrZ].MinCPU=NMin;
+ FPUFixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddFPUSt(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=FPUStOrderCnt) exit(255);
+ FPUStOrders[InstrZ].Name=NName;
+ FPUStOrders[InstrZ].MinCPU=NMin;
+ FPUStOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddFPU16(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=FPU16OrderCnt) exit(255);
+ FPU16Orders[InstrZ].Name=NName;
+ FPU16Orders[InstrZ].MinCPU=NMin;
+ FPU16Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddString(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=StringOrderCnt) exit(255);
+ StringOrders[InstrZ].Name=NName;
+ StringOrders[InstrZ].MinCPU=NMin;
+ StringOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRept(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=ReptOrderCnt) exit(255);
+ ReptOrders[InstrZ].Name=NName;
+ ReptOrders[InstrZ].MinCPU=NMin;
+ ReptOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRel(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ].MinCPU=NMin;
+ RelOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeRel);
+END
+
+ static void AddModReg(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=ModRegOrderCnt) exit(255);
+ ModRegOrders[InstrZ].Name=NName;
+ ModRegOrders[InstrZ].MinCPU=NMin;
+ ModRegOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddShift(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=ShiftOrderCnt) exit(255);
+ ShiftOrders[InstrZ].Name=NName;
+ ShiftOrders[InstrZ].MinCPU=NMin;
+ ShiftOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddReg16(char *NName, CPUVar NMin, Word NCode, Byte NAdd)
+BEGIN
+ if (InstrZ>=Reg16OrderCnt) exit(255);
+ Reg16Orders[InstrZ].Name=NName;
+ Reg16Orders[InstrZ].MinCPU=NMin;
+ Reg16Orders[InstrZ].Code=NCode;
+ Reg16Orders[InstrZ++].Add=NAdd;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(201);
+ AddInstTable(InstTable,"MOV" ,0,DecodeMOV);
+ AddInstTable(InstTable,"INC" ,0,DecodeINCDEC);
+ AddInstTable(InstTable,"DEC" ,8,DecodeINCDEC);
+ AddInstTable(InstTable,"INT" ,0,DecodeINT);
+ AddInstTable(InstTable,"IN" ,0,DecodeINOUT);
+ AddInstTable(InstTable,"OUT" ,2,DecodeINOUT);
+ AddInstTable(InstTable,"CALL" ,0,DecodeCALLJMP);
+ AddInstTable(InstTable,"JMP" ,1,DecodeCALLJMP);
+ AddInstTable(InstTable,"PUSH" ,0,DecodePUSHPOP);
+ AddInstTable(InstTable,"POP" ,1,DecodePUSHPOP);
+ AddInstTable(InstTable,"NOT" ,0,DecodeNOTNEG);
+ AddInstTable(InstTable,"NEG" ,8,DecodeNOTNEG);
+ AddInstTable(InstTable,"RET" ,0,DecodeRET);
+ AddInstTable(InstTable,"RETF" ,8,DecodeRET);
+ AddInstTable(InstTable,"TEST" ,0,DecodeTEST);
+ AddInstTable(InstTable,"XCHG" ,0,DecodeXCHG);
+ AddInstTable(InstTable,"CALLF",16,DecodeCALLJMPF);
+ AddInstTable(InstTable,"JMPF" ,0,DecodeCALLJMPF);
+ AddInstTable(InstTable,"ENTER",0,DecodeENTER);
+
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("AAA", CPU8086, 0x0037); AddFixed("AAS", CPU8086, 0x003f);
+ AddFixed("AAM", CPU8086, 0xd40a); AddFixed("AAD", CPU8086, 0xd50a);
+ AddFixed("CBW", CPU8086, 0x0098); AddFixed("CLC", CPU8086, 0x00f8);
+ AddFixed("CLD", CPU8086, 0x00fc); AddFixed("CLI", CPU8086, 0x00fa);
+ AddFixed("CMC", CPU8086, 0x00f5); AddFixed("CWD", CPU8086, 0x0099);
+ AddFixed("DAA", CPU8086, 0x0027); AddFixed("DAS", CPU8086, 0x002f);
+ AddFixed("HLT", CPU8086, 0x00f4); AddFixed("INTO", CPU8086, 0x00ce);
+ AddFixed("IRET", CPU8086, 0x00cf); AddFixed("LAHF", CPU8086, 0x009f);
+ AddFixed("LOCK", CPU8086, 0x00f0); AddFixed("NOP", CPU8086, 0x0090);
+ AddFixed("POPF", CPU8086, 0x009d); AddFixed("PUSHF", CPU8086, 0x009c);
+ AddFixed("SAHF", CPU8086, 0x009e); AddFixed("STC", CPU8086, 0x00f9);
+ AddFixed("STD", CPU8086, 0x00fd); AddFixed("STI", CPU8086, 0x00fb);
+ AddFixed("WAIT", CPU8086, 0x009b); AddFixed("XLAT", CPU8086, 0x00d7);
+ AddFixed("LEAVE", CPU80186, 0x00c9); AddFixed("PUSHA", CPU80186, 0x0060);
+ AddFixed("POPA", CPU80186, 0x0061); AddFixed("ADD4S", CPUV30, 0x0f20);
+ AddFixed("SUB4S", CPUV30, 0x0f22); AddFixed("CMP4S", CPUV30, 0x0f26);
+ AddFixed("STOP", CPUV35, 0x0f9e); AddFixed("RETRBI",CPUV35, 0x0f91);
+ AddFixed("FINT", CPUV35, 0x0f92); AddFixed("MOVSPA",CPUV35, 0x0f25);
+ AddFixed("SEGES", CPU8086, 0x0026); AddFixed("SEGCS", CPU8086, 0x002e);
+ AddFixed("SEGSS", CPU8086, 0x0036); AddFixed("SEGDS", CPU8086, 0x003e);
+ AddFixed("FWAIT", CPU8086, 0x009b);
+
+ FPUFixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FPUFixedOrderCnt); InstrZ=0;
+ AddFPUFixed("FCOMPP", CPU8086, 0xded9); AddFPUFixed("FTST", CPU8086, 0xd9e4);
+ AddFPUFixed("FXAM", CPU8086, 0xd9e5); AddFPUFixed("FLDZ", CPU8086, 0xd9ee);
+ AddFPUFixed("FLD1", CPU8086, 0xd9e8); AddFPUFixed("FLDPI", CPU8086, 0xd9eb);
+ AddFPUFixed("FLDL2T", CPU8086, 0xd9e9); AddFPUFixed("FLDL2E", CPU8086, 0xd9ea);
+ AddFPUFixed("FLDLG2", CPU8086, 0xd9ec); AddFPUFixed("FLDLN2", CPU8086, 0xd9ed);
+ AddFPUFixed("FSQRT", CPU8086, 0xd9fa); AddFPUFixed("FSCALE", CPU8086, 0xd9fd);
+ AddFPUFixed("FPREM", CPU8086, 0xd9f8); AddFPUFixed("FRNDINT",CPU8086, 0xd9fc);
+ AddFPUFixed("FXTRACT",CPU8086, 0xd9f4); AddFPUFixed("FABS", CPU8086, 0xd9e1);
+ AddFPUFixed("FCHS", CPU8086, 0xd9e0); AddFPUFixed("FPTAN", CPU8086, 0xd9f2);
+ AddFPUFixed("FPATAN", CPU8086, 0xd9f3); AddFPUFixed("F2XM1", CPU8086, 0xd9f0);
+ AddFPUFixed("FYL2X", CPU8086, 0xd9f1); AddFPUFixed("FYL2XP1",CPU8086, 0xd9f9);
+ AddFPUFixed("FINIT", CPU8086, 0xdbe3); AddFPUFixed("FENI", CPU8086, 0xdbe0);
+ AddFPUFixed("FDISI", CPU8086, 0xdbe1); AddFPUFixed("FCLEX", CPU8086, 0xdbe2);
+ AddFPUFixed("FINCSTP",CPU8086, 0xd9f7); AddFPUFixed("FDECSTP",CPU8086, 0xd9f6);
+ AddFPUFixed("FNOP", CPU8086, 0xd9d0);
+
+ FPUStOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FPUStOrderCnt); InstrZ=0;
+ AddFPUSt("FXCH", CPU8086, 0xd9c8);
+ AddFPUSt("FFREE", CPU8086, 0xddc0);
+
+ FPU16Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*FPU16OrderCnt); InstrZ=0;
+ AddFPU16("FLDCW", CPU8086, 0xd928);
+ AddFPU16("FSTCW", CPU8086, 0xd938);
+ AddFPU16("FSTSW", CPU8086, 0xdd38);
+ AddFPU16("FSTENV", CPU8086, 0xd930);
+ AddFPU16("FLDENV", CPU8086, 0xd920);
+
+ StringOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*StringOrderCnt); InstrZ=0;
+ AddString("CMPSB", CPU8086, 0x00a6);
+ AddString("CMPSW", CPU8086, 0x00a7);
+ AddString("LODSB", CPU8086, 0x00ac);
+ AddString("LODSW", CPU8086, 0x00ad);
+ AddString("MOVSB", CPU8086, 0x00a4);
+ AddString("MOVSW", CPU8086, 0x00a5);
+ AddString("SCASB", CPU8086, 0x00ae);
+ AddString("SCASW", CPU8086, 0x00af);
+ AddString("STOSB", CPU8086, 0x00aa);
+ AddString("STOSW", CPU8086, 0x00ab);
+ AddString("INSB", CPU80186, 0x006c);
+ AddString("INSW", CPU80186, 0x006d);
+ AddString("OUTSB", CPU80186, 0x006e);
+ AddString("OUTSW", CPU80186, 0x006f);
+
+ ReptOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ReptOrderCnt); InstrZ=0;
+ AddRept("REP", CPU8086, 0x00f3);
+ AddRept("REPE", CPU8086, 0x00f3);
+ AddRept("REPZ", CPU8086, 0x00f3);
+ AddRept("REPNE", CPU8086, 0x00f2);
+ AddRept("REPNZ", CPU8086, 0x00f2);
+ AddRept("REPC", CPUV30, 0x0065);
+ AddRept("REPNC", CPUV30, 0x0064);
+
+ RelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("JA", CPU8086, 0x0077); AddRel("JNBE", CPU8086, 0x0077);
+ AddRel("JAE", CPU8086, 0x0073); AddRel("JNB", CPU8086, 0x0073);
+ AddRel("JB", CPU8086, 0x0072); AddRel("JNAE", CPU8086, 0x0072);
+ AddRel("JBE", CPU8086, 0x0076); AddRel("JNA", CPU8086, 0x0076);
+ AddRel("JC", CPU8086, 0x0072); AddRel("JCXZ", CPU8086, 0x00e3);
+ AddRel("JE", CPU8086, 0x0074); AddRel("JZ", CPU8086, 0x0074);
+ AddRel("JG", CPU8086, 0x007f); AddRel("JNLE", CPU8086, 0x007f);
+ AddRel("JGE", CPU8086, 0x007d); AddRel("JNL", CPU8086, 0x007d);
+ AddRel("JL", CPU8086, 0x007c); AddRel("JNGE", CPU8086, 0x007c);
+ AddRel("JLE", CPU8086, 0x007e); AddRel("JNG", CPU8086, 0x007e);
+ AddRel("JNC", CPU8086, 0x0073); AddRel("JNE", CPU8086, 0x0075);
+ AddRel("JNZ", CPU8086, 0x0075); AddRel("JNO", CPU8086, 0x0071);
+ AddRel("JNS", CPU8086, 0x0079); AddRel("JNP", CPU8086, 0x007b);
+ AddRel("JPO", CPU8086, 0x007b); AddRel("JO", CPU8086, 0x0070);
+ AddRel("JP", CPU8086, 0x007a); AddRel("JPE", CPU8086, 0x007a);
+ AddRel("JS", CPU8086, 0x0078); AddRel("LOOP", CPU8086, 0x00e2);
+ AddRel("LOOPE", CPU8086, 0x00e1); AddRel("LOOPZ", CPU8086, 0x00e1);
+ AddRel("LOOPNE",CPU8086, 0x00e0); AddRel("LOOPNZ",CPU8086, 0x00e0);
+
+ ModRegOrders=(FixedOrder *) malloc (sizeof(FixedOrder)*ModRegOrderCnt); InstrZ=0;
+ AddModReg("LDS", CPU8086, 0x00c5);
+ AddModReg("LEA", CPU8086, 0x008d);
+ AddModReg("LES", CPU8086, 0x00c4);
+ AddModReg("BOUND", CPU80186, 0x0062);
+
+ ShiftOrders=(FixedOrder *) malloc (sizeof(FixedOrder)*ShiftOrderCnt); InstrZ=0;
+ AddShift("SHL", CPU8086, 4); AddShift("SAL", CPU8086, 4);
+ AddShift("SHR", CPU8086, 5); AddShift("SAR", CPU8086, 7);
+ AddShift("ROL", CPU8086, 0); AddShift("ROR", CPU8086, 1);
+ AddShift("RCL", CPU8086, 2); AddShift("RCR", CPU8086, 3);
+
+ Reg16Orders=(AddOrder *) malloc(sizeof(AddOrder)*Reg16OrderCnt); InstrZ=0;
+ AddReg16("BRKCS", CPUV35, 0x0f2d, 0xc0);
+ AddReg16("TSKSW", CPUV35, 0x0f94, 0xf8);
+ AddReg16("MOVSPB",CPUV35, 0x0f95, 0xf8);
+
+ InstrZ=0;
+ AddInstTable(InstTable,"ADD",InstrZ++,DecodeALU2);
+ AddInstTable(InstTable,"OR" ,InstrZ++,DecodeALU2);
+ AddInstTable(InstTable,"ADC",InstrZ++,DecodeALU2);
+ AddInstTable(InstTable,"SBB",InstrZ++,DecodeALU2);
+ AddInstTable(InstTable,"AND",InstrZ++,DecodeALU2);
+ AddInstTable(InstTable,"SUB",InstrZ++,DecodeALU2);
+ AddInstTable(InstTable,"XOR",InstrZ++,DecodeALU2);
+ AddInstTable(InstTable,"CMP",InstrZ++,DecodeALU2);
+
+ MulOrders=(char **) malloc(sizeof(char *)*MulOrderCnt); InstrZ=0;
+ MulOrders[InstrZ++]="MUL"; MulOrders[InstrZ++]="IMUL";
+ MulOrders[InstrZ++]="DIV"; MulOrders[InstrZ++]="IDIV";
+
+ Bit1Orders=(char **) malloc(sizeof(char *)*Bit1OrderCnt); InstrZ=0;
+ Bit1Orders[InstrZ++]="TEST1";
+ Bit1Orders[InstrZ++]="CLR1";
+ Bit1Orders[InstrZ++]="SET1";
+ Bit1Orders[InstrZ++]="NOT1";
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+ free(FPUFixedOrders);
+ free(FPUStOrders);
+ free(FPU16Orders);
+ free(StringOrders);
+ free(ReptOrders);
+ free(RelOrders);
+ free(ModRegOrders);
+ free(ShiftOrders);
+ free(Reg16Orders);
+ free(MulOrders);
+ free(Bit1Orders);
+END
+
+ static Boolean FMemo(char *Name)
+BEGIN
+ String tmp;
+
+ if (Memo(Name))
+ BEGIN
+ AddPrefix(0x9b); return True;
+ END
+ else
+ BEGIN
+ strmaxcpy(tmp,Name,255);
+ memmove(tmp+2,tmp+1,strlen(tmp));
+ tmp[1]='N';
+ return Memo(tmp);
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Boolean OK;
+ int z,z2,z3;
+ char *p;
+ String SegPart,ValPart;
+
+ if (Memo("PORT"))
+ BEGIN
+ CodeEquate(SegIO,0,0xffff);
+ return True;
+ END
+
+ if (Memo("ASSUME"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z=1; OK=True;
+ while ((z<=ArgCnt) AND (OK))
+ BEGIN
+ OK=False; p=QuotPos(ArgStr[z],':');
+ if (p!=Nil)
+ BEGIN
+ *p='\0'; strmaxcpy(SegPart,ArgStr[z],255); strmaxcpy(ValPart,p+1,255);
+ END
+ else
+ BEGIN
+ strmaxcpy(SegPart,ArgStr[z],255); *ValPart='\0';
+ END
+ z2=0;
+ while ((z2<=SegRegCnt) AND (strcasecmp(SegPart,SegRegNames[z2])!=0)) z2++;
+ if (z2>SegRegCnt) WrXError(1962,SegPart);
+ else
+ BEGIN
+ z3=0;
+ while ((z3<=PCMax) AND (strcasecmp(ValPart,SegNames[z3])!=0)) z3++;
+ if (z3>PCMax) WrXError(1961,ValPart);
+ else if ((z3!=SegCode) AND (z3!=SegData) AND (z3!=SegXData) AND (z3!=SegNone)) WrError(1960);
+ else
+ BEGIN
+ SegAssumes[z2]=z3; OK=True;
+ END
+ END
+ z++;
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static Boolean DecodeFPU(void)
+BEGIN
+ int z;
+ Byte OpAdd;
+
+ if (*OpPart!='F') return False;
+ if (NOT FPUAvail) return False;
+
+ for (z=0; z<FPUFixedOrderCnt; z++)
+ if (FMemo(FPUFixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<FPUFixedOrders[z].MinCPU) WrError(1500);
+ else PutCode(FPUFixedOrders[z].Code);
+ return True;
+ END
+
+ for (z=0; z<FPUStOrderCnt; z++)
+ if (FMemo(FPUStOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ if (AdrType==TypeFReg)
+ BEGIN
+ PutCode(FPUStOrders[z].Code); BAsmCode[CodeLen-1]+=AdrMode;
+ END
+ else if (AdrType!=TypeNone) WrError(1350);
+ END
+ return True;
+ END
+
+ if (FMemo("FLD"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ BAsmCode[CodeLen]=0xd9; BAsmCode[CodeLen+1]=0xc0+AdrMode;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=2;
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize<2) WrError(1130);
+ else
+ BEGIN
+ MoveAdr(2);
+ BAsmCode[CodeLen+1]=AdrMode;
+ switch (OpSize)
+ BEGIN
+ case 2: BAsmCode[CodeLen]=0xd9; break;
+ case 3: BAsmCode[CodeLen]=0xdd; break;
+ case 4: BAsmCode[CodeLen]=0xdb; BAsmCode[CodeLen+1]+=0x28; break;
+ END
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if (FMemo("FILD"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=1;
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize<1) OR (OpSize>3)) WrError(1130);
+ else
+ BEGIN
+ MoveAdr(2);
+ BAsmCode[CodeLen+1]=AdrMode;
+ switch (OpSize)
+ BEGIN
+ case 1: BAsmCode[CodeLen]=0xdf; break;
+ case 2: BAsmCode[CodeLen]=0xdb; break;
+ case 3: BAsmCode[CodeLen]=0xdf; BAsmCode[CodeLen+1]+=0x28; break;
+ END
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if (FMemo("FBLD"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=4;
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize!=4) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xdf;
+ MoveAdr(2);
+ BAsmCode[CodeLen+1]=AdrMode+0x20;
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FST")) OR (FMemo("FSTP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ BAsmCode[CodeLen]=0xdd; BAsmCode[CodeLen+1]=0xd0+AdrMode;
+ if (FMemo("FSTP")) BAsmCode[CodeLen+1]+=8;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=2;
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize<2) OR ((OpSize==4) AND (FMemo("FST")))) WrError(1130);
+ else
+ BEGIN
+ MoveAdr(2);
+ BAsmCode[CodeLen+1]=AdrMode+0x10;
+ if (FMemo("FSTP")) BAsmCode[CodeLen+1]+=8;
+ switch (OpSize)
+ BEGIN
+ case 2: BAsmCode[CodeLen]=0xd9; break;
+ case 3: BAsmCode[CodeLen]=0xdd;
+ case 4: BAsmCode[CodeLen]=0xdb; BAsmCode[CodeLen+1]+=0x20; break;
+ END
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FIST")) OR (FMemo("FISTP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=1;
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize<1) OR (OpSize==4) OR ((OpSize==3) AND (FMemo("FIST")))) WrError(1130);
+ else
+ BEGIN
+ MoveAdr(2);
+ BAsmCode[CodeLen+1]=AdrMode+0x10;
+ if (FMemo("FISTP")) BAsmCode[CodeLen+1]+=8;
+ switch (OpSize)
+ BEGIN
+ case 1: BAsmCode[CodeLen]=0xdf; break;
+ case 2: BAsmCode[CodeLen]=0xdb; break;
+ case 3: BAsmCode[CodeLen]=0xdf; BAsmCode[CodeLen+1]=0x20; break;
+ END
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if (FMemo("FBSTP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=1;
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize!=4) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xdf; BAsmCode[CodeLen+1]=AdrMode+0x30;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FCOM")) OR (FMemo("FCOMP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ BAsmCode[CodeLen]=0xd8; BAsmCode[CodeLen+1]=0xd0+AdrMode;
+ if (FMemo("FCOMP")) BAsmCode[CodeLen+1]+=8;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=1;
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=2) AND (OpSize!=3)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=(OpSize==2) ? 0xd8 : 0xdc;
+ BAsmCode[CodeLen+1]=AdrMode+0x10;
+ if (FMemo("FCOMP")) BAsmCode[CodeLen+1]+=8;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FICOM")) OR (FMemo("FICOMP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=1;
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=(OpSize==1) ? 0xde : 0xda;
+ BAsmCode[CodeLen+1]=AdrMode+0x10;
+ if (FMemo("FICOMP")) BAsmCode[CodeLen+1]+=8;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FADD")) OR (FMemo("FMUL")))
+ BEGIN
+ OpAdd=0; if (FMemo("FMUL")) OpAdd+=8;
+ if (ArgCnt==0)
+ BEGIN
+ BAsmCode[CodeLen]=0xde; BAsmCode[CodeLen+1]=0xc1+OpAdd;
+ CodeLen+=2;
+ return True;
+ END
+ if (ArgCnt==1)
+ BEGIN
+ strcpy (ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"ST",255); ArgCnt++;
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]); OpSize=(-1);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ if (AdrMode!=0) /* ST(i) ist Ziel */
+ BEGIN
+ BAsmCode[CodeLen+1]=AdrMode;
+ DecodeAdr(ArgStr[2]);
+ if ((AdrType!=TypeFReg) OR (AdrMode!=0)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xdc; BAsmCode[CodeLen+1]+=0xc0+OpAdd;
+ CodeLen+=2;
+ END
+ END
+ else /* ST ist Ziel */
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ BAsmCode[CodeLen]=0xd8;
+ BAsmCode[CodeLen+1]=0xc0+AdrMode+OpAdd;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=2;
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=2) AND (OpSize!=3)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=(OpSize==2) ? 0xd8 : 0xdc;
+ BAsmCode[CodeLen+1]=AdrMode+OpAdd;
+ MoveAdr(2);
+ CodeLen+=AdrCnt+2;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FIADD")) OR (FMemo("FIMUL")))
+ BEGIN
+ OpAdd=0; if (FMemo("FIIMUL")) OpAdd+=8;
+ if (ArgCnt==1)
+ BEGIN
+ ArgCnt=2; strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"ST",255);
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ if (AdrMode!=0) WrError(1350);
+ else
+ BEGIN
+ OpSize=(-1);
+ DecodeAdr(ArgStr[2]);
+ if ((AdrType!=TypeMem) AND (AdrType!=TypeNone)) WrError(1350);
+ else if (AdrType!=TypeNone)
+ BEGIN
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=1;
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=(OpSize==1) ? 0xde : 0xda;
+ BAsmCode[CodeLen+1]=AdrMode+OpAdd;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END
+ END
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FADDP")) OR (FMemo("FMULP")))
+ BEGIN
+ OpAdd=0; if (FMemo("FMULP")) OpAdd+=8;
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ if (AdrMode!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ if ((AdrType!=TypeFReg) AND (AdrType!=TypeNone)) WrError(1350);
+ else if (AdrType!=TypeNone)
+ BEGIN
+ BAsmCode[CodeLen]=0xde;
+ BAsmCode[CodeLen+1]=0xc0+AdrMode+OpAdd;
+ CodeLen+=2;
+ END
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FSUB")) OR (FMemo("FSUBR")) OR (FMemo("FDIV")) OR (FMemo("FDIVR")))
+ BEGIN
+ OpAdd=0;
+ if ((FMemo("FSUBR")) OR (FMemo("FDIVR"))) OpAdd+=8;
+ if ((FMemo("FDIV")) OR (FMemo("FDIVR"))) OpAdd+=16;
+ if (ArgCnt==0)
+ BEGIN
+ BAsmCode[CodeLen]=0xde; BAsmCode[CodeLen+1]=0xe1+(OpAdd ^ 8);
+ CodeLen+=2;
+ return True;
+ END
+ if (ArgCnt==1)
+ BEGIN
+ strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"ST",255); ArgCnt++;
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]); OpSize=(-1);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ if (AdrMode!=0) /* ST(i) ist Ziel */
+ BEGIN
+ BAsmCode[CodeLen+1]=AdrMode;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ if (AdrMode!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xdc; BAsmCode[CodeLen+1]+=0xe0+(OpAdd ^ 8);
+ CodeLen+=2;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ else /* ST ist Ziel */
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ BAsmCode[CodeLen]=0xd8;
+ BAsmCode[CodeLen+1]=0xe0+AdrMode+OpAdd;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=2;
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=2) AND (OpSize!=3)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=(OpSize==2) ? 0xd8 : 0xdc;
+ BAsmCode[CodeLen+1]=AdrMode+0x20+OpAdd;
+ MoveAdr(2);
+ CodeLen+=AdrCnt+2;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FISUB")) OR (FMemo("FISUBR")) OR (FMemo("FIDIV")) OR (FMemo("FIDIVR")))
+ BEGIN
+ OpAdd=0;
+ if ((FMemo("FISUBR")) OR (Memo("FIDIVR"))) OpAdd+=8;
+ if ((FMemo("FIDIV")) OR (Memo("FIDIVR"))) OpAdd+=16;
+ if (ArgCnt==1)
+ BEGIN
+ ArgCnt=2; strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"ST",255);
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ if (AdrMode!=0) WrError(1350);
+ else
+ BEGIN
+ OpSize=(-1);
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ if ((OpSize==-1) AND (UnknownFlag)) OpSize=1;
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=(OpSize==1) ? 0xde : 0xda;
+ BAsmCode[CodeLen+1]=AdrMode+0x20+OpAdd;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FSUBP")) OR (FMemo("FSUBRP")) OR (FMemo("FDIVP")) OR (FMemo("FDIVRP")))
+ BEGIN
+ OpAdd=0;
+ if ((Memo("FSUBRP")) OR (Memo("FDIVRP"))) OpAdd+=8;
+ if ((Memo("FDIVP")) OR (Memo("FDIVRP"))) OpAdd+=16;
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ if (AdrMode!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeFReg:
+ BAsmCode[CodeLen]=0xde;
+ BAsmCode[CodeLen+1]=0xe0+AdrMode+(OpAdd ^ 8);
+ CodeLen+=2;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ for (z=0; z<FPU16OrderCnt; z++)
+ if (FMemo(FPU16Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ OpSize=1;
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ PutCode(FPU16Orders[z].Code);
+ BAsmCode[CodeLen-1]+=AdrMode;
+ MoveAdr(0);
+ CodeLen+=AdrCnt;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((FMemo("FSAVE")) OR (FMemo("FRSTOR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ BAsmCode[CodeLen]=0xdd; BAsmCode[CodeLen+1]=AdrMode+0x20;
+ if (Memo("FSAVE")) BAsmCode[CodeLen+1]+=0x10;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_86(void)
+BEGIN
+ Boolean OK;
+ Word AdrWord;
+ Byte AdrByte;
+ int z,z2;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1); PrefixLen=0;
+ NoSegCheck=False; UnknownFlag=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* vermischtes */
+
+ if (LookupInstTable(InstTable,OpPart)) return;
+
+ /* Koprozessor */
+
+ if (DecodeFPU())
+ BEGIN
+ AddPrefixes(); return;
+ END
+
+ /* Stringoperationen */
+
+ for (z=0; z<StringOrderCnt; z++)
+ if (Memo(StringOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<StringOrders[z].MinCPU) WrError(1500);
+ else PutCode(StringOrders[z].Code);
+ AddPrefixes(); return;
+ END
+
+ /* mit Wiederholung */
+
+ for (z=0; z<ReptOrderCnt; z++)
+ if (Memo(ReptOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<ReptOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ for (z2=0; z2<StringOrderCnt; z2++)
+ if (strcasecmp(StringOrders[z2].Name,ArgStr[1])==0) break;
+ if (z2>=StringOrderCnt)WrError(1985);
+ else if (MomCPU<StringOrders[z2].MinCPU) WrError(1500);
+ else
+ BEGIN
+ PutCode(ReptOrders[z].Code); PutCode(StringOrders[z2].Code);
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<MulOrderCnt; z++)
+ if Memo(MulOrders[z])
+ BEGIN
+ switch (ArgCnt)
+ BEGIN
+ case 1:
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ BAsmCode[CodeLen]=0xf6+OpSize;
+ BAsmCode[CodeLen+1]=0xe0+(z << 3)+AdrMode;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ MinOneIs0();
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xf6+OpSize;
+ BAsmCode[CodeLen+1]=0x20+(z << 3)+AdrMode;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ case 2:
+ case 3:
+ if (MomCPU<CPU80186) WrError(1500);
+ else if (NOT Memo("IMUL")) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]); ArgCnt++;
+ END
+ BAsmCode[CodeLen]=0x69;
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg16:
+ BAsmCode[CodeLen+1]=(AdrMode << 3);
+ DecodeAdr(ArgStr[2]);
+ if (AdrType==TypeReg16)
+ BEGIN
+ AdrType=TypeMem; AdrMode+=0xc0;
+ END
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ BAsmCode[CodeLen+1]+=AdrMode;
+ MoveAdr(2);
+ AdrWord=EvalIntExpression(ArgStr[3],Int16,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[CodeLen+2+AdrCnt]=Lo(AdrWord);
+ BAsmCode[CodeLen+3+AdrCnt]=Hi(AdrWord);
+ CodeLen+=2+AdrCnt+2;
+ if ((AdrWord>=0xff80) OR (AdrWord<0x80))
+ BEGIN
+ CodeLen--;
+ BAsmCode[CodeLen-AdrCnt-2-1]+=2;
+ END
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ break;
+ default: WrError(1110);
+ END
+ AddPrefixes(); return;
+ END;
+
+ for (z=0; z<ModRegOrderCnt; z++)
+ if (Memo(ModRegOrders[z].Name))
+ BEGIN
+ NoSegCheck=Memo("LEA");
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<ModRegOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg16:
+ OpSize=(Memo("LEA")) ? -1 : 2;
+ AdrByte=(AdrMode << 3);
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeMem:
+ PutCode(ModRegOrders[z].Code);
+ BAsmCode[CodeLen]=AdrByte+AdrMode;
+ MoveAdr(1);
+ CodeLen+=1+AdrCnt;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<ShiftOrderCnt; z++)
+ if (Memo(ShiftOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ MinOneIs0();
+ if (OpSize==-1) WrError(1132);
+ else switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ case TypeReg16:
+ case TypeMem:
+ BAsmCode[CodeLen]=OpSize;
+ BAsmCode[CodeLen+1]=AdrMode+(ShiftOrders[z].Code << 3);
+ if (AdrType!=TypeMem) BAsmCode[CodeLen+1]+=0xc0;
+ MoveAdr(2);
+ if (strcasecmp(ArgStr[2],"CL")==0)
+ BEGIN
+ BAsmCode[CodeLen]+=0xd2;
+ CodeLen+=2+AdrCnt;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen+2+AdrCnt]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ if (BAsmCode[CodeLen+2+AdrCnt]==1)
+ BEGIN
+ BAsmCode[CodeLen]+=0xd0;
+ CodeLen+=2+AdrCnt;
+ END
+ else if (MomCPU<CPU80186) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[CodeLen]+=0xc0;
+ CodeLen+=3+AdrCnt;
+ END
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if ((Memo("ROL4")) OR (Memo("ROR4")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPUV30) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ BAsmCode[CodeLen ]=0x0f;
+ BAsmCode[CodeLen+1]=(Memo("ROL4")) ? 0x28 : 0x2a;
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ BAsmCode[CodeLen+2]=0xc0+AdrMode;
+ CodeLen+=3;
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen+2]=AdrMode;
+ MoveAdr(3);
+ CodeLen+=3+AdrCnt;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<Bit1OrderCnt; z++)
+ if (Memo(Bit1Orders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPUV30) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ if ((AdrType==TypeReg8) OR (AdrType==TypeReg16))
+ BEGIN
+ AdrMode+=0xc0; AdrType=TypeMem;
+ END
+ MinOneIs0();
+ if (OpSize==-1) WrError(1132);
+ else switch (AdrType)
+ BEGIN
+ case TypeMem:
+ BAsmCode[CodeLen ]=0x0f;
+ BAsmCode[CodeLen+1]=0x10+(z << 1)+OpSize;
+ BAsmCode[CodeLen+2]=AdrMode;
+ MoveAdr(3);
+ if (strcasecmp(ArgStr[2],"CL")==0) CodeLen+=3+AdrCnt;
+ else
+ BEGIN
+ BAsmCode[CodeLen+1]+=8;
+ BAsmCode[CodeLen+3+AdrCnt]=EvalIntExpression(ArgStr[2],Int4,&OK);
+ if (OK) CodeLen+=4+AdrCnt;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if ((Memo("INS")) OR (Memo("EXT")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPUV30) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ if (AdrType!=TypeNone)
+ if (AdrType!=TypeReg8) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[CodeLen ]=0x0f;
+ BAsmCode[CodeLen+1]=0x31;
+ if (Memo("EXT")) BAsmCode[CodeLen+1]+=2;
+ BAsmCode[CodeLen+2]=0xc0+AdrMode;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ BAsmCode[CodeLen+2]+=(AdrMode << 3);
+ CodeLen+=3;
+ break;
+ case TypeImm:
+ if (AdrVals[0]>15) WrError(1320);
+ else
+ BEGIN
+ BAsmCode[CodeLen+1]+=8;
+ BAsmCode[CodeLen+3]=AdrVals[1];
+ CodeLen+=4;
+ END
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if (Memo("FPO2"))
+ BEGIN
+ if ((ArgCnt==0) OR (ArgCnt>2)) WrError(1110);
+ else if (MomCPU<CPUV30) WrError(1500);
+ else
+ BEGIN
+ AdrByte=EvalIntExpression(ArgStr[1],Int4,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[CodeLen ]=0x66+(AdrByte >> 3);
+ BAsmCode[CodeLen+1]=(AdrByte & 7) << 3;
+ if (ArgCnt==1)
+ BEGIN
+ BAsmCode[CodeLen+1]+=0xc0;
+ CodeLen+=2;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg8:
+ BAsmCode[CodeLen+1]+=0xc0+AdrMode;
+ CodeLen+=2;
+ break;
+ case TypeMem:
+ BAsmCode[CodeLen+1]+=AdrMode;
+ MoveAdr(2);
+ CodeLen+=2+AdrCnt;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if (Memo("BTCLR"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (MomCPU<CPUV35) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[CodeLen ]=0x0f;
+ BAsmCode[CodeLen+1]=0x9c;
+ BAsmCode[CodeLen+2]=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[CodeLen+3]=EvalIntExpression(ArgStr[2],UInt3,&OK);
+ if (OK)
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[3],Int16,&OK)-(EProgCounter()+5);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrWord>0x7f) AND (AdrWord<0xff80))) WrError(1330);
+ else
+ BEGIN
+ BAsmCode[CodeLen+4]=Lo(AdrWord);
+ CodeLen+=5;
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<Reg16OrderCnt; z++)
+ if (Memo(Reg16Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<Reg16Orders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrType)
+ BEGIN
+ case TypeReg16:
+ PutCode(Reg16Orders[z].Code);
+ BAsmCode[CodeLen++]=Reg16Orders[z].Add+AdrMode;
+ break;
+ default:
+ if (AdrType!=TypeNone) WrError(1350);
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ WrXError(1200,OpPart); return;
+END
+
+ static void InitCode_86(void)
+BEGIN
+ SaveInitProc();
+ SegAssumes[0]=SegNone; /* ASSUME ES:NOTHING */
+ SegAssumes[1]=SegCode; /* ASSUME CS:CODE */
+ SegAssumes[2]=SegNone; /* ASSUME SS:NOTHING */
+ SegAssumes[3]=SegData; /* ASSUME DS:DATA */
+END
+
+ static Boolean IsDef_86(void)
+BEGIN
+ return (Memo("PORT"));
+END
+
+ static void SwitchFrom_86(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_86(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x42; NOPCode=0x90;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegXData)|(1<<SegIO);
+ Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
+ SegLimits[SegCode ] = 0xffff;
+ Grans[SegData ]=1; ListGrans[SegData ]=1; SegInits[SegData ]=0;
+ SegLimits[SegData ] = 0xffff;
+ Grans[SegXData]=1; ListGrans[SegXData]=1; SegInits[SegXData]=0;
+ SegLimits[SegXData] = 0xffff;
+ Grans[SegIO ]=1; ListGrans[SegIO ]=1; SegInits[SegIO ]=0;
+ SegLimits[SegIO ] = 0xffff;
+
+ MakeCode=MakeCode_86; IsDef=IsDef_86;
+ SwitchFrom=SwitchFrom_86; InitFields();
+ AddONOFF("FPU",&FPUAvail,FPUAvailName,False);
+END
+
+ void code86_init(void)
+BEGIN
+ CPU8086 =AddCPU("8086" ,SwitchTo_86);
+ CPU80186=AddCPU("80186",SwitchTo_86);
+ CPUV30 =AddCPU("V30" ,SwitchTo_86);
+ CPUV35 =AddCPU("V35" ,SwitchTo_86);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_86;
+END
diff --git a/code86.h b/code86.h
new file mode 100644
index 0000000..85a9b5d
--- /dev/null
+++ b/code86.h
@@ -0,0 +1,11 @@
+/* code86.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator 8086/V-Serie */
+/* */
+/* Historie: */
+/* */
+/*****************************************************************************/
+
+extern void code86_init(void);
diff --git a/code87c800.c b/code87c800.c
new file mode 100644
index 0000000..8cbfa33
--- /dev/null
+++ b/code87c800.c
@@ -0,0 +1,1316 @@
+/* code87c800.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TLCS-870 */
+/* */
+/* Historie: 29.12.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC umgebaut */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } CondRec;
+
+#define FixedOrderCnt 7
+#define ConditionCnt 12
+#define RegOrderCnt 7
+#define ALUOrderCnt 8
+
+
+#define ModNone (-1)
+#define ModReg8 0
+#define MModReg8 (1 << ModReg8)
+#define ModReg16 1
+#define MModReg16 (1 << ModReg16)
+#define ModImm 2
+#define MModImm (1 << ModImm)
+#define ModAbs 3
+#define MModAbs (1 << ModAbs)
+#define ModMem 4
+#define MModMem (1 << ModMem)
+
+#define AccReg 0
+#define WAReg 0
+
+#define Reg8Cnt 8
+static char *Reg8Names="AWCBEDLH";
+
+static CPUVar CPU87C00,CPU87C20,CPU87C40,CPU87C70;
+static ShortInt OpSize;
+static Byte AdrVals[4];
+static ShortInt AdrType;
+static Byte AdrMode;
+
+static FixedOrder *FixedOrders;
+static CondRec *Conditions;
+static FixedOrder *RegOrders;
+static char **ALUOrders;
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddCond(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ConditionCnt) exit(255);
+ Conditions[InstrZ].Name=NName;
+ Conditions[InstrZ++].Code=NCode;
+END
+
+ static void AddReg(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=RegOrderCnt) exit(255);
+ RegOrders[InstrZ].Name=NName;
+ RegOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("DI" , 0x483a);
+ AddFixed("EI" , 0x403a);
+ AddFixed("RET" , 0x0005);
+ AddFixed("RETI", 0x0004);
+ AddFixed("RETN", 0xe804);
+ AddFixed("SWI" , 0x00ff);
+ AddFixed("NOP" , 0x0000);
+
+ Conditions=(CondRec *) malloc(sizeof(CondRec)*ConditionCnt); InstrZ=0;
+ AddCond("EQ", 0); AddCond("Z" , 0);
+ AddCond("NE", 1); AddCond("NZ", 1);
+ AddCond("CS", 2); AddCond("LT", 2);
+ AddCond("CC", 3); AddCond("GE", 3);
+ AddCond("LE", 4); AddCond("GT", 5);
+ AddCond("T" , 6); AddCond("F" , 7);
+
+ RegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RegOrderCnt); InstrZ=0;
+ AddReg("DAA" , 0x0a); AddReg("DAS" , 0x0b);
+ AddReg("SHLC", 0x1c); AddReg("SHRC", 0x1d);
+ AddReg("ROLC", 0x1e); AddReg("RORC", 0x1f);
+ AddReg("SWAP", 0x01);
+
+ ALUOrders=(char **) malloc(sizeof(char *)*ALUOrderCnt); InstrZ=0;
+ ALUOrders[InstrZ++]="ADDC";
+ ALUOrders[InstrZ++]="ADD";
+ ALUOrders[InstrZ++]="SUBB";
+ ALUOrders[InstrZ++]="SUB";
+ ALUOrders[InstrZ++]="AND";
+ ALUOrders[InstrZ++]="XOR";
+ ALUOrders[InstrZ++]="OR";
+ ALUOrders[InstrZ++]="CMP";
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(Conditions);
+ free(RegOrders);
+ free(ALUOrders);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void ChkAdr(Byte Erl)
+BEGIN
+ if ((AdrType!=ModNone) AND (((1<<AdrType)&Erl)==0))
+ BEGIN
+ AdrType=ModNone; AdrCnt=0; WrError(1350);
+ END
+END
+
+ static void DecodeAdr(char *Asc, Byte Erl)
+BEGIN
+#define Reg16Cnt 4
+ static char *Reg16Names[Reg16Cnt]={"WA","BC","DE","HL"};
+#define AdrRegCnt 5
+ static char *AdrRegs[AdrRegCnt]={"HL","DE","C","PC","A"};
+
+ int z;
+ Byte RegFlag;
+ LongInt DispAcc,DispPart;
+ String AdrPart;
+ Boolean OK,NegFlag,NNegFlag,FirstFlag;
+ char *PPos,*NPos,*EPos;
+
+ AdrType=ModNone; AdrCnt=0;
+
+ if (strlen(Asc)==1)
+ for (z=0; z<Reg8Cnt; z++)
+ if (toupper(*Asc)==Reg8Names[z])
+ BEGIN
+ AdrType=ModReg8; OpSize=0; AdrMode=z;
+ ChkAdr(Erl); return;
+ END
+
+ for (z=0; z<Reg16Cnt; z++)
+ if (strcasecmp(Asc,Reg16Names[z])==0)
+ BEGIN
+ AdrType=ModReg16; OpSize=1; AdrMode=z;
+ ChkAdr(Erl); return;
+ END
+
+ if (IsIndirect(Asc))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ if (strcasecmp(Asc,"-HL")==0)
+ BEGIN
+ AdrType=ModMem; AdrMode=7; ChkAdr(Erl); return;
+ END
+ if (strcasecmp(Asc,"HL+")==0)
+ BEGIN
+ AdrType=ModMem; AdrMode=6; ChkAdr(Erl); return;
+ END
+ RegFlag=0; DispAcc=0; NegFlag=False; OK=True; FirstFlag=False;
+ while ((OK) AND (*Asc!='\0'))
+ BEGIN
+ PPos=QuotPos(Asc,'+'); NPos=QuotPos(Asc,'-');
+ if (PPos==Nil) EPos=NPos;
+ else if (NPos==Nil) EPos=PPos;
+ else EPos=min(NPos,PPos);
+ NNegFlag=((EPos!=Nil) AND (*EPos=='-'));
+ if (EPos==Nil)
+ BEGIN
+ strmaxcpy(AdrPart,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *EPos='\0'; strmaxcpy(AdrPart,Asc,255); strcpy(Asc,EPos+1);
+ END
+ for (z=0; z<AdrRegCnt; z++)
+ if (strcasecmp(AdrPart,AdrRegs[z])==0) break;
+ if (z>=AdrRegCnt)
+ BEGIN
+ FirstPassUnknown=False;
+ DispPart=EvalIntExpression(AdrPart,Int32,&OK);
+ FirstFlag|=FirstPassUnknown;
+ if (NegFlag) DispAcc-=DispPart; else DispAcc+=DispPart;
+ END
+ else if ((NegFlag) OR ((RegFlag & (1 << z))!=0))
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else RegFlag+=1 << z;
+ NegFlag=NNegFlag;
+ END
+ if (DispAcc!=0) RegFlag+=1 << AdrRegCnt;
+ if (OK)
+ switch (RegFlag)
+ BEGIN
+ case 0x20:
+ if (FirstFlag) DispAcc&=0xff;
+ if (DispAcc>0xff) WrError(1320);
+ else
+ BEGIN
+ AdrType=ModAbs; AdrMode=0;
+ AdrCnt=1; AdrVals[0]=DispAcc & 0xff;
+ END
+ break;
+ case 0x02:
+ AdrType=ModMem; AdrMode=2;
+ break;
+ case 0x01:
+ AdrType=ModMem; AdrMode=3;
+ break;
+ case 0x21:
+ if (FirstFlag) DispAcc&=0x7f;
+ if (DispAcc>127) WrError(1320);
+ else if (DispAcc<-128) WrError(1315);
+ else
+ BEGIN
+ AdrType=ModMem; AdrMode=4;
+ AdrCnt=1; AdrVals[0]=DispAcc & 0xff;
+ END
+ break;
+ case 0x05:
+ AdrType=ModMem; AdrMode=5;
+ break;
+ case 0x18:
+ AdrType=ModMem; AdrMode=1;
+ break;
+ default:
+ WrError(1350);
+ END
+ ChkAdr(Erl); return;
+ END
+ else
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1132);
+ break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=1;
+ END
+ break;
+ case 1:
+ DispAcc=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=2;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrVals[1]=(DispAcc >> 8) & 0xff;
+ END
+ break;
+ END
+
+ ChkAdr(Erl);
+END
+
+ static Boolean SplitBit(char *Asc, Byte *Erg)
+BEGIN
+ char *p;
+ String Part;
+
+ p=RQuotPos(Asc,'.');
+ if (p==Nil) return False;
+ *p='\0'; strmaxcpy(Part,p+1,255);
+
+ if (strlen(Part)!=1) return False;
+ else
+ if ((*Part>='0') AND (*Part<='7'))
+ BEGIN
+ *Erg=(*Part)-'0'; return True;
+ END
+ else
+ BEGIN
+ for (*Erg=0; *Erg<Reg8Cnt; (*Erg)++)
+ if (toupper(*Part)==Reg8Names[*Erg]) break;
+ if (*Erg<Reg8Cnt)
+ BEGIN
+ *Erg+=8; return True;
+ END
+ else return False;
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void CodeMem(Byte Entry, Byte Opcode)
+BEGIN
+ BAsmCode[0]=Entry+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=Opcode;
+END
+
+ static void MakeCode_87C800(void)
+BEGIN
+ int z;
+ Integer AdrInt,Condition;
+ Byte HReg,HCnt,HMode,HVal;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=0;
+ if (Hi(FixedOrders[z].Code)!=0) BAsmCode[CodeLen++]=Hi(FixedOrders[z].Code);
+ BAsmCode[CodeLen++]=Lo(FixedOrders[z].Code);
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("LD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"SP")==0)
+ BEGIN
+ OpSize=1;
+ DecodeAdr(ArgStr[2],MModImm+MModReg16);
+ switch (AdrType)
+ BEGIN
+ case ModReg16:
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0xfa;
+ break;
+ case ModImm:
+ CodeLen=3; BAsmCode[0]=0xfa; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ break;
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"SP")==0)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16);
+ switch (AdrType)
+ BEGIN
+ case ModReg16:
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0xfb;
+ break;
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"RBS")==0)
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],Int4,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x0f;
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"CF")==0)
+ BEGIN
+ if (NOT SplitBit(ArgStr[2],&HReg)) WrError(1510);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg8+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if (HReg>=8) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0xd8+HReg;
+ END
+ break;
+ case ModAbs:
+ if (HReg>=8) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xd8+HReg; BAsmCode[1]=AdrVals[0];
+ END
+ break;
+ case ModMem:
+ if (HReg<8)
+ BEGIN
+ CodeLen=2+AdrCnt;
+ CodeMem(0xe0,0xd8+HReg);
+ END
+ else if ((AdrMode!=2) AND (AdrMode!=3)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe0+HReg; BAsmCode[1]=0x9c+AdrMode;
+ END
+ break;
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"CF")==0)
+ BEGIN
+ if (NOT SplitBit(ArgStr[1],&HReg)) WrError(1510);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if (HReg>=8) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0xc8+HReg;
+ END
+ break;
+ case ModAbs:
+ case ModMem:
+ if (HReg<8)
+ BEGIN
+ CodeLen=2+AdrCnt; CodeMem(0xe0,0xc8+HReg);
+ END
+ else if ((AdrMode!=2) AND (AdrMode!=3)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe0+HReg; BAsmCode[1]=0x98+AdrMode;
+ END
+ break;
+ END
+ END
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModReg16+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg8+MModAbs+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if (HReg==AccReg)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x50+AdrMode;
+ END
+ else if (AdrMode==AccReg)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x58+HReg;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0x58+HReg;
+ END
+ break;
+ case ModAbs:
+ if (HReg==AccReg)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x22; BAsmCode[1]=AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xe0; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=0x58+HReg;
+ END
+ break;
+ case ModMem:
+ if ((HReg==AccReg) AND (AdrMode==3)) /* A,(HL) */
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x23;
+ END
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; CodeMem(0xe0,0x58+HReg);
+ if ((HReg>=6) AND (AdrMode==6)) WrError(140);
+ END
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x30+HReg; BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModReg16:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg16+MModAbs+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg16:
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0x14+HReg;
+ break;
+ case ModAbs:
+ CodeLen=3; BAsmCode[0]=0xe0; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=0x14+HReg;
+ break;
+ case ModMem:
+ if (AdrMode>5) WrError(1350); /* (-HL),(HL+) */
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xe0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x14+HReg;
+ END
+ break;
+ case ModImm:
+ CodeLen=3; BAsmCode[0]=0x14+HReg; memcpy(BAsmCode+1,AdrVals,2);
+ break;
+ END
+ break;
+ case ModAbs:
+ HReg=AdrVals[0]; OpSize=0;
+ DecodeAdr(ArgStr[2],MModReg8+MModReg16+MModAbs+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if (AdrMode==AccReg)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x2a; BAsmCode[1]=HReg;
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xf0; BAsmCode[1]=HReg;
+ BAsmCode[2]=0x50+AdrMode;
+ END
+ break;
+ case ModReg16:
+ CodeLen=3; BAsmCode[0]=0xf0; BAsmCode[1]=HReg;
+ BAsmCode[2]=0x10+AdrMode;
+ break;
+ case ModAbs:
+ CodeLen=3; BAsmCode[0]=0x26; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=HReg;
+ break;
+ case ModMem:
+ if (AdrMode>5) WrError(1350); /* (-HL),(HL+) */
+ else
+ BEGIN
+ CodeLen=3+AdrCnt; BAsmCode[0]=0xe0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=0x26;
+ BAsmCode[2+AdrCnt]=HReg;
+ END
+ break;
+ case ModImm:
+ CodeLen=3; BAsmCode[0]=0x2c; BAsmCode[1]=HReg;
+ BAsmCode[2]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModMem:
+ HVal=AdrVals[0]; HCnt=AdrCnt; HMode=AdrMode; OpSize=0;
+ DecodeAdr(ArgStr[2],MModReg8+MModReg16+MModAbs+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if ((HMode==3) AND (AdrMode==AccReg)) /* (HL),A */
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x2b;
+ END
+ else if ((HMode==1) OR (HMode==5)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2+HCnt; BAsmCode[0]=0xf0+HMode;
+ memcpy(BAsmCode+1,&HVal,HCnt);
+ BAsmCode[1+HCnt]=0x50+AdrMode;
+ if ((HMode==6) AND (AdrMode>=6)) WrError(140);
+ END
+ break;
+ case ModReg16:
+ if ((HMode<2) OR (HMode>4)) WrError(1350); /* (HL),(DE),(HL+d) */
+ else
+ BEGIN
+ CodeLen=2+HCnt; BAsmCode[0]=0xf0+HMode;
+ memcpy(BAsmCode+1,&HVal,HCnt); BAsmCode[1+HCnt]=0x10+AdrMode;
+ END
+ break;
+ case ModAbs:
+ if (HMode!=3) WrError(1350); /* (HL) */
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xe0; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=0x27;
+ END
+ break;
+ case ModMem:
+ if (HMode!=3) WrError(1350); /* (HL) */
+ else if (AdrMode>5) WrError(1350); /* (-HL),(HL+) */
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xe0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=0x27;
+ END
+ break;
+ case ModImm:
+ if ((HMode==1) OR (HMode==5)) WrError(1350); /* (HL+C),(PC+A) */
+ else if (HMode==3) /* (HL) */
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x2d; BAsmCode[1]=AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=3+HCnt; BAsmCode[0]=0xf0+HMode;
+ memcpy(BAsmCode+1,&HVal,HCnt); BAsmCode[1+HCnt]=0x2c;
+ BAsmCode[2+HCnt]=AdrVals[0];
+ END
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("XCH"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModReg16+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg8+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0xa8+HReg;
+ break;
+ case ModAbs:
+ case ModMem:
+ CodeLen=2+AdrCnt; CodeMem(0xe0,0xa8+HReg);
+ if ((HReg>=6) AND (AdrMode==6)) WrError(140);
+ break;
+ END
+ break;
+ case ModReg16:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg16);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0x10+HReg;
+ END
+ break;
+ case ModAbs:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModReg8);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xe0; BAsmCode[2]=0xa8+AdrMode;
+ END
+ break;
+ case ModMem:
+ BAsmCode[0]=0xe0+AdrMode; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ HReg=AdrCnt;
+ DecodeAdr(ArgStr[2],MModReg8);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2+HReg; BAsmCode[1+HReg]=0xa8+AdrMode;
+ if ((AdrMode>=6) AND ((BAsmCode[0] & 0x0f)==6)) WrError(140);
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CLR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CF")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x0c;
+ END
+ else if (SplitBit(ArgStr[1],&HReg))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if (HReg>=8) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0x48+HReg;
+ END
+ break;
+ case ModAbs:
+ if (HReg>=8) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x48+HReg; BAsmCode[1]=AdrVals[0];
+ END
+ break;
+ case ModMem:
+ if (HReg<=8)
+ BEGIN
+ CodeLen=2+AdrCnt; CodeMem(0xe0,0x48+HReg);
+ END
+ else if ((AdrMode!=2) AND (AdrMode!=3)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe0+HReg; BAsmCode[1]=0x88+AdrMode;
+ END
+ break;
+ END
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModReg16+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ CodeLen=2; BAsmCode[0]=0x30+AdrMode; BAsmCode[1]=0;
+ break;
+ case ModReg16:
+ CodeLen=3; BAsmCode[0]=0x14+AdrMode; BAsmCode[1]=0; BAsmCode[2]=0;
+ break;
+ case ModAbs:
+ CodeLen=2; BAsmCode[0]=0x2e; BAsmCode[1]=AdrVals[0];
+ break;
+ case ModMem:
+ if ((AdrMode==5) OR (AdrMode==1)) WrError(1350); /* (PC+A, HL+C) */
+ else if (AdrMode==3) /* (HL) */
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x2f;
+ END
+ else
+ BEGIN
+ CodeLen=3+AdrCnt; BAsmCode[0]=0xf0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x2c; BAsmCode[2+AdrCnt]=0;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDW"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int16,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg16:
+ CodeLen=3; BAsmCode[0]=0x14+AdrMode;
+ BAsmCode[1]=AdrInt & 0xff; BAsmCode[2]=AdrInt >> 8;
+ break;
+ case ModAbs:
+ CodeLen=4; BAsmCode[0]=0x24; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=AdrInt & 0xff; BAsmCode[3]=AdrInt >> 8;
+ break;
+ case ModMem:
+ if (AdrMode!=3) WrError(1350); /* (HL) */
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x25;
+ BAsmCode[1]=AdrInt & 0xff; BAsmCode[2]=AdrInt >> 8;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ HReg=Ord(Memo("PUSH"))+6;
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"PSW")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=HReg;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=HReg;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("TEST")) OR (Memo("CPL")) OR (Memo("SET")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CF")==0)
+ BEGIN
+ if (Memo("TEST")) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x0d+Ord(Memo("CPL"));
+ END
+ END
+ else if (NOT SplitBit(ArgStr[1],&HReg)) WrError(1510);
+ else
+ BEGIN
+ if (Memo("TEST")) HVal=0xd8;
+ else if (Memo("SET")) HVal=0x40;
+ else HVal=0xc0;
+ DecodeAdr(ArgStr[1],MModReg8+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if (HReg>=8) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=HVal+HReg;
+ END
+ break;
+ case ModAbs:
+ if (HReg>=8) WrError(1350);
+ else if (Memo("CPL"))
+ BEGIN
+ CodeLen=3; CodeMem(0xe0,HVal+HReg);
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=HVal+HReg; BAsmCode[1]=AdrVals[0];
+ END
+ break;
+ case ModMem:
+ if (HReg<8)
+ BEGIN
+ CodeLen=2+AdrCnt; CodeMem(0xe0,HVal+HReg);
+ END
+ else if ((AdrMode!=2) AND (AdrMode!=3)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe0+HReg;
+ BAsmCode[1]=((HVal & 0x18) >> 1)+((HVal & 0x80) >> 3)+0x80+AdrMode;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<RegOrderCnt; z++)
+ if (Memo(RegOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8);
+ if (AdrType!=ModNone)
+ if (AdrMode==AccReg)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=RegOrders[z].Code;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=RegOrders[z].Code;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ALUOrderCnt; z++)
+ if (Memo(ALUOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"CF")==0)
+ BEGIN
+ if (NOT Memo("XOR")) WrError(1350);
+ else if (NOT SplitBit(ArgStr[2],&HReg)) WrError(1510);
+ else if (HReg>=8) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg8+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0xd0+HReg;
+ break;
+ case ModAbs:
+ case ModMem:
+ CodeLen=2+AdrCnt; CodeMem(0xe0,0xd0+HReg);
+ break;
+ END
+ END
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModReg16+MModMem+MModAbs);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg8+MModMem+MModAbs+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if (HReg==AccReg)
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0x60+z;
+ END
+ else if (AdrMode==AccReg)
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0xe8+HReg; BAsmCode[1]=0x68+z;
+ END
+ else WrError(1350);
+ break;
+ case ModMem:
+ if (HReg!=AccReg) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xe0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x78+z;
+ END
+ break;
+ case ModAbs:
+ if (HReg!=AccReg) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x78+z; BAsmCode[1]=AdrVals[0];
+ END
+ break;
+ case ModImm:
+ if (HReg==AccReg)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x70+z; BAsmCode[1]=AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xe8+HReg;
+ BAsmCode[1]=0x70+z; BAsmCode[2]=AdrVals[0];
+ END
+ break;
+ END
+ break;
+ case ModReg16:
+ HReg=AdrMode; DecodeAdr(ArgStr[2],MModImm+MModReg16);
+ switch (AdrType)
+ BEGIN
+ case ModImm:
+ CodeLen=4; BAsmCode[0]=0xe8+HReg; BAsmCode[1]=0x38+z;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ case ModReg16:
+ if (HReg!=WAReg) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0x30+z;
+ END
+ break;
+ END
+ break;
+ case ModAbs:
+ if (strcasecmp(ArgStr[2],"(HL)")==0)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xe0;
+ BAsmCode[1]=AdrVals[0]; BAsmCode[2]=0x60+z;
+ END
+ else
+ BEGIN
+ BAsmCode[3]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0xe0;
+ BAsmCode[1]=AdrVals[0]; BAsmCode[2]=0x70+z;
+ END
+ END
+ break;
+ case ModMem:
+ if (strcasecmp(ArgStr[2],"(HL)")==0)
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xe0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=0x60+z;
+ END
+ else
+ BEGIN
+ BAsmCode[2+AdrCnt]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=3+AdrCnt; BAsmCode[0]=0xe0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=0x70+z;
+ END
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("MCMP"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMem+MModAbs);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=3+AdrCnt; CodeMem(0xe0,0x2f); BAsmCode[2+AdrCnt]=HReg;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("DEC")) OR (Memo("INC")))
+ BEGIN
+ HReg=Ord(Memo("DEC")) << 3;
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModReg16+MModAbs+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ CodeLen=1; BAsmCode[0]=0x60+HReg+AdrMode;
+ break;
+ case ModReg16:
+ CodeLen=1; BAsmCode[0]=0x10+HReg+AdrMode;
+ break;
+ case ModAbs:
+ CodeLen=2; BAsmCode[0]=0x20+HReg; BAsmCode[1]=AdrVals[0];
+ break;
+ case ModMem:
+ if (AdrMode==3) /* (HL) */
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x21+HReg;
+ END
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xe0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=0x20+HReg;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("MUL"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8);
+ if (AdrType==ModReg8)
+ BEGIN
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg8);
+ if (AdrType==ModReg8)
+ if ((HReg ^ AdrMode)!=1) WrError(1760);
+ else
+ BEGIN
+ HReg=HReg >> 1;
+ if (HReg==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x02;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+HReg; BAsmCode[1]=0x02;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("DIV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16);
+ if (AdrType==ModReg16)
+ BEGIN
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg8);
+ if (AdrType==ModReg8)
+ if (AdrMode!=2) WrError(1350); /* C */
+ else if (HReg==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x03;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe8+HReg; BAsmCode[1]=0x03;
+ if (HReg==1) WrError(140);
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("ROLD")) OR (Memo("RORD")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ HReg=Ord(Memo("RORD"))+8;
+ DecodeAdr(ArgStr[2],MModAbs+MModMem);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2+AdrCnt; CodeMem(0xe0,HReg);
+ if (AdrMode==1) WrError(140);
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if (Memo("JRS"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ for (Condition=ConditionCnt-2; Condition<ConditionCnt; Condition++)
+ if (strcmp(ArgStr[1],Conditions[Condition].Name)==0) break;
+ if (Condition>=ConditionCnt) WrXError(1360,ArgStr[1]);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if (((AdrInt<-16) OR (AdrInt>15)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=((Conditions[Condition].Code-2) << 5)+(AdrInt & 0x1f);
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("JR"))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1) Condition=(-1);
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ for (Condition=0; Condition<ConditionCnt; Condition++)
+ if (strcmp(ArgStr[1],Conditions[Condition].Name)==0) break;
+ END
+ if (Condition>=ConditionCnt) WrXError(1360,ArgStr[1]);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if (((AdrInt<-128) OR (AdrInt>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2;
+ if (Condition==-1) BAsmCode[0]=0xfb;
+ else BAsmCode[0]=0xd0+Conditions[Condition].Code;
+ BAsmCode[1]=AdrInt & 0xff;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JP")) OR (Memo("CALL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ OpSize=1; HReg=0xfc+2*Ord(Memo("JP"));
+ DecodeAdr(ArgStr[1],MModReg16+MModAbs+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg16:
+ CodeLen=2; BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=HReg;
+ break;
+ case ModAbs:
+ CodeLen=3; BAsmCode[0]=0xe0; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=HReg;
+ break;
+ case ModMem:
+ if (AdrMode>5) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xe0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=HReg;
+ END
+ break;
+ case ModImm:
+ if ((AdrVals[1]==0xff) AND (Memo("CALL")))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xfd; BAsmCode[1]=AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=HReg; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALLV"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ HVal=EvalIntExpression(ArgStr[1],Int4,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xc0+(HVal & 15);
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALLP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if ((Hi(AdrInt)!=0xff) AND (Hi(AdrInt)!=0)) WrError(1320);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xfd; BAsmCode[1]=Lo(AdrInt);
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_87C800(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_87C800(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_87C800(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=True;
+
+ PCSymbol="$"; HeaderID=0x54; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_87C800; IsDef=IsDef_87C800;
+ SwitchFrom=SwitchFrom_87C800; InitFields();
+END
+
+ void code87c800_init(void)
+BEGIN
+ CPU87C00=AddCPU("87C00",SwitchTo_87C800);
+ CPU87C20=AddCPU("87C20",SwitchTo_87C800);
+ CPU87C40=AddCPU("87C40",SwitchTo_87C800);
+ CPU87C70=AddCPU("87C70",SwitchTo_87C800);
+END
diff --git a/code87c800.h b/code87c800.h
new file mode 100644
index 0000000..d92aaf0
--- /dev/null
+++ b/code87c800.h
@@ -0,0 +1,11 @@
+/* code87c800.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TLCS-870 */
+/* */
+/* Historie: 29.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code87c800_init(void);
diff --git a/code8x30x.c b/code8x30x.c
new file mode 100644
index 0000000..1d15c07
--- /dev/null
+++ b/code8x30x.c
@@ -0,0 +1,559 @@
+/* code8x30x.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Signetics 8X30x */
+/* */
+/* Historie: 25. 6.1997 Grundsteinlegung */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "chunks.h"
+#include "bpemu.h"
+#include "strutil.h"
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+
+/*****************************************************************************/
+
+#define AriOrderCnt 4
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+static CPUVar CPU8x300,CPU8x305;
+static FixedOrder *AriOrders;
+
+/*-------------------------------------------------------------------------*/
+
+static int InstrZ;
+
+ static void AddAri(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=AriOrderCnt) exit(255);
+ AriOrders[InstrZ].Name=NName;
+ AriOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ AriOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*AriOrderCnt); InstrZ=0;
+ AddAri("MOVE",0); AddAri("ADD",1); AddAri("AND",2); AddAri("XOR",3);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(AriOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodeReg(char *Asc, Word *Erg, ShortInt *ErgLen)
+BEGIN
+ Boolean OK;
+ Word Acc;
+ LongInt Adr;
+ char *z;
+
+ *ErgLen=(-1);
+
+ if (strcasecmp(Asc,"AUX")==0)
+ BEGIN
+ *Erg=0; return True;
+ END
+
+ if (strcasecmp(Asc,"OVF")==0)
+ BEGIN
+ *Erg=8; return True;
+ END
+
+ if (strcasecmp(Asc,"IVL")==0)
+ BEGIN
+ *Erg=7; return True;
+ END
+
+ if (strcasecmp(Asc,"IVR")==0)
+ BEGIN
+ *Erg=15; return True;
+ END
+
+ if ((toupper(*Asc)=='R') AND (strlen(Asc)>1) AND (strlen(Asc)<4))
+ BEGIN
+ Acc=0; OK=True;
+ for (z=Asc+1; *z!='\0'; z++)
+ if (OK)
+ if ((*z<'0') OR (*z>'7')) OK=False;
+ else Acc=(Acc << 3)+(*z-'0');
+ if ((OK) AND (Acc<32))
+ BEGIN
+ if ((MomCPU==CPU8x300) AND (Acc>9) AND (Acc<15))
+ BEGIN
+ WrXError(1445,Asc); return False;
+ END
+ else *Erg=Acc;
+ return True;
+ END
+ END
+
+ if ((strlen(Asc)==4) AND (strncasecmp(Asc+1,"IV",2)==0) AND (Asc[3]>='0') AND (Asc[3]<='7'))
+ if (toupper(*Asc)=='L')
+ BEGIN
+ *Erg=Asc[3]-'0'+0x10; return True;
+ END
+ else if (toupper(*Asc)=='R')
+ BEGIN
+ *Erg=Asc[3]-'0'+0x18; return True;
+ END
+
+ /* IV - Objekte */
+
+ Adr=EvalIntExpression(Asc,UInt24,&OK);
+ if (OK)
+ BEGIN
+ *ErgLen=Adr & 7;
+ *Erg=0x10+((Adr & 0x10) >> 1)+((Adr & 0x700) >> 8);
+ return True;
+ END
+ else return False;
+END
+
+ static char *HasDisp(char *Asc)
+BEGIN
+ int Lev;
+ char *z;
+ int l=strlen(Asc);
+
+ if (Asc[l-1]==')')
+ BEGIN
+ z=Asc+l-2; Lev=0;
+ while ((z>=Asc) AND (Lev!=-1))
+ BEGIN
+ switch (*z)
+ BEGIN
+ case '(': Lev--; break;
+ case ')': Lev++; break;
+ END
+ if (Lev!=-1) z--;
+ END
+ if (Lev!=-1)
+ BEGIN
+ WrError(1300); return Nil;
+ END
+ END
+ else z=Nil;
+
+ return z;
+END
+
+ static Boolean GetLen(char *Asc, Word *Erg)
+BEGIN
+ Boolean OK;
+
+ FirstPassUnknown=False;
+ *Erg=EvalIntExpression(Asc,UInt4,&OK); if (NOT OK) return False;
+ if (FirstPassUnknown) *Erg=8;
+ if (NOT ChkRange(*Erg,1,8)) return False;
+ *Erg&=7; return True;
+END
+
+/*-------------------------------------------------------------------------*/
+
+/* Symbol: 00AA0ORL */
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ LongInt Adr,Ofs,Erg;
+ Word Len;
+ Boolean OK;
+
+ if ((Memo("LIV")) OR (Memo("RIV")))
+ BEGIN
+ Erg=0x10*Ord(Memo("RIV"));
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ Adr=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if (OK)
+ BEGIN
+ Ofs=EvalIntExpression(ArgStr[2],UInt3,&OK);
+ if (OK)
+ if (GetLen(ArgStr[3],&Len))
+ BEGIN
+ PushLocHandle(-1);
+ EnterIntSymbol(LabPart,Erg+(Adr << 16)+(Ofs << 8)+(Len & 7),SegNone,False);
+ PopLocHandle();
+ END
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_8x30X(void)
+BEGIN
+ Boolean OK;
+ Word SrcReg,DestReg;
+ ShortInt SrcLen,DestLen;
+ LongInt Op;
+ Word Rot,Adr;
+ int z;
+ char *p;
+ String tmp;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* eingebaute Makros */
+
+ if (Memo("NOP")) /* NOP = MOVE AUX,AUX */
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=0x0000; CodeLen=1;
+ END
+ return;
+ END
+
+ if (Memo("HALT")) /* HALT = JMP * */
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=0xe000+(EProgCounter() & 0x1fff); CodeLen=1;
+ END
+ return;
+ END
+
+ if ((Memo("XML")) OR (Memo("XMR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU8x305) WrError(1500);
+ else
+ BEGIN
+ Adr=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0xca00+(Ord(Memo("XER")) << 8)+(Adr & 0xff);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("SEL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Op=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0xc700+((Op & 0x10) << 7)+((Op >> 16) & 0xff);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("XMIT"))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
+ else if (DecodeReg(ArgStr[2],&SrcReg,&SrcLen))
+ if (SrcReg<16)
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ Adr=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0xc000+(SrcReg << 8)+(Adr & 0xff);
+ CodeLen=1;
+ END
+ END
+ END
+ else
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ Rot=0xffff; OK=True;
+ END
+ else OK=GetLen(ArgStr[3],&Rot);
+ if (OK)
+ BEGIN
+ if (Rot==0xffff)
+ Rot=(SrcLen==-1) ? 0 : SrcLen;
+ if ((SrcLen!=-1) AND (Rot!=SrcLen)) WrError(1131);
+ else
+ BEGIN
+ Adr=EvalIntExpression(ArgStr[1],Int5,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0xc000+(SrcReg << 8)+(Rot << 5)+(Adr & 0x1f);
+ CodeLen=1;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<AriOrderCnt; z++)
+ if (Memo(AriOrders[z].Name))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
+ else if (DecodeReg(ArgStr[ArgCnt],&DestReg,&DestLen))
+ if (DestReg<16) /* Ziel Register */
+ BEGIN
+ if (ArgCnt==2) /* wenn nur zwei Operanden und Ziel Register... */
+ BEGIN
+ p=HasDisp(ArgStr[1]); /* kann eine Rotation dabei sein */
+ if (p!=Nil)
+ BEGIN /* jau! */
+ strcpy(tmp,p+1); tmp[strlen(tmp)-1]='\0';
+ Rot=EvalIntExpression(tmp,UInt3,&OK);
+ if (OK)
+ BEGIN
+ *p='\0';
+ if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
+ if (SrcReg>=16) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ WAsmCode[0]=(AriOrders[z].Code << 13)+(SrcReg << 8)+(Rot << 5)+DestReg;
+ CodeLen=1;
+ END
+ END
+ END
+ else /* noi! */
+ BEGIN
+ if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
+ BEGIN
+ WAsmCode[0]=(AriOrders[z].Code << 13)+(SrcReg << 8)+DestReg;
+ if ((SrcReg>=16) AND (SrcLen!=-1)) WAsmCode[0]+=SrcLen << 5;
+ CodeLen=1;
+ END
+ END
+ END
+ else /* 3 Operanden --> Quelle ist I/O */
+ BEGIN
+ if (GetLen(ArgStr[2],&Rot))
+ if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
+ if (SrcReg<16) WrXError(1445,ArgStr[1]);
+ else if ((SrcLen!=-1) AND (SrcLen!=Rot)) WrError(1131);
+ else
+ BEGIN
+ WAsmCode[0]=(AriOrders[z].Code << 13)+(SrcReg << 8)+(Rot << 5)+DestReg;
+ CodeLen=1;
+ END
+ END
+ END
+ else /* Ziel I/O */
+ BEGIN
+ if (ArgCnt==2) /* 2 Argumente: Laenge=Laenge Ziel */
+ BEGIN
+ Rot=DestLen; OK=True;
+ END
+ else /* 3 Argumente: Laenge=Laenge Ziel+Angabe */
+ BEGIN
+ OK=GetLen(ArgStr[2],&Rot);
+ if (OK)
+ BEGIN
+ if (FirstPassUnknown) Rot=DestLen;
+ if (DestLen==-1) DestLen=Rot;
+ OK=Rot==DestLen;
+ if (NOT OK) WrError(1131);
+ END
+ END
+ if (OK)
+ if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
+ BEGIN
+ if ((Rot==0xffff))
+ Rot=((SrcLen==-1)) ? 0 : SrcLen;
+ if ((DestReg>=16) AND (SrcLen!=-1) AND (SrcLen!=Rot)) WrError(1131);
+ else
+ BEGIN
+ WAsmCode[0]=(AriOrders[z].Code << 13)+(SrcReg << 8)+(Rot << 5)+DestReg;
+ CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("XEC"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ p=HasDisp(ArgStr[1]);
+ if (p==Nil) WrError(1350);
+ else
+ BEGIN
+ strcpy(tmp,p+1); tmp[strlen(tmp)-1]='\0';
+ if (DecodeReg(tmp,&SrcReg,&SrcLen))
+ BEGIN
+ *p='\0';
+ if (SrcReg<16)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]+=0x8000+(SrcReg << 8);
+ CodeLen=1;
+ END
+ END
+ END
+ else
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ Rot=0xffff; OK=True;
+ END
+ else OK=GetLen(ArgStr[2],&Rot);
+ if (OK)
+ BEGIN
+ if (Rot==0xffff)
+ Rot=(SrcLen==-1) ? 0 : SrcLen;
+ if ((SrcLen!=-1) AND (Rot!=SrcLen)) WrError(1131);
+ else
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]+=0x8000+(SrcReg << 8)+(Rot << 5);
+ CodeLen=1;
+ END
+ END
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if (Memo("JMP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[1],UInt13,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]+=0xe000; CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("NZT"))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
+ else if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
+ if (SrcReg<16)
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ Adr=EvalIntExpression(ArgStr[2],UInt13,&OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Adr >> 8)!=(EProgCounter() >> 8))) WrError(1910);
+ else
+ BEGIN
+ WAsmCode[0]=0xa000+(SrcReg << 8)+(Adr & 0xff);
+ CodeLen=1;
+ END
+ END
+ END
+ else
+ BEGIN
+ if (ArgCnt==2)
+ BEGIN
+ Rot=0xffff; OK=True;
+ END
+ else OK=GetLen(ArgStr[2],&Rot);
+ if (OK)
+ BEGIN
+ if (Rot==0xffff)
+ Rot=(SrcLen==-1) ? 0 : SrcLen;
+ if ((SrcLen!=-1) AND (Rot!=SrcLen)) WrError(1131);
+ else
+ BEGIN
+ Adr=EvalIntExpression(ArgStr[ArgCnt],UInt13,&OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Adr >> 5)!=(EProgCounter() >> 5))) WrError(1910);
+ else
+ BEGIN
+ WAsmCode[0]=0xa000+(SrcReg << 8)+(Rot << 5)+(Adr & 0x1f);
+ CodeLen=1;
+ END
+ END
+ END
+ END
+ return;
+ END;
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_8x30X(void)
+BEGIN
+ return (Memo("LIV") OR Memo("RIV"));
+END
+
+ static void SwitchFrom_8x30X()
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_8x30X(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x3a; NOPCode=0x0000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=2; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0x1fff;
+
+ MakeCode=MakeCode_8x30X; IsDef=IsDef_8x30X;
+ SwitchFrom=SwitchFrom_8x30X; InitFields();
+END
+
+ void code8x30x_init(void)
+BEGIN
+ CPU8x300=AddCPU("8x300",SwitchTo_8x30X);
+ CPU8x305=AddCPU("8x305",SwitchTo_8x30X);
+END
+
diff --git a/code8x30x.h b/code8x30x.h
new file mode 100644
index 0000000..f440a00
--- /dev/null
+++ b/code8x30x.h
@@ -0,0 +1,11 @@
+/* code8x30x.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Signetics 8X30x */
+/* */
+/* Historie: 25.6.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code8x30x_init(void);
diff --git a/code90c141.c b/code90c141.c
new file mode 100644
index 0000000..8d9b528
--- /dev/null
+++ b/code90c141.c
@@ -0,0 +1,1293 @@
+/* code90c141.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Toshiba TLCS-90 */
+/* */
+/* Historie: 30.10.1996 Grundsteinlegung */
+/* 2. 1.1999 ChkPC umgebaut */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ Byte Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ Byte Code;
+ Boolean MayReg;
+ } ShiftOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } Condition;
+
+
+#define AccReg 6
+#define HLReg 2
+
+#define FixedOrderCnt 18
+#define MoveOrderCnt 8
+#define ShiftOrderCnt 10
+#define BitOrderCnt 4
+#define AccOrderCnt 3
+#define ALU2OrderCnt 8
+#define ConditionCnt 24
+
+#define ModNone (-1)
+#define ModReg8 0
+#define MModReg8 (1 << ModReg8)
+#define ModReg16 1
+#define MModReg16 (1 << ModReg16)
+#define ModIReg16 2
+#define MModIReg16 (1 << ModIReg16)
+#define ModIndReg 3
+#define MModIndReg (1 << ModIndReg)
+#define ModIdxReg 4
+#define MModIdxReg (1 << ModIdxReg)
+#define ModDir 5
+#define MModDir (1 << ModDir)
+#define ModMem 6
+#define MModMem (1 << ModMem)
+#define ModImm 7
+#define MModImm (1 << ModImm)
+
+static int DefaultCondition;
+
+static ShortInt AdrType;
+static Byte AdrMode;
+static ShortInt OpSize;
+static Byte AdrVals[10];
+static Boolean MinOneIs0;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *MoveOrders;
+static ShiftOrder *ShiftOrders;
+static FixedOrder *BitOrders;
+static FixedOrder *AccOrders;
+static char **ALU2Orders;
+static Condition *Conditions;
+static PInstTreeNode ITree;
+
+static CPUVar CPU90C141;
+
+/*---------------------------------------------------------------------------*/
+
+ static void ChkAdr(Byte Erl)
+BEGIN
+ if (AdrType!=ModNone)
+ if (((1 << AdrType) & Erl)==0)
+ BEGIN
+ WrError(1350); AdrType=ModNone; AdrCnt=0;
+ END
+END
+
+ static void SetOpSize(ShortInt New)
+BEGIN
+ if (OpSize==-1) OpSize=New;
+ else if (OpSize!=New)
+ BEGIN
+ WrError(1131); AdrType=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Byte Erl)
+BEGIN
+#define Reg8Cnt 7
+ static char *Reg8Names[Reg8Cnt]={"B","C","D","E","H","L","A"};
+#define Reg16Cnt 7
+ static char *Reg16Names[Reg16Cnt]={"BC","DE","HL","\0","IX","IY","SP"};
+#define IReg16Cnt 3
+ static char *IReg16Names[IReg16Cnt]={"IX","IY","SP"};
+
+ int z;
+ char *p,*ppos,*mpos;
+ LongInt DispAcc,DispVal;
+ Byte OccFlag,BaseReg;
+ Boolean ok,fnd,NegFlag,NNegFlag,Unknown;
+ String Part;
+
+ AdrType=ModNone; AdrCnt=0;
+
+ /* 1. 8-Bit-Register */
+
+ for (z=0; z<Reg8Cnt; z++)
+ if (strcasecmp(Asc,Reg8Names[z])==0)
+ BEGIN
+ AdrType=ModReg8; AdrMode=z; SetOpSize(0);
+ ChkAdr(Erl); return;
+ END
+
+ /* 2. 16-Bit-Register, indiziert */
+
+ if ((Erl & MModIReg16)!=0)
+ for (z=0; z<IReg16Cnt; z++)
+ if (strcasecmp(Asc,IReg16Names[z])==0)
+ BEGIN
+ AdrType=ModIReg16; AdrMode=z; SetOpSize(1);
+ ChkAdr(Erl); return;
+ END
+
+ /* 3. 16-Bit-Register, normal */
+
+ for (z=0; z<Reg16Cnt; z++)
+ if (strcasecmp(Asc,Reg16Names[z])==0)
+ BEGIN
+ AdrType=ModReg16; AdrMode=z; SetOpSize(1);
+ ChkAdr(Erl); return;
+ END
+
+ /* Speicheradresse */
+
+ if (IsIndirect(Asc))
+ BEGIN
+ OccFlag=0; BaseReg=0; DispAcc=0; ok=True; NegFlag=False; Unknown=False;
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ do
+ BEGIN
+ ppos=QuotPos(Asc,'+');
+ mpos=QuotPos(Asc,'-');
+ if (ppos==Nil) p=mpos;
+ else if (mpos==Nil) p=ppos;
+ else p=min(mpos,ppos);
+ NNegFlag=((p!=Nil) AND (*p=='-'));
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Part,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(Part,Asc,255); strcpy(Asc,p+1);
+ END
+ fnd=False;
+ if (strcasecmp(Part,"A")==0)
+ BEGIN
+ fnd=True;
+ ok=((NOT NegFlag) AND ((OccFlag & 1)==0));
+ if (ok) OccFlag+=1; else WrError(1350);
+ END
+ if (NOT fnd)
+ for (z=0; z<Reg16Cnt; z++)
+ if (strcasecmp(Part,Reg16Names[z])==0)
+ BEGIN
+ fnd=True; BaseReg=z;
+ ok=((NOT NegFlag) AND ((OccFlag & 2)==0));
+ if (ok) OccFlag+=2; else WrError(1350);
+ END
+ if (NOT fnd)
+ BEGIN
+ FirstPassUnknown=False;
+ DispVal=EvalIntExpression(Part,Int32,&ok);
+ if (ok)
+ BEGIN
+ if (NegFlag) DispAcc-=DispVal; else DispAcc+=DispVal;
+ if (FirstPassUnknown) Unknown=True;
+ END
+ END
+ NegFlag=NNegFlag;
+ END
+ while ((*Asc!='\0') AND (ok));
+ if (NOT ok) return;
+ if (Unknown) DispAcc&=0x7f;
+ switch (OccFlag)
+ BEGIN
+ case 1:
+ WrError(1350); break;
+ case 3:
+ if ((BaseReg!=2) OR (DispAcc!=0)) WrError(1350);
+ else
+ BEGIN
+ AdrType=ModIdxReg; AdrMode=3;
+ END
+ break;
+ case 2:
+ if ((DispAcc>127) OR (DispAcc<-128)) WrError(1320);
+ else if (DispAcc==0)
+ BEGIN
+ AdrType=ModIndReg; AdrMode=BaseReg;
+ END
+ else if (BaseReg<4) WrError(1350);
+ else
+ BEGIN
+ AdrType=ModIdxReg; AdrMode=BaseReg-4;
+ AdrCnt=1; AdrVals[0]=DispAcc & 0xff;
+ END
+ break;
+ case 0:
+ if (DispAcc>0xffff) WrError(1925);
+ else if ((Hi(DispAcc)==0xff) AND ((Erl & MModDir)!=0))
+ BEGIN
+ AdrType=ModDir; AdrCnt=1; AdrVals[0]=Lo(DispAcc);
+ END
+ else
+ BEGIN
+ AdrType=ModMem; AdrCnt=2;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc);
+ END
+ break;
+ END
+ END
+
+ /* immediate */
+
+ else
+ BEGIN
+ if ((OpSize==-1) AND (MinOneIs0)) OpSize=0;
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1130); break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc,Int8,&ok);
+ if (ok)
+ BEGIN
+ AdrType=ModImm; AdrCnt=1;
+ END
+ break;
+ case 1:
+ DispVal=EvalIntExpression(Asc,Int16,&ok);
+ if (ok)
+ BEGIN
+ AdrType=ModImm; AdrCnt=2;
+ AdrVals[0]=Lo(DispVal); AdrVals[1]=Hi(DispVal);
+ END
+ break;
+ END
+ END
+
+ /* gefunden */
+
+ ChkAdr(Erl);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static Boolean WMemo(char *Name)
+BEGIN
+ String tmp;
+
+ if (Memo(Name)) return True;
+
+ sprintf(tmp,"%sW",Name);
+ if (Memo(tmp))
+ BEGIN
+ OpSize=1; return True;
+ END
+ else return False;
+END
+
+ static Boolean ArgPair(char *Arg1, char *Arg2)
+BEGIN
+ return (((strcasecmp(ArgStr[1],Arg1)==0) AND (strcasecmp(ArgStr[2],Arg2)==0))
+ OR ((strcasecmp(ArgStr[1],Arg2)==0) AND (strcasecmp(ArgStr[2],Arg1)==0)));
+END
+
+/*-------------------------------------------------------------------------*/
+
+/* ohne Argument */
+
+ static void CodeFixed(Word Index)
+BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=FixedOrders[Index].Code;
+ END
+END
+
+ static void CodeMove(Word Index)
+BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xfe; BAsmCode[1]=MoveOrders[Index].Code;
+ END
+END
+
+ static void CodeShift(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],((ShiftOrders[Index].MayReg)?MModReg8:0)+MModIndReg+MModIdxReg+MModMem+MModDir);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ CodeLen=2; BAsmCode[0]=0xf8+AdrMode; BAsmCode[1]=ShiftOrders[Index].Code;
+ if (AdrMode==AccReg) WrError(10);
+ break;
+ case ModIndReg:
+ CodeLen=2; BAsmCode[0]=0xe0+AdrMode; BAsmCode[1]=ShiftOrders[Index].Code;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xf0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=ShiftOrders[Index].Code;
+ break;
+ case ModDir:
+ CodeLen=3; BAsmCode[0]=0xe7; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=ShiftOrders[Index].Code;
+ break;
+ case ModMem:
+ CodeLen=4; BAsmCode[0]=0xe3;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[3]=ShiftOrders[Index].Code;
+ break;
+ END
+ END
+END
+
+/* Logik */
+
+ static void CodeBit(Word Index)
+BEGIN
+ Byte HReg;
+ Boolean OK;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg8+MModIndReg+MModIdxReg+MModMem+MModDir);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ CodeLen=2;
+ BAsmCode[0]=0xf8+AdrMode; BAsmCode[1]=BitOrders[Index].Code+HReg;
+ break;
+ case ModIndReg:
+ CodeLen=2;
+ BAsmCode[0]=0xe0+AdrMode; BAsmCode[1]=BitOrders[Index].Code+HReg;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[0]=0xf0+AdrMode; BAsmCode[1+AdrCnt]=BitOrders[Index].Code+HReg;
+ break;
+ case ModMem:
+ CodeLen=4; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[0]=0xe3; BAsmCode[1+AdrCnt]=BitOrders[Index].Code+HReg;
+ break;
+ case ModDir:
+ BAsmCode[1]=AdrVals[0];
+ if (Index==4)
+ BEGIN
+ BAsmCode[0]=0xe7; BAsmCode[2]=BitOrders[Index].Code+HReg; CodeLen=3;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=BitOrders[Index].Code+HReg; CodeLen=2;
+ END
+ break;
+ END
+ END
+ END
+END
+
+ static void CodeAcc(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=AccOrders[Index].Code;
+ END
+END
+
+ static void MakeCode_90C141(void)
+BEGIN
+ int z;
+ Integer AdrInt;
+ Boolean OK;
+ Byte HReg;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ if (SearchInstTree(ITree,OpPart)) return;
+
+ /* Datentransfer */
+
+ if (WMemo("LD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModReg16+MModIndReg+MModIdxReg+MModDir+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg8+MModIndReg+MModIdxReg+MModDir+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if (HReg==AccReg)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x20+AdrMode;
+ END
+ else if (AdrMode==AccReg)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x28+HReg;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xf8+AdrMode; BAsmCode[1]=0x30+HReg;
+ END
+ break;
+ case ModIndReg:
+ CodeLen=2; BAsmCode[0]=0xe0+AdrMode; BAsmCode[1]=0x28+HReg;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xf0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=0x28+HReg;
+ break;
+ case ModDir:
+ if (HReg==AccReg)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x27; BAsmCode[1]=AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xe7; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=0x28+HReg;
+ END
+ break;
+ case ModMem:
+ CodeLen=4; BAsmCode[0]=0xe3;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[3]=0x28+HReg;
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x30+HReg; BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModReg16:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg16+MModIndReg+MModIdxReg+MModDir+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg16:
+ if (HReg==HLReg)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x40+AdrMode;
+ END
+ else if (AdrMode==HLReg)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x48+HReg;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xf8+AdrMode; BAsmCode[1]=0x38+HReg;
+ END
+ break;
+ case ModIndReg:
+ CodeLen=2;
+ BAsmCode[0]=0xe0+AdrMode; BAsmCode[1]=0x48+HReg;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xf0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=0x48+HReg;
+ break;
+ case ModDir:
+ if (HReg==HLReg)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x47; BAsmCode[1]=AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xe7; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=0x48+HReg;
+ END
+ break;
+ case ModMem:
+ CodeLen=4; BAsmCode[0]=0xe3; BAsmCode[3]=0x48+HReg;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ break;
+ case ModImm:
+ CodeLen=3; BAsmCode[0]=0x38+HReg;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ break;
+ END
+ break;
+ case ModIndReg:
+ case ModIdxReg:
+ case ModDir:
+ case ModMem:
+ MinOneIs0=True; HReg=AdrCnt; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ switch (AdrType)
+ BEGIN
+ case ModIndReg: BAsmCode[0]=0xe8+AdrMode; break;
+ case ModIdxReg: BAsmCode[0]=0xf4+AdrMode; break;
+ case ModMem: BAsmCode[0]=0xeb; break;
+ case ModDir: BAsmCode[0]=0x0f; break;
+ END
+ DecodeAdr(ArgStr[2],MModReg16+MModReg8+MModImm);
+ if (BAsmCode[0]==0x0f)
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ if (AdrMode==AccReg)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x2f;
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xef; BAsmCode[2]=0x20+AdrMode;
+ END
+ break;
+ case ModReg16:
+ if (AdrMode==HLReg)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x4f;
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xef; BAsmCode[2]=0x40+AdrMode;
+ END
+ break;
+ case ModImm:
+ CodeLen=3+OpSize; BAsmCode[0]=0x37+(OpSize << 3);
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ END
+ else
+ BEGIN
+ switch (AdrType)
+ BEGIN
+ case ModReg8: BAsmCode[1+HReg]=0x20+AdrMode; break;
+ case ModReg16: BAsmCode[1+HReg]=0x40+AdrMode; break;
+ case ModImm: BAsmCode[1+HReg]=0x37+(OpSize << 3); break;
+ END
+ memcpy(BAsmCode+2+HReg,AdrVals,AdrCnt);
+ CodeLen=1+HReg+1+AdrCnt;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ HReg=Ord(Memo("POP")) << 3;
+ if (strcasecmp(ArgStr[1],"AF")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x56+HReg;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16);
+ if (AdrType==ModReg16)
+ if (AdrMode==6) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x50+HReg+AdrMode;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDA"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16);
+ if (AdrType==ModReg16)
+ BEGIN
+ HReg=0x38+AdrMode;
+ DecodeAdr(ArgStr[2],MModIndReg+MModIdxReg);
+ switch (AdrType)
+ BEGIN
+ case ModIndReg:
+ if (AdrMode<4) WrError(1350);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xf0+AdrMode;
+ BAsmCode[1]=0; BAsmCode[2]=HReg;
+ END
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xf4+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); BAsmCode[1+AdrCnt]=HReg;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDAR"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"HL")!=0) WrError(1350);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int16,&OK)-(EProgCounter()+2);
+ if (OK)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x17;
+ BAsmCode[1]=Lo(AdrInt); BAsmCode[2]=Hi(AdrInt);
+ END
+ END
+ return;
+ END
+
+ if (Memo("EX"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (ArgPair("DE","HL"))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x08;
+ END
+ else if ((ArgPair("AF","AF\'") OR ArgPair("AF","AF`")))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x09;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg16+MModIndReg+MModIdxReg+MModMem+MModDir);
+ switch (AdrType)
+ BEGIN
+ case ModReg16:
+ HReg=0x50+AdrMode;
+ DecodeAdr(ArgStr[2],MModIndReg+MModIdxReg+MModMem+MModDir);
+ switch (AdrType)
+ BEGIN
+ case ModIndReg:
+ CodeLen=2; BAsmCode[0]=0xe0+AdrMode; BAsmCode[1]=HReg;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xf0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=HReg;
+ break;
+ case ModDir:
+ CodeLen=3; BAsmCode[0]=0xe7; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=HReg;
+ break;
+ case ModMem:
+ CodeLen=4; BAsmCode[0]=0xe3; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[3]=HReg;
+ break;
+ END
+ break;
+ case ModIndReg:
+ case ModIdxReg:
+ case ModDir:
+ case ModMem:
+ switch (AdrType)
+ BEGIN
+ case ModIndReg: BAsmCode[0]=0xe0+AdrMode; break;
+ case ModIdxReg: BAsmCode[0]=0xf0+AdrMode; break;
+ case ModDir: BAsmCode[0]=0xe7; break;
+ case ModMem: BAsmCode[0]=0xe3; break;
+ END
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); HReg=2+AdrCnt;
+ DecodeAdr(ArgStr[2],MModReg16);
+ if (AdrType==ModReg16)
+ BEGIN
+ BAsmCode[HReg-1]=0x50+AdrMode; CodeLen=HReg;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<ALU2OrderCnt; z++)
+ if (Memo(ALU2Orders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg8+MModReg16+MModIdxReg+MModIndReg+MModDir+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ DecodeAdr(ArgStr[2],MModImm+(((HReg=AdrMode)==AccReg)?MModReg8+MModIndReg+MModIdxReg+MModDir+MModMem:0));
+ switch(AdrType)
+ BEGIN
+ case ModReg8:
+ CodeLen=2;
+ BAsmCode[0]=0xf8+AdrMode; BAsmCode[1]=0x60+z;
+ break;
+ case ModIndReg:
+ CodeLen=2;
+ BAsmCode[0]=0xe0+AdrMode; BAsmCode[1]=0x60+z;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0xf0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x60+z;
+ break;
+ case ModDir:
+ CodeLen=2;
+ BAsmCode[0]=0x60+z;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ case ModMem:
+ CodeLen=4;
+ BAsmCode[0]=0xe3; BAsmCode[3]=0x60+z;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ break;
+ case ModImm:
+ if (HReg==AccReg)
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x68+z; BAsmCode[1]=AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=3;
+ BAsmCode[0]=0xf8+HReg; BAsmCode[1]=0x68+z;
+ BAsmCode[2]=AdrVals[0];
+ END
+ break;
+ END
+ break;
+ case ModReg16:
+ if ((AdrMode==2) OR ((z==0) AND (AdrMode>=4)))
+ BEGIN
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg16+MModIndReg+MModIdxReg+MModDir+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg16:
+ CodeLen=2;
+ BAsmCode[0]=0xf8+AdrMode;
+ BAsmCode[1]=(HReg>=4) ? 0x14+HReg-4 : 0x70+z;
+ break;
+ case ModIndReg:
+ CodeLen=2;
+ BAsmCode[0]=0xe0+AdrMode;
+ BAsmCode[1]=(HReg>=4) ? 0x14+HReg-4 : 0x70+z;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0xf0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=(HReg>=4) ? 0x14+HReg-4 : 0x70+z;
+ break;
+ case ModDir:
+ if (HReg>=4)
+ BEGIN
+ CodeLen=3;
+ BAsmCode[0]=0xe7;
+ BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=0x10+HReg;
+ END
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x70+z; BAsmCode[1]=AdrVals[0];
+ END
+ break;
+ case ModMem:
+ CodeLen=4;
+ BAsmCode[0]=0xe3;
+ memcpy(BAsmCode+1,AdrVals,2);
+ BAsmCode[3]=(HReg>=4) ? 0x14+HReg-4 : 0x70+z;
+ break;
+ case ModImm:
+ CodeLen=3;
+ BAsmCode[0]=(HReg>=4) ? 0x14+HReg-4 : 0x78+z;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ break;
+ END
+ END
+ else WrError(1350);
+ break;
+ case ModIndReg:
+ case ModIdxReg:
+ case ModDir:
+ case ModMem:
+ OpSize=0;
+ switch (AdrType)
+ BEGIN
+ case ModIndReg:
+ HReg=3;
+ BAsmCode[0]=0xe8+AdrMode; BAsmCode[1]=0x68+z;
+ break;
+ case ModIdxReg:
+ HReg=3+AdrCnt;
+ BAsmCode[0]=0xf4+AdrMode; BAsmCode[1+AdrCnt]=0x68+z;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ break;
+ case ModDir:
+ HReg=4;
+ BAsmCode[0]=0xef; BAsmCode[1]=AdrVals[0]; BAsmCode[2]=0x68+z;
+ break;
+ case ModMem:
+ HReg=5;
+ BAsmCode[0]=0xeb; memcpy(BAsmCode+1,AdrVals,2); BAsmCode[3]=0x68+z;
+ break;
+ default:
+ HReg=0;
+ END
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[HReg-1]=AdrVals[0]; CodeLen=HReg;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((WMemo("INC")) OR (WMemo("DEC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ HReg=Ord(WMemo("DEC")) << 3;
+ DecodeAdr(ArgStr[1],MModReg8+MModReg16+MModIndReg+MModIdxReg+MModDir+MModMem);
+ if (OpSize==-1) OpSize=0;
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ CodeLen=1; BAsmCode[0]=0x80+HReg+AdrMode;
+ break;
+ case ModReg16:
+ CodeLen=1; BAsmCode[0]=0x90+HReg+AdrMode;
+ break;
+ case ModIndReg:
+ CodeLen=2; BAsmCode[0]=0xe0+AdrMode;
+ BAsmCode[1]=0x87+(OpSize << 4)+HReg;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt; BAsmCode[0]=0xf0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x87+(OpSize << 4)+HReg;
+ break;
+ case ModDir:
+ CodeLen=2; BAsmCode[0]=0x87+(OpSize << 4)+HReg;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ case ModMem:
+ CodeLen=4; BAsmCode[0]=0xe3;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[3]=0x87+(OpSize << 4)+HReg;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INCX")) OR (Memo("DECX")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModDir);
+ if (AdrType==ModDir)
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x07+(Ord(Memo("DECX")) << 3);
+ BAsmCode[1]=AdrVals[0];
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MUL")) OR (Memo("DIV")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"HL")!=0) WrError(1350);
+ else
+ BEGIN
+ HReg=0x12+Ord(Memo("DIV")); OpSize=0;
+ DecodeAdr(ArgStr[2],MModReg8+MModIndReg+MModIdxReg+MModDir+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg8:
+ CodeLen=2;
+ BAsmCode[0]=0xf8+AdrMode; BAsmCode[1]=HReg;
+ break;
+ case ModIndReg:
+ CodeLen=2;
+ BAsmCode[0]=0xe0+AdrMode; BAsmCode[1]=HReg;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0xf0+AdrMode; BAsmCode[1+AdrCnt]=HReg;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ break;
+ case ModDir:
+ CodeLen=3; BAsmCode[0]=0xe7;
+ BAsmCode[1]=AdrVals[0]; BAsmCode[2]=HReg;
+ break;
+ case ModMem:
+ CodeLen=4; BAsmCode[0]=0xe3; BAsmCode[3]=HReg;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ break;
+ case ModImm:
+ CodeLen=3; BAsmCode[0]=0xe7; BAsmCode[1]=AdrVals[0]; BAsmCode[2]=HReg;
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if (Memo("JR"))
+ BEGIN
+ if ((ArgCnt==0) OR (ArgCnt>2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1) z=DefaultCondition;
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ for (z=0; z<ConditionCnt; z++)
+ if (strcmp(ArgStr[1],Conditions[z].Name)==0) break;
+ END
+ if (z>=ConditionCnt) WrError(1360);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[ArgCnt],Int16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt>127) OR (AdrInt<-128))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0xc0+Conditions[z].Code;
+ BAsmCode[1]=AdrInt & 0xff;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CALL")) OR (Memo("JP")))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1) z=DefaultCondition;
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ for (z=0; z<ConditionCnt; z++)
+ if (strcmp(Conditions[z].Name,ArgStr[1])==0) break;
+ END
+ if (z>=ConditionCnt) WrError(1360);
+ else
+ BEGIN
+ OpSize=1; HReg=Ord(Memo("CALL"));
+ DecodeAdr(ArgStr[ArgCnt],MModIndReg+MModIdxReg+MModMem+MModImm);
+ if (AdrType==ModImm) AdrType=ModMem;
+ switch (AdrType)
+ BEGIN
+ case ModIndReg:
+ CodeLen=2;
+ BAsmCode[0]=0xe8+AdrMode;
+ BAsmCode[1]=0xc0+(HReg << 4)+Conditions[z].Code;
+ break;
+ case ModIdxReg:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0xf4+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0xc0+(HReg << 4)+Conditions[z].Code;
+ break;
+ case ModMem:
+ if (z==DefaultCondition)
+ BEGIN
+ CodeLen=3;
+ BAsmCode[0]=0x1a+(HReg << 1);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ END
+ else
+ BEGIN
+ CodeLen=4;
+ BAsmCode[0]=0xeb;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[3]=0xc0+(HReg << 4)+Conditions[z].Code;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("RET"))
+ BEGIN
+ if ((ArgCnt!=0) AND (ArgCnt!=1)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==0) z=DefaultCondition;
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ for (z=0; z<ConditionCnt; z++)
+ if (strcmp(ArgStr[1],Conditions[z].Name)==0) break;
+ END
+ if (z>=ConditionCnt) WrError(1360);
+ if (z==DefaultCondition)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x1e;
+ END
+ else if (z<ConditionCnt)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xfe;
+ BAsmCode[1]=0xd0+Conditions[z].Code;
+ END
+ END
+ return;
+ END
+
+ if (Memo("DJNZ"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ AdrType=ModReg8; AdrMode=0; OpSize=0;
+ END
+ else DecodeAdr(ArgStr[1],MModReg8+MModReg16);
+ if (AdrType!=ModNone)
+ if (AdrMode!=0) WrError(1350);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[ArgCnt],Int16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt>127) OR (AdrInt<-128))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x18+OpSize;
+ BAsmCode[1]=AdrInt & 0xff;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JRL")) OR (Memo("CALR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK)-(EProgCounter()+2);
+ if (OK)
+ BEGIN
+ CodeLen=3;
+ if (Memo("JRL"))
+ BEGIN
+ BAsmCode[0]=0x1b;
+ if ((AdrInt>=-128) AND (AdrInt<=127)) WrError(20);
+ END
+ else BAsmCode[0]=0x1d;
+ BAsmCode[1]=Lo(AdrInt); BAsmCode[2]=Hi(AdrInt);
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Code=NCode;
+ AddInstTree(&ITree,NName,CodeFixed,InstrZ++);
+END
+
+ static void AddMove(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=MoveOrderCnt) exit(255);
+ MoveOrders[InstrZ].Code=NCode;
+ AddInstTree(&ITree,NName,CodeMove,InstrZ++);
+END
+
+ static void AddShift(char *NName, Byte NCode, Boolean NMay)
+BEGIN
+ if (InstrZ>=ShiftOrderCnt) exit(255);
+ ShiftOrders[InstrZ].Code=NCode;
+ ShiftOrders[InstrZ].MayReg=NMay;
+ AddInstTree(&ITree,NName,CodeShift,InstrZ++);
+END
+
+ static void AddBit(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=BitOrderCnt) exit(255);
+ BitOrders[InstrZ].Code=NCode;
+ AddInstTree(&ITree,NName,CodeBit,InstrZ++);
+END
+
+ static void AddAcc(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=AccOrderCnt) exit(255);
+ AccOrders[InstrZ].Code=NCode;
+ AddInstTree(&ITree,NName,CodeAcc,InstrZ++);
+END
+
+ static void AddCondition(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ConditionCnt) exit(255);
+ Conditions[InstrZ].Name=NName;
+ Conditions[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ ITree=Nil;
+
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("EXX" ,0x0a); AddFixed("CCF" ,0x0e);
+ AddFixed("SCF" ,0x0d); AddFixed("RCF" ,0x0c);
+ AddFixed("NOP" ,0x00); AddFixed("HALT",0x01);
+ AddFixed("DI" ,0x02); AddFixed("EI" ,0x03);
+ AddFixed("SWI" ,0xff); AddFixed("RLCA",0xa0);
+ AddFixed("RRCA",0xa1); AddFixed("RLA" ,0xa2);
+ AddFixed("RRA" ,0xa3); AddFixed("SLAA",0xa4);
+ AddFixed("SRAA",0xa5); AddFixed("SLLA",0xa6);
+ AddFixed("SRLA",0xa7); AddFixed("RETI",0x1f);
+
+ MoveOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*MoveOrderCnt); InstrZ=0;
+ AddMove("LDI" ,0x58);
+ AddMove("LDIR",0x59);
+ AddMove("LDD" ,0x5a);
+ AddMove("LDDR",0x5b);
+ AddMove("CPI" ,0x5c);
+ AddMove("CPIR",0x5d);
+ AddMove("CPD" ,0x5e);
+ AddMove("CPDR",0x5f);
+
+ ShiftOrders=(ShiftOrder *) malloc(sizeof(ShiftOrder)*ShiftOrderCnt); InstrZ=0;
+ AddShift("RLC",0xa0,True );
+ AddShift("RRC",0xa1,True );
+ AddShift("RL" ,0xa2,True );
+ AddShift("RR" ,0xa3,True );
+ AddShift("SLA",0xa4,True );
+ AddShift("SRA",0xa5,True );
+ AddShift("SLL",0xa6,True );
+ AddShift("SRL",0xa7,True );
+ AddShift("RLD",0x10,False);
+ AddShift("RRD",0x11,False);
+
+ BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCnt); InstrZ=0;
+ AddBit("BIT" ,0xa8);
+ AddBit("SET" ,0xb8);
+ AddBit("RES" ,0xb0);
+ AddBit("TSET",0x18);
+
+ AccOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*AccOrderCnt); InstrZ=0;
+ AddAcc("DAA",0x0b);
+ AddAcc("CPL",0x10);
+ AddAcc("NEG",0x11);
+
+ ALU2Orders=(char **) malloc(sizeof(char *)*ALU2OrderCnt); InstrZ=0;
+ ALU2Orders[InstrZ++]="ADD"; ALU2Orders[InstrZ++]="ADC";
+ ALU2Orders[InstrZ++]="SUB"; ALU2Orders[InstrZ++]="SBC";
+ ALU2Orders[InstrZ++]="AND"; ALU2Orders[InstrZ++]="XOR";
+ ALU2Orders[InstrZ++]="OR"; ALU2Orders[InstrZ++]="CP";
+
+ Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCnt); InstrZ=0;
+ AddCondition("F" , 0); DefaultCondition=InstrZ; AddCondition("T" , 8);
+ AddCondition("Z" , 6); AddCondition("NZ" , 14);
+ AddCondition("C" , 7); AddCondition("NC" , 15);
+ AddCondition("PL" , 13); AddCondition("MI" , 5);
+ AddCondition("P" , 13); AddCondition("M" , 5);
+ AddCondition("NE" , 14); AddCondition("EQ" , 6);
+ AddCondition("OV" , 4); AddCondition("NOV", 12);
+ AddCondition("PE" , 4); AddCondition("PO" , 12);
+ AddCondition("GE" , 9); AddCondition("LT" , 1);
+ AddCondition("GT" , 10); AddCondition("LE" , 2);
+ AddCondition("UGE", 15); AddCondition("ULT", 7);
+ AddCondition("UGT", 11); AddCondition("ULE", 3);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ ClearInstTree(&ITree);
+
+ free(FixedOrders);
+ free(MoveOrders);
+ free(ShiftOrders);
+ free(BitOrders);
+ free(AccOrders);
+ free(ALU2Orders);
+ free(Conditions);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean IsDef_90C141(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_90C141(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_90C141(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=True;
+
+ PCSymbol="$"; HeaderID=0x53; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_90C141; IsDef=IsDef_90C141;
+ SwitchFrom=SwitchFrom_90C141; InitFields();
+END
+
+ void code90c141_init(void)
+BEGIN
+ CPU90C141=AddCPU("90C141",SwitchTo_90C141);
+END
diff --git a/code90c141.h b/code90c141.h
new file mode 100644
index 0000000..3d4f0b6
--- /dev/null
+++ b/code90c141.h
@@ -0,0 +1,11 @@
+/* code90c141.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Toshiba TLCS-90 */
+/* */
+/* Historie: 30.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code90c141_init(void);
diff --git a/code96.c b/code96.c
new file mode 100644
index 0000000..7c13b58
--- /dev/null
+++ b/code96.c
@@ -0,0 +1,1253 @@
+/* code96.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator MCS/96-Familie */
+/* */
+/* Historie: 10.11.1996 */
+/* 16. 3.1997 80196N/80296 */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ CPUVar MinCPU,MaxCPU;
+ } BaseOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ Boolean Reloc;
+ } MacOrder;
+
+#define FixedOrderCnt 16
+
+#define ALU3OrderCnt 5
+
+#define ALU2OrderCnt 9
+
+#define ALU1OrderCnt 6
+
+#define ShiftOrderCnt 3
+
+#define RelOrderCnt 16
+
+#define MacOrderCnt 8
+
+#define RptOrderCnt 34
+
+
+static char *ShiftOrders[ShiftOrderCnt]={"SHR","SHL","SHRA"};
+
+#define ModNone (-1)
+#define ModDir 0
+#define MModDir (1 << ModDir)
+#define ModMem 1
+#define MModMem (1 << ModMem)
+#define ModImm 2
+#define MModImm (1 << ModImm)
+
+#define SFRStart 2
+#define SFRStop 0x17
+
+static BaseOrder *FixedOrders;
+static FixedOrder *ALU3Orders;
+static FixedOrder *ALU2Orders;
+static FixedOrder *ALU1Orders;
+static FixedOrder *RelOrders;
+static MacOrder *MacOrders;
+static FixedOrder *RptOrders;
+
+static CPUVar CPU8096,CPU80196,CPU80196N,CPU80296;
+static SimpProc SaveInitProc;
+
+static Byte AdrMode;
+static ShortInt AdrType;
+static Byte AdrVals[4];
+static ShortInt OpSize;
+
+static LongInt WSRVal,WSR1Val;
+static Word WinStart,WinStop,WinEnd,WinBegin;
+static Word Win1Start,Win1Stop,Win1Begin,Win1End;
+
+IntType MemInt;
+
+/*---------------------------------------------------------------------------*/
+
+
+ static void AddFixed(char *NName, Byte NCode, CPUVar NMin, CPUVar NMax)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ].MinCPU=NMin;
+ FixedOrders[InstrZ++].MaxCPU=NMax;
+END
+
+ static void AddALU3(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ALU3OrderCnt) exit(255);
+ ALU3Orders[InstrZ].Name=NName;
+ ALU3Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU2(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ALU2OrderCnt) exit(255);
+ ALU2Orders[InstrZ].Name=NName;
+ ALU2Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU1(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ALU1OrderCnt) exit(255);
+ ALU1Orders[InstrZ].Name=NName;
+ ALU1Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddRel(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddMac(char *NName, Byte NCode, Boolean NRel)
+BEGIN
+ if (InstrZ>=MacOrderCnt) exit(255);
+ MacOrders[InstrZ].Name=NName;
+ MacOrders[InstrZ].Code=NCode;
+ MacOrders[InstrZ++].Reloc=NRel;
+END
+
+ static void AddRpt(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=RptOrderCnt) exit(255);
+ RptOrders[InstrZ].Name=NName;
+ RptOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("CLRC" ,0xf8,CPU8096 ,CPU80296 );
+ AddFixed("CLRVT",0xfc,CPU8096 ,CPU80296 );
+ AddFixed("DI" ,0xfa,CPU8096 ,CPU80296 );
+ AddFixed("DPTS" ,0xea,CPU80196 ,CPU80196N);
+ AddFixed("EI" ,0xfb,CPU8096 ,CPU80296 );
+ AddFixed("EPTS" ,0xeb,CPU80196 ,CPU80196N);
+ AddFixed("NOP" ,0xfd,CPU8096 ,CPU80296 );
+ AddFixed("POPA" ,0xf5,CPU80196 ,CPU80296 );
+ AddFixed("POPF" ,0xf3,CPU8096 ,CPU80296 );
+ AddFixed("PUSHA",0xf4,CPU80196 ,CPU80296 );
+ AddFixed("PUSHF",0xf2,CPU8096 ,CPU80296 );
+ AddFixed("RET" ,0xf0,CPU8096 ,CPU80296 );
+ AddFixed("RSC" ,0xff,CPU8096 ,CPU80296 );
+ AddFixed("SETC" ,0xf9,CPU8096 ,CPU80296 );
+ AddFixed("TRAP" ,0xf7,CPU8096 ,CPU80296 );
+ AddFixed("RETI" ,0xe5,CPU80196N,CPU80296 );
+
+ ALU3Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU3OrderCnt); InstrZ=0;
+ AddALU3("ADD" , 0x01);
+ AddALU3("AND" , 0x00);
+ AddALU3("MUL" , 0x83); /* ** */
+ AddALU3("MULU", 0x03);
+ AddALU3("SUB" , 0x02);
+
+ ALU2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU2OrderCnt); InstrZ=0;
+ AddALU2("ADDC", 0xa4);
+ AddALU2("CMP" , 0x88);
+ AddALU2("DIV" , 0x8c); /* ** */
+ AddALU2("DIVU", 0x8c);
+ AddALU2("LD" , 0xa0);
+ AddALU2("OR" , 0x80);
+ AddALU2("ST" , 0xc0);
+ AddALU2("SUBC", 0xa8);
+ AddALU2("XOR" , 0x84);
+
+ ALU1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU1OrderCnt); InstrZ=0;
+ AddALU1("CLR", 0x01);
+ AddALU1("DEC", 0x05);
+ AddALU1("EXT", 0x06);
+ AddALU1("INC", 0x07);
+ AddALU1("NEG", 0x03);
+ AddALU1("NOT", 0x02);
+
+ RelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("JC" , 0xdb);
+ AddRel("JE" , 0xdf);
+ AddRel("JGE" , 0xd6);
+ AddRel("JGT" , 0xd2);
+ AddRel("JH" , 0xd9);
+ AddRel("JLE" , 0xda);
+ AddRel("JLT" , 0xde);
+ AddRel("JNC" , 0xd3);
+ AddRel("JNE" , 0xd7);
+ AddRel("JNH" , 0xd1);
+ AddRel("JNST" , 0xd0);
+ AddRel("JNV" , 0xd5);
+ AddRel("JNVT" , 0xd4);
+ AddRel("JST" , 0xd8);
+ AddRel("JV" , 0xdd);
+ AddRel("JVT" , 0xdc);
+
+ MacOrders=(MacOrder *) malloc(sizeof(MacOrder)*MacOrderCnt); InstrZ=0;
+ AddMac("MAC" ,0x00,False); AddMac("SMAC" ,0x01,False);
+ AddMac("MACR" ,0x04,True ); AddMac("SMACR" ,0x05,True );
+ AddMac("MACZ" ,0x08,False); AddMac("SMACZ" ,0x09,False);
+ AddMac("MACRZ" ,0x0c,True ); AddMac("SMACRZ",0x0d,True );
+
+ RptOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RptOrderCnt); InstrZ=0;
+ AddRpt("RPT" ,0x00); AddRpt("RPTNST" ,0x10); AddRpt("RPTNH" ,0x11);
+ AddRpt("RPTGT" ,0x12); AddRpt("RPTNC" ,0x13); AddRpt("RPTNVT" ,0x14);
+ AddRpt("RPTNV" ,0x15); AddRpt("RPTGE" ,0x16); AddRpt("RPTNE" ,0x17);
+ AddRpt("RPTST" ,0x18); AddRpt("RPTH" ,0x19); AddRpt("RPTLE" ,0x1a);
+ AddRpt("RPTC" ,0x1b); AddRpt("RPTVT" ,0x1c); AddRpt("RPTV" ,0x1d);
+ AddRpt("RPTLT" ,0x1e); AddRpt("RPTE" ,0x1f); AddRpt("RPTI" ,0x20);
+ AddRpt("RPTINST",0x30); AddRpt("RPTINH" ,0x31); AddRpt("RPTIGT" ,0x32);
+ AddRpt("RPTINC" ,0x33); AddRpt("RPTINVT",0x34); AddRpt("RPTINV" ,0x35);
+ AddRpt("RPTIGE" ,0x36); AddRpt("RPTINE" ,0x37); AddRpt("RPTIST" ,0x38);
+ AddRpt("RPTIH" ,0x39); AddRpt("RPTILE" ,0x3a); AddRpt("RPTIC" ,0x3b);
+ AddRpt("RPTIVT" ,0x3c); AddRpt("RPTIV" ,0x3d); AddRpt("RPTILT" ,0x3e);
+ AddRpt("RPTIE" ,0x3f);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(ALU3Orders);
+ free(ALU2Orders);
+ free(ALU1Orders);
+ free(RelOrders);
+ free(MacOrders);
+ free(RptOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void ChkSFR(Word Adr)
+BEGIN
+ if ((Adr>=SFRStart) & (Adr<=SFRStop)) WrError(190);
+END
+
+ static void Chk296(Word Adr)
+BEGIN
+ if ((MomCPU==CPU80296) AND (Adr<=1)) WrError(190);
+END
+
+ static Boolean ChkWork(Word *Adr)
+BEGIN
+ /* Registeradresse, die von Fenstern ueberdeckt wird ? */
+
+ if ((*Adr>=WinBegin) AND (*Adr<=WinEnd)) return False;
+
+ else if ((*Adr>=Win1Begin) AND (*Adr<=Win1End)) return False;
+
+ /* Speicheradresse in Fenster ? */
+
+ else if ((*Adr>=WinStart) AND (*Adr<=WinStop))
+ BEGIN
+ *Adr=(*Adr)-WinStart+WinBegin; return True;
+ END
+
+ else if ((*Adr>=Win1Start) AND (*Adr<=Win1Stop))
+ BEGIN
+ *Adr=(*Adr)-Win1Start+Win1Begin; return True;
+ END
+
+ /* Default */
+
+ else return (*Adr<=0xff);
+END
+
+ static void ChkAlign(Byte Adr)
+BEGIN
+ if (((OpSize==0) AND ((Adr & 1)!=0))
+ OR ((OpSize==1) AND ((Adr & 3)!=0))) WrError(180);
+END
+
+ static void ChkAdr(Byte Mask)
+BEGIN
+ if ((AdrType==ModDir) AND ((Mask & MModDir)==0))
+ BEGIN
+ AdrType=ModMem; AdrMode=0;
+ END
+
+ if ((AdrType!=ModNone) AND ((Mask & (1 << AdrType))==0))
+ BEGIN
+ WrError(1350); AdrType=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Byte Mask, Boolean AddrWide)
+BEGIN
+ LongInt AdrInt;
+ LongWord AdrWord;
+ Word BReg;
+ Boolean OK;
+ char *p,*p2;
+ int l;
+ Byte Reg;
+ LongWord OMask;
+
+ AdrType=ModNone; AdrCnt=0;
+ OMask=(1 << OpSize)-1;
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1132); break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=1; AdrMode=1;
+ END
+ break;
+ case 1:
+ AdrWord=EvalIntExpression(Asc+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=2; AdrMode=1;
+ AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord);
+ END
+ break;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ p=QuotPos(Asc,'[');
+ if (p!=Nil)
+ BEGIN
+ p2=RQuotPos(Asc,']'); l=strlen(Asc);
+ if ((p2>Asc+l-1) OR (p2<Asc+l-2)) WrError(1350);
+ else
+ BEGIN
+ FirstPassUnknown=False; *p2='\0';
+ BReg=EvalIntExpression(p+1,Int16,&OK);
+ if (FirstPassUnknown) BReg=0;
+ if (OK)
+ if (NOT ChkWork(&BReg)) WrError(1320);
+ else
+ BEGIN
+ Reg=Lo(BReg); ChkSFR(Reg);
+ if ((Reg&1)==1) WrError(1351);
+ else if ((p==Asc) AND (p2==Asc+l-2) AND (Asc[l-1]=='+'))
+ BEGIN
+ AdrType=ModMem; AdrMode=2; AdrCnt=1; AdrVals[0]=Reg+1;
+ END
+ else if (p2!=Asc+l-1) WrError(1350);
+ else if (p==Asc)
+ BEGIN
+ AdrType=ModMem; AdrMode=2; AdrCnt=1; AdrVals[0]=Reg;
+ END
+ else
+ BEGIN
+ *p='\0';
+ if (NOT AddrWide) AdrInt=EvalIntExpression(Asc,Int16,&OK);
+ else AdrInt=EvalIntExpression(Asc,Int24,&OK);
+ if (OK)
+ if (AdrInt==0)
+ BEGIN
+ AdrType=ModMem; AdrMode=2; AdrCnt=1; AdrVals[0]=Reg;
+ END
+ else if (AddrWide)
+ BEGIN
+ AdrType=ModMem; AdrMode=3; AdrCnt=4;
+ AdrVals[0]=Reg; AdrVals[1]=AdrInt & 0xff;
+ AdrVals[2]=(AdrInt >> 8) & 0xff;
+ AdrVals[3]=(AdrInt >> 16) & 0xff;
+ END
+ else if ((AdrInt>=-128) AND (AdrInt<127))
+ BEGIN
+ AdrType=ModMem; AdrMode=3; AdrCnt=2;
+ AdrVals[0]=Reg; AdrVals[1]=Lo(AdrInt);
+ END
+ else
+ BEGIN
+ AdrType=ModMem; AdrMode=3; AdrCnt=3;
+ AdrVals[0]=Reg+1; AdrVals[1]=Lo(AdrInt); AdrVals[2]=Hi(AdrInt);
+ END
+ END
+ END
+ END
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrWord=EvalIntExpression(Asc,MemInt,&OK);
+ if (FirstPassUnknown) AdrWord&=(0xffffffff-OMask);
+ if (OK)
+ if ((AdrWord & OMask)!=0) WrError(1325);
+ else
+ BEGIN
+ BReg=AdrWord & 0xffff;
+ if (((BReg & 0xffff0000)==0) AND (ChkWork(&BReg)))
+ BEGIN
+ AdrType=ModDir; AdrCnt=1; AdrVals[0]=Lo(BReg);
+ END
+ else if (AddrWide)
+ BEGIN
+ AdrType=ModMem; AdrMode=3; AdrCnt=4; AdrVals[0]=0;
+ AdrVals[1]=AdrWord & 0xff;
+ AdrVals[2]=(AdrWord >> 8) & 0xff;
+ AdrVals[3]=(AdrWord >> 16) & 0xff;
+ END
+ else if (AdrWord>=0xff80)
+ BEGIN
+ AdrType=ModMem; AdrMode=3; AdrCnt=2; AdrVals[0]=0;
+ AdrVals[1]=Lo(AdrWord);
+ END
+ else
+ BEGIN
+ AdrType=ModMem; AdrMode=3; AdrCnt=3; AdrVals[0]=1;
+ AdrVals[1]=Lo(AdrWord); AdrVals[2]=Hi(AdrWord);
+ END
+ END
+ END
+
+ ChkAdr(Mask);
+END
+
+ static void CalcWSRWindow(void)
+BEGIN
+ if (WSRVal<=0x0f)
+ BEGIN
+ WinStart=0xffff; WinStop=0; WinBegin=0xff; WinEnd=0;
+ END
+ else if (WSRVal<=0x1f)
+ BEGIN
+ WinBegin=0x80; WinEnd=0xff;
+ if (WSRVal<0x18) WinStart=(WSRVal-0x10) << 7;
+ else WinStart=(WSRVal+0x20) << 7;
+ WinStop=WinStart+0x7f;
+ END
+ else if (WSRVal<=0x3f)
+ BEGIN
+ WinBegin=0xc0; WinEnd=0xff;
+ if (WSRVal<0x30) WinStart=(WSRVal-0x20) << 6;
+ else WinStart=(WSRVal+0x40) << 6;
+ WinStop=WinStart+0x3f;
+ END
+ else if (WSRVal<=0x7f)
+ BEGIN
+ WinBegin=0xe0; WinEnd=0xff;
+ if (WSRVal<0x60) WinStart=(WSRVal-0x40) << 5;
+ else WinStart=(WSRVal+0x80) << 5;
+ WinStop=WinStart+0x1f;
+ END
+ if ((WinStop>0x1fdf) AND (MomCPU<CPU80296)) WinStop=0x1fdf;
+END
+
+ static void CalcWSR1Window(void)
+BEGIN
+ if (WSR1Val<=0x1f)
+ BEGIN
+ Win1Start=0xffff; Win1Stop=0; Win1Begin=0xff; Win1End=0;
+ END
+ else if (WSR1Val<=0x3f)
+ BEGIN
+ Win1Begin=0x40; Win1End=0x7f;
+ if (WSR1Val<0x30) Win1Start=(WSR1Val-0x20) << 6;
+ else Win1Start=(WSR1Val+0x40) << 6;
+ Win1Stop=Win1Start+0x3f;
+ END
+ else if (WSR1Val<=0x7f)
+ BEGIN
+ Win1Begin=0x60; Win1End=0x7f;
+ if (WSR1Val<0x60) Win1Start=(WSR1Val-0x40) << 5;
+ else Win1Start=(WSR1Val+0x80) << 5;
+ Win1Stop=Win1Start+0x1f;
+ END
+ else
+ BEGIN
+ Win1Begin=0x40; Win1End=0x7f;
+ Win1Start=(WSR1Val+0x340) << 6;
+ Win1Stop=Win1Start+0x3f;
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME96Count 2
+ static ASSUMERec ASSUME96s[ASSUME96Count]=
+ {{"WSR", &WSRVal, 0, 0xff, 0x00},
+ {"WSR1", &WSR1Val, 0, 0xbf, 0x00}};
+
+ if (Memo("ASSUME"))
+ BEGIN
+ if (MomCPU<CPU80196) WrError(1500);
+ else CodeASSUME(ASSUME96s,(MomCPU>=CPU80296)?ASSUME96Count:1);
+ WSRVal&=0x7f;
+ CalcWSRWindow(); CalcWSR1Window();
+ return True;
+ END
+
+ return False;
+END
+
+ static Boolean BMemo(char *Name)
+BEGIN
+ int l;
+
+ if (strncmp(OpPart,Name,l=strlen(Name))!=0) return False;
+ switch (OpPart[l])
+ BEGIN
+ case '\0':
+ OpSize=1; return True;
+ case 'B':
+ if (OpPart[l+1]=='\0')
+ BEGIN
+ OpSize=0; return True;
+ END
+ else return False;
+ default:
+ return False;
+ END
+END
+
+ static Boolean LMemo(char *Name)
+BEGIN
+ int l;
+
+ if (strncmp(OpPart,Name,l=strlen(Name))!=0) return False;
+ switch (OpPart[l])
+ BEGIN
+ case '\0':
+ OpSize=1; return True;
+ case 'B':
+ if (OpPart[l+1]=='\0')
+ BEGIN
+ OpSize=0; return True;
+ END
+ else return False;
+ case 'L':
+ if (OpPart[l+1]=='\0')
+ BEGIN
+ OpSize=2; return True;
+ END
+ else return False;
+ default:
+ return False;
+ END
+END
+
+ static void MakeCode_96(void)
+BEGIN
+ Boolean OK,Special,IsShort;
+ Word AdrWord;
+ int z;
+ LongInt AdrInt;
+ Byte Start,HReg,Mask;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<FixedOrders[z].MinCPU) WrError(1500);
+ else BAsmCode[(CodeLen=1)-1]=FixedOrders[z].Code;
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<ALU3OrderCnt; z++)
+ if (BMemo(ALU3Orders[z].Name))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
+ else
+ BEGIN
+ Start=0; Special=(strncmp(ALU3Orders[z].Name,"MUL",3)==0);
+ if ((ALU3Orders[z].Code & 0x80)!=0) BAsmCode[Start++]=0xfe;
+ BAsmCode[Start++]=0x40+(Ord(ArgCnt==2) << 5)
+ +((1-OpSize) << 4)
+ +((ALU3Orders[z].Code & 0x7f) << 2);
+ DecodeAdr(ArgStr[ArgCnt],MModImm+MModMem,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[Start-1]+=AdrMode;
+ memcpy(BAsmCode+Start,AdrVals,AdrCnt); Start+=AdrCnt;
+ if ((Special) AND (AdrMode==0)) ChkSFR(AdrVals[0]);
+ if (ArgCnt==3)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModDir,False);
+ OK=(AdrType!=ModNone);
+ if (OK)
+ BEGIN
+ BAsmCode[Start++]=AdrVals[0];
+ if (Special) ChkSFR(AdrVals[0]);
+ END
+ END
+ else OK=True;
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[Start]=AdrVals[0]; CodeLen=Start+1;
+ if (Special)
+ BEGIN
+ ChkSFR(AdrVals[0]);
+ Chk296(AdrVals[0]);
+ ChkAlign(AdrVals[0]);
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ALU2OrderCnt; z++)
+ if (BMemo(ALU2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ Start=0; Special=(strncmp(OpPart,"DIV",3)==0);
+ if (strcmp(ALU2Orders[z].Name,"DIV")==0) BAsmCode[Start++]=0xfe;
+ HReg=(1+Ord(strcmp(ALU2Orders[z].Name,"ST")!=0)) << 1;
+ BAsmCode[Start++]=ALU2Orders[z].Code+((1-OpSize) << HReg);
+ Mask=MModMem; if (NOT BMemo("ST")) Mask+=MModImm;
+ DecodeAdr(ArgStr[2],Mask,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[Start-1]+=AdrMode;
+ memcpy(BAsmCode+Start,AdrVals,AdrCnt); Start+=AdrCnt;
+ if ((Special) AND (AdrMode==0)) ChkSFR(AdrVals[0]);
+ DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[Start]=AdrVals[0]; CodeLen=1+Start;
+ if (Special)
+ BEGIN
+ ChkSFR(AdrVals[0]); ChkAlign(AdrVals[0]);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CMPL"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80196) WrError(1500);
+ else
+ BEGIN
+ OpSize=2;
+ DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[1]=AdrVals[0]; BAsmCode[0]=0xc5; CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ OpSize=1;
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Mask=MModMem; if (Memo("PUSH")) Mask+=MModImm;
+ DecodeAdr(ArgStr[1],Mask,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1+AdrCnt;
+ BAsmCode[0]=0xc8+AdrMode+(Ord(Memo("POP")) << 2);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BMOV")) OR (Memo("BMOVI")) OR (Memo("EBMOVI")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80196) WrError(1500);
+ else if ((MomCPU<CPU80196N) AND (Memo("EBMOVI"))) WrError(1500);
+ else
+ BEGIN
+ OpSize=2; DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[2]=AdrVals[0];
+ OpSize=1; DecodeAdr(ArgStr[2],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[1]=AdrVals[0];
+ if (Memo("BMOVI")) BAsmCode[0]=0xad;
+ else if (Memo("BMOV")) BAsmCode[0]=0xc1;
+ else BAsmCode[0]=0xe4;
+ CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ALU1OrderCnt; z++)
+ if (BMemo(ALU1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1+AdrCnt;
+ BAsmCode[0]=ALU1Orders[z].Code+((1-OpSize) << 4);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ if (BMemo("EXT")) ChkAlign(AdrVals[0]);
+ END
+ END
+ return;
+ END
+
+ if (BMemo("XCH"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80196) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMem+MModDir,False);
+ switch (AdrType)
+ BEGIN
+ case ModMem:
+ if (AdrMode==1) WrError(1350);
+ else
+ BEGIN
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); HReg=AdrCnt;
+ BAsmCode[0]=0x04+((1-OpSize) << 4)+AdrMode;
+ DecodeAdr(ArgStr[2],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[1+HReg]=AdrVals[0]; CodeLen=2+HReg;
+ END
+ END
+ break;
+ case ModDir:
+ HReg=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModMem,False);
+ if (AdrType!=ModNone)
+ if (AdrMode==1) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x04+((1-OpSize) << 4)+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=HReg; CodeLen=2+AdrCnt;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDBZE")) OR (Memo("LDBSE")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OpSize=0;
+ DecodeAdr(ArgStr[2],MModMem+MModImm,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xac+(Ord(Memo("LDBSE")) << 4)+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); Start=1+AdrCnt;
+ OpSize=1; DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[Start]=AdrVals[0]; CodeLen=1+Start;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("NORML"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[2],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[1]=AdrVals[0];
+ OpSize=1; DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x0f; BAsmCode[2]=AdrVals[0];
+ ChkAlign(AdrVals[0]);
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("IDLPD"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU80196) WrError(1500);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[1],MModImm,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xf6; BAsmCode[1]=AdrVals[0];
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ShiftOrderCnt; z++)
+ if (LMemo(ShiftOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x08+z+(Ord(OpSize==0) << 4)+(Ord(OpSize==2) << 2);
+ BAsmCode[2]=AdrVals[0];
+ OpSize=0; DecodeAdr(ArgStr[2],MModDir+MModImm,False);
+ if (AdrType!=ModNone)
+ if ((AdrType==ModImm) AND (AdrVals[0]>15)) WrError(1320);
+ else if ((AdrType==ModDir) AND (AdrVals[0]<16)) WrError(1315);
+ else
+ BEGIN
+ BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("SKIP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0; BAsmCode[1]=AdrVals[0];
+ END
+ END
+ return;
+ END
+
+ if ((BMemo("ELD")) OR (BMemo("EST")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80196N) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModMem,True);
+ if (AdrType==ModMem)
+ if ((AdrMode==2) AND (Odd(AdrVals[0]))) WrError(1350); /* kein Autoincrement */
+ else
+ BEGIN
+ BAsmCode[0]=(AdrMode & 1)+((1-OpSize) << 1);
+ if (OpPart[1]=='L') BAsmCode[0]+=0xe8;
+ else BAsmCode[0]+=0x1c;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); HReg=1+AdrCnt;
+ DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType==ModDir)
+ BEGIN
+ BAsmCode[HReg]=AdrVals[0]; CodeLen=HReg+1;
+ END;
+ END;
+ END;
+ return;
+ END
+
+ for (z=0; z<MacOrderCnt; z++)
+ if (Memo(MacOrders[z].Name))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if (MomCPU<CPU80296) WrError(1500);
+ else
+ BEGIN
+ OpSize=1; BAsmCode[0]=0x4c+(Ord(ArgCnt==1) << 5);
+ if (MacOrders[z].Reloc) DecodeAdr(ArgStr[ArgCnt],MModMem,False);
+ else DecodeAdr(ArgStr[ArgCnt],MModMem+MModImm,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]+=AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); HReg=1+AdrCnt;
+ if (ArgCnt==2)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType==ModDir)
+ BEGIN
+ BAsmCode[HReg]=AdrVals[0]; HReg++;
+ END
+ END
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[HReg]=MacOrders[z].Code; CodeLen=1+HReg;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MVAC")) OR (Memo("MSAC")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU80296) WrError(1500);
+ else
+ BEGIN
+ OpSize=2; DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType==ModDir)
+ BEGIN
+ BAsmCode[0]=0x0d; BAsmCode[2]=AdrVals[0]+1+(Ord(Memo("MSAC")) << 1);
+ OpSize=0; DecodeAdr(ArgStr[2],MModImm+MModDir,False);
+ BAsmCode[1]=AdrVals[0];
+ switch (AdrType)
+ BEGIN
+ case ModImm:
+ if (AdrVals[0]>31) WrError(1320); else CodeLen=3;
+ break;
+ case ModDir:
+ if (AdrVals[0]<32) WrError(1315); else CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<RptOrderCnt; z++)
+ if (Memo(RptOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU80296) WrError(1500);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[1],MModImm+MModMem,False);
+ if (AdrType!=ModNone)
+ if (AdrMode==3) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x40+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=RptOrders[z].Code;
+ BAsmCode[2+AdrCnt]=4;
+ CodeLen=3+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ for (z=0; z<RelOrderCnt; z++)
+ if (Memo(RelOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],MemInt,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=RelOrders[z].Code; BAsmCode[1]=AdrInt & 0xff;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("SCALL")) OR (Memo("LCALL")) OR (Memo("CALL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],MemInt,&OK);
+ if (OK)
+ BEGIN
+ AdrInt=AdrWord-(EProgCounter()+2);
+ if (Memo("SCALL")) IsShort=True;
+ else if (Memo("LCALL")) IsShort=False;
+ else IsShort=((AdrInt>=-1024) AND (AdrInt<1023));
+ if (IsShort)
+ BEGIN
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-1024) OR (AdrInt>1023))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[1]=AdrInt & 0xff;
+ BAsmCode[0]=0x28+((AdrInt & 0x700) >> 8);
+ END
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xef; AdrInt--;
+ BAsmCode[1]=Lo(AdrInt); BAsmCode[2]=Hi(AdrInt);
+ if ((NOT SymbolQuestionable) AND (AdrInt>=-1024) AND (AdrInt<=1023)) WrError(20);
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BR")) OR (Memo("LJMP")) OR (Memo("SJMP")))
+ BEGIN
+ OpSize=1;
+ if (ArgCnt!=1) WrError(1110);
+ else if ((Memo("BR")) AND (QuotPos(ArgStr[1],'[')!=Nil))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMem,False);
+ if (AdrType!=ModNone)
+ if ((AdrMode!=2) OR ((AdrVals[0]&1)==1)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xe3; BAsmCode[1]=AdrVals[0];
+ END
+ END
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],MemInt,&OK);
+ if (OK)
+ BEGIN
+ AdrInt=AdrWord-(EProgCounter()+2);
+ if (Memo("SJMP")) IsShort=True;
+ else if (Memo("LJMP")) IsShort=False;
+ else IsShort=((AdrInt>=-1024) AND (AdrInt<1023));
+ if (IsShort)
+ BEGIN
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-1024) OR (AdrInt>1023))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[1]=AdrInt & 0xff;
+ BAsmCode[0]=0x20+((AdrInt & 0x700) >> 8);
+ END
+ END
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xe7; AdrInt--;
+ BAsmCode[1]=Lo(AdrInt); BAsmCode[2]=Hi(AdrInt);
+ if ((NOT SymbolQuestionable) AND (AdrInt>=-1024) AND (AdrInt<=1023)) WrError(20);
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("TIJMP"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (MomCPU<CPU80196) WrError(1500);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[3]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[1]=AdrVals[0];
+ OpSize=0; DecodeAdr(ArgStr[3],MModImm,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[2]=AdrVals[0]; BAsmCode[0]=0xe2; CodeLen=4;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("DJNZ")) OR (Memo("DJNZW")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if ((Memo("DJNZW")) AND (MomCPU<CPU80196)) WrError(1500);
+ else
+ BEGIN
+ OpSize=Ord(Memo("DJNZW"));
+ DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xe0+OpSize; BAsmCode[1]=AdrVals[0];
+ AdrInt=EvalIntExpression(ArgStr[2],MemInt,&OK)-(EProgCounter()+3);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[2]=AdrInt & 0xff;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JBC")) OR (Memo("JBS")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=EvalIntExpression(ArgStr[2],UInt3,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]+=0x30+(Ord(Memo("JBS")) << 3);
+ OpSize=0; DecodeAdr(ArgStr[1],MModDir,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[1]=AdrVals[0];
+ AdrInt=EvalIntExpression(ArgStr[3],MemInt,&OK)-(EProgCounter()+3);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[2]=AdrInt & 0xff;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("ECALL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU80196N) WrError(1500);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],MemInt,&OK)-(EProgCounter()+4);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xf1;
+ BAsmCode[1]=AdrInt & 0xff;
+ BAsmCode[2]=(AdrInt >> 8) & 0xff;
+ BAsmCode[3]=(AdrInt >> 16) & 0xff;
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("EJMP")) OR (Memo("EBR")))
+ BEGIN
+ OpSize=1;
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU80196N) WrError(1500);
+ else if (*ArgStr[1]=='[')
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMem,False);
+ if (AdrType==ModMem)
+ if (AdrMode!=2) WrError(1350);
+ else if (Odd(AdrVals[0])) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xe3; BAsmCode[1]=AdrVals[0]+1;
+ CodeLen=2;
+ END
+ END
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],MemInt,&OK)-(EProgCounter()+4);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xe6;
+ BAsmCode[1]=AdrInt & 0xff;
+ BAsmCode[2]=(AdrInt >> 8) & 0xff;
+ BAsmCode[3]=(AdrInt >> 16) & 0xff;
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_96(void)
+BEGIN
+ SaveInitProc();
+ WSRVal=0; CalcWSRWindow();
+ WSR1Val=0; CalcWSR1Window();
+END
+
+ static Boolean IsDef_96(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_96(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_96(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x39; NOPCode=0xfd;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
+ SegLimits[SegCode] = (MomCPU >= CPU80196N) ? 0xffffffl : 0xffff;
+
+ MakeCode=MakeCode_96; IsDef=IsDef_96;
+ SwitchFrom=SwitchFrom_96;
+
+ if (MomCPU>=CPU80196N) MemInt=UInt24;
+ else MemInt=UInt16;
+
+ InitFields();
+END
+
+ void code96_init(void)
+BEGIN
+ CPU8096 =AddCPU("8096" ,SwitchTo_96);
+ CPU80196 =AddCPU("80196" ,SwitchTo_96);
+ CPU80196N=AddCPU("80196N",SwitchTo_96);
+ CPU80296 =AddCPU("80296" ,SwitchTo_96);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_96;
+END
diff --git a/code96.h b/code96.h
new file mode 100644
index 0000000..81e7f17
--- /dev/null
+++ b/code96.h
@@ -0,0 +1,11 @@
+/* code96.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator MCS/96-Familie */
+/* */
+/* Historie: 10.11.1996 */
+/* */
+/*****************************************************************************/
+
+extern void code96_init(void);
diff --git a/code960.c b/code960.c
new file mode 100644
index 0000000..2c46857
--- /dev/null
+++ b/code960.c
@@ -0,0 +1,767 @@
+/* code960.c */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Codegenerator i960-Familie */
+/* */
+/* Historie: 24. 8.1998 angelegt */
+/* 25. 8.1998 Register-Format */
+/* 27. 8.1998 Reg-Struktur hat getrennte Operandentypen */
+/* Fixed+COBR-Anweisungen */
+/* 28. 8.1998 CTRL-Anweisungen */
+/* MEM-Anweisungen */
+/* MODPC privilegiert gemacht */
+/* Sonderregisternamen */
+/* nicht ausgerichtete Instruktionen anmeckern */
+/* 29. 8.1998 Abfrage Id per headerid-Modul */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* 23. 1.1999 Unsauberkeit in Zuweisung (-1 an unsigned) beseitigt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "endian.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "asmitree.h"
+#include "codepseudo.h"
+#include "headids.h"
+
+/*--------------------------------------------------------------------------*/
+
+#define ModNone -1
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModFReg 1
+#define MModFReg (1 << ModFReg)
+#define ModImm 2
+#define MModImm (1 << ModImm)
+
+#define FixedOrderCnt 13
+#define RegOrderCnt 116
+#define CobrOrderCnt 24
+#define CtrlOrderCnt 11
+#define MemOrderCnt 20
+#define SpecRegCnt 4
+
+typedef enum {NoneOp,IntOp,LongOp,QuadOp,SingleOp,DoubleOp,ExtOp,OpCnt} OpType;
+
+static LongWord OpMasks[OpCnt]={0xffffffff,0,1,3,0,1,3};
+
+typedef struct
+ {
+ LongWord Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ LongWord Code;
+ Boolean HasSrc;
+ } CobrOrder;
+
+typedef struct
+ {
+ LongWord Code;
+ OpType Src1Type,Src2Type,DestType;
+ Boolean Imm1,Imm2;
+ } RegOrder;
+
+typedef struct
+ {
+ LongWord Code;
+ OpType Type;
+ ShortInt RegPos;
+ } MemOrder;
+
+typedef struct
+ {
+ char *Name;
+ LongWord Code;
+ } SpecReg;
+
+static PInstTable InstTable;
+static FixedOrder *FixedOrders;
+static RegOrder *RegOrders;
+static CobrOrder *CobrOrders;
+static FixedOrder *CtrlOrders;
+static MemOrder *MemOrders;
+static SpecReg *SpecRegs;
+
+static CPUVar CPU80960;
+static TSwitchProc SaveInitProc;
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean ChkAdr(int AMode, Byte Mask, LongWord *Erg, LongWord *Mode)
+BEGIN
+ if ((Mask & (1<<AMode))==0)
+ BEGIN
+ WrError(1350); return False;
+ END
+ else
+ BEGIN
+ *Mode=(AMode!=ModReg); return True;
+ END
+END
+
+ static Boolean DecodeIReg(char *Asc, LongWord *Erg)
+BEGIN
+ int z;
+ char *end;
+
+ for (z=0; z<SpecRegCnt; z++)
+ if (strcasecmp(Asc,SpecRegs[z].Name)==0)
+ BEGIN
+ *Erg=SpecRegs[z].Code; return True;
+ END
+
+ if ((toupper(*Asc)=='G') OR (toupper(*Asc)=='R'))
+ BEGIN
+ *Erg=strtol(Asc+1,&end,10);
+ if ((*end=='\0') AND (*Erg<=15))
+ BEGIN
+ if (toupper(*Asc)=='G') *Erg+=16;
+ return TRUE;
+ END
+ END
+
+ return False;
+END
+
+ static Boolean DecodeAdr(char *Asc, Byte Mask, OpType Type, LongWord *Erg, LongWord *Mode)
+BEGIN
+ char *end;
+ Double FVal;
+ Boolean OK;
+
+ *Mode=ModNone; *Erg=0;
+
+ if (DecodeIReg(Asc,Erg))
+ BEGIN
+ if (((*Erg)&OpMasks[Type])!=0)
+ BEGIN
+ WrXError(1760,Asc); return False;
+ END
+ else return ChkAdr(ModReg,Mask,Erg,Mode);
+ END
+
+ if (strncasecmp(Asc,"FP",2)==0)
+ BEGIN
+ *Erg=strtol(Asc+2,&end,10);
+ if ((*end=='\0') AND (*Erg<=3))
+ return ChkAdr(ModFReg,Mask,Erg,Mode);
+ END
+
+ if (Type!=IntOp)
+ BEGIN
+ FirstPassUnknown=False;
+ FVal=EvalFloatExpression(Asc,Float64,&OK);
+ if (OK)
+ BEGIN
+ if (FirstPassUnknown) FVal=0.0;
+ if (FVal==0.0) *Erg=16;
+ else if (FVal==1.0) *Erg=22;
+ else { WrError(1320); OK=False; }
+ if (OK) return ChkAdr(ModImm,Mask,Erg,Mode);
+ END
+ END
+ else
+ BEGIN
+ *Erg=EvalIntExpression(Asc,UInt5,&OK);
+ if (OK) return ChkAdr(ModImm,Mask,Erg,Mode);
+ END
+ return False;
+END
+
+#define NOREG 33
+#define IPREG 32
+
+ static int AddrError(int Num)
+BEGIN
+ WrError(Num); return -1;
+END
+
+ static int AddrXError(int Num, char *Param)
+BEGIN
+ WrXError(Num,Param); return -1;
+END
+
+ static int DecodeMem(char *Asc, LongWord *Erg, LongWord *Ext)
+BEGIN
+ LongInt DispAcc;
+ LongWord Base,Index,Scale,Mode;
+ Boolean Done;
+ int l,Scale2;
+ char *p,*p2,*end;
+ Boolean OK;
+
+ Base=Index=NOREG; Scale=0;
+
+ /* Register abhobeln */
+
+ Done=FALSE;
+ do
+ BEGIN
+ l=strlen(Asc);
+ if (l==0) Done=True;
+ else switch (Asc[l-1])
+ BEGIN
+ case ']':
+ if (Index!=NOREG) return AddrError(1350);
+ for (p=Asc+l-1; p>=Asc; p--)
+ if (*p=='[') break;
+ if (p<Asc) return AddrError(1300);
+ *(p++)='\0'; Asc[l-1]='\0';
+ p2=strchr(p,'*');
+ if (p2!=Nil)
+ BEGIN
+ *p2='\0';
+ Scale2=strtol(p2+1,&end,10);
+ if (*end!='\0') return AddrError(1350);
+ for (Scale=0; Scale<5; Scale++,Scale2=Scale2>>1)
+ if (Odd(Scale2)) break;
+ if (Scale2!=1) return AddrError(1350);
+ END
+ if (NOT DecodeIReg(p,&Index)) return AddrXError(1445,p);
+ break;
+ case ')':
+ if (Base!=NOREG) return AddrError(1350);
+ for (p=Asc+l-1; p>=Asc; p--)
+ if (*p=='(') break;
+ if (p<Asc) return AddrError(1300);
+ *(p++)='\0'; Asc[l-1]='\0';
+ if (strcasecmp(p,"IP")==0) Base=IPREG;
+ else if (NOT DecodeIReg(p,&Base)) return AddrXError(1445,p);
+ break;
+ default:
+ Done=True;
+ END
+ END
+ while (NOT Done);
+
+ DispAcc=EvalIntExpression(Asc,Int32,&OK);
+
+ if (Base==IPREG)
+ BEGIN
+ DispAcc-=EProgCounter()+8;
+ if (Index!=NOREG) return AddrError(1350);
+ else
+ BEGIN
+ *Erg=(5<<10); *Ext=DispAcc; return 1;
+ END
+ END
+ else if ((Index==NOREG) AND (DispAcc>=0) AND (DispAcc<=4095))
+ BEGIN
+ *Erg=DispAcc;
+ if (Base!=NOREG) *Erg+=0x2000+(Base<<14);
+ return 0;
+ END
+ else
+ BEGIN
+ Mode=(Ord(DispAcc!=0)<<3)+4+(Ord(Index!=NOREG)<<1)+Ord(Base!=NOREG);
+ if ((Mode&9)==0) Mode+=8; if (Mode==5) Mode--;
+ *Erg=(Mode<<10);
+ if (Base!=NOREG) *Erg+=Base<<14;
+ if (Index!=NOREG) *Erg+=Index+(Scale<<7);
+ if (Mode<8) return 0;
+ else
+ BEGIN
+ *Ext=DispAcc; return 1;
+ END
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *Op=FixedOrders+Index;
+
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ DAsmCode[0]=Op->Code;
+ CodeLen=4;
+ END
+END
+
+ static void DecodeReg(Word Index)
+BEGIN
+ RegOrder *Op=RegOrders+Index;
+ LongWord DReg=0,DMode=0;
+ LongWord S1Reg=0,S1Mode=0;
+ LongWord S2Reg=0,S2Mode=0;
+
+ if ((Op->DestType!=NoneOp) AND (ArgCnt==1+Ord(Op->Src2Type!=NoneOp)))
+ BEGIN
+ strcpy(ArgStr[ArgCnt+1],ArgStr[ArgCnt]);
+ ArgCnt++;
+ END
+
+ if (ArgCnt!=1+Ord(Op->Src2Type!=NoneOp)+Ord(Op->DestType!=NoneOp)) WrError(1110);
+ else if (((Op->DestType>=SingleOp) OR (Op->Src1Type>=SingleOp)) AND (NOT FPUAvail)) WrXError(1200,OpPart);
+ else if ((Op->DestType==NoneOp) OR (DecodeAdr(ArgStr[ArgCnt],MModReg+(Op->DestType>=SingleOp?MModFReg:0),Op->DestType,&DReg,&DMode)))
+ if (DecodeAdr(ArgStr[1],MModReg+(Op->Src1Type>=SingleOp?MModFReg:0)+(Op->Imm1?MModImm:0),Op->Src1Type,&S1Reg,&S1Mode))
+ if ((Op->Src2Type==NoneOp) OR (DecodeAdr(ArgStr[2],MModReg+(Op->Src2Type>=SingleOp?MModFReg:0)+(Op->Imm2?MModImm:0),Op->Src2Type,&S2Reg,&S2Mode)))
+ BEGIN
+ DAsmCode[0]= ((Op->Code&0xff0)<<20) + ((Op->Code&0xf)<<7)
+ + (S1Reg) + (S2Reg<<14) + (DReg<<19)
+ + (S1Mode<<11) + (S2Mode<<12) + (DMode<<13);
+ CodeLen=4;
+ if ((Memo("MODPC")) AND (NOT SupAllowed)) WrError(50);
+ END
+END
+
+ static void DecodeCobr(Word Index)
+BEGIN
+ CobrOrder *Op=CobrOrders+Index;
+ LongWord S1Reg,S1Mode;
+ LongWord S2Reg=0,S2Mode=0;
+ LongInt AdrInt;
+ Boolean OK;
+
+ if (ArgCnt!=1+2*Ord(Op->HasSrc)) WrError(1110);
+ else if (DecodeAdr(ArgStr[1],MModReg+(Op->HasSrc?MModImm:0),IntOp,&S1Reg,&S1Mode))
+ if ((NOT Op->HasSrc) OR (DecodeAdr(ArgStr[2],MModReg,IntOp,&S2Reg,&S2Mode)))
+ BEGIN
+ FirstPassUnknown=False; OK=True;
+ if (Op->HasSrc) AdrInt=EvalIntExpression(ArgStr[3],UInt32,&OK)-EProgCounter();
+ else AdrInt=0;
+ if (FirstPassUnknown) AdrInt &= (~3);
+ if (OK)
+ if ((AdrInt&3)!=0) WrError(1325);
+ else if ((NOT SymbolQuestionable) AND ((AdrInt<-4096) OR (AdrInt>4090))) WrError(1370);
+ else
+ BEGIN
+ DAsmCode[0]= (Op->Code<<24) + (S1Reg<<19) + (S2Reg<<14) + (S1Mode<<13)
+ + (AdrInt & 0x1ffc);
+ CodeLen=4;
+ END
+ END
+END
+
+ static void DecodeCtrl(Word Index)
+BEGIN
+ FixedOrder *Op=CtrlOrders+Index;
+ LongInt AdrInt;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrInt=EvalIntExpression(ArgStr[1],UInt32,&OK)-EProgCounter();
+ if (FirstPassUnknown) AdrInt &= (~3);
+ if (OK)
+ if ((AdrInt&3)!=0) WrError(1325);
+ else if ((NOT SymbolQuestionable) AND ((AdrInt<-8388608) OR (AdrInt>8388604))) WrError(1370);
+ else
+ BEGIN
+ DAsmCode[0]=(Op->Code<<24)+(AdrInt & 0xfffffc);
+ CodeLen=4;
+ END
+ END
+END
+
+ static void DecodeMemO(Word Index)
+BEGIN
+ MemOrder *Op=MemOrders+Index;
+ LongWord Reg=0,Mem;
+ int MemType;
+ ShortInt MemPos=(Op->RegPos>0) ? 3-Op->RegPos : 1;
+
+ if (ArgCnt!=1+Ord(Op->RegPos>0)) WrError(1110);
+ else if ((Op->RegPos>0) AND (NOT DecodeIReg(ArgStr[Op->RegPos],&Reg))) WrXError(1445,ArgStr[Op->RegPos]);
+ else if ((Reg&OpMasks[Op->Type])!=0) WrXError(1445,ArgStr[Op->RegPos]);
+ else if ((MemType=DecodeMem(ArgStr[MemPos],&Mem,DAsmCode+1))>=0)
+ BEGIN
+ DAsmCode[0]=(Op->Code<<24)+(Reg<<19)+Mem;
+ CodeLen=(1+MemType)<<2;
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ int z;
+ Boolean OK;
+ LongWord Size;
+
+ if (Memo("WORD"))
+ BEGIN
+ if (ArgCnt<1) WrError(1110);
+ else
+ BEGIN
+ OK=True; z=1;
+ while ((z<=ArgCnt) AND (OK))
+ BEGIN
+ DAsmCode[z-1]=EvalIntExpression(ArgStr[z],Int32,&OK);
+ z++;
+ END
+ if (OK) CodeLen=4*ArgCnt;
+ END
+ return True;
+ END
+
+ if (Memo("SPACE"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((OK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void MakeCode_960(void)
+BEGIN
+ CodeLen=0; DontPrint=False;
+
+ /* Nullanweisung */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodeIntelPseudo(False)) return;
+
+ if (DecodePseudo()) return;
+
+ /* Befehlszaehler nicht ausgerichtet? */
+
+ if ((EProgCounter()&3)!=0) WrError(180);
+
+ /* CPU-Anweisungen */
+
+ if (LookupInstTable(InstTable,OpPart)) return;
+
+ /* unbekannter Befehl */
+
+ WrXError(1200,OpPart);
+END
+
+/*--------------------------------------------------------------------------*/
+
+static int InstrZ;
+
+ static void AddFixed(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
+END
+
+ static void AddReg(char *NName, LongWord NCode,
+ OpType NSrc1, OpType NSrc2, OpType NDest,
+ Boolean NImm1, Boolean NImm2)
+BEGIN
+ if (InstrZ>=RegOrderCnt) exit(255);
+ RegOrders[InstrZ].Code=NCode;
+ RegOrders[InstrZ].Src1Type=NSrc1;
+ RegOrders[InstrZ].Src2Type=NSrc2;
+ RegOrders[InstrZ].DestType=NDest;
+ RegOrders[InstrZ].Imm1=NImm1;
+ RegOrders[InstrZ].Imm2=NImm2;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeReg);
+END
+
+ static void AddCobr(char *NName, LongWord NCode, Boolean NHas)
+BEGIN
+ if (InstrZ>=CobrOrderCnt) exit(255);
+ CobrOrders[InstrZ].Code=NCode;
+ CobrOrders[InstrZ].HasSrc=NHas;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeCobr);
+END
+
+ static void AddCtrl(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=CtrlOrderCnt) exit(255);
+ CtrlOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeCtrl);
+END
+
+ static void AddMem(char *NName, LongWord NCode, OpType NType, int NPos)
+BEGIN
+ if (InstrZ>=MemOrderCnt) exit(255);
+ MemOrders[InstrZ].Code=NCode;
+ MemOrders[InstrZ].Type=NType;
+ MemOrders[InstrZ].RegPos=NPos;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeMemO);
+END
+
+ static void AddSpecReg(char *NName, LongWord NCode)
+BEGIN
+ if (InstrZ>=SpecRegCnt) exit(255);
+ SpecRegs[InstrZ].Code=NCode;
+ SpecRegs[InstrZ++].Name=NName;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(301);
+
+ FixedOrders=(FixedOrder*) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("FLUSHREG", 0x66000680);
+ AddFixed("FMARK" , 0x66000600);
+ AddFixed("MARK" , 0x66000580);
+ AddFixed("RET" , 0x0a000000);
+ AddFixed("SYNCF" , 0x66000780);
+ AddFixed("FAULTNO" , 0x18000000);
+ AddFixed("FAULTG" , 0x19000000);
+ AddFixed("FAULTE" , 0x1a000000);
+ AddFixed("FAULTGE" , 0x1b000000);
+ AddFixed("FAULTL" , 0x1c000000);
+ AddFixed("FAULTNE" , 0x1d000000);
+ AddFixed("FAULTLE" , 0x1e000000);
+ AddFixed("FAULTO" , 0x1f000000);
+
+ RegOrders=(RegOrder*) malloc(sizeof(RegOrder)*RegOrderCnt); InstrZ=0;
+ /* Name OpCode Src1Type Src2Type DestType Imm1 Imm2 */
+ AddReg("ADDC" , 0x5b0, IntOp , IntOp , IntOp , True , True );
+ AddReg("ADDI" , 0x591, IntOp , IntOp , IntOp , True , True );
+ AddReg("ADDO" , 0x590, IntOp , IntOp , IntOp , True , True );
+ AddReg("ADDR" , 0x78f, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("ADDRL" , 0x79f, DoubleOp, DoubleOp, DoubleOp, True , True );
+ AddReg("ALTERBIT", 0x58f, IntOp , IntOp , IntOp , True , True );
+ AddReg("AND" , 0x581, IntOp , IntOp , IntOp , True , True );
+ AddReg("ANDNOT" , 0x582, IntOp , IntOp , IntOp , True , True );
+ AddReg("ATADD" , 0x612, IntOp , IntOp , IntOp , True , True );
+ AddReg("ATANR" , 0x680, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("ATANRL" , 0x690, DoubleOp, DoubleOp, DoubleOp, True , True );
+ AddReg("ATMOD" , 0x610, IntOp , IntOp , IntOp , True , True );
+ AddReg("CALLS" , 0x660, IntOp , NoneOp , NoneOp , True , False);
+ AddReg("CHKBIT" , 0x5ae, IntOp , IntOp , NoneOp , True , True );
+ AddReg("CLASSR" , 0x68f, SingleOp, NoneOp , NoneOp , True , False);
+ AddReg("CLASSRL" , 0x69f, DoubleOp, NoneOp , NoneOp , True , False);
+ AddReg("CLRBIT" , 0x58c, IntOp , IntOp , IntOp , True , True );
+ AddReg("CMPDECI" , 0x5a7, IntOp , IntOp , IntOp , True , False);
+ AddReg("CMPDECO" , 0x5a6, IntOp , IntOp , IntOp , True , False);
+ AddReg("CMPI" , 0x5a1, IntOp , IntOp , NoneOp , True , True );
+ AddReg("CMPO" , 0x5a0, IntOp , IntOp , NoneOp , True , True );
+ AddReg("CMPINCI" , 0x5a5, IntOp , IntOp , IntOp , True , False);
+ AddReg("CMPINCO" , 0x5a4, IntOp , IntOp , IntOp , True , False);
+ AddReg("CMPOR" , 0x684, SingleOp, SingleOp, NoneOp , True , True );
+ AddReg("CMPORL" , 0x694, DoubleOp, DoubleOp, NoneOp , True , True );
+ AddReg("CMPR" , 0x685, SingleOp, SingleOp, NoneOp , True , True );
+ AddReg("CMPRL" , 0x695, DoubleOp, DoubleOp, NoneOp , True , True );
+ AddReg("CONCMPI" , 0x5a3, IntOp , IntOp , NoneOp , True , True );
+ AddReg("CONCMPO" , 0x5a2, IntOp , IntOp , NoneOp , True , True );
+ AddReg("COSR" , 0x68d, SingleOp, NoneOp , SingleOp, True , False);
+ AddReg("COSRL" , 0x69d, DoubleOp, NoneOp , DoubleOp, True , False);
+ AddReg("CPYSRE" , 0x6e2, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("CPYRSRE" , 0x6e3, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("CVTIR" , 0x674, IntOp, NoneOp , SingleOp, True , False);
+ AddReg("CVTILR" , 0x675, LongOp, NoneOp , DoubleOp, True , False);
+ AddReg("CVTRI" , 0x6c0, SingleOp, NoneOp , IntOp , True , False);
+ AddReg("CVTRIL" , 0x6c1, SingleOp, NoneOp , LongOp , True , False);
+ AddReg("CVTZRI" , 0x6c2, IntOp , NoneOp , IntOp , True , False);
+ AddReg("CVTZRIL" , 0x6c2, LongOp , NoneOp , LongOp , True , False);
+ /* Name OpCode Src1Type Src2Type DestType Imm1 Imm2 */
+ AddReg("DADDC" , 0x642, IntOp , IntOp , IntOp , False, False);
+ AddReg("DIVI" , 0x74b, IntOp , IntOp , IntOp , True , True );
+ AddReg("DIVO" , 0x70b, IntOp , IntOp , IntOp , True , True );
+ AddReg("DIVR" , 0x78b, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("DIVRL" , 0x79b, DoubleOp, DoubleOp, DoubleOp, True , True );
+ AddReg("DMOVT" , 0x644, IntOp , NoneOp , IntOp , False, False);
+ AddReg("DSUBC" , 0x643, IntOp , IntOp , IntOp , False, False);
+ AddReg("EDIV" , 0x671, IntOp , LongOp , LongOp , True , True );
+ AddReg("EMUL" , 0x670, IntOp , IntOp , LongOp , True , True );
+ AddReg("EXPR" , 0x689, SingleOp, NoneOp , SingleOp, True , False);
+ AddReg("EXPRL" , 0x699, DoubleOp, NoneOp , DoubleOp, True , False);
+ AddReg("EXTRACT" , 0x651, IntOp , IntOp , IntOp , True , True );
+ AddReg("LOGBNR" , 0x68a, SingleOp, NoneOp , SingleOp, True , False);
+ AddReg("LOGBNRL" , 0x69a, DoubleOp, NoneOp , DoubleOp, True , False);
+ AddReg("LOGEPR" , 0x681, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("LOGEPRL" , 0x691, DoubleOp, DoubleOp, DoubleOp, True , True );
+ AddReg("LOGR" , 0x682, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("LOGRL" , 0x692, DoubleOp, DoubleOp, DoubleOp, True , True );
+ AddReg("MODAC" , 0x645, IntOp , IntOp , IntOp , True , True );
+ AddReg("MODI" , 0x749, IntOp , IntOp , IntOp , True , True );
+ AddReg("MODIFY" , 0x650, IntOp , IntOp , IntOp , True , True );
+ AddReg("MODPC" , 0x655, IntOp , IntOp , IntOp , True , True );
+ AddReg("MODTC" , 0x654, IntOp , IntOp , IntOp , True , True );
+ AddReg("MOV" , 0x5cc, IntOp , NoneOp , IntOp , True , False);
+ AddReg("MOVL" , 0x5dc, LongOp , NoneOp , LongOp , True , False);
+ AddReg("MOVT" , 0x5ec, QuadOp , NoneOp , QuadOp , True , False);
+ AddReg("MOVQ" , 0x5fc, QuadOp , NoneOp , QuadOp , True , False);
+ AddReg("MOVR" , 0x6c9, SingleOp, NoneOp , SingleOp, True , False);
+ AddReg("MOVRL" , 0x6d9, DoubleOp, NoneOp , DoubleOp, True , False);
+ AddReg("MOVRE" , 0x6e1, ExtOp , NoneOp , ExtOp , True , False);
+ AddReg("MULI" , 0x741, IntOp , IntOp , IntOp , True , True );
+ AddReg("MULO" , 0x701, IntOp , IntOp , IntOp , True , True );
+ AddReg("MULR" , 0x78c, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("MULRL" , 0x79c, DoubleOp, DoubleOp, DoubleOp, True , True );
+ AddReg("NAND" , 0x58e, IntOp , IntOp , IntOp , True , True );
+ AddReg("NOR" , 0x588, IntOp , IntOp , IntOp , True , True );
+ AddReg("NOT" , 0x58a, IntOp , NoneOp , IntOp , True , False);
+ AddReg("NOTAND" , 0x584, IntOp , IntOp , IntOp , True , True );
+ AddReg("NOTBIT" , 0x580, IntOp , IntOp , IntOp , True , True );
+ AddReg("NOTOR" , 0x58d, IntOp , IntOp , IntOp , True , True );
+ AddReg("OR" , 0x587, IntOp , IntOp , IntOp , True , True );
+ AddReg("ORNOT" , 0x58b, IntOp , IntOp , IntOp , True , True );
+ /* Name OpCode TwoSrc HDest Float Imm1 Imm2 */
+ AddReg("REMI" , 0x748, IntOp , IntOp , IntOp , True , True );
+ AddReg("REMO" , 0x708, IntOp , IntOp , IntOp , True , True );
+ AddReg("REMR" , 0x683, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("REMRL" , 0x693, DoubleOp, DoubleOp, DoubleOp, True , True );
+ AddReg("ROTATE" , 0x59d, IntOp , IntOp , IntOp , True , True );
+ AddReg("ROUNDR" , 0x68b, SingleOp, NoneOp , SingleOp, True , False);
+ AddReg("ROUNDRL" , 0x69b, DoubleOp, NoneOp , DoubleOp, True , False);
+ AddReg("SCALER" , 0x677, IntOp , SingleOp, SingleOp, True , True );
+ AddReg("SCALERL" , 0x676, IntOp , DoubleOp, DoubleOp, True , True );
+ AddReg("SCANBIT" , 0x641, IntOp , NoneOp , IntOp , True , False);
+ AddReg("SCANBYTE", 0x5ac, IntOp , NoneOp , IntOp , True , False);
+ AddReg("SETBIT" , 0x583, IntOp , IntOp , IntOp , True , True );
+ AddReg("SHLO" , 0x59c, IntOp , IntOp , IntOp , True , True );
+ AddReg("SHRO" , 0x598, IntOp , IntOp , IntOp , True , True );
+ AddReg("SHLI" , 0x59e, IntOp , IntOp , IntOp , True , True );
+ AddReg("SHRI" , 0x59B, IntOp , IntOp , IntOp , True , True );
+ AddReg("SHRDI" , 0x59a, IntOp , IntOp , IntOp , True , True );
+ AddReg("SINR" , 0x68c, SingleOp, NoneOp , SingleOp, True , False);
+ AddReg("SINRL" , 0x69c, DoubleOp, NoneOp , DoubleOp, True , False);
+ AddReg("SCANBIT" , 0x640, IntOp , NoneOp , IntOp , True , False);
+ AddReg("SQRTR" , 0x688, SingleOp, NoneOp , SingleOp, True , False);
+ AddReg("SQRTRL" , 0x698, DoubleOp, NoneOp , DoubleOp, True , False);
+ AddReg("SUBC" , 0x5b2, IntOp , IntOp , IntOp , True , True );
+ AddReg("SUBI" , 0x593, IntOp , IntOp , IntOp , True , True );
+ AddReg("SUBO" , 0x592, IntOp , IntOp , IntOp , True , True );
+ AddReg("SUBR" , 0x78d, SingleOp, SingleOp, SingleOp, True , True );
+ AddReg("SUBRL" , 0x79d, DoubleOp, DoubleOp, DoubleOp, True , True );
+ AddReg("SYNLD" , 0x615, IntOp , NoneOp , IntOp , False, False);
+ AddReg("SYNMOV" , 0x600, IntOp , NoneOp , IntOp , False, False);
+ AddReg("SYNMOVL" , 0x601, IntOp , NoneOp , IntOp , False, False);
+ AddReg("SYNMOVQ" , 0x602, IntOp , NoneOp , IntOp , False, False);
+ AddReg("TANR" , 0x68e, SingleOp, NoneOp , SingleOp, True , False);
+ AddReg("TANRL" , 0x69e, DoubleOp, NoneOp , DoubleOp, True , False);
+ AddReg("XOR" , 0x589, IntOp , IntOp , IntOp , True , True );
+ AddReg("XNOR" , 0x589, IntOp , IntOp , IntOp , True , True );
+
+ CobrOrders=(CobrOrder*) malloc(sizeof(CobrOrder)*CobrOrderCnt); InstrZ=0;
+ AddCobr("BBC" , 0x30, True ); AddCobr("BBS" , 0x37, True );
+ AddCobr("CMPIBE" , 0x3a, True ); AddCobr("CMPOBE" , 0x32, True );
+ AddCobr("CMPIBNE", 0x3d, True ); AddCobr("CMPOBNE", 0x35, True );
+ AddCobr("CMPIBL" , 0x3c, True ); AddCobr("CMPOBL" , 0x34, True );
+ AddCobr("CMPIBLE", 0x3e, True ); AddCobr("CMPOBLE", 0x36, True );
+ AddCobr("CMPIBG" , 0x39, True ); AddCobr("CMPOBG" , 0x31, True );
+ AddCobr("CMPIBGE", 0x3b, True ); AddCobr("CMPOBGE", 0x33, True );
+ AddCobr("CMPIBO" , 0x3f, True ); AddCobr("CMPIBNO", 0x38, True );
+ AddCobr("TESTE" , 0x22, False); AddCobr("TESTNE" , 0x25, False);
+ AddCobr("TESTL" , 0x24, False); AddCobr("TESTLE" , 0x26, False);
+ AddCobr("TESTG" , 0x21, False); AddCobr("TESTGE" , 0x23, False);
+ AddCobr("TESTO" , 0x27, False); AddCobr("TESTNO" , 0x27, False);
+
+ CtrlOrders=(FixedOrder*) malloc(sizeof(FixedOrder)*CtrlOrderCnt); InstrZ=0;
+ AddCtrl("B" , 0x08); AddCtrl("CALL", 0x09);
+ AddCtrl("BAL" , 0x0b); AddCtrl("BNO" , 0x19);
+ AddCtrl("BG" , 0x11); AddCtrl("BE" , 0x12);
+ AddCtrl("BGE" , 0x13); AddCtrl("BL" , 0x14);
+ AddCtrl("BNE" , 0x15); AddCtrl("BLE" , 0x16);
+ AddCtrl("BO" , 0x17);
+
+ MemOrders=(MemOrder*) malloc(sizeof(MemOrder)*MemOrderCnt); InstrZ=0;
+ AddMem("LDOB" , 0x80, IntOp , 2);
+ AddMem("STOB" , 0x82, IntOp , 1);
+ AddMem("BX" , 0x84, IntOp , 0);
+ AddMem("BALX" , 0x85, IntOp , 2);
+ AddMem("CALLX", 0x86, IntOp , 0);
+ AddMem("LDOS" , 0x88, IntOp , 2);
+ AddMem("STOS" , 0x8a, IntOp , 1);
+ AddMem("LDA" , 0x8c, IntOp , 2);
+ AddMem("LD" , 0x90, IntOp , 2);
+ AddMem("ST" , 0x92, IntOp , 1);
+ AddMem("LDL" , 0x98, LongOp , 2);
+ AddMem("STL" , 0x9a, LongOp , 1);
+ AddMem("LDT" , 0xa0, QuadOp , 2);
+ AddMem("STT" , 0xa2, QuadOp , 1);
+ AddMem("LDQ" , 0xb0, QuadOp , 2);
+ AddMem("STQ" , 0xb2, QuadOp , 1);
+ AddMem("LDIB" , 0xc0, IntOp , 2);
+ AddMem("STIB" , 0xc2, IntOp , 1);
+ AddMem("LDIS" , 0xc8, IntOp , 2);
+ AddMem("STIS" , 0xca, IntOp , 1);
+
+ SpecRegs=(SpecReg*) malloc(sizeof(SpecReg)*SpecRegCnt); InstrZ=0;
+ AddSpecReg("FP" ,31); AddSpecReg("PFP", 0);
+ AddSpecReg("SP" , 1); AddSpecReg("RIP", 2);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+ free(RegOrders);
+ free(CobrOrders);
+ free(CtrlOrders);
+ free(SpecRegs);
+END
+
+/*--------------------------------------------------------------------------*/
+
+
+ static Boolean IsDef_960(void)
+BEGIN
+ return False;
+END
+
+ static void InitPass_960(void)
+BEGIN
+ SaveInitProc();
+ SetFlag(&FPUAvail,FPUAvailName,False);
+END
+
+ static void SwitchFrom_960(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_960(void)
+BEGIN
+ PFamilyDescr FoundId;
+
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ FoundId=FindFamilyByName("i960"); if (FoundId==Nil) exit(255);
+ PCSymbol="$"; HeaderID=FoundId->Id; NOPCode=0x000000000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=4; SegInits[SegCode]=0;
+#ifdef __STDC__
+ SegLimits[SegCode] = 0xfffffffful;
+#else
+ SegLimits[SegCode] = 0xffffffffl;
+#endif
+
+ MakeCode=MakeCode_960; IsDef=IsDef_960;
+ SwitchFrom=SwitchFrom_960;
+ AddONOFF("FPU" , &FPUAvail , FPUAvailName , False);
+ AddONOFF("SUPMODE" , &SupAllowed, SupAllowedName, False);
+
+ InitFields();
+END
+
+ void code960_init(void)
+BEGIN
+ CPU80960=AddCPU("80960",SwitchTo_960);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitPass_960;
+END
diff --git a/code960.h b/code960.h
new file mode 100644
index 0000000..c6d4534
--- /dev/null
+++ b/code960.h
@@ -0,0 +1,11 @@
+/* code960.h */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Codegenerator i960-Familie */
+/* */
+/* Historie: 24.8.1998 angelegt */
+/* */
+/*****************************************************************************/
+
+extern void code960_init(void);
diff --git a/code96c141.c b/code96c141.c
new file mode 100644
index 0000000..a58abb5
--- /dev/null
+++ b/code96c141.c
@@ -0,0 +1,2331 @@
+/* code96c141.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TLCS-900(L) */
+/* */
+/* Historie: 27. 6.1996 Grundsteinlegung */
+/* 9. 1.1999 ChkPC jetzt mit Adresse als Parameter */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "strutil.h"
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+#include "asmitree.h"
+
+/*-------------------------------------------------------------------------*/
+/* Daten */
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Byte CPUFlag;
+ Boolean InSup;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Boolean InSup;
+ Byte MinMax,MaxMax;
+ ShortInt Default;
+ } ImmOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Byte OpMask;
+ } RegOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } ALU2Order;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } Condition;
+
+#define FixedOrderCnt 13
+#define ImmOrderCnt 3
+#define RegOrderCnt 8
+#define ALU2OrderCnt 8
+#define ShiftOrderCnt 8
+#define MulDivOrderCnt 4
+#define BitCFOrderCnt 5
+#define BitOrderCnt 5
+#define ConditionCnt 24
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModXReg 1
+#define MModXReg (1 << ModXReg)
+#define ModMem 2
+#define MModMem (1 << ModMem)
+#define ModImm 3
+#define MModImm (1 << ModImm)
+#define ModCReg 4
+#define MModCReg (1 << ModCReg)
+
+static FixedOrder *FixedOrders;
+static RegOrder *RegOrders;
+static ImmOrder *ImmOrders;
+static ALU2Order *ALU2Orders;
+static char **ShiftOrders;
+static char **MulDivOrders;
+static ALU2Order *BitCFOrders;
+static char **BitOrders;
+static Condition *Conditions;
+static LongInt DefaultCondition;
+static PInstTable InstTable;
+
+static ShortInt AdrType;
+static ShortInt OpSize; /* -1/0/1/2 = nix/Byte/Word/Long */
+static Byte AdrMode;
+static Byte AdrVals[10];
+static Boolean MinOneIs0;
+
+static CPUVar CPU96C141,CPU93C141;
+
+/*---------------------------------------------------------------------------*/
+/* Adressparser */
+
+ static Boolean IsRegBase(Byte No, Byte Size)
+BEGIN
+ return ((Size==2) OR ((Size==1) AND (No<0xf0) AND (NOT Maximum) AND ((No & 3)==0)));
+END
+
+ static void ChkMaximum(Boolean MustMax, Byte *Result)
+BEGIN
+ if (Maximum!=MustMax)
+ BEGIN
+ *Result=1;
+ WrError((MustMax)?1997:1996);
+ END
+END
+
+ static Boolean IsQuot(char Ch)
+BEGIN
+ return ((Ch=='\'') OR (Ch=='`'));
+END
+
+ static Byte CodeEReg(char *Asc, Byte *ErgNo, Byte *ErgSize)
+BEGIN
+#define RegCnt 8
+ static char Reg8Names[RegCnt+1]="AWCBEDLH";
+ static char *Reg16Names[RegCnt]=
+ {"WA" ,"BC" ,"DE" ,"HL" ,"IX" ,"IY" ,"IZ" ,"SP" };
+ static char *Reg32Names[RegCnt]=
+ {"XWA","XBC","XDE","XHL","XIX","XIY","XIZ","XSP"};
+
+ int z,l=strlen(Asc);
+ char *pos;
+ String HAsc,Asc_N;
+ Byte Result;
+
+ strmaxcpy(Asc_N,Asc,255); NLS_UpString(Asc_N); Asc=Asc_N;
+
+ Result=2;
+
+ /* mom. Bank ? */
+
+ if ((l==1) AND ((pos=strchr(Reg8Names,*Asc))!=Nil))
+ BEGIN
+ z=pos-Reg8Names;
+ *ErgNo=0xe0+((z & 6) << 1)+(z & 1); *ErgSize=0; return Result;
+ END
+ for (z=0; z<RegCnt; z++)
+ BEGIN
+ if (strcmp(Asc,Reg16Names[z])==0)
+ BEGIN
+ *ErgNo=0xe0+(z << 2); *ErgSize=1; return Result;
+ END
+ if (strcmp(Asc,Reg32Names[z])==0)
+ BEGIN
+ *ErgNo=0xe0+(z << 2); *ErgSize=2;
+ if (z<4) ChkMaximum(True,&Result);
+ return Result;
+ END
+ END
+
+ /* Bankregister, 8 Bit ? */
+
+ if ((l==3) AND ((*Asc=='Q') OR (*Asc=='R')) AND ((Asc[2]>='0') AND (Asc[2]<='7')))
+ for (z=0; z<RegCnt; z++)
+ if (Asc[1]==Reg8Names[z])
+ BEGIN
+ *ErgNo=((Asc[3]-'0') << 4)+((z & 6) << 1)+(z & 1);
+ if (*Asc=='Q')
+ BEGIN
+ ErgNo+=2; ChkMaximum(True,&Result);
+ END
+ if (((*Asc=='Q') OR (Maximum)) AND (Asc[2]>'3'))
+ BEGIN
+ WrError(1320); Result=1;
+ END
+ *ErgSize=0; return Result;
+ END
+
+ /* Bankregister, 16 Bit ? */
+
+ if ((l==4) AND ((*Asc=='Q') OR (*Asc=='R')) AND ((Asc[3]>='0') AND (Asc[3]<='7')))
+ BEGIN
+ strcpy(HAsc,Asc+2); HAsc[2]='\0';
+ for (z=0; z<(RegCnt/2)-1; z++)
+ if (strcmp(HAsc,Reg16Names[z])==0)
+ BEGIN
+ *ErgNo=((Asc[3]-'0') << 4)+(z << 2);
+ if (*Asc=='Q')
+ BEGIN
+ ErgNo+=2; ChkMaximum(True,&Result);
+ END
+ if (((*Asc=='Q') OR (Maximum)) AND (Asc[3]>'3'))
+ BEGIN
+ WrError(1320); Result=1;
+ END
+ *ErgSize=1; return Result;
+ END
+ END
+
+ /* Bankregister, 32 Bit ? */
+
+ if ((l==4) AND ((Asc[3]>='0') AND (Asc[3]<='7')))
+ BEGIN
+ strcpy(HAsc,Asc); HAsc[3]='\0';
+ for (z=0; z<(RegCnt/2)-1; z++)
+ if (strcmp(HAsc,Reg32Names[z])==0)
+ BEGIN
+ *ErgNo=((Asc[3]-'0') << 4)+(z << 2);
+ ChkMaximum(True,&Result);
+ if (Asc[3]>'3')
+ BEGIN
+ WrError(1320); Result=1;
+ END
+ *ErgSize=2; return Result;
+ END
+ END
+
+ /* obere 8-Bit-Haelften momentaner Bank ? */
+
+ if ((l==2) AND (*Asc=='Q'))
+ for (z=0; z<RegCnt; z++)
+ if (Asc[1]==Reg8Names[z])
+ BEGIN
+ *ErgNo=0xe2+((z & 6) << 1)+(z & 1);
+ ChkMaximum(True,&Result);
+ *ErgSize=0; return Result;
+ END
+
+ /* obere 16-Bit-Haelften momentaner Bank und von XIX..XSP ? */
+
+ if ((l==3) AND (*Asc=='Q'))
+ BEGIN
+ for (z=0; z<RegCnt; z++)
+ if (strcmp(Asc+1,Reg16Names[z])==0)
+ BEGIN
+ *ErgNo=0xe2+(z << 2);
+ if (z<4) ChkMaximum(True,&Result);
+ *ErgSize=1; return Result;
+ END
+ END
+
+ /* 8-Bit-Teile von XIX..XSP ? */
+
+ if (((l==3) OR ((l==4) AND (*Asc=='Q')))
+ AND ((Asc[l-1]=='L') OR (Asc[l-1]=='H')))
+ BEGIN
+ strcpy(HAsc,Asc+1); HAsc[l-2]='\0';
+ for (z=0; z<(RegCnt/2); z++)
+ if (strcmp(HAsc,Reg16Names[z+4])==0)
+ BEGIN
+ *ErgNo=0xf0+(z << 2)+((l-3) << 1)+(Ord(Asc[l-1]=='H'));
+ *ErgSize=0; return Result;
+ END
+ END
+
+ /* 8-Bit-Teile vorheriger Bank ? */
+
+ if (((l==2) OR ((l==3) AND (*Asc=='Q'))) AND (IsQuot(Asc[l-1])))
+ for (z=0; z<RegCnt; z++)
+ if (Asc[l-2]==Reg8Names[z])
+ BEGIN
+ *ErgNo=0xd0+((z & 6) << 1)+((strlen(Asc)-2) << 1)+(z & 1);
+ if (l==3) ChkMaximum(True,&Result);
+ *ErgSize=0; return Result;
+ END;
+
+ /* 16-Bit-Teile vorheriger Bank ? */
+
+ if (((l==3) OR ((l==4) AND (*Asc=='Q'))) AND (IsQuot(Asc[l-1])))
+ BEGIN
+ strcpy(HAsc,Asc+1); HAsc[l-2]='\0';
+ for (z=0; z<(RegCnt/2); z++)
+ if (strcmp(HAsc,Reg16Names[z])==0)
+ BEGIN
+ *ErgNo=0xd0+(z << 2)+((strlen(Asc)-3) << 1);
+ if (l==4) ChkMaximum(True,&Result);
+ *ErgSize=1; return Result;
+ END
+ END
+
+ /* 32-Bit-Register vorheriger Bank ? */
+
+ if ((l==4) AND (IsQuot(Asc[3])))
+ BEGIN
+ strcpy(HAsc,Asc); HAsc[3]='\0';
+ for (z=0; z<(RegCnt/2); z++)
+ if (strcmp(HAsc,Reg32Names[z])==0)
+ BEGIN
+ *ErgNo=0xd0+(z << 2);
+ ChkMaximum(True,&Result);
+ *ErgSize=2; return Result;
+ END
+ END
+
+ return (Result=0);
+END
+
+ static void ChkL(CPUVar Must, Byte *Result)
+BEGIN
+ if (MomCPU!=Must)
+ BEGIN
+ WrError(1440); *Result=0;
+ END
+END
+
+ static Byte CodeCReg(char *Asc, Byte *ErgNo, Byte *ErgSize)
+BEGIN
+ Byte Result=2;
+
+ if (strcasecmp(Asc,"NSP")==0)
+ BEGIN
+ *ErgNo=0x3c; *ErgSize=1;
+ ChkL(CPU96C141,&Result);
+ return Result;
+ END
+ if (strcasecmp(Asc,"XNSP")==0)
+ BEGIN
+ *ErgNo=0x3c; *ErgSize=2;
+ ChkL(CPU96C141,&Result);
+ return Result;
+ END
+ if (strcasecmp(Asc,"INTNEST")==0)
+ BEGIN
+ *ErgNo=0x3c; *ErgSize=1;
+ ChkL(CPU93C141,&Result);
+ return Result;
+ END
+ if ((strlen(Asc)==5) AND (strncasecmp(Asc,"DMA",3)==0) AND (Asc[4]>='0') AND (Asc[4]<='3'))
+ switch (toupper(Asc[3]))
+ BEGIN
+ case 'S':
+ *ErgNo=(Asc[4]-'0')*4; *ErgSize=2; return Result;
+ case 'D':
+ *ErgNo=(Asc[4]-'0')*4+0x10; *ErgSize=2; return Result;
+ case 'M':
+ *ErgNo=(Asc[4]-'0')*4+0x22; *ErgSize=0; return Result;
+ case 'C':
+ *ErgNo=(Asc[4]-'0')*4+0x20; *ErgSize=1; return Result;
+ END
+
+ return (Result=0);
+END
+
+
+typedef struct
+ {
+ char *Name;
+ Byte Num;
+ Boolean InMax,InMin;
+ } RegDesc;
+
+
+ static void SetOpSize(ShortInt NewSize)
+BEGIN
+ if (OpSize==-1) OpSize=NewSize;
+ else if (OpSize!=NewSize)
+ BEGIN
+ WrError(1131); AdrType=ModNone;
+ END
+END
+
+ static Boolean IsRegCurrent(Byte No, Byte Size, Byte *Erg)
+BEGIN
+ switch (Size)
+ BEGIN
+ case 0:
+ if ((No & 0xf2)==0xe0)
+ BEGIN
+ *Erg=((No & 0x0c) >> 1)+((No & 1) ^ 1);
+ return True;
+ END
+ else return False;
+ case 1:
+ case 2:
+ if ((No & 0xe3)==0xe0)
+ BEGIN
+ *Erg=((No & 0x1c) >> 2);
+ return True;
+ END
+ else return False;
+ default:
+ return False;
+ END
+END
+
+ static void ChkAdr(Byte Erl)
+BEGIN
+ if (AdrType!=ModNone)
+ if ((Erl&(1 << AdrType))==0)
+ BEGIN
+ WrError(1350); AdrType=ModNone;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Byte Erl)
+BEGIN
+ String HAsc,Rest;
+ Byte HNum,HSize;
+ Boolean OK,NegFlag,NNegFlag,MustInd,FirstFlag;
+ Byte BaseReg,BaseSize;
+ Byte IndReg,IndSize;
+ Byte PartMask;
+ LongInt DispPart,DispAcc;
+ char *MPos,*PPos,*EPos;
+
+ AdrType=ModNone;
+
+ /* Register ? */
+
+ switch (CodeEReg(Asc,&HNum,&HSize))
+ BEGIN
+ case 1:
+ ChkAdr(Erl); return;
+ case 2:
+ if (IsRegCurrent(HNum,HSize,&AdrMode)) AdrType=ModReg;
+ else
+ BEGIN
+ AdrType=ModXReg; AdrMode=HNum;
+ END
+ SetOpSize(HSize);
+ ChkAdr(Erl); return;
+ END
+
+ /* Steuerregister ? */
+
+ if (CodeCReg(Asc,&HNum,&HSize)==2)
+ BEGIN
+ AdrType=ModCReg; AdrMode=HNum;
+ SetOpSize(HSize);
+ ChkAdr(Erl); return;
+ END
+
+ /* Predekrement ? */
+
+ if ((strlen(Asc)>4) AND (Asc[strlen(Asc)-1]==')') AND (strncmp(Asc,"(-",2)==0))
+ BEGIN
+ strcpy(HAsc,Asc+2); HAsc[strlen(HAsc)-1]='\0';
+ if (CodeEReg(HAsc,&HNum,&HSize)!=2) WrError(1350);
+ else if (NOT IsRegBase(HNum,HSize)) WrError(1350);
+ else
+ BEGIN
+ AdrType=ModMem; AdrMode=0x44;
+ AdrCnt=1; AdrVals[0]=HNum; if (OpSize!=-1) AdrVals[0]+=OpSize;
+ END
+ ChkAdr(Erl); return;
+ END
+
+ /* Postinkrement ? */
+
+ if ((strlen(Asc)>4) AND (Asc[0]=='(') AND (strncmp(Asc+strlen(Asc)-2,"+)",2)==0))
+ BEGIN
+ strcpy(HAsc,Asc+1); HAsc[strlen(HAsc)-2]='\0';
+ if (CodeEReg(HAsc,&HNum,&HSize)!=2) WrError(1350);
+ else if (NOT IsRegBase(HNum,HSize)) WrError(1350);
+ else
+ BEGIN
+ AdrType=ModMem; AdrMode=0x45;
+ AdrCnt=1; AdrVals[0]=HNum; if (OpSize!=-1) AdrVals[0]+=OpSize;
+ END
+ ChkAdr(Erl); return;
+ END
+
+ /* Speicheroperand ? */
+
+ if (IsIndirect(Asc))
+ BEGIN
+ NegFlag=False; NNegFlag=False; FirstFlag=False;
+ PartMask=0; DispAcc=0; BaseReg=IndReg=BaseSize=IndSize=0xff;
+ strcpy(Rest,Asc+1); Rest[strlen(Rest)-1]='\0';
+
+ do
+ BEGIN
+ MPos=QuotPos(Rest,'-'); PPos=QuotPos(Rest,'+');
+ if ((PPos!=Nil) AND ((MPos==Nil) OR (PPos<MPos)))
+ BEGIN
+ EPos=PPos; NNegFlag=False;
+ END
+ else if ((MPos!=Nil) AND ((PPos==Nil) OR (MPos<PPos)))
+ BEGIN
+ EPos=MPos; NNegFlag=True;
+ END
+ else EPos=Rest+strlen(Rest);
+ if ((EPos==Rest) OR (EPos==Rest+strlen(Rest)-1))
+ BEGIN
+ WrError(1350); return;
+ END
+ strncpy(HAsc,Rest,EPos-Rest); HAsc[EPos-Rest]='\0';
+ if (EPos<Rest+strlen(Rest)) strcpy(Rest,EPos+1); else *Rest='\0';
+
+ switch (CodeEReg(HAsc,&HNum,&HSize))
+ BEGIN
+ case 0:
+ FirstPassUnknown=False;
+ DispPart=EvalIntExpression(HAsc,Int32,&OK);
+ if (FirstPassUnknown) FirstFlag=True;
+ if (NOT OK) return;
+ if (NegFlag) DispAcc-=DispPart; else DispAcc+=DispPart;
+ PartMask|=1;
+ break;
+ case 1:
+ break;
+ case 2:
+ if (NegFlag)
+ BEGIN
+ WrError(1350); return;
+ END
+ else
+ BEGIN
+ if (HSize==0) MustInd=True;
+ else if (HSize==2) MustInd=False;
+ else if (NOT IsRegBase(HNum,HSize)) MustInd=True;
+ else if ((PartMask & 4)!=0) MustInd=True;
+ else MustInd=False;
+ if (MustInd)
+ if ((PartMask & 2)!=0)
+ BEGIN
+ WrError(1350); return;
+ END
+ else
+ BEGIN
+ IndReg=HNum; PartMask|=2;
+ IndSize=HSize;
+ END
+ else
+ if ((PartMask & 4)!=0)
+ BEGIN
+ WrError(1350); return;
+ END
+ else
+ BEGIN
+ BaseReg=HNum; PartMask|=4;
+ BaseSize=HSize;
+ END
+ END
+ break;
+ END
+
+ NegFlag=NNegFlag; NNegFlag=False;
+ END
+ while (*Rest!='\0');
+
+ if ((DispAcc==0) AND (PartMask!=1)) PartMask&=6;
+ if ((PartMask==5) AND (FirstFlag)) DispAcc&=0x7fff;
+
+ switch (PartMask)
+ BEGIN
+ case 0:
+ case 2:
+ case 3:
+ case 7:
+ WrError(1350);
+ break;
+ case 1:
+ if (DispAcc<=0xff)
+ BEGIN
+ AdrType=ModMem; AdrMode=0x40; AdrCnt=1;
+ AdrVals[0]=DispAcc;
+ END
+ else if (DispAcc<0xffff)
+ BEGIN
+ AdrType=ModMem; AdrMode=0x41; AdrCnt=2;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc);
+ END
+ else if (DispAcc<0xffffff)
+ BEGIN
+ AdrType=ModMem; AdrMode=0x42; AdrCnt=3;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrVals[2]=(DispAcc >> 16) & 0xff;
+ END
+ else WrError(1925);
+ break;
+ case 4:
+ if (IsRegCurrent(BaseReg,BaseSize,&AdrMode))
+ BEGIN
+ AdrType=ModMem; AdrCnt=0;
+ END
+ else
+ BEGIN
+ AdrType=ModMem; AdrMode=0x43; AdrCnt=1;
+ AdrVals[0]=BaseReg;
+ END
+ break;
+ case 5:
+ if ((DispAcc<=127) AND (DispAcc>=-128) AND (IsRegCurrent(BaseReg,BaseSize,&AdrMode)))
+ BEGIN
+ AdrType=ModMem; AdrMode+=8; AdrCnt=1;
+ AdrVals[0]=DispAcc & 0xff;
+ END
+ else if ((DispAcc<=32767) AND (DispAcc>=-32768))
+ BEGIN
+ AdrType=ModMem; AdrMode=0x43; AdrCnt=3;
+ AdrVals[0]=BaseReg+1;
+ AdrVals[1]=DispAcc & 0xff;
+ AdrVals[2]=(DispAcc >> 8) & 0xff;
+ END
+ else WrError(1320);
+ break;
+ case 6:
+ AdrType=ModMem; AdrMode=0x43; AdrCnt=3;
+ AdrVals[0]=3+(IndSize << 2);
+ AdrVals[1]=BaseReg;
+ AdrVals[2]=IndReg;
+ break;
+ END
+ ChkAdr(Erl); return;
+ END
+
+ /* bleibt nur noch immediate... */
+
+ if ((MinOneIs0) AND (OpSize==-1)) OpSize=0;
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1132);
+ break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=1;
+ END
+ break;
+ case 1:
+ DispAcc=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=2;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc);
+ END
+ break;
+ case 2:
+ DispAcc=EvalIntExpression(Asc,Int32,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=4;
+ AdrVals[0]=Lo(DispAcc); AdrVals[1]=Hi(DispAcc);
+ AdrVals[2]=Lo(DispAcc >> 16); AdrVals[3]=Hi(DispAcc >> 16);
+ END
+ break;
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void CorrMode(Byte Ref, Byte Adr)
+BEGIN
+ if ((BAsmCode[Ref] & 0x4e)==0x44)
+ BAsmCode[Adr]=(BAsmCode[Adr] & 0xfc) | OpSize;
+END
+
+ static Boolean ArgPair(const char *Val1, const char *Val2)
+BEGIN
+ return (((strcasecmp(ArgStr[1],Val1)==0) AND (strcasecmp(ArgStr[2],Val2)==0)) OR
+ ((strcasecmp(ArgStr[1],Val2)==0) AND (strcasecmp(ArgStr[2],Val1)==0)));
+END
+
+ static LongInt ImmVal(void)
+BEGIN
+ LongInt tmp;
+
+ tmp=AdrVals[0];
+ if (OpSize>=1) tmp+=((LongInt)AdrVals[1]) << 8;
+ if (OpSize==2)
+ BEGIN
+ tmp+=((LongInt)AdrVals[2]) << 16;
+ tmp+=((LongInt)AdrVals[3]) << 24;
+ END
+ return tmp;
+END
+
+ static Boolean IsPwr2(LongInt Inp, Byte *Erg)
+BEGIN
+ LongInt Shift;
+
+ Shift=1; *Erg=0;
+ do
+ BEGIN
+ if (Inp==Shift) return True;
+ Shift+=Shift; (*Erg)++;
+ END
+ while (Shift!=0);
+ return False;
+END
+
+ static Boolean IsShort(Byte Code)
+BEGIN
+ return ((Code & 0x4e)==40);
+END
+
+ static void CheckSup(void)
+BEGIN
+ if (MomCPU==CPU96C141)
+ if (NOT SupAllowed) WrError(50);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void DecodeMULA(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModXReg);
+ if ((AdrType!=ModNone) AND (OpSize!=2)) WrError(1130);
+ else
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ BAsmCode[0]=0xd8+AdrMode;
+ BAsmCode[1]=0x19;
+ break;
+ case ModXReg:
+ CodeLen=3;
+ BAsmCode[0]=0xd7;
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x19;
+ break;
+ END
+ END
+END
+
+ static void DecodeJPCALL(Word Index)
+BEGIN
+ int z;
+
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1) z=DefaultCondition;
+ else
+ BEGIN
+ z=0; NLS_UpString(ArgStr[1]);
+ while ((z<ConditionCnt) AND (strcmp(Conditions[z].Name,ArgStr[1])!=0)) z++;
+ END
+ if (z>=ConditionCnt) WrError(1360);
+ else
+ BEGIN
+ OpSize=2;
+ DecodeAdr(ArgStr[ArgCnt],MModMem+MModImm);
+ if (AdrType==ModImm)
+ if (AdrVals[3]!=0)
+ BEGIN
+ WrError(1320); AdrType=ModNone;
+ END
+ else if (AdrVals[2]!=0)
+ BEGIN
+ AdrType=ModMem; AdrMode=0x42; AdrCnt=3;
+ END
+ else
+ BEGIN
+ AdrType=ModMem; AdrMode=0x41; AdrCnt=2;
+ END
+ if (AdrType==ModMem)
+ if ((z==DefaultCondition) AND ((AdrMode==0x41) OR (AdrMode==0x42)))
+ BEGIN
+ CodeLen=1+AdrCnt;
+ BAsmCode[0]=0x1a+2*Index+(AdrCnt-2);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ END
+ else
+ BEGIN
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0xb0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0xd0+(Index << 4)+(Conditions[z].Code);
+ END
+ END
+ END
+END
+
+ static void DecodeJR(Word Index)
+BEGIN
+ Boolean OK;
+ int z;
+ LongInt AdrLong;
+
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1) z=DefaultCondition;
+ else
+ BEGIN
+ z=0; NLS_UpString(ArgStr[1]);
+ while ((z<ConditionCnt) AND (strcmp(Conditions[z].Name,ArgStr[1])!=0)) z++;
+ END
+ if (z>=ConditionCnt) WrError(1360);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[ArgCnt],Int32,&OK);
+ if (OK)
+ if (Index==1)
+ BEGIN
+ AdrLong-=EProgCounter()+3;
+ if (((AdrLong>0x7fffl) OR (AdrLong<-0x8000l)) AND (NOT SymbolQuestionable)) WrError(1330);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x70+Conditions[z].Code;
+ BAsmCode[1]=Lo(AdrLong); BAsmCode[2]=Hi(AdrLong);
+ if (NOT FirstPassUnknown)
+ BEGIN
+ AdrLong++;
+ if ((AdrLong>=-128) AND (AdrLong<=127)) WrError(20);
+ END
+ END
+ END
+ else
+ BEGIN
+ AdrLong-=EProgCounter()+2;
+ if (((AdrLong>127) OR (AdrLong<-128)) AND (NOT SymbolQuestionable)) WrError(1330);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x60+Conditions[z].Code;
+ BAsmCode[1]=Lo(AdrLong);
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeCALR(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK)-(EProgCounter()+3);
+ if (OK)
+ if (((AdrLong<-32768) OR (AdrLong>32767)) AND (NOT SymbolQuestionable)) WrError(1330);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x1e;
+ BAsmCode[1]=Lo(AdrLong); BAsmCode[2]=Hi(AdrLong);
+ END
+ END
+END
+
+ static void DecodeRET(Word Index)
+BEGIN
+ int z;
+
+ if (ArgCnt>1) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==0) z=DefaultCondition;
+ else
+ BEGIN
+ z=0; NLS_UpString(ArgStr[1]);
+ while ((z<ConditionCnt) AND (strcmp(Conditions[z].Name,ArgStr[1])!=0)) z++;
+ END
+ if (z>=ConditionCnt) WrError(1360);
+ else if (z==DefaultCondition)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x0e;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xb0;
+ BAsmCode[1]=0xf0+Conditions[z].Code;
+ END
+ END
+END
+
+ static void DecodeRETD(Word Index)
+BEGIN
+ Word AdrWord;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0x0f;
+ BAsmCode[1]=Lo(AdrWord); BAsmCode[2]=Hi(AdrWord);
+ END
+ END
+END
+
+ static void DecodeDJNZ(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ AdrType=ModReg; AdrMode=2; OpSize=0;
+ END
+ else DecodeAdr(ArgStr[1],MModReg+MModXReg);
+ if (AdrType!=ModNone)
+ if (OpSize==2) WrError(1130);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[ArgCnt],Int32,&OK)-(EProgCounter()+3+Ord(AdrType==ModXReg));
+ if (OK)
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x1c;
+ BAsmCode[2]=AdrLong & 0xff;
+ break;
+ case ModXReg:
+ CodeLen=4;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x1c;
+ BAsmCode[3]=AdrLong & 0xff;
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeEX(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if ((ArgPair("F","F\'")) OR (ArgPair("F`","F")))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x16;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModXReg+MModMem);
+ if (OpSize==2) WrError(1130);
+ else
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModXReg+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0xb8+HReg;
+ break;
+ case ModXReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0xb8+HReg;
+ break;
+ case ModMem:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0x80+(OpSize << 4)+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x30+HReg;
+ break;
+ END
+ break;
+ case ModXReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrType==ModReg)
+ BEGIN
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=HReg;
+ BAsmCode[2]=0xb8+AdrMode;
+ END
+ break;
+ case ModMem:
+ MinOneIs0=True;
+ HReg=AdrCnt; BAsmCode[0]=AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrType==ModReg)
+ BEGIN
+ CodeLen=2+HReg; CorrMode(0,1);
+ BAsmCode[0]+=0x80+(OpSize << 4);
+ BAsmCode[1+HReg]=0x30+AdrMode;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeBS1x(Word Index)
+BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1135);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+MModXReg);
+ if (OpSize!=1) WrError(1130);
+ else
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ BAsmCode[0]=0xd8+AdrMode;
+ BAsmCode[1]=0x0e +Index; /* ANSI */
+ break;
+ case ModXReg:
+ CodeLen=3;
+ BAsmCode[0]=0xd7;
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x0e +Index; /* ANSI */
+ break;
+ END
+ END
+END
+
+ static void DecodeLDA(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrType!=ModNone)
+ if (OpSize<1) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModMem);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0xb0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x20+((OpSize-1) << 4)+HReg;
+ END
+ END
+ END
+END
+
+ static void DecodeLDAR(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[2],Int32,&OK)-(EProgCounter()+4);
+ if (OK)
+ if (((AdrLong<-32768) OR (AdrLong>32767)) AND (NOT SymbolQuestionable)) WrError(1330);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrType!=ModNone)
+ if (OpSize<1) WrError(1130);
+ else
+ BEGIN
+ CodeLen=5;
+ BAsmCode[0]=0xf3; BAsmCode[1]=0x13;
+ BAsmCode[2]=Lo(AdrLong); BAsmCode[3]=Hi(AdrLong);
+ BAsmCode[4]=0x20+((OpSize-1) << 4)+AdrMode;
+ END
+ END
+ END
+END
+
+ static void DecodeLDC(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModXReg+MModCReg);
+ HReg=AdrMode;
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ DecodeAdr(ArgStr[2],MModCReg);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=3;
+ BAsmCode[0]=0xc8+(OpSize << 4)+HReg;
+ BAsmCode[1]=0x2f;
+ BAsmCode[2]=AdrMode;
+ END
+ break;
+ case ModXReg:
+ DecodeAdr(ArgStr[2],MModCReg);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=4;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=HReg;
+ BAsmCode[2]=0x2f;
+ BAsmCode[3]=AdrMode;
+ END;
+ break;
+ case ModCReg:
+ DecodeAdr(ArgStr[2],MModReg+MModXReg);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x2e;
+ BAsmCode[2]=HReg;
+ break;
+ case ModXReg:
+ CodeLen=4;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x2e;
+ BAsmCode[3]=HReg;
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeLDX(Word Index)
+BEGIN
+ Boolean OK;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMem);
+ if (AdrType!=ModNone)
+ if (AdrMode!=0x40) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[4]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=6;
+ BAsmCode[0]=0xf7; BAsmCode[1]=0;
+ BAsmCode[2]=AdrVals[0]; BAsmCode[3]=0;
+ BAsmCode[5]=0;
+ END
+ END
+ END
+END
+
+ static void DecodeLINK(Word Index)
+BEGIN
+ Word AdrWord;
+ Boolean OK;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[2],Int16,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModXReg);
+ if ((AdrType!=ModNone) AND (OpSize!=2)) WrError(1130);
+ else
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=4;
+ BAsmCode[0]=0xe8+AdrMode;
+ BAsmCode[1]=0x0c;
+ BAsmCode[2]=Lo(AdrWord);
+ BAsmCode[3]=Hi(AdrWord);
+ break;
+ case ModXReg:
+ CodeLen=5;
+ BAsmCode[0]=0xe7;
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x0c;
+ BAsmCode[3]=Lo(AdrWord);
+ BAsmCode[4]=Hi(AdrWord);
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeLD(Word Index)
+BEGIN
+ Byte HReg;
+ Boolean ShDest,ShSrc,OK;
+
+ if (Index<3) OpSize=Index;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModXReg+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModXReg+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x88+HReg;
+ break;
+ case ModXReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x88+HReg;
+ break;
+ case ModMem:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0x80+(OpSize << 4)+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x20+HReg;
+ break;
+ case ModImm:
+ if ((ImmVal()<=7) AND (ImmVal()>=0))
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0xc8+(OpSize << 4)+HReg;
+ BAsmCode[1]=0xa8+AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=1+AdrCnt;
+ BAsmCode[0]=((OpSize+2) << 4)+HReg;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ END
+ break;
+ END
+ break;
+ case ModXReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=HReg;
+ BAsmCode[2]=0x98+AdrMode;
+ break;
+ case ModImm:
+ if ((ImmVal()<=7) AND (ImmVal()>=0))
+ BEGIN
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=HReg;
+ BAsmCode[2]=0xa8+AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=3+AdrCnt;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=HReg;
+ BAsmCode[2]=3;
+ memcpy(BAsmCode+3,AdrVals,AdrCnt);
+ END
+ break;
+ END
+ break;
+ case ModMem:
+ BAsmCode[0]=AdrMode;
+ HReg=AdrCnt; MinOneIs0=True;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModReg+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2+HReg;
+ BAsmCode[0]+=0xb0; CorrMode(0,1);
+ BAsmCode[1+HReg]=0x40+(OpSize << 4)+AdrMode;
+ break;
+ case ModMem:
+ if (OpSize==-1) OpSize=0;
+ ShDest=IsShort(BAsmCode[0]); ShSrc=IsShort(AdrMode);
+ if (NOT (ShDest OR ShSrc)) WrError(1350);
+ else
+ BEGIN
+ if ((ShDest AND (NOT ShSrc))) OK=True;
+ else if (ShSrc AND (NOT ShDest)) OK=False;
+ else if (AdrMode==0x40) OK=True;
+ else OK=False;
+ if (OK) /* dest=(dir8/16) */
+ BEGIN
+ CodeLen=4+AdrCnt; HReg=BAsmCode[0];
+ if (BAsmCode[0]==0x40) BAsmCode[3+AdrCnt]=0;
+ else BAsmCode[3+AdrCnt]=BAsmCode[2];
+ BAsmCode[2+AdrCnt]=BAsmCode[1];
+ BAsmCode[0]=0x80+(OpSize << 4)+AdrMode;
+ AdrMode=HReg; CorrMode(0,1);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x19;
+ END
+ else
+ BEGIN
+ CodeLen=4+HReg;
+ BAsmCode[2+HReg]=AdrVals[0];
+ if (AdrMode==0x40) BAsmCode[3+HReg]=0;
+ else BAsmCode[3+HReg]=AdrVals[1];
+ BAsmCode[0]+=0xb0; CorrMode(0,1);
+ BAsmCode[1+HReg]=0x14+(OpSize << 1);
+ END
+ END
+ break;
+ case ModImm:
+ if (BAsmCode[0]==0x40)
+ BEGIN
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0x08+(OpSize << 1);
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ END
+ else
+ BEGIN
+ CodeLen=2+HReg+AdrCnt;
+ BAsmCode[0]+=0xb0;
+ BAsmCode[1+HReg]=OpSize << 1;
+ memcpy(BAsmCode+2+HReg,AdrVals,AdrCnt);
+ END
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *FixedZ=FixedOrders+Index;
+
+ if (ArgCnt!=0) WrError(1110);
+ else if ((FixedZ->CPUFlag & (1 << (MomCPU-CPU96C141)))==0) WrError(1500);
+ else
+ BEGIN
+ if (Hi(FixedZ->Code)==0)
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=Lo(FixedZ->Code);
+ END
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=Hi(FixedZ->Code);
+ BAsmCode[1]=Lo(FixedZ->Code);
+ END
+ if (FixedZ->InSup) CheckSup();
+ END
+END
+
+ static void DecodeImm(Word Index)
+BEGIN
+ ImmOrder *ImmZ=ImmOrders+Index;
+ Word AdrWord;
+ Boolean OK;
+
+ if ((ArgCnt>1) OR ((ImmZ->Default==-1) AND (ArgCnt==0))) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ AdrWord=ImmZ->Default; OK=True;
+ END
+ else AdrWord=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ if (((Maximum) AND (AdrWord>ImmZ->MaxMax)) OR ((NOT Maximum) AND (AdrWord>ImmZ->MinMax))) WrError(1320);
+ else if (Hi(ImmZ->Code)==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=Lo(ImmZ->Code)+AdrWord;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=Hi(ImmZ->Code);
+ BAsmCode[1]=Lo(ImmZ->Code)+AdrWord;
+ END
+ if (ImmZ->InSup) CheckSup();
+ END
+END
+
+ static void DecodeReg(Word Index)
+BEGIN
+ RegOrder *RegZ=RegOrders+Index;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModXReg);
+ if (AdrType!=ModNone)
+ if (((1 << OpSize) & RegZ->OpMask)==0) WrError(1130);
+ else if (AdrType==ModReg)
+ BEGIN
+ BAsmCode[0]=Hi(RegZ->Code)+8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=Lo(RegZ->Code);
+ CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=Hi(RegZ->Code)+7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=Lo(RegZ->Code);
+ CodeLen=3;
+ END
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode, Byte NFlag, Boolean NSup)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ].CPUFlag=NFlag;
+ FixedOrders[InstrZ].InSup=NSup;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
+END
+
+ static void AddReg(char *NName, Word NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=RegOrderCnt) exit(255);
+ RegOrders[InstrZ].Name=NName;
+ RegOrders[InstrZ].Code=NCode;
+ RegOrders[InstrZ].OpMask=NMask;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeReg);
+END
+
+ static void AddImm(char *NName, Word NCode, Boolean NInSup,
+ Byte NMinMax, Byte NMaxMax, ShortInt NDefault)
+BEGIN
+ if (InstrZ>=ImmOrderCnt) exit(255);
+ ImmOrders[InstrZ].Name=NName;
+ ImmOrders[InstrZ].Code=NCode;
+ ImmOrders[InstrZ].InSup=NInSup;
+ ImmOrders[InstrZ].MinMax=NMinMax;
+ ImmOrders[InstrZ].MaxMax=NMaxMax;
+ ImmOrders[InstrZ].Default=NDefault;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeImm);
+END
+
+ static void AddALU2(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ALU2OrderCnt) exit(255);
+ ALU2Orders[InstrZ].Name=NName;
+ ALU2Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddShift(char *NName)
+BEGIN
+ if (InstrZ>=ShiftOrderCnt) exit(255);
+ ShiftOrders[InstrZ++]=NName;
+END
+
+ static void AddMulDiv(char *NName)
+BEGIN
+ if (InstrZ>=MulDivOrderCnt) exit(255);
+ MulDivOrders[InstrZ++]=NName;
+END
+
+ static void AddBitCF(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=BitCFOrderCnt) exit(255);
+ BitCFOrders[InstrZ].Name=NName;
+ BitCFOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddBit(char *NName)
+BEGIN
+ if (InstrZ>=BitOrderCnt) exit(255);
+ BitOrders[InstrZ++]=NName;
+END
+
+ static void AddCondition(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ConditionCnt) exit(255);
+ Conditions[InstrZ].Name=NName;
+ Conditions[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(201);
+ AddInstTable(InstTable,"MULA" ,0,DecodeMULA);
+ AddInstTable(InstTable,"JP" ,0,DecodeJPCALL);
+ AddInstTable(InstTable,"CALL" ,1,DecodeJPCALL);
+ AddInstTable(InstTable,"JR" ,0,DecodeJR);
+ AddInstTable(InstTable,"JRL" ,1,DecodeJR);
+ AddInstTable(InstTable,"CALR" ,0,DecodeCALR);
+ AddInstTable(InstTable,"RET" ,0,DecodeRET);
+ AddInstTable(InstTable,"RETD" ,0,DecodeRETD);
+ AddInstTable(InstTable,"DJNZ" ,0,DecodeDJNZ);
+ AddInstTable(InstTable,"EX" ,0,DecodeEX);
+ AddInstTable(InstTable,"BS1F" ,0,DecodeBS1x);
+ AddInstTable(InstTable,"BS1B" ,0,DecodeBS1x);
+ AddInstTable(InstTable,"LDA" ,0,DecodeLDA);
+ AddInstTable(InstTable,"LDAR" ,0,DecodeLDAR);
+ AddInstTable(InstTable,"LDC" ,0,DecodeLDC);
+ AddInstTable(InstTable,"LDX" ,0,DecodeLDX);
+ AddInstTable(InstTable,"LINK" ,0,DecodeLINK);
+ AddInstTable(InstTable,"LDB" ,0,DecodeLD);
+ AddInstTable(InstTable,"LDW" ,1,DecodeLD);
+ AddInstTable(InstTable,"LDL" ,2,DecodeLD);
+ AddInstTable(InstTable,"LD" ,3,DecodeLD);
+
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("CCF" , 0x0012, 3, False);
+ AddFixed("DECF" , 0x000d, 3, False);
+ AddFixed("DI" , 0x0607, 3, True );
+ AddFixed("HALT" , 0x0005, 3, True );
+ AddFixed("INCF" , 0x000c, 3, False);
+ AddFixed("MAX" , 0x0004, 1, True );
+ AddFixed("MIN" , 0x0004, 2, True );
+ AddFixed("NOP" , 0x0000, 3, False);
+ AddFixed("NORMAL", 0x0001, 1, True );
+ AddFixed("RCF" , 0x0010, 3, False);
+ AddFixed("RETI" , 0x0007, 3, True );
+ AddFixed("SCF" , 0x0011, 3, False);
+ AddFixed("ZCF" , 0x0013, 3, False);
+
+ RegOrders=(RegOrder *) malloc(sizeof(RegOrder)*RegOrderCnt); InstrZ=0;
+ AddReg("CPL" , 0xc006, 3);
+ AddReg("DAA" , 0xc010, 1);
+ AddReg("EXTS", 0xc013, 6);
+ AddReg("EXTZ", 0xc012, 6);
+ AddReg("MIRR", 0xc016, 2);
+ AddReg("NEG" , 0xc007, 3);
+ AddReg("PAA" , 0xc014, 6);
+ AddReg("UNLK", 0xc00d, 4);
+
+ ImmOrders=(ImmOrder *) malloc(sizeof(ImmOrder)*ImmOrderCnt); InstrZ=0;
+ AddImm("EI" , 0x0600, True, 7, 7, 0);
+ AddImm("LDF" , 0x1700, False, 7, 3, -1);
+ AddImm("SWI" , 0x00f8, False, 7, 7, 7);
+
+ ALU2Orders=(ALU2Order *) malloc(sizeof(ALU2Order)*ALU2OrderCnt); InstrZ=0;
+ AddALU2("ADC", 1);
+ AddALU2("ADD", 0);
+ AddALU2("AND", 4);
+ AddALU2("OR" , 6);
+ AddALU2("SBC", 3);
+ AddALU2("SUB", 2);
+ AddALU2("XOR", 5);
+ AddALU2("CP" , 7);
+
+ ShiftOrders=(char **) malloc(sizeof(char*)*ShiftOrderCnt); InstrZ=0;
+ AddShift("RLC");
+ AddShift("RRC");
+ AddShift("RL");
+ AddShift("RR");
+ AddShift("SLA");
+ AddShift("SRA");
+ AddShift("SLL");
+ AddShift("SRL");
+
+ MulDivOrders=(char **) malloc(sizeof(char*)*MulDivOrderCnt); InstrZ=0;
+ AddMulDiv("MUL");
+ AddMulDiv("MULS");
+ AddMulDiv("DIV");
+ AddMulDiv("DIVS");
+
+ BitCFOrders=(ALU2Order *) malloc(sizeof(ALU2Order)*BitCFOrderCnt); InstrZ=0;
+ AddBitCF("ANDCF" , 0);
+ AddBitCF("LDCF" , 3);
+ AddBitCF("ORCF" , 1);
+ AddBitCF("STCF" , 4);
+ AddBitCF("XORCF" , 2);
+
+ BitOrders=(char **) malloc(sizeof(char*)*BitOrderCnt); InstrZ=0;
+ AddBit("RES");
+ AddBit("SET");
+ AddBit("CHG");
+ AddBit("BIT");
+ AddBit("TSET");
+
+ Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCnt); InstrZ=0;
+ AddCondition("F" , 0);
+ DefaultCondition=InstrZ; AddCondition("T" , 8);
+ AddCondition("Z" , 6); AddCondition("NZ" , 14);
+ AddCondition("C" , 7); AddCondition("NC" , 15);
+ AddCondition("PL" , 13); AddCondition("MI" , 5);
+ AddCondition("P" , 13); AddCondition("M" , 5);
+ AddCondition("NE" , 14); AddCondition("EQ" , 6);
+ AddCondition("OV" , 4); AddCondition("NOV" , 12);
+ AddCondition("PE" , 4); AddCondition("PO" , 12);
+ AddCondition("GE" , 9); AddCondition("LT" , 1);
+ AddCondition("GT" , 10); AddCondition("LE" , 2);
+ AddCondition("UGE" , 15); AddCondition("ULT" , 7);
+ AddCondition("UGT" , 11); AddCondition("ULE" , 3);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+ free(RegOrders);
+ free(ImmOrders);
+ free(ALU2Orders);
+ free(ShiftOrders);
+ free(MulDivOrders);
+ free(BitCFOrders);
+ free(BitOrders);
+ free(Conditions);
+END
+
+ static Boolean WMemo(char *Asc_O)
+BEGIN
+ int l=strlen(Asc_O);
+
+ if (strncmp(OpPart,Asc_O,l)!=0) return False;
+ switch (OpPart[l])
+ BEGIN
+ case '\0':
+ return True;
+ case 'W':
+ if (OpPart[l+1]=='\0')
+ BEGIN
+ OpSize=1; return True;
+ END
+ else return False;
+ case 'L':
+ if (OpPart[l+1]=='\0')
+ BEGIN
+ OpSize=2; return True;
+ END
+ else return False;
+ case 'B':
+ if (OpPart[l+1]=='\0')
+ BEGIN
+ OpSize=0; return True;
+ END
+ else return False;
+ default:
+ return False;
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static Boolean CodeMove(void)
+BEGIN
+ if ((WMemo("POP")) OR (WMemo("PUSH")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"F")==0)
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=0x18+Ord(Memo("POP"));
+ END
+ else if (strcasecmp(ArgStr[1],"A")==0)
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=0x14+Ord(Memo("POP"));
+ END
+ else if (strcasecmp(ArgStr[1],"SR")==0)
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=0x02+Ord(Memo("POP"));
+ CheckSup();
+ END
+ else
+ BEGIN
+ MinOneIs0=True;
+ DecodeAdr(ArgStr[1],MModReg+MModXReg+MModMem+
+ (WMemo("PUSH")?MModImm:0));
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ if (OpSize==0)
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x04+Ord(Memo("POP"));
+ END
+ else
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=0x28+(Ord(Memo("POP")) << 5)+((OpSize-1) << 4)+AdrMode;
+ END
+ break;
+ case ModXReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x04+Ord(Memo("POP"));
+ break;
+ case ModMem:
+ if (OpSize==-1) OpSize=0;
+ CodeLen=2+AdrCnt;
+ if (strncmp(OpPart,"POP",3)==0)
+ BAsmCode[0]=0xb0+AdrMode;
+ else BAsmCode[0]=0x80+(OpSize << 4)+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ if (strncmp(OpPart,"POP",3)==0)
+ BAsmCode[1+AdrCnt]=0x04+(OpSize << 1);
+ else BAsmCode[1+AdrCnt]=0x04;
+ break;
+ case ModImm:
+ if (OpSize==-1) OpSize=0;
+ BAsmCode[0]=9+(OpSize << 1);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ break;
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_96C141(void)
+BEGIN
+ int z;
+ Word AdrWord;
+ Boolean OK;
+ Byte HReg;
+ char *CmpStr;
+ char LChar;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1); MinOneIs0=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ if (CodeMove()) return;
+
+ /* vermischt */
+
+ if (LookupInstTable(InstTable,OpPart)) return;
+
+ for (z=0; z<ALU2OrderCnt; z++)
+ if (WMemo(ALU2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModXReg+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModXReg+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x80+(ALU2Orders[z].Code << 4)+HReg;
+ break;
+ case ModXReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x80+(ALU2Orders[z].Code << 4)+HReg;
+ break;
+ case ModMem:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0x80+AdrMode+(OpSize << 4);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x80+HReg+(ALU2Orders[z].Code << 4);
+ break;
+ case ModImm:
+ if ((ALU2Orders[z].Code==7) AND (OpSize!=2) AND (ImmVal()<=7) AND (ImmVal()>=0))
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0xc8+(OpSize << 4)+HReg;
+ BAsmCode[1]=0xd8+AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0xc8+(OpSize << 4)+HReg;
+ BAsmCode[1]=0xc8+ALU2Orders[z].Code;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ END
+ break;
+ END
+ break;
+ case ModXReg:
+ HReg=AdrMode;
+ DecodeAdr(ArgStr[2],MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModImm:
+ if ((ALU2Orders[z].Code==7) AND (OpSize!=2) AND (ImmVal()<=7) AND (ImmVal()>=0))
+ BEGIN
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=HReg;
+ BAsmCode[2]=0xd8+AdrVals[0];
+ END
+ else
+ BEGIN
+ CodeLen=3+AdrCnt;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=HReg;
+ BAsmCode[2]=0xc8+ALU2Orders[z].Code;
+ memcpy(BAsmCode+3,AdrVals,AdrCnt);
+ END
+ break;
+ END
+ break;
+ case ModMem:
+ MinOneIs0=True;
+ HReg=AdrCnt; BAsmCode[0]=AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2+HReg; CorrMode(0,1);
+ BAsmCode[0]+=0x80+(OpSize << 4);
+ BAsmCode[1+HReg]=0x88+(ALU2Orders[z].Code << 4)+AdrMode;
+ break;
+ case ModImm:
+ CodeLen=2+HReg+AdrCnt;
+ BAsmCode[0]+=0x80+(OpSize << 4);
+ BAsmCode[1+HReg]=0x38+ALU2Orders[z].Code;
+ memcpy(BAsmCode+2+HReg,AdrVals,AdrCnt);
+ break;
+ END;
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ShiftOrderCnt; z++)
+ if (WMemo(ShiftOrders[z]))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ OK=True;
+ if (ArgCnt==1) HReg=1;
+ else if (strcasecmp(ArgStr[1],"A")==0) HReg=0xff;
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ HReg=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ if (FirstPassUnknown) HReg&=0x0f;
+ else
+ if ((HReg==0) OR (HReg>16))
+ BEGIN
+ WrError(1320); OK=False;
+ END
+ else HReg&=0x0f;
+ END
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[ArgCnt],MModReg+MModXReg+((HReg==0xff)?0:MModMem));
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2+Ord(HReg!=0xff);
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0xe8+z;
+ if (HReg==0xff) BAsmCode[1]+=0x10;
+ else BAsmCode[2]=HReg;
+ break;
+ case ModXReg:
+ CodeLen=3+Ord(HReg!=0xff);
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0xe8+z;
+ if (HReg==0xff) BAsmCode[2]+=0x10;
+ else BAsmCode[3]=HReg;
+ break;
+ case ModMem:
+ if (HReg!=1) WrError(1350);
+ else
+ BEGIN
+ if (OpSize==-1) OpSize=0;
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0x80+(OpSize << 4)+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x78+z;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0;z<MulDivOrderCnt; z++)
+ if (Memo(MulDivOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModXReg);
+ if (OpSize==0) WrError(1130);
+ else
+ BEGIN
+ if ((AdrType==ModReg) AND (OpSize==1))
+ if (AdrMode>3)
+ BEGIN
+ AdrType=ModXReg; AdrMode=0xe0+(AdrMode << 2);
+ END
+ else AdrMode+=1+AdrMode;
+ OpSize--;
+ HReg=AdrMode;
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ DecodeAdr(ArgStr[2],MModReg+MModXReg+MModMem+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x40+(z << 3)+HReg;
+ break;
+ case ModXReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x40+(z << 3)+HReg;
+ break;
+ case ModMem:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0x80+(OpSize << 4)+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x40+(z << 3)+HReg;
+ break;
+ case ModImm:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0xc8+(OpSize << 4)+HReg;
+ BAsmCode[1]=0x08+z;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ break;
+ END
+ break;
+ case ModXReg:
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType==ModImm)
+ BEGIN
+ CodeLen=3+AdrCnt;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=HReg;
+ BAsmCode[2]=0x08+z;
+ memcpy(BAsmCode+3,AdrVals,AdrCnt);
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitCFOrderCnt; z++)
+ if (Memo(BitCFOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+MModXReg+MModMem);
+ if (AdrType!=ModNone)
+ if (OpSize==2) WrError(1130);
+ else
+ BEGIN
+ if (AdrType==ModMem) OpSize=0;
+ if (strcasecmp(ArgStr[1],"A")==0)
+ BEGIN
+ HReg=0xff; OK=True;
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ HReg=EvalIntExpression(ArgStr[1],(OpSize==0)?UInt3:Int4,&OK);
+ END
+ if (OK)
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2+Ord(HReg!=0xff);
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x20+(Ord(HReg==0xff) << 3)+BitCFOrders[z].Code;
+ if (HReg!=0xff) BAsmCode[2]=HReg;
+ break;
+ case ModXReg:
+ CodeLen=3+Ord(HReg!=0xff);
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x20+(Ord(HReg==0xff) << 3)+BitCFOrders[z].Code;
+ if (HReg!=0xff) BAsmCode[3]=HReg;
+ break;
+ case ModMem:
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0xb0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ if (HReg==0xff) BAsmCode[1+AdrCnt]=0x28+BitCFOrders[z].Code;
+ else BAsmCode[1+AdrCnt]=0x80+(BitCFOrders[z].Code << 3)+HReg;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+MModXReg+MModMem);
+ if (AdrType==ModMem) OpSize=0;
+ if (AdrType!=ModNone)
+ if (OpSize==2) WrError(1130);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[1],(OpSize==0)?UInt3:Int4,&OK);
+ if (OK)
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x30+z;
+ BAsmCode[2]=HReg;
+ break;
+ case ModXReg:
+ CodeLen=4;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x30+z;
+ BAsmCode[3]=HReg;
+ break;
+ case ModMem:
+ CodeLen=2+AdrCnt;
+ if (z==4) z=0; else z++;
+ BAsmCode[0]=0xb0+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0xa8+(z << 3)+HReg;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((WMemo("INC")) OR (WMemo("DEC")))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ if (ArgCnt==1)
+ BEGIN
+ HReg=1; OK=True;
+ END
+ else HReg=EvalIntExpression(ArgStr[1],Int4,&OK);
+ if (OK)
+ if (FirstPassUnknown) HReg&=7;
+ else if ((HReg<1) OR (HReg>8))
+ BEGIN
+ WrError(1320); OK=False;
+ END
+ if (OK)
+ BEGIN
+ HReg&=7; /* 8-->0 */
+ DecodeAdr(ArgStr[ArgCnt],MModReg+MModXReg+MModMem);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x60+(Ord(WMemo("DEC")) << 3)+HReg;
+ break;
+ case ModXReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x60+(Ord(WMemo("DEC")) << 3)+HReg;
+ break;
+ case ModMem:
+ if (OpSize==-1) OpSize=0;
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0x80+AdrMode+(OpSize << 4);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x60+(Ord(WMemo("DEC")) << 3)+HReg;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CPD")) OR (Memo("CPDR")) OR (Memo("CPI")) OR (Memo("CPIR")))
+ BEGIN
+ if ((ArgCnt!=0) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ OK=True; OpSize=0; AdrMode=3;
+ END
+ else
+ BEGIN
+ OK=True;
+ if (strcasecmp(ArgStr[1],"A")==0) OpSize=0;
+ else if (strcasecmp(ArgStr[1],"WA")==0) OpSize=1;
+ if (OpPart[2]=='I') CmpStr="+)"; else CmpStr="-)";
+ if (OpSize==-1) OK=False;
+ else if ((*ArgStr[2]!='(') OR (strcasecmp(ArgStr[2]+strlen(ArgStr[2])-2,CmpStr)!=0)) OK=False;
+ else
+ BEGIN
+ ArgStr[2][strlen(ArgStr[2])-2]='\0';
+ if (CodeEReg(ArgStr[2]+1,&AdrMode,&HReg)!=2) OK=False;
+ else if (NOT IsRegBase(AdrMode,HReg)) OK=False;
+ else if (NOT IsRegCurrent(AdrMode,HReg,&AdrMode)) OK=False;
+ END
+ if (NOT OK) WrError(1135);
+ END
+ if (OK)
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x80+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x14+(Ord(OpPart[2]=='D') << 1)+(strlen(OpPart)-3);
+ END
+ END
+ return;
+ END
+
+ if ((WMemo("LDD")) OR (WMemo("LDDR")) OR (WMemo("LDI")) OR (WMemo("LDIR")))
+ BEGIN
+ if (OpSize==-1) OpSize=0;
+ if (OpSize==2) WrError(1130);
+ else if ((ArgCnt!=0) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ OK=True; HReg=0;
+ END
+ else
+ BEGIN
+ OK=True;
+ if (OpPart[2]=='I') CmpStr="+)"; else CmpStr="-)";
+ if ((*ArgStr[1]!='(') OR (*ArgStr[2]!='(') OR
+ (strcasecmp(ArgStr[1]+strlen(ArgStr[1])-2,CmpStr)!=0) OR
+ (strcasecmp(ArgStr[2]+strlen(ArgStr[2])-2,CmpStr)!=0)) OK=False;
+ else
+ BEGIN
+ strcpy(ArgStr[1],ArgStr[1]+1); ArgStr[1][strlen(ArgStr[1])-2]='\0';
+ strcpy(ArgStr[2],ArgStr[2]+1); ArgStr[2][strlen(ArgStr[2])-2]='\0';
+ if ((strcasecmp(ArgStr[1],"XIX")==0) AND (strcasecmp(ArgStr[2],"XIY")==0)) HReg=2;
+ else if ((Maximum) AND (strcasecmp(ArgStr[1],"XDE")==0) AND (strcasecmp(ArgStr[2],"XHL")==0)) HReg=0;
+ else if ((NOT Maximum) AND (strcasecmp(ArgStr[1],"DE")==0) AND (strcasecmp(ArgStr[2],"HL")==0)) HReg=0;
+ else OK=False;
+ END
+ END
+ if (NOT OK) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x83+(OpSize << 4)+HReg;
+ BAsmCode[1]=0x10+(Ord(OpPart[2]=='D') << 1)+Ord(strchr(OpPart,'R')!=Nil);
+ END
+ END
+ return;
+ END
+
+ LChar=OpPart[strlen(OpPart)-1];
+ if (((strncmp(OpPart,"MDEC",4)==0) OR (strncmp(OpPart,"MINC",4)==0)) AND (LChar>='1') AND (LChar<='4'))
+ BEGIN
+ if (LChar=='3') WrError(1135);
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if (NOT IsPwr2(AdrWord,&HReg)) WrError(1135);
+ else if ((HReg==0) OR ((LChar=='2') AND (HReg<2)) OR ((LChar=='4') AND (HReg<3))) WrError(1135);
+ else
+ BEGIN
+ AdrWord-=LChar-'0';
+ IsPwr2(LChar-'0',&HReg);
+ DecodeAdr(ArgStr[2],MModReg+MModXReg);
+ if ((AdrType!=ModNone) AND (OpSize!=1)) WrError(1130);
+ else
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=4;
+ BAsmCode[0]=0xd8+AdrMode;
+ BAsmCode[1]=0x38+(Ord(OpPart[2]=='D') << 2)+HReg;
+ BAsmCode[2]=Lo(AdrWord);
+ BAsmCode[3]=Hi(AdrWord);
+ break;
+ case ModXReg:
+ CodeLen=5;
+ BAsmCode[0]=0xd7;
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x38+(Ord(OpPart[2]=='D') << 2)+HReg;
+ BAsmCode[3]=Lo(AdrWord);
+ BAsmCode[4]=Hi(AdrWord);
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("RLD")) OR (Memo("RRD")))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"A")!=0)) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[ArgCnt],MModMem);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2+AdrCnt;
+ BAsmCode[0]=0x80+AdrMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x06+Ord(Memo("RRD"));
+ END
+ END
+ return;
+ END
+
+ if (Memo("SCC"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ z=0; NLS_UpString(ArgStr[1]);
+ while ((z<ConditionCnt) AND (strcmp(Conditions[z].Name,ArgStr[1])!=0)) z++;
+ if (z>=ConditionCnt) WrError(1360);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+MModXReg);
+ if (OpSize>1) WrError(1110);
+ else
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ BAsmCode[0]=0xc8+(OpSize << 4)+AdrMode;
+ BAsmCode[1]=0x70+Conditions[z].Code;
+ break;
+ case ModXReg:
+ CodeLen=3;
+ BAsmCode[0]=0xc7+(OpSize << 4);
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=0x70+Conditions[z].Code;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean ChkPC_96C141(LargeWord Addr)
+BEGIN
+ Boolean ok;
+
+ switch (ActPC)
+ BEGIN
+ case SegCode:
+ if (Maximum) ok=(Addr<=0xffffff);
+ else ok=(Addr<=0xffff);
+ break;
+ default:
+ ok=False;
+ END
+ return (ok);
+END
+
+
+ static Boolean IsDef_96C141(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_96C141(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_96C141(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=True;
+
+ PCSymbol="$"; HeaderID=0x52; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+
+ MakeCode=MakeCode_96C141; ChkPC=ChkPC_96C141; IsDef=IsDef_96C141;
+ SwitchFrom=SwitchFrom_96C141;
+ AddONOFF("MAXMODE", &Maximum , MaximumName ,False);
+ AddONOFF("SUPMODE", &SupAllowed, SupAllowedName,False);
+
+ InitFields();
+END
+
+ void code96c141_init(void)
+BEGIN
+ CPU96C141=AddCPU("96C141",SwitchTo_96C141);
+ CPU93C141=AddCPU("93C141",SwitchTo_96C141);
+END
diff --git a/code96c141.h b/code96c141.h
new file mode 100644
index 0000000..bcc8167
--- /dev/null
+++ b/code96c141.h
@@ -0,0 +1,11 @@
+/* code96c141.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TLCS-900(L) */
+/* */
+/* Historie: 27. 6.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code96c141_init(void);
diff --git a/code97c241.c b/code97c241.c
new file mode 100644
index 0000000..40f497d
--- /dev/null
+++ b/code97c241.c
@@ -0,0 +1,2190 @@
+/* code97c241.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TLCS-9000 */
+/* */
+/* Historie: */
+/* 2. 1.1999 ChkPC umgebaut */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ Byte Mask; /* B0..2=OpSizes, B4=-MayImm, B5=-MayReg */
+ } RMWOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ Byte Mask; /* B7: DD in A-Format gedreht */
+ enum {Equal,FirstCounts,SecondCounts,Op2Half} SizeType;
+ Boolean ImmKorr,ImmErl,RegErl;
+ } GAOrder;
+
+
+#define ConditionCount 20
+#define FixedOrderCount 20
+#define RMWOrderCount 14
+#define TrinomOrderCount 4
+#define StringOrderCount 4
+#define BFieldOrderCount 3
+#define GAEqOrderCount 10
+#define GAFirstOrderCount 6
+#define GASecondOrderCount 4
+#define GAHalfOrderCount 4
+#define GASI1OrderCount 4
+#define GASI2OrderCount 3
+#define BitOrderCount 4
+#define ShiftOrderCount 8
+
+
+static CPUVar CPU97C241;
+
+static int OpSize,OpSize2;
+static Integer LowLim4,LowLim8;
+
+static Boolean AdrOK;
+static Byte AdrMode,AdrMode2;
+static Byte AdrCnt2;
+static Word AdrVals[2],AdrVals2[2];
+static int AdrInc;
+static Word Prefs[2];
+static Boolean PrefUsed[2];
+static char Format;
+static Boolean MinOneIs0;
+
+static FixedOrder *FixedOrders;
+static RMWOrder *RMWOrders;
+static char **GASI1Orders;
+static char **GASI2Orders;
+static char **TrinomOrders;
+static char **BitOrders;
+static char **ShiftOrders;
+static char **BFieldOrders;
+static FixedOrder *GAEqOrders;
+static FixedOrder *GAHalfOrders;
+static FixedOrder *GAFirstOrders;
+static FixedOrder *GASecondOrders;
+static char **StringOrders;
+static char **Conditions;
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRMW(char *NName, Byte NCode, Byte NMask)
+BEGIN
+ if (InstrZ>=RMWOrderCount) exit(255);
+ RMWOrders[InstrZ].Name=NName;
+ RMWOrders[InstrZ].Mask=NMask;
+ RMWOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddGAEq(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=GAEqOrderCount) exit(255);
+ GAEqOrders[InstrZ].Name=NName;
+ GAEqOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddGAHalf(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=GAHalfOrderCount) exit(255);
+ GAHalfOrders[InstrZ].Name=NName;
+ GAHalfOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddGAFirst(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=GAFirstOrderCount) exit(255);
+ GAFirstOrders[InstrZ].Name=NName;
+ GAFirstOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddGASecond(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=GASecondOrderCount) exit(255);
+ GASecondOrders[InstrZ].Name=NName;
+ GASecondOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("CCF" , 0x7f82);
+ AddFixed("CSF" , 0x7f8a);
+ AddFixed("CVF" , 0x7f86);
+ AddFixed("CZF" , 0x7f8e);
+ AddFixed("DI" , 0x7fa1);
+ AddFixed("EI" , 0x7fa3);
+ AddFixed("HALT", 0x7fa5);
+ AddFixed("NOP" , 0x7fa0);
+ AddFixed("RCF" , 0x7f80);
+ AddFixed("RET" , 0x7fa4);
+ AddFixed("RETI", 0x7fa9);
+ AddFixed("RETS", 0x7fab);
+ AddFixed("RSF" , 0x7f88);
+ AddFixed("RVF" , 0x7f84);
+ AddFixed("RZF" , 0x7f8c);
+ AddFixed("SCF" , 0x7f81);
+ AddFixed("SSF" , 0x7f89);
+ AddFixed("SVF" , 0x7f85);
+ AddFixed("SZF" , 0x7f8b);
+ AddFixed("UNLK", 0x7fa2);
+
+ RMWOrders=(RMWOrder *) malloc(sizeof(RMWOrder)*RMWOrderCount); InstrZ=0;
+ AddRMW("CALL" , 0x35, 0x36);
+ AddRMW("CLR" , 0x2b, 0x17);
+ AddRMW("CPL" , 0x28, 0x17);
+ AddRMW("EXTS" , 0x33, 0x16);
+ AddRMW("EXTZ" , 0x32, 0x16);
+ AddRMW("JP" , 0x34, 0x36);
+ AddRMW("MIRR" , 0x23, 0x17);
+ AddRMW("NEG" , 0x29, 0x17);
+ AddRMW("POP" , 0x20, 0x17);
+ AddRMW("PUSH" , 0x21, 0x07);
+ AddRMW("PUSHA", 0x31, 0x36);
+ AddRMW("RVBY" , 0x22, 0x17);
+ AddRMW("TJP" , 0x36, 0x16);
+ AddRMW("TST" , 0x2a, 0x17);
+
+ GASI1Orders=(char **) malloc(sizeof(char *)*GASI1OrderCount); InstrZ=0;
+ GASI1Orders[InstrZ++]="ADD";
+ GASI1Orders[InstrZ++]="SUB";
+ GASI1Orders[InstrZ++]="CP";
+ GASI1Orders[InstrZ++]="LD";
+
+ GASI2Orders=(char **) malloc(sizeof(char *)*GASI2OrderCount); InstrZ=0;
+ GASI2Orders[InstrZ++]="AND";
+ GASI2Orders[InstrZ++]="OR";
+ GASI2Orders[InstrZ++]="XOR";
+
+ TrinomOrders=(char **) malloc(sizeof(char *)*TrinomOrderCount); InstrZ=0;
+ TrinomOrders[InstrZ++]="ADD3";
+ TrinomOrders[InstrZ++]="SUB3";
+ TrinomOrders[InstrZ++]="MAC";
+ TrinomOrders[InstrZ++]="MACS";
+
+ BitOrders=(char **) malloc(sizeof(char *)*BitOrderCount); InstrZ=0;
+ BitOrders[InstrZ++]="BRES";
+ BitOrders[InstrZ++]="BSET";
+ BitOrders[InstrZ++]="BCHG";
+ BitOrders[InstrZ++]="BTST";
+
+ ShiftOrders=(char **) malloc(sizeof(char *)*ShiftOrderCount); InstrZ=0;
+ ShiftOrders[InstrZ++]="SLL";
+ ShiftOrders[InstrZ++]="SRL";
+ ShiftOrders[InstrZ++]="SLA";
+ ShiftOrders[InstrZ++]="SRA";
+ ShiftOrders[InstrZ++]="RL";
+ ShiftOrders[InstrZ++]="RR";
+ ShiftOrders[InstrZ++]="RLC";
+ ShiftOrders[InstrZ++]="RRC";
+
+ BFieldOrders=(char **) malloc(sizeof(char *)*BFieldOrderCount); InstrZ=0;
+ BFieldOrders[InstrZ++]="BFEX";
+ BFieldOrders[InstrZ++]="BFEXS";
+ BFieldOrders[InstrZ++]="BFIN";
+
+ GAEqOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*GAEqOrderCount); InstrZ=0;
+ AddGAEq("ABCD" , 0x10);
+ AddGAEq("ADC" , 0x04);
+ AddGAEq("CBCD" , 0x12);
+ AddGAEq("CPC" , 0x06);
+ AddGAEq("MAX" , 0x16);
+ AddGAEq("MAXS" , 0x17);
+ AddGAEq("MIN" , 0x14);
+ AddGAEq("MINS" , 0x15);
+ AddGAEq("SBC" , 0x05);
+ AddGAEq("SBCD" , 0x11);
+
+ GAHalfOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*GAHalfOrderCount); InstrZ=0;
+ AddGAHalf("DIV" , 0x26);
+ AddGAHalf("DIVS" , 0x27);
+ AddGAHalf("MUL" , 0x24);
+ AddGAHalf("MULS" , 0x25);
+
+ GAFirstOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*GAFirstOrderCount); InstrZ=0;
+ AddGAFirst("ANDCF", 0x44);
+ AddGAFirst("LDCF" , 0x47);
+ AddGAFirst("ORCF" , 0x45);
+ AddGAFirst("STCF" , 0x43);
+ AddGAFirst("TSET" , 0x70);
+ AddGAFirst("XORCF", 0x46);
+
+ GASecondOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*GASecondOrderCount); InstrZ=0;
+ AddGASecond("BS0B" , 0x54);
+ AddGASecond("BS0F" , 0x55);
+ AddGASecond("BS1B" , 0x56);
+ AddGASecond("BS1F" , 0x57);
+
+ StringOrders=(char **) malloc(sizeof(char *)*StringOrderCount); InstrZ=0;
+ StringOrders[InstrZ++]="CPSZ";
+ StringOrders[InstrZ++]="CPSN";
+ StringOrders[InstrZ++]="";
+ StringOrders[InstrZ++]="LDS";
+
+ Conditions=(char **) malloc(sizeof(char *)*ConditionCount); InstrZ=0;
+ Conditions[InstrZ++]="C"; Conditions[InstrZ++]="NC";
+ Conditions[InstrZ++]="Z"; Conditions[InstrZ++]="NZ";
+ Conditions[InstrZ++]="OV"; Conditions[InstrZ++]="NOV";
+ Conditions[InstrZ++]="MI"; Conditions[InstrZ++]="PL";
+ Conditions[InstrZ++]="LE"; Conditions[InstrZ++]="GT";
+ Conditions[InstrZ++]="LT"; Conditions[InstrZ++]="GE";
+ Conditions[InstrZ++]="ULE"; Conditions[InstrZ++]="UGT";
+ Conditions[InstrZ++]="N"; Conditions[InstrZ++]="A";
+ Conditions[InstrZ++]="ULT"; Conditions[InstrZ++]="UGE";
+ Conditions[InstrZ++]="EQ"; Conditions[InstrZ++]="NE";
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(RMWOrders);
+ free(GASI1Orders);
+ free(GASI2Orders);
+ free(TrinomOrders);
+ free(BitOrders);
+ free(ShiftOrders);
+ free(BFieldOrders);
+ free(GAEqOrders);
+ free(GAHalfOrders);
+ free(GAFirstOrders);
+ free(GASecondOrders);
+ free(StringOrders);
+ free(Conditions);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddSignedPrefix(Byte Index, Byte MaxBits, LongInt Value)
+BEGIN
+ LongInt Max;
+
+ Max=1l << (MaxBits-1);
+ if ((Value<-Max) OR (Value>=Max))
+ BEGIN
+ PrefUsed[Index]=True;
+ Prefs[Index]=(Value >> MaxBits) & 0x7ff;
+ END
+END
+
+ static Boolean AddRelPrefix(Byte Index, Byte MaxBits, LongInt *Value)
+BEGIN
+ LongInt Max1,Max2;
+
+ Max1=1l << (MaxBits-1);
+ Max2=1l << (MaxBits+10);
+ if ((*Value<-Max2) OR (*Value>=Max2)) WrError(1370);
+ else
+ BEGIN
+ if ((*Value<-Max1) OR (*Value>=Max1))
+ BEGIN
+ PrefUsed[Index]=True;
+ Prefs[Index]=((*Value) >> MaxBits) & 0x7ff;
+ END
+ return True;
+ END
+ return False;
+END
+
+ static void AddAbsPrefix(Byte Index, Byte MaxBits, LongInt Value)
+BEGIN
+ LongInt Dist;
+
+ Dist=1l << (MaxBits-1);
+ if ((Value>=Dist) AND (Value<0x1000000-Dist))
+ BEGIN
+ PrefUsed[Index]=True;
+ Prefs[Index]=(Value >> MaxBits) & 0x7ff;
+ END
+END
+
+ static void InsertSinglePrefix(Byte Index)
+BEGIN
+ if (PrefUsed[Index])
+ BEGIN
+ memmove(WAsmCode+1,WAsmCode+0,CodeLen);
+ WAsmCode[0]=Prefs[Index]+0xd000+(((Word)Index) << 11);
+ CodeLen+=2;
+ END
+END
+
+ static Boolean DecodeReg(char *Asc, Byte *Result)
+BEGIN
+ Byte tmp;
+ Boolean Err;
+
+ if ((strlen(Asc)>4) OR (strlen(Asc)<3) OR (toupper(*Asc)!='R')) return False;
+ switch (toupper(Asc[1]))
+ BEGIN
+ case 'B': *Result=0x00; break;
+ case 'W': *Result=0x40; break;
+ case 'D': *Result=0x80; break;
+ default: return False;
+ END
+ tmp=ConstLongInt(Asc+2,&Err);
+ if ((NOT Err) OR (tmp>15)) return False;
+ if ((*Result==0x80) AND (Odd(tmp))) return False;
+ *Result+=tmp; return True;
+END
+
+ static Boolean DecodeSpecReg(char *Asc, Byte *Result)
+BEGIN
+ if (strcasecmp(Asc,"SP")==0) *Result=0x8c;
+ else if (strcasecmp(Asc,"ISP")==0) *Result=0x81;
+ else if (strcasecmp(Asc,"ESP")==0) *Result=0x83;
+ else if (strcasecmp(Asc,"PBP")==0) *Result=0x05;
+ else if (strcasecmp(Asc,"CBP")==0) *Result=0x07;
+ else if (strcasecmp(Asc,"PSW")==0) *Result=0x89;
+ else if (strcasecmp(Asc,"IMC")==0) *Result=0x0b;
+ else if (strcasecmp(Asc,"CC")==0) *Result=0x0e;
+ else return False;
+ return True;
+END
+
+ static Boolean DecodeRegAdr(char *Asc, Byte *Erg)
+BEGIN
+ if (NOT DecodeReg(Asc,Erg)) return False;
+ if (OpSize==-1) OpSize=(*Erg) >> 6;
+ if (((*Erg) >> 6)!=OpSize)
+ BEGIN
+ WrError(1132); return False;
+ END
+ *Erg&=0x3f;
+ return True;
+END
+
+ static void DecodeAdr(char *Asc, Byte PrefInd, Boolean MayImm, Boolean MayReg)
+BEGIN
+#define FreeReg 0xff
+#define SPReg 0xfe
+#define PCReg 0xfd
+
+ Byte Reg;
+ String AdrPart,tmp;
+ Byte BaseReg,IndReg,ScaleFact;
+ LongInt DispPart,DispAcc;
+ Boolean OK,MinFlag,NMinFlag;
+ char *MPos,*PPos,*EPos;
+ int l;
+
+ AdrCnt=0; AdrOK=False;
+
+ /* I. Speicheradresse */
+
+ if (IsIndirect(Asc))
+ BEGIN
+ /* I.1. vorkonditionieren */
+
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0'; KillBlanks(Asc);
+
+ /* I.2. Predekrement */
+
+ if ((*Asc=='-') AND (Asc[1]=='-')
+ AND (DecodeReg(Asc+2,&Reg)))
+ BEGIN
+ switch (Reg >> 6)
+ BEGIN
+ case 0:
+ WrError(1350); break;
+ case 1:
+ AdrMode=0x50+(Reg & 15); AdrOK=True;
+ break;
+ case 2:
+ AdrMode=0x71+(Reg & 14); AdrOK=True;
+ break;
+ END
+ return;
+ END
+
+ /* I.3. Postinkrement */
+
+ l=strlen(Asc);
+ if ((Asc[l-1]=='+') AND (Asc[l-2]=='+'))
+ BEGIN
+ strmaxcpy(AdrPart,Asc,255); AdrPart[l-2]='\0';
+ if (DecodeReg(AdrPart,&Reg))
+ BEGIN
+ switch (Reg >> 6)
+ BEGIN
+ case 0:
+ WrError(1350); break;
+ case 1:
+ AdrMode=0x40+(Reg & 15); AdrOK=True;
+ break;
+ case 2:
+ AdrMode=0x70+(Reg & 14); AdrOK=True;
+ break;
+ END
+ return;
+ END
+ END
+
+ /* I.4. Adresskomponenten zerlegen */
+
+ BaseReg=FreeReg; IndReg=FreeReg; ScaleFact=0;
+ DispAcc=AdrInc; MinFlag=False;
+ while (*Asc!='\0')
+ BEGIN
+
+ /* I.4.a. Trennzeichen suchen */
+
+ MPos=QuotPos(Asc,'-'); PPos=QuotPos(Asc,'+');
+ if (PPos==Nil) EPos=MPos;
+ else if (MPos==Nil) EPos=PPos;
+ else EPos=min(MPos,PPos);
+ NMinFlag=((EPos!=Nil) AND (*EPos=='-'));
+ if (EPos==Nil)
+ BEGIN
+ strmaxcpy(AdrPart,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *EPos='\0'; strmaxcpy(AdrPart,Asc,255); strcpy(Asc,EPos+1);
+ END
+
+ /* I.4.b. Indexregister mit Skalierung */
+
+ EPos=QuotPos(AdrPart,'*');
+ if (EPos!=Nil)
+ BEGIN
+ strcpy(tmp,AdrPart); tmp[EPos-AdrPart]='\0';
+ END
+ l=strlen(AdrPart);
+ if ((EPos==AdrPart+l-2)
+ AND ((AdrPart[l-1]=='1') OR (AdrPart[l-1]=='2') OR (AdrPart[l-1]=='4') OR (AdrPart[l-1]=='8'))
+ AND (DecodeReg(tmp,&Reg)))
+ BEGIN
+ if (((Reg >> 6)==0) OR (MinFlag) OR (IndReg!=FreeReg))
+ BEGIN
+ WrError(1350); return;
+ END
+ IndReg=Reg;
+ switch (AdrPart[l-1])
+ BEGIN
+ case '1': ScaleFact=0; break;
+ case '2': ScaleFact=1; break;
+ case '4': ScaleFact=2; break;
+ case '8': ScaleFact=3; break;
+ END
+ END
+
+ /* I.4.c. Basisregister */
+
+ else if (DecodeReg(AdrPart,&Reg))
+ BEGIN
+ if (((Reg >> 6)==0) OR (MinFlag))
+ BEGIN
+ WrError(1350); return;
+ END
+ if (BaseReg==FreeReg) BaseReg=Reg;
+ else if (IndReg==FreeReg)
+ BEGIN
+ IndReg=Reg; ScaleFact=0;
+ END
+ else
+ BEGIN
+ WrError(1350); return;
+ END
+ END
+
+ /* I.4.d. Sonderregister */
+
+ else if ((strcasecmp(AdrPart,"PC")==0) OR (strcasecmp(AdrPart,"SP")==0))
+ BEGIN
+ if ((BaseReg!=FreeReg) AND (IndReg==FreeReg))
+ BEGIN
+ IndReg=BaseReg; BaseReg=FreeReg; ScaleFact=0;
+ END;
+ if ((BaseReg!=FreeReg) OR (MinFlag))
+ BEGIN
+ WrError(1350); return;
+ END
+ BaseReg=(strcasecmp(AdrPart,"SP")==0) ? SPReg : PCReg;
+ END
+
+ /* I.4.e. Displacement */
+
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ DispPart=EvalIntExpression(AdrPart,Int32,&OK);
+ if (NOT OK) return;
+ if (FirstPassUnknown) DispPart=1;
+ if (MinFlag) DispAcc-=DispPart; else DispAcc+=DispPart;
+ END
+ MinFlag=NMinFlag;
+ END
+
+ /* I.5. Indexregister mit Skalierung 1 als Basis behandeln */
+
+ if ((BaseReg==FreeReg) AND (IndReg!=FreeReg) AND (ScaleFact==0))
+ BEGIN
+ BaseReg=IndReg; IndReg=FreeReg;
+ END
+
+ /* I.6. absolut */
+
+ if ((BaseReg==FreeReg) AND (IndReg==FreeReg))
+ BEGIN
+ AdrMode=0x20;
+ AdrVals[0]=0xe000+(DispAcc & 0x1fff); AdrCnt=2;
+ AddAbsPrefix(PrefInd,13,DispAcc);
+ AdrOK=True; return;
+ END
+
+ /* I.7. Basis [mit Displacement] */
+
+ if ((BaseReg!=FreeReg) AND (IndReg==FreeReg))
+ BEGIN
+
+ /* I.7.a. Basis ohne Displacement */
+
+ if (DispAcc==0)
+ BEGIN
+ if ((BaseReg >> 6)==1) AdrMode=0x10+(BaseReg & 15);
+ else AdrMode=0x61+(BaseReg & 14);
+ AdrOK=True; return;
+ END
+
+ /* I.7.b. Nullregister mit Displacement muss in Erweiterungswort */
+
+ else if ((BaseReg & 15)==0)
+ BEGIN
+ if (DispAcc>0x7ffff) WrError(1320);
+ else if (DispAcc<-0x80000) WrError(1315);
+ else
+ BEGIN
+ AdrMode=0x20;
+ if ((BaseReg >> 6)==1) AdrVals[0]=((Word)BaseReg & 15) << 11;
+ else AdrVals[0]=(((Word)BaseReg & 14) << 11)+0x8000;
+ AdrVals[0]+=DispAcc & 0x1ff; AdrCnt=2;
+ AddSignedPrefix(PrefInd,9,DispAcc);
+ AdrOK=True;
+ END
+ return;
+ END
+
+ /* I.7.c. Stack mit Displacement: Optimierung moeglich */
+
+ else if (BaseReg==SPReg)
+ BEGIN
+ if (DispAcc>0x7ffff) WrError(1320);
+ else if (DispAcc<-0x80000) WrError(1315);
+ else if ((DispAcc>=0) AND (DispAcc<=127))
+ BEGIN
+ AdrMode=0x80+(DispAcc & 0x7f); AdrOK=True;
+ END
+ else
+ BEGIN
+ AdrMode=0x20;
+ AdrVals[0]=0xd000+(DispAcc & 0x1ff); AdrCnt=2;
+ AddSignedPrefix(PrefInd,9,DispAcc);
+ AdrOK=True;
+ END
+ return;
+ END
+
+ /* I.7.d. Programmzaehler mit Displacement: keine Optimierung */
+
+ else if (BaseReg==PCReg)
+ BEGIN
+ if (DispAcc>0x7ffff) WrError(1320);
+ else if (DispAcc<-0x80000) WrError(1315);
+ else
+ BEGIN
+ AdrMode=0x20;
+ AdrVals[0]=0xd800+(DispAcc & 0x1ff); AdrCnt=2;
+ AddSignedPrefix(PrefInd,9,DispAcc);
+ AdrOK=True;
+ END
+ return;
+ END
+
+ /* I.7.e. einfaches Basisregister mit Displacement */
+
+ else
+ BEGIN
+ if (DispAcc>0x7fffff) WrError(1320);
+ else if (DispAcc<-0x800000) WrError(1315);
+ else
+ BEGIN
+ if ((BaseReg >> 6)==1) AdrMode=0x20+(BaseReg & 15);
+ else AdrMode=0x60+(BaseReg & 14);
+ AdrVals[0]=0xe000+(DispAcc & 0x1fff); AdrCnt=2;
+ AddSignedPrefix(PrefInd,13,DispAcc);
+ AdrOK=True;
+ END
+ return;
+ END
+ END
+
+ /* I.8. Index- [und Basisregister] */
+
+ else
+ BEGIN
+ if (DispAcc>0x7ffff) WrError(1320);
+ else if (DispAcc<-0x80000) WrError(1315);
+ else if ((IndReg & 15)==0) WrError(1350);
+ else
+ BEGIN
+ if ((IndReg >> 6)==1) AdrMode=0x20+(IndReg & 15);
+ else AdrMode=0x60+(IndReg & 14);
+ switch (BaseReg)
+ BEGIN
+ case FreeReg :AdrVals[0]=0xc000; break;
+ case SPReg :AdrVals[0]=0xd000; break;
+ case PCReg :AdrVals[0]=0xd800; break;
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ AdrVals[0]=((Word)BaseReg & 15) << 11; break;
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b:
+ case 0x8c: case 0x8d: case 0x8e:
+ AdrVals[0]=0x8000+(((Word)BaseReg & 14) << 10); break;
+ END
+ AdrVals[0]+=(((Word)ScaleFact) << 9)+(DispAcc & 0x1ff);
+ AdrCnt=2;
+ AddSignedPrefix(PrefInd,9,DispAcc);
+ AdrOK=True;
+ END
+ return;
+ END;
+ END
+
+ /* II. Arbeitsregister */
+
+ else if (DecodeReg(Asc,&Reg))
+ BEGIN
+ if (NOT MayReg) WrError(1350);
+ else
+ BEGIN
+ if (OpSize==-1) OpSize=Reg >> 6;
+ if ((Reg >> 6)!=OpSize) WrError(1131);
+ else
+ BEGIN
+ AdrMode=Reg & 15; AdrOK=True;
+ END
+ END
+ return;
+ END
+
+ /* III. Spezialregister */
+
+ else if (DecodeSpecReg(Asc,&Reg))
+ BEGIN
+ if (NOT MayReg) WrError(1350);
+ else
+ BEGIN
+ if (OpSize==-1) OpSize=Reg >> 6;
+ if ((Reg >> 6)!=OpSize) WrError(1131);
+ else
+ BEGIN
+ AdrMode=0x30+(Reg & 15); AdrOK=True;
+ END
+ END
+ return;
+ END
+
+ else if (NOT MayImm) WrError(1350);
+ else
+ BEGIN
+ if ((OpSize==-1) AND (MinOneIs0)) OpSize=0;
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ AdrMode=0x30;
+ switch (OpSize)
+ BEGIN
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc,Int8,&OK) & 0xff;
+ if (OK)
+ BEGIN
+ AdrCnt=2; AdrOK=True;
+ END
+ break;
+ case 1:
+ AdrVals[0]=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=2; AdrOK=True;
+ END
+ break;
+ case 2:
+ DispAcc=EvalIntExpression(Asc,Int32,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=DispAcc & 0xffff;
+ AdrVals[1]=DispAcc >> 16;
+ AdrCnt=4; AdrOK=True;
+ END
+ break;
+ END
+ END
+ END
+END
+
+ static void CopyAdr(void)
+BEGIN
+ OpSize2=OpSize;
+ AdrMode2=AdrMode;
+ AdrCnt2=AdrCnt;
+ memcpy(AdrVals2,AdrVals,AdrCnt);
+END
+
+ static Boolean IsReg(void)
+BEGIN
+ return (AdrMode<=15);
+END
+
+ static Boolean Is2Reg(void)
+BEGIN
+ return (AdrMode2<=15);
+END
+
+ static Boolean IsImmediate(void)
+BEGIN
+ return (AdrMode==0x30);
+END
+
+ static Boolean Is2Immediate(void)
+BEGIN
+ return (AdrMode2==0x30);
+END
+
+ static LongInt ImmVal(void)
+BEGIN
+ LongInt Tmp1;
+ Integer Tmp2;
+ ShortInt Tmp3;
+
+ switch (OpSize)
+ BEGIN
+ case 0:
+ Tmp3=AdrVals[0] & 0xff; return Tmp3;
+ case 1:
+ Tmp2=AdrVals[0]; return Tmp2;
+ case 2:
+ Tmp1=(((LongInt)AdrVals[1]) << 16)+AdrVals[0]; return Tmp1;
+ default:
+ WrError(10000); return 0;
+ END
+END
+
+ static LongInt ImmVal2(void)
+BEGIN
+ LongInt Tmp1;
+ Integer Tmp2;
+ ShortInt Tmp3;
+
+ switch (OpSize)
+ BEGIN
+ case 0:
+ Tmp3=AdrVals2[0] & 0xff; return Tmp3;
+ case 1:
+ Tmp2=AdrVals2[0]; return Tmp2;
+ case 2:
+ Tmp1=(((LongInt)AdrVals2[1]) << 16)+AdrVals2[0]; return Tmp1;
+ default:
+ WrError(10000); return 0;
+ END
+END
+
+ static Boolean IsAbsolute(void)
+BEGIN
+ return (((AdrMode==0x20) OR (AdrMode==0x60)) AND (AdrCnt==2)
+ AND ((AdrVals[0] & 0xe000)==0xe000));
+END
+
+ static Boolean Is2Absolute(void)
+BEGIN
+ return (((AdrMode2==0x20) OR (AdrMode2==0x60)) AND (AdrCnt2==2)
+ AND ((AdrVals2[0] & 0xe000)==0xe000));
+END
+
+ static Boolean IsShort(void)
+BEGIN
+ if (AdrMode<0x30) return True;
+ else if (AdrMode==0x30) return ((ImmVal()>=LowLim4) AND (ImmVal()<=7));
+ else return False;
+END
+
+ static Boolean Is2Short(void)
+BEGIN
+ if (AdrMode2<0x30) return True;
+ else if (AdrMode2==0x30) return ((ImmVal2()>=LowLim4) AND (ImmVal2()<=7));
+ else return False;
+END
+
+ static void ConvertShort(void)
+BEGIN
+ if (AdrMode==0x30)
+ BEGIN
+ AdrMode+=ImmVal() & 15; AdrCnt=0;
+ END
+END
+
+ static void Convert2Short(void)
+BEGIN
+ if (AdrMode2==0x30)
+ BEGIN
+ AdrMode2+=ImmVal2() & 15; AdrCnt2=0;
+ END
+END
+
+ static void SetULowLims(void)
+BEGIN
+ LowLim4=0; LowLim8=0;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void AddPrefixes(void)
+BEGIN
+ if (CodeLen!=0)
+ BEGIN
+ InsertSinglePrefix(1);
+ InsertSinglePrefix(0);
+ END
+END
+
+ static Boolean CodeAri(void)
+BEGIN
+ int z,Cnt;
+ Byte Reg;
+
+ for (z=0; z<GASI1OrderCount; z++)
+ if (Memo(GASI1Orders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],1,False,True);
+ if (AdrOK)
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[2],0,True,True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ if (Format==' ')
+ BEGIN
+ if (((IsReg()) AND (Is2Short()))
+ OR ((Is2Reg()) AND (IsShort()))) Format='S';
+ else if (((IsAbsolute()) AND (Is2Short()))
+ OR ((Is2Absolute()) AND (IsShort()))) Format='A';
+ else if ((IsImmediate()) AND (OpSize>0) AND ((ImmVal()>127) OR (ImmVal()<-128))) Format='I';
+ else Format='G';
+ END
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0x700+(((Word)OpSize+1) << 14);
+ if ((IsImmediate()) AND (ImmVal()<=127) AND (ImmVal()>=-128))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0x8400+(z << 8)+AdrMode2;
+ memcpy(WAsmCode+2+(AdrCnt >> 1),AdrVals2,AdrCnt2);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsShort()) AND (Is2Absolute()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x3900+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=(AdrVals2[0] & 0x1fff)+(z << 13);
+ CodeLen=4+AdrCnt;
+ END
+ else if ((Is2Short()) AND (IsAbsolute()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x3980+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=(AdrVals[0] & 0x1fff)+(z << 13);
+ CodeLen=4+AdrCnt2;
+ END
+ else WrError(1350);
+ break;
+ case 'S':
+ if ((IsShort()) AND (Is2Reg()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x0000+(((Word)OpSize+1) << 14)
+ +(AdrMode & 15)+(((Word)AdrMode & 0xf0) << 5)
+ +(((Word)AdrMode2 & 1) << 12)+((AdrMode2 & 14) << 4)
+ +((z & 1) << 4)+((z & 2) << 10);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ END
+ else if ((Is2Short()) AND (IsReg()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x0100+(((Word)OpSize+1) << 14)
+ +(AdrMode2 & 15)+(((Word)AdrMode2 & 0xf0) << 5)
+ +(((Word)AdrMode & 1) << 12)+((AdrMode & 14) << 4)
+ +((z & 1) << 4)+((z & 2) << 11);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2;
+ END
+ else WrError(1350);
+ break;
+ case 'I':
+ if ((NOT IsImmediate()) OR (OpSize==0)) WrError(1350);
+ else
+ BEGIN
+ WAsmCode[0]=AdrMode2+(((Word)OpSize-1) << 11)+(z << 8);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ memcpy(WAsmCode+1+(AdrCnt2 >> 1),AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt+AdrCnt2;
+ END
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return True;
+ END
+
+ for (z=0; z<GASI2OrderCount; z++)
+ if (Memo(GASI2Orders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],1,False,True);
+ if (AdrOK)
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[2],0,True,True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ if (Format==' ')
+ BEGIN
+ if ((IsReg()) AND (Is2Reg())) Format='S';
+ else if (((IsAbsolute()) AND (Is2Short()))
+ OR ((Is2Absolute()) AND (IsShort()))) Format='A';
+ else if ((IsImmediate()) AND (OpSize>0) AND ((ImmVal()>127) OR (ImmVal()<-128))) Format='I';
+ else Format='G';
+ END
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0x700+(((Word)OpSize+1) << 14);
+ if ((IsImmediate()) AND (ImmVal()<=127) AND (ImmVal()>=-128))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0xc400+(z << 8)+AdrMode2;
+ memcpy(WAsmCode+2+(AdrCnt >> 1),AdrVals2,AdrCnt2);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsShort()) AND (Is2Absolute()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x3940+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=(AdrVals2[0] & 0x1fff)+(z << 13);
+ CodeLen=4+AdrCnt;
+ END
+ else if ((Is2Short()) AND (IsAbsolute()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x39c0+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=(AdrVals[0] & 0x1fff)+(z << 13);
+ CodeLen=4+AdrCnt2;
+ END
+ else WrError(1350);
+ break;
+ case 'S':
+ if ((IsReg()) AND (Is2Reg()))
+ BEGIN
+ WAsmCode[0]=0x3800+(((Word)OpSize+1) << 14)
+ +(AdrMode & 15)+(AdrMode2 << 4)
+ +(z << 9);
+ CodeLen=2;
+ END
+ else WrError(1350);
+ break;
+ case 'I':
+ if ((NOT IsImmediate()) OR (OpSize==0)) WrError(1350);
+ else
+ BEGIN
+ WAsmCode[0]=0x400+AdrMode2+(((Word)OpSize-1) << 11)+(z << 8);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ memcpy(WAsmCode+1+(AdrCnt2 >> 1),AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt+AdrCnt2;
+ END
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return True;
+ END
+
+ for (z=0; z<TrinomOrderCount; z++)
+ if (Memo(TrinomOrders[z]))
+ BEGIN
+ if (Memo("MAC")) LowLim8=0;
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT DecodeRegAdr(ArgStr[1],&Reg)) WrError(1350);
+ else
+ BEGIN
+ if (z>=2) OpSize--;
+ if (OpSize<0) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[3],0,True,True);
+ if (AdrOK)
+ BEGIN
+ WAsmCode[0]=0x700;
+ if ((IsImmediate()) AND (ImmVal()<127) AND (ImmVal()>LowLim8))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=(((Word)OpSize+1) << 14)+AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt); Cnt=AdrCnt;
+ DecodeAdr(ArgStr[2],1,False,True);
+ if (AdrOK)
+ BEGIN
+ WAsmCode[1+(Cnt >> 1)]=AdrMode+(z << 8)+(((Word)Reg) << 11);
+ memcpy(WAsmCode+2+(Cnt >> 1),AdrVals,AdrCnt);
+ CodeLen=4+Cnt+AdrCnt;
+ END
+ END
+ END
+ END
+ AddPrefixes(); return True;
+ END
+
+ if ((Memo("RLM")) OR (Memo("RRM")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[2],&Reg)) WrError(1350);
+ else if ((Reg >> 6)!=1) WrError(1130);
+ else
+ BEGIN
+ Reg&=0x3f;
+ DecodeAdr(ArgStr[3],0,True,True);
+ if (AdrOK)
+ BEGIN
+ WAsmCode[0]=0x700;
+ if ((IsImmediate()) AND (ImmVal()<127) AND (ImmVal()>-128))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt); Cnt=AdrCnt;
+ DecodeAdr(ArgStr[1],1,False,True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ WAsmCode[0]+=((Word)OpSize+1) << 14;
+ WAsmCode[1+(Cnt >> 1)]=0x400+(((Word)Reg) << 11)+AdrMode;
+ if (Memo("RRM")) WAsmCode[1+(Cnt >> 1)]+=0x100;
+ memcpy(WAsmCode+2+(Cnt >> 1),AdrVals,AdrCnt);
+ CodeLen=4+AdrCnt+Cnt;
+ END
+ END
+ END
+ AddPrefixes(); return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_97C241(void)
+BEGIN
+ int z,Cnt;
+ Byte Reg,Num1,Num2;
+ char *p;
+ LongInt AdrInt,AdrLong;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False; PrefUsed[0]=False; PrefUsed[1]=False;
+ AdrInc=0; MinOneIs0=False; LowLim4=(-8); LowLim8=(-128);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Formatangabe abspalten */
+
+ switch (AttrSplit)
+ BEGIN
+ case '.':
+ p=strchr(AttrPart,':');
+ if (p!=0)
+ BEGIN
+ if (p<AttrPart+strlen(AttrPart)-1) Format=p[1];
+ else Format=' ';
+ *p='\0';
+ END
+ else Format=' ';
+ break;
+ case ':':
+ p=strchr(AttrPart,'.');
+ if (p==Nil)
+ BEGIN
+ Format=(*AttrPart); *AttrPart='\0';
+ END
+ else
+ BEGIN
+ if (p==AttrPart) Format=' '; else Format=(*AttrPart);
+ strcpy(AttrPart,p+1);
+ END
+ break;
+ default:
+ Format=' ';
+ END
+ Format=toupper(Format);
+
+ /* Attribut abarbeiten */
+
+ if (*AttrPart=='\0') OpSize=(-1);
+ else
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B': OpSize=0; break;
+ case 'W': OpSize=1; break;
+ case 'D': OpSize=2; break;
+ default:
+ WrError(1107); return;
+ END
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ WAsmCode[0]=FixedOrders[z].Code;
+ CodeLen=2;
+ END
+ return;
+ END
+
+ /* ein Operand */
+
+ for (z=0; z<RMWOrderCount; z++)
+ if (Memo(RMWOrders[z].Name))
+ BEGIN
+ if ((OpSize==-1) AND ((RMWOrders[z].Mask & 0x20)!=0)) OpSize=2;
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ if ((NOT IsIndirect(ArgStr[1])) AND ((RMWOrders[z].Mask & 0x20)!=0))
+ BEGIN
+ sprintf(ArgStr[2],"(%s)",ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]);
+ END
+ DecodeAdr(ArgStr[1],0,(RMWOrders[z].Mask & 0x10)==0,(RMWOrders[z].Mask & 0x20)==0);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else if ((RMWOrders[z].Mask & (1 << OpSize))==0) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=(((Word)OpSize+1) << 14)+(((Word)RMWOrders[z].Code) << 8)+AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ /* Arithmetik */
+
+ if (CodeAri()) return;
+
+ for (z=0; z<BitOrderCount; z++)
+ if (Memo(BitOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],1,False,True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ CopyAdr(); OpSize=(-1); MinOneIs0=True;
+ DecodeAdr(ArgStr[2],0,True,True);
+ if (AdrOK)
+ BEGIN
+ OpSize=OpSize2;
+ if (Format==' ')
+ BEGIN
+ if ((Is2Reg()) AND (IsImmediate())
+ AND (ImmVal()>0) AND (ImmVal()<(1 << (OpSize+3)))) Format='S';
+ else if (((IsShort()) AND (Is2Absolute()))
+ OR ((Is2Short()) AND (IsAbsolute()))) Format='A';
+ else Format='G';
+ END
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0x700+(((Word)OpSize+1) << 14);
+ if ((IsImmediate()) AND (ImmVal()>=LowLim8) AND (ImmVal()<127))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0xd400+(z << 8)+AdrMode2;
+ memcpy(WAsmCode+2+(AdrCnt >> 1),AdrVals2,AdrCnt2);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsAbsolute()) AND (Is2Short()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x39d0+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=(AdrVals[0] & 0x1fff)+(z << 13);
+ CodeLen=4+AdrCnt2;
+ END
+ else if ((Is2Absolute()) AND (IsShort()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x3950+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=(AdrVals2[0] & 0x1fff)+(z << 13);
+ CodeLen=4+AdrCnt;
+ END
+ else WrError(1350);
+ break;
+ case 'S':
+ if ((Is2Reg()) AND (IsImmediate()) AND (ImmVal()>=0) AND (ImmVal()<(1 << (3+OpSize))))
+ BEGIN
+ if (OpSize==2)
+ BEGIN
+ if (ImmVal()>=16)
+ BEGIN
+ AdrVals[0]-=16; AdrMode2++;
+ END
+ OpSize=1;
+ END
+ if (OpSize==1)
+ if (ImmVal()<8) OpSize=0;
+ else AdrVals[0]-=8;
+ WAsmCode[0]=0x1700+(((Word)OpSize+1) << 14)
+ +((z & 1) << 7)+((z & 2) << 10)
+ +(ImmVal() << 4)+AdrMode2;
+ CodeLen=2;
+ END
+ else WrError(1350);
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<ShiftOrderCount; z++)
+ if (Memo(ShiftOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],1,False,True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ CopyAdr(); OpSize=(-1); MinOneIs0=True;
+ DecodeAdr(ArgStr[2],0,True,True);
+ if (AdrOK)
+ BEGIN
+ OpSize=OpSize2;
+ if (Format==' ')
+ BEGIN
+ if ((IsImmediate()) AND (ImmVal()==1)) Format='S';
+ else if (((IsShort()) AND (Is2Absolute()))
+ OR ((Is2Short()) AND (IsAbsolute()))) Format='A';
+ else Format='G';
+ END
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0x700+(((Word)OpSize+1) << 14);
+ if ((IsImmediate()) AND (ImmVal()>=LowLim8) AND (ImmVal()<127))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0xb400+((z & 3) << 8)+((z & 4) << 9)+AdrMode2;
+ memcpy(WAsmCode+2+(AdrCnt >> 1),AdrVals2,AdrCnt2);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsAbsolute()) AND (Is2Short()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x39b0+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=(AdrVals[0] & 0x1fff)+(z << 13);
+ CodeLen=4+AdrCnt2;
+ END
+ else if ((Is2Absolute()) AND (IsShort()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x3930+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=(AdrVals2[0] & 0x1fff)+(z << 13);
+ CodeLen=4+AdrCnt;
+ END
+ else WrError(1350);
+ break;
+ case 'S':
+ if ((IsImmediate()) AND (ImmVal()==1))
+ BEGIN
+ WAsmCode[0]=0x2400+(((Word)OpSize+1) << 14)+AdrMode2
+ +((z & 3) << 8)+((z & 4) << 9);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ else WrError(1350);
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<BFieldOrderCount; z++)
+ if (Memo(BFieldOrders[z]))
+ BEGIN
+ if (ArgCnt!=4) WrError(1110);
+ else
+ BEGIN
+ if (z==2)
+ BEGIN
+ strcpy(ArgStr[5],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[5]);
+ END
+ if (NOT DecodeReg(ArgStr[1],&Reg)) WrError(1350);
+ else if ((Reg >> 6)!=1) WrError(1130);
+ else
+ BEGIN
+ Reg&=0x3f;
+ Num2=EvalIntExpression(ArgStr[4],Int5,&OK);
+ if (OK)
+ BEGIN
+ if (FirstPassUnknown) Num2&=15; Num2--;
+ if (Num2>15) WrError(1320);
+ else if ((OpSize==-1) AND (NOT DecodeRegAdr(ArgStr[2],&Num1))) WrError(1132);
+ else
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case 0: Num1=EvalIntExpression(ArgStr[3],UInt3,&OK) & 7; break;
+ case 1: Num1=EvalIntExpression(ArgStr[3],Int4,&OK) & 15; break;
+ case 2: Num1=EvalIntExpression(ArgStr[3],Int5,&OK) & 31; break;
+ END
+ if (OK)
+ BEGIN
+ if ((OpSize==2) AND (Num1>15)) AdrInc=2;
+ DecodeAdr(ArgStr[2],1,False,True);
+ if (AdrOK)
+ BEGIN
+ if ((OpSize==2) AND (Num1>15))
+ BEGIN
+ Num1-=16; OpSize--;
+ if ((AdrMode & 0xf0)==0) AdrMode++;
+ END
+ WAsmCode[0]=0x7000+(((Word)OpSize+1) << 8)+AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=(((Word)Reg) << 11)
+ +Num2+(((Word)Num1) << 5)
+ +((z & 1) << 10)
+ +((z & 2) << 14);
+ CodeLen=4+AdrCnt;
+ END
+ END
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<GAEqOrderCount; z++)
+ if (Memo(GAEqOrders[z].Name))
+ BEGIN
+ if ((Memo("ABCD")) OR (Memo("SBCD")) OR (Memo("CBCD"))
+ OR (Memo("MAX")) OR (Memo("MIN")) OR (Memo("SBC"))) SetULowLims();
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],1,False,True);
+ if (AdrOK)
+ BEGIN
+ CopyAdr();
+ DecodeAdr(ArgStr[2],0,True,True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ if (OpSize==0) LowLim8=(-128);
+ if (Format==' ')
+ BEGIN
+ if (((Is2Absolute()) AND (IsShort()))
+ OR ((Is2Short()) AND (IsAbsolute()))) Format='A';
+ else Format='G';
+ END
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0x700+(((Word)OpSize+1) << 14);
+ if ((IsImmediate()) AND (ImmVal()<127) AND (ImmVal()>LowLim8))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0x8400+AdrMode2
+ +(((Word)GAEqOrders[z].Code & 0xf0) << 8)
+ +(((Word)GAEqOrders[z].Code & 4) << 9)
+ +(((Word)GAEqOrders[z].Code & 3) << 8);
+ memcpy(WAsmCode+2+(AdrCnt >> 1),AdrVals2,AdrCnt2);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsAbsolute()) AND (Is2Short()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x3980+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15)
+ +(GAEqOrders[z].Code & 0xf0);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=(AdrVals[0] & 0x1fff)
+ +(((Word)GAEqOrders[z].Code & 15) << 13);
+ CodeLen=4+AdrCnt2;
+ END
+ else if ((Is2Absolute()) AND (IsShort()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x3900+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15)
+ +(GAEqOrders[z].Code & 0xf0);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=(AdrVals2[0] & 0x1fff)
+ +(((Word)GAEqOrders[z].Code & 15) << 13);
+ CodeLen=4+AdrCnt;
+ END
+ else WrError(1350);
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<GAHalfOrderCount; z++)
+ if (Memo(GAHalfOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],1,False,True);
+ if (AdrOK)
+ if (OpSize==0) WrError(1130);
+ else
+ BEGIN
+ if (OpSize!=-1) OpSize--; CopyAdr();
+ DecodeAdr(ArgStr[2],0,True,True);
+ if (AdrOK)
+ if (OpSize==2) WrError(1130);
+ else if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ if (Format==' ')
+ BEGIN
+ if (((Is2Absolute()) AND (IsShort))
+ OR ((Is2Short()) AND (IsAbsolute()))) Format='A';
+ else Format='G';
+ END;
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0x700+(((Word)OpSize+1) << 14);
+ if ((IsImmediate()) AND (ImmVal()<127) AND (ImmVal()>LowLim8))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0x8400+AdrMode2
+ +(((Word)GAHalfOrders[z].Code & 0xf0) << 8)
+ +(((Word)GAHalfOrders[z].Code & 4) << 9)
+ +(((Word)GAHalfOrders[z].Code & 3) << 8);
+ memcpy(WAsmCode+2+(AdrCnt >> 1),AdrVals2,AdrCnt2);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsAbsolute()) AND (Is2Short()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x3980+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15)
+ +(GAHalfOrders[z].Code & 0xf0);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=(AdrVals[0] & 0x1fff)
+ +(((Word)GAHalfOrders[z].Code & 15) << 13);
+ CodeLen=4+AdrCnt2;
+ END
+ else if ((Is2Absolute()) AND (IsShort()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x3900+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15)
+ +(GAHalfOrders[z].Code & 0xf0);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=(AdrVals2[0] & 0x1fff)
+ +(((Word)GAHalfOrders[z].Code & 15) << 13);
+ CodeLen=4+AdrCnt;
+ END
+ else WrError(1350);
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<GAFirstOrderCount; z++)
+ if (Memo(GAFirstOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],1,NOT(Memo("STCF") OR Memo("TSET")),True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ CopyAdr(); OpSize=(-1); MinOneIs0=True;
+ DecodeAdr(ArgStr[2],0,True,True);
+ OpSize=OpSize2;
+ if (AdrOK)
+ BEGIN
+ if (Format==' ')
+ BEGIN
+ if (((Is2Absolute()) AND (IsShort()))
+ OR ((Is2Short()) AND (IsAbsolute()))) Format='A';
+ else Format='G';
+ END
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0x700+(((Word)OpSize+1) << 14);
+ if ((IsImmediate()) AND (ImmVal()<127) AND (ImmVal()>LowLim8))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0x8400+AdrMode2
+ +(((Word)GAFirstOrders[z].Code & 0xf0) << 8)
+ +(((Word)GAFirstOrders[z].Code & 4) << 9)
+ +(((Word)GAFirstOrders[z].Code & 3) << 8);
+ memcpy(WAsmCode+2+(AdrCnt >> 1),AdrVals2,AdrCnt2);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsAbsolute()) AND (Is2Short()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x3980+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15)
+ +(GAFirstOrders[z].Code & 0xf0);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=(AdrVals[0] & 0x1fff)
+ +(((Word)GAFirstOrders[z].Code & 15) << 13);
+ CodeLen=4+AdrCnt2;
+ END
+ else if ((Is2Absolute()) AND (IsShort()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x3900+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15)
+ +(GAFirstOrders[z].Code & 0xf0);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=(AdrVals2[0] & 0x1fff)
+ +(((Word)GAFirstOrders[z].Code & 15) << 13);
+ CodeLen=4+AdrCnt;
+ END
+ else WrError(1350);
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ for (z=0; z<GASecondOrderCount; z++)
+ if (Memo(GASecondOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],0,True,True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ CopyAdr(); OpSize=(-1);
+ DecodeAdr(ArgStr[1],1,False,True);
+ OpSize=OpSize2;
+ if (AdrOK)
+ BEGIN
+ if (Format==' ')
+ BEGIN
+ if (((Is2Absolute()) AND (IsShort()))
+ OR ((Is2Short()) AND (IsAbsolute()))) Format='A';
+ else Format='G';
+ END
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0x700+(((Word)OpSize+1) << 14);
+ if ((Is2Immediate()) AND (ImmVal2()<127) AND (ImmVal2()>LowLim8))
+ BEGIN
+ AdrMode2=ImmVal2() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode2;
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=0x8400+AdrMode
+ +(((Word)GASecondOrders[z].Code & 0xf0) << 8)
+ +(((Word)GASecondOrders[z].Code & 4) << 9)
+ +(((Word)GASecondOrders[z].Code & 3) << 8);
+ memcpy(WAsmCode+2+(AdrCnt2 >> 1),AdrVals,AdrCnt);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsAbsolute()) AND (Is2Short()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x3900+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15)
+ +(GASecondOrders[z].Code & 0xf0);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=(AdrVals[0] & 0x1fff)
+ +(((Word)GASecondOrders[z].Code & 15) << 13);
+ CodeLen=4+AdrCnt2;
+ END
+ else if ((Is2Absolute()) AND (IsShort()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x3980+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15)
+ +(GASecondOrders[z].Code & 0xf0);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=(AdrVals2[0] & 0x1fff)
+ +(((Word)GASecondOrders[z].Code & 15) << 13);
+ CodeLen=4+AdrCnt;
+ END
+ else WrError(1350);
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if ((Memo("CHK")) OR (Memo("CHKS")))
+ BEGIN
+ if (Memo("CHK")) SetULowLims();
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],1,False,True);
+ if (AdrOK)
+ if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ CopyAdr();
+ DecodeAdr(ArgStr[1],0,False,False);
+ if (AdrOK)
+ BEGIN
+ if (OpSize==0) LowLim8=(-128);
+ if (Format==' ')
+ BEGIN
+ if (((Is2Absolute()) AND (IsShort()))
+ OR ((Is2Short()) AND (IsAbsolute()))) Format='A';
+ else Format='G';
+ END
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0xf00+(((Word)OpSize+1) << 14)+AdrMode2;
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=0xa600+AdrMode
+ +(((Word)Memo("CHKS")) << 8);
+ memcpy(WAsmCode+2+(AdrCnt2 >> 1),AdrVals,AdrCnt);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsAbsolute()) AND (Is2Short()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x3920+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=0x4000+(AdrVals[0] & 0x1fff)
+ +(((Word)Memo("CHKS")) << 13);
+ CodeLen=4+AdrCnt2;
+ END
+ else if ((Is2Absolute()) AND (IsShort()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x39a0+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0x4000+(AdrVals2[0] & 0x1fff)
+ +(((Word)Memo("CHKS")) << 13);
+ CodeLen=4+AdrCnt;
+ END
+ else WrError(1350);
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ /* Datentransfer */
+
+ for (z=0; z<StringOrderCount; z++)
+ if (Memo(StringOrders[z]))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[3],&Reg)) WrError(1350);
+ else if ((Reg >> 6)!=1) WrError(1130);
+ else
+ BEGIN
+ Reg&=0x3f;
+ DecodeAdr(ArgStr[2],0,True,True);
+ if (AdrOK)
+ BEGIN
+ WAsmCode[0]=0x700;
+ if ((IsImmediate()) AND (ImmVal()<127) AND (ImmVal()>LowLim8))
+ BEGIN
+ AdrMode=ImmVal() & 0xff; AdrCnt=0;
+ END
+ else WAsmCode[0]+=0x800;
+ WAsmCode[0]+=AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt); Cnt=AdrCnt;
+ DecodeAdr(ArgStr[1],1,True,True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ WAsmCode[0]+=((Word)OpSize+1) << 14;
+ WAsmCode[1+(Cnt >> 1)]=0x8000+AdrMode+(z << 8)+(((Word)Reg) << 11);
+ memcpy(WAsmCode+2+(Cnt >> 1),AdrVals,AdrCnt);
+ CodeLen=4+AdrCnt+Cnt;
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END;
+
+ if (Memo("EX"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],1,False,True);
+ if (AdrOK)
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[2],0,False,True);
+ if (AdrOK)
+ if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ if (Format==' ')
+ BEGIN
+ if ((IsReg()) AND (Is2Reg())) Format='S';
+ else if (((IsShort()) AND (Is2Absolute()))
+ OR ((Is2Short()) AND (IsAbsolute()))) Format='A';
+ else Format='G';
+ END
+ switch (Format)
+ BEGIN
+ case 'G':
+ WAsmCode[0]=0x0f00+(((Word)OpSize+1) << 14)+AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0x8f00+AdrMode2;
+ memcpy(WAsmCode+2+(AdrCnt >> 1),AdrVals2,AdrCnt2);
+ CodeLen=4+AdrCnt+AdrCnt2;
+ break;
+ case 'A':
+ if ((IsAbsolute()) AND (Is2Short()))
+ BEGIN
+ Convert2Short();
+ WAsmCode[0]=0x3980+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode2 & 0xf0) << 5)+(AdrMode2 & 15);
+ memcpy(WAsmCode+1,AdrVals2,AdrCnt2);
+ WAsmCode[1+(AdrCnt2 >> 1)]=AdrVals[0];
+ CodeLen=4+AdrCnt2;
+ END
+ else if ((Is2Absolute()) AND (IsShort()))
+ BEGIN
+ ConvertShort();
+ WAsmCode[0]=0x3900+(((Word)OpSize+1) << 14)
+ +(((Word)AdrMode & 0xf0) << 5)+(AdrMode & 15);
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=AdrVals2[0];
+ CodeLen=4+AdrCnt;
+ END
+ else WrError(1350);
+ break;
+ case 'S':
+ if ((IsReg()) AND (Is2Reg()))
+ BEGIN
+ WAsmCode[0]=0x3e00+(((Word)OpSize+1) << 14)+(AdrMode2 << 4)+AdrMode;
+ CodeLen=2;
+ END
+ else WrError(1350);
+ break;
+ default:
+ WrError(1090);
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ /* Spruenge */
+
+ if ((Memo("CALR")) OR (Memo("JR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int32,&OK)-EProgCounter();
+ if (OK)
+ if (AddRelPrefix(0,13,&AdrInt))
+ if (Odd(AdrInt)) WrError(1375);
+ else
+ BEGIN
+ WAsmCode[0]=0x2000+(AdrInt & 0x1ffe)+Ord(Memo("CALR"));
+ CodeLen=2;
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if (Memo("JRC"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ NLS_UpString(ArgStr[1]);
+ for (z=0; z<ConditionCount; z++)
+ if (strcmp(ArgStr[1],Conditions[z])==0) break;
+ if (z>=ConditionCount) WrError(1360);
+ else
+ BEGIN
+ z%=16;
+ AdrInt=EvalIntExpression(ArgStr[2],Int32,&OK)-EProgCounter();
+ if (OK)
+ if (AddRelPrefix(0,9,&AdrInt))
+ if (Odd(AdrInt)) WrError(1375);
+ else
+ BEGIN
+ WAsmCode[0]=0x1000+((z & 14) << 8)+(AdrInt & 0x1fe)+(z & 1);
+ CodeLen=2;
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if ((Memo("JRBC")) OR (Memo("JRBS")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ z=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(ArgStr[2],Int24,&OK);
+ if (OK)
+ BEGIN
+ AddAbsPrefix(1,13,AdrLong);
+ AdrInt=EvalIntExpression(ArgStr[3],Int32,&OK)-EProgCounter();
+ if (OK)
+ if (AddRelPrefix(0,9,&AdrInt))
+ if (Odd(AdrInt)) WrError(1375);
+ else
+ BEGIN
+ CodeLen=4;
+ WAsmCode[1]=(z << 13)+(AdrLong & 0x1fff);
+ WAsmCode[0]=0x1e00+(AdrInt & 0x1fe)+Ord(Memo("JRBS"));
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if (Memo("DJNZ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],0,False,True);
+ if (AdrOK)
+ if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int32,&OK)-(EProgCounter()+4+AdrCnt+2*Ord(PrefUsed[0]));
+ if (OK)
+ if (AddRelPrefix(1,13,&AdrInt))
+ if (Odd(AdrInt)) WrError(1375);
+ else
+ BEGIN
+ WAsmCode[0]=0x3700+(((Word)OpSize+1) << 14)+AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=0xe000+(AdrInt & 0x1ffe);
+ CodeLen=4+AdrCnt;
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if (Memo("DJNZC"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ NLS_UpString(ArgStr[2]);
+ for (z=0; z<ConditionCount; z++)
+ if (strcmp(ArgStr[2],Conditions[z])==0) break;
+ if (z>=ConditionCount) WrError(1360);
+ else
+ BEGIN
+ z%=16;
+ DecodeAdr(ArgStr[1],0,False,True);
+ if (AdrOK)
+ if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[3],Int32,&OK)-EProgCounter();
+ if (OK)
+ if (AddRelPrefix(1,13,&AdrInt))
+ if (Odd(AdrInt)) WrError(1375);
+ else
+ BEGIN
+ WAsmCode[0]=0x3700+(((Word)OpSize+1) << 14)+AdrMode;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[1+(AdrCnt >> 1)]=((z & 14) << 12)+(AdrInt & 0x1ffe)+(z & 1);
+ CodeLen=4+AdrCnt;
+ END
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ /* vermischtes... */
+
+ if ((Memo("LINK")) OR (Memo("RETD")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrInt=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (FirstPassUnknown) AdrInt&=0x1fe;
+ if (AdrInt>0x7ffff) WrError(1320);
+ else if (AdrInt<-0x80000) WrError(1315);
+ else if (Odd(AdrInt)) WrError(1325);
+ else
+ BEGIN
+ WAsmCode[0]=0xc001+(AdrInt & 0x1fe);
+ if (Memo("RETD")) WAsmCode[0]+=0x800;
+ AddSignedPrefix(0,9,AdrInt);
+ CodeLen=2;
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ if (Memo("SWI"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[1],Int4,&OK)+0x7f90;
+ if (OK) CodeLen=2;
+ END
+ return;
+ END
+
+ if (Memo("LDA"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],0,False,False);
+ if (AdrOK)
+ BEGIN
+ WAsmCode[0]=0x3000+AdrMode;
+ z=AdrCnt; memcpy(WAsmCode+1,AdrVals,z);
+ DecodeAdr(ArgStr[1],1,False,True);
+ if (AdrOK)
+ if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]+=((Word)OpSize) << 14;
+ WAsmCode[1+(z >> 1)]=0x9700+AdrMode;
+ memcpy(WAsmCode+2+(z >> 1),AdrVals,AdrCnt);
+ CodeLen=4+z+AdrCnt;
+ END
+ END
+ END
+ AddPrefixes(); return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_97C241(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_97C241(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_97C241(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x56; NOPCode=0x7fa0;
+ DivideChars=","; HasAttrs=True; AttrChars=".:";
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffffffl;
+
+ MakeCode=MakeCode_97C241; IsDef=IsDef_97C241;
+ SwitchFrom=SwitchFrom_97C241; InitFields();
+END
+
+ void code97c241_init(void)
+BEGIN
+ CPU97C241=AddCPU("97C241",SwitchTo_97C241);
+END
diff --git a/code97c241.h b/code97c241.h
new file mode 100644
index 0000000..745b748
--- /dev/null
+++ b/code97c241.h
@@ -0,0 +1,11 @@
+/* code97c241.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TLCS-9000 */
+/* */
+/* Historie: */
+/* */
+/*****************************************************************************/
+
+extern void code97c241_init(void);
diff --git a/code9900.c b/code9900.c
new file mode 100644
index 0000000..9b56527
--- /dev/null
+++ b/code9900.c
@@ -0,0 +1,685 @@
+/* code9900.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS99xx */
+/* */
+/* Historie: 9. 3.1997 Grundsteinlegung */
+/* 18. 8.1998 BookKeeping-Aufruf bei BSS */
+/* 2. 1.1999 ChkPC angepasst */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "strutil.h"
+#include "endian.h"
+#include "bpemu.h"
+#include "nls.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+#define TwoOrderCount 6
+#define OneOrderCount 6
+#define SingOrderCount 16
+#define SBitOrderCount 3
+#define JmpOrderCount 13
+#define ShiftOrderCount 4
+#define ImmOrderCount 5
+#define RegOrderCount 4
+#define FixedOrderCount 6
+
+
+typedef struct
+ {
+ char *Name;
+ int NameLen;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ int NameLen;
+ Word Code;
+ Boolean MustSup;
+ } SupOrder;
+
+
+static CPUVar CPU9900;
+
+static Boolean IsWord;
+static Word AdrVal,AdrPart;
+
+static FixedOrder *TwoOrders;
+static FixedOrder *OneOrders;
+static SupOrder *SingOrders;
+static FixedOrder *SBitOrders;
+static FixedOrder *JmpOrders;
+static FixedOrder *ShiftOrders;
+static FixedOrder *ImmOrders;
+static FixedOrder *RegOrders;
+static SupOrder *FixedOrders;
+
+/*-------------------------------------------------------------------------*/
+/* dynamische Belegung/Freigabe Codetabellen */
+
+ static void AddTwo(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=TwoOrderCount) exit(255);
+ TwoOrders[InstrZ].Name=NName;
+ TwoOrders[InstrZ].Code=NCode;
+ TwoOrders[InstrZ++].NameLen=strlen(NName);
+END
+
+ static void AddOne(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=OneOrderCount) exit(255);
+ OneOrders[InstrZ].Name=NName;
+ OneOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddSing(char *NName, Word NCode,Boolean NSup)
+BEGIN
+ if (InstrZ>=SingOrderCount) exit(255);
+ SingOrders[InstrZ].Name=NName;
+ SingOrders[InstrZ].MustSup=NSup;
+ SingOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddSBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=SBitOrderCount) exit(255);
+ SBitOrders[InstrZ].Name=NName;
+ SBitOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddJmp(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=JmpOrderCount) exit(255);
+ JmpOrders[InstrZ].Name=NName;
+ JmpOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddShift(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ShiftOrderCount) exit(255);
+ ShiftOrders[InstrZ].Name=NName;
+ ShiftOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddImm(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ImmOrderCount) exit(255);
+ ImmOrders[InstrZ].Name=NName;
+ ImmOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddReg(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=RegOrderCount) exit(255);
+ RegOrders[InstrZ].Name=NName;
+ RegOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddFixed(char *NName, Word NCode, Boolean NSup)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].MustSup=NSup;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ TwoOrders=(FixedOrder *) malloc(TwoOrderCount*sizeof(FixedOrder)); InstrZ=0;
+ AddTwo("A" ,5); AddTwo("C" ,4); AddTwo("S" ,3);
+ AddTwo("SOC" ,7); AddTwo("SZC" ,2); AddTwo("MOV" ,6);
+
+ OneOrders=(FixedOrder *) malloc(OneOrderCount*sizeof(FixedOrder)); InstrZ=0;
+ AddOne("COC" ,0x08); AddOne("CZC" ,0x09); AddOne("XOR" ,0x0a);
+ AddOne("MPY" ,0x0e); AddOne("DIV" ,0x0f); AddOne("XOP" ,0x0b);
+
+ SingOrders=(SupOrder *) malloc(SingOrderCount*sizeof(SupOrder)); InstrZ=0;
+ AddSing("B" ,0x0440,False); AddSing("BL" ,0x0680,False); AddSing("BLWP",0x0400,False);
+ AddSing("CLR" ,0x04c0,False); AddSing("SETO",0x0700,False); AddSing("INV" ,0x0540,False);
+ AddSing("NEG" ,0x0500,False); AddSing("ABS" ,0x0740,False); AddSing("SWPB",0x06c0,False);
+ AddSing("INC" ,0x0580,False); AddSing("INCT",0x05c0,False); AddSing("DEC" ,0x0600,False);
+ AddSing("DECT",0x0640,True ); AddSing("X" ,0x0480,False); AddSing("LDS" ,0x0780,True );
+ AddSing("LDD" ,0x07c0,True );
+
+ SBitOrders=(FixedOrder *) malloc(SBitOrderCount*sizeof(FixedOrder)); InstrZ=0;
+ AddSBit("SBO" ,0x1d); AddSBit("SBZ",0x1e); AddSBit("TB" ,0x1f);
+
+ JmpOrders=(FixedOrder *) malloc(JmpOrderCount*sizeof(FixedOrder)); InstrZ=0;
+ AddJmp("JEQ",0x13); AddJmp("JGT",0x15); AddJmp("JH" ,0x1b);
+ AddJmp("JHE",0x14); AddJmp("JL" ,0x1a); AddJmp("JLE",0x12);
+ AddJmp("JLT",0x11); AddJmp("JMP",0x10); AddJmp("JNC",0x17);
+ AddJmp("JNE",0x16); AddJmp("JNO",0x19); AddJmp("JOC",0x18);
+ AddJmp("JOP",0x1c);
+
+ ShiftOrders=(FixedOrder *) malloc(ShiftOrderCount*sizeof(FixedOrder)); InstrZ=0;
+ AddShift("SLA",0x0a); AddShift("SRA",0x08);
+ AddShift("SRC",0x0b); AddShift("SRL",0x09);
+
+ ImmOrders=(FixedOrder *) malloc(ImmOrderCount*sizeof(FixedOrder)); InstrZ=0;
+ AddImm("AI" ,0x011); AddImm("ANDI",0x012); AddImm("CI" ,0x014);
+ AddImm("LI" ,0x010); AddImm("ORI" ,0x013);
+
+ RegOrders=(FixedOrder *) malloc(RegOrderCount*sizeof(FixedOrder)); InstrZ=0;
+ AddReg("STST",0x02c); AddReg("LST",0x008);
+ AddReg("STWP",0x02a); AddReg("LWP",0x009);
+
+ FixedOrders=(SupOrder *) malloc(FixedOrderCount*sizeof(SupOrder)); InstrZ=0;
+ AddFixed("RTWP",0x0380,False); AddFixed("IDLE",0x0340,True );
+ AddFixed("RSET",0x0360,True ); AddFixed("CKOF",0x03c0,True );
+ AddFixed("CKON",0x03a0,True ); AddFixed("LREX",0x03e0,True );
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(TwoOrders);
+ free(OneOrders);
+ free(SingOrders);
+ free(SBitOrders);
+ free(JmpOrders);
+ free(ShiftOrders);
+ free(ImmOrders);
+ free(RegOrders);
+ free(FixedOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Adressparser */
+
+ static Boolean DecodeReg(char *Asc, Word *Erg)
+BEGIN
+ Boolean OK;
+ *Erg=EvalIntExpression(Asc,UInt4,&OK); return OK;
+END
+
+ static char *HasDisp(char *Asc)
+BEGIN
+ char *p;
+ int Lev;
+
+ if (Asc[strlen(Asc)-1]==')')
+ BEGIN
+ p=Asc+strlen(Asc)-2; Lev=0;
+ while ((p>=Asc) AND (Lev!=-1))
+ BEGIN
+ switch (*p)
+ BEGIN
+ case '(': Lev--; break;
+ case ')': Lev++; break;
+ END
+ if (Lev!=-1) p--;
+ END
+ if (Lev!=-1)
+ BEGIN
+ WrError(1300); p=Nil;
+ END
+ END
+ else p=Nil;
+
+ return p;
+END
+
+ static Boolean DecodeAdr(char *Asc)
+BEGIN
+ Boolean IncFlag;
+ String Reg;
+ Boolean OK;
+ char *p;
+
+ AdrCnt=0;
+
+ if (*Asc=='*')
+ BEGIN
+ Asc++;
+ if (Asc[strlen(Asc)-1]=='+')
+ BEGIN
+ IncFlag=True; Asc[strlen(Asc)-1]='\0';
+ END
+ else IncFlag=False;
+ if (DecodeReg(Asc,&AdrPart))
+ BEGIN
+ AdrPart+=0x10+(Ord(IncFlag) << 5);
+ return True;
+ END
+ return False;
+ END
+
+ if (*Asc=='@')
+ BEGIN
+ Asc++; p=HasDisp(Asc);
+ if (p==Nil)
+ BEGIN
+ FirstPassUnknown=False;
+ AdrVal=EvalIntExpression(Asc,UInt16,&OK);
+ if (OK)
+ BEGIN
+ AdrPart=0x20; AdrCnt=1;
+ if ((NOT FirstPassUnknown) AND (IsWord) AND (Odd(AdrVal))) WrError(180);
+ return True;
+ END
+ END
+ else
+ BEGIN
+ strmaxcpy(Reg,p+1,255); Reg[strlen(Reg)-1]='\0';
+ if (DecodeReg(Reg,&AdrPart))
+ if (AdrPart==0) WrXError(1445,Reg);
+ else
+ BEGIN
+ *p='\0';
+ AdrVal=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrPart+=0x20; AdrCnt=1; return True;
+ END
+ END
+ END
+ return False;
+ END
+
+ if (DecodeReg(Asc,&AdrPart)) return True;
+ else
+ BEGIN
+ WrError(1350); return False;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void PutByte(Byte Value)
+BEGIN
+ if (((CodeLen&1)==1) AND (NOT BigEndian))
+ BEGIN
+ BAsmCode[CodeLen]=BAsmCode[CodeLen-1];
+ BAsmCode[CodeLen-1]=Value;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=Value;
+ END
+ CodeLen++;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ int z;
+ char *p;
+ Boolean OK;
+ TempResult t;
+ Word HVal16;
+
+ if (Memo("BYTE"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z=1; OK=True;
+ do
+ BEGIN
+ KillBlanks(ArgStr[z]);
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (FirstPassUnknown) t.Contents.Int&=0xff;
+ if (NOT RangeCheck(t.Contents.Int,Int8)) WrError(1320);
+ else if (CodeLen==MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else PutByte(t.Contents.Int);
+ break;
+ case TempFloat:
+ WrError(1135); OK=False;
+ break;
+ case TempString:
+ if (strlen(t.Contents.Ascii)+CodeLen>=MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ TranslateString(t.Contents.Ascii);
+ for (p=t.Contents.Ascii; *p!='\0'; PutByte(*(p++)));
+ END
+ break;
+ case TempNone:
+ OK=False;
+ break;
+ END
+ z++;
+ END
+ while ((z<=ArgCnt) AND (OK));
+ if (NOT OK) CodeLen=0;
+ else if ((Odd(CodeLen)) AND (DoPadding)) PutByte(0);
+ END
+ return True;
+ END
+
+ if (Memo("WORD"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z=1; OK=True;
+ do
+ BEGIN
+ HVal16=EvalIntExpression(ArgStr[z],Int16,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[CodeLen >> 1]=HVal16;
+ CodeLen+=2;
+ END
+ z++;
+ END
+ while ((z<=ArgCnt) AND (OK));
+ if (NOT OK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("BSS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ HVal16=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ else if (OK)
+ BEGIN
+ if ((DoPadding) AND (Odd(HVal16))) HVal16++;
+ DontPrint=True; CodeLen=HVal16;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_9900(void)
+BEGIN
+ Word HPart;
+ Integer AdrInt;
+ int z;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False; IsWord=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* zwei Operanden */
+
+ for (z=0; z<TwoOrderCount; z++)
+ if ((strncmp(OpPart,TwoOrders[z].Name,TwoOrders[z].NameLen)==0) AND (((OpPart[TwoOrders[z].NameLen]=='B') AND (OpPart[TwoOrders[z].NameLen+1]=='\0')) OR (OpPart[TwoOrders[z].NameLen]=='\0')))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (DecodeAdr(ArgStr[1]))
+ BEGIN
+ WAsmCode[0]=AdrPart; WAsmCode[1]=AdrVal;
+ HPart=AdrCnt;
+ if (DecodeAdr(ArgStr[2]))
+ BEGIN
+ WAsmCode[0]+=AdrPart << 6; WAsmCode[1+HPart]=AdrVal;
+ CodeLen=(1+HPart+AdrCnt) << 1;
+ if (OpPart[strlen(OpPart)-1]=='B') WAsmCode[0]+=0x1000;
+ WAsmCode[0]+=TwoOrders[z].Code << 13;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<OneOrderCount; z++)
+ if (Memo(OneOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (DecodeAdr(ArgStr[1]))
+ BEGIN
+ WAsmCode[0]=AdrPart; WAsmCode[1]=AdrVal;
+ if (DecodeReg(ArgStr[2],&HPart))
+ BEGIN
+ WAsmCode[0]+=(HPart << 6)+(OneOrders[z].Code << 10);
+ CodeLen=(1+AdrCnt) << 1;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDCR")) OR (Memo("STCR")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (DecodeAdr(ArgStr[1]))
+ BEGIN
+ WAsmCode[0]=0x3000+(Ord(Memo("STCR")) << 10)+AdrPart;
+ WAsmCode[1]=AdrVal;
+ FirstPassUnknown=False;
+ HPart=EvalIntExpression(ArgStr[2],UInt5,&OK);
+ if (FirstPassUnknown) HPart=1;
+ if (OK)
+ if (ChkRange(HPart,1,16))
+ BEGIN
+ WAsmCode[0]+=(HPart & 15) << 6;
+ CodeLen=(1+AdrCnt) << 1;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ShiftOrderCount; z++)
+ if (Memo(ShiftOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (DecodeReg(ArgStr[1],WAsmCode+0))
+ BEGIN
+ if (DecodeReg(ArgStr[2],&HPart))
+ BEGIN
+ WAsmCode[0]+=(HPart << 4)+(ShiftOrders[z].Code << 8);
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ImmOrderCount; z++)
+ if (Memo(ImmOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (DecodeReg(ArgStr[1],WAsmCode+0))
+ BEGIN
+ WAsmCode[1]=EvalIntExpression(ArgStr[2],Int16,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]+=(ImmOrders[z].Code << 5); CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<RegOrderCount; z++)
+ if (Memo(RegOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeReg(ArgStr[1],WAsmCode+0))
+ BEGIN
+ WAsmCode[0]+=RegOrders[z].Code << 4; CodeLen=2;
+ END
+ return;
+ END;
+
+ if (Memo("LMF"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (DecodeReg(ArgStr[1],WAsmCode+0))
+ BEGIN
+ WAsmCode[0]+=0x320+(EvalIntExpression(ArgStr[2],UInt1,&OK) << 4);
+ if (OK) CodeLen=2;
+ if (NOT SupAllowed) WrError(50);
+ END
+ return;
+ END
+
+ /* ein Operand */
+
+ if ((Memo("MPYS")) OR (Memo("DIVS")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeAdr(ArgStr[1]))
+ BEGIN
+ WAsmCode[0]=0x0180+(Ord(Memo("MPYS")) << 6)+AdrPart;
+ WAsmCode[1]=AdrVal;
+ CodeLen=(1+AdrCnt) << 1;
+ END
+ return;
+ END
+
+ for (z=0; z<SingOrderCount; z++)
+ if (Memo(SingOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeAdr(ArgStr[1]))
+ BEGIN
+ WAsmCode[0]=SingOrders[z].Code+AdrPart;
+ WAsmCode[1]=AdrVal;
+ CodeLen=(1+AdrCnt) << 1;
+ if ((SingOrders[z].MustSup) AND (NOT SupAllowed)) WrError(50);
+ END
+ return;
+ END
+
+ for (z=0; z<SBitOrderCount; z++)
+ if (Memo(SBitOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=EvalIntExpression(ArgStr[1],SInt8,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=(WAsmCode[0] & 0xff) | (SBitOrders[z].Code << 8);
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<JmpOrderCount; z++)
+ if (Memo(JmpOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if (Odd(AdrInt)) WrError(1375);
+ else if ((NOT SymbolQuestionable) AND ((AdrInt<-256) OR (AdrInt>254))) WrError(1370);
+ else
+ BEGIN
+ WAsmCode[0]=((AdrInt>>1) & 0xff) | (JmpOrders[z].Code << 8);
+ CodeLen=2;
+ END
+ END;
+ return;
+ END
+
+ if ((Memo("LWPI")) OR (Memo("LIMI")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[1]=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=(0x017+Ord(Memo("LIMI"))) << 5;
+ CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ /* kein Operand */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=FixedOrders[z].Code; CodeLen=2;
+ if ((FixedOrders[z].MustSup) AND (NOT SupAllowed)) WrError(50);
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_9900(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_9900(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void InternSymbol_9900(char *Asc, TempResult*Erg)
+BEGIN
+ Boolean err;
+ char *h=Asc;
+
+ Erg->Typ=TempNone;
+ if ((strlen(Asc)>=2) AND (toupper(*Asc)=='R')) h=Asc+1;
+ else if ((strlen(Asc)>=3) AND (toupper(*Asc)=='W') AND (toupper(Asc[1])=='R')) h=Asc+2;
+
+ Erg->Contents.Int=ConstLongInt(h,&err);
+ if ((NOT err) OR (Erg->Contents.Int<0) OR (Erg->Contents.Int>15)) return;
+
+ Erg->Typ=TempInt;
+END
+
+ static void SwitchTo_9900()
+BEGIN
+ TurnWords=True; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x48; NOPCode=0x0000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_9900; IsDef=IsDef_9900;
+ SwitchFrom=SwitchFrom_9900; InternSymbol=InternSymbol_9900;
+ AddONOFF("PADDING", &DoPadding , DoPaddingName ,False);
+ AddONOFF("SUPMODE", &SupAllowed, SupAllowedName,False);
+
+ InitFields();
+END
+
+ void code9900_init(void)
+BEGIN
+ CPU9900=AddCPU("TMS9900",SwitchTo_9900);
+END
diff --git a/code9900.h b/code9900.h
new file mode 100644
index 0000000..6484cc0
--- /dev/null
+++ b/code9900.h
@@ -0,0 +1,11 @@
+/* code9900.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS99xx */
+/* */
+/* Historie: 9. 3.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void code9900_init(void);
diff --git a/codeace.c b/codeace.c
new file mode 100644
index 0000000..bfe0242
--- /dev/null
+++ b/codeace.c
@@ -0,0 +1,767 @@
+/* codeace.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul ACE-Familie */
+/* */
+/* Historie:14. 8.1999 Grundsteinlegung */
+/* 15. 8.1999 Datensegment immer 256 Byte */
+/* angekuendigte Typen */
+/* nur noch Intel-Pseudos */
+/* 16. 8.1999 Fehler beseitigt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "headids.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmitree.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+#define ModNone (-1)
+#define ModAcc 0
+#define MModAcc (1 << ModAcc)
+#define ModX 1
+#define MModX (1 << ModX)
+#define ModXInd 2
+#define MModXInd (1 << ModXInd)
+#define ModXDisp 3
+#define MModXDisp (1 << ModXDisp)
+#define ModDir 4
+#define MModDir (1 << ModDir)
+#define ModImm 5
+#define MModImm (1 << ModImm)
+
+#define FixedOrderCnt 9
+#define AriOrderCnt 7
+#define SingOrderCnt 3
+#define BitOrderCnt 6
+
+typedef struct
+ {
+ Byte Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ Byte ImmCode, DirCode, IndCode, DispCode;
+ } AriOrder;
+
+typedef struct
+ {
+ Byte AccCode, XCode, DirCode;
+ } SingOrder;
+
+typedef struct
+ {
+ Byte AccCode, XIndCode, DirCode;
+ } BitOrder;
+
+enum {D_CPUACE1001, D_CPUACE1101, D_CPUACE2101,
+ D_CPUACE1202, D_CPUACE2202, D_CPUACE2404};
+
+static CPUVar CPUACE1001, CPUACE1101, CPUACE2101,
+ CPUACE1202, CPUACE2202, CPUACE2404;
+
+static PInstTable InstTable;
+static FixedOrder *FixedOrders;
+static AriOrder *AriOrders;
+static SingOrder *SingOrders;
+static BitOrder *BitOrders;
+
+static ShortInt AdrMode;
+static Byte AdrVal;
+static Word WAdrVal;
+static Boolean BigFlag, OpSize;
+static IntType XType, CodeType;
+
+/*---------------------------------------------------------------------------*/
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrMode == ModXDisp) AND (MomCPU < CPUACE1202))
+ BEGIN
+ AdrMode = ModNone; WrError(1505);
+ END
+ else if ((AdrMode != ModNone) AND ((Mask & (1 << AdrMode)) == 0))
+ BEGIN
+ AdrMode = ModNone; WrError(1350);
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ Boolean OK, DispOcc, XOcc;
+ int l;
+ String Part;
+ char *p;
+
+ AdrMode = ModNone;
+
+ /* Register ? */
+
+ if (strcasecmp(Asc, "A") == 0)
+ AdrMode = ModAcc;
+
+ else if (strcasecmp(Asc, "X") == 0)
+ AdrMode = ModX;
+
+ /* immediate ? */
+
+ else if (*Asc == '#')
+ BEGIN
+ if (OpSize)
+ WAdrVal = EvalIntExpression(Asc + 1, XType, &OK);
+ else
+ AdrVal = EvalIntExpression(Asc + 1, Int8, &OK);
+ if (OK) AdrMode = ModImm;
+ END
+
+ /* indirekt ? */
+
+ else if (*Asc == '[')
+ BEGIN
+ l = strlen(Asc) - 1;
+ if (Asc[l] != ']') WrError(1350);
+ else
+ BEGIN
+ Asc[l] = '\0'; Asc++;
+ DispOcc = XOcc = False;
+ while (*Asc != '\0')
+ BEGIN
+ p = QuotPos(Asc, ',');
+ if (p != Nil) *p = '\0';
+ strmaxcpy(Part, Asc, 255);
+ KillPrefBlanks(Part); KillPostBlanks(Part);
+ if (strcasecmp(Part, "X") == 0)
+ if (XOcc)
+ BEGIN
+ WrError(1350); break;
+ END
+ else XOcc = True;
+ else if (DispOcc)
+ BEGIN
+ WrError(1350); break;
+ END
+ else
+ BEGIN
+ if (*Part == '#') strcpy(Part, Part +1);
+ AdrVal = EvalIntExpression(Part, SInt8, &OK);
+ if (NOT OK) break;
+ DispOcc = True;
+ END
+ if (p == Nil) Asc = "";
+ else Asc = p + 1;
+ END
+ if (*Asc == '\0')
+ AdrMode = (DispOcc && (AdrVal != 0)) ? ModXDisp : ModXInd;
+ END
+ END
+
+ /* direkt */
+
+ else
+ BEGIN
+ if (OpSize)
+ WAdrVal = EvalIntExpression(Asc, CodeType, &OK);
+ else
+ AdrVal = EvalIntExpression(Asc, UInt6, &OK);
+ if (OK) AdrMode = ModDir;
+ END
+
+ ChkAdr(Mask);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *porder = FixedOrders + Index;
+
+ if (ArgCnt != 0) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0] = porder->Code;
+ CodeLen = 1;
+ END
+END
+
+ static void DecodeAri(Word Index)
+BEGIN
+ AriOrder *porder = AriOrders + Index;
+
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc);
+ if (AdrMode != ModNone)
+ BEGIN
+ DecodeAdr(ArgStr[2], MModImm | MModDir | MModXInd | MModXDisp);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = porder->ImmCode; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModDir:
+ BAsmCode[0] = porder->DirCode; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModXInd:
+ BAsmCode[0] = porder->IndCode;
+ CodeLen = 1;
+ break;
+ case ModXDisp:
+ BAsmCode[0] = porder->DispCode; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeSing(Word Index)
+BEGIN
+ SingOrder *porder = SingOrders + Index;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModDir | MModX | MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0] = porder->DirCode; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModAcc:
+ BAsmCode[0] = porder->AccCode;
+ CodeLen = 1;
+ break;
+ case ModX:
+ BAsmCode[0] = porder->XCode;
+ CodeLen = 1;
+ break;
+ END
+ END
+END
+
+ static void DecodeBit(Word Index)
+BEGIN
+ Byte Bit, Mask;
+ BitOrder *porder = BitOrders + Index;
+ Boolean OK;
+
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ Bit = EvalIntExpression(ArgStr[1], UInt8, &OK);
+ if (OK)
+ BEGIN
+ Mask = 0;
+ if (porder->AccCode != 0xff) Mask |= MModAcc;
+ if (porder->XIndCode != 0xff) Mask |= MModXInd;
+ if (porder->DirCode != 0xff) Mask |= MModDir;
+ DecodeAdr(ArgStr[2], Mask);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = porder->AccCode;
+ if (porder->AccCode & 7)
+ BEGIN
+ BAsmCode[1] = 1 << Bit;
+ if (porder->AccCode & 1) BAsmCode[1] = 255 - BAsmCode[1];
+ CodeLen = 2;
+ END
+ else
+ BEGIN
+ BAsmCode[0] |= Bit; CodeLen = 1;
+ END
+ break;
+ case ModXInd:
+ BAsmCode[0] = porder->XIndCode + Bit;
+ CodeLen = 1;
+ break;
+ case ModDir:
+ BAsmCode[0] = porder->DirCode + Bit; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeIFEQ(Word Index)
+BEGIN
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModX | MModDir);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2], MModImm | MModDir | MModXInd | MModXDisp);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0x65; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModDir:
+ BAsmCode[0] = 0x56; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModXInd:
+ BAsmCode[0] = 0x09;
+ CodeLen = 1;
+ break;
+ case ModXDisp:
+ BAsmCode[0] = 0x76; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ END
+ break;
+ case ModX:
+ OpSize = True;
+ DecodeAdr(ArgStr[2], MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0x26;
+ BAsmCode[1] = Lo(WAdrVal); BAsmCode[2] = Hi(WAdrVal);
+ CodeLen = 3;
+ break;
+ END
+ break;
+ case ModDir:
+ BAsmCode[1] = AdrVal;
+ DecodeAdr(ArgStr[2], MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0x20;
+ BAsmCode[2] = AdrVal;
+ CodeLen = 3;
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeIFGT(Word Index)
+BEGIN
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModX);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2], MModImm | MModDir | MModXInd | MModXDisp);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0x67; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModDir:
+ BAsmCode[0] = 0x55; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModXInd:
+ BAsmCode[0] = 0x0a;
+ CodeLen = 1;
+ break;
+ case ModXDisp:
+ BAsmCode[0] = 0x77; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ END
+ break;
+ case ModX:
+ OpSize = True;
+ DecodeAdr(ArgStr[2], MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0x27;
+ BAsmCode[1] = Lo(WAdrVal); BAsmCode[2] = Hi(WAdrVal);
+ CodeLen = 3;
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeIFLT(Word Index)
+BEGIN
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModX);
+ switch (AdrMode)
+ BEGIN
+ case ModX:
+ OpSize = True;
+ DecodeAdr(ArgStr[2], MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0x28;
+ BAsmCode[1] = Lo(WAdrVal); BAsmCode[2] = Hi(WAdrVal);
+ CodeLen = 3;
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeJMPJSR(Word Index)
+BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ OpSize = True;
+ DecodeAdr(ArgStr[1], MModDir | MModXDisp);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0] = 0x24 - Index;
+ BAsmCode[1] = Lo(WAdrVal); BAsmCode[2] = Hi(WAdrVal);
+ CodeLen = 3;
+ break;
+ case ModXDisp:
+ BAsmCode[0] = 0x7e + Index; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ END
+ END
+END
+
+ static void DecodeJP(Word Index)
+BEGIN
+ LongInt Dist;
+ Boolean OK;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ Dist = EvalIntExpression(ArgStr[1], CodeType, &OK) - (EProgCounter() + 1);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Dist > 31) OR (Dist < -31))) WrError(1370);
+ else
+ BEGIN
+ if (Dist >= 0) BAsmCode[0] = 0xe0 + Dist;
+ else BAsmCode[0] = 0xc0 - Dist;
+ CodeLen = 1;
+ END
+ END
+END
+
+ static void DecodeLD(Word Index)
+BEGIN
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModX | MModDir);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2], MModImm | MModDir | MModXInd | MModXDisp);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0x51; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModDir:
+ BAsmCode[0] = 0x46; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModXInd:
+ BAsmCode[0] = 0x0e;
+ CodeLen = 1;
+ break;
+ case ModXDisp:
+ BAsmCode[0] = 0x52; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ END
+ break;
+ case ModX:
+ OpSize = True;
+ DecodeAdr(ArgStr[2], MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0x25;
+ BAsmCode[1] = Lo(WAdrVal); BAsmCode[2] = Hi(WAdrVal);
+ CodeLen = 3;
+ break;
+ END
+ break;
+ case ModDir:
+ BAsmCode[1] = AdrVal;
+ DecodeAdr(ArgStr[2], MModImm | MModDir);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0x21;
+ BAsmCode[2] = AdrVal;
+ CodeLen = 3;
+ break;
+ case ModDir:
+ BAsmCode[0] = 0x22;
+ BAsmCode[2] = BAsmCode[1];
+ BAsmCode[1] = AdrVal;
+ CodeLen = 3;
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeRotate(Word Index)
+BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModDir);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0x15 - Index - Index;
+ CodeLen = 1;
+ break;
+ case ModDir:
+ BAsmCode[0] = 0x79 + Index; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ END
+ END
+END
+
+ static void DecodeST(Word Index)
+BEGIN
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2], MModDir | MModXInd | MModXDisp);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0] = 0x47; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ case ModXInd:
+ BAsmCode[0] = 0x11;
+ CodeLen = 1;
+ break;
+ case ModXDisp:
+ BAsmCode[0] = 0x40; BAsmCode[1] = AdrVal;
+ CodeLen = 2;
+ break;
+ END
+ break;
+ END
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ >= FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Code = NCode;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
+END
+
+ static void AddAri(char *NName, Byte NImm, Byte NDir, Byte NInd, Byte NDisp)
+BEGIN
+ if (InstrZ >= AriOrderCnt) exit(255);
+ AriOrders[InstrZ].ImmCode = NImm;
+ AriOrders[InstrZ].DirCode = NDir;
+ AriOrders[InstrZ].IndCode = NInd;
+ AriOrders[InstrZ].DispCode = NDisp;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeAri);
+END
+
+ static void AddSing(char *NName, Byte NAcc, Byte NX, Byte NDir)
+BEGIN
+ if (InstrZ >= SingOrderCnt) exit(255);
+ SingOrders[InstrZ].AccCode = NAcc;
+ SingOrders[InstrZ].XCode = NX;
+ SingOrders[InstrZ].DirCode = NDir;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeSing);
+END
+
+ static void AddBit(char *NName, Byte NAcc, Byte NIndX, Byte NDir)
+BEGIN
+ if (InstrZ >= BitOrderCnt) exit(255);
+ BitOrders[InstrZ].AccCode = NAcc;
+ BitOrders[InstrZ].XIndCode = NIndX;
+ BitOrders[InstrZ].DirCode = NDir;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeBit);
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable = CreateInstTable(101);
+
+ FixedOrders = (FixedOrder *) malloc(FixedOrderCnt * sizeof(FixedOrder));
+ InstrZ = 0;
+ AddFixed("IFC" ,0x19); AddFixed("IFNC" ,0x1f); AddFixed("INTR" ,0x00);
+ AddFixed("INVC" ,0x12); AddFixed("NOP" ,0x1c); AddFixed("RC" ,0x1e);
+ AddFixed("RET" ,0x17); AddFixed("RETI" ,0x18); AddFixed("SC" ,0x1d);
+
+ AriOrders = (AriOrder *) malloc(AriOrderCnt * sizeof(AriOrder));
+ InstrZ = 0;
+ AddAri("ADC" , 0x60, 0x42, 0x02, 0x70);
+ AddAri("ADD" , 0x66, 0x43, 0x03, 0x71);
+ AddAri("AND" , 0x61, 0x50, 0x04, 0x72);
+ AddAri("IFNE", 0x57, 0x54, 0x0b, 0x78);
+ AddAri("OR" , 0x62, 0x44, 0x05, 0x73);
+ AddAri("SUBC", 0x63, 0x53, 0x06, 0x74);
+ AddAri("XOR" , 0x64, 0x45, 0x07, 0x75);
+
+ SingOrders = (SingOrder *) malloc(SingOrderCnt * sizeof(SingOrder));
+ InstrZ = 0;
+ AddSing("CLR" , 0x16, 0x0f, 0x7d);
+ AddSing("DEC" , 0x1a, 0x0c, 0x7b);
+ AddSing("INC" , 0x1b, 0x0d, 0x7c);
+
+ BitOrders = (BitOrder *) malloc(BitOrderCnt * sizeof(BitOrder));
+ InstrZ = 0;
+ AddBit("IFBIT", 0xa0, 0xa8, 0x58);
+ AddBit("LDC" , 0xff, 0xff, 0x80);
+ AddBit("RBIT" , 0x61, 0xb8, 0x68);
+ AddBit("SBIT" , 0x62, 0xb0, 0x48);
+ AddBit("STC" , 0xff, 0xff, 0x88);
+
+ AddInstTable(InstTable, "IFEQ", 0, DecodeIFEQ);
+ AddInstTable(InstTable, "IFGT", 0, DecodeIFGT);
+ AddInstTable(InstTable, "IFLT", 0, DecodeIFLT);
+ AddInstTable(InstTable, "JMP" , 0, DecodeJMPJSR);
+ AddInstTable(InstTable, "JSR" , 1, DecodeJMPJSR);
+ AddInstTable(InstTable, "JP" , 0, DecodeJP);
+ AddInstTable(InstTable, "LD" , 0, DecodeLD);
+ AddInstTable(InstTable, "RLC" , 0, DecodeRotate);
+ AddInstTable(InstTable, "RRC" , 1, DecodeRotate);
+ AddInstTable(InstTable, "ST" , 0, DecodeST);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+ free(AriOrders);
+ free(SingOrders);
+ free(BitOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,0xff);
+ return True;
+ END;
+
+ return False;
+END
+
+ static void MakeCode_ACE(void)
+BEGIN
+ CodeLen = 0; DontPrint = False; BigFlag = False; OpSize = False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(BigFlag)) return;
+
+ if (NOT LookupInstTable(InstTable, OpPart))
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_ACE(void)
+BEGIN
+ return (Memo("SFR"));
+END
+
+ static void SwitchFrom_ACE(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_ACE(void)
+BEGIN
+ PFamilyDescr Descr;
+
+ TurnWords = False; ConstMode = ConstModeIntel; SetIsOccupied = False;
+
+ Descr = FindFamilyByName("ACE");
+ PCSymbol = "$"; HeaderID = Descr->Id; NOPCode = 0x1c;
+ DivideChars = ","; HasAttrs = False;
+
+ ValidSegs = (1 << SegCode) | (1 << SegData);
+ Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
+ Grans[SegData] = 1; ListGrans[SegData] = 1; SegInits[SegData] = 0;
+ SegLimits[SegData] = 0xff;
+
+ switch (MomCPU - CPUACE1001)
+ BEGIN
+ case D_CPUACE1001: case D_CPUACE1101: case D_CPUACE2101:
+ SegLimits[SegCode] = 0x3ff;
+ CodeType = UInt10;
+ XType = UInt11;
+ break;
+ case D_CPUACE1202: case D_CPUACE2202:
+ SegLimits[SegCode] = 0x7ff;
+ CodeType = UInt11;
+ XType = UInt12;
+ break;
+ case D_CPUACE2404:
+ SegLimits[SegCode] = 0xfff;
+ CodeType = UInt12;
+ XType = UInt12;
+ break;
+ END
+
+ MakeCode = MakeCode_ACE; IsDef = IsDef_ACE;
+ SwitchFrom = SwitchFrom_ACE; InitFields();
+END
+
+ void codeace_init(void)
+BEGIN
+ CPUACE1001 = AddCPU("ACE1001", SwitchTo_ACE);
+ CPUACE1101 = AddCPU("ACE1101", SwitchTo_ACE);
+ CPUACE2101 = AddCPU("ACE2101", SwitchTo_ACE);
+ CPUACE1202 = AddCPU("ACE1202", SwitchTo_ACE);
+ CPUACE2202 = AddCPU("ACE2202", SwitchTo_ACE);
+ CPUACE2404 = AddCPU("ACE2404", SwitchTo_ACE);
+END
diff --git a/codeace.h b/codeace.h
new file mode 100644
index 0000000..6f33a91
--- /dev/null
+++ b/codeace.h
@@ -0,0 +1,11 @@
+/* codeace.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul ACE-Familie */
+/* */
+/* Historie:14. 8.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codeace_init(void);
diff --git a/codeavr.c b/codeavr.c
new file mode 100644
index 0000000..bae2314
--- /dev/null
+++ b/codeavr.c
@@ -0,0 +1,784 @@
+/* codeavr.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Atmel AVR */
+/* */
+/* Historie: 26.12.1996 Grundsteinlegung */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 18. 8.1998 BookKeeping-Aufruf bei RES */
+/* 15.10.1998 LDD/STD mit <reg>+<symbol> ging nicht */
+/* 2. 5.1999 JMP/CALL momentan bei keinem Mitglied erlaubt */
+/* WRAPMODE eingebaut */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "bpemu.h"
+#include "nls.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Word Code;
+ } ArchOrder;
+
+
+#define FixedOrderCnt 24
+#define Reg1OrderCnt 10
+#define Reg2OrderCnt 12
+#define Reg3OrderCnt 4
+#define ImmOrderCnt 7
+#define RelOrderCnt 18
+#define BitOrderCnt 4
+#define PBitOrderCnt 4
+
+
+static CPUVar CPU90S1200,CPU90S2313,CPU90S4414,CPU90S8515;
+
+static ArchOrder *FixedOrders;
+static ArchOrder *Reg1Orders;
+static ArchOrder *Reg2Orders;
+static FixedOrder *Reg3Orders;
+static FixedOrder *ImmOrders;
+static FixedOrder *RelOrders;
+static FixedOrder *BitOrders;
+static FixedOrder *PBitOrders;
+
+static Boolean WrapFlag;
+static LongInt ORMask, SignMask;
+
+static char *WrapFlagName = "WRAPMODE";
+
+/*---------------------------------------------------------------------------*/
+
+ static LongInt CutAdr(LongInt Adr)
+BEGIN
+ if ((Adr & SignMask) != 0) return (Adr | ORMask);
+ else return (Adr & SegLimits[SegCode]);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ].MinCPU=NMin;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddReg1(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=Reg1OrderCnt) exit(255);
+ Reg1Orders[InstrZ].Name=NName;
+ Reg1Orders[InstrZ].MinCPU=NMin;
+ Reg1Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddReg2(char *NName, CPUVar NMin, Word NCode)
+BEGIN
+ if (InstrZ>=Reg2OrderCnt) exit(255);
+ Reg2Orders[InstrZ].Name=NName;
+ Reg2Orders[InstrZ].MinCPU=NMin;
+ Reg2Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddReg3(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Reg3OrderCnt) exit(255);
+ Reg3Orders[InstrZ].Name=NName;
+ Reg3Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddImm(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ImmOrderCnt) exit(255);
+ ImmOrders[InstrZ].Name=NName;
+ ImmOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRel(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=BitOrderCnt) exit(255);
+ BitOrders[InstrZ].Name=NName;
+ BitOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddPBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=PBitOrderCnt) exit(255);
+ PBitOrders[InstrZ].Name=NName;
+ PBitOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(ArchOrder *) malloc(sizeof(ArchOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("IJMP" ,CPU90S2313,0x9409); AddFixed("ICALL",CPU90S2313,0x9509);
+ AddFixed("RET" ,CPU90S1200,0x9508); AddFixed("RETI" ,CPU90S1200,0x9518);
+ AddFixed("LPM" ,CPU90S2313,0x95c8); AddFixed("SEC" ,CPU90S1200,0x9408);
+ AddFixed("CLC" ,CPU90S1200,0x9488); AddFixed("SEN" ,CPU90S1200,0x9428);
+ AddFixed("CLN" ,CPU90S1200,0x94a8); AddFixed("SEZ" ,CPU90S1200,0x9418);
+ AddFixed("CLZ" ,CPU90S1200,0x9498); AddFixed("SEI" ,CPU90S1200,0x9478);
+ AddFixed("CLI" ,CPU90S1200,0x94f8); AddFixed("SES" ,CPU90S1200,0x9448);
+ AddFixed("CLS" ,CPU90S1200,0x94c8); AddFixed("SEV" ,CPU90S1200,0x9438);
+ AddFixed("CLV" ,CPU90S1200,0x94b8); AddFixed("SET" ,CPU90S1200,0x9468);
+ AddFixed("CLT" ,CPU90S1200,0x94e8); AddFixed("SEH" ,CPU90S1200,0x9458);
+ AddFixed("CLH" ,CPU90S1200,0x94d8); AddFixed("NOP" ,CPU90S1200,0x0000);
+ AddFixed("SLEEP",CPU90S1200,0x9588); AddFixed("WDR" ,CPU90S1200,0x95a8);
+
+ Reg1Orders=(ArchOrder *) malloc(sizeof(ArchOrder)*Reg1OrderCnt); InstrZ=0;
+ AddReg1("COM" ,CPU90S1200,0x9400); AddReg1("NEG" ,CPU90S1200,0x9401);
+ AddReg1("INC" ,CPU90S1200,0x9403); AddReg1("DEC" ,CPU90S1200,0x940a);
+ AddReg1("PUSH" ,CPU90S2313,0x920f); AddReg1("POP" ,CPU90S2313,0x900f);
+ AddReg1("LSR" ,CPU90S1200,0x9406); AddReg1("ROR" ,CPU90S1200,0x9407);
+ AddReg1("ASR" ,CPU90S1200,0x9405); AddReg1("SWAP" ,CPU90S1200,0x9402);
+
+ Reg2Orders=(ArchOrder *) malloc(sizeof(ArchOrder)*Reg2OrderCnt); InstrZ=0;
+ AddReg2("ADD" ,CPU90S1200,0x0c00); AddReg2("ADC" ,CPU90S1200,0x1c00);
+ AddReg2("SUB" ,CPU90S1200,0x1800); AddReg2("SBC" ,CPU90S1200,0x0800);
+ AddReg2("AND" ,CPU90S1200,0x2000); AddReg2("OR" ,CPU90S1200,0x2800);
+ AddReg2("EOR" ,CPU90S1200,0x2400); AddReg2("CPSE" ,CPU90S1200,0x1000);
+ AddReg2("CP" ,CPU90S1200,0x1400); AddReg2("CPC" ,CPU90S1200,0x0400);
+ AddReg2("MOV" ,CPU90S1200,0x2c00); AddReg2("MUL" ,CPU90S8515+1,0x9c00);
+
+ Reg3Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Reg3OrderCnt); InstrZ=0;
+ AddReg3("CLR" ,0x2400); AddReg3("TST" ,0x2000); AddReg3("LSL" ,0x0c00);
+ AddReg3("ROL" ,0x1c00);
+
+ ImmOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ImmOrderCnt); InstrZ=0;
+ AddImm("SUBI" ,0x5000); AddImm("SBCI" ,0x4000); AddImm("ANDI" ,0x7000);
+ AddImm("ORI" ,0x6000); AddImm("SBR" ,0x6000); AddImm("CPI" ,0x3000);
+ AddImm("LDI" ,0xe000);
+
+ RelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("BRCC" ,0xf400); AddRel("BRCS" ,0xf000); AddRel("BREQ" ,0xf001);
+ AddRel("BRGE" ,0xf404); AddRel("BRSH" ,0xf400); AddRel("BRID" ,0xf407);
+ AddRel("BRIE" ,0xf007); AddRel("BRLO" ,0xf000); AddRel("BRLT" ,0xf004);
+ AddRel("BRMI" ,0xf002); AddRel("BRNE" ,0xf401); AddRel("BRHC" ,0xf405);
+ AddRel("BRHS" ,0xf005); AddRel("BRPL" ,0xf402); AddRel("BRTC" ,0xf406);
+ AddRel("BRTS" ,0xf006); AddRel("BRVC" ,0xf403); AddRel("BRVS" ,0xf003);
+
+ BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCnt); InstrZ=0;
+ AddBit("BLD" ,0xf800); AddBit("BST" ,0xfa00);
+ AddBit("SBRC" ,0xfc00); AddBit("SBRS" ,0xfe00);
+
+ PBitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*PBitOrderCnt); InstrZ=0;
+ AddPBit("CBI" ,0x9800); AddPBit("SBI" ,0x9a00);
+ AddPBit("SBIC",0x9900); AddPBit("SBIS",0x9b00);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(Reg1Orders);
+ free(Reg2Orders);
+ free(Reg3Orders);
+ free(ImmOrders);
+ free(RelOrders);
+ free(BitOrders);
+ free(PBitOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean DecodeReg(char *Asc, Word *Erg)
+BEGIN
+ Boolean io;
+ char *s;
+
+ if (FindRegDef(Asc,&s)) Asc=s;
+
+ if ((strlen(Asc)<2) OR (strlen(Asc)>3) OR (toupper(*Asc)!='R')) return False;
+ else
+ BEGIN
+ *Erg=ConstLongInt(Asc+1,&io);
+ return ((io) AND (*Erg<32));
+ END
+END
+
+ static Boolean DecodeMem(char * Asc, Word *Erg)
+BEGIN
+ if (strcasecmp(Asc,"X")==0) *Erg=0x1c;
+ else if (strcasecmp(Asc,"X+")==0) *Erg=0x1d;
+ else if (strcasecmp(Asc,"-X")==0) *Erg=0x1e;
+ else if (strcasecmp(Asc,"Y")==0) *Erg=0x08;
+ else if (strcasecmp(Asc,"Y+")==0) *Erg=0x19;
+ else if (strcasecmp(Asc,"-Y")==0) *Erg=0x1a;
+ else if (strcasecmp(Asc,"Z")==0) *Erg=0x00;
+ else if (strcasecmp(Asc,"Z+")==0) *Erg=0x11;
+ else if (strcasecmp(Asc,"-Z")==0) *Erg=0x12;
+ else return False;
+ return True;
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Integer Size;
+ int z,z2;
+ Boolean ValOK;
+ TempResult t;
+ LongInt MinV,MaxV;
+
+ if (Memo("PORT"))
+ BEGIN
+ CodeEquate(SegIO,0,0x3f);
+ return True;
+ END
+
+ if (Memo("RES"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("DATA"))
+ BEGIN
+ MaxV=(ActPC==SegCode)?65535:255; MinV=(-((MaxV+1) >> 1));
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ ValOK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (ValOK)
+ BEGIN
+ EvalExpression(ArgStr[z],&t);
+ if ((FirstPassUnknown) AND (t.Typ==TempInt)) t.Contents.Int&=MaxV;
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (ChkRange(t.Contents.Int,MinV,MaxV))
+ if (ActPC==SegCode) WAsmCode[CodeLen++]=t.Contents.Int;
+ else BAsmCode[CodeLen++]=t.Contents.Int;
+ break;
+ case TempFloat:
+ WrError(1135); ValOK=False;
+ break;
+ case TempString:
+ for (z2=0; z2<strlen(t.Contents.Ascii); z2++)
+ BEGIN
+ Size=CharTransTable[((usint) t.Contents.Ascii[z2])&0xff];
+ if (ActPC!=SegCode) BAsmCode[CodeLen++]=Size;
+ else if ((z2&1)==0) WAsmCode[CodeLen++]=Size;
+ else WAsmCode[CodeLen-1]+=Size<<8;
+ END
+ break;
+ default:
+ ValOK=False;
+ END
+ END
+ if (NOT ValOK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("REG"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else AddRegDef(LabPart,ArgStr[1]);
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_AVR(void)
+BEGIN
+ int z;
+ LongInt AdrInt;
+ Word Reg1,Reg2;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* kein Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<FixedOrders[z].MinCPU) WrXError(1500,OpPart);
+ else
+ BEGIN
+ WAsmCode[0]=FixedOrders[z].Code; CodeLen=1;
+ END
+ return;
+ END
+
+ /* nur Register */
+
+ for (z=0; z<Reg1OrderCnt; z++)
+ if (Memo(Reg1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<Reg1Orders[z].MinCPU) WrXError(1500,OpPart);
+ else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ WAsmCode[0]=Reg1Orders[z].Code+(Reg1 << 4); CodeLen=1;
+ END
+ return;
+ END
+
+ for (z=0; z<Reg2OrderCnt; z++)
+ if (Memo(Reg2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<Reg2Orders[z].MinCPU) WrXError(1500,OpPart);
+ else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else if (NOT DecodeReg(ArgStr[2],&Reg2)) WrXError(1445,ArgStr[2]);
+ else
+ BEGIN
+ WAsmCode[0]=Reg2Orders[z].Code+(Reg2 & 15)+(Reg1 << 4)+
+ ((Reg2 & 16) << 5);
+ CodeLen=1;
+ END
+ return;
+ END
+
+ for (z=0; z<Reg3OrderCnt; z++)
+ if (Memo(Reg3Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ WAsmCode[0]=Reg3Orders[z].Code+(Reg1 & 15)+(Reg1 << 4)+
+ ((Reg1 & 16) << 5);
+ CodeLen=1;
+ END
+ return;
+ END
+
+ /* immediate mit Register */
+
+ for (z=0; z<ImmOrderCnt; z++)
+ if (Memo(ImmOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else if (Reg1<16) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Reg2=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=ImmOrders[z].Code+((Reg2 & 0xf0) << 4)+(Reg2 & 0x0f)+
+ ((Reg1 & 0x0f) << 4);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("ADIW")) OR (Memo("SBIW")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU90S2313) WrError(1500);
+ else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else if ((Reg1<24) OR (Odd(Reg1))) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Reg2=EvalIntExpression(ArgStr[2],UInt6,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0x9600+(Ord(Memo("SBIW")) << 8)+((Reg1 & 6) << 3)+
+ (Reg2 & 15)+((Reg2 & 0x30) << 2);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ /* Transfer */
+
+ if ((Memo("LD")) OR (Memo("ST")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (Memo("ST"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ z=0x200;
+ END
+ else z=0;
+ if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else if (NOT DecodeMem(ArgStr[2],&Reg2)) WrError(1350);
+ else if ((MomCPU<CPU90S2313) AND (Reg2!=0)) WrError(1351);
+ else
+ BEGIN
+ WAsmCode[0]=0x8000+z+(Reg1 << 4)+(Reg2 & 0x0f)+((Reg2 & 0x10) << 8);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDD")) OR (Memo("STD")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU90S2313) WrXError(1500,OpPart);
+ else
+ BEGIN
+ if (Memo("STD"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ z=0x200;
+ END
+ else z=0;
+ OK=True;
+ if (toupper(*ArgStr[2])=='Y') z+=8;
+ else if (toupper(*ArgStr[2])=='Z');
+ else OK=False;
+ if (NOT OK) WrError(1350);
+ else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ *ArgStr[2]='0';
+ Reg2=EvalIntExpression(ArgStr[2],UInt6,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0x8000+z+(Reg1 << 4)+(Reg2 & 7)+((Reg2 & 0x18) << 7)+((Reg2 & 0x20) << 8);
+ CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("IN")) OR (Memo("OUT")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if ((Memo("OUT")))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ z=0x800;
+ END
+ else z=0;
+ if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Reg2=EvalIntExpression(ArgStr[2],UInt6,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegIO);
+ WAsmCode[0]=0xb000+z+(Reg1 << 4)+(Reg2 & 0x0f)+((Reg2 & 0xf0) << 5);
+ CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDS")) OR (Memo("STS")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPU90S2313) WrError(1500);
+ else
+ BEGIN
+ if (Memo("STS"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ z=0x200;
+ END
+ else z=0;
+ if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ WAsmCode[1]=EvalIntExpression(ArgStr[2],UInt16,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegData);
+ WAsmCode[0]=0x9000+z+(Reg1 << 4);
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Bitoperationen */
+
+ if ((Memo("BCLR")) OR (Memo("BSET")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Reg1=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0x9408+(Reg1 << 4)+(Ord(Memo("BCLR")) << 7);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Reg2=EvalIntExpression(ArgStr[2],UInt3,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=BitOrders[z].Code+(Reg1 << 4)+Reg2;
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CBR"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else if (Reg1<16) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Reg2=EvalIntExpression(ArgStr[2],Int8,&OK) ^ 0xff;
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0x7000+((Reg2 & 0xf0) << 4)+(Reg2 & 0x0f)+
+ ((Reg1 & 0x0f) << 4);
+ CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("SER"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
+ else if (Reg1<16) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ WAsmCode[0]=0xef0f+((Reg1 & 0x0f) << 4);
+ CodeLen=1;
+ END
+ return;
+ END
+
+ for (z=0; z<PBitOrderCnt; z++)
+ if (Memo(PBitOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ Reg1=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegIO);
+ Reg2=EvalIntExpression(ArgStr[2],UInt3,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=PBitOrders[z].Code+Reg2+(Reg1 << 3);
+ CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ for (z=0; z<RelOrderCnt; z++)
+ if (Memo(RelOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+1);
+ if (OK)
+ BEGIN
+ if (WrapFlag) AdrInt = CutAdr(AdrInt);
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-64) OR (AdrInt>63))) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ WAsmCode[0]=RelOrders[z].Code+((AdrInt & 0x7f) << 3);
+ CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BRBC")) OR (Memo("BRBS")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ Reg1=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+1);
+ if (OK)
+ BEGIN
+ if (WrapFlag) AdrInt = CutAdr(AdrInt);
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-64) OR (AdrInt>63))) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ WAsmCode[0]=0xf000+(Ord(Memo("BRBC")) << 10)+((AdrInt & 0x7f) << 3)+Reg1;
+ CodeLen=1;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JMP")) OR (Memo("CALL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU90S8515+1) WrError(1500);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt22,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+ WAsmCode[0]=0x940c+(Ord(Memo("CALL")) << 1)+((AdrInt & 0x3e0000) >> 13)+((AdrInt & 0x10000) >> 16);
+ WAsmCode[1]=AdrInt & 0xffff;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("RJMP")) OR (Memo("RCALL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt22,&OK)-(EProgCounter()+1);
+ if (OK)
+ BEGIN
+ if (WrapFlag) AdrInt = CutAdr(AdrInt);
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-2048) OR (AdrInt>2047))) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ WAsmCode[0]=0xc000+(Ord(Memo("RCALL")) << 12)+(AdrInt & 0xfff);
+ CodeLen=1;
+ END
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_AVR(void)
+BEGIN
+ return (Memo("PORT") OR Memo("REG"));
+END
+
+ static void SwitchFrom_AVR(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_AVR(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=True;
+
+ PCSymbol="*"; HeaderID=0x3b; NOPCode=0x0000;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegIO);
+ Grans[SegCode]=2; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=32;
+ Grans[SegIO ]=1; ListGrans[SegIO ]=1; SegInits[SegIO ]=0; SegLimits[SegIO] = 0x3f;
+
+ if (MomCPU == CPU90S1200) SegLimits[SegCode] = 0x01ff;
+ else if (MomCPU == CPU90S2313) SegLimits[SegCode] = 0x03ff;
+ else if (MomCPU == CPU90S4414) SegLimits[SegCode] = 0x07ff;
+ else SegLimits[SegCode] = 0xfff;
+
+ if (MomCPU == CPU90S1200) SegLimits[SegData] = 0x5f;
+ else if (MomCPU == CPU90S2313) SegLimits[SegData] = 0xdf;
+ else SegLimits[SegData] = 0xffff;
+
+ SignMask = (SegLimits[SegCode] + 1) >> 1;
+ ORMask = ((LongInt) - 1) - SegLimits[SegCode];
+
+ AddONOFF("WRAPMODE", &WrapFlag, WrapFlagName, False);
+ SetFlag(&WrapFlag, WrapFlagName, False);
+
+ MakeCode=MakeCode_AVR; IsDef=IsDef_AVR;
+ SwitchFrom=SwitchFrom_AVR; InitFields();
+END
+
+ void codeavr_init(void)
+BEGIN
+ CPU90S1200=AddCPU("AT90S1200",SwitchTo_AVR);
+ CPU90S2313=AddCPU("AT90S2313",SwitchTo_AVR);
+ CPU90S4414=AddCPU("AT90S4414",SwitchTo_AVR);
+ CPU90S8515=AddCPU("AT90S8515",SwitchTo_AVR);
+END
+
diff --git a/codeavr.h b/codeavr.h
new file mode 100644
index 0000000..48055b5
--- /dev/null
+++ b/codeavr.h
@@ -0,0 +1,11 @@
+/* codeavr.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Atmel AVR */
+/* */
+/* Historie: 26.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codeavr_init(void);
diff --git a/codecop8.c b/codecop8.c
new file mode 100644
index 0000000..465f556
--- /dev/null
+++ b/codecop8.c
@@ -0,0 +1,727 @@
+/* codecop8.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul COP8-Familie */
+/* */
+/* Historie: 7.10.1996 Grundsteinlegung */
+/* 18. 8.1998 BookKeeping-Aufruf bei DSx */
+/* 2. 1.1998 ChkPC umgebaut */
+/* 14. 8.1999 Maskierung in ChkAdr falsch */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+#define ModNone (-1)
+#define ModAcc 0
+#define MModAcc (1 << ModAcc)
+#define ModBInd 1
+#define MModBInd (1 << ModBInd)
+#define ModBInc 2
+#define MModBInc (1 << ModBInc)
+#define ModBDec 3
+#define MModBDec (1 << ModBDec)
+#define ModXInd 4
+#define MModXInd (1 << ModXInd)
+#define ModXInc 5
+#define MModXInc (1 << ModXInc)
+#define ModXDec 6
+#define MModXDec (1 << ModXDec)
+#define ModDir 7
+#define MModDir (1 << ModDir)
+#define ModImm 8
+#define MModImm (1 << ModImm)
+
+#define DirPrefix 0xbd
+#define BReg 0xfe
+
+#define FixedOrderCnt 13
+#define AccOrderCnt 9
+#define AccMemOrderCnt 7
+#define BitOrderCnt 3
+
+ typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } FixedOrder;
+
+static CPUVar CPUCOP87L84;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *AccOrders;
+static FixedOrder *AccMemOrders;
+static FixedOrder *BitOrders;
+
+static ShortInt AdrMode;
+static Byte AdrVal;
+static Boolean BigFlag;
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddAcc(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=AccOrderCnt) exit(255);
+ AccOrders[InstrZ].Name=NName;
+ AccOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddAccMem(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=AccMemOrderCnt) exit(255);
+ AccMemOrders[InstrZ].Name=NName;
+ AccMemOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddBit(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=BitOrderCnt) exit(255);
+ BitOrders[InstrZ].Name=NName;
+ BitOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(FixedOrderCnt*sizeof(FixedOrder)); InstrZ=0;
+ AddFixed("LAID" ,0xa4); AddFixed("SC" ,0xa1); AddFixed("RC" ,0xa0);
+ AddFixed("IFC" ,0x88); AddFixed("IFNC" ,0x89); AddFixed("VIS" ,0xb4);
+ AddFixed("JID" ,0xa5); AddFixed("RET" ,0x8e); AddFixed("RETSK",0x8d);
+ AddFixed("RETI" ,0x8f); AddFixed("INTR" ,0x00); AddFixed("NOP" ,0xb8);
+ AddFixed("RPND" ,0xb5);
+
+ AccOrders=(FixedOrder *) malloc(AccOrderCnt*sizeof(FixedOrder)); InstrZ=0;
+ AddAcc("CLR" ,0x64); AddAcc("INC" ,0x8a); AddAcc("DEC" ,0x8b);
+ AddAcc("DCOR" ,0x66); AddAcc("RRC" ,0xb0); AddAcc("RLC" ,0xa8);
+ AddAcc("SWAP" ,0x65); AddAcc("POP" ,0x8c); AddAcc("PUSH" ,0x67);
+
+ AccMemOrders=(FixedOrder *) malloc(AccMemOrderCnt*sizeof(FixedOrder)); InstrZ=0;
+ AddAccMem("ADD" ,0x84); AddAccMem("ADC" ,0x80); AddAccMem("SUBC" ,0x81);
+ AddAccMem("AND" ,0x85); AddAccMem("OR" ,0x87); AddAccMem("XOR" ,0x86);
+ AddAccMem("IFGT" ,0x83);
+
+ BitOrders=(FixedOrder *) malloc(BitOrderCnt*sizeof(FixedOrder)); InstrZ=0;
+ AddBit("IFBIT",0x70); AddBit("SBIT",0x78); AddBit("RBIT",0x68);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(AccOrders);
+ free(AccMemOrders);
+ free(BitOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ AdrMode=ModNone; WrError(1350);
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ static char *ModStrings[ModXDec+1]=
+ {"A","[B]","[B+]","[B-]","[X]","[X+]","[X-]"};
+
+ int z;
+ Boolean OK;
+
+ AdrMode=ModNone;
+
+ /* indirekt/Akku */
+
+ for (z=ModAcc; z<=ModXDec; z++)
+ if (strcasecmp(Asc,ModStrings[z])==0)
+ BEGIN
+ AdrMode=z; ChkAdr(Mask); return;
+ END
+
+ /* immediate */
+
+ if (*Asc=='#')
+ BEGIN
+ AdrVal=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK) AdrMode=ModImm;
+ ChkAdr(Mask); return;
+ END
+
+ /* direkt */
+
+ AdrVal=EvalIntExpression(Asc,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrMode=ModDir; ChkSpace(SegData);
+ END
+
+ ChkAdr(Mask);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ Boolean ValOK;
+ Word Size,Value,t,z;
+
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,0xff);
+ return True;
+ END;
+
+ if (Memo("ADDR"))
+ BEGIN
+ strcpy(OpPart,"DB"); BigFlag=True;
+ END
+
+ if (Memo("ADDRW"))
+ BEGIN
+ strcpy(OpPart,"DW"); BigFlag=True;
+ END
+
+ if (Memo("BYTE")) strcpy(OpPart,"DB");
+
+ if (Memo("WORD")) strcpy(OpPart,"DW");
+
+ if ((Memo("DSB")) OR (Memo("DSW")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],UInt16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ if (Memo("DSW")) Size+=Size;
+ CodeLen=Size;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("FB"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],UInt16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ if (Size>MaxCodeLen) WrError(1920);
+ else
+ BEGIN
+ BAsmCode[0]=EvalIntExpression(ArgStr[2],Int8,&ValOK);
+ if (ValOK)
+ BEGIN
+ CodeLen=Size;
+ memset(BAsmCode+1,BAsmCode[0],Size-1);
+ END
+ END
+ END
+ return True;
+ END
+
+ if (Memo("FW"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ Size=EvalIntExpression(ArgStr[1],UInt16,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ if ((Size << 1)>MaxCodeLen) WrError(1920);
+ else
+ BEGIN
+ Value=EvalIntExpression(ArgStr[2],Int16,&ValOK);
+ if (ValOK)
+ BEGIN
+ CodeLen=Size << 1; t=0;
+ for (z=0; z<Size; z++)
+ BEGIN
+ BAsmCode[t++]=Lo(Value); BAsmCode[t++]=Hi(Value);
+ END
+ END
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_COP8(void)
+BEGIN
+ Integer AdrInt;
+ int z;
+ Byte HReg;
+ Boolean OK;
+ Word AdrWord;
+
+ CodeLen=0; DontPrint=False; BigFlag=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(BigFlag)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if Memo(FixedOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=FixedOrders[z].Code; CodeLen=1;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("LD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModDir+MModBInd+MModBInc+MModBDec);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModDir+MModImm+MModBInd+MModXInd+MModBInc+MModXInc+MModBDec+MModXDec);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0]=0x9d; BAsmCode[1]=AdrVal; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x98; BAsmCode[1]=AdrVal; CodeLen=2;
+ break;
+ case ModBInd:
+ BAsmCode[0]=0xae; CodeLen=1;
+ break;
+ case ModXInd:
+ BAsmCode[0]=0xbe; CodeLen=1;
+ break;
+ case ModBInc:
+ BAsmCode[0]=0xaa; CodeLen=1;
+ break;
+ case ModXInc:
+ BAsmCode[0]=0xba; CodeLen=1;
+ break;
+ case ModBDec:
+ BAsmCode[0]=0xab; CodeLen=1;
+ break;
+ case ModXDec:
+ BAsmCode[0]=0xbb; CodeLen=1;
+ break;
+ END
+ break;
+ case ModDir:
+ HReg=AdrVal; DecodeAdr(ArgStr[2],MModImm);
+ if (AdrMode==ModImm)
+ if (HReg==BReg)
+ if (AdrVal<=15)
+ BEGIN
+ BAsmCode[0]=0x5f-AdrVal; CodeLen=1;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x9f; BAsmCode[1]=AdrVal; CodeLen=2;
+ END
+ else if (HReg>=0xf0)
+ BEGIN
+ BAsmCode[0]=HReg-0x20; BAsmCode[1]=AdrVal; CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xbc; BAsmCode[1]=HReg; BAsmCode[2]=AdrVal; CodeLen=3;
+ END
+ break;
+ case ModBInd:
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x9e; BAsmCode[1]=AdrVal; CodeLen=2;
+ END
+ break;
+ case ModBInc:
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x9a; BAsmCode[1]=AdrVal; CodeLen=2;
+ END
+ break;
+ case ModBDec:
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x9b; BAsmCode[1]=AdrVal; CodeLen=2;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("X"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (strcasecmp(ArgStr[1],"A")!=0)
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ DecodeAdr(ArgStr[1],MModAcc);
+ if (AdrMode!=ModNone)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModDir+MModBInd+MModXInd+MModBInc+MModXInc+MModBDec+MModXDec);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0]=0x9c; BAsmCode[1]=AdrVal; CodeLen=2;
+ break;
+ case ModBInd:
+ BAsmCode[0]=0xa6; CodeLen=1;
+ break;
+ case ModBInc:
+ BAsmCode[0]=0xa2; CodeLen=1;
+ break;
+ case ModBDec:
+ BAsmCode[0]=0xa3; CodeLen=1;
+ break;
+ case ModXInd:
+ BAsmCode[0]=0xb6; CodeLen=1;
+ break;
+ case ModXInc:
+ BAsmCode[0]=0xb2; CodeLen=1;
+ break;
+ case ModXDec:
+ BAsmCode[0]=0xb3; CodeLen=1;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<AccOrderCnt; z++)
+ if Memo(AccOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=AccOrders[z].Code; CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<AccMemOrderCnt; z++)
+ if Memo(AccMemOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ if (AdrMode!=ModNone)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModDir+MModImm+MModBInd);
+ switch (AdrMode)
+ BEGIN
+ case ModBInd:
+ BAsmCode[0]=AccMemOrders[z].Code; CodeLen=1;
+ break;
+ case ModImm:
+ BAsmCode[0]=AccMemOrders[z].Code+0x10; BAsmCode[1]=AdrVal;
+ CodeLen=2;
+ break;
+ case ModDir:
+ BAsmCode[0]=DirPrefix; BAsmCode[1]=AdrVal;
+ BAsmCode[2]=AccMemOrders[z].Code;
+ CodeLen=3;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("ANDSZ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ if (AdrMode!=ModNone)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[0]=0x60; BAsmCode[1]=AdrVal; CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Bedingungen */
+
+ if (Memo("IFEQ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModDir);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModDir+MModBInd+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0]=DirPrefix; BAsmCode[1]=AdrVal; BAsmCode[2]=0x82;
+ CodeLen=3;
+ break;
+ case ModBInd:
+ BAsmCode[0]=0x82; CodeLen=1;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x92; BAsmCode[1]=AdrVal; CodeLen=2;
+ break;
+ END
+ break;
+ case ModDir:
+ BAsmCode[1]=AdrVal;
+ DecodeAdr(ArgStr[2],MModImm);
+ if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[0]=0xa9; BAsmCode[2]=AdrVal; CodeLen=3;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("IFNE"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModDir+MModBInd+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0]=DirPrefix; BAsmCode[1]=AdrVal; BAsmCode[2]=0xb9;
+ CodeLen=3;
+ break;
+ case ModBInd:
+ BAsmCode[0]=0xb9; CodeLen=1;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x99; BAsmCode[1]=AdrVal; CodeLen=2;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("IFBNE"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=EvalIntExpression(ArgStr[1]+1,UInt4,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]+=0x40; CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ /* Bitbefehle */
+
+ for (z=0; z<BitOrderCnt; z++)
+ if Memo(BitOrders[z].Name)
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModDir+MModBInd);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ BAsmCode[0]=DirPrefix; BAsmCode[1]=AdrVal;
+ BAsmCode[2]=BitOrders[z].Code+HReg; CodeLen=3;
+ break;
+ case ModBInd:
+ BAsmCode[0]=BitOrders[z].Code+HReg; CodeLen=1;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if ((Memo("JMP")) OR (Memo("JSR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ if (((EProgCounter()+2) >> 12)!=(AdrWord >> 12)) WrError(1910);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ BAsmCode[0]=0x20+(Ord(Memo("JSR")) << 4)+((AdrWord >> 8) & 15);
+ BAsmCode[1]=Lo(AdrWord);
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JMPL")) OR (Memo("JSRL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+ BAsmCode[0]=0xac+Ord(Memo("JSRL"));
+ BAsmCode[1]=Hi(AdrWord);
+ BAsmCode[2]=Lo(AdrWord);
+ CodeLen=3;
+ END
+ END
+ return;
+ END
+
+ if (Memo("JP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+1);
+ if (OK)
+ if (AdrInt==0)
+ BEGIN
+ BAsmCode[0]=NOPCode; CodeLen=1; WrError(60);
+ END
+ else if (((AdrInt>31) OR (AdrInt<-32)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=AdrInt & 0xff; CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("DRSZ"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ DecodeAdr(ArgStr[1],MModDir);
+ if (FirstPassUnknown) AdrVal|=0xf0;
+ if (AdrVal<0xf0) WrError(1315);
+ else
+ BEGIN
+ BAsmCode[0]=AdrVal-0x30; CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_COP8(void)
+BEGIN
+ return (Memo("SFR"));
+END
+
+ static void SwitchFrom_COP8(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_COP8(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeC; SetIsOccupied=False;
+
+ PCSymbol="."; HeaderID=0x6f; NOPCode=0xb8;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0x1fff;
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
+ SegLimits[SegData] = 0xff;
+
+ MakeCode=MakeCode_COP8; IsDef=IsDef_COP8;
+ SwitchFrom=SwitchFrom_COP8; InitFields();
+END
+
+ void codecop8_init(void)
+BEGIN
+ CPUCOP87L84=AddCPU("COP87L84",SwitchTo_COP8);
+END
+
+
diff --git a/codecop8.h b/codecop8.h
new file mode 100644
index 0000000..ae6bb40
--- /dev/null
+++ b/codecop8.h
@@ -0,0 +1,11 @@
+/* codecop8.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegeneratormodul COP8-Familie */
+/* */
+/* Historie: 7.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codecop8_init(void);
diff --git a/codeflt1750.c b/codeflt1750.c
new file mode 100644
index 0000000..40f488d
--- /dev/null
+++ b/codeflt1750.c
@@ -0,0 +1,158 @@
+/***************************************************************************/
+/* */
+/* Project : Mil-Std-1750 Host Development Support Library */
+/* */
+/* Component : flt1750.c -- host independent float conversion routines */
+/* */
+/* Copyright : (C) Daimler-Benz Aerospace AG, 1994-97 */
+/* */
+/* Author : Oliver M. Kellogg, Dornier Satellite Systems, */
+/* Dept. RST13, D-81663 Munich, Germany. */
+/* Contact : oliver.kellogg@space.otn.dasa.de */
+/* */
+/* Disclaimer: */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/***************************************************************************/
+
+/* These conversion functions have been tested on MIPS(ULTRIX), SPARC(Solaris),
+ i386(Linux/DOS), and VAX(VMS) machines. Should you encounter any problems
+ on other machines, please write to the e-mail contact address given above.
+ */
+
+
+#include "codeflt1750.h"
+#include <math.h>
+#define dfrexp frexp
+#define pow2(exp) pow(2.0,(double)exp)
+
+#define ushort unsigned short
+#define ulong unsigned long
+
+#define FLOATING_TWO_TO_THE_FIFTEEN 32768.0
+#define FLOATING_TWO_TO_THE_TWENTYTHREE 8388608.0
+#define FLOATING_TWO_TO_THE_THIRTYONE 2147483648.0
+#define FLOATING_TWO_TO_THE_THIRTYNINE 549755813888.0
+
+
+
+double
+from_1750flt (short *input) /* input : array of 2 shorts */
+{
+ long int_mant;
+ double flt_mant, flt_exp;
+ signed char int_exp;
+
+ int_exp = (signed char) (input[1] & 0xFF);
+ int_mant = ((long) input[0] << 8) | (((long) input[1] & 0xFF00L) >> 8);
+ /* printf("int_mant = 0x%08lx\n",int_mant); */
+ flt_mant = (double) int_mant / FLOATING_TWO_TO_THE_TWENTYTHREE;
+ flt_exp = pow2 (int_exp);
+ return flt_mant * flt_exp;
+}
+
+int
+to_1750flt (double input, short output[2])
+{
+ int exp;
+ long mant;
+
+ input = dfrexp (input, &exp);
+
+ if (exp < -128)
+ return -1; /* signalize underflow */
+ else if (exp > 127)
+ return 1; /* signalize overflow */
+
+ if (input < 0.0 && input >= -0.5) /* prompted by UNIX frexp */
+ {
+ input *= 2.0;
+ exp--;
+ }
+
+ mant = (long) (input * FLOATING_TWO_TO_THE_THIRTYONE);
+
+ /* printf("\n\tmant=%08lx\n",mant); */
+ output[0] = (short) (mant >> 16);
+ output[1] = (short) (mant & 0xFF00) | (exp & 0xFF);
+
+ return 0; /* success status */
+}
+
+double
+from_1750eflt (short *input) /* input : array of 3 shorts */
+{
+ long int_mant_hi, int_mant_lo;
+ double flt_mant, flt_exp;
+ signed char int_exp;
+
+ int_exp = (signed char) (input[1] & 0xFF);
+
+ int_mant_hi = (((long) input[0] << 16) | ((long) input[1] & 0xFF00L)) >> 8;
+ int_mant_lo = ((long) input[2] & 0xFFFFL);
+
+ flt_mant = (double) int_mant_hi / FLOATING_TWO_TO_THE_TWENTYTHREE
+ + (double) int_mant_lo / FLOATING_TWO_TO_THE_THIRTYNINE;
+ flt_exp = pow2 (int_exp);
+/* printf ("\tfrom: mant=%.12g, exp=%g\n", flt_mant, flt_exp); */
+
+ return flt_mant * flt_exp;
+}
+
+int
+to_1750eflt (double input, short output[3])
+{
+ int exp;
+ int is_neg = 0;
+ ushort hlp;
+
+ if (input < 0.0)
+ {
+ is_neg = 1;
+ input = -input - .03125 / FLOATING_TWO_TO_THE_THIRTYNINE;
+ }
+
+ input = dfrexp (input, &exp); /* input is now normalized mantissa */
+
+ if (input == 1.0) /* prompted by VAX frexp */
+ {
+ input = 0.5;
+ exp++;
+ }
+
+ if (exp < -128)
+ return -1; /* signalize underflow */
+ else if (exp > 127)
+ return 1; /* signalize overflow */
+
+ output[0] = (short) (input * FLOATING_TWO_TO_THE_FIFTEEN);
+ input -= (double) output[0] / FLOATING_TWO_TO_THE_FIFTEEN;
+ hlp = (ushort) (input * FLOATING_TWO_TO_THE_TWENTYTHREE);
+ output[1] = (short) ((hlp << 8) | (exp & 0xFF));
+ input -= (double) hlp / FLOATING_TWO_TO_THE_TWENTYTHREE;
+ hlp = (ushort) (input * FLOATING_TWO_TO_THE_THIRTYNINE);
+ output[2] = (short) hlp;
+
+ if (is_neg)
+ {
+ output[0] = ~output[0];
+ output[1] = (~output[1] & 0xFF00) | (output[1] & 0x00FF);
+ output[2] = ~output[2];
+ }
+
+ return 0; /* success status */
+}
+
diff --git a/codeflt1750.h b/codeflt1750.h
new file mode 100644
index 0000000..ca1db87
--- /dev/null
+++ b/codeflt1750.h
@@ -0,0 +1,7 @@
+/* flt1750.h -- exports of flt1750.c */
+
+extern double from_1750flt (short *input); /* input: array of 2 shorts */
+extern int to_1750flt (double input, short output[2]);
+extern double from_1750eflt (short *input); /* input: array of 3 shorts */
+extern int to_1750eflt (double input, short output[3]);
+
diff --git a/codefmc8.c b/codefmc8.c
new file mode 100644
index 0000000..0cd1b1c
--- /dev/null
+++ b/codefmc8.c
@@ -0,0 +1,1017 @@
+/* codefmc8.c */
+/****************************************************************************/
+/* AS, C-Version */
+/* */
+/* Codegenerator fuer Fujitsu-F2MC8L-Prozessoren */
+/* */
+/* Historie: 4. 7.1999 Grundsteinlegung */
+/* 29. 7.1999 doppelte Variable entfernt */
+/* */
+/****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmpars.h"
+#include "asmsub.h"
+#include "codepseudo.h"
+#include "codevars.h"
+#include "asmitree.h"
+#include "headids.h"
+
+/*--------------------------------------------------------------------------*/
+/* Definitionen */
+
+#define FixedOrderCnt 10
+#define ALUOrderCnt 5
+#define AccOrderCnt 10
+#define RelOrderCnt 12
+
+#define ModNone (-1)
+enum {ModAcc, ModDir, ModExt, ModIIX, ModIEP, ModIA, ModReg, ModReg16, ModT,
+ ModPC, ModPS, ModImm};
+#define MModAcc (1 << ModAcc)
+#define MModDir (1 << ModDir)
+#define MModExt (1 << ModExt)
+#define MModIIX (1 << ModIIX)
+#define MModIEP (1 << ModIEP)
+#define MModIA (1 << ModIA)
+#define MModReg (1 << ModReg)
+#define MModReg16 (1 << ModReg16)
+#define MModT (1 << ModT)
+#define MModPC (1 << ModPC)
+#define MModPS (1 << ModPS)
+#define MModImm (1 << ModImm)
+
+typedef struct
+ {
+ Byte Code;
+ } FixedOrder;
+
+static CPUVar CPU89190;
+
+static PInstTable InstTable;
+static FixedOrder *FixedOrders, *ALUOrders, *AccOrders, *RelOrders;
+
+static int AdrMode;
+static Byte AdrPart, AdrVals[2];
+static int OpSize;
+
+/*--------------------------------------------------------------------------*/
+/* Adressdekoder */
+
+ static void DecodeAdr(char *Asc, unsigned Mask)
+BEGIN
+ Boolean OK;
+ Word Address;
+
+ AdrMode = ModNone; AdrCnt = 0;
+
+ /* Register ? */
+
+ if (strcasecmp(Asc, "A") == 0)
+ AdrMode = ModAcc;
+
+ else if (strcasecmp(Asc, "SP") == 0)
+ BEGIN
+ AdrMode = ModReg16;
+ AdrPart = 1;
+ END
+
+ else if (strcasecmp(Asc, "IX") == 0)
+ BEGIN
+ AdrMode = ModReg16;
+ AdrPart = 2;
+ END
+
+ else if (strcasecmp(Asc, "EP") == 0)
+ BEGIN
+ AdrMode = ModReg16;
+ AdrPart = 3;
+ END
+
+ else if (strcasecmp(Asc, "T") == 0)
+ AdrMode = ModT;
+
+ else if (strcasecmp(Asc, "PC") == 0)
+ AdrMode = ModPC;
+
+ else if (strcasecmp(Asc, "PS") == 0)
+ AdrMode = ModPS;
+
+ else if ((strlen(Asc) == 2) AND (toupper(*Asc) == 'R') AND (Asc[1]>= '0') AND (Asc[1] <= '7'))
+ BEGIN
+ AdrMode = ModReg;
+ AdrPart = Asc[1] - '0' + 8;
+ END
+
+ /* immediate ? */
+
+ else if (*Asc == '#')
+ BEGIN
+ if (OpSize)
+ BEGIN
+ Address = EvalIntExpression(Asc + 1, Int16, &OK);
+ if (OK)
+ BEGIN
+ /***Problem: Byte order? */
+ AdrVals[0] = Lo(Address);
+ AdrVals[1] = Hi(Address);
+ AdrMode = ModImm;
+ AdrCnt = 2;
+ AdrPart = 4;
+ END
+ END
+ else
+ BEGIN
+ AdrVals[0] = EvalIntExpression(Asc + 1, Int8, &OK);
+ if (OK)
+ BEGIN
+ AdrMode = ModImm;
+ AdrCnt = 1;
+ AdrPart = 4;
+ END
+ END
+ END
+
+ /* indirekt ? */
+
+ else if (strcasecmp(Asc, "@EP") == 0)
+ BEGIN
+ AdrMode = ModIEP;
+ AdrPart = 7;
+ END
+
+ else if (strcasecmp(Asc, "@A") == 0)
+ BEGIN
+ AdrMode = ModIA;
+ AdrPart = 7;
+ END
+
+ else if (strncasecmp(Asc, "@IX", 3) == 0)
+ BEGIN
+ /***Problem: Offset signed oder unsigned? */
+ AdrVals[0] = EvalIntExpression(Asc + 3, SInt8, &OK);
+ if (OK)
+ BEGIN
+ AdrMode = ModIIX;
+ AdrCnt = 1;
+ AdrPart = 6;
+ END
+ END
+
+ /* direkt ? */
+
+ else
+ BEGIN
+ Address = EvalIntExpression(Asc, (Mask & MModExt) ? UInt16 : UInt8, &OK);
+ if (OK)
+ if ((Mask & MModDir) AND (Hi(Address) == 0))
+ BEGIN
+ AdrVals[0] = Lo(Address);
+ AdrMode = ModDir;
+ AdrCnt = 1;
+ AdrPart = 5;
+ END
+ else
+ BEGIN
+ AdrMode = ModExt;
+ AdrCnt = 2;
+ /***Problem: Byte order? */
+ AdrVals[0] = Lo(Address);
+ AdrVals[1] = Hi(Address);
+ END
+ END
+
+ /* erlaubt ? */
+
+ if ((AdrMode != ModNone) && ((Mask & (1 << AdrMode)) == 0))
+ BEGIN
+ WrError(1350);
+ AdrMode = ModNone;
+ AdrCnt = 0;
+ END
+END
+
+ static Boolean DecodeBitAdr(char *Asc, Byte *Adr, Byte *Bit)
+BEGIN
+ char *sep;
+ Boolean OK;
+
+ sep = strchr(Asc, ':');
+ if (sep == NULL) return FALSE;
+ *sep = '\0';
+
+ *Adr = EvalIntExpression(Asc, UInt8, &OK);
+ if (NOT OK) return FALSE;
+
+ *Bit = EvalIntExpression(sep + 1, UInt3, &OK);
+ if (NOT OK) return FALSE;
+
+ return TRUE;
+END
+
+/*--------------------------------------------------------------------------*/
+/* ind. Decoder */
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *porder = FixedOrders + Index;
+
+ if (ArgCnt != 0) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0] = porder->Code;
+ CodeLen = 1;
+ END
+END
+
+ static void DecodeAcc(Word Index)
+BEGIN
+ FixedOrder *porder = AccOrders + Index;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = porder->Code;
+ CodeLen = 1;
+ END
+ END
+END
+
+ static void DecodeALU(Word Index)
+BEGIN
+ FixedOrder *porder = ALUOrders + Index;
+
+ if ((ArgCnt != 1) AND (ArgCnt != 2)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc);
+ if (AdrMode != ModNone)
+ if (ArgCnt == 1)
+ BEGIN
+ BAsmCode[0] = porder->Code + 2;
+ CodeLen = 1;
+ END
+ else
+ BEGIN
+ OpSize = 0;
+ DecodeAdr(ArgStr[2], MModDir | MModIIX | MModIEP | MModReg | MModImm);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = porder->Code + AdrPart;
+ memcpy(BAsmCode + 1, AdrVals, AdrCnt);
+ CodeLen = 1 + AdrCnt;
+ END
+ END
+ END
+END
+
+ static void DecodeRel(Word Index)
+BEGIN
+ Integer Adr;
+ Boolean OK;
+ FixedOrder *porder = RelOrders + Index;
+
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ Adr = EvalIntExpression(ArgStr[1], UInt16, &OK) - (EProgCounter() + 2);
+ if (OK)
+ if (((Adr < -128) OR (Adr > 127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0] = porder->Code;
+ BAsmCode[1] = Adr & 0xff;
+ CodeLen = 2;
+ END
+ END
+END
+
+ static void DecodeMOV(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ OpSize = 0;
+ DecodeAdr(ArgStr[1], MModAcc | MModDir | MModIIX | MModIEP | MModExt | MModReg | MModIA);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2], MModDir | MModIIX | MModIEP | MModIA | MModReg | MModImm| MModExt);
+ switch (AdrMode)
+ BEGIN
+ case ModDir:
+ case ModIIX:
+ case ModIEP:
+ case ModReg:
+ case ModImm:
+ BAsmCode[0] = 0x00 + AdrPart;
+ memcpy(BAsmCode + 1, AdrVals, AdrCnt);
+ CodeLen = 1 + AdrCnt;
+ break;
+ case ModExt:
+ BAsmCode[0] = 0x60;
+ memcpy(BAsmCode + 1, AdrVals, AdrCnt);
+ CodeLen = 1 + AdrCnt;
+ break;
+ case ModIA:
+ BAsmCode[0] = 0x92;
+ CodeLen = 1 + AdrCnt;
+ break;
+ END
+ break;
+
+ case ModDir:
+ BAsmCode[1] = AdrVals[0];
+ DecodeAdr(ArgStr[2], MModAcc | MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0x45;
+ CodeLen = 2;
+ break;
+ case ModImm:
+ BAsmCode[0] = 0x85; /***turn Byte 1+2 for F2MC ? */
+ BAsmCode[2] = AdrVals[0];
+ CodeLen = 3;
+ break;
+ END
+ break;
+
+ case ModIIX:
+ BAsmCode[1] = AdrVals[0];
+ DecodeAdr(ArgStr[2], MModAcc | MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0x46;
+ CodeLen = 2;
+ break;
+ case ModImm:
+ BAsmCode[0] = 0x86; /***turn Byte 1+2 for F2MC ? */
+ BAsmCode[2] = AdrVals[0];
+ CodeLen = 3;
+ break;
+ END
+ break;
+
+ case ModIEP:
+ DecodeAdr(ArgStr[2], MModAcc | MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0x47;
+ CodeLen = 1;
+ break;
+ case ModImm:
+ BAsmCode[0] = 0x87;
+ BAsmCode[1] = AdrVals[0];
+ CodeLen = 2;
+ break;
+ END
+ break;
+
+ case ModExt:
+ BAsmCode[1] = AdrVals[0]; BAsmCode[2] = AdrVals[1];
+ DecodeAdr(ArgStr[2], MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0x61;
+ CodeLen = 3;
+ break;
+ END
+ break;
+
+ case ModReg:
+ HReg = AdrPart;
+ DecodeAdr(ArgStr[2], MModAcc | MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0x40 + HReg;
+ CodeLen = 1;
+ break;
+ case ModImm:
+ BAsmCode[0] = 0x80 + HReg;
+ BAsmCode[1] = AdrVals[0];
+ CodeLen = 2;
+ break;
+ END
+ break;
+
+ case ModIA:
+ DecodeAdr(ArgStr[2], MModT);
+ switch (AdrMode)
+ BEGIN
+ case ModT:
+ BAsmCode[0] = 0x82;
+ CodeLen = 1;
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeMOVW(Word Index)
+BEGIN
+ Byte HReg;
+
+ OpSize = 1;
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModDir | MModIIX | MModExt | MModIEP | MModReg16 | MModIA | MModPS);
+ switch(AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2], MModImm | MModDir | MModIEP | MModIIX | MModExt | MModIA | MModReg16 | MModPS | MModPC);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0] = 0xe4;
+ memcpy(BAsmCode + 1, AdrVals, AdrCnt);
+ CodeLen = 1 + AdrCnt;
+ break;
+ case ModExt:
+ BAsmCode[0] = 0xc4;
+ memcpy(BAsmCode + 1, AdrVals, AdrCnt);
+ CodeLen = 1 + AdrCnt;
+ break;
+ case ModDir:
+ case ModIEP:
+ case ModIIX:
+ BAsmCode[0] = 0xc0 | AdrPart;
+ memcpy(BAsmCode + 1, AdrVals, AdrCnt);
+ CodeLen = 1 + AdrCnt;
+ break;
+ case ModIA:
+ BAsmCode[0] = 0x93;
+ CodeLen = 1;
+ break;
+ case ModReg16:
+ BAsmCode[0] = 0xf0 + AdrPart;
+ CodeLen = 1;
+ break;
+ case ModPS:
+ BAsmCode[0] = 0x70;
+ CodeLen = 1;
+ break;
+ case ModPC:
+ BAsmCode[0] = 0xf0;
+ CodeLen = 1;
+ break;
+ END
+ break;
+
+ case ModDir:
+ BAsmCode[1] = AdrVals[0];
+ DecodeAdr(ArgStr[2], MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0xd5;
+ CodeLen = 2;
+ break;
+ END
+ break;
+
+ case ModIIX:
+ BAsmCode[1] = AdrVals[0];
+ DecodeAdr(ArgStr[2], MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0xd6;
+ CodeLen = 2;
+ break;
+ END
+ break;
+
+ case ModExt:
+ BAsmCode[1] = AdrVals[0]; BAsmCode[2] = AdrVals[1];
+ DecodeAdr(ArgStr[2], MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0xd4;
+ CodeLen = 3;
+ break;
+ END
+ break;
+
+ case ModIEP:
+ DecodeAdr(ArgStr[2], MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0xd7;
+ CodeLen = 1;
+ break;
+ END
+ break;
+
+ case ModReg16:
+ HReg = AdrPart;
+ DecodeAdr(ArgStr[2], MModAcc | MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0xe0 + HReg;
+ CodeLen = 1;
+ break;
+ case ModImm:
+ BAsmCode[0] = 0xe4 + HReg;
+ memcpy(BAsmCode + 1, AdrVals, AdrCnt);
+ CodeLen = 1 + AdrCnt;
+ break;
+ END
+ break;
+
+ case ModIA:
+ DecodeAdr(ArgStr[2], MModT);
+ switch (AdrMode)
+ BEGIN
+ case ModT:
+ BAsmCode[0] = 0x83;
+ CodeLen = 1;
+ break;
+ END
+ break;
+
+ case ModPS:
+ DecodeAdr(ArgStr[2], MModAcc);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0x71;
+ CodeLen = 1;
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeBit(Word Index)
+BEGIN
+ Byte Adr, Bit;
+
+ if (ArgCnt != 1) WrError(1110);
+ else if (NOT DecodeBitAdr(ArgStr[1], &Adr, &Bit)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0] = 0xa0 + (Index << 3) + Bit;
+ BAsmCode[1] = Adr;
+ CodeLen = 2;
+ END;
+END
+
+ static void DecodeXCH(Word Index)
+BEGIN
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModT);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2], MModT);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0x42;
+ CodeLen = 1;
+ END
+ break;
+ case ModT:
+ DecodeAdr(ArgStr[2], MModAcc);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0x42;
+ CodeLen = 1;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeXCHW(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModT | MModReg16 | MModPC);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2], MModT | MModReg16 | MModPC);
+ switch (AdrMode)
+ BEGIN
+ case ModT:
+ BAsmCode[0] = 0x43;
+ CodeLen = 1;
+ break;
+ case ModReg16:
+ BAsmCode[0] = 0xf4 + AdrPart;
+ CodeLen = 1;
+ break;
+ case ModPC:
+ BAsmCode[0] = 0xf4;
+ CodeLen = 1;
+ break;
+ END
+ break;
+ case ModT:
+ DecodeAdr(ArgStr[2], MModAcc);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0x43;
+ CodeLen = 1;
+ END
+ break;
+ case ModReg16:
+ HReg = AdrPart;
+ DecodeAdr(ArgStr[2], MModAcc);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0xf4 | HReg;
+ CodeLen = 1;
+ END
+ break;
+ case ModPC:
+ DecodeAdr(ArgStr[2], MModAcc);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0xf4;
+ CodeLen = 1;
+ END
+ END
+ END
+END
+
+ static void DecodeINCDEC(Word Index)
+BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModReg);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0xc0 + (Index << 4) + AdrPart;
+ CodeLen = 1;
+ END
+ END
+END
+
+ static void DecodeINCDECW(Word Index)
+BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModReg16);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0xc0 + (Index << 4);
+ CodeLen = 1;
+ break;
+ case ModReg16:
+ BAsmCode[0] = 0xc0 + (Index << 4) + AdrPart;
+ CodeLen = 1;
+ break;
+ END
+ END
+END
+
+ static void DecodeCMP(Word Index)
+BEGIN
+ Byte HReg;
+
+ if ((ArgCnt != 1) AND (ArgCnt != 2)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModDir | MModIIX | MModIEP | MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ if (ArgCnt == 1)
+ BEGIN
+ BAsmCode[0] = 0x12;
+ CodeLen = 1;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2], MModDir | MModIEP | MModIIX | MModReg | MModImm);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0x10 + AdrPart;
+ memcpy(BAsmCode + 1, AdrVals, AdrCnt);
+ CodeLen = 1 + AdrCnt;
+ END
+ END
+ break;
+ case ModDir:
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[1] = AdrVals[0];
+ DecodeAdr(ArgStr[2], MModImm);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0x95;
+ BAsmCode[2] = AdrVals[0]; /* reverse for F2MC8 */
+ CodeLen = 3;
+ END
+ END
+ break;
+ case ModIIX:
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[1] = AdrVals[0];
+ DecodeAdr(ArgStr[2], MModImm);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0x96;
+ BAsmCode[2] = AdrVals[0]; /* reverse for F2MC8 */
+ CodeLen = 3;
+ END
+ END
+ break;
+ case ModIEP:
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2], MModImm);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0x97;
+ BAsmCode[1] = AdrVals[0];
+ CodeLen = 2;
+ END
+ END
+ break;
+ case ModReg:
+ if (ArgCnt != 2) WrError(1110);
+ else
+ BEGIN
+ HReg = AdrPart;
+ DecodeAdr(ArgStr[2], MModImm);
+ if (AdrMode != ModNone)
+ BEGIN
+ BAsmCode[0] = 0x90 + HReg;
+ BAsmCode[1] = AdrVals[0];
+ CodeLen = 2;
+ END
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeBitBr(Word Index)
+BEGIN
+ Byte Bit, BAdr;
+ Boolean OK;
+ Integer Adr;
+
+ if (ArgCnt != 2) WrError(1110);
+ else if (NOT DecodeBitAdr(ArgStr[1], &BAdr, &Bit)) WrError(1350);
+ else
+ BEGIN
+ Adr = EvalIntExpression(ArgStr[2], UInt16, &OK) - (EProgCounter() + 3);
+ if (OK)
+ if (((Adr < -128) OR (Adr > 127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0] = 0xb0 + (Index << 3) + Bit;
+ BAsmCode[1] = BAdr; /* reverse for F2MC8? */
+ BAsmCode[2] = Adr & 0xff;
+ CodeLen = 3;
+ END
+ END
+END
+
+ static void DecodeJmp(Word Index)
+BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModExt | ((Index) ? 0 : MModIA));
+ switch (AdrMode)
+ BEGIN
+ case ModIA:
+ BAsmCode[0] = 0xe0;
+ CodeLen = 1;
+ break;
+ case ModExt:
+ BAsmCode[0] = 0x21 | (Index << 4);
+ memcpy(BAsmCode + 1, AdrVals, AdrCnt);
+ CodeLen = 1 + AdrCnt;
+ break;
+ END
+ END
+END
+
+ static void DecodeCALLV(Word Index)
+BEGIN
+ Boolean OK;
+
+ if (ArgCnt != 1) WrError(1110);
+ else if (*ArgStr[1] != '#') WrError(1120);
+ else
+ BEGIN
+ BAsmCode[0] = 0xb8 + EvalIntExpression(ArgStr[1] + 1, UInt3, &OK);
+ if (OK) CodeLen = 1;
+ END
+END
+
+ static void DecodeStack(Word Index)
+BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1], MModAcc | MModReg16);
+ switch (AdrMode)
+ BEGIN
+ case ModAcc:
+ BAsmCode[0] = 0x40 + (Index << 4);
+ CodeLen = 1;
+ break;
+ case ModReg16:
+ if (AdrPart != 2) WrXError(1445, ArgStr[1]);
+ else
+ BEGIN
+ BAsmCode[0] = 0x41 + (Index << 4);
+ CodeLen = 1;
+ END
+ break;
+ END
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+/* Codetabellen */
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ > FixedOrderCnt) exit(255);
+
+ FixedOrders[InstrZ].Code = NCode;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
+END
+
+ static void AddALU(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ > ALUOrderCnt) exit(255);
+
+ ALUOrders[InstrZ].Code = NCode;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeALU);
+END
+
+ static void AddAcc(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ > AccOrderCnt) exit(255);
+
+ AccOrders[InstrZ].Code = NCode;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeAcc);
+END
+
+ static void AddRel(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ > RelOrderCnt) exit(255);
+
+ RelOrders[InstrZ].Code = NCode;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeRel);
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable = CreateInstTable(201);
+
+ FixedOrders = (FixedOrder*) malloc(sizeof(FixedOrder) * FixedOrderCnt);
+ InstrZ = 0;
+ AddFixed("SWAP" , 0x10); AddFixed("DAA" , 0x84);
+ AddFixed("DAS" , 0x94); AddFixed("RET" , 0x20);
+ AddFixed("RETI" , 0x30); AddFixed("NOP" , 0x00);
+ AddFixed("CLRC" , 0x81); AddFixed("SETC" , 0x91);
+ AddFixed("CLRI" , 0x80); AddFixed("SETI" , 0x90);
+
+ ALUOrders = (FixedOrder*) malloc(sizeof(FixedOrder) * ALUOrderCnt);
+ InstrZ = 0;
+ AddALU("ADDC" , 0x20); AddALU("SUBC" , 0x30);
+ AddALU("XOR" , 0x50); AddALU("AND" , 0x60);
+ AddALU("OR" , 0x70);
+
+ AccOrders = (FixedOrder*) malloc(sizeof(FixedOrder) * AccOrderCnt);
+ InstrZ = 0;
+ AddAcc("ADDCW" , 0x23); AddAcc("SUBCW" , 0x33);
+ AddAcc("MULU" , 0x01); AddAcc("DIVU" , 0x11);
+ AddAcc("ANDW" , 0x63); AddAcc("ORW" , 0x73);
+ AddAcc("XORW" , 0x53); AddAcc("CMPW" , 0x13);
+ AddAcc("RORC" , 0x03); AddAcc("ROLC" , 0x02);
+
+ RelOrders = (FixedOrder*) malloc(sizeof(FixedOrder) * RelOrderCnt);
+ InstrZ = 0;
+ AddRel("BEQ", 0xfd); AddRel("BZ" , 0xfd);
+ AddRel("BNZ", 0xfc); AddRel("BNE", 0xfc);
+ AddRel("BC" , 0xf9); AddRel("BLO", 0xf9);
+ AddRel("BNC", 0xf8); AddRel("BHS", 0xf8);
+ AddRel("BN" , 0xfb); AddRel("BP" , 0xfa);
+ AddRel("BLT", 0xff); AddRel("BGE", 0xfe);
+
+ AddInstTable(InstTable, "MOV", 0, DecodeMOV);
+ AddInstTable(InstTable, "MOVW", 0, DecodeMOVW);
+ AddInstTable(InstTable, "XCH", 0, DecodeXCH);
+ AddInstTable(InstTable, "XCHW", 0, DecodeXCHW);
+ AddInstTable(InstTable, "SETB", 1, DecodeBit);
+ AddInstTable(InstTable, "CLRB", 0, DecodeBit);
+ AddInstTable(InstTable, "INC", 0, DecodeINCDEC);
+ AddInstTable(InstTable, "DEC", 1, DecodeINCDEC);
+ AddInstTable(InstTable, "INCW", 0, DecodeINCDECW);
+ AddInstTable(InstTable, "DECW", 1, DecodeINCDECW);
+ AddInstTable(InstTable, "CMP", 0, DecodeCMP);
+ AddInstTable(InstTable, "BBC", 0, DecodeBitBr);
+ AddInstTable(InstTable, "BBS", 1, DecodeBitBr);
+ AddInstTable(InstTable, "JMP", 0, DecodeJmp);
+ AddInstTable(InstTable, "CALL", 1, DecodeJmp);
+ AddInstTable(InstTable, "CALLV", 0, DecodeCALLV);
+ AddInstTable(InstTable, "PUSHW", 0, DecodeStack);
+ AddInstTable(InstTable, "POPW", 1, DecodeStack);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(ALUOrders);
+ free(AccOrders);
+ free(RelOrders);
+ DestroyInstTable(InstTable);
+END
+
+/*--------------------------------------------------------------------------*/
+/* Interface zu AS */
+
+ static void MakeCode_F2MC8(void)
+BEGIN
+ /* Leeranweisung ignorieren */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodeIntelPseudo(False)) return;
+
+ if (NOT LookupInstTable(InstTable, OpPart))
+ WrXError(1200, OpPart);
+END
+
+ static Boolean IsDef_F2MC8(void)
+BEGIN
+ return FALSE;
+END
+
+ static void SwitchFrom_F2MC8(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_F2MC8(void)
+BEGIN
+ PFamilyDescr FoundDescr;
+
+ FoundDescr = FindFamilyByName("F2MC8");
+
+ TurnWords = False; ConstMode = ConstModeIntel; SetIsOccupied = False;
+
+ PCSymbol = "$"; HeaderID = FoundDescr->Id; NOPCode=0x00;
+ DivideChars = ","; HasAttrs = False;
+
+ ValidSegs = 1 << SegCode;
+ Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode = MakeCode_F2MC8; IsDef = IsDef_F2MC8;
+ SwitchFrom = SwitchFrom_F2MC8; InitFields();
+END
+
+/*--------------------------------------------------------------------------*/
+/* Initialisierung */
+
+ void codef2mc8_init(void)
+BEGIN
+ CPU89190 = AddCPU("MB89190", SwitchTo_F2MC8);
+END
diff --git a/codefmc8.h b/codefmc8.h
new file mode 100644
index 0000000..1ef1dc0
--- /dev/null
+++ b/codefmc8.h
@@ -0,0 +1,11 @@
+/* codefmc8.h */
+/*****************************************************************************/
+/* AS, C-Version */
+/* */
+/* Codegenerator fuer Fujitsu-F2MC8-Prozessoren */
+/* */
+/* Historie: 4.7.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codef2mc8_init(void);
diff --git a/codeh8_3.c b/codeh8_3.c
new file mode 100644
index 0000000..fb0c3d0
--- /dev/null
+++ b/codeh8_3.c
@@ -0,0 +1,1707 @@
+/* codeh8_3.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator H8/300(L/H) */
+/* */
+/* Historie: 22.11.1996 Grundsteinlegung */
+/* 15.10.1998 TRAPA nachgetragen */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+#define FixedOrderCount 4
+#define ConditionCount 20
+#define ShiftOrderCount 8
+#define LogicOrderCount 3
+#define MulOrderCount 4
+#define Bit1OrderCount 10
+#define Bit2OrderCount 4
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModImm 1
+#define MModImm (1 << ModImm)
+#define ModAbs8 2
+#define MModAbs8 (1 << ModAbs8)
+#define ModAbs16 3
+#define MModAbs16 (1 << ModAbs16)
+#define ModAbs24 4
+#define MModAbs24 (1 << ModAbs24)
+#define MModAbs (MModAbs8+MModAbs16+MModAbs24)
+#define ModIReg 5
+#define MModIReg (1 << ModIReg)
+#define ModPreDec 6
+#define MModPreDec (1 << ModPreDec)
+#define ModPostInc 7
+#define MModPostInc (1 << ModPostInc)
+#define ModInd16 8
+#define MModInd16 (1 << ModInd16)
+#define ModInd24 9
+#define MModInd24 (1 << ModInd24)
+#define ModIIAbs 10
+#define MModIIAbs (1 << ModIIAbs)
+#define MModInd (MModInd16+MModInd24)
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } Condition;
+
+
+static ShortInt OpSize; /* Groesse=8*(2^OpSize) */
+static ShortInt AdrMode; /* Ergebnisadressmodus */
+static Byte AdrPart; /* Adressierungsmodusbits im Opcode */
+static Word AdrVals[6]; /* Adressargument */
+
+static CPUVar CPUH8_300L;
+static CPUVar CPU6413308,CPUH8_300;
+static CPUVar CPU6413309,CPUH8_300H;
+static Boolean CPU16; /* keine 32-Bit-Register */
+
+static Condition *Conditions;
+static FixedOrder *FixedOrders;
+static FixedOrder *ShiftOrders;
+static FixedOrder *LogicOrders;
+static FixedOrder *MulOrders;
+static FixedOrder *Bit1Orders;
+static FixedOrder *Bit2Orders;
+
+/*-------------------------------------------------------------------------*/
+/* dynamische Belegung/Freigabe Codetabellen */
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddCond(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ConditionCount) exit(255);
+ Conditions[InstrZ].Name=NName;
+ Conditions[InstrZ++].Code=NCode;
+END
+
+ static void AddShift(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ShiftOrderCount) exit(255);
+ ShiftOrders[InstrZ].Name=NName;
+ ShiftOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddLogic(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=LogicOrderCount) exit(255);
+ LogicOrders[InstrZ].Name=NName;
+ LogicOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddMul(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=MulOrderCount) exit(255);
+ MulOrders[InstrZ].Name=NName;
+ MulOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddBit1(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Bit1OrderCount) exit(255);
+ Bit1Orders[InstrZ].Name=NName;
+ Bit1Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddBit2(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Bit2OrderCount) exit(255);
+ Bit2Orders[InstrZ].Name=NName;
+ Bit2Orders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("NOP",0x0000); AddFixed("RTE",0x5670);
+ AddFixed("RTS",0x5470); AddFixed("SLEEP",0x0180);
+
+ Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCount); InstrZ=0;
+ AddCond("BRA",0x0); AddCond("BT" ,0x0);
+ AddCond("BRN",0x1); AddCond("BF" ,0x1);
+ AddCond("BHI",0x2); AddCond("BLS",0x3);
+ AddCond("BCC",0x4); AddCond("BHS",0x4);
+ AddCond("BCS",0x5); AddCond("BLO",0x5);
+ AddCond("BNE",0x6); AddCond("BEQ",0x7);
+ AddCond("BVC",0x8); AddCond("BVS",0x9);
+ AddCond("BPL",0xa); AddCond("BMI",0xb);
+ AddCond("BGE",0xc); AddCond("BLT",0xd);
+ AddCond("BGT",0xe); AddCond("BLE",0xf);
+
+ ShiftOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ShiftOrderCount); InstrZ=0;
+ AddShift("ROTL" ,0x1280); AddShift("ROTR" ,0x1380);
+ AddShift("ROTXL",0x1200); AddShift("ROTXR",0x1300);
+ AddShift("SHAL" ,0x1080); AddShift("SHAR" ,0x1180);
+ AddShift("SHLL" ,0x1000); AddShift("SHLR" ,0x1100);
+
+ LogicOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LogicOrderCount); InstrZ=0;
+ AddLogic("OR",0); AddLogic("XOR",1); AddLogic("AND",2);
+
+ MulOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*MulOrderCount); InstrZ=0;
+ AddMul("DIVXS",3); AddMul("DIVXU",1); AddMul("MULXS",2); AddMul("MULXU",0);
+
+ Bit1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Bit1OrderCount); InstrZ=0;
+ AddBit1("BAND",0x16); AddBit1("BIAND",0x96);
+ AddBit1("BOR" ,0x14); AddBit1("BIOR" ,0x94);
+ AddBit1("BXOR",0x15); AddBit1("BIXOR",0x95);
+ AddBit1("BLD" ,0x17); AddBit1("BILD" ,0x97);
+ AddBit1("BST" ,0x07); AddBit1("BIST" ,0x87);
+
+ Bit2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Bit2OrderCount); InstrZ=0;
+ AddBit2("BCLR",2); AddBit2("BNOT",1); AddBit2("BSET",0); AddBit2("BTST",3);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(Conditions);
+ free(ShiftOrders);
+ free(LogicOrders);
+ free(MulOrders);
+ free(Bit1Orders);
+ free(Bit2Orders);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Adressparsing */
+
+typedef enum {SizeNone,Size8,Size16,Size24} MomSize_t;
+static MomSize_t MomSize;
+
+ static void SetOpSize(ShortInt Size)
+BEGIN
+ if (OpSize==-1) OpSize=Size;
+ else if (Size!=OpSize)
+ BEGIN
+ WrError(1131); AdrMode=ModNone; AdrCnt=0;
+ END
+END
+
+ static Boolean IsNum(char Inp, Byte *Erg)
+BEGIN
+ if ((Inp<'0') OR (Inp>'7')) return False;
+ else
+ BEGIN
+ *Erg=Inp-AscOfs; return True;
+ END
+END
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg, ShortInt *Size)
+BEGIN
+ if (strcasecmp(Asc,"SP")==0)
+ BEGIN
+ *Erg=7; *Size=(Maximum) ? 2 : 1; return True;
+ END
+
+ else if ((strlen(Asc)==3) AND (toupper(*Asc)=='R') AND (IsNum(Asc[1],Erg)))
+ if (toupper(Asc[2])=='L')
+ BEGIN
+ *Erg+=8; *Size=0; return True;
+ END
+ else if (toupper(Asc[2])=='H')
+ BEGIN
+ *Size=0; return True;
+ END
+ else return False;
+
+ else if ((strlen(Asc)==2) AND (IsNum(Asc[1],Erg)))
+ if (toupper(*Asc)=='R')
+ BEGIN
+ *Size=1; return True;
+ END
+ else if (toupper(*Asc)=='E')
+ BEGIN
+ *Erg+=8; *Size=1; return True;
+ END
+ else return False;
+
+ else if ((strlen(Asc)==3) AND (toupper(*Asc)=='E') AND (toupper(Asc[1])=='R') AND (IsNum(Asc[2],Erg)))
+ BEGIN
+ *Size=2; return True;
+ END
+ else return False;
+END
+
+ static void CutSize(char *Asc)
+BEGIN
+ int l=strlen(Asc);
+
+ if ((l>=2) AND (Asc[l-2]==':') AND (Asc[l-1]=='8'))
+ BEGIN
+ Asc[l-2]='\0'; MomSize=Size8;
+ END
+ else if ((l>=3) AND (Asc[l-3]==':'))
+ BEGIN
+ if ((Asc[l-2]=='1') AND (Asc[l-1]=='6'))
+ BEGIN
+ Asc[l-3]='\0'; MomSize=Size16;
+ END
+ else if ((Asc[l-2]=='2') AND (Asc[l-1]=='4'))
+ BEGIN
+ Asc[l-3]='\0'; MomSize=Size24;
+ END
+ END
+END
+
+ static Byte DecodeBaseReg(char *Asc, Byte *Erg)
+BEGIN
+ ShortInt HSize;
+
+ if (NOT DecodeReg(Asc,Erg,&HSize)) return 0;
+ if ((HSize==0) OR ((HSize==1) AND (*Erg>7)))
+ BEGIN
+ WrError(1350); return 1;
+ END;
+ if ((CPU16) != (HSize==1))
+ BEGIN
+ WrError(1505); return 1;
+ END
+ return 2;
+END
+
+ static Boolean Is8(LongInt Address)
+BEGIN
+ if (CPU16) return (((Address >> 8)&0xff)==0xff);
+ else return (((Address >> 8)&0xffff)==0xffff);
+END
+
+ static Boolean Is16(LongInt Address)
+BEGIN
+ return (CPU16) ? (True) : (((Address>=0) AND (Address<=0x7fff)) OR ((Address>=0xff8000) AND (Address<=0xffffff)));
+END
+
+ static void DecideVAbsolute(LongInt Address, Word Mask)
+BEGIN
+ /* bei Automatik Operandengroesse festlegen */
+
+ if (MomSize==SizeNone)
+ BEGIN
+ if (Is8(Address)) MomSize=Size8;
+ else if (Is16(Address)) MomSize=Size16;
+ else MomSize=Size24;
+ END
+
+ /* wenn nicht vorhanden, eins rauf */
+
+ if ((MomSize==Size8) AND ((Mask & MModAbs8)==0)) MomSize=Size16;
+ if ((MomSize==Size16) AND ((Mask & MModAbs16)==0)) MomSize=Size24;
+
+ /* entsprechend Modus Bytes ablegen */
+
+ switch (MomSize)
+ BEGIN
+ case Size8:
+ if (NOT Is8(Address)) WrError(1925);
+ else
+ BEGIN
+ AdrCnt=2; AdrVals[0]=Address & 0xff; AdrMode=ModAbs8;
+ END
+ break;
+ case Size16:
+ if (NOT Is16(Address)) WrError(1925);
+ else
+ BEGIN
+ AdrCnt=2; AdrVals[0]=Address & 0xffff; AdrMode=ModAbs16;
+ END
+ break;
+ case Size24:
+ AdrCnt=4;
+ AdrVals[1]=Address & 0xffff;
+ AdrVals[0]=Lo(Address >> 16);
+ AdrMode=ModAbs24;
+ break;
+ default:
+ WrError(10000);
+ END
+END
+
+ static void DecideAbsolute(char *Asc, Word Mask)
+BEGIN
+ LongInt Addr;
+ Boolean OK;
+
+ Addr=EvalIntExpression(Asc,Int32,&OK);
+ if (OK) DecideVAbsolute(Addr,Mask);
+END
+
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if (CPU16)
+ if (((AdrMode==ModReg) AND (OpSize==2))
+ OR ((AdrMode==ModReg) AND (OpSize==1) AND (AdrPart>7))
+ OR (AdrMode==ModAbs24)
+ OR (AdrMode==ModInd24))
+ BEGIN
+ WrError(1505); AdrMode=ModNone; AdrCnt=0;
+ END
+ if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ WrError(1350); AdrMode=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ ShortInt HSize;
+ Byte HReg;
+ LongInt HLong;
+ Boolean OK;
+ char *p;
+ LongInt DispAcc;
+ String Part;
+ int l;
+
+ AdrMode=ModNone; AdrCnt=0; MomSize=SizeNone;
+
+ /* immediate ? */
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1132);
+ break;
+ case 0:
+ HReg=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=2; AdrVals[0]=HReg; AdrMode=ModImm;
+ END
+ break;
+ case 1:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=2; AdrMode=ModImm;
+ END
+ break;
+ case 2:
+ HLong=EvalIntExpression(Asc+1,Int32,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=4;
+ AdrVals[0]=HLong >> 16;
+ AdrVals[1]=HLong & 0xffff;
+ AdrMode=ModImm;
+ END
+ break;
+ default:
+ WrError(1130);
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* Register ? */
+
+ if (DecodeReg(Asc,&HReg,&HSize))
+ BEGIN
+ AdrMode=ModReg; AdrPart=HReg; SetOpSize(HSize); ChkAdr(Mask); return;
+ END
+
+ /* indirekt ? */
+
+ if (*Asc=='@')
+ BEGIN
+ strcpy(Asc,Asc+1);
+
+ if (*Asc=='@')
+ BEGIN
+ AdrVals[0]=EvalIntExpression(Asc+1,UInt8,&OK) & 0xff;
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrMode=ModIIAbs;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ switch (DecodeBaseReg(Asc,&AdrPart))
+ BEGIN
+ case 1:
+ ChkAdr(Mask); return;
+ case 2:
+ AdrMode=ModIReg; ChkAdr(Mask); return;
+ END
+
+ if (*Asc=='-')
+ switch (DecodeBaseReg(Asc+1,&AdrPart))
+ BEGIN
+ case 1:
+ ChkAdr(Mask); return;
+ case 2:
+ AdrMode=ModPreDec; ChkAdr(Mask); return;
+ END
+
+ if (Asc[l=strlen(Asc)-1]=='+')
+ BEGIN
+ Asc[l]='\0';
+ switch (DecodeBaseReg(Asc,&AdrPart))
+ BEGIN
+ case 1:
+ ChkAdr(Mask); return;
+ case 2:
+ AdrMode=ModPostInc; ChkAdr(Mask); return;
+ END
+ Asc[l]='+';
+ END
+
+ if (IsIndirect(Asc))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ AdrPart=0xff; DispAcc=0;
+ do
+ BEGIN
+ p=QuotPos(Asc,',');
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Part,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(Part,Asc,255); strmaxcpy(Asc,p+1,255);
+ END
+ switch (DecodeBaseReg(Part,&HReg))
+ BEGIN
+ case 2:
+ if (AdrPart!=0xff)
+ BEGIN
+ WrError(1350); ChkAdr(Mask); return;
+ END
+ else AdrPart=HReg;
+ break;
+ case 1:
+ ChkAdr(Mask); return;
+ case 0:
+ CutSize(Part);
+ DispAcc+=EvalIntExpression(Part,Int32,&OK);
+ if (NOT OK)
+ BEGIN
+ ChkAdr(Mask); return;
+ END
+ break;
+ END
+ END
+ while (*Asc!='\0');
+ if (AdrPart==0xff) DecideVAbsolute(DispAcc,Mask);
+ else
+ BEGIN
+ if ((CPU16) AND ((DispAcc & 0xffff8000)==0x8000)) DispAcc+=0xffff0000;
+ if (MomSize==SizeNone)
+ MomSize=((DispAcc>=-32768) AND (DispAcc<=32767)) ? Size16 : Size24;
+ switch (MomSize)
+ BEGIN
+ case Size8:
+ WrError(1130); break;
+ case Size16:
+ if (DispAcc<-32768) WrError(1315);
+ else if (DispAcc>32767) WrError(1320);
+ else
+ BEGIN
+ AdrCnt=2; AdrVals[0]=DispAcc & 0xffff; AdrMode=ModInd16;
+ END
+ break;
+ case Size24:
+ AdrVals[1]=DispAcc & 0xffff; AdrVals[0]=Lo(DispAcc >> 16);
+ AdrCnt=4; AdrMode=ModInd24;
+ break;
+ default:
+ WrError(10000);
+ END
+ END
+ END
+ else
+ BEGIN
+ CutSize(Asc);
+ DecideAbsolute(Asc,Mask);
+ END
+ ChkAdr(Mask); return;
+ END
+
+ CutSize(Asc);
+ DecideAbsolute(Asc,Mask);
+ ChkAdr(Mask);
+END
+
+ static LongInt ImmVal(void)
+BEGIN
+ switch (OpSize)
+ BEGIN
+ case 0: return Lo(AdrVals[0]);
+ case 1: return AdrVals[0];
+ case 2: return (((LongInt)AdrVals[0]) << 16)+AdrVals[1];
+ default: WrError(10000); return 0;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void MakeCode_H8_3(void)
+BEGIN
+ int z;
+ Word Mask;
+ ShortInt HSize;
+ LongInt AdrLong;
+ Byte HReg,OpCode;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* Attribut verwursten */
+
+ if (*AttrPart!='\0')
+ BEGIN
+ if (strlen(AttrPart)!=1)
+ BEGIN
+ WrError(1105); return;
+ END
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B': SetOpSize(0); break;
+ case 'W': SetOpSize(1); break;
+ case 'L': SetOpSize(2); break;
+ case 'Q': SetOpSize(3); break;
+ case 'S': SetOpSize(4); break;
+ case 'D': SetOpSize(5); break;
+ case 'X': SetOpSize(6); break;
+ case 'P': SetOpSize(7); break;
+ default:
+ WrError(1107); return;
+ END
+ END
+
+ if (DecodeMoto16Pseudo(OpSize,True)) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ CodeLen=2; WAsmCode[0]=FixedOrders[z].Code;
+ END;
+ return;
+ END
+
+ if (Memo("EEPMOV"))
+ BEGIN
+ if (OpSize==-1) OpSize=Ord(NOT CPU16);
+ if (OpSize>1) WrError(1130);
+ else if (ArgCnt!=0) WrError(1110);
+ else if ((OpSize==1) AND (CPU16)) WrError(1500);
+ else
+ BEGIN
+ CodeLen=4;
+ WAsmCode[0]=(OpSize==0) ? 0x7b5c : 0x7bd4;
+ WAsmCode[1]=0x598f;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+MModIReg+MModPreDec+MModInd+MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ HReg=AdrPart;
+ Mask=MModReg+MModIReg+MModPostInc+MModInd+MModAbs+MModImm;
+ if (OpSize!=0) Mask-=MModAbs8;
+ DecodeAdr(ArgStr[1],Mask);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ z=OpSize; if (z==2) z=3;
+ CodeLen=2; WAsmCode[0]=0x0c00+(z << 8)+(AdrPart << 4)+HReg;
+ if (OpSize==2) WAsmCode[0]+=0x80;
+ break;
+ case ModIReg:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0x6800+(AdrPart << 4)+HReg;
+ break;
+ case 1:
+ CodeLen=2; WAsmCode[0]=0x6900+(AdrPart << 4)+HReg;
+ break;
+ case 2:
+ CodeLen=4; WAsmCode[0]=0x0100;
+ WAsmCode[1]=0x6900+(AdrPart << 4)+HReg;
+ break;
+ END
+ break;
+ case ModPostInc:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0x6c00+(AdrPart << 4)+HReg;
+ break;
+ case 1:
+ CodeLen=2; WAsmCode[0]=0x6d00+(AdrPart << 4)+HReg;
+ break;
+ case 2:
+ CodeLen=4; WAsmCode[0]=0x0100;
+ WAsmCode[1]=0x6d00+(AdrPart << 4)+HReg;
+ break;
+ END
+ break;
+ case ModInd16:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=4; WAsmCode[0]=0x6e00+(AdrPart << 4)+HReg;
+ WAsmCode[1]=AdrVals[0];
+ break;
+ case 1:
+ CodeLen=4; WAsmCode[0]=0x6f00+(AdrPart << 4)+HReg;
+ WAsmCode[1]=AdrVals[0];
+ break;
+ case 2:
+ CodeLen=6; WAsmCode[0]=0x0100;
+ WAsmCode[1]=0x6f00+(AdrPart << 4)+HReg;
+ WAsmCode[2]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModInd24:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=8;
+ WAsmCode[0]=0x7800+(AdrPart << 4);
+ WAsmCode[1]=0x6a20+HReg;
+ memcpy(WAsmCode+2,AdrVals,AdrCnt);
+ break;
+ case 1:
+ CodeLen=8;
+ WAsmCode[0]=0x7800+(AdrPart << 4);
+ WAsmCode[1]=0x6b20+HReg;
+ memcpy(WAsmCode+2,AdrVals,AdrCnt);
+ break;
+ case 2:
+ CodeLen=10; WAsmCode[0]=0x0100;
+ WAsmCode[1]=0x7800+(AdrPart << 4);
+ WAsmCode[2]=0x6b20+HReg;
+ memcpy(WAsmCode+3,AdrVals,AdrCnt);
+ break;
+ END
+ break;
+ case ModAbs8:
+ CodeLen=2; WAsmCode[0]=0x2000+(((Word)HReg) << 8)+Lo(AdrVals[0]);
+ break;
+ case ModAbs16:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=4; WAsmCode[0]=0x6a00+HReg;
+ WAsmCode[1]=AdrVals[0];
+ break;
+ case 1:
+ CodeLen=4; WAsmCode[0]=0x6b00+HReg;
+ WAsmCode[1]=AdrVals[0];
+ break;
+ case 2:
+ CodeLen=6; WAsmCode[0]=0x0100;
+ WAsmCode[1]=0x6b00+HReg;
+ WAsmCode[2]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModAbs24:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=6; WAsmCode[0]=0x6a20+HReg;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ break;
+ case 1:
+ CodeLen=6; WAsmCode[0]=0x6b20+HReg;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ break;
+ case 2:
+ CodeLen=8; WAsmCode[0]=0x0100;
+ WAsmCode[1]=0x6b20+HReg;
+ memcpy(WAsmCode+2,AdrVals,AdrCnt);
+ break;
+ END
+ break;
+ case ModImm:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0xf000+(((Word)HReg) << 8)+Lo(AdrVals[0]);
+ break;
+ case 1:
+ CodeLen=4; WAsmCode[0]=0x7900+HReg; WAsmCode[1]=AdrVals[0];
+ break;
+ case 2:
+ CodeLen=6; WAsmCode[0]=0x7a00+HReg;
+ memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ break;
+ END
+ break;
+ END
+ break;
+ case ModIReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0x6880+(HReg << 4)+AdrPart;
+ break;
+ case 1:
+ CodeLen=2; WAsmCode[0]=0x6980+(HReg << 4)+AdrPart;
+ break;
+ case 2:
+ CodeLen=4; WAsmCode[0]=0x0100;
+ WAsmCode[1]=0x6980+(HReg << 4)+AdrPart;
+ break;
+ END
+ break;
+ case ModPreDec:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0x6c80+(HReg << 4)+AdrPart;
+ break;
+ case 1:
+ CodeLen=2; WAsmCode[0]=0x6d80+(HReg << 4)+AdrPart;
+ break;
+ case 2:
+ CodeLen=4; WAsmCode[0]=0x0100;
+ WAsmCode[1]=0x6d80+(HReg << 4)+AdrPart;
+ break;
+ END
+ break;
+ case ModInd16:
+ HReg=AdrPart; WAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=4; WAsmCode[0]=0x6e80+(HReg << 4)+AdrPart;
+ break;
+ case 1:
+ CodeLen=4; WAsmCode[0]=0x6f80+(HReg << 4)+AdrPart;
+ break;
+ case 2:
+ CodeLen=6; WAsmCode[0]=0x0100; WAsmCode[2]=WAsmCode[1];
+ WAsmCode[1]=0x6f80+(HReg << 4)+AdrPart;
+ break;
+ END
+ break;
+ case ModInd24:
+ HReg=AdrPart; memcpy(WAsmCode+2,AdrVals,4);
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=8; WAsmCode[0]=0x7800+(HReg << 4);
+ WAsmCode[1]=0x6aa0+AdrPart;
+ break;
+ case 1:
+ CodeLen=8; WAsmCode[0]=0x7800+(HReg << 4);
+ WAsmCode[1]=0x6ba0+AdrPart;
+ break;
+ case 2:
+ CodeLen=10; WAsmCode[0]=0x0100;
+ WAsmCode[4]=WAsmCode[3]; WAsmCode[3]=WAsmCode[2];
+ WAsmCode[1]=0x7800+(HReg << 4);
+ WAsmCode[2]=0x6ba0+AdrPart;
+ break;
+ END
+ break;
+ case ModAbs8:
+ HReg=Lo(AdrVals[0]);
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0x3000+(((Word)AdrPart) << 8)+HReg;
+ break;
+ case 1:
+ CodeLen=4;
+ WAsmCode[0]=0x6b80+AdrPart; WAsmCode[1]=0xff00+HReg;
+ break;
+ case 2:
+ CodeLen=6; WAsmCode[0]=0x0100;
+ WAsmCode[1]=0x6b80+AdrPart; WAsmCode[2]=0xff00+HReg;
+ break;
+ END
+ break;
+ case ModAbs16:
+ WAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=4; WAsmCode[0]=0x6a80+AdrPart;
+ break;
+ case 1:
+ CodeLen=4; WAsmCode[0]=0x6b80+AdrPart;
+ break;
+ case 2:
+ CodeLen=6; WAsmCode[0]=0x0100; WAsmCode[2]=WAsmCode[1];
+ WAsmCode[1]=0x6b80+AdrPart;
+ break;
+ END
+ break;
+ case ModAbs24:
+ memcpy(WAsmCode+1,AdrVals,4);
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=6; WAsmCode[0]=0x6aa0+AdrPart;
+ break;
+ case 1:
+ CodeLen=6; WAsmCode[0]=0x6ba0+AdrPart;
+ break;
+ case 2:
+ CodeLen=8; WAsmCode[0]=0x0100;
+ WAsmCode[3]=WAsmCode[2]; WAsmCode[2]=WAsmCode[1];
+ WAsmCode[1]=0x6ba0+AdrPart;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MOVTPE")) OR (Memo("MOVFPE")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<=CPUH8_300L) WrError(1500);
+ else
+ BEGIN
+ if (Memo("MOVTPE"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[2]); strcpy(ArgStr[2],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[3]);
+ END
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode!=ModNone)
+ if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart; DecodeAdr(ArgStr[1],MModAbs16);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0x6a40+HReg; WAsmCode[1]=AdrVals[0];
+ if (Memo("MOVTPE")) WAsmCode[0]+=0x80;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ z=Ord(Memo("PUSH"));
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ if (OpSize==0) WrError(1130);
+ else if ((CPU16) AND (OpSize==2)) WrError(1500);
+ else
+ BEGIN
+ if (OpSize==2) WAsmCode[0]=0x0100;
+ CodeLen=2*OpSize;
+ WAsmCode[(CodeLen-2) >> 1]=0x6d70+(z << 7)+AdrPart;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDC")) OR (Memo("STC")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (Memo("STC"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ z=0x80;
+ END
+ else z=0;
+ if (strcasecmp(ArgStr[2],"CCR")!=0) WrError(1350);
+ else
+ BEGIN
+ SetOpSize(0);
+ Mask=MModReg+MModIReg+MModInd+MModAbs16+MModAbs24;
+ if (Memo("LDC")) Mask+=MModImm+MModPostInc;
+ else Mask+=MModPreDec;
+ DecodeAdr(ArgStr[1],Mask);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ WAsmCode[0]=0x0300+AdrPart-(z << 1);
+ break;
+ case ModIReg:
+ CodeLen=4; WAsmCode[0]=0x0140;
+ WAsmCode[1]=0x6900+z+(AdrPart << 4);
+ break;
+ case ModPostInc:
+ case ModPreDec:
+ CodeLen=4; WAsmCode[0]=0x0140;
+ WAsmCode[1]=0x6d00+z+(AdrPart << 4);
+ break;
+ case ModInd16:
+ CodeLen=6; WAsmCode[0]=0x0140; WAsmCode[2]=AdrVals[0];
+ WAsmCode[1]=0x6f00+z+(AdrPart << 4);
+ break;
+ case ModInd24:
+ CodeLen=10; WAsmCode[0]=0x0140; WAsmCode[1]=0x7800+(AdrPart << 4);
+ WAsmCode[2]=0x6b20+z; memcpy(WAsmCode+3,AdrVals,AdrCnt);
+ break;
+ case ModAbs16:
+ CodeLen=6; WAsmCode[0]=0x0140; WAsmCode[2]=AdrVals[0];
+ WAsmCode[1]=0x6b00+z;
+ break;
+ case ModAbs24:
+ CodeLen=8; WAsmCode[0]=0x0140;
+ WAsmCode[1]=0x6b20+z; memcpy(WAsmCode+2,AdrVals,AdrCnt);
+ break;
+ case ModImm:
+ CodeLen=2; WAsmCode[0]=0x0700+Lo(AdrVals[0]);
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik mit 2 Operanden */
+
+ if ((Memo("ADD")) OR (Memo("SUB")))
+ BEGIN
+ z=Ord(Memo("SUB"));
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode!=ModNone)
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ if (AdrMode!=ModNone)
+ if ((CPU16) AND ((OpSize>1) OR ((OpSize==1) AND (AdrMode==ModImm)))) WrError(1500);
+ else switch (AdrMode)
+ BEGIN
+ case ModImm:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ if (z==1) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x8000+(((Word)HReg) << 8)+Lo(AdrVals[0]);
+ END
+ break;
+ case 1:
+ CodeLen=4; WAsmCode[1]=AdrVals[0];
+ WAsmCode[0]=0x7910+(z << 5)+HReg;
+ break;
+ case 2:
+ CodeLen=6; memcpy(WAsmCode+1,AdrVals,4);
+ WAsmCode[0]=0x7a10+(z << 5)+HReg;
+ break;
+ END
+ break;
+ case ModReg:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0x0800+(z << 12)+(AdrPart << 4)+HReg;
+ break;
+ case 1:
+ CodeLen=2; WAsmCode[0]=0x0900+(z << 12)+(AdrPart << 4)+HReg;
+ break;
+ case 2:
+ CodeLen=2; WAsmCode[0]=0x0a00+(z << 12)+0x80+(AdrPart << 4)+HReg;
+ break;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CMP"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode!=ModNone)
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ if (AdrMode!=ModNone)
+ if ((CPU16) AND ((OpSize>1) OR ((OpSize==1) AND (AdrMode==ModImm)))) WrError(1500);
+ else switch (AdrMode)
+ BEGIN
+ case ModImm:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0xa000+(((Word)HReg) << 8)+Lo(AdrVals[0]);
+ break;
+ case 1:
+ CodeLen=4; WAsmCode[1]=AdrVals[0];
+ WAsmCode[0]=0x7920+HReg;
+ break;
+ case 2:
+ CodeLen=6; memcpy(WAsmCode+1,AdrVals,4);
+ WAsmCode[0]=0x7a20+HReg;
+ END
+ break;
+ case ModReg:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0x1c00+(AdrPart << 4)+HReg;
+ break;
+ case 1:
+ CodeLen=2; WAsmCode[0]=0x1d00+(AdrPart << 4)+HReg;
+ break;
+ case 2:
+ CodeLen=2; WAsmCode[0]=0x1f80+(AdrPart << 4)+HReg;
+ break;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<LogicOrderCount; z++)
+ if (strncmp(OpPart,LogicOrders[z].Name,strlen(LogicOrders[z].Name))==0)
+ switch (OpPart[strlen(LogicOrders[z].Name)])
+ BEGIN
+ case '\0':
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode!=ModNone)
+ if ((CPU16) AND (OpSize>0)) WrError(1500);
+ else
+ BEGIN
+ HReg=AdrPart; DecodeAdr(ArgStr[1],MModImm+MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2;
+ WAsmCode[0]=0xc000+(((Word)LogicOrders[z].Code) << 12)+(((Word)HReg) << 8)+Lo(AdrVals[0]);
+ break;
+ case 1:
+ CodeLen=4; WAsmCode[1]=AdrVals[0];
+ WAsmCode[0]=0x7940+(((Word)LogicOrders[z].Code) << 4)+HReg;
+ break;
+ case 2:
+ CodeLen=6; memcpy(WAsmCode+1,AdrVals,AdrCnt);
+ WAsmCode[0]=0x7a40+(((Word)LogicOrders[z].Code) << 4)+HReg;
+ break;
+ END
+ break;
+ case ModReg:
+ switch (OpSize)
+ BEGIN
+ case 0:
+ CodeLen=2; WAsmCode[0]=0x1400+(((Word)LogicOrders[z].Code) << 8)+(AdrPart << 4)+HReg;
+ break;
+ case 1:
+ CodeLen=2; WAsmCode[0]=0x6400+(((Word)LogicOrders[z].Code) << 8)+(AdrPart << 4)+HReg;
+ break;
+ case 2:
+ CodeLen=4; WAsmCode[0]=0x01f0;
+ WAsmCode[1]=0x6400+(((Word)LogicOrders[z].Code) << 8)+(AdrPart << 4)+HReg;
+ break;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ case 'C':
+ SetOpSize(0);
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[2],"CCR")!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CodeLen=2;
+ WAsmCode[0]=0x0400+(((Word)LogicOrders[z].Code) << 8)+Lo(AdrVals[0]);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("ADDX")) OR (Memo("SUBX")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode!=ModNone)
+ if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[1],MModImm+MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ CodeLen=2; WAsmCode[0]=0x9000+(((Word)HReg) << 8)+Lo(AdrVals[0]);
+ if (Memo("SUBX")) WAsmCode[0]+=0x2000;
+ break;
+ case ModReg:
+ CodeLen=2; WAsmCode[0]=0x0e00+(AdrPart << 4)+HReg;
+ if (Memo("SUBX")) WAsmCode[0]+=0x1000;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("ADDS")) OR (Memo("SUBS")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode!=ModNone)
+ if (((CPU16) AND (OpSize!=1)) OR ((NOT CPU16) AND (OpSize!=2))) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[1],MModImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ AdrLong=ImmVal();
+ if ((AdrLong!=1) AND (AdrLong!=2) AND (AdrLong!=4)) WrError(1320);
+ else
+ BEGIN
+ switch (AdrLong)
+ BEGIN
+ case 1: WAsmCode[0]=0x0b00; break;
+ case 2: WAsmCode[0]=0x0b80; break;
+ case 4: WAsmCode[0]=0x0b90; break;
+ END
+ CodeLen=2; WAsmCode[0]+=HReg;
+ if (Memo("SUBS")) WAsmCode[0]+=0x1000;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<MulOrderCount; z++)
+ if (Memo(MulOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (OpSize!=-1) OpSize++;
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode!=ModNone)
+ if (OpSize==0) WrError(1130);
+ else if ((CPU16) AND (OpSize==2)) WrError(1500);
+ else
+ BEGIN
+ HReg=AdrPart; OpSize--;
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ BEGIN
+ if ((MulOrders[z].Code & 2)==2)
+ BEGIN
+ CodeLen=4; WAsmCode[0]=0x01c0;
+ if ((MulOrders[z].Code & 1)==1) WAsmCode[0]+=0x10;
+ END
+ else CodeLen=2;
+ WAsmCode[CodeLen >> 2]=0x5000
+ +(((Word)OpSize) << 9)
+ +(((Word)MulOrders[z].Code & 1) << 8)
+ +(AdrPart << 4)+HReg;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Bitoperationen */
+
+ for (z=0; z<Bit1OrderCount; z++)
+ if (Memo(Bit1Orders[z].Name))
+ BEGIN
+ OpCode=0x60+(Bit1Orders[z].Code & 0x7f);
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ HReg=EvalIntExpression(ArgStr[1]+1,UInt3,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+MModIReg+MModAbs8);
+ if (AdrMode!=ModNone)
+ if (OpSize>0) WrError(1130);
+ else switch (AdrMode)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ WAsmCode[0]=(((Word)OpCode) << 8)+(Bit1Orders[z].Code & 0x80)+(HReg << 4)+AdrPart;
+ break;
+ case ModIReg:
+ CodeLen=4;
+ WAsmCode[0]=0x7c00+(AdrPart << 4);
+ WAsmCode[1]=(((Word)OpCode) << 8)+(Bit1Orders[z].Code & 0x80)+(HReg << 4);
+ if (OpCode<0x70) WAsmCode[0]+=0x100;
+ break;
+ case ModAbs8:
+ CodeLen=4;
+ WAsmCode[0]=0x7e00+Lo(AdrVals[0]);
+ WAsmCode[1]=(((Word)OpCode) << 8)+(Bit1Orders[z].Code & 0x80)+(HReg << 4);
+ if (OpCode<0x70) WAsmCode[0]+=0x100;
+ break;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Bit2OrderCount; z++)
+ if (Memo(Bit2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (*ArgStr[1]=='#')
+ BEGIN
+ OpCode=Bit2Orders[z].Code+0x70;
+ HReg=EvalIntExpression(ArgStr[1]+1,UInt3,&OK);
+ END
+ else
+ BEGIN
+ OpCode=Bit2Orders[z].Code+0x60;
+ OK=DecodeReg(ArgStr[1],&HReg,&HSize);
+ if (NOT OK) WrError(1350);
+ if ((OK) AND (HSize!=0))
+ BEGIN
+ WrError(1130); OK=False;
+ END
+ END
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg+MModIReg+MModAbs8);
+ if (AdrMode!=ModNone)
+ if (OpSize>0) WrError(1130);
+ else switch (AdrMode)
+ BEGIN
+ case ModReg:
+ CodeLen=2;
+ WAsmCode[0]=(((Word)OpCode) << 8)+(HReg << 4)+AdrPart;
+ break;
+ case ModIReg:
+ CodeLen=4;
+ WAsmCode[0]=0x7d00+(AdrPart << 4);
+ WAsmCode[1]=(((Word)OpCode) << 8)+(HReg << 4);
+ if (Bit2Orders[z].Code==3) WAsmCode[0]-=0x100;
+ break;
+ case ModAbs8:
+ CodeLen=4;
+ WAsmCode[0]=0x7f00+Lo(AdrVals[0]);
+ WAsmCode[1]=(((Word)OpCode) << 8)+(HReg << 4);
+ if (Bit2Orders[z].Code==3) WAsmCode[0]-=0x100;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Read/Modify/Write-Operationen */
+
+ if ((Memo("INC")) OR (Memo("DEC")))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[ArgCnt],MModReg);
+ if (AdrMode!=ModNone)
+ if ((OpSize>0) AND (CPU16)) WrError(1500);
+ else
+ BEGIN
+ HReg=AdrPart;
+ if (ArgCnt==1)
+ BEGIN
+ OK=True; z=1;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModImm);
+ OK=(AdrMode==ModImm);
+ if (OK)
+ BEGIN
+ z=ImmVal();
+ if (z<1)
+ BEGIN
+ WrError(1315); OK=False;
+ END
+ else if (((OpSize==0) AND (z>1)) OR (z>2))
+ BEGIN
+ WrError(1320); OK=False;
+ END
+ END
+ END
+ if (OK)
+ BEGIN
+ CodeLen=2; z--;
+ switch (OpSize)
+ BEGIN
+ case 0:WAsmCode[0]=0x0a00+HReg; break;
+ case 1:WAsmCode[0]=0x0b50+HReg+(z << 7); break;
+ case 2:WAsmCode[0]=0x0b70+HReg+(z << 7);
+ END
+ if (Memo("DEC")) WAsmCode[0]+=0x1000;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ShiftOrderCount; z++)
+ if (Memo(ShiftOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ if ((OpSize>0) AND (CPU16)) WrError(1500);
+ else
+ BEGIN
+ CodeLen=2;
+ switch (OpSize)
+ BEGIN
+ case 0: WAsmCode[0]=ShiftOrders[z].Code+AdrPart; break;
+ case 1: WAsmCode[0]=ShiftOrders[z].Code+AdrPart+0x10; break;
+ case 2: WAsmCode[0]=ShiftOrders[z].Code+AdrPart+0x30; break;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("NEG")) OR (Memo("NOT")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ if ((OpSize>0) AND (CPU16)) WrError(1500);
+ else
+ BEGIN
+ CodeLen=2;
+ switch (OpSize)
+ BEGIN
+ case 0:WAsmCode[0]=0x1700+AdrPart; break;
+ case 1:WAsmCode[0]=0x1710+AdrPart; break;
+ case 2:WAsmCode[0]=0x1730+AdrPart; break;
+ END
+ if (Memo("NEG")) WAsmCode[0]+=0x80;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("EXTS")) OR (Memo("EXTU")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CPU16) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ CodeLen=2;
+ switch (OpSize)
+ BEGIN
+ case 1: WAsmCode[0]=(Memo("EXTS")) ? 0x17d0 : 0x1750; break;
+ case 2: WAsmCode[0]=(Memo("EXTS")) ? 0x17f0 : 0x1770; break;
+ END
+ WAsmCode[0]+=AdrPart;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("DAA")) OR (Memo("DAS")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ CodeLen=2;
+ WAsmCode[0]=0x0f00+AdrPart;
+ if (Memo("DAS")) WAsmCode[0]+=0x1000;
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ for (z=0; z<ConditionCount; z++)
+ if (Memo(Conditions[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if ((OpSize!=-1) AND (OpSize!=4) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int24,&OK)-(EProgCounter()+2);
+ if (OK)
+ BEGIN
+ if (OpSize==-1)
+ if ((AdrLong>=-128) AND (AdrLong<=127)) OpSize=4;
+ else
+ BEGIN
+ OpSize=2; AdrLong-=2;
+ END
+ else if (OpSize==2) AdrLong-=2;
+ if (OpSize==2)
+ BEGIN
+ if ((NOT SymbolQuestionable) AND ((AdrLong<-32768) OR (AdrLong>32767))) WrError(1370);
+ else if (CPU16) WrError(1500);
+ else
+ BEGIN
+ CodeLen=4;
+ WAsmCode[0]=0x5800+(Conditions[z].Code << 4); WAsmCode[1]=AdrLong & 0xffff;
+ END
+ END
+ else
+ BEGIN
+ if ((NOT SymbolQuestionable) AND ((AdrLong<-128) OR (AdrLong>127))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2;
+ WAsmCode[0]=0x4000+(((Word)Conditions[z].Code) << 8)+(AdrLong & 0xff);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JMP")) OR (Memo("JSR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ z=Ord(Memo("JSR")) << 10;
+ DecodeAdr(ArgStr[1],MModIReg+((CPU16)?MModAbs16:MModAbs24)+MModIIAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModIReg:
+ CodeLen=2; WAsmCode[0]=0x5900+z+(AdrPart << 4);
+ break;
+ case ModAbs16:
+ CodeLen=4; WAsmCode[0]=0x5a00+z; WAsmCode[1]=AdrVals[0];
+ break;
+ case ModAbs24:
+ CodeLen=4; WAsmCode[0]=0x5a00+z+Lo(AdrVals[0]);
+ WAsmCode[1]=AdrVals[1];
+ break;
+ case ModIIAbs:
+ CodeLen=2; WAsmCode[0]=0x5b00+z+Lo(AdrVals[0]);
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("BSR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if ((OpSize!=-1) AND (OpSize!=4) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int24,&OK)-(EProgCounter()+2);
+ if (OK)
+ BEGIN
+ if (OpSize==-1)
+ if ((AdrLong>=-128) AND (AdrLong<=127)) OpSize=4;
+ else
+ BEGIN
+ OpSize=2; AdrLong-=2;
+ END
+ else if (OpSize==2) AdrLong-=2;
+ if (OpSize==2)
+ BEGIN
+ if ((NOT SymbolQuestionable) AND ((AdrLong<-32768) OR (AdrLong>32767))) WrError(1370);
+ else if (CPU16) WrError(1500);
+ else
+ BEGIN
+ CodeLen=4;
+ WAsmCode[0]=0x5c00; WAsmCode[1]=AdrLong & 0xffff;
+ END
+ END
+ else
+ BEGIN
+ if ((AdrLong<-128) OR (AdrLong>127)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2;
+ WAsmCode[0]=0x5500+(AdrLong & 0xff);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("TRAPA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPU6413309) WrError(1500);
+ else
+ BEGIN
+ if (*ArgStr[1]=='#') strcpy(ArgStr[1],ArgStr[1]+1);
+ WAsmCode[0]=EvalIntExpression(ArgStr[1],UInt2,&OK)<<4;
+ if (OK)
+ BEGIN
+ WAsmCode[0]+=0x5700; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_H8_3(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_H8_3(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_H8_3(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x68; NOPCode=0x0000;
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ SegLimits[SegCode] = (MomCPU <= CPUH8_300) ? 0xffff : 0xffffffl;
+
+ MakeCode=MakeCode_H8_3; IsDef=IsDef_H8_3;
+ SwitchFrom=SwitchFrom_H8_3; InitFields();
+ AddONOFF("MAXMODE", &Maximum , MaximumName ,False);
+ AddONOFF("PADDING", &DoPadding , DoPaddingName ,False);
+ AddMoto16PseudoONOFF();
+
+ CPU16=(MomCPU<=CPUH8_300);
+
+ SetFlag(&DoPadding,DoPaddingName,False);
+END
+
+ void codeh8_3_init(void)
+BEGIN
+ CPUH8_300L=AddCPU("H8/300L" ,SwitchTo_H8_3);
+ CPU6413308=AddCPU("HD6413308" ,SwitchTo_H8_3);
+ CPUH8_300 =AddCPU("H8/300" ,SwitchTo_H8_3);
+ CPU6413309=AddCPU("HD6413309" ,SwitchTo_H8_3);
+ CPUH8_300H=AddCPU("H8/300H" ,SwitchTo_H8_3);
+END
diff --git a/codeh8_3.h b/codeh8_3.h
new file mode 100644
index 0000000..1a1f3f1
--- /dev/null
+++ b/codeh8_3.h
@@ -0,0 +1,11 @@
+/* codeh8_3.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator H8/300(L/H) */
+/* */
+/* Historie: 22.11.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codeh8_3_init(void);
diff --git a/codeh8_5.c b/codeh8_5.c
new file mode 100644
index 0000000..674052f
--- /dev/null
+++ b/codeh8_5.c
@@ -0,0 +1,1510 @@
+/* codeh8_5.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegenerator H8/500 */
+/* */
+/* Historie: 24.12.1996 Grundsteinlegung */
+/* 9. 1.1999 ChkPC jetzt mit Adresse als Parameter */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+#define FixedOrderCount 6
+#define RelOrderCount 21
+#define OneOrderCount 13
+#define OneRegOrderCount 3
+#define RegEAOrderCount 9
+#define TwoRegOrderCount 3
+#define LogOrderCount 3
+#define BitOrderCount 4
+
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModIReg 1
+#define MModIReg (1 << ModIReg)
+#define ModDisp8 2
+#define MModDisp8 (1 << ModDisp8)
+#define ModDisp16 3
+#define MModDisp16 (1 << ModDisp16)
+#define ModPredec 4
+#define MModPredec (1 << ModPredec)
+#define ModPostInc 5
+#define MModPostInc (1 << ModPostInc)
+#define ModAbs8 6
+#define MModAbs8 (1 << ModAbs8)
+#define ModAbs16 7
+#define MModAbs16 (1 << ModAbs16)
+#define ModImm 8
+#define MModImm (1 << ModImm)
+
+#define MModAll (MModReg|MModIReg|MModDisp8|MModDisp16|MModPredec|MModPostInc|MModAbs8|MModAbs16|MModImm)
+#define MModNoImm (MModAll-MModImm)
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Byte SizeMask;
+ ShortInt DefSize;
+ } OneOrder;
+
+
+static CPUVar CPU532,CPU534,CPU536,CPU538;
+static SimpProc SaveInitProc;
+
+static ShortInt OpSize;
+static String Format;
+static ShortInt AdrMode;
+static Byte AdrByte,FormatCode;
+static Byte AdrVals[3];
+static Byte AbsBank;
+
+static LongInt Reg_DP,Reg_EP,Reg_TP,Reg_BR;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *RelOrders;
+static OneOrder *OneOrders;
+static OneOrder *OneRegOrders;
+static OneOrder *RegEAOrders;
+static OneOrder *TwoRegOrders;
+static FixedOrder *LogOrders;
+static FixedOrder *BitOrders;
+
+/*-------------------------------------------------------------------------*/
+/* dynamische Belegung/Freigabe Codetabellen */
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ++].Name=NName;
+END
+
+ static void AddRel(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=RelOrderCount) exit(255);
+ RelOrders[InstrZ].Code=NCode;
+ RelOrders[InstrZ++].Name=NName;
+END
+
+ static void AddOne(char *NName, Word NCode, Byte NMask, ShortInt NDef)
+BEGIN
+ if (InstrZ>=OneOrderCount) exit(255);
+ OneOrders[InstrZ].Code=NCode;
+ OneOrders[InstrZ].Name=NName;
+ OneOrders[InstrZ].SizeMask=NMask;
+ OneOrders[InstrZ++].DefSize=NDef;
+END
+
+ static void AddOneReg(char *NName, Word NCode, Byte NMask, ShortInt NDef)
+BEGIN
+ if (InstrZ>=OneRegOrderCount) exit(255);
+ OneRegOrders[InstrZ].Code=NCode;
+ OneRegOrders[InstrZ].Name=NName;
+ OneRegOrders[InstrZ].SizeMask=NMask;
+ OneRegOrders[InstrZ++].DefSize=NDef;
+END
+
+ static void AddRegEA(char *NName, Word NCode, Byte NMask, ShortInt NDef)
+BEGIN
+ if (InstrZ>=RegEAOrderCount) exit(255);
+ RegEAOrders[InstrZ].Code=NCode;
+ RegEAOrders[InstrZ].Name=NName;
+ RegEAOrders[InstrZ].SizeMask=NMask;
+ RegEAOrders[InstrZ++].DefSize=NDef;
+END
+
+ static void AddTwoReg(char *NName, Word NCode, Byte NMask, ShortInt NDef)
+BEGIN
+ if (InstrZ>=TwoRegOrderCount) exit(255);
+ TwoRegOrders[InstrZ].Code=NCode;
+ TwoRegOrders[InstrZ].Name=NName;
+ TwoRegOrders[InstrZ].SizeMask=NMask;
+ TwoRegOrders[InstrZ++].DefSize=NDef;
+END
+
+ static void AddLog(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=LogOrderCount) exit(255);
+ LogOrders[InstrZ].Code=NCode;
+ LogOrders[InstrZ++].Name=NName;
+END
+
+ static void AddBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=BitOrderCount) exit(255);
+ BitOrders[InstrZ].Code=NCode;
+ BitOrders[InstrZ++].Name=NName;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstrZ=0; FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount);
+ AddFixed("NOP" ,0x0000); AddFixed("PRTS" ,0x1119);
+ AddFixed("RTE" ,0x000a); AddFixed("RTS" ,0x0019);
+ AddFixed("SLEEP",0x001a); AddFixed("TRAP/VS",0x0009);
+
+ InstrZ=0; RelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RelOrderCount);
+ AddRel("BRA",0x20); AddRel("BT" ,0x20); AddRel("BRN",0x21);
+ AddRel("BF" ,0x21); AddRel("BHI",0x22); AddRel("BLS",0x23);
+ AddRel("BCC",0x24); AddRel("BHS",0x24); AddRel("BCS",0x25);
+ AddRel("BLO",0x25); AddRel("BNE",0x26); AddRel("BEQ",0x27);
+ AddRel("BVC",0x28); AddRel("BVS",0x29); AddRel("BPL",0x2a);
+ AddRel("BMI",0x2b); AddRel("BGE",0x2c); AddRel("BLT",0x2d);
+ AddRel("BGT",0x2e); AddRel("BLE",0x2f); AddRel("BSR",0x0e);
+
+ InstrZ=0; OneOrders=(OneOrder *) malloc(sizeof(OneOrder)*OneOrderCount);
+ AddOne("CLR" ,0x13,3,1); AddOne("NEG" ,0x14,3,1);
+ AddOne("NOT" ,0x15,3,1); AddOne("ROTL" ,0x1c,3,1);
+ AddOne("ROTR" ,0x1d,3,1); AddOne("ROTXL",0x1e,3,1);
+ AddOne("ROTXR",0x1f,3,1); AddOne("SHAL" ,0x18,3,1);
+ AddOne("SHAR" ,0x19,3,1); AddOne("SHLL" ,0x1a,3,1);
+ AddOne("SHLR" ,0x1b,3,1); AddOne("TAS" ,0x17,1,0);
+ AddOne("TST" ,0x16,3,1);
+
+ InstrZ=0; OneRegOrders=(OneOrder *) malloc(sizeof(OneOrder)*OneRegOrderCount);
+ AddOneReg("EXTS",0x11,1,0); AddOneReg("EXTU",0x12,1,0);
+ AddOneReg("SWAP",0x10,1,0);
+
+ InstrZ=0; RegEAOrders=(OneOrder *) malloc(sizeof(OneOrder)*RegEAOrderCount);
+ AddRegEA("ADDS" ,0x28,3,1); AddRegEA("ADDX" ,0xa0,3,1);
+ AddRegEA("AND" ,0x50,3,1); AddRegEA("DIVXU",0xb8,3,1);
+ AddRegEA("MULXU",0xa8,3,1); AddRegEA("OR" ,0x40,3,1);
+ AddRegEA("SUBS" ,0x38,3,1); AddRegEA("SUBX" ,0xb0,3,1);
+ AddRegEA("XOR" ,0x60,3,1);
+
+ InstrZ=0; TwoRegOrders=(OneOrder *) malloc(sizeof(OneOrder)*TwoRegOrderCount);
+ AddTwoReg("DADD",0xa000,1,0); AddTwoReg("DSUB",0xb000,1,0);
+ AddTwoReg("XCH" ,0x90,2,1);
+
+ InstrZ=0; LogOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LogOrderCount);
+ AddLog("ANDC",0x58); AddLog("ORC",0x48); AddLog("XORC",0x68);
+
+ InstrZ=0; BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCount);
+ AddBit("BCLR",0x50); AddBit("BNOT",0x60);
+ AddBit("BSET",0x40); AddBit("BTST",0x70);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(RelOrders);
+ free(OneOrders);
+ free(OneRegOrders);
+ free(RegEAOrders);
+ free(TwoRegOrders);
+ free(LogOrders);
+ free(BitOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Adressparsing */
+
+ static void SetOpSize(ShortInt NSize)
+BEGIN
+ if (OpSize==-1) OpSize=NSize;
+ else if (OpSize!=NSize) WrError(1132);
+END
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg)
+BEGIN
+ if (strcasecmp(Asc,"SP")==0) *Erg=7;
+ else if (strcasecmp(Asc,"FP")==0) *Erg=6;
+ else if ((strlen(Asc)==2) AND (toupper(*Asc)=='R') AND (Asc[1]>='0') AND (Asc[1]<='7'))
+ *Erg=Asc[1]-'0';
+ else return False;
+ return True;
+END
+
+ static Boolean DecodeRegList(char *Asc, Byte *Erg)
+BEGIN
+ String Part;
+ Byte Reg1,Reg2,z;
+ char *p;
+
+ if (IsIndirect(Asc))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ KillBlanks(Asc);
+ END
+
+ *Erg=0;
+ while (*Asc!='\0')
+ BEGIN
+ p=QuotPos(Asc,',');
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Part,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(Part,Asc,255); strcpy(Asc,p+1);
+ END
+ if (DecodeReg(Part,&Reg1)) *Erg|=(1 << Reg1);
+ else
+ BEGIN
+ p=strchr(Part,'-');
+ if (p==Nil) return False; *p='\0';
+ if (NOT DecodeReg(Part,&Reg1)) return False;
+ if (NOT DecodeReg(p+1,&Reg2)) return False;
+ if (Reg1>Reg2) Reg2+=8;
+ for (z=Reg1; z<=Reg2; z++) *Erg|=(1 << (z & 7));
+ END
+ END
+
+ return True;
+END
+
+ static Boolean DecodeCReg(char *Asc, Byte *Erg)
+BEGIN
+ if (strcasecmp(Asc,"SR")==0)
+ BEGIN
+ *Erg=0; SetOpSize(1);
+ END
+ else if (strcasecmp(Asc,"CCR")==0)
+ BEGIN
+ *Erg=1; SetOpSize(0);
+ END
+ else if (strcasecmp(Asc,"BR")==0)
+ BEGIN
+ *Erg=3; SetOpSize(0);
+ END
+ else if (strcasecmp(Asc,"EP")==0)
+ BEGIN
+ *Erg=4; SetOpSize(0);
+ END
+ else if (strcasecmp(Asc,"DP")==0)
+ BEGIN
+ *Erg=5; SetOpSize(0);
+ END
+ else if (strcasecmp(Asc,"TP")==0)
+ BEGIN
+ *Erg=7; SetOpSize(0);
+ END
+ else return False;
+ return True;
+END
+
+ static void SplitDisp(char *Asc, ShortInt *Size)
+BEGIN
+ int l=strlen(Asc);
+
+ if ((l>2) AND (Asc[l-1]=='8') AND (Asc[l-2]==':'))
+ BEGIN
+ Asc[l-2]='\0'; *Size=0;
+ END
+ else if ((l>3) AND (Asc[l-1]=='6') AND (Asc[l-2]=='1') AND (Asc[l-3]==':'))
+ BEGIN
+ Asc[l-3]='\0'; *Size=1;
+ END
+END
+
+ static void DecideAbsolute(LongInt Value, ShortInt Size, Boolean Unknown, Word Mask)
+BEGIN
+ LongInt Base;
+
+ if (Size==-1)
+ if (((Value >> 8)==Reg_BR) AND ((Mask & MModAbs8)!=0)) Size=0; else Size=1;
+
+ switch (Size)
+ BEGIN
+ case 0:
+ if (Unknown) Value=(Value & 0xff) | (Reg_BR << 8);
+ if ((Value >> 8)!=Reg_BR) WrError(110);
+ AdrMode=ModAbs8; AdrByte=0x05;
+ AdrVals[0]=Value & 0xff; AdrCnt=1;
+ break;
+ case 1:
+ Base=(Maximum) ? ((LongInt)AbsBank) << 16 : 0;
+ if (Unknown) Value=(Value & 0xffff) | Base;
+ if ((Value >> 16)!=(Base >> 16)) WrError(110);
+ AdrMode=ModAbs16; AdrByte=0x15;
+ AdrVals[0]=(Value >> 8) & 0xff;
+ AdrVals[1]=Value & 0xff;
+ AdrCnt=2;
+ break;
+ END
+END
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ WrError(1350); AdrMode=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ Word AdrWord;
+ Boolean OK,Unknown;
+ LongInt DispAcc;
+ Byte HReg;
+ ShortInt DispSize,RegPart;
+ String Part;
+ char *p;
+
+ AdrMode=ModNone; AdrCnt=0;
+
+ /* einfaches Register ? */
+
+ if (DecodeReg(Asc,&AdrByte))
+ BEGIN
+ AdrMode=ModReg; AdrByte+=0xa0; ChkAdr(Mask); return;
+ END
+
+ /* immediate ? */
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case -1:
+ OK=False; WrError(1131);
+ break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ break;
+ case 1:
+ AdrWord=EvalIntExpression(Asc+1,Int16,&OK);
+ AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ break;
+ END
+ if (OK)
+ BEGIN
+ AdrMode=ModImm; AdrByte=0x04; AdrCnt=OpSize+1;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* indirekt ? */
+
+ if (*Asc=='@')
+ BEGIN
+ strcpy(Asc,Asc+1);
+ if (IsIndirect(Asc))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ END
+
+ /* Predekrement ? */
+
+ if ((*Asc=='-') AND (DecodeReg(Asc+1,&AdrByte)))
+ BEGIN
+ AdrMode=ModPredec; AdrByte+=0xb0;
+ END
+
+ /* Postinkrement ? */
+
+ else if (Asc[strlen(Asc)-1]=='+')
+ BEGIN
+ strmaxcpy(Part,Asc,255); Part[strlen(Part)-1]='\0';
+ if (DecodeReg(Part,&AdrByte))
+ BEGIN
+ AdrMode=ModPostInc; AdrByte+=0xc0;
+ END
+ END
+
+ /* zusammengesetzt */
+
+ else
+ BEGIN
+ DispAcc=0; DispSize=(-1); RegPart=(-1); OK=True; Unknown=False;
+ while ((*Asc!='\0') AND (OK))
+ BEGIN
+ p=QuotPos(Asc,',');
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Part,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(Part,Asc,255); strcpy(Asc,p+1);
+ END
+ if (DecodeReg(Part,&HReg))
+ if (RegPart!=-1)
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else RegPart=HReg;
+ else
+ BEGIN
+ SplitDisp(Part,&DispSize); if (*Part=='#') strcpy(Part,Part+1);
+ FirstPassUnknown=False;
+ DispAcc+=EvalIntExpression(Part,Int32,&OK);
+ if (FirstPassUnknown) Unknown=True;
+ END
+ END
+ if (OK)
+ BEGIN
+ if (RegPart==-1) DecideAbsolute(DispAcc,DispSize,Unknown,Mask);
+ else if (DispAcc==0)
+ switch (DispSize)
+ BEGIN
+ case -1:
+ AdrMode=ModIReg; AdrByte=0xd0+RegPart;
+ break;
+ case 0:
+ AdrMode=ModDisp8; AdrByte=0xe0+RegPart;
+ AdrVals[0]=0; AdrCnt=1;
+ break;
+ case 1:
+ AdrMode=ModDisp16; AdrByte=0xf0+RegPart;
+ AdrVals[0]=0; AdrVals[1]=0; AdrCnt=2;
+ break;
+ END
+ else
+ BEGIN
+ if (DispSize==-1)
+ if ((DispAcc>=-128) AND (DispAcc<127)) DispSize=0;
+ else DispSize=1;
+ switch (DispSize)
+ BEGIN
+ case 0:
+ if (Unknown) DispAcc&=0x7f;
+ if (ChkRange(DispAcc,-128,127))
+ BEGIN
+ AdrMode=ModDisp8; AdrByte=0xe0+RegPart;
+ AdrVals[0]=DispAcc & 0xff; AdrCnt=1;
+ END
+ break;
+ case 1:
+ if (Unknown) DispAcc&=0x7fff;
+ if (ChkRange(DispAcc,-0x8000l,0x7fffl))
+ BEGIN
+ AdrMode=ModDisp16; AdrByte=0xf0+RegPart;
+ AdrVals[1]=DispAcc & 0xff;
+ AdrVals[0]=(DispAcc >> 8) & 0xff;
+ AdrCnt=2;
+ END
+ break;
+ END
+ END
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* absolut */
+
+ DispSize=(-1); SplitDisp(Asc,&DispSize);
+ FirstPassUnknown=False;
+ DispAcc=EvalIntExpression(Asc,UInt24,&OK);
+ DecideAbsolute(DispAcc,DispSize,FirstPassUnknown,Mask);
+
+ ChkAdr(Mask);
+END
+
+ static LongInt ImmVal(void)
+BEGIN
+ LongInt t;
+
+ switch (OpSize)
+ BEGIN
+ case 0:
+ t=AdrVals[0]; if (t>127) t-=256;
+ break;
+ case 1:
+ t=(((Word)AdrVals[0]) << 8)+AdrVals[1];
+ if (t>0x7fff) t-=0x10000;
+ break;
+ default:
+ t=0; WrError(10000);
+ END
+ return t;
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static Boolean CheckFormat(char *FSet)
+BEGIN
+ char *p;
+
+ if (strcmp(Format," ")==0) FormatCode=0;
+ else
+ BEGIN
+ p=strchr(FSet,*Format);
+ if (p==Nil)
+ BEGIN
+ WrError(1090); return False;
+ END
+ else FormatCode=p-FSet+1;
+ END
+ return True;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUMEH8_5Count 4
+static ASSUMERec ASSUMEH8_5s[ASSUMEH8_5Count]=
+ {{"DP", &Reg_DP, 0, 0xff, -1},
+ {"EP", &Reg_EP, 0, 0xff, -1},
+ {"TP", &Reg_TP, 0, 0xff, -1},
+ {"BR", &Reg_BR, 0, 0xff, -1}};
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUMEH8_5s,ASSUMEH8_5Count);
+ return True;
+ END
+
+ return False;
+END
+
+static ShortInt Adr2Mode;
+static Byte Adr2Byte,Adr2Cnt;
+static Byte Adr2Vals[3];
+
+ static void CopyAdr(void)
+BEGIN
+ Adr2Mode=AdrMode;
+ Adr2Byte=AdrByte;
+ Adr2Cnt=AdrCnt;
+ memcpy(Adr2Vals,AdrVals,AdrCnt);
+END
+
+ static void MakeCode_H8_5(void)
+BEGIN
+ Integer AdrInt;
+ int z;
+ char *p;
+ Boolean OK;
+ LongInt AdrLong;
+ Byte HReg;
+ ShortInt HSize;
+
+ CodeLen=0; DontPrint=False; OpSize=(-1); AbsBank=Reg_DP;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* Formatangabe abspalten */
+
+ switch (AttrSplit)
+ BEGIN
+ case '.':
+ p=strchr(AttrPart,':');
+ if (p!=Nil)
+ BEGIN
+ if (p<AttrPart+strlen(AttrPart)-1) strmaxcpy(Format,p+1,255);
+ else strcpy(Format," ");
+ *p='\0';
+ END
+ else strcpy(Format," ");
+ break;
+ case ':':
+ p=strchr(AttrPart,'.');
+ if (p==0)
+ BEGIN
+ strmaxcpy(Format,AttrPart,255); *AttrPart='\0';
+ END
+ else
+ BEGIN
+ *p='\0';
+ if (p==AttrPart) strcpy(Format," "); else strmaxcpy(Format,AttrPart,255);
+ strcpy(AttrPart,p+1);
+ END
+ break;
+ default:
+ strcpy(Format," ");
+ END
+
+ /* Attribut abarbeiten */
+
+ if (*AttrPart=='\0') SetOpSize(-1);
+ else
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B':SetOpSize(0); break;
+ case 'W':SetOpSize(1); break;
+ case 'L':SetOpSize(2); break;
+ case 'Q':SetOpSize(3); break;
+ case 'S':SetOpSize(4); break;
+ case 'D':SetOpSize(5); break;
+ case 'X':SetOpSize(6); break;
+ case 'P':SetOpSize(7); break;
+ default:
+ WrError(1107); return;
+ END
+ NLS_UpString(Format);
+
+ if (DecodeMoto16Pseudo(OpSize,True)) return;
+
+ /* Anweisungen ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (OpSize!=-1) WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else
+ BEGIN
+ CodeLen=0;
+ if (Hi(FixedOrders[z].Code)!=0) BAsmCode[CodeLen++]=Hi(FixedOrders[z].Code);
+ BAsmCode[CodeLen++]=Lo(FixedOrders[z].Code);
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GEIFLS"))
+ BEGIN
+ if (OpSize==-1)
+ SetOpSize((FormatCode==2) ? 0 : 1);
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModNoImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CopyAdr();
+ DecodeAdr(ArgStr[1],MModAll);
+ if (AdrMode!=ModNone)
+ BEGIN
+ if (FormatCode==0)
+ if ((AdrMode==ModImm) AND (Adr2Mode==ModReg)) FormatCode=2+OpSize;
+ else if ((AdrMode==ModReg) AND (Adr2Byte==0xe6)) FormatCode=4;
+ else if ((Adr2Mode==ModReg) AND (AdrByte==0xe6)) FormatCode=4;
+ else if ((AdrMode==ModReg) AND (Adr2Mode==ModAbs8)) FormatCode=6;
+ else if ((AdrMode==ModAbs8) AND (Adr2Mode==ModReg)) FormatCode=5;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ if (AdrMode==ModReg)
+ BEGIN
+ BAsmCode[0]=Adr2Byte+(OpSize << 3);
+ memcpy(BAsmCode+1,Adr2Vals,Adr2Cnt);
+ BAsmCode[1+Adr2Cnt]=0x90+(AdrByte & 7);
+ CodeLen=2+Adr2Cnt;
+ END
+ else if (Adr2Mode==ModReg)
+ BEGIN
+ BAsmCode[0]=AdrByte+(OpSize << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x80+(Adr2Byte & 7);
+ CodeLen=2+AdrCnt;
+ END
+ else if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[0]=Adr2Byte+(OpSize << 3);
+ memcpy(BAsmCode+1,Adr2Vals,Adr2Cnt);
+ if ((OpSize==0) OR ((ImmVal()>=-128) AND (ImmVal()<127)))
+ BEGIN
+ BAsmCode[1+Adr2Cnt]=0x06;
+ BAsmCode[2+Adr2Cnt]=AdrVals[OpSize];
+ CodeLen=3+Adr2Cnt;
+ END
+ else
+ BEGIN
+ BAsmCode[1+Adr2Cnt]=0x07;
+ memcpy(BAsmCode+2+Adr2Cnt,AdrVals,AdrCnt);
+ CodeLen=2+Adr2Cnt+AdrCnt;
+ END
+ END
+ else WrError(1350);
+ break;
+ case 2:
+ if ((AdrMode!=ModImm) OR (Adr2Mode!=ModReg)) WrError(1350);
+ else if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=0x50+(Adr2Byte & 7);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ break;
+ case 3:
+ if ((AdrMode!=ModImm) OR (Adr2Mode!=ModReg)) WrError(1350);
+ else if (OpSize!=1) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=0x58+(Adr2Byte & 7);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ break;
+ case 4:
+ if ((AdrMode==ModReg) AND (Adr2Byte==0xe6))
+ BEGIN
+ BAsmCode[0]=0x90+(OpSize << 3)+(AdrByte & 7);
+ memcpy(BAsmCode+1,Adr2Vals,Adr2Cnt);
+ CodeLen=1+Adr2Cnt;
+ END
+ else if ((Adr2Mode==ModReg) AND (AdrByte==0xe6))
+ BEGIN
+ BAsmCode[0]=0x80+(OpSize << 3)+(Adr2Byte & 7);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ else WrError(1350);
+ break;
+ case 5:
+ if ((AdrMode!=ModAbs8) OR (Adr2Mode!=ModReg)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x60+(OpSize << 3)+(Adr2Byte & 7);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ break;
+ case 6:
+ if ((Adr2Mode!=ModAbs8) OR (AdrMode!=ModReg)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x70+(OpSize << 3)+(AdrByte & 7);
+ memcpy(BAsmCode+1,Adr2Vals,Adr2Cnt);
+ CodeLen=1+Adr2Cnt;
+ END
+ break;
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDC")) OR (Memo("STC")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else
+ BEGIN
+ if (Memo("STC"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ END
+ if (NOT DecodeCReg(ArgStr[2],&HReg)) WrXError(1440,ArgStr[2]);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],(Memo("LDC"))?MModAll:MModNoImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=AdrByte+(OpSize << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x88+(Ord(Memo("STC")) << 4)+HReg;
+ CodeLen=2+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDM"))
+ BEGIN
+ if (OpSize==-1) OpSize=1;
+ if (ArgCnt!=2) WrError(1110);
+ else if (OpSize!=1) WrError(1130);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (NOT DecodeRegList(ArgStr[2],BAsmCode+1)) WrError(1410);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModPostInc);
+ if (AdrMode!=ModNone)
+ if ((AdrByte & 7)!=7) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x02; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if (Memo("STM"))
+ BEGIN
+ if (OpSize==-1) OpSize=1;
+ if (ArgCnt!=2) WrError(1110);
+ else if (OpSize!=1) WrError(1130);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (NOT DecodeRegList(ArgStr[1],BAsmCode+1)) WrError(1410);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModPredec);
+ if (AdrMode!=ModNone)
+ if ((AdrByte & 7)!=7) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x12; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MOVTPE")) OR (Memo("MOVFPE")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ if (Memo("MOVTPE"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[3]);
+ END
+ if (OpSize==-1) SetOpSize(0);
+ if (OpSize!=0) WrError(1130);
+ else if (NOT DecodeReg(ArgStr[2],&HReg)) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModNoImm-MModReg);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=AdrByte+(OpSize << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0;
+ BAsmCode[2+AdrCnt]=0x80+HReg+(Ord(Memo("MOVTPE")) << 4);
+ CodeLen=3+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik mit 2 Operanden */
+
+ if ((Memo("ADD")) OR (Memo("SUB")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GQ"))
+ BEGIN
+ if (OpSize==-1) SetOpSize(1);
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModNoImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CopyAdr();
+ DecodeAdr(ArgStr[1],MModAll);
+ if (AdrMode!=ModNone)
+ BEGIN
+ AdrLong=ImmVal();
+ if (FormatCode==0)
+ if ((AdrMode==ModImm) AND (abs(AdrLong)>=1) AND (abs(AdrLong)<=2)) FormatCode=2;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ if (Adr2Mode!=ModReg) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=AdrByte+(OpSize << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x20+(Ord(Memo("SUB")) << 4)+(Adr2Byte & 7);
+ CodeLen=2+AdrCnt;
+ END
+ break;
+ case 2:
+ if (ChkRange(AdrLong,-2,2))
+ if (AdrLong==0) WrError(1315);
+ else
+ BEGIN
+ if (Memo("SUB")) AdrLong=(-AdrLong);
+ BAsmCode[0]=Adr2Byte+(OpSize << 3);
+ memcpy(BAsmCode+1,Adr2Vals,Adr2Cnt);
+ BAsmCode[1+Adr2Cnt]=0x08+abs(AdrLong)-1;
+ if (AdrLong<0) BAsmCode[1+Adr2Cnt]+=4;
+ CodeLen=2+Adr2Cnt;
+ END
+ break;
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CMP"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GEI"))
+ BEGIN
+ if (OpSize==-1)
+ SetOpSize((FormatCode==2)?0:1);
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModNoImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ CopyAdr();
+ DecodeAdr(ArgStr[1],MModAll);
+ if (AdrMode!=ModNone)
+ BEGIN
+ if (FormatCode==0)
+ if ((AdrMode==ModImm) AND (Adr2Mode==ModReg)) FormatCode=2+OpSize;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ if (Adr2Mode==ModReg)
+ BEGIN
+ BAsmCode[0]=AdrByte+(OpSize << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=0x70+(Adr2Byte & 7);
+ CodeLen=2+AdrCnt;
+ END
+ else if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[0]=Adr2Byte+(OpSize << 3);
+ memcpy(BAsmCode+1,Adr2Vals,Adr2Cnt);
+ BAsmCode[1+Adr2Cnt]=0x04+OpSize;
+ memcpy(BAsmCode+2+Adr2Cnt,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt+Adr2Cnt;
+ END
+ else WrError(1350);
+ break;
+ case 2:
+ if ((AdrMode!=ModImm) OR (Adr2Mode!=ModReg)) WrError(1350);
+ else if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=0x40+(Adr2Byte & 7);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ break;
+ case 3:
+ if ((AdrMode!=ModImm) OR (Adr2Mode!=ModReg)) WrError(1350);
+ else if (OpSize!=1) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=0x48+(Adr2Byte & 7);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ break;
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<RegEAOrderCount; z++)
+ if (Memo(RegEAOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ if (OpSize==-1) SetOpSize(RegEAOrders[z].DefSize);
+ if (((1 << OpSize) & RegEAOrders[z].SizeMask)==0) WrError(1130);
+ else if (NOT DecodeReg(ArgStr[2],&HReg)) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAll);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=AdrByte+(OpSize << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=RegEAOrders[z].Code+HReg;
+ CodeLen=2+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<TwoRegOrderCount; z++)
+ if (Memo(TwoRegOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (NOT DecodeReg(ArgStr[1],&HReg)) WrError(1350);
+ else if (NOT DecodeReg(ArgStr[2],&AdrByte)) WrError(1350);
+ else
+ BEGIN
+ if (OpSize==-1) SetOpSize(TwoRegOrders[z].DefSize);
+ if (((1 << OpSize) & TwoRegOrders[z].SizeMask)==0) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=0xa0+HReg+(OpSize << 3);
+ if (Hi(TwoRegOrders[z].Code)!=0)
+ BEGIN
+ BAsmCode[1]=Lo(TwoRegOrders[z].Code);
+ BAsmCode[2]=Hi(TwoRegOrders[z].Code)+AdrByte;
+ CodeLen=3;
+ END
+ else
+ BEGIN
+ BAsmCode[1]=TwoRegOrders[z].Code+AdrByte;
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<LogOrderCount; z++)
+ if (Memo(LogOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeCReg(ArgStr[2],&HReg)) WrXError(1440,ArgStr[2]);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=AdrByte+(OpSize << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=LogOrders[z].Code+HReg;
+ CodeLen=2+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik mit einem Operanden */
+
+ for (z=0; z<OneOrderCount; z++)
+ if (Memo(OneOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ if (OpSize==-1) SetOpSize(OneOrders[z].DefSize);
+ if (((1 << OpSize) & OneOrders[z].SizeMask)==0) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModNoImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=AdrByte+(OpSize << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=OneOrders[z].Code;
+ CodeLen=2+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<OneRegOrderCount; z++)
+ if (Memo(OneRegOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (NOT DecodeReg(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ if (OpSize==-1) SetOpSize(OneRegOrders[z].DefSize);
+ if (((1 << OpSize) & OneRegOrders[z].SizeMask)==0) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=0xa0+HReg+(OpSize << 3);
+ BAsmCode[1]=OneRegOrders[z].Code;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ /* Bitoperationen */
+
+ for (z=0; z<BitOrderCount; z++)
+ if (Memo(BitOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (OpSize==-1) OpSize=0;
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModNoImm);
+ if (AdrMode!=ModNone)
+ BEGIN
+ if (DecodeReg(ArgStr[1],&HReg))
+ BEGIN
+ OK=True; HReg+=8;
+ END
+ else
+ BEGIN
+ if (*ArgStr[1]=='#') strcpy(ArgStr[1],ArgStr[1]+1);
+ HReg=EvalIntExpression(ArgStr[1],(OpSize==0)?UInt3:UInt4,&OK);
+ if (OK) HReg+=0x80;
+ END
+ if (OK)
+ BEGIN
+ BAsmCode[0]=AdrByte+(OpSize << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ BAsmCode[1+AdrCnt]=BitOrders[z].Code+HReg;
+ CodeLen=2+AdrCnt;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ for (z=0; z<RelOrderCount; z++)
+ if (Memo(RelOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ if (((AdrLong >> 16)!=(EProgCounter() >> 16)) AND
+ (NOT FirstPassUnknown) AND (NOT SymbolQuestionable)) WrError(1910);
+ else if ((EProgCounter() & 0xffff)>=0xfffc) WrError(1905);
+ else
+ BEGIN
+ AdrLong-=EProgCounter()+2;
+ if (AdrLong>0x7fff) AdrLong-=0x10000;
+ else if (AdrLong<-0x8000l) AdrLong+=0x10000;
+ if (OpSize==-1)
+ if ((AdrLong<=127) AND (AdrLong>=-128)) OpSize=4;
+ else OpSize=2;
+ switch (OpSize)
+ BEGIN
+ case 2:
+ AdrLong--;
+ BAsmCode[0]=RelOrders[z].Code+0x10;
+ BAsmCode[1]=(AdrLong >> 8) & 0xff;
+ BAsmCode[2]=AdrLong & 0xff;
+ CodeLen=3;
+ break;
+ case 4:
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=RelOrders[z].Code;
+ BAsmCode[1]=AdrLong & 0xff;
+ CodeLen=2;
+ END
+ break;
+ default:
+ WrError(1130);
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JMP")) OR (Memo("JSR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ AbsBank=EProgCounter() >> 16;
+ HReg=Ord(Memo("JSR")) << 3;
+ DecodeAdr(ArgStr[1],MModIReg+MModReg+MModDisp8+MModDisp16+MModAbs16);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModIReg:
+ BAsmCode[0]=0x11; BAsmCode[1]=0xd0+HReg+(AdrByte & 7);
+ CodeLen=2;
+ break;
+ case ModDisp8:
+ case ModDisp16:
+ BAsmCode[0]=0x11; BAsmCode[1]=AdrByte+HReg;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ case ModAbs16:
+ BAsmCode[0]=0x10+HReg; memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ break;
+ END
+ END
+ return;
+ END
+
+ if (strncmp(OpPart,"SCB/",4)==0)
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (NOT DecodeReg(ArgStr[1],&HReg)) WrError(1350);
+ else
+ BEGIN
+ strmaxcpy(ArgStr[3],OpPart+4,255);
+ OK=True; NLS_UpString(ArgStr[3]);
+ if (strcmp(ArgStr[3],"F")==0) BAsmCode[0]=0x01;
+ else if (strcmp(ArgStr[3],"NE")==0) BAsmCode[0]=0x06;
+ else if (strcmp(ArgStr[3],"EQ")==0) BAsmCode[0]=0x07;
+ else OK=False;
+ if (NOT OK) WrError(1360);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(ArgStr[2],UInt24,&OK);
+ if (OK)
+ if (((AdrLong >> 16)!=(EProgCounter() >> 16)) AND
+ (NOT FirstPassUnknown) AND (NOT SymbolQuestionable)) WrError(1910);
+ else if ((EProgCounter() & 0xffff)>=0xfffc) WrError(1905);
+ else
+ BEGIN
+ AdrLong-=EProgCounter()+3;
+ if ((NOT SymbolQuestionable) AND ((AdrLong>127) OR (AdrLong<-128))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[1]=0xb8+HReg;
+ BAsmCode[2]=AdrLong & 0xff;
+ CodeLen=3;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PJMP")) OR (Memo("PJSR")))
+ BEGIN
+ z=Ord(Memo("PJMP"));
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (NOT Maximum) WrError(1997);
+ else
+ BEGIN
+ if (*ArgStr[1]=='@') strcpy(ArgStr[1],ArgStr[1]+1);
+ if (DecodeReg(ArgStr[1],&HReg))
+ BEGIN
+ BAsmCode[0]=0x11; BAsmCode[1]=0xc0+((1-z) << 3)+HReg;
+ CodeLen=2;
+ END
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x03+(z << 4);
+ BAsmCode[1]=(AdrLong >> 16) & 0xff;
+ BAsmCode[2]=(AdrLong >> 8) & 0xff;
+ BAsmCode[3]=AdrLong & 0xff;
+ CodeLen=4;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PRTD")) OR (Memo("RTD")))
+ BEGIN
+ HReg=Ord(Memo("PRTD"));
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ strcpy(ArgStr[1],ArgStr[1]+1);
+ HSize=(-1); SplitDisp(ArgStr[1],&HSize);
+ if (HSize!=-1) SetOpSize(HSize);
+ FirstPassUnknown=False;
+ AdrInt=EvalIntExpression(ArgStr[1],SInt16,&OK);
+ if (FirstPassUnknown) AdrInt&=127;
+ if (OK)
+ BEGIN
+ if (OpSize==-1)
+ if ((AdrInt<127) AND (AdrInt>-128)) OpSize=0;
+ else OpSize=1;
+ if (Memo("PRTD")) BAsmCode[0]=0x11;
+ switch (OpSize)
+ BEGIN
+ case 0:
+ if (ChkRange(AdrInt,-128,127))
+ BEGIN
+ BAsmCode[HReg]=0x14; BAsmCode[1+HReg]=AdrInt & 0xff;
+ CodeLen=2+HReg;
+ END
+ break;
+ case 1:
+ BAsmCode[HReg]=0x1c;
+ BAsmCode[1+HReg]=(AdrInt >> 8) & 0xff;
+ BAsmCode[2+HReg]=AdrInt & 0xff;
+ CodeLen=3+HReg;
+ break;
+ default:
+ WrError(1130);
+ END
+ END
+ END
+ return;
+ END
+
+ /* Sonderfaelle */
+
+ if (Memo("LINK"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ if ((AdrByte & 7)!=6) WrError(1350);
+ else if (*ArgStr[2]!='#') WrError(1120);
+ else
+ BEGIN
+ strcpy(ArgStr[2],ArgStr[2]+1);
+ HSize=(-1); SplitDisp(ArgStr[2],&HSize);
+ if (HSize!=-1) SetOpSize(HSize);
+ FirstPassUnknown=False;
+ AdrInt=EvalIntExpression(ArgStr[2],SInt16,&OK);
+ if (FirstPassUnknown) AdrInt&=127;
+ if (OK)
+ BEGIN
+ if (OpSize==-1)
+ if ((AdrInt<127) AND (AdrInt>-128)) OpSize=0;
+ else OpSize=1;
+ switch (OpSize)
+ BEGIN
+ case 0:
+ if (ChkRange(AdrInt,-128,127))
+ BEGIN
+ BAsmCode[0]=0x17; BAsmCode[1]=AdrInt & 0xff;
+ CodeLen=2;
+ END
+ break;
+ case 1:
+ BAsmCode[0]=0x1f;
+ BAsmCode[1]=(AdrInt >> 8) & 0xff;
+ BAsmCode[2]=AdrInt & 0xff;
+ CodeLen=3;
+ break;
+ default:
+ WrError(1130);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("UNLK"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ if ((AdrByte & 7)!=6) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x0f; CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("TRAPA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ BAsmCode[1]=0x10+EvalIntExpression(ArgStr[1]+1,UInt4,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x08; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean ChkPC_H8_5(LargeWord Addr)
+BEGIN
+ if (ActPC==SegCode)
+ return (Addr<(Maximum?0x1000000:0x10000));
+ else return False;
+END
+
+ static Boolean IsDef_H8_5(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_H8_5(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void InitCode_H8_5(void)
+BEGIN
+ SaveInitProc();
+ Reg_DP=(-1);
+ Reg_EP=(-1);
+ Reg_TP=(-1);
+ Reg_BR=(-1);
+END
+
+ static void SwitchTo_H8_5(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x69; NOPCode=0x00;
+ DivideChars=","; HasAttrs=True; AttrChars=".:";
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+
+ MakeCode=MakeCode_H8_5; ChkPC=ChkPC_H8_5; IsDef=IsDef_H8_5;
+ SwitchFrom=SwitchFrom_H8_5; InitFields();
+ AddONOFF("MAXMODE", &Maximum , MaximumName ,False);
+ AddMoto16PseudoONOFF();
+
+ SetFlag(&DoPadding,DoPaddingName,False);
+END
+
+ void codeh8_5_init(void)
+BEGIN
+ CPU532=AddCPU("HD6475328",SwitchTo_H8_5);
+ CPU534=AddCPU("HD6475348",SwitchTo_H8_5);
+ CPU536=AddCPU("HD6475368",SwitchTo_H8_5);
+ CPU538=AddCPU("HD6475388",SwitchTo_H8_5);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_H8_5;
+END
diff --git a/codeh8_5.h b/codeh8_5.h
new file mode 100644
index 0000000..f302fe5
--- /dev/null
+++ b/codeh8_5.h
@@ -0,0 +1,11 @@
+/* codeh8_5.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator H8/500-Familie */
+/* */
+/* Historie: 24.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codeh8_5_init(void);
diff --git a/codem16.c b/codem16.c
new file mode 100644
index 0000000..f0197a8
--- /dev/null
+++ b/codem16.c
@@ -0,0 +1,2819 @@
+/* codem16.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Mitsubishi M16 */
+/* */
+/* Historie: 27.12.1996 Grundsteinlegung */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+#include <ctype.h>
+
+#include "bpemu.h"
+#include "nls.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModIReg 1
+#define MModIReg (1 << ModIReg)
+#define ModDisp16 2
+#define MModDisp16 (1 << ModDisp16)
+#define ModDisp32 3
+#define MModDisp32 (1 << ModDisp32)
+#define ModImm 4
+#define MModImm (1 << ModImm)
+#define ModAbs16 5
+#define MModAbs16 (1 << ModAbs16)
+#define ModAbs32 6
+#define MModAbs32 (1 << ModAbs32)
+#define ModPCRel16 7
+#define MModPCRel16 (1 << ModPCRel16)
+#define ModPCRel32 8
+#define MModPCRel32 (1 << ModPCRel32)
+#define ModPop 9
+#define MModPop (1 << ModPop)
+#define ModPush 10
+#define MModPush (1 << ModPush)
+#define ModRegChain 11
+#define MModRegChain (1 << ModRegChain)
+#define ModPCChain 12
+#define MModPCChain (1 << ModPCChain)
+#define ModAbsChain 13
+#define MModAbsChain (1 << ModAbsChain)
+
+#define Mask_RegOnly (MModReg)
+#define Mask_AllShort (MModReg+MModIReg+MModDisp16+MModImm+MModAbs16+MModAbs32+MModPCRel16+MModPCRel32+MModPop+MModPush+MModPCChain+MModAbsChain)
+#define Mask_AllGen (Mask_AllShort+MModDisp32+MModRegChain)
+#define Mask_NoImmShort (Mask_AllShort-MModImm)
+#define Mask_NoImmGen (Mask_AllGen-MModImm)
+#define Mask_MemShort (Mask_NoImmShort-MModReg)
+#define Mask_MemGen (Mask_NoImmGen-MModReg)
+
+#define Mask_Source (Mask_AllGen-MModPush)
+#define Mask_Dest (Mask_NoImmGen-MModPop)
+#define Mask_PureDest (Mask_NoImmGen-MModPush-MModPop)
+#define Mask_PureMem (Mask_MemGen-MModPush-MModPop)
+
+#define FixedOrderCount 7
+#define OneOrderCount 13
+#define GE2OrderCount 11
+#define BitOrderCount 6
+#define GetPutOrderCount 8
+#define BFieldOrderCount 4
+#define MulOrderCount 4
+#define ConditionCount 14
+#define LogOrderCount 3
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Mask;
+ Byte OpMask;
+ Word Code;
+ } OneOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Mask1,Mask2;
+ Word SMask1,SMask2;
+ Word Code;
+ Boolean Signed;
+ } GE2Order;
+
+typedef struct
+ {
+ char *Name;
+ Boolean MustByte;
+ Word Code1,Code2;
+ } BitOrder;
+
+typedef struct
+ {
+ char *Name;
+ ShortInt Size;
+ Word Code;
+ Boolean Turn;
+ } GetPutOrder;
+
+
+static CPUVar CPUM16;
+
+static String Format;
+static Byte FormatCode;
+static ShortInt DOpSize,OpSize[5];
+static Word AdrMode[5];
+static ShortInt AdrType[5];
+static Byte AdrCnt1[5],AdrCnt2[5];
+static Word AdrVals[5][8];
+
+static Byte OptionCnt;
+static char Options[2][5];
+
+static FixedOrder *FixedOrders;
+static OneOrder *OneOrders;
+static GE2Order *GE2Orders;
+static BitOrder *BitOrders;
+static GetPutOrder *GetPutOrders;
+static char **BFieldOrders;
+static char **MulOrders;
+static char **Conditions;
+static char **LogOrders;
+
+/*------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddOne(char *NName, Byte NOpMask, Word NMask, Word NCode)
+BEGIN
+ if (InstrZ>=OneOrderCount) exit(255);
+ OneOrders[InstrZ].Name=NName;
+ OneOrders[InstrZ].Code=NCode;
+ OneOrders[InstrZ].Mask=NMask;
+ OneOrders[InstrZ++].OpMask=NOpMask;
+END
+
+ static void AddGE2(char *NName, Word NMask1, Word NMask2,
+ Byte NSMask1, Byte NSMask2, Word NCode,
+ Boolean NSigned)
+BEGIN
+ if (InstrZ>=GE2OrderCount) exit(255);
+ GE2Orders[InstrZ].Name=NName;
+ GE2Orders[InstrZ].Mask1=NMask1;
+ GE2Orders[InstrZ].Mask2=NMask2;
+ GE2Orders[InstrZ].SMask1=NSMask1;
+ GE2Orders[InstrZ].SMask2=NSMask2;
+ GE2Orders[InstrZ].Code=NCode;
+ GE2Orders[InstrZ++].Signed=NSigned;
+END
+
+ static void AddBit(char *NName, Boolean NMust, Word NCode1, Word NCode2)
+BEGIN
+ if (InstrZ>=BitOrderCount) exit(255);
+ BitOrders[InstrZ].Name=NName;
+ BitOrders[InstrZ].Code1=NCode1;
+ BitOrders[InstrZ].Code2=NCode2;
+ BitOrders[InstrZ++].MustByte=NMust;
+END
+
+ static void AddGetPut(char *NName, Byte NSize, Word NCode, Boolean NTurn)
+BEGIN
+ if (InstrZ>=GetPutOrderCount) exit(255);
+ GetPutOrders[InstrZ].Name=NName;
+ GetPutOrders[InstrZ].Code=NCode;
+ GetPutOrders[InstrZ].Turn=NTurn;
+ GetPutOrders[InstrZ++].Size=NSize;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ AddFixed("NOP" ,0x1bd6); AddFixed("PIB" ,0x0bd6);
+ AddFixed("RIE" ,0x08f7); AddFixed("RRNG" ,0x3bd6);
+ AddFixed("RTS" ,0x2bd6); AddFixed("STCTX",0x07d6);
+ AddFixed("REIT" ,0x2fd6);
+
+ OneOrders=(OneOrder *) malloc(sizeof(OneOrder)*OneOrderCount); InstrZ=0;
+ AddOne("ACS" ,0x00,Mask_PureMem, 0x8300);
+ AddOne("NEG" ,0x07,Mask_PureDest, 0xc800);
+ AddOne("NOT" ,0x07,Mask_PureDest, 0xcc00);
+ AddOne("JMP" ,0x00,Mask_PureMem, 0x8200);
+ AddOne("JSR" ,0x00,Mask_PureMem, 0xaa00);
+ AddOne("LDCTX" ,0x00,MModIReg+MModDisp16+MModDisp32+
+ MModAbs16+MModAbs32+MModPCRel16+MModPCRel32, 0x8600);
+ AddOne("LDPSB" ,0x02,Mask_Source, 0xdb00);
+ AddOne("LDPSM" ,0x02,Mask_Source, 0xdc00);
+ AddOne("POP" ,0x04,Mask_PureDest, 0x9000);
+ AddOne("PUSH" ,0x04,Mask_Source-MModPop, 0xb000);
+ AddOne("PUSHA" ,0x00,Mask_PureMem, 0xa200);
+ AddOne("STPSB" ,0x02,Mask_Dest, 0xdd00);
+ AddOne("STPSM" ,0x02,Mask_Dest, 0xde00);
+
+ GE2Orders=(GE2Order *) malloc(sizeof(GE2Order)*GE2OrderCount); InstrZ=0;
+ AddGE2("ADDU" ,Mask_Source,Mask_PureDest,7,7,0x0400,False);
+ AddGE2("ADDX" ,Mask_Source,Mask_PureDest,7,7,0x1000,True );
+ AddGE2("SUBU" ,Mask_Source,Mask_PureDest,7,7,0x0c00,False);
+ AddGE2("SUBX" ,Mask_Source,Mask_PureDest,7,7,0x1800,True );
+ AddGE2("CMPU" ,Mask_Source,Mask_PureDest,7,7,0x8400,False);
+ AddGE2("LDC" ,Mask_Source,Mask_PureDest,7,4,0x9800,True );
+ AddGE2("LDP" ,Mask_Source,Mask_PureMem ,7,7,0x9c00,True );
+ AddGE2("MOVU" ,Mask_Source,Mask_Dest ,7,7,0x8c00,True );
+ AddGE2("REM" ,Mask_Source,Mask_PureDest,7,7,0x5800,True );
+ AddGE2("REMU" ,Mask_Source,Mask_PureDest,7,7,0x5c00,True );
+ AddGE2("ROT" ,Mask_Source,Mask_PureDest,1,7,0x3800,True );
+
+ BitOrders=(BitOrder *) malloc(sizeof(BitOrder)*BitOrderCount); InstrZ=0;
+ AddBit("BCLR" ,False,0xb400,0xa180);
+ AddBit("BCLRI",True ,0xa400,0x0000);
+ AddBit("BNOT" ,False,0xb800,0x0000);
+ AddBit("BSET" ,False,0xb000,0x8180);
+ AddBit("BSETI",True ,0xa000,0x81c0);
+ AddBit("BTST" ,False,0xbc00,0xa1c0);
+
+ GetPutOrders=(GetPutOrder *) malloc(sizeof(GetPutOrder)*GetPutOrderCount); InstrZ=0;
+ AddGetPut("GETB0",0,0xc000,False);
+ AddGetPut("GETB1",0,0xc400,False);
+ AddGetPut("GETB2",0,0xc800,False);
+ AddGetPut("GETH0",1,0xcc00,False);
+ AddGetPut("PUTB0",0,0xd000,True );
+ AddGetPut("PUTB1",0,0xd400,True );
+ AddGetPut("PUTB2",0,0xd800,True );
+ AddGetPut("PUTH0",1,0xdc00,True );
+
+ BFieldOrders=(char **) malloc(sizeof(char *)*BFieldOrderCount); InstrZ=0;
+ BFieldOrders[InstrZ++]="BFCMP"; BFieldOrders[InstrZ++]="BFCMPU";
+ BFieldOrders[InstrZ++]="BFINS"; BFieldOrders[InstrZ++]="BFINSU";
+
+ MulOrders=(char **) malloc(sizeof(char *)*MulOrderCount); InstrZ=0;
+ MulOrders[InstrZ++]="MUL"; MulOrders[InstrZ++]="MULU";
+ MulOrders[InstrZ++]="DIV"; MulOrders[InstrZ++]="DIVU";
+
+ Conditions=(char **) malloc(sizeof(char *)*ConditionCount); InstrZ=0;
+ Conditions[InstrZ++]="XS"; Conditions[InstrZ++]="XC";
+ Conditions[InstrZ++]="EQ"; Conditions[InstrZ++]="NE";
+ Conditions[InstrZ++]="LT"; Conditions[InstrZ++]="GE";
+ Conditions[InstrZ++]="LE"; Conditions[InstrZ++]="GT";
+ Conditions[InstrZ++]="VS"; Conditions[InstrZ++]="VC";
+ Conditions[InstrZ++]="MS"; Conditions[InstrZ++]="MC";
+ Conditions[InstrZ++]="FS"; Conditions[InstrZ++]="FC";
+
+ LogOrders=(char **) malloc(sizeof(char *)*LogOrderCount); InstrZ=0;
+ LogOrders[InstrZ++]="AND"; LogOrders[InstrZ]="OR"; LogOrders[InstrZ++]="XOR";
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(OneOrders);
+ free(GE2Orders);
+ free(BitOrders);
+ free(GetPutOrders);
+ free(BFieldOrders);
+ free(MulOrders);
+ free(Conditions);
+ free(LogOrders);
+END
+
+/*------------------------------------------------------------------------*/
+
+typedef enum {DispSizeNone,DispSize4,DispSize4Eps,DispSize16,DispSize32} DispSize;
+typedef struct _TChainRec
+ {
+ struct _TChainRec *Next;
+ Byte RegCnt;
+ Word Regs[5],Scales[5];
+ LongInt DispAcc;
+ Boolean HasDisp;
+ DispSize DSize;
+ } *PChainRec,TChainRec;
+static Boolean ErrFlag;
+
+
+ static Boolean IsD4(LongInt inp)
+BEGIN
+ return ((inp>=-32) AND (inp<=28));
+END
+
+ static Boolean IsD16(LongInt inp)
+BEGIN
+ return ((inp>=-0x8000) AND (inp<=0x7fff));
+END
+
+ static Boolean DecodeReg(char *Asc, Word *Erg)
+BEGIN
+ Boolean IO;
+
+ if (strcasecmp(Asc,"SP")==0) *Erg=15;
+ else if (strcasecmp(Asc,"FP")==0) *Erg=14;
+ else if ((strlen(Asc)>1) AND (toupper(*Asc)=='R'))
+ BEGIN
+ *Erg=ConstLongInt(Asc+1,&IO);
+ return ((IO) AND (*Erg<=15));
+ END
+ else return False;
+ return True;
+END
+
+ static void SplitSize(char *s, DispSize *Erg)
+BEGIN
+ int l=strlen(s);
+
+ if ((l>2) AND (s[l-1]=='4') AND (s[l-2]==':'))
+ BEGIN
+ *Erg=DispSize4;
+ s[l-2]='\0';
+ END
+ else if ((l>3) AND (s[l-1]=='6') AND (s[l-2]=='1') AND (s[l-3]==':'))
+ BEGIN
+ *Erg=DispSize16;
+ s[l-3]='\0';
+ END
+ else if ((l>3) AND (s[l-1]=='2') AND (s[l-2]=='3') AND (s[l-3]==':'))
+ BEGIN
+ *Erg=DispSize32;
+ s[l-3]='\0';
+ END
+END
+
+ static void DecideAbs(LongInt Disp, DispSize Size, Word Mask, int Index)
+BEGIN
+ switch (Size)
+ BEGIN
+ case DispSize4:
+ Size=DispSize16; break;
+ case DispSizeNone:
+ if ((IsD16(Disp)) AND ((Mask & MModAbs16)!=0)) Size=DispSize16;
+ else Size=DispSize32;
+ break;
+ default:
+ break;
+ END
+
+ switch (Size)
+ BEGIN
+ case DispSize16:
+ if (ChkRange(Disp,-0x8000,0x7fff))
+ BEGIN
+ AdrType[Index]=ModAbs16; AdrMode[Index]=0x09;
+ AdrVals[Index][0]=Disp & 0xffff; AdrCnt1[Index]=2;
+ END
+ break;
+ case DispSize32:
+ AdrType[Index]=ModAbs32; AdrMode[Index]=0x0a;
+ AdrVals[Index][0]=Disp >> 16;
+ AdrVals[Index][1]=Disp & 0xffff; AdrCnt1[Index]=4;
+ break;
+ default:
+ WrError(10000);
+ END
+END
+
+ static void SetError(Word Code)
+BEGIN
+ WrError(Code); ErrFlag=True;
+END
+
+ static PChainRec DecodeChain(char *Asc)
+BEGIN
+ PChainRec Rec;
+ String Part,SReg;
+ int z;
+ char *p;
+ Boolean OK;
+ Byte Scale;
+
+ ChkStack();
+ Rec=(PChainRec) malloc(sizeof(TChainRec));
+ Rec->Next=Nil; Rec->RegCnt=0; Rec->DispAcc=0; Rec->HasDisp=False;
+ Rec->DSize=DispSizeNone;
+
+ while ((*Asc!='\0') AND (NOT ErrFlag))
+ BEGIN
+
+ /* eine Komponente abspalten */
+
+ p=QuotPos(Asc,',');
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Part,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(Part,Asc,255); strcpy(Asc,p+1);
+ END
+
+ strcpy(SReg,Part); p=QuotPos(SReg,'*'); if (p!=Nil) *p='\0';
+
+ /* weitere Indirektion ? */
+
+ if (*Part=='@')
+ if (Rec->Next!=Nil) SetError(1350);
+ else
+ BEGIN
+ strcpy(Part,Part+1);
+ if (IsIndirect(Part))
+ BEGIN
+ strcpy(Part,Part+1); Part[strlen(Part)-1]='\0';
+ END
+ Rec->Next=DecodeChain(Part);
+ END
+
+ /* Register, mit Skalierungsfaktor ? */
+
+ else if (DecodeReg(SReg,Rec->Regs+Rec->RegCnt))
+ BEGIN
+ if (Rec->RegCnt>=5) SetError(1350);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ if (p==Nil)
+ BEGIN
+ OK=True; Scale=1;
+ END
+ else Scale=EvalIntExpression(p+1,UInt4,&OK);
+ if (FirstPassUnknown) Scale=1;
+ if (NOT OK) ErrFlag=True;
+ else if ((Scale!=1) AND (Scale!=2) AND (Scale!=4) AND (Scale!=8)) SetError(1350);
+ else
+ BEGIN
+ Rec->Scales[Rec->RegCnt]=0;
+ while (Scale>1)
+ BEGIN
+ Rec->Scales[Rec->RegCnt]++; Scale=Scale >> 1;
+ END
+ Rec->RegCnt++;
+ END
+ END
+ END
+
+ /* PC, mit Skalierungsfaktor ? */
+
+ else if (strcasecmp(SReg,"PC")==0)
+ BEGIN
+ if (Rec->RegCnt>=5) SetError(1350);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ if (p==Nil)
+ BEGIN
+ OK=True; Scale=1;
+ END
+ else Scale=EvalIntExpression(p+1,UInt4,&OK);
+ if (FirstPassUnknown) Scale=1;
+ if (NOT OK) ErrFlag=True;
+ else if ((Scale!=1) AND (Scale!=2) AND (Scale!=4) AND (Scale!=8)) SetError(1350);
+ else
+ BEGIN
+ for (z=Rec->RegCnt-1; z>=0; z--)
+ BEGIN
+ Rec->Regs[z+1]=Rec->Regs[z];
+ Rec->Scales[z+1]=Rec->Scales[z];
+ END
+ Rec->Scales[0]=0;
+ while (Scale>1)
+ BEGIN
+ Rec->Scales[0]++; Scale=Scale >> 1;
+ END
+ Rec->Regs[0]=16;
+ Rec->RegCnt++;
+ END
+ END
+ END
+
+ /* ansonsten Displacement */
+
+ else
+ BEGIN
+ SplitSize(Part,&(Rec->DSize));
+ Rec->DispAcc+=EvalIntExpression(Part,Int32,&OK);
+ if (NOT OK) ErrFlag=True;
+ Rec->HasDisp=True;
+ END
+ END
+
+ if (ErrFlag)
+ BEGIN
+ free(Rec); return Nil;
+ END
+ else return Rec;
+END
+
+ static Boolean ChkAdr(Word Mask, int Index)
+BEGIN
+ AdrCnt2[Index]=AdrCnt1[Index] >> 1;
+ if ((AdrType[Index]!=-1) AND ((Mask & (1 << AdrType[Index]))==0))
+ BEGIN
+ AdrCnt1[Index]=AdrCnt2[Index]=0;
+ AdrType[Index]=ModNone;
+ WrError(1350);
+ return False;
+ END
+ else return (AdrType[Index]!=ModNone);
+END
+
+ static Boolean DecodeAdr(char *Asc, int Index, Word Mask)
+BEGIN
+ LongInt AdrLong,MinReserve,MaxReserve;
+ int z,z2,LastChain;
+ Boolean OK;
+ PChainRec RootChain,RunChain,PrevChain;
+ DispSize DSize;
+
+ AdrCnt1[Index]=0; AdrType[Index]=ModNone;
+
+ /* Register ? */
+
+ if (DecodeReg(Asc,AdrMode+Index))
+ BEGIN
+ AdrType[Index]=ModReg; AdrMode[Index]+=0x10; return ChkAdr(Mask,Index);
+ END
+
+ /* immediate ? */
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize[Index])
+ BEGIN
+ case -1:
+ WrError(1132); OK=False;
+ break;
+ case 0:
+ AdrVals[Index][0]=EvalIntExpression(Asc+1,Int8,&OK) & 0xff;
+ if (OK) AdrCnt1[Index]=2;
+ break;
+ case 1:
+ AdrVals[Index][0]=EvalIntExpression(Asc+1,Int16,&OK);
+ if (OK) AdrCnt1[Index]=2;
+ break;
+ case 2:
+ AdrLong=EvalIntExpression(Asc+1,Int32,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[Index][0]=AdrLong >> 16;
+ AdrVals[Index][1]=AdrLong & 0xffff;
+ AdrCnt1[Index]=4;
+ END
+ break;
+ END
+ if (OK)
+ BEGIN
+ AdrType[Index]=ModImm; AdrMode[Index]=0x0c;
+ END
+ return ChkAdr(Mask,Index);
+ END
+
+ /* indirekt ? */
+
+ if (*Asc=='@')
+ BEGIN
+ strcpy(Asc,Asc+1);
+ if (IsIndirect(Asc))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ END
+
+ /* Stack Push ? */
+
+ if ((strcasecmp(Asc,"-R15")==0) OR (strcasecmp(Asc,"-SP")==0))
+ BEGIN
+ AdrType[Index]=ModPush; AdrMode[Index]=0x05;
+ return ChkAdr(Mask,Index);
+ END
+
+ /* Stack Pop ? */
+
+ if ((strcasecmp(Asc,"R15+")==0) OR (strcasecmp(Asc,"SP+")==0))
+ BEGIN
+ AdrType[Index]=ModPop; AdrMode[Index]=0x04;
+ return ChkAdr(Mask,Index);
+ END
+
+ /* Register einfach indirekt ? */
+
+ if (DecodeReg(Asc,AdrMode+Index))
+ BEGIN
+ AdrType[Index]=ModIReg; AdrMode[Index]+=0x30;
+ return ChkAdr(Mask,Index);
+ END
+
+ /* zusammengesetzt indirekt ? */
+
+ ErrFlag=False;
+ RootChain=DecodeChain(Asc);
+
+ if (ErrFlag);
+
+ else if (RootChain==Nil);
+
+ /* absolut ? */
+
+ else if ((RootChain->Next==Nil) AND (RootChain->RegCnt==0))
+ BEGIN
+ if (NOT RootChain->HasDisp) RootChain->DispAcc=0;
+ DecideAbs(RootChain->DispAcc,RootChain->DSize,Mask,Index);
+ free(RootChain);
+ END
+
+ /* einfaches Register/PC mit Displacement ? */
+
+ else if ((RootChain->Next==Nil) AND (RootChain->RegCnt==1) AND (RootChain->Scales[0]==0))
+ BEGIN
+ if (RootChain->Regs[0]==16) RootChain->DispAcc-=EProgCounter();
+
+ /* Displacement-Groesse entscheiden */
+
+ if (RootChain->DSize==DispSizeNone)
+ if ((RootChain->DispAcc==0) AND (RootChain->Regs[0]<16));
+ else if (IsD16(RootChain->DispAcc))
+ RootChain->DSize=DispSize16;
+ else RootChain->DSize=DispSize32;
+
+ switch (RootChain->DSize)
+ BEGIN
+
+ /* kein Displacement mit Register */
+
+ case DispSizeNone:
+ if (ChkRange(RootChain->DispAcc,0,0))
+ if (RootChain->Regs[0]>=16) WrError(1350);
+ else
+ BEGIN
+ AdrType[Index]=ModIReg;
+ AdrMode[Index]=0x30+RootChain->Regs[0];
+ END
+ break;
+
+ /* 16-Bit-Displacement */
+
+ case DispSize4:
+ case DispSize16:
+ if (ChkRange(RootChain->DispAcc,-0x8000,0x7fff))
+ BEGIN
+ AdrVals[Index][0]=RootChain->DispAcc & 0xffff; AdrCnt1[Index]=2;
+ if (RootChain->Regs[0]==16)
+ BEGIN
+ AdrType[Index]=ModPCRel16; AdrMode[Index]=0x0d;
+ END
+ else
+ BEGIN
+ AdrType[Index]=ModDisp16; AdrMode[Index]=0x20+RootChain->Regs[0];
+ END
+ END
+ break;
+
+ /* 32-Bit-Displacement */
+
+ default:
+ AdrVals[Index][1]=RootChain->DispAcc & 0xffff;
+ AdrVals[Index][0]=RootChain->DispAcc >> 16; AdrCnt1[Index]=4;
+ if (RootChain->Regs[0]==16)
+ BEGIN
+ AdrType[Index]=ModPCRel32; AdrMode[Index]=0x0e;
+ END
+ else
+ BEGIN
+ AdrType[Index]=ModDisp32; AdrMode[Index]=0x40+RootChain->Regs[0];
+ END
+ END
+
+ free(RootChain);
+ END
+
+ /* komplex: dann chained iterieren */
+
+ else
+ BEGIN
+ /* bis zum innersten Element der Indirektion als Basis laufen */
+
+ RunChain=RootChain;
+ while (RunChain->Next!=Nil) RunChain=RunChain->Next;
+
+ /* Entscheidung des Basismodus: die Basis darf nicht skaliert
+ sein, und wenn ein Modus nicht erlaubt ist, muessen wir mit
+ Base-none anfangen... */
+
+ z=0; while ((z<RunChain->RegCnt) AND (RunChain->Scales[z]!=0)) z++;
+ if (z>=RunChain->RegCnt)
+ BEGIN
+ AdrType[Index]=ModAbsChain; AdrMode[Index]=0x0b;
+ END
+ else
+ BEGIN
+ if (RunChain->Regs[z]==16)
+ BEGIN
+ AdrType[Index]=ModPCChain; AdrMode[Index]=0x0f;
+ RunChain->DispAcc-=EProgCounter();
+ END
+ else
+ BEGIN
+ AdrType[Index]=ModRegChain;
+ AdrMode[Index]=0x60+RunChain->Regs[z];
+ END
+ for (z2=z; z2<=RunChain->RegCnt-2; z2++)
+ BEGIN
+ RunChain->Regs[z2]=RunChain->Regs[z2+1];
+ RunChain->Scales[z2]=RunChain->Scales[z2+1];
+ END
+ RunChain->RegCnt--;
+ END;
+
+ /* Jetzt ueber die einzelnen Komponenten iterieren */
+
+ LastChain=0;
+ while (RootChain!=Nil)
+ BEGIN
+ RunChain=RootChain; PrevChain=Nil;
+ while (RunChain->Next!=Nil)
+ BEGIN
+ PrevChain=RunChain;
+ RunChain=RunChain->Next;
+ END;
+
+ /* noch etwas abzulegen ? */
+
+ if ((RunChain->RegCnt!=0) OR (RunChain->HasDisp))
+ BEGIN
+ LastChain=AdrCnt1[Index] >> 1;
+
+ /* Register ablegen */
+
+ if (RunChain->RegCnt!=0)
+ BEGIN
+ if (RunChain->Regs[0]==16) AdrVals[Index][LastChain]=0x0600;
+ else AdrVals[Index][LastChain]=RunChain->Regs[0] << 10;
+ AdrVals[Index][LastChain]+=RunChain->Scales[0] << 5;
+ for (z2=0; z2<=RunChain->RegCnt-2; z2++)
+ BEGIN
+ RunChain->Regs[z2]=RunChain->Regs[z2+1];
+ RunChain->Scales[z2]=RunChain->Scales[z2+1];
+ END
+ RunChain->RegCnt--;
+ END
+ else AdrVals[Index][LastChain]=0x0200;
+ AdrCnt1[Index]+=2;
+
+ /* Displacement ablegen */
+
+ if (RunChain->HasDisp)
+ BEGIN
+ if ((AdrVals[Index][LastChain] & 0x3e00)==0x0600)
+ RunChain->DispAcc-=EProgCounter();
+
+ if (RunChain->DSize==DispSizeNone)
+ BEGIN
+ MinReserve=32*RunChain->RegCnt; MaxReserve=28*RunChain->RegCnt;
+ if (IsD4(RunChain->DispAcc))
+ if ((RunChain->DispAcc & 3)==0) DSize=DispSize4;
+ else DSize=DispSize16;
+ else if ((RunChain->DispAcc>=-32-MinReserve) AND
+ (RunChain->DispAcc<=28+MaxReserve)) DSize=DispSize4Eps;
+ else if (IsD16(RunChain->DispAcc)) DSize=DispSize16;
+ else if ((RunChain->DispAcc>=-0x8000-MinReserve) AND
+ (RunChain->DispAcc<=0x7fff+MaxReserve)) DSize=DispSize4Eps;
+ else DSize=DispSize32;
+ END
+ else DSize=RunChain->DSize;
+ RunChain->DSize=DispSizeNone;
+
+ switch (DSize)
+ BEGIN
+
+ /* Fall 1: passt komplett in 4er-Displacement */
+
+ case DispSize4:
+ if (ChkRange(RunChain->DispAcc,-32,28))
+ if ((RunChain->DispAcc & 3)!=0) WrError(1325);
+ else
+ BEGIN
+ AdrVals[Index][LastChain]+=(RunChain->DispAcc >> 2) & 0x000f;
+ RunChain->HasDisp=False;
+ END
+ break;
+
+ /* Fall 2: passt nicht mehr in naechstkleineres Displacement, aber wir
+ koennen hier schon einen Teil ablegen, um im naechsten Iterations-
+ schritt ein kuerzeres Displacement zu bekommen */
+
+ case DispSize4Eps:
+ if (RunChain->DispAcc>0)
+ BEGIN
+ AdrVals[Index][LastChain]+=0x0007;
+ RunChain->DispAcc-=28;
+ END
+ else
+ BEGIN
+ AdrVals[Index][LastChain]+=0x0008;
+ RunChain->DispAcc+=32;
+ END
+ break;
+
+ /* Fall 3: 16 Bit */
+
+ case DispSize16:
+ if (ChkRange(RunChain->DispAcc,-0x8000,0x7fff))
+ BEGIN
+ AdrVals[Index][LastChain]+=0x0011;
+ AdrVals[Index][LastChain+1]=RunChain->DispAcc & 0xffff;
+ AdrCnt1[Index]+=2;
+ RunChain->HasDisp=False;
+ END
+ break;
+
+ /* Fall 4: 32 Bit */
+
+ case DispSize32:
+ AdrVals[Index][LastChain]+=0x0012;
+ AdrVals[Index][LastChain+1]=RunChain->DispAcc >> 16;
+ AdrVals[Index][LastChain+2]=RunChain->DispAcc & 0xffff;
+ AdrCnt1[Index]+=4;
+ RunChain->HasDisp=False;
+ break;
+
+ default:
+ WrError(10000);
+ END
+ END
+ END
+
+ /* nichts mehr drin: dann ein leeres Steuerwort erzeugen. Tritt
+ auf, falls alles schon im Basisadressierungsbyte verschwunden */
+
+ else if (RunChain!=RootChain)
+ BEGIN
+ LastChain=AdrCnt1[Index] >> 1;
+ AdrVals[Index][LastChain]=0x0200; AdrCnt1[Index]+=2;
+ END
+
+ /* nichts mehr drin: wegwerfen
+ wenn wir noch nicht ganz vorne angekommen sind, dann ein
+ Indirektionsflag setzen */
+
+ if ((RunChain->RegCnt==0) AND (NOT RunChain->HasDisp))
+ BEGIN
+ if (RunChain!=RootChain) AdrVals[Index][LastChain]+=0x4000;
+ if (PrevChain==Nil) RootChain=Nil; else PrevChain->Next=Nil;
+ free(RunChain);
+ END
+ END
+
+ /* Ende-Kennung fuer letztes Glied */
+
+ AdrVals[Index][LastChain]+=0x8000;
+ END
+
+ return ChkAdr(Mask,Index);
+ END
+
+ /* ansonsten absolut */
+
+ DSize=DispSizeNone;
+ SplitSize(Asc,&DSize);
+ AdrLong=EvalIntExpression(Asc,Int32,&OK);
+ if (OK) DecideAbs(AdrLong,DSize,Mask,Index);
+
+ return ChkAdr(Mask,Index);
+END
+
+ static LongInt ImmVal(int Index)
+BEGIN
+ switch (OpSize[Index])
+ BEGIN
+ case 0: return (ShortInt) (AdrVals[Index][0] & 0xff);
+ case 1: return (Integer) (AdrVals[Index][0]);
+ case 2: return (((LongInt)AdrVals[Index][0]) << 16)+((Integer)AdrVals[Index][1]);
+ default: WrError(10000); return 0;
+ END
+END
+
+ static Boolean IsShort(int Index)
+BEGIN
+ return ((AdrMode[Index] & 0xc0)==0);
+END
+
+ static void AdaptImm(int Index, Byte NSize, Boolean Signed)
+BEGIN
+ switch (OpSize[Index])
+ BEGIN
+ case 0:
+ if (NSize!=0)
+ BEGIN
+ if (((AdrVals[Index][0] & 0x80)==0x80) AND (Signed))
+ AdrVals[Index][0]|=0xff00;
+ else AdrVals[Index][0]&=0xff;
+ if (NSize==2)
+ BEGIN
+ if (((AdrVals[Index][0] & 0x8000)==0x8000) AND (Signed))
+ AdrVals[Index][1]=0xffff;
+ else AdrVals[Index][1]=0;
+ AdrCnt1[Index]+=2; AdrCnt2[Index]++;
+ END
+ END
+ break;
+ case 1:
+ if (NSize==0) AdrVals[Index][0]&=0xff;
+ else if (NSize==2)
+ BEGIN
+ if (((AdrVals[Index][0] & 0x8000)==0x8000) AND (Signed))
+ AdrVals[Index][1]=0xffff;
+ else AdrVals[Index][1]=0;
+ AdrCnt1[Index]+=2; AdrCnt2[Index]++;
+ END
+ break;
+ case 2:
+ if (NSize!=2)
+ BEGIN
+ AdrCnt1[Index]-=2; AdrCnt2[Index]--;
+ if (NSize==0) AdrVals[Index][0]&=0xff;
+ END
+ break;
+ END
+ OpSize[Index]=NSize;
+END
+
+ static ShortInt DefSize(Byte Mask)
+BEGIN
+ ShortInt z;
+
+ z=2;
+ while ((z>=0) AND ((Mask & 4)==0))
+ BEGIN
+ Mask=(Mask << 1) & 7; z--;
+ END
+ return z;
+END
+
+ static Word RMask(Word No, Boolean Turn)
+BEGIN
+ return (Turn) ? (0x8000 >> No) : (1 << No);
+END
+
+ static Boolean DecodeRegList(char *Asc, Word *Erg, Boolean Turn)
+BEGIN
+ char Part[11];
+ char *p,*p1,*p2;
+ Word r1,r2,z;
+
+ if (IsIndirect(Asc))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ END
+ *Erg=0;
+ while (*Asc!='\0')
+ BEGIN
+ p1=strchr(Asc,','); p2=strchr(Asc,'/');
+ if ((p1!=Nil) AND (p1<p2)) p=p1; else p=p2;
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Part,Asc,11); *Asc='\0';
+ END
+ else
+ BEGIN
+ *p='\0'; strmaxcpy(Part,Asc,11); strcpy(Asc,p+1);
+ END
+ p=strchr(Part,'-');
+ if (p==Nil)
+ BEGIN
+ if (NOT DecodeReg(Part,&r1))
+ BEGIN
+ WrXError(1410,Part); return False;
+ END
+ *Erg|=RMask(r1,Turn);
+ END
+ else
+ BEGIN
+ *p='\0';
+ if (NOT DecodeReg(Part,&r1))
+ BEGIN
+ WrXError(1410,Part); return False;
+ END;
+ if (NOT DecodeReg(p+1,&r2))
+ BEGIN
+ WrXError(1410,p+1); return False;
+ END
+ if (r1<=r2)
+ for (z=r1; z<=r2; z++) *Erg|=RMask(z,Turn);
+ else
+ BEGIN
+ for (z=r2; z<=15; z++) *Erg|=RMask(z,Turn);
+ for (z=0; z<=r1; z++) *Erg|=RMask(z,Turn);
+ END
+ END
+ END
+ return True;
+END
+
+ static Boolean DecodeCondition(char *Asc, Word *Erg)
+BEGIN
+ int z;
+ String Asc_N;
+
+ strmaxcpy(Asc_N,Asc,255); NLS_UpString(Asc_N); Asc=Asc_N;
+
+ for (z=0; z<ConditionCount; z++)
+ if (strcmp(Asc,Conditions[z])==0) break;
+ *Erg=z; return (z<ConditionCount);
+END
+
+/*------------------------------------------------------------------------*/
+
+ static Boolean CheckFormat(char *FSet)
+BEGIN
+ char *p;
+
+ if (strcmp(Format," ")==0) FormatCode=0;
+ else
+ BEGIN
+ p=strchr(FSet,*Format);
+ if (p!=Nil) FormatCode=p-FSet+1;
+ else WrError(1090);
+ return (p!=Nil);
+ END;
+ return True;
+END
+
+ static Boolean CheckBFieldFormat(void)
+BEGIN
+ if ((strcmp(Format,"G:R")==0) OR (strcmp(Format,"R:G")==0)) FormatCode=1;
+ else if ((strcmp(Format,"G:I")==0) OR (strcmp(Format,"I:G")==0)) FormatCode=2;
+ else if ((strcmp(Format,"E:R")==0) OR (strcmp(Format,"R:E")==0)) FormatCode=3;
+ else if ((strcmp(Format,"E:I")==0) OR (strcmp(Format,"I:E")==0)) FormatCode=4;
+ else
+ BEGIN
+ WrError(1090); return False;
+ END
+ return True;
+END
+
+ static Boolean GetOpSize(char *Asc, Byte Index)
+BEGIN
+ char *p;
+ int l=strlen(Asc);
+
+ p=RQuotPos(Asc,'.');
+ if (p==Nil)
+ BEGIN
+ OpSize[Index]=DOpSize; return True;
+ END
+ else if (p==Asc+l-2)
+ BEGIN
+ switch (p[1])
+ BEGIN
+ case 'B': OpSize[Index]=0; break;
+ case 'H': OpSize[Index]=1; break;
+ case 'W': OpSize[Index]=2; break;
+ default:
+ WrError(1107); return False;
+ END
+ *p='\0';
+ return True;
+ END
+ else
+ BEGIN
+ WrError(1107); return False;
+ END
+END
+
+ static void SplitOptions(void)
+BEGIN
+ char *p;
+ int z;
+
+ OptionCnt=0; *Options[0]='\0'; *Options[1]='\0';
+ do
+ BEGIN
+ p=RQuotPos(OpPart,'/');
+ if (p!=Nil)
+ BEGIN
+ if (OptionCnt<2)
+ BEGIN
+ for (z=OptionCnt-1; z>=0; z--) strcpy(Options[z+1],Options[z]);
+ OptionCnt++; strmaxcpy(Options[0],p+1,255);
+ END
+ *p='\0';
+ END
+ END
+ while (p!=Nil);
+END
+
+/*------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void DecideBranch(LongInt Adr, Byte Index)
+BEGIN
+ LongInt Dist=Adr-EProgCounter();
+
+ if (FormatCode==0)
+ BEGIN
+ /* Groessenangabe erzwingt G-Format */
+ if (OpSize[Index]!=-1) FormatCode=1;
+ /* gerade 9-Bit-Zahl kurz darstellbar */
+ else if (((Dist & 1)==0) AND (Dist<=254) AND (Dist>=-256)) FormatCode=2;
+ /* ansonsten allgemein */
+ else FormatCode=1;
+ END
+ if ((FormatCode==1) AND (OpSize[Index]==-1))
+ if ((Dist<=127) AND (Dist>=-128)) OpSize[Index]=0;
+ else if ((Dist<=32767) AND (Dist>=-32768)) OpSize[Index]=1;
+ else OpSize[Index]=2;
+END
+
+ static Boolean DecideBranchLength(LongInt *Addr, int Index)
+BEGIN
+ *Addr-=EProgCounter();
+ if (OpSize[Index]==-1)
+ BEGIN
+ if ((*Addr>=-128) AND (*Addr<=127)) OpSize[Index]=0;
+ else if ((*Addr>=-32768) AND (*Addr<=32767)) OpSize[Index]=1;
+ else OpSize[Index]=2;
+ END
+
+ if ((NOT SymbolQuestionable) AND
+ (((OpSize[Index]==0) AND ((*Addr<-128) OR (*Addr>127)))
+ OR ((OpSize[Index]==1) AND ((*Addr<-32768) OR (*Addr>32767)))))
+ BEGIN
+ WrError(1370); return False;
+ END
+ else return True;
+END
+
+ static void Make_G(Word Code)
+BEGIN
+ WAsmCode[0]=0xd000+(OpSize[1] << 8)+AdrMode[1];
+ memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
+ WAsmCode[1+AdrCnt2[1]]=Code+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+2+AdrCnt2[1],AdrVals[2],AdrCnt1[2]);
+ CodeLen=4+AdrCnt1[1]+AdrCnt1[2];
+END
+
+ static void Make_E(Word Code, Boolean Signed)
+BEGIN
+ LongInt HVal,Min,Max;
+
+ Min=128*(-Ord(Signed)); Max=Min+255;
+ if (AdrType[1]!=ModImm) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,Min,Max))
+ BEGIN
+ WAsmCode[0]=0xbf00+(HVal & 0xff);
+ WAsmCode[1]=Code+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+2,AdrVals[2],AdrCnt1[2]);
+ CodeLen=4+AdrCnt1[2];
+ END
+ END
+END
+
+ static void Make_I(Word Code, Boolean Signed)
+BEGIN
+ if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
+ else
+ BEGIN
+ AdaptImm(1,OpSize[2],Signed);
+ WAsmCode[0]=Code+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ memcpy(WAsmCode+1+AdrCnt2[2],AdrVals[1],AdrCnt1[1]);
+ CodeLen=2+AdrCnt1[1]+AdrCnt1[2];
+ END
+END
+
+ static Boolean CodeAri(void)
+BEGIN
+ int z;
+ Word AdrWord,Mask,Mask2;
+ char Form[6];
+ LongInt HVal;
+
+ if ((Memo("ADD")) OR (Memo("SUB")))
+ BEGIN
+ z=Ord(Memo("SUB"));
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GELQI"))
+ if (GetOpSize(ArgStr[2],2))
+ if (GetOpSize(ArgStr[1],1))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[1]==-1) OpSize[1]=OpSize[2];
+ if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if (IsShort(2))
+ if ((HVal>=1) AND (HVal<=8)) FormatCode=4;
+ else FormatCode=5;
+ else if ((HVal>=-128) AND (HVal<127)) FormatCode=2;
+ else FormatCode=1;
+ END
+ else if (IsShort(1) AND (AdrType[2]==ModReg) AND (OpSize[1]==2) AND (OpSize[2]==2)) FormatCode=3;
+ else FormatCode=1;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ Make_G(z << 11);
+ break;
+ case 2:
+ Make_E(z << 11,True);
+ break;
+ case 3:
+ if ((NOT IsShort(1)) OR (AdrType[2]!=ModReg)) WrError(1350);
+ else if ((OpSize[1]!=2) OR (OpSize[2]!=2)) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0x8100+(z << 6)+((AdrMode[2] & 15) << 10)+AdrMode[1];
+ memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
+ CodeLen=2+AdrCnt1[1];
+ if ((AdrMode[1]==0x04) & (AdrMode[2]==15)) WrError(140);
+ END
+ break;
+ case 4:
+ if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,1,8))
+ BEGIN
+ WAsmCode[0]=0x4040+(z << 13)+((HVal & 7) << 10)+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ CodeLen=2+AdrCnt1[2];
+ END
+ END
+ break;
+ case 5:
+ Make_I(0x44c0+(z << 11),True);
+ break;
+ END
+ END
+ END
+ return True;
+ END
+
+ if (Memo("CMP"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GELZQI"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[1]==-1) OpSize[1]=OpSize[2];
+ if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_NoImmGen-MModPush))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if (HVal==0) FormatCode=4;
+ else if ((HVal>=1) AND (HVal<=8) AND (IsShort(2))) FormatCode=5;
+ else if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
+ else if (AdrType[2]==ModReg) FormatCode=3;
+ else if (IsShort(2)) FormatCode=5;
+ else FormatCode=1;
+ END
+ else if ((IsShort(1)) AND (AdrType[2]==ModReg)) FormatCode=3;
+ else FormatCode=1;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ Make_G(0x8000);
+ break;
+ case 2:
+ Make_E(0x8000,True);
+ break;
+ case 3:
+ if ((NOT IsShort(1)) OR (AdrType[2]!=ModReg)) WrError(1350);
+ else if (OpSize[1]!=2) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=((AdrMode[2] & 15) << 10)+(OpSize[2] << 8)+AdrMode[1];
+ memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
+ CodeLen=2+AdrCnt1[1];
+ END
+ break;
+ case 4:
+ if (AdrType[1]!=ModImm) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,0,0))
+ BEGIN
+ WAsmCode[0]=0xc000+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ CodeLen=2+AdrCnt1[2];
+ END
+ END
+ break;
+ case 5:
+ if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,1,8))
+ BEGIN
+ WAsmCode[0]=0x4000+(OpSize[2] << 8)+AdrMode[2]+((HVal & 7) << 10);
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ CodeLen=2+AdrCnt1[2];
+ END
+ END
+ break;
+ case 6:
+ Make_I(0x40c0,True);
+ break;
+ END
+ END
+ END
+ return True;
+ END
+
+ for (z=0; z<GE2OrderCount; z++)
+ if (Memo(GE2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GE"))
+ if (GetOpSize(ArgStr[2],2))
+ if (GetOpSize(ArgStr[1],1))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=DefSize(GE2Orders[z].SMask2);
+ if (OpSize[1]==-1) OpSize[1]=DefSize(GE2Orders[z].SMask1);
+ if (((GE2Orders[z].SMask1 & (1 << OpSize[1]))==0) OR ((GE2Orders[z].SMask2 & (1 << OpSize[2]))==0)) WrError(1130);
+ else if (DecodeAdr(ArgStr[1],1,GE2Orders[z].Mask1))
+ if (DecodeAdr(ArgStr[2],2,GE2Orders[z].Mask2))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if ((GE2Orders[z].Signed) AND (HVal>=-128) AND (HVal<=127)) FormatCode=2;
+ else if ((NOT GE2Orders[z].Signed) AND (HVal>=0) AND (HVal<=255)) FormatCode=2;
+ else FormatCode=1;
+ END
+ else FormatCode=1;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ Make_G(GE2Orders[z].Code); break;
+ case 2:
+ Make_E(GE2Orders[z].Code,GE2Orders[z].Signed); break;
+ END
+ END
+ END
+ return True;
+ END
+
+ for (z=0; z<LogOrderCount; z++)
+ if (Memo(LogOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GERI"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[1]==-1) OpSize[1]=OpSize[2];
+ if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_Dest-MModPush))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if ((HVal>=0) AND (HVal<=255)) FormatCode=2;
+ else if (IsShort(2)) FormatCode=4;
+ else FormatCode=1;
+ END
+ else if ((AdrType[1]==ModReg) AND (AdrType[2]==ModReg) AND (OpSize[1]==2) AND (OpSize[2]==2))
+ FormatCode=3;
+ else FormatCode=1;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ Make_G(0x2000+(z << 10));
+ break;
+ case 2:
+ Make_E(0x2000+(z << 10),False);
+ break;
+ case 3:
+ if ((AdrType[1]!=ModReg) OR (AdrType[2]!=ModReg)) WrError(1350);
+ else if ((OpSize[1]!=2) OR (OpSize[2]!=2)) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0x00c0+(z << 8)+(AdrMode[1] & 15)+((AdrMode[2] & 15) << 10);
+ CodeLen=2;
+ END
+ break;
+ case 4:
+ if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
+ else
+ BEGIN
+ WAsmCode[0]=0x50c0+(OpSize[2] << 8)+(z << 10)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ AdaptImm(1,OpSize[2],False);
+ memcpy(WAsmCode+1+AdrCnt2[2],AdrVals[1],AdrCnt1[1]);
+ CodeLen=2+AdrCnt1[1]+AdrCnt1[2];
+ END
+ break;
+ END
+ if (OpSize[1]>OpSize[2]) WrError(140);
+ END
+ END
+ return True;
+ END
+
+ for (z=0; z<MulOrderCount; z++)
+ if (Memo(MulOrders[z]))
+ BEGIN
+ strcpy(Form,(Odd(z)) ? "GE" : "GER");
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat(Form))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[1]==-1) OpSize[1]=OpSize[2];
+ if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if ((HVal>=-128+(Ord(Odd(z)) << 7)) AND
+ (HVal<=127+(Ord(Odd(z)) << 7))) FormatCode=2;
+ else FormatCode=1;
+ END
+ else if ((NOT Odd(z)) AND (AdrType[1]==ModReg) AND (OpSize[1]==2)
+ AND (AdrType[2]==ModReg) AND (OpSize[2]==2)) FormatCode=3;
+ else FormatCode=1;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ Make_G(0x4000+(z << 10)); break;
+ case 2:
+ Make_E(0x4000+(z << 10),NOT Odd(z)); break;
+ case 3:
+ if ((AdrType[1]!=ModReg) OR (AdrType[2]!=ModReg)) WrError(1350);
+ else if ((OpSize[1]!=2) OR (OpSize[2]!=2)) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0x00d0+((AdrMode[2] & 15) << 10)+(z << 7)+
+ (AdrMode[1] & 15);
+ CodeLen=2;
+ END
+ END
+ END
+ END
+ return True;
+ END
+
+ for (z=0; z<GetPutOrderCount; z++)
+ if (Memo(GetPutOrders[z].Name))
+ BEGIN
+ if (GetPutOrders[z].Turn)
+ BEGIN
+ Mask=Mask_Source; Mask2=MModReg; AdrWord=1;
+ END
+ else
+ BEGIN
+ Mask=MModReg; Mask2=Mask_Dest; AdrWord=2;
+ END;
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[AdrWord]==-1) OpSize[AdrWord]=GetPutOrders[z].Size;
+ if (OpSize[3-AdrWord]==-1) OpSize[3-AdrWord]=2;
+ if ((OpSize[AdrWord]!=GetPutOrders[z].Size) OR (OpSize[3-AdrWord]!=2)) WrError(1130);
+ else if (DecodeAdr(ArgStr[1],1,Mask))
+ if (DecodeAdr(ArgStr[2],2,Mask2))
+ BEGIN
+ Make_G(GetPutOrders[z].Code); WAsmCode[0]+=0x0400;
+ END
+ END
+ return True;
+ END
+
+ if (Memo("MOVA"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GR"))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=2;
+ OpSize[1]=0;
+ if (OpSize[2]!=2) WrError(1110);
+ else if (DecodeAdr(ArgStr[1],1,Mask_PureMem))
+ if (DecodeAdr(ArgStr[2],2,Mask_Dest))
+ BEGIN
+ if (FormatCode==0)
+ if ((AdrType[1]==ModDisp16) AND (AdrType[2]==ModReg)) FormatCode=2;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ Make_G(0xb400); WAsmCode[0]+=0x800;
+ break;
+ case 2:
+ if ((AdrType[1]!=ModDisp16) OR (AdrType[2]!=ModReg)) WrError(1350);
+ else
+ BEGIN
+ WAsmCode[0]=0x03c0+((AdrMode[2] & 15) << 10)+(AdrMode[1] & 15);
+ WAsmCode[1]=AdrVals[1][0];
+ CodeLen=4;
+ END
+ break;
+ END
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("QINS")) OR (Memo("QDEL")))
+ BEGIN
+ z=Ord(Memo("QINS")) << 11;
+ Mask=Mask_PureMem;
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ if ((Memo("QINS")) OR (GetOpSize(ArgStr[2],2)))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=2;
+ OpSize[1]=0;
+ if (OpSize[2]!=2) WrError(1130);
+ else if (DecodeAdr(ArgStr[1],1,Mask))
+ if (DecodeAdr(ArgStr[2],2,Mask+(Ord(Memo("QDEL"))*MModReg)))
+ BEGIN
+ Make_G(0xb000+z); WAsmCode[0]+=0x800;
+ END
+ END
+ return True;
+ END
+
+ if (Memo("RVBY"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[1]==-1) OpSize[1]=OpSize[2];
+ if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_Dest))
+ BEGIN
+ Make_G(0x4000); WAsmCode[0]+=0x400;
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("SHL")) OR (Memo("SHA")))
+ BEGIN
+ z=Ord(Memo("SHA"));
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GEQ"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[1]==-1) OpSize[1]=0;
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[1]!=0) WrError(1130);
+ else if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if ((IsShort(2)) AND (abs(HVal)>=1) AND (abs(HVal)<=8) AND ((z==0) OR (HVal<0))) FormatCode=3;
+ else if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
+ else FormatCode=1;
+ END
+ else FormatCode=1;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ Make_G(0x3000+(z << 10)); break;
+ case 2:
+ Make_E(0x3000+(z << 10),True); break;
+ case 3:
+ if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,-8,(1-z) << 3))
+ if (HVal==0) WrError(1135);
+ else
+ BEGIN
+ if (HVal<0) HVal+=16;
+ else HVal&=7;
+ WAsmCode[0]=0x4080+(HVal << 10)+(z << 6)+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ CodeLen=2+AdrCnt1[2];
+ END
+ END
+ break;
+ END
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("SHXL")) OR (Memo("SHXR")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],1))
+ BEGIN
+ if (OpSize[1]==-1) OpSize[1]=2;
+ if (OpSize[1]!=2) WrError(1130);
+ else if (DecodeAdr(ArgStr[1],1,Mask_PureDest))
+ BEGIN
+ WAsmCode[0]=0x02f7;
+ WAsmCode[1]=0x8a00+(Ord(Memo("SHXR")) << 12)+AdrMode[1];
+ memcpy(WAsmCode+1,AdrVals,AdrCnt1[1]);
+ CodeLen=4+AdrCnt1[1];
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static Boolean CodeBits(void)
+BEGIN
+ int z;
+ char Form[6];
+ LongInt HVal,AdrLong;
+ Word Mask;
+
+ for (z=0; z<BitOrderCount; z++)
+ if (Memo(BitOrders[z].Name))
+ BEGIN
+ strcpy(Form,(BitOrders[z].Code2!=0) ? "GER" : "GE");
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat(Form))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[1]==-1) OpSize[1]=2;
+ if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
+ BEGIN
+ if (OpSize[2]==-1)
+ if ((AdrType[2]==ModReg) AND (NOT BitOrders[z].MustByte)) OpSize[2]=2;
+ else OpSize[2]=0;
+ if (((AdrType[2]!=ModReg) OR (BitOrders[z].MustByte)) AND (OpSize[2]!=0)) WrError(1130);
+ else
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if ((HVal>=0) AND (HVal<=7) AND (IsShort(2)) AND (BitOrders[z].Code2!=0) AND (OpSize[2]==0)) FormatCode=3;
+ else if ((HVal>=-128) AND (HVal<127)) FormatCode=2;
+ else FormatCode=1;
+ END
+ else FormatCode=1;
+ END;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ Make_G(BitOrders[z].Code1); break;
+ case 2:
+ Make_E(BitOrders[z].Code1,True); break;
+ case 3:
+ if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
+ else if (OpSize[2]!=0) WrError(1130);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,0,7))
+ BEGIN
+ WAsmCode[0]=BitOrders[z].Code2+((HVal & 7) << 10)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ CodeLen=2+AdrCnt1[2];
+ END
+ END
+ break;
+ END
+ END
+ END
+ END
+ return True;
+ END
+
+ for (z=0; z<BFieldOrderCount; z++)
+ if (Memo(BFieldOrders[z]))
+ BEGIN
+ if (ArgCnt!=4) WrError(1110);
+ else if (CheckBFieldFormat())
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ if (GetOpSize(ArgStr[3],3))
+ if (GetOpSize(ArgStr[4],4))
+ BEGIN
+ if (OpSize[1]==-1) OpSize[1]=2;
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[3]==-1) OpSize[3]=2;
+ if (OpSize[4]==-1) OpSize[4]=2;
+ if (DecodeAdr(ArgStr[1],1,MModReg+MModImm))
+ if (DecodeAdr(ArgStr[3],3,MModReg+MModImm))
+ BEGIN
+ Mask=(AdrType[3]==ModReg) ? Mask_Source : MModImm;
+ if (DecodeAdr(ArgStr[2],2,Mask))
+ if (DecodeAdr(ArgStr[4],4,Mask_PureMem))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[3]==ModReg)
+ if (AdrType[1]==ModReg) FormatCode=1; else FormatCode=2;
+ else
+ if (AdrType[1]==ModReg) FormatCode=3; else FormatCode=4;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ if ((AdrType[1]!=ModReg) OR (AdrType[3]!=ModReg)) WrError(1350);
+ else if ((OpSize[1]!=2) OR (OpSize[3]!=2) OR (OpSize[4]!=2)) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0xd000+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ WAsmCode[1+AdrCnt2[2]]=0xc200+(z << 10)+AdrMode[4];
+ memcpy(WAsmCode+2+AdrCnt2[2],AdrVals[4],AdrCnt1[4]);
+ WAsmCode[2+AdrCnt2[2]+AdrCnt2[4]]=((AdrMode[3] & 15) << 10)+(AdrMode[1] & 15);
+ CodeLen=6+AdrCnt1[2]+AdrCnt1[4];
+ END
+ break;
+ case 2:
+ if ((AdrType[1]!=ModImm) OR (AdrType[3]!=ModReg)) WrError(1350);
+ else if ((OpSize[3]!=2) OR (OpSize[4]!=2)) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0xd000+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ WAsmCode[1+AdrCnt2[2]]=0xd200+(z << 10)+AdrMode[4];
+ memcpy(WAsmCode+2+AdrCnt2[2],AdrVals[4],AdrCnt1[4]);
+ WAsmCode[2+AdrCnt2[2]+AdrCnt2[4]]=((AdrMode[3] & 15) << 10)+(OpSize[1] << 8);
+ CodeLen=6+AdrCnt1[2]+AdrCnt1[4];
+ if (OpSize[1]==0) WAsmCode[(CodeLen-2) >> 1]+=AdrVals[1][0] & 0xff;
+ else
+ BEGIN
+ memcpy(WAsmCode+(CodeLen >> 1),AdrVals[1],AdrCnt1[1]);
+ CodeLen+=AdrCnt1[1];
+ END
+ END
+ break;
+ case 3:
+ if ((AdrType[1]!=ModReg) OR (AdrType[2]!=ModImm) OR (AdrType[3]!=ModImm)) WrError(1350);
+ else if ((OpSize[1]!=2) OR (OpSize[4]!=2)) WrError(1130);
+ else
+ BEGIN
+ HVal=ImmVal(2);
+ if (ChkRange(HVal,-128,-127))
+ BEGIN
+ AdrLong=ImmVal(3);
+ if (ChkRange(AdrLong,1,32))
+ BEGIN
+ WAsmCode[0]=0xbf00+(HVal & 0xff);
+ WAsmCode[1]=0xc200+(z << 10)+AdrMode[4];
+ memcpy(WAsmCode+2,AdrVals[4],AdrCnt1[4]);
+ WAsmCode[2+AdrCnt2[4]]=((AdrLong & 31) << 10)+(AdrMode[1] & 15);
+ CodeLen=6+AdrCnt1[4];
+ END
+ END
+ END
+ break;
+ case 4:
+ if ((AdrType[1]!=ModImm) OR (AdrType[2]!=ModImm) OR (AdrType[3]!=ModImm)) WrError(1350);
+ else if (OpSize[4]!=2) WrError(1130);
+ else
+ BEGIN
+ HVal=ImmVal(2);
+ if (ChkRange(HVal,-128,-127))
+ BEGIN
+ AdrLong=ImmVal(3);
+ if (ChkRange(AdrLong,1,32))
+ BEGIN
+ WAsmCode[0]=0xbf00+(HVal & 0xff);
+ WAsmCode[1]=0xd200+(z << 10)+AdrMode[4];
+ memcpy(WAsmCode+2,AdrVals[4],AdrCnt1[4]);
+ WAsmCode[2+AdrCnt2[4]]=((AdrLong & 31) << 10)+(OpSize[1] << 8);
+ CodeLen=6+AdrCnt1[4];
+ if (OpSize[1]==0) WAsmCode[(CodeLen-1) >> 1]+=AdrVals[1][0] & 0xff;
+ else
+ BEGIN
+ memcpy(WAsmCode+(CodeLen >> 1),AdrVals[1],AdrCnt1[1]);
+ CodeLen+=AdrCnt1[1];
+ END
+ END
+ END
+ END
+ break;
+ END
+ END
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("BFEXT")) OR (Memo("BFEXTU")))
+ BEGIN
+ z=Ord(Memo("BFEXTU"));
+ if (ArgCnt!=4) WrError(1110);
+ else if (CheckFormat("GE"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ if (GetOpSize(ArgStr[3],3))
+ if (GetOpSize(ArgStr[4],4))
+ BEGIN
+ if (OpSize[1]==-1) OpSize[1]=2;
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[3]==-1) OpSize[3]=2;
+ if (OpSize[4]==-1) OpSize[4]=2;
+ if (DecodeAdr(ArgStr[4],4,MModReg))
+ if (DecodeAdr(ArgStr[3],3,Mask_MemGen-MModPop-MModPush))
+ if (DecodeAdr(ArgStr[2],2,MModReg+MModImm))
+ BEGIN
+ if (AdrType[2]==ModReg) Mask=Mask_Source; else Mask=MModImm;
+ if (DecodeAdr(ArgStr[1],1,Mask))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[2]==ModReg) FormatCode=1; else FormatCode=2;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ if ((OpSize[2]!=2) OR (OpSize[3]!=2) OR (OpSize[4]!=2)) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0xd000+(OpSize[1] << 8)+AdrMode[1];
+ memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
+ WAsmCode[1+AdrCnt2[1]]=0xea00+(z << 10)+AdrMode[3];
+ memcpy(WAsmCode+2+AdrCnt2[1],AdrVals[3],AdrCnt1[3]);
+ WAsmCode[2+AdrCnt2[1]+AdrCnt2[3]]=((AdrMode[2] & 15) << 10)+(AdrMode[4] & 15);
+ CodeLen=6+AdrCnt1[1]+AdrCnt1[3];
+ END
+ break;
+ case 2:
+ if ((AdrType[1]!=ModImm) OR (AdrType[2]!=ModImm)) WrError(1350);
+ else if ((OpSize[3]!=2) OR (OpSize[4]!=2)) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,-128,127))
+ BEGIN
+ AdrLong=ImmVal(2);
+ if (ChkRange(AdrLong,1,32))
+ BEGIN
+ WAsmCode[0]=0xbf00+(HVal & 0xff);
+ WAsmCode[1]=0xea00+(z << 10)+AdrMode[3];
+ memcpy(WAsmCode+2,AdrVals[3],AdrCnt1[3]);
+ WAsmCode[2+AdrCnt2[3]]=((AdrLong & 31) << 10)+(AdrMode[4] & 15);
+ CodeLen=6+AdrCnt1[3];
+ END
+ END
+ END
+ break;
+ END
+ END
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("BSCH/0")) OR (Memo("BSCH/1")))
+ BEGIN
+ z=OpPart[5]-'0';
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[1]==-1) OpSize[1]=2;
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[1]!=2) WrError(1130);
+ else
+ if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
+ BEGIN
+ /* immer G-Format */
+ WAsmCode[0]=0xd600+AdrMode[1];
+ memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
+ WAsmCode[1+AdrCnt2[1]]=0x5000+(z << 10)+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+2+AdrCnt2[1],AdrVals[2],AdrCnt1[2]);
+ CodeLen=4+AdrCnt1[1]+AdrCnt1[2];
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_M16(void)
+BEGIN
+ int z;
+ char *p;
+ Word AdrWord,HReg,Mask;
+ LongInt AdrLong,HVal;
+ Boolean OK;
+
+ DOpSize=(-1); for (z=1; z<=ArgCnt; OpSize[z++]=(-1));
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Formatangabe abspalten */
+
+ switch (AttrSplit)
+ BEGIN
+ case '.':
+ p=strchr(AttrPart,':');
+ if (p!=Nil)
+ BEGIN
+ if (p<AttrPart+strlen(AttrPart)-1) strmaxcpy(Format,p+1,255);
+ else strcpy(Format," ");
+ *p='\0';
+ END
+ else strcpy(Format," ");
+ break;
+ case ':':
+ p=strchr(AttrPart,'.');
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Format,AttrPart,255); *AttrPart='\0';
+ END
+ else
+ BEGIN
+ *p='\0';
+ if (p==AttrPart) strcpy(Format," "); else strmaxcpy(Format,AttrPart,255);
+ END
+ break;
+ default:
+ strcpy(Format," ");
+ END
+ NLS_UpString(Format);
+
+ /* Attribut abarbeiten */
+
+ if (*AttrPart=='\0') DOpSize=(-1);
+ else
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B': DOpSize=0; break;
+ case 'H': DOpSize=1; break;
+ case 'W': DOpSize=2; break;
+ default:
+ WrError(1107); return;
+ END
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else
+ BEGIN
+ CodeLen=2; WAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ if ((Memo("STOP")) OR (Memo("SLEEP")))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else
+ BEGIN
+ CodeLen=10;
+ WAsmCode[0]=0xd20c;
+ if (Memo("STOP"))
+ BEGIN
+ WAsmCode[1]=0x5374;
+ WAsmCode[2]=0x6f70;
+ END
+ else
+ BEGIN
+ WAsmCode[1]=0x5761;
+ WAsmCode[2]=0x6974;
+ END;
+ WAsmCode[3]=0x9e09;
+ WAsmCode[4]=0x0700;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GELSZQI"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[1]==-1) OpSize[1]=OpSize[2];
+ if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_AllGen-MModPop))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if (HVal==0) FormatCode=5;
+ else if ((HVal>=1) AND (HVal<=8) AND (IsShort(2))) FormatCode=6;
+ else if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
+ else if (IsShort(2)) FormatCode=7;
+ else FormatCode=1;
+ END
+ else if ((AdrType[1]==ModReg) AND (OpSize[1]==2) AND (IsShort(2))) FormatCode=4;
+ else if ((AdrType[2]==ModReg) AND (OpSize[2]==2) AND (IsShort(1))) FormatCode=3;
+ else FormatCode=1;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ Make_G(0x8800);
+ break;
+ case 2:
+ Make_E(0x8800,True);
+ break;
+ case 3:
+ if ((NOT IsShort(1)) OR (AdrType[2]!=ModReg)) WrError(1350);
+ else if (OpSize[2]!=2) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0x0040+((AdrMode[2] & 15) << 10)+(OpSize[1] << 8)+AdrMode[1];
+ memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
+ CodeLen=2+AdrCnt1[1];
+ END
+ break;
+ case 4:
+ if ((NOT IsShort(2)) OR (AdrType[1]!=ModReg)) WrError(1350);
+ else if (OpSize[1]!=2) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0x0080+((AdrMode[1] & 15) << 10)+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ CodeLen=2+AdrCnt1[2];
+ END
+ break;
+ case 5:
+ if (AdrType[1]!=ModImm) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,0,0))
+ BEGIN
+ WAsmCode[0]=0xc400+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ CodeLen=2+AdrCnt1[2];
+ END
+ END
+ break;
+ case 6:
+ if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,1,8))
+ BEGIN
+ WAsmCode[0]=0x6000+((HVal & 7) << 10)+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ CodeLen=2+AdrCnt1[2];
+ END
+ END
+ break;
+ case 7:
+ Make_I(0x48c0,True);
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ /* ein Operand */
+
+ for (z=0; z<OneOrderCount; z++)
+ if (Memo(OneOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],1))
+ BEGIN
+ if ((OpSize[1]==-1) AND (OneOrders[z].OpMask!=0)) OpSize[1]=DefSize(OneOrders[z].OpMask);
+ if ((OpSize[1]!=-1) AND (((1 << OpSize[1]) & OneOrders[z].OpMask)==0)) WrError(1130);
+ else
+ BEGIN
+ if (DecodeAdr(ArgStr[1],1,OneOrders[z].Mask))
+ BEGIN
+ /* da nur G, Format ignorieren */
+ WAsmCode[0]=OneOrders[z].Code+AdrMode[1];
+ if (OneOrders[z].OpMask!=0) WAsmCode[0]+=OpSize[1] << 8;
+ memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
+ CodeLen=2+AdrCnt1[1];
+ END
+ END
+ END
+ return;
+ END
+
+ /* zwei Operanden */
+
+ if (CodeAri()) return;
+
+ /* drei Operanden */
+
+ if ((Memo("CHK/N")) OR (Memo("CHK/S")) OR (Memo("CHK")))
+ BEGIN
+ z=Ord(OpPart[strlen(OpPart)-1]=='S');
+ if (ArgCnt!=3) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],2))
+ if (GetOpSize(ArgStr[2],1))
+ if (GetOpSize(ArgStr[3],3))
+ BEGIN
+ if (OpSize[3]==-1) OpSize[3]=2;
+ if (OpSize[2]==-1) OpSize[2]=OpSize[3];
+ if (OpSize[1]==-1) OpSize[1]=OpSize[3];
+ if ((OpSize[1]!=OpSize[2]) OR (OpSize[2]!=OpSize[3])) WrError(1131);
+ else
+ if (DecodeAdr(ArgStr[1],2,Mask_MemGen-MModPop-MModPush))
+ if (DecodeAdr(ArgStr[2],1,Mask_Source))
+ if (DecodeAdr(ArgStr[3],3,MModReg))
+ BEGIN
+ OpSize[2]=2+z;
+ Make_G((AdrMode[3] & 15) << 10);
+ WAsmCode[0]+=0x400;
+ END
+ END
+ return;
+ END
+
+ if (Memo("CSI"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],3))
+ if (GetOpSize(ArgStr[2],1))
+ if (GetOpSize(ArgStr[3],2))
+ BEGIN
+ if (OpSize[3]==-1) OpSize[3]=2;
+ if (OpSize[2]==-1) OpSize[2]=OpSize[3];
+ if (OpSize[1]==-1) OpSize[1]=OpSize[2];
+ if ((OpSize[1]!=OpSize[2]) OR (OpSize[2]!=OpSize[3])) WrError(1131);
+ else if (DecodeAdr(ArgStr[1],3,MModReg))
+ if (DecodeAdr(ArgStr[2],1,Mask_Source))
+ if (DecodeAdr(ArgStr[3],2,Mask_PureMem))
+ BEGIN
+ OpSize[2]=0;
+ Make_G((AdrMode[3] & 15) << 10);
+ WAsmCode[0]+=0x400;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("DIVX")) OR (Memo("MULX")))
+ BEGIN
+ z=Ord(Memo("DIVX"));
+ if (ArgCnt!=3) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ if (GetOpSize(ArgStr[3],3))
+ BEGIN
+ if (OpSize[3]==-1) OpSize[3]=2;
+ if (OpSize[2]==-1) OpSize[2]=OpSize[3];
+ if (OpSize[1]==-1) OpSize[1]=OpSize[2];
+ if ((OpSize[1]!=2) OR (OpSize[2]!=2) OR (OpSize[3]!=2)) WrError(1130);
+ else if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
+ if (DecodeAdr(ArgStr[3],3,MModReg))
+ BEGIN
+ OpSize[2]=0;
+ Make_G(0x8200+((AdrMode[3] & 15) << 10)+(z << 8));
+ WAsmCode[0]+=0x400;
+ END
+ END
+ return;
+ END
+
+ /* Bitoperationen */
+
+ if (CodeBits()) return;
+
+ /* Spruenge */
+
+ if ((Memo("BSR")) OR (Memo("BRA")))
+ BEGIN
+ z=Ord(Memo("BSR"));
+ if (ArgCnt!=1) WrError(1110);
+ else
+ if (CheckFormat("GD"))
+ if (GetOpSize(ArgStr[1],1))
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (OK)
+ BEGIN
+ DecideBranch(AdrLong,1);
+ switch (FormatCode)
+ BEGIN
+ case 2:
+ if (OpSize[1]!=-1) WrError(1100);
+ else
+ BEGIN
+ AdrLong-=EProgCounter();
+ if ((NOT SymbolQuestionable) AND ((AdrLong<-256) OR (AdrLong>254))) WrError(1370);
+ else if (Odd(AdrLong)) WrError(1375);
+ else
+ BEGIN
+ CodeLen=2;
+ WAsmCode[0]=0xae00+(z << 8)+Lo(AdrLong >> 1);
+ END
+ END
+ break;
+ case 1:
+ WAsmCode[0]=0x20f7+(z << 11)+(((Word)OpSize[1]) << 8);
+ AdrLong-=EProgCounter();
+ switch (OpSize[1])
+ BEGIN
+ case 0:
+ if ((NOT SymbolQuestionable) AND ((AdrLong<-128) OR (AdrLong>127))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=4; WAsmCode[1]=Lo(AdrLong);
+ END
+ break;
+ case 1:
+ if ((NOT SymbolQuestionable) AND ((AdrLong<-32768) OR (AdrLong>32767))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=4; WAsmCode[1]=AdrLong & 0xffff;
+ END
+ break;
+ case 2:
+ CodeLen=6; WAsmCode[1]=AdrLong >> 16;
+ WAsmCode[2]=AdrLong & 0xffff;
+ break;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (*OpPart=='B')
+ for (z=0; z<ConditionCount; z++)
+ if (strcmp(OpPart+1,Conditions[z])==0)
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ if (CheckFormat("GD"))
+ if (GetOpSize(ArgStr[1],1))
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (OK)
+ BEGIN
+ DecideBranch(AdrLong,1);
+ switch (FormatCode)
+ BEGIN
+ case 2:
+ if (OpSize[1]!=-1) WrError(1100);
+ else
+ BEGIN
+ AdrLong-=EProgCounter();
+ if ((NOT SymbolQuestionable) AND ((AdrLong<-256) OR (AdrLong>254))) WrError(1370);
+ else if (Odd(AdrLong)) WrError(1375);
+ else
+ BEGIN
+ CodeLen=2;
+ WAsmCode[0]=0x8000+(z << 10)+Lo(AdrLong >> 1);
+ END
+ END
+ break;
+ case 1:
+ WAsmCode[0]=0x00f6+(z << 10)+(((Word)OpSize[1]) << 8);
+ AdrLong-=EProgCounter();
+ switch (OpSize[1])
+ BEGIN
+ case 0:
+ if ((AdrLong<-128) OR (AdrLong>127)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=4; WAsmCode[1]=Lo(AdrLong);
+ END
+ break;
+ case 1:
+ if ((AdrLong<-32768) OR (AdrLong>32767)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=4; WAsmCode[1]=AdrLong & 0xffff;
+ END
+ break;
+ case 2:
+ CodeLen=6; WAsmCode[1]=AdrLong >> 16;
+ WAsmCode[2]=AdrLong & 0xffff;
+ break;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("ACB")) OR (Memo("SCB")))
+ BEGIN
+ AdrWord=Ord(Memo("SCB"));
+ if (ArgCnt!=4) WrError(1110);
+ else if (CheckFormat("GEQR"))
+ if (GetOpSize(ArgStr[2],3))
+ if (GetOpSize(ArgStr[4],4))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[3],2))
+ BEGIN
+ if ((OpSize[3]==-1) AND (OpSize[2]==-1)) OpSize[3]=2;
+ if ((OpSize[3]==-1) AND (OpSize[2]!=-1)) OpSize[3]=OpSize[2];
+ else if ((OpSize[3]!=-1) AND (OpSize[2]==-1)) OpSize[2]=OpSize[3];
+ if (OpSize[1]==-1) OpSize[1]=OpSize[2];
+ if (OpSize[3]!=OpSize[2]) WrError(1131);
+ else if (NOT DecodeReg(ArgStr[2],&HReg)) WrError(1350);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[4],Int32,&OK);
+ if (OK)
+ BEGIN
+ if (DecodeAdr(ArgStr[1],1,Mask_Source))
+ if (DecodeAdr(ArgStr[3],2,Mask_Source))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]!=ModImm) FormatCode=1;
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if ((HVal==1) AND (AdrType[2]==ModReg)) FormatCode=4;
+ else if ((HVal==1) AND (AdrType[2]==ModImm))
+ BEGIN
+ HVal=ImmVal(2);
+ if ((HVal>=1-AdrWord) AND (HVal<=64-AdrWord)) FormatCode=3;
+ else FormatCode=2;
+ END
+ else if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
+ else FormatCode=1;
+ END
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ if (DecideBranchLength(&AdrLong,4)) /* ??? */
+ BEGIN
+ WAsmCode[0]=0xd000+(OpSize[1] << 8)+AdrMode[1];
+ memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
+ WAsmCode[1+AdrCnt2[1]]=0xf000+(AdrWord << 11)+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+2+AdrCnt2[1],AdrVals[2],AdrCnt1[2]);
+ WAsmCode[2+AdrCnt2[1]+AdrCnt2[2]]=(HReg << 10)+(OpSize[4] << 8);
+ CodeLen=6+AdrCnt1[1]+AdrCnt1[2];
+ END
+ break;
+ case 2:
+ if (DecideBranchLength(&AdrLong,4)) /* ??? */
+ if (AdrType[1]!=ModImm) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,-128,127))
+ BEGIN
+ WAsmCode[0]=0xbf00+(HVal & 0xff);
+ WAsmCode[1]=0xf000+(AdrWord << 11)+(OpSize[2] << 8)+AdrMode[2];
+ memcpy(WAsmCode+2,AdrVals[2],AdrCnt1[2]);
+ WAsmCode[2+AdrCnt2[2]]=(HReg << 10)+(OpSize[4] << 8);
+ CodeLen=6+AdrCnt1[2];
+ END
+ END
+ break;
+ case 3:
+ if (DecideBranchLength(&AdrLong,4)) /* ??? */
+ if (AdrType[1]!=ModImm) WrError(1350);
+ else if (ImmVal(1)!=1) WrError(1135);
+ else if (AdrType[2]!=ModImm) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(2);
+ if (ChkRange(HVal,1-AdrWord,64-AdrWord))
+ BEGIN
+ WAsmCode[0]=0x03d1+(HReg << 10)+(AdrWord << 1);
+ WAsmCode[1]=((HVal & 0x3f) << 10)+(OpSize[4] << 8);
+ CodeLen=4;
+ END
+ END
+ break;
+ case 4:
+ if (DecideBranchLength(&AdrLong,4)) /* ??? */
+ if (AdrType[1]!=ModImm) WrError(1350);
+ else if (ImmVal(1)!=1) WrError(1135);
+ else if (OpSize[2]!=2) WrError(1130);
+ else if (AdrType[2]!=ModReg) WrError(1350);
+ else
+ BEGIN
+ WAsmCode[0]=0x03d0+(HReg << 10)+(AdrWord << 1);
+ WAsmCode[1]=((AdrMode[2] & 15) << 10)+(OpSize[4] << 8);
+ CodeLen=4;
+ END
+ break;
+ END
+ if (CodeLen>0)
+ switch (OpSize[4])
+ BEGIN
+ case 0:
+ WAsmCode[(CodeLen >> 1)-1]+=AdrLong & 0xff;
+ break;
+ case 1:
+ WAsmCode[CodeLen >> 1]=AdrLong & 0xffff;
+ CodeLen+=2;
+ break;
+ case 2:
+ WAsmCode[ CodeLen >> 1 ]=AdrLong >> 16;
+ WAsmCode[(CodeLen >> 1)+1]=AdrLong & 0xffff;
+ CodeLen+=4;
+ break;
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("TRAPA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1]+1,UInt4,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x03d5+(AdrWord << 10);
+ END
+ END
+ return;
+ END
+
+ if (strncmp(OpPart,"TRAP",4)==0)
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else
+ BEGIN
+ SplitOptions();
+ if (OptionCnt!=1) WrError(1115);
+ else if (NOT DecodeCondition(Options[0],&AdrWord)) WrError(1360);
+ else
+ BEGIN
+ CodeLen=2; WAsmCode[0]=0x03d4+(AdrWord << 10);
+ END
+ END
+ return;
+ END
+
+ /* Specials */
+
+ if ((Memo("ENTER")) OR (Memo("EXITD")))
+ BEGIN
+ if (Memo("EXITD"))
+ BEGIN
+ z=1; strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ else z=0;
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GE"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[1]==-1) OpSize[1]=2;
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[2]!=2) WrError(1130);
+ else if (DecodeAdr(ArgStr[1],1,MModReg+MModImm))
+ if (DecodeRegList(ArgStr[2],&AdrWord,z==1))
+ if ((z & 0xc000)!=0) WrXError(1410,"SP/FP");
+ else
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
+ else FormatCode=1;
+ END
+ else FormatCode=1;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ WAsmCode[0]=0x02f7;
+ WAsmCode[1]=0x8c00+(z << 12)+(OpSize[1] << 8)+AdrMode[1];
+ memcpy(WAsmCode+2,AdrVals[1],AdrCnt1[1]);
+ WAsmCode[2+AdrCnt2[1]]=AdrWord;
+ CodeLen=6+AdrCnt1[1];
+ break;
+ case 2:
+ if (AdrType[1]!=ModImm) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,-128,127))
+ BEGIN
+ WAsmCode[0]=0x8e00+(z << 12)+(HVal & 0xff);
+ WAsmCode[1]=AdrWord;
+ CodeLen=4;
+ END
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ if (strncmp(OpPart,"SCMP",4)==0)
+ BEGIN
+ if (DOpSize==-1) DOpSize=2;
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ SplitOptions();
+ if (OptionCnt>1) WrError(1115);
+ else
+ BEGIN
+ OK=True;
+ if (OptionCnt==0) AdrWord=6;
+ else if (strcasecmp(Options[0],"LTU")==0) AdrWord=0;
+ else if (strcasecmp(Options[0],"GEU")==0) AdrWord=1;
+ else OK=(DecodeCondition(Options[0],&AdrWord) AND (AdrWord>1) AND (AdrWord<6));
+ if (NOT OK) WrXError(1360,Options[0]);
+ else
+ BEGIN
+ WAsmCode[0]=0x00e0+(DOpSize << 8)+(AdrWord << 10);
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((strncmp(OpPart,"SMOV",4)==0) OR (strncmp(OpPart,"SSCH",4)==0))
+ BEGIN
+ if (DOpSize==-1) DOpSize=2;
+ z=Ord(OpPart[1]=='S') << 4;
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ SplitOptions();
+ if (strcasecmp(Options[0],"F")==0)
+ BEGIN
+ Mask=0; strcpy(Options[0],Options[1]); OptionCnt--;
+ END
+ else if (strcasecmp(Options[0],"B")==0)
+ BEGIN
+ Mask=1; strcpy(Options[0],Options[1]); OptionCnt--;
+ END
+ else if (strcasecmp(Options[1],"F")==0)
+ BEGIN
+ Mask=0; OptionCnt--;
+ END
+ else if (strcasecmp(Options[1],"B")==0)
+ BEGIN
+ Mask=1; OptionCnt--;
+ END
+ else Mask=0;
+ if (OptionCnt>1) WrError(1115);
+ else
+ BEGIN
+ OK=True;
+ if (OptionCnt==0) AdrWord=6;
+ else if (strcasecmp(Options[0],"LTU")==0) AdrWord=0;
+ else if (strcasecmp(Options[0],"GEU")==0) AdrWord=1;
+ else OK=(DecodeCondition(Options[0],&AdrWord)) AND (AdrWord>1) AND (AdrWord<6);
+ if (NOT OK) WrXError(1360,Options[0]);
+ else
+ BEGIN
+ WAsmCode[0]=0x00e4+(DOpSize << 8)+(AdrWord << 10)+Mask+z;
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("SSTR"))
+ BEGIN
+ if (DOpSize==-1) DOpSize=2;
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ WAsmCode[0]=0x24f7+(DOpSize << 8); CodeLen=2;
+ END
+ return;
+ END
+
+ if ((Memo("LDM")) OR (Memo("STM")))
+ BEGIN
+ Mask=MModIReg+MModDisp16+MModDisp32+MModAbs16+MModAbs32+MModPCRel16+MModPCRel32;
+ if (Memo("LDM"))
+ BEGIN
+ z=0x1000; Mask+=MModPop;
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ else
+ BEGIN
+ z=0; Mask+=MModPush;
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[1]==-1) OpSize[1]=2;
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if ((OpSize[1]!=2) OR (OpSize[2]!=2)) WrError(1130);
+ else if (DecodeAdr(ArgStr[2],2,Mask))
+ if (DecodeRegList(ArgStr[1],&AdrWord,AdrType[2]!=ModPush))
+ BEGIN
+ WAsmCode[0]=0x8a00+z+AdrMode[2];
+ memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
+ WAsmCode[1+AdrCnt2[2]]=AdrWord;
+ CodeLen=4+AdrCnt1[2];
+ END
+ END
+ return;
+ END
+
+ if ((Memo("STC")) OR (Memo("STP")))
+ BEGIN
+ z=Ord(Memo("STP")) << 10;
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ if (GetOpSize(ArgStr[1],1))
+ if (GetOpSize(ArgStr[2],2))
+ BEGIN
+ if (OpSize[2]==-1) OpSize[2]=2;
+ if (OpSize[1]==-1) OpSize[1]=OpSize[1];
+ if (OpSize[1]!=OpSize[2]) WrError(1132);
+ else if ((z==0) AND (OpSize[2]!=2)) WrError(1130);
+ else if (DecodeAdr(ArgStr[1],1,Mask_PureMem))
+ if (DecodeAdr(ArgStr[2],2,Mask_Dest))
+ BEGIN
+ OpSize[1]=0;
+ Make_G(0xa800+z);
+ WAsmCode[0]+=0x800;
+ END
+ END
+ return;
+ END
+
+ if (Memo("WAIT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ WAsmCode[1]=EvalIntExpression(ArgStr[1]+1,UInt3,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0x0fd6; CodeLen=4;
+ END
+ END
+ return;
+ END
+
+ if (Memo("JRNG"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("GE"))
+ if (GetOpSize(ArgStr[1],1))
+ BEGIN
+ if (OpSize[1]==-1) OpSize[1]=1;
+ if (OpSize[1]!=1) WrError(1130);
+ else if (DecodeAdr(ArgStr[1],1,MModReg+MModImm))
+ BEGIN
+ if (FormatCode==0)
+ BEGIN
+ if (AdrType[1]==ModImm)
+ BEGIN
+ HVal=ImmVal(1);
+ if ((HVal>=0) AND (HVal<=255)) FormatCode=2;
+ else FormatCode=1;
+ END
+ else FormatCode=1;
+ END
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ WAsmCode[0]=0xba00+AdrMode[1];
+ memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
+ CodeLen=2+AdrCnt1[1];
+ break;
+ case 2:
+ if (AdrType[1]!=ModImm) WrError(1350);
+ else
+ BEGIN
+ HVal=ImmVal(1);
+ if (ChkRange(HVal,0,255))
+ BEGIN
+ WAsmCode[0]=0xbe00+(HVal & 0xff); CodeLen=2;
+ END
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_M16(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_M16(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_M16(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x13; NOPCode=0x1bd6;
+ DivideChars=","; HasAttrs=True; AttrChars=".:";
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+#ifdef __STDC__
+ SegLimits[SegCode] = 0xfffffffful;
+#else
+ SegLimits[SegCode] = 0xffffffffl;
+#endif
+
+ MakeCode=MakeCode_M16; IsDef=IsDef_M16;
+ SwitchFrom=SwitchFrom_M16; InitFields();
+END
+
+ void codem16_init(void)
+BEGIN
+ CPUM16=AddCPU("M16",SwitchTo_M16);
+END
+
diff --git a/codem16.h b/codem16.h
new file mode 100644
index 0000000..311dd29
--- /dev/null
+++ b/codem16.h
@@ -0,0 +1,11 @@
+/* codem16.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Mitsubishi M16 */
+/* */
+/* Historie: 27.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codem16_init(void);
diff --git a/codem16c.c b/codem16c.c
new file mode 100644
index 0000000..ae03b86
--- /dev/null
+++ b/codem16c.c
@@ -0,0 +1,2360 @@
+/* codem16c.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator M16C */
+/* */
+/* Historie: 17.12.1996 Grundsteinlegung */
+/* 21. 9.1998 Kodierungsfehler: mov.b:s #0,...->dests vergessen */
+/* mov.x:s #imm,reg->OpSize invertiert*/
+/* sub.x:q #imm4,...->falscher Opcode */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* {RMS} 6. 2.1999 Fixed remaining code generation errors - M16C is now */
+/* 100% correct, validated against reference assemblers */
+/* and official Mitsubishi documentation. */
+/* Search for RMS: tags to see changes */
+/* {RMS} 8. 2.1999 Fixed ChkPC SegLimit typo [M16s have 20 bits] */
+/* {RMS} 10. 2.1999 Accomodate JMP.S crossing 64k boundary bug in M16C */
+/* {RMS} 2. 4.1999 Made the JMP.S promotion fix CPU-dependent, and made */
+/* repairs to the JMP.S handling for forward label refs */
+/* so they now work. [JMP.S symbol] now works. */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include "string.h"
+#include <ctype.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+#define ModNone (-1)
+#define ModGen 0
+#define MModGen (1 << ModGen)
+#define ModAbs20 1
+#define MModAbs20 (1 << ModAbs20)
+#define ModAReg32 2
+#define MModAReg32 (1 << ModAReg32)
+#define ModDisp20 3
+#define MModDisp20 (1 << ModDisp20)
+#define ModReg32 4
+#define MModReg32 (1 << ModReg32)
+#define ModIReg32 5
+#define MModIReg32 (1 << ModIReg32)
+#define ModImm 6
+#define MModImm (1 << ModImm)
+#define ModSPRel 7
+#define MModSPRel (1 << ModSPRel)
+
+#define FixedOrderCnt 8
+#define StringOrderCnt 4
+#define Gen1OrderCnt 5
+#define Gen2OrderCnt 6
+#define DivOrderCnt 3
+#define ConditionCnt 18
+#define BCDOrderCnt 4
+#define DirOrderCnt 4
+#define BitOrderCnt 13
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code1,Code2,Code3;
+ } Gen2Order;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } Condition;
+
+
+static char *Flags="CDZSBOIU";
+
+static CPUVar CPUM16C,CPUM30600M8,CPUM30610,CPUM30620;
+
+static String Format;
+static Byte FormatCode;
+static ShortInt OpSize;
+static Byte AdrMode,AdrMode2;
+static ShortInt AdrType,AdrType2;
+static Byte AdrCnt2;
+static Byte AdrVals[3],AdrVals2[3];
+
+static FixedOrder *FixedOrders;
+static FixedOrder *StringOrders;
+static FixedOrder *Gen1Orders;
+static Gen2Order *Gen2Orders;
+static Gen2Order *DivOrders;
+static Condition *Conditions;
+static char **BCDOrders;
+static char **DirOrders;
+static FixedOrder *BitOrders;
+
+/*------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddString(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=StringOrderCnt) exit(255);
+ StringOrders[InstrZ].Name=NName;
+ StringOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddGen1(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Gen1OrderCnt) exit(255);
+ Gen1Orders[InstrZ].Name=NName;
+ Gen1Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddGen2(char *NName, Byte NCode1, Byte NCode2, Byte NCode3)
+BEGIN
+ if (InstrZ>=Gen2OrderCnt) exit(255);
+ Gen2Orders[InstrZ].Name=NName;
+ Gen2Orders[InstrZ].Code1=NCode1;
+ Gen2Orders[InstrZ].Code2=NCode2;
+ Gen2Orders[InstrZ++].Code3=NCode3;
+END
+
+ static void AddDiv(char *NName, Byte NCode1, Byte NCode2, Byte NCode3)
+BEGIN
+ if (InstrZ>=DivOrderCnt) exit(255);
+ DivOrders[InstrZ].Name=NName;
+ DivOrders[InstrZ].Code1=NCode1;
+ DivOrders[InstrZ].Code2=NCode2;
+ DivOrders[InstrZ++].Code3=NCode3;
+END
+
+ static void AddCondition(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ConditionCnt) exit(255);
+ Conditions[InstrZ].Name=NName;
+ Conditions[InstrZ++].Code=NCode;
+END
+
+ static void AddBCD(char *NName)
+BEGIN
+ if (InstrZ>=BCDOrderCnt) exit(255);
+ BCDOrders[InstrZ++]=NName;
+END
+
+ static void AddDir(char *NName)
+BEGIN
+ if (InstrZ>=DirOrderCnt) exit(255);
+ DirOrders[InstrZ++]=NName;
+END
+
+ static void AddBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=BitOrderCnt) exit(255);
+ BitOrders[InstrZ].Name=NName;
+ BitOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstrZ=0; FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt);
+ AddFixed("BRK" ,0x0000);
+ AddFixed("EXITD" ,0x7df2);
+ AddFixed("INTO" ,0x00f6);
+ AddFixed("NOP" ,0x0004);
+ AddFixed("REIT" ,0x00fb);
+ AddFixed("RTS" ,0x00f3);
+ AddFixed("UND" ,0x00ff);
+ AddFixed("WAIT" ,0x7df3);
+
+ InstrZ=0; StringOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*StringOrderCnt);
+ AddString("RMPA" ,0x7cf1);
+ AddString("SMOVB",0x7ce9);
+ AddString("SMOVF",0x7ce8);
+ AddString("SSTR" ,0x7cea);
+
+ InstrZ=0; Gen1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Gen1OrderCnt);
+ AddGen1("ABS" ,0x76f0);
+ AddGen1("ADCF",0x76e0);
+ AddGen1("NEG" ,0x7450);
+ AddGen1("ROLC",0x76a0);
+ AddGen1("RORC",0x76b0);
+
+ InstrZ=0; Gen2Orders=(Gen2Order *) malloc(sizeof(Gen2Order)*Gen2OrderCnt);
+ AddGen2("ADC" ,0xb0,0x76,0x60);
+ AddGen2("SBB" ,0xb8,0x76,0x70);
+ AddGen2("TST" ,0x80,0x76,0x00);
+ AddGen2("XOR" ,0x88,0x76,0x10);
+ AddGen2("MUL" ,0x78,0x7c,0x50);
+ AddGen2("MULU",0x70,0x7c,0x40);
+
+ InstrZ=0; DivOrders=(Gen2Order *) malloc(sizeof(Gen2Order)*DivOrderCnt);
+ AddDiv("DIV" ,0xe1,0x76,0xd0);
+ AddDiv("DIVU",0xe0,0x76,0xc0);
+ AddDiv("DIVX",0xe3,0x76,0x90);
+
+ InstrZ=0; Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCnt);
+ AddCondition("GEU", 0); AddCondition("C" , 0);
+ AddCondition("GTU", 1); AddCondition("EQ" , 2);
+ AddCondition("Z" , 2); AddCondition("N" , 3);
+ AddCondition("LTU", 4); AddCondition("NC" , 4);
+ AddCondition("LEU", 5); AddCondition("NE" , 6);
+ AddCondition("NZ" , 6); AddCondition("PZ" , 7);
+ AddCondition("LE" , 8); AddCondition("O" , 9);
+ AddCondition("GE" ,10); AddCondition("GT" ,12);
+ AddCondition("NO" ,13); AddCondition("LT" ,14);
+
+ InstrZ=0; BCDOrders=(char **) malloc(sizeof(char *)*BCDOrderCnt);
+ AddBCD("DADD"); AddBCD("DSUB"); AddBCD("DADC"); AddBCD("DSBB");
+
+ InstrZ=0; DirOrders=(char **) malloc(sizeof(char *)*DirOrderCnt);
+ AddDir("MOVLL"); AddDir("MOVHL"); AddDir("MOVLH"); AddDir("MOVHH");
+
+ InstrZ=0; BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCnt);
+ AddBit("BAND" , 4); AddBit("BNAND" , 5);
+ AddBit("BNOR" , 7); AddBit("BNTST" , 3);
+ AddBit("BNXOR" ,13); AddBit("BOR" , 6);
+ AddBit("BTSTC" , 0); AddBit("BTSTS" , 1);
+ AddBit("BXOR" ,12); AddBit("BCLR" , 8);
+ AddBit("BNOT" ,10); AddBit("BSET" , 9);
+ AddBit("BTST" ,11);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(StringOrders);
+ free(Gen1Orders);
+ free(Gen2Orders);
+ free(DivOrders);
+ free(Conditions);
+ free(BCDOrders);
+ free(DirOrders);
+ free(BitOrders);
+END
+
+/*------------------------------------------------------------------------*/
+/* Adressparser */
+
+ static void SetOpSize(ShortInt NSize)
+BEGIN
+ if (OpSize==-1) OpSize=NSize;
+ else if (NSize!=OpSize)
+ BEGIN
+ WrError(1131);
+ AdrCnt=0; AdrType=ModNone;
+ END
+END
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrType!=ModNone) AND ((Mask & (1 << AdrType))==0))
+ BEGIN
+ AdrCnt=0; AdrType=ModNone; WrError(1350);
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ LongInt DispAcc;
+ String RegPart;
+ char *p;
+ Boolean OK;
+
+ AdrCnt=0; AdrType=ModNone;
+
+ /* Datenregister 8 Bit */
+
+ if ((strlen(Asc)==3) AND (toupper(*Asc)=='R') AND (Asc[1]>='0') AND (Asc[1]<='1') AND
+ ((toupper(Asc[2])=='L') OR (toupper(Asc[2])=='H')))
+ BEGIN
+ AdrType=ModGen;
+ AdrMode=((Asc[1]-'0') << 1)+Ord(toupper(Asc[2])=='H');
+ SetOpSize(0);
+ ChkAdr(Mask); return;
+ END;
+
+ /* Datenregister 16 Bit */
+
+ if ((strlen(Asc)==2) AND (toupper(*Asc)=='R') AND (Asc[1]>='0') AND (Asc[1]<='3'))
+ BEGIN
+ AdrType=ModGen;
+ AdrMode=Asc[1]-'0';
+ SetOpSize(1);
+ ChkAdr(Mask); return;
+ END
+
+ /* Datenregister 32 Bit */
+
+ if (strcasecmp(Asc,"R2R0")==0)
+ BEGIN
+ AdrType=ModReg32; AdrMode=0;
+ SetOpSize(2);
+ ChkAdr(Mask); return;
+ END;
+
+ if (strcasecmp(Asc,"R3R1")==0)
+ BEGIN
+ AdrType=ModReg32; AdrMode=1;
+ SetOpSize(2);
+ ChkAdr(Mask); return;
+ END
+
+ /* Adressregister */
+
+ if ((strlen(Asc)==2) AND (toupper(*Asc)=='A') AND (Asc[1]>='0') AND (Asc[1]<='1'))
+ BEGIN
+ AdrType=ModGen;
+ AdrMode=Asc[1]-'0'+4;
+ ChkAdr(Mask); return;
+ END
+
+ /* Adressregister 32 Bit */
+
+ if (strcasecmp(Asc,"A1A0")==0)
+ BEGIN
+ AdrType=ModAReg32;
+ SetOpSize(2);
+ ChkAdr(Mask); return;
+ END
+
+ /* indirekt */
+
+ p=strchr(Asc,'[');
+ if ((p!=Nil) AND (Asc[strlen(Asc)-1]==']'))
+ BEGIN
+ strmaxcpy(RegPart,p+1,255); RegPart[strlen(RegPart)-1]='\0';
+ if ((strcasecmp(RegPart,"A0")==0) OR (strcasecmp(RegPart,"A1")==0))
+ BEGIN
+ *p='\0';
+ DispAcc=EvalIntExpression(Asc,((Mask & MModDisp20)==0)?Int16:Int20,&OK);
+ if (OK)
+ if ((DispAcc==0) AND ((Mask & MModGen)!=0))
+ BEGIN
+ AdrType=ModGen;
+ AdrMode=RegPart[1]-'0'+6;
+ END
+ else if ((DispAcc>=0) AND (DispAcc<=255) AND ((Mask & MModGen)!=0))
+ BEGIN
+ AdrType=ModGen;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrCnt=1;
+ AdrMode=RegPart[1]-'0'+8;
+ END
+ else if ((DispAcc>=-32768) AND (DispAcc<=65535) AND ((Mask & MModGen)!=0))
+ BEGIN
+ AdrType=ModGen;
+ AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrCnt=2;
+ AdrMode=RegPart[1]-'0'+12;
+ END
+ else if (strcasecmp(RegPart,"A0")!=0) WrError(1350);
+ else
+ BEGIN
+ AdrType=ModDisp20;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrVals[2]=(DispAcc >> 16) & 0x0f;
+ AdrCnt=3;
+ AdrMode=RegPart[1]-'0';
+ END
+ END
+ else if (strcasecmp(RegPart,"SB")==0)
+ BEGIN
+ *p='\0';
+ DispAcc=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ if ((DispAcc>=0) AND (DispAcc<=255))
+ BEGIN
+ AdrType=ModGen;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrCnt=1;
+ AdrMode=10;
+ END
+ else
+ BEGIN
+ AdrType=ModGen;
+ AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrCnt=2;
+ AdrMode=14;
+ END
+ END
+ else if (strcasecmp(RegPart,"FB")==0)
+ BEGIN
+ *p='\0';
+ DispAcc=EvalIntExpression(Asc,SInt8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModGen;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrCnt=1;
+ AdrMode=11;
+ END
+ END
+ else if (strcasecmp(RegPart,"SP")==0)
+ BEGIN
+ *p='\0';
+ DispAcc=EvalIntExpression(Asc,SInt8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModSPRel;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrCnt=1;
+ END
+ END
+ else if (strcasecmp(RegPart,"A1A0")==0)
+ BEGIN
+ *p='\0';
+ DispAcc=EvalIntExpression(Asc,SInt8,&OK);
+ if (OK)
+ if (DispAcc!=0) WrError(1320);
+ else AdrType=ModIReg32;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* immediate */
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case -1:
+ WrError(1132);
+ break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrCnt=1;
+ END
+ break;
+ case 1:
+ DispAcc=EvalIntExpression(Asc+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrCnt=2;
+ END
+ break;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* dann absolut */
+
+ DispAcc=EvalIntExpression(Asc,((Mask & MModAbs20)==0)?UInt16:UInt20,&OK);
+ if ((DispAcc<=0xffff) AND ((Mask & MModGen)!=0))
+ BEGIN
+ AdrType=ModGen;
+ AdrMode=15;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrCnt=2;
+ END
+ else
+ BEGIN
+ AdrType=ModAbs20;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrVals[2]=(DispAcc >> 16) & 0x0f;
+ AdrCnt=3;
+ END
+
+ ChkAdr(Mask);
+END
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg)
+BEGIN
+ if (strcasecmp(Asc,"FB")==0) *Erg=7;
+ else if (strcasecmp(Asc,"SB")==0) *Erg=6;
+ else if ((strlen(Asc)==2) AND (toupper(*Asc)=='A') AND
+ (Asc[1]>='0') AND (Asc[1]<='1')) *Erg=Asc[1]-'0'+4;
+ else if ((strlen(Asc)==2) AND (toupper(*Asc)=='R') AND
+ (Asc[1]>='0') AND (Asc[1]<='3')) *Erg=Asc[1]-'0';
+ else return False;
+ return True;
+END
+
+ static Boolean DecodeCReg(char *Asc, Byte *Erg)
+BEGIN
+ if (strcasecmp(Asc,"INTBL")==0) *Erg=1;
+ else if (strcasecmp(Asc,"INTBH")==0) *Erg=2;
+ else if (strcasecmp(Asc,"FLG")==0) *Erg=3;
+ else if (strcasecmp(Asc,"ISP")==0) *Erg=4;
+ else if (strcasecmp(Asc,"SP")==0) *Erg=5;
+ else if (strcasecmp(Asc,"SB")==0) *Erg=6;
+ else if (strcasecmp(Asc,"FB")==0) *Erg=7;
+ else
+ BEGIN
+ WrXError(1440,Asc); return False;
+ END
+ return True;
+END
+
+ static void DecodeDisp(char *Asc, IntType Type1, IntType Type2, LongInt *DispAcc, Boolean *OK)
+BEGIN
+ if (ArgCnt==2) *DispAcc+=EvalIntExpression(Asc,Type2,OK)*8;
+ else *DispAcc=EvalIntExpression(Asc,Type1,OK);
+END
+
+ static Boolean DecodeBitAdr(Boolean MayShort)
+BEGIN
+ LongInt DispAcc;
+ Boolean OK;
+ char *Pos1;
+ String Asc,Reg;
+
+ AdrCnt=0;
+
+ /* Nur 1 oder 2 Argumente zugelassen */
+
+ if ((ArgCnt<1) OR (ArgCnt>2))
+ BEGIN
+ WrError(1110); return False;
+ END
+
+ /* Ist Teil 1 ein Register ? */
+
+ if ((DecodeReg(ArgStr[ArgCnt],&AdrMode)))
+ if (AdrMode<6)
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrVals[0]=EvalIntExpression(ArgStr[1],UInt4,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; return True;
+ END
+ END
+ return False;
+ END
+
+ /* Bitnummer ? */
+
+ if (ArgCnt==2)
+ BEGIN
+ DispAcc=EvalIntExpression(ArgStr[1],UInt16,&OK); /* RMS 02: The displacement can be 16 bits */
+ if (NOT OK) return False;
+ END
+ else DispAcc=0;
+
+ /* Registerangabe ? */
+
+ strmaxcpy(Asc,ArgStr[ArgCnt],255);
+ Pos1=QuotPos(Asc,'[');
+
+ /* nein->absolut */
+
+ if (Pos1==Nil)
+ BEGIN
+ DecodeDisp(Asc,UInt16,UInt13,&DispAcc,&OK);
+ if ((OK) && (DispAcc<0x10000)) /* RMS 09: This is optional, it detects rollover of the bit address. */
+ BEGIN
+ AdrMode=15;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrCnt=2;
+ return True;
+ END
+ WrError(1510); /* RMS 08: Notify user there's a problem with address */
+ return False;
+ END
+
+ /* Register abspalten */
+
+ if (Asc[strlen(Asc)-1]!=']')
+ BEGIN
+ WrError(1350); return False;
+ END
+ *Pos1='\0'; strmaxcpy(Reg,Pos1+1,255); Reg[strlen(Reg)-1]='\0';
+
+ if ((strlen(Reg)==2) AND (toupper(*Reg)=='A') AND (Reg[1]>='0') AND (Reg[1]<='1'))
+ BEGIN
+ AdrMode=Reg[1]-'0';
+ DecodeDisp(Asc,UInt16,UInt16,&DispAcc,&OK); /* RMS 03: The offset is a full 16 bits */
+ if (OK)
+ BEGIN
+ if (DispAcc==0) AdrMode+=6;
+ else if ((DispAcc>0) AND (DispAcc<256))
+ BEGIN
+ AdrMode+=8; AdrVals[0]=DispAcc & 0xff; AdrCnt=1;
+ END
+ else
+ BEGIN
+ AdrMode+=12;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrCnt=2;
+ END
+ return True;
+ END
+ WrError(1510); /* RMS 08: Notify user there's a problem with the offset */
+ return False;
+ END
+ else if (strcasecmp(Reg,"SB")==0)
+ BEGIN
+ DecodeDisp(Asc,UInt13,UInt16,&DispAcc,&OK);
+ if (OK)
+ BEGIN
+ if ((MayShort) AND (DispAcc<0x7ff))
+ BEGIN
+ AdrMode=16+(DispAcc & 7);
+ AdrVals[0]=DispAcc >> 3; AdrCnt=1;
+ END
+ else if ((DispAcc>0) AND (DispAcc<256))
+ BEGIN
+ AdrMode=10; AdrVals[0]=DispAcc & 0xff; AdrCnt=1;
+ END
+ else
+ BEGIN
+ AdrMode=14;
+ AdrVals[0]=DispAcc & 0xff;
+ AdrVals[1]=(DispAcc >> 8) & 0xff;
+ AdrCnt=2;
+ END
+ return True;
+ END
+ WrError(1510); /* RMS 08: Notify user there's a problem with the offset */
+ return False;
+ END
+ else if (strcasecmp(Reg,"FB")==0)
+ BEGIN
+ DecodeDisp(Asc,SInt5,SInt8,&DispAcc,&OK);
+ if (OK)
+ BEGIN
+ AdrMode=11; AdrVals[0]=DispAcc & 0xff; AdrCnt=1;
+ return True;
+ END
+ WrError(1510); /* RMS 08: Notify user there's a problem with the offset */
+ return False;
+ END
+ else
+ BEGIN
+ WrXError(1445,Reg);
+ return False;
+ END
+END
+
+/*------------------------------------------------------------------------*/
+
+ static Boolean CheckFormat(char *FSet)
+BEGIN
+ char *p;
+
+ if (strcmp(Format," ")==0)
+ BEGIN
+ FormatCode=0; return True;
+ END
+ else
+ BEGIN
+ p=strchr(FSet,*Format);
+ if (p==Nil) WrError(1090);
+ else FormatCode=p-FSet+1;
+ return (p!=0);
+ END
+END
+
+ static Integer ImmVal(void)
+BEGIN
+ if (OpSize==0) return (ShortInt)AdrVals[0];
+ else return (((Integer)AdrVals[1]) << 8)+AdrVals[0];
+END
+
+ static Boolean IsShort(Byte GenMode, Byte *SMode)
+BEGIN
+ switch (GenMode)
+ BEGIN
+ case 0: *SMode=4; break;
+ case 1: *SMode=3; break;
+ case 10: *SMode=5; break;
+ case 11: *SMode=6; break;
+ case 15: *SMode=7; break;
+ default: return False;
+ END
+ return True;
+END
+
+/*------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void CopyAdr(void)
+BEGIN
+ AdrType2=AdrType;
+ AdrMode2=AdrMode;
+ AdrCnt2=AdrCnt;
+ memcpy(AdrVals2,AdrVals,AdrCnt2);
+END
+
+ static void CodeGen(Byte GenCode,Byte Imm1Code,Byte Imm2Code)
+BEGIN
+ if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[0]=Imm1Code+OpSize;
+ BAsmCode[1]=Imm2Code+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ memcpy(BAsmCode+2+AdrCnt2,AdrVals,AdrCnt);
+ END
+ else
+ BEGIN
+ BAsmCode[0]=GenCode+OpSize;
+ BAsmCode[1]=(AdrMode << 4)+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ memcpy(BAsmCode+2+AdrCnt,AdrVals2,AdrCnt2);
+ END
+ CodeLen=2+AdrCnt+AdrCnt2;
+END
+
+ static Boolean CodeData(void)
+BEGIN
+ Integer Num1;
+ int z;
+ Boolean OK;
+ Byte SMode;
+
+ if (Memo("MOV"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GSQZ"))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModGen+MModSPRel);
+ if (AdrType!=ModNone)
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[1],MModGen+MModSPRel+MModImm);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ if (FormatCode==0)
+ if ((AdrType2==ModSPRel) OR (AdrType==ModSPRel)) FormatCode=1;
+ else if ((OpSize==0) AND (AdrType==ModImm) AND (IsShort(AdrMode2,&SMode)))
+ FormatCode=(ImmVal()==0) ? 4 : 2;
+ else if ((AdrType==ModImm) AND (ImmVal()>=-8) AND (ImmVal()<=7)) FormatCode=3;
+ else if ((AdrType==ModImm) AND ((AdrMode2 & 14)==4)) FormatCode=2;
+ else if ((OpSize==0) AND (AdrType==ModGen) AND (IsShort(AdrMode,&SMode)) AND ((AdrMode2 & 14)==4)
+ AND ((AdrMode>=2) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=2;
+ else if ((OpSize==0) AND (AdrType==ModGen) AND (AdrMode<=1) AND (IsShort(AdrMode2,&SMode))
+ AND ((AdrMode2>=2) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=2;
+ else if ((OpSize==0) AND (AdrMode2<=1) AND (AdrType==ModGen) AND (IsShort(AdrMode,&SMode))
+ AND ((AdrMode>=2) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=2;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ if (AdrType==ModSPRel)
+ BEGIN
+ BAsmCode[0]=0x74+OpSize;
+ BAsmCode[1]=0xb0+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ memcpy(BAsmCode+2+AdrCnt2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt+AdrCnt2;
+ END
+ else if (AdrType2==ModSPRel)
+ BEGIN
+ BAsmCode[0]=0x74+OpSize;
+ BAsmCode[1]=0x30+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ memcpy(BAsmCode+2+AdrCnt,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2+AdrCnt;
+ END
+ else CodeGen(0x72,0x74,0xc0);
+ break;
+ case 2:
+ if (AdrType==ModImm)
+ if (AdrType2!=ModGen) WrError(1350);
+ else if ((AdrMode2 & 14)==4)
+ BEGIN
+ BAsmCode[0]=0xe2-(OpSize << 6)+((AdrMode2 & 1) << 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ else if (IsShort(AdrMode2,&SMode))
+ if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=0xc0+SMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ memcpy(BAsmCode+1+AdrCnt,AdrVals2,AdrCnt2);
+ CodeLen=1+AdrCnt+AdrCnt2;
+ END
+ else WrError(1350);
+ else if ((AdrType==ModGen) AND (IsShort(AdrMode,&SMode)))
+ if (AdrType2!=ModGen) WrError(1350);
+ else if ((AdrMode2 & 14)==4)
+ if ((AdrMode<=1) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350);
+ else
+ BEGIN
+ if (SMode==3) SMode++;
+ BAsmCode[0]=0x30+((AdrMode2 & 1) << 2)+(SMode & 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ else if ((AdrMode2 & 14)==0)
+ if ((AdrMode<=1) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350);
+ else
+ BEGIN
+ if (SMode==3) SMode++;
+ BAsmCode[0]=0x08+((AdrMode2 & 1) << 2)+(SMode & 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ else if (((AdrMode & 14)!=0) OR (NOT IsShort(AdrMode2,&SMode))) WrError(1350);
+ else if ((AdrMode2<=1) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350);
+ else
+ BEGIN
+ if (SMode==3) SMode++;
+ BAsmCode[0]=0x00+((AdrMode & 1) << 2)+(SMode & 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt2);
+ CodeLen=1+AdrCnt2;
+ END
+ else WrError(1350);
+ break;
+ case 3:
+ if (AdrType!=ModImm) WrError(1350);
+ else
+ BEGIN
+ Num1=ImmVal();
+ if (ChkRange(Num1,-8,7))
+ BEGIN
+ BAsmCode[0]=0xd8+OpSize;
+ BAsmCode[1]=(Num1 << 4)+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ END
+ break;
+ case 4:
+ if (OpSize!=0) WrError(1130);
+ else if (AdrType!=ModImm) WrError(1350);
+ else if (NOT IsShort(AdrMode2,&SMode)) WrError(1350);
+ else
+ BEGIN
+ Num1=ImmVal();
+ if (ChkRange(Num1,0,0))
+ BEGIN
+ BAsmCode[0]=0xb0+SMode;
+ memcpy(BAsmCode+1,AdrVals2,AdrCnt2);
+ CodeLen=1+AdrCnt2;
+ END
+ END
+ break;
+ END
+ END;
+ END;
+ END
+ return True;
+ END
+
+ if ((Memo("LDC")) OR (Memo("STC")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ if (Memo("STC"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ z=1;
+ END
+ else z=0;
+ if (strcasecmp(ArgStr[2],"PC")==0)
+ if (Memo("LDC")) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen+MModReg32+MModAReg32);
+ if (AdrType==ModAReg32) AdrMode=4;
+ if ((AdrType==ModGen) AND (AdrMode<6)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x7c; BAsmCode[1]=0xc0+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ else if (DecodeCReg(ArgStr[2],&SMode))
+ BEGIN
+ SetOpSize(1);
+ DecodeAdr(ArgStr[1],MModGen+(Memo("LDC")?MModImm:0));
+ if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[0]=0xeb; BAsmCode[1]=SMode << 4;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ else if (AdrType==ModGen)
+ BEGIN
+ BAsmCode[0]=0x7a+z; BAsmCode[1]=0x80+(SMode << 4)+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("LDCTX")) OR (Memo("STCTX")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen);
+ if (AdrType==ModGen)
+ if (AdrMode!=15) WrError(1350);
+ else
+ BEGIN
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModAbs20);
+ if (AdrType==ModAbs20)
+ BEGIN
+ memcpy(BAsmCode+4,AdrVals,AdrCnt);
+ BAsmCode[0]=0x7c+Ord(Memo("STCTX"));
+ BAsmCode[1]=0xf0;
+ CodeLen=7;
+ END
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("LDE")) OR (Memo("STE")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ if (Memo("LDE"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]);
+ strcpy(ArgStr[1],ArgStr[2]);
+ strcpy(ArgStr[2],ArgStr[3]);
+ z=1;
+ END
+ else z=0;
+ DecodeAdr(ArgStr[1],MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize>1) WrError(1130);
+ else
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[2],MModAbs20+MModDisp20+MModIReg32);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x74+OpSize;
+ BAsmCode[1]=(z << 7)+AdrMode2;
+ switch (AdrType)
+ BEGIN
+ case ModDisp20: BAsmCode[1]+=0x10; break;
+ case ModIReg32: BAsmCode[1]+=0x20; break;
+ END
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ memcpy(BAsmCode+2+AdrCnt2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt2+AdrCnt;
+ END
+ END
+ END
+ return True;
+ END
+
+ if (Memo("MOVA"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen);
+ if (AdrType!=ModNone)
+ if (AdrMode<8) WrError(1350);
+ else
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ if (AdrMode>5) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xeb;
+ BAsmCode[1]=(AdrMode << 4)+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ END
+ END
+ return True;
+ END
+
+ for (z=0; z<DirOrderCnt; z++)
+ if (Memo(DirOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (OpSize>0) WrError(1130);
+ else if (CheckFormat("G"))
+ BEGIN
+ OK=True; Num1=0;
+ if (strcasecmp(ArgStr[2],"R0L")==0);
+ else if (strcasecmp(ArgStr[1],"R0L")==0) Num1=1;
+ else OK=False;
+ if (NOT OK) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[Num1+1],MModGen);
+ if (AdrType!=ModNone)
+ if (((AdrMode & 14)==4) OR ((AdrMode==0) AND (Num1==1))) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x7c; BAsmCode[1]=(Num1 << 7)+(z << 4)+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("GS"))
+ BEGIN
+ z=Ord(Memo("POP"));
+ DecodeAdr(ArgStr[1],MModGen+((Memo("PUSH"))?MModImm:0));
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize>1) WrError(1130);
+ else
+ BEGIN
+ if (FormatCode==0)
+ if ((AdrType!=ModGen)) FormatCode=1;
+ else if ((OpSize==0) AND (AdrMode<2)) FormatCode=2;
+ else if ((OpSize==1) AND ((AdrMode & 14)==4)) FormatCode=2;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[0]=0x7c+OpSize;
+ BAsmCode[1]=0xe2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x74+OpSize;
+ BAsmCode[1]=0x40+(z*0x90)+AdrMode;
+ END
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ case 2:
+ if (AdrType!=ModGen) WrError(1350);
+ else if ((OpSize==0) AND (AdrMode<2))
+ BEGIN
+ BAsmCode[0]=0x82+(AdrMode << 3)+(z << 4);
+ CodeLen=1;
+ END
+ else if ((OpSize==1) AND ((AdrMode & 14)==4))
+ BEGIN
+ BAsmCode[0]=0xc2+((AdrMode & 1) << 3)+(z << 4);
+ CodeLen=1;
+ END
+ else WrError(1350);
+ break;
+ END
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("PUSHC")) OR (Memo("POPC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ if (DecodeCReg(ArgStr[1],&SMode))
+ BEGIN
+ BAsmCode[0]=0xeb;
+ BAsmCode[1]=0x02+Ord(Memo("POPC"))+(SMode << 4);
+ CodeLen=2;
+ END
+ return True;
+ END
+
+ if ((Memo("PUSHM")) OR (Memo("POPM")))
+ BEGIN
+ if (ArgCnt<1) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[1]=0; OK=True; z=1;
+ while ((OK) AND (z<=ArgCnt))
+ BEGIN
+ OK=DecodeReg(ArgStr[z],&SMode);
+ if (OK)
+ BEGIN
+ BAsmCode[1]|=(1<<((Memo("POPM"))?SMode:7-SMode));
+ z++;
+ END
+ END
+ if (NOT OK) WrXError(1440,ArgStr[z]);
+ else
+ BEGIN
+ BAsmCode[0]=0xec+Ord(Memo("POPM"));
+ CodeLen=2;
+ END
+ END
+ return True;
+ END
+
+ if (Memo("PUSHA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen);
+ if (AdrType!=ModNone)
+ if (AdrMode<8) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x7d;
+ BAsmCode[1]=0x90+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ return True;
+ END
+
+ if (Memo("XCHG"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen);
+ if (AdrType!=ModNone)
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize>1) WrError(1130);
+ else if (AdrMode<4)
+ BEGIN
+ BAsmCode[0]=0x7a+OpSize;
+ BAsmCode[1]=(AdrMode << 4)+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ else if (AdrMode2<4)
+ BEGIN
+ BAsmCode[0]=0x7a+OpSize;
+ BAsmCode[1]=(AdrMode2 << 4)+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ else WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("STZ")) OR (Memo("STNZ")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ if (OpSize==-1) OpSize++;
+ DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ if (NOT IsShort(AdrMode,&SMode)) WrError(1350);
+ else
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[1],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xc8+(Ord(Memo("STNZ")) << 3)+SMode;
+ BAsmCode[1]=AdrVals[0];
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("STZX")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ if (OpSize==-1) OpSize++;
+ DecodeAdr(ArgStr[3],MModGen);
+ if (AdrType!=ModNone)
+ if (NOT IsShort(AdrMode,&SMode)) WrError(1350);
+ else
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[1],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ Num1=AdrVals[0]; DecodeAdr(ArgStr[2],MModImm);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xd8+SMode;
+ BAsmCode[1]=Num1;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ BAsmCode[2+AdrCnt2]=AdrVals[0];
+ CodeLen=3+AdrCnt2;
+ END
+ END
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_M16C(void)
+BEGIN
+ Integer Num1;
+ int z;
+ char *p;
+ LongInt AdrLong,Diff;
+ Boolean OK,MayShort;
+ Byte SMode;
+ ShortInt OpSize2;
+
+ OpSize=(-1);
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Formatangabe abspalten */
+
+ switch (AttrSplit)
+ BEGIN
+ case '.':
+ p=strchr(AttrPart,':');
+ if (p!=Nil)
+ BEGIN
+ if (p<AttrPart+strlen(AttrPart)-1) strmaxcpy(Format,p+1,255);
+ *p='\0';
+ END
+ else strcpy(Format," ");
+ break;
+ case ':':
+ p=strchr(AttrPart,'.');
+ if (p==Nil)
+ BEGIN
+ strmaxcpy(Format,AttrPart,255); *AttrPart='\0';
+ END
+ else
+ BEGIN
+ *p='\0';
+ strmaxcpy(Format,(p==AttrPart)?" ":AttrPart,255);
+ END
+ break;
+ default:
+ strcpy(Format," ");
+ END
+
+ /* Attribut abarbeiten */
+
+ switch (toupper(*AttrPart))
+ BEGIN
+ case '\0': OpSize=(-1); break;
+ case 'B': OpSize=0; break;
+ case 'W': OpSize=1; break;
+ case 'L': OpSize=2; break;
+ case 'Q': OpSize=3; break;
+ case 'S': OpSize=4; break;
+ case 'D': OpSize=5; break;
+ case 'X': OpSize=6; break;
+ case 'A': OpSize=7; break;
+ default:
+ WrError(1107); return;
+ END
+ NLS_UpString(Format);
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (Hi(FixedOrders[z].Code)==0)
+ BEGIN
+ BAsmCode[0]=Lo(FixedOrders[z].Code); CodeLen=1;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=Hi(FixedOrders[z].Code);
+ BAsmCode[1]=Lo(FixedOrders[z].Code); CodeLen=2;
+ END;
+ return;
+ END
+
+ for (z=0; z<StringOrderCnt; z++)
+ if (Memo(StringOrders[z].Name))
+ BEGIN
+ if (OpSize==-1) OpSize=1;
+ if (ArgCnt!=0) WrError(1110);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else if (Hi(StringOrders[z].Code)==0)
+ BEGIN
+ BAsmCode[0]=Lo(StringOrders[z].Code)+OpSize; CodeLen=1;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=Hi(StringOrders[z].Code)+OpSize;
+ BAsmCode[1]=Lo(StringOrders[z].Code); CodeLen=2;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (CodeData()) return;
+
+ /* Arithmetik */
+
+ if (Memo("ADD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[2],"SP")==0)
+ BEGIN
+ if (OpSize==-1) OpSize=1;
+ if (CheckFormat("GQ"))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModImm);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize>1) WrError(1130);
+ else
+ BEGIN
+ AdrLong=ImmVal();
+ if (FormatCode==0)
+ if ((AdrLong>=-8) AND (AdrLong<=7)) FormatCode=2;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ BAsmCode[0]=0x7c+OpSize;
+ BAsmCode[1]=0xeb;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ case 2:
+ if (ChkRange(AdrLong,-8,7))
+ BEGIN
+ BAsmCode[0]=0x7d;
+ BAsmCode[1]=0xb0+(AdrLong & 15);
+ CodeLen=2;
+ END
+ break;
+ END
+ END
+ END
+ END
+ else if (CheckFormat("GQS"))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ BEGIN
+ CopyAdr();
+ DecodeAdr(ArgStr[1],MModImm+MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ if (FormatCode==0)
+ if (AdrType==ModImm)
+ if ((ImmVal()>=-8) AND (ImmVal()<=7)) FormatCode=2;
+ else if ((IsShort(AdrMode2,&SMode)) AND (OpSize==0)) FormatCode=3;
+ else FormatCode=1;
+ else
+ if ((OpSize==0) AND (IsShort(AdrMode,&SMode)) AND (AdrMode2<=1) AND
+ ((AdrMode>1) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=3;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ CodeGen(0xa0,0x76,0x40);
+ break;
+ case 2:
+ if (AdrType!=ModImm) WrError(1350);
+ else
+ BEGIN
+ Num1=ImmVal();
+ if (ChkRange(Num1,-8,7))
+ BEGIN
+ BAsmCode[0]=0xc8+OpSize;
+ BAsmCode[1]=(Num1 << 4)+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ END
+ break;
+ case 3:
+ if (OpSize!=0) WrError(1130);
+ else if (NOT IsShort(AdrMode2,&SMode)) WrError(1350);
+ else if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[0]=0x80+SMode; BAsmCode[1]=AdrVals[0];
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ else if ((AdrMode2>=2) OR (NOT IsShort(AdrMode,&SMode))) WrError(1350);
+ else if ((AdrMode<2) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350);
+ else
+ BEGIN
+ if (SMode==3) SMode++;
+ BAsmCode[0]=0x20+((AdrMode2 & 1) << 2)+(SMode & 3); /* RMS 05: Just like #04 */
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ break;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CMP"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GQS"))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[1],MModImm+MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ if (FormatCode==0)
+ if (AdrType==ModImm)
+ if ((ImmVal()>=-8) AND (ImmVal()<=7)) FormatCode=2;
+ else if ((IsShort(AdrMode2,&SMode)) AND (OpSize==0)) FormatCode=3;
+ else FormatCode=1;
+ else
+ if ((OpSize==0) AND (IsShort(AdrMode,&SMode)) AND (AdrMode2<=1) AND
+ ((AdrMode>1) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=3;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ CodeGen(0xc0,0x76,0x80);
+ break;
+ case 2:
+ if (AdrType!=ModImm) WrError(1350);
+ else
+ BEGIN
+ Num1=ImmVal();
+ if (ChkRange(Num1,-8,7))
+ BEGIN
+ BAsmCode[0]=0xd0+OpSize;
+ BAsmCode[1]=(Num1 << 4)+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ END
+ break;
+ case 3:
+ if (OpSize!=0) WrError(1130);
+ else if (NOT IsShort(AdrMode2,&SMode)) WrError(1350);
+ else if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[0]=0xe0+SMode; BAsmCode[1]=AdrVals[0];
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ else if ((AdrMode2>=2) OR (NOT IsShort(AdrMode,&SMode))) WrError(1350);
+ else if ((AdrMode<2) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350);
+ else
+ BEGIN
+ if (SMode==3) SMode++;
+ BAsmCode[0]=0x38+((AdrMode2 & 1) << 2)+(SMode & 3); /* RMS 04: destination reg is bit 2! */
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ break;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("SUB"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GQS"))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[1],MModImm+MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ if (FormatCode==0)
+ if (AdrType==ModImm)
+ if ((ImmVal()>=-7) AND (ImmVal()<=8)) FormatCode=2;
+ else if ((IsShort(AdrMode2,&SMode)) AND (OpSize==0)) FormatCode=3;
+ else FormatCode=1;
+ else
+ if ((OpSize==0) AND (IsShort(AdrMode,&SMode)) AND (AdrMode2<=1) AND
+ ((AdrMode>1) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=3;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ CodeGen(0xa8,0x76,0x50);
+ break;
+ case 2:
+ if (AdrType!=ModImm) WrError(1350);
+ else
+ BEGIN
+ Num1=ImmVal();
+ if (ChkRange(Num1,-7,8))
+ BEGIN
+ BAsmCode[0]=0xc8+OpSize;
+ BAsmCode[1]=((-Num1) << 4)+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ END
+ break;
+ case 3:
+ if (OpSize!=0) WrError(1130);
+ else if (NOT IsShort(AdrMode2,&SMode)) WrError(1350);
+ else if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[0]=0x88+SMode; BAsmCode[1]=AdrVals[0];
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ else if ((AdrMode2>=2) OR (NOT IsShort(AdrMode,&SMode))) WrError(1350);
+ else if ((AdrMode<2) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350);
+ else
+ BEGIN
+ if (SMode==3) SMode++;
+ BAsmCode[0]=0x28+((AdrMode2 & 1) << 2)+(SMode & 3); /* RMS 06: just like RMS 04 */
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ break;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Gen1OrderCnt; z++)
+ if (Memo(Gen1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=Hi(Gen1Orders[z].Code)+OpSize;
+ BAsmCode[1]=Lo(Gen1Orders[z].Code)+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Gen2OrderCnt; z++)
+ if (Memo(Gen2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[1],MModGen+MModImm);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else if ((*OpPart=='M') AND ((AdrMode2==3) OR (AdrMode2==5) OR (AdrMode2-OpSize==1))) WrError(1350);
+ else CodeGen(Gen2Orders[z].Code1,Gen2Orders[z].Code2,Gen2Orders[z].Code3);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INC")) OR (Memo("DEC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize==1) AND ((AdrMode & 14)==4))
+ BEGIN
+ BAsmCode[0]=0xb2+(Ord(Memo("DEC")) << 6)+((AdrMode & 1) << 3);
+ CodeLen=1;
+ END
+ else if (NOT IsShort(AdrMode,&SMode)) WrError(1350);
+ else if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=0xa0+(Ord(Memo("DEC")) << 3)+SMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<DivOrderCnt; z++)
+ if (Memo(DivOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModImm+MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[0]=0x7c+OpSize;
+ BAsmCode[1]=DivOrders[z].Code1;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=DivOrders[z].Code2+OpSize;
+ BAsmCode[1]=DivOrders[z].Code3+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<BCDOrderCnt; z++)
+ if (Memo(BCDOrders[z]))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ if (AdrMode!=0) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen+MModImm);
+ if (AdrType!=ModNone)
+ if (AdrType==ModImm)
+ BEGIN
+ BAsmCode[0]=0x7c+OpSize;
+ BAsmCode[1]=0xec+z;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ else if (AdrMode!=1) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x7c+OpSize;
+ BAsmCode[1]=0xe4+z;
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("EXTS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen);
+ if (OpSize==-1) OpSize=0;
+ if (AdrType!=ModNone)
+ if (OpSize==0)
+ if ((AdrMode==1) OR ((AdrMode>=3) AND (AdrMode<=5))) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x7c;
+ BAsmCode[1]=0x60+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ else if (OpSize==1)
+ if (AdrMode!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x7c; BAsmCode[1]=0xf3;
+ CodeLen=2;
+ END
+ else WrError(1130);
+ END
+ return;
+ END
+
+ if (Memo("NOT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("GS"))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize>1) WrError(1130);
+ else
+ BEGIN
+ if (FormatCode==0)
+ if ((OpSize==0) AND (IsShort(AdrMode,&SMode))) FormatCode=2;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ BAsmCode[0]=0x74+OpSize;
+ BAsmCode[1]=0x70+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ case 2:
+ if (OpSize!=0) WrError(1130);
+ else if (NOT IsShort(AdrMode,&SMode)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xb8+SMode;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Logik*/
+
+ if ((Memo("AND")) OR (Memo("OR")))
+ BEGIN
+ z=Ord(Memo("OR"));
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("GS")) /* RMS 01: The format codes are G and S, not G and Q */
+ BEGIN
+ DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ BEGIN
+ CopyAdr(); DecodeAdr(ArgStr[1],MModGen+MModImm);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize>1) WrError(1130);
+ else
+ BEGIN
+ if (FormatCode==0)
+ if (AdrType==ModImm)
+ if ((OpSize==0) AND (IsShort(AdrMode2,&SMode))) FormatCode=2;
+ else FormatCode=1;
+ else
+ if ((AdrMode2<=1) AND (IsShort(AdrMode,&SMode)) AND ((AdrMode>1) OR Odd(AdrMode ^ AdrMode2))) FormatCode=2;
+ else FormatCode=1;
+ switch (FormatCode)
+ BEGIN
+ case 1:
+ CodeGen(0x90+(z << 3),0x76,0x20+(z << 4));
+ break;
+ case 2:
+ if (OpSize!=0) WrError(1130);
+ else if (AdrType==ModImm)
+ if (NOT IsShort(AdrMode2,&SMode)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x90+(z << 3)+SMode;
+ BAsmCode[1]=ImmVal();
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ else if ((NOT IsShort(AdrMode,&SMode)) OR (AdrMode2>1)) WrError(1350);
+ else if ((AdrMode<=1) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350);
+ else
+ BEGIN
+ if (SMode==3) SMode++;
+ BAsmCode[0]=0x10+(z << 3)+((AdrMode2 & 1) << 2)+(SMode & 3);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("ROT"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize>1) WrError(1130);
+ else
+ BEGIN
+ OpSize2=OpSize; OpSize=0; CopyAdr();
+ DecodeAdr(ArgStr[1],MModGen+MModImm);
+ if (AdrType==ModGen)
+ if (AdrMode!=3) WrError(1350);
+ else if (AdrMode2+2*OpSize2==3) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x74+OpSize2;
+ BAsmCode[1]=0x60+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ else if (AdrType==ModImm)
+ BEGIN
+ Num1=ImmVal();
+ if (Num1==0) WrError(1315);
+ else if (ChkRange(Num1,-8,8))
+ BEGIN
+ if (Num1>0) Num1--; else Num1=(-9)-Num1;
+ BAsmCode[0]=0xe0+OpSize2;
+ BAsmCode[1]=(Num1 << 4)+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt);
+ CodeLen=2+AdrCnt2;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("SHA")) OR (Memo("SHL")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ z=Ord(Memo("SHA"));
+ DecodeAdr(ArgStr[2],MModGen+MModReg32);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize>2) OR ((OpSize==2) AND (AdrType==ModGen))) WrError(1130);
+ else
+ BEGIN
+ CopyAdr(); OpSize2=OpSize; OpSize=0;
+ DecodeAdr(ArgStr[1],MModImm+MModGen);
+ if (AdrType==ModGen)
+ if (AdrMode!=3) WrError(1350);
+ else if (AdrMode2*2+OpSize2==3) WrError(1350);
+ else
+ BEGIN
+ if (OpSize2==2)
+ BEGIN
+ BAsmCode[0]=0xeb;
+ BAsmCode[1]=0x01+(AdrMode2 << 4)+(z << 5);
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x74+OpSize2;
+ BAsmCode[1]=0xe0+(z << 4)+AdrMode2;
+ END
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ else if (AdrType==ModImm)
+ BEGIN
+ Num1=ImmVal();
+ if (Num1==0) WrError(1315);
+ else if (ChkRange(Num1,-8,8))
+ BEGIN
+ if (Num1>0) Num1--; else Num1=(-9)-Num1;
+ if (OpSize2==2)
+ BEGIN
+ BAsmCode[0]=0xeb;
+ BAsmCode[1]=0x80+(AdrMode2 << 4)+(z << 5)+(Num1 & 15);
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xe8+(z << 3)+OpSize2;
+ BAsmCode[1]=(Num1 << 4)+AdrMode2;
+ END
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ CodeLen=2+AdrCnt2;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Bitoperationen */
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z].Name))
+ BEGIN
+ MayShort=(BitOrders[z].Code & 12)==8;
+ if (CheckFormat(MayShort?"GS":"G"))
+ if (DecodeBitAdr((FormatCode!=1) AND (MayShort)))
+ if (AdrMode>=16)
+ BEGIN
+ BAsmCode[0]=0x40+((BitOrders[z].Code-8) << 3)+(AdrMode & 7);
+ BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x7e;
+ BAsmCode[1]=(BitOrders[z].Code << 4)+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ return;
+ END
+
+ if (strncmp(OpPart,"BM",2)==0)
+ for (z=0; z<ConditionCnt; z++)
+ if (strcmp(OpPart+2,Conditions[z].Name)==0)
+ BEGIN
+ if ((ArgCnt==1) AND (strcasecmp(ArgStr[1],"C")==0))
+ BEGIN
+ BAsmCode[0]=0x7d; BAsmCode[1]=0xd0+Conditions[z].Code;
+ CodeLen=2;
+ END
+ else if (DecodeBitAdr(False))
+ BEGIN
+ BAsmCode[0]=0x7e;
+ BAsmCode[1]=0x20+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); z=Conditions[z].Code;
+ if ((z>=4) AND (z<12)) z^=12;
+ if (z>=8) z+=0xf0;
+ BAsmCode[2+AdrCnt]=z;
+ CodeLen=3+AdrCnt;
+ END
+ return;
+ END
+
+ if ((Memo("FCLR")) OR (Memo("FSET")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (strlen(ArgStr[1])!=1) WrError(1350);
+ else
+ BEGIN
+ p=strchr(Flags,toupper(*ArgStr[1]));
+ if (p==Nil) WrXError(1440,ArgStr[1]);
+ else
+ BEGIN
+ BAsmCode[0]=0xeb;
+ BAsmCode[1]=0x04+Ord(Memo("FCLR"))+((p-Flags) << 4);
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if (Memo("JMP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False; /* RMS 12: Mod to allow JMP.S to work */
+ AdrLong=EvalIntExpression(ArgStr[1],UInt20,&OK);
+ Diff=AdrLong-EProgCounter();
+
+/* RMS 12: Repaired JMP.S forward-label as follows:
+
+ If it's an unknown symbol, make PC+2 the "safe" value, otherwise
+ the user will get OUT OF RANGE errors on every attempt to use JMP.S
+ Since the instruction can only branch forward, and AS stuffs the PC
+ back for a "temp" forward reference value, the range-checking will
+ always fail.
+
+ One side-effect also is that for auto-determination purposes, one
+ fewer pass is needed. Before, the first pass would signal JMP.B,
+ then once the forward reference is known, it'd signal JMP.S, which
+ would cause a "phase error" forcing another pass.
+*/
+ if ( (FirstPassUnknown) AND (Diff == 0) )
+ Diff = 2;
+
+ if (OpSize==-1)
+ BEGIN
+ if ((Diff>=2) AND (Diff<=9)) OpSize=4;
+ else if ((Diff>=-127) AND (Diff<=128)) OpSize=0;
+ else if ((Diff>=-32767) AND (Diff<=32768)) OpSize=1;
+ else OpSize=7;
+ END
+/*
+ The following code is to deal with a silicon bug in the first generation of
+ M16C CPUs (the so-called M16C/60 group). It has been observed that this
+ silicon bug has been fixed as of the M16C/61, so we disable JMP.S promotion
+ to JMP.B when the target crosses a 64k boundary for those CPUs.
+
+ Since M16C is a "generic" specification, we do JMP.S promotion for that
+ CPU specification, as follows:
+
+ RMS 11: According to Mitsubishi App Note M16C-06-9612
+ JMP.S cannot cross a 64k boundary.. so trim up to JMP.B
+
+ It is admittedly a very low likelihood of occurrence [JMP.S has only 8
+ possible targets, being a 3 bit "jump addressing mode"], but since the
+ occurrence of this bug could cause such evil debugging issues, I have
+ taken the liberty of addressing it in the assembler. Heck, it's JUST one
+ extra byte. One byte's worth the peace of mind, isn't it? :)
+
+*/
+ if (!( ( strcmp(MomCPUIdent,"M16C") ) && ( strcmp(MomCPUIdent,"M30600M8"))))
+ if (OpSize == 4)
+ BEGIN
+ if ( (AdrLong & 0x0f0000) != (EProgCounter() & 0x0f0000) )
+ OpSize = 0;
+ END /* NOTE! This not an ASX bug, but rather in the CPU!! */
+ switch (OpSize)
+ BEGIN
+ case 4:
+ if (((Diff<2) OR (Diff>9)) AND (NOT SymbolQuestionable) ) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0x60+((Diff-2) & 7); CodeLen=1;
+ END
+ break;
+ case 0:
+ if (((Diff<-127) OR (Diff>128)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0xfe;
+ BAsmCode[1]=(Diff-1) & 0xff;
+ CodeLen=2;
+ END
+ break;
+ case 1:
+ if (((Diff<-32767) OR (Diff>32768)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0xf4; Diff--;
+ BAsmCode[1]=Diff & 0xff;
+ BAsmCode[2]=(Diff >> 8) & 0xff;
+ CodeLen=3;
+ END
+ break;
+ case 7:
+ BAsmCode[0]=0xfc;
+ BAsmCode[1]=AdrLong & 0xff;
+ BAsmCode[2]=(AdrLong >> 8) & 0xff;
+ BAsmCode[3]=(AdrLong >> 16) & 0xff;
+ CodeLen=4;
+ break;
+ default:
+ WrError(1130);
+ END
+ END
+ return;
+ END
+
+ if (Memo("JSR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt20,&OK);
+ Diff=AdrLong-EProgCounter();
+ if (OpSize==-1)
+ BEGIN
+ if ((Diff>=-32767) AND (Diff<=32768)) OpSize=1;
+ else OpSize=7;
+ END
+ switch (OpSize)
+ BEGIN
+ case 1:
+ if (((Diff<-32767) OR (Diff>32768)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0xf5; Diff--;
+ BAsmCode[1]=Diff & 0xff;
+ BAsmCode[2]=(Diff >> 8) & 0xff;
+ CodeLen=3;
+ END
+ break;
+ case 7:
+ BAsmCode[0]=0xfd;
+ BAsmCode[1]=AdrLong & 0xff;
+ BAsmCode[2]=(AdrLong >> 8) & 0xff;
+ BAsmCode[3]=(AdrLong >> 16) & 0xff;
+ CodeLen=4;
+ break;
+ default:
+ WrError(1130);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JMPI")) OR (Memo("JSRI")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ if (OpSize==7) OpSize=2;
+ DecodeAdr(ArgStr[1],MModGen+MModDisp20+MModReg32+MModAReg32);
+ if ((AdrType==ModGen) AND ((AdrMode & 14)==12))
+ AdrVals[AdrCnt++]=0;
+ if ((AdrType==ModGen) AND ((AdrMode & 14)==4))
+ if (OpSize==-1) OpSize=1;
+ else if (OpSize!=1)
+ BEGIN
+ AdrType=ModNone; WrError(1131);
+ END
+ if (AdrType==ModAReg32) AdrMode=4;
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[0]=0x7d;
+ BAsmCode[1]=(Ord(Memo("JSRI")) << 4)+(Ord(OpSize==1) << 5)+AdrMode;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JMPS")) OR (Memo("JSRS")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ OpSize=0;
+ FirstPassUnknown=False;
+ DecodeAdr(ArgStr[1],MModImm);
+ if ((FirstPassUnknown) AND (AdrVals[0]<18)) AdrVals[0]=18;
+ if (AdrType!=ModNone)
+ if (AdrVals[0]<18) WrError(1315);
+ else
+ BEGIN
+ BAsmCode[0]=0xee + Ord(Memo("JSRS")); /* ANSI :-O */
+ BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if (*OpPart=='J')
+ for (z=0; z<ConditionCnt; z++)
+ if (strcmp(Conditions[z].Name,OpPart+1)==0)
+ BEGIN
+ Num1=1+Ord(Conditions[z].Code>=8);
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcmp(Format," ")!=0) WrError(1090);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1],UInt20,&OK)-(EProgCounter()+Num1);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrLong>127) OR (AdrLong<-128))) WrError(1370);
+ else if (Conditions[z].Code>=8)
+ BEGIN
+ BAsmCode[0]=0x7d; BAsmCode[1]=0xc0+Conditions[z].Code;
+ BAsmCode[2]=AdrLong & 0xff;
+ CodeLen=3;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0x68+Conditions[z].Code; BAsmCode[1]=AdrLong & 0xff;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("ADJNZ")) OR (Memo("SBJNZ")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (CheckFormat("G"))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModGen);
+ if (AdrType!=ModNone)
+ if (OpSize==-1) WrError(1132);
+ else if (OpSize>1) WrError(1130);
+ else
+ BEGIN
+ CopyAdr(); OpSize2=OpSize; OpSize=0;
+ FirstPassUnknown=False;
+ DecodeAdr(ArgStr[1],MModImm); Num1=ImmVal();
+ if (FirstPassUnknown) Num1=0;
+ if (Memo("SBJNZ")) Num1=(-Num1);
+ if (ChkRange(Num1,-8,7))
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[3],UInt20,&OK)-(EProgCounter()+2);
+ if (OK)
+ if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT SymbolQuestionable)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0xf8+OpSize2;
+ BAsmCode[1]=(Num1 << 4)+AdrMode2;
+ memcpy(BAsmCode+2,AdrVals2,AdrCnt2);
+ BAsmCode[2+AdrCnt2]=AdrLong & 0xff;
+ CodeLen=3+AdrCnt2;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("INT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=0xc0+EvalIntExpression(ArgStr[1]+1,UInt6,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xeb; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ /* Miszellaneen */
+
+ if (Memo("ENTER"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[1]+1,UInt8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x7c; BAsmCode[1]=0xf2; CodeLen=3;
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDINTB"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[1]+1,UInt20,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xeb; BAsmCode[1]=0x20;
+ BAsmCode[2]=(AdrLong >> 16) & 0xff; BAsmCode[3]=0;
+ BAsmCode[4]=0xeb; BAsmCode[5]=0x10;
+ BAsmCode[7]=(AdrLong >> 8) & 0xff; BAsmCode[6]=AdrLong & 0xff; /* RMS 07: needs to be LSB, MSB order */
+ CodeLen=8;
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDIPL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=0xa0+EvalIntExpression(ArgStr[1]+1,UInt3,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0x7d; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_M16C(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_M16C(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_M16C(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x14; NOPCode=0x04;
+ DivideChars=","; HasAttrs=True; AttrChars=".:";
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xfffff; /* RMS 10: Probably a typo (was 0xffff) */
+
+ MakeCode=MakeCode_M16C; IsDef=IsDef_M16C;
+ SwitchFrom=SwitchFrom_M16C; InitFields();
+END
+
+ void codem16c_init(void)
+BEGIN
+ CPUM16C=AddCPU("M16C",SwitchTo_M16C);
+ CPUM30600M8=AddCPU("M30600M8",SwitchTo_M16C);
+ CPUM30610=AddCPU("M30610",SwitchTo_M16C);
+ CPUM30620=AddCPU("M30620",SwitchTo_M16C);
+
+ AddCopyright("Mitsubishi M16C-Generator also (C) 1999 RMS");
+END
+
+
diff --git a/codem16c.h b/codem16c.h
new file mode 100644
index 0000000..e5b4cb3
--- /dev/null
+++ b/codem16c.h
@@ -0,0 +1,11 @@
+/* codem16c.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator M16C */
+/* */
+/* Historie: 17.12.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codem16c_init(void);
diff --git a/codemcore.c b/codemcore.c
new file mode 100644
index 0000000..786d09f
--- /dev/null
+++ b/codemcore.c
@@ -0,0 +1,806 @@
+/* codemcore.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator MCORE-Familie */
+/* */
+/* Historie: 31. 1.1998 Grundsteinlegung */
+/* 3. 1.1999 ChkPC-Anpassung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "nls.h"
+#include "endian.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "asmitree.h"
+
+/*--------------------------------------------------------------------------*/
+/* Variablen */
+
+#define FixedOrderCnt 7
+#define OneRegOrderCnt 32
+#define TwoRegOrderCnt 23
+#define UImm5OrderCnt 13
+#define LJmpOrderCnt 4
+#define CRegCnt 13
+
+typedef struct
+ {
+ Word Code;
+ Boolean Priv;
+ } FixedOrder;
+
+typedef struct
+ {
+ Word Code;
+ Word Min,Ofs;
+ } ImmOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } CReg;
+
+static CPUVar CPUMCORE;
+static Byte OpSize;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *OneRegOrders;
+static FixedOrder *TwoRegOrders;
+static ImmOrder *UImm5Orders;
+static FixedOrder *LJmpOrders;
+static PInstTable InstTable;
+static CReg *CRegs;
+
+/*--------------------------------------------------------------------------*/
+/* Hilfsdekoder */
+
+ static Boolean DecodeReg(char *Asc, Word *Erg)
+BEGIN
+ char *endptr,*s;
+
+ if (FindRegDef(Asc,&s)) Asc=s;
+
+ if (strcasecmp(Asc,"SP")==0)
+ BEGIN
+ *Erg=0; return True;
+ END
+
+ if (strcasecmp(Asc,"LR")==0)
+ BEGIN
+ *Erg=15; return True;
+ END
+
+ if (toupper(*Asc)!='R') return False;
+ else
+ BEGIN
+ *Erg=strtol(Asc+1,&endptr,10);
+ return ((*endptr=='\0') AND (*Erg<=15));
+ END
+END
+
+ static Boolean DecodeCReg(char *Asc, Word *Erg)
+BEGIN
+ char *endptr;
+ int z;
+
+ for (z=0; z<CRegCnt; z++)
+ if (strcasecmp(Asc,CRegs[z].Name)==0)
+ BEGIN
+ *Erg=CRegs[z].Code; return True;
+ END
+
+ if ((toupper(*Asc)!='C') OR (toupper(Asc[1])!='R')) return False;
+ else
+ BEGIN
+ *Erg=strtol(Asc+2,&endptr,10);
+ return ((*endptr=='\0') AND (*Erg<=31));
+ END
+END
+
+ static Boolean DecodeAdr(char *Asc, Word *Erg)
+BEGIN
+ Word Base=0xff,Tmp;
+ LongInt DispAcc=0,DMask=(1<<OpSize)-1,DMax=15<<OpSize;
+ Boolean OK,FirstFlag=False;
+ char *Pos;
+
+ if (NOT IsIndirect(Asc))
+ BEGIN
+ WrError(1350); return False;
+ END
+
+ Asc++; Asc[strlen(Asc)-1]='\0';
+ do
+ BEGIN
+ Pos=QuotPos(Asc,',');
+ if (Pos!=Nil) *Pos='\0';
+ if (DecodeReg(Asc,&Tmp))
+ BEGIN
+ if (Base==0xff) Base=Tmp;
+ else
+ BEGIN
+ WrError(1350); return False;
+ END
+ END
+ else
+ BEGIN
+ FirstPassUnknown=FALSE;
+ DispAcc+=EvalIntExpression(Asc,Int32,&OK);
+ if (FirstPassUnknown) FirstFlag=True;
+ if (NOT OK) return False;
+ END
+ if (Pos!=Nil) Asc=Pos+1;
+ END
+ while (Pos!=Nil);
+
+ if (Base==0xff)
+ BEGIN
+ WrError(1350); return False;
+ END
+
+ if (FirstFlag)
+ BEGIN
+ DispAcc-=DispAcc&DMask;
+ if (DispAcc<0) DispAcc=0;
+ if (DispAcc>DMax) DispAcc=DMax;
+ END
+
+ if ((DispAcc&DMask)!=0)
+ BEGIN
+ WrError(1325); return False;
+ END
+ if (NOT ChkRange(DispAcc,0,DMax)) return False;
+ *Erg=Base+((DispAcc>>OpSize)<<4); return True;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ if (Memo("REG"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else AddRegDef(LabPart,ArgStr[1]);
+ return True;
+ END
+
+ return False;
+END
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *Instr=FixedOrders+Index;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ if ((Instr->Priv) AND (NOT SupAllowed)) WrError(50);
+ WAsmCode[0]=Instr->Code; CodeLen=2;
+ END
+END
+
+ static void DecodeOneReg(Word Index)
+BEGIN
+ FixedOrder *Instr=OneRegOrders+Index;
+ Word RegX;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
+ BEGIN
+ if ((Instr->Priv) AND (NOT SupAllowed)) WrError(50);
+ WAsmCode[0]=Instr->Code+RegX; CodeLen=2;
+ END
+END
+
+ static void DecodeTwoReg(Word Index)
+BEGIN
+ FixedOrder *Instr=TwoRegOrders+Index;
+ Word RegX,RegY;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
+ else if (NOT DecodeReg(ArgStr[2],&RegY)) WrXError(1445,ArgStr[2]);
+ BEGIN
+ if ((Instr->Priv) AND (NOT SupAllowed)) WrError(50);
+ WAsmCode[0]=Instr->Code+(RegY<<4)+RegX; CodeLen=2;
+ END
+END
+
+ static void DecodeUImm5(Word Index)
+BEGIN
+ ImmOrder *Instr=UImm5Orders+Index;
+ Word RegX,ImmV;
+ Boolean OK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ ImmV=EvalIntExpression(ArgStr[2],(Instr->Ofs>0) ? UInt6 : UInt5,&OK);
+ if ((Instr->Min>0) AND (ImmV<Instr->Min))
+ if (FirstPassUnknown) ImmV=Instr->Min;
+ else
+ BEGIN
+ WrError(1315); OK=False;
+ END
+ if ((Instr->Ofs>0) AND ((ImmV<Instr->Ofs) OR (ImmV>31+Instr->Ofs)))
+ if (FirstPassUnknown) ImmV=Instr->Ofs;
+ else
+ BEGIN
+ WrError((ImmV<Instr->Ofs) ? 1315 : 1320);
+ OK=False;
+ END
+ if (OK)
+ BEGIN
+ WAsmCode[0]=Instr->Code+((ImmV-Instr->Ofs)<<4)+RegX; CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeLJmp(Word Index)
+BEGIN
+ FixedOrder *Instr=LJmpOrders+Index;
+ LongInt Dest;
+ Boolean OK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Dest=EvalIntExpression(ArgStr[1],UInt32,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Dest&1)==1)) WrError(1375);
+ else if ((NOT SymbolQuestionable) AND ((Dest>2046) OR (Dest<-2048))) WrError(1370);
+ else
+ BEGIN
+ if ((Instr->Priv) AND (NOT SupAllowed)) WrError(50);
+ WAsmCode[0]=Instr->Code+((Dest>>1)&0x7ff);
+ CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeSJmp(Word Index)
+BEGIN
+ LongInt Dest;
+ Boolean OK;
+ int l=0;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if ((*ArgStr[1]!='[') OR (ArgStr[1][l=strlen(ArgStr[1])-1]!=']')) WrError(1350);
+ else
+ BEGIN
+ ArgStr[1][l]='\0';
+ Dest=EvalIntExpression(ArgStr[1]+1,UInt32,&OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Dest&3)!=0)) WrError(1325);
+ else
+ BEGIN
+ Dest=(Dest-(EProgCounter()+2))>>2;
+ if ((EProgCounter()&3)<2) Dest++;
+ if ((NOT SymbolQuestionable) AND ((Dest<0) OR (Dest>255))) WrError(1370);
+ else
+ BEGIN
+ WAsmCode[0]=0x7000+(Index<<8)+(Dest&0xff);
+ CodeLen=2;
+ END
+ END
+ END
+END
+
+ static void DecodeBGENI(Word Index)
+BEGIN
+ Word RegX,ImmV;
+ Boolean OK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ ImmV=EvalIntExpression(ArgStr[2],UInt5,&OK);
+ if (OK)
+ BEGIN
+ if (ImmV>6)
+ WAsmCode[0]=0x3200+(ImmV<<4)+RegX;
+ else
+ WAsmCode[0]=0x6000+(1<<(4+ImmV))+RegX;
+ CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeBMASKI(Word Index)
+BEGIN
+ Word RegX,ImmV;
+ Boolean OK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ ImmV=EvalIntExpression(ArgStr[2],UInt6,&OK);
+ if ((FirstPassUnknown) AND ((ImmV<1) OR (ImmV>32))) ImmV=8;
+ if (OK)
+ if (ChkRange(ImmV,1,32))
+ BEGIN
+ ImmV&=31;
+ if ((ImmV<1) OR (ImmV>7))
+ WAsmCode[0]=0x2c00+(ImmV<<4)+RegX;
+ else
+ WAsmCode[0]=0x6000+(((1<<ImmV)-1)<<4)+RegX;
+ CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeLdSt(Word Index)
+BEGIN
+ Word RegX,RegZ,NSize;
+
+ if ((*AttrPart!=0) AND (Lo(Index)!=0xff)) WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (OpSize>2) WrError(1130);
+ else
+ BEGIN
+ if (Lo(Index)!=0xff) OpSize=Lo(Index);
+ if (NOT DecodeReg(ArgStr[1],&RegZ)) WrXError(1445,ArgStr[1]);
+ else if (DecodeAdr(ArgStr[2],&RegX))
+ BEGIN
+ NSize=(OpSize==2) ? 0 : OpSize+1;
+ WAsmCode[0]=0x8000+(NSize<<13)+(Hi(Index)<<12)+(RegZ<<8)+RegX;
+ CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeLdStm(Word Index)
+BEGIN
+ char *p;
+ int l;
+ Word RegF,RegL,RegI;
+
+ if (*AttrPart!=0) WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if ((*ArgStr[2]!='(') OR (ArgStr[2][l=strlen(ArgStr[2])-1]!=')')) WrError(1350);
+ else
+ BEGIN
+ ArgStr[2][l]='\0';
+ if (NOT DecodeReg(ArgStr[2]+1,&RegI)) WrXError(1445,ArgStr[2]+1);
+ else if (RegI!=0) WrXError(1445,ArgStr[2]+1);
+ else if ((p=strchr(ArgStr[1],'-'))==Nil) WrError(1350);
+ else if (NOT DecodeReg(p+1,&RegL)) WrXError(1445,p+1);
+ else if (RegL!=15) WrXError(1445,p+1);
+ else
+ BEGIN
+ *p='\0';
+ if (NOT DecodeReg(ArgStr[1],&RegF)) WrXError(1445,ArgStr[1]);
+ else if ((RegF<1) OR (RegF>14)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ WAsmCode[0]=0x0060+(Index <<4)+RegF;
+ CodeLen=2;
+ END
+ END
+ END
+END
+
+ static void DecodeLdStq(Word Index)
+BEGIN
+ char *p;
+ int l;
+ Word RegF,RegL,RegX;
+
+ if (*AttrPart!=0) WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if ((*ArgStr[2]!='(') OR (ArgStr[2][l=strlen(ArgStr[2])-1]!=')')) WrError(1350);
+ else
+ BEGIN
+ ArgStr[2][l]='\0';
+ if (NOT DecodeReg(ArgStr[2]+1,&RegX)) WrXError(1445,ArgStr[2]+1);
+ else if ((RegX>=4) AND (RegX<=7)) WrXError(1445,ArgStr[2]+1);
+ else if ((p=strchr(ArgStr[1],'-'))==Nil) WrError(1350);
+ else if (NOT DecodeReg(p+1,&RegL)) WrXError(1445,p+1);
+ else if (RegL!=7) WrXError(1445,p+1);
+ else
+ BEGIN
+ *p='\0';
+ if (NOT DecodeReg(ArgStr[1],&RegF)) WrXError(1445,ArgStr[1]);
+ else if (RegF!=4) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ WAsmCode[0]=0x0040+(Index <<4)+RegX;
+ CodeLen=2;
+ END
+ END
+ END
+END
+
+ static void DecodeLoopt(Word Index)
+BEGIN
+ Word RegY;
+ LongInt Dest;
+ Boolean OK;
+
+ if (*AttrPart!=0) WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&RegY)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ Dest=EvalIntExpression(ArgStr[2],UInt32,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Dest&1)==1)) WrError(1375);
+ else if ((NOT SymbolQuestionable) AND ((Dest>-2) OR (Dest<-32))) WrError(1370);
+ else
+ BEGIN
+ WAsmCode[0]=0x0400+(RegY<<4)+((Dest>>1)&15);
+ CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeLrm(Word Index)
+BEGIN
+ LongInt Dest;
+ Word RegZ;
+ Boolean OK;
+ int l=0;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&RegZ)) WrXError(1445,ArgStr[1]);
+ else if ((RegZ==0) OR (RegZ==15)) WrXError(1445,ArgStr[1]);
+ else if ((*ArgStr[2]!='[') OR (ArgStr[2][l=strlen(ArgStr[2])-1]!=']')) WrError(1350);
+ else
+ BEGIN
+ ArgStr[2][l]='\0';
+ Dest=EvalIntExpression(ArgStr[2]+1,UInt32,&OK);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Dest&3)!=0)) WrError(1325);
+ else
+ BEGIN
+ Dest=(Dest-(EProgCounter()+2))>>2;
+ if ((EProgCounter()&3)<2) Dest++;
+ if ((NOT SymbolQuestionable) AND ((Dest<0) OR (Dest>255))) WrError(1370);
+ else
+ BEGIN
+ WAsmCode[0]=0x7000+(RegZ<<8)+(Dest&0xff);
+ CodeLen=2;
+ END
+ END
+ END
+END
+
+ static void DecodeMcr(Word Index)
+BEGIN
+ Word RegX,CRegY;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
+ else if (NOT DecodeCReg(ArgStr[2],&CRegY)) WrXError(1440,ArgStr[2]);
+ else
+ BEGIN
+ if (NOT SupAllowed) WrError(50);
+ WAsmCode[0]=0x1000+(Index<<11)+(CRegY<<4)+RegX;
+ CodeLen=2;
+ END
+END
+
+ static void DecodeMovi(Word Index)
+BEGIN
+ Word RegX,ImmV;
+ Boolean OK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ ImmV=EvalIntExpression(ArgStr[2],UInt7,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0x6000+((ImmV&127)<<4)+RegX;
+ CodeLen=2;
+ END
+ END
+END
+
+ static void DecodeTrap(Word Index)
+BEGIN
+ Word ImmV;
+ Boolean OK;
+
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]!='#') WrError(1120);
+ else
+ BEGIN
+ ImmV=EvalIntExpression(ArgStr[1]+1,UInt2,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[0]=0x0008+ImmV;
+ CodeLen=2;
+ END
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+/* Codetabellenverwaltung */
+
+static int InstrZ;
+
+ static void AddFixed(char *NName, Word NCode, Boolean NPriv)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ else
+ BEGIN
+ FixedOrders[InstrZ].Code=NCode;
+ FixedOrders[InstrZ].Priv=NPriv;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
+ END
+END
+
+ static void AddOneReg(char *NName, Word NCode, Boolean NPriv)
+BEGIN
+ if (InstrZ>=OneRegOrderCnt) exit(255);
+ else
+ BEGIN
+ OneRegOrders[InstrZ].Code=NCode;
+ OneRegOrders[InstrZ].Priv=NPriv;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeOneReg);
+ END
+END
+
+ static void AddTwoReg(char *NName, Word NCode, Boolean NPriv)
+BEGIN
+ if (InstrZ>=TwoRegOrderCnt) exit(255);
+ else
+ BEGIN
+ TwoRegOrders[InstrZ].Code=NCode;
+ TwoRegOrders[InstrZ].Priv=NPriv;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeTwoReg);
+ END
+END
+
+ static void AddUImm5(char *NName, Word NCode, Word NMin, Word NOfs)
+BEGIN
+ if (InstrZ>=UImm5OrderCnt) exit(255);
+ else
+ BEGIN
+ UImm5Orders[InstrZ].Code=NCode;
+ UImm5Orders[InstrZ].Min=NMin;
+ UImm5Orders[InstrZ].Ofs=NOfs;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeUImm5);
+ END
+END
+
+ static void AddLJmp(char *NName, Word NCode, Boolean NPriv)
+BEGIN
+ if (InstrZ>=LJmpOrderCnt) exit(255);
+ else
+ BEGIN
+ LJmpOrders[InstrZ].Code=NCode;
+ LJmpOrders[InstrZ].Priv=NPriv;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeLJmp);
+ END
+END
+
+ static void AddCReg(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=CRegCnt) exit(255);
+ else
+ BEGIN
+ CRegs[InstrZ].Name=NName;
+ CRegs[InstrZ++].Code=NCode;
+ END
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(201);
+
+ InstrZ=0; FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt);
+ AddFixed("BKPT" ,0x0000,False);
+ AddFixed("DOZE" ,0x0006,True );
+ AddFixed("RFI" ,0x0003,True );
+ AddFixed("RTE" ,0x0002,True );
+ AddFixed("STOP" ,0x0004,True );
+ AddFixed("SYNC" ,0x0001,False);
+ AddFixed("WAIT" ,0x0005,True );
+
+ InstrZ=0; OneRegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*OneRegOrderCnt);
+ AddOneReg("ABS" ,0x01e0,False); AddOneReg("ASRC" ,0x3a00,False);
+ AddOneReg("BREV" ,0x00f0,False); AddOneReg("CLRF" ,0x01d0,False);
+ AddOneReg("CLRT" ,0x01c0,False); AddOneReg("DECF" ,0x0090,False);
+ AddOneReg("DECGT",0x01a0,False); AddOneReg("DECLT",0x0180,False);
+ AddOneReg("DECNE",0x01b0,False); AddOneReg("DECT" ,0x0080,False);
+ AddOneReg("DIVS" ,0x3210,False); AddOneReg("DIVU" ,0x2c10,False);
+ AddOneReg("FF1" ,0x00e0,False); AddOneReg("INCF" ,0x00b0,False);
+ AddOneReg("INCT" ,0x00a0,False); AddOneReg("JMP" ,0x00c0,False);
+ AddOneReg("JSR" ,0x00d0,False); AddOneReg("LSLC" ,0x3c00,False);
+ AddOneReg("LSRC" ,0x3e00,False); AddOneReg("MVC" ,0x0020,False);
+ AddOneReg("MVCV" ,0x0030,False); AddOneReg("NOT" ,0x01f0,False);
+ AddOneReg("SEXTB",0x0150,False); AddOneReg("SEXTH",0x0170,False);
+ AddOneReg("TSTNBZ",0x0190,False); AddOneReg("XSR" ,0x3800,False);
+ AddOneReg("XTRB0",0x0130,False); AddOneReg("XTRB1",0x0120,False);
+ AddOneReg("XTRB2",0x0110,False); AddOneReg("XTRB3",0x0100,False);
+ AddOneReg("ZEXTB",0x0140,False); AddOneReg("ZEXTH",0x0160,False);
+
+ InstrZ=0; TwoRegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*TwoRegOrderCnt);
+ AddTwoReg("ADDC" ,0x0600,False); AddTwoReg("ADDU" ,0x1c00,False);
+ AddTwoReg("AND" ,0x1600,False); AddTwoReg("ANDN" ,0x1f00,False);
+ AddTwoReg("ASR" ,0x1a00,False); AddTwoReg("BGENR",0x1300,False);
+ AddTwoReg("CMPHS",0x0c00,False); AddTwoReg("CMPLT",0x0d00,False);
+ AddTwoReg("CMPNE",0x0f00,False); AddTwoReg("IXH" ,0x1d00,False);
+ AddTwoReg("IXW" ,0x1500,False); AddTwoReg("LSL" ,0x1b00,False);
+ AddTwoReg("LSR" ,0x0b00,False); AddTwoReg("MOV" ,0x1200,False);
+ AddTwoReg("MOVF" ,0x0a00,False); AddTwoReg("MOVT" ,0x0200,False);
+ AddTwoReg("MULT" ,0x0300,False); AddTwoReg("OR" ,0x1e00,False);
+ AddTwoReg("RSUB" ,0x1400,False); AddTwoReg("SUBC" ,0x0700,False);
+ AddTwoReg("SUBU" ,0x0500,False); AddTwoReg("TST" ,0x0e00,False);
+ AddTwoReg("XOR" ,0x1700,False);
+
+ InstrZ=0; UImm5Orders=(ImmOrder *) malloc(sizeof(ImmOrder)*UImm5OrderCnt);
+ AddUImm5("ADDI" ,0x2000,0,1); AddUImm5("ANDI" ,0x2e00,0,0);
+ AddUImm5("ASRI" ,0x3a00,1,0); AddUImm5("BCLRI",0x3000,0,0);
+ AddUImm5("BSETI",0x3400,0,0); AddUImm5("BTSTI",0x3600,0,0);
+ AddUImm5("CMPLTI",0x2200,0,1); AddUImm5("CMPNEI",0x2a00,0,0);
+ AddUImm5("LSLI" ,0x3c00,1,0); AddUImm5("LSRI" ,0x3e00,1,0);
+ AddUImm5("ROTLI",0x3800,1,0); AddUImm5("RSUBI",0x2800,0,0);
+ AddUImm5("SUBI" ,0x2400,0,1);
+
+ InstrZ=0; LJmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LJmpOrderCnt);
+ AddLJmp("BF" ,0xe800,False); AddLJmp("BR" ,0xf000,False);
+ AddLJmp("BSR" ,0xf800,False); AddLJmp("BT" ,0xe000,False);
+
+ InstrZ=0; CRegs=(CReg *) malloc(sizeof(CReg)*CRegCnt);
+ AddCReg("PSR" , 0); AddCReg("VBR" , 1);
+ AddCReg("EPSR", 2); AddCReg("FPSR", 3);
+ AddCReg("EPC" , 4); AddCReg("FPC", 5);
+ AddCReg("SS0", 6); AddCReg("SS1", 7);
+ AddCReg("SS2", 8); AddCReg("SS3", 9);
+ AddCReg("SS4", 10); AddCReg("GCR", 11);
+ AddCReg("GSR", 12);
+
+ AddInstTable(InstTable,"BGENI" ,0,DecodeBGENI);
+ AddInstTable(InstTable,"BMASKI",0,DecodeBMASKI);
+ AddInstTable(InstTable,"JMPI" ,0,DecodeSJmp);
+ AddInstTable(InstTable,"JSRI" ,0,DecodeSJmp);
+ AddInstTable(InstTable,"LD" ,0x0ff,DecodeLdSt);
+ AddInstTable(InstTable,"LDB" ,0x000,DecodeLdSt);
+ AddInstTable(InstTable,"LDH" ,0x001,DecodeLdSt);
+ AddInstTable(InstTable,"LDW" ,0x002,DecodeLdSt);
+ AddInstTable(InstTable,"ST" ,0x1ff,DecodeLdSt);
+ AddInstTable(InstTable,"STB" ,0x100,DecodeLdSt);
+ AddInstTable(InstTable,"STH" ,0x101,DecodeLdSt);
+ AddInstTable(InstTable,"STW" ,0x102,DecodeLdSt);
+ AddInstTable(InstTable,"LDM" ,0,DecodeLdStm);
+ AddInstTable(InstTable,"STM" ,1,DecodeLdStm);
+ AddInstTable(InstTable,"LDQ" ,0,DecodeLdStq);
+ AddInstTable(InstTable,"STQ" ,1,DecodeLdStq);
+ AddInstTable(InstTable,"LOOPT" ,0,DecodeLoopt);
+ AddInstTable(InstTable,"LRM" ,0,DecodeLrm);
+ AddInstTable(InstTable,"MFCR" ,0,DecodeMcr);
+ AddInstTable(InstTable,"MTCR" ,1,DecodeMcr);
+ AddInstTable(InstTable,"MOVI" ,0,DecodeMovi);
+ AddInstTable(InstTable,"TRAP" ,0,DecodeTrap);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+ free(OneRegOrders);
+ free(TwoRegOrders);
+ free(UImm5Orders);
+ free(LJmpOrders);
+ free(CRegs);
+END
+
+/*--------------------------------------------------------------------------*/
+/* Callbacks */
+
+ static void MakeCode_MCORE(void)
+BEGIN
+ CodeLen=0;
+
+ OpSize=2;
+ DontPrint=False;
+
+ if (*AttrPart!='\0')
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B': OpSize=0; break;
+ case 'H': OpSize=1; break;
+ case 'W': OpSize=2; break;
+ case 'Q': OpSize=3; break;
+ case 'S': OpSize=4; break;
+ case 'D': OpSize=5; break;
+ case 'X': OpSize=6; break;
+ case 'P': OpSize=7; break;
+ default: WrError(1107); return;
+ END
+
+ /* Nullanweisung */
+
+ if ((*OpPart=='\0') AND (*AttrPart=='\0') AND (ArgCnt==0)) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodeMoto16Pseudo(OpSize,True)) return;
+
+ if (DecodePseudo()) return;
+
+ /* Befehlszaehler ungerade ? */
+
+ if (Odd(EProgCounter())) WrError(180);
+
+ /* alles aus der Tabelle */
+
+ if (LookupInstTable(InstTable,OpPart)) return;
+
+ /* unbekannter Befehl */
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_MCORE(void)
+BEGIN
+ return Memo("REG");
+END
+
+ static void SwitchFrom_MCORE(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_MCORE(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="*"; HeaderID=0x03; NOPCode=0x1200; /* ==MOV r0,r0 */
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+
+ ValidSegs=(1<<SegCode);
+ Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+#ifdef __STDC__
+ SegLimits[SegCode] = 0xfffffffful;
+#else
+ SegLimits[SegCode] = 0xffffffffl;
+#endif
+
+ MakeCode=MakeCode_MCORE; IsDef=IsDef_MCORE;
+
+ SwitchFrom=SwitchFrom_MCORE; InitFields();
+ AddONOFF("SUPMODE" , &SupAllowed, SupAllowedName,False);
+ AddMoto16PseudoONOFF();
+
+ SetFlag(&DoPadding,DoPaddingName,True);
+END
+
+/*--------------------------------------------------------------------------*/
+/* Initialisierung */
+
+ void codemcore_init(void)
+BEGIN
+ CPUMCORE=AddCPU("MCORE",SwitchTo_MCORE);
+END
diff --git a/codemcore.h b/codemcore.h
new file mode 100644
index 0000000..52e1f24
--- /dev/null
+++ b/codemcore.h
@@ -0,0 +1,11 @@
+/* codemcore.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator MCORE-Familie */
+/* */
+/* Historie: 31.1.1998 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codemcore_init(void);
diff --git a/codemsp.c b/codemsp.c
new file mode 100644
index 0000000..b674efe
--- /dev/null
+++ b/codemsp.c
@@ -0,0 +1,539 @@
+/* codemsp.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator MSP430 */
+/* */
+/* Historie: */
+/* 18. 8.1998 BookKeeping-Aufruf bei BSS */
+/* 2. 1.1998 ChkPC umgestellt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nls.h"
+#include "endian.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+#define TwoOpCount 12
+#define OneOpCount 6
+#define JmpCount 10
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Boolean MayByte;
+ Word Code;
+ } OneOpOrder;
+
+
+static CPUVar CPUMSP430;
+
+static FixedOrder *TwoOpOrders;
+static OneOpOrder *OneOpOrders;
+static FixedOrder *JmpOrders;
+
+static Word AdrMode,AdrMode2,AdrPart,AdrPart2;
+static Byte AdrCnt2;
+static Word AdrVal,AdrVal2;
+static Byte OpSize;
+static Word PCDist;
+
+/*-------------------------------------------------------------------------*/
+
+ static void AddTwoOp(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=TwoOpCount) exit(255);
+ TwoOpOrders[InstrZ].Name=NName;
+ TwoOpOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddOneOp(char *NName, Boolean NMay, Word NCode)
+BEGIN
+ if (InstrZ>=OneOpCount) exit(255);
+ OneOpOrders[InstrZ].Name=NName;
+ OneOpOrders[InstrZ].MayByte=NMay;
+ OneOpOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddJmp(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=JmpCount) exit(255);
+ JmpOrders[InstrZ].Name=NName;
+ JmpOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ TwoOpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*TwoOpCount); InstrZ=0;
+ AddTwoOp("MOV" ,0x4000); AddTwoOp("ADD" ,0x5000);
+ AddTwoOp("ADDC",0x6000); AddTwoOp("SUBC",0x7000);
+ AddTwoOp("SUB" ,0x8000); AddTwoOp("CMP" ,0x9000);
+ AddTwoOp("DADD",0xa000); AddTwoOp("BIT" ,0xb000);
+ AddTwoOp("BIC" ,0xc000); AddTwoOp("BIS" ,0xd000);
+ AddTwoOp("XOR" ,0xe000); AddTwoOp("AND" ,0xf000);
+
+ OneOpOrders=(OneOpOrder *) malloc(sizeof(OneOpOrder)*OneOpCount); InstrZ=0;
+ AddOneOp("RRC" ,True ,0x1000); AddOneOp("RRA" ,True ,0x1100);
+ AddOneOp("PUSH",True ,0x1200); AddOneOp("SWPB",False,0x1080);
+ AddOneOp("CALL",False,0x1280); AddOneOp("SXT" ,False,0x1180);
+
+ JmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*JmpCount); InstrZ=0;
+ AddJmp("JNE" ,0x2000); AddJmp("JNZ" ,0x2000);
+ AddJmp("JE" ,0x2400); AddJmp("JZ" ,0x2400);
+ AddJmp("JNC" ,0x2800); AddJmp("JC" ,0x2c00);
+ AddJmp("JN" ,0x3000); AddJmp("JGE" ,0x3400);
+ AddJmp("JL" ,0x3800); AddJmp("JMP" ,0x3C00);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(TwoOpOrders);
+ free(OneOpOrders);
+ free(JmpOrders);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void ResetAdr(void)
+BEGIN
+ AdrMode=0xff; AdrCnt=0;
+END
+
+ static void ChkAdr(Byte Mask)
+BEGIN
+ if ((AdrMode!=0xff) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ ResetAdr(); WrError(1350);
+ END
+END
+
+ static Boolean DecodeReg(char *Asc, Word *Erg)
+BEGIN
+ Boolean OK;
+
+ if (strcasecmp(Asc,"PC")==0)
+ BEGIN
+ *Erg=0; return True;
+ END
+ else if (strcasecmp(Asc,"SP")==0)
+ BEGIN
+ *Erg=1; return True;
+ END
+ else if (strcasecmp(Asc,"SR")==0)
+ BEGIN
+ *Erg=2; return True;
+ END
+ if ((toupper(*Asc)=='R') AND (strlen(Asc)>=2) AND (strlen(Asc)<=3))
+ BEGIN
+ *Erg=ConstLongInt(Asc+1,&OK);
+ return ((OK) AND (*Erg<16));
+ END
+ return False;
+END
+
+ static void DecodeAdr(char *Asc, Byte Mask, Boolean MayImm)
+BEGIN
+ Word AdrWord;
+ Boolean OK;
+ char *p;
+
+ ResetAdr();
+
+ /* immediate */
+
+ if (*Asc=='#')
+ BEGIN
+ if (NOT MayImm) WrError(1350);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(Asc+1,(OpSize==1)?Int8:Int16,&OK);
+ if (OK)
+ BEGIN
+ switch (AdrWord)
+ BEGIN
+ case 0:
+ AdrPart=3; AdrMode=0;
+ break;
+ case 1:
+ AdrPart=3; AdrMode=1;
+ break;
+ case 2:
+ AdrPart=3; AdrMode=2;
+ break;
+ case 4:
+ AdrPart=2; AdrMode=2;
+ break;
+ case 8:
+ AdrPart=2; AdrMode=3;
+ break;
+ case 0xffff:
+ AdrPart=3; AdrMode=3;
+ break;
+ default:
+ AdrVal=AdrWord; AdrCnt=1;
+ AdrPart=0; AdrMode=3;
+ break;
+ END
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* absolut */
+
+ if (*Asc=='&')
+ BEGIN
+ AdrVal=EvalIntExpression(Asc+1,UInt16,&OK);
+ if (OK)
+ BEGIN
+ AdrMode=1; AdrPart=2; AdrCnt=1;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* Register */
+
+ if (DecodeReg(Asc,&AdrPart))
+ BEGIN
+ if (AdrPart==3) WrXError(1445,Asc);
+ else AdrMode=0;
+ ChkAdr(Mask); return;
+ END
+
+ /* Displacement */
+
+ if (Asc[strlen(Asc)-1]==')')
+ BEGIN
+ Asc[strlen(Asc)-1]='\0';
+ p=RQuotPos(Asc,'(');
+ if (p!=Nil)
+ BEGIN
+ if (DecodeReg(p+1,&AdrPart))
+ BEGIN
+ *p='\0';
+ AdrVal=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ if ((AdrPart==2) OR (AdrPart==3)) WrXError(1445,Asc);
+ else if ((AdrVal==0) AND ((Mask & 4)!=0)) AdrMode=2;
+ else
+ BEGIN
+ AdrCnt=1; AdrMode=1;
+ END
+ *p='(';
+ ChkAdr(Mask); return;
+ END
+ END
+ Asc[strlen(Asc)]=')';
+ END
+
+ /* indirekt mit/ohne Autoinkrement */
+
+ if ((*Asc=='@') OR (*Asc=='*'))
+ BEGIN
+ if (Asc[strlen(Asc)-1]=='+')
+ BEGIN
+ AdrWord=1; Asc[strlen(Asc)-1]='\0';
+ END
+ else AdrWord=0;
+ if (NOT DecodeReg(Asc+1,&AdrPart)) WrXError(1445,Asc);
+ else if ((AdrPart==2) OR (AdrPart==3)) WrXError(1445,Asc);
+ else if ((AdrWord==0) AND ((Mask & 4)==0))
+ BEGIN
+ AdrVal=0; AdrCnt=1; AdrMode=1;
+ END
+ else AdrMode=2+AdrWord;
+ ChkAdr(Mask); return;
+ END
+
+ /* bleibt PC-relativ */
+
+ AdrWord=EvalIntExpression(Asc,UInt16,&OK)-EProgCounter()-PCDist;
+ if (OK)
+ BEGIN
+ AdrPart=0; AdrMode=1; AdrCnt=1; AdrVal=AdrWord;
+ END
+
+ ChkAdr(Mask);
+END
+
+/*-------------------------------------------------------------------------*/
+
+ static void PutByte(Byte Value)
+BEGIN
+ if (((CodeLen&1)==1) AND (NOT BigEndian))
+ BEGIN
+ BAsmCode[CodeLen]=BAsmCode[CodeLen-1];
+ BAsmCode[CodeLen-1]=Value;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=Value;
+ END
+ CodeLen++;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ TempResult t;
+ Word HVal16;
+ int z;
+ char *p;
+ Boolean OK;
+
+ if (Memo("BYTE"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z=1; OK=True;
+ do
+ BEGIN
+ KillBlanks(ArgStr[z]);
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (FirstPassUnknown) t.Contents.Int&=0xff;
+ if (NOT RangeCheck(t.Contents.Int,Int8)) WrError(1320);
+ else if (CodeLen==MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else PutByte(t.Contents.Int);
+ break;
+ case TempFloat:
+ WrError(1135); OK=False;
+ break;
+ case TempString:
+ if (strlen(t.Contents.Ascii)+CodeLen>=MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ TranslateString(t.Contents.Ascii);
+ for (p=t.Contents.Ascii; *p!='\0'; PutByte(*(p++)));
+ END
+ break;
+ case TempNone:
+ OK=False; break;
+ END
+ z++;
+ END
+ while ((z<=ArgCnt) AND (OK));
+ if (NOT OK) CodeLen=0;
+ else if ((Odd(CodeLen)) AND (DoPadding)) PutByte(0);
+ END
+ return True;
+ END
+
+ if (Memo("WORD"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z=1; OK=True;
+ do
+ BEGIN
+ HVal16=EvalIntExpression(ArgStr[z],Int16,&OK);
+ if (OK)
+ BEGIN
+ WAsmCode[CodeLen >> 1]=HVal16;
+ CodeLen+=2;
+ END
+ z++;
+ END
+ while ((z<=ArgCnt) AND (OK));
+ if (NOT OK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("BSS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ HVal16=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ else if (OK)
+ BEGIN
+ if ((Odd(HVal16)) AND (DoPadding)) HVal16++;
+ DontPrint=True; CodeLen=HVal16;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+/* float exp (8bit bias 128) sign mant (impl. norm.)
+ double exp (8bit bias 128) sign mant (impl. norm.) */
+
+ return False;
+END
+
+ static void MakeCode_MSP(void)
+BEGIN
+ int z;
+ Integer AdrInt;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Attribut bearbeiten */
+
+ if (*AttrPart=='\0') OpSize=0;
+ else if (strlen(AttrPart)>1) WrError(1107);
+ else
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B': OpSize=1; break;
+ case 'W': OpSize=0; break;
+ default: WrError(1107); return;
+ END
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* zwei Operanden */
+
+ for (z=0; z<TwoOpCount; z++)
+ if (Memo(TwoOpOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ PCDist=2; DecodeAdr(ArgStr[1],15,True);
+ if (AdrMode!=0xff)
+ BEGIN
+ AdrMode2=AdrMode; AdrPart2=AdrPart; AdrCnt2=AdrCnt; AdrVal2=AdrVal;
+ PCDist+=AdrCnt2 << 1; DecodeAdr(ArgStr[2],3,False);
+ if (AdrMode!=0xff)
+ BEGIN
+ WAsmCode[0]=TwoOpOrders[z].Code+(AdrPart2 << 8)+(AdrMode << 7)
+ +(OpSize << 6)+(AdrMode2 << 4)+AdrPart;
+ memcpy(WAsmCode+1,&AdrVal2,AdrCnt2 << 1);
+ memcpy(WAsmCode+1+AdrCnt2,&AdrVal,AdrCnt << 1);
+ CodeLen=(1+AdrCnt+AdrCnt2) << 1;
+ END
+ END
+ END
+ return;
+ END
+
+ /* ein Operand */
+
+ for (z=0; z<OneOpCount; z++)
+ if (Memo(OneOpOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if ((OpSize==1) AND (NOT OneOpOrders[z].MayByte)) WrError(1130);
+ else
+ BEGIN
+ PCDist=2; DecodeAdr(ArgStr[1],15,False);
+ if (AdrMode!=0xff)
+ BEGIN
+ WAsmCode[0]=OneOpOrders[z].Code+(OpSize << 6)+(AdrMode << 4)+AdrPart;
+ memcpy(WAsmCode+1,&AdrVal,AdrCnt << 1);
+ CodeLen=(1+AdrCnt) << 1;
+ END
+ END
+ return;
+ END
+
+ /* kein Operand */
+
+ if (Memo("RETI"))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ WAsmCode[0]=0x1300; CodeLen=2;
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ for (z=0; z<JmpCount; z++)
+ if (Memo(JmpOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if (Odd(AdrInt)) WrError(1375);
+ else if ((NOT SymbolQuestionable) AND ((AdrInt<-1024) OR (AdrInt>1022))) WrError(1370);
+ else
+ BEGIN
+ WAsmCode[0]=JmpOrders[z].Code+((AdrInt >> 1) & 0x3ff);
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_MSP(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_MSP(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_MSP(void)
+BEGIN
+ TurnWords=True; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x4a; NOPCode=0x4303; /* = MOV #0,#0 */
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ AddONOFF("PADDING", &DoPadding, DoPaddingName,False);
+
+ MakeCode=MakeCode_MSP; IsDef=IsDef_MSP;
+ SwitchFrom=SwitchFrom_MSP; InitFields();
+END
+
+ void codemsp_init(void)
+BEGIN
+ CPUMSP430=AddCPU("MSP430",SwitchTo_MSP);
+END
diff --git a/codemsp.h b/codemsp.h
new file mode 100644
index 0000000..b1b6d74
--- /dev/null
+++ b/codemsp.h
@@ -0,0 +1,11 @@
+/* codemsp.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator MSP430 */
+/* */
+/* Historie: */
+/* */
+/*****************************************************************************/
+
+extern void codemsp_init(void);
diff --git a/codepseudo.c b/codepseudo.c
new file mode 100644
index 0000000..8d474de
--- /dev/null
+++ b/codepseudo.c
@@ -0,0 +1,1246 @@
+/* codepseudo.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Haeufiger benutzte Pseudo-Befehle */
+/* */
+/* Historie: 23. 5.1996 Grundsteinlegung */
+/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
+/* 18. 8.1998 BookKeeping-Aufrufe bei SPeicherreservierungen */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "nls.h"
+#include "bpemu.h"
+#include "endian.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "asmitree.h"
+
+#include "codepseudo.h"
+
+
+ int FindInst(void *Field, int Size, int Count)
+BEGIN
+ char *cptr,**ptr;
+
+#ifdef OPT
+ int l=0,r=Count-1,m,res;
+
+ while (TRUE)
+ BEGIN
+ m=(l+r)>>1; cptr=((char *) Field)+(Size*m);
+ ptr=(char**) cptr;
+ res=strcmp(*ptr,OpPart);
+ if (res==0) return m;
+ else if (l==r) return -1;
+ else if (res<0)
+ BEGIN
+ if (r-l==1) return -1; else l=m;
+ END
+ else r=m;
+ END
+
+#else
+ int z,res;
+
+ cptr=(char *) Field;
+ for (z=0; z<Count; z++)
+ BEGIN
+ ptr=(char**) cptr;
+ res=strcmp(*ptr,OpPart);
+ if (res==0) return z;
+ if (res>0) return -1;
+ cptr+=Size;
+ END
+ return -1;
+#endif
+END
+
+
+ Boolean IsIndirect(char *Asc)
+BEGIN
+ int z,Level,l;
+
+ if (((l=strlen(Asc))<=2) OR (Asc[0]!='(') OR (Asc[l-1]!=')')) return False;
+
+ Level=0;
+ for (z=1; z<=l-2; z++)
+ BEGIN
+ if (Asc[z]=='(') Level++;
+ if (Asc[z]==')') Level--;
+ if (Level<0) return False;
+ END
+
+ return True;
+END
+
+
+static enum{DSNone,DSConstant,DSSpace} DSFlag;
+typedef Boolean (*TLayoutFunc)(
+#ifdef __PROTOS__
+ char *Asc, Word *Cnt, Boolean Turn
+#endif
+ );
+
+ static Boolean LayoutByte(char *Asc, Word *Cnt, Boolean Turn)
+BEGIN
+ Boolean Result;
+ TempResult t;
+
+ Result=False;
+
+ if (strcmp(Asc,"?")==0)
+ BEGIN
+ if (DSFlag==DSConstant) WrError(1930);
+ else
+ BEGIN
+ *Cnt=1; Result=True; DSFlag=DSSpace; CodeLen++;
+ END
+ return Result;
+ END
+ else
+ BEGIN
+ if (DSFlag==DSSpace)
+ BEGIN
+ WrError(1930); return Result;
+ END
+ else DSFlag=DSConstant;
+ END
+
+ FirstPassUnknown=False; EvalExpression(Asc,&t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (FirstPassUnknown) t.Contents.Int&=0xff;
+ if (NOT RangeCheck(t.Contents.Int,Int8)) WrError(1320);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=t.Contents.Int; *Cnt=1;
+ Result=True;
+ END;
+ break;
+ case TempFloat:
+ WrError(1135);
+ break;
+ case TempString:
+ TranslateString(t.Contents.Ascii);
+ memcpy(BAsmCode+CodeLen,t.Contents.Ascii,strlen(t.Contents.Ascii));
+ CodeLen+=(*Cnt=strlen(t.Contents.Ascii));
+ Result=True;
+ break;
+ case TempNone:
+ break;
+ END
+
+ return Result;
+END
+
+
+ static Boolean LayoutWord(char *Asc, Word *Cnt, Boolean Turn)
+BEGIN
+ Boolean OK,Result;
+ Word erg;
+
+ *Cnt=2; Result=False;
+
+ if (strcmp(Asc,"?")==0)
+ BEGIN
+ if (DSFlag==DSConstant) WrError(1930);
+ else
+ BEGIN
+ Result=True; DSFlag=DSSpace; CodeLen+=2;
+ END
+ return Result;
+ END
+ else
+ BEGIN
+ if (DSFlag==DSSpace)
+ BEGIN
+ WrError(1930); return Result;
+ END
+ else DSFlag=DSConstant;
+ END
+
+ if (CodeLen+2>MaxCodeLen)
+ BEGIN
+ WrError(1920); return Result;
+ END
+ erg=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ if (Turn) erg=((erg>>8)&0xff)+((erg&0xff)<<8);
+ BAsmCode[CodeLen]=erg&0xff; BAsmCode[CodeLen+1]=erg>>8;
+ CodeLen+=2;
+ END
+ return OK;
+END
+
+
+ static Boolean LayoutDoubleWord(char *Asc, Word *Cnt, Boolean Turn)
+BEGIN
+ TempResult erg;
+ Boolean Result=False;
+
+ *Cnt=4;
+
+ if (strcmp(Asc,"?")==0)
+ BEGIN
+ if (DSFlag==DSConstant) WrError(1930);
+ else
+ BEGIN
+ Result=True; DSFlag=DSSpace; CodeLen+=4;
+ END
+ return Result;
+ END
+ else
+ BEGIN
+ if (DSFlag==DSSpace)
+ BEGIN
+ WrError(1930); return Result;
+ END
+ else DSFlag=DSConstant;
+ END
+
+ if (CodeLen+4>MaxCodeLen)
+ BEGIN
+ WrError(1920); return Result;
+ END
+
+ KillBlanks(Asc); EvalExpression(Asc,&erg);
+ switch (erg.Typ)
+ BEGIN
+ case TempNone: return Result;
+ case TempInt:
+ if (RangeCheck(erg.Contents.Int,Int32))
+ BEGIN
+ BAsmCode[CodeLen ]=((erg.Contents.Int )&0xff);
+ BAsmCode[CodeLen+1]=((erg.Contents.Int>> 8)&0xff);
+ BAsmCode[CodeLen+2]=((erg.Contents.Int>>16)&0xff);
+ BAsmCode[CodeLen+3]=((erg.Contents.Int>>24)&0xff);
+ CodeLen+=4;
+ END
+ else
+ BEGIN
+ WrError(1320);
+ return Result;
+ END
+ break;
+ case TempFloat:
+ if (FloatRangeCheck(erg.Contents.Float,Float32))
+ BEGIN
+ Double_2_ieee4(erg.Contents.Float,BAsmCode+CodeLen,False);
+ CodeLen+=4;
+ END
+ else
+ BEGIN
+ WrError(1320);
+ return Result;
+ END
+ break;
+ case TempString:
+ WrError(1135);
+ return Result;
+ END
+
+ if (Turn) DSwap(BAsmCode+CodeLen-4,4);
+ return True;
+END
+
+
+ static Boolean LayoutQuadWord(char *Asc, Word *Cnt, Boolean Turn)
+BEGIN
+ Boolean Result;
+ TempResult erg;
+#ifndef HAS64
+ int z;
+#endif
+
+ Result=False; *Cnt=8;
+
+ if (strcmp(Asc,"?")==0)
+ BEGIN
+ if (DSFlag==DSConstant) WrError(1930);
+ else
+ BEGIN
+ Result=True; DSFlag=DSSpace; CodeLen+=8;
+ END
+ return Result;
+ END
+ else
+ BEGIN
+ if (DSFlag==DSSpace)
+ BEGIN
+ WrError(1930); return Result;
+ END
+ else DSFlag=DSConstant;
+ END
+
+ if (CodeLen+8>MaxCodeLen)
+ BEGIN
+ WrError(1920); return Result;
+ END
+
+ KillBlanks(Asc); EvalExpression(Asc,&erg);
+ switch(erg.Typ)
+ BEGIN
+ case TempNone:
+ return Result;
+ case TempInt:
+ memcpy(BAsmCode+CodeLen,&(erg.Contents.Int),sizeof(LargeInt));
+#ifdef HAS64
+ if (BigEndian) QSwap(BAsmCode+CodeLen,8);
+#else
+ if (BigEndian) DSwap(BAsmCode+CodeLen,4);
+ for (z=4; z<8; BAsmCode[CodeLen+(z++)]=(BAsmCode[CodeLen+3]>=0x80)?0xff:0x00);
+#endif
+ CodeLen+=8;
+ break;
+ case TempFloat:
+ Double_2_ieee8(erg.Contents.Float,BAsmCode+CodeLen,False);
+ CodeLen+=8;
+ break;
+ case TempString:
+ WrError(1135);
+ return Result;
+ END
+
+ if (Turn) QSwap(BAsmCode+CodeLen-8,8);
+ return True;
+END
+
+
+ static Boolean LayoutTenBytes(char *Asc, Word *Cnt, Boolean Turn)
+BEGIN
+ Boolean OK,Result;
+ Double erg;
+ int z;
+ Byte Exg;
+
+ Result=False; *Cnt=10;
+
+ if (strcmp(Asc,"?")==0)
+ BEGIN
+ if (DSFlag==DSConstant) WrError(1930);
+ else
+ BEGIN
+ Result=True; DSFlag=DSSpace; CodeLen+=10;
+ END
+ return Result;
+ END
+ else
+ BEGIN
+ if (DSFlag==DSSpace)
+ BEGIN
+ WrError(1930); return Result;
+ END
+ else DSFlag=DSConstant;
+ END
+
+ if (CodeLen+10>MaxCodeLen)
+ BEGIN
+ WrError(1920); return Result;
+ END
+ erg=EvalFloatExpression(Asc,Float64,&OK);
+ if (OK)
+ BEGIN
+ Double_2_ieee10(erg,BAsmCode+CodeLen,False);
+ CodeLen+=10;
+ if (Turn)
+ for (z=0; z<5; z++)
+ BEGIN
+ Exg=BAsmCode[CodeLen-10+z];
+ BAsmCode[CodeLen-10+z]=BAsmCode[CodeLen-1-z];
+ BAsmCode[CodeLen-1-z]=Exg;
+ END
+ END
+ return OK;
+END
+
+
+ static Boolean DecodeIntelPseudo_ValidSymChar(char ch)
+BEGIN
+ return (((ch>='A') AND (ch<='Z')) OR ((ch>='0') AND (ch<='9')) OR (ch=='_') OR (ch=='.'));
+END
+
+ static Boolean DecodeIntelPseudo_LayoutMult(char *Asc_O, Word *Cnt,
+ TLayoutFunc LayoutFunc,
+ Boolean Turn)
+BEGIN
+ int z,Depth,Fnd,ALen;
+ String Asc,Part;
+ Word SumCnt,ECnt,SInd;
+ LongInt Rep;
+ Boolean OK,Hyp;
+
+ strmaxcpy(Asc,Asc_O,255);
+
+ /* nach DUP suchen */
+
+ Depth=0; Fnd=0; ALen=strlen(Asc);
+ for (z=0; z<ALen-2; z++)
+ BEGIN
+ if (Asc[z]=='(') Depth++;
+ else if (Asc[z]==')') Depth--;
+ else if (Depth==0)
+ if ( ((z==0) OR (NOT DecodeIntelPseudo_ValidSymChar(Asc[z-1])))
+ AND (NOT DecodeIntelPseudo_ValidSymChar(Asc[z+3]))
+ AND (strncasecmp(Asc+z,"DUP",3)==0)) Fnd=z;
+ END
+
+ /* DUP gefunden: */
+
+ if (Fnd!=0)
+ BEGIN
+ /* Anzahl ausrechnen */
+
+ FirstPassUnknown=False;
+ Asc[Fnd]='\0'; Rep=EvalIntExpression(Asc,Int32,&OK); Asc[Fnd]='D';
+ if (FirstPassUnknown)
+ BEGIN
+ WrError(1820); return False;
+ END
+ if (NOT OK) return False;
+
+ /* Nullargument vergessen, bei negativem warnen */
+
+ if (Rep<0) WrError(270);
+ if (Rep<=0) return True;
+
+ /* Einzelteile bilden & evaluieren */
+
+ strcpy(Asc,Asc+Fnd+3); KillPrefBlanks(Asc); SumCnt=0;
+ if ((strlen(Asc)>=2) AND (*Asc=='(') AND (Asc[strlen(Asc)-1]==')'))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ END
+ do
+ BEGIN
+ Fnd=0; z=0; Hyp=False; Depth=0;
+ do
+ BEGIN
+ if (Asc[z]=='\'') Hyp=NOT Hyp;
+ else if (NOT Hyp)
+ BEGIN
+ if (Asc[z]=='(') Depth++;
+ else if (Asc[z]==')') Depth--;
+ else if ((Depth==0) AND (Asc[z]==',')) Fnd=z;
+ END
+ z++;
+ END
+ while ((z<strlen(Asc)) AND (Fnd==0));
+ if (Fnd==0)
+ BEGIN
+ strmaxcpy(Part,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ Asc[Fnd]='\0'; strmaxcpy(Part,Asc,255);
+ strcpy(Asc,Asc+Fnd+1);
+ END
+ if (NOT DecodeIntelPseudo_LayoutMult(Part,&ECnt,LayoutFunc,Turn))
+ return False;
+ SumCnt+=ECnt;
+ END
+ while (*Asc!='\0');
+
+ /* Ergebnis vervielfachen */
+
+ if (DSFlag==DSConstant)
+ BEGIN
+ SInd=CodeLen-SumCnt;
+ if (CodeLen+SumCnt*(Rep-1)>MaxCodeLen)
+ BEGIN
+ WrError(1920); return False;
+ END
+ for (z=1; z<=Rep-1; z++)
+ BEGIN
+ if (CodeLen+SumCnt>MaxCodeLen) return False;
+ memcpy(BAsmCode+CodeLen,BAsmCode+SInd,SumCnt);
+ CodeLen+=SumCnt;
+ END
+ END
+ else CodeLen+=SumCnt*(Rep-1);
+ *Cnt=SumCnt*Rep; return True;
+ END
+
+ /* kein DUP: einfacher Ausdruck */
+
+ else return LayoutFunc(Asc,Cnt,Turn);
+END
+
+ Boolean DecodeIntelPseudo(Boolean Turn)
+BEGIN
+ Word Dummy;
+ int z;
+ TLayoutFunc LayoutFunc=Nil;
+ Boolean OK;
+ LongInt HVal;
+ char Ident;
+
+ if ((strlen(OpPart)!=2) OR (*OpPart!='D')) return False;
+ Ident=OpPart[1];
+
+ if ((Ident=='B') OR (Ident=='W') OR (Ident=='D') OR (Ident=='Q') OR (Ident=='T'))
+ BEGIN
+ DSFlag=DSNone;
+ switch (Ident)
+ BEGIN
+ case 'B':
+ LayoutFunc=LayoutByte;
+ if (*LabPart!='\0') SetSymbolSize(LabPart,0);
+ break;
+ case 'W':
+ LayoutFunc=LayoutWord;
+ if (*LabPart!='\0') SetSymbolSize(LabPart,1);
+ break;
+ case 'D':
+ LayoutFunc=LayoutDoubleWord;
+ if (*LabPart!='\0') SetSymbolSize(LabPart,2);
+ break;
+ case 'Q':
+ LayoutFunc=LayoutQuadWord;
+ if (*LabPart!='\0') SetSymbolSize(LabPart,3);
+ break;
+ case 'T':
+ LayoutFunc=LayoutTenBytes;
+ if (*LabPart!='\0') SetSymbolSize(LabPart,4);
+ break;
+ END
+ z=1;
+ do
+ BEGIN
+ OK=DecodeIntelPseudo_LayoutMult(ArgStr[z],&Dummy,LayoutFunc,Turn);
+ if (NOT OK) CodeLen=0;
+ z++;
+ END
+ while ((OK) AND (z<=ArgCnt));
+ DontPrint=(DSFlag==DSSpace);
+ if (DontPrint) BookKeeping();
+ if (OK) ActListGran=1;
+ return True;
+ END
+
+ if (Ident=='S')
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ HVal=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ else if (OK)
+ BEGIN
+ DontPrint=True; CodeLen=HVal;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+/*--------------------------------------------------------------------------*/
+
+static Boolean M16Turn=False;
+
+ static Boolean CutRep(char *Asc, LongInt *Erg)
+BEGIN
+ char *p;
+ Boolean OK;
+
+ if (*Asc!='[')
+ BEGIN
+ *Erg=1; return True;
+ END
+ else
+ BEGIN
+ strcpy(Asc,Asc+1); p=QuotPos(Asc,']');
+ if (p==Nil)
+ BEGIN
+ WrError(1300); return False;
+ END
+ else
+ BEGIN
+ *p='\0';
+ *Erg=EvalIntExpression(Asc,Int32,&OK);
+ strcpy(Asc,p+1); return OK;
+ END
+ END
+END
+
+ static void DecodeBYT(Word Index)
+BEGIN
+ int z;
+ Boolean OK;
+ TempResult t;
+ LongInt Rep,z2;
+
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z=1; OK=True;
+ do
+ BEGIN
+ KillBlanks(ArgStr[z]);
+ OK=CutRep(ArgStr[z],&Rep);
+ if (OK)
+ BEGIN
+ EvalExpression(ArgStr[z],&t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (NOT RangeCheck(t.Contents.Int,Int8))
+ BEGIN
+ WrError(1320); OK=False;
+ END
+ else if (CodeLen+Rep>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ memset(BAsmCode+CodeLen,t.Contents.Int,Rep);
+ CodeLen+=Rep;
+ END
+ break;
+ case TempFloat:
+ WrError(1135); OK=False;
+ break;
+ case TempString:
+ TranslateString(t.Contents.Ascii);
+ if (CodeLen+Rep*strlen(t.Contents.Ascii)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else for (z2=0; z2<Rep; z2++)
+ BEGIN
+ memcpy(BAsmCode+CodeLen,t.Contents.Ascii,strlen(t.Contents.Ascii));
+ CodeLen+=strlen(t.Contents.Ascii);
+ END
+ break;
+ default:
+ OK=False;
+ break;
+ END
+ END
+ z++;
+ END
+ while ((z<=ArgCnt) AND (OK));
+ if (NOT OK) CodeLen=0;
+ END
+END
+
+ static void DecodeADR(Word Index)
+BEGIN
+ int z;
+ Word HVal16;
+ Boolean OK;
+ LongInt Rep,z2;
+
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z=1; OK=True;
+ do
+ BEGIN
+ OK=CutRep(ArgStr[z],&Rep);
+ if (OK)
+ if (CodeLen+(Rep<<1)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ HVal16=EvalIntExpression(ArgStr[z],Int16,&OK);
+ if (OK)
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ if (M16Turn)
+ BEGIN
+ BAsmCode[CodeLen++]=Hi(HVal16);
+ BAsmCode[CodeLen++]=Lo(HVal16);
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=Lo(HVal16);
+ BAsmCode[CodeLen++]=Hi(HVal16);
+ END
+ END
+ END
+ z++;
+ END
+ while ((z<=ArgCnt) AND (OK));
+ if (NOT OK) CodeLen=0;
+ END
+END
+
+ static void DecodeFCC(Word Index)
+BEGIN
+ String SVal;
+ Boolean OK;
+ int z;
+ LongInt Rep,z2;
+
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z=1; OK=True;
+ do
+ BEGIN
+ OK=CutRep(ArgStr[z],&Rep);
+ if (OK)
+ BEGIN
+ EvalStringExpression(ArgStr[z],&OK,SVal);
+ if (OK)
+ if (CodeLen+Rep*strlen(SVal)>=MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ TranslateString(SVal);
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ memcpy(BAsmCode+CodeLen,SVal,strlen(SVal));
+ CodeLen+=strlen(SVal);
+ END
+ END
+ END
+ z++;
+ END
+ while ((z<=ArgCnt) AND (OK));
+ if (NOT OK) CodeLen=0;
+ END
+END
+
+ static void DecodeDFS(Word Index)
+BEGIN
+ Word HVal16;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ HVal16=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (FirstPassUnknown) WrError(1820);
+ else if (OK)
+ BEGIN
+ DontPrint=True; CodeLen=HVal16;
+ BookKeeping();
+ END
+ END
+END
+
+ Boolean DecodeMotoPseudo(Boolean Turn)
+BEGIN
+ static PInstTable InstTable=Nil;
+
+ if (InstTable==Nil)
+ BEGIN
+ InstTable=CreateInstTable(17);
+ AddInstTable(InstTable,"BYT",0,DecodeBYT);
+ AddInstTable(InstTable,"FCB",0,DecodeBYT);
+ AddInstTable(InstTable,"ADR",0,DecodeADR);
+ AddInstTable(InstTable,"FDB",0,DecodeADR);
+ AddInstTable(InstTable,"FCC",0,DecodeFCC);
+ AddInstTable(InstTable,"DFS",0,DecodeDFS);
+ AddInstTable(InstTable,"RMB",0,DecodeDFS);
+ END
+
+ M16Turn=Turn;
+ return LookupInstTable(InstTable,OpPart);
+END
+
+ static void DigIns(char Ch, Byte Pos, Word *w)
+BEGIN
+ Byte wpos=Pos>>2,bpos=(Pos&3)*4;
+ Word dig=Ch-'0';
+
+ w[wpos]|=(dig<<bpos);
+END
+
+ void ConvertDec(Double F, Word *w)
+BEGIN
+ char s[30],Man[30],Exp[30];
+ char *h;
+ LongInt z;
+ Byte epos;
+
+ sprintf(s,"%0.16e",F); h=strchr(s,'e');
+ if (h==Nil)
+ BEGIN
+ strcpy(Man,s); strcpy(Exp,"+0000");
+ END
+ else
+ BEGIN
+ *h='\0';
+ strcpy(Man,s); strcpy(Exp,h+1);
+ END
+ memset(w,0,12);
+ if (*Man=='-')
+ BEGIN
+ w[5]|=0x8000; strcpy(Man,Man+1);
+ END
+ else if (*Man=='+') strcpy(Man,Man+1);
+ if (*Exp=='-')
+ BEGIN
+ w[5]|=0x4000; strcpy(Exp,Exp+1);
+ END
+ else if (*Exp=='+') strcpy(Exp,Exp+1);
+ DigIns(*Man,16,w); strcpy(Man,Man+2);
+ if (strlen(Man)>16) Man[16]='\0';
+ for (z=0; z<strlen(Man); z++) DigIns(Man[z],15-z,w);
+ if (strlen(Exp)>4) strcpy(Exp,Exp+strlen(Exp)-4);
+ for (z=strlen(Exp)-1; z>=0; z--)
+ BEGIN
+ epos=strlen(Exp)-1-z;
+ if (epos==3) DigIns(Exp[z],19,w); else DigIns(Exp[z],epos+20,w);
+ END
+END
+
+
+ static void EnterByte(Byte b)
+BEGIN
+ if (((CodeLen&1)==1) AND (NOT BigEndian) AND (ListGran()!=1))
+ BEGIN
+ BAsmCode[CodeLen]=BAsmCode[CodeLen-1];
+ BAsmCode[CodeLen-1]=b;
+ END
+ else
+ BEGIN
+ BAsmCode[CodeLen]=b;
+ END
+ CodeLen++;
+END
+
+ void AddMoto16PseudoONOFF(void)
+BEGIN
+ AddONOFF("PADDING",&DoPadding,DoPaddingName,False);
+END
+
+ Boolean DecodeMoto16Pseudo(ShortInt OpSize, Boolean Turn)
+BEGIN
+ Byte z;
+ Word TurnField[8];
+ char *zp;
+ LongInt z2;
+ LongInt WSize,Rep=0;
+ LongInt NewPC,HVal,WLen;
+#ifdef HAS64
+ QuadInt QVal;
+#endif
+ Integer HVal16;
+ Double DVal;
+ TempResult t;
+ Boolean OK,ValOK;
+
+ if (OpSize<0) OpSize=1;
+
+ if (*OpPart!='D') return False;
+
+ if (Memo("DC"))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ OK=True; z=1; WLen=0;
+ do
+ BEGIN
+ FirstPassUnknown=False;
+ OK=CutRep(ArgStr[z],&Rep);
+ if (OK)
+ if (FirstPassUnknown) WrError(1820);
+ else
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case 0:
+ FirstPassUnknown=False;
+ EvalExpression(ArgStr[z],&t);
+ if ((FirstPassUnknown) AND (t.Typ==TempInt)) t.Contents.Int&=0xff;
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (NOT RangeCheck(t.Contents.Int,Int8))
+ BEGIN
+ WrError(1320); OK=False;
+ END
+ else if (CodeLen+Rep>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else for (z2=0; z2<Rep; z2++) EnterByte(t.Contents.Int);
+ break;
+ case TempFloat:
+ WrError(1135); OK=False;
+ break;
+ case TempString:
+ if (CodeLen+Rep*strlen(t.Contents.Ascii)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ for (z2=0; z2<Rep; z2++)
+ for (zp=t.Contents.Ascii; *zp!='\0'; EnterByte(CharTransTable[((usint) *(zp++))&0xff]));
+ break;
+ default: OK=False;
+ END
+ break;
+ case 1:
+ HVal16=EvalIntExpression(ArgStr[z],Int16,&OK);
+ if (OK)
+ if (CodeLen+(Rep<<1)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ if (ListGran()==1)
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ BAsmCode[(WLen<<1) ]=Hi(HVal16);
+ BAsmCode[(WLen<<1)+1]=Lo(HVal16);
+ WLen++;
+ END
+ else
+ for (z2=0; z2<Rep; z2++) WAsmCode[WLen++]=HVal16;
+ CodeLen+=Rep<<1;
+ END
+ break;
+ case 2:
+ HVal=EvalIntExpression(ArgStr[z],Int32,&OK);
+ if (OK)
+ if (CodeLen+(Rep<<2)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ if (ListGran()==1)
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ BAsmCode[(WLen<<1) ]=(HVal >> 24) & 0xff;
+ BAsmCode[(WLen<<1)+1]=(HVal >> 16) & 0xff;
+ BAsmCode[(WLen<<1)+2]=(HVal >> 8) & 0xff;
+ BAsmCode[(WLen<<1)+3]=(HVal ) & 0xff;
+ WLen+=2;
+ END
+ else
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ WAsmCode[WLen++]=HVal >> 16;
+ WAsmCode[WLen++]=HVal & 0xffff;
+ END
+ CodeLen+=Rep<<2;
+ END
+ break;
+#ifdef HAS64
+ case 3:
+ QVal=EvalIntExpression(ArgStr[z],Int64,&OK);
+ if (OK)
+ if (CodeLen+(Rep<<3)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ if (ListGran()==1)
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ BAsmCode[(WLen<<1) ]=(QVal >> 56) & 0xff;
+ BAsmCode[(WLen<<1)+1]=(QVal >> 48) & 0xff;
+ BAsmCode[(WLen<<1)+2]=(QVal >> 40) & 0xff;
+ BAsmCode[(WLen<<1)+3]=(QVal >> 32) & 0xff;
+ BAsmCode[(WLen<<1)+4]=(QVal >> 24) & 0xff;
+ BAsmCode[(WLen<<1)+5]=(QVal >> 16) & 0xff;
+ BAsmCode[(WLen<<1)+6]=(QVal >> 8) & 0xff;
+ BAsmCode[(WLen<<1)+7]=(QVal ) & 0xff;
+ WLen+=4;
+ END
+ else
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ WAsmCode[WLen++]=(QVal >> 48) & 0xffff;
+ WAsmCode[WLen++]=(QVal >> 32) & 0xffff;
+ WAsmCode[WLen++]=(QVal >> 16) & 0xffff;
+ WAsmCode[WLen++]=QVal & 0xffff;
+ END
+ CodeLen+=Rep<<3;
+ END
+ break;
+#endif
+ case 4:
+ DVal=EvalFloatExpression(ArgStr[z],Float32,&OK);
+ if (OK)
+ if (CodeLen+(Rep<<2)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ Double_2_ieee4(DVal,(Byte *) TurnField,BigEndian);
+ if (BigEndian) DWSwap((void*) TurnField,4);
+ if (ListGran()==1)
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ BAsmCode[(WLen<<1) ]=Hi(TurnField[1]);
+ BAsmCode[(WLen<<1)+1]=Lo(TurnField[1]);
+ BAsmCode[(WLen<<1)+2]=Hi(TurnField[0]);
+ BAsmCode[(WLen<<1)+3]=Lo(TurnField[0]);
+ WLen+=2;
+ END
+ else
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ WAsmCode[WLen++]=TurnField[1];
+ WAsmCode[WLen++]=TurnField[0];
+ END
+ CodeLen+=Rep<<2;
+ END
+ break;
+ case 5:
+ DVal=EvalFloatExpression(ArgStr[z],Float64,&OK);
+ if (OK)
+ if (CodeLen+(Rep<<3)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ Double_2_ieee8(DVal,(Byte *) TurnField,BigEndian);
+ if (BigEndian) QWSwap((void *) TurnField,8);
+ if (ListGran()==1)
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ BAsmCode[(WLen<<1) ]=Hi(TurnField[3]);
+ BAsmCode[(WLen<<1)+1]=Lo(TurnField[3]);
+ BAsmCode[(WLen<<1)+2]=Hi(TurnField[2]);
+ BAsmCode[(WLen<<1)+3]=Lo(TurnField[2]);
+ BAsmCode[(WLen<<1)+4]=Hi(TurnField[1]);
+ BAsmCode[(WLen<<1)+5]=Lo(TurnField[1]);
+ BAsmCode[(WLen<<1)+6]=Hi(TurnField[0]);
+ BAsmCode[(WLen<<1)+7]=Lo(TurnField[0]);
+ WLen+=4;
+ END
+ else
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ WAsmCode[WLen++]=TurnField[3];
+ WAsmCode[WLen++]=TurnField[2];
+ WAsmCode[WLen++]=TurnField[1];
+ WAsmCode[WLen++]=TurnField[0];
+ END
+ CodeLen+=Rep<<3;
+ END
+ break;
+ case 6:
+ DVal=EvalFloatExpression(ArgStr[z],Float64,&OK);
+ if (OK)
+ if (CodeLen+(Rep*12)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ Double_2_ieee10(DVal,(Byte *) TurnField,False);
+ if (BigEndian) WSwap((void *) TurnField,10);
+ if (ListGran()==1)
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ BAsmCode[(WLen<<1) ]=Hi(TurnField[4]);
+ BAsmCode[(WLen<<1)+ 1]=Lo(TurnField[4]);
+ BAsmCode[(WLen<<1)+ 2]=0;
+ BAsmCode[(WLen<<1)+ 3]=0;
+ BAsmCode[(WLen<<1)+ 4]=Hi(TurnField[3]);
+ BAsmCode[(WLen<<1)+ 5]=Lo(TurnField[3]);
+ BAsmCode[(WLen<<1)+ 6]=Hi(TurnField[2]);
+ BAsmCode[(WLen<<1)+ 7]=Lo(TurnField[2]);
+ BAsmCode[(WLen<<1)+ 8]=Hi(TurnField[1]);
+ BAsmCode[(WLen<<1)+ 9]=Lo(TurnField[1]);
+ BAsmCode[(WLen<<1)+10]=Hi(TurnField[0]);
+ BAsmCode[(WLen<<1)+11]=Lo(TurnField[0]);
+ WLen+=6;
+ END
+ else
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ WAsmCode[WLen++]=TurnField[4];
+ WAsmCode[WLen++]=0;
+ WAsmCode[WLen++]=TurnField[3];
+ WAsmCode[WLen++]=TurnField[2];
+ WAsmCode[WLen++]=TurnField[1];
+ WAsmCode[WLen++]=TurnField[0];
+ END
+ CodeLen+=Rep*12;
+ END
+ break;
+ case 7:
+ DVal=EvalFloatExpression(ArgStr[z],Float64,&OK);
+ if (OK)
+ if (CodeLen+(Rep*12)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ ConvertDec(DVal,TurnField);
+ if (ListGran()==1)
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ BAsmCode[(WLen<<1) ]=Hi(TurnField[5]);
+ BAsmCode[(WLen<<1)+ 1]=Lo(TurnField[5]);
+ BAsmCode[(WLen<<1)+ 2]=Hi(TurnField[4]);
+ BAsmCode[(WLen<<1)+ 3]=Lo(TurnField[4]);
+ BAsmCode[(WLen<<1)+ 4]=Hi(TurnField[3]);
+ BAsmCode[(WLen<<1)+ 5]=Lo(TurnField[3]);
+ BAsmCode[(WLen<<1)+ 6]=Hi(TurnField[2]);
+ BAsmCode[(WLen<<1)+ 7]=Lo(TurnField[2]);
+ BAsmCode[(WLen<<1)+ 8]=Hi(TurnField[1]);
+ BAsmCode[(WLen<<1)+ 9]=Lo(TurnField[1]);
+ BAsmCode[(WLen<<1)+10]=Hi(TurnField[0]);
+ BAsmCode[(WLen<<1)+11]=Lo(TurnField[0]);
+ WLen+=6;
+ END
+ else
+ for (z2=0; z2<Rep; z2++)
+ BEGIN
+ WAsmCode[WLen++]=TurnField[5];
+ WAsmCode[WLen++]=TurnField[4];
+ WAsmCode[WLen++]=TurnField[3];
+ WAsmCode[WLen++]=TurnField[2];
+ WAsmCode[WLen++]=TurnField[1];
+ WAsmCode[WLen++]=TurnField[0];
+ END
+ CodeLen+=Rep*12;
+ END
+ break;
+ END
+ END
+ z++;
+ END
+ while ((z<=ArgCnt) AND (OK));
+ if (NOT OK) CodeLen=0;
+ if ((DoPadding) AND ((CodeLen&1)==1)) EnterByte(0);
+ END
+ return True;
+ END
+
+ if (Memo("DS"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ HVal=EvalIntExpression(ArgStr[1],Int32,&ValOK);
+ if (FirstPassUnknown) WrError(1820);
+ if ((ValOK) AND (NOT FirstPassUnknown))
+ BEGIN
+ DontPrint=True;
+ switch (OpSize)
+ BEGIN
+ case 0: WSize=1; if (((HVal&1)==1) AND (DoPadding)) HVal++; break;
+ case 1: WSize=2; break;
+ case 2:
+ case 4: WSize=4; break;
+ case 3:
+ case 5: WSize=8; break;
+ case 6:
+ case 7: WSize=12; break;
+ default: WSize=0;
+ END
+ if (HVal==0)
+ BEGIN
+ NewPC=ProgCounter()+WSize-1;
+ NewPC=NewPC-(NewPC % WSize);
+ CodeLen=NewPC-ProgCounter();
+ if (CodeLen==0) DontPrint=False;
+ END
+ else CodeLen=HVal*WSize;
+ if (DontPrint) BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+
+ void CodeEquate(ShortInt DestSeg, LargeInt Min, LargeInt Max)
+BEGIN
+ Boolean OK;
+ TempResult t;
+ LargeInt Erg;
+
+ FirstPassUnknown=False;
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ Erg=EvalIntExpression(ArgStr[1],Int32,&OK);
+ if ((OK) AND (NOT FirstPassUnknown))
+ if (Min>Erg) WrError(1315);
+ else if (Erg>Max) WrError(1320);
+ else
+ BEGIN
+ PushLocHandle(-1);
+ EnterIntSymbol(LabPart,Erg,DestSeg,False);
+ PopLocHandle();
+ if (MakeUseList)
+ if (AddChunk(SegChunks+DestSeg,Erg,1,False)) WrError(90);
+ t.Typ=TempInt; t.Contents.Int=Erg; SetListLineVal(&t);
+ END
+ END
+END
+
+ void CodeASSUME(ASSUMERec *Def, Integer Cnt)
+BEGIN
+ int z1,z2;
+ Boolean OK;
+ LongInt HVal;
+ String RegPart,ValPart;
+
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z1=1; OK=True;
+ while ((z1<=ArgCnt) AND (OK))
+ BEGIN
+ SplitString(ArgStr[z1],RegPart,ValPart,QuotPos(ArgStr[z1],':'));
+ z2=0; NLS_UpString(RegPart);
+ while ((z2<Cnt) AND (strcmp(Def[z2].Name,RegPart)!=0)) z2++;
+ OK=(z2<Cnt);
+ if (NOT OK) WrXError(1980,RegPart);
+ else
+ if (strcmp(ValPart,"NOTHING")==0)
+ if (Def[z2].NothingVal==-1) WrError(1350);
+ else *Def[z2].Dest=Def[z2].NothingVal;
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ HVal=EvalIntExpression(ValPart,Int32,&OK);
+ if (OK)
+ if (FirstPassUnknown)
+ BEGIN
+ WrError(1820); OK=False;
+ END
+ else if (ChkRange(HVal,Def[z2].Min,Def[z2].Max)) *Def[z2].Dest=HVal;
+ END
+ z1++;
+ END
+ END
+END
+
+ void codepseudo_init(void)
+BEGIN
+END
+
diff --git a/codepseudo.h b/codepseudo.h
new file mode 100644
index 0000000..0ffbfe8
--- /dev/null
+++ b/codepseudo.h
@@ -0,0 +1,37 @@
+/* codepseudo.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Haeufiger benutzte Pseudo-Befehle */
+/* */
+/* Historie: 23. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+typedef struct
+ {
+ char *Name;
+ LongInt *Dest;
+ LongInt Min,Max;
+ LongInt NothingVal;
+ } ASSUMERec;
+
+extern int FindInst(void *Field, int Size, int Count);
+
+extern Boolean IsIndirect(char *Asc);
+
+extern void ConvertDec(Double F, Word *w);
+
+extern Boolean DecodeIntelPseudo(Boolean Turn);
+
+extern Boolean DecodeMotoPseudo(Boolean Turn);
+
+extern void AddMoto16PseudoONOFF(void);
+
+extern Boolean DecodeMoto16Pseudo(ShortInt OpSize, Boolean Turn);
+
+extern void CodeEquate(ShortInt DestSeg, LargeInt Min, LargeInt Max);
+
+extern void CodeASSUME(ASSUMERec *Def, Integer Cnt);
+
+extern void codepseudo_init(void);
diff --git a/codesc14xxx.c b/codesc14xxx.c
new file mode 100644
index 0000000..5a5943f
--- /dev/null
+++ b/codesc14xxx.c
@@ -0,0 +1,441 @@
+/* codesc14xxx.c */
+
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator SC14xxx */
+/* */
+/* Historie: 25. 3.1999 Grundsteinlegung */
+/* 27. 3.1999 Durch die Befehle durch */
+/* 19. 4.1999 Argumentbereich B_BR korrigiert */
+/* 20. 4.1999 Argumentbereich B_RST korrigiert */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "headids.h"
+#include "asmitree.h"
+
+/*---------------------------------------------------------------------------*/
+
+#define M_14400 (1 << 0)
+#define M_14401 (1 << 1)
+#define M_14402 (1 << 2)
+#define M_14404 (1 << 3)
+#define M_14405 (1 << 4)
+#define M_14420 (1 << 5)
+#define M_14421 (1 << 6)
+#define M_14422 (1 << 7)
+#define M_14424 (1 << 8)
+
+#define FixedOrderCnt 155
+
+typedef struct
+ {
+ Word CPUMask;
+ Byte Code, MinArg, MaxArg;
+ } FixedOrder;
+
+static CPUVar CPU14400, CPU14401, CPU14402, CPU14404, CPU14405,
+ CPU14420, CPU14421, CPU14422, CPU14424;
+static PInstTable InstTable;
+static FixedOrder *FixedOrders;
+static Word CurrMask;
+
+/*---------------------------------------------------------------------------*/
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *POp = FixedOrders + Index;
+ Boolean OK;
+ Byte Value;
+
+ if ((ArgCnt > 1) OR ((ArgCnt == 0) AND (POp->MinArg != POp->MaxArg))) WrError(1110);
+ else if ((POp->CPUMask & CurrMask) == 0) WrError(1500);
+ else
+ BEGIN
+ OK = True;
+ if (ArgCnt == 0) Value = 0;
+ else
+ BEGIN
+ FirstPassUnknown = False;
+ Value = EvalIntExpression(ArgStr[1], Int8, &OK);
+ if (FirstPassUnknown) Value = POp->MinArg;
+ if (OK) OK = ChkRange(Value, POp->MinArg, POp->MaxArg);
+ END
+ if (OK)
+ BEGIN
+ WAsmCode[0] = (((Word) POp->Code) << 8) + (Value & 0xff);
+ CodeLen = 1;
+ END
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+static Boolean Toggle;
+
+ static void PutByte(Byte Val)
+BEGIN
+ if (Toggle) WAsmCode[CodeLen++] |= ((Word) Val) << 8;
+ else WAsmCode[CodeLen] = Val & 0xff;
+ Toggle = NOT Toggle;
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ int z;
+ Boolean OK;
+ TempResult t;
+ char *p;
+
+ if ((Memo("DC")) OR (Memo("DC8")))
+ BEGIN
+ if (ArgCnt == 0) WrError(1110);
+ else
+ BEGIN
+ z = 1; OK = TRUE; Toggle = FALSE;
+ while ((OK) AND (z <= ArgCnt))
+ BEGIN
+ FirstPassUnknown = False;
+ EvalExpression(ArgStr[z], &t);
+ switch (t.Typ)
+ BEGIN
+ case TempInt:
+ if (FirstPassUnknown) t.Contents.Int &= 127;
+ if (ChkRange(t.Contents.Int, -128, 255)) PutByte(t.Contents.Int);
+ break;
+ case TempString:
+ for (p = t.Contents.Ascii; *p != '\0'; p++)
+ PutByte(CharTransTable[((usint) *p) & 0xff]);
+ break;
+ case TempFloat:
+ WrError(1135);
+ default:
+ OK = False;
+ END
+ z++;
+ END
+ if (NOT OK) CodeLen = 0;
+ else if (Toggle) CodeLen++;
+ END
+ return True;
+ END
+
+ if ((Memo("DW")) OR (Memo("DW16")))
+ BEGIN
+ if (ArgCnt == 0) WrError(1110);
+ else
+ BEGIN
+ z = 1; OK = TRUE;
+ while ((OK) AND (z <= ArgCnt))
+ BEGIN
+ WAsmCode[z - 1] = EvalIntExpression(ArgStr[z], Int16, &OK);
+ z++;
+ END
+ if (OK) CodeLen = ArgCnt;
+ END
+ return True;
+ END
+
+ if ((Memo("DS8")) OR (Memo("DS")))
+ BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown = False;
+ z = EvalIntExpression(ArgStr[1], UInt16, &OK);
+ if (OK)
+ if (FirstPassUnknown) WrError(1820);
+ else
+ BEGIN
+ CodeLen = (z + 1) >> 1;
+ DontPrint = True;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ if (Memo("DS16"))
+ BEGIN
+ if (ArgCnt != 1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown = False;
+ z = EvalIntExpression(ArgStr[1], UInt16, &OK);
+ if (OK)
+ if (FirstPassUnknown) WrError(1820);
+ else
+ BEGIN
+ CodeLen = z;
+ DontPrint = True;
+ BookKeeping();
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+/*---------------------------------------------------------------------------*/
+
+static int InstrZ;
+
+ static void AddFixed(char *NName, Byte NCode, Word NMask,
+ Byte NMin, Byte NMax)
+BEGIN
+ if (InstrZ >= FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].CPUMask = NMask;
+ FixedOrders[InstrZ].Code = NCode;
+ FixedOrders[InstrZ].MinArg = NMin;
+ FixedOrders[InstrZ].MaxArg = NMax;
+ AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable = CreateInstTable(301);
+
+ FixedOrders = (FixedOrder*) malloc(sizeof(FixedOrder) * FixedOrderCnt);
+ InstrZ = 0;
+
+ /* standard set */
+
+ AddFixed("BR" , 0x01, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x01, 0xff);
+ AddFixed("BRK" , 0x6e, M_14402 | M_14404 | M_14405 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("JMP" , 0x02, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x01, 0xff);
+ AddFixed("JMP1" , 0x03, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x01, 0xff);
+ AddFixed("RTN" , 0x04, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("WNT" , 0x08, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x01, 0xff);
+ AddFixed("WT" , 0x09, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x01, 0xff);
+ AddFixed("WSC" , 0x48, M_14404 | M_14405 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("RFEN" , 0x0b, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("RFDIS" , 0x0a, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("BK_A" , 0x0e, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("BK_A1" , 0x05, M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("BK_C" , 0x0f, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("SLOTZERO" , 0x0d, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("EN_SL_ADJ", 0x2c, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("WNTP1" , 0x07, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("WNTM1" , 0x06, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("LD_PTR" , 0x0c, M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("UNLCK" , 0x28, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RX" , 0x49, M_14404 | M_14405 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("A_TX" , 0x4a, M_14404 | M_14405 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("A_MUTE" , 0xc1, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_MTOFF" , 0xc9, M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_MUTE1" , 0xca, M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_MTOFF1" , 0xcb, M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_STOFF" , 0xc2, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_STON" , 0xcc, M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV0" , 0x80, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV36" , 0x82, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV30" , 0x83, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV24" , 0x84, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV18" , 0x85, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV12" , 0x86, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV6" , 0x87, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV33" , 0x8a, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV27" , 0x8b, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV21" , 0x8c, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV15" , 0x8d, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV9" , 0x8e, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RCV3" , 0x8f, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_NORM" , 0xc5, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_RST" , 0xc0, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_LDR" , 0xc6, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("A_LDW" , 0xc7, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("A_RST1" , 0xeb, M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("A_LDR1" , 0xce, M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("A_LDW1" , 0xcf, M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("A_ST18" , 0xe1, M_14402 , 0x00, 0x00);
+ AddFixed("B_ST" , 0x31, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_ST2" , 0x21, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_PPT" , 0x22, M_14404 | M_14405 | M_14424, 0x00, 0x00);
+ AddFixed("B_ZT" , 0x22, M_14400 , 0x00, 0x00);
+ AddFixed("B_ZR" , 0x2a, M_14400 , 0x00, 0x00);
+ AddFixed("B_AT" , 0x32, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_AT2" , 0x37, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BT" , 0x34, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BTFM" , 0x23, M_14404 | M_14405 | M_14424, 0x00, 0xff);
+ AddFixed("B_BTFU" , 0x25, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BTFP" , 0x35, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BTDU" , 0x71, M_14404 | M_14405 | M_14424, 0x00, 0xff);
+ AddFixed("B_BTDP" , 0x72, M_14404 | M_14405 | M_14424, 0x00, 0xff);
+ AddFixed("B_XON" , 0x27, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_XOFF" , 0x26, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_SR" , 0x29, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_AR" , 0x3a, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_AR2" , 0x3f, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_RON" , 0x2f, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_RINV" , 0x2e, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_BR" , 0x3c, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BRFU" , 0x2d, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BRFP" , 0x3d, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BRFD" , 0x2a, M_14404 | M_14405 | M_14424, 0x00, 0xff);
+ AddFixed("B_BRDU" , 0x79, M_14404 | M_14405 | M_14424, 0x00, 0xff);
+ AddFixed("B_BRDP" , 0x7a, M_14404 | M_14405 | M_14424, 0x00, 0xff);
+ AddFixed("B_XR" , 0x2b, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_XT" , 0x24, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_WB_ON" , 0x65, M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_WB_OFF" , 0x64, M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_WRS" , 0x39, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_RC" , 0x33, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_RST" , 0x20, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("B_DIV1" , 0x4f, M_14405 , 0x00, 0x00);
+ AddFixed("B_DIV2" , 0x4e, M_14405 , 0x00, 0x00);
+ AddFixed("B_DIV4" , 0x4d, M_14405 , 0x00, 0x00);
+ AddFixed("C_LD" , 0xfa, M_14401 | M_14402 | M_14420 | M_14421 | M_14422 , 0x00, 0xff);
+ AddFixed("C_ON" , 0xee, M_14420 | M_14421 | M_14422 , 0x00, 0x00);
+ AddFixed("C_OFF" , 0xef, M_14420 | M_14421 | M_14422 , 0x00, 0x00);
+ AddFixed("C_LD2" , 0xba, M_14424, 0x00, 0xff);
+ AddFixed("C_ON2" , 0xae, M_14424, 0x00, 0x00);
+ AddFixed("C_OFF2" , 0xaf, M_14424, 0x00, 0x00);
+ AddFixed("D_LDK" , 0x50, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("D_PREP" , 0x44, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("D_WRS" , 0x5f, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("D_LDS" , 0x57, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("D_RST" , 0x40, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("M_WR" , 0xb9, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("M_RST" , 0xa9, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("M_INI0" , 0xa0, M_14404 | M_14405 | M_14424, 0x00, 0x00);
+ AddFixed("M_INI1" , 0xa1, M_14404 | M_14405 | M_14424, 0x00, 0x00);
+ AddFixed("MEN1N" , 0xa4, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("MEN1" , 0xa5, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("P_EN" , 0xe9, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("P_LDH" , 0xed, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("P_LDL" , 0xec, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("P_LD" , 0xe8, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("P_SC" , 0xea, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("U_INT0" , 0x61, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("U_INT1" , 0x6b, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("U_INT2" , 0x6d, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("U_INT3" , 0x6f, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("U_PSC" , 0x60, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+ AddFixed("U_VINT" , 0x63, M_14404 | M_14405 | M_14422 | M_14424, 0x00, 0xff);
+
+ /* obsolete stuff - argument range may be incorrect */
+
+ AddFixed("D_ON" , 0x42, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("D_OFF" , 0x43, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("RCK_INT" , 0x62, M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("CLK1" , 0x66, M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("CLK3" , 0x67, M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("U_CK8" , 0x68, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("U_CK4" , 0x69, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("U_CK2" , 0x6a, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("U_CK1" , 0x6c, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("MEN3N" , 0xa2, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("MEN3" , 0xa3, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("MEN2N" , 0xa6, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("MEN2" , 0xa7, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("M_RD" , 0xa8, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0xff);
+ AddFixed("M_WRS" , 0xb8, M_14400 | M_14420 | M_14421 , 0x00, 0xff);
+ AddFixed("A_ALAW" , 0xc3, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("A_DT" , 0xc4, M_14400 | M_14401 | M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("A_LIN" , 0xc8, M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("A_DT1" , 0xcd, M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("A_STRN" , 0xe0, M_14420 | M_14421 , 0x00, 0x00);
+ AddFixed("RCK_EXT" , 0x63, M_14420 | M_14421 , 0x00, 0xff);
+ AddFixed("P_SPD0" , 0xe8, M_14400 , 0x00, 0xff);
+ AddFixed("P_SPD1" , 0xe9, M_14400 , 0x00, 0xff);
+ AddFixed("P_SPD2" , 0xea, M_14400 , 0x00, 0xff);
+ AddFixed("P_SPD3" , 0xeb, M_14400 , 0x00, 0xff);
+ AddFixed("P_SPD4" , 0xec, M_14400 , 0x00, 0xff);
+ AddFixed("P_SPD5" , 0xed, M_14400 , 0x00, 0xff);
+ AddFixed("P_SPD6" , 0xee, M_14400 , 0x00, 0xff);
+ AddFixed("P_SPD7" , 0xef, M_14400 , 0x00, 0xff);
+ AddFixed("P_RPD0" , 0xe0, M_14400 , 0x00, 0xff);
+ AddFixed("P_RPD1" , 0xe1, M_14400 , 0x00, 0xff);
+ AddFixed("P_RPD2" , 0xe2, M_14400 , 0x00, 0xff);
+ AddFixed("P_RPD3" , 0xe3, M_14400 , 0x00, 0xff);
+ AddFixed("P_RPD4" , 0xe4, M_14400 , 0x00, 0xff);
+ AddFixed("P_RPD5" , 0xe5, M_14400 , 0x00, 0xff);
+ AddFixed("P_RPD6" , 0xe6, M_14400 , 0x00, 0xff);
+ AddFixed("P_RPD7" , 0xe7, M_14400 , 0x00, 0xff);
+
+ /* aliases */
+
+ AddFixed("B_TX" , 0x31, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BT2" , 0x25, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BR2" , 0x2d, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BTP" , 0x35, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_BRP" , 0x3d, M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0xff);
+ AddFixed("B_ON" , 0x27, M_14400 | M_14401 | M_14402 | M_14404 | M_14405 | M_14420 | M_14421 | M_14422 | M_14424, 0x00, 0x00);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ DestroyInstTable(InstTable);
+ free(FixedOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void MakeCode_sc14xxx(void)
+BEGIN
+ /* Leeranweisung ignorieren */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (NOT LookupInstTable(InstTable,OpPart))
+ WrXError(1200, OpPart);
+END
+
+ static Boolean IsDef_sc14xxx(void)
+BEGIN
+ return FALSE;
+END
+
+ static void SwitchFrom_sc14xxx(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_sc14xxx(void)
+BEGIN
+ PFamilyDescr FoundDescr;
+
+ FoundDescr = FindFamilyByName("SC14XXX");
+
+ TurnWords = False; ConstMode = ConstModeC; SetIsOccupied = False;
+ PCSymbol = "$"; HeaderID = FoundDescr->Id; NOPCode = 0x0000;
+ DivideChars = ","; HasAttrs = False;
+
+ ValidSegs = (1<<SegCode);
+ Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 1;
+ SegLimits[SegCode] = 0xff;
+
+ MakeCode=MakeCode_sc14xxx; IsDef = IsDef_sc14xxx;
+ SwitchFrom = SwitchFrom_sc14xxx;
+
+ InitFields();
+ CurrMask = 1 << (MomCPU - CPU14400);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ void codesc14xxx_init(void)
+BEGIN
+ CPU14400 = AddCPU("SC14400", SwitchTo_sc14xxx);
+ CPU14401 = AddCPU("SC14401", SwitchTo_sc14xxx);
+ CPU14402 = AddCPU("SC14402", SwitchTo_sc14xxx);
+ CPU14404 = AddCPU("SC14404", SwitchTo_sc14xxx);
+ CPU14405 = AddCPU("SC14405", SwitchTo_sc14xxx);
+ CPU14420 = AddCPU("SC14420", SwitchTo_sc14xxx);
+ CPU14421 = AddCPU("SC14421", SwitchTo_sc14xxx);
+ CPU14422 = AddCPU("SC14422", SwitchTo_sc14xxx);
+ CPU14424 = AddCPU("SC14424", SwitchTo_sc14xxx);
+END
diff --git a/codesc14xxx.h b/codesc14xxx.h
new file mode 100644
index 0000000..913a8f0
--- /dev/null
+++ b/codesc14xxx.h
@@ -0,0 +1,16 @@
+/* codesc14xxx.h */
+#ifndef _CODESC14XXX_H
+#define _CODESC14XXX_H
+
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator SC14xxx */
+/* */
+/* Historie: 25. 3.1999 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codesc14xxx_init(void);
+
+#endif /* _CODESC14XXX_H */
diff --git a/codescmp.c b/codescmp.c
new file mode 100644
index 0000000..18af961
--- /dev/null
+++ b/codescmp.c
@@ -0,0 +1,326 @@
+/* codescmp.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator National SC/MP */
+/* */
+/* Historie: 17. 2.1996 Grundsteinlegung */
+/* 2. 1.1998 ChkPC umgestellt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+#define FixedOrderCnt 21
+#define ImmOrderCnt 8
+#define RegOrderCnt 3
+#define MemOrderCnt 8
+#define JmpOrderCnt 4
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } FixedOrder;
+
+
+static CPUVar CPUSCMP;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *ImmOrders;
+static FixedOrder *RegOrders;
+static FixedOrder *MemOrders;
+static FixedOrder *JmpOrders;
+
+/*---------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddImm(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ImmOrderCnt) exit(255);
+ ImmOrders[InstrZ].Name=NName;
+ ImmOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddReg(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=RegOrderCnt) exit(255);
+ RegOrders[InstrZ].Name=NName;
+ RegOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddMem(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=MemOrderCnt) exit(255);
+ MemOrders[InstrZ].Name=NName;
+ MemOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddJmp(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=JmpOrderCnt) exit(255);
+ JmpOrders[InstrZ].Name=NName;
+ JmpOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("LDE" ,0x40); AddFixed("XAE" ,0x01); AddFixed("ANE" ,0x50);
+ AddFixed("ORE" ,0x58); AddFixed("XRE" ,0x60); AddFixed("DAE" ,0x68);
+ AddFixed("ADE" ,0x70); AddFixed("CAE" ,0x78); AddFixed("SIO" ,0x19);
+ AddFixed("SR" ,0x1c); AddFixed("SRL" ,0x1d); AddFixed("RR" ,0x1e);
+ AddFixed("RRL" ,0x1f); AddFixed("HALT",0x00); AddFixed("CCL" ,0x02);
+ AddFixed("SCL" ,0x03); AddFixed("DINT",0x04); AddFixed("IEN" ,0x05);
+ AddFixed("CSA" ,0x06); AddFixed("CAS" ,0x07); AddFixed("NOP" ,0x08);
+
+ ImmOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ImmOrderCnt); InstrZ=0;
+ AddImm("LDI" ,0xc4); AddImm("ANI" ,0xd4); AddImm("ORI" ,0xdc);
+ AddImm("XRI" ,0xe4); AddImm("DAI" ,0xec); AddImm("ADI" ,0xf4);
+ AddImm("CAI" ,0xfc); AddImm("DLY" ,0x8f);
+
+ RegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RegOrderCnt); InstrZ=0;
+ AddReg("XPAL",0x30); AddReg("XPAH",0x34); AddReg("XPPC",0x3c);
+
+ MemOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*MemOrderCnt); InstrZ=0;
+ AddMem("LD" ,0xc0); AddMem("ST" ,0xc8); AddMem("AND" ,0xd0);
+ AddMem("OR" ,0xd8); AddMem("XOR" ,0xe0); AddMem("DAD" ,0xe8);
+ AddMem("ADD" ,0xf0); AddMem("CAD" ,0xf8);
+
+ JmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*JmpOrderCnt); InstrZ=0;
+ AddJmp("JMP" ,0x90); AddJmp("JP" ,0x94); AddJmp("JZ" ,0x98);
+ AddJmp("JNZ" ,0x9c);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(ImmOrders);
+ free(RegOrders);
+ free(MemOrders);
+ free(JmpOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean DecodeReg(char *Asc, Byte *Erg)
+BEGIN
+ if ((strlen(Asc)!=2) OR (toupper(*Asc)!='P')) return False;
+
+ switch (toupper(Asc[1]))
+ BEGIN
+ case 'C': *Erg=0; break;
+ case '0': case '1': case '2':
+ case '3': *Erg=Asc[1]-'0'; break;
+ default: return False;
+ END
+
+ return True;
+END
+
+ static Boolean DecodeAdr(char *Asc, Boolean MayInc, Byte PCDisp, Byte *Arg)
+BEGIN
+ Integer Disp;
+ Word PCVal;
+ Boolean OK;
+ int l=strlen(Asc);
+
+ if ((l>=4) AND (Asc[l-1]==')') AND (Asc[l-4]=='('))
+ BEGIN
+ Asc[l-1]='\0';
+ if (DecodeReg(Asc+l-3,Arg))
+ BEGIN
+ Asc[l-4]='\0';
+ if (*Asc=='@')
+ BEGIN
+ if (NOT MayInc)
+ BEGIN
+ WrError(1350); return False;
+ END
+ strcpy(Asc,Asc+1); *Arg+=4;
+ END
+ if (strcasecmp(Asc,"E")==0) BAsmCode[1]=0x80;
+ else if (*Arg==0)
+ BEGIN
+ WrXError(1445,Asc+l-3); return False;
+ END
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(Asc,SInt8,&OK);
+ if (NOT OK) return False;
+ END
+ return True;
+ END
+ else Asc[l-1]=')';
+ END
+
+ PCVal=(EProgCounter() & 0xf000)+((EProgCounter()+1) & 0xfff);
+ Disp=EvalIntExpression(Asc,UInt16,&OK)-PCDisp-PCVal;
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((Disp<-128) OR (Disp>127))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[1]=Disp & 0xff; *Arg=0; return True;
+ END
+ return False;
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void ChkPage(void)
+BEGIN
+ if (((EProgCounter()) & 0xf000)!=((EProgCounter()+CodeLen) & 0xf000)) WrError(250);
+END
+
+ static void MakeCode_SCMP(void)
+BEGIN
+ int z;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(False)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=FixedOrders[z].Code; CodeLen=1;
+ END
+ return;
+ END
+
+ /* immediate */
+
+ for (z=0; z<ImmOrderCnt; z++)
+ if (Memo(ImmOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=ImmOrders[z].Code; CodeLen=2; ChkPage();
+ END
+ END
+ return;
+ END
+
+ /* ein Register */
+
+ for (z=0; z<RegOrderCnt; z++)
+ if (Memo(RegOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeReg(ArgStr[1],BAsmCode+0)) WrXError(1445,ArgStr[1]);
+ else
+ BEGIN
+ BAsmCode[0]+=RegOrders[z].Code; CodeLen=1;
+ END
+ return;
+ END
+
+ /* ein Speicheroperand */
+
+ for (z=0; z<MemOrderCnt; z++)
+ if (Memo(MemOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeAdr(ArgStr[1],True,0,BAsmCode+0))
+ BEGIN
+ BAsmCode[0]+=MemOrders[z].Code; CodeLen=2; ChkPage();
+ END
+ return;
+ END
+
+ for (z=0; z<JmpOrderCnt; z++)
+ if (Memo(JmpOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeAdr(ArgStr[1],False,1,BAsmCode+0))
+ BEGIN
+ BAsmCode[0]+=JmpOrders[z].Code; CodeLen=2; ChkPage();
+ END
+ return;
+ END
+
+ if ((Memo("ILD")) OR (Memo("DLD")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (DecodeAdr(ArgStr[1],False,0,BAsmCode+0))
+ BEGIN
+ BAsmCode[0]+=0xa8+(Ord(Memo("DLD")) << 4); CodeLen=2; ChkPage();
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_SCMP(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_SCMP(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_SCMP(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeC; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x6e; NOPCode=0x08;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_SCMP; IsDef=IsDef_SCMP;
+ SwitchFrom=SwitchFrom_SCMP; InitFields();
+END
+
+ void codescmp_init(void)
+BEGIN
+ CPUSCMP=AddCPU("SC/MP",SwitchTo_SCMP);
+END
+
+
diff --git a/codescmp.h b/codescmp.h
new file mode 100644
index 0000000..538d562
--- /dev/null
+++ b/codescmp.h
@@ -0,0 +1,11 @@
+/* codescmp.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator National SC/MP */
+/* */
+/* Historie: 17.2.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codescmp_init(void);
diff --git a/codest6.c b/codest6.c
new file mode 100644
index 0000000..ea7f242
--- /dev/null
+++ b/codest6.c
@@ -0,0 +1,634 @@
+/* codest6.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator ST6-Familie */
+/* */
+/* Historie: 14.11.1996 Grundsteinlegung */
+/* 2. 1.1998 ChkPC ersetzt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } AccOrder;
+
+
+#define FixedOrderCnt 5
+
+#define RelOrderCnt 4
+
+#define ALUOrderCnt 4
+
+#define AccOrderCnt 3
+
+
+#define ModNone (-1)
+#define ModAcc 0
+#define MModAcc (1 << ModAcc)
+#define ModDir 1
+#define MModDir (1 << ModDir)
+#define ModInd 2
+#define MModInd (1 << ModInd)
+
+
+static Byte AdrMode;
+static ShortInt AdrType;
+static Byte AdrVal;
+
+static LongInt WinAssume;
+
+static SimpProc SaveInitProc;
+
+static CPUVar CPUST6210,CPUST6215,CPUST6220,CPUST6225;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *RelOrders;
+static FixedOrder *ALUOrders;
+static AccOrder *AccOrders;
+
+/*---------------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRel(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ALUOrderCnt) exit(255);
+ ALUOrders[InstrZ].Name=NName;
+ ALUOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddAcc(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=AccOrderCnt) exit(255);
+ AccOrders[InstrZ].Name=NName;
+ AccOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("NOP" , 0x04);
+ AddFixed("RET" , 0xcd);
+ AddFixed("RETI", 0x4d);
+ AddFixed("STOP", 0x6d);
+ AddFixed("WAIT", 0xed);
+
+ RelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RelOrderCnt); InstrZ=0;
+ AddRel("JRZ" , 0x04);
+ AddRel("JRNZ", 0x00);
+ AddRel("JRC" , 0x06);
+ AddRel("JRNC", 0x02);
+
+ ALUOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALUOrderCnt); InstrZ=0;
+ AddALU("ADD" , 0x47);
+ AddALU("AND" , 0xa7);
+ AddALU("CP" , 0x27);
+ AddALU("SUB" , 0xc7);
+
+ AccOrders=(AccOrder *) malloc(sizeof(AccOrder)*AccOrderCnt); InstrZ=0;
+ AddAcc("COM", 0x002d);
+ AddAcc("RLC", 0x00ad);
+ AddAcc("SLA", 0xff5f);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(RelOrders);
+ free(ALUOrders);
+ free(AccOrders);
+END
+
+/*---------------------------------------------------------------------------------*/
+
+ static void ResetAdr(void)
+BEGIN
+ AdrType=ModNone; AdrCnt=0;
+END
+
+ static void ChkAdr(Byte Mask)
+BEGIN
+ if ((AdrType!=ModNone) AND ((Mask AND (1 << AdrType))==0))
+ BEGIN
+ ResetAdr(); WrError(1350);
+ END
+END
+
+ static void DecodeAdr(char *Asc, Byte Mask)
+BEGIN
+#define RegCnt 5
+ static char *RegNames[RegCnt+1]={"A","V","W","X","Y"};
+ static Byte RegCodes[RegCnt+1]={0xff,0x82,0x83,0x80,0x81};
+
+ Boolean OK;
+ int z;
+ Integer AdrInt;
+
+ ResetAdr();
+
+ if ((strcasecmp(Asc,"A")==0) AND ((Mask & MModAcc)!=0))
+ BEGIN
+ AdrType=ModAcc; ChkAdr(Mask); return;
+ END
+
+ for (z=0; z<RegCnt; z++)
+ if (strcasecmp(Asc,RegNames[z])==0)
+ BEGIN
+ AdrType=ModDir; AdrCnt=1; AdrVal=RegCodes[z];
+ ChkAdr(Mask); return;
+ END
+
+ if (strcasecmp(Asc,"(X)")==0)
+ BEGIN
+ AdrType=ModInd; AdrMode=0; ChkAdr(Mask); return;
+ END
+
+ if (strcasecmp(Asc,"(Y)")==0)
+ BEGIN
+ AdrType=ModInd; AdrMode=1; ChkAdr(Mask); return;
+ END
+
+ AdrInt=EvalIntExpression(Asc,UInt16,&OK);
+ if (OK)
+ if ((TypeFlag & (1 << SegCode))!=0)
+ BEGIN
+ AdrType=ModDir; AdrVal=(AdrInt & 0x3f)+0x40; AdrCnt=1;
+ if (NOT FirstPassUnknown)
+ if (WinAssume!=(AdrInt >> 6)) WrError(110);
+ END
+ else
+ BEGIN
+ if (FirstPassUnknown) AdrInt=Lo(AdrInt);
+ if (AdrInt>0xff) WrError(1320);
+ else
+ BEGIN
+ AdrType=ModDir; AdrVal=AdrInt; ChkAdr(Mask); return;
+ END
+ END
+
+ ChkAdr(Mask);
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUME62Count 1
+ static ASSUMERec ASSUME62s[ASSUME62Count]=
+ {{"ROMBASE", &WinAssume, 0, 0x3f, 0x40}};
+
+ Boolean OK,Flag;
+ int z;
+ String s;
+
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,0xff);
+ return True;
+ END
+
+ if ((Memo("ASCII")) OR (Memo("ASCIZ")))
+ BEGIN
+ if (ArgCnt==0) WrError(1110);
+ else
+ BEGIN
+ z=1; Flag=Memo("ASCIZ");
+ do
+ BEGIN
+ EvalStringExpression(ArgStr[z],&OK,s);
+ if (OK)
+ BEGIN
+ TranslateString(s);
+ if (CodeLen+strlen(s)+Ord(Flag)>MaxCodeLen)
+ BEGIN
+ WrError(1920); OK=False;
+ END
+ else
+ BEGIN
+ memcpy(BAsmCode+CodeLen,s,strlen(s)); CodeLen+=strlen(s);
+ if (Flag) BAsmCode[CodeLen++]=0;
+ END
+ END
+ z++;
+ END
+ while ((OK) AND (z<=ArgCnt));
+ if (NOT OK) CodeLen=0;
+ END
+ return True;
+ END
+
+ if (Memo("BYTE"))
+ BEGIN
+ strmaxcpy(OpPart,"BYT",255); DecodeMotoPseudo(False);
+ return True;
+ END
+
+ if (Memo("WORD"))
+ BEGIN
+ strmaxcpy(OpPart,"ADR",255); DecodeMotoPseudo(False);
+ return True;
+ END
+
+ if (Memo("BLOCK"))
+ BEGIN
+ strmaxcpy(OpPart,"DFS",255); DecodeMotoPseudo(False);
+ return True;
+ END
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUME62s,ASSUME62Count);
+ return True;
+ END
+
+ return False;
+END
+
+ static Boolean IsReg(Byte Adr)
+BEGIN
+ return ((Adr & 0xfc)==0x80);
+END
+
+ static Byte MirrBit(Byte inp)
+BEGIN
+ return (((inp & 1) << 2)+(inp & 2)+((inp & 4) >> 2));
+END
+
+ static void MakeCode_ST62(void)
+BEGIN
+ Integer AdrInt;
+ int z;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("LD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModDir+MModInd);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ DecodeAdr(ArgStr[2],MModDir+MModInd);
+ switch (AdrType)
+ BEGIN
+ case ModDir:
+ if (IsReg(AdrVal))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x35+((AdrVal & 3) << 6);
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x1f; BAsmCode[1]=AdrVal;
+ END
+ break;
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=0x07+(AdrMode << 3);
+ break;
+ END
+ break;
+ case ModDir:
+ DecodeAdr(ArgStr[2],MModAcc);
+ if (AdrType!=ModNone)
+ if (IsReg(AdrVal))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x3d+((AdrVal & 3) << 6);
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x9f; BAsmCode[1]=AdrVal;
+ END
+ break;
+ case ModInd:
+ DecodeAdr(ArgStr[2],MModAcc);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x87+(AdrMode << 3);
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDI"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModDir);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ CodeLen=2; BAsmCode[0]=0x17; BAsmCode[1]=Lo(AdrInt);
+ break;
+ case ModDir:
+ CodeLen=3; BAsmCode[0]=0x0d; BAsmCode[1]=AdrVal;
+ BAsmCode[2]=Lo(AdrInt);
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ for (z=0; z<RelOrderCnt; z++)
+ if (Memo(RelOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+1);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-16) OR (AdrInt>15))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=1;
+ BAsmCode[0]=RelOrders[z].Code+((AdrInt << 3) & 0xf8);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JP")) OR (Memo("CALL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],Int16,&OK);
+ if (OK)
+ if ((AdrInt<0) OR (AdrInt>0xfff)) WrError(1925);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0x01+(Ord(Memo("JP")) << 3)+((AdrInt & 0x00f) << 4);
+ BAsmCode[1]=AdrInt >> 4;
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<ALUOrderCnt; z++)
+ if (strncmp(ALUOrders[z].Name,OpPart,strlen(ALUOrders[z].Name))==0)
+ switch (OpPart[strlen(ALUOrders[z].Name)])
+ BEGIN
+ case '\0':
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ if (AdrType!=ModNone)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModDir+MModInd);
+ switch (AdrType)
+ BEGIN
+ case ModDir:
+ CodeLen=2; BAsmCode[0]=ALUOrders[z].Code+0x18;
+ BAsmCode[1]=AdrVal;
+ break;
+ case ModInd:
+ CodeLen=1; BAsmCode[0]=ALUOrders[z].Code+(AdrMode << 3);
+ break;
+ END
+ END
+ END
+ return;
+ case 'I':
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],Int8,&OK);
+ if (OK)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=ALUOrders[z].Code+0x10;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CLR"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc+MModDir);
+ switch (AdrType)
+ BEGIN
+ case ModAcc:
+ CodeLen=2; BAsmCode[0]=0xdf; BAsmCode[1]=0xff;
+ break;
+ case ModDir:
+ CodeLen=3; BAsmCode[0]=0x0d; BAsmCode[1]=AdrVal; BAsmCode[2]=0;
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<AccOrderCnt; z++)
+ if (Memo(AccOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAcc);
+ if (AdrType!=ModNone)
+ BEGIN
+ OK=(Hi(AccOrders[z].Code)!=0);
+ CodeLen=1+Ord(OK);
+ BAsmCode[0]=Lo(AccOrders[z].Code);
+ if (OK) BAsmCode[1]=Hi(AccOrders[z].Code);
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INC")) OR (Memo("DEC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModDir+MModInd);
+ switch (AdrType)
+ BEGIN
+ case ModDir:
+ if (IsReg(AdrVal))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x15+((AdrVal & 3) << 6);
+ if (Memo("DEC")) BAsmCode[0]+=8;
+ END
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x7f+(Ord(Memo("DEC")) << 7);
+ BAsmCode[1]=AdrVal;
+ END
+ break;
+ case ModInd:
+ CodeLen=1;
+ BAsmCode[0]=0x67+(AdrMode << 3)+(Ord(Memo("DEC")) << 7);
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Bitbefehle */
+
+ if ((Memo("SET")) OR (Memo("RES")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=MirrBit(EvalIntExpression(ArgStr[1],UInt3,&OK));
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[2],MModDir);
+ if (AdrType!=ModNone)
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=(BAsmCode[0] << 5)+(Ord(Memo("SET")) << 4)+0x0b;
+ BAsmCode[1]=AdrVal;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JRR")) OR (Memo("JRS")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=MirrBit(EvalIntExpression(ArgStr[1],UInt3,&OK));
+ if (OK)
+ BEGIN
+ BAsmCode[0]=(BAsmCode[0] << 5)+3+(Ord(Memo("JRS")) << 4);
+ DecodeAdr(ArgStr[2],MModDir);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[1]=AdrVal;
+ AdrInt=EvalIntExpression(ArgStr[3],UInt16,&OK)-(EProgCounter()+3);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt>127) OR (AdrInt<-128))) WrError(1370);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[2]=Lo(AdrInt);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_ST62(void)
+BEGIN
+ SaveInitProc();
+ WinAssume=0x40;
+END
+
+ static Boolean IsDef_ST62(void)
+BEGIN
+ return (Memo("SFR"));
+END
+
+ static void SwitchFrom_ST62(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_ST62(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=True;
+
+ PCSymbol="PC"; HeaderID=0x78; NOPCode=0x04;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)+(1<<SegData);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = (MomCPU < CPUST6220) ? 0xfff : 0x7ff;
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
+ SegLimits[SegData] = 0xff;
+
+ MakeCode=MakeCode_ST62; IsDef=IsDef_ST62;
+ SwitchFrom=SwitchFrom_ST62; InitFields();
+END
+
+ void codest6_init(void)
+BEGIN
+ CPUST6210=AddCPU("ST6210",SwitchTo_ST62);
+ CPUST6215=AddCPU("ST6215",SwitchTo_ST62);
+ CPUST6220=AddCPU("ST6220",SwitchTo_ST62);
+ CPUST6225=AddCPU("ST6225",SwitchTo_ST62);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_ST62;
+END
+
diff --git a/codest6.h b/codest6.h
new file mode 100644
index 0000000..b9f2181
--- /dev/null
+++ b/codest6.h
@@ -0,0 +1,11 @@
+/* codest6.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator ST6-Familie */
+/* */
+/* Historie: 14.11.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codest6_init(void);
diff --git a/codest7.c b/codest7.c
new file mode 100644
index 0000000..da714f8
--- /dev/null
+++ b/codest7.c
@@ -0,0 +1,878 @@
+/* codest7.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator SGS-Thomson ST7 */
+/* */
+/* Historie: 21. 5.1997 Grundsteinlegung */
+/* 2. 1.1999 ChkPC ersetzt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "nls.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ Boolean MayImm;
+ } AriOrder;
+
+
+#define FixedOrderCnt 11
+#define AriOrderCnt 8
+#define RMWOrderCnt 13
+#define RelOrderCnt 20
+
+
+#define ModNone (-1)
+#define ModImm 0
+#define MModImm (1l << ModImm)
+#define ModAbs8 1
+#define MModAbs8 (1l << ModAbs8)
+#define ModAbs16 2
+#define MModAbs16 (1l << ModAbs16)
+#define ModIX 3
+#define MModIX (1l << ModIX)
+#define ModIX8 4
+#define MModIX8 (1l << ModIX8)
+#define ModIX16 5
+#define MModIX16 (1l << ModIX16)
+#define ModIY 6
+#define MModIY (1l << ModIY)
+#define ModIY8 7
+#define MModIY8 (1l << ModIY8)
+#define ModIY16 8
+#define MModIY16 (1l << ModIY16)
+#define ModIAbs8 9
+#define MModIAbs8 (1l << ModIAbs8)
+#define ModIAbs16 10
+#define MModIAbs16 (1l << ModIAbs16)
+#define ModIXAbs8 11
+#define MModIXAbs8 (1l << ModIXAbs8)
+#define ModIXAbs16 12
+#define MModIXAbs16 (1l << ModIXAbs16)
+#define ModIYAbs8 13
+#define MModIYAbs8 (1l << ModIYAbs8)
+#define ModIYAbs16 14
+#define MModIYAbs16 (1l << ModIYAbs16)
+#define ModA 15
+#define MModA (1l << ModA)
+#define ModX 16
+#define MModX (1l << ModX)
+#define ModY 17
+#define MModY (1l << ModY)
+#define ModS 18
+#define MModS (1l << ModS)
+#define ModCCR 19
+#define MModCCR (1l << ModCCR)
+
+
+static CPUVar CPUST7;
+
+static FixedOrder *FixedOrders;
+static AriOrder *AriOrders;
+static FixedOrder *RMWOrders;
+static FixedOrder *RelOrders;
+
+static ShortInt AdrType;
+static Byte AdrPart,OpSize,PrefixCnt;
+static Byte AdrVals[3];
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddAri(char *NName, Byte NCode, Boolean NMay)
+BEGIN
+ if (InstrZ>=AriOrderCnt) exit(255);
+ AriOrders[InstrZ].Name=NName;
+ AriOrders[InstrZ].Code=NCode;
+ AriOrders[InstrZ++].MayImm=NMay;
+END
+
+ static void AddRMW(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=RMWOrderCnt) exit(255);
+ RMWOrders[InstrZ].Name=NName;
+ RMWOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddRel(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=RelOrderCnt) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstrZ=0; FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt);
+ AddFixed("HALT" ,0x8e); AddFixed("IRET" ,0x80); AddFixed("NOP" ,0x9d);
+ AddFixed("RCF" ,0x98); AddFixed("RET" ,0x81); AddFixed("RIM" ,0x9a);
+ AddFixed("RSP" ,0x9c); AddFixed("SCF" ,0x99); AddFixed("SIM" ,0x9b);
+ AddFixed("TRAP" ,0x83); AddFixed("WFI" ,0x8f);
+
+ InstrZ=0; AriOrders=(AriOrder *) malloc(sizeof(AriOrder)*AriOrderCnt);
+ AddAri("ADC" ,0x09,True ); AddAri("ADD" ,0x0b,True ); AddAri("AND" ,0x04,True );
+ AddAri("BCP" ,0x05,True ); AddAri("OR" ,0x0a,True ); AddAri("SBC" ,0x02,True );
+ AddAri("SUB" ,0x00,True ); AddAri("XOR" ,0x08,True );
+
+ InstrZ=0; RMWOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RMWOrderCnt);
+ AddRMW("CLR" ,0x0f); AddRMW("CPL" ,0x03); AddRMW("DEC" ,0x0a);
+ AddRMW("INC" ,0x0c); AddRMW("NEG" ,0x00); AddRMW("RLC" ,0x09);
+ AddRMW("RRC" ,0x06); AddRMW("SLA" ,0x08); AddRMW("SLL" ,0x08);
+ AddRMW("SRA" ,0x07); AddRMW("SRL" ,0x04); AddRMW("SWAP",0x0e);
+ AddRMW("TNZ" ,0x0d);
+
+ InstrZ=0; RelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RelOrderCnt);
+ AddRel("CALLR",0xad); AddRel("JRA" ,0x20); AddRel("JRC" ,0x25);
+ AddRel("JREQ" ,0x27); AddRel("JRF" ,0x21); AddRel("JRH" ,0x29);
+ AddRel("JRIH" ,0x2f); AddRel("JRIL" ,0x2e); AddRel("JRM" ,0x2d);
+ AddRel("JRMI" ,0x2b); AddRel("JRNC" ,0x24); AddRel("JRNE" ,0x26);
+ AddRel("JRNH" ,0x28); AddRel("JRNM" ,0x2c); AddRel("JRPL" ,0x2a);
+ AddRel("JRT" ,0x20); AddRel("JRUGE",0x24); AddRel("JRUGT",0x22);
+ AddRel("JRULE",0x23); AddRel("JRULT",0x25);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(AriOrders);
+ free(RMWOrders);
+ free(RelOrders);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddPrefix(Byte Pref)
+BEGIN
+ BAsmCode[PrefixCnt++]=Pref;
+END
+
+ static void DecideSize(LongInt Mask, char *Asc, LongInt Type1, LongInt Type2, Byte Part1, Byte Part2)
+BEGIN
+ enum {None,I8,I16} Size;
+ Word Value;
+ Boolean OK;
+ int l=strlen(Asc);
+
+ if ((l>=3) AND (Asc[l-2]=='.'))
+ BEGIN
+ if (toupper(Asc[l-1])=='B')
+ BEGIN
+ Size=I8; Asc[l-2]='\0';
+ END
+ else if (toupper(Asc[l-1])=='W')
+ BEGIN
+ Size=I16; Asc[l-2]='\0';
+ END
+ else Size=None;
+ END
+ else Size=None;
+
+ if (Size==I8) Value=EvalIntExpression(Asc,UInt8,&OK);
+ else Value=EvalIntExpression(Asc,Int16,&OK);
+
+ if (OK)
+ if ((Size==I8) OR (((Mask & (1l << Type1))!=0) AND (Size==None) AND (Hi(Value)==0)))
+ BEGIN
+ AdrVals[0]=Lo(Value); AdrCnt=1;
+ AdrPart=Part1; AdrType=Type1;
+ END
+ else
+ BEGIN
+ AdrVals[0]=Hi(Value); AdrVals[1]=Lo(Value); AdrCnt=2;
+ AdrPart=Part2; AdrType=Type2;
+ END
+END
+
+ static void DecideASize(LongInt Mask, char *Asc, LongInt Type1, LongInt Type2, Byte Part1, Byte Part2)
+BEGIN
+ Boolean I16;
+ Boolean OK;
+ int l=strlen(Asc);
+
+ if ((l>=3) AND (Asc[l-2]=='.') AND (toupper(Asc[l-1])=='W'))
+ BEGIN
+ I16=True; Asc[l-2]='\0';
+ END
+ else if (((Mask & (1l << Type1)))==0) I16=True;
+ else I16=False;
+
+ AdrVals[0]=EvalIntExpression(Asc,UInt8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1;
+ if (I16)
+ BEGIN
+ AdrPart=Part2; AdrType=Type2;
+ END
+ else
+ BEGIN
+ AdrPart=Part1; AdrType=Type1;
+ END
+ END
+END
+
+ static void ChkAdr(LongInt Mask)
+BEGIN
+ if ( (AdrType!=ModNone) AND ((Mask & (1l << AdrType))==0) )
+ BEGIN
+ WrError(1350); AdrType=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(char *Asc_O, LongInt Mask)
+BEGIN
+ Boolean OK,YReg;
+ String Asc,Asc2;
+ char *p;
+
+ strmaxcpy(Asc,Asc_O,255);
+
+ AdrType=ModNone; AdrCnt=0;
+
+ /* Register ? */
+
+ if (strcasecmp(Asc,"A")==0)
+ BEGIN
+ AdrType=ModA; ChkAdr(Mask); return;
+ END
+
+ if (strcasecmp(Asc,"X")==0)
+ BEGIN
+ AdrType=ModX; ChkAdr(Mask); return;
+ END
+
+ if (strcasecmp(Asc,"Y")==0)
+ BEGIN
+ AdrType=ModY; AddPrefix(0x90); ChkAdr(Mask); return;
+ END
+
+ if (strcasecmp(Asc,"S")==0)
+ BEGIN
+ AdrType=ModS; ChkAdr(Mask); return;
+ END
+
+ if (strcasecmp(Asc,"CC")==0)
+ BEGIN
+ AdrType=ModCCR; ChkAdr(Mask); return;
+ END
+
+ /* immediate ? */
+
+ if (*Asc=='#')
+ BEGIN
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModImm; AdrPart=0xa; AdrCnt=1;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* speicherindirekt ? */
+
+ if ((*Asc=='[') AND (Asc[strlen(Asc)-1]==']'))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ DecideASize(Mask,Asc,ModIAbs8,ModIAbs16,0xb,0xc);
+ if (AdrType!=ModNone) AddPrefix(0x92);
+ ChkAdr(Mask); return;
+ END
+
+ /* sonstwie indirekt ? */
+
+ if (IsIndirect(Asc))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+
+ /* ein oder zwei Argumente ? */
+
+ p=QuotPos(Asc,',');
+ if (p==Nil)
+ BEGIN
+ AdrPart=0xf;
+ if (strcasecmp(Asc,"X")==0) AdrType=ModIX;
+ else if (strcasecmp(Asc,"Y")==0)
+ BEGIN
+ AdrType=ModIY; AddPrefix(0x90);
+ END
+ else WrXError(1445,Asc);
+ ChkAdr(Mask); return;
+ END
+
+ strmaxcpy(Asc2,p+1,255); *p='\0';
+
+ if (strcasecmp(Asc,"X")==0)
+ BEGIN
+ strmaxcpy(Asc,Asc2,255); YReg=False;
+ END
+ else if (strcasecmp(Asc2,"X")==0) YReg=False;
+ else if (strcasecmp(Asc,"Y")==0)
+ BEGIN
+ strmaxcpy(Asc,Asc2,255); YReg=True;
+ END
+ else if (strcasecmp(Asc2,"Y")==0) YReg=True;
+ else
+ BEGIN
+ WrError(1350); return;
+ END
+
+ /* speicherindirekt ? */
+
+ if ((*Asc=='[') AND (Asc[strlen(Asc)-1]==']'))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ if (YReg)
+ BEGIN
+ DecideASize(Mask,Asc,ModIYAbs8,ModIYAbs16,0xe,0xd);
+ if (AdrType!=ModNone) AddPrefix(0x91);
+ END
+ else
+ BEGIN
+ DecideASize(Mask,Asc,ModIXAbs8,ModIXAbs16,0xe,0xd);
+ if (AdrType!=ModNone) AddPrefix(0x92);
+ END
+ END
+ else
+ BEGIN
+ if (YReg) DecideSize(Mask,Asc,ModIY8,ModIY16,0xe,0xd);
+ else DecideSize(Mask,Asc,ModIX8,ModIX16,0xe,0xd);
+ if ((AdrType!=ModNone) AND (YReg)) AddPrefix(0x90);
+ END
+
+ ChkAdr(Mask); return;
+ END
+
+ /* dann absolut */
+
+ DecideSize(Mask,Asc,ModAbs8,ModAbs16,0xb,0xc);
+
+ ChkAdr(Mask);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void MakeCode_ST7(void)
+BEGIN
+ Integer AdrInt;
+ int z;
+ LongInt Mask;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False; OpSize=1; PrefixCnt=0;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Attribut verarbeiten */
+
+ if (*AttrPart!='\0')
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B': OpSize=0; break;
+ case 'W': OpSize=1; break;
+ case 'L': OpSize=2; break;
+ case 'Q': OpSize=3; break;
+ case 'S': OpSize=4; break;
+ case 'D': OpSize=5; break;
+ case 'X': OpSize=6; break;
+ case 'P': OpSize=7; break;
+ default:
+ WrError(1107); return;
+ END
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeMotoPseudo(True)) return;
+ if (DecodeMoto16Pseudo(OpSize,True)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=FixedOrders[z].Code; CodeLen=PrefixCnt+1;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("LD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModA+MModX+MModY+MModS+
+ MModImm+MModAbs8+MModAbs16+MModIX+MModIX8+MModIX16+MModIY+
+ MModIY8+MModIY16+MModIAbs8+MModIAbs16+MModIXAbs8+MModIXAbs16+
+ MModIYAbs8+MModIYAbs16);
+
+ switch (AdrType)
+ BEGIN
+ case ModA:
+ DecodeAdr(ArgStr[2],MModImm+MModAbs8+MModAbs16+MModIX+MModIX8+MModIX16+MModIY+
+ MModIY8+MModIY16+MModIAbs8+MModIAbs16+MModIXAbs8+MModIXAbs16+
+ MModIYAbs8+MModIYAbs16+MModX+MModY+MModS);
+ switch (AdrType)
+ BEGIN
+ case ModX:
+ case ModY:
+ BAsmCode[PrefixCnt]=0x9f; CodeLen=PrefixCnt+1;
+ break;
+ case ModS:
+ BAsmCode[PrefixCnt]=0x9e; CodeLen=PrefixCnt+1;
+ break;
+ default:
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x06+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ END
+ break;
+ case ModX:
+ DecodeAdr(ArgStr[2],MModImm+MModAbs8+MModAbs16+MModIX+MModIX8+
+ MModIX16+MModIAbs8+MModIAbs16+MModIXAbs8+MModIXAbs16+
+ MModA+MModY+MModS);
+ switch (AdrType)
+ BEGIN
+ case ModA:
+ BAsmCode[PrefixCnt]=0x97; CodeLen=PrefixCnt+1;
+ break;
+ case ModY:
+ BAsmCode[0]=0x93; CodeLen=1;
+ break;
+ case ModS:
+ BAsmCode[PrefixCnt]=0x96; CodeLen=PrefixCnt+1;
+ break;
+ default:
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x0e + (AdrPart << 4); /* ANSI :-O */
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ END
+ break;
+ case ModY:
+ PrefixCnt=0;
+ DecodeAdr(ArgStr[2],MModImm+MModAbs8+MModAbs16+MModIY+MModIY8+
+ MModIY16+MModIAbs8+MModIAbs16+MModIYAbs8+MModIYAbs16+
+ MModA+MModX+MModS);
+ switch (AdrType)
+ BEGIN
+ case ModA:
+ AddPrefix(0x90); BAsmCode[PrefixCnt]=0x97; CodeLen=PrefixCnt+1;
+ break;
+ case ModX:
+ AddPrefix(0x90); BAsmCode[PrefixCnt]=0x93; CodeLen=PrefixCnt+1;
+ break;
+ case ModS:
+ AddPrefix(0x90); BAsmCode[PrefixCnt]=0x96; CodeLen=PrefixCnt+1;
+ break;
+ default:
+ if (AdrType!=ModNone)
+ BEGIN
+ if (PrefixCnt==0) AddPrefix(0x90);
+ if (BAsmCode[0]==0x92) BAsmCode[0]--;
+ BAsmCode[PrefixCnt]=0x0e + (AdrPart << 4); /* ANSI :-O */
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ END
+ break;
+ case ModS:
+ DecodeAdr(ArgStr[2],MModA+MModX+MModY);
+ switch (AdrType)
+ BEGIN
+ case ModA:
+ BAsmCode[PrefixCnt]=0x95; CodeLen=PrefixCnt+1;
+ break;
+ case ModX:
+ case ModY:
+ BAsmCode[PrefixCnt]=0x94; CodeLen=PrefixCnt+1;
+ break;
+ END
+ break;
+ default:
+ if (AdrType!=ModNone)
+ BEGIN
+ PrefixCnt=0; DecodeAdr(ArgStr[2],MModA+MModX+MModY);
+ switch (AdrType)
+ BEGIN
+ case ModA:
+ Mask=MModAbs8+MModAbs16+MModIX+MModIX8+MModIX16+MModIY+
+ MModIY8+MModIY16+MModIAbs8+MModIAbs16+MModIXAbs8+MModIXAbs16+
+ MModIYAbs8+MModIYAbs16;
+ DecodeAdr(ArgStr[1],Mask);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x07+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ case ModX:
+ DecodeAdr(ArgStr[1],MModAbs8+MModAbs16+MModIX+MModIX8+
+ MModIX16+MModIAbs8+MModIAbs16+MModIXAbs8+MModIXAbs16);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x0f+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ case ModY:
+ PrefixCnt=0;
+ DecodeAdr(ArgStr[1],MModAbs8+MModAbs16+MModIY+MModIY8+
+ MModIY16+MModIAbs8+MModIAbs16+MModIYAbs8+MModIYAbs16);
+ if (AdrType!=ModNone)
+ BEGIN
+ if (PrefixCnt==0) AddPrefix(0x90);
+ if (BAsmCode[0]==0x92) BAsmCode[0]--;
+ BAsmCode[PrefixCnt]=0x0f+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModA+MModX+MModY+MModCCR);
+ if (AdrType!=ModNone)
+ BEGIN
+ switch (AdrType)
+ BEGIN
+ case ModA: BAsmCode[PrefixCnt]=0x84; break;
+ case ModX:
+ case ModY: BAsmCode[PrefixCnt]=0x85; break;
+ case ModCCR: BAsmCode[PrefixCnt]=0x86; break;
+ END
+ if (Memo("PUSH")) BAsmCode[PrefixCnt]+=4;
+ CodeLen=PrefixCnt+1;
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ if (Memo("CP"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModA+MModX+MModY);
+ switch (AdrType)
+ BEGIN
+ case ModA:
+ Mask=MModImm+MModAbs8+MModAbs16+MModIX+MModIX8+MModIX16+MModIY+
+ MModIY8+MModIY16+MModIAbs8+MModIAbs16+MModIXAbs8+MModIXAbs16+
+ MModIYAbs8+MModIYAbs16;
+ DecodeAdr(ArgStr[2],Mask);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x01+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ case ModX:
+ DecodeAdr(ArgStr[2],MModImm+MModAbs8+MModAbs16+MModIX+MModIX8+
+ MModIX16+MModIAbs8+MModIAbs16+MModIXAbs8+MModIXAbs16);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x03+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ case ModY:
+ PrefixCnt=0;
+ DecodeAdr(ArgStr[2],MModImm+MModAbs8+MModAbs16+MModIY+MModIY8+
+ MModIY16+MModIAbs8+MModIAbs16+MModIYAbs8+MModIYAbs16);
+ if (AdrType!=ModNone)
+ BEGIN
+ if (PrefixCnt==0) AddPrefix(0x90);
+ if (BAsmCode[0]==0x92) BAsmCode[0]--;
+ BAsmCode[PrefixCnt]=0x03+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<AriOrderCnt; z++)
+ if (Memo(AriOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModA);
+ if (AdrType==ModA)
+ BEGIN
+ Mask=MModAbs8+MModAbs16+MModIX+MModIX8+MModIX16+MModIY+
+ MModIY8+MModIY16+MModIAbs8+MModIAbs16+MModIXAbs8+MModIXAbs16+
+ MModIYAbs8+MModIYAbs16;
+ if (AriOrders[z].MayImm) Mask+=MModImm;
+ DecodeAdr(ArgStr[2],Mask);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=AriOrders[z].Code+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<RMWOrderCnt; z++)
+ if (Memo(RMWOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModA+MModX+MModY+MModAbs8+MModIX+MModIX8+
+ MModIY+MModIY8+MModIAbs8+MModIXAbs8+MModIYAbs8);
+ switch (AdrType)
+ BEGIN
+ case ModA:
+ BAsmCode[PrefixCnt]=0x40+RMWOrders[z].Code; CodeLen=PrefixCnt+1;
+ break;
+ case ModX:
+ case ModY:
+ BAsmCode[PrefixCnt]=0x50+RMWOrders[z].Code; CodeLen=PrefixCnt+1;
+ break;
+ default:
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=RMWOrders[z].Code+((AdrPart-8) << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("MUL"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModA);
+ if (AdrType!=ModNone)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModX+MModY);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x42; CodeLen=PrefixCnt+1;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Bitbefehle */
+
+ if ((Memo("BRES")) OR (Memo("BSET")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (*ArgStr[2]!='#') WrError(1350);
+ else
+ BEGIN
+ z=EvalIntExpression(ArgStr[2]+1,UInt3,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAbs8+MModIAbs8);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x10+Ord(Memo("BRES"))+(z << 1);
+ memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("BTJF")) OR (Memo("BTJT")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (*ArgStr[2]!='#') WrError(1350);
+ else
+ BEGIN
+ z=EvalIntExpression(ArgStr[2]+1,UInt3,&OK);
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAbs8+MModIAbs8);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x00+Ord(Memo("BTJF"))+(z << 1);
+ memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
+ AdrInt=EvalIntExpression(ArgStr[3],UInt16,&OK)-(EProgCounter()+PrefixCnt+1+AdrCnt);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt+1+AdrCnt]=AdrInt & 0xff;
+ CodeLen=PrefixCnt+1+AdrCnt+1;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if ((Memo("JP")) OR (Memo("CALL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ Mask=MModAbs8+MModAbs16+MModIX+MModIX8+MModIX16+MModIY+
+ MModIY8+MModIY16+MModIAbs8+MModIAbs16+MModIXAbs8+MModIXAbs16+
+ MModIYAbs8+MModIYAbs16;
+ DecodeAdr(ArgStr[1],Mask);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x0c+Ord(Memo("CALL"))+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<RelOrderCnt; z++)
+ if (Memo(RelOrders[z].Name))
+ BEGIN
+ if (*AttrPart!='\0') WrError(1100);
+ else if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]=='[')
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIAbs8);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[PrefixCnt]=RelOrders[z].Code;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ END
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=RelOrders[z].Code; BAsmCode[1]=AdrInt & 0xff;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ /* nix gefunden */
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_ST7(void)
+BEGIN
+ return False;
+END
+
+ static void SwitchFrom_ST7(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_ST7(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
+
+ PCSymbol="PC"; HeaderID=0x33; NOPCode=0x9d;
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_ST7; IsDef=IsDef_ST7;
+ SwitchFrom=SwitchFrom_ST7; InitFields();
+ AddMoto16PseudoONOFF();
+
+ SetFlag(&DoPadding,DoPaddingName,False);
+END
+
+ void codest7_init(void)
+BEGIN
+ CPUST7=AddCPU("ST7",SwitchTo_ST7);
+END
+
+
diff --git a/codest7.h b/codest7.h
new file mode 100644
index 0000000..ccfdc71
--- /dev/null
+++ b/codest7.h
@@ -0,0 +1,11 @@
+/* codest7.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator SGS-Thomson ST7 */
+/* */
+/* Historie: 21.5.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codest7_init(void);
diff --git a/codest9.c b/codest9.c
new file mode 100644
index 0000000..bf54690
--- /dev/null
+++ b/codest9.c
@@ -0,0 +1,1878 @@
+/* codest9.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator SGS-Thomson ST9 */
+/* */
+/* Historie: 10. 2.1997 Grundsteinlegung */
+/* 1. 7.1998 Warnungen bei is...()-Funktionen beseitigt */
+/* 2. 1.1999 ChkPC umgestellt */
+/* 30. 1.1999 Formate maschinenunabhaengig gemacht */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "bpemu.h"
+#include "strutil.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ int len;
+ Word Code;
+ } ALUOrder;
+
+
+#define WorkOfs 0xd0
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1l << ModReg) /* Rn */
+#define ModWReg 1
+#define MModWReg (1l << ModWReg) /* rn */
+#define ModRReg 2
+#define MModRReg (1l << ModRReg) /* RRn */
+#define ModWRReg 3
+#define MModWRReg (1l << ModWRReg) /* rrn */
+#define ModIReg 4
+#define MModIReg (1l << ModIReg) /* (Rn) */
+#define ModIWReg 5
+#define MModIWReg (1l << ModIWReg) /* (rn) */
+#define ModIRReg 6
+#define MModIRReg (1l << ModIRReg) /* (RRn) */
+#define ModIWRReg 7
+#define MModIWRReg (1l << ModIWRReg) /* (rrn) */
+#define ModIncWReg 8
+#define MModIncWReg (1l << ModIncWReg) /* (rn)+ */
+#define ModIncWRReg 9
+#define MModIncWRReg (1l << ModIncWRReg) /* (rrn)+ */
+#define ModDecWRReg 10
+#define MModDecWRReg (1l << ModDecWRReg) /* -(rrn) */
+#define ModDisp8WReg 11
+#define MModDisp8WReg (1l << ModDisp8WReg) /* d8(rn) */
+#define ModDisp8WRReg 12
+#define MModDisp8WRReg (1l << ModDisp8WRReg) /* d8(rrn) */
+#define ModDisp16WRReg 13
+#define MModDisp16WRReg (1l << ModDisp16WRReg) /* d16(rrn) */
+#define ModDispRWRReg 14
+#define MModDispRWRReg (1l << ModDispRWRReg) /* rrm(rrn */
+#define ModAbs 15
+#define MModAbs (1l << ModAbs) /* NN */
+#define ModImm 16
+#define MModImm (1l << ModImm) /* #N/#NN */
+#define ModDisp8RReg 17
+#define MModDisp8RReg (1l << ModDisp8RReg) /* d8(RRn) */
+#define ModDisp16RReg 18
+#define MModDisp16RReg (1l << ModDisp16RReg) /* d16(RRn) */
+
+#define FixedOrderCnt 12
+#define ALUOrderCnt 10
+#define RegOrderCnt 13
+#define Reg16OrderCnt 8
+#define Bit2OrderCnt 4
+#define Bit1OrderCnt 4
+#define ConditionCnt 20
+#define LoadOrderCnt 4
+
+
+static CPUVar CPUST9020,CPUST9030,CPUST9040,CPUST9050;
+
+static FixedOrder *FixedOrders;
+static ALUOrder *ALUOrders;
+static FixedOrder *RegOrders;
+static FixedOrder *Reg16Orders;
+static FixedOrder *Bit2Orders;
+static FixedOrder *Bit1Orders;
+static FixedOrder *Conditions;
+static FixedOrder *LoadOrders;
+
+static ShortInt AdrMode,AbsSeg;
+static Byte AdrPart,OpSize;
+static Byte AdrVals[3];
+
+static SimpProc SaveInitProc;
+static LongInt DPAssume;
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ALUOrderCnt) exit(255);
+ ALUOrders[InstrZ].Name=NName;
+ ALUOrders[InstrZ].len=strlen(NName);
+ ALUOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddReg(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=RegOrderCnt) exit(255);
+ RegOrders[InstrZ].Name=NName;
+ RegOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddReg16(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Reg16OrderCnt) exit(255);
+ Reg16Orders[InstrZ].Name=NName;
+ Reg16Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddBit2(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Bit2OrderCnt) exit(255);
+ Bit2Orders[InstrZ].Name=NName;
+ Bit2Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddBit1(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Bit1OrderCnt) exit(255);
+ Bit1Orders[InstrZ].Name=NName;
+ Bit1Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddCondition(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ConditionCnt) exit(255);
+ Conditions[InstrZ].Name=NName;
+ Conditions[InstrZ++].Code=NCode;
+END
+
+ static void AddLoad(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=LoadOrderCnt) exit(255);
+ LoadOrders[InstrZ].Name=NName;
+ LoadOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("CCF" ,0x0061); AddFixed("DI" ,0x0010);
+ AddFixed("EI" ,0x0000); AddFixed("HALT",0xbf01);
+ AddFixed("IRET",0x00d3); AddFixed("NOP" ,0x00ff);
+ AddFixed("RCF" ,0x0011); AddFixed("RET" ,0x0046);
+ AddFixed("SCF" ,0x0001); AddFixed("SDM" ,0x00fe);
+ AddFixed("SPM" ,0x00ee); AddFixed("WFI" ,0xef01);
+
+ ALUOrders=(ALUOrder *) malloc(sizeof(ALUOrder)*ALUOrderCnt); InstrZ=0;
+ AddALU("ADC", 3); AddALU("ADD", 4); AddALU("AND", 1);
+ AddALU("CP" , 9); AddALU("OR" , 0); AddALU("SBC", 2);
+ AddALU("SUB", 5); AddALU("TCM", 8); AddALU("TM" ,10);
+ AddALU("XOR", 6);
+
+ RegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RegOrderCnt); InstrZ=0;
+ AddReg("CLR" ,0x90); AddReg("CPL" ,0x80); AddReg("DA" ,0x70);
+ AddReg("DEC" ,0x40); AddReg("INC" ,0x50); AddReg("POP" ,0x76);
+ AddReg("POPU",0x20); AddReg("RLC" ,0xb0); AddReg("ROL" ,0xa0);
+ AddReg("ROR" ,0xc0); AddReg("RRC" ,0xd0); AddReg("SRA" ,0xe0);
+ AddReg("SWAP",0xf0);
+
+ Reg16Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Reg16OrderCnt); InstrZ=0;
+ AddReg16("DECW" ,0xcf); AddReg16("EXT" ,0xc6);
+ AddReg16("INCW" ,0xdf); AddReg16("POPUW",0xb7);
+ AddReg16("POPW" ,0x75); AddReg16("RLCW" ,0x8f);
+ AddReg16("RRCW" ,0x36); AddReg16("SRAW" ,0x2f);
+
+ Bit2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Bit2OrderCnt); InstrZ=0;
+ AddBit2("BAND",0x1f); AddBit2("BLD" ,0xf2);
+ AddBit2("BOR" ,0x0f); AddBit2("BXOR",0x6f);
+
+ Bit1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Bit1OrderCnt); InstrZ=0;
+ AddBit1("BCPL",0x6f); AddBit1("BRES" ,0x1f);
+ AddBit1("BSET",0x0f); AddBit1("BTSET",0xf2);
+
+ Conditions=(FixedOrder *) malloc(sizeof(FixedOrder)*ConditionCnt); InstrZ=0;
+ AddCondition("F" ,0x0); AddCondition("T" ,0x8);
+ AddCondition("C" ,0x7); AddCondition("NC" ,0xf);
+ AddCondition("Z" ,0x6); AddCondition("NZ" ,0xe);
+ AddCondition("PL" ,0xd); AddCondition("MI" ,0x5);
+ AddCondition("OV" ,0x4); AddCondition("NOV" ,0xc);
+ AddCondition("EQ" ,0x6); AddCondition("NE" ,0xe);
+ AddCondition("GE" ,0x9); AddCondition("LT" ,0x1);
+ AddCondition("GT" ,0xa); AddCondition("LE" ,0x2);
+ AddCondition("UGE" ,0xf); AddCondition("UL" ,0x7);
+ AddCondition("UGT" ,0xb); AddCondition("ULE" ,0x3);
+
+ LoadOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LoadOrderCnt); InstrZ=0;
+ AddLoad("LDPP",0x00); AddLoad("LDDP",0x10);
+ AddLoad("LDPD",0x01); AddLoad("LDDD",0x11);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(ALUOrders);
+ free(RegOrders);
+ free(Reg16Orders);
+ free(Bit2Orders);
+ free(Bit1Orders);
+ free(Conditions);
+ free(LoadOrders);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean DecodeReg(char *Asc_O, Byte *Erg, Byte *Size)
+BEGIN
+ Boolean Res;
+ char *Asc;
+
+ Asc=Asc_O;
+
+ if (strlen(Asc)<2) return False;
+ if (*Asc!='r') return False; Asc++;
+ if (*Asc=='r')
+ BEGIN
+ if (strlen(Asc)<2) return False;
+ *Size=1; Asc++;
+ END
+ else *Size=0;
+
+ *Erg=ConstLongInt(Asc,&Res);
+ if ((NOT Res) OR (*Erg>15)) return False;
+ if ((*Size==1) AND (Odd(*Erg))) return False;
+
+ return True;
+END
+
+ static void ChkAdr(LongWord Mask)
+BEGIN
+ if ((AdrMode!=ModNone) AND (((1l << AdrMode) & Mask)==0))
+ BEGIN
+ WrError(1350); AdrMode=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(char *Asc_O, LongWord Mask)
+BEGIN
+ Word AdrWord;
+ int level;
+ Byte flg,Size;
+ Boolean OK;
+ String Reg,Asc;
+ char *p;
+
+ AdrMode=ModNone; AdrCnt=0;
+ strmaxcpy(Asc,Asc_O,255);
+
+ /* immediate */
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ break;
+ case 1:
+ AdrWord=EvalIntExpression(Asc+1,Int16,&OK);
+ AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ break;
+ END
+ if (OK)
+ BEGIN
+ AdrMode=ModImm; AdrCnt=OpSize+1;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* Arbeitsregister */
+
+ if (DecodeReg(Asc,&AdrPart,&Size))
+ BEGIN
+ if (Size==0)
+ if ((Mask & MModWReg)!=0) AdrMode=ModWReg;
+ else
+ BEGIN
+ AdrVals[0]=WorkOfs+AdrPart; AdrCnt=1; AdrMode=ModReg;
+ END
+ else
+ if ((Mask & MModWRReg)!=0) AdrMode=ModWRReg;
+ else
+ BEGIN
+ AdrVals[0]=WorkOfs+AdrPart; AdrCnt=1; AdrMode=ModRReg;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* Postinkrement */
+
+ if (Asc[strlen(Asc)-1]=='+')
+ BEGIN
+ if ((*Asc!='(') OR (Asc[strlen(Asc)-2]!=')')) WrError(1350);
+ else
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-2]='\0';
+ if (NOT DecodeReg(Asc,&AdrPart,&Size)) WrXError(1445,Asc);
+ AdrMode=(Size==0) ? ModIncWReg : ModIncWRReg;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* Predekrement */
+
+ if ((*Asc=='-') AND (Asc[1]=='(') AND (Asc[strlen(Asc)-1]==')'))
+ BEGIN
+ strcpy(Reg,Asc+2); Reg[strlen(Reg)-1]='\0';
+ if (DecodeReg(Reg,&AdrPart,&Size))
+ BEGIN
+ if (Size==0) WrError(1350); else AdrMode=ModDecWRReg;
+ ChkAdr(Mask); return;
+ END
+ END
+
+ /* indirekt<->direkt */
+
+ if ((Asc[strlen(Asc)-1]!=')') OR (strlen(Asc)<3))
+ BEGIN
+ OK=False; p=Asc;
+ END
+ else
+ BEGIN
+ level=0; p=Asc+strlen(Asc)-2; flg=0;
+ while ((p>=Asc) AND (level>=0))
+ BEGIN
+ switch (*p)
+ BEGIN
+ case '(': if (flg==0) level--; break;
+ case ')': if (flg==0) level++; break;
+ case '\'': if (((flg & 2)==0)) flg^=1; break;
+ case '"': if (((flg & 1)==0)) flg^=2; break;
+ END
+ p--;
+ END
+ OK=(level==-1) AND ((p<Asc) OR ((*p=='.') OR (*p=='_') OR (isdigit(((unsigned int)*p)&0xff)) OR (isalpha(((unsigned int)*p)&0xff))));
+ END
+
+ /* indirekt */
+
+ if (OK)
+ BEGIN
+ strcpy(Reg,p+2); Reg[strlen(Reg)-1]='\0'; p[1]='\0';
+ if (DecodeReg(Reg,&AdrPart,&Size))
+ if (Size==0) /* d(r) */
+ BEGIN
+ AdrVals[0]=EvalIntExpression(Asc,Int8,&OK);
+ if (OK)
+ BEGIN
+ if (((Mask & MModIWReg)!=0) AND (AdrVals[0]==0)) AdrMode=ModIWReg;
+ else if (((Mask & MModIReg)!=0) AND (AdrVals[0]==0))
+ BEGIN
+ AdrVals[0]=WorkOfs+AdrPart; AdrMode=ModIReg; AdrCnt=1;
+ END
+ else
+ BEGIN
+ AdrMode=ModDisp8WReg; AdrCnt=1;
+ END
+ END
+ END
+ else /* ...(rr) */
+ BEGIN
+ if (DecodeReg(Asc,AdrVals,&Size))
+ BEGIN /* rr(rr) */
+ if (Size!=1) WrError(1350);
+ else
+ BEGIN
+ AdrMode=ModDispRWRReg; AdrCnt=1;
+ END
+ END
+ else
+ BEGIN /* d(rr) */
+ AdrWord=EvalIntExpression(Asc,Int16,&OK);
+ if ((AdrWord==0) AND ((Mask & (MModIRReg+MModIWRReg))!=0))
+ BEGIN
+ if (((Mask & MModIWRReg)!=0)) AdrMode=ModIWRReg;
+ else
+ BEGIN
+ AdrMode=ModIRReg; AdrVals[0]=AdrPart+WorkOfs; AdrCnt=1;
+ END
+ END
+ else if ((AdrWord<0x100) AND ((Mask & (MModDisp8WRReg+MModDisp8RReg))!=0))
+ BEGIN
+ if (((Mask & MModDisp8WRReg)!=0))
+ BEGIN
+ AdrVals[0]=Lo(AdrWord); AdrCnt=1; AdrMode=ModDisp8WRReg;
+ END
+ else
+ BEGIN
+ AdrVals[0]=AdrPart+WorkOfs; AdrVals[1]=Lo(AdrWord);
+ AdrCnt=2; AdrMode=ModDisp8RReg;
+ END
+ END
+ else if (((Mask & MModDisp16WRReg)!=0))
+ BEGIN
+ AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ AdrCnt=2; AdrMode=ModDisp16WRReg;
+ END
+ else
+ BEGIN
+ AdrVals[0]=AdrPart+WorkOfs;
+ AdrVals[2]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ AdrCnt=3; AdrMode=ModDisp16RReg;
+ END
+ END
+ END
+
+ else /* ...(RR) */
+ BEGIN
+ AdrWord=EvalIntExpression(Reg,UInt9,&OK);
+ if (((TypeFlag & (1 << SegReg))==0)) WrError(1350);
+ else if (AdrWord<0xff)
+ BEGIN
+ AdrVals[0]=Lo(AdrWord);
+ AdrWord=EvalIntExpression(Asc,Int8,&OK);
+ if (AdrWord!=0) WrError(1320);
+ else
+ BEGIN
+ AdrCnt=1; AdrMode=ModIReg;
+ END
+ END
+ else if ((AdrWord>0x1ff) OR (Odd(AdrWord))) WrError(1350);
+ else
+ BEGIN
+ AdrVals[0]=Lo(AdrWord);
+ AdrWord=EvalIntExpression(Asc,Int16,&OK);
+ if ((AdrWord==0) AND ((Mask & MModIRReg)!=0))
+ BEGIN
+ AdrCnt=1; AdrMode=ModIRReg;
+ END
+ else if ((AdrWord<0x100) AND ((Mask & MModDisp8RReg)!=0))
+ BEGIN
+ AdrVals[1]=Lo(AdrWord); AdrCnt=2; AdrMode=ModDisp8RReg;
+ END
+ else
+ BEGIN
+ AdrVals[2]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ AdrCnt=3; AdrMode=ModDisp16RReg;
+ END
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+
+ /* direkt */
+
+ AdrWord=EvalIntExpression(Asc,UInt16,&OK);
+ if (OK)
+ if (((TypeFlag & (1 << SegReg)))==0)
+ BEGIN
+ AdrMode=ModAbs;
+ AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
+ AdrCnt=2; ChkSpace(AbsSeg);
+ END
+ else if (AdrWord<0xff)
+ BEGIN
+ AdrMode=ModReg; AdrVals[0]=Lo(AdrWord); AdrCnt=1;
+ END
+ else if ((AdrWord>0x1ff) OR (Odd(AdrWord))) WrError(1350);
+ else
+ BEGIN
+ AdrMode=ModRReg; AdrVals[0]=Lo(AdrWord); AdrCnt=1;
+ END
+
+ ChkAdr(Mask);
+END
+
+ static Boolean SplitBit(char *Asc, Byte *Erg)
+BEGIN
+ char *p;
+ Integer val;
+ Boolean OK,Inv;
+
+ p=RQuotPos(Asc,'.');
+ if ((p==Nil) OR (p==Asc+strlen(Asc)+1))
+ BEGIN
+ if (*Asc=='!')
+ BEGIN
+ Inv=True; strcpy(Asc,Asc+1);
+ END
+ else Inv=False;
+ val=EvalIntExpression(Asc,UInt8,&OK);
+ if (OK)
+ BEGIN
+ *Erg=val & 15; if (Inv) *Erg^=1;
+ sprintf(Asc, "r%d", (int)(val >> 4));
+ return True;
+ END
+ return False;
+ END
+
+ if (p[1]=='!')
+ *Erg=1+(EvalIntExpression(p+2,UInt3,&OK) << 1);
+ else
+ *Erg=EvalIntExpression(p+1,UInt3,&OK) << 1;
+ *p='\0';
+ return OK;
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUMEST9Count 1
+static ASSUMERec ASSUMEST9s[ASSUMEST9Count]=
+ {{"DP", &DPAssume, 0, 1, 0x0}};
+ Byte Bit;
+
+ if (Memo("REG"))
+ BEGIN
+ CodeEquate(SegReg,0,0x1ff);
+ return True;
+ END
+
+ if (Memo("BIT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (SplitBit(ArgStr[1],&Bit))
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg);
+ if (AdrMode==ModWReg)
+ BEGIN
+ PushLocHandle(-1);
+ EnterIntSymbol(LabPart,(AdrPart << 4)+Bit,SegNone,False);
+ PopLocHandle();
+ sprintf(ListLine,"=r%d.%s%c", (int)AdrPart,
+ (Odd(Bit))?"!":"", (Bit >> 1)+AscOfs);
+ END
+ END
+ return True;
+ END
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUMEST9s,ASSUMEST9Count);
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_ST9(void)
+BEGIN
+ Integer AdrInt;
+ int z;
+ Boolean OK;
+ Byte HReg,HPart;
+ Word Mask1,Mask2,AdrWord;
+
+ CodeLen=0; DontPrint=False; OpSize=0;
+ AbsSeg=(DPAssume==1) ? SegData : SegCode;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(True)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ OK=Hi(FixedOrders[z].Code)!=0;
+ if (OK) BAsmCode[0]=Hi(FixedOrders[z].Code);
+ CodeLen=Ord(OK);
+ BAsmCode[CodeLen++]=Lo(FixedOrders[z].Code);
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if ((Memo("LD")) OR (Memo("LDW")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (OpPart[strlen(OpPart)-1]=='W')
+ BEGIN
+ OpSize=1; Mask1=MModWRReg; Mask2=MModRReg;
+ END
+ else
+ BEGIN
+ Mask1=MModWReg; Mask2=MModReg;
+ END;
+ DecodeAdr(ArgStr[1],Mask1+Mask2+MModIWReg+MModDisp8WReg+MModIncWReg+
+ MModIWRReg+MModIncWRReg+MModDecWRReg+MModDisp8WRReg+
+ MModDisp16WRReg+MModDispRWRReg+MModAbs+MModIRReg);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ case ModWRReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask1+Mask2+MModIWReg+MModDisp8WReg+MModIWRReg+
+ MModIncWRReg+MModDecWRReg+MModDispRWRReg+MModDisp8WRReg+
+ MModDisp16WRReg+MModAbs+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=(HReg << 4)+8; BAsmCode[1]=WorkOfs+AdrPart;
+ CodeLen=2;
+ break;
+ case ModWRReg:
+ BAsmCode[0]=0xe3; BAsmCode[1]=(HReg << 4)+AdrPart;
+ CodeLen=2;
+ break;
+ case ModReg:
+ BAsmCode[0]=(HReg << 4)+8; BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ break;
+ case ModRReg:
+ BAsmCode[0]=0xef; BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=HReg+WorkOfs; CodeLen=3;
+ break;
+ case ModIWReg:
+ if (OpSize==0)
+ BEGIN
+ BAsmCode[0]=0xe4; BAsmCode[1]=(HReg << 4)+AdrPart;
+ CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xa6; BAsmCode[1]=0xf0+AdrPart;
+ BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
+ END
+ break;
+ case ModDisp8WReg:
+ BAsmCode[0]=0xb3+(OpSize*0x2b);
+ BAsmCode[1]=(HReg << 4)+AdrPart;
+ BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModIWRReg:
+ BAsmCode[0]=0xb5+(OpSize*0x2e);
+ BAsmCode[1]=(HReg << 4)+AdrPart+OpSize;
+ CodeLen=2;
+ break;
+ case ModIncWRReg:
+ BAsmCode[0]=0xb4+(OpSize*0x21);
+ BAsmCode[1]=0xf1+AdrPart;
+ BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
+ break;
+ case ModDecWRReg:
+ BAsmCode[0]=0xc2+OpSize;
+ BAsmCode[1]=0xf1+AdrPart;
+ BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
+ break;
+ case ModDispRWRReg:
+ BAsmCode[0]=0x60;
+ BAsmCode[1]=(0x10*(1-OpSize))+(AdrVals[0] << 4)+AdrPart;
+ BAsmCode[2]=0xf0+HReg; CodeLen=3;
+ break;
+ case ModDisp8WRReg:
+ BAsmCode[0]=0x7f+(OpSize*7);
+ BAsmCode[1]=0xf1+AdrPart;
+ BAsmCode[2]=AdrVals[0]; BAsmCode[3]=HReg+WorkOfs;
+ CodeLen=4;
+ break;
+ case ModDisp16WRReg:
+ BAsmCode[0]=0x7f+(OpSize*7);
+ BAsmCode[1]=0xf0+AdrPart;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); BAsmCode[2+AdrCnt]=HReg+WorkOfs;
+ CodeLen=3+AdrCnt;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0xc4+(OpSize*0x1e);
+ BAsmCode[1]=0xf0+AdrPart;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ case ModImm:
+ if (OpSize==0)
+ BEGIN
+ BAsmCode[0]=(HReg << 4)+0x0c;
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ CodeLen=1+AdrCnt;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xbf; BAsmCode[1]=WorkOfs+HReg;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ break;
+ END
+ break;
+ case ModReg:
+ case ModRReg:
+ HReg=AdrVals[0];
+ DecodeAdr(ArgStr[2],Mask1+Mask2+MModIWReg+MModIWRReg+MModIncWRReg+
+ MModDecWRReg+MModDispRWRReg+MModDisp8WRReg+MModDisp16WRReg+
+ MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=(AdrPart << 4)+0x09; BAsmCode[1]=HReg; CodeLen=2;
+ break;
+ case ModWRReg:
+ BAsmCode[0]=0xef; BAsmCode[1]=WorkOfs+AdrPart;
+ BAsmCode[2]=HReg; CodeLen=3;
+ break;
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0xf4-(OpSize*5);
+ BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=HReg; CodeLen=3;
+ break;
+ case ModIWReg:
+ BAsmCode[0]=0xe7-(0x41*OpSize); BAsmCode[1]=0xf0+AdrPart;
+ BAsmCode[2]=HReg; CodeLen=3;
+ break;
+ case ModIWRReg:
+ BAsmCode[0]=0x72+(OpSize*12);
+ BAsmCode[1]=0xf1+AdrPart-OpSize; BAsmCode[2]=HReg;
+ CodeLen=3;
+ break;
+ case ModIncWRReg:
+ BAsmCode[0]=0xb4+(0x21*OpSize);
+ BAsmCode[1]=0xf1+AdrPart; BAsmCode[2]=HReg;
+ CodeLen=3;
+ break;
+ case ModDecWRReg:
+ BAsmCode[0]=0xc2+OpSize;
+ BAsmCode[1]=0xf1+AdrPart; BAsmCode[2]=HReg;
+ CodeLen=3;
+ break;
+ case ModDisp8WRReg:
+ BAsmCode[0]=0x7f+(OpSize*7);
+ BAsmCode[1]=0xf1+AdrPart;
+ BAsmCode[2]=AdrVals[0];
+ BAsmCode[3]=HReg; CodeLen=4;
+ break;
+ case ModDisp16WRReg:
+ BAsmCode[0]=0x7f+(OpSize*7);
+ BAsmCode[1]=0xf0+AdrPart;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ BAsmCode[2+AdrCnt]=HReg; CodeLen=3+AdrCnt;
+ break;
+ case ModImm:
+ BAsmCode[0]=0xf5-(OpSize*0x36);
+ BAsmCode[1]=HReg;
+ memcpy(BAsmCode+2,AdrVals,2); CodeLen=2+AdrCnt;
+ break;
+ END
+ break;
+ case ModIWReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask2+Mask1);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=0xe5; BAsmCode[1]=(HReg << 4)+AdrPart; CodeLen=2;
+ break;
+ case ModWRReg:
+ BAsmCode[0]=0x96; BAsmCode[1]=WorkOfs+AdrPart;
+ BAsmCode[2]=0xf0+HReg; CodeLen=3;
+ break;
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0xe6-(0x50*OpSize); BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=0xf0+HReg; CodeLen=3;
+ break;
+ END
+ break;
+ case ModDisp8WReg:
+ BAsmCode[2]=AdrVals[0]; HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask1);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ case ModWRReg:
+ BAsmCode[0]=0xb2+(OpSize*0x2c);
+ BAsmCode[1]=(AdrPart << 4)+(OpSize << 4)+HReg;
+ CodeLen=3;
+ break;
+ END
+ break;
+ case ModIncWReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModIncWRReg*(1-OpSize));
+ switch (AdrMode)
+ BEGIN
+ case ModIncWRReg:
+ BAsmCode[0]=0xd7; BAsmCode[1]=(HReg << 4)+AdrPart+1; CodeLen=2;
+ break;
+ END
+ break;
+ case ModIWRReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],(MModIWReg*(1-OpSize))+Mask1+Mask2+MModIWRReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModIWReg:
+ BAsmCode[0]=0xb5; BAsmCode[1]=(AdrPart << 4)+HReg+1; CodeLen=2;
+ break;
+ case ModWReg:
+ BAsmCode[0]=0x72; BAsmCode[1]=0xf0+HReg;
+ BAsmCode[2]=AdrPart+WorkOfs;
+ CodeLen=3;
+ break;
+ case ModWRReg:
+ BAsmCode[0]=0xe3; BAsmCode[1]=(HReg << 4)+0x10+AdrPart;
+ CodeLen=2;
+ break;
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0x72+(OpSize*0x4c);
+ BAsmCode[1]=0xf0+HReg+OpSize; BAsmCode[2]=AdrVals[0];
+ CodeLen=3;
+ break;
+ case ModIWRReg:
+ if (OpSize==0)
+ BEGIN
+ BAsmCode[0]=0x73;
+ BAsmCode[1]=0xf0+AdrPart;
+ BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xe3; BAsmCode[1]=0x11+(HReg << 4)+AdrPart;
+ CodeLen=2;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xf3-(OpSize*0x35);
+ BAsmCode[1]=0xf0+HReg;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ END
+ break;
+ case ModIncWRReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask2+(MModIncWReg*(1-OpSize)));
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0xb4+(OpSize*0x21);
+ BAsmCode[1]=0xf0+HReg; BAsmCode[2]=AdrVals[0];
+ CodeLen=3;
+ break;
+ case ModIncWReg:
+ BAsmCode[0]=0xd7; BAsmCode[1]=(AdrPart << 4)+HReg;
+ CodeLen=2;
+ break;
+ END;
+ break;
+ case ModDecWRReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask2);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0xc2+OpSize;
+ BAsmCode[1]=0xf0+HReg; BAsmCode[2]=AdrVals[0];
+ CodeLen=3;
+ break;
+ END
+ break;
+ case ModDispRWRReg:
+ HReg=AdrPart; HPart=AdrVals[0];
+ DecodeAdr(ArgStr[2],Mask1);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ case ModWRReg:
+ BAsmCode[0]=0x60;
+ BAsmCode[1]=(0x10*(1-OpSize))+0x01+(HPart << 4)+HReg;
+ BAsmCode[2]=0xf0+AdrPart;
+ CodeLen=3;
+ break;
+ END
+ break;
+ case ModDisp8WRReg:
+ BAsmCode[2]=AdrVals[0]; HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask2+(OpSize*MModImm));
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0x26+(OpSize*0x60);
+ BAsmCode[1]=0xf1+HReg; BAsmCode[3]=AdrVals[0];
+ CodeLen=4;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x06; BAsmCode[1]=0xf1+HReg;
+ memcpy(BAsmCode+3,AdrVals,AdrCnt); CodeLen=3+AdrCnt;
+ break;
+ END
+ break;
+ case ModDisp16WRReg:
+ memcpy(BAsmCode+2,AdrVals,2); HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask2+(OpSize*MModImm));
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0x26+(OpSize*0x60);
+ BAsmCode[1]=0xf0+HReg; BAsmCode[4]=AdrVals[0];
+ CodeLen=5;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x06; BAsmCode[1]=0xf0+HReg;
+ memcpy(BAsmCode+4,AdrVals,AdrCnt); CodeLen=4+AdrCnt;
+ break;
+ END
+ break;
+ case ModAbs:
+ memcpy(BAsmCode+2,AdrVals,2);
+ DecodeAdr(ArgStr[2],Mask1+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ case ModWRReg:
+ BAsmCode[0]=0xc5+(OpSize*0x1d);
+ BAsmCode[1]=0xf0+AdrPart+OpSize;
+ CodeLen=4;
+ break;
+ case ModImm:
+ memmove(BAsmCode+2+AdrCnt,BAsmCode+2,2); BAsmCode[0]=0x2f+(OpSize*7);
+ BAsmCode[1]=0xf1; memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=4+AdrCnt;
+ break;
+ END
+ break;
+ case ModIRReg:
+ HReg=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModIWRReg*(1-OpSize));
+ switch (AdrMode)
+ BEGIN
+ case ModIWRReg:
+ BAsmCode[0]=0x73; BAsmCode[1]=0xf0+AdrPart; BAsmCode[2]=HReg;
+ CodeLen=3;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<LoadOrderCnt; z++)
+ if (Memo(LoadOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIncWRReg);
+ if (AdrMode==ModIncWRReg)
+ BEGIN
+ HReg=AdrPart << 4;
+ DecodeAdr(ArgStr[2],MModIncWRReg);
+ if (AdrMode==ModIncWRReg)
+ BEGIN
+ BAsmCode[0]=0xd6;
+ BAsmCode[1]=LoadOrders[z].Code+HReg+AdrPart;
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PEA")) OR (Memo("PEAU")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModDisp8RReg+MModDisp16RReg);
+ if (AdrMode!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x8f;
+ BAsmCode[1]=0x01+(2*Ord(Memo("PEAU")));
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ BAsmCode[2]+=AdrCnt-2;
+ CodeLen=2+AdrCnt;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSH")) OR (Memo("PUSHU")))
+ BEGIN
+ z=Ord(Memo("PUSHU"));
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModIReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x66-(z*0x36); BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0xf7-(z*0xc6); BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x8f; BAsmCode[1]=0xf1+(z*2);
+ BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("PUSHW")) OR (Memo("PUSHUW")))
+ BEGIN
+ z=Ord(Memo("PUSHUW")); OpSize=1;
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModRReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModRReg:
+ BAsmCode[0]=0x74+(z*0x42); BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x8f; BAsmCode[1]=0xc1+(z*2);
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("XCH"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode==ModReg)
+ BEGIN
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode==ModReg)
+ BEGIN
+ BAsmCode[1]=AdrVals[0];
+ BAsmCode[0]=0x16;
+ CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<ALUOrderCnt; z++)
+ if ((strncmp(OpPart,ALUOrders[z].Name,ALUOrders[z].len)==0) AND ((OpPart[ALUOrders[z].len]=='\0') OR (OpPart[ALUOrders[z].len]=='W')))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (OpPart[strlen(OpPart)-1]=='W')
+ BEGIN
+ OpSize=1; Mask1=MModWRReg; Mask2=MModRReg;
+ END
+ else
+ BEGIN
+ Mask1=MModWReg; Mask2=MModReg;
+ END
+ DecodeAdr(ArgStr[1],Mask1+Mask2+MModIWReg+MModIWRReg+MModIncWRReg+
+ MModDecWRReg+MModDispRWRReg+MModDisp8WRReg+MModDisp16WRReg+
+ MModAbs+MModIRReg);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ case ModWRReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask1+MModIWReg+Mask2+MModIWRReg+MModIncWRReg+
+ MModDecWRReg+MModDispRWRReg+MModDisp8WRReg+MModDisp16WRReg+
+ MModAbs+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ case ModWRReg:
+ BAsmCode[0]=(ALUOrders[z].Code << 4)+2+(OpSize*12);
+ BAsmCode[1]=(HReg << 4)+AdrPart;
+ CodeLen=2;
+ break;
+ case ModIWReg:
+ if (OpSize==0)
+ BEGIN
+ BAsmCode[0]=(ALUOrders[z].Code << 4)+3; BAsmCode[1]=(HReg << 4)+AdrPart;
+ CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=0xa6; BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
+ BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
+ END
+ break;
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=(ALUOrders[z].Code << 4)+4+(OpSize*3);
+ BAsmCode[1]=AdrVals[0]; BAsmCode[2]=HReg+WorkOfs;
+ CodeLen=3;
+ break;
+ case ModIWRReg:
+ if (OpSize==0)
+ BEGIN
+ BAsmCode[0]=0x72; BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
+ BAsmCode[2]=HReg+WorkOfs;
+ CodeLen=3;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=(ALUOrders[z].Code << 4)+0x0e;
+ BAsmCode[1]=(HReg << 4)+AdrPart+1;
+ CodeLen=2;
+ END
+ break;
+ case ModIncWRReg:
+ BAsmCode[0]=0xb4+(OpSize*0x21);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
+ BAsmCode[2]=HReg+WorkOfs;
+ CodeLen=3;
+ break;
+ case ModDecWRReg:
+ BAsmCode[0]=0xc2+OpSize;
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
+ BAsmCode[2]=HReg+WorkOfs;
+ CodeLen=3;
+ break;
+ case ModDispRWRReg:
+ BAsmCode[0]=0x60;
+ BAsmCode[1]=0x10*(1-OpSize)+(AdrVals[0] << 4)+AdrPart;
+ BAsmCode[2]=(ALUOrders[z].Code << 4)+HReg;
+ CodeLen=3;
+ break;
+ case ModDisp8WRReg:
+ BAsmCode[0]=0x7f+(OpSize*7);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
+ BAsmCode[2]=AdrVals[0]; BAsmCode[3]=WorkOfs+HReg;
+ CodeLen=4;
+ break;
+ case ModDisp16WRReg:
+ BAsmCode[0]=0x7f+(OpSize*7);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ BAsmCode[2+AdrCnt]=WorkOfs+HReg;
+ CodeLen=3+AdrCnt;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0xc4+(OpSize*30);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ case ModImm:
+ BAsmCode[0]=(ALUOrders[z].Code << 4)+5+(OpSize*2);
+ BAsmCode[1]=WorkOfs+HReg+OpSize;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ END
+ break;
+ case ModReg:
+ case ModRReg:
+ HReg=AdrVals[0];
+ DecodeAdr(ArgStr[2],Mask2+MModIWReg+MModIWRReg+MModIncWRReg+MModDecWRReg+
+ MModDisp8WRReg+MModDisp16WRReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=(ALUOrders[z].Code << 4)+4+(OpSize*3); CodeLen=3;
+ BAsmCode[1]=AdrVals[0]; BAsmCode[2]=HReg;
+ break;
+ case ModIWReg:
+ BAsmCode[0]=0xa6+65*(1-OpSize);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
+ BAsmCode[2]=HReg; CodeLen=3;
+ break;
+ case ModIWRReg:
+ BAsmCode[0]=0x72+(OpSize*12);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+(1-OpSize);
+ BAsmCode[2]=HReg; CodeLen=3;
+ break;
+ case ModIncWRReg:
+ BAsmCode[0]=0xb4+(OpSize*0x21);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
+ BAsmCode[2]=HReg; CodeLen=3;
+ break;
+ case ModDecWRReg:
+ BAsmCode[0]=0xc2+OpSize;
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
+ BAsmCode[2]=HReg; CodeLen=3;
+ break;
+ case ModDisp8WRReg:
+ BAsmCode[0]=0x7f+(OpSize*7);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
+ BAsmCode[2]=AdrVals[0]; BAsmCode[3]=HReg; CodeLen=4;
+ break;
+ case ModDisp16WRReg:
+ BAsmCode[0]=0x7f+(OpSize*7);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); BAsmCode[2+AdrCnt]=HReg;
+ CodeLen=3+AdrCnt;
+ break;
+ case ModImm:
+ BAsmCode[0]=(ALUOrders[z].Code << 4)+5+(OpSize*2);
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); BAsmCode[1]=HReg+OpSize;
+ CodeLen=2+AdrCnt;
+ break;
+ END
+ break;
+ case ModIWReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask2);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0xe6-(OpSize*0x50); BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=(ALUOrders[z].Code << 4)+HReg; CodeLen=3;
+ break;
+ END
+ break;
+ case ModIWRReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],(OpSize*MModWRReg)+Mask2+MModIWRReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModWRReg:
+ BAsmCode[0]=(ALUOrders[z].Code << 4)+0x0e;
+ BAsmCode[1]=(HReg << 4)+0x10+AdrPart; CodeLen=2;
+ break;
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0x72+(OpSize*76);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg+OpSize;
+ BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModIWRReg:
+ if (OpSize==0)
+ BEGIN
+ BAsmCode[0]=0x73; BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
+ BAsmCode[2]=HReg+WorkOfs; CodeLen=3;
+ END
+ else
+ BEGIN
+ BAsmCode[0]=(ALUOrders[z].Code << 4)+0x0e;
+ BAsmCode[1]=0x11+(HReg << 4)+AdrPart;
+ CodeLen=2;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xf3-(OpSize*0x35);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ END
+ break;
+ case ModIncWRReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask2);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0xb4+(OpSize*0x21);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
+ BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ case ModDecWRReg:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],Mask2);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0xc2+OpSize;
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
+ BAsmCode[2]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ case ModDispRWRReg:
+ HReg=AdrPart; HPart=AdrVals[0];
+ DecodeAdr(ArgStr[2],Mask1);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ case ModWRReg:
+ BAsmCode[0]=0x60;
+ BAsmCode[1]=0x11-(OpSize*0x10)+(HPart << 4)+HReg;
+ BAsmCode[2]=(ALUOrders[z].Code << 4)+AdrPart; CodeLen=3;
+ break;
+ END
+ break;
+ case ModDisp8WRReg:
+ HReg=AdrPart; BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[2],Mask2+(OpSize*MModImm));
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0x26+(OpSize*0x60);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg+1;
+ BAsmCode[3]=AdrVals[0]+OpSize; CodeLen=4;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x06; BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg+1;
+ memcpy(BAsmCode+3,AdrVals,AdrCnt); CodeLen=3+AdrCnt;
+ break;
+ END
+ break;
+ case ModDisp16WRReg:
+ HReg=AdrPart; memcpy(BAsmCode+2,AdrVals,2);
+ DecodeAdr(ArgStr[2],Mask2+(OpSize*MModImm));
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ case ModRReg:
+ BAsmCode[0]=0x26+(OpSize*0x60);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
+ BAsmCode[4]=AdrVals[0]+OpSize; CodeLen=5;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x06; BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
+ memcpy(BAsmCode+4,AdrVals,AdrCnt); CodeLen=4+AdrCnt;
+ break;
+ END
+ break;
+ case ModAbs:
+ memcpy(BAsmCode+2,AdrVals,2);
+ DecodeAdr(ArgStr[2],Mask1+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ case ModWRReg:
+ BAsmCode[0]=0xc5+(OpSize*29);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+OpSize;
+ CodeLen=4;
+ break;
+ case ModImm:
+ memmove(BAsmCode+2+AdrCnt,BAsmCode+2,2); memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ BAsmCode[0]=0x2f+(OpSize*7);
+ BAsmCode[1]=(ALUOrders[z].Code << 4)+1;
+ CodeLen=4+AdrCnt;
+ break;
+ END
+ break;
+ case ModIRReg:
+ HReg=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModIWRReg*(1-OpSize));
+ switch (AdrMode)
+ BEGIN
+ case ModIWRReg:
+ BAsmCode[0]=0x73; BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
+ BAsmCode[2]=HReg; CodeLen=3;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<RegOrderCnt; z++)
+ if (Memo(RegOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModIReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=RegOrders[z].Code; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModIReg:
+ BAsmCode[0]=RegOrders[z].Code+1; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Reg16OrderCnt; z++)
+ if (Memo(Reg16Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModRReg);
+ switch (AdrMode)
+ BEGIN
+ case ModRReg:
+ BAsmCode[0]=Reg16Orders[z].Code; BAsmCode[1]=AdrVals[0]+Ord(Memo("EXT"));
+ CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("DIV")) OR (Memo("MUL")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWRReg);
+ if (AdrMode==ModWRReg)
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModWReg);
+ if (AdrMode==ModWReg)
+ BEGIN
+ BAsmCode[0]=0x5f-(0x10*Ord(Memo("MUL")));
+ BAsmCode[1]=(HReg << 4)+AdrPart;
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("DIVWS"))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWRReg);
+ if (AdrMode==ModWRReg)
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModWRReg);
+ if (AdrMode==ModWRReg)
+ BEGIN
+ BAsmCode[2]=(HReg << 4)+AdrPart;
+ DecodeAdr(ArgStr[3],MModRReg);
+ if (AdrMode==ModRReg)
+ BEGIN
+ BAsmCode[0]=0x56; BAsmCode[1]=AdrVals[0];
+ CodeLen=3;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* Bitoperationen */
+
+ for (z=0; z<Bit2OrderCnt; z++)
+ if (Memo(Bit2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (SplitBit(ArgStr[1],&HReg))
+ if (Odd(HReg)) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg);
+ if (AdrMode==ModWReg)
+ BEGIN
+ HReg=(HReg << 4)+AdrPart;
+ if (SplitBit(ArgStr[2],&HPart))
+ BEGIN
+ DecodeAdr(ArgStr[2],MModWReg);
+ if (AdrMode==ModWReg)
+ BEGIN
+ HPart=(HPart << 4)+AdrPart;
+ BAsmCode[0]=Bit2Orders[z].Code;
+ if (Memo("BLD"))
+ BEGIN
+ BAsmCode[1]=HPart | 0x10; BAsmCode[2]=HReg | (HPart & 0x10);
+ END
+ else if (Memo("BXOR"))
+ BEGIN
+ BAsmCode[1]=0x10+HReg; BAsmCode[2]=HPart;
+ END
+ else
+ BEGIN
+ BAsmCode[1]=0x10+HReg; BAsmCode[2]=HPart ^ 0x10;
+ END
+ CodeLen=3;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Bit1OrderCnt; z++)
+ if (Memo(Bit1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (SplitBit(ArgStr[1],&HReg))
+ if (Odd(HReg)) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg+(Ord(Memo("BTSET"))*MModIWRReg));
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=Bit1Orders[z].Code; BAsmCode[1]=(HReg << 4)+AdrPart;
+ CodeLen=2;
+ break;
+ case ModIWRReg:
+ BAsmCode[0]=0xf6; BAsmCode[1]=(HReg << 4)+AdrPart;
+ CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if ((Memo("BTJF")) OR (Memo("BTJT")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (SplitBit(ArgStr[1],&HReg))
+ if (Odd(HReg)) WrError(1350);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg);
+ if (AdrMode==ModWReg)
+ BEGIN
+ BAsmCode[1]=(HReg << 4)+AdrPart+(Ord(Memo("BTJF")) << 4);
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+3);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=0xaf; BAsmCode[2]=AdrInt & 0xff; CodeLen=3;
+ ChkSpace(SegCode);
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("JP")) OR (Memo("CALL")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AbsSeg=SegCode;
+ DecodeAdr(ArgStr[1],MModIRReg+MModAbs);
+ switch (AdrMode)
+ BEGIN
+ case ModIRReg:
+ BAsmCode[0]=0x74+(Ord(Memo("JP"))*0x60);
+ BAsmCode[1]=AdrVals[0]+Ord(Memo("CALL")); CodeLen=2;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0x8d+(Ord(Memo("CALL"))*0x45);
+ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CPJFI")) OR (Memo("CPJTI")))
+ BEGIN
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg);
+ if (AdrMode==ModWReg)
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModIWRReg);
+ if (AdrMode==ModIWRReg)
+ BEGIN
+ BAsmCode[1]=(AdrPart << 4)+(Ord(Memo("CPJTI")) << 4)+HReg;
+ AdrInt=EvalIntExpression(ArgStr[3],UInt16,&OK)-(EProgCounter()+3);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ BAsmCode[0]=0x9f; BAsmCode[2]=AdrInt & 0xff;
+ CodeLen=3;
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("DJNZ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg);
+ if (AdrMode==ModWReg)
+ BEGIN
+ BAsmCode[0]=(AdrPart << 4)+0x0a;
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ BAsmCode[1]=AdrInt & 0xff;
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("DWJNZ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModRReg);
+ if (AdrMode==ModRReg)
+ BEGIN
+ BAsmCode[1]=AdrVals[0];
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+3);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ BAsmCode[0]=0xc6; BAsmCode[2]=AdrInt & 0xff;
+ CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ConditionCnt; z++)
+ if ((*OpPart=='J') AND (OpPart[1]=='P') AND (strcmp(OpPart+2,Conditions[z].Name)==0))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrWord=EvalIntExpression(ArgStr[1],UInt16,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+ BAsmCode[0]=0x0d+(Conditions[z].Code << 4);
+ BAsmCode[1]=Hi(AdrWord); BAsmCode[2]=Lo(AdrWord);
+ CodeLen=3;
+ END
+ END
+ return;
+ END
+ else if ((*OpPart=='J') AND (OpPart[1]=='R') AND (strcmp(OpPart+2,Conditions[z].Name)==0))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ BAsmCode[0]=0x0b+(Conditions[z].Code << 4); BAsmCode[1]=AdrInt & 0xff;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ /* Besonderheiten */
+
+ if (Memo("SPP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=(EvalIntExpression(ArgStr[1]+1,UInt6,&OK) << 2)+0x02;
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xc7; CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("SRP")) OR (Memo("SRP0")) OR (Memo("SRP1")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*ArgStr[1]!='#') WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[1]+1,UInt5,&OK) << 3;
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xc7; CodeLen=2;
+ if (strlen(OpPart)==4) BAsmCode[1]+=4;
+ if (OpPart[strlen(OpPart)-1]=='1') BAsmCode[1]++;
+ END
+ END
+ return;
+ END
+
+ /* Fakes... */
+
+ if (Memo("SLA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg+MModReg+MModIWRReg);
+ switch (AdrMode)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=0x42; BAsmCode[1]=(AdrPart << 4)+AdrPart;
+ CodeLen=2;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x44;
+ BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=AdrVals[0];
+ CodeLen=3;
+ break;
+ case ModIWRReg:
+ BAsmCode[0]=0x73; BAsmCode[1]=0x40+AdrPart;
+ BAsmCode[2]=WorkOfs+AdrPart; CodeLen=3;
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("SLAW"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWRReg+MModRReg+MModIWRReg);
+ switch (AdrMode)
+ BEGIN
+ case ModWRReg:
+ BAsmCode[0]=0x4e; BAsmCode[1]=(AdrPart << 4)+AdrPart;
+ CodeLen=2;
+ break;
+ case ModRReg:
+ BAsmCode[0]=0x47;
+ BAsmCode[1]=AdrVals[0];
+ BAsmCode[2]=AdrVals[0];
+ CodeLen=3;
+ break;
+ case ModIWRReg:
+ BAsmCode[0]=0x4e; BAsmCode[1]=0x11+(AdrPart << 4)+AdrPart;
+ CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_ST9(void)
+BEGIN
+ SaveInitProc();
+
+ DPAssume=0;
+END
+
+ static Boolean IsDef_ST9(void)
+BEGIN
+ return (Memo("REG") OR Memo("BIT"));
+END
+
+ static void SwitchFrom_ST9(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void InternSymbol_ST9(char *Asc, TempResult *Erg)
+BEGIN
+ String h;
+ Boolean Err;
+ Boolean Pair;
+
+ Erg->Typ=TempNone;
+ if ((strlen(Asc)<2) OR (*Asc!='R')) return;
+
+ strmaxcpy(h,Asc+1,255);
+ if (*h=='R')
+ BEGIN
+ if (strlen(h)<2) return;
+ Pair=True; strcpy(h,h+1);
+ END
+ else Pair=False;
+ Erg->Contents.Int=ConstLongInt(h,&Err);
+ if ((NOT Err) OR (Erg->Contents.Int<0) OR (Erg->Contents.Int>255)) return;
+ if ((Erg->Contents.Int & 0xf0)==0xd0) return;
+ if ((Pair) AND (Odd(Erg->Contents.Int))) return;
+
+ if (Pair) Erg->Contents.Int+=0x100;
+ Erg->Typ=TempInt; TypeFlag|=(1 << SegReg);
+END
+
+ static void SwitchTo_ST9(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="PC"; HeaderID=0x32; NOPCode=0xff;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegReg);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
+ SegLimits[SegData] = 0xffff;
+ Grans[SegReg ]=1; ListGrans[SegReg ]=1; SegInits[SegReg ]=0;
+ SegLimits[SegReg ] = 0xff;
+
+ MakeCode=MakeCode_ST9; IsDef=IsDef_ST9;
+ SwitchFrom=SwitchFrom_ST9; InternSymbol=InternSymbol_ST9;
+
+ InitFields();
+END
+
+ void codest9_init(void)
+BEGIN
+ CPUST9020=AddCPU("ST9020",SwitchTo_ST9);
+ CPUST9030=AddCPU("ST9030",SwitchTo_ST9);
+ CPUST9040=AddCPU("ST9040",SwitchTo_ST9);
+ CPUST9050=AddCPU("ST9050",SwitchTo_ST9);
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_ST9;
+END
+
+
diff --git a/codest9.h b/codest9.h
new file mode 100644
index 0000000..197e53e
--- /dev/null
+++ b/codest9.h
@@ -0,0 +1,11 @@
+/* codest9.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator SGS-Thomson ST9 */
+/* */
+/* Historie: 10.2.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codest9_init(void);
diff --git a/codetms7.c b/codetms7.c
new file mode 100644
index 0000000..23da68b
--- /dev/null
+++ b/codetms7.c
@@ -0,0 +1,954 @@
+/* codetms7.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS7000-Familie */
+/* */
+/* Historie: 26.2.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "strutil.h"
+#include "bpemu.h"
+#include "nls.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+
+typedef struct
+ {
+ char *Name;
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ int Length;
+ Word Code;
+ } LengthOrder;
+
+
+#define ModNone (-1)
+#define ModAccA 0
+#define MModAccA (1 << ModAccA) /* A */
+#define ModAccB 1
+#define MModAccB (1 << ModAccB) /* B */
+#define ModReg 2
+#define MModReg (1 << ModReg) /* Rn */
+#define ModPort 3
+#define MModPort (1 << ModPort) /* Pn */
+#define ModAbs 4
+#define MModAbs (1 << ModAbs) /* nnnn */
+#define ModBRel 5
+#define MModBRel (1 << ModBRel) /* nnnn(B) */
+#define ModIReg 6
+#define MModIReg (1 << ModIReg) /* *Rn */
+#define ModImm 7
+#define MModImm (1 << ModImm) /* #nn */
+#define ModImmBRel 8
+#define MModImmBRel (1 << ModImmBRel) /* #nnnn(b) */
+
+
+#define FixedOrderCount 14
+#define Rel8OrderCount 12
+#define ALU1OrderCount 7
+#define ALU2OrderCount 5
+#define JmpOrderCount 2
+#define ABRegOrderCount 14
+
+
+static CPUVar CPU70C40,CPU70C20,CPU70C00,
+ CPU70CT40,CPU70CT20,
+ CPU70C82,CPU70C42,CPU70C02,
+ CPU70C48,CPU70C08;
+
+static Byte OpSize;
+static ShortInt AdrType;
+static Byte AdrVals[2];
+
+static FixedOrder *FixedOrders;
+static FixedOrder *Rel8Orders;
+static FixedOrder *ALU1Orders;
+static LengthOrder *ALU2Orders;
+static FixedOrder *JmpOrders;
+static FixedOrder *ABRegOrders;
+
+/*---------------------------------------------------------------------------*/
+
+ static void InitFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCount) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitRel8(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=Rel8OrderCount) exit(255);
+ Rel8Orders[InstrZ].Name=NName;
+ Rel8Orders[InstrZ++].Code=NCode;
+END
+
+ static void InitALU1(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ALU1OrderCount) exit(255);
+ ALU1Orders[InstrZ].Name=NName;
+ ALU1Orders[InstrZ++].Code=NCode;
+END
+
+ static void InitALU2(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ALU2OrderCount) exit(255);
+ ALU2Orders[InstrZ].Name=NName;
+ ALU2Orders[InstrZ].Length=strlen(NName);
+ ALU2Orders[InstrZ++].Code=NCode;
+END
+
+ static void InitJmp(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=JmpOrderCount) exit(255);
+ JmpOrders[InstrZ].Name=NName;
+ JmpOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitABReg(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=ABRegOrderCount) exit(255);
+ ABRegOrders[InstrZ].Name=NName;
+ ABRegOrders[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
+ InitFixed("CLRC" ,0x00b0); InitFixed("DINT" ,0x0060);
+ InitFixed("EINT" ,0x0005); InitFixed("IDLE" ,0x0001);
+ InitFixed("LDSP" ,0x000d); InitFixed("NOP" ,0x0000);
+ InitFixed("RETI" ,0x000b); InitFixed("RTI" ,0x000b);
+ InitFixed("RETS" ,0x000a); InitFixed("RTS" ,0x000a);
+ InitFixed("SETC" ,0x0007); InitFixed("STSP" ,0x0009);
+ InitFixed("TSTA" ,0x00b0); InitFixed("TSTB" ,0x00c1);
+
+ Rel8Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Rel8OrderCount); InstrZ=0;
+ InitRel8("JMP",0xe0); InitRel8("JC" ,0xe3); InitRel8("JEQ",0xe2);
+ InitRel8("JHS",0xe3); InitRel8("JL" ,0xe7); InitRel8("JN" ,0xe1);
+ InitRel8("JNC",0xe7); InitRel8("JNE",0xe6); InitRel8("JNZ",0xe6);
+ InitRel8("JP" ,0xe4); InitRel8("JPZ",0xe5); InitRel8("JZ" ,0xe2);
+
+ ALU1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU1OrderCount); InstrZ=0;
+ InitALU1("ADC", 9); InitALU1("ADD", 8);
+ InitALU1("DAC",14); InitALU1("DSB",15);
+ InitALU1("SBB",11); InitALU1("SUB",10); InitALU1("MPY",12);
+
+ ALU2Orders=(LengthOrder *) malloc(sizeof(LengthOrder)*ALU2OrderCount); InstrZ=0;
+ InitALU2("AND" , 3); InitALU2("BTJO", 6);
+ InitALU2("BTJZ", 7); InitALU2("OR" , 4); InitALU2("XOR", 5);
+
+ JmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*JmpOrderCount); InstrZ=0;
+ InitJmp("BR" ,12); InitJmp("CALL" ,14);
+
+ ABRegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ABRegOrderCount); InstrZ=0;
+ InitABReg("CLR" , 5); InitABReg("DEC" , 2); InitABReg("DECD" ,11);
+ InitABReg("INC" , 3); InitABReg("INV" , 4); InitABReg("POP" , 9);
+ InitABReg("PUSH" , 8); InitABReg("RL" ,14); InitABReg("RLC" ,15);
+ InitABReg("RR" ,12); InitABReg("RRC" ,13); InitABReg("SWAP" , 7);
+ InitABReg("XCHB" , 6); InitABReg("DJNZ" ,10);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(Rel8Orders);
+ free(ALU1Orders);
+ free(ALU2Orders);
+ free(JmpOrders);
+ free(ABRegOrders);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrType!=-1) AND ((Mask & (1L << AdrType))==0))
+ BEGIN
+ WrError(1350); AdrType=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ Integer HVal;
+ int Lev,l;
+ char *p;
+ Boolean OK;
+
+ AdrType=ModNone; AdrCnt=0;
+
+ if (strcasecmp(Asc,"A")==0)
+ BEGIN
+ if (((Mask & MModAccA)!=0)) AdrType=ModAccA;
+ else if (((Mask & MModReg)!=0))
+ BEGIN
+ AdrCnt=1; AdrVals[0]=0; AdrType=ModReg;
+ END
+ else
+ BEGIN
+ AdrCnt=2; AdrVals[0]=0; AdrVals[1]=0; AdrType=ModAbs;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if (strcasecmp(Asc,"B")==0)
+ BEGIN
+ if (((Mask & MModAccB)!=0)) AdrType=ModAccB;
+ else if (((Mask & MModReg)!=0))
+ BEGIN
+ AdrCnt=1; AdrVals[0]=1; AdrType=ModReg;
+ END
+ else
+ BEGIN
+ AdrCnt=2; AdrVals[0]=0; AdrVals[1]=1; AdrType=ModAbs;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if ((*Asc=='#') OR (*Asc=='%'))
+ BEGIN
+ strcpy(Asc,Asc+1); l=strlen(Asc);
+ if ((l>=3) AND (strcasecmp(Asc+l-3,"(B)")==0))
+ BEGIN
+ Asc[l-3]='\0';
+ HVal=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=Hi(HVal); AdrVals[1]=Lo(HVal);
+ AdrType=ModImmBRel; AdrCnt=2;
+ END
+ END
+ else
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc,Int8,&OK); break;
+ case 1:
+ HVal=EvalIntExpression(Asc,Int16,&OK);
+ AdrVals[0]=Hi(HVal); AdrVals[1]=Lo(HVal);
+ break;
+ END
+ if (OK)
+ BEGIN
+ AdrCnt=1+OpSize; AdrType=ModImm;
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if (*Asc=='*')
+ BEGIN
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrType=ModIReg;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if (*Asc=='@') strcpy(Asc,Asc+1);
+
+ if (Asc[strlen(Asc)-1]==')')
+ BEGIN
+ p=Asc+strlen(Asc)-2; Lev=0;
+ while ((p>=Asc) AND (Lev!=-1))
+ BEGIN
+ switch (*p)
+ BEGIN
+ case '(': Lev--; break;
+ case ')': Lev++; break;
+ END
+ if (Lev!=-1) p--;
+ END
+ if (p<Asc)
+ BEGIN
+ WrError(1300); p=Nil;
+ END
+ END
+ else p=Nil;
+
+ if (p==Nil)
+ BEGIN
+ HVal=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ if (((Mask & MModReg)!=0) AND (Hi(HVal)==0))
+ BEGIN
+ AdrVals[0]=Lo(HVal); AdrCnt=1; AdrType=ModReg;
+ END
+ else if (((Mask & MModPort)!=0) AND (Hi(HVal)==0x01))
+ BEGIN
+ AdrVals[0]=Lo(HVal); AdrCnt=1; AdrType=ModPort;
+ END
+ else
+ BEGIN
+ AdrVals[0]=Hi(HVal); AdrVals[1]=Lo(HVal); AdrCnt=2;
+ AdrType=ModAbs;
+ END
+ ChkAdr(Mask); return;
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False; *p='\0';
+ HVal=EvalIntExpression(Asc,Int16,&OK);
+ if (OK)
+ BEGIN
+ p++; p[strlen(p)-1]='\0';
+ if (strcasecmp(p,"B")==0)
+ BEGIN
+ AdrVals[0]=Hi(HVal); AdrVals[1]=Lo(HVal); AdrCnt=2;
+ AdrType=ModBRel;
+ END
+ else WrXError(1445,p);
+ END
+ ChkAdr(Mask); return;
+ END
+END
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ return False;
+END
+
+ static void PutCode(Word Code)
+BEGIN
+ if (Hi(Code)!=0) BAsmCode[CodeLen++]=Hi(Code);
+ BAsmCode[CodeLen++]=Lo(Code);
+END
+
+ static void MakeCode_TMS7(void)
+BEGIN
+ Integer AdrInt;
+ int z;
+ Boolean OK,Rela;
+
+ CodeLen=0; DontPrint=False; OpSize=0;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(True)) return;
+
+ for (z=0; z<FixedOrderCount; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else PutCode(FixedOrders[z].Code);
+ return;
+ END
+
+ if ((Memo("MOV")) OR (Memo("MOVP")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModPort+MModAccA+MModAccB+
+ ((Memo("MOVP"))?0:MModReg+MModAbs+MModIReg+MModBRel));
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ DecodeAdr(ArgStr[1],MModPort+
+ ((Memo("MOVP"))?0:MModReg+MModAbs+MModIReg+MModBRel+MModAccB+MModImm));
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x12; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModAbs:
+ BAsmCode[0]=0x8a; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0x9a; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModBRel:
+ BAsmCode[0]=0xaa; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0x62; CodeLen=1;
+ break;
+ case ModPort:
+ BAsmCode[0]=0x80; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x22; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModAccB:
+ DecodeAdr(ArgStr[1],MModPort+
+ ((Memo("MOVP"))?0:MModAccA+MModReg+MModImm));
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0xc0; CodeLen=1;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x32; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModPort:
+ BAsmCode[0]=0x91; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x52; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModReg:
+ BAsmCode[1]=BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB+MModReg+MModPort+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0xd0; CodeLen=2;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0xd1; CodeLen=2;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x42; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModPort:
+ BAsmCode[0]=0xa2; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x72; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ case ModPort:
+ BAsmCode[1]=AdrVals[0]; BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0x82; CodeLen=2;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0x92; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0xa2; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ case ModAbs:
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[1],MModAccA);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x8b; CodeLen=3;
+ END
+ break;
+ case ModIReg:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModAccA);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0x9b; CodeLen=2;
+ END
+ break;
+ case ModBRel:
+ memcpy(BAsmCode+1,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[1],MModAccA);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=0xab; CodeLen=3;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAbs+MModBRel+MModIReg);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ BAsmCode[0]=0x8a; memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ break;
+ case ModBRel:
+ BAsmCode[0]=0xaa; memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0x9a; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("STA"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAbs+MModBRel+MModIReg);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ BAsmCode[0]=0x8b; memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ break;
+ case ModBRel:
+ BAsmCode[0]=0xab; memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0x9b; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("MOVW")) OR (Memo("MOVD")))
+ BEGIN
+ OpSize=1;
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrType!=ModNone)
+ BEGIN
+ z=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg+MModImm+MModImmBRel);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x98; BAsmCode[1]=AdrVals[0]; BAsmCode[2]=z;
+ CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x88; memcpy(BAsmCode+1,AdrVals,2);
+ BAsmCode[3]=z;
+ CodeLen=4;
+ break;
+ case ModImmBRel:
+ BAsmCode[0]=0xa8; memcpy(BAsmCode+1,AdrVals,2);
+ BAsmCode[3]=z;
+ CodeLen=4;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<Rel8OrderCount; z++)
+ if (Memo(Rel8Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((AdrInt>127) OR (AdrInt<-128)) WrError(1370);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=Rel8Orders[z].Code; BAsmCode[1]=AdrInt & 0xff;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("CMP")) OR (Memo("CMPA")))
+ BEGIN
+ if (((Memo("CMP")) AND (ArgCnt!=2)) OR ((Memo("CMPA")) AND (ArgCnt!=1))) WrError(1110);
+ else
+ BEGIN
+ if (Memo("CMPA")) AdrType=ModAccA;
+ else DecodeAdr(ArgStr[2],MModAccA+MModAccB+MModReg);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ DecodeAdr(ArgStr[1],MModAbs+MModIReg+MModBRel+MModAccB+MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ BAsmCode[0]=0x8d; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0x9d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModBRel:
+ BAsmCode[0]=0xad; memcpy(BAsmCode+1,AdrVals,2); CodeLen=3;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0x6d; CodeLen=1;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x1d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x2d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModAccB:
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x3d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x5d; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ break;
+ case ModReg:
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x4d; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x7d; BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ALU1OrderCount; z++)
+ if (Memo(ALU1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModAccA+MModAccB+MModReg);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ DecodeAdr(ArgStr[1],MModAccB+MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccB:
+ CodeLen=1; BAsmCode[0]=0x60+ALU1Orders[z].Code;
+ break;
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0x10+ALU1Orders[z].Code;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x20+ALU1Orders[z].Code;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModAccB:
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=2; BAsmCode[0]=0x30+ALU1Orders[z].Code;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ case ModImm:
+ CodeLen=2; BAsmCode[0]=0x50+ALU1Orders[z].Code;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ case ModReg:
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ CodeLen=3; BAsmCode[0]=0x40+ALU1Orders[z].Code;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ case ModImm:
+ CodeLen=3; BAsmCode[0]=0x70+ALU1Orders[z].Code;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ALU2OrderCount; z++)
+ if ((strncmp(OpPart,ALU2Orders[z].Name,ALU2Orders[z].Length)==0)
+ AND ((OpPart[ALU2Orders[z].Length]=='P') OR (OpPart[ALU2Orders[z].Length]=='\0')))
+ BEGIN
+ Rela=strncmp(OpPart,"BTJ",3)==0;
+ if (((Rela) AND (ArgCnt!=3))
+ OR ((NOT Rela) AND (ArgCnt!=2))) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[2],MModPort+
+ ((OpPart[strlen(OpPart)-1]=='P')?0:MModAccA+MModAccB+MModReg));
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ DecodeAdr(ArgStr[1],MModAccB+MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccB:
+ BAsmCode[0]=0x60+ALU2Orders[z].Code; CodeLen=1;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x10+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x20+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ break;
+ END
+ break;
+ case ModAccB:
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x30+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x50+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ break;
+ END
+ break;
+ case ModReg:
+ BAsmCode[2]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModReg+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0x40+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0x70+ALU2Orders[z].Code; BAsmCode[1]=AdrVals[0];
+ CodeLen=3;
+ END
+ break;
+ case ModPort:
+ BAsmCode[1]=AdrVals[0];
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB+MModImm);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0x80+ALU2Orders[z].Code; CodeLen=2;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0x90+ALU2Orders[z].Code; CodeLen=2;
+ break;
+ case ModImm:
+ BAsmCode[0]=0xa0+ALU2Orders[z].Code; BAsmCode[2]=BAsmCode[1];
+ BAsmCode[1]=AdrVals[0]; CodeLen=3;
+ END
+ break;
+ END
+ if ((CodeLen!=0) AND (Rela))
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[3],Int16,&OK)-(EProgCounter()+CodeLen+1);
+ if (NOT OK) CodeLen=0;
+ else if ((NOT SymbolQuestionable) AND ((AdrInt>127) OR (AdrInt<-128)))
+ BEGIN
+ WrError(1370); CodeLen=0;
+ END
+ else BAsmCode[CodeLen++]=AdrInt & 0xff;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<JmpOrderCount; z++)
+ if (Memo(JmpOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAbs+MModIReg+MModBRel);
+ switch (AdrType)
+ BEGIN
+ case ModAbs:
+ CodeLen=3; BAsmCode[0]=0x80+JmpOrders[z].Code;
+ memcpy(BAsmCode+1,AdrVals,2);
+ break;
+ case ModIReg:
+ CodeLen=2; BAsmCode[0]=0x90+JmpOrders[z].Code;
+ BAsmCode[1]=AdrVals[0];
+ break;
+ case ModBRel:
+ CodeLen=3; BAsmCode[0]=0xa0+JmpOrders[z].Code;
+ memcpy(BAsmCode+1,AdrVals,2);
+ break;
+ END
+ END
+ return;
+ END
+
+ for (z=0; z<ABRegOrderCount; z++)
+ if (Memo(ABRegOrders[z].Name))
+ BEGIN
+ if (((NOT Memo("DJNZ")) AND (ArgCnt!=1))
+ OR (( Memo("DJNZ")) AND (ArgCnt!=2))) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"ST")==0)
+ BEGIN
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ BAsmCode[0]=8+(Ord(Memo("PUSH"))*6); CodeLen=1;
+ END
+ else WrError(1350);
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB+MModReg);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0xb0+ABRegOrders[z].Code; CodeLen=1;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0xc0+ABRegOrders[z].Code; CodeLen=1;
+ break;
+ case ModReg:
+ BAsmCode[0]=0xd0+ABRegOrders[z].Code;
+ BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ END
+ if ((Memo("DJNZ")) AND (CodeLen!=0))
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+CodeLen+1);
+ if (NOT OK) CodeLen=0;
+ else if ((NOT SymbolQuestionable) AND ((AdrInt>127) OR (AdrInt<-128)))
+ BEGIN
+ WrError(1370); CodeLen=0;
+ END
+ else BAsmCode[CodeLen++]=AdrInt & 0xff;
+ END
+ END
+ return;
+ END
+
+ if (Memo("TRAP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ BAsmCode[0]=EvalIntExpression(ArgStr[1],UInt5,&OK);
+ if (FirstPassUnknown) BAsmCode[0]&=15;
+ if (OK)
+ if (BAsmCode[0]>23) WrError(1320);
+ else
+ BEGIN
+ BAsmCode[0]=0xff-BAsmCode[0]; CodeLen=1;
+ END
+ END
+ return;
+ END
+
+ if (Memo("TST"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModAccA+MModAccB);
+ switch (AdrType)
+ BEGIN
+ case ModAccA:
+ BAsmCode[0]=0xb0; CodeLen=1;
+ break;
+ case ModAccB:
+ BAsmCode[0]=0xc1; CodeLen=1;
+ break;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_TMS7(void)
+BEGIN
+ return False;
+END
+
+ static void InternSymbol_TMS7(char *Asc, TempResult *Erg)
+BEGIN
+ String h;
+ Boolean Err;
+
+ Erg->Typ=TempNone;
+ if ((strlen(Asc)<2) OR ((toupper(*Asc)!='R') AND (toupper(*Asc)!='P'))) return;
+
+ strmaxcpy(h,Asc+1,255);
+ if ((*h=='0') AND (strlen(h)>1)) *h='$';
+ Erg->Contents.Int=ConstLongInt(h,&Err);
+ if ((NOT Err) OR (Erg->Contents.Int<0) OR (Erg->Contents.Int>255)) return;
+
+ Erg->Typ=TempInt; if (toupper(*Asc)=='P') Erg->Contents.Int+=0x100;
+END
+
+ static void SwitchFrom_TMS7(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_TMS7(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x73; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=1<<SegCode;
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+
+ MakeCode=MakeCode_TMS7; IsDef=IsDef_TMS7;
+ SwitchFrom=SwitchFrom_TMS7; InternSymbol=InternSymbol_TMS7;
+
+ InitFields();
+END
+
+ void codetms7_init(void)
+BEGIN
+ CPU70C00 =AddCPU("TMS70C00", SwitchTo_TMS7);
+ CPU70C20 =AddCPU("TMS70C20", SwitchTo_TMS7);
+ CPU70C40 =AddCPU("TMS70C40", SwitchTo_TMS7);
+ CPU70CT20=AddCPU("TMS70CT20",SwitchTo_TMS7);
+ CPU70CT40=AddCPU("TMS70CT40",SwitchTo_TMS7);
+ CPU70C02 =AddCPU("TMS70C02", SwitchTo_TMS7);
+ CPU70C42 =AddCPU("TMS70C42", SwitchTo_TMS7);
+ CPU70C82 =AddCPU("TMS70C82", SwitchTo_TMS7);
+ CPU70C08 =AddCPU("TMS70C08", SwitchTo_TMS7);
+ CPU70C48 =AddCPU("TMS70C48", SwitchTo_TMS7);
+END
diff --git a/codetms7.h b/codetms7.h
new file mode 100644
index 0000000..c11fb1c
--- /dev/null
+++ b/codetms7.h
@@ -0,0 +1,11 @@
+/* codetms7.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator TMS7000-Familie */
+/* */
+/* Historie: 26.2.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codetms7_init(void);
diff --git a/codevars.c b/codevars.c
new file mode 100644
index 0000000..c786e4c
--- /dev/null
+++ b/codevars.c
@@ -0,0 +1,14 @@
+/* codevars.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Gemeinsame Variablen aller Codegeneratoren */
+/* */
+/* Historie: 26.5.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+int InstrZ;
+int AdrCnt;
diff --git a/codevars.h b/codevars.h
new file mode 100644
index 0000000..e284369
--- /dev/null
+++ b/codevars.h
@@ -0,0 +1,12 @@
+/* codevars.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Gemeinsame Variablen aller Codegeneratoren */
+/* */
+/* Historie: 26.5.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern int InstrZ;
+extern int AdrCnt;
diff --git a/codexa.c b/codexa.c
new file mode 100644
index 0000000..871da67
--- /dev/null
+++ b/codexa.c
@@ -0,0 +1,1975 @@
+/* codexa.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegenerator Philips XA */
+/* */
+/* Historie: 25.10.1996 Grundsteinlegung */
+/* 19. 8.1998 autom. Verlaengerung Spruenge */
+/* 23. 8.1998 Umbau auf Hash-Tabelle */
+/* lange Spruenge fuer JBC */
+/* 24. 8.1998 lange Spruenge fuer DJNZ CJNE */
+/* 25. 8.1998 nach Hashing ueberfluessige Namensfelder entfernt */
+/* 14.10.1998 BRANCHEXT auch fuer BR-Befehle */
+/* Padding-Byte auch fuer Sprung auf sich selber */
+/* Das $ zu verschieben ist aber noch etwas tricky... */
+/* 9. 1.1999 ChkPC jetzt mit Adresse als Parameter */
+/* 20. 1.1999 Formate maschinenunabhaengig gemacht */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmallg.h"
+#include "asmitree.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+/*-------------------------------------------------------------------------*/
+/* Definitionen */
+
+#define ModNone (-1)
+#define ModReg 0
+#define MModReg (1 << ModReg)
+#define ModMem 1
+#define MModMem (1 << ModMem)
+#define ModImm 2
+#define MModImm (1 << ModImm)
+#define ModAbs 3
+#define MModAbs (1 << ModAbs)
+
+#define FixedOrderCnt 5
+#define JBitOrderCnt 3
+#define RegOrderCnt 4
+#define RotateOrderCount 4
+#define RelOrderCount 17
+#define StackOrderCount 4
+
+typedef struct
+ {
+ Word Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ Byte SizeMask;
+ Byte Code;
+ } RegOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte SizeMask;
+ Byte Code;
+ Byte Inversion;
+ } InvOrder;
+
+static CPUVar CPUXAG1,CPUXAG2,CPUXAG3;
+
+static FixedOrder *FixedOrders;
+static InvOrder *JBitOrders;
+static FixedOrder *StackOrders;
+static RegOrder *RegOrders;
+static FixedOrder *RotateOrders;
+static InvOrder *RelOrders;
+
+static PInstTable InstTable;
+
+static LongInt Reg_DS;
+static SimpProc SaveInitProc;
+
+static ShortInt AdrMode;
+static Byte AdrPart,MemPart;
+static Byte AdrVals[4];
+static ShortInt OpSize;
+
+/*-------------------------------------------------------------------------*/
+/* Hilfsroutinen */
+
+ static void SetOpSize(ShortInt NSize)
+BEGIN
+ if (OpSize==-1) OpSize=NSize;
+ else if (OpSize!=NSize)
+ BEGIN
+ AdrMode=ModNone; AdrCnt=0; WrError(1131);
+ END
+END
+
+ static Boolean DecodeReg(char *Asc, ShortInt *NSize, Byte *Erg)
+BEGIN
+ if (strcasecmp(Asc,"SP")==0)
+ BEGIN
+ *Erg=7; *NSize=1; return True;
+ END
+ else if ((strlen(Asc)>=2) AND (toupper(*Asc)=='R') AND (Asc[1]>='0') AND (Asc[1]<='7'))
+ if (strlen(Asc)==2)
+ BEGIN
+ *Erg=Asc[1]-'0';
+ if (OpSize==2)
+ BEGIN
+ if ((*Erg&1)==1)
+ BEGIN
+ WrError(1760); (*Erg)--;
+ END
+ *NSize=2;
+ return True;
+ END
+ else
+ BEGIN
+ *NSize=1;
+ return True;
+ END
+ END
+ else if ((strlen(Asc)==3) AND (toupper(Asc[2])=='L'))
+ BEGIN
+ *Erg=(Asc[1]-'0') << 1; *NSize=0; return True;
+ END
+ else if ((strlen(Asc)==3) AND (toupper(Asc[2])=='H'))
+ BEGIN
+ *Erg=((Asc[1]-'0') << 1)+1; *NSize=0; return True;
+ END
+ else return False;
+ return False;
+END
+
+ static void ChkAdr(Word Mask)
+BEGIN
+ if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
+ BEGIN
+ WrError(1350); AdrMode=ModNone; AdrCnt=0;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Word Mask)
+BEGIN
+ ShortInt NSize;
+ LongInt DispAcc,DispPart,AdrLong;
+ Boolean FirstFlag,NegFlag,NextFlag,ErrFlag,OK;
+ char *PPos,*MPos;
+ Word AdrInt;
+ Byte Reg;
+ String Part;
+
+ AdrMode=ModNone; AdrCnt=0; KillBlanks(Asc);
+
+ if (DecodeReg(Asc,&NSize,&AdrPart))
+ BEGIN
+ if ((Mask & MModReg)!=0)
+ BEGIN
+ AdrMode=ModReg; SetOpSize(NSize);
+ END
+ else
+ BEGIN
+ AdrMode=ModMem; MemPart=1; SetOpSize(NSize);
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if (*Asc=='#')
+ BEGIN
+ switch (OpSize)
+ BEGIN
+ case -4:
+ AdrVals[0]=EvalIntExpression(Asc+1,UInt5,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrMode=ModImm;
+ END
+ break;
+ case -3:
+ AdrVals[0]=EvalIntExpression(Asc+1,SInt4,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrMode=ModImm;
+ END
+ break;
+ case -2:
+ AdrVals[0]=EvalIntExpression(Asc+1,UInt4,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrMode=ModImm;
+ END
+ break;
+ case -1:
+ WrError(1132);
+ break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrCnt=1; AdrMode=ModImm;
+ END
+ break;
+ case 1:
+ AdrInt=EvalIntExpression(Asc+1,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=Hi(AdrInt); AdrVals[1]=Lo(AdrInt);
+ AdrCnt=2; AdrMode=ModImm;
+ END
+ break;
+ case 2:
+ AdrLong=EvalIntExpression(Asc+1,Int32,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=(AdrLong >> 24) & 0xff;
+ AdrVals[1]=(AdrLong >> 16) & 0xff;
+ AdrVals[2]=(AdrLong >> 8) & 0xff;
+ AdrVals[3]=AdrLong & 0xff;
+ AdrCnt=4; AdrMode=ModImm;
+ END
+ break;
+ END
+ ChkAdr(Mask); return;
+ END
+
+ if ((*Asc=='[') AND (Asc[strlen(Asc)-1]==']'))
+ BEGIN
+ strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
+ if (Asc[strlen(Asc)-1]=='+')
+ BEGIN
+ Asc[strlen(Asc)-1]='\0';
+ if (NOT DecodeReg(Asc,&NSize,&AdrPart)) WrXError(1445,Asc);
+ else if (NSize!=1) WrError(1350);
+ else
+ BEGIN
+ AdrMode=ModMem; MemPart=3;
+ END
+ END
+ else
+ BEGIN
+ FirstFlag=False; ErrFlag=False;
+ DispAcc=0; AdrPart=0xff; NegFlag=False;
+ while ((*Asc!='\0') AND (NOT ErrFlag))
+ BEGIN
+ PPos=QuotPos(Asc,'+'); MPos=QuotPos(Asc,'-');
+ if (PPos==Nil) PPos=MPos;
+ else if ((MPos!=Nil) AND (PPos>MPos)) PPos=MPos;
+ NextFlag=((PPos!=Nil) AND (*PPos=='-'));
+ if (PPos==Nil)
+ BEGIN
+ strmaxcpy(Part,Asc,255); *Asc='\0';
+ END
+ else
+ BEGIN
+ *PPos='\0'; strmaxcpy(Part,Asc,255); strcpy(Asc,PPos+1);
+ END
+ if (DecodeReg(Part,&NSize,&Reg))
+ if ((NSize!=1) OR (AdrPart!=0xff) OR (NegFlag))
+ BEGIN
+ WrError(1350); ErrFlag=True;
+ END
+ else AdrPart=Reg;
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ DispPart=EvalIntExpression(Part,Int32,&ErrFlag);
+ ErrFlag=NOT ErrFlag;
+ if (NOT ErrFlag)
+ BEGIN
+ FirstFlag=FirstFlag OR FirstPassUnknown;
+ if (NegFlag) DispAcc-=DispPart;
+ else DispAcc+=DispPart;
+ END
+ END
+ NegFlag=NextFlag;
+ END
+ if (FirstFlag) DispAcc&=0x7fff;
+ if (AdrPart==0xff) WrError(1350);
+ else if (DispAcc==0)
+ BEGIN
+ AdrMode=ModMem; MemPart=2;
+ END
+ else if ((DispAcc>=-128) AND (DispAcc<127))
+ BEGIN
+ AdrMode=ModMem; MemPart=4;
+ AdrVals[0]=DispAcc & 0xff; AdrCnt=1;
+ END
+ else if (ChkRange(DispAcc,-0x8000l,0x7fffl))
+ BEGIN
+ AdrMode=ModMem; MemPart=5;
+ AdrVals[0]=(DispAcc >> 8) & 0xff;
+ AdrVals[1]=DispAcc & 0xff;
+ AdrCnt=2;
+ END
+ END
+ ChkAdr(Mask); return;
+ END
+
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(Asc,UInt24,&OK);
+ if (OK)
+ BEGIN
+ if (FirstPassUnknown)
+ BEGIN
+ if ((Mask & MModAbs)==0) AdrLong&=0x3ff;
+ END
+ if ((AdrLong & 0xffff)>0x7ff) WrError(1925);
+ else if ((AdrLong & 0xffff)<=0x3ff)
+ BEGIN
+ if ((AdrLong >> 16)!=Reg_DS) WrError(110);
+ ChkSpace(SegData);
+ AdrMode=ModMem; MemPart=6;
+ AdrPart=Hi(AdrLong); AdrVals[0]=Lo(AdrLong);
+ AdrCnt=1;
+ END
+ else if (AdrLong>0x7ff) WrError(1925);
+ else
+ BEGIN
+ ChkSpace(SegIO);
+ AdrMode=ModMem; MemPart=6;
+ AdrPart=Hi(AdrLong); AdrVals[0]=Lo(AdrLong);
+ AdrCnt=1;
+ END
+ END
+
+ ChkAdr(Mask);
+END
+
+ static Boolean DecodeBitAddr(char *Asc, LongInt *Erg)
+BEGIN
+ char *p;
+ Byte BPos,Reg;
+ ShortInt Size,Res;
+ LongInt AdrLong;
+ Boolean OK;
+
+ p=RQuotPos(Asc,'.'); Res=0;
+ if (p==Nil)
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(Asc,UInt24,&OK);
+ if (FirstPassUnknown) AdrLong&=0x3ff;
+ *Erg=AdrLong; Res=1;
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False; *p='\0';
+ BPos=EvalIntExpression(p+1,UInt4,&OK);
+ if (FirstPassUnknown) BPos&=7;
+ if (OK)
+ BEGIN
+ if (DecodeReg(Asc,&Size,&Reg))
+ if ((Size==0) AND (BPos>7)) WrError(1320);
+ else
+ BEGIN
+ if (Size==0) *Erg=(Reg << 3)+BPos;
+ else *Erg=(Reg << 4)+BPos;
+ Res=1;
+ END
+ else if (BPos>7) WrError(1320);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(Asc,UInt24,&OK);
+ if ((TypeFlag & (1 << SegIO))!=0)
+ BEGIN
+ ChkSpace(SegIO);
+ if (FirstPassUnknown) AdrLong=(AdrLong & 0x3f) | 0x400;
+ if (ChkRange(AdrLong,0x400,0x43f))
+ BEGIN
+ *Erg=0x200+((AdrLong & 0x3f) << 3)+BPos;
+ Res=1;
+ END
+ else Res=(-1);
+ END
+ else
+ BEGIN
+ ChkSpace(SegData);
+ if (FirstPassUnknown) AdrLong=(AdrLong & 0x00ff003f) | 0x20;
+ if (ChkRange(AdrLong & 0xff,0x20,0x3f))
+ BEGIN
+ *Erg=0x100+((AdrLong & 0x1f) << 3)+BPos+(AdrLong & 0xff0000);
+ Res=1;
+ END
+ else Res=(-1);
+ END
+ END
+ END
+ *p='.';
+ END
+ if (Res==0) WrError(1350);
+ return (Res==1);
+END
+
+ static void ChkBitPage(LongInt Adr)
+BEGIN
+ if ((Adr >> 16)!=Reg_DS) WrError(110);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Befehlsdekoder */
+
+ static Boolean DecodePseudo(void)
+BEGIN
+#define ASSUMEXACount 1
+static ASSUMERec ASSUMEXAs[ASSUMEXACount]=
+ {{"DS", &Reg_DS, 0, 0xff, 0x100}};
+ LongInt BAdr;
+
+ if (Memo("PORT"))
+ BEGIN
+ CodeEquate(SegIO,0x400,0x7ff);
+ return True;
+ END
+
+ if (Memo("BIT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (DecodeBitAddr(ArgStr[1],&BAdr))
+ BEGIN
+ EnterIntSymbol(LabPart,BAdr,SegNone,False);
+ switch ((BAdr & 0x3ff) >> 8)
+ BEGIN
+ case 0:
+ sprintf(ListLine,"=R%d.%d", (int)((BAdr >> 4) & 15),
+ (int) (BAdr & 15));
+ break;
+ case 1:
+ sprintf(ListLine,"=%x:%x.%d",(int)((BAdr >> 16) & 255),
+ (int)((BAdr & 0x1f8) >> 3), (int)(BAdr & 7));
+ break;
+ default:
+ sprintf(ListLine, "=S:%x.%d", (int)(((BAdr >> 3) & 0x3f)+0x400),
+ (int)(BAdr & 7));
+ break;
+ END
+ END
+ return True;
+ END
+
+ if (Memo("ASSUME"))
+ BEGIN
+ CodeASSUME(ASSUMEXAs,ASSUMEXACount);
+ return True;
+ END
+
+ return False;
+END
+
+ static void DecodeFixed(Word Index)
+BEGIN
+ FixedOrder *Op=FixedOrders+Index;
+
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ if (Hi(Op->Code)!=0) BAsmCode[CodeLen++]=Hi(Op->Code);
+ BAsmCode[CodeLen++]=Lo(Op->Code);
+ if ((Memo("RETI")) AND (NOT SupAllowed)) WrError(50);
+ END
+END
+
+ static void DecodeStack(Word Index)
+BEGIN
+ FixedOrder *Op=StackOrders+Index;
+ Byte HReg;
+ Boolean OK;
+ Word Mask;
+ int i;
+
+ if (ArgCnt<1) WrError(1110);
+ else
+ BEGIN
+ HReg=0xff; OK=True; Mask=0;
+ for (i=1; i<=ArgCnt; i++)
+ if (OK)
+ BEGIN
+ DecodeAdr(ArgStr[i],MModMem);
+ if (AdrMode==ModNone) OK=False;
+ else switch (MemPart)
+ BEGIN
+ case 1:
+ if (HReg==0)
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else
+ BEGIN
+ HReg=1; Mask|=(1 << AdrPart);
+ END
+ break;
+ case 6:
+ if (HReg!=0xff)
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else HReg=0;
+ break;
+ default:
+ WrError(1350); OK=False;
+ END
+ END
+ if (OK)
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else if (HReg==0)
+ BEGIN
+ BAsmCode[CodeLen++]=0x87+(OpSize << 3);
+ BAsmCode[CodeLen++]=Hi(Op->Code)+AdrPart;
+ BAsmCode[CodeLen++]=AdrVals[0];
+ END
+ else if (Index<2) /* POP: obere Register zuerst */
+ BEGIN
+ if (Hi(Mask)!=0)
+ BEGIN
+ BAsmCode[CodeLen++]=Lo(Op->Code)+(OpSize << 3)+0x40;
+ BAsmCode[CodeLen++]=Hi(Mask);
+ END
+ if (Lo(Mask)!=0)
+ BEGIN
+ BAsmCode[CodeLen++]=Lo(Op->Code)+(OpSize << 3);
+ BAsmCode[CodeLen++]=Lo(Mask);
+ END
+ if ((OpSize==1) AND (Memo("POP")) AND ((Mask & 0x80)!=0)) WrError(140);
+ END
+ else /* PUSH: untere Register zuerst */
+ BEGIN
+ if (Lo(Mask)!=0)
+ BEGIN
+ BAsmCode[CodeLen++]=Lo(Op->Code)+(OpSize << 3);
+ BAsmCode[CodeLen++]=Lo(Mask);
+ END
+ if (Hi(Mask)!=0)
+ BEGIN
+ BAsmCode[CodeLen++]=Lo(Op->Code)+(OpSize << 3)+0x40;
+ BAsmCode[CodeLen++]=Hi(Mask);
+ END
+ END
+ END
+END
+
+ static void DecodeALU(Word Index)
+BEGIN
+ Byte HReg,HCnt,HVals[3],HMem;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModMem);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize>=2) WrError(1130);
+ else if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModMem+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModMem:
+ BAsmCode[CodeLen++]=(Index << 4)+(OpSize << 3)+MemPart;
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ if ((MemPart==3) AND ((HReg >> (1-OpSize))==AdrPart)) WrError(140);
+ break;
+ case ModImm:
+ BAsmCode[CodeLen++]=0x91+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+Index;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ END
+ END
+ break;
+ case ModMem:
+ HReg=AdrPart; HMem=MemPart; HCnt=AdrCnt;
+ memcpy(HVals,AdrVals,AdrCnt);
+ DecodeAdr(ArgStr[2],MModReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize==2) WrError(1130);
+ else if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=(Index << 4)+(OpSize << 3)+HMem;
+ BAsmCode[CodeLen++]=(AdrPart << 4)+8+HReg;
+ memcpy(BAsmCode+CodeLen,HVals,HCnt);
+ CodeLen+=HCnt;
+ if ((HMem==3) AND ((AdrPart >> (1-OpSize))==HReg)) WrError(140);
+ END
+ break;
+ case ModImm:
+ if (OpSize==2) WrError(1130);
+ else if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x90+HMem+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+Index;
+ memcpy(BAsmCode+CodeLen,HVals,HCnt);
+ memcpy(BAsmCode+CodeLen+HCnt,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt+HCnt;
+ END
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeRegO(Word Index)
+BEGIN
+ RegOrder *Op=RegOrders+Index;
+
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((Op->SizeMask & (1 << OpSize))==0) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x90+(OpSize << 3);
+ BAsmCode[CodeLen++]=(AdrPart << 4)+Op->Code;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeShift(Word Index)
+BEGIN
+ Byte HReg,HMem;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (OpSize>2) WrError(1130);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ HReg=AdrPart; HMem=OpSize;
+ if (*ArgStr[2]=='#') OpSize=(HMem==2)?-4:-2;
+ else OpSize=0;
+ DecodeAdr(ArgStr[2],MModReg+((Index==3)?0:MModImm));
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ BAsmCode[CodeLen++]=0xc0+((HMem & 1) << 3)+Index;
+ if (HMem==2) BAsmCode[CodeLen-1]+=12;
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ if (Memo("NORM"))
+ if (HMem==2)
+ BEGIN
+ if ((AdrPart >> 2)==(HReg >> 1)) WrError(140);
+ END
+ else if ((AdrPart >> HMem)==HReg) WrError(140);
+ break;
+ case ModImm:
+ BAsmCode[CodeLen++]=0xd0+((HMem & 1) << 3)+Index;
+ if (HMem==2)
+ BEGIN
+ BAsmCode[CodeLen-1]+=12;
+ BAsmCode[CodeLen++]=((HReg & 14) << 4)+AdrVals[0];
+ END
+ else BAsmCode[CodeLen++]=(HReg << 4)+AdrVals[0];
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeRotate(Word Index)
+BEGIN
+ FixedOrder *Op=RotateOrders+Index;
+ Byte HReg,HMem;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if (OpSize==2) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart; HMem=OpSize; OpSize=(-2);
+ DecodeAdr(ArgStr[2],MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[CodeLen++]=Op->Code+(HMem << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrVals[0];
+ break;
+ END
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeRel(Word Index)
+BEGIN
+ InvOrder *Op=RelOrders+Index;
+ Boolean OK;
+ LongInt SaveLong,AdrLong;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ FirstPassUnknown=True;
+ AdrLong=SaveLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+#ifdef __STDC__
+ if (FirstPassUnknown) AdrLong&=0xfffffffeu;
+#else
+ if (FirstPassUnknown) AdrLong&=0xfffffffe;
+#endif
+ AdrLong-=(EProgCounter()+CodeLen+2) & 0xfffffe;
+ if ((AdrLong&1)==1) WrError(1325);
+ else if ((SymbolQuestionable) OR ((AdrLong<=254) AND (AdrLong>=-256)))
+ BEGIN
+ BAsmCode[CodeLen++]=Op->Code;
+ BAsmCode[CodeLen++]=(AdrLong >> 1) & 0xff;
+ END
+ else if (NOT DoBranchExt) WrError(1370);
+ else if (Op->Inversion==255) /* BR */
+ BEGIN
+ AdrLong=SaveLong-((EProgCounter()+CodeLen+3) & 0xfffffe);
+ if ((NOT SymbolQuestionable) AND ((AdrLong>65534) OR (AdrLong<-65536))) WrError(1370);
+ else if ((AdrLong&1)==1) WrError(1325);
+ else
+ BEGIN
+ AdrLong>>=1;
+ BAsmCode[CodeLen++]=0xd5;
+ BAsmCode[CodeLen++]=(AdrLong >> 8) & 0xff;
+ BAsmCode[CodeLen++]=AdrLong & 0xff;
+ END
+ END
+ else
+ BEGIN
+ AdrLong=SaveLong-((EProgCounter()+CodeLen+5) & 0xfffffe);
+ if ((AdrLong>65534) OR (AdrLong<-65536)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=RelOrders[Op->Inversion].Code;
+ BAsmCode[CodeLen++]=2;
+ BAsmCode[CodeLen++]=0xd5;
+ BAsmCode[CodeLen++]=(AdrLong>>9)&0xff;
+ BAsmCode[CodeLen++]=(AdrLong>>1)&0xff;
+ if (Odd(EProgCounter()+CodeLen)) BAsmCode[CodeLen++]=0;
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeJBit(Word Index)
+BEGIN
+ LongInt BitAdr,AdrLong,SaveLong,odd;
+ Boolean OK;
+ InvOrder *Op=JBitOrders+Index;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (DecodeBitAddr(ArgStr[1],&BitAdr))
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=SaveLong=EvalIntExpression(ArgStr[2],UInt24,&OK);
+ if (OK)
+ BEGIN
+#ifdef __STDC__
+ if (FirstPassUnknown) AdrLong&=0xfffffffeu;
+#else
+ if (FirstPassUnknown) AdrLong&=0xfffffffe;
+#endif
+ AdrLong-=(EProgCounter()+CodeLen+4) & 0xfffffe;
+ if ((AdrLong&1)==1) WrError(1325);
+ else if ((SymbolQuestionable) OR ((AdrLong<=254) AND (AdrLong>=-256)))
+ BEGIN
+ BAsmCode[CodeLen++]=0x97;
+ BAsmCode[CodeLen++]=Op->Code+Hi(BitAdr);
+ BAsmCode[CodeLen++]=Lo(BitAdr);
+ BAsmCode[CodeLen++]=(AdrLong >> 1) & 0xff;
+ END
+ else if (NOT DoBranchExt) WrError(1370);
+ else if (Op->Inversion==255)
+ BEGIN
+ odd=EProgCounter()&1;
+ AdrLong=SaveLong-((EProgCounter()+CodeLen+9+odd) & 0xfffffe);
+ if ((AdrLong>65534) OR (AdrLong<-65536)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x97;
+ BAsmCode[CodeLen++]=Op->Code+Hi(BitAdr);
+ BAsmCode[CodeLen++]=Lo(BitAdr);
+ BAsmCode[CodeLen++]=1+odd;
+ BAsmCode[CodeLen++]=0xfe;
+ BAsmCode[CodeLen++]=2+odd;
+ if (odd) BAsmCode[CodeLen++]=0;
+ BAsmCode[CodeLen++]=0xd5;
+ BAsmCode[CodeLen++]=(AdrLong>>9)&0xff;
+ BAsmCode[CodeLen++]=(AdrLong>>1)&0xff;
+ BAsmCode[CodeLen++]=0;
+ END
+ END
+ else
+ BEGIN
+ AdrLong=SaveLong-((EProgCounter()+CodeLen+7) & 0xfffffe);
+ if ((AdrLong>65534) OR (AdrLong<-65536)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x97;
+ BAsmCode[CodeLen++]=JBitOrders[Op->Inversion].Code+Hi(BitAdr);
+ BAsmCode[CodeLen++]=Lo(BitAdr);
+ BAsmCode[CodeLen++]=2;
+ BAsmCode[CodeLen++]=0xd5;
+ BAsmCode[CodeLen++]=(AdrLong>>9)&0xff;
+ BAsmCode[CodeLen++]=(AdrLong>>1)&0xff;
+ if (Odd(EProgCounter()+CodeLen)) BAsmCode[CodeLen++]=0;
+ END
+ END
+ END
+ END
+END
+
+
+ static void DecodeMOV(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Byte HVals[3],HReg,HPart,HCnt;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"C")==0)
+ BEGIN
+ if (DecodeBitAddr(ArgStr[2],&AdrLong))
+ if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ ChkBitPage(AdrLong);
+ BAsmCode[CodeLen++]=0x08;
+ BAsmCode[CodeLen++]=0x20+Hi(AdrLong);
+ BAsmCode[CodeLen++]=Lo(AdrLong);
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"C")==0)
+ BEGIN
+ if (DecodeBitAddr(ArgStr[1],&AdrLong))
+ if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ ChkBitPage(AdrLong);
+ BAsmCode[CodeLen++]=0x08;
+ BAsmCode[CodeLen++]=0x30+Hi(AdrLong);
+ BAsmCode[CodeLen++]=Lo(AdrLong);
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"USP")==0)
+ BEGIN
+ SetOpSize(1);
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode==ModReg)
+ BEGIN
+ BAsmCode[CodeLen++]=0x98;
+ BAsmCode[CodeLen++]=(AdrPart << 4)+0x0f;
+ END
+ END
+ else if (strcasecmp(ArgStr[2],"USP")==0)
+ BEGIN
+ SetOpSize(1);
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode==ModReg)
+ BEGIN
+ BAsmCode[CodeLen++]=0x90;
+ BAsmCode[CodeLen++]=(AdrPart << 4)+0x0f;
+ END
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModMem);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModMem+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModMem:
+ BAsmCode[CodeLen++]=0x80+(OpSize << 3)+MemPart;
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ if ((MemPart==3) AND ((HReg >> (1-OpSize))==AdrPart)) WrError(140);
+ break;
+ case ModImm:
+ BAsmCode[CodeLen++]=0x91+(OpSize << 3);
+ BAsmCode[CodeLen++]=0x08+(HReg << 4);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ END
+ END
+ break;
+ case ModMem:
+ memcpy(HVals,AdrVals,AdrCnt); HCnt=AdrCnt; HPart=MemPart; HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg+MModMem+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x80+(OpSize << 3)+HPart;
+ BAsmCode[CodeLen++]=(AdrPart << 4)+0x08+HReg;
+ memcpy(BAsmCode+CodeLen,HVals,HCnt);
+ CodeLen+=HCnt;
+ if ((HPart==3) AND ((AdrPart >> (1-OpSize))==HReg)) WrError(140);
+ END
+ break;
+ case ModMem:
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else if ((HPart==6) AND (MemPart==6))
+ BEGIN
+ BAsmCode[CodeLen++]=0x97+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ BAsmCode[CodeLen++]=HVals[0];
+ BAsmCode[CodeLen++]=AdrVals[0];
+ END
+ else if ((HPart==6) AND (MemPart==2))
+ BEGIN
+ BAsmCode[CodeLen++]=0xa0+(OpSize << 3);
+ BAsmCode[CodeLen++]=0x80+(AdrPart << 4)+HReg;
+ BAsmCode[CodeLen++]=HVals[0];
+ END
+ else if ((HPart==2) AND (MemPart==6))
+ BEGIN
+ BAsmCode[CodeLen++]=0xa0+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ BAsmCode[CodeLen++]=AdrVals[0];
+ END
+ else if ((HPart==3) AND (MemPart==3))
+ BEGIN
+ BAsmCode[CodeLen++]=0x90+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ if (HReg==AdrPart) WrError(140);
+ END
+ else WrError(1350);
+ break;
+ case ModImm:
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x90+(OpSize << 3)+HPart;
+ BAsmCode[CodeLen++]=0x08+(HReg << 4);
+ memcpy(BAsmCode+CodeLen,HVals,HCnt);
+ memcpy(BAsmCode+CodeLen+HCnt,AdrVals,AdrCnt);
+ CodeLen+=HCnt+AdrCnt;
+ END
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeMOVC(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if ((*AttrPart=='\0') AND (strcasecmp(ArgStr[1],"A")==0)) OpSize=0;
+ if (strcasecmp(ArgStr[2],"[A+DPTR]")==0)
+ if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x90;
+ BAsmCode[CodeLen++]=0x4e;
+ END
+ else if (strcasecmp(ArgStr[2],"[A+PC]")==0)
+ if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else if (OpSize!=0) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x90;
+ BAsmCode[CodeLen++]=0x4c;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode!=ModNone)
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModMem);
+ if (AdrMode!=ModNone)
+ if (MemPart!=3) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x80+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ if ((MemPart==3) AND ((HReg >> (1-OpSize))==AdrPart)) WrError(140);
+ END
+ END
+ END
+ END
+END
+
+ static void DecodeMOVX(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMem);
+ if (AdrMode==ModMem)
+ switch (MemPart)
+ BEGIN
+ case 1:
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart; DecodeAdr(ArgStr[2],MModMem);
+ if (AdrMode==ModMem)
+ if (MemPart!=2) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0xa7+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ END
+ END
+ break;
+ case 2:
+ HReg=AdrPart; DecodeAdr(ArgStr[2],MModReg);
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0xa7+(OpSize << 3);
+ BAsmCode[CodeLen++]=0x08+(AdrPart << 4)+HReg;
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+END
+
+ static void DecodeXCH(Word Index)
+BEGIN
+ Byte HReg,HPart,HVals[3];
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMem);
+ if (AdrMode==ModMem)
+ switch (MemPart)
+ BEGIN
+ case 1:
+ HReg=AdrPart; DecodeAdr(ArgStr[2],MModMem);
+ if (AdrMode==ModMem)
+ if ((OpSize!=1) AND (OpSize!=0)) WrError(1130);
+ else switch (MemPart)
+ BEGIN
+ case 1:
+ BAsmCode[CodeLen++]=0x60+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ if (HReg==AdrPart) WrError(140);
+ break;
+ case 2:
+ BAsmCode[CodeLen++]=0x50+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ break;
+ case 6:
+ BAsmCode[CodeLen++]=0xa0+(OpSize << 3);
+ BAsmCode[CodeLen++]=0x08+(HReg << 4)+AdrPart;
+ BAsmCode[CodeLen++]=AdrVals[0];
+ break;
+ default:
+ WrError(1350);
+ END
+ break;
+ case 2:
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode==ModReg)
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0x50+(OpSize << 3);
+ BAsmCode[CodeLen++]=(AdrPart << 4)+HReg;
+ END
+ break;
+ case 6:
+ HPart=AdrPart; HVals[0]=AdrVals[0];
+ DecodeAdr(ArgStr[2],MModReg);
+ if (AdrMode==ModReg)
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0xa0+(OpSize << 3);
+ BAsmCode[CodeLen++]=0x08+(AdrPart << 4)+HPart;
+ BAsmCode[CodeLen++]=HVals[0];
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+END
+
+ static void DecodeADDSMOVS(Word Index)
+BEGIN
+ Byte HReg,HMem;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ HMem=OpSize; OpSize=(-3);
+ DecodeAdr(ArgStr[2],MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ HReg=AdrVals[0]; OpSize=HMem;
+ DecodeAdr(ArgStr[1],MModMem);
+ switch (AdrMode)
+ BEGIN
+ case ModMem:
+ if (OpSize==2) WrError(1130);
+ else if (OpSize==-1) WrError(1132);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0xa0+(Index << 4)+(OpSize << 3)+MemPart;
+ BAsmCode[CodeLen++]=(AdrPart << 4)+(HReg & 0x0f);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ END
+ break;
+ END
+ break;
+ END
+ END
+END
+
+ static void DecodeDIV(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode==ModReg)
+ if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart; OpSize--; DecodeAdr(ArgStr[2],MModReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ BAsmCode[CodeLen++]=0xe7+(OpSize << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ break;
+ case ModImm:
+ BAsmCode[CodeLen++]=0xe8+OpSize;
+ BAsmCode[CodeLen++]=(HReg << 4)+0x0b-(OpSize << 1);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeDIVU(Word Index)
+BEGIN
+ Byte HReg;
+ int z;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode==ModReg)
+ if ((OpSize==0) AND ((AdrPart&1)==1)) WrError(1445);
+ else
+ BEGIN
+ HReg=AdrPart; z=OpSize; if (OpSize!=0) OpSize--;
+ DecodeAdr(ArgStr[2],MModReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ BAsmCode[CodeLen++]=0xe1+(z << 2);
+ if (z==2) BAsmCode[CodeLen-1]+=4;
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ break;
+ case ModImm:
+ BAsmCode[CodeLen++]=0xe8+Ord(z==2);
+ BAsmCode[CodeLen++]=(HReg << 4)+0x01+(Ord(z==1) << 1);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeMUL(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode==ModReg)
+ if (OpSize!=1) WrError(1130);
+ else if ((AdrPart&1)==1) WrError(1445);
+ else
+ BEGIN
+ HReg=AdrPart; DecodeAdr(ArgStr[2],MModReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ BAsmCode[CodeLen++]=0xe6;
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ break;
+ case ModImm:
+ BAsmCode[CodeLen++]=0xe9;
+ BAsmCode[CodeLen++]=(HReg << 4)+0x08;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeMULU(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode==ModReg)
+ if ((AdrPart&1)==1) WrError(1445);
+ else
+ BEGIN
+ HReg=AdrPart;
+ DecodeAdr(ArgStr[2],MModReg+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModReg:
+ BAsmCode[CodeLen++]=0xe0+(OpSize << 2);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ break;
+ case ModImm:
+ BAsmCode[CodeLen++]=0xe8+OpSize;
+ BAsmCode[CodeLen++]=(HReg << 4);
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ END
+ END
+ END
+END
+
+ static void DecodeLEA(Word Index)
+BEGIN
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg);
+ if (AdrMode==ModReg)
+ if (OpSize!=1) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart;
+ strmaxprep(ArgStr[2],"[",255); strmaxcat(ArgStr[2],"]",255);
+ DecodeAdr(ArgStr[2],MModMem);
+ if (AdrMode==ModMem)
+ switch (MemPart)
+ BEGIN
+ case 4:
+ case 5:
+ BAsmCode[CodeLen++]=0x20+(MemPart << 3);
+ BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
+ memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
+ CodeLen+=AdrCnt;
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ END
+END
+
+ static void DecodeANLORL(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ if (ArgCnt!=2) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcasecmp(ArgStr[1],"C")!=0) WrError(1350);
+ else
+ BEGIN
+ if (*ArgStr[2]=='/')
+ BEGIN
+ OK=True; strcpy(ArgStr[2],ArgStr[2]+1);
+ END
+ else OK=False;
+ if (DecodeBitAddr(ArgStr[2],&AdrLong))
+ BEGIN
+ ChkBitPage(AdrLong);
+ BAsmCode[CodeLen++]=0x08;
+ BAsmCode[CodeLen++]=0x40+(Index << 5)+(Ord(OK) << 4)+(Hi(AdrLong) & 3);
+ BAsmCode[CodeLen++]=Lo(AdrLong);
+ END
+ END
+END
+
+ static void DecodeCLRSETB(Word Index)
+BEGIN
+ LongInt AdrLong;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (DecodeBitAddr(ArgStr[1],&AdrLong))
+ BEGIN
+ ChkBitPage(AdrLong);
+ BAsmCode[CodeLen++]=0x08;
+ BAsmCode[CodeLen++]=(Index << 4)+(Hi(AdrLong) & 3);
+ BAsmCode[CodeLen++]=Lo(AdrLong);
+ END
+END
+
+ static void DecodeTRAP(Word Index)
+BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ OpSize=(-2);
+ DecodeAdr(ArgStr[1],MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[CodeLen++]=0xd6;
+ BAsmCode[CodeLen++]=0x30+AdrVals[0];
+ break;
+ END
+ END
+END
+
+ static void DecodeCALL(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (*ArgStr[1]=='[')
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMem);
+ if (AdrMode!=ModNone)
+ if (MemPart!=2) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0xc6;
+ BAsmCode[CodeLen++]=AdrPart;
+ END
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+#ifdef __STDC__
+ if (FirstPassUnknown) AdrLong&=0xfffffffeu;
+#else
+ if (FirstPassUnknown) AdrLong&=0xfffffffe;
+#endif
+ AdrLong-=(EProgCounter()+CodeLen+3) & 0xfffffe;
+ if ((NOT SymbolQuestionable) AND ((AdrLong>65534) OR (AdrLong<-65536))) WrError(1370);
+ else if ((AdrLong&1)==1) WrError(1325);
+ else
+ BEGIN
+ AdrLong>>=1;
+ BAsmCode[CodeLen++]=0xc5;
+ BAsmCode[CodeLen++]=(AdrLong >> 8) & 0xff;
+ BAsmCode[CodeLen++]=AdrLong & 0xff;
+ END
+ END
+ END
+END
+
+ static void DecodeJMP(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else if (strcasecmp(ArgStr[1],"[A+DPTR]")==0)
+ BEGIN
+ BAsmCode[CodeLen++]=0xd6;
+ BAsmCode[CodeLen++]=0x46;
+ END
+ else if (strncmp(ArgStr[1],"[[",2)==0)
+ BEGIN
+ ArgStr[1][strlen(ArgStr[1])-1]='\0';
+ DecodeAdr(ArgStr[1]+1,MModMem);
+ if (AdrMode==ModMem)
+ switch (MemPart)
+ BEGIN
+ case 3:
+ BAsmCode[CodeLen++]=0xd6;
+ BAsmCode[CodeLen++]=0x60+AdrPart;
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ else if (*ArgStr[1]=='[')
+ BEGIN
+ DecodeAdr(ArgStr[1],MModMem);
+ if (AdrMode==ModMem)
+ switch (MemPart)
+ BEGIN
+ case 2:
+ BAsmCode[CodeLen++]=0xd6;
+ BAsmCode[CodeLen++]=0x70+AdrPart;
+ break;
+ default:
+ WrError(1350);
+ END
+ END
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+#ifdef __STDC__
+ if (FirstPassUnknown) AdrLong&=0xfffffffeu;
+#else
+ if (FirstPassUnknown) AdrLong&=0xfffffffe;
+#endif
+ AdrLong-=((EProgCounter()+CodeLen+3) & 0xfffffe);
+ if ((NOT SymbolQuestionable) AND ((AdrLong>65534) OR (AdrLong<-65536))) WrError(1370);
+ else if ((AdrLong&1)==1) WrError(1325);
+ else
+ BEGIN
+ AdrLong>>=1;
+ BAsmCode[CodeLen++]=0xd5;
+ BAsmCode[CodeLen++]=(AdrLong >> 8) & 0xff;
+ BAsmCode[CodeLen++]=AdrLong & 0xff;
+ END
+ END
+ END
+END
+
+ static void DecodeCJNE(Word Index)
+BEGIN
+ LongInt AdrLong,SaveLong,odd;
+ Boolean OK;
+ Byte HReg;
+
+ if (ArgCnt!=3) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=SaveLong=EvalIntExpression(ArgStr[3],UInt24,&OK);
+ if (FirstPassUnknown) AdrLong&=0xfffffe;
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode); OK=False; HReg=0;
+ DecodeAdr(ArgStr[1],MModMem);
+ if (AdrMode==ModMem)
+ switch (MemPart)
+ BEGIN
+ case 1:
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart; DecodeAdr(ArgStr[2],MModMem+MModImm);
+ switch (AdrMode)
+ BEGIN
+ case ModMem:
+ if (MemPart!=6) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xe2+(OpSize << 3);
+ BAsmCode[CodeLen+1]=(HReg << 4)+AdrPart;
+ BAsmCode[CodeLen+2]=AdrVals[0];
+ HReg=CodeLen+3;
+ CodeLen+=4; OK=True;
+ END
+ break;
+ case ModImm:
+ BAsmCode[CodeLen]=0xe3+(OpSize << 3);
+ BAsmCode[CodeLen+1]=HReg << 4;
+ HReg=CodeLen+2;
+ memcpy(BAsmCode+CodeLen+3,AdrVals,AdrCnt);
+ CodeLen+=3+AdrCnt; OK=True;
+ break;
+ END
+ END
+ break;
+ case 2:
+ if ((OpSize!=-1) AND (OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ HReg=AdrPart; DecodeAdr(ArgStr[2],MModImm);
+ if (AdrMode==ModImm)
+ BEGIN
+ BAsmCode[CodeLen]=0xe3+(OpSize << 3);
+ BAsmCode[CodeLen+1]=(HReg << 4)+8;
+ HReg=CodeLen+2;
+ memcpy(BAsmCode+CodeLen+3,AdrVals,AdrCnt);
+ CodeLen+=3+AdrCnt; OK=True;
+ END
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ if (OK)
+ BEGIN
+ AdrLong-=(EProgCounter()+CodeLen) & 0xfffffe; OK=False;
+ if ((AdrLong&1)==1) WrError(1325);
+ else if ((SymbolQuestionable) OR ((AdrLong<=254) AND (AdrLong>=-256)))
+ BEGIN
+ BAsmCode[HReg]=(AdrLong >> 1) & 0xff; OK=True;
+ END
+ else if (NOT DoBranchExt) WrError(1370);
+ else
+ BEGIN
+ odd=(EProgCounter()+CodeLen) & 1;
+ AdrLong=SaveLong-((EProgCounter()+CodeLen+5+odd)&0xfffffe);
+ if ((AdrLong<-65536) OR (AdrLong>65534)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[HReg]=1+odd;
+ BAsmCode[CodeLen++]=0xfe;
+ BAsmCode[CodeLen++]=2+odd;
+ if (odd) BAsmCode[CodeLen++]=0;
+ BAsmCode[CodeLen++]=0xd5;
+ BAsmCode[CodeLen++]=(AdrLong >> 9) & 0xff;
+ BAsmCode[CodeLen++]=(AdrLong >> 1) & 0xff;
+ BAsmCode[CodeLen++]=0;
+ OK=True;
+ END
+ END
+ END
+ if (NOT OK) CodeLen=0;
+ END
+ END
+END
+
+ static void DecodeDJNZ(Word Index)
+BEGIN
+ LongInt AdrLong,SaveLong,odd;
+ Boolean OK;
+ Byte HReg;
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ SaveLong=AdrLong=EvalIntExpression(ArgStr[2],UInt24,&OK);
+ if (FirstPassUnknown) AdrLong&=0xfffffe;
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode); HReg=0;
+ DecodeAdr(ArgStr[1],MModMem);
+ OK=False; DecodeAdr(ArgStr[1],MModMem);
+ if (AdrMode==ModMem)
+ switch (MemPart)
+ BEGIN
+ case 1:
+ if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0x87+(OpSize << 3);
+ BAsmCode[CodeLen+1]=(AdrPart << 4)+0x08;
+ HReg=CodeLen+2;
+ CodeLen+=3; OK=True;
+ END
+ break;
+ case 6:
+ if (OpSize==-1) WrError(1132);
+ else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xe2+(OpSize << 3);
+ BAsmCode[CodeLen+1]=0x08+AdrPart;
+ BAsmCode[CodeLen+2]=AdrVals[0];
+ HReg=CodeLen+3;
+ CodeLen+=4; OK=True;
+ END
+ break;
+ default:
+ WrError(1350);
+ END
+ if (OK)
+ BEGIN
+ AdrLong-=(EProgCounter()+CodeLen) & 0xfffffe; OK=False;
+ if ((AdrLong&1)==1) WrError(1325);
+ else if ((SymbolQuestionable) OR ((AdrLong<=254) AND (AdrLong>=-256)))
+ BEGIN
+ BAsmCode[HReg]=(AdrLong >> 1) & 0xff; OK=True;
+ END
+ else if (NOT DoBranchExt) WrError(1370);
+ else
+ BEGIN
+ odd=(EProgCounter()+CodeLen) & 1;
+ AdrLong=SaveLong-((EProgCounter()+CodeLen+5+odd)&0xfffffe);
+ if ((AdrLong<-65536) OR (AdrLong>65534)) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[HReg]=1+odd;
+ BAsmCode[CodeLen++]=0xfe;
+ BAsmCode[CodeLen++]=2+odd;
+ if (odd) BAsmCode[CodeLen++]=0;
+ BAsmCode[CodeLen++]=0xd5;
+ BAsmCode[CodeLen++]=(AdrLong >> 9) & 0xff;
+ BAsmCode[CodeLen++]=(AdrLong >> 1) & 0xff;
+ BAsmCode[CodeLen++]=0;
+ OK=True;
+ END
+ END
+ END
+ if (NOT OK) CodeLen=0;
+ END
+ END
+END
+
+ static void DecodeFCALLJMP(Word Index)
+BEGIN
+ LongInt AdrLong;
+ Boolean OK;
+
+ if (ArgCnt!=1) WrError(1110);
+ else if (*AttrPart!='\0') WrError(1100);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
+ if (FirstPassUnknown) AdrLong&=0xfffffe;
+ if (OK)
+ if ((AdrLong&1)==1) WrError(1325);
+ else
+ BEGIN
+ BAsmCode[CodeLen++]=0xc4+(Index << 4);
+ BAsmCode[CodeLen++]=(AdrLong >> 8) & 0xff;
+ BAsmCode[CodeLen++]=AdrLong & 0xff;
+ BAsmCode[CodeLen++]=(AdrLong >> 16) & 0xff;
+ END
+ END
+END
+
+ static Boolean IsRealDef(void)
+BEGIN
+ return ((Memo("PORT")) OR (Memo("BIT")));
+END
+
+ static void ForceAlign(void)
+BEGIN
+ if ((EProgCounter()&1)==1)
+ BEGIN
+ BAsmCode[0]=NOPCode; CodeLen=1;
+ END
+END
+
+ static void MakeCode_XA(void)
+BEGIN
+ CodeLen=0; DontPrint=False; OpSize=(-1);
+
+ /* Operandengroesse */
+
+ if (*AttrPart!='\0')
+ switch (toupper(*AttrPart))
+ BEGIN
+ case 'B': SetOpSize(0); break;
+ case 'W': SetOpSize(1); break;
+ case 'D': SetOpSize(2); break;
+ default : WrError(1107); return;
+ END
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* Labels muessen auf geraden Adressen liegen */
+
+ if ( (ActPC==SegCode) AND (NOT IsRealDef()) AND
+ ((*LabPart!='\0') OR ((ArgCnt == 1) AND (strcmp(ArgStr[1],"$")==0))) )
+ BEGIN
+ ForceAlign();
+ if (*LabPart!='\0')
+ EnterIntSymbol(LabPart,EProgCounter()+CodeLen,ActPC,False);
+ END
+
+ if (DecodeMoto16Pseudo(OpSize,False)) return;
+ if (DecodeIntelPseudo(False)) return;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* via Tabelle suchen */
+
+ if (NOT LookupInstTable(InstTable,OpPart)) WrXError(1200,OpPart);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Codetabellenverwaltung */
+
+ static void AddFixed(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
+END
+
+ static void AddJBit(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=JBitOrderCnt) exit(255);
+ JBitOrders[InstrZ].Name=NName;
+ JBitOrders[InstrZ].Inversion=255;
+ JBitOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeJBit);
+END
+
+ static void AddStack(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=StackOrderCount) exit(255);
+ StackOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeStack);
+END
+
+ static void AddReg(char *NName, Byte NMask, Byte NCode)
+BEGIN
+ if (InstrZ>=RegOrderCnt) exit(255);
+ RegOrders[InstrZ].Code=NCode;
+ RegOrders[InstrZ].SizeMask=NMask;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeRegO);
+END
+
+ static void AddRotate(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=RotateOrderCount) exit(255);
+ RotateOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeRotate);
+END
+
+ static void AddRel(char *NName, Word NCode)
+BEGIN
+ if (InstrZ>=RelOrderCount) exit(255);
+ RelOrders[InstrZ].Name=NName;
+ RelOrders[InstrZ].Inversion=255;
+ RelOrders[InstrZ].Code=NCode;
+ AddInstTable(InstTable,NName,InstrZ++,DecodeRel);
+END
+
+ static void SetInv(char *Name1, char *Name2, InvOrder *Orders)
+BEGIN
+ InvOrder *Order1,*Order2;
+
+ for (Order1=Orders; strcmp(Order1->Name,Name1)!=0; Order1++);
+ for (Order2=Orders; strcmp(Order2->Name,Name2)!=0; Order2++);
+ Order1->Inversion=Order2-Orders;
+ Order2->Inversion=Order1-Orders;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstTable=CreateInstTable(201);
+ AddInstTable(InstTable,"MOV" ,0,DecodeMOV);
+ AddInstTable(InstTable,"MOVC",0,DecodeMOVC);
+ AddInstTable(InstTable,"MOVX",0,DecodeMOVX);
+ AddInstTable(InstTable,"XCH" ,0,DecodeXCH);
+ AddInstTable(InstTable,"ADDS",0,DecodeADDSMOVS);
+ AddInstTable(InstTable,"MOVS",1,DecodeADDSMOVS);
+ AddInstTable(InstTable,"DIV" ,0,DecodeDIV);
+ AddInstTable(InstTable,"DIVU",0,DecodeDIVU);
+ AddInstTable(InstTable,"MUL" ,0,DecodeMUL);
+ AddInstTable(InstTable,"DIVU",0,DecodeDIVU);
+ AddInstTable(InstTable,"MULU",0,DecodeMULU);
+ AddInstTable(InstTable,"LEA" ,0,DecodeLEA);
+ AddInstTable(InstTable,"ANL" ,0,DecodeANLORL);
+ AddInstTable(InstTable,"ORL" ,1,DecodeANLORL);
+ AddInstTable(InstTable,"CLR" ,0,DecodeCLRSETB);
+ AddInstTable(InstTable,"SETB",1,DecodeCLRSETB);
+ AddInstTable(InstTable,"TRAP",0,DecodeTRAP);
+ AddInstTable(InstTable,"CALL",0,DecodeCALL);
+ AddInstTable(InstTable,"JMP" ,0,DecodeJMP);
+ AddInstTable(InstTable,"CJNE",0,DecodeCJNE);
+ AddInstTable(InstTable,"DJNZ",0,DecodeDJNZ);
+ AddInstTable(InstTable,"FCALL",0,DecodeFCALLJMP);
+ AddInstTable(InstTable,"FJMP",1,DecodeFCALLJMP);
+
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("NOP" ,0x0000);
+ AddFixed("RET" ,0xd680);
+ AddFixed("RETI" ,0xd690);
+ AddFixed("BKPT" ,0x00ff);
+ AddFixed("RESET",0xd610);
+
+ JBitOrders=(InvOrder *) malloc(sizeof(InvOrder)*JBitOrderCnt); InstrZ=0;
+ AddJBit("JB" ,0x80);
+ AddJBit("JBC" ,0xc0);
+ AddJBit("JNB" ,0xa0);
+ SetInv("JB","JNB",JBitOrders);
+
+ StackOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*StackOrderCount); InstrZ=0;
+ AddStack("POP" ,0x1027);
+ AddStack("POPU" ,0x0037);
+ AddStack("PUSH" ,0x3007);
+ AddStack("PUSHU",0x2017);
+
+ InstrZ=0;
+ AddInstTable(InstTable,"ADD" ,InstrZ++,DecodeALU);
+ AddInstTable(InstTable,"ADDC",InstrZ++,DecodeALU);
+ AddInstTable(InstTable,"SUB" ,InstrZ++,DecodeALU);
+ AddInstTable(InstTable,"SUBB",InstrZ++,DecodeALU);
+ AddInstTable(InstTable,"CMP" ,InstrZ++,DecodeALU);
+ AddInstTable(InstTable,"AND" ,InstrZ++,DecodeALU);
+ AddInstTable(InstTable,"OR" ,InstrZ++,DecodeALU);
+ AddInstTable(InstTable,"XOR" ,InstrZ++,DecodeALU);
+
+ RegOrders=(RegOrder *) malloc(sizeof(RegOrder)*RegOrderCnt); InstrZ=0;
+ AddReg("NEG" ,3,0x0b);
+ AddReg("CPL" ,3,0x0a);
+ AddReg("SEXT",3,0x09);
+ AddReg("DA" ,1,0x08);
+
+ InstrZ=0;
+ AddInstTable(InstTable,"LSR" ,InstrZ++,DecodeShift);
+ AddInstTable(InstTable,"ASL" ,InstrZ++,DecodeShift);
+ AddInstTable(InstTable,"ASR" ,InstrZ++,DecodeShift);
+ AddInstTable(InstTable,"NORM",InstrZ++,DecodeShift);
+
+ RotateOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RotateOrderCount); InstrZ=0;
+ AddRotate("RR" ,0xb0); AddRotate("RL" ,0xd3);
+ AddRotate("RRC",0xb7); AddRotate("RLC",0xd7);
+
+ RelOrders=(InvOrder *) malloc(sizeof(InvOrder)*RelOrderCount); InstrZ=0;
+ AddRel("BCC",0xf0); AddRel("BCS",0xf1); AddRel("BNE",0xf2);
+ AddRel("BEQ",0xf3); AddRel("BNV",0xf4); AddRel("BOV",0xf5);
+ AddRel("BPL",0xf6); AddRel("BMI",0xf7); AddRel("BG" ,0xf8);
+ AddRel("BL" ,0xf9); AddRel("BGE",0xfa); AddRel("BLT",0xfb);
+ AddRel("BGT",0xfc); AddRel("BLE",0xfd); AddRel("BR" ,0xfe);
+ AddRel("JZ" ,0xec); AddRel("JNZ",0xee);
+ SetInv("BCC","BCS",RelOrders);
+ SetInv("BNE","BEQ",RelOrders);
+ SetInv("BNV","BOV",RelOrders);
+ SetInv("BPL","BMI",RelOrders);
+ SetInv("BG" ,"BL" ,RelOrders);
+ SetInv("BGE","BLT",RelOrders);
+ SetInv("BGT","BLE",RelOrders);
+ SetInv("JZ" ,"JNZ",RelOrders);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(JBitOrders);
+ free(StackOrders);
+ free(RegOrders);
+ free(RotateOrders);
+ free(RelOrders);
+
+ DestroyInstTable(InstTable);
+END
+
+/*-------------------------------------------------------------------------*/
+/* Callbacks */
+
+ static void InitCode_XA(void)
+BEGIN
+ SaveInitProc();
+ Reg_DS=0;
+END
+
+ static Boolean ChkPC_XA(LargeWord Addr)
+BEGIN
+ switch (ActPC)
+ BEGIN
+ case SegCode:
+ case SegData:
+ return (Addr<0x1000000);
+ case SegIO:
+ return ((Addr>0x3ff) AND (Addr<0x800));
+ default:
+ return False;
+ END
+END
+
+ static Boolean IsDef_XA(void)
+BEGIN
+ return (ActPC==SegCode);
+END
+
+ static void SwitchFrom_XA(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_XA(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x3c; NOPCode=0x00;
+ DivideChars=","; HasAttrs=True; AttrChars=".";
+
+ ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegIO);
+ Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
+ Grans[SegData ]=1; ListGrans[SegData ]=1; SegInits[SegData ]=0;
+ Grans[SegIO ]=1; ListGrans[SegIO ]=1; SegInits[SegIO ]=0x400;
+
+ MakeCode=MakeCode_XA; ChkPC=ChkPC_XA; IsDef=IsDef_XA;
+ SwitchFrom=SwitchFrom_XA; InitFields();
+ AddONOFF("SUPMODE", &SupAllowed, SupAllowedName,False);
+ AddONOFF("BRANCHEXT",&DoBranchExt,BranchExtName ,False);
+ AddMoto16PseudoONOFF();
+
+ SetFlag(&DoPadding,DoPaddingName,False);
+END
+
+ void codexa_init(void)
+BEGIN
+ CPUXAG1=AddCPU("XAG1",SwitchTo_XA);
+ CPUXAG2=AddCPU("XAG2",SwitchTo_XA);
+ CPUXAG3=AddCPU("XAG3",SwitchTo_XA);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_XA;
+END
diff --git a/codexa.h b/codexa.h
new file mode 100644
index 0000000..34bff12
--- /dev/null
+++ b/codexa.h
@@ -0,0 +1,11 @@
+/* codexa.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* AS-Codegenerator Philips XA */
+/* */
+/* Historie: 25.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codexa_init(void);
diff --git a/codez8.c b/codez8.c
new file mode 100644
index 0000000..5818bb5
--- /dev/null
+++ b/codez8.c
@@ -0,0 +1,856 @@
+/* codez8.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Zilog Z8 */
+/* */
+/* Historie: 8.11.1996 Grundsteinlegung */
+/* 2. 1.1998 ChkPC ersetzt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } FixedOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ Boolean Is16;
+ } ALU1Order;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } Condition;
+
+
+#define WorkOfs 0xe0
+
+
+#define FixedOrderCnt 12
+
+#define ALU2OrderCnt 10
+
+#define ALU1OrderCnt 14
+
+#define CondCnt 20
+
+#define ModNone (-1)
+#define ModWReg 0
+#define MModWReg (1 << ModWReg)
+#define ModReg 1
+#define MModReg (1 << ModReg)
+#define ModIWReg 2
+#define MModIWReg (1 << ModIWReg)
+#define ModIReg 3
+#define MModIReg (1 << ModIReg)
+#define ModImm 4
+#define MModImm (1 << ModImm)
+#define ModRReg 5
+#define MModRReg (1 << ModRReg)
+#define ModIRReg 6
+#define MModIRReg (1 << ModIRReg)
+#define ModInd 7
+#define MModInd (1 << ModInd)
+
+static ShortInt AdrType;
+static Byte AdrMode,AdrIndex;
+static Word AdrWMode;
+
+static FixedOrder *FixedOrders;
+static FixedOrder *ALU2Orders;
+static ALU1Order *ALU1Orders;
+static Condition *Conditions;
+static int TrueCond;
+
+static CPUVar CPUZ8601,CPUZ8604,CPUZ8608,CPUZ8630,CPUZ8631;
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddFixed(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NName;
+ FixedOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU2(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=ALU2OrderCnt) exit(255);
+ ALU2Orders[InstrZ].Name=NName;
+ ALU2Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddALU1(char *NName, Byte NCode, Boolean NIs)
+BEGIN
+ if (InstrZ>=ALU1OrderCnt) exit(255);
+ ALU1Orders[InstrZ].Name=NName;
+ ALU1Orders[InstrZ].Is16=NIs;
+ ALU1Orders[InstrZ++].Code=NCode;
+END
+
+ static void AddCondition(char *NName, Byte NCode)
+BEGIN
+ if (InstrZ>=CondCnt) exit(255);
+ Conditions[InstrZ].Name=NName;
+ Conditions[InstrZ++].Code=NCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
+ AddFixed("CCF" , 0xef); AddFixed("DI" , 0x8f);
+ AddFixed("EI" , 0x9f); AddFixed("HALT", 0x7f);
+ AddFixed("IRET", 0xbf); AddFixed("NOP" , 0xff);
+ AddFixed("RCF" , 0xcf); AddFixed("RET" , 0xaf);
+ AddFixed("SCF" , 0xdf); AddFixed("STOP", 0x6f);
+ AddFixed("WDH" , 0x4f); AddFixed("WDT" , 0x5f);
+
+ ALU2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU2OrderCnt); InstrZ=0;
+ AddALU2("ADD" ,0x00);
+ AddALU2("ADC" ,0x10);
+ AddALU2("SUB" ,0x20);
+ AddALU2("SBC" ,0x30);
+ AddALU2("OR" ,0x40);
+ AddALU2("AND" ,0x50);
+ AddALU2("TCM" ,0x60);
+ AddALU2("TM" ,0x70);
+ AddALU2("CP" ,0xa0);
+ AddALU2("XOR" ,0xb0);
+
+ ALU1Orders=(ALU1Order *) malloc(sizeof(ALU1Order)*ALU1OrderCnt); InstrZ=0;
+ AddALU1("DEC" , 0x00, False);
+ AddALU1("RLC" , 0x10, False);
+ AddALU1("DA" , 0x40, False);
+ AddALU1("POP" , 0x50, False);
+ AddALU1("COM" , 0x60, False);
+ AddALU1("PUSH", 0x70, False);
+ AddALU1("DECW", 0x80, True );
+ AddALU1("RL" , 0x90, False);
+ AddALU1("INCW", 0xa0, True );
+ AddALU1("CLR" , 0xb0, False);
+ AddALU1("RRC" , 0xc0, False);
+ AddALU1("SRA" , 0xd0, False);
+ AddALU1("RR" , 0xe0, False);
+ AddALU1("SWAP", 0xf0, False);
+
+ Conditions=(Condition *) malloc(sizeof(Condition)*CondCnt); InstrZ=0;
+ AddCondition("F" , 0); TrueCond=InstrZ; AddCondition("T" , 8);
+ AddCondition("C" , 7); AddCondition("NC" ,15);
+ AddCondition("Z" , 6); AddCondition("NZ" ,14);
+ AddCondition("MI" , 5); AddCondition("PL" ,13);
+ AddCondition("OV" , 4); AddCondition("NOV",12);
+ AddCondition("EQ" , 6); AddCondition("NE" ,14);
+ AddCondition("LT" , 1); AddCondition("GE" , 9);
+ AddCondition("LE" , 2); AddCondition("GT" ,10);
+ AddCondition("ULT", 7); AddCondition("UGE",15);
+ AddCondition("ULE", 3); AddCondition("UGT",11);
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(FixedOrders);
+ free(ALU2Orders);
+ free(ALU1Orders);
+ free(Conditions);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean IsWReg(char *Asc, Byte *Erg)
+BEGIN
+ Boolean Err;
+
+ if ((strlen(Asc)<2) OR (toupper(*Asc)!='R')) return False;
+ else
+ BEGIN
+ *Erg=ConstLongInt(Asc+1,&Err);
+ if (NOT Err) return False;
+ else return (*Erg<=15);
+ END
+END
+
+ static Boolean IsRReg(char *Asc, Byte *Erg)
+BEGIN
+ Boolean Err;
+
+ if ((strlen(Asc)<3) OR (strncasecmp(Asc,"RR",2)!=0)) return False;
+ else
+ BEGIN
+ *Erg=ConstLongInt(Asc+2,&Err);
+ if (NOT Err) return False;
+ else return (*Erg<=15);
+ END
+END
+
+ static void CorrMode(Byte Mask, ShortInt Old, ShortInt New)
+BEGIN
+ if ((AdrType==Old) AND ((Mask & (1 << Old))==0))
+ BEGIN
+ AdrType=New; AdrMode+=WorkOfs;
+ END
+END
+
+ static void ChkAdr(Byte Mask, Boolean Is16)
+BEGIN
+ if (NOT Is16)
+ BEGIN
+ CorrMode(Mask,ModWReg,ModReg);
+ CorrMode(Mask,ModIWReg,ModIReg);
+ END
+
+ if ((AdrType!=ModNone) AND ((Mask & (1 << AdrType))==0))
+ BEGIN
+ WrError(1350); AdrType=ModNone;
+ END
+END
+
+ static void DecodeAdr(char *Asc, Byte Mask, Boolean Is16)
+BEGIN
+ Boolean OK;
+ char *p;
+
+ AdrType=ModNone;
+
+ /* immediate ? */
+
+ if (*Asc=='#')
+ BEGIN
+ AdrMode=EvalIntExpression(Asc+1,Int8,&OK);
+ if (OK) AdrType=ModImm;
+ ChkAdr(Mask,Is16); return;
+ END;
+
+ /* Register ? */
+
+ if (IsWReg(Asc,&AdrMode))
+ BEGIN
+ AdrType=ModWReg; ChkAdr(Mask,Is16); return;
+ END
+
+ if (IsRReg(Asc,&AdrMode))
+ BEGIN
+ if ((AdrMode&1)==1) WrError(1351); else AdrType=ModRReg;
+ ChkAdr(Mask,Is16); return;
+ END
+
+ /* indirekte Konstrukte ? */
+
+ if (*Asc=='@')
+ BEGIN
+ strcpy(Asc,Asc+1);
+ if (IsWReg(Asc,&AdrMode)) AdrType=ModIWReg;
+ else if (IsRReg(Asc,&AdrMode))
+ BEGIN
+ if ((AdrMode&1)==1) WrError(1351); else AdrType=ModIRReg;
+ END
+ else
+ BEGIN
+ AdrMode=EvalIntExpression(Asc,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModIReg; ChkSpace(SegData);
+ END
+ END
+ ChkAdr(Mask,Is16); return;
+ END
+
+ /* indiziert ? */
+
+ if ((Asc[strlen(Asc)-1]==')') AND (strlen(Asc)>4))
+ BEGIN
+ p=Asc+strlen(Asc)-1; *p='\0';
+ while ((p>=Asc) AND (*p!='(')) p--;
+ if (*p!='(') WrError(1300);
+ else if (NOT IsWReg(p+1,&AdrMode)) WrXError(1445,p+1);
+ else
+ BEGIN
+ *p='\0';
+ AdrIndex=EvalIntExpression(Asc,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModInd; ChkSpace(SegData);
+ END
+ ChkAdr(Mask,Is16); return;
+ END
+ END
+
+ /* einfache direkte Adresse ? */
+
+ if (Is16) AdrWMode=EvalIntExpression(Asc,UInt16,&OK);
+ else AdrMode=EvalIntExpression(Asc,UInt8,&OK);
+ if (OK)
+ BEGIN
+ AdrType=ModReg;
+ ChkSpace((Is16)?SegCode:SegData);
+ ChkAdr(Mask,Is16); return;
+ END
+
+ ChkAdr(Mask,Is16);
+END
+
+/*---------------------------------------------------------------------*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ if (Memo("SFR"))
+ BEGIN
+ CodeEquate(SegData,0,0xff);
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_Z8(void)
+BEGIN
+ Integer AdrInt;
+ int z;
+ Byte Save;
+ Boolean OK;
+
+ CodeLen=0; DontPrint=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ if (DecodeIntelPseudo(True)) return;
+
+ /* ohne Argument */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=FixedOrders[z].Code;
+ END
+ return;
+ END
+
+ /* Datentransfer */
+
+ if (Memo("LD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModWReg+MModIReg+MModIWReg+MModInd,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ Save=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModWReg+MModIReg+MModImm,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0xe4;
+ BAsmCode[1]=AdrMode; BAsmCode[2]=Save;
+ CodeLen=3;
+ break;
+ case ModWReg:
+ BAsmCode[0]=(AdrMode << 4)+9;
+ BAsmCode[1]=Save;
+ CodeLen=2;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0xe5;
+ BAsmCode[1]=AdrMode; BAsmCode[2]=Save;
+ CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0xe6;
+ BAsmCode[1]=Save; BAsmCode[2]=AdrMode;
+ CodeLen=3;
+ break;
+ END
+ break;
+ case ModWReg:
+ Save=AdrMode;
+ DecodeAdr(ArgStr[2],MModWReg+MModReg+MModIWReg+MModIReg+MModImm+MModInd,False);
+ switch (AdrType)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=(Save << 4)+8; BAsmCode[1]=AdrMode+WorkOfs;
+ CodeLen=2;
+ break;
+ case ModReg:
+ BAsmCode[0]=(Save << 4)+8; BAsmCode[1]=AdrMode;
+ CodeLen=2;
+ break;
+ case ModIWReg:
+ BAsmCode[0]=0xe3; BAsmCode[1]=(Save << 4)+AdrMode;
+ CodeLen=2;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0xe5;
+ BAsmCode[1]=AdrMode; BAsmCode[2]=WorkOfs+Save;
+ CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=(Save << 4)+12; BAsmCode[1]=AdrMode;
+ CodeLen=2;
+ break;
+ case ModInd:
+ BAsmCode[0]=0xc7;
+ BAsmCode[1]=(Save << 4)+AdrMode; BAsmCode[2]=AdrIndex;
+ CodeLen=3;
+ break;
+ END
+ break;
+ case ModIReg:
+ Save=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModImm,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=0xf5;
+ BAsmCode[1]=AdrMode; BAsmCode[2]=Save;
+ CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0xe7;
+ BAsmCode[1]=Save; BAsmCode[2]=AdrMode;
+ CodeLen=3;
+ break;
+ END
+ break;
+ case ModIWReg:
+ Save=AdrMode;
+ DecodeAdr(ArgStr[2],MModWReg+MModReg+MModImm,False);
+ switch (AdrType)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=0xf3; BAsmCode[1]=(Save << 4)+AdrMode;
+ CodeLen=2;
+ break;
+ case ModReg:
+ BAsmCode[0]=0xf5;
+ BAsmCode[1]=AdrMode; BAsmCode[2]=WorkOfs+Save;
+ CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=0xe7;
+ BAsmCode[1]=WorkOfs+Save; BAsmCode[2]=AdrMode;
+ CodeLen=3;
+ break;
+ END
+ break;
+ case ModInd:
+ Save=AdrMode;
+ DecodeAdr(ArgStr[2],MModWReg,False);
+ switch (AdrType)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=0xd7;
+ BAsmCode[1]=(AdrMode << 4)+Save; BAsmCode[2]=AdrIndex;
+ CodeLen=3;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDC")) OR (Memo("LDE")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg+MModIRReg,False);
+ switch (AdrType)
+ BEGIN
+ case ModWReg:
+ Save=AdrMode; DecodeAdr(ArgStr[2],MModIRReg,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=(Memo("LDC")) ? 0xc2 : 0x82;
+ BAsmCode[1]=(Save << 4)+AdrMode;
+ CodeLen=2;
+ END
+ break;
+ case ModIRReg:
+ Save=AdrMode; DecodeAdr(ArgStr[2],MModWReg,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=(Memo("LDC")) ? 0xd2 : 0x92;
+ BAsmCode[1]=(AdrMode << 4)+Save;
+ CodeLen=2;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ if ((Memo("LDCI")) OR (Memo("LDEI")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIWReg+MModIRReg,False);
+ switch (AdrType)
+ BEGIN
+ case ModIWReg:
+ Save=AdrMode; DecodeAdr(ArgStr[2],MModIRReg,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=(Memo("LDCI")) ? 0xc3 : 0x83;
+ BAsmCode[1]=(Save << 4)+AdrMode;
+ CodeLen=2;
+ END
+ break;
+ case ModIRReg:
+ Save=AdrMode; DecodeAdr(ArgStr[2],MModIWReg,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ BAsmCode[0]=(Memo("LDCI")) ? 0xd3 : 0x93;
+ BAsmCode[1]=(AdrMode << 4)+Save;
+ CodeLen=2;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Arithmetik */
+
+ for (z=0; z<ALU2OrderCnt; z++)
+ if (Memo(ALU2Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModReg+MModWReg+MModIReg,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ Save=AdrMode;
+ DecodeAdr(ArgStr[2],MModReg+MModIReg+MModImm,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=ALU2Orders[z].Code+4;
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=Save;
+ CodeLen=3;
+ break;
+ case ModIReg:
+ BAsmCode[0]=ALU2Orders[z].Code+5;
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=Save;
+ CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=ALU2Orders[z].Code+6;
+ BAsmCode[1]=Save;
+ BAsmCode[2]=AdrMode;
+ CodeLen=3;
+ break;
+ END
+ break;
+ case ModWReg:
+ Save=AdrMode;
+ DecodeAdr(ArgStr[2],MModWReg+MModReg+MModIWReg+MModIReg+MModImm,False);
+ switch (AdrType)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=ALU2Orders[z].Code+2;
+ BAsmCode[1]=(Save << 4)+AdrMode;
+ CodeLen=2;
+ break;
+ case ModReg:
+ BAsmCode[0]=ALU2Orders[z].Code+4;
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=WorkOfs+Save;
+ CodeLen=3;
+ break;
+ case ModIWReg:
+ BAsmCode[0]=ALU2Orders[z].Code+3;
+ BAsmCode[1]=(Save << 4)+AdrMode;
+ CodeLen=2;
+ break;
+ case ModIReg:
+ BAsmCode[0]=ALU2Orders[z].Code+5;
+ BAsmCode[1]=AdrMode;
+ BAsmCode[2]=WorkOfs+Save;
+ CodeLen=3;
+ break;
+ case ModImm:
+ BAsmCode[0]=ALU2Orders[z].Code+6;
+ BAsmCode[1]=Save+WorkOfs;
+ BAsmCode[2]=AdrMode;
+ CodeLen=3;
+ break;
+ END
+ break;
+ case ModIReg:
+ Save=AdrMode;
+ DecodeAdr(ArgStr[2],MModImm,False);
+ switch (AdrType)
+ BEGIN
+ case ModImm:
+ BAsmCode[0]=ALU2Orders[z].Code+7;
+ BAsmCode[1]=Save;
+ BAsmCode[2]=AdrMode;
+ CodeLen=3;
+ break;
+ END
+ break;
+ END
+ END
+ return;
+ END
+
+ /* INC hat eine Optimierungsmoeglichkeit */
+
+ if (Memo("INC"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg+MModReg+MModIReg,False);
+ switch (AdrType)
+ BEGIN
+ case ModWReg:
+ BAsmCode[0]=(AdrMode << 4)+0x0e; CodeLen=1;
+ break;
+ case ModReg:
+ BAsmCode[0]=0x20; BAsmCode[1]=AdrMode; CodeLen=2;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0x21; BAsmCode[1]=AdrMode; CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ /* ...alle anderen nicht */
+
+ for (z=0; z<ALU1OrderCnt; z++)
+ if (Memo(ALU1Orders[z].Name))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],((ALU1Orders[z].Is16)?MModRReg:0)+MModReg+MModIReg,False);
+ switch (AdrType)
+ BEGIN
+ case ModReg:
+ BAsmCode[0]=ALU1Orders[z].Code; BAsmCode[1]=AdrMode; CodeLen=2;
+ break;
+ case ModRReg:
+ BAsmCode[0]=ALU1Orders[z].Code; BAsmCode[1]=WorkOfs+AdrMode; CodeLen=2;
+ break;
+ case ModIReg:
+ BAsmCode[0]=ALU1Orders[z].Code+1; BAsmCode[1]=AdrMode; CodeLen=2;
+ break;
+ END
+ END
+ return;
+ END
+
+ /* Spruenge */
+
+ if (Memo("JR"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1) z=TrueCond;
+ else
+ BEGIN
+ z=0; NLS_UpString(ArgStr[1]);
+ while ((z<CondCnt) AND (strcmp(Conditions[z].Name,ArgStr[1])!=0)) z++;
+ if (z>=CondCnt) WrError(1360);
+ END
+ if (z<CondCnt)
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[ArgCnt],Int16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt>127) OR (AdrInt<-128))) WrError(1370);
+ else
+ BEGIN
+ ChkSpace(SegCode);
+ BAsmCode[0]=(Conditions[z].Code << 4)+0x0b;
+ BAsmCode[1]=Lo(AdrInt);
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("DJNZ"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModWReg,False);
+ if (AdrType!=ModNone)
+ BEGIN
+ AdrInt=EvalIntExpression(ArgStr[2],Int16,&OK)-(EProgCounter()+2);
+ if (OK)
+ if ((NOT SymbolQuestionable) AND ((AdrInt>127) OR (AdrInt<-128))) WrError(1370);
+ else
+ BEGIN
+ BAsmCode[0]=(AdrMode << 4)+0x0a;
+ BAsmCode[1]=Lo(AdrInt);
+ CodeLen=2;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALL"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModIRReg+MModIReg+MModReg,True);
+ switch (AdrType)
+ BEGIN
+ case ModIRReg:
+ BAsmCode[0]=0xd4; BAsmCode[1]=0xe0+AdrMode; CodeLen=2;
+ break;
+ case ModIReg:
+ BAsmCode[0]=0xd4; BAsmCode[1]=AdrMode; CodeLen=2;
+ break;
+ case ModReg:
+ BAsmCode[0]=0xd6;
+ BAsmCode[1]=Hi(AdrWMode); BAsmCode[2]=Lo(AdrWMode);
+ CodeLen=3;
+ break;
+ END
+ END
+ return;
+ END
+
+ if (Memo("JP"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else
+ BEGIN
+ if (ArgCnt==1) z=TrueCond;
+ else
+ BEGIN
+ z=0; NLS_UpString(ArgStr[1]);
+ while ((z<CondCnt) AND (strcmp(Conditions[z].Name,ArgStr[1])!=0)) z++;
+ if (z>=CondCnt) WrError(1360);
+ END
+ if (z<CondCnt)
+ BEGIN
+ DecodeAdr(ArgStr[ArgCnt],MModIRReg+MModIReg+MModReg,True);
+ switch (AdrType)
+ BEGIN
+ case ModIRReg:
+ if (z!=TrueCond) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x30; BAsmCode[1]=0xe0+AdrMode; CodeLen=2;
+ END
+ break;
+ case ModIReg:
+ if (z!=TrueCond) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0x30; BAsmCode[1]=AdrMode; CodeLen=2;
+ END
+ break;
+ case ModReg:
+ BAsmCode[0]=(Conditions[z].Code << 4)+0x0d;
+ BAsmCode[1]=Hi(AdrWMode); BAsmCode[2]=Lo(AdrWMode);
+ CodeLen=3;
+ break;
+ END
+ END
+ END
+ return;
+ END
+
+ /* Sonderbefehle */
+
+ if (Memo("SRP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1],MModImm,False);
+ if (AdrType==ModImm)
+ if (((AdrMode & 15)!=0) OR ((AdrMode>0x70) AND (AdrMode<0xf0))) WrError(120);
+ else
+ BEGIN
+ BAsmCode[0]=0x31; BAsmCode[1]=AdrMode;
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static Boolean IsDef_Z8(void)
+BEGIN
+ return (Memo("SFR"));
+END
+
+ static void SwitchFrom_Z8(void)
+BEGIN
+ DeinitFields();
+END
+
+ static void SwitchTo_Z8(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
+
+ PCSymbol="$"; HeaderID=0x79; NOPCode=0xff;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)|(1<<SegData);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = 0xffff;
+ Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
+ SegLimits[SegData] = 0xff;
+
+ MakeCode=MakeCode_Z8; IsDef=IsDef_Z8;
+ SwitchFrom=SwitchFrom_Z8; InitFields();
+END
+
+ void codez8_init(void)
+BEGIN
+ CPUZ8601=AddCPU("Z8601",SwitchTo_Z8);
+ CPUZ8604=AddCPU("Z8604",SwitchTo_Z8);
+ CPUZ8608=AddCPU("Z8608",SwitchTo_Z8);
+ CPUZ8630=AddCPU("Z8630",SwitchTo_Z8);
+ CPUZ8631=AddCPU("Z8631",SwitchTo_Z8);
+END
+
diff --git a/codez8.h b/codez8.h
new file mode 100644
index 0000000..5d98453
--- /dev/null
+++ b/codez8.h
@@ -0,0 +1,11 @@
+/* codez8.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Zilog Z8 */
+/* */
+/* Historie: 8.11.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codez8_init(void);
diff --git a/codez80.c b/codez80.c
new file mode 100644
index 0000000..055a5f0
--- /dev/null
+++ b/codez80.c
@@ -0,0 +1,2814 @@
+/* codez80.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Zilog Z80/180/380 */
+/* */
+/* Historie: 26. 8.1996 Grundsteinlegung */
+/* 1. 2.1998 ChkPC ersetzt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "nls.h"
+#include "strutil.h"
+#include "bpemu.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "asmcode.h"
+#include "asmallg.h"
+#include "codepseudo.h"
+#include "codevars.h"
+
+/*-------------------------------------------------------------------------*/
+/* Instruktionsgruppendefinitionen */
+
+typedef struct
+ {
+ char *Name;
+ CPUVar MinCPU;
+ Byte Len;
+ Word Code;
+ } BaseOrder;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } Condition;
+
+typedef struct
+ {
+ char *Name;
+ Byte Code;
+ } ALUOrder;
+
+/*-------------------------------------------------------------------------*/
+/* Praefixtyp */
+
+typedef enum {Pref_IN_N,Pref_IN_W ,Pref_IB_W ,Pref_IW_W ,Pref_IB_N ,
+ Pref_IN_LW,Pref_IB_LW,Pref_IW_LW,Pref_IW_N} PrefType;
+
+
+#define ExtFlagName "INEXTMODE" /* Flag-Symbolnamen */
+#define LWordFlagName "INLWORDMODE"
+
+#define ModNone (-1)
+#define ModReg8 1
+#define ModReg16 2
+#define ModIndReg16 3
+#define ModImm 4
+#define ModAbs 5
+#define ModRef 6
+#define ModInt 7
+#define ModSPRel 8
+
+#define FixedOrderCnt 53
+#define AccOrderCnt 3
+#define HLOrderCnt 3
+#define ALUOrderCnt 5
+#define ShiftOrderCnt 8
+#define BitOrderCnt 3
+#define ConditionCnt 12
+
+#define IXPrefix 0xdd
+#define IYPrefix 0xfd
+
+/*-------------------------------------------------------------------------*/
+
+static Byte PrefixCnt;
+static Byte AdrPart,OpSize;
+static Byte AdrVals[4];
+static ShortInt AdrMode;
+
+static BaseOrder *FixedOrders;
+static BaseOrder *AccOrders;
+static BaseOrder *HLOrders;
+static ALUOrder *ALUOrders;
+static char **ShiftOrders;
+static char **BitOrders;
+static Condition *Conditions;
+
+static SimpProc SaveInitProc;
+
+static CPUVar CPUZ80,CPUZ80U,CPUZ180,CPUZ380;
+
+static Boolean MayLW, /* Instruktion erlaubt 32 Bit */
+ ExtFlag, /* Prozessor im 4GByte-Modus ? */
+ LWordFlag; /* 32-Bit-Verarbeitung ? */
+
+static PrefType CurrPrefix, /* mom. explizit erzeugter Praefix */
+ LastPrefix; /* von der letzten Anweisung generierter Praefix */
+
+/*==========================================================================*/
+/* Codetabellenerzeugung */
+
+ static void AddFixed(char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
+BEGIN
+ if (InstrZ>=FixedOrderCnt) exit(255);
+ FixedOrders[InstrZ].Name=NewName;
+ FixedOrders[InstrZ].MinCPU=NewMin;
+ FixedOrders[InstrZ].Len=NewLen;
+ FixedOrders[InstrZ++].Code=NewCode;
+END
+
+ static void AddAcc(char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
+BEGIN
+ if (InstrZ>=AccOrderCnt) exit(255);
+ AccOrders[InstrZ].Name=NewName;
+ AccOrders[InstrZ].MinCPU=NewMin;
+ AccOrders[InstrZ].Len=NewLen;
+ AccOrders[InstrZ++].Code=NewCode;
+END
+
+ static void AddHL(char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
+BEGIN
+ if (InstrZ>=HLOrderCnt) exit(255);
+ HLOrders[InstrZ].Name=NewName;
+ HLOrders[InstrZ].MinCPU=NewMin;
+ HLOrders[InstrZ].Len=NewLen;
+ HLOrders[InstrZ++].Code=NewCode;
+END
+
+ static void AddALU(char *NewName, Byte NCode)
+BEGIN
+ if (InstrZ>=ALUOrderCnt) exit(255);
+ ALUOrders[InstrZ].Name=NewName;
+ ALUOrders[InstrZ++].Code=NCode;
+END
+
+ static void AddShift(char *NName)
+BEGIN
+ if (InstrZ>=ShiftOrderCnt) exit(255);
+ ShiftOrders[InstrZ++]=NName;
+END
+
+ static void AddBit(char *NName)
+BEGIN
+ if (InstrZ>=BitOrderCnt) exit(255);
+ BitOrders[InstrZ++]=NName;
+END
+
+ static void AddCondition(char *NewName, Byte NewCode)
+BEGIN
+ if (InstrZ>=ConditionCnt) exit(255);
+ Conditions[InstrZ].Name=NewName;
+ Conditions[InstrZ++].Code=NewCode;
+END
+
+ static void InitFields(void)
+BEGIN
+ InstrZ=0; Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCnt);
+ AddCondition("NZ",0); AddCondition("Z" ,1);
+ AddCondition("NC",2); AddCondition("C" ,3);
+ AddCondition("PO",4); AddCondition("NV",4);
+ AddCondition("PE",5); AddCondition("V" ,5);
+ AddCondition("P" ,6); AddCondition("NS",6);
+ AddCondition("M" ,7); AddCondition("S" ,7);
+
+ InstrZ=0; FixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FixedOrderCnt);
+ AddFixed("EXX" ,CPUZ80 ,1,0x00d9); AddFixed("LDI" ,CPUZ80 ,2,0xeda0);
+ AddFixed("LDIR" ,CPUZ80 ,2,0xedb0); AddFixed("LDD" ,CPUZ80 ,2,0xeda8);
+ AddFixed("LDDR" ,CPUZ80 ,2,0xedb8); AddFixed("CPI" ,CPUZ80 ,2,0xeda1);
+ AddFixed("CPIR" ,CPUZ80 ,2,0xedb1); AddFixed("CPD" ,CPUZ80 ,2,0xeda9);
+ AddFixed("CPDR" ,CPUZ80 ,2,0xedb9); AddFixed("RLCA" ,CPUZ80 ,1,0x0007);
+ AddFixed("RRCA" ,CPUZ80 ,1,0x000f); AddFixed("RLA" ,CPUZ80 ,1,0x0017);
+ AddFixed("RRA" ,CPUZ80 ,1,0x001f); AddFixed("RLD" ,CPUZ80 ,2,0xed6f);
+ AddFixed("RRD" ,CPUZ80 ,2,0xed67); AddFixed("DAA" ,CPUZ80 ,1,0x0027);
+ AddFixed("CCF" ,CPUZ80 ,1,0x003f); AddFixed("SCF" ,CPUZ80 ,1,0x0037);
+ AddFixed("NOP" ,CPUZ80 ,1,0x0000); AddFixed("HALT" ,CPUZ80 ,1,0x0076);
+ AddFixed("RETI" ,CPUZ80 ,2,0xed4d); AddFixed("RETN" ,CPUZ80 ,2,0xed45);
+ AddFixed("INI" ,CPUZ80 ,2,0xeda2); AddFixed("INIR" ,CPUZ80 ,2,0xedb2);
+ AddFixed("IND" ,CPUZ80 ,2,0xedaa); AddFixed("INDR" ,CPUZ80 ,2,0xedba);
+ AddFixed("OUTI" ,CPUZ80 ,2,0xeda3); AddFixed("OTIR" ,CPUZ80 ,2,0xedb3);
+ AddFixed("OUTD" ,CPUZ80 ,2,0xedab); AddFixed("OTDR" ,CPUZ80 ,2,0xedbb);
+ AddFixed("SLP" ,CPUZ180,2,0xed76); AddFixed("OTIM" ,CPUZ180,2,0xed83);
+ AddFixed("OTIMR",CPUZ180,2,0xed93); AddFixed("OTDM" ,CPUZ180,2,0xed8b);
+ AddFixed("OTDMR",CPUZ180,2,0xed9b); AddFixed("BTEST",CPUZ380,2,0xedcf);
+ AddFixed("EXALL",CPUZ380,2,0xedd9); AddFixed("EXXX" ,CPUZ380,2,0xddd9);
+ AddFixed("EXXY" ,CPUZ380,2,0xfdd9); AddFixed("INDW" ,CPUZ380,2,0xedea);
+ AddFixed("INDRW",CPUZ380,2,0xedfa); AddFixed("INIW" ,CPUZ380,2,0xede2);
+ AddFixed("INIRW",CPUZ380,2,0xedf2); AddFixed("LDDW" ,CPUZ380,2,0xede8);
+ AddFixed("LDDRW",CPUZ380,2,0xedf8); AddFixed("LDIW" ,CPUZ380,2,0xede0);
+ AddFixed("LDIRW",CPUZ380,2,0xedf0); AddFixed("MTEST",CPUZ380,2,0xddcf);
+ AddFixed("OTDRW",CPUZ380,2,0xedfb); AddFixed("OTIRW",CPUZ380,2,0xedf3);
+ AddFixed("OUTDW",CPUZ380,2,0xedeb); AddFixed("OUTIW",CPUZ380,2,0xede3);
+ AddFixed("RETB" ,CPUZ380,2,0xed55);
+
+ InstrZ=0; AccOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*AccOrderCnt);
+ AddAcc("CPL" ,CPUZ80 ,1,0x002f); AddAcc("NEG" ,CPUZ80 ,2,0xed44);
+ AddAcc("EXTS" ,CPUZ380,2,0xed65);
+
+ InstrZ=0; HLOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*HLOrderCnt);
+ AddHL("CPLW" ,CPUZ380,2,0xdd2f); AddHL("NEGW" ,CPUZ380,2,0xed54);
+ AddHL("EXTSW",CPUZ380,2,0xed75);
+
+ InstrZ=0; ALUOrders=(ALUOrder *) malloc(sizeof(ALUOrder)*ALUOrderCnt);
+ AddALU("SUB", 2); AddALU("AND", 4);
+ AddALU("OR" , 6); AddALU("XOR", 5);
+ AddALU("CP" , 7);
+
+ InstrZ=0; ShiftOrders=(char **) malloc(sizeof(char *)*ShiftOrderCnt);
+ AddShift("RLC"); AddShift("RRC"); AddShift("RL"); AddShift("RR");
+ AddShift("SLA"); AddShift("SRA"); AddShift("SLIA"); AddShift("SRL");
+
+ InstrZ=0; BitOrders=(char **) malloc(sizeof(char *)*BitOrderCnt);
+ AddBit("BIT"); AddBit("RES"); AddBit("SET");
+END
+
+ static void DeinitFields(void)
+BEGIN
+ free(Conditions);
+ free(FixedOrders);
+ free(AccOrders);
+ free(HLOrders);
+ free(ALUOrders);
+ free(ShiftOrders);
+ free(BitOrders);
+END
+
+/*==========================================================================*/
+/* Adressbereiche */
+
+ static LargeWord CodeEnd(void)
+BEGIN
+#ifdef __STDC__
+ if (ExtFlag) return 0xfffffffflu;
+#else
+ if (ExtFlag) return 0xffffffffl;
+#endif
+ else if (MomCPU==CPUZ180) return 0x7ffffl;
+ else return 0xffff;
+END
+
+ static LargeWord PortEnd(void)
+BEGIN
+#ifdef __STDC__
+ if (ExtFlag) return 0xfffffffflu;
+#else
+ if (ExtFlag) return 0xffffffffl;
+#endif
+ else return 0xff;
+END
+
+/*==========================================================================*/
+/* Praefix dazuaddieren */
+
+ static Boolean ExtendPrefix(PrefType *Dest, char *AddArg)
+BEGIN
+ Byte SPart,IPart;
+
+ switch (*Dest)
+ BEGIN
+ case Pref_IB_N:
+ case Pref_IB_W:
+ case Pref_IB_LW: IPart=1; break;
+ case Pref_IW_N:
+ case Pref_IW_W:
+ case Pref_IW_LW: IPart=2; break;
+ default: IPart=0;
+ END
+
+ switch (*Dest)
+ BEGIN
+ case Pref_IN_W:
+ case Pref_IB_W:
+ case Pref_IW_W: SPart=1; break;
+ case Pref_IN_LW:
+ case Pref_IB_LW:
+ case Pref_IW_LW: SPart=2; break;
+ default: SPart=0;
+ END
+
+ if (strcmp(AddArg,"W")==0) /* Wortverarbeitung */
+ SPart=1;
+ else if (strcmp(AddArg,"LW")==0) /* Langwortverarbeitung */
+ SPart=2;
+ else if (strcmp(AddArg,"IB")==0) /* ein Byte im Argument mehr */
+ IPart=1;
+ else if (strcmp(AddArg,"IW")==0) /* ein Wort im Argument mehr */
+ IPart=2;
+ else return False;
+
+ switch ((IPart << 4)+SPart)
+ BEGIN
+ case 0x00:*Dest=Pref_IN_N; break;
+ case 0x01:*Dest=Pref_IN_W; break;
+ case 0x02:*Dest=Pref_IN_LW; break;
+ case 0x10:*Dest=Pref_IB_N; break;
+ case 0x11:*Dest=Pref_IB_W; break;
+ case 0x12:*Dest=Pref_IB_LW; break;
+ case 0x20:*Dest=Pref_IW_N; break;
+ case 0x21:*Dest=Pref_IW_W; break;
+ case 0x22:*Dest=Pref_IW_LW; break;
+ END
+
+ return True;
+END
+
+/*--------------------------------------------------------------------------*/
+/* Code fuer Praefix bilden */
+
+ static void GetPrefixCode(PrefType inp, Byte *b1 ,Byte *b2)
+BEGIN
+ int z;
+
+ z=((int)inp)-1;
+ *b1=0xdd+((z & 4) << 3);
+ *b2=0xc0+(z & 3);
+END
+
+/*--------------------------------------------------------------------------*/
+/* DD-Praefix addieren, nur EINMAL pro Instruktion benutzen! */
+
+ static void ChangeDDPrefix(char *Add)
+BEGIN
+ PrefType ActPrefix;
+ int z;
+
+ ActPrefix=LastPrefix;
+ if (ExtendPrefix(&ActPrefix,Add))
+ if (LastPrefix!=ActPrefix)
+ BEGIN
+ if (LastPrefix!=Pref_IN_N) RetractWords(2);
+ for (z=PrefixCnt-1; z>=0; z--) BAsmCode[2+z]=BAsmCode[z];
+ PrefixCnt+=2;
+ GetPrefixCode(ActPrefix,BAsmCode+0,BAsmCode+1);
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+/* Wortgroesse ? */
+
+ static Boolean InLongMode(void)
+BEGIN
+ switch (LastPrefix)
+ BEGIN
+ case Pref_IN_W:
+ case Pref_IB_W:
+ case Pref_IW_W: return False;
+ case Pref_IN_LW:
+ case Pref_IB_LW:
+ case Pref_IW_LW: return MayLW;
+ default: return LWordFlag AND MayLW;
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+/* absolute Adresse */
+
+ static LongWord EvalAbsAdrExpression(char *inp, Boolean *OK)
+BEGIN
+ return EvalIntExpression(inp,ExtFlag?Int32:UInt16,OK);
+END
+
+/*==========================================================================*/
+/* Adressparser */
+
+ static Boolean DecodeReg8(char *Asc, Byte *Erg)
+BEGIN
+#define Reg8Cnt 7
+ static char *Reg8Names[Reg8Cnt]={"B","C","D","E","H","L","A"};
+ int z;
+
+ for (z=0; z<Reg8Cnt; z++)
+ if (strcasecmp(Asc,Reg8Names[z])==0)
+ BEGIN
+ *Erg=z; if (z==6) (*Erg)++;
+ return True;
+ END
+
+ return False;
+END
+
+ static Boolean IsSym(char ch)
+BEGIN
+ return ((ch=='_') OR ((ch>='0') AND (ch<='9')) OR ((ch>='A') AND (ch<='Z')) OR ((ch>='a') AND (ch<='z')));
+END
+
+ static void DecodeAdr(char *Asc_O)
+BEGIN
+#define Reg8XCnt 4
+ static char *Reg8XNames[Reg8XCnt]={"IXU","IXL","IYU","IYL"};
+#define Reg16Cnt 6
+ static char *Reg16Names[Reg16Cnt]={"BC","DE","HL","SP","IX","IY"};
+
+ int z;
+ Integer AdrInt;
+ LongInt AdrLong;
+ Boolean OK;
+ String Asc;
+
+ AdrMode=ModNone; AdrCnt=0; AdrPart=0;
+
+ /* 0. Sonderregister */
+
+ if (strcasecmp(Asc_O,"R")==0)
+ BEGIN
+ AdrMode=ModRef; return;
+ END
+
+ if (strcasecmp(Asc_O,"I")==0)
+ BEGIN
+ AdrMode=ModInt; return;
+ END
+
+ /* 1. 8-Bit-Register ? */
+
+ if (DecodeReg8(Asc_O,&AdrPart))
+ BEGIN
+ AdrMode=ModReg8;
+ return;
+ END
+
+ /* 1a. 8-Bit-Haelften von IX/IY ? (nur Z380, sonst als Symbole zulassen) */
+
+ if ((MomCPU>=CPUZ380) OR (MomCPU==CPUZ80U))
+ for (z=0; z<Reg8XCnt; z++)
+ if (strcasecmp(Asc_O,Reg8XNames[z])==0)
+ BEGIN
+ AdrMode=ModReg8;
+ BAsmCode[PrefixCnt++]=(z<=1)?IXPrefix:IYPrefix;
+ AdrPart=4+(z & 1); /* = H /L */
+ return;
+ END
+
+ /* 2. 16-Bit-Register ? */
+
+ for (z=0; z<Reg16Cnt; z++)
+ if (strcasecmp(Asc_O,Reg16Names[z])==0)
+ BEGIN
+ AdrMode=ModReg16;
+ if (z<=3) AdrPart=z;
+ else
+ BEGIN
+ BAsmCode[PrefixCnt++]=(z==4)?IXPrefix:IYPrefix;
+ AdrPart=2; /* = HL */
+ END
+ return;
+ END
+
+ /* 3. 16-Bit-Register indirekt ? */
+
+ if ((strlen(Asc_O)>=4) AND (*Asc_O=='(') AND (Asc_O[strlen(Asc_O)-1]==')'))
+ for (z=0; z<Reg16Cnt; z++)
+ if ((strncasecmp(Asc_O+1,Reg16Names[z],2)==0)
+ AND (NOT IsSym(Asc_O[3])))
+ BEGIN
+ if (z<3)
+ BEGIN
+ if (strlen(Asc_O)!=4)
+ BEGIN
+ WrError(1350); return;
+ END
+ switch (z)
+ BEGIN
+ case 0:
+ case 1: /* BC,DE */
+ AdrMode=ModIndReg16; AdrPart=z;
+ break;
+ case 2: /* HL=M-Register */
+ AdrMode=ModReg8; AdrPart=6;
+ break;
+ END
+ END
+ else
+ BEGIN /* SP,IX,IY */
+ strmaxcpy(Asc,Asc_O+3,255); Asc[strlen(Asc)-1]='\0';
+ if (*Asc=='+') strcpy(Asc,Asc+1);
+ AdrLong=EvalIntExpression(Asc,(MomCPU>=CPUZ380)?SInt24:SInt8,&OK);
+ if (OK)
+ BEGIN
+ if (z==3) AdrMode=ModSPRel;
+ else
+ BEGIN
+ AdrMode=ModReg8; AdrPart=6;
+ BAsmCode[PrefixCnt++]=(z==4)?IXPrefix:IYPrefix;
+ END
+ AdrVals[AdrCnt++]=AdrLong & 0xff;
+ if ((AdrLong>=-0x80l) AND (AdrLong<=0x7fl));
+ else
+ BEGIN
+ AdrVals[AdrCnt++]=(AdrLong >> 8) & 0xff;
+ if ((AdrLong>=-0x8000l) AND (AdrLong<=0x7fffl)) ChangeDDPrefix("IB");
+ else
+ BEGIN
+ AdrVals[AdrCnt++]=(AdrLong >> 16) & 0xff;
+ ChangeDDPrefix("IW");
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ /* absolut ? */
+
+ if (IsIndirect(Asc_O))
+ BEGIN
+ AdrLong=EvalAbsAdrExpression(Asc_O,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegCode);
+ AdrMode=ModAbs;
+ AdrVals[0]=AdrLong & 0xff;
+ AdrVals[1]=(AdrLong >> 8) & 0xff;
+ AdrCnt=2;
+#ifdef __STDC__
+ if ((AdrLong & 0xffff0000u)==0);
+#else
+ if ((AdrLong & 0xffff0000)==0);
+#endif
+ else
+ BEGIN
+ AdrVals[AdrCnt++]=((AdrLong >> 16) & 0xff);
+#ifdef __STDC__
+ if ((AdrLong & 0xff000000u)==0) ChangeDDPrefix("IB");
+#else
+ if ((AdrLong & 0xff000000)==0) ChangeDDPrefix("IB");
+#endif
+ else
+ BEGIN
+ AdrVals[AdrCnt++]=((AdrLong >> 24) & 0xff);
+ ChangeDDPrefix("IW");
+ END
+ END
+ END
+ return;
+ END
+
+ /* ...immediate */
+
+ switch (OpSize)
+ BEGIN
+ case 0xff:
+ WrError(1132);
+ break;
+ case 0:
+ AdrVals[0]=EvalIntExpression(Asc_O,Int8,&OK);
+ if (OK)
+ BEGIN
+ AdrMode=ModImm; AdrCnt=1;
+ END;
+ break;
+ case 1:
+ if (InLongMode())
+ BEGIN
+ AdrLong=EvalIntExpression(Asc_O,Int32,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=Lo(AdrLong); AdrVals[1]=Hi(AdrLong);
+ AdrMode=ModImm; AdrCnt=2;
+#ifdef __STDC__
+ if ((AdrLong & 0xffff0000u)==0);
+#else
+ if ((AdrLong & 0xffff0000)==0);
+#endif
+ else
+ BEGIN
+ AdrVals[AdrCnt++]=(AdrLong >> 16) & 0xff;
+#ifdef __STDC__
+ if ((AdrLong & 0xff000000u)==0) ChangeDDPrefix("IB");
+#else
+ if ((AdrLong & 0xff000000)==0) ChangeDDPrefix("IB");
+#endif
+ else
+ BEGIN
+ AdrVals[AdrCnt++]=(AdrLong >> 24) & 0xff;
+ ChangeDDPrefix("IW");
+ END
+ END
+ END
+ END
+ else
+ BEGIN
+ AdrInt=EvalIntExpression(Asc_O,Int16,&OK);
+ if (OK)
+ BEGIN
+ AdrVals[0]=Lo(AdrInt); AdrVals[1]=Hi(AdrInt);
+ AdrMode=ModImm; AdrCnt=2;
+ END
+ END
+ break;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/* Bedingung entschluesseln */
+
+ static Boolean DecodeCondition(char *Name, int *Erg)
+BEGIN
+ int z;
+ String Name_N;
+
+ strmaxcpy(Name_N,Name,255); NLS_UpString(Name_N);
+
+ z=0;
+ while ((z<ConditionCnt) AND (strcmp(Conditions[z].Name,Name_N)!=0)) z++;
+ if (z>ConditionCnt) return False;
+ else
+ BEGIN
+ *Erg=Conditions[z].Code; return True;
+ END
+END
+
+/*-------------------------------------------------------------------------*/
+/* Sonderregister dekodieren */
+
+ static Boolean DecodeSFR(char *Inp, Byte *Erg)
+BEGIN
+ if (strcasecmp(Inp,"SR")==0) *Erg=1;
+ else if (strcasecmp(Inp,"XSR")==0) *Erg=5;
+ else if (strcasecmp(Inp,"DSR")==0) *Erg=6;
+ else if (strcasecmp(Inp,"YSR")==0) *Erg=7;
+ else return False;
+ return True;
+END
+
+/*=========================================================================*/
+
+ static Boolean DecodePseudo(void)
+BEGIN
+ if (Memo("PORT"))
+ BEGIN
+ CodeEquate(SegIO,0,PortEnd());
+ return True;
+ END
+
+ /* Kompatibilitaet zum M80 */
+
+ if (Memo("DEFB")) strmaxcpy(OpPart,"DB",255);
+ if (Memo("DEFW")) strmaxcpy(OpPart,"DW",255);
+
+ return False;
+END
+
+ static void DecodeLD(void)
+BEGIN
+ Byte AdrByte,HLen;
+ int z;
+ Byte HVals[5];
+
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart==7) /* LD A,... */
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8: /* LD A,R8/RX8/(HL)/(XY+D) */
+ BAsmCode[PrefixCnt]=0x78+AdrPart;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ break;
+ case ModIndReg16: /* LD A,(BC)/(DE) */
+ BAsmCode[0]=0x0a+(AdrPart << 4); CodeLen=1;
+ break;
+ case ModImm: /* LD A,imm8 */
+ BAsmCode[0]=0x3e; BAsmCode[1]=AdrVals[0]; CodeLen=2;
+ break;
+ case ModAbs: /* LD a,(adr) */
+ BAsmCode[PrefixCnt]=0x3a;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ break;
+ case ModRef: /* LD A,R */
+ BAsmCode[0]=0xed; BAsmCode[1]=0x5f;
+ CodeLen=2;
+ break;
+ case ModInt: /* LD A,I */
+ BAsmCode[0]=0xed; BAsmCode[1]=0x57;
+ CodeLen=2;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else if ((AdrPart!=6) AND (PrefixCnt==0)) /* LD R8,... */
+ BEGIN
+ AdrByte=AdrPart; OpSize=0; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8: /* LD R8,R8/RX8/(HL)/(XY+D) */
+ if (((AdrByte==4) OR (AdrByte==5)) AND (PrefixCnt==1) AND (AdrCnt==0)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0x40+(AdrByte << 3)+AdrPart;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ case ModImm: /* LD R8,imm8 */
+ BAsmCode[0]=0x06+(AdrByte << 3); BAsmCode[1]=AdrVals[0];
+ CodeLen=2;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else if ((AdrPart==4) OR (AdrPart==5)) /* LD RX8,... */
+ BEGIN
+ AdrByte=AdrPart; OpSize=0; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8: /* LD RX8,R8/RX8 */
+ if (AdrPart==6) WrError(1350);
+ else if ((AdrPart>=4) AND (AdrPart<=5) AND (PrefixCnt!=2)) WrError(1350);
+ else if ((AdrPart>=4) AND (AdrPart<=5) AND (BAsmCode[0]!=BAsmCode[1])) WrError(1350);
+ else
+ BEGIN
+ if (PrefixCnt==2) PrefixCnt--;
+ BAsmCode[PrefixCnt]=0x40+(AdrByte << 3)+AdrPart;
+ CodeLen=PrefixCnt+1;
+ END
+ break;
+ case ModImm: /* LD RX8,imm8 */
+ BAsmCode[PrefixCnt]=0x06+(AdrByte << 3);
+ BAsmCode[PrefixCnt+1]=AdrVals[0];
+ CodeLen=PrefixCnt+2;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else /* LD (HL)/(XY+d),... */
+ BEGIN
+ HLen=AdrCnt; memcpy(HVals,AdrVals,AdrCnt); z=PrefixCnt;
+ if ((z==0) AND (Memo("LDW")))
+ BEGIN
+ OpSize=1; MayLW=True;
+ END
+ else OpSize=0;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8: /* LD (HL)/(XY+D),R8 */
+ if ((PrefixCnt!=z) OR (AdrPart==6)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0x70+AdrPart;
+ memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
+ CodeLen=PrefixCnt+1+HLen;
+ END
+ break;
+ case ModImm: /* LD (HL)/(XY+D),imm8:16:32 */
+ if ((z==0) AND (Memo("LDW")))
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0x36;
+ memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+2+AdrCnt;
+ END
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0x36;
+ memcpy(BAsmCode+1+PrefixCnt,HVals,HLen);
+ BAsmCode[PrefixCnt+1+HLen]=AdrVals[0];
+ CodeLen=PrefixCnt+1+HLen+AdrCnt;
+ END
+ break;
+ case ModReg16: /* LD (HL)/(XY+D),R16/XY */
+ if (MomCPU<CPUZ380) WrError(1500);
+ else if (AdrPart==3) WrError(1350);
+ else if (HLen==0)
+ if (PrefixCnt==z) /* LD (HL),R16 */
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[0]=0xfd; BAsmCode[1]=0x0f+(AdrPart << 4);
+ CodeLen=2;
+ END
+ else /* LD (HL),XY */
+ BEGIN
+ CodeLen=PrefixCnt+1; BAsmCode[PrefixCnt]=0x31;
+ CodeLen=1+PrefixCnt;
+ END
+ else
+ if (PrefixCnt==z) /* LD (XY+D),R16 */
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
+ BAsmCode[PrefixCnt+1+HLen]=0x0b+(AdrPart << 4);
+ CodeLen=PrefixCnt+1+HLen+1;
+ END
+ else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
+ else
+ BEGIN
+ PrefixCnt--;
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
+ BAsmCode[PrefixCnt+1+HLen]=0x2b;
+ CodeLen=PrefixCnt+1+HLen+1;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ break;
+ case ModReg16:
+ if (AdrPart==3) /* LD SP,... */
+ BEGIN
+ OpSize=1; MayLW=True; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16: /* LD SP,HL/XY */
+ if (AdrPart!=2) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xf9; CodeLen=PrefixCnt+1;
+ END
+ break;
+ case ModImm: /* LD SP,imm16:32 */
+ BAsmCode[PrefixCnt]=0x31;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ break;
+ case ModAbs: /* LD SP,(adr) */
+ BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0x7b;
+ memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+2+AdrCnt;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else if (PrefixCnt==0) /* LD R16,... */
+ BEGIN
+ AdrByte=(AdrPart==2) ? 3 : AdrPart;
+ OpSize=1; MayLW=True; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModInt: /* LD HL,I */
+ if (MomCPU<CPUZ380) WrError(1500);
+ else if (AdrByte!=3) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xdd; BAsmCode[1]=0x57; CodeLen=2;
+ END
+ break;
+ case ModReg8:
+ if (AdrPart!=6) WrError(1350);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if (PrefixCnt==0) /* LD R16,(HL) */
+ BEGIN
+ BAsmCode[0]=0xdd; BAsmCode[1]=0x0f+(AdrByte << 4);
+ CodeLen=2;
+ END
+ else /* LD R16,(XY+d) */
+ BEGIN
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ BAsmCode[PrefixCnt+1+AdrCnt]=0x03+(AdrByte << 4);
+ CodeLen=PrefixCnt+1+AdrCnt+1;
+ END
+ break;
+ case ModReg16:
+ if (AdrPart==3) WrError(1350);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if (PrefixCnt==0) /* LD R16,R16 */
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ else if (AdrPart==0) AdrPart=2;
+ BAsmCode[0]=0xcd+(AdrPart << 4);
+ BAsmCode[1]=0x02+(AdrByte << 4);
+ CodeLen=2;
+ END
+ else /* LD R16,XY */
+ BEGIN
+ BAsmCode[PrefixCnt]=0x0b+(AdrByte << 4);
+ CodeLen=PrefixCnt+1;
+ END
+ break;
+ case ModIndReg16: /* LD R16,(R16) */
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xdd;
+ BAsmCode[1]=0x0c+(AdrByte << 4)+AdrPart;
+ END
+ break;
+ case ModImm: /* LD R16,imm */
+ if (AdrByte==3) AdrByte=2;
+ CodeLen=PrefixCnt+1+AdrCnt;
+ BAsmCode[PrefixCnt]=0x01+(AdrByte << 4);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ break;
+ case ModAbs: /* LD R16,(adr) */
+ if (AdrByte==3)
+ BEGIN
+ BAsmCode[PrefixCnt]=0x2a;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=1+PrefixCnt+AdrCnt;
+ END
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xed;
+ BAsmCode[PrefixCnt+1]=0x4b+(AdrByte << 4);
+ memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+2+AdrCnt;
+ END
+ break;
+ case ModSPRel: /* LD R16,(SP+D) */
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xdd;
+ BAsmCode[PrefixCnt+1]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
+ BAsmCode[PrefixCnt+2+AdrCnt]=0x01+(AdrByte << 4);
+ CodeLen=PrefixCnt+3+AdrCnt;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else /* LD XY,... */
+ BEGIN
+ OpSize=1; MayLW=True; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart!=6) WrError(1350);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if (AdrCnt==0) /* LD XY,(HL) */
+ BEGIN
+ BAsmCode[PrefixCnt]=0x33; CodeLen=PrefixCnt+1;
+ END
+ else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
+ else /* LD XY,(XY+D) */
+ BEGIN
+ BAsmCode[0]=BAsmCode[1]; PrefixCnt--;
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ BAsmCode[PrefixCnt+1+AdrCnt]=0x23;
+ CodeLen=PrefixCnt+1+AdrCnt+1;
+ END
+ break;
+ case ModReg16:
+ if (MomCPU<CPUZ380) WrError(1500);
+ else if (AdrPart==3) WrError(1350);
+ else if (PrefixCnt==1) /* LD XY,R16 */
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ CodeLen=1+PrefixCnt;
+ BAsmCode[PrefixCnt]=0x07+(AdrPart << 4);
+ END
+ else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
+ else /* LD XY,XY */
+ BEGIN
+ BAsmCode[--PrefixCnt]=0x27;
+ CodeLen=1+PrefixCnt;
+ END
+ break;
+ case ModIndReg16:
+ if (MomCPU<CPUZ380) WrError(1500);
+ else /* LD XY,(R16) */
+ BEGIN
+ BAsmCode[PrefixCnt]=0x03+(AdrPart << 4);
+ CodeLen=PrefixCnt+1;
+ END
+ break;
+ case ModImm: /* LD XY,imm16:32 */
+ BAsmCode[PrefixCnt]=0x21;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ break;
+ case ModAbs: /* LD XY,(adr) */
+ BAsmCode[PrefixCnt]=0x2a;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ break;
+ case ModSPRel: /* LD XY,(SP+D) */
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ BAsmCode[PrefixCnt+1+AdrCnt]=0x21;
+ CodeLen=PrefixCnt+1+AdrCnt+1;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ break;
+ case ModIndReg16:
+ AdrByte=AdrPart;
+ if (Memo("LDW"))
+ BEGIN
+ OpSize=1; MayLW=True;
+ END
+ else OpSize=0;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8: /* LD (R16),A */
+ if (AdrPart!=7) WrError(1350);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x02+(AdrByte << 4);
+ END
+ break;
+ case ModReg16:
+ if (AdrPart==3) WrError(1350);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if (PrefixCnt==0) /* LD (R16),R16 */
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[0]=0xfd; BAsmCode[1]=0x0c+AdrByte+(AdrPart << 4);
+ CodeLen=2;
+ END
+ else /* LD (R16),XY */
+ BEGIN
+ BAsmCode[PrefixCnt]=0x01+(AdrByte << 4);
+ CodeLen=PrefixCnt+1;
+ END
+ break;
+ case ModImm:
+ if (NOT Memo("LDW")) WrError(1350);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xed;
+ BAsmCode[PrefixCnt+1]=0x06+(AdrByte << 4);
+ memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+2+AdrCnt;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ break;
+ case ModAbs:
+ HLen=AdrCnt; memcpy(HVals,AdrVals,AdrCnt);
+ OpSize=0; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8: /* LD (adr),A */
+ if (AdrPart!=7) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0x32;
+ memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
+ CodeLen=PrefixCnt+1+HLen;
+ END
+ break;
+ case ModReg16:
+ if (AdrPart==2) /* LD (adr),HL/XY */
+ BEGIN
+ BAsmCode[PrefixCnt]=0x22;
+ memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
+ CodeLen=PrefixCnt+1+HLen;
+ END
+ else /* LD (adr),R16 */
+ BEGIN
+ BAsmCode[PrefixCnt]=0xed;
+ BAsmCode[PrefixCnt+1]=0x43+(AdrPart << 4);
+ memcpy(BAsmCode+PrefixCnt+2,HVals,HLen);
+ CodeLen=PrefixCnt+2+HLen;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ break;
+ case ModInt:
+ if (strcasecmp(ArgStr[2],"A")==0) /* LD I,A */
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x47;
+ END
+ else if (strcasecmp(ArgStr[2],"HL")==0) /* LD I,HL */
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xdd; BAsmCode[1]=0x47;
+ END
+ else WrError(1350);
+ break;
+ case ModRef:
+ if (strcasecmp(ArgStr[2],"A")==0) /* LD R,A */
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x4f;
+ END
+ else WrError(1350);
+ break;
+ case ModSPRel:
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ HLen=AdrCnt; memcpy(HVals,AdrVals,AdrCnt);
+ OpSize=0; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (AdrPart==3) WrError(1350);
+ else if (PrefixCnt==0) /* LD (SP+D),R16 */
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[PrefixCnt]=0xdd;
+ BAsmCode[PrefixCnt+1]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+2,HVals,HLen);
+ BAsmCode[PrefixCnt+2+HLen]=0x09+(AdrPart << 4);
+ CodeLen=PrefixCnt+2+HLen+1;
+ END
+ else /* LD (SP+D),XY */
+ BEGIN
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
+ BAsmCode[PrefixCnt+1+HLen]=0x29;
+ CodeLen=PrefixCnt+1+HLen+1;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END /* outer switch */
+ END
+END
+
+ static Boolean ParPair(char *Name1, char *Name2)
+BEGIN
+ return (((strcasecmp(ArgStr[1],Name1)==0) AND (strcasecmp(ArgStr[2],Name2)==0)) OR
+ ((strcasecmp(ArgStr[1],Name2)==0) AND (strcasecmp(ArgStr[2],Name1)==0)));
+END
+
+ static Boolean ImmIs8(void)
+BEGIN
+ Word tmp;
+
+ if (AdrCnt<2) return True;
+
+ tmp=(Word) AdrVals[AdrCnt-2];
+
+ return ((tmp<=255) OR (tmp>=0xff80));
+END
+
+ static Boolean CodeAri(void)
+BEGIN
+ int z;
+ Byte AdrByte;
+ Boolean OK;
+
+ for (z=0; z<ALUOrderCnt; z++)
+ if (Memo(ALUOrders[z].Name))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"A",255); ArgCnt=2;
+ END
+ if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"HL")==0)
+ BEGIN
+ if (NOT Memo("SUB")) WrError(1350);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModAbs:
+ BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0xd6;
+ memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+2+AdrCnt;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"SP")==0)
+ BEGIN
+ if (NOT Memo("SUB")) WrError(1350);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ BAsmCode[0]=0xed; BAsmCode[1]=0x92;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ CodeLen=PrefixCnt+1+AdrCnt;
+ BAsmCode[PrefixCnt]=0x80+(ALUOrders[z].Code << 3)+AdrPart;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ break;
+ case ModImm:
+ if (NOT ImmIs8()) WrError(1320);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0xc6+(ALUOrders[z].Code << 3);
+ BAsmCode[1]=AdrVals[0];
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+ else if ((strncmp(ALUOrders[z].Name,OpPart,strlen(ALUOrders[z].Name))==0) AND (OpPart[strlen(OpPart)-1]=='W'))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (PrefixCnt>0) /* wenn Register, dann nie DDIR! */
+ BEGIN
+ BAsmCode[PrefixCnt]=0x87+(ALUOrders[z].Code << 3);
+ CodeLen=1+PrefixCnt;
+ END
+ else if (AdrPart==3) WrError(1350);
+ else
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[0]=0xed; BAsmCode[1]=0x84+(ALUOrders[z].Code << 3)+AdrPart;
+ CodeLen=2;
+ END
+ break;
+ case ModReg8:
+ if ((AdrPart!=6) OR (AdrCnt==0)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xc6+(ALUOrders[z].Code << 3);
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xed; BAsmCode[1]=0x86+(ALUOrders[z].Code << 3);
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if (Memo("ADD"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart!=7) WrError(1350);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ CodeLen=PrefixCnt+1+AdrCnt;
+ BAsmCode[PrefixCnt]=0x80+AdrPart;
+ memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
+ break;
+ case ModImm:
+ CodeLen=PrefixCnt+1+AdrCnt;
+ BAsmCode[PrefixCnt]=0xc6;
+ memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ break;
+ case ModReg16:
+ if (AdrPart==3) /* SP */
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModImm:
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x82;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else if (AdrPart!=2) WrError(1350);
+ else
+ BEGIN
+ z=PrefixCnt; /* merkt, ob Indexregister */
+ OpSize=1; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if ((AdrPart==2) AND (PrefixCnt!=0) AND ((PrefixCnt!=2) OR (BAsmCode[0]!=BAsmCode[1]))) WrError(1350);
+ else
+ BEGIN
+ if (PrefixCnt==2) PrefixCnt--; CodeLen=1+PrefixCnt;
+ BAsmCode[PrefixCnt]=0x09+(AdrPart << 4);
+ END
+ break;
+ case ModAbs:
+ if (z!=0) WrError(1350);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0xc2;
+ memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+2+AdrCnt;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if (Memo("ADDW"))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (PrefixCnt>0) /* wenn Register, dann nie DDIR! */
+ BEGIN
+ BAsmCode[PrefixCnt]=0x87;
+ CodeLen=1+PrefixCnt;
+ END
+ else if (AdrPart==3) WrError(1350);
+ else
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[0]=0xed; BAsmCode[1]=0x84+AdrPart;
+ CodeLen=2;
+ END
+ break;
+ case ModReg8:
+ if ((AdrPart!=6) OR (AdrCnt==0)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xc6;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xed; BAsmCode[1]=0x86;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("ADC")) OR (Memo("SBC")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart!=7) WrError(1350);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ CodeLen=PrefixCnt+1+AdrCnt;
+ BAsmCode[PrefixCnt]=0x88+AdrPart;
+ memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
+ break;
+ case ModImm:
+ CodeLen=PrefixCnt+1+AdrCnt;
+ BAsmCode[PrefixCnt]=0xce;
+ memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ if ((Memo("SBC")) AND (CodeLen!=0)) BAsmCode[PrefixCnt]+=0x10;
+ END
+ break;
+ case ModReg16:
+ if ((AdrPart!=2) OR (PrefixCnt!=0)) WrError(1350);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (PrefixCnt!=0) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xed;
+ BAsmCode[1]=0x42+(AdrPart << 4);
+ if (Memo("ADC")) BAsmCode[1]+=8;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("ADCW")) OR (Memo("SBCW")))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
+ else
+ BEGIN
+ z=Ord(Memo("SBCW")) << 4;
+ OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (PrefixCnt>0) /* wenn Register, dann nie DDIR! */
+ BEGIN
+ BAsmCode[PrefixCnt]=0x8f+z;
+ CodeLen=1+PrefixCnt;
+ END
+ else if (AdrPart==3) WrError(1350);
+ else
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[0]=0xed; BAsmCode[1]=0x8c+z+AdrPart;
+ CodeLen=2;
+ END
+ break;
+ case ModReg8:
+ if ((AdrPart!=6) OR (AdrCnt==0)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xce + z; /* ANSI :-0 */
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+1+AdrCnt;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xed; BAsmCode[1]=0x8e + z;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("INC")) OR (Memo("DEC")) OR (Memo("INCW")) OR (Memo("DECW")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ z=Ord((Memo("DEC")) OR (Memo("DECW")));
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (OpPart[strlen(OpPart)-1]=='W') WrError(1350);
+ else
+ BEGIN
+ CodeLen=PrefixCnt+1+AdrCnt;
+ BAsmCode[PrefixCnt]=0x04+(AdrPart << 3)+z;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ END
+ break;
+ case ModReg16:
+ CodeLen=1+PrefixCnt;
+ BAsmCode[PrefixCnt]=0x03+(AdrPart << 4)+(z << 3);
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ for (z=0; z<ShiftOrderCnt; z++)
+ if (Memo(ShiftOrders[z]))
+ BEGIN
+ if ((ArgCnt==0) OR (ArgCnt>2)) WrError(1110);
+ else if ((z==6) AND (MomCPU!=CPUZ80U)) WrError(1500); /* SLIA undok. Z80 */
+ else
+ BEGIN
+ OpSize=0;
+ DecodeAdr(ArgStr[ArgCnt]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if ((PrefixCnt>0) AND (AdrPart!=6)) WrError(1350); /* IXL..IYU verbieten */
+ else
+ BEGIN
+ if (ArgCnt==1) OK=True;
+ else if (MomCPU!=CPUZ80U)
+ BEGIN
+ WrError(1500); OK=False;
+ END
+ else if ((AdrPart!=6) OR (PrefixCnt!=1) OR (NOT DecodeReg8(ArgStr[1],&AdrPart)))
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else OK=True;
+ if (OK)
+ BEGIN
+ CodeLen=PrefixCnt+1+AdrCnt+1;
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ BAsmCode[PrefixCnt+1+AdrCnt]=AdrPart+(z << 3);
+ if ((AdrPart==7) AND (z<4)) WrError(10);
+ END
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+ else if ((strncmp(OpPart,ShiftOrders[z],strlen(ShiftOrders[z]))==0) AND (OpPart[strlen(OpPart)-1]=='W'))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if ((MomCPU<CPUZ380) OR (z==6)) WrError(1500);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (PrefixCnt>0)
+ BEGIN
+ BAsmCode[2]=0x04+(z << 3)+((BAsmCode[0] >> 5) & 1);
+ BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
+ CodeLen=3;
+ END
+ else if (AdrPart==3) WrError(1350);
+ else
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
+ BAsmCode[2]=(z << 3)+AdrPart;
+ CodeLen=3;
+ END
+ break;
+ case ModReg8:
+ if (AdrPart!=6) WrError(1350);
+ else
+ BEGIN
+ if (AdrCnt==0)
+ BEGIN
+ BAsmCode[0]=0xed; PrefixCnt=1;
+ END
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ BAsmCode[PrefixCnt+1+AdrCnt]=0x02+(z << 3);
+ CodeLen=PrefixCnt+1+AdrCnt+1;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ for (z=0; z<BitOrderCnt; z++)
+ if (Memo(BitOrders[z]))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[ArgCnt]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if ((AdrPart!=6) AND (PrefixCnt!=0)) WrError(1350);
+ else
+ BEGIN
+ AdrByte=EvalIntExpression(ArgStr[ArgCnt-1],UInt3,&OK);
+ if (OK)
+ BEGIN
+ if (ArgCnt==2) OK=True;
+ else if (MomCPU!=CPUZ80U)
+ BEGIN
+ WrError(1500); OK=False;
+ END
+ else if ((AdrPart!=6) OR (PrefixCnt!=1) OR (z==0) OR (NOT DecodeReg8(ArgStr[1],&AdrPart)))
+ BEGIN
+ WrError(1350); OK=False;
+ END
+ else OK=True;
+ if (OK)
+ BEGIN
+ CodeLen=PrefixCnt+2+AdrCnt;
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ BAsmCode[PrefixCnt+1+AdrCnt]=AdrPart+(AdrByte << 3)+((z+1) << 6);
+ END
+ END
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if (Memo("MLT"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPUZ180) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ if ((AdrMode!=ModReg16) OR (PrefixCnt!=0)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[CodeLen]=0xed; BAsmCode[CodeLen+1]=0x4c+(AdrPart << 4);
+ CodeLen=2;
+ END
+ END
+ return True;
+ END
+
+ if ((Memo("DIVUW")) OR (Memo("MULTW")) OR (Memo("MULTUW")))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"HL",255); ArgCnt=2;
+ END
+ if (MomCPU<CPUZ380) WrError(1500);
+ else if (ArgCnt!=2) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"HL")!=0) WrError(1350);
+ else
+ BEGIN
+ AdrByte=Ord(*OpPart=='D');
+ z=Ord(OpPart[strlen(OpPart)-2]=='U');
+ OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if ((AdrPart!=6) OR (PrefixCnt==0)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xcb;
+ memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
+ BAsmCode[PrefixCnt+1+AdrCnt]=0x92+(z << 3)+(AdrByte << 5);
+ CodeLen=PrefixCnt+1+AdrCnt+1;
+ END
+ break;
+ case ModReg16:
+ if (AdrPart==3) WrError(1350);
+ else if (PrefixCnt==0)
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
+ BAsmCode[2]=0x90+AdrPart+(z << 3)+(AdrByte << 5);
+ CodeLen=3;
+ END
+ else
+ BEGIN
+ BAsmCode[2]=0x94+((BAsmCode[0] >> 5) & 1)+(z << 3)+(AdrByte << 5);
+ BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
+ CodeLen=3;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
+ BAsmCode[2]=0x97+(z << 3)+(AdrByte << 5);
+ memcpy(BAsmCode+3,AdrVals,AdrCnt);
+ CodeLen=3+AdrCnt;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if (Memo("TST"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPUZ180) WrError(1500);
+ else
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (PrefixCnt!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=4+(AdrPart << 3);
+ CodeLen=2;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xed; BAsmCode[1]=0x64; BAsmCode[2]=AdrVals[0];
+ CodeLen=3;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ if (Memo("SWAP"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (AdrPart==3) WrError(1350);
+ else if (PrefixCnt==0)
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[0]=0xed; BAsmCode[1]=0x0e + (AdrPart << 4); /*?*/
+ CodeLen=2;
+ END
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0x3e; CodeLen=PrefixCnt+1;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return True;
+ END
+
+ return False;
+END
+
+ static void MakeCode_Z80(void)
+BEGIN
+ Boolean OK;
+ LongWord AdrLong;
+ LongInt AdrLInt;
+ Byte AdrByte;
+ int z;
+
+ CodeLen=0; DontPrint=False; PrefixCnt=0; OpSize=0xff; MayLW=False;
+
+ /* zu ignorierendes */
+
+ if (Memo("")) return;
+
+ /* Pseudoanweisungen */
+
+ if (DecodePseudo()) return;
+
+ /* letzten Praefix umkopieren */
+
+ LastPrefix=CurrPrefix; CurrPrefix=Pref_IN_N;
+
+ /* evtl. Datenablage */
+
+ if (DecodeIntelPseudo(False)) return;
+
+/*--------------------------------------------------------------------------*/
+/* Instruktionspraefix */
+
+ if (Memo("DDIR"))
+ BEGIN
+ if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ OK=True;
+ for (z=1; z<=ArgCnt; z++)
+ if (OK)
+ BEGIN
+ NLS_UpString(ArgStr[z]);
+ OK=ExtendPrefix(&CurrPrefix,ArgStr[z]);
+ if (NOT OK) WrError(1135);
+ END
+ if (OK)
+ BEGIN
+ GetPrefixCode(CurrPrefix,BAsmCode+0,BAsmCode+1);
+ CodeLen=2;
+ END
+ END
+ return;
+ END
+
+/*--------------------------------------------------------------------------*/
+/* mit Sicherheit am haeufigsten... */
+
+ if ((Memo("LD")) OR (Memo("LDW")))
+ BEGIN
+ DecodeLD();
+ return;
+ END
+
+/*--------------------------------------------------------------------------*/
+/* ohne Operanden */
+
+ for (z=0; z<FixedOrderCnt; z++)
+ if (Memo(FixedOrders[z].Name))
+ BEGIN
+ if (ArgCnt!=0) WrError(1110);
+ else if (MomCPU<FixedOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ if ((CodeLen=FixedOrders[z].Len)==2)
+ BEGIN
+ BAsmCode[0]=Hi(FixedOrders[z].Code);
+ BAsmCode[1]=Lo(FixedOrders[z].Code);
+ END
+ else BAsmCode[0]=Lo(FixedOrders[z].Code);
+ END;
+ return;
+ END
+
+ /* nur Akku zugelassen */
+
+ for (z=0; z<AccOrderCnt; z++)
+ if (Memo(AccOrders[z].Name))
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ ArgCnt=1; strmaxcpy(ArgStr[1],"A",255);
+ END
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else if (MomCPU<AccOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ if ((CodeLen=AccOrders[z].Len)==2)
+ BEGIN
+ BAsmCode[0]=Hi(AccOrders[z].Code);
+ BAsmCode[1]=Lo(AccOrders[z].Code);
+ END
+ else BAsmCode[0]=Lo(AccOrders[z].Code);
+ END
+ return;
+ END
+
+ for (z=0; z<HLOrderCnt; z++)
+ if (Memo(HLOrders[z].Name))
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ ArgCnt=1; strmaxcpy(ArgStr[1],"HL",255);
+ END;
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"HL")!=0) WrError(1350);
+ else if (MomCPU<HLOrders[z].MinCPU) WrError(1500);
+ else
+ BEGIN
+ if ((CodeLen=HLOrders[z].Len)==2)
+ BEGIN
+ BAsmCode[0]=Hi(HLOrders[z].Code);
+ BAsmCode[1]=Lo(HLOrders[z].Code);
+ END
+ else BAsmCode[0]=Lo(HLOrders[z].Code);
+ END
+ return;
+ END
+
+/*-------------------------------------------------------------------------*/
+/* Datentransfer */
+
+ if ((Memo("PUSH")) OR (Memo("POP")))
+ BEGIN
+ z=Ord(Memo("PUSH")) << 2;
+ if (ArgCnt!=1) WrError(1110);
+ else if (strcasecmp(ArgStr[1],"SR")==0)
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0xc1+z;
+ END
+ else
+ BEGIN
+ if (strcasecmp(ArgStr[1],"SP")==0) strmaxcpy(ArgStr[1],"A",255);
+ if (strcasecmp(ArgStr[1],"AF")==0) strmaxcpy(ArgStr[1],"SP",255);
+ OpSize=1; MayLW=True;
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ CodeLen=1+PrefixCnt;
+ BAsmCode[PrefixCnt]=0xc1+(AdrPart << 4)+z;
+ break;
+ case ModImm:
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[PrefixCnt]=0xfd; BAsmCode[PrefixCnt+1]=0xf5;
+ memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
+ CodeLen=PrefixCnt+2+AdrCnt;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return;
+ END
+
+ if (Memo("EX"))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (ParPair("DE","HL"))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xeb;
+ END
+ else if (ParPair("AF","AF\'"))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x08;
+ END
+ else if (ParPair("AF","AF`"))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0x08;
+ END
+ else if (ParPair("(SP)","HL"))
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xe3;
+ END
+ else if (ParPair("(SP)","IX"))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=IXPrefix; BAsmCode[1]=0xe3;
+ END
+ else if (ParPair("(SP)","IY"))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=IYPrefix; BAsmCode[1]=0xe3;
+ END
+ else if (ParPair("(HL)","A"))
+ BEGIN
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x37;
+ END
+ END
+ else
+ BEGIN
+ if (ArgStr[2][strlen(ArgStr[2])-1]=='\'')
+ BEGIN
+ OK=True; ArgStr[2][strlen(ArgStr[2])-1]='\0';
+ END
+ else OK=False;
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if ((AdrPart==6) OR (PrefixCnt!=0)) WrError(1350);
+ else
+ BEGIN
+ AdrByte=AdrPart;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if ((AdrPart==6) OR (PrefixCnt!=0)) WrError(1350);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if ((AdrByte==7) AND (NOT OK))
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x07+(AdrPart << 3);
+ CodeLen=2;
+ END
+ else if ((AdrPart==7) AND (NOT OK))
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x07+(AdrByte << 3);
+ CodeLen=2;
+ END
+ else if ((OK) AND (AdrPart==AdrByte))
+ BEGIN
+ BAsmCode[0]=0xcb; BAsmCode[1]=0x30+AdrPart;
+ CodeLen=2;
+ END
+ else WrError(1350);
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ break;
+ case ModReg16:
+ if (AdrPart==3) WrError(1350);
+ else if (PrefixCnt==0) /* EX R16,... */
+ BEGIN
+ if (AdrPart==2) AdrByte=3; else AdrByte=AdrPart;
+ DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (AdrPart==3) WrError(1350);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if (OK)
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ if ((PrefixCnt!=0) OR (AdrPart!=AdrByte)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
+ BAsmCode[2]=0x30+AdrByte;
+ END
+ END
+ else if (PrefixCnt==0)
+ BEGIN
+ if (AdrByte==0)
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[0]=0xed; BAsmCode[1]=0x01+(AdrPart << 2);
+ CodeLen=2;
+ END
+ else if (AdrPart==0)
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x01+(AdrByte << 2);
+ CodeLen=2;
+ END
+ END
+ else
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[1]=0x03+((BAsmCode[0] >> 2) & 8)+(AdrByte << 4);
+ BAsmCode[0]=0xed;
+ CodeLen=2;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else /* EX XY,... */
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if (AdrPart==3) WrError(1350);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if (OK)
+ if ((PrefixCnt!=2) OR (BAsmCode[0]!=BAsmCode[1])) WrError(1350);
+ else
+ BEGIN
+ CodeLen=3; BAsmCode[2]=((BAsmCode[0] >> 5) & 1)+0x34;
+ BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
+ END
+ else if (PrefixCnt==1)
+ BEGIN
+ if (AdrPart==2) AdrPart=3;
+ BAsmCode[1]=((BAsmCode[0] >> 2) & 8)+3+(AdrPart << 4);
+ BAsmCode[0]=0xed;
+ CodeLen=2;
+ END
+ else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x2b; CodeLen=2;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ return;
+ END
+
+/*-------------------------------------------------------------------------*/
+/* Arithmetik */
+
+ if (CodeAri()) return;
+
+/*-------------------------------------------------------------------------*/
+/* Ein/Ausgabe */
+
+ if (Memo("TSTI"))
+ BEGIN
+ if (MomCPU!=CPUZ80U) WrError(1500);
+ else if (ArgCnt!=0) WrError(1110);
+ else
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x70; CodeLen=2;
+ END
+ return;
+ END
+
+ if ((Memo("IN")) OR (Memo("OUT")))
+ BEGIN
+ if ((ArgCnt==1) AND (Memo("IN")))
+ BEGIN
+ if (MomCPU!=CPUZ80U) WrError(1500);
+ else if (strcasecmp(ArgStr[1],"(C)")!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x70; CodeLen=2;
+ END
+ END
+ else if (ArgCnt!=2) WrError(1110);
+ else
+ BEGIN
+ if (Memo("OUT"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ if (strcasecmp(ArgStr[2],"(C)")==0)
+ BEGIN
+ OpSize=0; DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if ((AdrPart==6) OR (PrefixCnt!=0)) WrError(1350);
+ else
+ BEGIN
+ CodeLen=2;
+ BAsmCode[0]=0xed; BAsmCode[1]=0x40+(AdrPart << 3);
+ if (Memo("OUT")) BAsmCode[1]++;
+ END
+ break;
+ case ModImm:
+ if (Memo("IN")) WrError(1350);
+ else if ((MomCPU==CPUZ80U) AND (AdrVals[0]==0))
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x71; CodeLen=2;
+ END
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x71; BAsmCode[2]=AdrVals[0];
+ CodeLen=3;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[1]=EvalIntExpression(ArgStr[2],UInt8,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegIO);
+ CodeLen=2;
+ BAsmCode[0]=(Memo("OUT")) ? 0xd3 : 0xdb;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INW")) OR (Memo("OUTW")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ if (Memo("OUTW"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END;
+ if (strcasecmp(ArgStr[2],"(C)")!=0) WrError(1350);
+ else
+ BEGIN
+ OpSize=1; DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg16:
+ if ((AdrPart==3) OR (PrefixCnt>0)) WrError(1350);
+ else
+ BEGIN
+ switch (AdrPart)
+ BEGIN
+ case 1: AdrPart=2; break;
+ case 2: AdrPart=7; break;
+ END
+ BAsmCode[0]=0xdd; BAsmCode[1]=0x40+(AdrPart << 3);
+ if (Memo("OUTW")) BAsmCode[1]++;
+ CodeLen=2;
+ END
+ break;
+ case ModImm:
+ if (Memo("INW")) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xfd; BAsmCode[1]=0x79;
+ memcpy(BAsmCode+2,AdrVals,AdrCnt);
+ CodeLen=2+AdrCnt;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("IN0")) OR (Memo("OUT0")))
+ BEGIN
+ if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
+ else if ((ArgCnt==1) AND (Memo("OUT0"))) WrError(1110);
+ else if (MomCPU<CPUZ180) WrError(1500);
+ else
+ BEGIN
+ if (Memo("OUT0"))
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ OpSize=0;
+ if (ArgCnt==1)
+ BEGIN
+ AdrPart=6; OK=True;
+ END
+ else
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ if ((AdrMode==ModReg8) AND (AdrPart!=6) AND (PrefixCnt==0)) OK=True;
+ else
+ BEGIN
+ OK=False; if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ if (OK)
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[ArgCnt],UInt8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=AdrPart << 3;
+ if (Memo("OUT0")) BAsmCode[1]++;
+ CodeLen=3;
+ END
+ END
+ END
+ return;
+ END
+
+ if ((Memo("INA")) OR (Memo("INAW")) OR (Memo("OUTA")) OR (Memo("OUTAW")))
+ BEGIN
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ if (*OpPart=='O')
+ BEGIN
+ strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
+ END
+ OpSize=Ord(OpPart[strlen(OpPart)-1]=='W');
+ if (((OpSize==0) AND (strcasecmp(ArgStr[1],"A")!=0))
+ OR ((OpSize==1) AND (strcasecmp(ArgStr[1],"HL")!=0))) WrError(1350);
+ else
+ BEGIN
+ AdrLong=EvalIntExpression(ArgStr[2],ExtFlag?Int32:UInt8,&OK);
+ if (OK)
+ BEGIN
+ ChkSpace(SegIO);
+ if (AdrLong>0xffffff) ChangeDDPrefix("IW");
+ else if (AdrLong>0xffff) ChangeDDPrefix("IB");
+ BAsmCode[PrefixCnt]=0xed+(OpSize << 4);
+ BAsmCode[PrefixCnt+1]=0xd3+(Ord(*OpPart=='I') << 3);
+ BAsmCode[PrefixCnt+2]=AdrLong & 0xff;
+ BAsmCode[PrefixCnt+3]=(AdrLong >> 8) & 0xff;
+ CodeLen=PrefixCnt+4;
+ if (AdrLong>0xffff)
+ BAsmCode[CodeLen++]=(AdrLong >> 16) & 0xff;
+ if (AdrLong>0xffffff)
+ BAsmCode[CodeLen++]=(AdrLong >> 24) & 0xff;
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("TSTIO"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPUZ180) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0x74;
+ CodeLen=3;
+ END
+ END
+ return;
+ END
+
+/*-------------------------------------------------------------------------*/
+/* Spruenge */
+
+ if (Memo("RET"))
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xc9;
+ END
+ else if (ArgCnt!=1) WrError(1110);
+ else if (NOT DecodeCondition(ArgStr[1],&z)) WrError(1360);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xc0+(z << 3);
+ END
+ return;
+ END
+
+ if (Memo("JP"))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ if (strcasecmp(ArgStr[1],"(HL)")==0)
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xe9; OK=False;
+ END
+ else if (strcasecmp(ArgStr[1],"(IX)")==0)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=IXPrefix; BAsmCode[1]=0xe9; OK=False;
+ END
+ else if (strcasecmp(ArgStr[1],"(IY)")==0)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=IYPrefix; BAsmCode[1]=0xe9; OK=False;
+ END
+ else
+ BEGIN
+ z=1; OK=True;
+ END
+ END
+ else if (ArgCnt==2)
+ BEGIN
+ OK=DecodeCondition(ArgStr[1],&z);
+ if (OK) z<<=3; else WrError(1360);
+ END
+ else
+ BEGIN
+ WrError(1110); OK=False;
+ END
+ if (OK)
+ BEGIN
+ AdrLong=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
+ if (OK)
+#ifdef __STDC__
+ if ((AdrLong & 0xffff0000u)==0)
+#else
+ if ((AdrLong & 0xffff0000)==0)
+#endif
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xc2+z;
+ BAsmCode[1]=Lo(AdrLong); BAsmCode[2]=Hi(AdrLong);
+ END
+#ifdef __STDC__
+ else if ((AdrLong & 0xff000000u)==0)
+#else
+ else if ((AdrLong & 0xff000000)==0)
+#endif
+ BEGIN
+ ChangeDDPrefix("IB");
+ CodeLen=4+PrefixCnt; BAsmCode[PrefixCnt]=0xc2+z;
+ BAsmCode[PrefixCnt+1]=Lo(AdrLong);
+ BAsmCode[PrefixCnt+2]=Hi(AdrLong);
+ BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
+ END
+ else
+ BEGIN
+ ChangeDDPrefix("IW");
+ CodeLen=5+PrefixCnt; BAsmCode[PrefixCnt]=0xc2+z;
+ BAsmCode[PrefixCnt+1]=Lo(AdrLong);
+ BAsmCode[PrefixCnt+2]=Hi(AdrLong);
+ BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
+ BAsmCode[PrefixCnt+4]=Hi(AdrLong >> 16);
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALL"))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ z=9; OK=True;
+ END
+ else if (ArgCnt==2)
+ BEGIN
+ OK=DecodeCondition(ArgStr[1],&z);
+ if (OK) z<<=3; else WrError(1360);
+ END
+ else
+ BEGIN
+ WrError(1110); OK=False;
+ END
+ if (OK)
+ BEGIN
+ AdrLong=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
+ if (OK)
+#ifdef __STDC__
+ if ((AdrLong & 0xffff0000u)==0)
+#else
+ if ((AdrLong & 0xffff0000)==0)
+#endif
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xc4+z;
+ BAsmCode[1]=Lo(AdrLong); BAsmCode[2]=Hi(AdrLong);
+ END
+#ifdef __STDC__
+ else if ((AdrLong & 0xff000000u)==0)
+#else
+ else if ((AdrLong & 0xff000000)==0)
+#endif
+ BEGIN
+ ChangeDDPrefix("IB");
+ CodeLen=4+PrefixCnt; BAsmCode[PrefixCnt]=0xc4+z;
+ BAsmCode[PrefixCnt+1]=Lo(AdrLong);
+ BAsmCode[PrefixCnt+2]=Hi(AdrLong);
+ BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
+ END
+ else
+ BEGIN
+ ChangeDDPrefix("IW");
+ CodeLen=5+PrefixCnt; BAsmCode[PrefixCnt]=0xc4+z;
+ BAsmCode[PrefixCnt+1]=Lo(AdrLong);
+ BAsmCode[PrefixCnt+2]=Hi(AdrLong);
+ BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
+ BAsmCode[PrefixCnt+4]=Hi(AdrLong >> 16);
+ END
+ END
+ return;
+ END
+
+ if (Memo("JR"))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ z=3; OK=True;
+ END
+ else if (ArgCnt==2)
+ BEGIN
+ OK=DecodeCondition(ArgStr[1],&z);
+ if ((OK) AND (z>3)) OK=False;
+ if (OK) z+=4; else WrError(1360);
+ END
+ else
+ BEGIN
+ WrError(1110); OK=False;
+ END
+ if (OK)
+ BEGIN
+ AdrLInt=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
+ if (OK)
+ BEGIN
+ AdrLInt-=EProgCounter()+2;
+ if ((AdrLInt<=0x7fl) AND (AdrLInt>=-0x80l))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=z << 3;
+ BAsmCode[1]=AdrLInt & 0xff;
+ END
+ else
+ if (MomCPU<CPUZ380) WrError(1370);
+ else
+ BEGIN
+ AdrLInt-=2;
+ if ((AdrLInt<=0x7fffl) AND (AdrLInt>=-0x8000l))
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0xdd; BAsmCode[1]=z << 3;
+ BAsmCode[2]=AdrLInt & 0xff;
+ BAsmCode[3]=(AdrLInt >> 8) & 0xff;
+ END
+ else
+ BEGIN
+ AdrLInt--;
+ if ((AdrLInt<=0x7fffffl) AND (AdrLInt>=-0x800000l))
+ BEGIN
+ CodeLen=5; BAsmCode[0]=0xfd; BAsmCode[1]=z << 3;
+ BAsmCode[2]=AdrLInt & 0xff;
+ BAsmCode[3]=(AdrLInt >> 8) & 0xff;
+ BAsmCode[4]=(AdrLInt >> 16) & 0xff;
+ END
+ else WrError(1370);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("CALR"))
+ BEGIN
+ if (ArgCnt==1)
+ BEGIN
+ z=9; OK=True;
+ END
+ else if (ArgCnt==2)
+ BEGIN
+ OK=DecodeCondition(ArgStr[1],&z);
+ if (OK) z<<=3; else WrError(1360);
+ END
+ else
+ BEGIN
+ WrError(1110); OK=False;
+ END
+ if (OK)
+ if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ AdrLInt=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
+ if (OK)
+ BEGIN
+ AdrLInt-=EProgCounter()+3;
+ if ((AdrLInt<=0x7fl) AND (AdrLInt>=-0x80l))
+ BEGIN
+ CodeLen=3; BAsmCode[0]=0xed; BAsmCode[1]=0xc4+z;
+ BAsmCode[2]=AdrLInt & 0xff;
+ END
+ else
+ BEGIN
+ AdrLInt--;
+ if ((AdrLInt<=0x7fffl) AND (AdrLInt>=-0x8000l))
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0xdd; BAsmCode[1]=0xc4+z;
+ BAsmCode[2]=AdrLInt & 0xff;
+ BAsmCode[3]=(AdrLInt >> 8) & 0xff;
+ END
+ else
+ BEGIN
+ AdrLInt--;
+ if ((AdrLInt<=0x7fffffl) AND (AdrLInt>=-0x800000l))
+ BEGIN
+ CodeLen=5; BAsmCode[0]=0xfd; BAsmCode[1]=0xc4+z;
+ BAsmCode[2]=AdrLInt & 0xff;
+ BAsmCode[3]=(AdrLInt >> 8) & 0xff;
+ BAsmCode[4]=(AdrLInt >> 16) & 0xff;
+ END
+ else WrError(1370);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("DJNZ"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrLInt=EvalAbsAdrExpression(ArgStr[1],&OK);
+ if (OK)
+ BEGIN
+ AdrLInt-=EProgCounter()+2;
+ if ((AdrLInt<=0x7fl) AND (AdrLInt>=-0x80l))
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0x10; BAsmCode[1]=Lo(AdrLInt);
+ END
+ else if (MomCPU<CPUZ380) WrError(1370);
+ else
+ BEGIN
+ AdrLInt-=2;
+ if ((AdrLInt<=0x7fffl) AND (AdrLInt>=-0x8000l))
+ BEGIN
+ CodeLen=4; BAsmCode[0]=0xdd; BAsmCode[1]=0x10;
+ BAsmCode[2]=AdrLInt & 0xff;
+ BAsmCode[3]=(AdrLInt >> 8) & 0xff;
+ END
+ else
+ BEGIN
+ AdrLInt--;
+ if ((AdrLInt<=0x7fffffl) AND (AdrLInt>=-0x800000l))
+ BEGIN
+ CodeLen=5; BAsmCode[0]=0xfd; BAsmCode[1]=0x10;
+ BAsmCode[2]=AdrLInt & 0xff;
+ BAsmCode[3]=(AdrLInt >> 8) & 0xff;
+ BAsmCode[4]=(AdrLInt >> 16) & 0xff;
+ END
+ else WrError(1370);
+ END
+ END
+ END
+ END
+ return;
+ END
+
+ if (Memo("RST"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ FirstPassUnknown=False;
+ AdrByte=EvalIntExpression(ArgStr[1],Int8,&OK);
+ if (FirstPassUnknown) AdrByte=AdrByte & 0x38;
+ if (OK)
+ if ((AdrByte>0x38) OR ((AdrByte & 7)!=0)) WrError(1320);
+ else
+ BEGIN
+ CodeLen=1; BAsmCode[0]=0xc7+AdrByte;
+ END
+ END
+ return;
+ END
+
+/*-------------------------------------------------------------------------*/
+/* Sonderbefehle */
+
+ if ((Memo("EI")) OR (Memo("DI")))
+ BEGIN
+ if (ArgCnt==0)
+ BEGIN
+ BAsmCode[0]=0xf3+(Ord(Memo("EI")) << 3);
+ CodeLen=1;
+ END
+ else if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ BAsmCode[2]=EvalIntExpression(ArgStr[1],UInt8,&OK);
+ if (OK)
+ BEGIN
+ BAsmCode[0]=0xdd; BAsmCode[1]=0xf3+(Ord(Memo("EI")) << 3);
+ CodeLen=3;
+ END
+ END
+ return;
+ END
+
+ if (Memo("IM"))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else
+ BEGIN
+ AdrByte=EvalIntExpression(ArgStr[1],UInt2,&OK);
+ if (OK)
+ if (AdrByte>3) WrError(1320);
+ else if ((AdrByte==3) AND (MomCPU<CPUZ380)) WrError(1500);
+ else
+ BEGIN
+ if (AdrByte==3) AdrByte=1;
+ else if (AdrByte>=1) AdrByte++;
+ CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x46+(AdrByte << 3);
+ END
+ END
+ return;
+ END
+
+ if (Memo("LDCTL"))
+ BEGIN
+ OpSize=0;
+ if (ArgCnt!=2) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else if (DecodeSFR(ArgStr[1],&AdrByte))
+ BEGIN
+ DecodeAdr(ArgStr[2]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if (AdrPart!=7) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xcd+((AdrByte & 3) << 4);
+ BAsmCode[1]=0xc8+((AdrByte & 4) << 2);
+ CodeLen=2;
+ END
+ break;
+ case ModReg16:
+ if ((AdrByte!=1) OR (AdrPart!=2) OR (PrefixCnt!=0)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0xc8; CodeLen=2;
+ END
+ break;
+ case ModImm:
+ BAsmCode[0]=0xcd+((AdrByte & 3) << 4);
+ BAsmCode[1]=0xca+((AdrByte & 4) << 2);
+ BAsmCode[2]=AdrVals[0];
+ CodeLen=3;
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else if (DecodeSFR(ArgStr[2],&AdrByte))
+ BEGIN
+ DecodeAdr(ArgStr[1]);
+ switch (AdrMode)
+ BEGIN
+ case ModReg8:
+ if ((AdrPart!=7) OR (AdrByte==1)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xcd+((AdrByte & 3) << 4);
+ BAsmCode[1]=0xd0;
+ CodeLen=2;
+ END
+ break;
+ case ModReg16:
+ if ((AdrByte!=1) OR (AdrPart!=2) OR (PrefixCnt!=0)) WrError(1350);
+ else
+ BEGIN
+ BAsmCode[0]=0xed; BAsmCode[1]=0xc0; CodeLen=2;
+ END
+ break;
+ default: if (AdrMode!=ModNone) WrError(1350);
+ END
+ END
+ else WrError(1350);
+ return;
+ END
+
+ if ((Memo("RESC")) OR (Memo("SETC")))
+ BEGIN
+ if (ArgCnt!=1) WrError(1110);
+ else if (MomCPU<CPUZ380) WrError(1500);
+ else
+ BEGIN
+ AdrByte=0xff; NLS_UpString(ArgStr[1]);
+ if (strcmp(ArgStr[1],"LW")==0) AdrByte=1;
+ else if (strcmp(ArgStr[1],"LCK")==0) AdrByte=2;
+ else if (strcmp(ArgStr[1],"XM")==0) AdrByte=3;
+ else WrError(1440);
+ if (AdrByte!=0xff)
+ BEGIN
+ CodeLen=2; BAsmCode[0]=0xcd+(AdrByte << 4);
+ BAsmCode[1]=0xf7+(Ord(Memo("RESC")) << 3);
+ END
+ END
+ return;
+ END
+
+ WrXError(1200,OpPart);
+END
+
+ static void InitCode_Z80(void)
+BEGIN
+ SaveInitProc();
+ SetFlag(&ExtFlag,ExtFlagName,False);
+ SetFlag(&LWordFlag,LWordFlagName,False);
+END
+
+ static Boolean IsDef_Z80(void)
+BEGIN
+ return Memo("PORT");
+END
+
+ static void SwitchFrom_Z80(void)
+BEGIN
+ DeinitFields(); ClearONOFF();
+END
+
+ static void SwitchTo_Z80(void)
+BEGIN
+ TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=True;
+
+ PCSymbol="$"; HeaderID=0x51; NOPCode=0x00;
+ DivideChars=","; HasAttrs=False;
+
+ ValidSegs=(1<<SegCode)+(1<<SegIO);
+ Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
+ SegLimits[SegCode] = CodeEnd();
+ Grans[SegIO ]=1; ListGrans[SegIO ]=1; SegInits[SegIO ]=0;
+ SegLimits[SegIO ] = PortEnd();
+
+ MakeCode=MakeCode_Z80; IsDef=IsDef_Z80;
+ SwitchFrom=SwitchFrom_Z80; InitFields();
+
+ /* erweiterte Modi nur bei Z380 */
+
+ if (MomCPU>=CPUZ380)
+ BEGIN
+ AddONOFF("EXTMODE", &ExtFlag , ExtFlagName ,False);
+ AddONOFF("LWORDMODE", &LWordFlag , LWordFlagName ,False);
+ END
+ SetFlag(&ExtFlag,ExtFlagName,False);
+ SetFlag(&LWordFlag,LWordFlagName,False);
+END
+
+ void codez80_init(void)
+BEGIN
+ CPUZ80 =AddCPU("Z80" ,SwitchTo_Z80);
+ CPUZ80U=AddCPU("Z80UNDOC",SwitchTo_Z80);
+ CPUZ180=AddCPU("Z180",SwitchTo_Z80);
+ CPUZ380=AddCPU("Z380",SwitchTo_Z80);
+
+ SaveInitProc=InitPassProc; InitPassProc=InitCode_Z80;
+END
diff --git a/codez80.h b/codez80.h
new file mode 100644
index 0000000..c42114f
--- /dev/null
+++ b/codez80.h
@@ -0,0 +1,11 @@
+/* codez80.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Codegenerator Zilog Z80/180/380 */
+/* */
+/* Historie: 26.8.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern void codez80_init(void);
diff --git a/datatypes.h b/datatypes.h
new file mode 100644
index 0000000..532e581
--- /dev/null
+++ b/datatypes.h
@@ -0,0 +1,55 @@
+#include "sysdefs.h"
+
+typedef Card8 Byte; /* Integertypen */
+typedef Integ8 ShortInt;
+
+#ifdef HAS16
+typedef Card16 Word;
+typedef Integ16 Integer;
+#endif
+
+typedef Card32 LongWord;
+typedef Integ32 LongInt;
+
+#ifdef HAS64
+typedef Card64 QuadWord;
+typedef Integ64 QuadInt;
+#endif
+
+#ifdef HAS64
+typedef QuadInt LargeInt;
+typedef QuadWord LargeWord;
+#define LARGEBITS 64
+#else
+typedef LongInt LargeInt;
+typedef LongWord LargeWord;
+#define LARGEBITS 32
+#endif
+
+typedef signed int sint;
+typedef unsigned int usint;
+
+typedef char Char;
+
+typedef double Double;
+typedef float Single;
+
+typedef Byte Boolean;
+
+typedef char String[256];
+typedef char ShortString[65];
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef True
+#define True 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef False
+#define False 0
+#endif
+
diff --git a/doc_DE/Makefile b/doc_DE/Makefile
new file mode 100644
index 0000000..946e431
--- /dev/null
+++ b/doc_DE/Makefile
@@ -0,0 +1,37 @@
+INCFILES = taborg*.tex pscpu.tex pscomm.tex
+
+all: as.doc as.html as.ps
+
+as.ps: as.dvi
+ dvips as -o
+
+as.dvi: as.tex $(INCFILES)
+ latex as
+ latex as
+ makeindex as
+ latex as
+
+as.doc: as.tex $(INCFILES) $(TEX2DOC)
+ $(TEX2DOC) as.tex as.doc
+ $(TEX2DOC) as.tex as.doc
+
+as.html: as.tex $(INCFILES) $(TEX2HTML)
+ $(TEX2HTML) as.tex as.html
+ $(TEX2HTML) as.tex as.html
+
+clean:
+ $(RM) as.dvi
+ $(RM) as.ps
+ $(RM) as.i*
+ $(RM) *log
+ $(RM) as.aux
+ $(RM) as.toc
+ $(RM) *~
+ $(RM) DEADJOE
+ $(RM) as.doc
+ $(RM) as.dtoc
+ $(RM) as.daux
+ $(RM) as.html
+ $(RM) as.htoc
+ $(RM) as.haux
+ $(RM) commpseudo.tex cpupseudo.tex
diff --git a/doc_DE/as.tex b/doc_DE/as.tex
new file mode 100644
index 0000000..32db43c
--- /dev/null
+++ b/doc_DE/as.tex
@@ -0,0 +1,11792 @@
+%%TITLE Bedienungsanleitung Makroassembler AS
+\documentstyle[german,12pt,dina4,twoside,makeidx]{report}
+\pagestyle{headings}
+\sloppy
+\textwidth 15cm
+\evensidemargin 0.5cm
+\oddsidemargin 0.5cm
+\topsep 1mm
+\parskip 0.3cm plus0.2cm minus0.2cm
+
+\hyphenation{Lis-ting-er-zeu-gung}
+\hyphenation{back-slash}
+
+\newif\ifelektor
+\elektorfalse
+
+\newcommand{\ii}[1]{{\it #1}}
+\newcommand{\bb}[1]{{\bf #1}}
+\newcommand{\tty}[1]{{\tt #1}}
+\newcommand{\tin}[1]{{\scriptsize #1}}
+\newcommand{\ttindex}[1]{\index{#1@{\tt #1}}}
+
+\font\mengft=cmss9 scaled \magstep1
+\def \rz{\hbox{\mengft{I \hskip -1.7mm R}}}
+
+\makeindex
+
+%%===========================================================================
+
+\begin{document}
+
+\thispagestyle{empty}
+
+\
+\vspace{7cm}\par
+
+\begin{raggedright}
+{\large Alfred Arnold}\\
+\vspace{1cm}\par
+{\huge Makroassembler AS V1.41r8}\\
+\rule{9.5cm}{0.3mm}\\
+\vspace{2mm}\par
+{\huge Benutzeranleitung}
+
+\vspace{1cm}\par
+
+{\large Stand November 1999}
+\end{raggedright}
+
+\clearpage
+\thispagestyle{empty}
+
+\ \vspace{4cm}
+
+{\em IBM, PPC403Gx, OS/2} und {\em PowerPC} sind eingetragene Warenzeichen
+der IBM Corporation.
+
+{\em Intel, MCS-48, MCS-51, MCS-251, MCS-96, MCS-196} und {\em MCS-296}
+sind eingetragene Warenzeichen der Intel Corp. .
+
+{\em Motorola} und {\em ColdFire} sind eingetragene Warenzeichen von
+Motorola Inc. .
+
+{\em UNIX} ist ein eingetragenes Warenzeichen der X/Open Company.
+
+{\em Linux} ist ein eingetragenes Warenzeichen von Linus Thorvalds.
+
+{\em Microsoft, Windows} und {\em MS-DOS} sind eingetragene Warenzeichen
+der Microsoft Corporation.
+
+Alle anderen Warenzeichen, die nicht ausdr"ucklich in diesem Abschnitt
+genannt wurden und in diesem Handbuch verwendet werden, sind Eigentum
+der entsprechenden Eigent"umer.
+
+\vspace{9cm}
+
+Dieses Dokument wurde mit dem LaTeX-Satzsystem unter den Betriebssystemen
+Digital Unix, Linux und OS/2 auf AMD K6- und DEC Alpha-Prozessoren
+angefertigt und formatiert.
+
+\clearpage
+
+%%===========================================================================
+
+\ifelektor
+\thispagestyle{empty} \
+\clearpage
+\thispagestyle{empty} \
+\clearpage
+\fi
+
+%%===========================================================================
+
+{\parskip 0cm plus0.1cm \tableofcontents}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Allgemeines}
+
+Diese Anleitung wendet sich an Leute, die bereits in Assembler programmiert
+haben und sich dar"uber informieren m"ochten, wie man mit AS umgeht. Sie
+hat eher die Form eines Referenz- und nicht Benutzerhandbuches. Als solches
+macht sie weder den Versuch, die Sprache Assembler an sich zu erkl"aren, noch
+erl"autert sie die Architektur bestimmter Prozessoren. Im Literaturverzeichnis
+habe ich weiterf"uhrende Literatur aufgelistet, die bei der Implementation der
+einzelnen Codegeneratoren ma"sgebend war. Um Assembler von Grund auf zu
+lernen, kenne ich kein Buch; ich habe es im wesentlichen im ,,Trial and
+error''-Verfahren gelernt.
+
+%%---------------------------------------------------------------------------
+
+\section{Lizenzbedingungen}
+\label{SectLicense}
+
+Bevor es in medias res geht, erst einmal der unvermeidliche Prolog:
+\par
+AS in der vorliegenden Version gebe ich als ,,Public Domain'' weiter,
+d.h. die Programm-und Overlaydatei sowie die dazugeh"orenden
+Hilfsprogramme d"urfen frei kopiert und benutzt werden. Es existieren keine
+Planungen, AS in ein kommerzielles oder Shareware-Programm umzuwandeln. Diese
+Erlaubnis gilt jedoch nur unter der Voraussetzung, da"s die Startmeldung
+der Programme --- insbesondere die Copyrightmeldung --- nicht entfernt oder
+"uberschrieben wird und f"ur das Kopieren/Verschicken nicht mehr als
+eine Aufwandsentsch"adigung (unter DM 20,-) verlangt wird.
+\par
+Auf Anfrage wird auch der Quellcode dieses Programmes ausgegeben.
+Daraus abgeleitete oder darauf aufbauende Programme m"ussen unter
+den gleichen Bedingungen weitergegeben werden wie dieses Programm.
+\par
+Ich fordere ausdr"ucklich dazu auf, dieses Programm per Diskette oder
+Mailbox/Netzwerk zu verbreiten!
+\par
+Es mag sein, da"s Sie dieses Programm als Beilage zu einem kommerziellen
+Programm erhalten haben. Die f"ur das kommerzielle Programm geltenden
+Lizenzbedingungen beziehen sich jedoch auf keinen Fall auf AS.
+\par
+Sollte Ihnen der Assembler so gut gefallen, da"s sie mir unbedingt
+Geld daf"ur schicken wollen, so fordere ich Sie dazu auf, den Betrag
+f"ur Greenpeace zu spenden.
+\par
+Ich habe mich bem"uht, das Programm so fehlerfrei wie nur irgendm"oglich
+zu machen. Da es aber grunds"atzlich keine fehlerfreie Software
+gibt (die einzigen Leute, die keine Fehler machen, liegen auf dem
+Friedhof!), "ubernehme ich keine Garantie f"ur die Funktion von AS
+in einer bestimmten Umgebung (Hard-oder Software) oder Haftung f"ur
+entstehende Sch"aden. F"ur Hinweise auf Fehler bin ich selbstverst"andlich
+immer dankbar und werde mich bem"uhen, sie zu korrigieren.
+\par
+Um eine m"oglichst schnelle Fehlerdiagnose und -korrektur zu erm"oglichen,
+bitte ich, dem Fehlerbericht folgende Angaben beizuf"ugen:
+\begin{itemize}
+\item{Hardware: \begin{itemize}
+ \item{Prozessortyp (mit/ohne Koprozessor)}
+ \item{Speicherausbau}
+ \item{Grafikkarte}
+ \item{Festplatte und Typ deren Interfaces}
+ \end{itemize}}
+\item{Software: \begin{itemize}
+ \item{Betriebssystem (MS/DR/Novell-DOS, OS/2, Windows)
+ und Version}
+ \item{installierte speicherresidente Programme}
+ \item{benutzte Version von AS + Datum des EXE-Files}
+ \end{itemize}}
+\item{m"oglicht die Quelldatei, bei der der Fehler auftritt}
+\end{itemize}
+Zu erreichen bin ich folgenderma"sen:
+\begin{itemize}
+\item{per Post: \begin{description}
+ \item{Alfred Arnold}
+ \item{Hirschgraben 29}
+ \item{52062 Aachen}
+ \end{description}}
+\item{per E-Mail: \tty{alfred@ccac.rwth-aachen.de}}
+\end{itemize}
+Wer mir pers"onlich Fragen stellen will (und in der N"ahe von Aachen
+wohnt), kann dies mit hoher Wahrscheinlichkeit donnerstags von 19.00
+bis 21.00 Uhr im Computerclub an der RWTH Aachen (Eilfschornsteinstra"se 16,
+Keller Philosophengeb"aude R"uckseite).
+\par
+Von Telefonanrufen bitte ich abzusehen. Erstens, weil sich die
+komplizierten Zusammenh"ange am Telefon nur "au"serst schwer er"orten
+lassen, und zweitens ist die Telekom schon reich genug...
+\par
+Die neueste Version von AS (DOS,DPMI,OS/2) findet sich auf folgendem
+FTP-Server:
+\begin{verbatim}
+ ftp.uni-stuttgart.de
+ Verzeichnis pub/systems/msdos/programming/as
+\end{verbatim}
+Die Quellen der C-Version k"onnen von folgendem Server geholt werden:
+\begin{verbatim}
+ sunsite.unc.edu
+ Verzeichnis pub/Linux/devel/lang/assemblers/asl-<version>.tar.gz
+\end{verbatim}
+...und damit nat"urlich von jedem Sunsite-Spiegel der Welt!
+\par
+Wer "uber keinen FTP-Zugang verf"ugt, kann den Assembler auch von mir
+anfordern. Ich werde aber nur Anfragen beantworten, die zwei Disketten (f"ur
+720K/1,2M-Format 4/3 St"uck) und einen passenden, frankierten R"uckumschlag
+enthalten. \bb{KEIN} Geld schicken!!!
+\par
+So. Nach diesem unvermeidlichen Vorwort k"onnen wir wohl beruhigt
+zur eigentlichen Anleitung schreiten:
+
+%%---------------------------------------------------------------------------
+
+\section{allgemeine F"ahigkeiten des Assemblers}
+
+AS bietet im Gegensatz zu normalen Assemblern die M"oglichkeit, Code
+f"ur v"ollig verschiedene Prozessoren zu erzeugen. Momentan sind
+folgende Prozessorfamilien implementiert:
+\begin{itemize}
+\item{Motorola 68000..68040,683xx inkl. Koprozessor und MMU}
+\item{Motorola ColdFire}
+\item{Motorola DSP5600x,DSP56300}
+\item{Motorola/IBM MPC601/MPC505/PPC403}
+\item{Motorola M-Core}
+\item{Motorola 6800, 6805, 68HC08, 6809, 68(HC)11, 68HC12, 68HC16 sowie Hitachi 6301}
+\item{Hitachi 6309}
+\item{Hitachi H8/300(H)}
+\item{Hitachi H8/500}
+\item{Hitachi SH7000/7600/7700}
+\item{Rockwell 6502 und 65(S)C02}
+\item{CMD 65816}
+\item{Mitsubishi MELPS-740}
+\item{Mitsubishi MELPS-7700}
+\item{Mitsubishi MELPS-4500}
+\item{Mitsubishi M16}
+\item{Mitsubishi M16C}
+\item{Intel 4004}
+\item{Intel MCS-48/41}
+\item{Intel MCS-51/251}
+\item{Intel MCS-96/196(Nx)/296}
+\item{Intel 8080/8085}
+\item{Intel i960}
+\item{Signetics 8X30x}
+\item{Philips XA}
+\item{Atmel AVR}
+\item{AMD 29K}
+\item{Siemens 80C166/167}
+\item{Zilog Z80, Z180, Z380}
+\item{Zilog Z8}
+\item{Toshiba TLCS-900(L)}
+\item{Toshiba TLCS-90}
+\item{Toshiba TLCS-870}
+\item{Toshiba TLCS-47}
+\item{Toshiba TLCS-9000}
+\item{Microchip PIC16C54..16C57}
+\item{Microchip PIC16C84/PIC16C64}
+\item{Microchip PIC17C42}
+\item{SGS-Thomson ST6}
+\item{SGS-Thomson ST7}
+\item{SGS-Thomson ST9}
+\item{SGS-Thomson 6804}
+\item{Texas Instruments TMS32010/32015}
+\item{Texas Instruments TMS3202x}
+\item{Texas Instruments TMS320C3x}
+\item{Texas Instruments TMS320C20x/TMS320C5x}
+\item{Texas Instruments TMS320C6x}
+\item{Texas Instruments TMS9900}
+\item{Texas Instruments TMS7000}
+\item{Texas Instruments TMS370xxx}
+\item{Texas Instruments MSP430}
+\item{National Semiconductor SC/MP}
+\item{National Semiconductor COP8}
+\item{National Semiconductor SC144xx}
+\item{Fairchild ACE}
+\item{NEC $\mu$PD78(C)1x}
+\item{NEC $\mu$PD75xxx (alias 75K0)}
+\item{NEC $\mu$PD78xxx (alias 78K0)}
+\item{NEC $\mu$PD7720/7725}
+\item{NEC $\mu$PD77230}
+\item{Fujitsu F$^2$MC8L}
+\item{Symbios Logic SYM53C8xx (ja, die kann man programmieren!)}
+\end{itemize}
+in Arbeit / Planung / "Uberlegung :
+\begin{itemize}
+\item{Intel 8008}
+\item{Analog Devices ADSP21xx}
+\item{SGS-Thomson ST20}
+\item{Texas Instruments TMS320C4x}
+\item{Texas Instruments TMS320C8x}
+\item{Toshiba TC9331}
+\end{itemize}
+Noch gesucht werden Unterlagen f"ur:
+\begin{itemize}
+\item{NEC 78K4}
+\item{die ganze Palette der OKI-Controller}
+\end{itemize}
+ungeliebt, aber {\it doch} vorhanden :
+\begin{itemize}
+\item{Intel 8086, 80186, NEC V30\&V35 inkl. Koprozessor 8087}
+\end{itemize}
+Die Umschaltung des Codegenerators darf dabei auch mitten in der Datei
+erfolgen, und das beliebig oft!
+\par
+Der Grund f"ur diese Flexibilit"at ist, da"s AS eine Vorgeschichte hat,
+die auch in der Versionsnummer deutlich wird: AS ist als Erweiterung eines
+Makroassemblers f"ur die 68000er-Familie entstanden. Auf besonderen
+Wunsch habe ich den urspr"unglichen Assembler um die F"ahigkeit zur
+"Ubersetzung von 8051-Mnemonics erweitert, und auf dem Weg (Abstieg?!) vom
+68000 zum 8051 sind eine Reihe anderer fast nebenbei abgefallen...die
+restlichen Prozessoren wurden allesamt auf Benutzeranfrage hin integriert.
+Zumindest beim prozessorunabh"angigen Kern kann man also getrost davon
+ausgehen, da"s er gut ausgetestet und von offensichtlichen Bugs frei ist.
+Leider habe ich aber h"aufig mangels passender Hardware nicht die
+M"oglichkeit, einen neuen Codegenerator praktisch zu testen, so da"s bei
+Neuerungen "Uberraschungen nie ganz auszuschlie"sen sind. Das in
+Abschnitt \ref{SectLicense} gesagte hat also schon seinen Grund...
+\par
+Diese Flexibilit"at bedingt ein etwas exotisches Codeformat, f"ur dessen
+Bearbeitung ich einige Tools beigelegt habe. Deren Beschreibung findet
+sich in Abschnitt \ref{ChapTools}.
+\par
+AS ist ein Makroassembler, d.h. dem Programmierer ist die M"oglichkeit
+gegeben, sich mittels Makros neue ,,Befehle'' zu definieren. Zus"atzlich
+beherrscht er die bedingte Assemblierung. Labels in Makror"umpfen werden
+automatisch als lokal betrachtet.
+\par
+Symbole k"onnen f"ur den Assembler sowohl Integer-, String- als auch
+Gleitkommawerte haben. Diese werden --- wie Zwischergebnisse bei Formeln
+--- mit einer Breite von 32 Bit f"ur Integerwerte, 80/64 Bit f"ur
+Gleitkommawerte und 255 Zeichen f"ur Strings gespeichert. F"ur eine Reihe
+von Mikrokontrollern besteht die M"oglichkeit, durch Segmentbildung die
+Symbole bestimmten Klassen zuzuordnen. Dem Assembler kann man auf diese
+Weise die --- begrenzte --- M"oglichkeit geben, Zugriffe in falsche
+Adre"sr"aume zu erkennen.
+\par
+Der Assembler kennt keine expliziten Beschr"ankungen bzgl.
+Verschachtelungstiefe von Includefiles oder Makros, eine Grenze bildet
+lediglich die durch den Hauptspeicher beschr"ankte Rekursionstiefe.
+Ebenso gibt es keine Grenze f"ur die Symboll"ange, diese wird nur durch
+die maximale Zeilenl"ange begrenzt.
+\par
+Ab Version 1.38 ist AS ein Mehrpass-Assembler. Dieser hochtrabende Begriff
+bedeutet nicht mehr, als das die Anzahl der Durchg"ange durch die Quelltexte
+nicht mehr zwei sein mu"s. Sind keine Vorw"artsreferenzen im Quellcode
+enthalten, so kommt AS mit einem Durchgang aus. Stellt sich dagegen im zweiten
+Durchgang heraus, da"s ein Befehl mit einer k"urzeren oder l"angeren Kodierung
+benutzt werden mu"s, so wird ein dritter (vierter, f"unfter...) Durchgang
+eingelegt, um alle Symbolreferenzen richtig zu stellen. Mehr steckt hinter dem
+Begriff ,,Multipass'' nicht...er wird im weiteren Verlauf dieser Anleitung
+deswegen auch nicht mehr auftauchen.
+\par
+Nach soviel Lobhudelei ein dicker Wermutstropfen: AS erzeugt keinen
+linkf"ahigen Code. Eine Erweiterung um einen Linker w"are mit erheblichem
+Aufwand verbunden und ist momentan nicht in Planung.
+\par
+Zum Thema ,,Herausgabe von Sourcen'': Die Sourcen von AS sind nicht
+in einer Form, die ein einfaches Verst"andnis erm"oglicht (== null
+Kommentare). Sourcen werde ich daher nur f"ur den Fall herausgeben,
+da"s jemand wirklich damit etwas anfangen will (z.B. AS auf
+einen anderen Rechner portieren) und das daraus entstehende wiederum
+Public Domain wird. Insbesondere will ich verhindern, da"s jemand
+5 Zeilen "andert (bevorzugt den Copyrighteintrag) und das Ergebnis
+dann kommerziell als ,,sein'' Programm vertreibt.
+
+%%----------------------------------------------------------------------
+
+\section{Unterst"utzte Plattformen}
+
+Obwohl AS als ein reines DOS-Programm \marginpar{{\em DOS}} angefangen
+hat, stehen auch eine Reihe von Versionen zur Verf"ugung, die etwas mehr
+als den Real-Mode eines Intel-Prozessors ausnutzen k"onnen. Diese sind in
+ihrer Benutzung soweit als m"oglich kompatibel gehalten zur DOS-Version,
+es ergeben sich nat"urlich bisweilen Unterschiede in der Installation und
+der Einbindung in die jeweilige Betriebssystemumgebung. Abschnitte in
+dieser Anleitung, die nur f"ur eine bestimmte Version von AS gelten, sind
+mit einer entsprechenden Randbemerkung (an diesem Absatz f"ur die
+DOS-Version) gekennzeichnet. Im einzelnen existieren die folgenden,
+weiteren Versionen (die als getrennte Pakete distributiert werden):
+
+F"ur den Fall, da"s \marginpar{{\em DPMI}} man bei der "Ubersetzung
+gro"ser, komplexer Programme unter DOS Speicherplatzprobleme bekommt,
+existiert eine DOS-Version, die mittels eines DOS-Extenders im Protected
+Mode abl"auft und so das komplette Extended Memory eines ATs nutzen kann.
+Die "Ubersetzung wird durch den Extender merklich langsamer, aber immerhin
+l"auft es dann noch...
+
+F"ur Freunde von IBM's Betriebssystem OS/2 \marginpar{{\em OS/2}} gibt es
+eine native OS/2-Version von AS. Diese ist zwar zur Zeit nur 16-bittig,
+aber man erspart sich immerhin den Umweg "uber DOS-Boxen und hat auch
+keine Probleme mehr mit l"angeren Dateinamen.
+
+Den reinen PC-Bereich verl"a"st man mit der \marginpar{{\em UNIX}}
+C-Version von AS, die so gehalten wurde, da"s sie auf einer m"oglichst
+gro"sen Zahl von UNIX-artigen Systemen (dazu z"ahlt aber auch OS/2 mit dem
+emx-Compiler) ohne gro"sartige Verrenkungen "ubersetzbar ist. Im
+Gegensatz zu den vorherigen Versionen (die auf den auf Anfrage
+erh"altlichen Pascal-Sourcen basieren) wird die C-Version im Quellcode
+ausgeliefert, d.h. man mu"s sich mittels eines Compilers selbst die
+Binaries erzeugen. Dies ist aber (f"ur mich) der eindeutig einfachere
+Weg, als ein Dutzend Binaries f"ur Maschinen vorzukompilieren, auf die ich
+auch nicht immer Zugriff habe...
+
+Wer die bisherige \marginpar{{\em ???}} Aufz"ahlung liest, wird
+feststellen, da"s das meistverkaufte Betriebssystem der Welt aus Redmont
+in dieser Aufz"ahlung fehlt. Wer mich pers"onlich kennt, wei"s, da"s ich
+Windows (egal, ob 3.X, 95 oder NT) {\em nicht} f"ur das Ei des Kolumbus
+halte. Kurzgesagt, ich bin ein ,,Windows-Hasser''. Auch wenn eine gro"se
+Zahl an Leuten diese Einstellung f"ur "uberholt bis l"acherlich erachten
+und mir jetzt vorhalten, ich w"urde hier einem gro"sen Teil potentieller
+Anwender AS vorenthalten, so werden sie sich doch damit abfinden m"ussen:
+Ich treibe die Entwicklung an AS prim"ar weiter, weil sie mir {\em Spa"s}
+macht; AS ist ein nicht-kommerzielles Projekt und ich nehme mir deswegen
+die Freiheit, nicht auf potentielle Marktanteile zu schielen. Ich suche
+mir die Plattformen aus, auf denen das Programmieren {\em mir} Spa"s
+macht, und Programmieren unter Windows macht mir definitiv keinen Spa"s!
+Ich habe "ubrigens durchaus schon einmal Windows-Programme schreiben
+m"ussen, es ist also nicht so, da"s ich hier ohne Erfahrung etwas
+daherreden w"urde. Sofern irgendjemand AS in diese Richtung portieren
+will, werde ich mich ihm nicht in den Weg stellen, "uber die Sourcen
+hinaus hat er aber nicht viel Hilfe von mir zu erwarten (und mu"s sich
+selber mit den Anfragen der Qualit"at herumschlagen, warum AS denn jetzt
+nicht mehr l"auft, nachdem man den Brummi-CAD 18.53-Eintrag in der
+Registry von Gro"s- in Kleinbuchstaben ge"andert hat...).
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Benutzung des Assemblers}
+
+\begin{quote}\begin{raggedright}{\it
+Scotty: Captain, we din\verb!'! can reference it! \\
+Kirk: Analysis, Mr. Spock? \\
+Spock: Captain, it doesn\verb!'!t appear in the symbol table. \\
+Kirk: Then it\verb!'!s of external origin? \\
+Spock: Affirmative. \\
+Kirk: Mr. Sulu, go to pass two. \\
+Sulu: Aye aye, sir, going to pass two. \\
+}\end{raggedright}\end{quote}
+
+%%---------------------------------------------------------------------------
+
+\section{Hardware-Anforderungen}
+
+Je nach Version von AS variieren die Hardware-Anforderungen deutlich:
+
+Die DOS-Version \marginpar{{\em DOS}} l"auft prinzipiell auf allen
+IBM-kompatiblen PCs, angefangen vom PC/XT mit vierkommawenig Megaherz bis
+hin zum Pentium. Wie bei vielen anderen Programmen aber auch, steigt der
+Lustgewinn mit der Hardware-Ausstattung. So d"urfte ein XT-Benutzer ohne
+Festplatte erhebliche Probleme haben, die "uber 500 Kbyte gro"se
+Overlay-Datei von AS auf einer Diskette unterzubringen...eine Festplatte
+sollte der PC also schon haben, allein um vern"unftige Ladezeiten zu
+erreichen. Im Hauptspeicherbedarf ist AS recht gen"ugsam: Das Programm
+selber belegt knapp 300 Kbyte Hauptspeicher, AS sollte also ab einer
+Hauptspeichergr"o"se von 512 Kbyte ausf"uhrbar sein.
+
+Die Version von AS f"ur das \marginpar{{\em DPMI}}
+DOS-Protected-Mode-Interface (DPMI) ben"otigt zum Ablaufen mindestens
+einen 80286-Prozessor und 1 Mbyte freies extended memory. Daher stellen 2
+Mbyte Hauptspeicher das absolute Minimum dar, wenn man im XMS sonst keine
+anderen Spielereien (Platten-Cache, RAM-Disk, hochgeladenes DOS)
+installiert hat, sonst entsprechend mehr. Falls man die DPMI-Version in
+einer DOS-Box von OS/2 laufen l"a"st, so sollte DPMI auch in den
+DOS-Einstellungen der Box erlaubt sein (Einstellung \tty{An} oder
+\tty{Auto}) und der Box eine entsprechende Menge von XMS-Speicher
+zugeordnet sein. Die virtuelle Speicherverwaltung von OS/2 sorgt hier
+"ubrigens daf"ur, da"s man sich keine Gedanken machen mu"s, ob der
+eingestellte Speicher auch real verf"ugbar ist.
+
+Die Hardware-Anforderungen der \marginpar{{\em OS/2}} OS/2-Version ergeben sich
+weitestgehend durch die des darunterliegenden Betriebssytemes, d.h.
+mindestens ein 80386SX-Prozessor, 8 Mbyte RAM (bzw. 4 ohne grafische
+Benutzeroberfl"ache) sowie ca 100..150 Mbyte Platz auf der Festplatte. Da
+AS2 nur eine 16-Bit-Applikation ist, sollte er theoretisch auch auf
+"alteren OS/2-Versionen (und damit 80286-Prozessoren) lauff"ahig sein;
+ausprobieren konnte ich dies aber nicht.
+
+Die C-Version \marginpar{{\em UNIX}} von AS wird im Quellcode ausgeliefert
+und erfordert damit ein Unix- oder OS/2-System mit einem C-Compiler.
+Der Compiler mu"s dem ANSI-Standard gen"ugen (GNU-C erf"ullt diese
+Bedingung zum Beispiel). Ob Ihr UNIX-System bereits getestet und die
+n"otigen Definitionen vorgenommen wurden, k"onnen Sie der \tty{README}-Datei
+entnehmen. Als zur Kompilation ben"otigten Plattenplatz sollten Sie
+ca. 15 Mbyte veranschlagen; dieser Wert (und der nach der "Ubersetzung
+noch ben"otigte Platz f"ur die "ubersetzten Programme) variiert
+allerdings stark von System zu System, so da"s man diesen Wert nur als
+Richtschnur betrachten sollte.
+
+%%---------------------------------------------------------------------------
+
+\section{Lieferumfang}
+
+Prinzipiell erh"alt man AS in einer von zwei Formen: Als {\em
+Bin"ardistribution} oder {\em Quellcodedistribution}. Im Falle einer
+Bin"ardistribution bekommt man AS mit den zugeh"origen Dienstprogrammen
+und Hilfsdateien fertig "ubersetzt, so da"s man nach dem Auspacken des
+Archivs an die gew"unschte Stelle direkt loslegen kann.
+Bin"ardistributionen werden f"ur verbreitete Plattformen gemacht, bei
+denen die Mehrzahl der Benutzer keinen Compiler hat oder die "Ubersetzung
+trickreich ist (im Moment sind dies DOS und OS/2). Eine
+Quellcodedistribution enth"alt im Gegensatz den kompletten Satz an
+C-Quellen, um AS zu generieren; es ist letzten Endes ein Schnappschu"s
+des Quellenbaumes, an dem ich AS weiterentwickele. Die Generierung von AS
+aus dem Quellcode und dessen Struktur ist n"aher in Anhang
+\ref{ChapSource} beschrieben, weshalb an dieser Stelle nur auf den
+Umfang und die Installation einer Bin"ardistribution beschrieben wird:
+
+Das Archiv des Lieferumfangs gliedert sich in einige Unterverzeichnisse,
+so da"s man nach dem Auspacken sofort einen Verzeichnisbaum erh"alt. Die
+Verzeichnisse enthalten im einzelnen:
+\begin{itemize}
+\item{{\tt BIN}: ausf"uhrbare Programme, Text-Resourcen;}
+\item{{\tt INCLUDE}: Include-Dateien f"ur Assemblerprogramme, z.B.
+ Registerdefinitionen oder Standardmakros;}
+\item{{\tt MAN}: Kurzreferenzen f"ur die Programme im Unix-Man-Format;}
+\item{{\tt DOC}: diese Dokumentation in verschiedenen Formaten;}
+\item{{\tt LIB}: vorgesehen f"ur Initialisierungsdateien.}
+\end{itemize}
+Eine Auflistung der Dateien, die in jeder Bin"ardistribution enthalten
+sind, findet sich in den Tabellen \ref{TabCommonPackageList1} und
+\ref{TabCommonPackageList2}. Falls eine der in diesen (oder den
+folgenden) Tabellen aufgef"uhrten Dateien fehlt, hat jemand (im
+Zweifelsfalle ich) beim Kopieren geschlafen...
+
+\begin{table*}[htp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+Datei & Funktion \\
+\hline
+\hline
+{\bf Verzeichnis BIN} & \\
+\hline
+AS.EXE & Programmdatei Assembler \\
+PLIST.EXE & listet Inhalt von Codedateien auf \\
+PBIND.EXE & kopiert Codedateien zusammen \\
+P2HEX.EXE & wandelt Code- in Hexdateien um \\
+P2BIN.EXE & wandelt Code- in Bin"ardateien um \\
+AS.MSG & Textresourcen zu AS \\
+PLIST.MSG & Textresourcen zu PLIST \\
+PBIND.MSG & Textresourcen zu PBIND \\
+P2HEX.MSG & Textresourcen zu P2HEX \\
+P2BIN.MSG & Textresourcen zu P2BIN \\
+TOOLS.MSG & gemeinsame Textresourcen zu den Tools \\
+CMDARG.MSG & gemeinsame Textresourcen zu allen Programmen \\
+DECODECMD.MSG & \\
+IOERRS.MSG & \\
+\hline
+\hline
+{\bf Verzeichnis DOC} & \\
+\hline
+AS\_DE.DOC & deutsche Dokumentation, ASCII-Format \\
+AS\_DE.HTML & deutsche Dokumentation, HTML-Format \\
+AS\_DE.TEX & deutsche Dokumentation, LaTeX-Format \\
+AS\_EN.DOC & englische Dokumentation, ASCII-Format \\
+AS\_EN.HTML & englische Dokumentation, HTML-Format \\
+AS\_EN.TEX & englische Dokumentation, LaTeX-Format \\
+\hline
+\hline
+{\bf Verzeichnis INCLUDE} & \\
+\hline
+BITFUNCS.INC & Funktionen zur Bitmanipulation \\
+CTYPE.INC & Funktionen zur Klassifizierung von \\
+ & Zeichen \\
+80C50X.INC & Registeradressen SAB C50x \\
+80C552.INC & Registeradressen 80C552 \\
+H8\_3048.INC & Registeradressen H8/3048 \\
+REG166.INC & Adressen \& Befehlsmakros 80C166/167 \\
+REG251.INC & Adressen \& Bits 80C251 \\
+REG29K.INC & Peripherieadressen AMD 2924x \\
+REG53X.INC & Registeradressen H8/53x \\
+REG683XX.INC & Registeradressen 68332/68340/68360 \\
+REG7000.INC & Registeradressen TMS70Cxx \\
+REG78K0.INC & Registeradressen 78K0 \\
+REG96.INC & Registeradressen MCS-96 \\
+REGACE.INC & Registeradressen ACE \\
+\hline
+\end{tabular}\end{center}
+\caption{Standardumfang einer Bin"ardistribution - Teil 1
+ \label{TabCommonPackageList1}}
+\end{table*}
+\begin{table*}[htp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+Datei & Funktion \\
+\hline
+\hline
+{\bf Verzeichnis INCLUDE} & \\
+\hline
+REGAVR.INC & Register- \& Bitadressen AVR-Familie \\
+REGCOP8.INC & Registeradressen COP8 \\
+REGHC12.INC & Registeradressen 68HC12 \\
+REGM16C.INC & Registeradressen Mitsubishi M16C \\
+REGMSP.INC & Registeradressen TI MSP430 \\
+REGST9.INC & Register- \& Makrodefinitionen ST9 \\
+REGZ380.INC & Registeradressen Z380 \\
+STDDEF04.INC & Registeradressen 6804 \\
+STDDEF16.INC & Befehlsmakros und Registeradressen \\
+ & PIC16C5x \\
+STDDEF17.INC & Registeradressen PIC17C4x \\
+STDDEF18.INC & Registeradressen PIC16C8x \\
+STDDEF2X.INC & Registeradressen TMS3202x \\
+STDDEF37.INC & Register- \& Bitadressen TMS370xxx \\
+STDDEF3X.INC & Peripherieadressen TMS320C3x \\
+STDDEF47.INC & Befehlsmakros TLCS-47 \\
+STDDEF51.INC & Definition von SFRs und Bits f"ur \\
+ & 8051/8052/80515 \\
+STDDEF56K.INC & Registeradressen DSP56000 \\
+STDDEF5X.INC & Peripherieadressen TMS320C5x \\
+STDDEF60.INC & Befehlsmakros \& Registeradressen \\
+ & PowerPC \\
+STDDEF62.INC & Registeradressen \& Makros ST6 \\
+STDDEF75.INC & Registeradressen 75K0 \\
+STDDEF87.INC & Register- \& Speicheradressen TLCS-870 \\
+STDDEF90.INC & Register- \& Speicheradressen TLCS-90 \\
+STDDEF96.INC & Register- \& Speicheradressen TLCS-900 \\
+STDDEFXA.INC & SFR-\& Bitadressen Philips XA \\
+STDDEFZ8.INC & Registeradressen Z8-Familie \\
+\hline
+\hline
+{\bf Verzeichnis LIB} & \\
+\hline
+\hline
+{\bf Verzeichnis MAN} & \\
+\hline
+ASL.1 & Kurzanleitung zu AS \\
+PLIST.1 & Kurzanleitung zu PLIST \\
+PBIND.1 & Kurzanleitung zu PBIND \\
+P2HEX.1 & Kurzanleitung zu P2HEX \\
+P2BIN.1 & Kurzanleitung zu P2BIN \\
+\hline
+\end{tabular}\end{center}
+\caption{Standardumfang einer Bin"ardistribution - Teil 2
+ \label{TabCommonPackageList2}}
+\end{table*}
+
+Je nach Plattform kann eine Bin"ardistribution aber noch weitere Dateien
+enthalten, um einen Betrieb zu erm"oglichen, wie es z.B. bei DOS-Extendern
+der Fall ist. F"ur die DOS-DPMI-Version \marginpar{{\em DPMI}} ergeben
+sich die in Tabelle \ref{TabDPMIPackageList} gelisteten Erg"anzungen. Es
+spricht "ubrigens nichts dagegen, als Hilfsprogramme die Versionen aus
+einer DOS-Distribution zu verwenden, da diese einerseits ohne den
+Extender-Overhead deutlich schneller ablaufen und andererseits den
+vom Extender bereitgestellten erweiterten Speicher nicht ben"otigen.
+
+\begin{table*}[htp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+Datei & Funktion \\
+\hline
+\hline
+{\bf Verzeichnis BIN} & \\
+\hline
+DPMI16BI.OVL & DPMI-Server f"ur den Assembler \\
+RTM.EXE & Laufzeit-Modul des Extenders \\
+\hline
+\end{tabular}\end{center}
+\caption{Zus"atzliche Dateien in einer DPMI-Bin"ardistribution
+ \label{TabDPMIPackageList}}
+\end{table*}
+
+Eine OS/2-Bin"ardistribution \marginpar{{\em OS/2}} enth"alt neben den
+Basisdateien eine Reihe von DLLs, die zur Laufzeitumgebung des verwendeten
+emx-Compilers geh"oren (Tabelle \ref{TabOS2PackageList}). Falls man diese
+DLLs (oder neuere Versionen davon) bereits besitzt, kann man diese auch
+wieder l"oschen und seine eigenen benutzen.
+
+\begin{table*}[htp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+Datei & Funktion \\
+\hline
+\hline
+{\bf Verzeichnis BIN} & \\
+\hline
+EMX.DLL & Laufzeitbibliotheken f"ur AS und \\
+EMXIO.DLL & die Dienstprogramme \\
+EMXLIBC.DLL & \\
+EMXWRAP.DLL & \\
+\hline
+\end{tabular}\end{center}
+\caption{Zus"atzliche Dateien in einer OS/2-Bin"ardistribution
+ \label{TabOS2PackageList}}
+\end{table*}
+
+%%---------------------------------------------------------------------------
+
+\section{Installation}
+
+Eine besondere \marginpar{{\em DOS}} Installation ist f"ur die Nutzung
+einer Bin"ardistribution nicht notwendig, es gen"ugt, das Archiv an
+passender Stelle auszupacken und dann noch einige Kleinigkeiten zu
+erg"anzen. Als Beispiel hier eine Installation, wie sie vielleicht
+ein UNIX-Anh"anger vornehmen w"urde:
+
+Legen Sie ein Verzeichnis \verb!c:\as! an (im folgenden nehme ich an,
+da"s Sie AS auf Laufwerk C installieren wollen), wechseln Sie in dieses
+und entpacken Sie das Archiv unter Erhalt der Verzeichnisnamen (bei
+Verwendung von PKUNZIP ist dazu die Kommandozeilenoption \verb!-d!
+erforderlich). Sie sollten jetzt folgenden Verzeichnisbaum haben:
+\begin{verbatim}
+c:\as
+c:\as\bin
+c:\as\include
+c:\as\lib
+c:\as\man
+c:\as\doc
+\end{verbatim}
+Erg"anzen Sie jetzt die \tty{PATH}-Anweisung in Ihrer \tty{AUTOEXEC.BAT}
+um das Verzeichnis \verb!c:\as\bin!, so da"s AS und seine Hilfsprogramme
+vom System gefunden werden. In dem \tty{lib}-Verzeichnis erzeugen Sie
+mit einem beliebigen Texteditor eine Datei \tty{AS.RC} mit folgendem
+Inhalt:
+\begin{verbatim}
+-i c:\as\include
+\end{verbatim}
+Diese sogenannte {\em Key-Datei} zeigt AS, in welchem Verzeichnis er seine
+Include-Dateien suchen soll. Damit AS diese Key-Datei bei Start
+auch beachtet, mu"s noch folgende Anweisung in die \tty{AUTOEXEC.BAT}:
+\begin{verbatim}
+set ASCMD=@c:\as\lib\as.rc
+\end{verbatim}
+Was Sie alles noch in der Key-Datei voreinstellen k"onnen, steht im
+folgenden Abschnitt.
+
+Die Installation der DPMI-Version \marginpar{{\em DPMI}} sollte im Prinzip
+genauso verlaufen wie der reinen DOS-Version; wenn der Pfad das {\tt
+bin}-Verzeichnis enth"alt, werden die Dateien des DOS-Extenders
+automatisch gefunden und man sollte von dieser Mimik (mit Ausnahme der
+l"angeren Anlaufzeit...) nichts mitbekommen. Theoretisch ist es m"oglich,
+da"s Sie auf 80286-Rechnern beim ersten Start mit einer Meldung der
+folgenden Form konfrontiert werden:
+\begin{verbatim}
+ machine not in database (run DPMIINST)
+\end{verbatim}
+Da das Tool DPMIINST bei neueren Versionen des DOS-Extenders von Borland
+aber nicht mehr dabei ist, nehme ich einmal an, da"s diese Sache sich
+erledigt hat...falls doch nicht, bitte ich um R"uckmeldung!
+
+Die Installation der OS/2-Version \marginpar{{\em OS/2}} kann in weiten
+Z"ugen genauso ablaufen wie f"ur die DOS-Version, nur da"s dem System noch
+die DLLs bwkannt gemacht werden m"ussen. Wenn Sie den {\tt
+LIBPATH}-Eintrag in Ihrer {\tt CONFIG.SYS} nicht erweitern wollen, ist es
+nat"urlich auch m"oglich, die DLLs in ein Verzeichnis zu verschieben, das
+bereits dort aufgef"uhrt ist.
+
+Wie bereits erw"ahnt, beschr"ankt sich die Installationsbeschreibung hier
+nur auf Bin"ardistributionen. Da eine Installation unter Unix
+\marginpar{{\em UNIX}} im Augenblick immer eine Quellcodedistribution ist,
+geht der Verweis hier unisono in Anhang \ref{ChapSource}.
+
+%%---------------------------------------------------------------------------
+
+\section{Aufruf, Parameter}\label{SectCallConvention}
+
+AS ist ein kommandozeilengesteuertes Programm, d.h. alle Parameter
+und Dateiangaben sind in der Kommandozeile anzugeben.
+
+Zu AS geh"ort eine Reihe Reihe von Nachrichtendateien (erkennbar an der
+Endung {\tt MSG}, aus denen AS zur Laufzeit die f"ur die jeweilige
+Landessprache dynamisch nachl"adt. AS sucht nach diesen Dateien in den
+folgenden Verzeichnissen:
+\begin{itemize}
+\item{im aktuellen Verzeichnis;}
+\item{im Verzeichnis der EXE-Datei;}
+\item{in dem in der Environment-Variablen {\tt AS\_MSGPATH} angegebenen
+ Verzeichnis, oder alternativ in den in der {\tt PATH}-Variablen
+ gelisteten Verzeichnissen;}
+\item{In dem Verzeichnis, das AS zur Kompilationszeit durch das
+ Makro {\tt LIBDIR} mitgegeben wurde.}
+\end{itemize}
+Diese Dateien werden von AS {\em zwingend} zum Betrieb ben"otigt, d.h.
+findet AS diese Dateien nicht, bricht er an dieser Stelle sofort ab.
+
+Die Auswahl der Sprache (momentan Deutsch oder Englisch) orientiert sich
+unter DOS und OS/2 an der {\tt COUNTRY}-Einstellung in der {\tt
+CONFIG.SYS}, unter Unix an der {\tt LANG}-Environment-Variablen.
+
+Um den \marginpar{{\em DOS}} Speicherbedarf von AS unter DOS "uberhaupt
+befriedigen zu k"onnen, wurden die verschiedenen Codegeneratormodule in
+der DOS-Version in einen Overlay verlegt, der Teil des EXE-Files ist.
+Eine getrennte OVR-Datei wie bei fr"uheren Versionen von AS existiert also
+nicht mehr, AS versucht aber wie bisher auch weiterhin, die durch das
+Overlaying entstehenden Verzögerungen durch Nutzung von eventuellem EMS-
+oder XMS-Speicher zu reduzieren. Sollte diese Verwendung zu Problemen
+f"uhren, so k"onnen Sie die Verwendung von EMS bzw. XMS unterbinden, indem
+Sie einer Environment-Variablen \tty{USEXMS} bzw. \tty{USEEMS} den Wert
+\tty{n} zuweisen. So kann man z.B. mit dem Befehl
+\begin{verbatim}
+ SET USEXMS=n
+\end{verbatim}
+die Verwendung von extended memory verhindern.
+\par
+Da AS alle Ein-und Ausgaben "uber das Betriebssystem abwickelt (und daher
+unter DOS auch auf nicht ganz so kompatiblen PC's laufen sollte) und eine
+rudiment"are Bildschirmsteuerung ben"otigt, gibt er w"ahrend der
+Assemblierung ANSI-Steuersequenzen aus.
+Falls Sie in den Ausgaben von AS \marginpar{{\em DOS/}} also seltsame
+Zeichen sehen sollten, fehlt offensichtlich in Ihrer CONFIG.SYS die
+Einbindung des ANSI-Trei\-bers (\tty{device=\-ansi.sys}), die weitere Funktion
+von AS \marginpar{{\em DPMI}} wird dadurch aber nicht beeinflu"st. Alternativ
+k"onnen Sie aber auch die Ausgabe von ANSI-Sequenzen durch das Setzen der
+Environment-Variablen \tty{USEANSI} auf \tty{n} ganz unterdr"ucken.
+
+Der DOS-Extender der DPMI-Version \marginpar{{\em DPMI}} l"a"st sich in
+seiner Speicherbelegung durch diverse Kommandozeilenoptionen beeinflussen.
+Diese k"onnen Sie bei Bedarf der Datei DPMIUSER.DOC entnehmen.
+Zus"atzlich ist ASX in der Lage, bei Bedarf den vorhandenen Speicher
+durch eine Swap-Datei zu ,,erweitern''. Dazu belegt man eine
+Environment-Variable \tty{ASXSWAP} folgenderma"sen:
+\begin{quote}{\tt
+ SET ASXSWAP=$<$Gr"o"se$>$[,Dateiname]
+}\end{quote}
+Die Gr"o"senangabe erfolgt in Megabytes und \bb{mu"s} gemacht werden. Der
+Name der Datei ist dagegen optional; fehlt er, so wird die Swap-Datei im
+aktuellen Verzeichnis unter dem Namen \tty{ASX.TMP} angelegt. In jedem
+Falle wird die Swap-Datei nach Programmende wieder gel"oscht.
+
+Die Kommandozeilenparameter k"onnen grob in drei Klassen eingeteilt
+werden: Schalter, Key-File-Referenzen (s.u.) und Dateispezifikationen.
+Parameter dieser beiden Klassen k"onnen beliebig gemischt in der
+Kommandozeile auftreten, AS wertet zuerst alle Parameter aus und
+assembliert dann die angegebenen Dateien. Daraus folgen zwei Dinge:
+\begin{itemize}
+\item{Die angegebenen Schalter wirken auf alle angegebenen Quelldateien.
+ Sollen mehrere Quelldateien mit unterschiedlich gesetzten Schaltern
+ assembliert werden, so mu"s dies in getrennten L"aufen erfolgen.}
+\item{Es k"onnen in einem Durchgang mehrere Dateien assembliert werden.
+ Um der Sache die Krone aufzusetzen, d"urfen die Dateiangaben
+ Jokerzeichen enthalten.}
+\end{itemize}
+Schalterparameter erkennt AS daran, da"s sie durch einen
+Schr"agstrich (/) oder Bindestrich (-) eingeleitet werden. Es gibt dabei
+sowohl Schalter, die nur aus einem Buchstaben bestehen, als auch Schalter,
+die aus einem ganzen Wort bestehen. Immer wenn AS einen Schalter nicht
+als ,,Wort-Schalter'' verstehen kann, so versucht er, die Buchstaben des
+Wortes als einzelne Schalter zu interpretieren. Wenn man also z.B.
+\begin{verbatim}
+ -queit
+\end{verbatim}
+anstelle von
+\begin{verbatim}
+ -quiet
+\end{verbatim}
+geschrieben h"atte, w"urde AS die Buchstaben \tty{q, u, e, i} und \tty{t}
+als einzelne Schalter auffassen. Mehrbuchstabige Schalter unterscheiden
+sich weiterhin von einbuchstabigen dadurch, da"s AS bei ihnen beliebige
+Gro"s-und Kleinschreibungen akzeptiert, w"ahrend einbuchstabige Schalter
+je nach Gro"s- oder Kleinschreibung unterschiedliche Bedeutung haben.
+\par
+Momentan sind folgende Schalter definiert:
+\ttindex{SHARED}
+\begin{itemize}
+\item{\tty{l}: Assemblerlisting auf Konsole ausgeben. Falls mehrere
+ Passes ausgef"uhrt werden m"ussen, landen im Gegensatz zur
+ n"achsten Option die Listings aller Durchg"ange auf der Ausgabe!}
+\item{\tty{L}: Assemblerlisting auf Datei schreiben. Die Listdatei erh"alt
+ dabei den gleichen Namen wie die Quelldatei, lediglich die Endung
+ wird durch \tty{LST} ersetzt.}
+\item{\tty{o}:Bestimmt einen neuen Namen f"ur die von AS zu erzeugende
+ Code-Datei. Wird diese Option mehrfach verwendet, so werden
+ die angegebenen Namen nacheinander den zu assemblierenden
+ Quelldateien zugeordnet; Negation (s.u.) dieser Option in
+ Verbindung mit einem Namen l"oscht den Namen aus der Liste;
+ Negation ohne Namensangabe l"oscht die komplette Liste.}
+\item{\tty{SHAREOUT}:dito, nur f"ur eine eventuell zu erzeugende
+ SHARE-Datei}
+\item{\tty{c}: SHARED-Variablen werden in einem Format abgelegt, das die
+ Einbindung in eine C-Quelldatei erlaubt. Die Endung der Datei
+ ist \tty{H}.}
+\item{\tty{p}: SHARED-Variablen werden in einem Format abgelegt, das die
+ Einbindung in den \tty{CONST}-Block eines Pascal- oder Modula-Programmes
+ erlaubt. Die Endung der Datei ist \tty{INC}.}
+\item{\tty{a}: SHARED-Variablen werden in einem Format abgelegt, das die
+ Einbindung in eine Assembler-Quelldatei erlaubt. Die Endung
+ der Datei ist \tty{INC}.}
+\end{itemize}
+Zu Sinn und Funktion der SHARED-Symbole siehe Kapitel \ref{ChapShareMain}
+bzw. \ref{ChapShareOrder}.
+\begin{itemize}
+\item{\tty{g [Format]}: Mit diesem Schalter erzeugt AS zus"atzlich eine
+ Datei, die Debug-Informationen f"ur dieses Programm enth"alt.
+ Als Format ist dabei entweder ein AS-eigenes \tty{MAP}-Format, eine
+ \tty{NoICE}-kompatible Kommandodatei oder das \tty{ATMEL}-Format
+ der AVR-Tools erlaubt. Zu den im MAP-Format gespeicherten
+ Informationen geh"ort zum einen die Symboltabelle, zum anderen eine
+ Zuordnung von Quellzeilen zu Maschinenadressen. Eine genauere
+ Beschreibung des benutzten MAP-Dateiformates findet sich in
+ Abschnitt \ref{SectDebugFormat}. Die Endung der Datei ist
+ \tty{MAP}, \tty{NOI} bzw. \tty{OBJ}, je nach gew"ahltem Format.
+ Wird keine explizite Formatangabe gemacht, wird das MAP-Format
+ gew"ahlt.}
+\item{\tty{w}: Ausgabe von Warnungen unterdr"ucken;}
+\item{\tty{E [Datei]}: Die von AS erzeugten Fehlermeldungen und Warnungen
+ in eine Datei umleiten. Anstatt einer Datei k"onnen auch die 5
+ Standardhandles (STDIN..STDPRN) als !0 bis !4 angegeben werden.
+ Default ist !2, also STDERR. Wird die Dateiangabe weggelassen,
+ so ist der Name der Fehlerdatei gleich dem der Quelldatei, nur
+ mit der Endung \tty{LOG}.}
+\item{\tty{q}: Dieser Schalter unterdr"uckt alle Meldungen von AS mit
+ Ausnahme von Fehlermeldungen und vom Programm selber erzeugten
+ Ausgaben. Die Assemblierzeit kann dadurch geringf"ugig reduziert
+ werden, und beim Aufruf aus einer Shell heraus kann man sich eine
+ Umleitung ersparen. Der Nachteil ist, da"s man u.U. einige Minuten
+ ,,im Dunklen'' steht... Anstelle von 'q' darf auch 'quiet' geschrieben
+ werden.}
+\item{\tty{h}: Hexadezimalzahlen mit Klein- anstelle von Gro"sbuchstaben ausgeben.
+ Diese Option ist in erster Linie eine Frage des pers"onlichen
+ Geschmacks.}
+\item{\tty{i $<$Pfadliste$>$}: gibt eine Liste von Verzeichnissen an, in denen
+ der Assembler automatisch nach Include-Dateien suchen soll, falls
+ er diese nicht im aktuellen Verzeichnis findet. Die einzelnen
+ Verzeichnisse m"ussen durch Semikolons getrennt werden.}
+\item{\tty{u}: eine Liste der in den Segmenten belegten Bereiche berechnen.
+ Sie ist nur sinnvoll, falls ein Listing erzeugt
+ wird. Diese Option ben"otigt erhebliche zus"atzliche Speicher-
+ und Rechenleistung, im Normalbetrieb sollte sie daher abgeschaltet
+ sein. Da AS aber unabh"angig vom eingeschalteten Listing mit dieser
+ Option auf "uberlappende Speicherbelegung pr"uft, hat sie auch
+ unabh"angig vom Listing einen gewissen Sinn...}
+\item{\tty{C}: erzeugt eine Liste mit Querverweisen. Aufgelistet wird,
+ welche (globalen) Symbole in welchen Dateien in welchen Zeilen
+ benutzt werden. Auch diese Liste wird nur generiert, falls
+ ein Listing erzeugt wird und belegt w"ahrend der
+ Assemblierung zus"atzlichen Speicherplatz.}
+\item{\tty{s}: eine Liste aller Sektionen (s. Abschnitt \ref{ChapLocSyms})
+ ausgeben. Die Verschachtelung wird dabei durch Einr"uckungen
+ angedeutet.}
+\item{\tty{I}: Analog zur Sektionsliste eine Liste aller bearbeiteten
+ Include-Dateien ausgeben.}
+\item{\tty{t $<$Maske$>$}: Mit diesem Schalter lassen sich einzelne Komponenten
+ des standardm"a"sig ausgegebenen Assemblerlistings ein-und ausblenden.
+ Welcher Teil dabei welchem Bit zugeordnet ist, ist im "ubern"achsten
+ Abschnitt, der genauer auf das Format des Assemblerlistings eingeht,
+ nachgelesen werden.}
+\item{\tty{D $<$Symbolliste$>$}: Symbole definieren. Die hinter dieser Option
+ angegebenen, durch Kommas getrennten Symbole werden in der
+ globalen Symboltabelle vor Beginn der Assemblierung abgelegt.
+ Defaultm"a"sig werden diese Symbole als ganze Zahlen mit dem
+ Wert TRUE abgelegt, mit einem nachgestellten Gleichheitszeichen
+ kann aber auch eine andere Belegung gew"ahlt werden. Der dem
+ Gleichheitszeichen folgende Ausdruck darf dabei auch Operatoren
+ oder interne Funktionen beinhalten, jedoch \bb{KEINE} anderen
+ Symbole, selbst wenn diese schon davor in der Liste definiert
+ sein sollten! Zusammen mit den Befehlen zur bedingten
+ Assemblierung (siehe dort) k"onnen so per Kommandozeile aus einer
+ Quelldatei unterschiedliche Programmversionen erzeugt werden.}
+\item{\tty{A}: Die Liste globaler Symbole in einer anderen, kompakteren Form
+ ablegen. Verwenden Sie diese Option, wenn der Assembler bei
+ langen Symboltabellen mit einem Stapel"uberlauf abst"urzt.
+ Eventuell kann diese Option die Arbeitsgeschwindigkeit des
+ Assemblers erh"ohen, dies h"angt jedoch von den Quellen ab.}
+\item{\tty{x}: Legt die Ausf"uhrlichkeitsstufe von Fehlermeldungen fest.
+ Jedesmal, wenn diese Option angegeben wird, wird die Stufe
+ um eins erh"oht oder gesenkt. W"ahrend auf Stufe 0 (Vorgabe) nur
+ der Fehler selber ausgegeben wird, wird ab Stufe 1 noch eine
+ erweiterte Meldung ausgegeben, anhand der die Identifizierung des
+ Fehlers erleichtert werden soll. Welche Fehlermeldungen welche
+ Zusatzinformationen tragen k"onnen, steht in Anhang \ref{ChapErrMess}
+ mit der Liste aller Fehlermeldungen. Auf Stufe 2 (Maximum) wird
+ zus"atzlich noch die betroffene Quellzeile mit ausgegeben.}
+\item{\tty{n}: Wird diese Option angegeben, so werden Fehlermeldungen nicht nur
+ mit ihrem Klartext, sondern auch mit ihren im Anhang
+ \ref{ChapErrMess} genannten internen Nummern ausgegeben. Diese
+ Option ist prim"ar f"ur Shells und Entwicklungsumgebungen gedacht,
+ denen mit diesen Nummern die Identifizierung von Fehlern erleichtert
+ werden soll.}
+\item{\tty{U}: Mit dieser Option schaltet man AS in den case-sensitiven
+ Modus um, d.h. in Namen von Symbolen, Sektionen, Makros,
+ Zeichentabellen und selbstdefinierte Funktionen werden Klein-
+ und Gro"sbuchstaben unterschieden, was normalerweise nicht der
+ Fall ist.}
+\item{\tty{P}: weist AS an, den von Makroprozessor und bedingter Assemblierung
+ bearbeiteten Quelltext in einer Datei abzulegen. Dieser Datei
+ fehlen zus"atzlich Leer- und reine Kommentarzeilen. Die Endung
+ der Datei ist \tty{I}.}
+\item{\tty{M}: mit diesem Schalter erzeugt AS eine Datei, in der die Definitionen
+ der Makros aus der Quelldatei abgespeichert werden, die die
+ \tty{EXPORT}-Option verwenden. Diese neue Datei hat den gleichen
+ Namen wie die Quelldatei, lediglich die Endung wird in \tty{MAC} ge"andert.}
+\item{\tty{G}: Dieser Schalter bestimmt, ob AS Code erzeugen soll oder nicht.
+ Ist er ausgeschaltet, wird die Datei zwar assembliert,
+ aber keine Code-Datei geschrieben. Dieser Schalter ist defaultm"a"sig aktiviert
+ (logisch, sonst bek"ame man ja auch gar kein Codefile).}
+\item{\tty{r [n]}: Warnungen ausgeben, falls Situationen eintreten, die
+ einen weiteren Pass erfordern. Diese Information kann genutzt
+ werden, um die Anzahl der Durchl"aufe zu verringern. Optional kann
+ man die Nummer des Passes angeben, ab dem diese Warnungen erzeugt
+ werden; ohne Angabe kommen die Warnungen ab dem ersten Pass. Machen
+ Sie sich aber so oder so auf einen ziemlichen Haufen an Meldungen
+ gefa"st!!}
+\item{\tty{Y}: Mit diesem Schalter weist man AS an, alle Fehlermeldungen
+ wegen zu langer Sprungdistanzen zu verwerfen, sobald die Notwendigkeit
+ eines neuen Durchlaufs feststeht. In welchen (seltenen) Situationen
+ dieser Schalter notwendig ist, kann man in Abschnitt \ref{ForwRefs}
+ nachlesen.}
+\item{\tty{cpu $<$Name$>$}: Hiermit kann man man den Zielprozessor
+ vorgeben, f"ur den AS Code erzeugen soll, wenn die Quelldatei keinen
+ {\tt CPU}-Befehl enth"alt und es sich nicht um 68008-Code handelt.}
+\item{\tty{alias $<$neu$>$=$<$alt$>$}:\\
+ definiert den Prozessortyp \tty{$<$neu$>$} als einen Alias f"ur den
+ Typen \tty{$<$alt$>$}. Zu den Sinn und Zweck von Aliassen siehe
+ Abschnitt \ref{SectAlias}}
+\end{itemize}
+Sofern Schalter keine Argumente ben"otigen und ihre Zusammenziehung
+keinen mehrbuchstabigen Schalter ergibt, k"onnen mehrere Schalter
+auch auf einen Rutsch angegeben werden, wie z.B im folgenden Beispiel:
+\begin{verbatim}
+ as test*.asm firstprog -cl /i c:\as\8051\include
+\end{verbatim}
+Es werden alle Dateien TEST*.ASM sowie die Datei FIRSTPROG.ASM
+assembliert, wobei f"ur alle Dateien Listings auf der Konsole
+ausgegeben und Sharefiles im C-Format erzeugt werden. Nach Includes
+soll der Assembler zus"atzlich im Verzeichnis \verb! C:\AS\8051\INCLUDE !
+suchen.
+\par
+Dieses Beispiel zeigt nebenbei, da"s AS als Defaultendung f"ur Quelldateien
+\tty{ASM} annimmt.
+\par
+Etwas Vorsicht ist bei Schaltern angebracht, die ein optionales Argument
+haben: Folgt auf einen solchen Schalter ohne Argument ein Dateiname, so
+versucht AS, diesen als Argument zu verwerten, was naturgem"a"s schief
+geht:
+\begin{verbatim}
+ as -g test.asm
+\end{verbatim}
+Die L"osung w"are in diesem Fall, die \tty{-g}-Option ans Ende der
+Kommandozeile zu setzen oder ein explizites \tty{MAP}-Argument zu
+spezifizieren.
+\par
+Neben der Angabe in der Kommandozeile k"onnen dauernd ben"otigte
+Optionen in der Environment-Variablen ASCMD abgelegt werden. Wer z.B.
+immer Listdateien haben m"ochte und ein festes Includeverzeichnis hat,
+kann sich mit dem Befehl
+\begin{verbatim}
+ set ASCMD=-L -i c:\as\8051\include
+\end{verbatim}
+eine Menge Tipparbeit ersparen. Da die Environment-Optionen vor der
+Kommandozeile abgearbeitet werden, k"onnen Optionen in der
+Kommandozeile widersprechende im Environment "ubersteuern.
+\par
+Bei sehr langen Pfaden kann es jedoch auch in der ASCMD-Variablen eng
+werden. F"ur solche F"alle kann auf eine sog. \ii{Key}- Datei
+ausgewichen werden, in der die Optionen genauso wie in der Kommandozeile
+oder ASCMD-Variablen abgelegt werden k"onnen, nur da"s diese Datei
+mehrere Zeilen mit jeweils maximal 255 Zeichen enthalten darf. Wichtig
+ist dabei, da"s bei Optionen, die ein Argument ben"otigen, sowohl Schalter
+als auch Argument in \bb{einer} Zeile stehen m"ussen. Der Name der
+Datei wird AS dadurch mitgeteilt, da"s er mit einem vorangestellten
+Klammeraffen in der ASCMD-Variablen abgelegt wird, z.B.
+\begin{verbatim}
+ set ASCMD=@c:\as\as.key
+\end{verbatim}
+Um Optionen in der ASCMD-Variablen (oder der Key-Datei) wieder aufzuheben,
+kann die Option mit einem vorangestellten Pluszeichen wieder aufgehoben
+werden. Soll in einem Einzelfall z.B. doch kein Listing erzeugt werden,
+so kann es mit
+\begin{verbatim}
+ as +L <Datei>
+\end{verbatim}
+wieder aufgehoben werden. Nat"urlich ist es nicht ganz logisch, eine
+Option mit einem Pluszeichen zu negieren...UNIX soit qui mal y pense.
+\par
+Referenzen auf eine Key-Datei k"onnen nicht nur von der {\tt
+ASCMD}-Variablen aus erfolgen, sondern auch direkt von der Kommandozeile
+aus, indem man analog zur {\tt ASCMD}-Variablen dem Dateinamen einen
+Klammeraffen voranstellt:
+\begin{verbatim}
+ as @<Datei> ....
+\end{verbatim}
+Die in einem solchen Fall aus dem Key-File gelesenen Optionen werden so
+eingearbeitet, als h"atten sie anstelle dieser Referenz in der
+Kommandozeile gestanden - es ist also {\em nicht} wie bei der {\tt
+ASCMD}-Variablen so, da"s sie vor allen anderen Kommandozeilenoptionen
+abgearbeitet werden w"urden.
+\par
+Das Referenzieren eines Key-Files von einem Key-File selber ist nicht
+erlaubt und wird von AS mit einer Fehlermeldung quittiert.
+\par
+F"ur den Fall, da"s Sie AS von einem anderen Programm oder einer Shell
+aufrufen wollen und diese Shell nur Klein- oder Gro"sbuchstaben in der
+Kommandozeile "ubergeben will, existiert folgendes Workaround: Wird vor
+den Buchstaben der Option eine Tilde gesetzt, so werden die folgenden
+Buchstaben immer als Kleinbuchstaben interpretiert. Analog erzwingt
+ein Lattenzaun die Interpretation als Gro"sbuchstaben. Es ergeben
+sich z.B. folgende Transformationen:
+\begin{quote}{\tt
+ /\verb!~!I $\longrightarrow$ /i \\
+ -\verb!#!u $\longrightarrow$ -U}
+\end{quote}
+\par
+Abh"angig vom Ablauf der Assemblierung endet der Assembler mit
+folgenden Returncodes:
+\begin{description}
+\item[0]{fehlerfreier Ablauf, h"ochstens Warnungen aufgetreten}
+\item[1]{Der Assembler hat nur die Aufrufparameter ausgegeben und
+ endete danach sofort.}
+\item[2]{Es sind Fehler bei der Assemblierung aufgetreten, es wurde
+ kein Codefile erzeugt.}
+\item[3]{Es trat ein fataler Fehler w"ahrend des Ablaufes auf, der
+ zum sofortigen Abbruch gef"uhrt hat.}
+\item[4]{Bereits w"ahrend des Starts des Assemblers ist ein Fehler
+ aufgetreten. Dies kann ein Parameterfehler oder eine fehlerhafte
+ Overlay-Datei sein.}
+\item[255]{Bei der Initialisierung ist irgendein interner Fehler
+ aufgetreten, der auf keinen Fall auftreten sollte...neu booten,
+ noch einmal probieren, und bei Reproduzierbarkeit mit mir
+ Verbindung aufnehmen!}
+\end{description}
+
+Zus"atzlich endet jede Assemblierung einer Datei mit einer kleinen
+Statistik, die Fehlerzahlen, Laufzeit, Anzahl der Durchl"aufe und freien
+Speicher ausgibt. Bei eingeschaltetem Assembler-Listing wird diese
+Statistik zus"atzlich auch in das Listing geschrieben.
+
+OS/2 \marginpar{{\em OS/2}} erweitert wie Unix das Datensegment einer
+Anwendung erst dann, wenn sie wirklich mehr Speicher anfordert. Eine
+Angabe wie
+\begin{quote}{\tt
+511 KByte verf"ugbarer Restspeicher
+}\end{quote}
+bedeutet also nicht einen nahenden Systemabsturz wegen Speichermangel,
+sondern stellt nur den Abstand zu der Grenze dar, bei der OS/2 einfach
+ein paar mehr Kohlen in den Ofen schaufelt...
+
+Da es unter C \marginpar{{\em UNIX}} auf verschiedenen Betriebssystemen
+keine kompatible M"oglichkeit gibt, den noch verf"ugbaren Speicher bzw.
+Stack zu ermitteln, fehlen bei der C-Version diese beiden Angaben ganz.
+
+%%---------------------------------------------------------------------------
+
+\section{Format der Eingabedateien}
+\label{AttrTypes}
+
+Wie die meisten Assembler auch erwartet AS genau einen Befehl pro Zeile
+(Leerzeilen sind nat"urlich auch zugelassen). Die Zeilen d"urfen nicht
+l"anger als 255 Zeichen werden, dar"uber hinaus gehende Zeichen werden
+abgeschnitten.
+\par
+Eine einzelne Zeile hat folgendes Format:
+\begin{verbatim}
+[Label[:]]<Befehl>[.Attribut] [Parameter[,Parameter..]] [;Kommentar]
+\end{verbatim}
+Der Doppelpunkt nach dem Label ist optional, falls das Label in der
+ersten Spalte beginnt (woraus folgt, da"s der Befehl niemals in Spalte
+1 beginnen darf). Man mu"s ihn aber setzen, falls das Label nicht
+in der ersten Spalte beginnt, damit AS es von einem Befehl unterscheiden
+kann. In letzterem Fall mu"s "ubrigens zwischen Doppelpunkt und dem
+Befehl mindestens ein Leerzeichen stehen, falls der eingestellte
+Zielprozessor zu denjenigen geh"ort, bei denen das Attribut auch
+eine mit einem Doppelpunkt abgetrennte Formatangabe sein darf. Dieser
+Knopf ist aus Eindeutigkeitsgr"unden n"otig, da sonst keine
+Unterscheidung zwischen Befehl mit Format und Label mit Befehl m"oglich
+w"are.
+\par
+Einige Signalprozessorreihen von Texas Instruments verwenden den f"ur das
+Label vorgesehenen Platz wahlweise auch f"ur einen Doppelstrich
+(\verb!||!), der die parallele Ausf"uhrung mit der vorangehenden
+Instruktion anzeigt. Wenn diese beiden Instruktionen auf Maschinenebene
+in einem einzigen Wort vereinigt werden (C3x), macht ein zus"atzliches
+Label vor der zweiten Anweisung nat"urlich keinen Sinn und ist auch nicht
+vorgesehen. Anders sieht es beim C6x mit seinen Instruktionspaketen
+variabler L"ange aus: Wer dort (unsch"onerweise...) mitten in ein Paket
+hineinspringen will, mu"s das Label daf"ur in eine Extrazeile davor setzen
+(das gleiche gilt "ubrigens auch f"ur Bedingungen, die aber zusammen mit
+dem Doppelstrich in einer Zeile stehen d"urfen).
+\par
+Das Attribut wird von einer Reihe von Prozessoren benutzt, um
+Spezialisierungen oder Kodierungsvarianten eines bestimmten Befehls zu
+spezifizieren. Die bekannteste Nutzung des Attributs ist die Angabe der
+Operandengr"o"se, wie z. B. bei der 680x0-Familie (Tabelle
+\ref{TabAttrs}).
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+Attribut & arithmetisch-logischer Befehl & Sprungbefehl \\
+\hline
+\hline
+B & Byte (8 Bit) & --------- \\
+W & Wort (16 Bit) & --------- \\
+L & Langwort (32 Bit) & 16-Bit-Displacement \\
+Q & Vierfachwort (64 Bit) & --------- \\
+S & Single Precision (32 Bit) & 8-Bit-Displacement \\
+D & Double Precision (64 Bit) & --------- \\
+X & Extended Precision (80/96 Bit) & 32-Bit-Displacement \\
+P & Dezimalgleitkomma (80/96 Bit) & --------- \\
+\hline
+\end{tabular}\end{center}
+\caption{Erlaubte Attribute (Beispiel 680x0) \label{TabAttrs}}
+\end{table*}
+\par
+Da sich diese Anleitung nicht gleichzeitig als Handbuch f"ur die von AS
+unterst"utzten Prozessorfamilien versteht, ist dies leider auch nicht der
+richtige Platz, um hier alle m"oglichen Attribute f"ur alle unterst"utzten
+Familien aufzuz"ahlen. Es sei aber angemerkt, da"s i.a. nicht alle Befehle
+alle Attribute zulassen, andererseits das Fortlassen eines Attributs meist
+zur Verwendung der f"ur diese Familie ,,nat"urlichen'' Operandengr"o"se
+f"uhrt. Zum genaueren Studium greife man auf ein Programmierhandbuch f"ur
+die jeweilige Familie zur"uck, z.B. in \cite{Williams} f"ur die 68000er.
+\par
+Bei TLCS-9000, H8/500 und M16(C) dient das Attribut sowohl der Angabe der
+Operandengr"o"se, falls diese nicht durch die Operanden klar sein sollte,
+als auch der des zu verwendenden Befehlsformates.
+Dieses mu"s durch einen Doppelpunkt von der Operandengr"o"se getrennt werden,
+z.B. so:
+\begin{verbatim}
+ add.w:g rw10,rw8
+\end{verbatim}
+Was dieses Beispiel nicht zeigt, ist, da"s die Formatangabe auch ohne
+Operandengr"o"se geschrieben werden darf. Steht demgegen"uber eine
+Operandengr"o"se ohne Formatangabe, verwendet AS automatisch das
+k"urzeste Format. Die erlaubten Befehlsformate und Operandengr"o"sen
+sind vom Maschinenbefehl abh"angig und k"onnen z.B. \cite{Tosh9000},
+\cite{HitH8_5}, \cite{MitM16} bzw. \cite{MitM16C} entnommen werden.
+\par
+Die Zahl der Befehlsparameter ist abh"angig vom Befehl und kann
+prinzipiell zwischen 0 und 20 liegen. Die Trennung der Parameter
+voneinander erfolgt ausschlie"slich durch Kommas (Ausnahme: DSP56xxx,
+dessen parallele Datentransfers durch Leerzeichen getrennt werden),
+wobei in Klammern oder Hochkommas eingeschlossene Kommas nat"urlich
+nicht beachtet werden.
+\par
+Anstelle eines Kommentars am Ende kann die Zeile auch nur aus einem
+Kommentar bestehen, wenn er in der ersten Spalte beginnt.
+\par
+Bei den Leerzeichen zur Trennung einzelnen Komponenten darf es sich
+genauso gut um Tabulatoren handeln.
+
+%%---------------------------------------------------------------------------
+
+\section{Format des Listings}
+
+Das von AS bei Angabe der Kommandozeilenoptionen \tty{l} oder \tty{L}
+erzeugte Listing l"a"st sich grob in folgende Teile gliedern:
+\begin{enumerate}
+\item{Wiedergabe des assemblierten Quellcodes;}
+\item{Symbolliste;}
+\item{Makroliste;}
+\item{Funktionsliste;}
+\item{Belegungsliste;}
+\item{Querverweisliste.}
+\end{enumerate}
+Letztere beide werden nur erzeugt, wenn sie durch zus"atzliche
+Kommandozeilenoptionen angefordert wurden.
+\par
+Im ersten Teil listet AS den kompletten Inhalt aller Quelldateien inklusive
+des erzeugten Codes auf. Eine Zeile in diesem Listing hat dabei folgende Form:
+\begin{verbatim}
+[<n>] <Zeile>/<Adresse> <Code> <Quelle>
+\end{verbatim}
+Im Feld $n$ zeigt AS die Include-Verschachtelungstiefe an. Die
+Hauptdatei (die Datei, mit der die Assemblierung begann), hat dabei die
+Tiefe 0, von dort aus eingebundene Dateien haben Tiefe 1 usw. Die Tiefe
+0 wird dabei nicht angezeigt.
+\par
+Im Feld \tty{Zeile} wird die Zeilennummer bezogen auf die jeweilige Datei
+ausgegeben. Die erste Zeile einer Datei hat dabei Nummer 1. Die Adresse,
+an der der f"ur diese Zeile erzeugte Code abgelegt wurde, folgt hinter dem
+Schr"agstrich im Feld \tty{Adresse}.
+\par
+Der erzeugte Code selber steht dahinter im Feld \tty{Code} in
+hexadezimaler Schreibweise. Je nach Prozessortyp und aktuellem Segment
+k"onnen die Werte entweder als Bytes oder 16/32-Bit-Worte formatiert sein.
+Sollte mehr Code erzeugt worden sein, als in das Feld hineinpa"st, so
+werden im Anschlu"s an die Zeile weitere Zeilen erzeugt, in denen nur
+dieses Feld belegt ist.
+\par
+Im Feld \tty{Quelle} schlu"sendlich wird die Zeile aus der Quelldatei in
+ihrer Originalform ausgegeben.
+\par
+Die Symboltabelle ist so ausgelegt, da"s sie nach M"oglichkeit immer in 80
+Spalten dargestellt werden kann. F"ur Symbole ,,normaler L"ange'' wird
+eine zweispaltige Ausgabe gew"ahlt. Sollten einzelne Symbole mit ihrem
+Wert die Grenze von 40 Spalten "uberschreiten, werden sie in einer
+einzelnen Zeile ausgegeben. Die Ausgabe erfolgt in alphabetischer
+Reihenfolge. Symbole, die zwar definiert, aber nie benutzt wurden,
+werden mit einem vorangestellten Stern (\verb!*!) gekennzeichnet.
+\par
+Die bisher genannten Teile sowie die Auflistung aller definierten
+Makros / Funktionen lassen sich selektiv aus dem Gesamtlisting ein-und
+ausblenden, und zwar mit dem bereits erw"ahnten \tty{t}-Kommandozeilenschalter.
+Intern existiert in AS ein Byte, dessen Bits repr"asentieren, welche Teile
+ausgegeben werden sollen. Die Zuordnung von Bits zu den Teilen ist in
+Tabelle \ref{TabTBits} aufgelistet.
+\par
+\begin{table*}[p]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+Bit & Teil \\
+\hline
+\hline
+0 & Quelldatei(en)+erzeugter Code \\
+1 & Symboltabelle \\
+2 & Makroliste \\
+3 & Funktionsliste \\
+4 & Zeilennumerierung \\
+5 & Registersymboltabelle \\
+7 & Zeichentabellenliste \\
+\hline
+\end{tabular}\end{center}
+\caption{Zuordnung der Bits zu den Listingkomponenten\label{TabTBits}}
+\end{table*}
+Defaultm"a"sig sind alle Bits auf 1 gesetzt, bei Verwendung des Schalters
+\begin{verbatim}
+-t <Maske>
+\end{verbatim}
+werden die in \verb!<Maske>! gesetzten Bits gel"oscht, so da"s die entsprechenden
+Listing-Teile unterdr"uckt werden. Analog lassen sich mit einem Pluszeichen
+einzelne Teile wieder einschalten, falls man es in der \tty{ASCMD}-Variablen
+"ubertrieben hat...will man z.B. nur die Symboltabelle haben, so reicht
+\begin{verbatim}
+-t 2 .
+\end{verbatim}
+In der Belegungsliste werden f"ur jedes Segment einzeln die belegten Bereiche
+hexadezimal ausgegeben. Handelt es sich bei einem Bereich um eine einzige
+Adresse, wird nur diese ausgegeben, ansonsten erste und letzte Adresse.
+\par
+In der Querverweisliste wird f"ur jedes definierte Symbol in alphabetischer
+Reihenfolge eine Ausgabe folgender Form erzeugt:
+\begin{verbatim}
+Symbol <Symbolname> (=<Wert>,<Datei>/<Zeile>):
+ Datei <Datei 1>:
+ <n1>[(m1)] ..... <nk>[(mk)]
+ .
+ .
+ Datei <Datei l>:
+ <n1>[(m1)] ..... <nk>[(mk)]
+\end{verbatim}
+F"ur jedes Symbol wird aufgelistet, in welchen Dateien es in welchen Zeilen
+angesprochen wurde. Sollte ein Symbol mehrmals in der gleichen Zeile
+benutzt worden sein, so wird dies durch eine in Klammern gesetzte Anzahl
+hinter der Zeilennummer angedeutet. Sollte ein Symbol niemals benutzt
+worden sein, erscheint es auch nicht in der Liste; entsprechend erscheint
+eine Datei auch "uberhaupt nicht in der Liste eines Symbols, falls es in
+der entsprechenden Datei nicht referenziert wurde.
+\par
+\bb{ACHTUNG!} AS kann dieses Listing nur dann korrekt aufs Papier bringen,
+wenn man ihm vorher die L"ange und Breite des Ausgabemediums mit Hilfe des
+\tty{PAGE}-Befehls (siehe dort) mitgeteilt hat! Der voreingestellte
+Default sind 60 Zeilen und eine unbegrenzte Zeilenbreite.
+
+%%---------------------------------------------------------------------------
+
+\section{Symbolkonventionen}
+\label{SectSymConv}
+
+Symbole d"urfen zwar (wie in der Einleitung bereits angedeutet) bis zu
+255 Zeichen lang werden und werden auch auf der ganzen L"ange
+unterschieden, die Symbolnamen m"ussen aber einigen Konventionen
+gen"ugen:
+\par
+Symbolnamen d"urfen aus einer beliebigen Kombination von Buchstaben,
+Ziffern, Unterstrichen und Punkten bestehen, wobei das erste Zeichen
+keine Ziffer sein darf. Der Punkt wurde nur zugelassen, um der
+MCS-51-Notation von Registerbits zu gen"ugen, und sollte m"oglichst nicht in
+eigenen Symbolnamen verwendet werden. Zur Segmentierung von Symbolnamen
+sollte auf jeden Fall der Unterstrich und nicht der Punkt verwendet werden.
+\par
+Defaultm"a"sig ist AS nicht case-sensitiv, es ist also egal, ob man
+Gro"s-oder Kleinbuchstaben verwendet. Mittels des Kommandozeilenschalters
+\tty{U} l"a"st sich AS jedoch in einen Modus umschalten, in dem Gro"s- und
+Kleinschreibung unterschieden wird. Ob AS umgeschaltet wurde, kann mit dem
+vordefinierten Symbol \tty{CASESENSITIVE} ermittelt werden: TRUE bedeutet
+Unterscheidung, FALSE keine.
+\par
+Tabelle \ref{TabPredefined} zeigt die wichtigsten, von AS vordefinierten
+Symbole.
+\begin{table*}[p]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+Name & Bedeutung \\
+\hline
+\hline
+\tty{TRUE} & logisch ,,wahr'' \\
+\tty{FALSE} & logisch ,,falsch'' \\
+\tty{CONSTPI} & Kreiszahl Pi (3.1415.....) \\
+\tty{VERSION} & Version von AS in BCD-Kodierung, \\
+ & z.B. 1331 hex f"ur Version 1.33p1 \\
+\tty{ARCHITECTURE} & Zielplattform, f"ur die AS "ubersetzt wurde, \\
+ & in der Form Prozesor-Hersteller-Betriebssystem \\
+\tty{DATE} & Datum und \\
+\tty{TIME} & Zeitpunkt der Assemblierung (Beginn) \\
+\tty{MOMCPU} & momentan gesetzte Ziel-CPU \\
+\tty{MOMCPUNAME} & dito, nur als voll ausgeschriebener String \\
+\tty{MOMFILE} & augenblickliche Quelldatei \\
+\tty{MOMLINE} & Zeilennummer in Quelldatei \\
+\tty{MOMPASS} & Nummer das laufenden Durchgangs \\
+\tty{MOMSECTION} & Name der aktuellen Sektion oder \\
+ & Leerstring \\
+\tty{MOMSEGMENT} & Name des mit \tty{SEGMENT} gew"ahlten \\
+ & Adre"sraumes \\
+\verb!*!, \$ bzw. \tty{PC} & mom. Programmz"ahler \\
+\hline
+\end{tabular}\end{center}
+\caption{Vordefinierte Symbole\label{TabPredefined}}
+\end{table*}
+\bb{VORSICHT!} W"ahrend es im case-insensitiven Modus egal ist,
+mit welcher Kombination von Gro"s- und Kleinbuchstaben man
+vordefinierte Symbole anspricht, mu"s man sich im case-sensitiven
+Modus exakt an die oben angegebene Schreibweise (nur Gro"sbuchstaben)
+halten!
+\par
+Zus"atzlich definieren einige Pseudobefehle noch Symbole, die eine
+Abfrage des damit momentan eingestellten Wertes erm"oglichen. Deren
+Beschreibung findet sich bei den zugeh"origen Befehlen.
+\par
+Ein etwas verstecktes (und mit Vorsicht zu nutzendes) Feature ist,
+Symbolnamen aus String-Variablen zusammenzubauen, indem man den
+Namen des Strings mit geschweiften Klammern in den Symbolnamen
+einbaut. So kann man z.B. den Namen eines Symbols anhand des
+Wertes eines anderen Symbols festlegen:
+\begin{verbatim}
+cnt set cnt+1
+temp equ "\{CNT}"
+ jnz skip{temp}
+ .
+ .
+skip{temp}: nop
+\end{verbatim}
+\bb{ACHTUNG!} Der Programmierer ist selber daf"ur verantwortlich,
+da"s sich dabei g"ultige Symbolnamen ergeben!
+\par
+Eine vollst"andige Auflistung aller von AS verwendeten Symbolnamen
+findet sich in Anhang \ref{AppInternSyms}.
+\par
+Neben seinem Wert besitzt auch jedes Symbol eine Markierung, zu welchen
+{\em Segment} es geh"ort. In erster Linie wird eine solche Unterscheidung
+bei Prozessoren ben"otigt, die mehrere Adre"sr"aume besitzen. AS kann mit
+dieser Zusatzinformation bei Zugriffen "uber ein Symbol warnen, wenn ein
+f"ur diesen Adre"sraum ungeeigneter Befehl verwendet wird. Ein
+Segmentattribut wird einem Symol automatisch angeh"angt, wenn es als Label
+oder mit einem Spezialbefehl (z.B. \tty{BIT}) definiert wird; ein mit
+dem ,,Universalbefehl'' \tty{SET} oder \tty{EQU} definiertes Symbol ist
+jedoch ,,typenlos'', d.h. seine Verwendung wird niemals Warnungen
+ausl"osen. Das Segmentattribut eines Symbols kann mit der eingebauten
+Funktion \tty{SYMTYPE} abgefragt werden, etwa so:
+\begin{verbatim}
+Label:
+ .
+ .
+Attr equ symtype(Label) ; ergibt 1
+\end{verbatim}
+Den einzelnen Segmenttypen sind die in Tabelle \ref{TabSegNums}
+aufgelisteten Nummern zugeordnet. Die aus der Ordnung normaler Symbole
+etwas herausfallenden Registersymbole sind n"aher in Abschnitt
+\ref{SectRegSyms} erl"autert. Mit einem undefinierten Symbol als Argument
+liefert die \tty{SYMTYPE}-Funktion -1 als Ergebnis.
+\begin{table}[htb]
+\begin{center}
+\begin{tabular}{|l|c|}
+\hline
+Segment & R"uckgabewert \\
+\hline
+$<$keines$>$ & 0 \\
+CODE & 1 \\
+DATA & 2 \\
+IDATA & 3 \\
+XDATA & 4 \\
+YDATA & 5 \\
+BITDATA & 6 \\
+IO & 7 \\
+REG & 8 \\
+ROMDATA & 9 \\
+$<$Registersymbol$>$ & 128 \\
+\hline
+\end{tabular}
+\end{center}
+\caption{R"uckgabewerte der \tty{SYMTYPE}-Funktion\label{TabSegNums}}
+\end{table}
+
+%%---------------------------------------------------------------------------
+
+\section{Formelausdr"ucke}
+
+An den meisten Stellen, an denen der Assembler Zahlenangaben erwartet,
+k"onnen nicht nur einfache Symbole oder Konstanten angegeben werden,
+sondern ganze Formelausdr"ucke. Bei den Komponenten der Formelausdr"ucke
+kann es sich sowohl um ein einzelnes Symbol als auch um eine Konstante
+handeln. Konstanten d"urfen entweder Integer-, Gleitkomma-, oder
+Stringkonstanten sein.
+
+\subsection{Integerkonstanten}
+\label{SectIntConsts}
+
+Integerkonstanten bezeichnen ganze Zahlen. Sie d"urfen entweder als eine
+Folge von Ziffern oder als eine Reihe von in {\em einfachen} Hochkommas
+eingeschlossenen Zeichen geschrieben werden. Werden sie als Ziffernfolgen
+geschrieben, so kann dies in verschiedenen Zahlensystemen erfolgen, deren
+Kennzeichnung von verwendeten Zielprozessor abh"angt (Tabelle
+\ref{TabSystems}).
+\par
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|c|c|c|}
+\hline
+ & Intel-Modus & Motorola-Modus & C-Modus \\
+ & (Intel, Zilog, & (Rockwell, Motorola, & (PowerPC, \\
+ & Thomson, Texas, & Microchip, Thomson, & AMD29K, \\
+ & Toshiba, NEC, & Hitachi, Atmel) & National,\\
+ & Siemens, Philips, & & Symbios) \\
+ & Fujitsu, Fairchild) & & \\
+\hline
+\hline
+dezimal & direkt & direkt & direkt \\
+hexadezimal & nachgestelltes H & vorangestelltes \$ & vorangestelltes 0x \\
+bin"ar & nachgestelltes B & vorangestelltes \% & vorangestelltes 0b \\
+oktal & nachgestelltes O & vorangestelltes @ & vorangestellte 0 \\
+\hline
+\end{tabular}\end{center}
+\caption{m"ogliche Zahlensysteme\label{TabSystems}}
+\end{table*}
+Falls das Zahlensystem nicht explizit durch vor-oder nachgestelle Zeichen
+vorgegeben wird, nimmt AS die Basis an, die mit dem {\tt RADIX}-Befehl
+vorgegeben wurde (der Default dieser Einstellung ist wiederum 10). Mit
+diesem Befehl lassen sich auch ,,ungew"ohnliche" Zahlensysteme, d.h.
+andere als 2, 8, 10 oder 16 einstellen.
+
+G"ultige Ziffern sind die Zahlen 0 bis 9 sowie die Buchstaben A bis Z
+(Wert 10 bis 35) bis zur Basis des Zahlensystems minus eins. Die
+Verwendung von Buchstaben in Integerkonstanten bringt allerdings auch
+einige Mehrdeutigkeiten mit sich, da Symbolnamen ja auch Ketten aus Zahlen
+und Buchstaben sind: Ein Symbolname darf nicht mit einem Zeichen von 0 bis
+9 beginnen, was bedeutet, da"s eine Integerkonstante, die nicht durch ein
+anderes Sonderzeichen eindeutig als solche erkennbar ist, niemals mit
+einem Buchstaben beginnen darf; notfalls mu"s man eine eigentlich
+"uberfl"ussige Null voranstellen. Der bekannteste Fall ist das Scheiben
+von Hexadezimalkonstanten im Intel-Modus: Ist die vorderste Stelle
+zwischen A und F, so hilft das hintangestellte H "uberhaupt nichts, es
+mu"s noch eine Null davor (statt F0H also 0F0H). Die Motorola-oder
+C-Syntax, die beide das Zahlensystem am Anfang einer Integerkonstante
+kennzeichnen, kennen dieses Problem nicht. (\ii{hihihi!}).
+
+Reichlich heimt"uckisch ist auch, da"s bei immer h"oheren, mit {\tt RADIX}
+eingestellten Zahlensystemen, die bei Intel- und C-Syntax benutzten
+Buchstaben zur Zahlensystemkennung immer weiter ,,aufgefressen'' werden; so
+kann man z.B. nach {\tt RADIX 16} keine bin"aren Konstanten mehr
+schreiben, und ab {\tt RADIX 18} in Intel-Syntax auch keine hexadezimalen
+Konstanten mehr. Also {\bf VORSICHT!}
+
+Mit Hilfe des \tty{RELAXED}-Befehls (siehe Abschnitt \ref{SectRELAXED})
+kann die starre Zuordnung einer Schreibweise zu einem Zielprozessor
+aufgehoben werden, so da"s man eine beliebige Schreibweise verwenden
+kann (auf Kosten der Kompatibilit"at zu Standard-Assemblern).
+Defaultm"a"sig ist diese Option aber ausgeschaltet.
+
+Wie bereits angesprochen, k"onnen Integer-Konstanten auch als ASCII-Werte
+geschrieben werden, so entsprechen
+\begin{verbatim}
+'A' ==$41
+'AB' ==$4142
+'ABCD' ==$41424344
+\end{verbatim}
+Wichtig ist, da"s hier die Zeichen in {\em einfachen Hochkommas}
+geschrieben werden, um sie von den weiter unten beschriebenen
+Stringkonstanten zu unterscheiden.
+
+\subsection{Gleitkommakonstanten}
+
+Gleitkommazahlen werden in der "ublichen halblogarithmischen
+Schreibweise geschrieben, die in der allgemeinsten Form
+\begin{verbatim}
+ [-]<Vorkommastellen>[.Nachkommastellen][E[-]Exponent]
+\end{verbatim}
+lautet. \bb{ACHTUNG!} Der Assembler versucht eine Konstante zuerst als
+Integerkonstante zu verstehen und macht erst dann einen Versuch mit
+Gleitkomma, falls dies gescheitert ist. Will man aus irgendwelchen
+Gr"unden die Auswertung als Gleitkommazahl erzwingen, so kann man
+dies durch Dummy-Nachkommastellen erreichen, z.B. \tty{2.0} anstelle
+\tty{2}.
+
+\subsection{Stringkonstanten}
+\label{SectStringConsts}
+
+Stringkonstanten m"ussen in {\em doppelte Hochkommas} (um sie von den oben
+beschrieben ASCII-Integers zu unterscheiden) eingeschlossen werden. Um nun
+aber auch G"ansef"u"schen und Sonderzeichen ohne Verrenkungen in
+String-Konstanten einbauen zu k"onnen, wurde ein ,,Escape-Mechanismus''
+eingebaut, der Programmierer(inne)n aus C bekannt vorkommen d"urfte:
+
+Schreibt man einen Backslash mit einer maximal dreiziffrigen Zahl im
+String, so versteht der Assembler dies als Zeichen mit dem entsprechenden
+dezimalen ASCII-Wert. Alternativ kann der Zahlenwert auch hexadezimal
+oder oktal mit einem vorangestellten x oder einer vorangestellten 0
+geschrieben werden. F"ur die hexadezimale Schreibweise reduziert sich die
+Maximalanzahl von Stellen auf 2. So kann man z.B. mit {\tt\verb!\3!} ein
+ETX-Zeichen definieren. Vorsicht allerdings mit der Definition von
+NUL-Zeichen! Da die C-Version \marginpar{{\em UNIX}} von AS momentan
+intern zur Speicherung von String-Symbolen C-Strings benutzt (die durch
+NUL-Zeichen terminiert werden), sind NUL-Zeichen in Strings momentan nicht
+portabel!
+
+Einige besonders h"aufig gebrauchte Steuerzeichen kann man auch mit
+folgenden Abk"urzungen erreichen:
+\begin{quote}\begin{tabbing}
+\hspace{4cm} \= \hspace{4cm} \= \kill
+\verb!\b! : Backspace \> \verb!\a! : Klingel \> \verb!\e! : Escape \\
+\verb!\t! : Tabulator \> \verb!\n! : Zeilenvorschub \> \verb!\r! : Wagenr"ucklauf \\
+\verb!\\! : Backslash \> \verb!\'! oder \verb!\h! : Hochkomma \\
+\verb!\"! oder \verb!\i! : G"ansef"u"schen \\
+\end{tabbing}\end{quote}
+Die Kennbuchstaben d"urfen sowohl gro"s als auch klein geschrieben
+werden.
+\par
+"Uber dieses Escape-Zeichen k"onnen sogar Formelausdr"ucke in den
+String eingebaut werden, wenn sie in geschweifte Klammern eingefa"st
+werden: z.B. ergibt
+\begin{verbatim}
+ message "Wurzel aus 81 : \{sqrt(81)}"
+\end{verbatim}
+die Ausgabe
+\begin{verbatim}
+ Wurzel aus 81 : 9
+\end{verbatim}
+Der Assembler w"ahlt anhand des Formelergebnistyps die richtige
+Ausgabeform, zu vermeiden sind lediglich weitere Stringkonstanten
+im Ausdruck, da der Assembler bei der Gro"s-zu-Kleinbuchstabenumwandlung
+sonst durcheinanderkommt. Integer-Ausdr"ucke werden defaultm"a"sig
+hexadezimal ausgegeben, dies l"a"st sich jedoch mit dem
+\tty{OUTRADIX}-Befehl "andern.
+\par
+Bis auf den Einbau von Formelausdr"ucken ist dieser Escape-Mechanismus
+auch in als ASCII definierten Integerkonstanten zul"assig, z.B. so:
+\begin{verbatim}
+ move.b #'\n',d0
+\end{verbatim}
+Jedoch hat alles seine Grenzen, weil der dar"uberliegende Splitter, der
+die Zeile in Opcode und Parameter zerlegt, nicht wei"s, womit er da
+eigentlich arbeitet, z.B. hier:
+\begin{verbatim}
+ move.l #'\'abc',d0
+\end{verbatim}
+Nach dem dritten Hochkomma findet er das Komma nicht mehr, weil er
+vermutet, da"s eine weitere Zeichenkonstante beginnt, und eine
+Fehlermeldung "uber eine falsche Parameterzahl ist die Folge. Abhilfe
+w"are z.B., \verb!\h! anstelle \verb!\'! zu schreiben.
+
+\subsection{Evaluierung}
+
+Die Berechnung von im Formelausdruck entstehenden Zwischenergebnissen
+erfolgt immer mit der h"ochsten verf"ugbaren Wortbreite, d.h. 32 Bit f"ur
+Ganzzahlen, 80 Bit f"ur Gleitkommazahlen und 255 Zeichen f"ur Strings.
+Eine eventuelle Pr"ufung auf Wertebereichs"uberschreitung findet erst am
+Endergebnis statt.
+\par
+Die portable C-Version \marginpar{{\em UNIX}} kann nur mit
+64-Bit-Gleitkommazahlen umgehen, ist daher auf einen Maximalwert von ca.
+$10^{308}$ beschr"ankt. Als Ausgleich werden auf einigen Plattformen
+Integers mit 64 Bit Breite behandelt.
+
+\subsection{Operatoren}
+
+Der Assembler stellt zur Verkn"upfung die in Tabelle \ref{TabOps} genannten
+Operanden zur Verf"ugung.
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|c|l|c|c|c|c|c|}
+\hline
+Op. & Funktion & \#Ops. & Int & Float & String & Rang \\
+\hline
+\hline
+$<>$ & Ungleichheit & 2 & ja & ja & ja & 14 \\
+$>=$ & gr"o"ser o. gleich & 2 & ja & ja & ja & 14 \\
+$<=$ & kleiner o. gleich & 2 & ja & ja & ja & 14 \\
+$<$ & echt kleiner & 2 & ja & ja & ja & 14 \\
+$>$ & echt gr"o"ser & 2 & ja & ja & ja & 14 \\
+$=$ & Gleichheit & 2 & ja & ja & ja & 14 \\
+$==$ & Alias f"ur $=$ & & & & & \\
+ & & & & & & \\
+$!!$ & log. XOR & 2 & ja & nein & nein & 13 \\
+$||$ & log. OR & 2 & ja & nein & nein & 12 \\
+\&\& & log. AND & 2 & ja & nein & nein & 11 \\
+\verb! ~~ ! & log. NOT & 1 & ja & nein & nein & 2 \\
+ & & & & & & \\
+- & Differenz & 2 & ja & ja & nein & 10 \\
++ & Summe & 2 & ja & ja & ja & 10 \\
+\# & Modulodivision & 2 & ja & nein & nein & 9 \\
+/ & Quotient & 2 & ja*) & ja & nein & 9 \\
+\verb! * ! & Produkt & 2 & ja & ja & nein & 9 \\
+\verb! ^ ! & Potenz & 2 & ja & ja & nein & 8 \\
+ & & & & & & \\
+$!$ & bin"ares XOR & 2 & ja & nein & nein & 7 \\
+$|$ & bin"ares OR & 2 & ja & nein & nein & 6 \\
+\& & bin"ares AND & 2 & ja & nein & nein & 5 \\
+$><$ & Bitspiegelung & 2 & ja & nein & nein & 4 \\
+$>>$ & log. Rechtsschieben & 2 & ja & nein & nein & 3 \\
+$<<$ & log. Linksschieben & 2 & ja & nein & nein & 3 \\
+\verb! ~ ! & bin"ares NOT & 1 & ja & nein & nein & 1 \\
+\hline
+\multicolumn{7}{|l|}{*) Rest wird verworfen} \\
+\hline
+\end{tabular}\end{center}
+\caption{in AS definierte Operatoren\label{TabOps}}
+\end{table*}
+Unter ,,Rang'' ist dabei die Priorit"at zu verstehen, die dieser Operator bei
+der Teilung eines Ausdruckes in Unterausdr"ucke hat, der rangh"ochste
+Operator wird also \ii{zuletzt} ausgewertet. Die Reihenfolge der
+Evaluierung l"a"st sich durch Klammerung neu festlegen.
+\par
+Die Vergleichsoperatoren liefern TRUE, falls die Bedingung zutrifft,
+und FALSE falls nicht. Vergleiche betrachten Integerzahlen dabei als
+32 Bit breit und vorzeichenbehaftet. F"ur die logischen Operatoren
+ist ein Ausdruck TRUE, falls er ungleich 0 ist, ansonsten FALSE.
+\par
+Die Bitspiegelung ist wohl etwas erkl"arungsbed"urftig: Der Operator
+spiegelt die untersten Bits im ersten Operanden, l"a"st die
+dar"uberliegenden Bits aber unver"andert. Die Zahl der zu spiegelnden
+Bits ist der rechte Operand und darf zwischen 1 und 32 liegen.
+\par
+Eine keine Fu"sangel beim bin"aren Komplement: Da die Berechnung
+grunds"atzlich auf 32- oder 64-Bit-Ebene erfolgt, ergibt seine Anwendung
+auf z.B. 8-Bit-Masken "ublicherweise Werte, die durch voranstehende
+Einsen nicht mehr im entferntesten in 8-Bit-Zahlen hineinpassen. Eine
+bin"are UND-Verkn"upfung mit einer passenden Maske ist daher unvermeidlich!
+
+\subsection{Funktionen}
+
+Zus"atzlich zu den Operatoren definiert der Assembler noch eine Reihe
+in erster Linie transzendenter Funktionen mit Gleitkommaargument, die
+Tabellen \ref{TabFuncs1} und \ref{TabFuncs2} auflisten.
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+Name & Funktion & Argument & Ergebnis \\
+\hline
+\hline
+SQRT & Quadratwurzel & $arg \geq 0$ & Gleitkomma \\
+ & & & \\
+SIN & Sinus & $arg \in \rz$ & Gleitkomma \\
+COS & Kosinus & $arg \in \rz$ & Gleitkomma \\
+TAN & Tangens & $arg \neq (2*n+1)*\frac{\pi}{2}$ & Gleitkomma \\
+COT & Kotangens & $arg \neq n*\pi$ & Gleitkomma \\
+ & & & \\
+ASIN & inverser Sinus & $\mid arg \mid \leq 1$ & Gleitkomma \\
+ACOS & inverser Kosinus & $\mid arg \mid \leq 1$ & Gleitkomma \\
+ATAN & inverser Tangens & $arg \in \rz$ & Gleitkomma \\
+ACOT & inverser Kotangens & $arg \in \rz$ & Gleitkomma \\
+ & & & \\
+EXP & Exponentialfunktion & $arg \in \rz$ & Gleitkomma \\
+ALOG & 10 hoch Argument & $arg \in \rz$ & Gleitkomma \\
+ALD & 2 hoch Argument & $arg \in \rz$ & Gleitkomma \\
+SINH & hyp. Sinus & $arg \in \rz$ & Gleitkomma \\
+COSH & hyp. Kosinus & $arg \in \rz$ & Gleitkomma \\
+TANH & hyp. Tangens & $arg \in \rz$ & Gleitkomma \\
+COTH & hyp. Kotangens & $arg \neq 0$ & Gleitkomma \\
+ & & & \\
+LN & nat. Logarithmus & $arg > 0$ & Gleitkomma \\
+LOG & dek. Logarithmus & $arg > 0$ & Gleitkomma \\
+LD & 2er Logarithmus & $arg > 0$ & Gleitkomma \\
+ASINH & inv. hyp. Sinus & $arg \in \rz$ & Gleitkomma \\
+ACOSH & inv. hyp. Kosinus & $arg \geq 1$ & Gleitkomma \\
+ATANH & inv. hyp. Tangens & $\mid arg \mid < 1$ & Gleitkomma \\
+ACOTH & inv. hyp. Kotangens & $\mid arg \mid > 1$ & Gleitkomma \\
+ & & & \\
+INT & ganzzahliger Anteil & $arg \in \rz$ & Integer \\
+ & & & \\
+BITCNT & bin"are Quersumme & Integer & Integer \\
+FIRSTBIT & niedrigstes 1-Bit & Integer & Integer \\
+LASTBIT & h"ochstes 1-Bit & Integer & Integer \\
+BITPOS & einziges 1-Bit & Integer & Integer \\
+ & & & \\
+SGN & Vorzeichen (0/1/-1) & Integer oder & Integer \\
+ & & Gleitkomma & \\
+\hline
+\end{tabular}\end{center}
+\caption{vordefinierte Funktionen in AS - Teil 1 (Integer- und
+ Gleitkommafunktionen)\label{TabFuncs1}}
+\end{table*}
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+Name & Funktion & Argument & Ergebnis \\
+\hline
+\hline
+ABS & Betrag & Integer oder & Integer oder \\
+ & & Gleitkomma & Gleitkomma \\
+TOUPPER & pass. Gro"sbuchstabe & Integer & Integer \\
+TOLOWER & pass. Kleinbuchstabe & Integer & Integer \\
+UPSTRING & wandelt alle Zeichen & String & String \\
+ & in Gro"sbuchstaben & & \\
+LOWSTRING & wandelt alle Zeichen & String & String \\
+ & in Kleinbuchstaben & & \\
+STRLEN & liefert L"ange eines & String & Integer \\
+ & Strings & & \\
+SUBSTR & extrahiert Teil eines & String, & String \\
+ & Strings & Integer, & \\
+ & & Integer & \\
+STRSTR & sucht Teilstring in & String, & Integer \\
+ & einem String & String & \\
+VAL & evaluiert Stringin- & String & abh. von \\
+ & halt als Ausdruck & & Argument \\
+\hline
+\end{tabular}\end{center}
+\caption{vordefinierte Funktionen in AS - Teil 2
+ (Integer- und String-Funk\-tio\-nen)\label{TabFuncs2}}
+\end{table*}
+Die Funktionen \tty{FIRSTBIT}, \tty{LASTBIT} und \tty{BITPOS} liefern
+als Ergebnis -1, falls "uberhaupt kein bzw. nicht genau ein Bit gesetzt
+ist. Zus"atzlich gibt \tty{BITPOS} in einem solchen Fall eine
+Fehlermeldung aus.
+\par
+Die String-Funktion \tty{SUBSTR} erwartet als ersten Parameter den
+Quellstring, als zweiten die Startposition und als dritten die Anzahl zu
+extrahierender Zeichen (eine 0 bedeutet, alle Zeichen bis zum Ende zu
+extrahieren). \tty{STRSTR} liefert das erste Auftreten des zweiten Strings
+im ersten bzw. -1, falls das Suchmuster nicht gefunden wurde. Beide
+Funktionen numerieren die Zeichen in einem String ab 0 durch!
+\par
+Wenn eine Funktion auch Gleitkommaargumente erwartet, so soll
+dies nicht bedeuten, da"s man nicht z.B.
+\begin{verbatim}
+wur2 equ sqrt(2)
+\end{verbatim}
+schreiben d"urfte --- in solchen F"allen findet automatisch eine
+Typkonvertierung statt. Umgekehrt mu"s allerdings die \tty{INT}-Funktion
+angewandt werden, um eine Gleitkommazahl ganz zu bekommen. Bei der
+Benutzung dieser Funktion ist zu beachten, da"s sie als Ergebnis
+immer einen vorzeichenbehafteten Integer liefert, sie hat also
+einen Wertebereich von ca. +/-2.0E9.
+\par
+Schaltet man AS in den case-sensitiven Modus, so k"onnen im
+Gegensatz zu vordefinierten Symbolen die vordefinierten Funktionen
+weiterhin in beliebiger Schreibweise angesprochen werden. Bei
+selbstdefinierten Funktionen (siehe Abschnitt \ref{SectFUNCTION}
+wird allerdings unterschieden. Dies hat zur Folge, da"s z.B. bei
+der Definition einer Funktion \tty{Sin} man mit \tty{Sin} diese
+Funktion auch erreicht, mit allen anderen Schreibweisen jedoch die
+eingebaute Funktion.
+\par
+F"ur die korrekte Umwandlung \marginpar{{\em DOS/}} von Klein-zu
+Gro"sbuchstaben ist eine DOS-Version $\geq$ 3.30
+erforderlich.
+
+\vspace{2mm}
+\marginpar{{\em DPMI}}
+
+%%---------------------------------------------------------------------------
+
+\section{Vorw"artsreferenzen und andere Desaster}
+\label{ForwRefs}
+
+Dieser Abschnitt ist das Produkt eines gewissen Grolls auf die (durchaus
+legale) Art und Weise, wie einige Leute programmieren, die in Zusammenhang
+mit AS bisweilen das eine oder andere Problem verursachen kann. Die Rede
+ist hier von sogenannten ,,Vorw"artsreferenzen''. Was unterscheidet eine
+Vorw"artsreferenz von einer normalen Referenz? Dazu sehe man sich folgendes
+Programmbeispiel an (man sehe mir bitte meine -- auch im Rest dieser Anleitung
+anzutreffende -- 68000-Lastigkeit nach):
+\begin{verbatim}
+ move.l d0,#10
+loop: move.l d1,(a1)
+ beq skip
+ neg.l d1
+skip: move.l (a1+),d1
+ dbra d0,loop
+\end{verbatim}
+Denkt man sich den Scheifenrumpf mit dem Sprung weg, so bleibt ein
+"au"serst angenehm zu assemblierendes Programm "ubrig: die einzige
+Referenz ist der R"ucksprung zum Anfang des Rumpfes, und da ein
+Assembler ein Programm von vorne nach hinten durcharbeitet, hat er
+den Symbolwert bereits ermittelt, bevor er ihn zum erstem Mal ben"otigt.
+Sofern man ein Programm hat, das nur solche R"uckw"artsreferenzen besitzt,
+ist man in der angenehmen Lage, nur einmal durch den Quellcode gehen zu
+m"ussen, um den korrekten und optimalen Maschinencode zu finden. Einige
+Hochsprachen wie Pascal mit ihrer strikten Regel, da"s alles vor der ersten
+Benutzung definiert sein mu"s, nutzen genau diese Eigenschaft aus, um den
+"ubersetzungsvorgang zu beschleunigen.
+
+Leider ist die Sache im Falle von Assembler nicht so einfach, denn man
+will ja bisweilen auch vorw"arts im Code springen oder mu"s aus bestimmten
+Gr"unden Variablendefinitionen hinter den Code verlegen. Dies ist
+im Beispiel der Fall f"ur den bedingten Sprung, mit dem ein anderer
+Befehl "ubersprungen wird. Wenn der Assembler im ersten Durchlauf auf
+den Sprungbefehl trifft, so sieht er sich mit der Situation konfrontiert,
+entweder die Teilfelder der Instruktion, die die Sprungadresse beinhalten,
+leerzulassen, oder seitens des Formelparsers (der das Adre"sargument ja
+auswerten mu"s) anstelle des korrekten, aber unbekannten Wertes einen Wert
+anzubieten, der ,,niemandem wehtut''. Bei einem einfachen Assembler, der
+nur eine Zielarchitektur kennt und bei dem sich die betroffenen Befehle
+an einer Hand abz"ahlen lassen, wird man sicher die erste Variante w"ahlen,
+bei AS mit seinen vielen Dutzend Zielen w"are die Zahl der Sonderabfragen
+aber extrem hoch geworden, so da"s nur der zweite Weg in Frage kam: Falls
+im ersten Pass ein unbekanntes Symbol auftaucht, so liefert der Formelparser
+den momentanen Stand des Programmz"ahlers als Ergebnis zur"uck! Nur dieser
+Wert ist geeignet, relativen Spr"ungen mit Sprungdistanzen unbekannter
+L"ange eine Adresse anzubieten, die nicht zu Fehlern f"uhrt. Dies beantwortet
+auch die bisweilen gestellte Frage, warum in einem Listing des ersten
+Passes (dies bleibt z.B. stehen, wenn AS aufgrund anderer Fehler den
+zweiten Pass erst gar nicht beginnt), z.T. falsche Adressen im erzeugten
+Bin"arcode gezeigt werden - dies sind noch nicht aufgel"oste
+Vorw"artsreferenzen.
+
+Das obige Beispiel offenbart allerdings noch eine weitere Schwierigkeit
+von Vorw"artsreferenzen: Je nach Abstand von Quelle und Ziel im Code kann
+der Sprungbefehl entweder lang oder kurz sein. Diese Entscheidung "uber
+die Code-L"ange - und damit auch die Adressen folgender Labels - kann
+jedoch mangels genauer Kenntnis der Zieladresse im ersten Pass nicht
+erfolgen. Sofern der Programmierer nicht explizit kenntlich gemacht hat,
+ob der Sprung lang oder kurz sein soll, behelfen sich reine 2-Pass-Assembler
+wie "altere MASM-Versionen von Microsoft damit, im ersten Pass (nach diesem
+m"ussen alle Adressen festliegen) Platz f"ur die l"angste Version zu
+reservieren und im zweiten Pass den "ubersch"ussigen Platz mit \tty{NOP}s
+aufzuf"ullen. AS-Versionen bis 1.37 taten dieses ebenfalls, danach bin
+ich auf das Multipass-Verfahren "ubergegangen, das die strenge Einteilung
+in zwei Passes aufhebt und beliebig viele Durchg"ange erlaubt. Dazu wird
+im ersten Pass der optimale Code mit den angenommenen Symbolwerten erzeugt.
+Stellt AS fest, da"s im zweiten Pass durch Codel"angenver"anderungen sich
+Werte von Symbolen ge"andert haben, so wird einfach noch ein dritter Pass
+eingelegt, und da durch die neuen Symbolwerte des zweiten Passes auch
+im dritten Pass sich der Code wieder verk"urzen oder verl"angern kann,
+ist ein weiterer Pass nicht unm"oglich. Ich habe schon 8086-Programme
+erlebt, bei denen erst nach 12 Durchg"angen alles stimmte. Leider
+erlaubt dieser Mechanismus nicht die Vorgabe einer Maximalzahl von
+Durchl"aufen, ich kann als Regel nur sagen, da"s die Anzahl von Durchl"aufen
+sinkt, je mehr man davon Gebrauch macht, Sprung- oder Adre"sl"angen explizit
+vorzugeben.
+
+Speziell bei gro"sen Programmen kann es zu einer interessanten Situation
+kommen: Die Lage eines vorw"arts gerichteten Sprunges hat sich
+im zweiten Pass so weit gegen"uber dem ersten verschoben, da"s der
+jetzt noch benutzte Label-Wert aus dem ersten Pass au"serhalb der
+erlaubten Sprungdistanz liegt. AS ber"ucksichtigt solche Situationen,
+indem er jegliche Fehlermeldungen "uber zu weite Sprungdistanzen unterdr"uckt,
+sobald er erkannt hat, da"s er wegen sich "andernder Symbolwerte ohnehin
+einen weiteren Durchlauf machen mu"s. Dies funktioniert zwar in 99\%
+aller F"alle, es gibt jedoch auch Konstrukte, in denen der erste, derartig
+kritische Befehl bereits auftaucht, bevor AS eine Chance hat, zu erkennen,
+da"s ein neuer Pass erforderlich ist. Das folgende Beispiel konstruiert
+eine solche Situation mit Hilfe einer Vorw"artsreferenz (und war der
+Anla"s f"ur die "Uberschrift dieses Abschnitts...):
+\begin{verbatim}
+ cpu 6811
+
+ org $8000
+ beq skip
+ rept 60
+ ldd Var
+ endm
+skip: nop
+
+Var equ $10
+\end{verbatim}
+Aufgrund der Adre"slage nimmt AS im ersten Pass lange Adressen f"ur die
+\tty{LDD}-Befehle an, was eine Code-L"ange von 180 Bytes ergibt und im
+zweiten Pass (zum Zeitpunkt des \tty{BEQ}-Befehls ist noch der ,,falsche''
+Wert von \tty{skip} aktuell, d.h. AS wei"s zu diesem Zeitpunkt noch nicht,
+da"s der Code in Wirklichkeit nur 120 Bytes lang ist) gibt es eine
+Fehlermeldung wegen einer "uberschrittenen Sprungdistanz. Dieser Fehler
+l"a"st sich auf drei Arten vermeiden:
+\begin{enumerate}
+\item{Weisen Sie AS explizit darauf hin, da"s er f"ur die \tty{LDD}-Befehle
+ kurze Adressen verwenden darf (\tty{ldd <Var})}
+\item{Entfernen Sie diese vermaledeite, verfluchte Vorw"artsreferenz und
+ setzen Sie die \tty{EQU}-Anweisung nach vorne, wo sie hingeh"ort
+ (OK, ich beruhige mich ja schon wieder...)}
+\item{F"ur ganz Unentwegte: Benutzten Sie die \tty{-Y}-Option, so da"s AS die
+ Fehlermeldung beim Erkennen der Adre"sverschiebung nachtr"aglich
+ verwirft. Nicht sch"on, aber...}
+\end{enumerate}
+Noch ein Hinweis zum \tty{EQU}-Befehl: Da AS nicht wissen kann, in welchem
+Zusammenhang ein mit \tty{EQU} definiertes Symbol sp"ater verwendet wird,
+wird ein \tty{EQU} mit Vorw"artsreferenzen im ersten Pass "uberhaupt nicht
+durchgef"uhrt. Wird das mit \tty{EQU} definierte Symbol also im zweiten
+Pass vorw"arts referenziert:
+\begin{verbatim}
+ move.l #sym2,d0
+sym2 equ sym1+5
+sym1 equ 0
+\end{verbatim}
+so handelt man sich im zweiten Pass eine Fehlermeldung wegen eines
+undefinerten Symbols ein...aber warum machen Leute eigentlich solche
+Dinge ???
+
+Zugegeben, das war ein ziemlich l"anglicher Ausflug, aber es mu"ste einfach
+einmal sein. Was sollte man als Erkenntnis aus diesem Abschnitt mitnehmen?
+\begin{enumerate}
+\item{AS versucht immer, den k"urzestm"oglichen Code zu erzeugen. Dazu
+ ben"otigt er eine endliche Zahl von Durchl"aufen. Wenn man ihn
+ nicht gerade knebelt, kennt AS keine R"ucksichten...}
+\item{Wenn sinnvoll und m"oglich, Sprung- und Adre"sl"angen explizit
+ vorgeben. Man kann damit u.U. die Anzahl der Durchl"aufe deutlich
+ reduzieren.}
+\item{Vorw"artsreferenzen auf das allern"otigste beschr"anken. Man
+ erleichtert sich und AS das Leben damit erheblich!}
+\end{enumerate}
+
+%%---------------------------------------------------------------------------
+
+\section{Registersymbole}
+\label{SectRegSyms} \ttindex{Registersymbole}
+
+{\em G"ultigkeit: PowerPC, M-Core, 4004, 80C16x, AVR}
+
+Manchmal ist es erw"unscht, nicht nur einer Speicheradresse oder einer
+Konstanten, sondern auch einem Register einen symbolischen Namen zuzuweisen,
+um seine Funktion in einem bestimmten Programmabschnitt zu verdeutlichen.
+Dies ist bei Prozessoren, die die Register schlicht als einen weiteren
+Adre"sraum behandeln, recht problemlos, da als Register damit auch
+Zahlenausdr"ucke erlaubt sind und man solche Symbole mit schlichten
+\tty{EQU}s definieren kann (z.B. bei MCS-96 oder TMS7000). Bei den
+allermeisten Prozessoren jedoch sind Registernamen festgelegte Literale, und
+AS behandelt sie aus Geschwindigkeitsgr"unden gesondert, so da"s ein besonderer
+Mechanismus vonn"oten ist, um symbolische Register zu definieren. Ein Registersymbol
+wird "ublicherweise durch die \tty{REG}-Anweisung definiert und hat ansonsten
+die gleiche Form wie eine \tty{EQU}-Definition. Sie unterliegt jedoch einer
+Reihe von Einschr"ankungen: Zum einen ist ein Registersymbol eine reine 'as is'
+gespeicherte Zeichenkette, die auch nur in dieser Form verwendet werden kann.
+Es ist also z.B. keine Arithmetik m"oglich, um aus einem Register den Nachfolger
+zu berechnen, etwa so:
+\begin{verbatim}
+myreg reg r17 ; Definition Registersymbol
+ addi myreg+1,3 ; geht nicht!
+\end{verbatim}
+Zum anderen mu"s ein Registersymbol vor seiner ersten Nutzung definiert
+werden; eine Vorw"artsreferenz w"urde dazu f"uhren, da"s AS bei nicht gefundenem
+Registersymbol eine Vorw"artsreferenz auf eine Speicherstelle vermutet, und bei
+den meisten Prozessoren sind die Nutzungsm"oglichkeiten f"ur Speicherstellen als
+Operanden deutlich eingeschr"ankter als f"ur Register, so da"s es mit ziemlicher
+Sicherheit Fehler hagelt...
+
+Registersymbole sind analog zu normalen Symbolen lokal zu Sektionen,
+und es ist auch durch Anh"angen eines in eckige Klammern gesetzten Sektionsnamens
+m"oglich, auf ein Registersymbol aus einer bestimmten Sektion zuzugreifen.
+Aufgrund der fehlenden M"oglichkeit zur Vorw"artsreferenz gibt es aber keine
+Entsprechung zur \tty{FORWARD}-Direktive, und da Registersymbole im allgemeinen
+nur in einem sehr eng umschr"ankten Kontext eine Bedeutung haben, ist ein Export
+per \tty{PUBLIC} oder \tty{GLOBAL} auch nicht vorgesehen.
+
+Sind in einem Kontext ein normales als auch ein Registersymbol gleichen Namens
+bekannt, so wird immer das Registersymbol vorgezogen. Dies ist aber nicht der
+Fall, wenn der Name nicht alleine, sondern eingebunden in einen Ausdruck
+steht (dazu reichen Klammern!), dann wird das normale Symbol benutzt.
+
+%%---------------------------------------------------------------------------
+
+\section{Sharefile}
+\label{ChapShareMain} \ttindex{SHARED}
+
+Diese Funktion ist ein Abfallprodukt aus den reinen 68000er-Vorg"angern
+von AS, da sie vielleicht doch der (die?!) eine oder andere gebrauchen
+k"onnte, habe ich sie dringelassen. Grundproblem ist es, an bestimmte
+beim Assemblieren entstehende Symbole heranzukommen, weil man evtl. mit
+diesen Adre"sinformationen auf den Speicher des Zielsystems zugreifen
+m"ochte. Der Assembler erlaubt es, mit Hilfe des \tty{SHARED}-Pseudobefehles
+(siehe dort) Symbolwerte extern zur Verf"ugung zu stellen. Zu diesem
+Zweck erstellt der Assembler im zweiten Pass eine Textdatei mit den
+gew"unschten Symbolen und ihren Werten, die mittels Include in ein
+Hochsprachen-oder weiteres Assemblerprogramm eingebunden werden k"onnen.
+Das Format der Textdatei (C, Pascal oder Assembler) wird durch die
+Kommandozeilenschalter \tty{p}, \tty{c} oder \tty{a} festgelegt.
+\par
+\bb{ACHTUNG!} Ist keiner dieser Schalter angegeben, so wird auch keine
+Datei erzeugt, egal ob sich \tty{SHARED}-Befehle im Quelltext finden oder
+nicht!
+\par
+AS pr"uft beim Anlegen der Share-Datei nicht, ob bereits eine Datei gleichen
+Namens existiert, eine solche wird ggfs. einfach "uberschrieben. Eine
+Abfrage halte ich nicht f"ur sinnvoll, da AS dann bei jedem Lauf fragen
+w"urde, ob er die alte Version der Share-Datei "uberschreiben darf, und das
+w"are doch sehr l"astig...
+
+%%---------------------------------------------------------------------------
+
+\section{Prozessor-Aliasse}
+\label{SectAlias}
+
+Mit Varianten g"angiger Mikrocontroller-Familien ist es wie mit
+Kaninchen: Sie vermehren sich schneller, als man mit der Versorgung
+hinterherkommen kann. Im Zuge der Entwicklung von Prozessorkernen als
+Bausteine f"ur ASICs und von Controller-Familien mit vom Kunden w"ahlbarer
+Peripherie wird die Zahl von Controller-Varianten, die sich von einem
+bekannten Typ nur in einigen Peripherie-Details unterscheiden, immer
+gr"o"ser. Die Unterscheidung der einzelnen Typen ist aber trotz meist
+identischer Prozessorkernes wichtig, um z.B. in den Includefiles den
+korrekten Satz von Peripherieregistern einzublenden. Bisher habe ich
+mich zwar immer bem"uht, die wichtigsten Vertreter einer Familie in AS
+einzubauen (und werde das auch weiter tun), aber manchmal l"auft mir
+die Entwicklung einfach auf und davon...es mu"ste also ein Mechanismus
+her, mit dem man die Liste der unterscheidbaren Prozessortypen selbst
+erweitern kann.
+\par
+Das Ergebnis davon sind Prozessor-Aliasse: Mit der Kommandozeilenoption \tty{alias}
+kann man einen neuen Prozessortyp definieren, der im Befehlssatz einem
+anderen, in AS fest eingebauten Typ entspricht. Bei Benutzung dieses
+Typs im \tty{CPU}-Befehl wird sich AS also wie beim ,,Original'' verhalten,
+mit einem Unterschied: Die Variablen \tty{MOMCPU} bzw. \tty{MOMCPUNAME}
+werden auf den Namen des Alias gesetzt, wodurch der neue Name zur
+Unterscheidung z.B. in Includefiles dienen kann.
+\par
+Die Definition dieser Aliasse wurde aus zwei Gr"unden mit
+Kommandozeilenoptionen anstatt Pseudobefehlen vorgenommen: zum einen
+w"are es ohnehin nicht m"oglich gewesen, die Definition der Aliasse
+zusammen mit den Registerdefinitionen in eine Include-Datei zu legen, denn
+in einem Programm, das so eine Datei benutzen wollte, m"u"ste sie ja sowohl
+vor als auch nach dem \tty{CPU}-Befehl in der Hauptdatei eingebunden
+werden - eine Vorstellung, die irgendwo zwischen unelegant und unm"oglich
+liegt. Zum zweiten erm"oglicht diese Implementierung, die Definition der
+neuen Typen in eine Datei zu legen, die "uber die \tty{ASCMD}-Variable beim
+Start automatisch ausgef"uhrt wird, ohne das sich das Programm darum
+k"ummern m"u"ste.
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Pseudobefehle}
+
+Nicht f"ur alle Prozessoren sind alle Pseudobefehle definiert. Vor
+der Beschreibung eines Befehls ist deshalb jeweils vermerkt, f"ur
+welche Prozessortypen dieser Befehl erlaubt ist.
+
+%%---------------------------------------------------------------------------
+
+\section{Definitionen}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SET und EQU}
+\ttindex{SET}\ttindex{EQU}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+\tty{SET} und \tty{EQU} erlauben die Definition typenloser Konstanten, d.h. sie
+werden keinem Segment zugeordnet und ihre Verwendung erzeugt in keinem
+Fall eine Warnung wegen Segmentverquickung. W"ahrend \tty{EQU} Konstanten
+definiert, die nicht wieder (mit \tty{EQU}) ge"andert werden k"onnen, erlaubt
+\tty{SET} die Definition von Variablen, die sich w"ahrend des Assemblerlaufes
+ver"andern lassen. Dies ist n"utzlich z.B. bei der Allokation von
+Resourcen \`a la Interruptvektoren, wie im folgenden Beispiel:
+\begin{verbatim}
+VecCnt SET 0 ; irgendwo am Anfang
+ ...
+DefVec MACRO Name ; einen neuen Vektor belegen
+Name EQU VecCnt
+VecCnt SET VecCnt+4
+ ENDM
+ ...
+ DefVec Vec1 ; ergibt Vec1=0
+ DefVec Vec2 ; ergibt Vec2=4
+\end{verbatim}
+Intern werden Konstanten und Variablen identisch gespeichert, der
+einzige Unterschied ist, da"s sie mit \tty{SET} umdefiniert werden
+k"onnen und mit \tty{EQU} nicht. Es ist daher m"oglich, ein Symbol
+mit \tty{EQU} zu definieren und es mit \tty{SET} zu "andern, auch
+wenn das nicht der Sinn der Sache ist. Aus einem weiteren Grund
+sollte man davon sogar explizit die Finger lassen: Im Gegensatz zu
+\tty{SET} pr"uft \tty{EQU}, ob der neu zugewiesene Wert sich von
+einem evtl. bisher existierenden unterscheidet. Da sich dieser f"ur
+mit \tty{EQU} definierte Konstanten nicht "andern sollte, vermutet
+AS einen Phasenfehler und legt einen weiteren Pass ein...w"urde man
+in obigem Beispiel z.B. die Initialisierung des Z"ahlers mit \tty{EQU}
+durchf"uhren, so w"urde AS sich zwar nicht beschweren, da eine einmalige
+Neuzuweisung pro Pass erlaubt ist (bei $n$ Durchg"angen kommt man nun
+einmal $n$-mal an dieser Stelle vorbei), aber endlos neue Passes ansto"sen,
+da der Initialwert des Z"ahlers immer vom Endwert verschieden ist.
+\par
+Mit \tty{EQU/SET} lassen sich Konstanten aller Typen definieren, z.B.
+\begin{verbatim}
+IntZwei EQU 2
+FloatZwei EQU 2.0
+\end{verbatim}
+Einige Prozessoren besitzen leider bereits selber einen \tty{SET}-Befehl.
+Bei diesen mu"s \tty{EVAL} anstelle von \tty{SET} verwendet werden.
+\par
+Anstelle von \tty{EQU} darf auch einfach ein Gleichheitszeichen geschrieben
+werden, analog kann man anstelle von \tty{SET} bzw. \tty{EVAL}
+einfach \tty{:=} schreiben.
+\par
+Defaultm"a"sig sind mit \tty{SET} oder \tty{EQU} definierte Symbole
+typenlos, optional kann jedoch als zweites Argument ein Segmentname
+(\tty{CODE, DATA, IDATA, XDATA, YDATA, BITDATA, IO oder REG}) oder
+\tty{MOMSEGMENT} f"ur das aktuell gesetzte Segment angegeben werden,
+um das Symbol einem bestimmten Adre"sraum zuordnen. AS ber"ucksichtigt
+dabei nicht, ob der benutzte Adre"sraum bei dem aktuell gesetzten
+Zielprozessor auch vorhanden ist!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SFR und SFRB}
+\ttindex{SFR}\ttindex{SFRB}
+
+{\em G"ultigkeit: diverse, SFRB nur MCS-51}
+
+Diese Befehle funktionieren wie \tty{EQU}, nur sind die damit definierten
+Symbole dem direkt adressierbaren Datensegment zugeordnet, d.h. sie
+dienen bevorzugt zur Definition von RAM-Zellen und (wie der Name
+ahnen l"a"st) im Datenbereich eingeblendeten Hardwareregistern. Der
+dabei zugelassene Wertebereich ist identisch mit dem bei \tty{ORG} f"ur
+das \tty{DATA}-Segment zugelassenen (s. Abschnitt \ref{SectORG}).
+\tty{SFR} und \tty{SFRB} unterscheiden sich darin, da"s \tty{SFRB}
+das Register als bitadressierbar kennzeichnet, weshalb AS zus"atzlich 8
+Symbole erzeugt, die dem Bitsegment zugeordnet werden und die Namen
+\tty{xx.0} bis \tty{xx.7} tragen, z.B.
+\begin{verbatim}
+PSW SFR 0d0h ; ergibt PSW = D0H (Datensegment)
+
+PSW SFRB 0d0h ; zusaetzlich PSW.0 = D0H (Bit)
+ ; bis PSW.7 = D7H (Bit)
+\end{verbatim}
+Da beim 80C251 grunds"atzlich alle SFRs ohne zus"atzliche Bit-Symbole
+bitadressierbar sind, ist der \tty{SFRB}-Befehl f"ur ihn auch nicht mehr
+definiert; die Bits \tty{PSW.0} bis \tty{PSW.7} sind automatisch vorhanden.
+\par
+AS "uberpr"uft bei der Definition eines bitadressierbaren Registers mit
+\tty{SFRB}, ob die Speicherstelle "uberhaupt bitadressierbar ist (Bereich
+20h..3fh bzw. 80h, 88h, 90h, 98h...0f8h). Ist sie es nicht, so wird eine
+Warnung ausgegeben; die dann erzeugten Bit-Symbole sind undefiniert.
+
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{XSFR und YSFR}
+\ttindex{XSFR}\ttindex{YSFR}
+
+{\em G"ultigkeit: DSP56xxx}
+
+Auch der DSP56000 hat einige Peripherieregister memory-mapped im
+Speicher liegen, die Sache wird jedoch dadurch komplizierter, da"s
+es zwei Datenbereiche gibt, den X-und Y-Bereich. Diese Architektur
+erlaubt einerseits zwar einen h"oheren Parallelit"atsgrad, zwingt
+jedoch andererseits dazu, den normalen \tty{SFR}-Befehl in die beiden
+oben genannten Varianten aufzuspalten. Sie verhalten sich identisch zu
+\tty{SFR}, nur da"s \tty{XSFR} ein Symbol im X-Adre"sraum definiert
+und \tty{YSFR} entsprechend eines im Y-Adre"sraum. Der erlaubte
+Wertebereich ist 0..\$ffff.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LABEL}
+\ttindex{LABEL}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Die Funktion des \tty{LABEL}-Befehls ist identisch zu \tty{EQU}, nur
+wird das Symbol nicht typenlos, sondern erh"alt das Attribut ,,Code''.
+\tty{LABEL} wird genau f"ur einen Zweck ben"otigt: Labels in Makros
+sind normalerweise lokal, also nicht au"serhalb des Makros zugreifbar.
+Mit einem \tty{EQU}-Befehl kann man sich zwar aus der Aff"are ziehen,
+die Formulierung
+\begin{verbatim}
+<Name> label $
+\end{verbatim}
+erzeugt aber ein Symbol mit korrekten Attributen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BIT}
+\ttindex{BIT}
+
+{\em G"ultigkeit: MCS-(2)51, XA, 80C166, 75K0, ST9}
+
+\tty{BIT} dient dazu, ein einzelnes Bit einer Speicherstelle mit einem
+symbolischen Namen gleichzusetzen. Da die Art und Weise, wie
+verschiedene Prozessoren Bitverarbeitung und -adressierung betreiben,
+stark variiert, verh"alt sich auch dieser Befehl je nach Zielplattform
+anders:
+\par
+F"ur die MCS/51-Familie, die einen eigenen Adre"sraum f"ur Bitoperanden
+besitzt, ist die Funktion von \tty{BIT} ganz analog zu \tty{SFR}, d.h.
+es wird einfach ein Integer-Symbol mit dem angegebenen Wert und dem
+Segment BDATA erzeugt. F"ur alle anderen Prozessoren wird die
+Bitadressierung dagegen zweidimensional mit Adresse und Bitstelle
+vorgenommen. In diesem Fall verpackt AS beide Teile in einer vom
+jeweiligen Prozessor abh"angigen Weise in ein Integer-Symbol und dr"oselt
+dieses bei der Benutzung wieder in die beiden Teile auseinander.
+Letzterer Fall trifft auch schon f"ur den 80C251 zu: W"ahrend zum Beispiel
+der Befehl
+\begin{verbatim}
+Mein_Carry bit PSW.7
+\end{verbatim}
+auf einem 8051 noch dem Symbol \tty{Mein\_Carry} den Wert 0d7h zuweisen
+w"urde, w"urde auf einem 80C251 dagegen ein Wert von 070000d0h generiert
+werden, d.h. die Adresse steht in Bit 0..7 sowie die Bitstelle in Bit
+24..26. Dieses Verfahren entspricht dem, das auch beim DBIT-
+Befehl des TMS370 angewendet wird und funktioniert sinngem"a"s so auch
+beim 80C166, nur da"s dort Bitstellen von 0 bis 15 reichen d"urfen:
+\begin{verbatim}
+MSB BIT r5.15
+\end{verbatim}
+Beim Philips XA findet sich in Bit 0..9 die Bitadresse, wie sie auch
+in die Maschinenbefehle eingesetzt wird, f"ur Bits aus den RAM-Speicher
+wird in Bit 16..23 die 64K-Bank eingesetzt.
+\par
+Noch etwas weiter geht der \tty{BIT}-Befehl bei der 75K0-Familie: Da
+dort Bitadressierungen nicht nur absolute Basisadressen verwenden
+d"urfen, sind sogar Ausdr"ucke wie
+\begin{verbatim}
+bit1 BIT @h+5.2
+\end{verbatim}
+erlaubt.
+\par
+Beim ST9 ist es hingegen m"oglich, Bits auch invertiert anzusprechen,
+was beim \tty{BIT}-Befehl auch ber"ucksichtigt wird:
+\begin{verbatim}
+invbit BIT r6.!3
+\end{verbatim}
+N"aheres zum \tty{BIT}-Befehl beim ST9 findet sich bei den
+prozessorspezifischen Hinweisen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DBIT}
+\ttindex{DBIT}
+
+{\em G"ultigkeit: TMS 370xxx}
+
+Die TMS370-Reihe hat zwar kein explizites Bit-Segment, jedoch k"onnen
+einzelne Bits als Symbol durch diesen Befehl simuliert werden. \tty{DBIT}
+ben"otigt zwei Operanden, n"amlich einmal die Adresse der Speicherstelle,
+in der das Bit liegt, sowie die genaue Position des Bits im Byte.
+So definiert man z.B. mit
+\begin{verbatim}
+INT3 EQU P019
+INT3_ENABLE DBIT 0,INT3
+\end{verbatim}
+das Bit, welches Interrupts von Anschlu"s INT3 freigibt. So definierte
+Bits k"onnen dann von den Befehlen \tty{SBIT0, SBIT1, CMPBIT, JBIT0}
+und \tty{JBIT} genutzt werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PORT}
+\ttindex{PORT}
+
+{\em G"ultigkeit: 8080/8085/8086, XA, Z80, 320xx, TLCS-47, AVR}
+
+\tty{PORT} arbeitet analog zu \tty{SFR}, nur wird das Symbol dem I/O-Adre"sbereich
+zugeordnet. Erlaubte Werte sind 0..7 beim 3201x, 0..15 beim 320C2x,
+0..65535 beim 8086, 0..63 beim AVR und 0..255 beim Rest.
+\par
+Beispiel: eine PIO 8255 liege auf Adresse 20H:
+\begin{verbatim}
+PIO_Port_A PORT 20h
+PIO_Port_B PORT PIO_Port_A+1
+PIO_Port_C PORT PIO_Port_A+2
+PIO_Ctrl PORT PIO_Port_A+3
+\end{verbatim}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{REG}
+\ttindex{REG}
+
+{\em G"ultigkeit: AVR, M*Core, ST9, 80C16x}
+
+Obwohl immer mit gleicher Syntax, hat diese Anweisung von Prozessor
+zu Prozessor eine leicht abweichende Bedeutung: Falls der Zielprozessor
+f"ur Register einen eigenen Adre"sraum verwendet, so hat \tty{REG}
+die Wirkung eines simplen \tty{EQU}s f"ur eben diesen Adre"sraum (z.B. beim
+ST9). F"ur alle anderen Prozessoren definiert \tty{REG} Registersymbole,
+deren Funktion in Abschnitt \ref{SectRegSyms} beschrieben sind.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LIV und RIV}
+\ttindex{LIV}\ttindex{RIV}
+
+{\em G"ultigkeit: 8X30x}
+
+\tty{LIV} und \tty{RIV} dienen dazu, sogenannte IV-Bus-Objekte zu definieren.
+Bei diesen handelt es sich um Bitgruppen in peripheren Speicherzellen
+mit einer L"ange von 1..8 Bit, die fortan symbolisch angesprochen
+werden k"onnen, so da"s man bei den entsprechenden Befehlen nicht mehr
+Adresse, L"ange und Position separat angeben mu"s. Da die
+8X30x-Prozessoren zwei periphere Adre"sr"aume besitzen (einen ,,linken''
+und einen ,,rechten'', sind auch zwei separate Befehle definiert. Die
+Parameter dieser Befehle sind allerdings identisch: es m"ussen drei
+Parameter sein, die Adresse, Startposition und L"ange angeben.
+Weitere Hinweise zur Benutzung von Busobjekten finden sich in
+Abschnitt \ref{8X30xSpec}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{CHARSET}
+\ttindex{CHARSET}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Einplatinensysteme, zumal wenn sie LCDs ansteuern, benutzen h"aufig
+einen anderen Zeichensatz als ASCII, und da"s die Umlautkodierung mit
+der im PC "ubereinstimmt, d"urfte wohl reiner Zufall sein. Um nun
+aber keine fehlertr"achtigen Handumkodierungen vornehmen zu m"ussen,
+enth"alt der Assembler eine Umsetzungstabelle f"ur Zeichen, die jedem
+Quellcode ein Zielzeichen zuordnet. Zur Modifikation dieser Tabelle
+(die initial 1:1 "ubersetzt), dient der Befehl \tty{CHARSET}.
+\tty{CHARSET} kann mit verschiedenen Parameterzahlen und -typen angewendet
+werden. Ist die Parameterzahl eins, so mu"s es sich um einen
+String-Ausdruck handeln, der von AS als Dateiname interpretiert wird. Aus
+dieser Datei liest AS dann die ersten 256 Bytes aus und kopiert sie in die
+"Ubersetzungstabelle. Hiermit lassen sich also komplexere, extern
+erzeugte Tabellen in einem Schlag aktivieren. In allen anderen Varianten
+mu"s der erste Parameter ein Integer im Bereich von 0 bis 255 sein, der
+den Startpunkt der in der "Ubersetzungstabelle zu modifizierenden
+Eintr"age angibt. Es folgen dann ein oder zwei weitere Parameter, die die
+Art der "Ubersetzung angeben:
+
+Ein einzelner, weiterer Integer ver"andert genau einen Eintrag. So
+bedeutet z.B.
+\begin{quote}{\tt
+ CHARSET '"a',128}
+\end{quote}
+da"s das Zielsystem das "a mit der Zahl 128 kodiert. Sind jedoch zwei
+weitere Integers angegeben, so ist der erste von ihnen der letzte zu
+modifizierende Eintrag, der zweite der neue Wert des ersten Eintrags; alle
+weiteren Eintr"age bis zum Bereichsende werden sequentiell neu belegt.
+Falls z.B. das Zielsystem keine Kleinbuchstaben unterst"utzt, k"onnen mit
+\begin{verbatim}
+ CHARSET 'a','z','A'
+\end{verbatim}
+alle Kleinbuchstaben auf die passenden Gro"sbuchstaben automatisch
+umgemappt werden.
+
+In der letzten Variante folgt nach dem Startindex ein String, der die ab
+dem Startindex abzulegenden Zeichen angibt. Das letzte Beispiel k"onnte
+man also auch so formulieren:
+\begin{verbatim}
+ CHARSET 'a',"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+\end{verbatim}
+
+\tty{CHARSET} kann auch ganz ohne Parameter aufgerufen werden, allerdings
+mit ziemlich gr"undlichen Folgen: Dies bewirkt eine Reinitialisierung der
+"Ubersetzungstabelle in ihren Urzustand, d.h. man bekommt wieder eine
+1:1-"Ubersetzung.
+
+\bb{ACHTUNG!} \tty{CHARSET} beeinflu"st nicht nur im Speicher abgelegte
+Stringkonstanten, sondern auch als ,,ASCII'' formulierte Integerkonstanten.
+Dies bedeutet, da"s eine evtl. bereits modifizierte Umsetzungstabelle
+in den obigen Beispielen zu anderen Ergebnissen f"uhren kann!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{CODEPAGE}
+\ttindex{CODEPAGE}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Mit der \tty{CHARSET}-Anweisung hat man zwar beliebige Freiheiten in der
+Zeichenzuordnung zwischen Entwicklungs- und Zielplattform, wenn auf der
+Zielplattform jedoch verschiedene Zeichens"atze existieren, kann das
+Umschalten zwischen diesen jedoch zu einer umst"andlichen Orgie von
+\tty{CHARSET}-Kommandos werden. Mit der \tty{CODEPAGE}-Anweisung kann
+man jedoch mehrere Zeichentabellen vorhalten und zwischen diesen mit einem
+Befehl umschalten. Als Parameter erwartet \tty{CODEPAGE} ein oder zwei
+Namen: zum einen den Namen der fortan zu benutzenden Tabelle, zum anderen
+optional den Namen der Tabelle, die die initiale Belegung der Tabelle
+vorgibt (dieser Parameter hat somit auch nur eine Bedeutung beim ersten
+Umschalten auf eine Tabelle, bei der AS sie automatisch anlegt). Fehlt
+der zweite Parameter, so ist die initiale Belegung der neuen Tabelle
+gleich der vorher aktiven Tabelle. Alle folgenden
+\tty{CHARSET}-Anweisungen verändern {\em nur} die momentan aktive Tabelle.
+
+Zu Beginn eines Durchlaufes wird von AS automatisch eine einzelne
+Zeichentabelle mit dem Namen \tty{STANDARD} erzeugt und 1:1 vorbelegt.
+Verwendet man keine \tty{CODEPAGE}-Anweisungen, so beziehen sich alle mit
+\tty{CHARSET} gemachten Einstellungen auf diese Tabelle.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ENUM}
+\ttindex{ENUM}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+\tty{ENUM} dient analog zu dem entsprechenden Befehl in C dazu,
+Aufz"ahlungstypen zu definieren, d.h. eine Reihe von Integer-Konstanten,
+denen fortlaufende Werte (von 0 an beginnend) zugewiesen
+werden. Als Parameter werden dabei die Namen der zu definierenden
+Symbole angegeben, wie in dem folgenden Beispiel:
+\begin{quote}{\tt
+ ENUM SymA,SymB,SymC}
+\end{quote}
+Dieser Befehl weist den Symbolen \tty{SymA}, \tty{SymB} und \tty{SymC}
+die Werte 0, 1 und 2 zu.
+\par
+\tty{ENUM}-Befehle sind von Hause aus einzeilig, d.h. bei einem neuen
+\tty{ENUM}-Befehl beginnt die Numerierung wieder bei Null. Mehrzeilige
+Aufz"ahlungen kann man aber mit einem kleinen Trick erreichen, der
+die Tatsache ausnutzt, da"s man mit einer expliziten Zuweisung den
+internen Z"ahler neu setzen kann, wie in dem folgenden Fall:
+\begin{quote}{\tt
+ ENUM Januar=1,Februar,M"arz,April,Mai,Juni}
+\end{quote}
+Hier werden den Monatsnamen die Zahlenwerte 1..6
+zugewiesen. M"ochte man die Aufz"ahlung nun fortsetzen, geht
+das folgenderma"sen:
+\begin{quote}{\tt
+ ENUM Juli=Juni+1,August,September,Oktober \\
+ ENUM November=Oktober+1,Dezember
+}\end{quote}
+Die Definition von Symbolen mit \tty{ENUM} gleicht einer Definition
+mit \tty{EQU}, d.h. es ist nicht m"oglich, einem Symbol einen neuen
+Wert zuzuweisen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{STRUCT und ENDSTRUCT}
+\ttindex{STRUCT}\ttindex{ENDSTRUCT}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Auch in Assemblerprogrammen ergibt sich dann und wann die Notwendigkeit,
+analog zu Hochsprachen zusammengesetzte Datenstrukturen zu definieren.
+AS unterst"utzt dies mit den Befehlen \tty{STRUCT} und \tty{ENDSTRUCT},
+die die Definition einer solchen Struktur einleiten bzw. abschlie"sen.
+Das Verfahren ist simpel: Mit einem \tty{STRUCT} wird der momentane
+Programmz"ahler gesichert und auf Null zur"uckgesetzt. Alle Labels
+ergeben mithin die Offsets der einzelnen Datenfelder in der Struktur.
+Die Reservierung des Platzes f"ur die einzelnen Felder erfolgt mit den
+f"ur den jeweils aktiven Zielprozessor zul"assigen Befehlen zur
+Speicherplatzreservierung, also z.B. \tty{DS.x} f"ur die Motorolas oder
+\tty{DB} \& Co. f"ur Intels. Das dem \tty{STRUCT}-Befehl vorangestellte
+(nicht optionale) Label ist der Name des Records und kann optional beim
+\tty{ENDSTRUCT}-Befehl wiederholt werden. Weiterhin legt \tty{ENDSTRUCT} in
+\tty{$<$Name$>$\_len} die Gesamtl"ange der Struktur ab (man kann auch die
+Verwendung eines anderen Symbolnamens erzwingen, indem man dessen
+Name als Argument von \tty{ENDSTRUCT} angibt). In der Definition
+\begin{verbatim}
+Rec STRUCT
+Ident db ?
+Pad db ?
+Pointer dd ?
+Rec ENDSTRUCT
+\end{verbatim}
+w"urde also dem Symbol \tty{Rec\_len} der Wert 6 zugewiesen. \bb{ACHTUNG!}
+Innerhalb einer Strukturdefinition d"urfen keine Befehle verwendet werden,
+die Code erzeugen, da es sich hier um eine reine Anordnung von Elementen
+im Adre"sraum handelt!
+
+\tty{STRUCT}-Definitionen d"urfen auch geschachtelt werden; nach Beendigung
+der inneren \tty{STRUCT}-Definition wird dann der Adre"sz"ahler der "au"seren
+Struktur automatisch um die Gr"o"se der inneren Struktur inkrementiert
+(die Z"ahlung innerhalb der inneren Struktur l"auft nat"urlich ab 0).
+
+Um Mehrdeutigkeiten bei gleichnamigen Feldern in verschiedenen Strukturen
+zu vermeiden, stellt AS den Feldnamen defaultm"a"sig den Namen der Struktur,
+mit einem Unterstrich getrennt, voran. Im obigen Beispiel w"urden also die
+Symbole \tty{Rec\_Ident, Rec\_Pad} und \tty{Rec\_Pointer} erzeugt. Diese
+Verhalten l"a"st sich unterbinden, indem man als Parameter der
+\tty{STRUCT}-Anweisung ein \tty{NOEXTNAMES} anbringt. Bei geschachtelten
+Strukturdefinitionen funktioniert dies sinngem"a"s, d.h Feldnamen werden
+um die Namen aller sie umschlie"senden Strukturen erweitert, die keine
+\tty{NOEXTNAMES}-Direktive bekamen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PUSHV und POPV}
+\ttindex{PUSHV}\ttindex{POPV}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Mit \tty{PUSHV} und \tty{POPV} ist es m"oglich, den Wert von (nicht
+makrolokalen) Symbolen tempor"ar zu speichern und zu einem sp"ateren
+Zeitpunkt wiederherzustellen. Die Speicherung erfolgt auf {\em Stacks},
+d.h. Last-In-First-Out-Speichern. Ein Stack hat einen Namen, der den
+allgemeinen Symbolkonventionen gen"ugen mu"s, und existiert so lange,
+wie er mindestens ein Element enth"alt: Ein bisher nicht existierender
+Stack wird bei \tty{PUSHV} automatisch angelegt, ein durch \tty{POPV} leer
+werdender Stack wird automatisch wieder aufgel"ost. Der Name des Stacks,
+auf den Symbole abgelegt und von dem sie wieder abgeholt werden sollen,
+ist der erste Parameter von \tty{PUSHV} bzw. \tty{POPV}, danach folgt
+eine beliebige Menge von Symbolen als weitere Parameter. Alle in der
+Liste aufgef"uhrten Symbole m"ussen bereits existieren, es ist also
+{\em nicht} m"oglich, mit einem \tty{POPV}-Befehl implizit neue Symbole
+zu definieren.
+\par
+Stacks stellen eine globale Ressource dar, d.h. ihre Namen sind
+nicht lokal zu Sektionen.
+\par
+Wichtig ist, da"s die Variablenliste {\em immer} von links nach rechts
+abgearbeitet wird. Wer also mehrere Variablen mit \tty{POPV} von einem
+Stack herunterholen will, mu"s diese in genau umgekehrter Reihenfolge
+zum entsprechenden \tty{PUSHV} angeben!
+\par
+Der Name des Stacks kann auch weggelassen werden, etwa so:
+\begin{verbatim}
+ pushv ,var1,var2,var3
+ .
+ .
+ popv ,var3,var2,var1
+\end{verbatim}
+AS verwendet dann einen internen, vordefinierten Default-Stack.
+\par
+Nach Ende eines Durchlaufes "uberpr"uft AS, ob noch Stacks existieren,
+die nicht leer sind, und gibt deren Namen sowie ,,F"ullstand'' aus. Mit
+diesen Warnungen kann man herausfinden, ob an irgendeiner Stelle die
+\tty{PUSHV}'s und \tty{POPV}'s nicht paarig sind. Es ist jedoch in
+keinem Fall m"oglich, Symbolwerte in einem Stack "uber mehrere Durchl"aufe
+hinwegzuretten: Zu Beginn eines Durchlaufes werden alle Stacks geleert!
+
+%%---------------------------------------------------------------------------
+
+\section{Codebeeinflussung}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ORG}
+\label{SectORG}\ttindex{ORG}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+\tty{ORG} erlaubt es, den assemblerinternen Adre"sz"ahler mit einem neuen
+Wert zu besetzen. Der Wertebereich ist vom momentan gew"ahlten Segment
+und vom Prozessortyp abh"angig (Tabellen \ref{TabORG1} bis \ref{TabORG4}).
+Die untere Grenze ist dabei immer 0; die obere Grenze der angegebene Wert
+minus eins.
+\par
+Falls in einer Familie verschiedene Varianten unterschiedlich
+gro"se Adre"sr"aume haben, ist jeweils der maximale Raum aufgef"uhrt.
+\par
+ORG wird in erster Linie ben"otigt, um dem Code eine neue Startadresse
+zu geben und damit verschiedene, nicht zusammenh"angende Codest"ucke in
+einer Quelldatei unterzubringen. Sofern nicht in einem Feld explizit anders
+angegeben, ist die vorgegebene Startadresse in einem Segment (d.h. die ohne
+{\tt ORG} angenommene) immer 0.
+\small
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
+\hline
+\tin{Prozessor} & \tin{CODE} & \tin{DATA} & \tin{IDATA} & \tin{XDATA} & \tin{YDATA} & \tin{BITDATA} & \tin{IO} & \tin{REG} & \tin{ROMDATA} \\
+\hline
+\hline
+\input{taborg1.tex}
+\hline
+\end{tabular}\end{center}
+\caption{Adre"sbereiche f"ur \tty{ORG} --- Teil 1\label{TabORG1}}
+\end{table*}
+\clearpage
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
+\hline
+\tin{Prozessor} & \tin{CODE} & \tin{DATA} & \tin{IDATA} & \tin{XDATA} & \tin{YDATA} & \tin{BITDATA} & \tin{IO} & \tin{REG} & \tin{ROMDATA} \\
+\hline
+\hline
+\input{taborg2.tex}
+\hline
+\multicolumn{10}{|l|}{* Da der 8051 kein RAM jenseits 80h hat, mu"s der Initialwert f"ur den 8051} \\
+\multicolumn{10}{|l|}{ als Zielprozessor auf jeden Fall mit \tty{ORG} angepa"st werden!!} \\
+\hline
+\multicolumn{10}{|l|}{+ Da der Z180 weiterhin logisch nur 64K ansprechen kann, ist der} \\
+\multicolumn{10}{|l|}{ganze Adre"sraum nur mittels \tty{PHASE}-Anweisungen erreichbar!} \\
+\hline
+\end{tabular}\end{center}
+\caption{Adre"sbereiche f"ur \tty{ORG} --- Teil 2\label{TabORG2}}
+\end{table*}
+\clearpage
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
+\hline
+\tin{Prozessor} & \tin{CODE} & \tin{DATA} & \tin{IDATA} & \tin{XDATA} & \tin{YDATA} & \tin{BITDATA} & \tin{IO} & \tin{REG} & \tin{ROMDATA} \\
+\hline
+\hline
+\input{taborg3.tex}
+\hline
+\end{tabular}\end{center}
+\caption{Adre"sbereiche f"ur \tty{ORG} --- Teil 3\label{TabORG3}}
+\end{table*}
+\clearpage
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
+\hline
+\tin{Prozessor} & \tin{CODE} & \tin{DATA} & \tin{IDATA} & \tin{XDATA} & \tin{YDATA} & \tin{BITDATA} & \tin{IO} & \tin{REG} & \tin{ROMDATA} \\
+\hline
+\hline
+\input{taborg4.tex}
+\hline
+\end{tabular}\end{center}
+\caption{Adre"sbereiche f"ur \tty{ORG} --- Teil 4\label{TabORG4}}
+\end{table*}
+\normalsize
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{CPU}
+\ttindex{CPU}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Mit diesem Befehl wird festgelegt, f"ur welchen Prozessor im weiteren
+Code erzeugt werden soll. Die Befehle der anderen Prozessorfamilien
+sind dann nicht greifbar und erzeugen eine Fehlermeldung!
+\par
+Die Prozessoren k"onnen grob in Familien unterschieden werden, in den
+Familien dienen unterschiedliche Typen noch einmal zur Feinunterscheidung:
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+a) \> 68008 $\rightarrow$ 68000 $\rightarrow$ 68010 $\rightarrow$ 68012 $\rightarrow$ \\
+ \> MCF5200 $\rightarrow$ 68332 $\rightarrow$ 68340 $\rightarrow$ 68360 $\rightarrow$ \\
+ \> 68020 $\rightarrow$ 68030 $\rightarrow$ 68040
+\end{tabbing}
+\end{quote}
+In dieser Familie liegen die Unterschiede in hinzukommenden Befehlen
+und Adressierungsarten (ab 68020). Eine kleine Ausnahme stellt der
+Schritt zum 68030 dar, dem 2 Befehle fehlen: \tty{CALLM} und \tty{RTM}.
+Die drei Vertreter der 683xx-Famile haben den gleichen Prozessorkern (eine
+leicht abgemagerte 68020-CPU), jedoch v"ollig unterschiedliche Peripherie.
+MCF5200 repr"asentiert die ColdFire-Familie von Motorola, zum 680x0 bin"ar
+abw"artskompatible RISC-Prozesoren. Beim 68040 kommen die zus"atzlichen
+Steuerregister (via \tty{MOVEC} erreichbar) f"ur On-Chip-MMU und Caches
+sowie einige Systembefehle f"ur selbige hinzu.
+%%-----------
+\begin{quote}
+b) 56000 $\longrightarrow$ 56002 $\longrightarrow$ 56300
+\end{quote}
+W"ahrend der 56002 nur Befehle zum Inkrementieren und Dekrementieren der
+Akkus erg"anzt, ist der 56300-Kern schon fast ein neuer Prozessor: Er
+vergr"o"sert alle Adre"sr"aume von 64K-W"ortern auf 16M und verdoppelt fast
+die Anzahl der Befehle.
+%%-----------
+\begin{quote}
+c) PPC403 $\rightarrow$ PPC403GC $\rightarrow$ MPC505 $\rightarrow$ MPC601 $\rightarrow$ RS6000
+\end{quote}
+Der PCC403 ist eine abgespeckte Version der PowerPC-Linie ohne
+Gleitkommaeinheit, demzufolge sind s"amtliche Gleitkommabefehle
+bei ihm gesperrt; daf"ur sind einige mikrocontrollerspezifische
+Befehle enthalten, die er als einziges Mitglied in dieser Familie
+kennt. Die GC-Variante des PPC403 hat zus"atzlich eine MMU und deshalb
+einige Befehle zu deren Steuerung mehr. Der MPC505 (eine Mikrokontroller-Variante mit FPU)
+unterscheidet sich solange vom 601er nur in den Peripherieregistern,
+wie ich es nicht besser wei"s - \cite{Mot505} h"alt sich da noch etwas bedeckt...
+Die RS6000-Reihe kennt noch einige Befehle mehr (die auf vielen
+601er-Systemen emuliert werden, um vollst"andige Kompatibilit"at
+herzustellen), au"serdem verwendet IBM z.T. andere Mnemonics f"ur
+diese reinen Workstation-Prozessoren, als Remineszenz an die
+370er-Gro"srechner...
+%%-----------
+\begin{quote}
+d) MCORE
+\end{quote}
+%%-----------
+\begin{quote}
+e) 6800 $\rightarrow$ 6301 $\rightarrow$ 6811
+\end{quote}
+W"ahrend der 6301 nur neue Befehle definiert, liefert der 6811 neben
+weiteren Befehlen ein zweites Indexregister Y zur Adressierung.
+%%-----------
+\begin{quote}
+f) 6809/6309 und 6805/68HC08
+\end{quote}
+Diese Prozessoren sind zwar teilweise quellcodekompatibel zu den
+anderen 68xx-ern, haben aber ein anderes Bin"arcodeformat und einen
+deutlich eingeschr"ankteren (6805) bzw. erweiterten (6809) Befehlssatz.
+Der 6309 ist eine CMOS-Version des 6809, die zwar offiziell
+nur kompatibel zum 6809 ist, inoffiziell aber mehr Register und
+deutlich mehr Befehle besitzt (siehe \cite{Kaku}).
+%%-----------
+\begin{quote}
+g) 68HC12
+\end{quote}
+%%-----------
+\begin{quote}
+h) 68HC16
+\end{quote}
+%%-----------
+\begin{quote}
+i) HD6413308 $\longrightarrow$ HD6413309
+\end{quote}
+Diese beiden Namen repr"asentieren die 300er und 300H-Varianten der
+H8-Familie; die H-Version besitzt dabei einen gr"o"seren Adre"sraum
+(16 Mbyte statt 64Kbyte), doppelt so breite Register (32 Bit) und
+kennt einige zus"atzliche Befehle und Adressierungsarten. Trotzdem
+ist sie bin"ar aufw"artskompatibel.
+%%-----------
+\begin{quote}
+j) HD6475328 $\longrightarrow$ HD6475348 $\longrightarrow$
+ HD6475368 $\longrightarrow$ HD6475388
+\end{quote}
+Diese Prozessoren besitzen alle den gleichen CPU-Kern; Die unter-
+schiedlichen Typen dienen lediglich der Einbindung des korrekten
+Registersatzes in der Datei \tty{REG53X.INC}.
+%%-----------
+\begin{quote}
+k) SH7000 $\longrightarrow$ SH7600 $\longrightarrow$ SH7700
+\end{quote}
+Der Prozessorkern des 7600ers bietet eine Handvoll Befehle mehr, die
+L"ucken im Befehlssatz des 7000ers schlie"sen (verz"ogerte, bedingte
+sowie relative und indirekte Spr"unge, Multiplikationen mit 32-Bit-Operanden
+sowie Multiplizier/Addier-Befehle). Die 7700er-Reihe (auch als SH3
+gel"aufig) bietet weiterhin eine zweite Registerbank, bessere
+Schiebebefehle sowie Befehle zur Cache-Steuerung.
+%%-----------
+\begin{quote}
+l) 6502 $\rightarrow$ 65(S)C02 / MELPS740
+\end{quote}
+Die CMOS-Version definiert einige zus"atzliche Befehle, au"serdem sind
+bei einigen Befehlen Adressierungsarten hinzugekommen, die beim 6502
+nicht m"oglich waren. Die Mitsubishi-Mikrokontroller dagegen erweitern den
+6502-Befehlssatz in erster Linie um Bitoperationen und
+Multiplikations-/Divisionsbefehle. Bis auf den unbedingten Sprung und
+Befehle zur Inkrementierung/Dekremetierung des Akkumulatos sind die
+Erweiterungen disjunkt. Dem 65SC02 fehlen die Bitmanipulationsbefehle
+des 65C02. Mit dem Prozessortyp 6502UNDOC sind die ,,undokumentierten''
+6502-Befehle erreichbar, d.h. die Operationen, die sich bei der Verwendung
+nicht als Befehle definierter Bitkombinationen im Opcode ergeben. Die von
+AS unterst"utzten Varianten sind im Kapitel mit den prozessorspezifischen
+Hinweisen beschrieben.
+%%-----------
+\begin{quote}
+m) MELPS7700, 65816
+\end{quote}
+Neben einer ,,16-Bit-Version'' des 6502-Befehlssatzes bieten diese
+Prozessoren einige Befehlserweiterungen. Diese sind aber gr"o"serenteils
+disjunkt, da sie sich an ihren jeweiligen 8-bittigen Vorbildern (65C02
+bzw. MELPS-740) orientieren. Z.T.~werden auch andere Mnemonics f"ur
+gleiche Befehle verwendet.
+%%-----------
+\begin{quote}
+n) MELPS4500
+\end{quote}
+%%-----------
+\begin{quote}
+o) M16
+\end{quote}
+%%-----------
+\begin{quote}
+p) M16
+\end{quote}
+%%-----------
+\begin{quote}
+q) 4004
+\end{quote}
+%%-----------
+\begin{quote}
+r) 8021, 8022, 8039, 80C39, 8048, 80C48, 8041, 8042
+\end{quote}
+Bei den ROM-losen Versionen 8039 und 80C39 sind die Befehle verboten,
+die den BUS (Port 0) ansprechen. Der 8021 und 8022 sind Sonderversionen
+mit stark abgemagertem Befehlssatz, wof"ur der 8022 zwei A/D-Wandler
+und die dazugeh"origen Steuerbefehle enth"alt. Die CMOS-Versionen lassen
+sich mit dem \tty{IDL}-Befehl in einen Ruhezustand niedriger Stromaufnahme
+"uberf"uhren. Der 8041 und 8042 haben einige Zusatzbefehle zur
+Steuerung der Busschnittstelle, daf"ur fehlen aber einige andere Befehle.
+Dar"uber hinaus ist bei diesen Prozessoren der Programmadre"sraum nicht
+extern erweiterbar, weshalb AS das Codesegment bei diesen Prozessoren
+auf 1 bzw. 2 Kbyte begrenzt.
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+s) \> 87C750 $\rightarrow$ 8051, 8052, 80C320, 80C501, 80C502, \\
+ \> 80C504, 80515, and 80517 $\rightarrow$ 80C251
+\end{tabbing}
+\end{quote}
+Der 87C750 kann nur max. 2 Kbyte Programmspeicher adressieren, weshalb
+die \tty{LCALL}- und \tty{LJMP}-Befehle bei ihm fehlen. Zwischen den
+acht mittleren Prozessoren nimmt AS selber "uberhaupt keine Unterscheidung
+vor, sondern verwaltet den Unterschied lediglich in der Variablen
+\tty{MOMCPU} (s.u.), die man mit \tty{IF}-Befehlen abfragen kann. Eine
+Ausnahme stellt lediglich der 80C504, der in seiner momentanen Form noch einen
+Maskenfehler zeigt, wenn eine \tty{AJMP}- oder \tty{ACALL}-Anweisung auf der
+vorletzten Adresse einer 2K-Seite steht. AS benutzt in einem solchen
+Fall automatisch lange Sprungbefehle bzw. gibt eine Fehlermeldung aus. Der
+80C251 hingegen stellt einen drastischen Fortschritt in Richtung 16/32 Bit,
+gr"o"serer Adre"sr"aume und orthogonalerem Befehlssatz dar.
+%%-----------
+\begin{quote}
+t) 8096 $\rightarrow$ 80196 $\rightarrow$ 80196N $\rightarrow$ 80296
+\end{quote}
+Neben einem anderen Satz von SFRs (die "ubrigens von Unterversion zu
+Unterversion stark differieren) kennt der 80196 eine Reihe von
+zus"atzlichen Befehlen und kennt einen ,,Windowing''-Mechanismus, um
+das gr"o"sere interne RAM anzusprechen. Die 80196N-Familie wiederum
+erweitert den Adre"sraum auf 16 Mbyte und f"uhrt eine Reihe von
+Befehlen ein, mit denen man auf Adressen jenseits 64 Kbyte zugreifen
+kann. Der 80296 erweitert den CPU-Kern um Befehle zur Signalverarbeitung
+und ein zweites Windowing-Register, verzichtet jedoch auf den {\em
+Peripheral Transaction Server} (PTS) und verliert damit wieder zwei
+Maschinenbefehle.
+%%-----------
+\begin{quote}
+u) 8080 und 8085
+\end{quote}
+Der 8085 kennt zus"atzlich die Befehle \tty{RIM} und \tty{SIM} zum Steuern der
+Interruptmaske und der zwei I/O-Pins.
+%%-----------
+\begin{quote}
+v) 8086 $\rightarrow$ 80186 $\rightarrow$ V30 $\rightarrow$ V35
+\end{quote}
+Hier kommen wieder nur neue Befehle dazu. Die entsprechenden 8-Bitter sind
+wegen ihrer Befehlskompatibilit"at nicht aufgef"uhrt, f"ur ein 8088-System
+ist also z.B. 8086 anzugeben.
+%%-----------
+\begin{quote}
+w) 80960
+\end{quote}
+%%-----------
+\begin{quote}
+x) 8X300 $\rightarrow$ 8X305
+\end{quote}
+Der 8X305 besitzt eine Reihe zus"atzlicher Arbeitsregister, die dem
+8X300 fehlen und kann mit diesen auch zus"atzliche Operationen ausf"uhren,
+wie das direkte Schreiben von 8-Bit-Werten auf Peripherieadressen.
+%%-----------
+\begin{quote}
+y) XAG1, XAG2, XAG3
+\end{quote}
+Diese Prozessoren unterscheiden sich nur in der Gr"o"se des eingebauten
+ROMs, die in \tty{STDDEFXA.INC} definiert ist.
+%%-----------
+\begin{quote}
+z) AT90S1200 $\rightarrow$ AT90S2313 $\rightarrow$ AT90S4414 $\rightarrow$
+ AT90S8515
+\end{quote}
+Der erste Vertreter der AVR-Reihe stellt die Minimalkonfiguration dar,
+ohne RAM-Speicher und demzufolge auch ohne Load/Store-Befehle. Die
+beiden anderen Prozessoren unterscheiden sich nur im Speicherausbau
+und in der eingebauten Peripherie, was in \tty{REGAVR.INC} differenziert
+wird.
+%%-----------
+\begin{quote}
+aa) AM29245 $\rightarrow$ AM29243 $\rightarrow$ AM29240 $\rightarrow$ AM29000
+\end{quote}
+Je weiter man sich in der Liste nach rechts bewegt, desto weniger
+Befehle m"ussen in Software emuliert werden. W"ahrend z.B. der 29245
+noch nicht einmal einen Hardware-Multiplizierer besitzt, fehlen den
+beiden Vertretern in der Mitte nur die Gleitkommabefehle. Der 29000
+dient dabei als ,,generischer'' Typ, der alle Befehle in Hardware versteht.
+%%-----------
+\begin{quote}
+ab) 80C166 $\longrightarrow$ 80C167,80C165,80C163
+\end{quote}
+80C167 und 80C165/163 haben anstelle 256 Kbyte max. 16 Mbyte Adre"sraum,
+au"serdem kennen sie einige zus"atzliche Befehle f"ur erweiterte
+Adressierungsmodi sowie atomare Befehlssequenzen. Untereinander
+unterscheiden sich diese Prozessoren der ,,zweiten Generation'' nur in der
+eingebauten Peripherie.
+%%-----------
+\begin{quote}
+ac) Z80 $\rightarrow$ Z80UNDOC $\rightarrow$ Z180 $\rightarrow$ Z380
+\end{quote}
+W"ahrend f"ur den Z180 nur die zus"atzlichen Befehle definiert sind
+(d.h. die Z180-MMU findet noch keine Ber"ucksichtigung), besitzt der
+Z380 32-Bit-Register, einen linearen 4Gbyte-Adre"sraum sowie neben
+einer Reihe von Befehlserweiterungen, die den Befehlssatz deutlich
+orthogonaler machen, neue Adressierungsmodi (Ansprechen der
+Indexregisterh"alften, Stack-relativ). Zu einem kleinen Teil existieren
+diese Erweiterungen aber auch schon beim Z80 als undokumentierte
+Befehle, die mit der Variante \tty{Z80UNDOC} zugeschaltet werden
+k"onnen. Eine Liste mit den zus"atzlichen Befehlen findet sich im
+Kapitel mit den prozessorspezifischen Hinweisen.
+%%-----------
+\begin{quote}
+ad) Z8601, Z8604, Z8608, Z8630, Z8631
+\end{quote}
+Diese Prozessoren unterscheiden sich wieder nur in
+Speicherausbau und Peripherie, d.h. die Wahl hat auf den
+unterst"utzten Befehlssatz keinen Effekt.
+%%-----------
+\begin{quote}
+ae) 96C141, 93C141
+\end{quote}
+Diese beiden Prozessoren repr"asentieren die beiden Varianten der
+Prozessorfamilie: TLCS-900 und TLCS-900L. Die Unterschiede dieser beiden
+Varianten werden in Abschnitt \ref{TLCS900Spec} genauer beleuchtet.
+%%-----------
+\begin{quote}
+af) 90C141
+\end{quote}
+%%-----------
+\begin{quote}
+ag) 87C00, 87C20, 87C40, 87C70
+\end{quote}
+Die Prozessoren der TLCS-870-Reihe haben zwar den identischen CPU-Kern, je
+nach Variante aber eine unterschiedliche Peripherieausstattung. Zum
+Teil liegen Register gleichen Namens auf unterschiedlichen Adressen.
+Die Datei STDDEF87.INC benutzt analog zur MCS-51-Familie die hier
+m"ogliche Unterscheidung, um automatisch den korrekten Symbolsatz
+bereitzustellen.
+%%-----------
+\begin{quote}
+ah) 47C00 $\rightarrow$ 470C00 $\rightarrow$ 470AC00
+\end{quote}
+Diese drei Varianten der TLCS-47-Familie haben unterschiedlich gro"se
+RAM-und ROM-Adre"sbereiche, wodurch jeweils einige Befehle zur
+Bankumschaltung hinzukommen oder wegfallen.
+%%-----------
+\begin{quote}
+ai) 97C241
+\end{quote}
+%%-----------
+\begin{quote}
+aj) 16C54 $\rightarrow$ 16C55 $\rightarrow$ 16C56 $\rightarrow$ 16C57
+\end{quote}
+Diese Prozessoren unterscheiden sich durch den verf"ugbaren
+Adre"sraum im Programmspeicher, d.h. durch die Adresse, ab der
+der AS "Uberl"aufe anmeckert.
+%%-----------
+\begin{quote}
+ak) 16C64, 16C84
+\end{quote}
+Analog zur MCS-51-Familie findet hier keine Unterscheidung im
+Codegenerator statt, die unterschiedlichen Nummern dienen lediglich
+der Einblendung der korrekten SFRs in STDDEF18.INC.
+%%-----------
+\begin{quote}
+al) 17C42
+\end{quote}
+%%-----------
+\begin{quote}
+am) ST6210/ST6215 $\rightarrow$ ST6220/ST6225
+\end{quote}
+Die einzige Unterscheidung, die AS zwischen den beiden Paaren vornimmt, ist
+der bei den ersten beiden kleinere Adre"sraum (2K anstelle 4K). Die
+Feinunterscheidung dient zur automatischen Unterscheidung in der Quelldatei,
+welche Hardware jeweils vorhanden ist (analog zum 8051/52/515).
+%%-----------
+\begin{quote}
+an) ST7
+\end{quote}
+%%-----------
+\begin{quote}
+ao) ST9020, ST9030, ST9040, ST9050
+\end{quote}
+Diese 4 Namen vetreten die vier ,,Unterfamilien'' der ST9-Familie, die
+sich durch eine unterschiedliche Ausstattung mit On-Chip-Peripherie
+auszeichen. Im Prozessorkern sind sie identisch, so da"s diese
+Unterscheidung wieder nur im Includefile mit den Peripherieadressen zum
+Zuge kommt.
+%%-----------
+\begin{quote}
+ap) 6804
+\end{quote}
+%%-----------
+\begin{quote}
+aq) 32010 $\rightarrow$ 32015
+\end{quote}
+Der TMS32010 besitzt nur 144 Byte internes RAM, weshalb AS Adressen im
+Datensegment auf eben diesen Bereich begrenzt. F"ur den 32015 gilt diese
+Beschr"ankung nicht, es kann der volle Bereich von 0--255 angesprochen
+werden.
+%%-----------
+\begin{quote}
+ar) 320C25 $\rightarrow$ 320C26 $\rightarrow$ 320C28
+\end{quote}
+Diese Prozessoren unterscheiden sich nur leicht in der
+On-Chip-Peripherie sowie den Konfigurationsbefehlen.
+%%-----------
+\begin{quote}
+as) 320C30, 320C31
+\end{quote}
+Der 320C31 ist eine etwas ,,abgespeckte'' Version mit dem gleichen
+Befehlssatz, jedoch weniger Peripherie. In STDDEF3X.INC wird diese
+Unterscheidung ausgenutzt.
+%%-----------
+\begin{quote}
+at) 320C203 $\rightarrow$ 320C50, 320C51, 320C53
+\end{quote}
+Ersterer ist der generelle Repr"asentant f"ur die
+C20x-Signalprozessorfamilie, die eine Untermenge des C5x-Befehlssatzes
+implementieren. Die Unterscheidung zwischen den verschiedenen
+C5x-Prozessoren wird von AS momentan nicht ausgenutzt.
+%%-----------
+\begin{quote}
+au) TMS9900
+\end{quote}
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+av) \> TMS70C00, TMS70C20, TMS70C40, \\
+ \> TMS70CT20, TMS70CT40, \\
+ \> TMS70C02, TMS70C42, TMS70C82, \\
+ \> TMS70C08, TMS70C48 \\
+\end{tabbing}
+\end{quote}
+Alle Mitglieder dieser Familie haben den gleichen CPU-Kern,
+unterscheiden sich im Befehlssatz also nicht. Die Unterschiede
+finden sich nur in der Datei REG7000.INC, in der Speicherbereiche
+und Peripherieadressen definiert werden. Die in einer Zeile
+stehenden Typen besitzen jeweils gleiche Peripherie und gleiche
+interne RAM-Menge, unterscheiden sich also nur in der Menge
+eingebauten ROMs.
+%%-----------
+\begin{quote}
+aw) 370C010, 370C020, 370C030, 370C040 und 370C050
+\end{quote}
+Analog zur MCS-51-Familie werden die unterschiedlichen Typen nur
+zur Unterscheidung der Peripherie in STDDEF37.INC genutzt, der
+Befehlssatz ist identisch.
+%%-----------
+\begin{quote}
+ax) MSP430
+\end{quote}
+%%-----------
+\begin{quote}
+ay) SC/MP
+\end{quote}
+%%-----------
+\begin{quote}
+az) COP87L84
+\end{quote}
+Dies ist das momentan einzige unterst"utzte Mitglied der COP8-Familie
+von National Semiconductor. Mir ist bekannt, da"s die Familie
+wesentlich gr"o"ser ist und auch Vertreter mit unterschiedlich gro"sem
+Befehlssatz existieren, die nach Bedarf hinzukommen werden. Es ist eben
+ein Anfang, und die Dokumentation von National ist ziemlich umfangreich...
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+ba) \> SC14400, SC14401, SC14402, SC14404, SC14405, \\
+ \> SC14420, SC14421, SC14422, SC14424 \\
+\end{tabbing}
+\end{quote}
+Diese Gruppe von DECT-Controller unterscheidet sich in ihrem
+Befehlsumfang, da jeweils unterschiedliche B-Feld Datenformate
+unterst"utzt werden und deren Architektur im Laufe der Zeit optimiert
+wurde.
+%%-----------
+\begin{quote}
+bb) 7810 $\rightarrow$ 78C10
+\end{quote}
+Die NMOS-Version besitzt keinen STOP-Modus; der entspechende Befehl sowie
+das ZCM-Register fehlen demzufolge. \bb{VORSICHT!} NMOS- und CMOS-Version
+differieren zum Teil in den Reset-Werten einiger Register!
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+bc) \> 75402, \\
+ \> 75004, 75006, 75008, \\
+ \> 75268, \\
+ \> 75304, 75306, 75308, 75312, 75316, \\
+ \> 75328, \\
+ \> 75104, 75106, 75108, 75112, 75116, \\
+ \> 75206, 75208, 75212, 75216, \\
+ \> 75512, 75516 \\
+\end{tabbing}
+\end{quote}
+Dieses ,,F"ullhorn'' an Prozessoren unterscheidet sich innerhalb einer
+Gruppe nur durch die RAM- und ROM-Gr"o"se; die Gruppen untereinander
+unterscheiden sich einmal durch ihre on-chip-Peripherie und
+zum anderen durch die M"achtigkeit des Befehlssatzes.
+%%-----------
+\begin{quote}
+bd) 78070
+\end{quote}
+Dies ist das einzige, mir momentan vertraute Mitglied der
+78K0-Familie von NEC. Es gelten "ahnliche Aussagen wie zur
+COP8-Familie!
+%%-----------
+\begin{quote}
+be) 7720 $\rightarrow$ 7725
+\end{quote}
+Der $\mu$PD7725 bietet im Vergleich zu seinem Vorg"anger gr"o"sere
+Adre"sr"aume und einige zus"atzliche Befehle. {\bf VORSICHT!} Die
+Prozessoren sind nicht zueinander bin"arkompatibel!
+%%-----------
+\begin{quote}
+bf) 77230
+\end{quote}
+%%-----------
+\begin{quote}
+\begin{tabbing}
+bg) \= SYM53C810, SYM53C860, SYM53C815, SYM53C825, \\
+ \> SYM53C875, SYM53C895
+\end{tabbing}
+\end{quote}
+Die einfacheren Mitglieder dieser Familie von SCSI-Prozessoren besitzen
+einige Befehlsvarianten nicht, au"serdem unterscheiden sie sich in ihrem
+Satz interner Register.
+%%-----------
+\begin{quote}
+bh) MB89190
+\end{quote}
+Dieser Prozessortyp repr"asentiert die F$^{2}$MC8L-Serie von Fujitsu.
+
+Beim CPU-Befehl mu"s der Prozessortyp als einfache Konstante
+angegeben werden, eine Berechnung \`a la
+\begin{verbatim}
+ CPU 68010+10
+\end{verbatim}
+ist also nicht zul"assig. G"ultige Aufrufe sind z.B.
+\begin{verbatim}
+ CPU 8051
+\end{verbatim}
+oder
+\begin{verbatim}
+ CPU 6800
+\end{verbatim}
+Egal, welcher Prozessortyp gerade eingestellt ist, in der
+Integervariablen MOMCPU wird der momentane Status als Hexadezimalzahl
+abgelegt. F"ur den 68010 ist z.B. \tty{MOMCPU=\$68010}, f"ur den 80C48
+\tty{MOMCPU=80C48H}. Da man Buchstaben au"ser A..F nicht als Hexziffer
+interpretieren kann, mu"s man sich diese bei der Hex-Darstellung
+des Prozessors wegdenken. F"ur den Z80 ist z.B. \tty{MOMCPU=80H}.
+\par
+Dieses Feature kann
+man vorteilhaft einsetzen, um je nach Prozessortyp unterschiedlichen
+Code zu erzeugen. Der 68000 z.B. kennt noch keinen Befehl f"ur den
+Unterprogrammr"ucksprung mit Stapelkorrektur. Mit der Variablen
+\tty{MOMCPU} kann man ein Makro definieren, das je nach Prozessortyp den
+richtigen Befehl benutzt oder ihn emuliert:
+\begin{verbatim}
+myrtd MACRO disp
+ IF MOMCPU$<$68010 ; auf 68008 und
+ MOVE.L (sp),disp(sp) ; 68000 emulieren
+ LEA disp(sp),sp
+ RTS
+ ELSEIF
+ RTD #disp ; ab 68010 direkt
+ ENDIF ; benutzen
+ ENDM
+
+ CPU 68010
+ MYRTD 12 ; ergibt RTD #12
+
+ CPU 68000
+ MYRTD 12 ; ergibt MOVE.. /
+ ; LEA.. / RTS
+\end{verbatim}
+Da nicht alle Prozessornamen nur aus Ziffern und Buchstaben zwischen
+A und F bestehen, wird zus"atzlich der volle Name in der
+String-Variablen \tty{MOMCPUNAME} abgelegt.
+\par
+Implizit schaltet der Assembler mit dem \tty{CPU}-Befehl das aktuelle Segment
+wieder auf Code zur"uck, da dies das einzige Segment ist, das alle
+Prozessoren definieren.
+\par
+Default f"ur den Prozessortyp ist \tty{68008}, sofern dieser "uber die
+gleichnamige Kommandozeilenoption nicht ver"andert wurde.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SUPMODE, FPU, PMMU}
+\ttindex{SUPMODE}\ttindex{FPU}\ttindex{PMMU}
+
+{\em\begin{tabbing}
+G"ultigkeit: \= 680x0, FPU auch 80x86, i960, SUPMODE auch TLCS-900, \\
+ \> SH7000, i960, 29K, XA, PowerPC, M*CORE und TMS9900
+\end{tabbing}}
+
+Mit diesen drei Schaltern kann bestimmt werden, auf welche Teile des
+Befehlssatzes verzichtet werden soll, weil die daf"ur n"otigen
+Vorbedingungen im folgenden Codest"uck nicht gegeben sind. Als
+Parameter f"ur diese Befehle darf entweder \tty{ON} oder \tty{OFF} gegeben werden,
+der momentan gesetzte Zustand kann aus einer Variablen ausgelesen
+werden, die entweder TRUE oder FALSE ist.
+\par
+Die Befehle bedeuten im einzelnen folgendes:
+\begin{itemize}
+\item{\tty{SUPMODE}: erlaubt bzw. sperrt Befehle, f"ur deren Ausf"uhrung
+ der Prozessor im Supervisorstatus sein mu"s. Die Statusvariable
+ hei"st \tty{INSUPMODE}.}
+\item{\tty{FPU}: erlaubt bzw. sperrt die Befehle des numerischen Koprozessors
+ 8087 bzw. 68881/68882. Die Statusvariable hei"st \tty{FPUAVAIL}.}
+\item{\tty{PMMU}: erlaubt bzw. sperrt die Befehle der Speicherverwaltungseinheit
+ 68851 bzw. der im 68030 eingebauten MMU. \bb{ACHTUNG!} Die 68030-MMU
+ erlaubt nur eine rel. kleine Untermenge der 68851-Befehle. Der
+ Assembler kann hier keine Pr"ufung vornehmen! Die Statusvariable hei"st
+ \tty{PMMUAVAIL}.}
+\end{itemize}
+Benutzung von auf diese Weise gesperrten Befehlen erzeugt bei \tty{SUPMODE}
+eine Warnung, bei \tty{PMMU} und \tty{FPU} eine echte Fehlermeldung.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FULLPMMU}
+\ttindex{FULLPMMU}
+
+{\em G"ultigkeit: 680x0}
+
+Motorola hat zwar ab dem 68030 die PMMU in den Prozessor integriert,
+diese aber nur mit einer Funktionsuntermenge der externen PMMU 68851
+ausgestattet. AS sperrt bei aktiviertem PMMU-Befehlssatz (s.o.) deshalb
+alle fehlenden Befehle, wenn als Zielprozessor 68030 oder h"oher
+eingestellt wurde. Nun kann es aber sein, da"s in einem System mit
+68030-Prozessor die interne MMU abgeschaltet wurde und der Prozessor
+mit einer externen 68851 betrieben wird. Mit \tty{FULLPMMU ON} kann man
+AS dann mitteilen, da"s der vollst"andige MMU-Befehlssatz zugelassen
+ist. Umgekehrt kann man, wenn man portablen Code erzeugen will, alle
+zus"atzlichen Befehle trotz 68020-Zielplattform mit \tty{FULLPMMU OFF}
+abschalten. Die Umschaltung darf beliebig oft erfolgen, die momentane
+Einstellung kann aus einem gleichnamigen Symbol ausgelesen werden.
+\bb{ACHTUNG!} Der \tty{CPU}-Befehl besetzt f"ur 680x0-Argumente implizit
+diese Einstellung vor! \tty{FULLPMMU} mu"s also auf jeden Fall nach dem
+\tty{CPU}-Befehl kommen!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PADDING}
+\ttindex{PADDING}
+
+{\em G"ultigkeit: 680x0, M*Core, XA, H8, SH7000, TMS9900, MSP430, ST7}
+
+Prozessoren der 680x0-Familie stehen ungeraden Adressen ziemlich
+kritisch gegen"uber: Befehle d"urfen nicht auf einer ungeraden Adresse
+beginnen, und Datenzugriffe sind mit ungeraden Adressen bis zum
+68010 nur byteorientiert erlaubt. Die H8-Familie setzt bei Zugriffen
+auf ungerade Adressen das unterste Adre"sbit einfach ganz auf Null,
+die 500er ,,bedanken'' sich wiederum mit einer Exception...
+AS bem"uht sich daher, mit \tty{DC} oder \tty{DS} angelegte Datenstrukturen
+immer mit einer geraden Bytezahl abzulegen. Das bedeutet bei den Befehlen
+\tty{DS.B} und \tty{DC.B} aber unter Umst"anden, da"s ein F"ullbyte
+eingef"ugt werden mu"s. Dieses Verhalten kann man mit dem
+\tty{PADDING}-Befehl ein- und ausschalten. Als Argument
+ist analog zu den vorherigen Befehlen \tty{ON} oder \tty{OFF} erlaubt, und
+die augenblickliche Einstellung kann aus dem gleichnamigen Symbol
+ausgelesen werden. Defaultm"a"sig ist \tty{PADDING} nur f"ur die
+680x0-Familie eingeschaltet, f"ur alle anderen werden erst nach Umschaltung
+Padding-Bytes eingef"ugt!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{MAXMODE}
+\ttindex{MAXMODE}
+
+{\em G"ultigkeit: TLCS-900, H8}
+
+Die Prozessoren der TLCS-900-Reihe k"onnen in 2 Betriebsarten arbeiten,
+dem Minimum-und Maximum-Modus. Je nach momentaner Betriebsart gelten
+f"ur den Betrieb und den Assembler etwas andere Eckwerte. Mit diesem Befehl
+und den Parametern \tty{ON} oder \tty{OFF} teilt man AS mit, da"s der
+folgende Code im Maximum- oder Minimum-Modus abl"auft. Die momentane
+Einstellung kann aus der Variablen \tty{INMAXMODE} ausgelesen werden.
+Voreinstellung ist \tty{OFF}, d.h. Minimum-Modus.
+\par
+Analog dazu teilt man im H8-Modus AS mit diesem Befehl mit, ob
+mit einem 64K- oder 16Mbyte-Adre"sraum gearbeitet wird. F"ur den
+einfachen 300er ist diese Einstellung immer \tty{OFF} und kann nicht
+ver"andert werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{EXTMODE und LWORDMODE}
+\ttindex{EXTMODE}\ttindex{LWORDMODE}
+
+{\em G"ultigkeit: Z380}
+
+Der Z380 kann in insgesamt 4 Betriebsarten arbeiten, die sich durch
+die Einstellung von 2 Flags ergeben: Das XM-Flag bestimmt, ob der
+Prozessor mit einem 64 Kbyte oder 4 Gbyte gro"sen Adre"sraum arbeiten
+soll und kann nur gesetzt werden (nach einem Reset steht es
+Z80-kompatibel auf 0). Demgegen"uber legt das LW-Flag fest, ob
+Wort-Befehle mit einer Wortl"ange von 16 oder 32 Bit arbeiten sollen.
+Die Stellung dieser beiden Flags beeinflu"st Wertebereichseinschr"ankungen
+von Konstanten oder Adressen, weshalb man AS "uber diese beiden Befehle
+deren Stellung mitteilen mu"s. Als Default nimmt AS an, da"s beide
+Flags auf 0 stehen, die momentane Einstellung (\tty{ON} oder \tty{OFF})
+kann aus den vordefinierten Variablen \tty{INEXTMODE} bzw. \tty{INLWORDMODE}
+ausgelesen werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SRCMODE}
+\ttindex{SRCMODE}
+
+{\em G"ultigkeit: MCS-251}
+
+Intel hat den Befehlssatz der 8051er beim 80C251 deutlich erweitert,
+hatte aber leider nur noch einen einzigen freien Opcode f"ur diese
+Befehle frei. Damit der Prozessor nicht auf alle Ewigkeit durch
+einen Pr"afix behindert bleibt, hat Intel zwei Betriebsarten vorgesehen:
+Den Bin"ar- und den Quellmodus. Im Bin"armodus ist der Prozessor voll
+8051-kompatibel, alle erweiterten Befehle ben"otigen den noch freien
+Opcode als Pr"afix. Im Quellmodus tauschen diese neuen Befehle ihre
+Position in der Code-Tabelle mit den entsprechenden 8051-Instruktionen,
+welche dann wiederum mit einem Pr"afix versehen werden m"ussen.
+Damit AS wei"s, wann er Pr"afixe setzen mu"s und wann nicht, mu"s man
+ihm mit diesem Befehl mitteilen, ob der Prozessor im Quellmodus (\tty{ON})
+oder Bin"armodus (\tty{OFF}) betrieben wird. Die momentane Einstellung
+kann man aus der Variablen \tty{INSRCMODE} auslesen. Der Default ist
+\tty{OFF}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BIGENDIAN}
+\ttindex{BIGENDIAN}
+
+{\em G"ultigkeit: MCS-51/251, PowerPC}
+
+Bei den Prozessoren der 8051-Serie ist Intel seinen eigenen Prinzipien
+untreu geworden: Der Prozessor verwendet entgegen jeglicher Tradition
+eine Big-Endian-Orientierung von Mehrbytewerten! W"ahrend dies bei
+den MCS-51-Prozessoren noch nicht gro"sartig auffiel, da der Prozessor
+ohnehin nur 8-bittig auf Speicherzellen zugreifen konnte, man sich die
+Byte-Anordnung bei eigenen Datenstrukturen also aussuchen konnte, ist
+dies beim MCS-251 nicht mehr so, er kann auch ganze (Lang-)Worte aus
+dem Speicher lesen und erwartet dabei das MSB zuerst. Da dies nicht der
+bisherigen Arbeitsweise von AS bei der Konstantenablage entspricht,
+kann man nun mit diesem Befehl umschalten, ob die Befehle \tty{DB, DW, DD,
+DQ} und \tty{DT} mit Big- oder Little-Endian-Orientierung arbeiten sollen.
+Mit \tty{BIGENDIAN OFF} (Voreinstellung) wird wie bei "alteren AS-Versionen
+zuerst das niederwertigste Byte abgelegt, mit \tty{BIGENDIAN ON} wird die
+MCS-251-kompatible Variante benutzt. Nat"urlich kann man diese Einstellung
+beliebig oft im Code "andern; die momentane Einstellung kann aus dem
+gleichnamigen Symbol ausgelesen werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{WRAPMODE}
+\ttindex{WRAPMODE}
+
+{\em G"ultigkeit: Atmel AVR}
+
+Ist dieser Schalter auf {\tt ON} gesetzt, so veranla"st man AS dazu,
+anzunehmen, der Programmz"ahler des Prozessors habe nicht die volle, durch
+die Architektur gegebene L"ange von 16 Bits, sondern nur eine L"ange, die
+es gerade eben erlaubt, das interne ROM zu adressieren. Im Falle des
+AT90S8515 sind dies z.B. 12 Bit, entsprechend 4 KWorten oder 8 KBytes.
+Damit werden relative Spr"unge vom Anfang des ROMs zum Ende und umgekehrt
+m"oglich, die bei strenger Arithmetik einen out-of-branch ergeben w"urden,
+hier jedoch funktionieren, weil die "Ubertragsbits bei der
+Zieladressenberechnung 'unter den Tisch' fallen. Vergewissern Sie sich
+genau, ob die von Ihnen eingesetzte Prozessorvariante so arbeitet, bevor
+Sie diese Option einschalten! Im Falle des oben erw"ahnten AT90S8515 ist
+diese Option sogar zwingend n"otig, um überhaupt quer durch den ganzen
+Adre"sraum springen zu k"onnen...
+
+Defaultm"a"sig steht dieser Schalter auf {\tt OFF}, der momentane Stand
+l"a"st sich aus einem gleichnamigen Symbol auslesen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SEGMENT}
+\ttindex{SEGMENT}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Bestimmte Mikrokontroller und Signalprozessoren kennen mehrere
+Adre"sbereiche, die nicht miteinander mischbar sind und jeweils auch
+verschiedene Befehle zur Ansprache ben"otigen. Um auch diese verwalten zu
+k"onnen, stellt der Assembler mehrere Programmz"ahler zur Verf"ugung,
+zwischen denen mit dem
+\tty{SEGMENT}-Befehl hin-und hergeschaltet werden kann. Dies erlaubt es,
+sowohl in mit \tty{INCLUDE} eingebundenen Unterprogrammen als auch im
+Hauptprogramm ben"otigte Daten an der Stelle zu definieren, an denen
+sie benutzt werden. Im einzelnen werden folgende Segmente mit folgenden
+Namen verwaltet:
+\begin{itemize}
+\item{\tty{CODE}: Programcode;}
+\item{\tty{DATA}: direkt adressierbare Daten (dazu rechnen auch SFRs);}
+\item{\tty{XDATA}: im extern angeschlossenen RAM liegende Daten oder
+ X-Adre"sraum beim DSP56xxx oder ROM-Daten beim $\mu$PD772x;}
+\item{\tty{YDATA}: Y-Adre"sraum beim DSP56xxx;}
+\item{\tty{IDATA}: indirekt adressierbare (interne) Daten;}
+\item{\tty{BITDATA}: der Teil des 8051-internen RAMs, der bitweise
+ adressierbar ist;}
+\item{\tty{IO}: I/O-Adre"sbereich;}
+\item{\tty{REG}: Registerbank des ST9;}
+\item{\tty{ROMDATA}: Konstanten-ROM der NEC-Signalprozessoren.}
+\end{itemize}
+Zu Adre"sbereich und Initialwerten der Segmente siehe Abschnitt \ref{SectORG}.
+(\tty{ORG}). Je nach Prozessorfamilie sind auch nicht alle Segmenttypen
+erlaubt.
+\par
+Das Bitsegment wird so verwaltet, als ob es ein Bytesegment w"are,
+d.h. die Adressen inkrementieren um 1 pro Bit.
+\par
+Labels, die in einem Segment eines bestimmten Typs definiert werden,
+erhalten diesen Typ als Attribut. Damit hat der Assembler eine
+begrenzte Pr"ufm"oglichkeit, ob mit den falschen Befehlen auf Symbole
+in einem Segment zugegriffen wird. In solchen F"allen wird der
+Assembler eine Warnung ausgeben.
+\par
+Beispiel:
+\begin{verbatim}
+ CPU 8051 ; MCS-51-Code
+
+ SEGMENT code ; Testcodeblock
+
+ SETB flag ; keine Warnung
+ SETB var ; Warnung : falsches Segment
+
+ SEGMENT data
+
+var DB ?
+
+ SEGMENT bitdata
+
+flag DB ?
+\end{verbatim}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PHASE und DEPHASE}
+\ttindex{PHASE}\ttindex{DEPHASE}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+In manchen Anwendungen (speziell Z80-Systeme) mu"s Code vor der
+Benutzung in einen anderen Adre"sbereich verschoben werden. Da der
+Assembler davon aber nichts wei"s, w"urde er alle Labels in dem zu
+verschiebenden Teil auf die Ladeadressen ausrichten. Der Programmierer
+m"u"ste Spr"unge innerhalb dieses Bereiches entweder lageunabh"angig
+kodieren oder die Verschiebung bei jedem Symbol ,,zu Fu"s'' addieren.
+Ersteres ist bei manchen Prozessoren gar nicht m"oglich, letzteres sehr
+fehleranf"allig.
+\par
+Mit dem Befehlen \tty{PHASE} und \tty{DEPHASE} ist es m"oglich, dem
+Assembler mitzuteilen, auf welcher Adresse der Code im Zielsystem
+effektiv ablaufen wird:
+\begin{verbatim}
+ PHASE <Adresse>
+\end{verbatim}
+informiert den Assembler davon, da"s der folgende Code auf der
+spezifizierten Adresse ablaufen soll. Der Assembler berechnet
+daraufhin die Differenz zum echten Programmz"ahler und addiert diese
+Differenz bei folgenden Operationen dazu:
+\begin{itemize}
+\item{Adre"sangabe im Listing}
+\item{Ablage von Labelwerten}
+\item{Programmz"ahlerreferenzen in relativen Spr"ungen und
+ Adre"sausdr"ucken}
+\item{Abfrage des Programmz"ahlers mit den Symbolen \verb!*! bzw. \verb!$!}
+\end{itemize}
+Diese ,,Verschiebung'' wird mit dem Befehl
+\begin{verbatim}
+ DEPHASE
+\end{verbatim}
+wieder aufgehoben.
+\par
+Obwohl dieses Befehlspaar vornehmlich in Codesegmenten Sinn macht,
+verwaltet der Assembler f"ur alle definierten Segmente Phasenwerte.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SAVE und RESTORE}
+\ttindex{SAVE}\ttindex{RESTORE}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Mit dem Befehl \tty{SAVE} legt der Assembler den Inhalt folgender
+Variablen auf einen internen Stapel:
+\begin{itemize}
+\item{momentan gew"ahlter Prozessortyp (mit \tty{CPU} gesetzt);}
+\item{momentan aktiver Speicherbereich (mit \tty{SEGMENT} gesetzt);}
+\item{Flag, ob Listing ein- oder ausgeschaltet ist (mit \tty{LISTING}
+ gesetzt);}
+\item{Flag, ob Expansionen folgender Makos im Listing ausgegeben
+ werden sollen (mit \tty{MACEXP} gesetzt).}
+\item{momentan aktive Zeichen"ubersetzungstabelle (mit \tty{CODEPAGE}
+ gesetzt).}
+\end{itemize}
+Mit dem Gegenst"uck \tty{RESTORE} wird entsprechend der zuletzt
+gesicherte Zustand von diesem Stapel wieder heruntergeladen. Diese beiden
+Befehle sind in erster Linie f"ur Includefiles definiert worden, um
+in diesen Dateien die obigen Variablen beliebig ver"andern zu k"onnen,
+ohne ihren originalen Inhalt zu verlieren. So kann es z.B. sinnvoll sein,
+in Includefiles mit eigenen, ausgetesteten Unterprogrammen die
+Listingerzeugung auszuschalten:
+\begin{verbatim}
+ SAVE ; alten Zustand retten
+ LISTING OFF ; Papier sparen
+ .. ; der eigentliche Code
+ RESTORE ; wiederherstellen
+\end{verbatim}
+Gegen"uber einem einfachen \tty{LISTING OFF..ON}-P"archen wird hier
+auch dann der korrekte Zustand wieder hergestellt, wenn die Listingerzeugung
+bereits vorher ausgeschaltet war.
+\par
+Der Assembler "uberpr"uft, ob die Zahl von \tty{SAVE}-und \tty{RESTORE}-Befehlen
+"ubereinstimmt und liefert in folgenden F"allen Fehlermeldungen:
+\begin{itemize}
+\item{\tty{RESTORE} und der interne Stapel ist leer;}
+\item{nach Ende eines Passes ist der Stapel nicht leer.}
+\end{itemize}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ASSUME}
+\ttindex{ASSUME}
+
+{\em G"ultigkeit: diverse}
+
+Mit diesem Befehl kann man AS den aktuellen Stand bestimmter Register
+mitteilen, deren Inhalt sich nicht mit einem einfachen \tty{ON} oder
+\tty{OFF} beschreiben l"a"st. Typischerweise sind dies Register, die die
+Adressierungseinheiten beeinflussen und deren Werte AS wissen mu"s, um
+korrekte Adressierungen zu erzeugen. Wichtig ist, da"s man AS mit ASSUME
+diese Werte nur mitteilt, es wird {\em kein} Maschinencode erzeugt, der
+diese Werte in die entsprechenden Register l"adt!
+
+\subsubsection{6809}
+
+Im Gegensatz zu seinen ,,Vorg"angern'' wie 6800 und 6502 kann beim
+6809 die Lage der direct page, d.h. des Adressbereiches, der mit ein
+Byte langen Adressen erreichbar ist, frei bestimmt werden. Dazu dient
+das sog. ,,Direct Page Register'' (\tty{DPR}), das die Seitennummer
+festlegt. Ihm mu"s man mittels \tty{ASSUME} einen passenden Wert
+zuweisen, wenn man einen anderen Wert als die Vorgabe von 0 in DPR
+schreibt, sonst werden Adressen falscher L"ange erzeugt...
+
+
+\subsubsection{68HC16}
+
+Um mit seinen nur 16 Bit breiten Adre"soperanden einen 1 Mbyte gro"sen
+Adre"sraum ansprechen zu k"onnen, bedient sich der 68HC16 einer Reihe
+von Bank-Registern, die die fehlenden oberen vier Adre"sbits nachliefern.
+Davon ist das \tty{EK}-Register f"ur absolute Datenzugriffe (nicht
+Spr"unge!) zust"andig. AS "uberpr"uft bei jeder absoluten Adressierung,
+ob die oberen vier Bits der Adresse mit dem "uber \tty{ASSUME}
+spezifizierten Wert "ubereinstimmen. Differieren die Werte, gibt AS eine
+Warnung aus. Der Vorgabewert f"ur \tty{EK} ist 0.
+
+
+\subsubsection{H8/500}
+
+Im Maximum-Modus wird der erweiterte Adre"sraum dieser Prozessorreihe
+durch eine Reihe von Bank-Registern adressiert. Diese tragen die
+Namen DP (Register 0..3, absolute Adressen), EP (Register 4/5) und
+TP (Stack). Den momentanen Wert von DP ben"otigt AS, um zu "uberpr"ufen,
+ob absolute Adressen in der momentan adressierbaren Bank liegen;
+die beiden anderen Register werden nur f"ur indirekte Adressierungen
+benutzt und entziehen sich daher der Kontrolle; ob man ihre Werte
+angibt oder nicht, ist daher Geschmackssache. Wichtig ist dagegen
+wieder das BR-Register, das angibt, auf welchen 256-Byte-Bereich
+mit kurzen Adressen zugegriffen werden kann. Allen Registern ist
+gemeinsam, da"s AS {\em keine} Initialwerte f"ur sie annimmt, da sie nach
+einem Prozessor-Reset undefiniert sind; wer absolut adressieren
+will, mu"s daher auf jeden Fall DR und DP belegen!
+
+
+\subsubsection{MELPS740}
+
+Die Mikrokontroller dieser Reihe kennen f"ur den \tty{JSR}-Befehl eine
+besondere Adressierungsart ,,special page'', mit deren Hilfe man Spr"unge
+in die oberste Seite des internen ROMs k"urzer kodieren kann. Diese
+ist nat"urlich vom jeweiligen Chip abh"angig, und es gibt mehr Chips,
+als es mit dem \tty{CPU}-Befehl sinnvoll w"are, zu kodieren...also mu"s
+\tty{ASSUME} herhalten, um die Lage dieser Seite vorzugeben, z.B.
+\begin{verbatim}
+ ASSUME SP:$1f ,
+\end{verbatim}
+falls das interne ROM 8K gro"s ist.
+
+
+\subsubsection{MELPS7700/65816}
+
+Diese Prozessoren beinhalten eine Reihe von Registern, deren Inhalt AS
+kennen mu"s, um den korrekten Code zu erzeugen. Es handelt sich um folgende
+Register:
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+Name & Bedeutung & Wertebereich & Default\\
+\hline
+\hline
+DT & Datenbank & 0-\$ff & 0 \\
+PG & Code-Bank & 0-\$ff & 0 \\
+DPR & direkt adr. Seite & 0-\$ffff & 0 \\
+X & Indexregisterbreite & 0 oder 1 & 0 \\
+M & Akkumulatorbreite & 0 oder 1 & 0 \\
+\hline
+\end{tabular}\end{center}
+\par
+Um mich nicht in endlose Wiederholungen zu ergehen, verweise ich f"ur die
+Benutzung dieser Werte auf Kapitel \ref{MELPS7700Spec}. Die Handhabung
+erfolgt ansonsten genauso wie beim 8086, d.h. es k"onnen auch hier mehrere
+Werte auf einmal gesetzt werden und es wird \bb{kein} Code erzeugt, der
+die Register mit den Werten besetzt. Dies bleibt wieder einzig und allein
+dem Programmierer "uberlassen!
+
+
+\subsubsection{MCS-196/296}
+
+Alle Prozessoren der MCS-96-Familie besitzen ab dem 80196 ein Register \tty{WSR},
+mit dessen Hilfe Speicherbereiche aus dem erweiterten internen RAM
+oder dem SFR-Bereich in Bereiche des Registerfiles eingeblendet werden
+und so mit kurzen Adressen angesprochen werden k"onnen. Teilt man AS
+mit Hilfe des \tty{ASSUME}-Befehls mit, welchen Wert das WSR-Register
+hat, so stellt er bei absoluten Adressen automatisch fest, ob sie
+durch das Windowing mit 1-Byte-Adressen erreicht werden k"onnen;
+umgekehrt werden auch f"ur durch das Windowing "uberdeckte Register
+automatisch lange Adressen erzeugt. Der 80296 besitzt ein zus"atzliches,
+zweites Register \tty{WSR1}, um zwei unterschiedliche Speicherbereiche
+gleichzeitig in das Registerfile einblenden zu k"onnen. Sollte
+es m"oglich sein, eine Speicherzelle "uber beide Bereiche zu adressieren,
+so w"ahlt AS immer den Weg "uber \tty{WSR}!
+
+
+\subsubsection{8086}
+
+Der 8086 kann Daten aus allen Segmenten in einem Befehl adressieren,
+ben"otigt jedoch sog. ,,Segment-Pr"afixe'', wenn ein anderes Segmentregister
+als DS verwendet werden soll. Zus"atzlich kann es sein, da"s das
+DS-Register auf ein anderes Segment verstellt ist, um z.B. "uber l"angere
+Strecken nur Daten im Codesegment zu adressieren. Da AS aber keine
+Sinnanalyse des Codes vornimmt, mu"s ihm "uber diesen Befehl mitgeteilt
+werden, auf welche Segmente die Segmentregister momentan zeigen, z.B.
+\begin{verbatim}
+ ASSUME CS:CODE, DS:DATA .
+\end{verbatim}
+Allen vier Segmenten des 8086 (SS,DS,CS,ES) k"onnen auf diese Weise Annahmen
+zugewiesen werden. Dieser Befehl erzeugt jedoch \bb{keinen} Code, um
+die Werte auch wirklich in die Segmentregister zu laden, dies mu"s vom
+Programm getan werden.
+\par
+Die Benutzung diese Befehls hat zum einen die Folge, da"s AS bei
+sporadischen Zugriffen ins Codesegment automatisch Pr"afixe voranstellen
+kann, andererseits da"s man AS mitteilen kann, da"s das DS-Register verstellt
+wurde und man sich im folgenden explizite \tty{CS:}-Anweisungen sparen
+kann.
+\par
+G"ultige Argumente hinter dem Doppelpunkt sind \tty{CODE, DATA} und
+\tty{NOTHING}. Letzterer Wert dient dazu, AS mitzuteilen, da"s das
+Segmentregister keinen f"ur AS verwendbaren Wert enth"alt.
+Vorinitialisiert sind folgende \tty{ASSUME}s :
+\begin{verbatim}
+ CS:CODE, DS:DATA, ES:NOTHING, SS:NOTHING
+\end{verbatim}
+
+
+\subsubsection{XA}
+
+Die XA-Familie besitzt einen Datenadre"sraum von 16 Mbyte, ein Proze"s
+kann jedoch nur immer innerhalb einer 64K-Seite adressieren, die
+durch das DS-Register vorgegeben wird. AS mu"s man den momentanen
+Wert dieses Registers vorgeben, damit er Zugriffe auf absolute
+Adressen "uberpr"ufen kann.
+
+
+\subsubsection{29K}
+
+Die Prozessoren der 29K-Familie besitzen ein Register \tty{RBP}, mit dessen
+Hilfe B"anke von 16 Registern vor der Benutzung im User-Modus gesch"utzt
+werden k"onnen. Dazu kann man ein entsprechendes Bit in diesem Register
+setzen. Mit \tty{ASSUME} kann man AS nun mitteilen, welchen Wert RBP
+gerade hat. Auf diese Weise kann AS warnen, falls versucht wird, im
+User-Modus auf gesch"utzte Register zuzugreifen.
+
+
+\subsubsection{80C166/167}
+
+Obwohl keines der Register im 80C166/167 breiter als 16 Bit ist, besitzt
+dieser Prozessor 18/24 Adre"sleitungen, kann also bis zu 256 Kbyte/16 Mbyte
+adressieren. Um diesen Widerspruch unter einen Hut zu bekommen, verwendet
+er nicht die von Intel her bekannte (...und ber"uchtigte) Segmentierung oder
+hat unflexible Bankregister...nein, er macht Paging! Dazu wird der ,,logische''
+Adre"sraum von 64 Kbyte in 4 Seiten zu 16 Kbyte eingeteilt, und f"ur jede
+Seite existiert ein Seitenregister (bezeichnet als \tty{DPP0...DPP3}), das
+bestimmt, welche der physikalischen 16/1024 Seiten dort eingeblendet wird. AS versucht
+nun, den Adre"sraum grunds"atzlich mit 256 Kbyte/16 Mbyte aus der Sicht des
+Programmierers zu verwalten, d.h. bei absoluten Zugriffen ermittelt AS die
+physikalische Seite und schaut in der mit \tty{ASSUME} eingestellten
+Seitenverteilung nach, wie die Bits 14 und 15 der logischen Adresse gesetzt
+werden m"ussen. Pa"st kein Seitenregister, so wird eine Warnung ausgegeben.
+Defaultm"a"sig nimmt AS an, da"s die vier Register linear die ersten 64 Kbyte
+abbilden, etwa in der folgenden Form:
+\begin{verbatim}
+ ASSUME DPP0:0,DPP1:1,DPP2:2,DPP3:3
+\end{verbatim}
+Der 80C167 kennt noch einige Befehle, die die Seitenregister in ihrer
+Funktion "ubersteuern k"onnen. Wie diese Befehle die Adre"sgenerierung
+beeinflussen, ist im Kapitel mit den prozessorspezifischen Hinweisen
+beschrieben.
+
+
+\subsubsection{TLCS-47}
+
+Der von der Architektur her vorgegebene Datenadre"sraum dieser
+Prozessoren (egal ob man direkt oder "uber das HL-Register adressiert)
+betr"agt lediglich 256 Nibbles. Da die ,,besseren'' Familienmitglieder
+aber bis zu 1024 Nibbles RAM on chip haben, war Toshiba gezwungen, einen
+Bankingmechanismus "uber das DMB-Register einzuf"uhren. AS verwaltet
+das Datensegment als einen durchgehenden Adre"sraum und pr"uft bei jeder
+direkten Adressierung, ob die Adresse in der momentan aktiven Bank
+liegt. Die von AS momentan angenommene Bank kann mittels
+\begin{verbatim}
+ ASSUME DMB:<0..3>
+\end{verbatim}
+festgelegt werden. Der Default ist 0.
+
+
+\subsubsection{ST6}
+\label{ST6Assume}
+
+Die Mikrokontroller der ST62-Reihe sind in der Lage, einen Teil (64 Byte)
+des Codebereiches in den Datenbereich einzublenden, z.B. um Konstanten aus
+dem ROM zu laden. Dies bedeutet aber auch, da"s zu einem Zeitpunkt immer
+nur ein Teil des ROMs adressiert werden kann. Welcher Teil dies ist, wird
+durch ein bestimmtes Register bestimmt. Dem Inhalt dieses Registers kann
+AS zwar nicht direkt kontrollieren, man kann ihm aber mit diesem Befehl
+mitteilen, wenn man dem Register einen neuen Wert zugewiesen hat. AS kann
+dann pr"ufen und ggfs. warnen, falls auf Adressen im Codesegment
+zugegriffen wird, die nicht im ,,angek"undigten'' Fenster liegt.
+Hat die Variable \tty{VARI} z.B. den Wert 456h, so setzt
+\begin{verbatim}
+ ASSUME ROMBASE:VARI>>6
+\end{verbatim}
+die AS-interne Variable auf 11h, und ein Zugriff auf \tty{VARI} erzeugt einen
+Zugriff auf die Adresse 56h im Datensegment.
+
+Anstelle eines Symbols kann auch schlicht \tty{NOTHING} angegeben
+werden, z.B. wenn das Bank-Register tempor"ar als Speicherzelle benutzt
+wird. Dieser Wert ist auch die Voreinstellung.
+
+
+\subsubsection{ST9}
+
+Die ST9-Familie verwendet zur Adressierung von Code- und Datenbereich
+exakt die gleichen Befehle. Welcher Adre"sraum dabei jeweils
+angesprochen wird, h"angt vom Stand des DP-Flags im Flag-Register ab.
+Damit AS bei absoluten Zugriffen "uberpr"ufen kann, ob man mit Symbolen
+aus dem korrekten Adre"sraum arbeitet (das funktioniert nat"urlich {\em nur}
+bei absoluten Zugriffen!), mu"s man ihm per \tty{ASSUME} mitteilen, ob das
+DP-Flag momentan auf 0 (Code) oder 1 (Daten) steht. Der Initialwert
+dieser Annahme ist 0.
+
+
+\subsubsection{$\mu$PD78(C)10}
+
+Diese Prozessoren besitzen ein Register (V), mit dessen Hilfe die
+,,Zeropage'', d.h. die Lage der mit nur einem Byte adressierbaren
+Speicherzellen sich in Seitengrenzen im Speicher frei verschieben l"a"st.
+Da man aber aus Bequemlichkeitsgr"unden nicht mit Ausdr"ucken wie
+\begin{verbatim}
+ inrw Lo(Zaehler)
+\end{verbatim}
+arbeiten will, "ubernimmt AS diese Arbeit, allerdings nur unter der
+Voraussetzung, da"s man ihm "uber einen \tty{ASSUME}-Befehl den
+Inhalt des V-Registers mitteilt. Wird ein Befehl mit Kurzadressierung
+benutzt, so wird "uberpr"uft, ob die obere H"alfte des Adre"sausdrucks
+mit dem angenommenen Inhalt "ubereinstimmt. Stimmt sie nicht, so erfolgt
+eine Warnung.
+
+
+\subsubsection{320C3x}
+
+Da alle Instruktionsworte dieser Prozessorfamilie nur 32 Bit lang
+sind, und von diesen 32 Bit nur 16 Bit f"ur absolute Adressen vorgesehen
+wurden, m"ussen die fehlenden oberen 8 Bit aus dem DP-Register
+erg"anzt werden. Bei Adressierungen kann man aber trotzdem die volle
+24-Bit-Adresse angeben, AS pr"uft dann, ob die oberen 8 Bit mit dem
+angenommenen Inhalt von DP "ubereinstimmen. Gegen"uber dem \tty{LDP}-Befehl
+weicht \tty{ASSUME} darin ab, da"s man hier nicht eine beliebige Adresse
+aus der Speicherbank angeben kann, das Herausziehen der oberen Bits
+mu"s man also ,,zu Fu"s'' machen, z.B. so:
+\begin{verbatim}
+ ldp @adr
+ assume dp:adr>>16
+ .
+ .
+ .
+ ldi @adr,r2
+\end{verbatim}
+
+
+\subsubsection{75K0}
+
+Da selbst mit Hilfe von Doppelregistern (8 Bit) nicht der komplette
+Adre"sraum von 12 Bit zu erreichen ist, mu"ste NEC (wie andere auch...)
+auf Banking zur"uckgreifen: Die oberen 4 Adre"sbits werden aus dem
+\tty{MBS}-Register geholt (welchem demzufolge mit \tty{ASSUME} Werte
+zwischen 0 und 15 zugeordnet werden k"onnen), das aber nur beachtet
+wird, falls das \tty{MBE}-Flag auf 1 gesetzt wurde. Steht es (wie
+die Vorgabe ist) auf 0, so kann man die obersten und untersten 128
+Nibbles des Adre"sraumes ohne Bankumschaltung erreichen. Da der 75402
+weder \tty{MBE}-Flag noch \tty{MBS}-Register kennt, ist f"ur ihn der
+\tty{ASSUME}-Befehl nicht definiert; Die Initialwerte von \tty{MBE} und
+\tty{MBS} lassen sich daher nicht "andern.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{EMULATED}
+\ttindex{EMULATED}
+
+{\em G"ultigkeit: 29K}
+
+AMD hat die Ausnahmebehandlung f"ur undefinierte Befehle bei der
+29000-Serie so definiert, da"s f"ur jeden einzelnen Befehl ein
+Exceptionvektor zur Verf"ugung steht. Dies legt es nahe, durch
+gezielte Software-Emulationen den Befehlssatz eines kleineren
+Mitgliedes dieser Familie zu erweitern. Damit nun aber AS diese
+zus"atzlichen Befehle nicht als Fehler anmeckert, erlaubt es der
+\tty{EMULATED}-Befehl, AS mitzuteilen, da"s bestimmte Befehle doch
+erlaubt sind. Die Pr"ufung, ob der momentan gesetzte Prozessor
+diesen Befehl beherrscht, wird dann "ubergangen. Hat man z.B. f"ur
+einen Prozessor ohne Gleitkommaeinheit ein Modul geschrieben, das
+aber nur mit 32-Bit-IEEE-Zahlen umgehen kann, so schreibt man
+\begin{verbatim}
+ EMULATED FADD,FSUB,FMUL,FDIV
+ EMULATED FEQ,FGE,FGT,SQRT,CLASS
+\end{verbatim}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BRANCHEXT}
+\ttindex{BRANCHEXT}
+
+{\em G"ultigkeit: XA}
+
+{\tt BRANCHEXT} mit \tty{ON} oder \tty{OFF} als Argument legt fest, ob AS
+kurze, nur mit einem 8-Bit-Displacement verf"ugbare Spr"unge automatisch
+,,verl"angern'' soll, indem z.B. aus einem einfachen
+\begin{verbatim}
+ bne target
+\end{verbatim}
+automatisch eine l"angere Sequenz mit gleicher Funktion wird, falls das
+Sprungziel zu weit von momentanen Programmz"ahler entfernt ist. F"ur
+{\tt bne} w"are dies z.B. die Sequenz
+\begin{verbatim}
+ beq skip
+ jmp target
+skip:
+\end{verbatim}
+Falls f"ur eine Anweisung aber kein passendes ,,Gegenteil'' existiert,
+kann die Sequenz auch l"anger werden, z.B. f"ur {\tt jbc}:
+\begin{verbatim}
+ jbc dobr
+ bra skip
+dobr: jmp target
+skip:
+\end{verbatim}
+Durch dieses Feature gibt es bei Spr"ungen keine eineindeutige Zuordnung
+von Maschinen- und Assemblercode mehr, und bei Vorw"artsreferenzen handelt
+man sich m"oglicherweise zus"atzliche Passes ein. Man sollte dieses
+Feature daher mit Vorsicht einsetzen!
+
+%%---------------------------------------------------------------------------
+
+\section{Datendefinitionen}
+
+Die hier beschriebenen Befehle "uberschneiden sich teilweise in ihrer
+Funktionalit"at, jedoch definiert jede Prozessorfamilie andere Namen
+f"ur die gleiche Funktion. Um mit den Standardassemblern konform zu
+bleiben, wurde diese Form der Implementierung gew"ahlt.
+
+Sofern nicht ausdr"ucklich anders erw"ahnt, kann bei allen Befehlen zur
+Datenablage (nicht bei denen zur Speicherreservierung!) eine beliebige Zahl
+von Parametern angegeben werden, die der Reihe nach abgearbeitet werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DC[.size]}
+\ttindex{DC}
+
+{\em G"ultigkeit: 680x0, M*Core, 68xx, H8, SH7000, DSP56xxx, XA, ST7}
+
+Dieser Befehl legt eine oder mehrere Konstanten des beim durch
+das Attribut bestimmten Typs im Speicher ab. Die Attribute entsprechen
+den in Abschnitt \ref{AttrTypes} definierten, zus"atzlich ist f"ur
+Byte-Konstanten die M"oglichkeit vorhanden, Stringausdr"ucke im Speicher
+abzulegen, wie z.B.
+\begin{verbatim}
+String dc.b "Hello world!\0"
+\end{verbatim}
+Die Parameterzahl darf zwischen 1 und 20 liegen, zus"atzlich darf jedem
+Parameter ein in eckigen Klammern eingeschlossener Wiederholungsfaktor
+vorausgehen, z.B. kann man mit
+\begin{verbatim}
+ dc.b [(*+255)&$ffffff00-*]0
+\end{verbatim}
+den Bereich bis zur n"achsten Seitengrenze mit Nullen f"ullen.
+\bb{Vorsicht!}
+Mit dieser Funktion kann man sehr leicht die Grenze von 1 Kbyte erzeugten
+Codes pro Zeile Quellcode "uberschreiten!
+\par
+Sollte die Byte-Summe ungerade sein, so kann vom Assembler automatisch
+ein weiteres Byte angef"ugt werden, um die Wortausrichtung von Daten zu
+erhalten. Dieses Verhalten kann mit dem \tty{PADDING}-Befehl ein-
+und ausgeschaltet werden.
+\par
+Mit diesem Befehl abgelegte Dezimalgleitkommazahlen (\tty{DC.P} ...) k"onnen
+zwar den ganzen Bereich der extended precision "uberstreichen, zu beachten
+ist dabei allerdings, da"s die von Motorola verf"ugbaren Koprozessoren
+68881/68882 beim Einlesen solcher Konstanten die Tausenderstelle des
+Exponenten ignorieren!
+\par
+Default-Attribut ist \tty{W}, also 16-Bit-Integerzahlen.
+\par
+Beim DSP56xxx ist der Datentyp auf Integerzahlen festgelegt (ein
+Attribut ist deshalb weder n"otig noch erlaubt), die im Bereich
+-8M..16M-1 liegen d"urfen. Stringkonstanten sind ebenfalls erlaubt,
+wobei jeweils drei Zeichen in ein Wort gepackt werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DS[.size]}
+\ttindex{DS}
+
+{\em G"ultigkeit: 680x0, M*Core, 68xx, H8, SH7x00, DSP56xxx, XA, ST7}
+
+Mit diesem Befehl l"a"st sich zum einen Speicherplatz f"ur die angegebene
+Zahl im Attribut beschriebener Zahlen reservieren. So reserviert
+\begin{verbatim}
+ DS.B 20
+\end{verbatim}
+z.B. 20 Bytes Speicher,
+\begin{verbatim}
+ DS.X 20
+\end{verbatim}
+aber 240 Byte !
+\par
+Die andere Bedeutung ist die Ausrichtung des Programmz"ahlers, die
+mit der Wertangabe 0 erreicht wird. So wird mit
+\begin{verbatim}
+ DS.W 0
+\end{verbatim}
+der Programmz"ahler auf die n"achste gerade Adresse aufgerundet, mit
+\begin{verbatim}
+ DS.D 0
+\end{verbatim}
+dagegen auf die n"achste Langwortgrenze. Eventuell dabei freibleibende
+Speicherzellen sind nicht etwa mit Nullen oder NOPs gef"ullt,
+sondern undefiniert.
+\par
+Vorgabe f"ur die Operandengr"o"se ist --- wie "ublich --- W, also 16 Bit.
+\par
+Beim 56xxx ist die Operandengr"o"se auf Worte (a 24 Bit) festgelegt,
+Attribute gibt es deswegen wie bei \tty{DC} auch hier nicht.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DB,DW,DD,DQ \& DT}
+\ttindex{DB}\ttindex{DW}\ttindex{DD}\ttindex{DQ}\ttindex{DT}
+
+{\em\begin{tabbing}
+G"ultigkeit: \= Intel, Zilog, Toshiba, NEC, TMS370, Siemens, AMD, M16(C),\\
+ \> MELPS7700/65816, National, ST9, TMS7000, $\mu$PD77230, \\
+ \> Fairchild
+\end{tabbing}}
+
+Diese Befehle stellen sozusagen das Intel-Gegenst"uck zu \tty{DS}
+und \tty{DC} dar, und wie nicht anders zu erwarten, ist die Logik
+etwas anders:
+\par
+Zum einen wird die Kennung der Operandengr"o"se in das Mnemonic
+verlegt:
+\begin{itemize}
+\item{\tty{DB}: Byte oder ASCII-String wie bei \tty{DC.B}}
+\item{\tty{DW}: 16-Bit-Integer}
+\item{\tty{DD}: 32-Bit-Integer oder single precision}
+\item{\tty{DQ}: double precision (64 Bit)}
+\item{\tty{DT}: extended precision (80 Bit)}
+\end{itemize}
+Zum anderen erfolgt die Unterscheidung, ob Konstantendefinition oder
+Speicherreservierung, im Operanden. Eine Reservierung von Speicher
+wird durch ein \tty{?} gekennzeichnet:
+\begin{verbatim}
+ db ? ; reserviert ein Byte
+ dw ?,? ; reserviert Speicher fuer 2 Worte (=4 Byte)
+ dd -1 ; legt die Konstante -1 (FFFFFFFFH) ab !
+\end{verbatim}
+Speicherreservierung und Konstantendefinition d"urfen \bb{nicht in einer
+Anweisung} gemischt werden:
+\begin{verbatim}
+ db "Hallo",? ; -->Fehlermeldung
+\end{verbatim}
+\ttindex{DUP}
+Zus"atzlich ist noch der \tty{DUP}-Operator erlaubt, der die mehrfache Ablage
+von Konstantenfolgen oder die Reservierung ganzer Speicherbl"ocke erlaubt:
+\begin{verbatim}
+ db 3 dup (1,2) ; --> 1 2 1 2 1 2
+ dw 20 dup (?) ; reserviert 40 Byte Speicher.
+\end{verbatim}
+Wie man sehen kann, mu"s das \tty{DUP}-Argument geklammert werden, darf daf"ur
+aber auch wieder aus mehreren Teilen bestehen, die selber auch wieder
+\tty{DUP}s sein k"onnen...das ganze funktioniert also rekursiv.
+\par
+\tty{DUP} ist aber auch eine Stelle, an der man mit einer anderen Grenze des
+Assemblers in Ber"uhrung kommen kann: maximal k"onnen 1024 Byte Code
+oder Daten in einer Zeile erzeugt werden. Dies bezieht sich \bb{nicht}
+auf die Reservierung von Speicher, nur auf die Definition von
+Konstantenfeldern!
+\par
+\ttindex{DEFB}\ttindex{DEFW}
+Um mit dem M80 vertr"aglich zu sein, darf im Z80-Modus anstelle von
+\tty{DB}/\tty{DW} auch \tty{DEFB}/\tty{DEFW} geschrieben werden.
+\par
+\ttindex{BYTE}\ttindex{WORD}\ttindex{ADDR}\ttindex{ADDRW}
+Analog stellen \tty{BYTE/ADDR} bzw. \tty{WORD/ADDRW} beim COP8 einen
+Alias f"ur \tty{DB} bzw. \tty{DW} dar, wobei die beiden Paare sich
+jedoch in der Byte-Order unterscheiden: Die Befehle, die von National
+zur Adre"sablage vorgesehen waren, benutzen Big-Endian, \tty{BYTE} bzw.
+\tty{WORD} jedoch Little-Endian.
+
+Der NEC 77230 nimmt mit seiner \tty{DW}-Anweisung eine Sonderstellung ein:
+Sie funktioniert eher wie \tty{DATA} bei seinen kleineren Br"udern,
+akzeptiert aber neben String- und Integerargumenten auch Gleitkommawerte
+(und legt sie prozessorspezifischen 32-Bit-Format ab). \tty{DUP} gibt es {\em
+nicht}!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DS, DS8}
+\ttindex{DS}
+\ttindex{DS8}
+
+{\em\begin{tabbing}
+G"ultigkeit: \= Intel, Zilog, Toshiba, NEC, TMS370, Siemens, AMD, M16(C),\\
+ \> National, ST9, TMS7000
+\end{tabbing}}
+
+Dieser Befehl stellt eine Kurzschreibweise dar, um Speicherbereiche
+zu reservieren:
+\begin{quote}{\tt
+ DS $<Anzahl>$
+}\end{quote}
+ist eine Kurzschreibweise f"ur
+\begin{quote}{\tt
+ DB $<Anzahl>$ DUP (?)
+}\end{quote}
+dar, lie"se sich also prinzipiell auch einfach "uber ein Makro realisieren,
+nur scheint dieser Befehl in den K"opfen einiger mit Motorola-CPUs gro"s
+gewordener Leute (gell, Michael?) so fest verdrahtet zu sein, da"s sie
+ihn als eingebauten Befehl erwarten...hoffentlich sind selbige jetzt
+zufrieden {\tt ;-)}
+
+{\tt DS8} ist beim National SC14xxx als Alias f"ur {\tt DS} definiert.
+Achten Sie aber darauf, da"s der Speicher dieser Prozessoren in Worten zu
+16 Bit organisiert ist, d.h. es ist unm"oglich, einzelne Bytes zu
+reservieren. Falls das Argument von {\tt DS} ungerade ist, wird es auf
+die n"achstgr"o"sere gerade Zahl aufgerundet.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BYT oder FCB}
+\ttindex{BYT}\ttindex{FCB}
+
+{\em G"ultigkeit: 6502, 68xx}
+
+Mit diesem Befehl werden im 65xx/68xx-Modus Byte-Konstanten oder
+ASCII-Strings abgelegt, er entspricht also \tty{DC.B} beim 68000 oder
+\tty{DB} bei Intel. Ein Wiederholungsfaktor darf analog zu \tty{DC}
+jedem einzelnen Parameter in eckigen Klammern vorangestellt werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BYTE}
+\ttindex{BYTE}
+
+{\em G"ultigkeit: ST6, 320C2(0)x, 320C5x, MSP, TMS9900}
+
+Dito. Ein im 320C2(0)x/5x-Modus vor dem Befehl stehendes Label wird
+als untypisiert gespeichert, d.h. keinem Adre"sraum zugeordnet.
+Der Sinn dieses Verhaltens wird bei den prozessorspezifischen
+Hinweisen erl"autert.
+
+Ob beim MSP bzw. TMS9900 ungerade Mengen von Bytes automatisch um
+ein Null-Byte erg"anzt werden sollen, kann mit dem PADDING-Befehl
+eingestellt werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DC8}
+\ttindex{DC8}
+
+{\em G"ultigkeit: SC144xx}
+
+Dieser Befehl ist ein Alias f"ur {\tt DB}, d.h. mit ihm k"onnen
+Byte-Konstanten oder Strings im Speicher abgelegt werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ADR oder FDB}
+\ttindex{ADR}\ttindex{FDB}
+
+{\em G"ultigkeit: 6502, 68xx}
+
+Mit diesem Befehl werden im 65xx/68xx-Modus Wortkonstanten
+abgelegt, er entspricht also \tty{DC.W} beim 68000 oder \tty{DW}
+bei Intel. Ein Wiederholungsfaktor darf analog zu \tty{DC} jedem
+einzelnen Parameter in eckigen Klammern vorangestellt werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{WORD}
+\ttindex{WORD}
+
+{\em G"ultigkeit: ST6, i960, 320C2(0)x, 320C3x, 320C5x, MSP}
+
+F"ur den 320C3x und i960 werden hiermit 32-Bit-Worte abgelegt, f"ur die
+alle anderen Familien 16-Bit-Worte. Ein im 320C2(0)x/5x-Modus vor dem Befehl
+stehendes Label wird als untypisiert gespeichert, d.h. keinem Adre"sraum
+zugeordnet. Der Sinn dieses Verhaltens wird bei den prozessorspezifischen
+Hinweisen erl"autert.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DW16}
+\ttindex{DW16}
+
+{\em G"ultigkeit: SC144xx}
+
+Diser Befehl ist beim SC144xx der Weg, Konstanten mit Wortl"ange (16 Bit)
+im Speicher abzulegen und damit ein ALIAS f"ur DW.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LONG}
+\ttindex{LONG}
+
+{\em G"ultigkeit: 320C2(0)x, 320C5x}
+
+Hiermit werden 32-Bit-Integer im Speicher abgelegt, und zwar in
+der Reihenfolge LoWord-HiWord. Ein eventuell vor dem Befehl
+stehendes Label wird dabei wieder als untypisiert abgelegt
+(der Sinn dieser Ma"snahme ist in den prozessorspezifischen
+Hinweisen erl"autert).
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SINGLE und EXTENDED}
+\ttindex{SINGLE}\ttindex{EXTENDED}
+
+{\em G"ultigkeit: 320C3x}
+
+Mit diesen Befehlen werden Gleitkomma-Konstanten im Speicher abgelegt,
+jedoch nicht im IEEE-Format, sondern in den vom Prozessor verwendeten
+32- und 40-Bit-Formaten. Da 40 Bit nicht mehr in eine Speicherzelle
+hineinpassen, werden im Falle von \tty{EXTENDED} immer derer 2 pro Wert
+belegt. Im ersten Wort finden sich die oberen 8 Bit (der Exponent), der
+Rest (Vorzeichen und Mantisse) in zweiten Wort.
+
+
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FLOAT und DOUBLE}
+\ttindex{FLOAT}\ttindex{DOUBLE}
+
+{\em G"ultigkeit: 320C2(0)x, 320C5x}
+
+Mit diesen Befehlen k"onnen 32- bzw. 64-Bit-Gleitkommazahlen
+im IEEE-Format im Speicher abgelegt werden. Dabei wird das
+niederwertigste Byte jeweils auf der ersten Speicherstelle
+abgelegt. Ein eventuell vor dem Befehl stehendes Label wird
+wieder als untypisiert gespeichert (der Sinn dieser Ma"snahme
+ist in den prozessorspezifischen Hinweisen erl"autert).
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{EFLOAT, BFLOAT, TFLOAT}
+\ttindex{EFLOAT}\ttindex{BFLOAT}\ttindex{TFLOAT}
+
+{\em G"ultigkeit: 320C2(0)x, 320C5x}
+
+Auch diese Befehle legen Gleitkommazahlen im Speicher ab,
+jedoch in einem nicht-IEEE-Format, das evtl. leichter von
+Signalprozessoren zu verarbeiten ist:
+\begin{itemize}
+\item{\tty{EFLOAT}: Mantisse mit 16 Bit, Exponent mit 16 Bit}
+\item{\tty{BFLOAT}: Mantisse mit 32 Bit, Exponent mit 16 Bit}
+\item{\tty{DFLOAT}: Mantisse mit 64 Bit, Exponent mit 32 Bit}
+\end{itemize}
+Gemeinsam ist den Befehlen, da"s die Mantisse vor dem
+Exponenten abgelegt wird (Lo-Word jeweils zuerst) und
+beide im Zweierkomplement dargestellt werden. Ein eventuell
+vor dem Befehl stehendes Label wird wieder als untypisiert
+gespeichert (der Sinn dieser Ma"snahme ist in den
+prozessorspezifischen Hinweisen erl"autert).
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{Qxx und LQxx}
+\ttindex{Qxx}\ttindex{LQxx}
+
+{\em G"ultigkeit: 320C2(0)x, 320C5x}
+
+Mit diesen Befehlen k"onnen Gleitkommazahlen in einem Festkommaformat
+abgelegt werden. \tty{xx} ist dabei eine zweistellige Zahl, mit deren
+Zweierpotenz der Gleitkommawert vor der Umwandlung in eine ganze Zahl
+multipliziert werden soll. Er bestimmt also praktisch, wieviele Bits
+f"ur die Nachkommastellen reserviert werden sollen. W"ahrend aber
+\tty{Qxx} nur ein Wort (16 Bit) ablegt, wird das Ergebnis bei \tty{LQxx}
+in 2 Worten (LoWord zuerst) abgelegt. Das sieht dann z.B. so
+aus:
+\begin{verbatim}
+ q05 2.5 ; --> 0050h
+ lq20 ConstPI ; --> 43F7h 0032h
+\end{verbatim}
+Mich m"oge niemand steinigen, wenn ich mich auf meinem HP28
+verrechnet haben sollte...
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DATA}
+\ttindex{DATA}
+
+{\em G"ultigkeit: PIC, 320xx, AVR, MELPS-4500, 4004, $\mu$PD772x}
+
+Mit diesem Befehl werden Daten im aktuellen Segment abgelegt, wobei sowohl
+Integer- als auch Stringwerte zul"assig sind. Bei Strings belegt beim
+16C5x/16C8x, 17C4x im Datensegment und 4500er ein Zeichen ein Wort, bei
+AVR, 17C4x im Codesegment, $\mu$PD772x in den Datensegmenten und
+3201x/3202x passen zwei Zeichen in ein Wort (LSB zuerst), beim $\mu$PD7725
+drei und beim 320C3x sogar derer 4 (MSB zuerst). Im Gegensatz dazu mu"s
+im Datensegment des 4500ers ein Zeichen auf zwei Speicherstellen verteilt
+werden, ebenso wie beim 4004. Der Wertebereich f"ur Integers entspricht
+der Wortbreite des jeweiligen Prozessors im jeweiligen Segment. Das
+bedeutet, da"s \tty{DATA} beim 320C3x die Funktion von \tty{WORD} mit
+einschlie"st (die von \tty{SINGLE} "ubrigens auch, wenn AS das Argument
+als Gleitkommazahl erkennt).
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ZERO}
+\ttindex{ZERO}
+
+{\em G"ultigkeit: PIC}
+
+Dieser Befehl legt einen durch den Parameter spezifizierte
+Zahl von Nullworten (=NOPs) im Speicher ab. Es k"onnen maximal
+512 Nullen mit einem Befehl abgelegt werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FB und FW}
+\ttindex{FB}\ttindex{FW}
+
+{\em G"ultigkeit: COP8}
+
+Mit diesen Befehlen kann ein gr"o"serer Block von Speicher (dessen L"ange
+in Bytes bzw. Worten der erste Parameter angibt) mit einer Byte- bzw.
+Wortkonstanten gef"ullt werden, die durch den zweiten Parameter angegeben
+wird. Die Maximalgr"o"se des Blocks betr"agt 1024 Elemente f"ur
+\tty{FB} bzw. 512 Elemente f"ur \tty{FW}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ASCII und ASCIZ}
+\ttindex{ASCII}\ttindex{ASCIZ}
+
+{\em G"ultigkeit: ST6}
+
+Mit diesen beiden Befehlen k"onnen Stringkonstanten im Speicher
+abgelegt werden. W"ahrend ASCII nur die reinen Daten im Speicher
+ablegt, versieht \tty{ASCIZ} automatisch \ii{jeden} angegebenen String
+mit einem NUL-Zeichen am Ende.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{STRING und RSTRING}
+\ttindex{STRING}\ttindex{RSTRING}
+
+{\em G"ultigkeit: 320C2(0)x, 320C5x}
+
+Diese Anweisungen funktionieren analog zu {\tt DATA}, jedoch werden
+hier Integer-Ausdr"ucke grunds"atzlich als {\it Bytes} mit einem
+entsprechend eingeschr"ankten Wertebereich betrachtet, wodurch es
+m"ogliich wird, die Zahlen zusammen mit anderen Zahlen oder Zeichen
+paarweise in Worte zu verpacken.
+Die beiden Befehle unterscheiden sich lediglich in der Reihenfolge
+der Bytes in einem Wort: Bei {\tt STRING} wird zuerst das
+obere und danach das untere gef"ullt, bei {\tt RSTRING} ist es
+genau umgekehrt.
+
+Ein eventuell vor dem Befehl stehendes Label wird wieder als
+untypisiert gespeichert. Der Sinn dieser Ma"snahme ist im
+entsprechenden Kapitel mit den prozessorspezifischen Befehlen
+erl"autert.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FCC}
+\ttindex{FCC}
+
+{\em G"ultigkeit: 6502, 68xx}
+
+Mit diesem Befehl werden im 65xx/68xx-Modus String-Konstanten abgelegt.
+Beachten Sie jedoch, da"s im Gegensatz zum Originalassembler
+AS11 von Motorola (dessentwegen dieser Befehl existiert, bei AS ist
+diese Funktion im \tty{BYT}-Befehl enthalten), String-Argumente nur in
+G"ansef"u"schen und nicht in Hochkommas oder Schr"agstrichen eingeschlossen
+werden d"urfen! Ein Wiederholungsfaktor darf analog zu \tty{DC} jedem
+einzelnen Parameter in eckigen Klammern vorangestellt werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DFS oder RMB}
+\ttindex{DFS}\ttindex{RMB}
+
+{\em G"ultigkeit: 6502, 68xx}
+
+Dieser Befehl dient im 65xx/68xx-Modus zur Reservierung von
+Speicher, er entspricht \tty{DS.B} beim 68000 oder \tty{DB ?}
+bei Intel.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BLOCK}
+\ttindex{BLOCK}
+
+{\em G"ultigkeit: ST6}
+
+Dito.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SPACE}
+\ttindex{SPACE}
+
+{\em G"ultigkeit: i960}
+
+Dito.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{RES}
+\ttindex{RES}
+
+{\em G"ultigkeit: PIC, MELPS-4500, 3201x, 320C2(0)x, 320C5x, AVR, $\mu$PD772x}
+
+Dieser Befehl dient zur Reservierung von Speicher. Er reserviert
+im Codesegment immer W"orter (10/12/14/16 Bit), im Datensegment bei
+den PICs Bytes, beim 4500er Nibbles sowie bei Texas ebenfalls W"orter.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BSS}
+\ttindex{BSS}
+
+{\em G"ultigkeit: 320C2(0)x, 320C3x, 320C5x, MSP}
+
+\tty{BSS} arbeitet analog zu \tty{RES}, lediglich ein eventuell vor dem
+Befehl stehendes Symbol wird beim 320C2(0)x/5x als untypisiert gespeichert.
+Der Sinn dieser Ma"snahme kann im Kapitel mit den prozessorspezifischen
+Hinweisen nachgelesen werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DSB und DSW}
+\ttindex{DSB}\ttindex{DSW}
+
+{\em G"ultigkeit: COP8}
+
+Diese beiden Befehle stellen im COP8-Modus die zum ASMCOP von National
+kompatible Methode dar, Speicher zu reservieren. W"ahrend \tty{DSB} nur
+einzelne Bytes freih"alt, reserviert \tty{DSW} W"orter und damit effektiv
+doppelt soviel Bytes wie \tty{DSB}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DS16}
+\ttindex{DS16}
+
+{\em G"ultigkeit: SC144xx}
+
+Dieser Befehl reserviert Speicher in Schritten von vollst"andigen Worten,
+d.h. 16 Bit. Er stellt einen Alias zu {\tt DW} dar.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ALIGN}
+\ttindex{ALIGN}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+\tty{ALIGN} mit einem Integerausdruck als Argument erlaubt es, den
+Programmz"ahler auf eine bestimmte Adresse auszurichten. Die
+Ausrichtung erfolgt dergestalt, da"s der Programmz"ahler so weit
+erh"oht wird, da"s er ein ganzzahliges mehrfaches des Argumentes
+wird. In seiner Funktion entspricht \tty{ALIGN} also \tty{DS.x 0}
+beim den 680x0ern, nur ist die Ausrichtung noch flexibler.
+\par
+Beispiel:
+\begin{verbatim}
+ align 2
+\end{verbatim}
+macht den Programmz"ahler gerade. Wie auch bei \tty{DS.x 0} ist der
+freibleibende Speicherraum undefiniert.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LTORG}
+\ttindex{LTORG}
+
+{\em G"ultigkeit: SH7x00}
+
+Da der SH7000-Prozessor seine Register immediate nur mit 8-Bit-Werten
+laden kann, AS dem Programmierer jedoch vorgaukelt, da"s es eine solche
+Einschr"ankung nicht g"abe, mu"s er die dabei entstehenden Konstanten
+irgendwo im Speicher ablegen. Da es nicht sinnvoll w"are, dies einzeln
+zu tun (wobei jedes Mal Sprungbefehle anfallen w"urden...), werden die
+Literale gesammelt und k"onnen vom Programmierer mit diesem Befehl
+gezielt blockweise (z.B. am Ende eines Unterprogrammes) abgelegt werden.
+Zu den zu beachtenden Details und Fallen sei auf das Kapitel mit den
+SH7000-spezifischen Dingen hingewiesen.
+
+%%---------------------------------------------------------------------------
+
+\section{Makrobefehle}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Kommen wir nun zu dem, was einen Makroassembler vom normalen Assembler
+unterscheidet: der M"oglichkeit, Makros zu definieren (ach was ?!).
+\par
+Unter Makros verstehe ich hier erst einmal eine Menge von Anweisungen
+(normal oder Pseudo), die mit bestimmten Befehlen zu einem Block
+zusammengefa"st werden und dann auf bestimmte Weise bearbeitet
+werden k"onnen. Zur Bearbeitung solcher Bl"ocke kennt der Assembler
+folgende Befehle:
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{MACRO}
+\ttindex{MACRO}\ttindex{ENDM}
+
+ist der wohl wichtigste Befehl zur Makroprogrammierung. Mit der
+Befehlsfolge
+\begin{verbatim}
+<Name> MACRO [Parameterliste]
+ <Befehle>
+ ENDM
+\end{verbatim}
+wird das Makro \tty{$<$Name$>$} als die eingeschlossene Befehlsfolge
+definiert. Diese Definition alleine erzeugt noch keinen Code! Daf"ur kann
+fortan die Befehlsfolge einfach durch den Namen abgerufen werden, das Ganze
+stellt also eine Schreiberleichterung dar. Um die ganze Sache etwas
+n"utzlicher zu machen, kann man der Makrodefinition eine Parameterliste
+mitgeben. Die Parameternamen werden wie "ublich durch Kommas getrennt
+und m"ussen --- wie der Makroname selber --- den Konventionen f"ur
+Symbolnamen (\ref{SectSymConv}) gen"ugen.
+\par
+Sowohl Makronamen als auch -parameter sind von einer Umschaltung
+von AS in den case-sensitiven Modus betroffen.
+\par
+Makros sind "ahnlich wie Symbole lokal, d.h. bei Definition in
+einer Sektion sind sie nur in dieser Sektion und ihren Untersektionen
+bekannt. Dieses Verhalten l"a"st sich aber durch die weiter unten
+beschriebenen Optionen \tty{PUBLIC} und \tty{GLOBAL} in weiten Grenzen
+steuern.
+\par
+Neben den eigentlichen Makroparametern k"onnen in der Parameterliste
+auch Steuerparameter enthalten sein, die die Abarbeitung des betroffenen
+Makros beeinflussen; diese Parameter werden von normalen Parametern
+dadurch unterschieden, da"s sie in geschweifte Klammern eingeschlossen
+sind. Es sind folgende Steuerparameter definiert:
+\begin{itemize}
+\item{\tty{EXPAND/NOEXPAND} : legen fest, ob bei der sp"ateren
+ Verwendung diese Makros der expandierte Code mit angezeigt
+ werden soll. Default ist der durch den Pseudobefehl \tty{MACEXP}
+ festgelegte Wert.}
+\item{\tty{PUBLIC[:Sektionsname]} : ordnet das Makro nicht der
+ aktuellen, sondern einer ihr "ubergeordneten Sektion zu.
+ Auf diese Weise kann eine Sektion Makros f"ur die ,,Au"senwelt''
+ zur Verf"ugung stellen. Fehlt eine Sektionsangabe, so wird das
+ Makro v"ollig global, d.h. ist "uberall benutzbar.}
+\item{\tty{GLOBAL[:Sektionsname]} : legt fest, da"s neben diesem
+ Makro noch ein weiteres Makro abgelegt werden soll, das zwar
+ den gleichen Inhalt hat, dessen Name aber zus"atzlich mit dem
+ Namen der Sektion versehen ist, in der es definiert wurde und
+ das der spezifizierten Sektion zugeordnet werden soll. Bei
+ dieser mu"s es sich um eine Obersektion zu der aktuellen Sektion
+ handeln; fehlt die Angabe, so wird das zus"atzliche Makro
+ global sichtbar. Wird z.B. ein Makro \tty{A} in der Sektion \tty{B}
+ definiert, die wiederum eine Untersektion der Sektion \tty{C} ist,
+ so w"urde neben z.B. dem Makro A ein weiteres globales mit dem
+ Namen \tty{C\_B\_A} erzeugt. W"urde dagegen \tty{C} als Zielsektion
+ angegeben, so w"urde das Makro \tty{B\_A} hei"sen und der Sektion
+ \tty{C} zugeordnet. Diese Option ist defaultm"a"sig ausgeschaltet und
+ hat auch nur einen Effekt, falls sie innerhalb einer Sektion
+ benutzt wird. Das lokal bekannte Originalmakro wird von ihr
+ nicht beeinflu"st.}
+\item{\tty{EXPORT/NOEXPORT} : legen fest, ob die Definition dieses
+ Makros in einer getrennten Datei abgelegt werden soll, falls
+ die Kommandozeilenoption \tty{-M} gegeben wurde. Auf diese
+ Weise k"onnen einzelne Definitionen ,,privater'' Makros selektiv
+ ausgeblendet werden. Der Default ist FALSE, d.h. die Definition
+ wird nicht in der Datei abgelegt. Ist zus"atzlich die
+ \tty{GLOBAL}-Option gegeben worden, so wird das Makro mit dem
+ modifizierten Namen abgelegt.}
+\end{itemize}
+Diese eben beschriebenen Steuerparameter werden von AS aus der
+Parameterliste ausgefiltert, haben also keine weitere Wirkung in
+der folgenden Verarbeitung und Benutzung.
+\par
+Beim Aufruf eines Makros werden die beim Aufruf angegebenen
+Parameternamen "uberall textuell im Befehlsblock eingesetzt und der
+sich so ergebene Assemblercode wird normal assembliert. Sollten
+beim Aufruf zu wenige Parameter angegeben werden, werden Nullstrings
+eingef"ugt. Wichtig ist zu wissen, da"s bei der Makroexpansion keine
+R"ucksicht auf eventuell in der Zeile enthaltene Stringkonstanten
+genommen wird. Zu diesem Detail gilt die alte IBM-Regel:
+\begin{quote}
+\ii{It's not a bug, it's a feature!}
+\end {quote}
+Diese L"ucke kann man bewu"st ausnutzen, um Parameter mittels
+Stringvergleichen abzupr"ufen. So kann man auf folgende Weise
+z.B. pr"ufen, wie ein Makroparameter aussieht:
+\begin{verbatim}
+mul MACRO para,parb
+ IF UpString("PARA")<>"A"
+ MOV a,para
+ ENDIF
+ IF UpString("PARB")<>"B"
+ MOV b,parb
+ ENDIF
+ mul ab
+ ENDM
+\end{verbatim}
+Wichtig ist bei obigem Beispiel, da"s der Assembler alle
+Parameternamen im case-sensitiven Modus in Gro"sbuchstaben
+umsetzt, in Strings aber nie eine Umwandlung in Gro"sbuchstaben
+erfolgt. Die Makroparameternamen m"ussen in den Stringkonstanten
+daher gro"s geschrieben werden.
+\par
+F"ur die Makroparameter gelten die gleichen Konventionen wie bei
+normalen Symbolen, mit der Ausnahme, da"s hier nur Buchstaben
+und Ziffern zugelassen sind, also weder Punkte noch
+Unterstriche. Diese Einschr"ankung hat ihren Grund in einem
+verstecktem Feature: Der Unterstrich erlaubt es, einzelne
+Makroparameternamen zu einem Symbol zusammenzuketten, z.B. in
+folgendem Beispiel:
+\begin{verbatim}
+concat MACRO part1,part2
+ CALL part1_part2
+ ENDM
+\end{verbatim}
+Der Aufruf
+\begin{verbatim}
+ concat Modul,Funktion
+\end{verbatim}
+ergibt also
+\begin{verbatim}
+ CALL Modul_Funktion
+\end{verbatim}
+\par
+Um alle Klarheiten auszur"aumen, ein einfaches Beispiel:
+Ein intelverbl"odeter Programmierer m"ochte die Befehle \tty{PUSH/POP}
+unbedingt auch auf dem 68000 haben. Er l"ost das ,,Problem''
+folgenderma"sen:
+\begin{verbatim}
+push MACRO op
+ MOVE op,-(sp)
+ ENDM
+
+pop MACRO op
+ MOVE (sp)+,op
+ ENDM
+\end{verbatim}
+Schreibt man nun im Code
+\begin{verbatim}
+ push d0
+ pop a2 ,
+\end{verbatim}
+so wird daraus
+\begin{verbatim}
+ MOVE d0,-(sp)
+ MOVE (sp)+,a2
+\end{verbatim}
+Eine Makrodefinition darf nicht "uber Includefilegrenzen hinausgehen.
+\par
+In Makror"umpfen definierte Labels werden immer als lokal betrachtet,
+ein expliziter \tty{LOCAL}-Befehl ist also nicht erforderlich (und ist
+auch nicht definiert). Ist es aus irgendwelchen Gr"unden erforderlich,
+so kann man es mit \tty{LABEL} definieren, dessen Anwendung (wie bei
+\tty{BIT,SFR}...) immer globale Symbole ergibt :
+\begin{verbatim}
+<Name> LABEL *
+\end{verbatim}
+Da der Assembler beim Parsing einer Zeile zuerst die Makroliste und
+danach die Prozessorbefehle abklappert, lassen sich auch Prozessorbefehle
+neu definieren. Die Definition sollte dann aber vor der ersten Benutzung
+des Befehles durchgef"uhrt werden, um Phasenfehler wie im folgenden
+Beispiel zu vermeiden:
+\begin{verbatim}
+ BSR ziel
+
+bsr MACRO target
+ JSR ziel
+ ENDM
+
+ BSR ziel
+\end{verbatim}
+Im ersten Pass ist bei der Assemblierung des \tty{BSR}-Befehles das Makro
+noch nicht bekannt, es wird ein 4 Byte langer Befehl erzeugt. Im
+zweiten Pass jedoch steht die Makrodefinition sofort (aus dem ersten
+Pass) zur Verf"ugung, es wird also ein 6 Byte langer \tty{JSR} kodiert.
+Infolgedessen sind alle darauffolgenden Labels um zwei zu niedrig,
+bei allen weiteren Labels sind Phasenfehler die Folge, und ein weiterer
+Pass ist erforderlich.
+\par
+Da durch die Definition eines Makros ein gleichnamiger Maschinen- oder
+Pseudobefehl nicht mehr zugreifbar ist, gibt es eine Hintert"ur, die
+Originalbedeutung zu erreichen: Stellt man dem Mnemonic ein \tty{!} voran,
+so wird das Durchsuchen der Makroliste unterdr"uckt. Das kann
+beispielsweise n"utzlich sein, um Befehle in ihrer M"achtigkeit zu
+erweitern, z.B. die Schiebebefehle beim TLCS-90:
+\begin{verbatim}
+srl macro op,n ; Schieben um n Stellen
+ rept n ; n einfache Befehle
+ !srl op
+ endm
+ endm
+\end{verbatim}
+Fortan hat der \tty{SRL}-Befehl einen weiteren Parameter...
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{IRP}
+\ttindex{IRP}
+
+ist die eine vereinfachte Form von Makrodefinitionen f"ur den Fall,
+da"s eine Befehlsfolge einmal auf mehrere Operanden angewendet werden
+soll und danach nicht mehr gebraucht wird. \tty{IRP} ben"otigt als ersten
+Parameter ein Symbol f"ur den Operanden, und danach eine (fast)
+beliebige Menge von Parametern, die nacheinander in den Befehlsblock
+eingesetzt werden. Um eine Menge von Registern auf den Stack zu
+schieben, kann man z.B. schreiben
+\begin{verbatim}
+ IRP op, acc,b,dpl,dph
+ PUSH op
+ ENDM
+\end{verbatim}
+was in folgendem resultiert:
+\begin{verbatim}
+ PUSH acc
+ PUSH b
+ PUSH dpl
+ PUSH dph
+\end{verbatim}
+Benutzte Labels sind wieder f"ur jeden Durchgang automatisch lokal.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{IRPC}
+\ttindex{IRPC}
+
+\tty{IRPC} ist eine Variante von \tty{IRP}, bei der das erste Argument in
+den bis \tty{ENDM} folgenden Zeilen nicht sukzessiv durch die weiteren
+Parameter, sondern durch die Zeichen eines Strings ersetzt wird. Einen
+String kann man z.B. also auch ganz umst"andlich so im Speicher ablegen:
+\begin{verbatim}
+ irpc char,"Hello World"
+ db 'CHAR'
+ endm
+\end{verbatim}
+\bb{ACHTUNG!} Wie das Beispiel schon zeigt, setzt \tty{IRPC} nur das
+Zeichen selber ein, da"s daraus ein g"ultiger Ausdruck entsteht (also hier
+durch die Hochkommas, inklusive des Details, da"s hier keine automatische
+Umwandlung in Gro"sbuchstaben vorgenommen wird), mu"s man selber
+sicherstellen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{REPT}
+\ttindex{REPT}
+
+ist die einfachste Form der Makrobenutzung. Der im Rumpf angegebene
+Code wird einfach sooft assembliert, wie der Integerparameter von
+\tty{REPT} angibt. Dieser Befehl wird h"aufig in kleinen Schleifen anstelle
+einer programmierten Schleife verwendet, um den Schleifenoverhead zu
+sparen.
+\par
+Der Vollst"andigkeit halber ein Beispiel:
+\begin{verbatim}
+ REPT 3
+ RR a
+ ENDM
+\end{verbatim}
+rotiert den Akku um 3 Stellen nach rechts.
+\par
+Symbole sind wiederum f"ur jede einzelne Repetition lokal.
+
+Ist das Argument von \tty{REPT} kleiner oder gleich Null, so wird
+"uberhaupt keine Expansion durchgef"uhrt. Dies ist ein Unterschied
+zu fr"uheren Versionen von AS, die hier etwas ,,schlampig'' waren
+und immer mindestens eine Expansion ausf"uhrten.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{WHILE}
+\ttindex{WHILE}
+
+\tty{WHILE} arbeitet analog zu \tty{REPT}, allerdings tritt an die
+Stelle einer festen Anzahl als Argument ein boolescher Ausdruck, und
+der zwischen \tty{WHILE} und \tty{ENDM} eingeschlossene Code wird sooft
+assenbliert, bis der Ausdruck logisch falsch wird. Im Extremfall kann
+dies bedeuten, da"s der Code "uberhaupt nicht assembliert wird, falls die
+Bedingung bereits beim Eintritt in das Konstrukt falsch ist. Andererseits
+kann es nat"urlich auch passieren, da"s die Bedingung immer wahr bleibt,
+und AS l"auft bis an das Ende aller Tage...hier sollte man also etwas
+Umsicht walten lassen, d.h. im Rumpf mu"s eine Anweisung stehen, die die
+Bedingung auch beeinflu"st, z.B. so:
+\begin{verbatim}
+cnt set 1
+sq set cnt*cnt
+ while sq<=1000
+ dc.l sq
+cnt set cnt+1
+sq set cnt*cnt
+ endm
+\end{verbatim}
+Dieses Beispiel legt alle Quadratzahlen bis 1000 im Speicher ab.
+\par
+Ein unsch"ones Detail bei \tty{WHILE} ist im Augenblick leider noch,
+da"s am Ende der Expansion eine zus"atzliche Leerzeile, die im Quellrumpf
+nicht vorhanden war, eingef"ugt wird. Dies ist ein ,,Dreckeffekt'',
+der auf einer Schw"ache des Makroprozessors beruht und leider nicht so
+einfach zu beheben ist. Hoffentlich st"ort es nicht allzusehr....
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{EXITM}
+\ttindex{EXITM}
+
+\tty{EXITM} stellt einen Weg dar, um eine Makroexpansion oder einen der
+Befehle \tty{REPT}, \tty{IRP} oder \tty{WHILE} vorzeitig abzubrechen.
+Eine solche M"oglichkeit hilft zum Beispiel, umfangreichere Klammerungen
+mit \tty{IF-ENDIF}-Sequenzen in Makros "ubersichtlicher zu gestalten.
+Sinnvollerweise ist ein \tty{EXITM} aber selber auch immer bedingt, was zu
+einem wichtigen Detail f"uhrt: Der Stack, der "uber momentan offene
+\tty{IF}- oder \tty{SWITCH}-Konstrukte Buch f"uhrt, wird auf den Stand vor
+Beginn der Makroexpansion zur"uckgesetzt. Dies ist f"ur bedingte
+\tty{EXITM}'s zwingend notwendig, da das den \tty{EXITM}-Befehl in
+irgendeiner Form einschlie"sende \tty{ENDIF} oder \tty{ENDCASE} nicht mehr
+erreicht wird und AS ohne einen solchen Trick eine Fehlermeldung erzeugen
+w"urde. Weiterhin ist es f"ur verschachtelte Makrokonstruktionen
+wichtig, zu beachten, da"s \tty{EXITM} immer nur das momentan innerste
+Konstrukt abbricht! Wer aus seiner geschachtelten Konstruktion
+vollst"andig ,,ausbrechen'' will, mu"s auf den h"oheren Ebenen ebenfalls
+\tty{EXITM}'s vorsehen!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FUNCTION}
+\ttindex{FUNCTION}
+\label{SectFUNCTION}
+
+\tty{FUNCTION} ist zwar kein Makrobefehl im engeren Sinne, da
+hierbei aber "ahnliche Mechanismen wie bei Makroersetzungen
+angewendet werden, soll er hier beschrieben werden.
+\par
+Dieser Befehl dient dazu, neue Funktionen zu definieren, die in
+Formel\-ausdr"ucken wie die vordefinierten Funktionen verwendet werden
+k"onnen. Die Definition mu"s in folgender Form erfolgen:
+\begin{verbatim}
+<Name> FUNCTION <Arg>,..,<Arg>,<Ausdruck>
+\end{verbatim}
+Die Argumente sind die Werte, die sozusagen in die Funktion
+,,hineingesteckt'' werden. In der Definition werden f"ur die Argumente
+symbolische Namen gebraucht, damit der Assembler bei der Benutzung
+der Funktion wei"s, an welchen Stellen die aktuellen Werte einzusetzen
+sind. Dies kann man an folgendem Beispiel sehen:
+\begin{verbatim}
+isgit FUNCTION ch,(ch>='0')&&(ch<='9')
+\end{verbatim}
+Diese Funktion "uberpr"uft, ob es sich bei dem Argument (wenn man es
+als Zeichen interpretiert) um eine Ziffer im momentan g"ultigen
+Zeichencode handelt (der momentane Zeichencode ist mittels \tty{CHARSET}
+ver"anderbar, daher die vorsichtige Formulierung).
+\par
+Die Argumentnamen (in diesem Falle \tty{CH}) m"ussen den gleichen h"arteren
+Symbolkonventionen gen"ugen wie Parameter bei einer Makrodefinition,
+d.h. die Sonderzeichen . und \_ sind nicht erlaubt.
+\par
+Selbstdefinierte Funktionen werden genauso benutzt wie eingebaute,
+d.h. mit einer durch Kommas getrennten, geklammerten Argumentliste:
+\begin{verbatim}
+ IF isdigit(Zeichen)
+ message "\{Zeichen} ist eine Ziffer"
+ ELSEIF
+ message "\{Zeichen} ist keine Ziffer"
+ ENDIF
+\end{verbatim}
+\par
+Bei dem Aufruf der Funktion werden die Argumente nur einmal berechnet
+und danach an allen Stellen der Formel eingesetzt, um den
+Rechenaufwand zu reduzieren und Seiteneffekte zu vermeiden.
+Bei Funktionen mit mehreren Argumenten m"ussen die einzelnen Argumente
+bei der Benutzung durch Kommata getrennt werden.
+\par
+\bb{ACHTUNG!} Analog wie bei Makros kann man mit der Definition von
+Funktionen bestehende Funktionen umdefinieren. Damit lassen sich auch
+wieder Phasenfehler provozieren. Solche Definitionen sollten daher auf
+jeden Fall vor der ersten Benutzung erfolgen!
+\par
+Da die Berechnung des Funktionsergebnisses anhand des Formelausdruckes
+auf textueller Ebene erfolgt, kann der Ergebnistyp von dem Typ des
+Eingangsargumentes abh"angen. So kann bei folgender Funktion
+\begin{verbatim}
+double function x,x+x
+\end{verbatim}
+das Ergebnis ein Integer, eine Gleitkommazahl oder sogar ein String
+sein, je nach Typ des Arguments!
+\par
+Bei der Definition und Ansprache von Funktionen wird im case-sensitiven
+Modus zwischen Gro"s- und Kleinschreibung unterschieden, im Gegensatz
+zu eingebauten Funktionen!
+
+%%---------------------------------------------------------------------------
+
+\section{bedingte Assemblierung}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Der Assembler unterst"utzt die bedingte Assemblierung mit Hilfe der
+Konstrukte \tty{IF}... sowie \tty{SWITCH}... . Diese Befehle wirken zur
+Assemblierzeit, indem entsprechend der Bedingung Teile "ubersetzt oder
+"ubersprungen werden. Diese Befehle sind also \ii{nicht} mit den
+IF-Statements h"oherer Programmiersprachen zu vergleichen (obwohl es
+sehr verlockend w"are, den Assembler um die Strukturierungsbefehle
+h"oherer Sprachen zu erweitern...).
+\par
+Die folgenden Konstrukte d"urfen beliebig (bis zum Speicher"uberlauf)
+geschachtelt werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{IF / ELSEIF / ENDIF}
+\ttindex{IF}
+\ttindex{ELSEIF}\ttindex{ELSE}
+\ttindex{ENDIF}
+
+\tty{IF} ist das gebr"auchlichere und allgemeiner verwendbare Konstrukt.
+Die allgemeine Form eines \tty{IF}-Befehles lautet folgenderma"sen:
+\begin{verbatim}
+ IF <Ausdruck 1>
+ <Block 1>
+ ELSEIF <Ausdruck 2>
+ <Block 2>
+ (evtl. weitere ELSEIFs)
+ ELSEIF
+ <Block n>
+ ENDIF
+\end{verbatim}
+\tty{IF} dient als Einleitung und wertet den ersten Ausdruck aus und assembliert
+Block 1, falls der Ausdruck wahr (d.h. ungleich 0) ist. Alle weiteren
+\tty{ELSEIF}-Teile werden dann ignoriert. Falls der Ausdruck aber nicht wahr
+ist, wird Block 1 "ubersprungen und Ausdruck 2 ausgewertet. Sollte dieser
+nun wahr sein, wird Block 2 assembliert. Die Zahl der \tty{ELSEIF}-Teile ist
+variabel und ergibt eine \tty{IF-THEN-ELSE}-Leiter beliebiger L"ange. Der dem
+letzten \tty{ELSEIF} (ohne Parameter) zugeordnete Block wird nur assembliert,
+falls alle vorigen Ausdr"ucke falsch ergaben und bildet sozusagen einen
+,,Default-Zweig''. Wichtig ist, da"s von den Bl"ocken immer nur \ii{einer}
+assembliert wird, und zwar der erste, dessen zugeordnetes \tty{IF/ELSEIF} einen
+wahren Ausdruck hatte.
+\par
+Die \tty{ELSEIF}-Teile sind optional, d.h. auf \tty{IF} darf auch direkt \tty{ENDIF}
+folgen, ein parameterloses \tty{ELSEIF} bildet aber immer den letzten Zweig.
+Ein \tty{ELSEIF} bezieht sich immer auf das letzte, noch nicht abgeschlossene \tty{IF}.
+\par
+Neben \tty{IF} sind noch folgende weitere bedingte Befehle definiert:
+\ttindex{IFDEF}\ttindex{IFNDEF}
+\ttindex{IFUSED}\ttindex{IFNUSED}
+\ttindex{IFEXIST}\ttindex{IFNEXIST}
+\ttindex{IFB}\ttindex{IFNB}
+\begin{itemize}
+\item{\tty{IFDEF} $<$Symbol$>$ : wahr, falls das Symbol definiert wurde.
+ Die Definition mu"s vor \tty{IFDEF} erfolgt sein.}
+\item{\tty{IFNDEF} $<$Symbol$>$ : Umkehrung zu \tty{IFDEF}}
+\item{\tty{IFUSED} $<$Symbol$>$ : wahr, falls das Symbol bisher mindestens einmal
+ benutzt wurde.}
+\item{\tty{IFNUSED} $<$Symbol$>$ : Umkehrung zu \tty{IFUSED}}
+\item{\tty{IFEXIST} $<$Name$>$ : wahr, falls die angegebene Datei existiert.
+ F"ur Schreibweise und Suchpfade gelten gleiche Regeln wie beim
+ \tty{INCLUDE}-Befehl (siehe Abschnitt \ref{SectInclude}).}
+\item{\tty{IFNEXIST} $<$Name$>$ : Umkehrung zu \tty{IFEXIST}}
+\item{\tty{IFB} $<$Arg-Liste$>$ : wahr, falls alle Argumente der Parameterliste leer
+ sind.}
+\item{\tty{IFNB} $<$Arg-Liste$>$ : Umkehrung zu IFB.}
+\end{itemize}
+
+Anstelle von {\tt ELSEIF} darf auch {\tt ELSE} geschrieben werden, weil
+das wohl alle so gewohnt sind....
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SWITCH / CASE / ELSECASE / ENDCASE}
+\ttindex{SWITCH}\ttindex{CASE}\ttindex{ELSECASE}\ttindex{ENDCASE}
+
+\tty{SWITCH} ist ein Spezialfall von \tty{IF} und f"ur den Fall gedacht, da"s ein
+Ausdruck mit einer Reihe von Werten verglichen werden soll. Dies ist
+nat"urlich auch mit \tty{IF} und einer Reihe von \tty{ELSEIF}s machbar, die folgende
+Form
+\begin{verbatim}
+ SWITCH <Ausdruck>
+ ...
+ CASE <Wert 1>
+ ...
+ <Block 1>
+ ...
+ CASE <Wert 2>
+ ...
+ <Block 2>
+ ...
+ (weitere CASE-Konstrukte)
+ ...
+ CASE <Wert n-1>
+ ...
+ <Block n-1>
+ ...
+ ELSECASE
+ ...
+ <Block n>
+ ...
+ ENDCASE
+\end{verbatim}
+bietet aber den Vorteil, da"s der zu pr"ufende Ausdruck nur einmal hingeschrieben
+und berechnet werden mu"s, er ist also weniger fehleranf"allig und etwas
+schneller als eine \tty{IF}-Kette, daf"ur nat"urlich auch nicht so flexibel.
+\par
+Es ist m"oglich, bei den \tty{CASE}-Anweisungen mehrere, durch Kommata getrennte
+Werte anzugeben, um den entsprechenden Block in mehreren F"allen assemblieren
+zu lassen. Der \tty{ELSECASE}-Zweig dient wiederum als ,,Auffangstelle'' f"ur den
+Fall, da"s keine der \tty{CASE}-Bedingungen greift. Fehlt er und fallen alle
+Pr"ufungen negativ aus, so gibt AS eine Warnung aus.
+\par
+Auch wenn die Wertelisten der \tty{CASE}-Teile sich "uberlappen, so wird immer
+nur \ii{ein} Zweig ausgef"uhrt, und zwar bei Mehrdeutigkeiten der erste.
+\par
+\tty{SWITCH} dient nur der Einleitung des ganzen Konstruktes; zwischen ihm und
+dem ersten \tty{CASE} darf beliebiger Code stehen (andere \tty{IF}s d"urfen aber nicht
+offen bleiben!), im Sinne eines durchschaubaren Codes sollte davon aber
+kein Gebrauch gemacht werden.
+
+%%---------------------------------------------------------------------------
+
+\section{Listing-Steuerung}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PAGE}
+\ttindex{PAGE}
+
+Mit \tty{PAGE} kann man AS die Dimensionen des Papiers, auf dem das
+Listing ausgedruckt werden soll, mitteilen. Als erster Parameter
+wird dabei die Anzahl von Zeilen angegeben, nach der AS automatisch
+einen Zeilenvorschub ausgeben soll. Zu ber"ucksichtigen ist allerdings,
+da"s bei dieser Angabe die Kopfzeilen inklusive einer evtl. mit \tty{TITLE}
+spezifizierten Zeile nicht mitgerechnet werden. Der Minimalwert f"ur
+die Zeilenzahl ist 5, der Maximalwert 255. Eine Angabe von 0 f"uhrt dazu,
+da"s AS "uberhaupt keine automatischen Seitenvorsch"ube ausf"uhrt, sondern
+nur noch solche, die explizit durch \tty{NEWPAGE}-Befehle oder implizit am
+Ende des Listings (z.B. vor der Symboltabelle) von AS ausgel"ost
+wurden.
+\par
+Die Angabe der Breite des Listings in Zeichen kann als optionaler
+zweiter Parameter erfolgen und erf"ullt zwei Zwecke: Zum einen l"auft
+der Zeilenz"ahler von AS korrekt weiter, wenn eine Quell-Zeile "uber mehrere
+Listing-Zeilen geht, zum anderen gibt es Drucker (wie z.B. Laserdrucker),
+die beim "Uberschreiten des rechten Randes nicht automatisch in eine neue
+Zeile umbrechen, sondern den Rest einfach ,,verschlucken''. Aus diesem
+Grund f"uhrt AS auch den Zeilenumbruch selbstst"andig durch, d.h. zu lange
+Zeilen werden in Bruchst"ucke zerlegt, die eine L"ange kleiner oder
+gleich der eingestellten L"ange haben. In Zusammenhang mit Druckern, die
+einen automatischen Zeilenumbruch besitzen, kann das aber zu doppelten
+Zeilenvorsch"uben f"uhren, wenn man als Breite exakt die Zeilenbreite des
+Druckers angibt. Die L"osung in einem solchen Fall ist, als Zeilenbreite
+ein Zeichen weniger anzugeben. Die eingestellte Zeilenbreite darf zwischen
+5 und 255 Zeichen liegen; analog zur Seitenl"ange bedeutet ein Wert von 0,
+da"s AS keine Splittung der Listing-Zeilen vornehmen soll; eine
+Ber"ucksichtigung von zu langen Zeilen im Listing beim Seitenumbruch kann
+dann nat"urlich auch nicht mehr erfolgen.
+\par
+Die Defaulteinstellung f"ur die Seitenl"ange ist 60 Zeilen, f"ur die
+Zeilenbreite 0; letztere Wert wird auch angenommen, wenn \tty{PAGE} nur mit
+einem Argument aufgerufen wird.
+\par
+\bb{ACHTUNG!} AS hat keine M"oglichkeit, zu "uberpr"ufen, ob die
+eingestellte Listing-L"ange und Breite mit der Wirklichkeit "ubereinstimmen!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{NEWPAGE}
+\ttindex{NEWPAGE}
+
+\tty{NEWPAGE} kann dazu benutzt werden, einen Seitenvorschub zu erzwingen,
+obwohl die Seite noch gar nicht voll ist. Dies kann z.B. sinnvoll
+sein, um logisch voneinander getrennte Teile im Assemblerprogramm
+auch seitenm"a"sig zu trennen. Der programminterne Zeilenz"ahler wird
+zur"uckgesetzt, der Seitenz"ahler um Eins heraufgez"ahlt. Der optionale
+Parameter steht in Zusammenhang mit einer hierarchischen Seitennumerierung,
+die AS bis zu einer Kapiteltiefe von 4 unterst"utzt. 0 bedeutet dabei
+immer die tiefste Kapitelebene, der Maximalwert kann sich w"ahrend des
+Laufes ver"andern, wenn das auch verwirrend wirken kann, wie folgendes
+Beispiel zeigt:
+\begin{quote}\begin{tabbing}
+\hspace{2.5cm} \= \hspace{4.5cm} \= \kill
+Seite 1, \> Angabe \tty{NEWPAGE 0} \> $\rightarrow$ Seite 2 \\
+Seite 2, \> Angabe \tty{NEWPAGE 1} \> $\rightarrow$ Seite 2.1 \\
+Seite 2.1, \> Angabe \tty{NEWPAGE 1} \> $\rightarrow$ Seite 3.1 \\
+Seite 3.1, \> Angabe \tty{NEWPAGE 0} \> $\rightarrow$ Seite 3.2 \\
+Seite 3.2, \> Angabe \tty{NEWPAGE 2} \> $\rightarrow$ Seite 4.1.1 \\
+\end{tabbing}\end{quote}
+Je nach momentan vorhandener Kapiteltiefe kann \tty{NEWPAGE $<$Nummer$>$}
+also an verschiedenen Stellen eine Erh"ohung bedeuten. Ein automatischer
+Seitenvorschub wegen Zeilen"uberlauf oder ein fehlender Parameter ist
+gleichbedeutend mit \tty{NEWPAGE 0}. Am Ende des Listings wird vor Ausgabe
+der Symboltabelle ein implizites \tty{NEWPAGE $<$bish. Maximum$>$} durchgef"uhrt,
+um sozusagen ein neues Hauptkapitel zu beginnen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{MACEXP}
+\ttindex{MACEXP}
+
+Mit dem Befehl
+\begin{verbatim}
+ MACEXP off
+\end{verbatim}
+kann man erreichen, da"s bei Makroexpansionen nur noch der Makroaufruf
+und nicht der expandierte Text ausgegeben wird. Die ist bei
+makrointensivem Code sinnvoll, um das Listing nicht ins Uferlose
+wachsen zu lassen. Mit
+\begin{verbatim}
+ MACEXP on
+\end{verbatim}
+wird die vollst"andige Listingform wieder eingeschaltet, dies ist auch
+die Default-Vorgabe.
+\par
+Zwischen der Bedeutung von \tty{MACEXP} f"ur Makros und der f"ur alle
+anderen makroartigen Konstrukte (z.B. \tty{REPT}) besteht ein subtiler
+Unterschied: W"ahrend Makros intern ein Flag besitzen, das anzeigt, ob
+Expansionen dieses Makros ausgegeben werden sollen oder nicht, wirkt
+\tty{MACEXP} direkt auf alle anderen Konstrukte, die ,,vor Ort''
+aufgel"ost werden. Der Sinn dieser Differenzierung besteht darin, da"s
+es Makros geben kann, die ausgetestet sind und die man nicht mehr sehen
+will, andere aber sehr wohl noch. \tty{MACEXP} dient hier als
+Default f"ur das bei der Definition des Makros zu setzende Flag, der mit
+den Steuerparametern \tty{NOEXPAND/EXPAND} "ubersteuert werden kann.
+
+Die momentane Einstellung l"a"st sich aus dem Symbol \tty{MACEXP} auslesen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LISTING}
+\ttindex{LISTING}
+
+funktioniert wie \tty{MACEXP} und akzeptiert die gleichen Parameter,
+arbeitet aber wesentlich radikaler: Mit
+\begin{verbatim}
+ LISTING off
+\end{verbatim}
+wird \ii{"uberhaupt} nichts mehr im Listing ausgegeben. Diese Anweisung
+macht Sinn f"ur erprobte Codeteile oder Includefiles, um den
+Papierverbrauch nicht ins Unerme"sliche zu steigern. \bb{ACHTUNG!}
+Wer sp"ater das Gegenst"uck vergi"st, bekommt auch keine Symboltabelle
+mehr zu sehen! Zus"atzlich zu \tty{ON} und \tty{OFF} akzeptiert
+\tty{LISTING} auch \tty{NOSKIPPED} und \tty{PURECODE} als Argument. Mit
+der \tty{NOSKIPPED}-Einstellung werden aufgrund bedingter Assemblierung
+nicht assemblierte Teile nicht im Listing aufgef"uhrt, w"ahrend
+\tty{PURECODE} - wie der Name schon erahnen l"a"st - auch die
+\tty{IF}-Konstrukte selber nicht mehr im Listing auff"uhrt. Diese
+Einstellungen sind n"utzlich, wenn man Makros, die anhand von
+Parametern verschiedene Aktionen ausf"uhren, benutzt, und im Listing
+nur noch die jeweils benutzten Teile sehen m"ochte.
+\par
+Die momentane Einstellung l"a"st sich aus dem Symbol \tty{LISTING}
+(0=\tty{OFF}, 1=\tty{ON}, 2=\tty{NOSKIPPED}, 3=\tty{PURECODE}) auslesen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PRTINIT und PRTEXIT}
+\ttindex{PRTINIT}\ttindex{PRTEXIT}
+
+Bei der Listingausgabe auf Druckern ist es oftmals sinnvoll, den
+Drucker in eine andere Betriebsart (z.B. Schmalschrift) umzuschalten
+und am Ende des Listings diese Betriebsart wieder zu deaktivieren. Mit
+diesen Befehlen kann die Ausgabe dieser Steuerfolgen automatisiert
+werden, indem man mit
+\begin{verbatim}
+ PRTINIT <String>
+\end{verbatim}
+die Zeichenfolge angibt, die vor Listingbeginn an das Ausgabeger"at
+geschickt werden soll und mit
+\begin{verbatim}
+ PRTEXIT <String>
+\end{verbatim}
+analog den Deinitialisierungsstring. In beiden F"allen mu"s
+\tty{$<$String$>$} ein Stringausdruck sein. Die Syntaxregeln f"ur
+Stringkonstanten erm"oglichen es, ohne Verrenkungen Steuerzeichen in den
+String einzubauen.
+\par
+Bei der Ausgabe dieser Strings unterscheidet der Assembler \bb{nicht},
+wohin das Listing geschickt wird, d.h. Druckersteuerzeichen werden
+r"ucksichtslos auch auf den Bildschirm geschickt!
+\par
+Beispiel :
+\par
+Bei Epson-Druckern ist es sinnvoll, f"ur die breiten Listings
+in den Kompre"sdruck zu schalten. Die beiden Zeilen
+\begin{verbatim}
+ PRTINIT "\15"
+ PRTEXIT "\18"
+\end{verbatim}
+sorgen daf"ur, da"s der Kompre"sdruck ein- und nach dem Druck wieder
+ausgeschaltet wird.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{TITLE}
+\ttindex{TITLE}
+
+Normalerweise versieht der Assembler bereits jede Listingseite mit
+einer Titelzeile, die Quelldatei, Datum und Uhrzeit enth"alt. Mit
+diesem Befehl kann man den Seitenkopf um eine beliebige zus"atzliche
+Zeile erweitern. Der anzugebende String ist dabei ein beliebiger
+Stringausdruck.
+\par
+Beispiel:
+\par
+Bei dem bereits oben angesprochenenen Epson-Drucker soll eine Titelzeile
+im Breitdruck ausgegeben werden, wozu vorher der Kompre"smodus
+abgeschaltet werden mu"s:
+\begin{verbatim}
+ TITLE "\18\14Breiter Titel\15"
+\end{verbatim}
+(Epson-Drucker schalten den Breitdruck automatisch am Zeilenende aus.)
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{RADIX}
+\ttindex{RADIX}
+
+\tty{RADIX} mit einem numerischen Argument zwischen 2 und 36 legt das
+Default-Zahlensystem f"ur Integer-Konstanten fest, d.h. das Zahlensystem,
+das angenommen wird, wenn man nichts ausdr"ucklich anderes angegeben hat.
+Defaultm"a"sig ist dies 10, und bei der Ver"anderung dieses Wertes sind
+einige Fallstricke zu beachten, die in Abschnitt \ref{SectIntConsts}
+beschrieben sind.
+
+Unabh"angig von der momentanen Einstellung ist das Argument von {\tt
+RADIX} {\em immer dezimal}; weiterhin d"urfen keine symbolischen oder
+Formelausdr"ucke verwendet werden, sondern nur einfache Zahlenkonstanten!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{OUTRADIX}
+\ttindex{OUTRADIX}
+
+\tty{OUTRADIX} is gewisserma"sen das Gegenst"uck zu \tty{RADIX}: Mit ihm
+kann man festlegen, in welchem Zahlensystem berechnete Integer-Ausdr"ucke
+in Strings eingesetzt werden sollen, wenn man \verb!\{...}!-Konstrukte in
+Stringkonstanten verwendet (siehe Abschnitt \ref{SectStringConsts}). Als
+Argument sind wieder Werte zwischen 2 und 36 erlaubt; der Default ist 16.
+
+%%---------------------------------------------------------------------------
+
+\section{lokale Symbole}
+\label{ChapLocSyms}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Bei den lokalen Labels und den dazu eingef"uhrten Sektionen handelt es
+sich um eine grundlegend neue Funktion, die mit Version 1.39 eingef"uhrt
+wird. Da dieser Teil sozusagen ,,1.0'' ist, ist er sicherlich noch nicht
+der Weisheit letzter Schlu"s. Anregungen und (konstruktive) Kritik sind
+daher besonders erw"unscht. Insbesondere habe ich die Verwendung von
+Sektionen hier so dargestellt, wie ich sie mir vorstelle. Es kann dadurch
+passiert sein, da"s die Realit"at nicht ganz meinem Modell im Kopf entspricht.
+F"ur den Fall von Diskrepanzen verspreche ich, da"s die Realit"at der
+Dokumentation angepa"st wird, und nicht umgekehrt, wie es bei gr"o"seren
+Firmen schon einmal vorgekommen sein soll...
+\par
+AS erzeugt keinen linkf"ahigen Code (und wird es wohl auch nicht in n"aherer
+Zukunft tun \tty{:-(} ). Diese Tatsache zwingt dazu, ein Programm immer im ganzen
+zu "ubersetzen. Dieser Technik gegen"uber h"atte eine Aufteilung in
+Linker-Module einige Vorteile:
+\begin{itemize}
+\item{k"urzere "Ubersetzungszeiten, da lediglich die ge"anderten Module
+ neu "ubersetzt werden m"ussen;}
+\item{die M"oglichkeit, durch Definition "offentlicher und privater
+ Symbole definierte Schnittstellen zwischen den Modulen festzulegen;}
+\item{Durch die geringere L"ange der einzelnen Module reduziert sich die
+ Anzahl der Symbole im einzelnen Modul, so da"s k"urzere und trotzdem
+ eindeutige Symbolnamen benutzt werden k"onnen.}
+\end{itemize}
+Insbesondere der letzte Punkt hat mich pers"onlich immer etwas gest"ort:
+War ein Label-Name einmal am Anfang eines 2000 Zeilen langen Programmes
+benutzt, so durfte er nirgendwo wieder verwendet werden --- auch nicht am
+anderen Ende des Quelltextes, wo Routinen mit ganz anderem Kontext standen.
+Ich war dadurch gezwungen, zusammengesetzte Namen der Form
+\begin{verbatim}
+<Unterprogrammname>_<Symbolname>
+\end{verbatim}
+zu verwenden, die dann L"angen zwischen 15 und 25 Zeichen hatten und das
+Programm un"ubersichlich machten.
+Das im folgenden eingehender beschriebene Sektionen-Konzept sollte zumindest
+den beiden letzten genannten Punkten abhelfen. Es ist vollst"andig optional:
+Wollen Sie keine Sektionen verwenden, so lassen Sie es einfach bleiben
+und arbeiten weiter wie unter den "alteren AS-Versionen.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{Grunddefinition (SECTION/ENDSECTION)}
+
+Eine \ii{Sektion} stellt einen durch spezielle Befehle eingerahmten
+Teil des Assembler-Programmes dar und hat einen vom Programmierer
+festlegbaren, eindeutigen Namen:
+\begin{verbatim}
+ ...
+ <anderer Code>
+ ...
+ SECTION <Sektionsname>
+ ...
+ <Code in der Sektion>
+ ...
+ ENDSECTION [Sektionsname]
+ ...
+ <anderer Code>
+ ...
+\end{verbatim}
+Der Name f"ur eine Sektion mu"s den Konventionen f"ur einen Symbolnamen
+entsprechen; da AS Sektions-und Symbolnamen in getrennten Tabellen speichert,
+darf ein Name sowohl f"ur ein Symbol als auch eine Sektion verwendet werden.
+Sektionsnamen m"ussen in dem Sinne eindeutig sein, da"s auf einer Ebene
+nicht zwei Sektionen den gleichen Namen haben d"urfen (was es mit den
+,,Ebenen'' auf sich hat, erl"autere ich im n"achsten Abschnitt). Das Argument
+zu \tty{ENDSECTION} ist optional, es darf auch weggelassen werden; Falls
+es weggelassen wird, zeigt AS den Namen der Sektion an, der er das
+\tty{ENDSECTION} zugeordnet hat. Code in einer Sektion wird von AS genauso
+behandelt wie au"serhalb, lediglich mit drei entscheidenden Unterschieden:
+\begin{itemize}
+\item{Innerhalb der Sektion definierte Symbole (z.B. Labels, \tty{EQU}s...) werden
+ mit einer von AS intern vergebenen, der Sektion zugeordneten Nummer
+ versehen. Diese Symbole sind von Code au"serhalb der Sektion nicht
+ ansprechbar (das l"a"st sich nat"urlich durch Pseudobefehle variieren,
+ aber dazu sp"ater mehr).}
+\item{Durch das zus"atzliche Attribut kann ein Symbolname sowohl au"serhalb
+ der Sektion als auch innerhalb definiert werden, das Attribut erlaubt
+ also, Symbolnamen mehrfach zu benutzen, ohne da"s AS Protest anmeldet.}
+\item{Falls ein Symbol sowohl au"serhalb als auch innerhalb definiert ist,
+ wird innerhalb der Sektion das ,,lokale'' verwendet, d.h. AS sucht
+ in der Symboltabelle zuerst nach einem Symbol des gew"unschten Namens,
+ das auch gleichzeitig der Sektion zugeordnet wurde. Erst danach wird
+ nach einem globalen Symbol dieses Namens gefahndet.}
+\end{itemize}
+Mit diesem Mechanismus kann man z.B. den Code in Module aufteilen, wie man
+es mit einem Linker getan h"atte. Eine feinere Aufteilung w"are dagegen,
+alle Routinen in getrennte Sektionen zu verpacken. Je nach L"ange der
+Routinen k"onnen die nur intern ben"otigten Symbole dann sehr kurze Namen
+haben.
+\par
+Defaultm"a"sig unterscheidet AS Gro"s-und Kleinschreibung in Sektions-
+namen nicht; schaltet man jedoch in den case-sensitiven Modus um, so
+wird die Schreibweise genauso wie bei Symbolnamen ber"ucksichtigt.
+\par
+Die bisher beschriebene Aufteilung w"urde in etwa der Sprache C entsprechen,
+in der alle Funktionen auf gleicher Ebene nebeneinander stehen. Da mein
+,,hochsprachliches'' Vorbild aber Pascal ist, bin ich noch einen Schritt
+weiter gegangen:
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{Verschachtelung und Sichtbarkeitsregeln}
+
+Es ist erlaubt, in einer Sektion weitere Sektionen zu definieren, analog
+zu der M"oglichkeit in Pascal, in einer Prozedur/Funktion weitere
+Prozeduren zu definieren. Dies zeigt folgendes Beispiel:
+\begin{verbatim}
+sym EQU 0
+
+ SECTION ModulA
+ SECTION ProcA1
+sym EQU 5
+ ENDSECTION ProcA1
+ SECTION ProcA2
+sym EQU 10
+ ENDSECTION ProcA2
+ ENDSECTION ModulA
+
+ SECTION ModulB
+sym EQU 15
+ SECTION ProcB
+ ENDSECTION ProcB
+ ENDSECTION ModulB
+\end{verbatim}
+Bei der Suche nach einem Symbol sucht AS zuerst ein Symbol, das der aktuellen
+Sektion zugeordnet ist, und geht danach die ganze ,,Liste'' der Vatersektionen
+durch, bis er bei den globalen Symbolen angekommen ist. Im Beispiel sehen
+die Sektionen die in Tabelle \ref{TabSymErg} angegebenen Werte f"ur das Symbol
+\tty{sym}.
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+Sektion & Wert & aus Sektion... \\
+\hline
+\hline
+Global & 0 & Global \\
+\hline
+\tty{ModulA} & 0 & Global \\
+\hline
+\tty{ProcA1} & 5 & \tty{ProcA1} \\
+\hline
+\tty{ProcA2} & 10 & \tty{ProcA2} \\
+\hline
+\tty{ModulB} & 15 & \tty{ModulB} \\
+\hline
+\tty{ProcB} & 15 & \tty{ModulB} \\
+\hline
+\end{tabular}\end{center}
+\caption{F"ur die einzelnen Sektionen g"ultigen Werte\label{TabSymErg}}
+\end{table*}
+Diese Regel kann man durchbrechen, indem man explizit an den Symbolnamen
+die Sektion anh"angt, aus der man das Symbol holen will, und zwar in
+eckigen Klammern am Ende des Symbolnamens:
+\begin{verbatim}
+ move.l #sym[ModulB],d0
+\end{verbatim}
+Es d"urfen dabei nur Sektionsnamen verwendet werden, die eine Obersektion
+zur aktuellen Sektion darstellen. Als Sonderwert sind die Namen
+\tty{PARENT0..PARENT9} erlaubt, mit denen man die n-ten ,,Vatersektionen''
+relativ zur momentanen Sektion ansprechen kann; \tty{PARENT0} entspricht
+also der momentanen Sektion selber, \tty{PARENT1} der direkt "ubergeordneten
+usw. Anstelle \tty{PARENT1} kann man auch kurz nur \tty{PARENT} schreiben.
+L"a"st man dagegen den Platz zwischen den Klammern komplett frei, also
+etwa so
+\begin{verbatim}
+ move.l #sym[],d0 ,
+\end{verbatim}
+so erreicht man das globale Symbol. \bb{ACHTUNG!} Wenn man explizit ein
+Symbol aus einer Sektion anspricht, so wird auch nur noch bei den
+Symbolen dieser Sektion gesucht, der Sektionsbaum wird nicht mehr
+bis nach oben durchgegangen!
+\par
+Analog zu Pascal ist es erlaubt, da"s verschiedene Sektionen Untersektionen
+gleichen Namens haben d"urfen, das Prinzip der Lokalit"at verhindert hier
+Irritationen. M.E. sollte man davon aber trotzdem sparsamen Gebrauch machen,
+da in Symbol-und Querverweisliste Symbole zwar mit der Sektion, in der sie
+definiert wurden, gekennzeichnet werden, aber nicht mit der "uber dieser
+Sektion evtl. liegenden ,,Sektionshierarchie'' (das h"atte einfach den Platz
+in der Zeile gesprengt); Unterscheidungen sind dadurch nicht erkennbar.
+\par
+Da ein \tty{SECTION}-Befehl von selber kein Label definiert, besteht hier
+ein wichtiger Unterschied zu Pascal: Eine Pascal-Prozedur kann
+ihre Unterprozeduren/funktionen automatisch ,,sehen'', unter AS mu"s man
+noch einen Einsprungpunkt extra definieren. Das kann man z.B. mit folgendem
+Makro-P"archen tun:
+\begin{verbatim}
+proc MACRO name
+ SECTION name
+name LABEL $
+ ENDM
+
+endp MACRO name
+ ENDSECTION name
+ ENDM
+\end{verbatim}
+Diese Beispiel zeigt gleichzeitig, da"s die Lokalit"at von Labels in
+Makros nicht von den Sektionen beeinflu"st wird, deshalb der Trick mit dem
+\tty{LABEL}-Befehl.
+\par
+Nat"urlich ist mit dieser Definition das Problen noch nicht ganz gel"ost,
+bisher ist das Einsprung-Label ja noch lokal und von au"sen nicht zu
+erreichen. Wer nun meint, man h"atte das Label einfach nur vor der
+SECTION-Anweisung plazieren m"ussen, sei jetzt bitte ruhig, denn er
+verdirbt mir den "Ubergang auf das n"achste Thema:
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PUBLIC und GLOBAL}
+
+Die \tty{PUBLIC}-Anweisung erlaubt es, die Zugeh"origkeit eines Symbols
+zu einer bestimmten Sektion zu ver"andern. Es ist m"oglich, mit einem
+\tty{PUBLIC}-Befehl mehrere Symbole zu bearbeiten, ohne Beschr"ankung
+der Allgemeinheit will ich aber ein Beispiel mit nur einer Variable verwenden:
+Im einfachsten Falle erkl"art man ein Symbol als vollst"andig global, d.h.
+es ist von allen Stellen des Programmes ansprechbar:
+\begin{verbatim}
+ PUBLIC <Name>
+\end{verbatim}
+Da ein Symbol bei seiner Definition endg"ultig in der Symboltabelle
+einsortiert wird, mu"s diese Anweisung \bb{vor} der Definition des
+Symbols erfolgen. Alle \tty{PUBLIC}s werden von AS in einer Liste
+vermerkt und bei ihrer Definition aus dieser Liste wieder entfernt. Bei
+Beendigung einer Sektion gibt AS Fehlermeldungen f"ur alle nicht
+aufgel"osten ,,Vorw"artsreferenzen'' aus.
+\par
+Angesichts des hierarchischen Sektionenkonzepts erscheint die Methode,
+ein Symbol als vollst"andig global zu definieren, reichlich brachial.
+Es geht aber auch etwas differenzierter, indem man zus"atzlich einen
+Sektionsnamen angibt:
+\begin{verbatim}
+ PUBLIC <Name>:<Sektion>
+\end{verbatim}
+Damit wird das Symbol der genannten Sektion zugeordnet und damit auch
+allen ihren Untersektionen zug"anglich (es sei denn, diese definieren
+wiederum ein Symbol gleichen Namens, das dann das ,,globalere''
+"ubersteuert). Naturgem"a"s protestiert AS, falls mehrere Untersektionen
+ein Symbol gleichen Namens auf die gleiche Ebene exportieren wollen.
+Als Spezialwert f"ur \tty{$<$Sektion$>$} sind die im vorigen Abschnitt
+genannten \tty{PARENTx}-Namen zugelassen, um das Symbol genau n Ebenen hinaufzuexportieren.
+Es sind als Sektionen nur der momentanen Sektion "ubergeordnete Sektionen
+zugelassen, also keine, die im Baum aller Sektionen in einem anderen Zweig
+stehen. Sollten dabei mehrere Sektionen den gleichen Namen haben (dies ist
+legal), so wird die tiefste gew"ahlt.
+\par
+Mit diesem Werkzeug kann das obige Prozedurmakro nun Sinn ergeben:
+\begin{verbatim}
+proc MACRO name
+ SECTION name
+ PUBLIC name:PARENT
+name LABEL $
+ ENDM
+\end{verbatim}
+Diese Einstellung entspricht dem Modell von Pascal, in der eine
+Unterprozedur auch nur von ihrem ,,Vater'' gesehen werden kann, jedoch
+nicht vom ,,Gro"svater''.
+\par
+Falls mehrere Untersektionen versuchen, ein Symbol gleichen Namens
+in die gleiche Obersektion zu exportieren, meckert AS "uber doppelt
+definierte Symbole, was an sich ja korrekt ist. War das gewollt,
+so mu"s man die Symbole in irgendeiner Weise ,,qualifizieren'', damit
+sie voneinander unterschieden werden k"onnen. Dies ist mit der
+\tty{GLOBAL}-Anweisung m"oglich. Die Syntax von \tty{GLOBAL} ist
+der von \tty{PUBLIC} identisch, das Symbol bleibt aber lokal, anstatt
+einer h"oheren Sektion zugeordnet zu werden. Stattdessen wird ein
+weiteres Symbol gleichen Werts erzeugt, dem jedoch der Untersektionsname
+mit einem Unterstrich vorangestellt wird, und nur dieses Symbol wird der
+Sektionsangabe entsprechend "offentlich gemacht. Definieren z.B. zwei
+Sektionen \tty{A} und \tty{B} ein Symbol \tty{SYM} und exportieren
+es mit \tty{GLOBAL} zu ihrer Vatersektion, so werden dort die Symbole
+unter den Namen \tty{A\_SYM} und \tty{B\_SYM} eingeordnet.
+\par
+Falls zwischen Quell- und Zielsektion mehrere Stufen stehen sollten,
+so wird entsprechend der komplette Namenszweig von der Ziel- bis zur
+Quellsektion dem Symbolnamen vorangestellt.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FORWARD}
+
+So sch"on das bisher besprochene Modell ist, ein bei Pascal nicht
+auftauchendes Detail macht "Arger: die bei Assembler m"oglichen
+Vorw"artsreferenzen. Bei Vorw"artsreferenzen kann es sein, da"s AS
+im ersten Pass auf ein Symbol einer h"oheren Sektion zugreift. Dies
+ist an sich nicht weiter tragisch, solange im zweiten Pass das richtige
+Symbol genommen wird, es k"onnen aber Unf"alle der folgenden Art passieren:
+\begin{verbatim}
+loop: .
+ <Code>
+ ..
+ SECTION sub
+ .. ; ***
+ bra.s loop
+ ..
+loop: ..
+ ENDSECTION
+ ..
+ jmp loop ; Hauptschleife
+\end{verbatim}
+AS wird im ersten Pass das globale Label \tty{loop} verwenden, sofern
+das Programmst"uck bei \tty{$<$Code$>$} hinreichend lang ist, wird er
+sich "uber eine zu gro"se Sprungdistanz beklagen und den zweiten Pass erst
+gar nicht versuchen. Um die Uneindeutigkeit zu vermeiden, kann man den
+Symbolnamen mit einem expliziten Bezug versehen:
+\begin{verbatim}
+ bra.s loop[sub]
+\end{verbatim}
+Falls ein lokales Symbol h"aufig referenziert wird, k"onnen die vielen
+Klammern mit dem \tty{FORWARD}-Befehl eingespart werden. Das Symbol
+wird damit explizit als lokal angek"undigt. AS wird dann bei Zugriffen
+auf dieses Symbol automatisch nur im lokalen Symbolbereich suchen.
+In diesem Falle m"u"ste an der mit \tty{***} gekennzeichneten Stelle
+daf"ur der Befehl
+\begin{verbatim}
+ FORWARD loop
+\end{verbatim}
+stehen.
+Damit \tty{FORWARD} Sinn macht, mu"s es nicht nur vor der Definition des
+Symbols, sondern vor seiner ersten Benutzung in der Sektion gegeben werden.
+Ein Symbol gleichzeitig privat und "offentlich zu definieren, ergibt keinen
+Sinn und wird von AS auch angemahnt.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{Geschwindigkeitsaspekte}
+
+Die mehrstufige Suche in der Symboltabelle und die Entscheidung, mit welchem
+Attribut ein Symbol eingetragen werden soll, kosten naturgem"a"s etwas
+Rechenzeit. Ein 1800 Zeilen langes 8086-Programm z.B. wurde nach der
+Umstellung auf Sektionen statt in 33 in 34,5 Sekunden assembliert
+(80386 SX, 16MHz, 3 Durchg"ange). Der Overhead h"alt sich also in Grenzen:
+Ob man ihn in Kauf nehmen will, ist (wie am Anfang erw"ahnt) eine Frage des
+Geschmacks; man kann AS genauso gut ohne Sektionen verwenden.
+
+%%---------------------------------------------------------------------------
+
+\section{Diverses}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SHARED}
+\label{ChapShareOrder} \ttindex{SHARED}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Mit diesem Befehl weist man den AS an, die in der Parameterliste
+angegebenen Symbole (egal ob Integer, Gleitkomma oder String) im
+Sharefile mit ihren Werten abzulegen. Ob eine solche Datei "uberhaupt
+und in welchem Format erzeugt wird, h"angt von den in
+\ref{SectCallConvention} beschriebenen Kommandozeilenschaltern ab.
+Findet AS diesen Befehl und es wird keine Datei erzeugt, f"uhrt das zu
+einer Warnung.
+\par
+\bb{VORSICHT!} Ein eventuell der Befehlszeile anh"angender Kommentar
+wird in die erste, ausgegebene Zeile mit "ubertragen (sofern die
+Argumentliste von \tty{SHARED} leer ist, wird nur der Kommentar ausgegeben).
+Falls die Share-Datei f"ur C oder Pascal erzeugt wird, sind einen
+C/Pascal-Kommentar schlie"sende Zeichenfolgen (\verb!*/! bzw.
+\verb!*)!) im Kommentar zu vermeiden. AS pr"uft dies \ii{nicht}!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{INCLUDE}
+\ttindex{INCLUDE}\label{SectInclude}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Dieser Befehl f"ugt die im Parameter angegebene Datei (die optional in
+G"an\-se\-f"u"s\-chen eingeschlossen sein darf) so im Text ein, als ob sie dort
+stehen w"urde. Dieser Befehl ist sinnvoll, um Quelldateien aufzuspalten,
+die alleine nicht in den Speicher passen w"urden oder um sich ''Toolboxen''
+zu erzeugen.
+\par
+Falls der angegebene Dateiname keine Endung hat, wird er automatisch
+um die Endung \tty{INC} erweitert.
+\par
+Mit der Kommandozeilenoption
+\begin{verbatim}
+ -i <Pfadliste>
+\end{verbatim}
+l"a"st sich eine Liste von Verzeichnissen angeben, in denen automatisch
+zus"atzlich nach der Includedatei gesucht werden soll. Wird die Datei
+nicht gefunden, so ist dies ein \ii{fataler} Fehler, d.h. der Assembler
+bricht sofort ab.
+\par
+Aus Kompatibilit"atsgr"unden ist es erlaubt, den Namen in G"ansef"u"schen
+zu schreiben,
+\begin{verbatim}
+ INCLUDE stddef51
+\end{verbatim}
+und
+\begin{verbatim}
+ INCLUDE "stddef51.inc"
+\end{verbatim}
+sind also "aquivalent. \bb{ACHTUNG!} Wegen dieser Wahlfreiheit ist
+hier nur eine Stringkonstante, aber kein Stringausdruck zul"assig!
+\par
+Sollte der Dateiname eine Pfadangabe enthalten, so wird die Suchliste
+ignoriert.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BINCLUDE}
+\ttindex{BINCLUDE}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+\tty{BINCLUDE} dient dazu, in den von AS erzeugten Code Bin"ardaten
+einzubetten, die von einem anderen Programm erzeugt wurden (das kann
+nat"urlich theoretisch auch von AS selber erzeugter Code sein...).
+\tty{BINCLUDE} hat drei Formen:
+\begin{verbatim}
+ BINCLUDE <Datei>
+\end{verbatim}
+In dieser Form wird die Datei komplett eingebunden.
+\begin{verbatim}
+ BINCLUDE <Datei>,<Offset>
+\end{verbatim}
+In dieser Form wird der Inhalt der Datei ab \verb!<Offset>! bis zum Ende
+der Datei eingebunden.
+\begin{verbatim}
+ BINCLUDE <Datei>,<Offset>,<Len>
+\end{verbatim}
+In dieser Form werden \verb!<Len>! Bytes ab Offset \verb!<Offset>! eingebunden.
+\par
+Es gelten die gleichen Regeln bez"uglich Suchpfaden wie bei \tty{INCLUDE}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{MESSAGE, WARNING, ERROR und FATAL}
+\ttindex{MESSAGE}\ttindex{WARNING}\ttindex{ERROR}\ttindex{FATAL}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Der Assembler pr"uft zwar die Quelltexte so streng wie m"oglich und
+liefert diffenzierte Fehlermeldungen, je nach Anwendung kann es
+aber sinnvoll sein, unter bestimmten Bedingungen zus"atzliche
+Fehlermeldungen auszul"osen, mit denen sich logische Fehler automatisch
+pr"ufen lassen. Der Assembler unterscheidet drei Typen von Fehlermeldungen,
+die "uber die drei Befehle auch dem Programmierer zug"anglich sind:
+\begin{itemize}
+\item{\tty{WARNING}: Fehler, die auf m"oglicherweise falschen oder
+ ineffizienten Code hinweisen. Die Assemblierung l"auft weiter,
+ eine Codedatei wird erzeugt.}
+\item{\tty{ERROR}: echte Fehler im Programm. Die Assemblierung l"auft weiter,
+ um m"ogliche weitere Fehler in einem Durchgang entdecken und
+ korrigieren zu k"onnen. Eine Codedatei wird nicht erzeugt.}
+\item{\tty{FATAL}: schwerwiegende Fehler, die einen sofortigen Abbruch des
+ Assemblers bedingen. Eine Codedatei kann m"oglicherweise entstehen,
+ ist aber unvollst"andig.}
+\end{itemize}
+Allen drei Befehlen ist das Format gemeinsam, in dem die Fehlermeldung
+angegeben werden mu"s: Ein beliebig (berechneter?!) Stringausdruck, der
+damit sowohl eine Konstante als auch variabel sein darf.
+\par
+Diese Anweisungen ergeben nur in Zusammenhang mit bedingter Assemblierung
+Sinn. Ist f"ur ein Programm z.B. nur ein begrenzter Adre"sraum vorhanden,
+so kann man den "Uberlauf folgenderma"sen testen:
+\begin{verbatim}
+ROMSize equ 8000h ; 27256-EPROM
+
+ProgStart: ..
+ <das eigentliche Programm>
+ ..
+ProgEnd:
+ if ProgEnd-ProgStart>ROMSize
+ error "\aDas Programm ist zu lang!"
+ endif
+\end{verbatim}
+Neben diesen fehlererzeugenden Befehlen gibt es noch den Befehl
+\tty{MESSAGE}, der einfach nur eine Meldung auf der Konsole bzw. im
+Listing erzeugt. Seine Benutzung ist den anderen drei Befehlen
+gleich.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{READ}
+\ttindex{READ}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+\tty{READ} ist sozusagen das Gegenst"uck zu der vorigen Befehlsgruppe: mit
+ihm ist es m"oglich, \ii{w"ahrend} der Assemblierung Werte von der
+Tastatur einzulesen. Wozu das gut sein soll? Um das darzulegen, soll
+hier ausnahmsweise einmal das Beispiel vor die genauere Erl"auterung
+gezogen werden:
+\par
+Ein Programm ben"otigt zum Datentransfer einen Puffer mit einer zur
+"Ubersetzungszeit festzulegenden Gr"o"se. Um die Gr"o"se des Puffers
+festzulegen, k"onnte man sie einmal mit \tty{EQU} in einem Symbol
+ablegen, es geht aber auch interaktiv mit \tty{READ} :
+\begin{verbatim}
+ IF MomPass=1
+ READ "Puffer (Bytes)",BufferSize
+ ENDIF
+\end{verbatim}
+Auf diese Weise k"onnen Programme sich w"ahrend der "Ubersetzung
+interaktiv konfigurieren, man kann sein Programm z.B. jemandem geben,
+der es mit seinen Parametern "ubersetzen kann, ohne im Quellcode
+,,herumstochern'' zu m"ussen. Die im Beispiel gezeigte \tty{IF-}
+Abfrage sollte "ubrigens immer verwendet werden, damit der Anwender
+nur einmal mit der Abfrage bel"astigt wird.
+\par
+\tty{READ} "ahnelt sehr stark dem \tty{SET-} Befehl, nur da"s der
+dem Symbol zuzuweisende Wert nicht rechts vom Schl"usselwort steht,
+sondern von der Tastatur eingelesen wird. Dies bedeutet z.B. auch,
+da"s AS anhand der Eingabe automatisch festlegt, ob es sich um eine
+Integer- oder Gleitkommazahl oder einen String handelt und anstelle
+einzelner Konstanten auch ganze Formelausdr"ucke eingegeben werden
+k"onnen.
+\par
+\tty{READ} darf entweder nur einen Parameter oder zwei Parameter
+haben, denn die Meldung zur Eingabeaufforderung ist optional. Fehlt
+sie, so gibt AS eine aus dem Symbolnamen konstruierte Meldung aus.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{RELAXED}
+\label{SectRELAXED}
+\ttindex{RELAXED}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+Defaultm"a"sig ist einer Prozessorfamilie eine bestimmte Schreibweise
+von Integer-Konstanten zugeordnet (die i.a. der Herstellervorgabe
+entspricht, solange der nicht eine allzu abgefahrene Syntax benutzt...).
+Nun hat aber jeder seine pers"onlichen Vorlieben f"ur die eine oder
+andere Schreibweise und kann gut damit leben, da"s sich seine Programme
+nicht mehr mit dem Standard-Assembler "ubersetzen lassen. Setzt man ein
+\begin{verbatim}
+ RELAXED ON
+\end{verbatim}
+an den Programmanfang, so kann man fortan alle Schreibweisen beliebig
+gemischt und durcheinander verwenden; bei jedem Ausdruck versucht AS
+automatisch zu ermitteln, welche Schreibweise verwendet wurde. Da"s
+diese Automatik nicht immer das Ergebnis liefert, das man sich vorgestellt
+hat, ist auch der Grund, weshalb diese Option explizit eingeschaltet
+werden mu"s (und man sich davor h"uten sollte, sie einfach in einem
+existierenden Programm dazuzusetzen): Ist nicht durch vor- oder
+nachgestellte Zeichen zu erkennen, da"s es sich um Intel- oder
+Motorola-Konstanten handelt, wird im C-Modus gearbeitet. Eventuell
+vorangestellte, eigentlich "uberfl"ussige Nullen haben in diesem Modus
+durchaus eine Bedeutung:
+\begin{verbatim}
+ move.b #08,d0
+\end{verbatim}
+Diese Konstante w"urde als Oktalkonstante verstanden werden, und weil
+Oktalzahlen nur Ziffern von 0..7 enthalten k"onnen, f"uhrt das zu einem
+Fehler. Dabei h"atte man in diesem Fall noch Gl"uck gehabt, bei der
+Zahl \tty{077} z.B. h"atte man ohne Meldung Probleme bekommen. Ohne
+\tty{RELAXED}-Modus w"are in beiden F"allen klar gewesen, da"s es sich
+um dezimale Konstanten handelt.
+\par
+Die momentane Einstellung kann aus dem gleichnamigen Symbol ausgelesen
+werden.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{END}
+\ttindex{END}
+
+{\em G"ultigkeit: alle Prozessoren}
+
+\tty{END} kennzeichnet das Ende des Assemblerprogrammes. Danach
+noch in der Quelldatei stehende Zeilen werden ignoriert.
+\bb{WICHTIG:} \tty{END} darf zwar aus einem Makro heraus aufgerufen
+werden, der Stapel der bedingten Assemblierung wird aber nicht
+automatisch abger"aumt. Das folgende Konstrukt f"uhrt daher zu
+einer Fehlermeldung:
+\begin{verbatim}
+ IF KeineLustMehr
+ END
+ ENDIF
+\end{verbatim}
+Optional darf \tty{END} auch einen Integer-Ausdruck als Argument haben,
+der den Startpunkt des Programmes vermerkt. Dieser wird von AS in einem
+speziellen Record der Datei vermerkt und kann z.B. von P2HEX
+weiterverarbeitet werden.
+\par
+\tty{END} war eigentlich schon immer in AS definiert, nur war es
+bei fr"uheren Versionen von AS aus Kompatibilit"at zu anderen
+Assemblern vorhanden und hatte keine Wirkung.
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Prozessorspezifische Hinweise}
+
+Ich habe mich bem"uht, die einzelnen Codegeneratoren m"oglichst kompatibel
+zu den Originalassemblern zu halten, jedoch nur soweit, wie es keinen
+unvertretbaren Mehraufwand bedeutete. Wichtige Unterschiede, Details und
+Fallstricke habe ich im folgenden aufgelistet.
+
+%%---------------------------------------------------------------------------
+
+\section{6811}
+
+,,Wo gibt es denn das zu kaufen, den HC11 in NMOS?'', fragt jetzt vielleicht
+der eine oder andere. Gibt es nat"urlich nicht, aber ein H l"a"st sich nun
+einmal nicht in einer Hexzahl darstellen ("altere Versionen von AS h"atten
+solche Namen deswegen nicht akzeptiert), und dann habe ich die Buchstaben
+gleich ganz weggelassen...
+\par
+\begin{quote}{\it
+,,Jemand, der sagt, etwas sei unm"oglich,sollte wenigstens so kooperativ
+sein, denjenigen, der es gerade tut, nicht am Arbeiten zu hindern.''
+}\end{quote}
+Ab und zu ist man gezwungen, seine Meinung zu revidieren. Vor einigen
+Versionen hatte ich an dieser Stelle noch behauptet, ich k"onne es im Parser
+von AS nicht realisieren, da"s man die Argumente von \tty{BSET/BCLR} bzw.
+\tty{BRSET/BRCLR} auch mit Leerzeichen trennen kann. Offensichtlich kann
+selbiger aber mehr, als ich vermutet habe...nach der soundsovielten Anfrage
+habe ich mich noch einmal drangesetzt, und jetzt scheint es zu laufen. Man
+darf sowohl Leerzeichen als auch Kommas verwenden, aber nicht in allen
+Varianten, um es nicht uneindeutig zu machen: Es gibt zu jeder
+Befehlsvariante zwei M"oglichkeiten; eine, die nur Kommas verwendet, sowie
+eine, wie sie von Motorola wohl definiert wurde (leider sind die Datenb"ucher
+nicht immer so gut wie die zugeh"orige Hardware...):
+\begin{verbatim}
+ Bxxx abs8 #mask entspricht Bxxx abs8,#mask
+ Bxxx disp8,X #mask entspricht Bxxx disp8,X,#mask
+ BRxxx abs8 #mask adr entspricht BRxxx abs8,#mask,adr
+ BRxxx disp8,X #mask adr entspricht BRxxx disp8,X,#mask,adr
+\end{verbatim}
+Dabei steht \tty{xxx} entweder f"ur \tty{SET} oder \tty{CLR} und \tty{\#mask}
+f"ur die zu verwendende Bitmaske; der Lattenzaun ist dabei optional.
+Anstelle des X-Registers darf nat"urlich auch Y verwendet werden.
+
+%%---------------------------------------------------------------------------
+
+\section{PowerPC}
+
+Sicher hat es ein bi"schen den Anflug einer Schnapsidee, einen Prozessor,
+der eher f"ur den Einsatz in Workstations konzipiert wurde, in AS
+einzubauen, der sich ja eher an Programmierer von Einplatinencomputern
+wendet. Aber was heute noch das Hei"seste vom Hei"sen ist, ist es morgen
+schon nicht mehr, und sowohl der Z80 als auch der 8088 haben ja inzwischen
+die Mutation von der Personal Computer-CPU zum sog. ,,Mikrocontroller''
+vollzogen. Mit dem Erscheinen von MPC505 und PPC403 hat sich die Vermutung
+dann auch best"atigt, da"s IBM und Motorola diese Prozessorserie auf allen
+Ebenen durchdr"ucken wollen.
+\par
+Die Unterst"utzung ist momentan noch nicht vollst"andig: Als Pseudobefehle
+zur Datenablage werden momentan provisorisch die Intel-Mnemonics
+unterst"utzt und es fehlen die etwas ungew"ohnlicheren, in \cite{Mot601}
+genannten RS6000-Befehle (die aber hoffentlich keiner vermi"st...). Das
+wird aber nachgeholt, sobald Informationen verf"ugbar sind!
+
+%%---------------------------------------------------------------------------
+
+\section{DSP56xxx}
+
+Motorola, was ist nur in Dich gefahren! Wer bei Dir ist nur auf das
+schmale Brett gekommen, die einzelnen parallelen Datentransfers
+ausgerechnet durch Leerzeichen zu trennen! Wer immer nun seine Codes
+etwas "ubersichtlicher formatieren will, z.B. so:
+\begin{verbatim}
+ move x:var9 ,r0
+ move y:var10,r3 ,
+\end{verbatim}
+der ist gekniffen, weil das Leerzeichen als Trennung paralleler
+Datentransfers erkannt wird!
+\par
+Sei's drum; Motorola hat es so definiert, und ich kann es nicht
+"andern. Als Trennung der Operationen sind statt Leerzeichen auch
+Tabulatoren zugelassen, und die einzelnen Teile sind ja wieder ganz
+normal mit Kommas getrennt.
+\par
+In \cite{Mot56} steht, da"s bei den Befehlen \tty{MOVEC, MOVEM, ANDI} und
+\tty{ORI} auch die allgemeineren Mnemonics \tty{MOVE, AND} und \tty{OR}
+verwendet werden k"onnen. Bei AS geht das (noch) nicht.
+
+%%---------------------------------------------------------------------------
+
+\section{H8/300}
+
+Bei der Assemblersyntax dieser Prozessoren hat Hitachi reichlich
+bei Motorola abgekupfert (was so verkehrt ja nun auch nicht war...),
+nur leider wollte die Firma unbedingt ihr eigenes Format f"ur
+Hexadezimalzahlen einf"uhren, und dazu noch eines, das "ahnlich wie
+bei Microchip Hochkommas verwendet. Das konnte (und wollte) ich bei
+AS nicht nachvollziehen, bei dem Hochkommas zur Einrahmung von
+ASCII-Sequenzen benutzt werden. Anstelledessen werden Zahlen in der
+"ublichen Motorola-Syntax geschrieben, d.h. mit einem Dollarzeichen.
+
+%%---------------------------------------------------------------------------
+
+\section{SH7000/7600/7700}
+
+Leider hat Hitachi auch hier wieder das Extrawurst-Format f"ur
+Hexadezimalzahlen verwendet, und wieder habe ich in AS das nicht
+nachvollzogen...bitte Motorola-Syntax benutzen!
+\par
+Bei der Verwendung von Literalen und dem \tty{LTORG}-Befehl sind
+einige Details zu beachten, wenn man nicht auf einmal mit eigenartigen
+Fehlermeldungen konfrontiert werden will:
+\par
+Literale existieren, weil der Prozessor nicht in der Lage ist, Konstanten
+au"serhalb des Bereiches von -128 bis 127 mit immediate-Adressierung
+zu laden. AS (und der Hitachi-Assembler) verstecken diese Unzul"anglichkeit,
+indem sie automatisch entsprechende Konstanten im Speicher ablegen, die
+dann mittels PC-relativer Adressierung angesprochen werden. Die Frage, die
+sich nun erhebt, ist die, wo diese Konstanten im Speicher abgelegt werden
+sollen. AS legt sie nicht sofort ab, sondern sammelt sie so lange
+auf, bis im Programm eine \tty{LTORG}-Anweisung auftritt. Dort werden
+alle Konstanten abgelegt, wobei deren Adressen mit ganz normalen
+Labels versehen werden, die man auch in der Symboltabelle sehen kann.
+Ein Label hat die Form
+\begin{verbatim}
+ LITERAL_s_xxxx_n .
+\end{verbatim}
+Dabei repr"asentiert \tty{s} den Typ des Literals. Unterschieden werden
+Literale, die 16-Bit-Konstanten (\tty{s=W}), 32-Bit-Konstanten (\tty{s=L})
+oder Vorw"artsreferenzen, bei denen AS die Operandengr"o"se nicht
+im voraus erkennen kann (\tty{s=F}), enthalten. F"ur \tty{W} oder \tty{L}
+bedeutet \tty{xxxx} den hexadezimal geschriebenen Wert der Konstante, bei
+Vorw"artsreferenzen, bei denen man den Literalwert ja noch nicht kennt,
+bezeichnet \tty{xxxx} eine einfache Durchnumerierung. \tty{n} kennzeichnet
+das wievielte Auftreten dieses Literals in dieser Sektion. Literale machen
+ganz normal die Lokalisierung durch Sektionen mit, es ist daher zwingend
+erforderlich, in einer Sektion entstandene Literale mit \tty{LTORG} auch
+dort abzulegen!
+\par
+Die Durchnumerierung mit \tty{n} ist erforderlich, weil ein Literal in
+einer Sektion mehrfach auftreten kann. Dies ist einmal bedingt dadurch,
+da"s die PC-relative Adressierung nur positive Displacements erlaubt,
+einmal mit \tty{LTORG} abgelegte Literale also im folgenden Code nicht
+mitbenutzt werden k"onnen, andererseits auch, weil die Reichweite der
+Displacements beschr"ankt ist (512 bzw. 1024 Byte).
+Ein automatisches \tty{LTORG} am Ende des Programmes oder beim Umschalten
+zu einer anderen CPU erfolgt nicht; findet AS in einer solchen Situation
+noch abzulegende Literale, so wird eine Fehlermeldung ausgegeben.
+\par
+Da bei der PC-relativen Adressierung der zur Adressierung herangezogene
+PC-Wert der Instruktionsadresse+4 entspricht, ist es nicht m"oglich, ein
+Literal zu benutzen, welches direkt hinter dem betroffenen Befehl abgelegt
+wird, also z.B. so:
+\begin{verbatim}
+ mov #$1234,r6
+ ltorg
+\end{verbatim}
+Da der Prozessor dann aber sowieso versuchen w"urde, Daten als Code
+auszuf"uhren, sollte diese Situation in realen Programmen nicht auftreten.
+Wesentlich realer ist aber ein anderer Fallstrick: Wird hinter einem
+verz"ogerten Sprung PC-relativ zugegriffen, so ist der Programmz"ahler
+bereits auf die Sprungzieladresse gesetzt, und das Displacement wird
+relativ zum Sprungziel+2 berechnet. Im folgenden Beispiel kann daher
+das Literal nicht erreicht werden:
+\begin{verbatim}
+ bra Target
+ mov #$12345678,r4 ; wird noch ausgefuehrt
+ .
+ .
+ ltorg ; hier liegt das Literal
+ .
+ .
+Target: mov r4,r7 ; hier geht es weiter
+\end{verbatim}
+Da Target+2 hinter dem Literal liegt, w"urde sich ein negatives
+Displacement ergeben. Besonders haarig wird es, wenn mit den
+Befehlen \tty{JMP, JSR, BRAF} oder \tty{BSRF} verzweigt wird: Da AS die
+Zieladresse hier nicht ermitteln kann (sie ergibt sich erst zur
+Laufzeit aus dem Registerinhalt), nimmt AS hier eine Adresse an,
+die nach M"oglichkeit nie pa"st, so da"s PC-relative Adressierung g"anzlich
+unm"oglich wird.
+\par
+Es ist nicht direkt m"oglich, aus der Zahl und Gr"o"se der Literale
+auf den belegten Speicher zu schlie"sen. U.u. mu"s AS ein F"ullwort
+einbauen, um einen Langwort-Wert auf eine durch 4 teilbare Adresse
+auszurichten, andererseits kann er m"oglicherweise Teile eines
+32-bittigen Literals f"ur 16-Bit-Literale mitbenutzten. Mehrfach
+auftretende Literale erzeugen nat"urlich nur einen Eintrag. Solche
+Optimierungen werden f"ur Vorw"artsreferenzen allerdings ganz
+unterdr"uckt, da AS den Wert dieser Literale noch nicht kennt.
+\par
+Da Literale die PC-relative Adressierung ausnutzen, die nur beim
+\tty{MOV}-Befehl erlaubt sind, beschr"anken sich Literale ebenfalls auf
+die Verwendung in \tty{MOV}. Etwas trickreich ist hier die Art und Weise,
+in der AS die Operandengr"o"se auswertet. Eine Angabe von Byte oder
+Wort bedeutet, da"s AS einen m"oglichst kurzen \tty{MOV}-Befehl erzeugt,
+der den angegebenen Wert in den unteren 8 oder 16 Bit erzeugt, d.h.
+die oberen 24 oder 16 Bit werden als don't care behandelt. Gibt
+man dagegen Langwort oder gar nichts an, so sagt dies aus, da"s
+das komplette 32-Bit-Register den angegebenen Wert enthalten soll.
+Das hat z.B. den Effekt, da"s in folgendem Beispiel
+\begin{verbatim}
+ mov.b #$c0,r0
+ mov.w #$c0,r0
+ mov.l #$c0,r0
+\end{verbatim}
+der erste Befehl echte immediate-Adressierung erzeugt, der zweite und
+dritte jedoch ein Wort-Literal benutzen: Da das Bit 7 in der Zahl gesetzt
+ist, erzeugt der Byte-Befehl effektiv \$FFFFFFC0 im Register, was nach
+der Konvention nicht das w"are, was man im zweiten und dritten Fall haben
+m"ochte. Im dritten Fall reicht auch ein Wort-Literal, weil das gel"oschte
+Bit 15 des Operanden vom Prozessor in Bit 16..31 fortgesetzt wird.
+\par
+Wie man sieht, ist dieses ganze Literal-Konzept reichlich kompliziert;
+einfacher ging's aber wirklich nicht. Es liegt leider in der Natur
+der Sache, da"s man manchmal Fehlermeldungen "uber nicht gefundene
+Literale bekommt, die eigentlich logisch nicht auftreten k"onnten, weil
+AS die Literale ja komplett in eigener Regie verwaltet. Treten aber bei
+der Assemblierung Fehler erst im zweiten Pass auf, so verschieben sich
+z.B. hinter der Fehlerstelle liegende Labels gegen"uber dem ersten Pass,
+weil AS f"ur die jetzt als fehlerhaft erkannten Befehle keinen Code mehr
+erzeugt. Da aber Literalnamen u.a. aus den Werten von Symbolen erzeugt
+werden, werden als Folgefehler davon eventuell andere Literalnamen
+nachgefragt, als im ersten Pass abgelegt wurden und AS beschwert sich
+"uber nicht gefundene Symbole...sollten also neben anderen Fehlern solche
+Literal-Fehler auftreten, beseitigen Sie erst die anderen Fehler, bevor
+Sie mich und alle Literale verfluchen...
+\par
+Wer aus der Motorola-Ecke kommt und PC-relative Adressierung explizit
+benutzen will (z.B. um Variablen lageunabh"angig zu erreichen), sollte
+wissen, da"s beim Ausschreiben der Adressierung nach Programmierhandbuch,
+also z.B. so:
+\begin{verbatim}
+ mov.l @(Var,PC),r8
+\end{verbatim}
+{\it keine} implizite Umrechnung der Adresse auf ein Displacement erfolgt,
+d.h. der Operand wird so eingesetzt, wie er ist (und w"urde in diesen
+Beispiel wohl mit hoher Wahrscheinlichkeit eine Fehlermeldung
+hervorrufen...). Will man beim SH7x00 PC-relativ adressieren, so tut man
+das einfach mit ,,absoluter'' Adressierung, die auf Maschinenebene ja
+gar nicht existiert:
+\begin{verbatim}
+ mov.l Var,r8
+\end{verbatim}
+Hier wird das Displacement korrekt berechnet (es gelten nat"urlich die
+gleichen Einschr"ankungen f"ur das Displacement wie bei Literalen).
+
+%%---------------------------------------------------------------------------
+
+\section{MELPS-4500}
+
+Der Programmspeicher dieser Mikrokontroller ist in Seiten zu
+128 Worten eingeteilt. Diese Einteilung existiert eigentlich nur
+deswegen, weil es Sprungbefehle gibt, deren Ziel innerhalb der
+gleichen Seite liegen darf, und andererseits ,,lange'' Exemplare,
+die den ganzen Adre"sbereich erreichen k"onnen. Die Standard-Syntax
+von Mitsubishi verlangt eigentlich, da"s Seite und Offset als getrennte
+Argument geschrieben werden m"ussen. Da das aber reichlich unpraktisch
+ist (ansonsten hat man als Programmierer keine Veranlassung, sich um
+Seiten zu k"ummern, mit der Ausnahme von indirekten Spr"ungen), erlaubt
+es AS auch wahlweise, die Zieladresse linear zu schreiben, also z.B.
+\begin{verbatim}
+ bl $1234
+\end{verbatim}
+anstelle
+\begin{verbatim}
+ bl $24,$34 .
+\end{verbatim}
+
+%%---------------------------------------------------------------------------
+
+\section{6502UNDOC}
+
+Da die undokumentierten Befehle des 6502 sich naturgem"a"s in keinem
+Datenbuch finden, sollen sie an dieser Stelle kurz aufgelistet werden.
+Die Verwendung erfolgt naturgem"a"s auf eigene Gefahr, da es keine
+Gew"ahr gibt, da"s alle Maskenversionen alle Varianten unterst"utzen!
+Bei den CMOS-Nachfolgern des 6502 funktionieren sie sowieso nicht
+mehr, da diese die ensprechenden Bitkombinationen mit offiziellen Befehlen
+belegen...
+
+%%TEMP
+\clearpage
+
+Es bedeuten:
+
+\begin{tabbing}
+\hspace{2cm} \= \kill \\
+\& \> bin"ares UND \\
+| \> bin"ares ODER \\
+\verb!^! \> bin"ares EXOR \\
+$<<$ \> logischer Linksshift \\
+$>>$ \> logischer Rechtsshift \\
+$<<<$ \> Linksrotation \\
+$>>>$ \> Rechtsrotation \\
+$\leftarrow$ \> Zuweisung \\
+(..) \> Inhalt von .. \\
+{..} \> Bits .. \\
+A \> Akkumulator \\
+X,Y \> Indexregister X,Y \\
+S \> Stapelzeiger \\
+An \> Akkumulatorbit n \\
+M \> Operand \\
+C \> Carry \\
+PCH \> obere H"alfte Programmz"ahler \\
+\end{tabbing}
+
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{JAM, KIL} oder \tty{CRS} \\
+Funktion \> : \> keine, Prozessor wird angehalten \\
+Adressierungsmodi \> : \> implizit \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{SLO} \\
+Funktion \> : \> $M\leftarrow((M)<<1)|(A)$ \\
+Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
+ \> \> Y-indiziert lang, X/Y-indirekt \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{ANC} \\
+Funktion \> : \> $A\leftarrow(A)\&(M), C\leftarrow A7$ \\
+Adressierungsmodi \> : \> immediate \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{RLA} \\
+Funktion \> : \> $M\leftarrow((M)<<1)\&(A)$ \\
+Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
+ \> \> Y-indiziert lang, X/Y-indirekt \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{SRE} \\
+Funktion \> : \> $M\leftarrow((M)>>1)$\verb!^!$(A)$ \\
+Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
+ \> \> Y-indiziert lang, X/Y-indirekt \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{ASR} \\
+Funktion \> : \> $A\leftarrow((A)\&(M))>>1$ \\
+Adressierungsmodi \> : \> immediate \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{RRA} \\
+Funktion \> : \> $M\leftarrow((M)>>>1)+(A)+(C)$ \\
+Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
+ \> \> Y-indiziert lang, X/Y-indirekt \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{ARR} \\
+Funktion \> : \> $A\leftarrow((A)\&(M))>>>1$ \\
+Adressierungsmodi \> : \> immediate \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{SAX} \\
+Funktion \> : \> $M\leftarrow(A)\&(X)$ \\
+Adressierungsmodi \> : \> absolut lang/kurz, Y-indiziert kurz, \\
+ \> \> Y-indirekt \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{ANE} \\
+Funktion \> : \> $M\leftarrow((A)\&\$ee)|((X)\&(M))$ \\
+Adressierungsmodi \> : \> immediate \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{SHA} \\
+Funktion \> : \> $M\leftarrow(A)\&(X)\&(PCH+1)$ \\
+Adressierungsmodi \> : \> X/Y-indiziert lang \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{SHS} \\
+Funktion \> : \> $X\leftarrow(A)\&(X), S\leftarrow(X), M\leftarrow(X)\&(PCH+1)$ \\
+Adressierungsmodi \> : \> Y-indiziert lang \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{SHY} \\
+Funktion \> : \> $M\leftarrow(Y)\&(PCH+1)$ \\
+Adressierungsmodi \> : \> Y-indiziert lang \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{SHX} \\
+Funktion \> : \> $M\leftarrow(X)\&(PCH+1)$ \\
+Adressierungsmodi \> : \> X-indiziert lang \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{LAX} \\
+Funktion \> : \> $A,X\leftarrow(M)$ \\
+Adressierungsmodi \> : \> absolut lang/kurz, Y-indiziert lang/kurz, \\
+ \> \> X/Y-indirekt \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{LXA} \\
+Funktion \> : \> $X{04}\leftarrow(X){04} \& (M){04},$ \\
+ \> \> $A{04}\leftarrow(A){04} \& (M){04}$ \\
+Adressierungsmodi \> : \> immediate \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{LAE} \\
+Funktion \> : \> $X,S,A\leftarrow((S)\&(M))$ \\
+Adressierungsmodi \> : \> Y-indiziert lang \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{DCP} \\
+Funktion \> : \> $M \leftarrow(M)-1, Flags\leftarrow((A)-(M))$ \\
+Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
+ \> \> Y-indiziert lang, X/Y-indirekt \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{SBX} \\
+Funktion \> : \> $X\leftarrow((X)\&(A))-(M)$ \\
+Adressierungsmodi \> : \> immediate \\
+\end{tabbing}
+\begin{tabbing}
+Adressierungsmodi \= : \= \kill \\
+Anweisung \> : \> \tty{ISB} \\
+Funktion \> : \> $M\leftarrow(M)+1, A\leftarrow(A)-(M)-(C)$ \\
+Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
+ \> \> Y-indiziert lang, X/Y-indirekt \\
+\end{tabbing}
+
+%%---------------------------------------------------------------------------
+
+\section{MELPS-740}
+
+Die Mikrokontroller dieser Reihe haben ein sehr nettes, verstecktes
+Feature: Setzt man mit dem Befehl \tty{SET} das Bit 5 des
+Statusregisters, so wird bei allen arithmetischen Operationen (und
+Ladebefehlen) der Akkumulator durch die durch das X-Register adressierte
+Speicherzelle ersetzt. Dieses Feature syntaxm"a"sig sauber zu integrieren,
+ist bisher nicht geschehen, d.h. es kann bisher nur im ,,Handbetrieb''
+(\tty{SET}...Befehle mit Akkuadressierung...\tty{CLT}) genutzt werden.
+\par
+Nicht alle MELPS-740-Prozessoren implementieren alle Befehle. An dieser
+Stelle mu"s der Programmierer aufpassen, da"s er nur die Befehle benutzt,
+die auch wirklich vorhanden sind, da AS die Prozessoren dieser Familie
+nicht n"aher unterscheidet. Die Besonderheiten der
+Special-Page-Adressierung werden bei der Erkl"arung von \tty{ASSUME} n"aher
+erl"autert.
+
+%%---------------------------------------------------------------------------
+
+\section{MELPS-7700/65816}
+\label{MELPS7700Spec}
+
+Offensichtlich haben diese beiden Prozessorfamilien ausgehend vom
+6502 ("uber ihre 8-bittigen Vorg"anger) etwas disjunkte Entwicklungswege
+hinter sich. Kurz aufgelistet, ergeben sich folgende Unterschiede:
+\begin{itemize}
+\item{der 65816 hat keinen B-Akkumulator.}
+\item{beim 65816 fehlen Multiplikations- sowie Divisionsbefehle.}
+\item{Die Befehle \tty{SEB}, \tty{CLB}, \tty{BBC}, \tty{BBS},
+ \tty{CLM}, \tty{SEM}, \tty{PSH}, \tty{PUL} und \tty{LDM}
+ fehlen beim 65816. An deren Stelle in der Code-Tabelle finden
+ sich \tty{TSB}, \tty{TRB}, \tty{BIT}, \tty{CLD}, \tty{SED},
+ \tty{XBA}, \tty{XCE} und \tty{STZ}.}
+\end{itemize}
+Identische Funktion, jedoch andere Namen haben folgende Befehle:
+\par
+\begin{center}\begin{tabular}{|c|c||c|c|}
+\hline
+ 65816 & MELPS-7700 & 65816 & MELPS-7700 \\
+\hline
+\hline
+ \tty{REP} & \tty{CLP} & \tty{PHK} & \tty{PHG} \\
+ \tty{TCS} & \tty{TAS} & \tty{TSC} & \tty{TSA} \\
+ \tty{TCD} & \tty{TAD} & \tty{TDC} & \tty{TDA} \\
+ \tty{PHB} & \tty{PHT} & \tty{PLB} & \tty{PLT} \\
+ \tty{WAI} & \tty{WIT} & & \\
+\hline
+\end{tabular}\end{center}
+\par
+Besonders t"uckisch sind die Befehle \tty{PHB}, \tty{PLB} und \tty{TSB}:
+diese Befehle haben jeweils eine v"ollig andere Funktion und Kodierung!
+\par
+Leider tun diese Prozessoren mit ihrem Speicher etwas, was f"ur mich
+auf der nach oben offenen Perversit"atsskala noch vor der
+Intel-m"a"sigen Segmentierung rangiert: sie banken ihn!
+Nunja, dies ist wohl der Preis f"ur die 6502-Aufw"artskompatibilit"at;
+wie dem auch sei, damit AS den gew"unschten Code erzeugen kann, mu"s
+man ihn "uber den \tty{ASSUME}-Befehl "uber den Inhalt einiger
+Register in Kenntnis setzen:
+\par
+Das M-Flag bestimmt, ob die Akkumulatoren A und B 8 Bit (1) oder 16 Bit
+(0) breit sein sollen. Analog entscheidet das Flag X "uber die Breite
+der Indexregister X und Y. AS ben"otigt die Information "uber die
+Registerbreite bei unmittelbarer Adressierung (\tty{\#<Konstante>}), ob das
+Argument 8 oder 16 Bit breit sein soll.
+\par
+Der Speicher ist in 256 B"anke zu 64 Kbyte geteilt. Da alle Register
+im Prozessor nur maximal 16 Bit breit sind, kommen die obersten 8
+Adre"sbits aus 2 speziellen Bank-Registern: DT liefert die oberen 8
+Bits bei Datenzugriffen, PG erweitert den 16-bittigen Programmz"ahler
+auf 24 Bit. Die vom 6502 her bekannte ,,Zero-Page'' ist mittels
+des 16 Bit breiten Registers DPR frei innerhalb der ersten Bank
+verschiebbar. Trifft AS nun im Code auf eine Adresse (egal ob in
+einem absoluten, indizierten oder indirekten Ausdruck), so versucht
+er der Reihe nach folgende Adressierungsvarianten:
+\begin{enumerate}
+\item{Liegt die Adresse im Bereich von DPR...DPR+\$ff? Falls ja,
+ Verwendung von direkter Adressierung mit 8-Bit-Adresse.}
+\item{Liegt die Adresse innerhalb der durch DT (bzw. PG f"ur
+ Sprungbefehle) festgelegten Seite? Falls ja, Verwendung von
+ absoluter Adressierung mit 16-Bit-Adresse.}
+\item{Falls nichts anderes hilft, Verwendung von langer Adressierung
+ mit 24-Bit-Adresse.}
+\end{enumerate}
+Aus dieser Aufz"ahlung folgt, da"s das Wissen "uber die momentanen
+Werte von DT,PG und DPR f"ur die Funktion von AS essentiell ist;
+sind die Angaben fehlerhaft, adressiert das Programm ,,in die W"uste''.
+Diese Aufz"ahlung geht "ubrigens davon aus, da"s alle drei
+Adre"sl"angen verf"ugbar sind; sollte dies einmal nicht der Fall sein,
+so wird die Entscheidungskette entsprechen k"urzer.
+
+Die oben geschilderte, automatische Festlegung der Adre"sl"ange l"a"st
+sich auch durch die Verwendung von Pr"afixen "ubersteuern. Stellt
+man der Adresse ein $<$, $>$ oder $>>$ ohne trennendes Leerzeichen voran,
+so wird eine Adresse mit 1, 2 oder 3 Bytes benutzt, unabh"angig davon,
+ob dies die optimale L"ange ist. Benutzt man eine f"ur diesen Befehl
+nicht erlaubte oder f"ur die Adresse zu kurze L"ange, gibt es eine
+Fehlermeldung.
+
+Um die Portierung von 6502-Programmen zu erleichtern, verwendet AS f"ur
+Hexadezimalkonstanten die Motorola-Syntax und nicht die von Mitsubishi
+"ubrigens f"ur die 740er favorisierte Intel/IEEE-Schreibweise.
+Ich halte erstere auch f"ur die bessere Schreibweise, und die Entwickler
+des 65816 werden dies vermutlich "ahnlich gesehen haben (da man mittels
+der \tty{RELAXED}-Anweisung auch Intel-Notation benutzen kann, wird durch
+diese Entscheidung auch niemand festgelegt). Ein f"ur die
+Portierung "ahnlich wichtiges Detail ist, da"s der Akkumulator A als
+Ziel von Operationen auch weggelassen werden darf, anstelle von
+\tty{LDA A,\#0} darf also z.B. auch einfach \tty{LDA \#0} geschrieben
+werden.
+\par
+Ein echtes Bonbon in dem Befehlssatz sind dagegen die Blocktransferbefehle
+\tty{MVN} und \tty{MVP}. Etwas eigenartig ist nur die Adre"sangabe:
+Bit 0--15 im Indexregister, Bit 16--23 im Befehl. Bei AS gibt man als
+Argument f"ur beide Speicherbl"ocke einfach die vollen Adressen an, AS
+fischt sich dann die passenden Bits automatisch heraus. Dies ist ein
+feiner, aber wichtiger Unterschied zum Mitsubishi-Assembler, bei dem
+man die oberen 8 Bit selber herausziehen mu"s. Richtig bequem
+wird es aber erst mit einem Makro im folgendem Stil:
+\begin{verbatim}
+mvpos macro src,dest,len
+ if MomCPU=$7700
+ lda #len
+ elseif
+ lda #(len-1)
+ endif
+ ldx #(src&$ffff)
+ ldy #(dest&$ffff)
+ mvp dest,src
+ endm
+\end{verbatim}
+Vorsicht, Falle: Steht im Akkumulator die Zahl $n$, so transferiert
+der Mitsubishi $n$ Bytes, der 65816 jedoch $n+1$ Bytes!
+\par
+Sehr nett sind auch die Befehle \tty{PSH} und \tty{PUL}, mit deren Hilfe es
+m"oglich ist, mit einem Befehl einen frei w"ahlbaren Satz von Registern
+auf dem Stack zu sichern oder von ihm zu laden. Nach dem
+Mitsubishi-Datenbuch\cite{Mit16} mu"s die Angabe der Bitmasken immediate
+erfolgen, der Programmierer soll also entweder alle
+Register$\leftrightarrow$Bitstellen-Zuordnungen im Kopf behalten oder
+sich passende Symbole definieren. Hier habe ich die Syntax eigenm"achtig
+erweitert, um die Sache etwas angenehmer zu machen: Es darf eine Liste
+angegeben werden, die sowohl immediate-Ausdr"ucke als auch Registernamen
+enthalten darf. Damit sind z.B. die Anweisungen
+\begin{verbatim}
+ psh #$0f
+\end{verbatim}
+und
+\begin{verbatim}
+ psh a,b,#$0c
+\end{verbatim}
+und
+\begin{verbatim}
+ psh a,b,x,y
+\end{verbatim}
+"aquivalent. Da die immediate-Version weiterhin erlaubt ist, bleibt
+AS hier ,,aufw"artskompatibel'' zu den Mitsubishi-Assemblern.
+\par
+Nicht ganz habe ich beim Mitsubishi-Assembler die Behandlung des
+\tty{PER}-Befehles verstanden: Mit diesem Befehl kann man eine
+16-Bit-Variable auf den Stack legen, deren Adresse relativ zum
+Programmz"ahler angegeben wird. Es ist aus der Sicht des Programmierers
+also eine absolute Adressierung einer Speicherzelle. Nichtsdestotrotz
+verlangt Mitsubishi eine immediate-Adressierung, und das Argument wird so
+in den Code eingesetzt, wie es im Quelltext steht. Die Differenz mu"s
+man selber ausrechnen, was mit der Einf"uhrung von symbolischen Assemblern
+ja abgeschafft werden sollte...da ich aber auch ein bi"schen ,,kompatibel''
+denken mu"s, enth"alt AS eine Kompromi"sl"osung: W"ahlt man
+immediate-Adressierung (also mit Gartenzaun), so verh"alt sich AS wie das
+Original von Mitsubishi. L"a"st man ihn jedoch weg, so berechnet AS die
+Differenz vom Argument zum momentanen Programmz"ahler und setzt diese
+ein.
+\par
+"Ahnlich sieht es beim \tty{PEI}-Befehl aus, der den Inhalt einer
+16-Bit-Variablen auf der Zeropage auf den Stack legt: Obwohl der Operand
+eine Adresse ist, wird wieder immediate-Adressierung verlangt. Hier
+l"a"st AS schlicht beide Versionen zu (d.h. mit oder ohne Gartenzaun).
+
+%%---------------------------------------------------------------------------
+
+\section{M16}
+
+Die M16-Familie ist eine Familie "au"serst komplexer CISC-Prozessoren
+mit einem entsprechend komplizierten Befehlssatz. Zu den Eigenschaften
+dieses Befehlssatzes geh"ort es unter anderem, da"s bei Operationen
+mit zwei Operanden beide Operanden verschiedene L"angen haben d"urfen.
+Die bei Motorola "ubliche und von Mitsubishi "ubernommene Methode, die
+Operandengr"o"se als Attribut an den Befehl anzuh"angen, mu"ste daher
+erweitert werden: Es ist erlaubt, auch an die Operanden selber Attribute
+anzuh"angen. So wird im folgenden Beispiel
+\begin{verbatim}
+ mov r0.b,r6.w
+\end{verbatim}
+Register 0 8-bittig gelesen, auf 32 Bit vorzeichenerweitert und das
+Ergebnis in Register 6 kopiert. Da man in 9 von 10 F"allen aber von
+diesen M"oglichkeiten doch keinen Gebrauch macht, kann man weiterhin
+die Operandengr"o"se an den Befehl selber schreiben, z.B. so:
+\begin{verbatim}
+ mov.w r0,r6
+\end{verbatim}
+Beide Varianten d"urfen auch gemischt verwendet werden, eine
+Gr"o"senangabe am Operanden "ubersteuert dann den ,,Default'' am Befehl.
+Eine Ausnahme stellen Befehle mit zwei Operanden dar. Bei diesen ist
+der Default f"ur den Quelloperanden die Gr"o"se des Zieloperanden. In
+folgendem Beispiel
+\begin{verbatim}
+ mov.h r0,r6.w
+\end{verbatim}
+wird also auf Register 0 32-bittig zugegriffen, die Gr"o"senangabe
+am Befehl wird "uberhaupt nicht mehr benutzt. Finden sich "uberhaupt
+keine Angaben zur Operandengr"o"se, so wird Wort(w) verwendet. Merke:
+im Gegensatz zu den 68000ern bedeutet dies 32 und nicht 16 Bit!
+\par
+Reichlich kompliziert sind auch die verketteten Adressierungsmodi;
+dadurch, da"s AS die Verteilung auf Kettenelemente automatisch
+vornimmt, bleibt die Sache aber einigerma"sen "ubersichtlich. Die
+einzige Eingriffsm"oglichkeit, die bei AS gegeben ist (der Originalassembler
+von Mitsubishi/Green Hills kann da noch etwas mehr), ist die explizite
+Festlegung von Displacement-L"angen mittels der Anh"angsel \tty{:4},
+\tty{:16} und \tty{:32}.
+
+%%---------------------------------------------------------------------------
+
+\section{4004}
+
+Noch ein St"uck Geschichte...leider habe ich noch keine offizielle
+Dokumentation zum ersten Mikroprozessor "uberhaupt gefunden, und da gibt
+es noch das eine oder andere Loch: Die Syntax f"ur Registerpaare (f"ur
+8-Bit-Operationen) ist mir noch nicht ganz klar. Momentan ist die Syntax
+\tty{RnRm}, wobei \tty{n} bzw. \tty{m} gerade Integers im Bereich 0 bis E
+bzw. 1 bis F sind. Dabei gilt immer \tty{m = n + 1}.
+
+%%---------------------------------------------------------------------------
+
+\section{MCS-48}
+
+Der maximale Adre"sraum dieser Prozessoren betr"agt 4 Kbyte. Dieser Raum
+ist jedoch nicht linear organisiert (wie k"onnte das bei Intel auch anders
+sein...), sondern in 2 B"anke zu 2 Kbyte geteilt. Ein Wechsel zwischen
+diesen beiden B"anken ist nur durch die Befehle \tty{CALL} und \tty{JMP}
+erlaubt, indem vor dem Sprung das h"ochste Adre"sbit mit den Befehlen
+\tty{SEL MB0} bzw. \tty{SEL MB1} vorgegeben wird.
+Um den Wechsel zwischen den B"anken zu vereinfachen, ist
+eine Automatik in den Befehlen \tty{JMP} und \tty{CALL} eingebaut, die einen dieser
+beiden Befehle einf"ugt, falls die Adresse des Sprungbefehles und das
+Sprungziel in unterschiedlichen B"anken liegen. Die explizite Benutzung der
+\tty{SEL MBx}-Befehle sollte daher nicht notwendig sein (obwohl sie m"oglich
+ist) und kann die Automatik auch durcheinanderbringen, wie in dem folgenden
+Beispiel:
+\begin{verbatim}
+000: SEL MB1
+ JMP 200h
+\end{verbatim}
+AS nimmt an, da"s das MB-Flag auf 0 steht und f"ugt keinen
+\tty{SEL MB0}-Befehl vor dem Sprung ein, mit der Folge, da"s der
+Prozessor zur Adresse A00h springt.
+Weiterhin ist zu beachten, da"s ein Sprungbefehl durch diesen Mechanismus
+unter Umst"anden ein Byte l"anger wird.
+
+%%---------------------------------------------------------------------------
+
+\section{MCS-51}
+
+Dem Assembler liegen die Dateien STDDEF51.INC bzw. 80C50X.INC bei, in
+denen alle Bits und SFRs der Prozessoren 8051, 8052 und 80515 bzw. 80C501,
+502 und 504 verzeichnet sind. Je nach Einstellung des Prozessortyps mit
+dem \tty{CPU}-Befehl wird dabei die korrekte Untermenge eingebunden, die
+richtige Reihenfolge f"ur den Anfang eines Programmes ist daher
+\begin{verbatim}
+ CPU <Prozessortyp>
+ INCLUDE stddef51.inc ,
+\end{verbatim}
+sonst f"uhren die MCS-51-Pseudobefehle in der Include-Datei zu
+Fehlermeldungen.
+\par
+Da der 8051 keinen Befehl kennt, um die Register 0..7 auf den Stack zu
+legen, mu"s mit deren absoluten Adressen gearbeitet werden. Diese
+h"angen aber von der momentan aktiven Registerbank ab. Um diesem Mi"sstand
+etwas abzuhelfen, ist in den Include-Dateien das Makro \tty{USING} definiert,
+dem als Parameter die Symbole \tty{Bank0..Bank3} gegeben werden k"onnen.
+Das Makro belegt daraufhin die Symbole \tty{AR0..AR7} mit den passenden
+absoluten Adressen der Register. Dieses Makro sollte nach jeder
+Bankumschaltung benutzt werden. Es erzeugt selber \ii{keinen} Code zur
+Umschaltung!
+\par
+Das Makro f"uhrt in der Variablen \tty{RegUsage} gleichzeitig Buch "uber
+alle jemals benutzten Registerb"anke; Bit 0 entspricht Bank 0, Bit 1 der
+Bank 1 usw. . Der Inhalt kann am Ende der Quelldatei z.B. mit folgendem
+Codest"uck ausgegeben werden:
+\begin{verbatim}
+ irp BANK,Bank0,Bank1,Bank2,Bank3
+ if (RegUsage&(2^BANK))<>0
+ message "Bank \{BANK} benutzt"
+ endif
+ endm
+\end{verbatim}
+Mit der Mehrpass-F"ahigkeit ab Version 1.38 wurde es m"oglich, zus"atzlich
+die Befehle \tty{JMP} und \tty{CALL} einzuf"uhren. Bei der Kodierung
+von Spr"ungen mit diesen Befehlen w"ahlt AS je nach Adre"slage automatisch
+die optimale Variante, d.h. \tty{SJMP/AJMP/LJMP} f"ur \tty{JMP} und
+\tty{ACALL/LCALL} f"ur \tty{CALL}. Es ist nat"urlich weiterhin m"oglich,
+die Varianten direkt zu verwenden, um eine bestimmte Kodierung zu erzwingen.
+
+%%---------------------------------------------------------------------------
+
+\section{MCS-251}
+
+Intel hat sich beim 80C251 ja bem"uht, den "Ubergang f"ur den Programmierer
+auf die neue Familie so weich wie m"oglich zu gestalten, was darin gipfelt,
+da"s alte Anwendungen ohne Neu"ubersetzung auf dem neuen Prozessor ablaufen
+k"onnen. Sobald man jedoch den erweiterten Befehlssatz der 80C251 nutzen
+will, gilt es, einige Details zu beachten, die sich als versteckte
+Fu"sangeln auftun.
+\par
+An vorderster Stelle steht dabei die Tatsache, da"s der 80C251 keinen
+getrennten Bitadre"sraum mehr hat. Es sind nunmehr alle SFRs unabh"angig
+von ihrer Adre"slage sowie die ersten 128 Speicherstellen des internen
+RAMs bitadressierbar. M"oglich wird dies dadurch, da"s die Bitadressierung
+nicht mehr "uber einen zus"atzlichen virtuellen Adre"sraum, der andere
+Adre"sr"aume "uberdeckt, erfolgt, sondern so wie bei anderen Prozessoren
+auch durch eine zweidimensionale Adressierung, die aus der Speicherstelle,
+die das Bit beinhaltet sowie der Bitstelle im Byte besteht. Dies bedeutet
+zum einen, da"s bei einer Bitangabe wie z.B. PSW.7 AS die Zerlegung der
+Teile links und rechts vom Punkt selber vornimmt. Es ist also nicht mehr
+n"otig, mittels eines \tty{SFRB}-Befehls wie noch beim 8051 explizit 8
+Bitsymbole zu erzeugen. Dies bedeutet zum anderen, da"s es den
+\tty{SFRB}-Befehl "uberhaupt nicht mehr gibt. Wird er in zu portierenden
+8051-Programmen benutzt, kann er durch einen einfachen \tty{SFR}-Befehl
+ersetzt werden.
+\par
+Weiterhin hat Intel in den unterschiedlichen Adre"sr"aumen des 8051
+geh"orig aufger"aumt: Der Bereich des internen RAMs (\tty{DATA} bzw.
+\tty{IDATA}), der \tty{XDATA}-Bereich und er bisherige \tty{CODE}-Bereich
+wurden in einem einzigen, 16 Mbyte gro"sen \tty{CODE}-Bereich vereinigt.
+Das interne RAM beginnt bei Adresse 0, das interne ROM beginnt bei
+Adresse ff0000h, dorthin mu"s also auch der Code mittels \tty{ORG}
+hinverlagert werden. Ausgelagert wurden dagegen die \tty{SFRs} in einen
+eigenen Adre"sraum (der bei AS als \tty{IO}-Segment definiert ist). In
+diesem neuen Adre"sraum haben sie aber die gleichen Adressen wie beim 8051.
+Der \tty{SFR}-Befehl kennt diesen Unterschied und legt mit ihm erzeugte
+Symbole je nach Zielprozessor automatisch ins \tty{DATA}- bzw.
+\tty{IO}-Segment. Da es keinen Bit-Adre"sraum mehr gibt, funktioniert der
+\tty{BIT}-Befehl v"ollig anders: anstelle einer linearen Adresse von 0 bis
+255 beinhalten Bit-Symbole jetzt in Bit 0..7 die Adresse, in Bit 24..26
+die Bitstelle. Damit ist es jetzt leider nicht mehr so einfach m"oglich,
+Felder von Flags mit symbolischen Namen anzulegen: Wo man beim 8051 noch
+z.B.
+\begin{verbatim}
+ segment bitdata
+
+bit1 db ?
+bit2 db ?
+\end{verbatim}
+oder
+\begin{verbatim}
+defbit macro name
+name bit cnt
+cnt set cnt+1
+ endm
+\end{verbatim}
+schreiben konnte, hilft jetzt nur noch die zweite Variante weiter, z.B.
+so:
+\begin{verbatim}
+adr set 20h ; Startadresse Flags im internen RAM
+bpos set 0
+
+defbit macro name
+name bit adr.bpos
+bpos set bpos+1
+ if bpos=8
+bpos set 0
+adr set adr+1
+ endif
+ endm
+\end{verbatim}
+Ein weiteres, kleines Detail: Da Intel als Kennzeichnung f"ur den Carry
+nun CY statt C bevorzugt, sollte man ein eventuell benutztes Symbol
+umbenennen. AS versteht aber auch weiterhin die alte Variante in den
+Befehlen \tty{CLR, CPL, SETB, MOV, ANL,} und \tty{ORL}. Gleiches gilt
+sinngem"a"s f"ur die dazugekommenen Register \tty{R8..R15, WR0..WR30,
+DR0..DR28, DR56, DR60, DPX} und \tty{SPX}.
+\par
+Intel m"ochte es gerne, da"s man absolute Adressen in der Form \tty{XX:YYYY}
+schreibt, wobei \tty{XX} eine 64K-Bank im Adre"sraum angibt bzw. mit einem
+\tty{S} Adressen im IO-Raum kennzeichnet. Wie man sich schon denken kann,
+halte ich davon nicht allzu viel, weshalb man an allen Stellen Adressen
+genauso gut linear angeben kann; lediglich um das S f"ur die Kennzeichnung
+von I/O-Adressen kommt man nicht herum, z.B. hier:
+\begin{verbatim}
+Carry bit s:0d0h.7
+\end{verbatim}
+Ohne den Pr"afix w"urde AS die absolute Adresse in das Code-Segment
+legen, und dort sind ja nur die ersten 128 Byte bitadressierbar...
+\par
+Wie auch schon beim 8051 gibt es die generischen Befehle \tty{JMP} und
+\tty{CALL}, die je nach Adre"slage automatisch die k"urzeste Variante
+einsetzen. W"ahrend \tty{JMP} aber die Variante mit 24 Bit mitber"ucksichtigt,
+tut \tty{CALL} dies aus gutem Grund nicht: Der \tty{ECALL}-Befehl legt
+n"amlich im Gegensatz zu \tty{ACALL} und \tty{LCALL} 3 Bytes auf den
+Stack, und man h"atte sonst einen \tty{CALL}-Befehl, bei dem man nicht
+mehr genau wei"s, was er tut. Bei \tty{JMP} tritt diese Problem nicht auf.
+\par
+Aus einer Sache bin ich nicht ganz schlau geworden: Der 80251 kann
+auch immediate-Operanden auf den Stack legen, und zwar sowohl einzelne
+Bytes als auch ganze W"orter. F"ur beide Varianten ist aber der gleiche
+Befehl \tty{PUSH} vorgesehen -- und woher soll bitte ein Assembler bei
+einer Anweisung wie
+\begin{verbatim}
+ push #10
+\end{verbatim}
+wissen, ob ein Byte oder ein Wort mit dem Wert 10 auf den Stack gelegt
+werden soll? Daher gilt im Augenblick die Regelung, da"s \tty{PUSH}
+grunds"atzlich ein Byte ablegt; wer ein Wort ablegen will, schreibt
+einfach \tty{PUSHW} anstelle \tty{PUSH}.
+\par
+Noch ein gutgemeinter Ratschlag: Wer den erweiterten Befehlssatz des
+80C251 nutzt, sollte den Prozessor auch tunlichst im Source-Modus
+betreiben, sonst werden alle neuen Anweisungen ein Byte l"anger! Um
+die origin"aren 8051-Anweisungem, die daf"ur im Source-Modus l"anger
+werden, ist es nicht besonders schade: Sie werden entweder von AS
+automatisch durch neue, leistungsf"ahigere ersetzt oder sind be-
+treffen veraltete Adressierungsarten (indirekte Adressierung mit
+8-Bit-Registern).
+
+%%---------------------------------------------------------------------------
+
+\section{8086..V35}
+
+Eigentlich hatte ich mir geschworen, die Segmentseuche der 8086er aus diesem
+Assembler herauszuhalten. Da aber nun eine Nachfrage kam und Studenten
+flexiblere Menschen als die Entwickler dieses Prozessors sind, findet sich
+ab sofort auch eine rudiment"are Unterst"utzung dieser Prozessoren in AS.
+Unter ,,rudiment"ar'' verstehe ich dabei nicht, da"s der Befehlssatz nicht
+vollst"andig abgedeckt wird, sondern da"s ich nicht den ganzen Wust an
+Pseudoanweisungen integriert habe, die sich bei MASM, TASM \& Co. finden.
+AS ist auch nicht in erster Linie geschrieben worden, um PC-Programme zu
+entwickeln (Gott bewahre, das hie"se wirklich, das Rad neu zu erfinden),
+sondern zur Programmentwicklung f"ur Einplatinenrechner, die eben unter
+anderem auch mit 8086ern best"uckt sein k"onnen.
+\par
+F"ur Unentwegte, die mit AS doch DOS-Programme schreiben wollen, eine kleine
+Liste dessen, was zu beachten ist:
+\begin{itemize}
+\item{Es k"onnen nur COM-Programme erzeugt werden.}
+\item{Verwenden Sie nur das \tty{CODE}-Segment, und legen Sie auch alle
+ Variablen darin ab.}
+\item{Alle Segmentregister werden von DOS auf das Codesegment
+ vorinitialisiert. Ein \tty{ASSUME DS:CODE, SS:CODE} am
+ Programmanfang ist daher notwendig.}
+\item{DOS l"adt den Code ab Adresse 100h. Ein \tty{ORG} auf diese
+ Adresse ist daher zwingend.}
+\item{Die Umwandlung in eine Bin"ardatei erfolgt mit P2BIN (s.u.), wobei als
+ als Adre"sbereich \tty{\$-\$} anzugeben ist.}
+\end{itemize}
+Allgemein unterst"utzt AS f"ur diese Prozessoren nur ein Small-Programmiermodell, d.h.
+\ii{ein} Codesegment mit maximal 64 KByte und ein ebenfalls h"ochstens 64
+KByte gro"ses Datensegment mit (f"ur COM-Dateien uninitialisierten) Daten.
+Zwischen diesen beiden Segmenten kann mit dem \tty{SEGMENT}-Befehl hin-und hergeschaltet werden.
+Aus dieser Tatsache folgert, da"s Spr"unge immer intrasegment"ar sind,
+sofern sie sich auf Adressen im Codesegment beziehen. Falls weite Spr"unge
+doch einmal erforderlich sein sollten, k"onnen sie mit \tty{CALLF} und
+\tty{JMPF} und einer Speicheradresse oder einen Segment:Offset-Wert als
+Argument erreicht werden.
+\par
+Ein weiteres gro"ses Problem dieser Prozessoren ist deren Assemblersyntax,
+deren genaue Bedeutung nur aus dem Zusammenhang erkennbar ist. So kann im
+folgenden Beispiel je nach Symboltyp sowohl unmittelbare als auch absolute
+Adressierung gemeint sein:
+\begin{verbatim}
+ mov ax,wert
+\end{verbatim}
+Bei AS ist immer unmittelbare Adressierung gemeint, wenn um den Operanden
+keine eckigen Klammern stehen. Soll z.B. die Adresse oder der Inhalt einer
+Variablen geladen werden, so ergeben sich die in Tabelle \ref{TabMASM}
+aufgelisteten Unterschiede.
+\begin{table*}
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+Assembler & Adresse & Inhalt \\
+\hline
+\hline
+MASM & \tty{mov ax,offset vari} & \tty{mov ax,vari} \\
+ & \tty{lea ax,vari} & \tty{mov ax,[vari]} \\
+ & \tty{lea ax,[vari]} & \\
+ & & \\
+AS & \tty{mov ax,vari} & \tty{mov ax,[vari]} \\
+ & \tty{lea ax,[vari]} & \\
+ & & \\
+\hline
+\end{tabular}\end{center}
+\caption{Unterschiede in der Adressierungssyntax AS$\leftrightarrow$MASM\label{TabMASM}}
+\normalsize
+\end{table*}
+\par
+Der Assembler pr"uft bei Symbolen, ob sie im Datensegment liegen und
+versucht, automatisch einen passenden Segmentpr"afix einzuf"ugen, z.B.
+falls ohne CS-Pr"afix auf Symbole im Code zugegriffen wird. Dieser
+Mechanismus kann jedoch nur funktionieren, falls der \tty{ASSUME}-Befehl
+(siehe dort) korrekt angewendet wurde.
+\par
+Die Intel-Syntax verlangt eine Abspeicherung, ob an einem Symbol Bytes oder
+W"orter abgelegt wurden. AS nimmt diese Typisierung nur vor, falls in der
+gleichen Zeile wie das Label ein \tty{DB} oder \tty{DW} steht. F"ur alle anderen F"alle
+mu"s mit den Operatoren \tty{WORD PTR, BYTE PTR} usw. explizit angegeben werden,
+um was f"ur eine Operandengr"o"se es sich handelt. Solange ein Register an der
+Operation beteiligt ist, kann auf diese Kennzeichnung verzichtet werden, da
+durch den Registernamen die Operandengr"o"se eindeutig bestimmt ist.
+\par
+Der Koprozessor in 8086-Systemen wird "ublicherweise durch den TEST-Eingang
+des Prozessors synchronisiert, indem selbiger mit dem BUSY-Ausgang des
+Koprozessors verbunden wird. AS unterst"utzt dieses Handshaking, indem
+vor jedem 8087-Befehl automatisch ein \tty{WAIT}-Befehl eingef"ugt wird. Ist
+dies aus irgendwelchen Gr"unden unerw"unscht (z.B. w"ahrend der
+Initialisierung), so mu"s im Opcode hinter dem \tty{F} ein \tty{N} eingef"ugt
+werden; aus
+\begin{verbatim}
+ FINIT
+ FSTSW [vari]
+\end{verbatim}
+wird so z.B.
+\begin{verbatim}
+ FNINIT
+ FNSTSW [vari]
+\end{verbatim}
+Diese Variante ist bei \ii{allen} Koprozessorbefehlen erlaubt.
+
+%%---------------------------------------------------------------------------
+
+\section{8X30x}
+\label{8X30xSpec}
+
+Die Prozessoren dieser Reihe sind auf eine einfache Manipulation von
+Bitgruppen auf Peripherieadressen optimiert worden. Um mit solchen
+Bitgruppen auch symbolisch umgehen zu k"onnen, existieren die Befehle
+\tty{LIV} und \tty{RIV}, mit denen einer solchen Bitgruppe ein
+symbolischer Name zugewiesen wird. Diese Befehle arbeiten "ahnlich
+wie \tty{EQU}, ben"otigen aber drei Parameter:
+\begin{enumerate}
+\item{die Adresse der peripheren Speicherzelle, in der sich die
+ Bitgruppe befindet (0..255);}
+\item{die Bitnummer des ersten Bits in der Gruppe (0..7);}
+\item{die L"ange der Gruppe in Bits (1..8).}
+\end{enumerate}
+\bb{ACHTUNG!} Der 8X30x unterst"utzt keine Bitgruppen, die "uber mehrere
+Speicherstellen hinausreichen, so da"s je nach Startposition der
+Wertebereich f"ur die L"ange eingeschr"ankt sein kann. AS nimmt hier
+\bb{keine} Pr"ufung vor, man bekommt lediglich zur Laufzeit merkw"urdige
+Ergebnisse!
+
+Im Maschinencode dr"ucken sich L"ange und Position durch ein 3-Bit-Feld
+im Instruktionswort sowie ein passende Registernummer (\tty{LIVx} bzw.
+\tty{RIVx}) aus. Bei der Verwendung eines symbolischen Objektes wird AS
+diese Felder automatisch richtig besetzen, es ist aber auch erlaubt,
+die L"ange als dritten Operanden explizit anzugeben, wenn man nicht
+mit symbolischen Busobjekten arbeitet. Trifft AS auf eine L"angenangabe
+trotz eines symbolischen Operanden, so vergleicht er beide L"angen
+und gibt eine Fehlermeldung bei Ungleichheit aus (das gleiche passiert
+"ubrigens auch, wenn man bei einem \tty{MOVE}-Befehl zwei symbolische
+Operanden mit unterschiedlicher L"ange benutzt - die Instruktion hat
+einfach nur ein L"angenfeld...).
+
+Neben den eigentlichen Maschinenbefehlen des 8X30x implementiert AS
+noch "ahnlich wie das ,,Vorbild'' MCCAP einige Pseudoinstruktionen, die
+als eingebaute Makros ausgef"uhrt sind:
+\begin{itemize}
+\item{\tty{NOP} ist eine Kurzschreibweise f"ur \tty{MOVE AUX,AUX}}
+\item{\tty{HALT} ist eine Kurzschreibweise f"ur \tty{JMP \verb!*!}}
+\item{\tty{XML ii} ist eine Kurzschreibweise f"ur \tty{XMIT ii,R12} (nur
+ 8X305)}
+\item{\tty{XMR ii} ist eine Kurzschreibweise f"ur \tty{XMIT ii,R13} (nur
+ 8X305)}
+\item{\tty{SEL $<$busobj$>$} ist eine Kurzschreibweise f"ur
+ \tty{XMIT $<$adr$>$,IVL/IVR}, f"uhrt also die notwendige Vorselektion
+ durch, um \tty{$<$busobj$>$} ansprechen zu k"onnen.}
+\end{itemize}
+Die bei MCCAP ebenfalls noch vorhandenen \tty{CALL-} und
+\tty{RTN-}Instruktionen sind mangels ausreichender Dokumentation momentan
+nicht implementiert. Das gleiche gilt f"ur einen Satz an
+Pseudoinstruktionen zur Datenablage. Kommt Zeit, kommt Rat...
+
+%%---------------------------------------------------------------------------
+
+\section{XA}
+
+"Ahnlich wie sein Vorg"anger MCS/51, jedoch im Unterschied zu seinem
+,,Konkurrenten'' MCS/251 besitzt der Philips XA einen getrennten Bitadre"sraum,
+d.h. alle mit Bitbefehlen manipulierbaren Bits haben eine
+bestimmte, eindimensionale Adresse, die in den Maschinenbefehlen auch
+so abgelegt wird. Die naheliegende M"oglichkeit, diesen dritten
+Adre"sraum (neben Code und Daten) auch so in AS anzubieten, habe ich
+nicht nutzen k"onnen, und zwar aus dem Grund, da"s ein Teil der Bitadressen
+im Gegensatz zum MCS/51 nicht mehr eindeutig ist: Bits mit
+den Adressen 256 bis 511 bezeichnen Bits der Speicherzellen 20h..3fh
+aus dem aktuellen Datensegment. Dies bedeutet aber, da"s diese Adressen
+je nach Situation unterschiedliche Bits ansprechen k"onnen - ein definieren
+von Bits mit Hilfe von \tty{DC}-Befehlen, was durch ein extra Segment
+m"oglich geworden w"are, w"urde also nicht "uberm"a"sig viel Sinn ergeben.
+Zur Definition einzelner, symbolisch ansprechbarer Bits steht aber
+nach wie vor der \tty{BIT}-Befehl zur Verf"ugung, mit dem beliebige Bitadressen
+(Register, RAM, SFR) definiert werden k"onnen. F"ur Bitadressen im
+internen RAM wird auch die 64K-Bank-Adresse gespeichert, so da"s AS
+Zugriffe "uberpr"ufen kann, sofern das DS-Register korrekt mit \tty{ASSUME}
+vorbesetzt wurde.
+\par
+Nichts drehen kann man dagegen an den Bem"uhungen von AS, potentielle
+Sprungziele (also Zeilen im Code mit Label) auf gerade Adressen
+auszurichten. Dies macht AS genauso wie andere XA-Assembler auch durch
+Einf"ugen von \tty{NOP}s vor dem fraglichen Befehl.
+
+%%---------------------------------------------------------------------------
+
+\section{AVR}
+
+Im Gegensatz zum AVR-Assembler verwendet AS defaultm"a"sig das Intel-Format
+zur Darstellung von Hexadezimalkonstanten und nicht die C-Syntax. OK, nicht
+vorher in den (freien) AVR-Assembler hineingeschaut, aber als ich mit dem
+AVR-Teil anfing, gab es zum AVR noch nicht wesentlich mehr als ein
+vorl"aufiges Datenbuch mit Prozessortypen, die dann doch nie kamen...mit
+einem \tty{RELAXED ON} schafft man dieses Problem aus der Welt.
+
+Optional kann AS f"ur die AVRs (es geht auch f"ur andere CPU's, nur
+macht es dort keinen Sinn...) sogenannte ,,Objekt-Dateien'' erzeugen.
+Das sind Dateien, die sowohl Code als auch Quellzeileninformationen
+enthalten und z.B. eine schrittweise Abarbeitung auf Quellcodeebene
+mit dem von Atmel gelieferten Simulator WAVRSIM erlauben. Leider
+scheint dieser mit Quelldateispezifikationen, die l"anger als ca. 20
+Zeichen sind, seine liebe Not zu haben: Namen werden abgeschnitten
+oder um wirre Sonderzeichen erg"anzt, wenn die Maximall"ange "uberschritten
+wird. AS speichert deshalb in den Objekt-Dateien Dateinamen ohne
+Pfadangabe, so da"s es eventuell Probleme geben k"onnte, wenn
+Dateien (z.B. Includes) nicht im Arbeitsverzeichnis liegen.
+
+Eine kleine Besonderheit sind Befehle, die Atmel bereits in der
+Architektur vorgesehen hat, aber noch in keinem Mitglied der Familie
+implementiert wurden. Dabei handelt es sich um die Befehle {\tt MUL, JMP}
+und {\tt CALL}. Besonders bei letzteren fragt man sich vielleicht, wie man
+denn nun den 4 KWorte gro"sen Adre"sraum des AT90S8515 erreichen kann,
+wenn die 'n"achstbesten' Befehle {\tt RJMP} und {\tt RCALL} doch nur 2
+KWorte weit springen kann. Der Kunstgriff lautet 'Abschneiden der oberen
+Adre"sbits' und ist n"aher bei der {\tt WRAPMODE}-Anweisung beschrieben.
+
+%%---------------------------------------------------------------------------
+
+\section{Z80UNDOC}
+
+Da es von Zilog naturgem"a"s keine Syntaxvorgaben f"ur die undokumentierten
+Befehle gibt und wohl auch nicht jeder den kompletten Satz kennt,
+ist es vielleicht sinnvoll, diese Befehle hier kurz aufzuz"ahlen:
+\par
+Wie auch beim Z380 ist es m"oglich, die Byte-H"alften von IX und IY
+einzeln anzusprechen. Im einzelnen sind dies folgende Varianten:
+\begin{verbatim}
+ INC Rx LD R,Rx LD Rx,n
+ DEC Rx LD Rx,R LD Rx,Ry
+ ADD/ADC/SUB/SBC/AND/XOR/OR/CP A,Rx
+\end{verbatim}
+Dabei stehen \tty{Rx} bzw. \tty{Ry} f"ur \tty{IXL, IXU, IYL} oder
+\tty{IYU}. Zu beachten ist jedoch, da"s in der \tty{LD Rx,Ry}-Variante
+beide Register aus dem gleichen Indexregister stammen m"ussen.
+\par
+Die Kodierung von Schiebebefehlen besitzt noch eine undefinierte
+Bitkombination, die als \tty{SLIA}-Befehl zug"anglich ist. \tty{SLIA}
+funktioniert wie \tty{SLA}, es wird jedoch eine Eins und nicht eine Null
+in Bit 0 eingeschoben. Dieser Befehl kann, wie alle anderen
+Schiebebefehle auch, noch in einer weiteren Variante geschrieben
+werden:
+\begin{verbatim}
+ SLIA R,(XY+d)
+\end{verbatim}
+Dabei steht \tty{R} f"ur ein beliebiges 8-Bit-Register (aber nicht eine
+Indexregisterh"alfte...), und \tty{(XY+d)} f"ur eine normale
+indexregister-relative Adressierung. Das Ergebnis dieser Operation
+ist, da"s das Schiebeergebnis zus"atzlich ins Register geladen wird.
+Dies funktioniert auch bei den \tty{RES-} und \tty{SET-}Befehlen:
+\begin{verbatim}
+ SET/RES R,n,(XY+d)
+\end{verbatim}
+Des weiteren gibt es noch zwei versteckte I/O-Befehle:
+\begin{verbatim}
+ IN (C) bzw. TSTI
+ OUT (C),0
+\end{verbatim}
+Deren Funktionsweise sollte klar sein. \bb{ACHTUNG!} Es gibt keine
+Garantie daf"ur, da"s alle Z80-Masken alle diese Befehle beherrschen,
+und die Z80-Nachfolger l"osen zuverl"assig Traps aus. Anwendung
+daher auf eigene Gefahr...
+
+%%---------------------------------------------------------------------------
+
+\section{Z380}
+
+Da dieser Prozessor als Enkel des wohl immer noch beliebtesten
+8-Bit-Prozessors konzipiert wurde, war es bei der Entwicklung
+unabdingbar, da"s dieser bestehende Z80-Programme ohne "Anderung
+ausf"uhren kann (nat"urlich geringf"ugig schneller, etwa um den
+Faktor 10...). Die erweiterten F"ahigkeiten k"onnen daher nach
+einem Reset mit zwei Flags zugeschaltet werden, die XM (eXtended
+Mode, d.h. 32- statt 16-Bit-Adre"sraum) und LW (long word mode,
+d.h. 32- statt 16- Bit-Operanden) hei"sen. Deren Stand mu"s man
+AS "uber die Befehle \tty{EXTMODE} und \tty{LWORDMODE} mitteilen, damit
+Adressen und Konstantenwerte gegen die korrekten Obergrenzen
+gepr"uft werden. Die Umschaltung zwischen 32- und 16-Bit-Befehlen
+bewirkt nat"urlich nur bei solchen Befehlen etwas, die auch in
+einer 32-Bit-Version existieren; beim Z380 sind das momentan
+leider nur Lade- und Speicherbefehle, die ganze Aritmetik kann
+nur 16-bittig ausgef"uhrt werden. Hier sollte Zilog wohl noch
+einmal etwas nachbessern, sonst kann man den Z380 selbst beim
+besten Willen nur als ,,16-Bit-Prozessor mit 32-Bit-Erweiterungen''
+bezeichnen...
+
+Kompliziert wird die Sache dadurch, da"s die mit LW eingestellte
+Operandengr"o"se f"ur einzelne Befehle mit den Pr"afixen \tty{DDIR W}
+und \tty{DDIR LW} "ubersteuert werden kann. AS merkt sich das
+Auftreten solcher Befehle und schaltet dann f"ur den n"achsten
+Prozessorbefehl automatisch mit um. Andere \tty{DDIR}-Varianten
+als \tty{W} und \tty{LW} sollte man "ubrigens nie explizit
+verwenden, da AS bei zu langen Operanden diese automatisch
+einsetzt, und das k"onnte zu Verwirrungen f"uhren. Die Automatik
+geht "ubrigens so weit, da"s in der Befehlsfolge
+\begin{verbatim}
+ DDIR LW
+ LD BC,12345678h
+\end{verbatim}
+automatisch der erforderliche \tty{IW}-Pr"afix mit in die
+vorangehende Anweisung hineingezogen wird, effektiv wird also
+der Code
+\begin{verbatim}
+ DDIR LW,IW
+ LD BC,12345678h
+\end{verbatim}
+erzeugt. Der im ersten Schritt erzeugte Code f"ur \tty{DDIR LW}
+wird verworfen, was an einem \tty{R} im Listing zu erkennen
+ist.
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-900(L)}
+\label{TLCS900Spec}
+
+Diese Prozessoren k"onnen in zwei Betriebsarten laufen, einmal im
+\ii{Minimum}-Modus, der weitgehende Z80- und TLCS-90-Quellcodekompatibilit"at
+bietet, und zum anderen im \ii{Maximum}-Modus, in dem der Prozessor
+erst seine wahren Qualit"aten entfaltet. Die Hauptunterschiede zwischen
+den beiden Betriebsarten sind:
+\begin{itemize}
+\item{Breite der Register WA,BC,DE und HL: 16 oder 32 Bit;}
+\item{Anzahl der Registerbanks: 8 oder 4;}
+\item{Programmadre"sraum: 64 Kbyte oder 16 Mbyte;}
+\item{Breite von R"ucksprungadressen: 16 oder 32 Bit.}
+\end{itemize}
+Damit AS gegen die richtigen Grenzen pr"ufen kann, mu"s man ihm zu Anfang
+mit dem Befehl \tty{MAXMODE} (siehe dort) mitteilen, in welcher Betriebsart
+der Code ausgef"uhrt werden wird; Voreinstellung ist der Minimum-Modus.
+\par
+Je nach Betriebsart m"ussen demzufolge auch die 16- oder 32-Bit-Versionen
+der Bankregister zur Adressierung verwendet werden, d.h. WA, BC, DE und HL
+im Minimum-Modus sowie XWA, XBC, XDE und XHL im Maximum-Modus. Die Register
+XIX..XIZ und XSP sind \bb{immer} 32 Bit breit und m"ussen zur Adressierung
+auch immer in dieser Form verwendet werden; hier mu"s bestehender Z80-Code
+also auf jeden Fall angepa"st werden (neben der Tatsache, da"s es gar keinen
+I/O-Adre"sraum mehr gibt und alle I/O-Register memory-mapped sind...).
+\par
+Die von Toshiba gew"ahlte Syntax f"ur Registernamen ist in der Hinsicht
+etwas ungl"ucklich, als da"s zur Anwahl der vorherigen Registerbank ein
+Hochkomma (') benutzt wird.
+Dieses Zeichen wird von den prozessorunabh"angigen Teilen von AS bereits zur
+Kennzeichnung von Zeichenkonstanten benutzt. Im Befehl
+\begin{verbatim}
+ ld wa',wa
+\end{verbatim}
+erkennt AS z.B. nicht das Komma zur Parametertrennung.
+Dieses Problem kann man aber umgehen,
+indem man ein umgekehrtes Hochkomma (`) verwendet, z.B.
+\begin{verbatim}
+ ld wa`,wa
+\end{verbatim}
+Toshiba liefert f"ur die TLCS-900-Reihe selber einen Assembler (TAS900), der
+sich in einigen Punkten von AS unterscheidet:
+
+\subsubsection{Symbolkonventionen}
+
+\begin{itemize}
+\item{TAS900 unterscheidet Symbolnamen nur auf den ersten 32 Zeichen.
+ AS dagegen speichert Symbolnamen immer in der vollen L"ange (bis
+ 255 Zeichen) und unterscheidet auch auf dieser L"ange.}
+\item{Unter TAS900 k"onnen Integerkonstanten sowohl in C-Notation (mit
+ vorangestellter 0 f"ur oktal bzw. 0x f"ur hexadezimal) als auch in
+ normaler Intel-Notation geschrieben werden. AS unterst"utzt in der
+ Default-Einstellung \bb{nur} die Intel-Notation. Mit dem
+ \tty{RELAXED}-Befehl bekommt man (unter anderem) auch die C-Notation.}
+\item{AS macht keinen Unterschied zwischen Gro"s- und Kleinschreibung,
+ TAS900 hingegen unterscheidet Gro"s-und Kleinbuchstaben in
+ Symbolnamen. Dieses Verhalten erh"alt man bei AS erst, wenn man
+ die \tty{-u}-Kommandozeilenoption benutzt.}
+\end{itemize}
+
+\subsubsection{Syntax}
+
+AS ist bei vielen Befehlen in der Syntaxpr"ufung weniger streng als TAS900,
+bei einigen weicht er (sehr) geringf"ugig ab. Diese Erweiterungen bzw.
+"Anderungen dienen teilweise der leichteren Portierung von bestehendem
+Z80-Code, teilweise einer Schreiberleichterung und teilweise einer besseren
+Orthogonalit"at der Assemblersyntax:
+\begin{itemize}
+\item{Bei den Befehlen \tty{LDA, JP} und \tty{CALL} verlangt TAS, da"s
+ Adre"sausdr"ucke wie \tty{XIX+5} nicht geklammert sein d"urfen, wie
+ es sonst "ublich ist. AS verlangt im Sinne der Orthogonalit"at f"ur
+ \tty{LDA} dagegen immer eine Klammerung, bei \tty{JP} und \tty{CALL}
+ ist sie dagegen f"ur einfache, absolute Adressen optional.}
+\item{Bei den bedingten Befehlen \tty{JP, CALL, JR} und \tty{SCC} stellt
+ AS es dem Programmierer frei, die Default-Bedingung \tty{T} (= true) als
+ ersten Parameter anzugeben oder nicht. TAS900 hingegen erlaubt es
+ nur, die Default-Bedingung implizit zu benutzen (also z.B.
+ \tty{jp (xix+5)} anstelle von \tty{jp t,(xix+5)}).}
+\item{AS erlaubt beim \tty{EX}-Befehl auch Operandenkombinationen, die
+ zwar nicht direkt im User's Manual\cite{Tosh900} genannt werden,
+ aber durch Vertauschung auf eine genannte zur"uckgef"uhrt werden
+ k"onnen. Kombinationen wie \tty{EX f`,f} oder \tty{EX wa,(xhl)}
+ werden damit m"oglich. TAS900 hingegen l"a"st nur die ,,reine Lehre''
+ zu.}
+\item{AS erlaubt, bei den Befehlen \tty{INC} und \tty{DEC} die Angabe
+ des Inkrements oder Dekrements wegzulassen, wenn dies 1 ist. Unter
+ TAS900 dagegen mu"s auch eine 1 hingeschrieben werden.}
+\item{"Ahnlich verh"alt es sich bei allen Schiebebefehlen: Ist der zu
+ verschiebende Operand ein Register, so verlangt TAS900, da"s auch
+ eine Schiebeamplitude von 1 ausgeschrieben werden mu"s; ist dagegen
+ eine Speicherstelle der Operand, so ist die Schiebezahl
+ (hardwarebedingt) immer 1 und darf auch nicht hingeschrieben werden.
+ Unter AS dagegen ist die Schiebezahl 1 immer optional und auch f"ur
+ alle Operandentypen zul"assig.}
+\end{itemize}
+
+\subsubsection{Makroprozessor}
+
+Der Makroprozessor wird TAS900 als externes Programm vorgeschaltet und
+besteht aus zwei Komponenten: einem C-artigen Pr"aprozessor und einer
+speziellen Makrosprache (MPL), die an h"ohere Programmiersprachen
+erinnert. Der Makroprozessor von AS dagegen orientiert sich an
+,,klassischen'' Makroassemblern wie dem M80 oder MASM (beides Programme
+von Microsoft). Er ist fester Bestandteil des Programmes.
+
+\subsubsection{Ausgabeformat}
+
+TAS900 erzeugt relokatiblen Code, so da"s sich mehrere, getrennt assemblierte
+Teile zu einem Programm zusammenbinden lassen. AS hingegen erzeugt direkt
+absoluten Maschinencode, der nicht linkbar ist. An eine Erweiterung ist
+(vorl"aufig) nicht gedacht.
+
+\subsubsection{Pseudoanweisungen}
+
+Bedingt durch den fehlenden Linker fehlen in AS eine ganze Reihe von f"ur
+relokatiblen Code erforderlichen Pseudoanweisungen, die TAS900 implementiert.
+In gleicher Weise wie bei TAS900 sind folgende Anweisungen vorhanden:
+\begin{quote}{\tt
+EQU, DB, DW, ORG, ALIGN, END, TITLE, SAVE, RESTORE,
+}\end{quote}
+wobei die beiden letzteren einen erweiterten Funktionsumfang haben.
+Einige weitere TAS900-Pseudobefehle lassen sich durch "aquivalente AS-Befehle
+ersetzen (siehe Tabelle \ref{TabTAS900}).
+\par
+Von Toshiba existieren zwei Versionen des Prozessorkerns, wobei die
+L-Variante eine ,,Sparversion'' darstellt. Zwischen TLCS-900 und TLCS-900L
+macht AS folgende Unterschiede:
+\begin{itemize}
+\item{Die Befehle \tty{MAX} und \tty{NORMAL} sind f"ur die L-Version
+ nicht erlaubt, der \tty{MIN}-Befehl ist f"ur die Vollversion
+ gesperrt.}
+\item{Die L-Version kennt den Normal-Stapelzeiger \tty{XNSP/NSP} nicht,
+ daf"ur das Steuerregister \tty{INTNEST}.}
+\end{itemize}
+Die Befehle \tty{SUPMODE} und \tty{MAXMODE} werden nicht beeinflu"st,
+ebenso nicht deren ini\-tiale Einstellung OFF. Die Tatsache, da"s die
+L-Version im Maximum-Modus startet und keinen Normal-Modus kennt, mu"s
+also vom Programmierer ber"ucksichtigt werden. AS zeigt sich jedoch
+insofern kulant gegen"uber der L-Variante, als da"s Warnungen wegen
+privilegierter Anweisungen im L-Modus unterdr"uckt werden.
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+TAS900 & AS & Bedeutung/Funktion \\
+\hline
+\hline
+\tty{DL} $<Daten>$ & \tty{DD} $<Daten>$ & Speicher in Langworten belegen \\
+\hline
+\tty{DSB} $<Zahl>$ & \tty{DB} $<Zahl>$ \tty{DUP} (?) & Speicher byteweise reservieren \\
+\hline
+\tty{DSW} $<Zahl>$ & \tty{DW} $<Zahl>$ \tty{DUP} (?) & Speicher wortweise reservieren \\
+\hline
+\tty{DSD} $<Zahl>$ & \tty{DD} $<Zahl>$ \tty{DUP} (?) & Speicher langwortweise reservieren \\
+\hline
+\tty{\$MIN[IMUM]} & \tty{MAXMODE OFF} & folgender Code im Minimum-Modus \\
+\hline
+\tty{\$MAX[IMUM]} & \tty{MAXMODE ON} & folgender Code im Maximum-Modus \\
+\hline
+\tty{\$SYS[TEM]} & \tty{SUPMODE ON} & folgender Code im System-Modus \\
+\hline
+\tty{\$NOR[MAL]} & \tty{SUPMODE OFF} & folgender Code im User-Modus \\
+\hline
+\tty{\$NOLIST} & \tty{LISTING OFF} & Assemblerlisting ausschalten \\
+\hline
+\tty{\$LIST} & \tty{LISTING ON} & Assemblerlisting einschalten \\
+\hline
+\tty{\$EJECT} & \tty{NEWPAGE} & neue Seite im Listing beginnen \\
+\hline
+\end{tabular}\end{center}
+\caption{"aquivalente Befehle TAS900$\leftrightarrow$AS\label{TabTAS900}}
+\end{table*}
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-90}
+
+Vielleicht fragt sich der eine oder andere, ob bei mir die Reihenfolge
+durcheinandergekommen ist, es gab ja von Toshiba zuerst den 90er als
+,,aufgebohrten Z80'' und danach den 900er als 16-Bit-Version. Nun, ich
+bin einfach "uber den 900er zum 90er gekommen (Danke, Oliver!). Die
+beiden Familien sind sich sehr artverwandt, nicht nur was ihre Syntax
+angeht, sondern auch ihre Architektur. Die Hinweise f"ur den 90er sind
+daher eine Untermenge derer f"ur den 900er: Da Schieben, Inkrementieren
+und Dekrementieren hier nur um eins m"oglich sind, braucht und darf diese
+Eins auch nicht als erstes Argument hingeschrieben werden. Bei den
+Befehlen \tty{LDA, JP} und \tty{CALL} m"ochte Toshiba wieder die
+Klammern um Speicheroperanden weglassen, bei AS m"ussen sie aber aus
+Gr"unden der Orthogonalit"at gesetzt werden (der tiefere Grund ist
+nat"urlich, da"s ich mir damit eine Sonderabfrage im Parser gespart habe,
+aber das sagt man nicht so laut).
+\par
+Die TLCS-90er besitzen bereits prinzipiell einen Adre"sraum von 1
+Mbyte, dieser Raum erschlie"st sich aber nur bei Datenzugriffen "uber
+die Indexregister. AS verzichtet daher auf eine Ber"ucksichtigung
+der Bankregister und begrenzt den Adre"sraum f"ur Code auf 64 Kbyte.
+Da der Bereich jenseits aber sowieso nur "uber indirekte Adressierung
+erreichbar ist, sollte dies keine allzu gro"se Einschr"ankung darstellen.
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-870}
+
+Schon wieder Toshiba...diese Firma ist im Augenblick wirklich sehr
+produktiv! Speziell dieser Spro"s der Familie (Toshibas Mikrokontroller
+sind sich ja alle in Bin"arkodierung und Programmiermodell recht "ahnlich)
+scheint auf den 8051-Markt abzuzielen: Die Methode, Bitstellen durch einen
+Punkt getrennt an den Adre"sausdruck anzuh"angen, hatte ja beim 8051 ihren
+Ursprung, f"uhrt jetzt aber auch genau zu den Problemen, die ich beim 8051
+geahnt hatte: Der Punkt ist jetzt einerseits legales Zeichen in Symbolnamen,
+andererseits aber auch Teil der Adre"ssyntax, d.h. AS mu"s Adresse und
+Bitstelle trennen und einzeln weiterverarbeiten. Diesen Interessenkonflikt
+habe ich vorerst so gel"ost, da"s der Ausdruck von \bb{hinten} an nach
+Punkten durchsucht wird und so der letzte Punkt als Trenner gilt, eventuelle
+weitere Punkte werden dem Symbolnamen zugerechnet. Es gilt weiterhin die
+flehentliche Bitte, im eigenen Interesse auf Punkte in Symbolnamen zu
+verzichten, sie f"uhren nur zu Verwirrungen:
+\begin{verbatim}
+ LD CF,A.7 ; Akku Bit 7 nach Carry
+ LD C,A.7 ; Konstante A.7 nach Register C
+\end{verbatim}
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-47}
+
+Mit dieser 4-Bit-Prozessorfamilie d"urfte wohl das unter Ende dessen
+erreicht sein, was AS unterst"utzen kann. Neben dem \tty{ASSUME}-Befehl
+f"ur das Datenbankregister (siehe dort) ist eigentlich nur ein Detail
+erw"ahnenswert: im Daten- und I/O-Segment werden keine Bytes, sondern
+Nibbles reserviert (eben 4-Bitter...). Die Sache funktioniert "ahnlich
+wie das Bitdatensegment beim 8051, wo ein \tty{DB} ja nur einzelne Bit
+reserviert, nur da"s es hier eben Nibbles sind.
+\par
+Toshiba hat f"ur diese Prozessorfamilie einen ,,erweiterten Befehlssatz''
+in Makroform definiert, um das Arbeiten mit diesem doch recht
+beschr"ankten Befehlssatz zu erleichtern. Im Fall von AS ist er in der
+Datei STDDEF47.INC definiert. Einige Befehle, deren makrom"a"sige
+Realisierung nicht m"oglich war, sind allerdings ,,eingebaut'' und stehen
+daher auch ohne die Include-Datei zur Verf"ugung:
+\begin{itemize}
+\item{der \tty{B}-Befehl, der die jeweils optimale Version des
+ Sprungbefehls (\tty{BSS, BS oder BSL}) automatisch w"ahlt;}
+\item{\tty{LD} in der Variante HL mit immediate;}
+\item{\tty{ROLC} und \tty{RORC} mit einer Schiebeamplitude $>$1.}
+\end{itemize}
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-9000}
+
+Hier ist es zum ersten Mal passiert, da"s ich einen Prozessor in AS
+implementiert habe, der zu diesem Zeitpunkt noch gar nicht auf dem
+Markt war. Toshiba hat sich leider auch vorl"aufig dazu entschieden,
+diesen Prozessor ,,auf Eis'' zu legen, bis auf weiteres wird es also
+auch kein Silizium geben. Das hat nat"urlich zur Folge, da"s dieser Teil
+\begin{description}
+\item[1.]{ein ,,Paper-Design'' ist, d.h. noch nicht praktisch getestet
+ wurde und}
+\item[2.]{Die Unterlagen, die ich zum 9000er hatte \cite{Tosh9000},
+ noch vorl"aufig waren, also noch nicht bis ins letzte Klarheit
+ lieferten.}
+\end{description}
+Fehler in diesem Teil sind also durchaus noch m"oglich (und werden
+nat"urlich bereinigt, wenn es denn einmal gehen sollte!). Zumindest
+die Handvoll Beispiele in \cite{Tosh9000} werden aber richtig "ubersetzt.
+
+%%---------------------------------------------------------------------------
+
+\section{29xxx}
+
+Wie schon beim \tty{ASSUME}-Befehl beschrieben, kann AS mit der Kenntnis
+"uber den Inhalt des RBP-Registers feststellen, ob im User-Modus
+auf gesperrte Register zugegriffen wird. Diese F"ahigkeit
+beschr"ankt sich nat"urlich auf direkte Zugriffe (also nicht, wenn
+die Register IPA...IPC benutzt werden), und sie hat noch einen
+weiteren Haken: da lokale Register (also solche mit Nummern$>$127)
+relativ zum Stackpointer adressiert werden, die Bits in RBP sich
+aber immer auf absolute Nummern beziehen, wird die Pr"ufung f"ur
+lokale Register NICHT durchgef"uhrt. Eine Erweiterung auf lokale
+Register w"urde bedingen, da"s AS zu jedem Zeitpunkt den absoluten
+Wert von SP kennt, und das w"urde sp"atestens bei rekursiven
+Unterprogrammen scheitern...
+
+%%---------------------------------------------------------------------------
+
+\section{80C16x}
+
+Wie in der Erkl"arung des \tty{ASSUME}-Befehls schon erl"autert, versucht
+AS, dem Programmierer die Tatsache, da"s der Prozessor mehr physikalischen
+als logischen Speicher hat, soweit als m"oglich zu verbergen. Beachten
+Sie aber, da"s die DPP-Register \bb{nur} Datenzugriffe betreffen und auch dort
+nur absolute Adressierung, also weder indirekte noch indizierte Zugriffe,
+da AS ja nicht wissen kann, wie die berechnete Adresse zur Laufzeit
+aussehen wird...Bei Codezugriffen arbeitet die Paging-Einheit leider nicht,
+man mu"s also explizit mit langen oder kurzen \tty{CALL}s, \tty{JMP}s oder
+\tty{RET}s arbeiten. Zumindest bei den ,,universellen'' Befehlen \tty{CALL}
+und \tty{JMP} w"ahlt AS automatisch die k"urzeste Form, aber sp"atestens
+beim \tty{RET} sollte man wissen, woher der Aufruf kam. Prinzipiell
+verlangen \tty{JMPS} und \tty{CALLS} dabei, da"s man Segment und Adresse
+getrennt angibt, AS ist jedoch so geschrieben, da"s er eine Adresse selber
+zerlegen kann, z.B.
+\begin{verbatim}
+ jmps 12345h
+\end{verbatim}
+anstelle von
+\begin{verbatim}
+ jmps 1,2345h
+\end{verbatim}
+Leider sind nicht alle Effekte der chipinternen Instruktions-Pipeline
+versteckt: Werden CP (Registerbankadresse), SP (Stack) oder eines der
+Paging-Register ver"andert, so steht der neue Wert noch nicht f"ur den
+n"achsten Befehl zur Verf"ugung. AS versucht, solche Situationen zu
+erkennen und gibt im Falle eines Falles eine Warnung aus. Aber auch
+diese Mimik greift nur bei direkten Zugriffen.
+\par
+Mit \tty{BIT} definierte Bits werden intern in einem 13-Bit-Wort abgelegt,
+wobei die Bitadresse in Bit 4..11 liegt und die Bitnummer in den unteren
+vier Bits. Diese Anordnung erlaubt es, das n"achsth"ohere bzw.
+n"achstniedrigere Bit durch Inkrementieren bzw. Dekrementieren anzusprechen.
+Bei expliziten Bitangaben mit Punkt funktioniert das aber nicht "uber
+Wortgrenzen hinaus. So erzeugt folgender Ausdruck eine
+Wertebereichs"uberschreitung:
+\begin{verbatim}
+ bclr r5.15+1
+\end{verbatim}
+Hier mu"s ein \tty{BIT} her:
+\begin{verbatim}
+msb bit r5.15
+ .
+ .
+ .
+ bclr msb+1
+\end{verbatim}
+F"ur den 80C167/165/163 ist der SFR-Bereich verdoppelt worden; da"s ein Bit im
+zweiten Teil liegt, wird durch ein gesetztes Bit 12 vermerkt. Leider
+hatte Siemens bei der Definition des 80C166 nicht vorausgesehen, da"s
+256 SFRs (davon 128 bitadressierbar) f"ur Nachfolgechips nicht reichen
+w"urden. So w"are es unm"oglich, den zweiten SFR-Bereich von F000H..F1DFH
+mit kurzen Adressen oder Bitbefehlen zu erreichen, h"atten die Entwickler
+nicht einen Umschaltbefehl eingebaut:
+\begin{verbatim}
+ EXTR #n
+\end{verbatim}
+Dieser Befehl bewirkt, da"s f"ur die n"achsten \tty{n} Befehle (0$<$\tty{n}$<$5)
+anstelle des normalen der erweiterte SFR-Bereich angesprochen werden kann.
+AS erzeugt bei diesm Befehl nicht nur den passenden Code, sondern setzt
+intern ein Flag, da"s f"ur die n"achsten \tty{n} Befehle nur Zugriffe auf den
+erweiterten SFR-Bereich zul"a"st. Da d"urfen nat"urlich keine Spr"unge
+dabei sein... Bits aus beiden Bereichen lassen sich nat"urlich jederzeit
+definieren, ebenso sind komplette Register aus beiden SFR-Bereichen
+jederzeit mit absoluter Adressierung erreichbar. Nur die kurze bzw.
+Bitadressierung geht immer nur abwechselnd, Zuwiderhandlungen werden
+mit einer Fehlermeldung geahndet.
+\par
+"Ahnlich sieht es mit den Pr"afixen f"ur absolute bzw. indirekte
+Adressierung aus: Da aber sowohl Argument des Pr"afixes als auch der
+Adre"sausdruck nicht immer zur "Ubersetzungszeit bestimmbar sind, sind
+die Pr"ufungsm"oglichkeiten durch AS sehr eingeschr"ankt, weshalb er es
+auch bei Warnungen bel"a"st...im einzelnen sieht das folgenderma"sen aus:
+\begin{itemize}
+\item{feste Vorgabe einer 64K-Bank mittels \tty{EXTS} oder \tty{EXTSR}:
+ Im Adre"sausdruck werden direkt die unteren 16 Bit der Zieladresse
+ eingesetzt. Haben sowohl Pr"afix als auch Befehl einen konstanten
+ Operanden, so wird "uberpr"uft, ob Pr"afixargument und Bit 16..23 der
+ Zieladresse identisch sind.}
+\item{feste Vorgabe einer 16K-Seite mittels \tty{EXTP} oder \tty{EXTPR}:
+ Im Adre"sausdruck werden direkt die unteren 14 Bit der Zieladresse
+ eingesetzt. Bit 14 und 15 bleiben konstant 0, da sie in diesem Modus
+ nicht vom Prozessor ausgewertet werden. Haben sowohl Pr"afix als
+ auch Befehl einen konstanten Operanden, so wird "uberpr"uft, ob
+ Pr"afixargument und Bit 14..23 der Zieladresse identisch sind.}
+\end{itemize}
+Damit das etwas klarer wird, ein Beispiel (die DPP-Register haben
+die Reset-Vorbelegung) :
+\begin{verbatim}
+ extp #7,#1 ; Bereich von 112K..128K
+ mov r0,1cdefh ; ergibt Adresse 0defh im Code
+ mov r0,1cdefh ; -->Warnung
+ exts #1,#1 ; Bereich von 64K..128K
+ mov r0,1cdefh ; ergibt Adresse 0cdefh im Code
+ mov r0,1cdefh ; -->Warnung
+\end{verbatim}
+
+%%---------------------------------------------------------------------------
+
+\section{PIC16C5x/16C8x}
+
+"Ahnlich wie die MCS-48-Familie teilen auch die PICs ihren
+Programmspeicher in mehrere B"anke auf, da im Opcode nicht gen"ugend Platz
+f"ur die vollst"andige Adresse war. AS verwendet f"ur die Befehle \tty{CALL}
+und \tty{GOTO} die gleiche Automatik, d.h. setzt die PA-Bits im
+Statuswort entsprechend Start- und Zieladresse. Im Gegensatz zu den 48ern
+ist dieses Verfahren hier aber noch deutlich problematischer:
+\begin{enumerate}
+\item{Die Befehle sind nicht mehr nur ein Wort, sondern bis zu drei Worten
+ lang, k"onnen also nicht mehr in jedem Fall mit einem bedingten Sprung
+ "ubergangen werden.}
+\item{Es ist m"oglich, da"s der Programmz"ahler beim normalen
+ Programmfortgang eine Seitengrenze "uberschreitet. Die vom Assembler
+ angenommene Belegung der PA-Bits stimmt dann nicht mehr mit der
+ Realit"at "uberein.}
+\end{enumerate}
+Bei den Befehlen, die das Register W mit einem anderen Register
+verkn"upfen, mu"s normalerweise als zweiter Parameter angegeben werden, ob
+das Ergebnis in W oder im Register abgelegt werden soll. Bei diesem
+Assembler ist es erlaubt, den zweiten Parameter wegzulassen. Welches Ziel
+dann angenommen werden soll, h"angt vom Typ des Befehls ab: bei un"aren
+Operationen wird defaultm"a"sig das Ergebnis zur"uck ins Register gelegt.
+Diese Befehle sind:
+\begin{quote}
+{\tt COMF, DECF, DECFSZ, INCF, INCFSZ, RLF, RRF} und {\tt SWAPF}
+\end{quote}
+Die anderen Befehle betrachten W defaultm"a"sig als Akkumulator, zu dem ein
+Register verkn"upft wird:
+\begin{quote}
+{\tt ADDWF, ANDWF, IORWF, MOVF, SUBWF} und {\tt XORWF}
+\end{quote}
+\par
+Die von Microchip vorgegebene Schreibweise f"ur Literale ist ziemlich
+abstrus und erinnert an die auf IBM 360/370-Systemen "ubliche Schreibweise
+(Gr"u"se aus Neandertal...). Um nicht noch einen Zweig in den Parser
+einf"ugen zu m"ussen, sind bei AS Konstanten in
+Motorola-Syntax zu schreiben (wahlweise auch Intel oder C im \tty{RELAXED}-Modus).
+\par
+Dem Assembler liegt die Include-Datei STDDEF16.INC bei, in der die Adressen
+der Hardware-Register und Statusbits verewigt sind. Daneben enth"alt sie
+eine Liste von ,,Befehlen'', die der Microchip-Assembler als Makro
+implementiert. Bei der Benutzung dieser Befehlsmakros ist gro"se Vorsicht
+angebracht, da sie mehrere Worte lang sind und sich somit nicht "uberspringen
+lassen!!
+
+%%---------------------------------------------------------------------------
+
+\section{PIC17C4x}
+
+F"ur diese Prozessoren gelten im wesentlichen die gleichen Hinweise wie
+f"ur ihre kleinen Br"uder, mit zwei Ausnahmen: Die zugeh"orige Include-Datei
+enth"alt nur Registerdefinitionen, und die Probleme bei Sprungbefehlen
+sind deutlich kleiner. Aus der Reihe f"allt nur \tty{LCALL}, der einen
+16-Bit-Sprung erlaubt. Dieser wird mit folgendem ,,Makro'' "ubersetzt:
+\begin{verbatim}
+ MOVLW <Adr15..8>
+ MOWF 3
+ LCALL <Adr0..7>
+\end{verbatim}
+
+%%---------------------------------------------------------------------------
+
+\section{ST6}
+
+Diese Prozessoren k"onnen das Code-ROM seitenweise in den Datenbereich
+einblenden. Weil ich nicht die ganze Mimik des \tty{ASSUME}-Befehles
+hier wiederk"auen m"ochte, verweise ich auf das entsprechende Kapitel
+(\ref{ST6Assume}), in dem steht, wie man mit diesem Befehl einigerma"sen
+unfallfrei Konstanten aus dem ROM lesen kann.
+\par
+Bei n"ahererer Betrachtung des Befehlssatzes fallen einige eingebaute
+,,Makros'' auf. Die Befehle, die mir aufgefallen sind (es gibt aber
+vielleicht noch mehr...), sind in Tabelle \ref{TabHid62} aufgelistet.
+\par
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+Befehl & in Wirklichkeit \\
+\hline
+\hline
+\tty{CLR A} & \tty{SUB A,A} \\
+\tty{SLA A} & \tty{ADD A,A} \\
+\tty{CLR adr} & \tty{LDI adr,0} \\
+\tty{NOP} & \tty{JRZ PC+1} \\
+\hline
+\end{tabular}\end{center}
+\caption{versteckte Makros im ST6225-Befehlssatz\label{TabHid62}}
+\end{table*}
+Insbesondere der letztere Fall verbl"ufft doch etwas...
+Leider fehlen aber einige Anweisungen wirklich. So gibt es z.B. zwar einen
+\tty{AND}-Befehl, aber kein \tty{OR}...von \tty{XOR} gar nicht zu
+reden. In der Datei STDDEF62.INC finden sich deshalb neben den Adressen
+der SFRs noch einige Makros zur Abhilfe.
+\par
+Der Original-Assembler AST6 von SGS-Thomson verwendet teilweise andere
+Pseudobefehle als AS. Au"ser der Tatsache, da"s AS Pseudobefehle nicht
+mit einem vorangestellten Punkt kennzeichnet, sind folgende Befehle
+identisch:
+\begin{verbatim}
+ ASCII, ASCIZ, BLOCK, BYTE, END, ENDM, EQU, ERROR, MACRO,
+ ORG, TITLE, WARNING
+\end{verbatim}
+Tabelle \ref{TabAST6} zeigt die AST6-Befehle, zu denen analoge in AS
+existieren.
+\par
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+AST6 & AS & Bedeutung/Funktion \\
+\hline
+\hline
+\tty{.DISPLAY} & \tty{MESSAGE} & Meldung ausgeben \\
+\hline
+\tty{.EJECT} & \tty{NEWPAGE} & neue Seite im Listing \\
+\hline
+\tty{.ELSE} & \tty{ELSEIF} & bed. Assemblierung \\
+\hline
+\tty{.ENDC} & \tty{ENDIF} & bed. Assemblierung \\
+\hline
+\tty{.IFC} & \tty{IF...} & bed. Assemblierung \\
+\hline
+\tty{.INPUT} & \tty{INCLUDE} & Include-Datei einbinden \\
+\hline
+\tty{.LIST} & \tty{LISTING}, \tty{MACEXP} & Listing-Einstellung \\
+\hline
+\tty{.PL} & \tty{PAGE} & Seitenl"ange Listing \\
+\hline
+\tty{.ROMSIZE} & \tty{CPU} & Zielprozessor einstellen \\
+\hline
+\tty{.VERS} & \tty{VERSION} (Symbol) & Version abfragen \\
+\hline
+\tty{.SET} & \tty{EVAL} & Variablen neu setzen \\
+\hline
+\end{tabular}\end{center}
+\caption{"aquivalente Befehle AST6$\leftrightarrow$AS\label{TabAST6}}
+\end{table*}
+
+%%---------------------------------------------------------------------------
+
+\section{ST7}
+
+In \cite{ST7Man} ist der '.w'-Postfix f"ur 16-Bit-Adressen nur f"ur
+speicherindirekte Operanden definiert, um zu vermerken, da"s auf einer
+Zeropageadresse eine 16-bittige Adresse liegt; AS unterst"utzt ihn jedoch
+zus"atzlich auch f"ur absolute Adressen oder Displacements in indizierter
+Adressierung, um trotz eines nur 8 Bit langen Wertes (0..255) ein
+16-bittiges Displacement zu erzeugen.
+
+%%---------------------------------------------------------------------------
+
+\section{ST9}
+
+Die Bitadressierungsm"oglichkeiten des ST9 sind relativ eingeschr"ankt:
+Mit Ausnahme des \tty{BTSET}-Befehls ist es nur m"oglich, auf Bits innerhalb
+des aktuellen Arbeitsregistersatzes zuzugreifen. Eine Bit-Adresse
+sieht also folgenderma"sen aus:
+\begin{verbatim}
+ rn.[!]b
+\end{verbatim}
+wobei \verb?!? eine optionale Invertierung eines Quelloperanden bedeutet.
+Wird ein Bit symbolisch mittels des \tty{BIT}-Befehles definiert, so wird
+die Registernummer im Symbolwert in Bit 7..4, die Bitnummer in Bit
+3..1 und eine optionale Invertierung in Bit 0 vermerkt. AS unterscheidet
+direkte und symbolische Bitangaben am Fehlen eines Punktes,
+der Name eines Bitsymboles darf also keinen Punkt enthalten, obwohl
+sie an sich zul"assig w"aren. Es ist auch zul"assig, bei der Referenzierung
+von Bitsymbolen diese zu nachtr"aglich zu invertieren:
+\begin{verbatim}
+bit2 bit r5.3
+ .
+ .
+ bld r0.0,!bit2
+\end{verbatim}
+Auf diese Weise ist es auch m"oglich, eine inverse Definition nachtr"aglich
+wieder aufzuheben.
+\par
+Bitdefinitionen finden sich in gro"ser Zahl in der Include-Datei
+REGST9.INC, in der die Register- und Bitnamen aller On-Chip-Peripherie
+beschrieben sind. Beachten Sie jedoch, da"s deren Nutzung
+nur m"oglich ist, wenn die Arbeitsregisterbank vorher auch auf diese
+Register ausgerichtet wurde!
+\par
+Im Gegensatz zu der zum AST9 von SGS-Thomson geh"orenden Definitionsdatei
+sind f"ur AS die Namen der Peripherieregister nur als allgemeine
+Registernamen definiert (\tty{R...}), nicht auch noch als Arbeitsregister
+(\tty{r...}). Dies ist so, weil AS Geschwindigkeitsgr"unden keine
+Aliasnamen f"ur Register definieren kann.
+
+%%---------------------------------------------------------------------------
+
+\section{6804}
+
+Eigentlich habe ich diesen Prozessor ja nur eingebaut, um mich "uber
+das seltsame Gebaren von SGS-Thomson zu beklagen: Als ich das
+6804-Datenbuch zum ersten Mal in die Hand bekam, f"uhlte ich mich ob des
+etwas ,,unvollst"andigen'' Befehlssatzes und der eingebauten Makros
+spontan an die ST62-Serie vom gleichen Hersteller erinnert. Ein
+genauerer Vergleich der Opcodes f"orderte erstaunliches zu Tage:
+Ein 6804-Opcode ergibt sich durch Spiegelung aller Bits im entsprechenden
+ST62-OpCode! Thomson hat hier also offensichtlich etwas
+Prozessorkern-Recycling betrieben...wogegen ja auch nichts einzuwenden
+w"are, wenn nicht so eine Verschleierungstaktik betrieben werden w"urde:
+andere Peripherie, Motorola- anstelle Zilog-Syntax sowie das h"a"sliche
+Detail, in Opcodes enthaltene Argumente (z.B. Bitfelder mit Displacements)
+\bb{nicht} zu drehen. Letzterer Punkt hat mich auch nach l"angerem "Uberlegen
+dazu bewogen, den 6804 doch in AS aufzunehmen. Ich wage "ubrigens keine
+Spekulationen, welche Abteilung bei Thomson von welcher abgekupfert hat...
+\par
+Im Gegensatz zur ST62-Version enth"alt die Include-Datei f"ur den
+6804 keine Makros, die die L"ucken im Befehlssatz etwas ,,auspolstern''
+sollen. Dies "uberlasse ich dem geneigten Leser als Finger"ubung!
+
+%%---------------------------------------------------------------------------
+
+\section{TMS3201x}
+
+Offensichtlich ist es Ehrgeiz jedes Prozessorherstellers, seine eigene
+Notation f"ur Hexadezimalkonstanten zu erfinden. Texas Instruments
+war bei diesen Prozessoren besonders originell: ein vorangestelltes
+$>$-Zeichen! Die "Ubernahme dieses Formates in AS h"atte zu schweren
+Konflikten mit den Vergleichs-und Schiebeoperatoren von AS im Formelparser
+gef"uhrt. Ich habe mich deshalb f"ur die Intel-Notation entschieden, zu
+der sich TI bei der 340x0-Serie und den 3201x-Nachfolgern ja dann auch
+durchgerungen hat...
+\par
+Leider hat das Instruktionswort dieser Prozessoren nicht gen"ugend Bits,
+um bei direkter Adressierung alle 8 Bits zu enthalten, weshalb der
+Datenadre"sraum logisch in 2 B"anke zu 128 W"ortern gespalten ist. AS
+verwaltet diesen als ein durchgehendes Segment von 256 W"ortern und
+l"oscht bei direkten Zugriffen automatisch das Bit 7 (Ausnahme: Befehl
+\tty{SST}, der nur in die obere Bank schreiben kann). Der Programmierer
+ist daf"ur erforderlich, da"s das Bank-Bit stets den richtigen Wert hat!
+\par
+Ein weiterer, nur sehr versteckt im Datenbuch stehender Hinweis: Die
+\tty{SUBC}-Anweisung ben"otigt zur Ausf"uhrung intern mehr als einen
+Takt, das Steuerwerk arbeitet jedoch schon an dem n"achsten Befehl weiter.
+Im auf ein \tty{SUBC} folgenden Befehl darf deshalb nicht auf den
+Akkumulator zugegriffen werden. AS nimmt hier \bb{keine} Pr"ufung vor!
+
+%%---------------------------------------------------------------------------
+
+\section{TMS320C2x}
+
+Da ich nicht selber diesen Codegenerator geschrieben habe (was nichts an
+seiner Qualit"at mindert), kann ich nur kurz hier umrei"sen, wieso es
+Befehle gibt, bei denen ein vorangestelltes Label als untypisiert, d.h.
+keinem Adre"sraum zugeordnet, gespeichert wird: Der 20er der TMS-Reihe
+kennt sowohl ein 64 Kbyte gro"ses Code- als auch Datensegment. Je nach
+externer Beschaltung kann man dabei Code- und Datenbereiche "uberlappen,
+um z.B. Konstanten im Codebereich zu abzulegen und auf diese als Daten
+zuzugreifen (Ablage im Code ist notwendig, weil "altere AS-Versionen davon
+ausgehen, da"s ein Datensegment aus RAM besteht, das in einem
+Standalone-System nach dem Einschalten keinen definierten Inhalt hat und
+verweigern in Segmenten au"ser Code deshalb die Ablage von Daten). Ohne
+dieses Feature w"urde AS nun jeden Zugriff auf die abgelegten Daten mit
+einer Warnung (,,Symbol aus falschem Segment'') quittieren. Im einzelnen
+erzeugen folgende Pseudobefehle untypisierte Labels:
+\begin{quote}
+ {\tt BSS, STRING, RSTRING, BYTE, WORD , LONG, FLOAT \\
+ DOUBLE, EFLOAT, BFLOAT} und {\tt TFLOAT}
+\end{quote}
+Sollten doch einmal typisierte Labels gew"unscht sein, so kann man sich
+behelfen, indem man das Label in eine getrennte Zeile vor dem Pseudobefehl
+schreibt. Umgekehrt kann man einen der anderen Pseudobefehle mit einem
+typenlosen Label versehen, indem man vor dem Befehl das Label mit
+\begin{verbatim}
+<Name> EQU $
+\end{verbatim}
+definiert.
+
+%%---------------------------------------------------------------------------
+
+\section{TMS320C3x}
+
+Die gr"o"sten Magenschmerzen bei diesem Prozessor hat mir die Syntax
+paralleler Befehle bereitet, die auf zwei Zeilen verteilt werden,
+wobei beide Befehle an sich auch sequentiell ausgef"uhrt werden k"onnen.
+Deshalb erzeugt AS zuerst den Code f"ur die einzelne erste Operation,
+wenn er dann in der zweiten Zeile erkennt, da"s eine parallele Aweisung
+vorliegt, wird der zuerst erzeugte Code durch den neuen ersetzt.
+Im Listing kann man dies daran erkennen, da"s der Programmz"ahler
+nicht weiterl"auft und in der zweiten Zeile anstelle eines Doppelpunktes
+ein \tty{R} vor dem erzeugten Code steht.
+\par
+Bez"uglich der doppelten senkrechten Striche und ihrer Position in der
+Zeile ist man nicht ganz so flexibel wie beim TI-Assembler: Entweder
+man schreibt sie anstelle eines Labels (d.h. in der ersten Spalte oder
+mit einem angeh"angten Doppelpunkt, das ist aber nicht mehr
+TI-kompatibel...) oder direkt vor den zweiten Befehl ohne Leerzeichen,
+sonst bekommt der Zeilenparser von AS Probleme und h"alt die Striche
+f"ur das Mnemonic.
+
+%%---------------------------------------------------------------------------
+
+\section{TMS9900}
+
+Wie bei den meisten "alteren Prozessorfamilien auch, hatte TI seinerzeit
+ein eigenes Format zur Schreibweise von Hexadezimal- und Bin"arkonstanten
+verwendet, anstelle deren AS die normale, heute auch bei TI
+gebr"auchliche Intel-Notation verwendet.
+
+Die TI-Syntax f"ur Register erlaubt es, da"s anstelle eines echten Namens
+(entweder \tty{Rx} oder \tty{WRx}) auch eine einfache Integer-Zahl
+zwischen 0 und 15 benutzt werden kann. Dies hat zwei Folgen:
+\begin{itemize}
+\item{\tty{R0...R15} bzw. \tty{WR0..WR15} sind einfache, vordefinierte
+ Integersymbole mit den Werten 0..15, und die Definition von
+ Registeraliasen funktioniert "uber schlichte \tty{EQUs}.}
+\item{Im Gegensatz zu einigen anderen Prozessoren kann ich nicht das
+ zus"atzliche AS-Feature anbieten, da"s das Kennzeichen f"ur
+ absolute Adressierung (hier ein Klammeraffe) weggelassen werden
+ darf. Da ein fehlendes Kennzeichen hier aber Registernummern (im
+ Bereich 0 bis 15) bedeuten w"urde, war das hier nicht m"oglich.}
+\end{itemize}
+Weiterhin wechselt TI mit der Registerbezeichnung zwischen \tty{Rx} und
+\tty{WRx}...vorerst ist beides zugelassen.
+
+%%---------------------------------------------------------------------------
+
+\section{TMS70Cxx}
+
+Diese Prozessorreihe geh"ort noch zu den "alteren, von TI entwickelten
+Reihen, und deswegen benutzt TI in ihren eigenen Assemblern noch die
+herstellereigene Syntax f"ur hexadezimale und bin"are Konstanten
+(vorangestelltes $<$ bzw. ?). Da das in AS aber so nicht machbar ist, wird
+defaultm"a"sig die Intel-Syntax verwendet. Auf diese ist Texas bei den
+Nachfolgern dieser Familie, n"amlich den 370ern auch umgestiegen. Beim
+genaueren Betrachten des Maschinenbefehlssatzes stellt man fest, da"s
+ca. 80\% der 7000er-Befehle bin"ar aufw"artskompatibel sind, und auch die
+Assemblersyntax ist fast gleich - aber eben nur fast. Bei der Erweiterung
+des 7000er-Befehlssatzes hat TI n"amlich auch gleich die Chance genutzt,
+die Syntax etwas zu vereinheitlichen und zu vereinfachen. Ich habe mich
+bem"uht, einen Teil dieser "anderungen auch in die 7000er Syntax
+einflie"sen zu lassen:
+\begin{itemize}
+\item{Anstelle eines Prozentzeichens zur Kennzeichnung von
+ unmittelbarer Adressierung darf auch das allgemein bekanntere Doppelkreuz
+ verwendet werden.}
+\item{Wenn bei den Befehlen \tty{AND, BTJO, BTJZ, MOV, OR} und
+ \tty{XOR} eine Port-Adresse (\tty{P...}) als Quelle oder Ziel
+ benutzt wird, ist es nicht notwendig, die Mnemonic-Form mit explizit
+ angeh"angtem \tty{P} zu benutzen - die allgemeine Form reicht genauso
+ aus.}
+\item{Der vorangestelle Klammeraffe f"ur absolute oder B-indizierte
+ Adressierung darf weggelassen werden.}
+\item{Anstelle des \tty{CMPA}-Befehls darf auch einfach
+ \tty{CMP} mit \tty{A} als Ziel benutzt werden.}
+\item{Anstelle \tty{LDA} oder \tty{STA} darf auch einfach der \tty{MOV}-Befehl
+ mit \tty{A} als Ziel bzw. Quelle benutzt werden.}
+\item{Anstelle des \tty{MOVD}-Befehls darf auch \tty{MOVW} benutzt werden.}
+\item{Anstelle von \tty{RETS} oder \tty{RETI} darf auch verk"urzt
+ \tty{RTS} bzw. \tty{RTI} geschrieben werden.}
+\item{\tty{TSTA} bzw. \tty{TSTB} d"urfen auch als \tty{TST A} bzw. \tt{TST
+ B} geschrieben werden.}
+\item{\tty{XCHB B} ist als Alias f"ur \tty{TSTB} zugelassen.}
+\end{itemize}
+Wichtig - diese Varianten sind nur beim TMS70Cxx zugelassen - entsprechende
+7000er-Varianten sind bei den 370ern {\em nicht} erlaubt!
+
+%%---------------------------------------------------------------------------
+
+\section{TMS370xxx}
+
+Obwohl diese Prozessoren keine speziellen Befehle zur Bitmanipulation
+besitzen, wird mit Hilfe des Assemblers und des \tty{DBIT}-Befehles
+(siehe dort) die Illusion erzeugt, als ob man einzelne Bits manipulieren
+w"urde. Dazu wird beim \tty{DBIT}-Befehl eine Adresse mit einer
+Bitposition zusammengefa"st und in einem Symbol abgelegt, das man dann
+als Argument f"ur die Pseudobefehle \tty{SBIT0, SBIT1, CMPBIT, JBIT0}
+und \tty{JBIT1} verwenden kann. Diese werden in die Befehle
+\tty{OR, AND, XOR, BTJZ} und \tty{BTJO} mit einer passenden Bitmaske
+"ubersetzt.
+\par
+An diesen Bit-Symbolen ist "uberhaupt nichts geheimnisvolles, es handelt
+sich um schlichte Integerwerte, in deren unterer H"alfte die
+Speicheradresse und in deren oberer H"alfte die Bitstelle gespeichert
+wird. Man k"onnte sich seine Symbole also auch ohne weiteres selber
+basteln:
+\begin{verbatim}
+defbit macro name,bit,adr
+name equ adr+(bit<<16)
+ endm
+\end{verbatim}
+aber mit dieser Schreibweise erreicht man nicht den \tty{EQU}-artigen Stil,
+den Texas vorgegeben hat (d.h. das zu definierende Symbol steht anstelle
+eines Labels). ACHTUNG! Obwohl \tty{DBIT} eine beliebige Adresse
+zul"a"st, k"onnen f"ur die Pseudobefehle nur die Adressen 0..255 und
+1000h..10ffh verwendet werden, eine absolute Adressierungsart kennt
+der Prozessor an dieser Stelle nicht...
+
+%%---------------------------------------------------------------------------
+
+\section{MSP430}
+\label{MSPSpec}
+
+Der MSP430 wurde als RISC-Prozessor mit minimalem Stromverbrauch
+konzipiert. Aus diesem Grund ist der Satz von Befehlen, die der
+Prozessor in Hardware versteht, auf das absolut notwendige reduziert
+worden (da RISC-Prozessoren keinen Mikrocode besitzen, mu"s jeder
+Befehl mit zus"atzlichem Silizium implementiert werden und erh"oht so
+den Stromverbrauch). Eine Reihe von Befehlen, die bei anderen
+Prozessoren in Hardware gegossen wurden, werden beim MSP durch eine
+Emulation mit anderen Befehlen realisiert. Bei AS finden sich diese
+Befehle mit in der Datei \tty{REGMSP.INC}. Wer diese Datei nicht
+einbindet, wird bei "uber der H"alfte der insgesamt von TI definierten
+Befehle Fehlermeldungen bekommen!!
+
+%%---------------------------------------------------------------------------
+
+\section{COP8 \& SC/MP}
+\label{COP8Spec}
+
+Leider Gottes hat sich auch National dazu entschieden, als
+Schreibweise f"ur nichtdezimale Integer-Konstanten die von
+IBM-Gro"srechnern bekannte (und von mir vielgeha"ste) Variante
+\verb!X'...! zu benutzen. Das geht nat"urlich (wie immer) nicht.
+Zum Gl"uck scheint der ASMCOP aber auch die C-Variante zuzulassen,
+und diese wurde deshalb der Default f"ur die COPs...
+
+%%---------------------------------------------------------------------------
+
+\section{SC144xxx}
+\label{SC144xxspec}
+
+Original gab es f"ur diese Reihe von DECT-Controllern mit relativ
+einfachem Befehlssatz nur einen sehr schlichten Assembler von National
+selber. Ein Assembler von IAR Systems ist angek"undigt, aber noch nicht
+erh"altlich. Da die Entwicklungstools von IAR allerdings auch nach
+M"oglichkeit CPU-unabh"angig angelegt sind, kann man anhand erh"altlicher
+Zielplattformen in ungef"ahr absch"atzen, wie dessen Pseudobefehle
+aussehen werden, und damit im Blick sind die (wenigen) SC144xx-spezifisch
+realisierten Befehle {\tt DC, DC8, DW16, DS, DS8, DS16, DW} angelegt. Bei
+Befehlen, die bereits im AS-Kern angelegt sind, wollte ich nat"urlich
+nicht das Rad neu erfinden, deshalb hier eine Tabelle mit "Aquivalenzen:
+
+Die Befehle \tty{ALIGN, END, ENDM, EXITM, MACRO, ORG, RADIX, SET} und
+\tty{REPT} exisieren sowohl bei IAR als auch AS und haben gleiche
+Bedeutung. Bei folgenden Befehlen mu"s man umstellen:
+
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+IAR & AS & Funktion\\
+\hline
+\hline
+\tty{\#include} & \tty{include} & Include-Datei einbinden \\
+\tty{\#define} & \tty{SET, EQU} & Symbole definieren \\
+\tty{\#elif, ELIF, ELSEIF} & \tty{ELSEIF} & Weiterer Zweig einer IF-Kette \\
+\tty{\#else, ELSE} & \tty{ELSE} & Letzter Zweig einer IF-Kette \\
+\tty{\#endif, ENDIF} & \tty{ENDIF} & Beendet eine IF-Kette \\
+\tty{\#error} & \tty{ERROR, FATAL} & Fehlermeldung erzeugen \\
+\tty{\#if, IF} & \tty{IF} & Beginn einer IF-Kette\\
+\tty{\#ifdef} & \tty{IFDEF} & Symbol definiert ? \\
+\tty{\#ifndef} & \tty{IFNDEF} & Symbol nicht definiert ? \\
+\tty{\#message} & \tty{MESSAGE} & Nachricht ausgeben \\
+\tty{=, DEFINE, EQU} & \tty{=, EQU} & Feste Wertzuweisung \\
+\tty{EVEN} & \tty{ALIGN 2} & Programmz"ahler gerade machen \\
+\tty{COL, PAGSIZ} & \tty{PAGE} & Seitengr"o"se f"ur Listing setzen \\
+\tty{ENDR} & \tty{ENDM} & Ende einer REPT-Struktur \\
+\tty{LSTCND, LSTOUT} & \tty{LISTING} & Umfang des Listings steuern \\
+\tty{LSTEXP, LSTREP} & \tty{MACEXP} & Expandierte Makros anzeigen? \\
+\tty{LSTXRF} & \verb!<Kommandozeile>! & Querverweisliste erzeugen \\
+\tty{PAGE} & \tty{NEWPAGE} & Neue Seite im Listing \\
+\tty{REPTC} & \tty{IRPC} & Repetition mit Zeichenersetzung \\
+\hline
+\end{tabular}\end{center}
+\end{table*}
+
+Keine direkte Entsprechung gibt es f"ur die Befehle {\tt CASEON, CASEOFF,
+LOCAL, LSTPAG, \#undef} und {\tt REPTI}.
+
+Ein direktes "Aquivalent der Pr"aprozessorbefehle ist nat"urlich nicht
+m"oglich, solange AS keinen C-artigen Pr"aprozessor besitzt. C-artige
+Kommentare sind im Moment leider auch nicht m"oglich. Achtung: Wer
+IAR-Codes f"ur AS umsetzt, mu"s die Pr"aprozessorstatements nicht nur
+umwandeln, sondern auch aus Spalte 1 herausbewegen, da bei AS in Spalte 1
+nur Labels stehen d"urfen!
+
+%%---------------------------------------------------------------------------
+
+\section{75K0}
+\label{75K0Spec}
+
+Wie bei einigen anderen Prozessoren auch, kennt die Assemblersprache
+der 75er von NEC Pseudo-Bitoperanden, d.h. man kann einem Symbol
+eine Kombination aus Adresse und Bitnummer zuweisen, die dann bei
+bitorientierten Befehlen anstelle direkter Ausdr"ucke verwendet werden
+kann. Die drei folgenden Befehle erzeugen daher z.B. identischen
+Code:
+\begin{verbatim}
+ADM sfr 0fd8h
+SOC bit ADM.3
+
+ skt 0fd8h.3
+ skt ADM.3
+ skt SOC
+\end{verbatim}
+AS unterscheidet direkte und symbolische Bitzugriffe an einem
+bei Symbolen fehlenden Punkt; Punkte in Symbolnamen darf man daher
+nicht verwenden, da es sonst zu Mi"sverst"andnissen bei der Aufl"osung
+kommt.
+\par
+Die Ablage von Bitsymbolen orientiert sich dabei weitgehend an der
+bin"aren Kodierung, die die Prozessorhardware selber verwendet: Es
+werden 16 Bit belegt, und es existieren ein ,,kurzes'' und ein ,,langes''
+Format. Das kurze Format kann folgende Varianten aufnehmen:
+\begin{itemize}
+ \item{direkte Zugriffe auf die Bereiche 0FBxH und 0FFxH}
+ \item{indirekte Zugriffe der Form Adr.@L (0FC0H $\leq$ \tty{Adr} $\leq$ 0FFFH)}
+ \item{indirekte Zugriffe der Form @H+d4.bit}
+\end{itemize}
+Das obere Byte ist auf 0 gesetzt, das untere Byte enth"alt den gem"a"s
+\cite{NEC75} kodierten Bitausdruck. Das lange Format kennt im Gegensatz
+dazu nur direkte Adressierung, kann daf"ur aber (korrekte Einstellungen
+von \tty{MBS} und \tty{MBE} vorausgesetzt) den ganzen Adre"sraum abdecken.
+Bei langen Ausdr"ucken stehen im unteren Byte Bit 7..0 der Adresse, in
+Bit 8 und 9 die Bitstelle sowie in Bit 10 und 11 konstant 01. Letztere
+erm"oglichen es, langes und kurzes Format einfach durch einen Vergleich
+des oberen Bytes gegen Null zu unterscheiden. Die Bits 12..15 enthalten
+Bit 8..11 der Adresse; sie werden zwar nicht zur Generierung des Kodes
+ben"otigt, m"ussen jedoch gespeichert werden, da eine Pr"ufung auf ein
+korrektes Banking erst bei der Verwendung des Symboles erfolgen kann.
+
+%%---------------------------------------------------------------------------
+
+\section{78K0}
+\label{78K0Spec}
+
+NEC benutzt in seinen Datenb"uchern zur Kennzeichnung der Zugriffsweise
+auf absolute Adressen verschiedene Schreibweisen:
+\begin{itemize}
+\item{absolut kurz: kein Pr"afix}
+\item{absolut lang: vorangestelltes \verb"!"}
+\item{PC-relativ: vorangestelltes \verb"$"}
+\end{itemize}
+Bei AS sind diese Pr"afixe nur notwendig, falls man eine bestimmte
+Adressierung erzwingen will und der Befehl verschiedene Varianten
+zul"a"st. Setzt man keinen Pr"afix, so w"ahlt AS automatisch die
+k"urzeste Variante. Es d"urfte daher in der Praxis sehr selten
+notwendig sein, einen Pr"afix zu verwenden.
+
+%%---------------------------------------------------------------------------
+
+\section{$\mu$PD772x}
+
+Sowohl 7720 als auch 7725 werden von dem gleichen Codegenerator behandelt
+und sind sich in ihren Befehlssatz extrem "ahnlich. Trotzdem sollte man
+sich nicht zu der Annahme verleiten lassen, sie seien bin"ar kompatibel:
+Um die l"angeren Adre"sfelder und zus"atzlichen Befehle unterbringen zu
+k"onnen, haben sich die Bitpositionen einiger Felder im Instruktionswort
+verschoben, die Instruktionsl"ange hat sich auch insgesamt von 23 auf 24
+Bit ge"andert. Im Code-Format sind deshalb auch unterschiedliche
+Header-Ids f"ur beide reserviert.
+
+Gemeinsam ist beiden, da"s sie neben Code- und Datensegment auch noch ein
+ROM zur Ablage von Konstanten besitzen. Dieses ist bei AS auf das
+\tty{ROMDATA}-Segment abgebildet!
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Dateiformate}
+
+In diesem Kapitel sollen die Formate von von AS erzeugten Dateien
+beschrieben werden, deren Format sich nicht direkt erschlie"st.
+
+\section{Code-Dateien}
+\label{SectCodeFormat}
+
+Das vom Assembler ausgegebene Codedatenformat mu"s in der Lage sein,
+die Codeteile f"ur unterschiedliche Prozessoren voneinander zu trennen,
+und sieht daher etwas anders aus als g"angige Formate. Obwohl dem
+Assembler Tools zur Bearbeitung der Codedateien beiliegen, halte ich es
+f"ur guten Stil, das Format hier kurz offenzulegen:
+\par
+Sofern in der Datei Mehrbyte-Integers gespeichert sind, werden sie
+im Intelformat abgelegt, d.h. mit dem LSB zuerst. Diese Regel gilt
+bereits f"ur das 16-Bit-Kennungswort mit dem Wert \$1489, d.h. jede
+Codedatei beginnt mit den Bytes \$89/\$14.
+\par
+Danach folgt eine Reihe beliebig vieler ,,Records'', wobei ein Record
+entweder ein zusammenh"angendes Teilfeld des Codes darstellt oder bestimmte
+Zusatzinformationen enth"alt. Eine Datei
+kann auch ohne Umschaltung des Prozessortyps mehrere Records enthalten,
+wenn Code- oder Konstantenbereiche durch reservierte (und nicht zu
+initialisierende) Speicherbereiche unterbrochen werden. Der Assembler
+versucht auf diese Weise, die Datei nicht l"anger als n"otig werden
+zu lassen.
+\par
+Allen Records ist gemein ist ein Header-Byte, das den Typ des Records
+und die damit folgenden Datenstrukturen festlegt. In einer Pascal-artigen
+Form l"a"st sich die Record-Struktur folgenderma"sen beschreiben:
+\begin{verbatim}
+FileRecord = RECORD CASE Header:Byte OF
+ $00:(Creator:ARRAY[] OF Char);
+ $01..
+ $7f:(StartAdr : LongInt;
+ Length : Word;
+ Data : ARRAY[0..Length-1] OF Byte);
+ $80:(EntryPoint:LongInt);
+ $81:(Header : Byte;
+ Segment : Byte;
+ Gran : Byte;
+ StartAdr : LongInt;
+ Length : Word;
+ Data : ARRAY[0..Length-1] OF Byte);
+ END
+\end{verbatim}
+Was in dieser Schreibweise nicht ganz zum Ausdruck kommt, ist, da"s
+die L"ange von Datenfeldern variabel ist und von {\tt Length} abh"angt.
+\par
+Ein Record mit einem Header-Byte von \verb!$81! ist ein Record, der Code
+oder Daten aus beliebigen Segmenten beinhalten kann. Das erste
+Byte (Header) gibt an, f"ur welche Prozessorfamilie die folgenden
+Daten bzw. der folgende Code bestimmt ist (siehe Tabelle \ref{TabHeader}).
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|c|l||c|l|}
+\hline
+Header & Familie & Header & Familie \\
+\hline
+\hline
+\input{tabids.tex}
+\end{tabular}\end{center}
+\caption{Headerbytes f"ur die verschiedenen Prozessorfamilien\label{TabHeader}}
+\end{table*}
+Das Segment-Feld gibt an, in welchen Adre"sraum des Prozessors der
+folgende Code geh"ort. Dabei gilt die in Tabelle \ref{TabSegments}
+angegeben Zuordnung.
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|c|l||c|l|}
+\hline
+Nummer & Segment & Nummer & Segment \\
+\hline
+\hline
+\$00 & $<$undefiniert$>$ & \$01 & CODE \\
+\$02 & DATA & \$03 & IDATA \\
+\$04 & XDATA & \$05 & YDATA \\
+\$06 & BDATA & \$07 & IO \\
+\$08 & REG & \$09 & ROMDATA \\
+\hline
+\end{tabular}\end{center}
+\caption{Kodierungen des {\tt Segment}-Feldes\label{TabSegments}}
+\end{table*}
+Das Gran-Feld gibt die ,,Granularit"at'' des Codes an, d.h. die Gr"o"se
+der kleinsten, adressierbaren Einheit im folgenden Datensatz. Dieser
+Wert ist eine Funktion von Prozessortyp und Segment und ein wichtiges
+Detail f"ur die Interpretation der beiden folgenden Felder, die
+Startadresse und L"ange angeben: W"ahrend die Startadresse sich auf die
+Granularit"at bezieht, erfolgt die L"angenangabe immer in Bytes! W"are
+die Startadresse z.B. \$300 und die L"ange 12, so w"are die sich
+ergebende Endadresse bei einer Granularit"at von 1 \$30b, bei einer
+Granularit"at von z.B. 4 jedoch \$303! Andere Granularit"aten als eins
+sind selten und treten in erster Linie bei Signalprozessoren auf, die
+nicht auf Einzelbyteverarbeitung ausgelegt sind deren Datenspeicher z.B.
+aus 64kWorten zu 16 Bit besteht (DSP56K). Der sich ergebende Speicherplatz
+betr"agt dann zwar 128 KByte, er ist aber in $2^{16}$ Worten organisiert,
+die mit Adressen von 0,1,2,...65535 adressiert werden!
+\par
+Die Startadresse ist 32-bittig, unabh"angig von der Adre"sbreite der
+jeweiligen Prozessorfamilie. Im Gegensatz dazu ist die L"angenangabe
+nur 16 Bit lang, ein Record kann also maximal (4+4+2+(64K-1)) = 65545
+Byte lang werden.
+\par
+Daten-Records mit den Header-Bytes \verb!$01..$7f! stellen eine
+Kurzschreibweise dar und stellen die Abw"artskompatibilit"at mit fr"uheren
+Definitionen des Dateiformats her: Das Header-Byte gibt direkt den
+Prozessortyp gem"a"s der ersten Tabelle an, das Zielsegment ist auf \tty{CODE}
+festgelegt und die Granularit"at ergibt sich aus dem Prozessortyp,
+aufgerundet auf eine Zweierpotenz von Bytes. AS bevorzugt diese Records,
+wenn Daten bzw. Code f"ur das \tty{CODE}-Segment anstehen.
+\par
+Der Record mit dem Typ-Byte \verb!$80! legt den Einsprungpunkt fest, d.h.
+die Adresse, an der mit der Ausf"uhrung des Programmes begonnen werden
+soll. Ein solcher Record ist das Ergebnis einer \tty{END}-Anweisung mit
+einer entsprechenden Adresse als Argument.
+\par
+Der letzte Record in der Datei tr"agt das Header-Byte \verb!$00! und besitzt
+als einziges Datenfeld einen String, dessen Ende durch das Dateiende
+definiert ist. Dieser String spezifiziert, von welchem Programm diese
+Datei erzeugt wurde und hat keine weitere Bedeutung.
+
+
+\section{Debug-Dateien}\label{SectDebugFormat}
+
+Debug-Dateien k"onnen optional von AS erzeugt werden und liefern
+nachgeschalteten Werkzeugen wie Disassemblern oder Debuggern f"ur diese
+wichtige Informationen. AS kann Debug-Informationen in drei Formaten
+ausgeben: Zum einen im Objekt-Format der AVR-Tools von Atmel sowie eine zu
+NoICE kompatible Kommandodatei und zum anderen in einem eigenen Format.
+Die ersten beiden werden in \cite{AVRObj} bzw. der Dokumentation zu
+NoICE ausf"uhrlich beschrieben, deshalb beschr"ankt sich die folgende
+Beschreibung auf das AS-eigene MAP-Format:
+
+Diese Informationen in einer MAP-Datei teilen sich in drei Gruppen:
+\begin{itemize}
+\item{Symboltabelle}
+\item{Speicherberlegung, auf Sektionen verteilt}
+\item{Maschinenadressen von Quellzeilen}
+\end{itemize}
+Letzterer Teil findet sich zuerst in der Datei. Ein einzelner
+Eintrag in dieser Liste besteht aus zwei, von einem Doppelpunkt
+getrennten Zahlen:
+\begin{verbatim}
+ <Zeilennummer>:<Adresse>
+\end{verbatim}
+Ein solcher Eintrag besagt, da"s der aus einer bestimmten
+Quellcodezeile erzeugte Maschinencode auf der angegebenen Adresse
+(hexadezimal) zu liegen kam. Mit einer solchen Information kann ein
+Debugger beim Durchsteppen des Programmes die entsprechenden
+Quellcodezeilen anzeigen. Da ein Programm aber auch aus mehreren
+Include-Dateien bestehen kann, und viele Prozessoren mehr als nur
+einen Adre"sraum besitzen (von dem zugegebenerma"sen nur in einem Code
+liegt), m"ussen die oben beschriebenen Eintr"age sortiert werden. AS
+tut dies in zwei Stufen: Das prim"are Sortierkriterium ist das
+Zielsegment, innerhalb dieser Segmente wird noch einmal nach Dateien
+sortiert. Einzelne Abschnitte werden dabei durch durch spezielle
+Zeilen der Form
+\begin{verbatim}
+Segment <Segmentname>
+\end{verbatim}
+bzw.
+\begin{verbatim}
+File <Dateiname>
+\end{verbatim}
+getrennt.
+
+Die Symboltabelle folgt der Quellzeileninformation und ist wieder
+prim"ar nach den Segmenten geordnet, aus denen die Symbole stammen.
+Im Gegensatz zur Zeileninformation kommt hier allerdings auch der
+Abschnitt \tty{NOTHING} hinzu, der die Symbole beinhaltet, die keinem
+speziellen Adre"sraum zugeordnet sind (z.B. Symbole, die einfach mit
+\tty{EQU} definiert wurden). Die Einleitung eines Abschnittes in der
+Symboltabelle erfolgt mit einer Zeile der Form
+\begin{verbatim}
+Symbols in Segment <Segmentname> .
+\end{verbatim}
+Innerhalb eines Abschnittes sind die Symbole nach Namen sortiert, und
+ein Symboleintrag belegt genau eine Zeile. Eine solche Zeile besteht
+wiederum aus 5 Feldern, die durch jeweils mindestens ein Leerzeichen
+getrennt sind:
+
+Das erste Feld ist der Name des Symbols selber, eventuell erweitert
+um eine in eckigen Klammern eingeschlossene Sektionsnummer, die den
+G"ultigkeitsbereich des Symbols einschr"ankt. Die zweite Spalte
+bezeichnet den Typ des Symbols: \tty{Int} f"ur Integerzahlen, \tty{Float} f"ur
+Gleitkommazahlen und \tty{String} f"ur Zeichenketten. Die dritte Zeile
+schlie"slich beinhaltet den eigentliche Wert des Symbols. Falls das
+Symbol eine Zeichenkette beinhaltet, ist es notwendig, Steuer- und
+Leerzeichen mit einer gesonderten Notation zu kennzeichnen, damit ein
+im String enthaltenes Leerzeichen nicht eventuell als Trennzeichen
+zur n"achsten Spalte interpretiert werden kann. AS bedient sich dazu
+der bereits der in Assemblerquellen "ublichen Schreibweise, den
+ASCII-Zahlenwert mit einem f"uhrenden Backslash (\verb!\!) einzusetzen. Aus
+dem String
+\begin{verbatim}
+ Dies ist ein Test
+\end{verbatim}
+wird also z.B.
+\begin{verbatim}
+ Dies\032ist\032ein\032Test
+\end{verbatim}
+Die Zahlenangabe ist immer dezimal und dreistellig, und der Backslash
+selber wird ebenfalls in dieser Schreibweise kodiert.
+
+Das vierte Feld gibt - falls vorhanden - die Gr"o"se der Datenstruktur
+an, die an der durch das Symbol gekennzeichneten Adresse abgelegt
+ist. Ein Debugger kann eine solche Information z.B. nutzen, um
+symbolisch angesprochene Variablen direkt in der korrekten L"ange
+aufzulisten. Hat AS keine Informationen "uber die Symbolgr"o"se, so
+steht in diesem Feld eine schlichte -1.
+
+Das f"unfte und letzte Feld gibt schlu"sendlich durch eine 0 oder 1 an,
+ob das Symbol w"ahrend der Assemblierung jemals referenziert wurde.
+Ein Programm, da"s die Symboltabelle liest, kann auf diese Weise z.B.
+nicht benutzte Symbole automatisch verwerfen, da sie beim folgenden
+Debugging oder der Disassemblierung mit hoher Wahrscheinlichkeit auch
+nicht ben"otigt werden.
+
+Der dritte Abschnitt in einer Debug-Datei beschreibt die im Programm
+benutzten Sektionen n"aher. Eine solche Beschreibung ist erforderlich,
+da Sektionen den G"ultigkeitsbereich von Symbolen einschr"anken
+k"onnen. Je nach momentanem Stand des Programmz"ahlers kann z.B. ein
+symbolischer Debugger einzelne Symboldefinitionen f"ur eine R"uck"ubersetzung
+nicht nutzen oder mu"s Priorit"aten bei der Symbolnutzung beachten.
+Die Definition einer Sektion beginnt mit einer Zeile der Form
+\begin{verbatim}
+Info for Section nn ssss pp ,
+\end{verbatim}
+wobei \tty{nn} die Nummer der Sektion angibt (die Nummer, die als Postfix
+f"ur Symbolnamen in der Symboltabelle genutzt wird), \tty{ssss} der Name der
+Sektion ist und \tty{pp} die Nummer der Vatersektion darstellt. Letztere
+Information ben"otigt ein R"uck"ubersetzer, um sich bei der Auffindung
+eines Symbols f"ur einen Zahlenwert ausgehend von der aktuellen Sektion
+im Baum bis zur Wurzel ,,durchhangeln'' kann, bis ein passendes
+Symbol gefunden wird. Auf diese Zeile folgt eine Reihe weiterer
+Zeilen, die den von dieser Sektion belegten Code-Bereich beschreiben.
+Jeder einzelne Eintrag (genau einer pro Zeile) beschreibt entweder
+eine einzelne Adresse oder einen durch zwei Grenzwerte beschriebenen
+Bereich (Trennung von Anfangs-und Endwert durch ein Minuszeichen).
+Die Grenzen sind dabei ,,inklusive'', d.h. die Grenzen geh"oren auch zu
+dem Bereich. Wichtig ist, da"s ein einer Sektion zugeh"origer Bereich
+nicht nochmals f"ur ihre Vatersektionen aufgef"uhrt wird (eine Ausnahme
+ist nat"urlich, wenn Bereiche absichtlich mehrfach belegt werden, aber
+so etwas macht man ja auch nicht, gelle?). Dies dient einer Optimierung
+der Bereichsspeicherung w"ahrend der Assemblierung und sollte auch
+f"ur eine Symbolr"uck"ubersetzung keine Probleme darstellen, da durch
+die einfache Kennzeichnung bereits der Einstiegspunkt und damit der
+Suchpfad im Sektionsbaum gegeben ist. Die Beschreibung einer Sektion
+wird durch eine Leerzeile oder das Dateiende gekennzeichnet.
+
+Programmteile, die au"serhalb aller Sektionen liegen, werden nicht
+gesondert ausgewiesen. Diese ,,implizite Wurzelsektion'' tr"agt die
+Nummer -1 und wird auch als Vatersektion f"ur Sektionen benutzt, die
+keine eigentliche Vatersektion besitzen.
+
+Es ist m"oglich, da"s die Datei Leerzeilen oder Kommentarzeilen
+(Semikolon am Zeilenanfang) beinhaltet. Diese sind von einem
+Leseprogramm zu ignorieren.
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Hilfsprogramme}
+\label{ChapTools}
+
+Um die Arbeit mit dem Codeformat des Assemblers etwas zu erleichtern,
+lege ich einige Progamme zu deren Bearbeitung bei. F"ur diese Programme
+gilt sinngem"a"s das gleiche wie in \ref{SectLicense}!
+
+Allen Programmen gemeinsam sind die Returncodes, die sie liefern (Tabelle
+\ref{TabToolReturns}).
+\par
+\begin{table*}[ht]
+\begin{center}\begin{tabular}{|c|l|}
+\hline
+Returncode & tritt auf bei... \\
+\hline
+\hline
+0 & kein Fehler \\
+1 & Kommandozeilenparameterfehler \\
+2 & I/O-Fehler \\
+3 & Dateiformatfehler \\
+\hline
+\end{tabular}\end{center}
+\caption{Returncodes der Dienstprogramme\label{TabToolReturns}}
+\end{table*}
+Ebenso eintr"achtig wie AS lesen sie ihre Eingaben von STDIN und schreiben
+Meldungen auf STDOUT (bzw. Fehlermeldungen auf STDERR). Ein-und
+Ausgaben sollten sich daher problemlos umleiten lassen.
+\par
+Sofern Programme im folgenden Zahlen-oder Adre"sangaben von der
+Kommandozeile lesen, d"urfen diese auch hexadezimal geschrieben werden,
+indem man sie mit einem voranstehenden Dollarzeichen oder \tty{0x} wie
+in C versieht (z.B. \verb!$10! oder \verb!0x10! anstelle von 16).
+\par
+Unix-Shells \marginpar{{\em UNIX}} ordnen dem Dollarzeichen allerdings
+eine spezielle Bedeutung zu (Parameterexpansion), weshalb es n"otig ist,
+einem Dollarzeichen direkt einen Backslash voranzustellen. Die
+\tty{0x}-Variante ist hier sicherlich angenehmer.
+\par
+Ansonsten folgen die Aufrufkonventionen und -variationen (bis auf PLIST
+und AS2MSG) denen von AS, d.h. man kann dauernd gebrauchte Schalter in
+einer Environmentvariablen ablegen (deren Name sich aus dem Anh"angen von
+CMD an den Programmnamen ergibt, z.B. BINDCMD f"ur BIND), Optionen
+negieren und Gro"s-bzw. Kleinschreibung erzwingen (n"aheres zu dem Wie in
+Abschnitt \ref{SectCallConvention}).
+\par
+Sofern Adre"sangaben benutzt werden, beziehen sie sich immer auf die
+Granularit"at des Adre"sraumes des jeweiligen Prozessors; beim PIC bedeutet
+z.B. eine Adre"sdifferenz von 1 nicht ein Byte, sondern ein Wort.
+
+%%---------------------------------------------------------------------------
+
+\section{PLIST}
+
+PLIST ist das einfachste Programm der vier mitgelieferten; es dient
+einfach nur dazu, die in einer Codedatei gespeicherten Records aufzulisten.
+Da das Programm nicht allzuviel bewirkt, ist der Aufruf ziemlich simpel:
+\begin{verbatim}
+ PLIST $<$Dateiname$>$
+\end{verbatim}
+Der Dateiname wird automatisch um die Endung P erweitert, falls keine
+Endung vorhanden ist.
+\par
+\bb{ACHTUNG!} An dieser Stelle sind keine Jokerzeichen erlaubt! Falls mit
+einem Befehl trotzdem mehrere Programmdateien gelistet werden sollen,
+kann man sich mit folgendem ''Minibatch'' behelfen:
+\begin{verbatim}
+ for %n in (*.p) do plist %n
+\end{verbatim}
+PLIST gibt den Inhalt der Codedatei in Tabellenform aus, wobei f"ur
+jeden Record genau eine Zeile ausgegeben wird. Die Spalten haben
+dabei folgende Bedeutung:
+\begin{itemize}
+\item{Codetyp: die Prozessorfamilie, f"ur die der Code erzeugt wurde.}
+\item{Startadresse: absolute Speicheradresse, an die der Code zu laden ist.}
+\item{L"ange: L"ange des Codest"ucks in Byte.}
+\item{Endadresse: letzte absolute Adresse des Codest"ucks. Diese berechnet
+ sich als Startadresse+L"ange-1.}
+\end{itemize}
+Alle Angaben sind als hexadezimal zu verstehen.
+\par
+Zuletzt gibt PLIST noch einen Copyrightvermerk aus, sofern er einen
+solchen in der Datei findet, und die Summe aller Codel"angen.
+\par
+PLIST ist praktisch ein DIR f"ur Codedateien. Man kann es benutzen,
+um sich den Inhalt einer Datei auflisten zu lassen, bevor man sie
+weiterbearbeitet.
+
+%%---------------------------------------------------------------------------
+
+\section{BIND}
+
+BIND ist ein Programm, mit dem man die Records mehrerer Codedateien
+in eine Datei zusammenkopieren kann. Die dabei vorhandene Filterfunktion
+erlaubt es aber auch, nur Records eines bestimmten Typs zu "ubernehmen.
+Auf diese Weise kann BIND auch dazu verwendet werden, um eine Codedatei
+in mehrere aufzuspalten.
+\par
+Die allgemeine Syntax von BIND lautet
+\begin{verbatim}
+ BIND <Quelldatei(en)> <Zieldatei> [Optionen]
+\end{verbatim}
+Wie auch AS betrachtet BIND alle nicht mit einem +, - oder / eingeleiteten
+Parameter als Dateiangaben, von denen die letzte die Zieldatei angeben
+mu"s. Alle anderen Dateiangaben bezeichnen Quellen, diese Angaben d"urfen
+auch wieder Jokerzeichen enthalten.
+\par
+An Optionen definiert BIND momentan nur eine:
+\begin{itemize}
+\item{\tty{f $<$Header[,Header...]$>$}: gibt eine Liste von Header-IDs
+ an, die kopiert werden sollen. Alle anderen Records werden
+ nicht kopiert. Ohne diese Angabe werden alle Records kopiert.
+ Die in der Liste angegebenen entsprechen dem Header-Feld in der
+ Recordstruktur, wie es in Abschnitt \ref{SectCodeFormat} beschrieben wurden. Die
+ einzelnen Header-Nummern in der Liste werden durch Kommas getrennt.}
+\end{itemize}
+Um z.B. alle MCS-51-Codeteile aus einer Programmdatei auszusieben,
+benutzt man BIND folgenderma"sen:
+\begin{verbatim}
+ BIND <Quellname> <Zielname> -f $31
+\end{verbatim}
+Fehlt bei einer Dateiangabe eine Endung, so wird automatisch die Endung
+P angef"ugt.
+
+%%---------------------------------------------------------------------------
+
+\section{P2HEX}
+
+P2HEX ist eine Erweiterung von BIND. Es besitzt alle
+Kommandozeilenoptionen von BIND und hat die gleichen Konventionen
+bzgl. Dateinamen. Im Gegensatz zu BIND wird die Zieldatei aber als
+Hexfile ausgegeben, d.h. als eine Folge von Zeilen, die den Code als
+ASCII-Hexzahlen enthalten.
+\par
+P2HEX kennt 8 verschiedene Zielformate, die "uber den
+Kommandozeilenparameter \bb{F} ausgew"ahlt werden k"onnen:
+\begin{itemize}
+\item{Motorola S-Record (\tty{-F Moto})}
+\item{MOS Hex (\tty{-F MOS})}
+\item{Intel-Hex (Intellec-8, \tty{-F Intel})}
+\item{16-Bit Intel-Hex (MCS-86, \tty{-F Intel16})}
+\item{32-Bit Intel-Hex (\tty{-F Intel32})}
+\item{Tektronix Hex (\tty{-F Tex})}
+\item{Texas Instruments DSK (\tty{-F DSK})}
+\item{Atmel AVR Generic (-F Atmel, siehe \cite{AVRObj})}
+\end{itemize}
+Wird kein Zielformat explizit angegeben, so w"ahlt P2HEX anhand des
+Prozessortyps automatisch eines aus, und zwar S-Records f"ur Motorola-
+Prozessoren, Hitachi und TLCS-900(0), MOS f"ur 65xx/MELPS, DSK f"ur die
+16-Bit-Texas-Signalprozessoren, Atmel Generic f"ur die AVRs und Intel-Hex
+f"ur den Rest. Je nach Breite der Startadresse kommen bei S-Record Records
+der Typen 1,2 oder 3 zum Einsatz, jedoch nie in einer Gruppe gemischt.
+Diese Automatik l"a"st sich mit der Kommandozeilenoption
+\begin{verbatim}
+ -M <1|2|3>
+\end{verbatim}
+teilweise unterdr"ucken: Ein Wert von 2 bzw. 3 sorgt daf"ur, da"s
+S-Records mit einem Mindesttyp von 2 bzw. 3 benutzt werden, w"ahrend ein
+Wert von 0 der vollen Automatik entspricht.
+
+Die Intel-, Tektronix- und MOS-Formate sind auf 16 Bit-Adressen
+beschr"ankt, das 16-Bit Intel-Format reicht 4 Bit weiter. L"angere
+Adressen werden von P2HEX mit einer Warnung gemeldet und abgeschnitten(!).
+F"ur die PICs k"onnen die drei von Microchip spezifizierten Varianten des
+Intel-Hex-Formates erzeugt werden, und zwar mit dem Schalter
+\begin{verbatim}
+ -m <0..3>
+\end{verbatim}
+Das Format 0 ist INHX8M, in dem alle Bytes in Lo-Hi-Ordnung enthalten
+sind. Die Adre"sangaben verdoppeln sich, weil bei den PICs die Adresse
+sich nur um 1 pro Wort erh"oht. Dieses Format ist gleichzeitig die Vorgabe.
+Im Format 1 (INHX16M) werden alle Worte in ihrer nat"urlichen Ordnung
+abgelegt. Dieses Format verwendet Microchip f"ur seine eigenen
+Programierger"ate. Format 2 (INHX8L) und 3 (INHX8H) trennen die Worte
+in ihre oberen und unteren Bytes auf. Um die komplette Information zu
+erhalten, mu"s P2HEX zweimal aufgerufen werden, z.B. so:
+\begin{verbatim}
+ p2hex test -m 2
+ rename test.hex test.obl
+ p2hex test -m 3
+ rename test.hex test.obh
+\end{verbatim}
+F"ur das Motorola-Format verwendet P2HEX zus"atzlich einen in \cite{CPM68K}
+genannten Recordtyp mit der Nummer 5, der die Zahl der folgenden
+Daten-Records (S1/S2/S3) bezeichnet. Da dieser Typ vielleicht nicht jedem
+Programm bekannt ist, kann man ihn mit der Option
+\begin{verbatim}
+ +5
+\end{verbatim}
+unterdr"ucken.
+\par
+Finden sich Code-Records verschiedener Prozessoren in einer Quelldatei,
+so erscheinen die verschiedenen Hexformate auch gemischt in der Zieldatei
+--- es empfiehlt sich also dringend, von der Filterfunktion Gebrauch zu
+machen.
+\par
+Neben dem Codetypenfilter kennt P2HEX noch ein Adre"sfilter, das n"utzlich
+ist, falls der Code auf mehrere EPROMs verteilt werden mu"s:
+\begin{verbatim}
+ -r <Startadresse>-<Endadresse>
+\end{verbatim}
+Die Startadresse ist dabei die erste Speicherzelle, die im Fenster liegen
+soll, die Endadresse die der letzten Speicherzelle im Fenster, \ii{nicht}
+die der ersten au"serhalb. Um z.B. ein 8051-Programm in 4 2764-EPROMs
+aufzuteilen, geht man folgenderma"sen vor:
+\begin{verbatim}
+p2hex <Quelldatei> eprom1 -f $31 -r $0000-$1fff
+p2hex <Quelldatei> eprom2 -f $31 -r $2000-$3fff
+p2hex <Quelldatei> eprom3 -f $31 -r $4000-$5fff
+p2hex <Quelldatei> eprom4 -f $31 -r $6000-$7fff
+\end{verbatim}
+Defaultm"a"sig ist das Fenster 32 KByte gro"s und beginnt bei Adresse 0.
+\par
+\bb{ACHTUNG!} Die Splittung "andert nichts an den absoluten Adressen, die
+in den Hexfiles stehen! Sollen die Adressen im Hexfile bei 0 beginnen,
+so kann man dies durch den zus"atzlichen Schalter
+\begin{verbatim}
+ -a
+\end{verbatim}
+erreichen. Um im Gegenteil die Adre"slage auf einen bestimmten Wert zu
+verschieben, kann man den Schalter
+\begin{verbatim}
+ -R <Wert>
+\end{verbatim}
+verwenden. Der dabei angegebene Wert ist ein {\em Offset}, d.h. er wird
+auf die in der Code-Datei angegebenen Adressen aufaddiert.
+\par
+Als Sonderwerte f"ur Start-und Endadresse beim r-Parameter ist ein
+schlichtes Dollar-Zeichen (\$) erlaubt. Diese kennzeichnet die erste
+bzw. letzte in der Programmdatei belegte Adresse. Wer also sicher
+sein will, da"s immer das ganze Programm in der Hex-Datei abgelegt
+wird, braucht sich mit dem Schalter
+\begin{verbatim}
+ -r $-$
+\end{verbatim}
+keine Gedanken mehr zu machen. Dollarzeichen und feste Adressen
+lassen sich selbstverst"andlich auch gemischt verwenden, z.B. kann
+mit
+\begin{verbatim}
+ -r $-$7fff
+\end{verbatim}
+das obere Ende auf die ersten 32K begrenzt werden.
+\par
+Den Inhalt einer Datei kann man mit einem Offset auf eine beliebige
+Position verschieben; diesen Offset h"angt man einfach in Klammern an
+den Dateinamen an. Ist der Code in einer Datei z.B. auf Adresse 0 in
+der P-Datei abgelegt, man m"ochte ihn jedoch auf Adresse 1000h
+verschieben, so h"angt man an \tty{(\$1000)} an den Dateinamen (ohne
+Leerzeichen!) an.
+\par
+Da das TI-DSK-Format Daten und Code unterscheiden kann, l"a"st sich
+mit dem Schalter
+\begin{verbatim}
+ -d <Start>-<Ende>
+\end{verbatim}
+festlegen, welche Adre"sbereiche als Daten ausgegeben werden sollen.
+Dollarzeichen sind hier \bb{nicht} zugelassen. F"ur das DSK-
+sowie Intel- und Motorola-Format relevant ist dagegen die Option
+\begin{verbatim}
+ -e <Adresse> ,
+\end{verbatim}
+mit der man die in die Hex-Datei einzutragende Startadresse festlegen
+kann. Fehlt diese Angabe, so wird nach einen entsprechenden Eintrag
+in der Code-Datei gesucht. Ist auch dort kein Hinweis auf einen
+Einsprungpunkt zu finden, so wird kein Eintrag in die HEX-Datei
+geschrieben (DSK/Intel) bzw. das entsprechende Feld wird auf 0 gesetzt
+(Motorola).
+\par
+Leider ist sich die Literatur nicht ganz "uber die Endezeile f"ur
+Intel-Hexfiles einig. P2HEX kennt daher 3 Varianten, einstellbar "uber
+den Parameter \bb{i} mit einer nachfolgenden Ziffer:
+\begin{description}
+\item[0]{ :00000001FF}
+\item[1]{ :00000001}
+\item[2]{ :0000000000}
+\end{description}
+\par
+Defaultm"a"sig wird die Variante 0 benutzt, die die gebr"auchlichste zu
+sein scheint.
+\par
+Fehlt der Zieldateiangabe eine Endung, so wird \tty{HEX} als Endung angenommen.
+\par
+Defaultm"a"sig gibt P2HEX pro Zeile maximal 16 Datenbytes aus, wie es
+auch die meisten anderen Tools tun, die Hex-Files erzeugen. Wollen
+Sie dies "andern, so k"onnen Sie dies mit dem Schalter
+\begin{verbatim}
+-l <Anzahl>
+\end{verbatim}
+tun. Der erlaubte Wertebereich liegt dabei zwischen 2 und 254 Datenbytes;
+ungerade Werte werden implizit auf gerade Anzahlen aufgerundet.
+\par
+Meist werden die tempor"aren, von AS erzeugten Code-Dateien nach einer
+Umwandlung nicht mehr unbedingt gebraucht. Mit der Kommandozeilen-
+option
+\begin{verbatim}
+-k
+\end{verbatim}
+kann man P2HEX anweisen, diese automatisch nach der Konversion zu l"oschen.
+\par
+Anders als BIND erzeugt P2HEX keine Leerdatei, wenn nur ein Dateiname
+(=Zieldatei) angegeben wurde, sondern bearbeitet die dazugeh"orige
+Codedatei. Es ist also ein Minimalaufruf \`a la
+\begin{verbatim}
+ P2HEX <Name>
+\end{verbatim}
+m"oglich, um $<$Name$>$.HEX aus $<$Name$>$.P zu erzeugen.
+
+%%---------------------------------------------------------------------------
+
+\section{P2BIN}
+
+P2BIN funktioniert wie P2HEX und bietet die gleichen Optionen (bis
+auf die a- und i- Optionen, die bei Bin"ardateien keinen Sinn ergeben), nur
+wird das Ergebnis nicht als Hexdatei, sondern als einfache Bin"ardatei
+abgelegt. Dies kann dann z.B. direkt in ein EPROM gebrannt werden.
+\par
+Zur Beeinflussung der Bin"ardatei kennt P2BIN gegen"uber P2HEX noch
+drei weitere Optionen:
+\begin{itemize}
+\item{\tty{l $<8-Bit-Zahl>$}: gibt den Wert an, mit dem unbenutzte
+ Speicherstellen in der Datei gef"ullt werden sollen.
+ Defaultm"a"sig ist der Wert \$ff, so da"s ein halbwegs
+ intelligenter EPROM-Brenner sie "uberspringt. Man kann aber
+ hiermit auch andere Werte einstellen, z.B. enthalten die gel"oschten
+ Speicherzellen der MCS-48-EPROM-Versionen Nullen. In einem solchen
+ Falle w"are 0 der richtige Wert.}
+\item{\tty{s}: weist das Programm an, eine Pr"ufsumme "uber die Bin"ardatei zu
+ berechnen. Die Pr"ufsumme wird einmal als 32-Bit-Wert ausgegeben,
+ zum anderen wird das Zweierkomplement der Bits 0..7 in der letzten
+ Speicherstelle abgelegt, so da"s die Modulo-256-Summe zu 0 wird.}
+\item{\tty{m}: f"ur den Fall, da"s ein Prozessor mit 16- oder 32-Bit-Datenbus
+ eingesetzt wird und die Bin"ardatei f"ur mehrere EPROMs aufgesplittet
+ werden mu"s. Das Argument kann folgende Werte annnehmen:
+ \begin{itemize}
+ \item{\tty{ALL}: alles kopieren}
+ \item{\tty{ODD}: alle Bytes mit ungerader Adresse kopieren}
+ \item{\tty{EVEN}: alle Bytes mit gerader Adresse kopieren}
+ \item{\tty{BYTE0}..\tty{BYTE3}: nur alle Bytes kopieren, deren Adresse die Form
+ $4n+0$...$4n+3$ hat.}
+ \item{\tty{WORD0},\tty{WORD1}: nur das untere bzw. obere 16-Bit-Wort der
+ 32-Bit-Worte kopieren.}
+ \end{itemize}}
+\end{itemize}
+
+Nicht wundern: Bei letzteren Optionen ist die Bin"ardatei um den Faktor 2
+oder 4 kleiner als bei \tty{ALL}. Dies ist bei konstantem Adre"sfenster logisch!
+
+Falls die Code-Datei keine Startadresse enth"alt, kann man diese
+analog zu P2HEX "uber die \tty{-e}-Kommandozeilenoption vorgeben. Auf
+Anforderung teilt P2BIN ihren Wert der Ergebnisdatei voran. Mit der
+Kommandozeilenoption
+\begin{verbatim}
+-S
+\end{verbatim}
+wird diese Funktion aktiviert. Sie erwartet als Argument eine
+Zahlenangabe zwischen 1 und 4, die die L"ange des Adressfeldes in
+Bytes bestimmt. Optional kann dieser Angabe auch noch der Buchstabe
+L oder B vorangestellt werden, um die Byte-Order dieser Adresse
+festzulegen. So erzeugt z.B. die Angabe \tty{B4} eine 4-Byte-Adresse in
+Big-Endian-Anordnung, \tty{L2} oder nur '2' eine 2-Byte-Adresse in
+Little-Endian-Anordnung.
+
+%%---------------------------------------------------------------------------
+
+\section{AS2MSG}
+
+Bei AS2MSG handelt es sich eigentlich um kein Hilfsprogramm, sondern um ein
+Filter, das (gl"ucklichen) Besitzern von Borland-Pascal 7.0 das Arbeiten
+mit dem Assembler erleichtern soll. In den DOS-Arbeitsumgebungen existiert
+ein ,,Tools''-Men"u, das man um eigene Programme, z.B. AS erweitern kann.
+Das Filter erlaubt, die von AS gelieferten Fehlermeldungen mit Zeilenangabe
+direkt im Editorfenster anzuzeigen. Dazu mu"s im Tools-Men"u ein neuer
+Eintrag angelegt werden (\tty{Options/Tools/New}). Tragen Sie in die
+einzelnen Felder folgende Werte ein :
+\begin{itemize}
+\item{Title: \tty{\verb!~!M\verb!~!akroassembler}}
+\item{Program path: \tty{AS}}
+\item{Command line: \tty{-E !1 \$EDNAME \$CAP MSG(AS2MSG) \$NOSWAP \$SAVE
+ALL}}
+\item{bei Bedarf einen Hotkey zuordnen (z.B. Shift-F7)}
+\end{itemize}
+Die Option \tty{-E} sorgt daf"ur, da"s Turbo-Pascal nicht mit STDOUT und
+STDERR durcheinander kommt.
+\par
+Ich setze dabei voraus, da"s sowohl AS als auch AS2MSG sich in einem
+Verzeichnis befinden, welches in der Pfadliste aufgef"uhrt ist. Nach einem
+Druck auf dem passenden Hotkey (oder Auswahl aus dem Tools-Men"u) wird AS mit
+dem Namen der Textdatei im aktiven Editorfenster aufgerufen. Die dabei
+aufgetretenen Fehler werden in ein separates Fenster geleitet, durch das man
+nun ,,browsen'' kann. Mit \bb{Ctrl-Enter} springt man eine fehlerhafte
+Zeile an. Zus"atzlich enth"alt das Fenster die Statistik, die AS am Ende
+der Assemblierung ausgibt. Diese erhalten als Dummy-Zeilennummer 1.
+\par
+F"ur diese Arbeitsweise sind sowohl TURBO.EXE (Real Mode) als auch BP.EXE
+(Protected Mode) geeignet. Ich empfehle BP, da in dieser Variante beim
+Aufruf nicht erst der halbe DOS-Speicher ,,freigeswappt'' werden mu"s.
+
+\cleardoublepage
+
+\appendix
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Fehlermeldungen von AS}
+\label{ChapErrMess}
+
+Im folgenden findet sich eine halb-tabellarische Auflistung der in AS
+definierten Fehlermeldungen. Zu jeder Fehlermeldung finden sich folgende
+Angaben:
+\begin{itemize}
+\item{interne Fehlernummer (f"ur den Anwender nur mit der \tty{n}-Option sichtbar);}
+\item{Fehlermeldung im Klartext;}
+\item{Typ:
+ \begin{itemize}
+ \item{Warnung: zeigt m"ogliche Fehler oder ineffizienten Code an.
+ Assemblierung geht weiter.}
+ \item{Fehler: echte Fehler. Assemblierung geht weiter, aber keine
+ Code-Datei wird geschrieben.}
+ \item{Fatal: schwerwiegende Fehler. Assemblierung wird abgebrochen.}
+ \end{itemize}}
+\item{Ursache: die Situation(en), in denen der Fehler ausgegeben
+ wird;}
+\item{Argument: Die Ausgabe, die auf Wunsch als erweiterte Fehlermeldung
+ erfolgt.}
+\end{itemize}
+
+\par
+
+\newcommand{\errentry}[5]
+ {\item[#1]{#2
+ \begin{description}
+ \item[Type:]{\ \\#3}
+ \item[Reason:]{\ \\#4}
+ \item[Argument:]{\ \\#5}
+ \end{description}}
+ }
+
+\begin{description}
+\errentry{ 0}{Displacement=0, "uberfl"ussig}
+ {Warnung}
+ {bei 680x0-,6809- und COP8-Prozessoren: Das Displacement
+ in einem Adre"sausdruck hat den Wert 0 ergeben. Es wird
+ ein Adre"sausdruck ohne Displacement erzeugt. Um keine
+ Phasenfehler zu erzeugen, werden NOP-Befehle eingef"ugt.}
+ {keines}
+\errentry{ 10}{Kurzadressierung m"oglich}
+ {Warnung}
+ {bei 680x0-, 6502- und 68xx-Prozessoren k"onnen
+ bestimmte Speicherbereiche mit kurzen Adressen erreicht
+ werden. Um keine Phasefehler zu erzeugen, wird zwar der
+ k"urzere Ausdruck erzeugt, der freie Platz wird aber mit
+ NOPs aufgef"ullt.}
+ {keines}
+\errentry{ 20}{kurzer Sprung m"oglich}
+ {Warnung}
+ {Bei 680x0 und 8086-Prozessoren kann der Sprung
+ sowohl mit langem als auch kurzem Displacement ausgef"uhrt
+ werden. Da kein kurzer Sprung angefordert wurde, wurde im
+ ersten Pass Platz f"ur den langen Sprung freigehalten.
+ Es wird ein kurzer Sprung erzeugt, der freie Platz wird
+ mit NOPs aufgef"ullt, um Phasenfehler zu vermeiden.}
+ {keines}
+\errentry{ 30}{kein Sharefile angelegt, SHARED ignoriert}
+ {Warnung}
+ {Es wurde eine \tty{SHARED}-Anweisung gefunden, es
+ wurde aber keine Kommandozeilenoption angegeben, um eine
+ Shared-Datei zu erzeugen.}
+ {keines}
+\errentry{ 40}{FPU liest Wert evtl. nicht korrekt ein ($>$=1E1000)}
+ {Warnung}
+ {Das BCD-Gleitkommaformat der 680x0-Koprozessoren
+ erlaubt zwar vierstellige Exponenten, lt. Datenbuch
+ k"onnen solche Werte aber nicht korrekt eingelesen werden.
+ Der vierstellige Wert wird zwar erzeugt, eine Funktion ist
+ aber nicht gew"ahleistet.}
+ {keines}
+\errentry{ 50}{Privilegierte Anweisung}
+ {Warnung}
+ {Es wurde eine Anweisung benutzt, die nur im
+ Supervisor-Mode zul"assig ist, obwohl dieser nicht mittels
+ \tty{SUPMODE ON} vorher explizit angezeigt wurde.}
+ {keines}
+\errentry{ 60}{Distanz 0 nicht bei Kurzsprung erlaubt (NOP erzeugt)}
+ {Warnung}
+ {Ein kurzer Sprung mit der Distanz 0 ist bei
+ 680x0- bzw. COP8-Prozessoren nicht erlaubt, da dieser Sonderwert f"ur
+ lange Spr"unge ben"otigt wird. Stattdessen wurde ein
+ NOP-Befehl eingef"ugt.}
+ {keines}
+\errentry{ 70}{Symbol aus falschem Segment}
+ {Warnung}
+ {Das in dem Operanden benutzte Symbol
+ ist aus einem Adre"sraum, der nicht mit dem benutzten
+ Befehl bearbeitet werden kann.}
+ {keines}
+\errentry{ 75}{Segment nicht adressierbar}
+ {Warnung}
+ {Das in dem Operanden benutzte Symbol
+ ist aus einem Adre"sraum, der mit keinem der Segmentregister
+ des 8086 adressiert werden kann.}
+ {Name des nicht adressierbaren Segments}
+\errentry{ 80}{"Anderung des Symbolwertes erzwingt zus"atzlichen Pass}
+ {Warnung}
+ {Ein Symbol hat einen anderen Wert zugewiesen
+ bekommen als im vorhergehenden Pass. Diese Warnung wird
+ nur ausgegeben, falls die \tty{r}-Option angegeben wurde.}
+ {Der Name des fraglichen Symbols}
+\errentry{ 90}{"Uberlappende Speicherbelegung}
+ {Warnung}
+ {Bei der Bildung der Belegungsliste wurde
+ festgestellt, da"s ein Speicherbereich im Codesegment
+ mehrfach benutzt wurde. Ursache k"onnen un"uberlegte
+ \tty{ORG}-Anweisungen sein.}
+ {keines}
+\errentry{ 100}{keine CASE-Bedingung zugetroffen}
+ {Warnung}
+ {bei einem \tty{SWITCH}..\tty{CASE}-Konstrukt ohne
+ \tty{ELSECASE}-Zweig traf keiner der \tty{CASE}-Zweige zu.}
+ {keines}
+\errentry{ 110}{Seite m"oglicherweise nicht adressierbar}
+ {Warnung}
+ {Das in dem Operanden benutzte Symbol
+ liegt nicht in der momentan mit \tty{ASSUME} eingestellten
+ Fenster (ST6,78(C)10).}
+ {keines}
+\errentry{ 120}{Registernummer mu"s gerade sein}
+ {Warnung}
+ {Die Hardware erlaubt nur ein Registerpaar
+ zu verketten, dessen Startadresse gerade ist (RR0, RR2...,
+ nur Z8).}
+ {keines}
+\errentry{ 130}{veralteter Befehl}
+ {Warnung}
+ {Der verwendete Befehl ist zwar noch
+ definiert, ist in seiner Funktion aber durch andere,
+ neue Befehle ersetzbar und daher in zuk"unftigen
+ Prozessorversionen eventuell nicht mehr vorhanden.}
+ {keines}
+\errentry{ 140}{Nicht vorhersagbare Ausf"uhrung dieser Anweisung}
+ {Warnung}
+ {Die verwendete Adressierungsart ist bei
+ diesem Befehl zwar prinzipiell erlaubt, ein Register
+ wird jedoch in einer Weise doppelt verwendet, da"s je
+ nach Aus"uhrungsreihenfolge sich unterschiedliche
+ Ergebnisse einstellen k"onnen.}
+ {keines}
+\errentry{ 150}{Lokaloperator au"serhalb einer Sektion "uberfl"ussig}
+ {Warnung}
+ {Ein vorangestellter Klammeraffe dient
+ dazu, sich explizit auf zu der Sektion lokale Symbole
+ zu beziehen. Wenn man sich au"serhalb einer Sektion
+ befindet, gibt es keine lokalen Symbole, weshalb dieser
+ Operator "uberfl"ussig ist.}
+ {keines}
+\errentry{ 160}{sinnlose Operation}
+ {Warnung}
+ {Die Anweisung ergibt entweder "uberhaupt
+ keinen Sinn oder kann auf andere Weise schneller und k"urzer
+ ausgef"uhrt werden.}
+ {keines}
+\errentry{ 170}{unbekannter Symbolwert erzwingt zus"atzlichen Pass}
+ {Warnung}
+ {AS vermutet eine Vorw"artsreferenz eines
+ Symbols, d.h. das Symbol wird benutzt, bevor es definiert
+ wurde, und h"alt einen weiteren Pass f"ur unumg"anglich.
+ Diese Warnung wird nur ausgegeben, falls die \tty{r}-Option
+ angegeben wurde.}
+ {Der Name des fraglichen Symbols}
+\errentry{ 180}{Adresse nicht ausgerichtet}
+ {Warnung}
+ {Eine Adresse ist nicht ein mehrfaches der
+ Operandengr"o"se. Das Datenbuch verbietet zwar solche Zugriffe,
+ im Instruktionswort ist aber Platz f"ur diese Adresse, so da"s
+ AS es bei einer Warnung belassen hat.}
+ {keines}
+\errentry{ 190}{I/O-Adresse darf nicht verwendet werden}
+ {Warnung}
+ {Der verwendete Adressierungsmodus oder die
+ angesprochene Adresse sind zwar prinzipiell erlaubt, die
+ Adresse liegt aber im Bereich der Peripherieregister, die in
+ diesem Zusammenhang nicht verwendet werden d"urfen.}
+ {keines}
+\errentry{ 200}{m"ogliche Pipeline-Effekte}
+ {Warnung}
+ {Ein Register wird in einer Befehlsfolge so
+ verwendet, da"s die Befehlsausf"uhrung m"oglicherweise nicht
+ in der hingeschriebenen Form ablaufen wird. "Ublicherweise
+ wird ein Register benutzt, bevor der neue Wert zur Verf"ugung
+ steht.}
+ {das die Verklemmung verursachende Register}
+\errentry{ 210}{mehrfache Adre"sregisterbenutzung in einer Anweisung}
+ {Warnung}
+ {Ein Adre"sregister wird in mehreren
+ Adre"sausdr"ucken eines Befehls benutzt. Sofern einer der
+ beiden Ausdr"ucke das Register modifiziert, sind die
+ Ergebnisadressen nicht eindeutig festgelegt.}
+ {das mehrfach verwendete Register}
+\errentry{ 220}{Speicherstelle ist nicht bitadressierbar}
+ {Warnung}
+ {Mit einer \tty{SFRB}-Anweisung wurde
+ versucht, eine Speicherstelle als bitadressierbar zu
+ deklarieren, die aufgrund der Architektur des 8051 nicht
+ bitadressierbar ist.}
+ {keines}
+\errentry{ 230}{Stack ist nicht leer}
+ {Warnung}
+ {Am Ende eines Durchlaufes ist ein vom
+ Programm definierter Stack nicht leer.}
+ {der Name des Stacks sowie seine Resttiefe}
+\errentry{ 240}{NUL-Zeichen in Strings, Ergebnis undefiniert}
+ {Warnung}
+ {Eine String-Konstante enth"alt ein
+ NUL-Zeichen. Dies funktioniert zwar mit der Pascal-Version,
+ in Hinblick auf die C-Version von AS ist dies aber ein Problem,
+ da C Strings mit einem NUL-Zeichen terminiert, d.h. der String
+ w"are f"ur C an dieser Stelle zu Ende...}
+ {keines}
+\errentry{ 250}{Befehl "uberschreitet Seitengrenze}
+ {Warnung}
+ {Ein Befehl steht zu Teilen auf
+ verschiedenen Seiten. Da der Programmz"ahler des Prozessors
+ aber nicht "uber Seitengrenzen hinweg inkrementiert wird,
+ w"urde zur Laufzeit anstelle des Instruktionsbytes von der
+ Folgeseite wieder das erste Byte der alten Seite geholt; das
+ Programm w"urde fehlerhaft ablaufen.}
+ {keines}
+\errentry{ 260}{Bereichs"uberschreitung}
+ {Warnung}
+ {Ein Zahlenwert lag au"serhalb des erlaubten Bereichs. AS
+ hat den Wert durch ein Abschneiden der oberen Bitstellen
+ in den erlaubten Bereich gebracht, es ist jedoch nicht
+ garantiert, da"s sich durch diese Operation sinnvoller und
+ korrekter Code ergibt.}
+ {keines}
+\errentry{ 270}{negatives Argument f"ur DUP}
+ {Warnung}
+ {Das Wiederholungsargument einer \tty{DUP}-Direktive war
+ kleiner als 0. Es werden (analog zu einem Argument von
+ genau 0) keine Daten abgelegt.}
+ {keines}
+\errentry{1000}{Symbol doppelt definiert}
+ {Fehler}
+ {Einem Symbol wurde durch ein Label oder
+ \tty{EQU}, \tty{PORT}, \tty{SFR}, \tty{LABEL},
+ \tty{SFRB} oder \tty{BIT} ein neuer Wert zugewiesen, dies
+ ist aber nur bei \tty{SET/EVAL} erlaubt.}
+ {Name des fraglichen Symbols, bei eingeschalteter
+ Querverweisliste zus"atzlich die Zeile der ersten Definition}
+\errentry{1010}{Symbol nicht definiert}
+ {Fehler}
+ {Ein benutztes Symbol ist auch im 2.Pass noch
+ nicht in der Symboltabelle enthalten.}
+ {Name des nicht gefundenen Symbols}
+\errentry{1020}{Ung"ultiger Symbolname}
+ {Fehler}
+ {Ein Symbolname entspricht nicht den Bedingungen
+ f"ur einen g"ultigen Symbolnamen. Beachten Sie, da"s f"ur
+ Makro-und Funktionsparameter strengere Regeln gelten!}
+ {der fehlerhafte Symbolname}
+\errentry{1090}{Ung"ultiges Format}
+ {Fehler}
+ {Das benutzte Befehlsformat existiert bei diesem
+ Befehl nicht.}
+ {Der Kennbuchstabe des verwendeten Formates}
+\errentry{1100}{"Uberfl"ussiges Attribut}
+ {Fehler}
+ {Der benutzte Befehl (Prozessor oder Pseudo) darf
+ kein mit einem Punkt angeh"angtes Attribut haben.}
+ {keines}
+\errentry{1105}{Attribut darf nur 1 Zeichen lang sein}
+ {Fehler}
+ {Das mit einem Punkt an einen Befehl angeh"angte
+ Attribut mu"s genau ein Zeichen lang sein; weder mehr noch
+ weniger ist erlaubt.}
+ {keines}
+\errentry{1110}{Unpassende Operandenzahl}
+ {Fehler}
+ {Die bei einem Befehl (Prozessor oder Pseudo)
+ angegebene Operandenzahl liegt nicht in dem f"ur diesen
+ Befehl erlaubten Bereich.}
+ {keines}
+\errentry{1115}{Unpassende Optionenzahl}
+ {Fehler}
+ {Die bei diesem Befehl angegebene Zahl
+ von Optionen liegt nicht in dem f"ur diesen
+ Befehl erlaubten Bereich.}
+ {keines}
+\errentry{1120}{nur immediate-Adressierung erlaubt}
+ {Fehler}
+ {Der benutzte Befehl l"a"st nur
+ immediate-Operanden (mit vorangestelltem \#) zu.}
+ {keines}
+\errentry{1130}{Unpassende Operandengr"o"se}
+ {Fehler}
+ {Der Operand hat zwar einen f"ur den Befehl
+ zugelassenen Typ, jedoch nicht die richtige L"ange (in
+ Bits).}
+ {keines}
+\errentry{1131}{Widersprechende Operandengr"o"sen}
+ {Fehler}
+ {Die angegebenen Operanden haben unterschiedliche
+ L"angen (in Bit).}
+ {keines}
+\errentry{1132}{Undefinierte Operandengr"o"se}
+ {Fehler}
+ {Aus Opcode und Operanden l"a"st sich die
+ Operandengr"o"se nicht eindeutig bestimmen (ein Problem
+ des 8086-Assemblers). Sie m"ussen die Operandengr"o"se
+ durch einen \tty{BYTE}, \tty{WORD}, usw. \tty{PTR}-Pr"afix
+ festlegen.}
+ {keines}
+\errentry{1135}{Ung"ultiger Operandentyp}
+ {Fehler}
+ {Ein Ausdruck hat einen an dieser Stelle nicht
+ zul"assigen Typ (Integer/Gleitkomma/String).}
+ {Die an dieser Stelle zul"assigen Datentypen}
+\errentry{1140}{Zuviele Argumente}
+ {Fehler}
+ {Einem Befehl wurden mehr als die unter AS
+ zul"assigen 20 Parameter "ubergeben.}
+ {keines}
+\errentry{1200}{Unbekannter Befehl}
+ {Fehler}
+ {Der benutzte Befehl ist weder ein Pseudobefehl
+ von AS noch ein Befehl des momentan eingestellten
+ Prozessors.}
+ {keines}
+\errentry{1300}{Klammerfehler}
+ {Fehler}
+ {Der Formelparser ist auf einen (Teil-)Ausdruck
+ gesto"sen, in dem die Summe "offnender und schlie"sender
+ Klammern nicht "ubereinstimmt.}
+ {der beanstandete (Teil-)Ausdruck}
+\errentry{1310}{Division durch 0}
+ {Fehler}
+ {Bei einer Division oder Modulooperation ergab
+ die Auswertung des rechten Teilausdruckes 0.}
+ {keines}
+\errentry{1315}{Bereichsunterschreitung}
+ {Fehler}
+ {Der angegebene Integer-Wert unterschreitet
+ den zul"assigen Bereich.}
+ {aktueller Wert und zul"assiges Minimum
+ (manchmal, ich stelle das gerade um...)}
+\errentry{1320}{Bereichs"uberschreitung}
+ {Fehler}
+ {Der angegebene Integer-Wert "uberschreitet
+ den zul"assigen Bereich.}
+ {aktueller Wert und zul"assiges Maximum
+ (manchmal,ich stelle das gerade um...)}
+\errentry{1325}{Adresse nicht ausgerichtet}
+ {Fehler}
+ {Die angegebene direkte Speicheradresse
+ entspricht nicht den Anspr"uchen des Datentransfers, d.h.
+ ist nicht ein mehrfaches der Operandengr"o"se. Nicht alle
+ Prozessoren erlauben unausgerichtete Datenzugriffe.}
+ {keines}
+\errentry{1330}{Distanz zu gro"s}
+ {Fehler}
+ {Der in einem Adre"sausdruck enthaltene
+ Displacement-Wert ist zu gro"s.}
+ {keines}
+\errentry{1340}{Kurzadressierung nicht m"oglich}
+ {Fehler}
+ {Die Adresse des Operanden liegt au"serhalb des
+ Speicherbereiches, in dem Kurzadressierung m"oglich ist.}
+ {keines}
+\errentry{1350}{Unerlaubter Adressierungsmodus}
+ {Fehler}
+ {Der benutzte Adressierungsmodus existiert
+ generell zwar, ist an dieser Stelle aber nicht erlaubt.}
+ {keines}
+\errentry{1351}{Nummer mu"s ausgerichtet sein}
+ {Fehler}
+ {An dieser Stelle sind nur ausgerichtete
+ (d.h z.B. gerade) Adressen erlaubt, da die untersten Bits f"ur
+ andere Zwecke verwendet werden oder reserviert sind.}
+ {keines}
+\errentry{1355}{Adressierungsmodus im Parallelbetrieb nicht erlaubt}
+ {Fehler}
+ {Die verwendeten Adressierungsmodi
+ sind zwar im sequentiellen Modus zul"assig, jedoch nicht
+ bei parallelen Instruktionen.}
+ {keines}
+\errentry{1360}{Undefinierte Bedingung}
+ {Fehler}
+ {Die benutzte Bedingung f"ur bedingte Spr"unge
+ existiert nicht.}
+ {keines}
+\errentry{1370}{Sprungdistanz zu gro"s}
+ {Fehler}
+ {Sprungbefehl und Sprungziel liegen zu weit
+ auseinander, um mit einem Sprung der benutzten L"ange
+ "uberbr"uckt werden zu k"onnen.}
+ {keines}
+\errentry{1375}{Sprungdistanz ist ungerade}
+ {Fehler}
+ {Da Befehle nur auf geraden Adressen liegen
+ d"urfen, mu"s eine Sprungdistanz zwischen zwei Befehlen
+ auch immer gerade sein, das Bit 0 der Distanz wird
+ anderweitig verwendet. Diese Bedingung ist verletzt
+ worden. Grund ist "ublicherweise die Ablage einer
+ ungeraden Anzahl von Daten in Bytes oder ein falsches \tty{ORG}.}
+ {keines}
+\errentry{1380}{ung"ultiges Schiebeargument}
+ {Fehler}
+ {als Argument f"ur die Schiebeamplitude darf nur
+ eine Konstante oder ein Datenregister verwendet werden.
+ (nur 680x0)}
+ {keines}
+\errentry{1390}{Nur Bereich 1..8 erlaubt}
+ {Fehler}
+ {Konstanten f"ur Schiebeamplituden oder
+ \tty{ADDQ}-Argumente d"urfen nur im Bereich 1..8 liegen. (nur
+ 680x0)}
+ {keines}
+\errentry{1400}{Schiebezahl zu gro"s}
+ {Fehler}
+ {(nicht mehr verwendet)}
+ {keines}
+\errentry{1410}{Ung"ultige Registerliste}
+ {Fehler}
+ {Das Registerlisten-Argument von \tty{MOVEM}
+ oder \tty{FMOVEM} hat ein falsches Format. (nur 680x0)}
+ {keines}
+\errentry{1420}{Ung"ultiger Modus mit CMP}
+ {Fehler}
+ {Die verwendete Operandenkombination von \tty{CMP}
+ ist nicht erlaubt. (nur 680x0)}
+ {keines}
+\errentry{1430}{Ung"ultiger Prozessortyp}
+ {Fehler}
+ {Den mit CPU angeforderten Zielprozessor kennt AS
+ nicht.}
+ {der unbekannte Prozessortyp}
+\errentry{1440}{Ung"ultiges Kontrollregister}
+ {Fehler}
+ {Das bei z.B. \tty{MOVEC} benutzte
+ Kontrollregister kennt der mit CPU gesetzte Prozessor
+ (noch) nicht.}
+ {keines}
+\errentry{1445}{Ung"ultiges Register}
+ {Fehler}
+ {Das benutzte Register ist zwar prinzipiell
+ vorhanden, hier aber nicht erlaubt.}
+ {keines}
+\errentry{1450}{RESTORE ohne SAVE}
+ {Fehler}
+ {Es wurde ein \tty{RESTORE}-Befehl gefunden, obwohl
+ kein mit \tty{SAVE} gespeicherter Zustand (mehr) auf dem Stapel
+ vorhanden ist.}
+ {keines}
+\errentry{1460}{fehlendes RESTORE}
+ {Fehler}
+ {Nach der Assemblierung sind nicht alle
+ \tty{SAVE}-Befehle wieder aufgel"ost worden.}
+ {keines}
+\errentry{1465}{unbekannte Makro-Steueranweisung}
+ {Fehler}
+ {Eine beim \tty{MACRO}-Befehl zus"atzlich angegebene
+ Steueranweisung ist AS unbekannt.}
+ {die fragliche Anweisung}
+\errentry{1470}{fehlendes ENDIF/ENDCASE}
+ {Fehler}
+ {Nach der Assemblierung sind nicht alle
+ Konstrukte zur bedingten Assemblierung aufgel"ost
+ worden.}
+ {keines}
+\errentry{1480}{ung"ultiges IF-Konstrukt}
+ {Fehler}
+ {Die Reihenfolge der Befehle in einem \tty{IF}-
+ oder \tty{SWITCH}-Konstrukt stimmt nicht.}
+ {keines}
+\errentry{1483}{doppelter Sektionsname}
+ {Fehler}
+ {Es existiert bereits eine Sektion gleichen
+ Namens auf dieser Ebene.}
+ {der doppelte Name}
+\errentry{1484}{unbekannte Sektion}
+ {Fehler}
+ {Im momentanen Sichtbarkeitsbereich existiert
+ keine Sektion dieses Namens.}
+ {der unbekannte Name}
+\errentry{1485}{fehlendes ENDSECTION}
+ {Fehler}
+ {Nach Ende eines Durchganges sind nicht alle
+ Sektionen wieder geschlossen worden.}
+ {keines}
+\errentry{1486}{falsches ENDSECTION}
+ {Fehler}
+ {die bei \tty{ENDSECTION} angegebene Sektion
+ ist nicht die innerste offene.}
+ {keines}
+\errentry{1487}{ENDSECTION ohne SECTION}
+ {Fehler}
+ {Es wurde ein \tty{ENDSECTION}-Befehl gegeben, obwohl
+ gar keine Sektion offen war.}
+ {keines}
+\errentry{1488}{nicht aufgel"oste Vorw"artsdeklaration}
+ {Fehler}
+ {ein mit \tty{FORWARD} oder \tty{PUBLIC}
+ angek"undigtes Symbol wurde nicht in der Sektion definiert.}
+ {der Name des fraglichen Symbols}
+\errentry{1489}{widersprechende FORWARD $\leftrightarrow$PUBLIC-Deklaration}
+ {Fehler}
+ {Ein Symbol wurde sowohl als privat als auch
+ global definiert.}
+ {der Name des Symbols}
+\errentry{1490}{falsche Argumentzahl f"ur Funktion}
+ {Fehler}
+ {Die Anzahl der Argumente f"ur eine
+ selbstdefinierte Funktion stimmt nicht mit der geforderten
+ Anzahl "uberein.}
+ {keines}
+\errentry{1495}{unaufgel"oste Literale (LTORG fehlt)}
+ {Fehler}
+ {Am Programmende oder beim Umachalten
+ zu einem anderen Zielprozessor blieben noch nicht
+ abgelegte Literale "ubrig.}
+ {keines}
+\errentry{1500}{Befehl auf dem ... nicht vorhanden}
+ {Fehler}
+ {Der benutzte Befehl existiert zwar
+ grunds"atzlich, das eingestellte Mitglied der
+ Prozessorfamilie beherrscht ihn aber noch nicht.}
+ {keines}
+\errentry{1505}{Adressierungsart auf dem ... nicht vorhanden}
+ {Fehler}
+ {Der benutzte Adressierungsmodus existiert
+ zwar grunds"atzlich, das eingestellte Mitglied der
+ Prozessorfamilie beherrscht ihn aber noch nicht.}
+ {keines}
+\errentry{1510}{Ung"ultige Bitstelle}
+ {Fehler}
+ {Die angegebene Bitnummer ist nicht erlaubt
+ oder eine Angabe fehlt komplett.}
+ {keines}
+\errentry{1520}{nur ON/OFF erlaubt}
+ {Fehler}
+ {Dieser Pseudobefehl darf als Argument nur \tty{ON}
+ oder \tty{OFF} haben.}
+ {keines}
+\errentry{1530}{Stack ist leer oder nicht definiert}
+ {Fehler}
+ {Es wurde bei einem \tty{POPV}
+ einen Stack anzusprechen, der entweder nie definiert oder
+ bereits leerger"aumt wurde.}
+ {der Name des fraglichen Stacks}
+\errentry{1540}{Nicht genau ein Bit gesetzt}
+ {Fehler}
+ {In einer Bitmaske, die der \tty{BITPOS}-
+ Funktion "ubergeben wurde, war nicht genau ein Bit
+ gesetzt.}
+ {keines}
+\errentry{1550}{ENDSTRUCT ohne STRUCT}
+ {Fehler}
+ {Eine \tty{ENDSTRUCT}-Anweisung wurde gegeben, obwohl
+ momentan keine Strukturdefinition in Gange war.}
+ {keines}
+\errentry{1551}{offene Strukturdefinition}
+ {Fehler}
+ {Nach Ende der Assemblierung waren noch nicht alle
+ \tty{STRUCT}-Anweisungen durch passende \tty{ENDSTRUCT}s
+ abgeschlossen.}
+ {die innerste, noch nicht abgeschlossene
+ Strukturdefinition}
+\errentry{1552}{falsches ENDSTRUCT}
+ {Fehler}
+ {Der Namensparameter einer \tty{ENDSTRUCT}-Anweisung
+ entspricht nicht der innersten, offenen
+ Strukturdefinition.}
+ {keines}
+\errentry{1553}{Phasendefinition nicht in Strukturen erlaubt}
+ {Fehler}
+ {Was gibt es dazu zu sagen? \tty{PHASE} in einem Record
+ ergibt einfach keinen Sinn und nur Verwirrung...}
+ {keines}
+\errentry{1554}{ung"ultige \tty{STRUCT}-Direktive}
+ {Fehler}
+ {Als Direktive f"ur \tty{STRUCT} ist nur
+ \tty{EXTNAMES} oder \tty{NOEXTNAMES} zugelassen.}
+ {die unbekannte Direktive}
+\errentry{1600}{vorzeitiges Dateiende}
+ {Fehler}
+ {Es wurde mit einem \tty{BINCLUDE}-Befehl versucht,
+ "uber das Ende einer Datei hinauszulesen.}
+ {keines}
+\errentry{1700}{ROM-Offset geht nur von 0..63}
+ {Fehler}
+ {Das Konstanten-ROM der 680x0-Koprozessoren hat
+ nur max. 63 Eintr"age.}
+ {keines}
+\errentry{1710}{Ung"ultiger Funktionscode}
+ {Fehler}
+ {Als Funktionscodeargument darf nur SFC, DFC, ein
+ Datenregister oder eine Konstante von 0..15 verwendet
+ werden. (nur 680x0-MMU)}
+ {keines}
+\errentry{1720}{Ung"ultige Funktionscodemaske}
+ {Fehler}
+ {Als Funktionscodemaske darf nur ein Wert von
+ 0..15 verwendet werden. (nur 680x0-MMU)}
+ {keines}
+\errentry{1730}{Ung"ultiges MMU-Register}
+ {Fehler}
+ {Die MMU hat kein Register mit dem angegebenen
+ Namen. (nur 680x0-MMU)}
+ {keines}
+\errentry{1740}{Level nur von 0..7}
+ {Fehler}
+ {Die Ebene f"ur \tty{PTESTW} und \tty{PTESTR} mu"s eine
+ Konstante von 0..7 sein. (nur 680x0-MMU)}
+ {keines}
+\errentry{1750}{ung"ultige Bitmaske}
+ {Fehler}
+ {Die bei den Bit-Feld-Befehlen angegebene
+ Bitmaske hat ein falsches Format. (nur 680x0)}
+ {keines}
+\errentry{1760}{ung"ultiges Registerpaar}
+ {Fehler}
+ {Das angegebene Registerpaar ist hier nicht
+ verwendbar oder syntaktisch falsch. (nur 680x0)}
+ {keines}
+\errentry{1800}{offene Makrodefinition}
+ {Fehler}
+ {Eine Makrodefinition war am Dateiende nicht
+ zuende. Vermutlich fehlt ein \tty{ENDM}.}
+ {keines}
+\errentry{1805}{EXITM au"serhalb eines Makrorumpfes}
+ {Fehler}
+ {\tty{EXITM} bricht die Expansion von
+ Makro-Konstrukten ab. Dieser Befehl macht nur innerhalb
+ von Makros Sinn und es wurde versucht, ihn au"serhalb
+ aufzurufen.}
+ {keines}
+\errentry{1810}{mehr als 10 Makroparameter}
+ {Fehler}
+ {Ein Makro darf h"ochstens 10 Parameter haben.}
+ {keines}
+\errentry{1815}{doppelte Makrodefinition}
+ {Fehler}
+ {Ein Makronamne wurde in einer Sektion doppelt
+ vergeben.}
+ {der doppelt verwendete Name}
+\errentry{1820}{Ausdruck mu"s im ersten Pass berechenbar sein}
+ {Fehler}
+ {Der benutzte Befehl beeinflu"st die Codel"ange,
+ daher sind Vorw"artsreferenzen hier nicht erlaubt.}
+ {keines}
+\errentry{1830}{zu viele verschachtelte IFs}
+ {Fehler}
+ {(nicht mehr verwendet)}
+ {keines}
+\errentry{1840}{ELSEIF/ENDIF ohne ENDIF}
+ {Fehler}
+ {es wurde ein \tty{ELSEIF}- oder \tty{ENDIF}-Befehl gefunden,
+ obwohl kein offener \tty{IF}-Befehl vorhanden ist.}
+ {keines}
+\errentry{1850}{verschachtelter/rekursiver Makroaufruf}
+ {Fehler}
+ {(nicht mehr verwendet)}
+ {keines}
+\errentry{1860}{unbekannte Funktion}
+ {Fehler}
+ {Die angesprochene Funktion ist weder eingebaut
+ noch nachtr"aglich definiert worden.}
+ {der Funktionsname}
+\errentry{1870}{Funktionsargument au"serhalb Definitionsbereich}
+ {Fehler}
+ {Das Argument liegt nicht im Bereich der
+ angesprochenen transzendenten Funktion.}
+ {keines}
+\errentry{1880}{Gleitkomma"uberlauf}
+ {Fehler}
+ {Das Argument liegt zwar im Bereich der
+ angesprochenen transzendenten Funktion, das Ergebnis
+ w"are aber nicht mehr darstellbar.}
+ {keines}
+\errentry{1890}{ung"ultiges Wertepaar}
+ {Fehler}
+ {Das benutzte P"archen aus Basis und Exponent
+ kann nicht berechnet werden.}
+ {keines}
+\errentry{1900}{Befehl darf nicht auf dieser Adresse liegen}
+ {Fehler}
+ {Die Prozessorhardware erlaubt keine
+ Spr"unge von dieser Adresse.}
+ {keines}
+\errentry{1905}{ung"ultiges Sprungziel}
+ {Fehler}
+ {Die Prozessorhardware erlaubt keine
+ Spr"unge zu dieser Adresse.}
+ {keines}
+\errentry{1910}{Sprungziel nicht auf gleicher Seite}
+ {Fehler}
+ {Sprungbefehl und Sprungziel m"ussen bei diesem
+ Befehl auf der gleichen Seite liegen.}
+ {keines}
+\errentry{1920}{Code"uberlauf}
+ {Fehler}
+ {Es wurde versucht, mehr als 1024 Bytes Code oder
+ Daten in einer Zeile zu erzeugen.}
+ {keines}
+\errentry{1925}{Adre"s"uberlauf}
+ {Fehler}
+ {Der Adre"sraum dieses Prozessors wurde
+ "uberschritten.}
+ {keines}
+\errentry{1930}{Konstanten und Platzhalter nicht mischbar}
+ {Fehler}
+ {Anweisungen, die Speicher reservieren und solche,
+ die ihn mit Konstanten belegen, d"urfen nicht in einer
+ Pseudoanweisung gemischt werden.}
+ {keines}
+\errentry{1940}{Codeerzeugung in Strukturdefinition nicht zul"assig}
+ {Fehler}
+ {Ein \tty{STRUCT}-Konstrukt dient nur der Beschreibung
+ einer Datenstruktur und nicht dem Anlegen einer solchen,
+ es sind daher keine Befehle zugelassen, die Code erzeugen.}
+ {keines}
+\errentry{1950}{Paralleles Konstrukt nicht m"oglich}
+ {Fehler}
+ {Entweder sind die beiden Instruktionen
+ prinzipiell nicht parallel ausf"uhrbar, oder sie stehen nicht
+ unmittelbar untereinander.}
+ {keines}
+\errentry{1960}{ung"ultiges Segment}
+ {Fehler}
+ {Das angegebene Segment ist an dieser Stelle
+ nicht anwendbar.}
+ {der benutzte Segmentname}
+\errentry{1961}{unbekanntes Segment}
+ {Fehler}
+ {Das angegebene Segment existiert bei
+ diesem Prozessor nicht.}
+ {der benutzte Segmentname}
+\errentry{1962}{unbekanntes Segmentregister}
+ {Fehler}
+ {Das angegebene Segmentregister existiert
+ nicht (nur 8086).}
+ {keines}
+\errentry{1970}{ung"ultiger String}
+ {Fehler}
+ {Der angegebene String hat ein ung"ultiges
+ Format.}
+ {keines}
+\errentry{1980}{ung"ultiger Registername}
+ {Fehler}
+ {Das angegebene Register existiert nicht oder
+ darf hier nicht verwendet werden.}
+ {keines}
+\errentry{1985}{ung"ultiges Argument}
+ {Fehler}
+ {Der angegebene Befehl darf nicht mit einem
+ \tty{REP}-Pr"afix versehen werden.}
+ {keines}
+\errentry{1990}{keine Indirektion erlaubt}
+ {Fehler}
+ {in dieser Kombination ist keine indirekte
+ Adressierung erlaubt.}
+ {keines}
+\errentry{1995}{nicht im aktuellen Segment erlaubt}
+ {Fehler}
+ {(nicht mehr verwendet)}
+ {keines}
+\errentry{1996}{nicht im Maximum-Modus zul"assig}
+ {Fehler}
+ {Dieses Register ist nur im Minimum-Modus
+ definiert.}
+ {keines}
+\errentry{1997}{nicht im Minimum-Modus zul"assig}
+ {Fehler}
+ {Dieses Register ist nur im Maximum-Modus
+ definiert.}
+ {keines}
+\errentry{2000}{ung"ultige Pr"afix-Kombination}
+ {Fehler}
+ {Die angegebene Kombination von Pr"afixen
+ ist nicht zul"assig oder nicht im
+ Maschinenkode darstellbar.}
+ {keines}
+\errentry{2010}{Ung"ultige Escape-Sequenz}
+ {Fehler}
+ {Das mit einem Backslash eingeleitete
+ Sonderzeichen ist nicht definiert.}
+ {keines}
+\errentry{10001}{Fehler bein "Offnen der Datei}
+ {fatal}
+ {Beim Versuch, eine Datei zu "offnen, ist ein
+ Fehler aufgetreten.}
+ {Beschreibung des E/A-Fehlers}
+\errentry{10002}{Listingschreibfehler}
+ {fatal}
+ {Beim Schreiben des Assemblerlistings ist ein
+ Fehler aufgetreten.}
+ {Beschreibung des E/A-Fehlers}
+\errentry{10003}{Dateilesefehler}
+ {fatal}
+ {Beim Lesen aus einer Quelldatei ist ein
+ Fehler aufgetreten.}
+ {Beschreibung des E/A-Fehlers}
+\errentry{10004}{Dateischreibfehler}
+ {fatal}
+ {Beim Schreiben von Code- oder Share-Datei
+ ist ein Fehler aufgetreten.}
+ {Beschreibung des E/A-Fehlers}
+\errentry{10006}{Speicher"uberlauf}
+ {fatal}
+ {Der verf"ugbare Speicher reicht nicht mehr,
+ alle Datenstrukturen aufzunehmen. Weichen Sie auf die
+ DPMI- oder OS/2-Version von AS aus.}
+ {keines}
+\errentry{10007}{Stapel"uberlauf}
+ {fatal}
+ {Der Programmstapel ist wegen zu komplizierter
+ Formelausdr"ucke oder einer ung"unstigen Anlage der Symbol-
+ oder Makrotabelle "ubergelaufen. Versuchen Sie es noch
+ einmal mit der \tty{-A}-Option.}
+ {keines}
+\end{description}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{E/A-Fehlermeldungen}
+
+Die hier aufgelisteten Fehlermeldungen werden nicht nur von AS bei E/A-
+Fehlern ausgegeben, sondern auch von den Hilfsprogrammen PLIST, BIND,
+P2HEX und P2BIN. Es sind nur die Fehler n"aher erkl"art, die m.E. bei
+der Arbeit auftreten k"onnen. Sollte doch einmal ein nicht erl"auterter
+E/A-Fehler auftreten, so d"urfte der Grund in einem Programmfehler
+liegen. Melden Sie dies unbedingt!!
+
+\begin{description}
+\item[2]{Datei nicht gefunden\\
+ Die angegebene Datei existiert nicht oder liegt auf einem
+ anderen Laufwerk.}
+
+\item[3]{Pfad nicht gefunden\\
+ Der Pfad eines Dateinamens existiert nicht oder liegt auf
+ einem anderen Laufwerk.}
+
+\item[4]{zu viele offene Dateien\\
+ DOS sind die Dateihandles ausgegangen. Erh"ohen Sie die
+ \tty{FILES=}-Angabe in der CONFIG.SYS.}
+
+\item[5]{Dateizugriff verweigert\\
+ Entweder reichen die Netzwerkrechte f"ur einen Dateizugriff
+ nicht, oder es wur\-de ver\-sucht, ei\-ne schreib\-ge\-sch"utz\-te Da\-tei
+ zu "uber\-schrei\-ben oder zu ver\-"an\-dern. Bei Benutzung in
+ DOS- Fenstern von Multitasking- Systemen ist es "uberdies m"oglich,
+ da"s ein andere Proze"s die Datei in exklusivem Zugriff hat.}
+
+\item[6]{ung"ultiger Dateihandle}
+
+\item[12]{ung"ultiger Zugriffsmodus}
+
+\item[15]{ung"ultiger Laufwerksbuchstabe\\
+ Das angesprochene Laufwerk existiert nicht.}
+
+
+\item[16]{aktuelles Verzeichnis kann nicht gel"oscht werden}
+
+\item[17]{RENAME geht nicht "uber Laufwerke}
+
+\item[100]{vorzeitiges Dateiende\\
+ Eine Datei war zuende, obwohl sie es aufgrund ihrer Struktur
+ noch nicht sein d"urfte. Vermutlich ist sie besch"adigt.}
+
+\item[101]{Diskette/Platte voll\\
+ Das spricht wohl f"ur sich! Aufr"aumen!!}
+
+\item[102]{ASSIGN fehlt}
+
+\item[103]{Datei nicht offen}
+
+\item[104]{Datei nicht f"ur Einlesen offen}
+
+\item[105]{Datei nicht f"ur Ausgaben offen}
+
+\item[106]{Ung"ultiges numerisches Format}
+
+\item[150]{Diskette ist schreibgesch"utzt\\
+ Wenn Sie schon keine Festplatte als Arbeitsmedium verwenden,
+ so sollten Sie wenigstens den Schreibschutz entfernen!}
+
+\item[151]{Unbekanntes Ger"at\\
+ Sie haben versucht, ein Peripherieger"at anzusprechen, welches
+ DOS unbekannt ist. Dies sollte normalerweise nicht auftreten,
+ da der Name dann automatisch als Datei interpretiert wird.}
+
+\item[152]{Laufwerk nicht bereit\\
+ Schlie"sen Sie die Klappe des Diskettenlaufwerks.}
+
+\item[153]{unbekannte DOS-Funktion}
+
+\item[154]{Pr"ufsummenfehler auf Diskette/Platte\\
+ Ein harter Lesefehler auf der Diskette. Nochmal versuchen; wenn
+ immer noch vorhanden, Diskette neu formatieren bzw. ernste Sorgen
+ um Festplatte machen!}
+
+\item[155]{ung"ultiger DPB}
+
+\item[156]{Positionierfehler\\
+ Der Platten/Disketten-Controller hat eine bestimmte Spur nicht
+ gefunden. Siehe Nr. 154!}
+
+\item[157]{unbekanntes Sektorformat\\
+ DOS kann mit dem Format der Diskette nichts anfangen.}
+
+\item[158]{Sektor nicht gefunden\\
+ Analog zu Nr. 158, nur da"s hier der angeforderte Sektor auf
+ der Spur nicht gefunden werden konnte.}
+
+\item[159]{Papierende\\
+ Offensichtlich haben Sie die Ausgaben von AS direkt auf einen
+ Drucker umgeleitet. Assemblerlistings k"onnen seeehr lang
+ sein...}
+
+\item[160]{Ger"atelesefehler\\
+ Nicht n"aher vom Ger"atetreiber klassifizierter Lesefehler.}
+
+\item[161]{Ger"ateschreibfehler\\
+ Nicht n"aher vom Ger"atetreiber klassifizierter Schreibfehler.}
+
+\item[162]{allgemeiner Ger"atefehler\\
+ Hier ist der Ger"atetreiber v"ollig ratlos, was passiert
+ sein k"onnte.}
+\end{description}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{H"aufig gestellte Fragen}
+
+In diesem Kapitel habe ich versucht, einige besonders h"aufig gestellte
+Fragen mit den passenden Antworten zu sammeln. Die Antworten auf
+die hier auftauchenden Probleme finden sich zwar auch an anderer
+Stelle in der Anleitung, jedoch findet man sie vielleicht nicht auf
+den ersten Blick...
+
+\begin{description}
+\item[F:]{Ich bin DOS leid. F"ur welche Plattformen gibt es AS sonst ?}
+\item[A:]{Neben der Protected-Mode-Version, die AS unter DOS mehr Speicher
+ zur Verf"ugung stellt, existieren Portierungen f"ur OS/2 und
+ Unix-Systeme wie z.B. Linux (im Teststadium). An Versionen,
+ die Softwareherstellern in Redmond beim Geldscheffeln zuarbeiten
+ w"urden, ist momentan nicht gedacht. Sofern jemand anders in
+ dieser Hinsicht aktiv werden will, stelle ich ihm aber gerne
+ die AS-Quellen zur Verf"ugung, von denen sich die C-Variante
+ insbesondere eignen d"urfte. "Uber Fragen zu diesen Quellen
+ hinaus sollte er sich aber nicht viel von mir erwarten...}
+\vspace{0.3cm}
+\item[F:]{Ist eine Unterst"utzung des XYZ-Prozessors f"ur AS geplant?}
+\item[A:]{Es kommen immer neue Prozessoren heraus, und ich bem"uhe
+ mich, bei Erweiterung von AS Schritt zu halten. Der Stapel
+ mit der Aufschrift ,,Unerledigt'' auf meinem Schreibtisch
+ unterschreitet aber selten die 10cm-Grenze... Bei der Planung,
+ welche Kandidaten zuerst abgearbeitet werden, spielen W"unsche
+ von Anwendern nat"urlich eine gro"se Rolle. Das Internet und
+ die steigende Zahl elektronisch publizierter Dokumentation
+ erleichtern die Beschaffung von Unterlagen, speziell bei
+ ausgefallenen oder "alteren Architekturen wird es aber immer
+ wieder schwierig. Wenn sich die fragliche Prozessorfamilie
+ nicht in der Liste in Planung befindlicher Prozessoren
+ befindet (siehe Kapitel 1), macht es sich sehr gut, der
+ Anfrage auch gleich ein passendes Datenbuch hinzuzupacken
+ (zur Not auch leihweise!).}
+\vspace{0.3cm}
+\item[F:]{Ein freier Assembler ist ja eine feine Sache, aber eigentlich
+ br"auchte ich jetzt auch noch einen Disassembler...und einen
+ Debugger...ein Simulator w"are auch ganz nett..}
+\item[A:]{AS ist ein Freizeitprojekt von mir, d.h. etwas, was ich in der
+ Zeit tue, wenn ich mich nicht gerade um den Broterwerb k"ummere.
+ Von dieser Zeit nimmt AS schon einen ganz erheblichen Teil ein,
+ und ab und zu genehmige ich mir auch mal eine Auszeit, um den
+ L"otkolben zu schwingen, mal wieder eine Tangerine Dream-Platte
+ bewu"st zu h"oren, mich vor den Fernseher zu hocken oder einfach
+ nur dringenden menschlichen Bed"urfnissen nachzugehen. Ich habe
+ einmal angefangen, einen Disassembler zu konzipieren, der wieder
+ voll reassemblierbaren Code erzeugt und automatisch Daten- und
+ Code-Bereiche trennt, habe das Projekt aber relativ schnell wieder
+ eingestellt, weil die restliche Zeit f"ur so etwas einfach nicht
+ mehr reicht. Ich mache lieber eine Sache gut als ein halbes
+ Dutzend m"a"sig. Von daher mu"s die Antwort also wohl ,,nein''
+ hei"sen...}
+\vspace{0.3cm}
+\item[F:]{In den Bildschirmausgaben von AS tauchen seltsame Zeichen auf,
+ z.B. Pfeile und eckige Klammern. Warum?}
+\item[A:]{AS verwendet zur Bildschirmsteuerung defaultm"a"sig einige
+ ANSI-Terminal-Steuersequenzen. Haben Sie keinen ANSI-Treiber
+ installiert, so kommen diese Steuerzeichen ungefiltert auf
+ Ihrem Bildschirm heraus. Installieren Sie entweder einen
+ ANSI-Treiber oder schalten Sie die Steuersequenzen mit dem
+ DOS-Befehl \tty{SET USEANSI=N} ab.}
+\vspace{0.3cm}
+\item[F:]{W"ahrend der Assemblierung bricht AS pl"otzlich mit der
+ Meldung eines Stapel"uberlaufes ab. Ist mein Programm zu
+ kompliziert?}
+\item[A:]{Ja und Nein. Die Symboltabelle f"ur Ihr Programm ist nur
+ etwas unregelm"a"sig gewachsen, was zu zu hohen Rekursionstiefen
+ im Zugriff auf die Tabelle gef"uhrt hat. Diese Fehler treten
+ insbesondere bei der 16-Bit-OS/2-Version von AS auf, die nur
+ "uber einen relativ kleinen Stack verf"ugt. Starten Sie AS noch
+ einmal mit dem \tty{-A}-Kommandozeilenschalter. Hilft dies auch
+ nicht, so kommen als m"ogliche Problemstellen noch zu komplizierte
+ Formelausdr"ucke in Frage. Versuchen Sie in einem solchen Fall,
+ die Formel in Zwischenschritte aufzuspalten.}
+\vspace{0.3cm}
+\item[F:]{AS scheint mein Programm nicht bis zum Ende zu assemblieren.
+ Mit einer "alteren Version von AS (1.39) hat es dagegen
+ funktioniert.}
+\item[A:]{Neuere Versionen von AS ignorieren das \tty{END}-Statement nicht
+ mehr, sondern beenden danach wirklich die Assemblierung.
+ Insbesondere bei Include-Dateien ist es fr"uher vorgekommen, da"s
+ Anwender jede Datei mit einem \tty{END}-Statement beendet haben.
+ Entfernen Sie die "uberfl"ussigen \tty{END}s.}
+\vspace{0.3cm}
+\item[F:]{Weil ich noch ein paar kompliziertere Assemblierfehler im Programm
+ hatte, habe ich mir ein Listing gemacht und es einmal genauer
+ angeschaut. Dabei ist mir aufgefallen, da"s einige Spr"unge nicht
+ auf das gew"unschte Ziel, sondern auf sich selbst zeigen!}
+\item[A:]{Dieser Effekt tritt bei Vorw"artsspr"ungen auf, bei denen der
+ Formelparser von AS im ersten Pass die Zieladresse noch nicht kennen
+ kann. Da der Formelparser ein unabh"angiges Modul ist, mu"s er sich
+ in einem solchen Fall einen Wert ausdenken, der auch relativen
+ Spr"ungen mit kurzer Reichweite nicht wehtut, und dies ist nun
+ einmal die aktuelle Programmz"ahleradresse selber...im zweiten Pass
+ w"aren die korrekten Werte erschienen, aber zu diesem ist es nicht
+ gekommen, da schon im ersten Pass Fehler auftraten. Korrigieren
+ Sie die anderen Fehler zuerst, so da"s AS zum zweiten Pass kommt,
+ und das Listing sollte wieder vern"unftiger aussehen.}
+\vspace{0.3cm}
+\item[F:]{Mein Programm wird zwar korrekt assembliert, bei der Umwandlung
+ mit P2BIN oder P2HEX erhalte ich aber nur eine leere Datei.}
+\item[A:]{Dann haben Sie wahrscheinlich das Adre"s\-fil\-ter nicht korrekt
+ eingestellt. De\-faul\-tm"a"sig reicht der Filter von 0 bis 32
+ Kbyte, falls Ihr Programm Teile au"serhalb dieses Bereiches
+ besitzen sollte, werden diese nicht "ubernommen. Sollte Ihr
+ Code komplett jenseits 32 Kbyte liegen (wie es bei 65er und
+ 68er-Prozessoren "ublich ist), dann erhalten Sie das von Ihnen
+ geschilderte Ergebnis. Setzen Sie das Adre"sfilter einfach auf
+ einen passenden Bereich (s. das Kapitel zu P2BIN/P2HEX).}
+\vspace{0.3cm}
+\item[F:]{Ich bekomme unter Unix bei der Benutzung von P2BIN oder P2HEX
+ das Dollarzeichen nicht eingegeben. Die automatische
+ Bereichsfestlegung funktioniert nicht, stattdessen gibt es
+ eigenartige Fehlermeldungen.}
+\item[A:]{Unix-Shells benutzen das Dollarzeichen zur Expansion von
+ Shell-Variablen. Wollen Sie ein Dollarzeichen an eine Anwendung
+ durchreichen, stellen Sie einen Backslash (\verb!\!) voran.
+ Im Falle der Adre"sangabe bei P2BIN und P2HEX darf aber auch
+ \tty{0x} anstelle des Dollarzeichens benutzt werden, was dieses
+ Problem von vornherein vermeidet.}
+\end{description}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Pseudobefehle gesammelt}
+
+In diesem Anhang finden sich noch einmal als schnelle Referenz alle
+von AS zur Verf"ugung gestellten Pseudobefehle. Die Liste ist in zwei
+Teile gegliedert: Im ersten Teil finden sich Befehle, die unabh"angig
+vom eingestellten Zielprozessor vorhanden sind, danach folgen f"ur
+jede Prozessorfamilie die zus"atzlich vorhandenen Befehle:
+
+\subsubsection{Immer vorhandene Befehle}
+\input{pscomm.tex}
+Zus"atzlich existiert \tty{SET} bzw. \tty{EVAL}, falls \tty{SET} bereits
+ein Prozessorbefehl ist.
+
+\input{pscpu.tex}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Vordefinierte Symbole}\label{AppInternSyms}
+
+\begin{table*}[ht]
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+Name & Datentyp & Definition & Bedeutung \\
+\hline\hline
+\tty{ARCHITECTURE} & String & vordef. & Zielplattform, f"ur die AS \\
+ & & & "ubersetzt wurde, in der Form \\
+ & & & Prozesor-Hersteller-Betriebs- \\
+ & & & system \\
+\hline
+\tty{BIGENDIAN} & Boolean & normal & Konstantenablage mit MSB \\
+ & & & first ? \\
+\hline
+\tty{CASESENSITIVE} & Boolean & normal & Unterscheidung von Gro"s- \\
+ & & & und Kleinbuchstaben in \\
+ & & & Symbolnamen ? \\
+\hline
+\tty{CONSTPI} & Gleitkomma & normal & Kreiszahl Pi (3.1415.....) \\
+\hline
+\tty{DATE} & String & vordef. & Datum des Beginns der \\
+ & & & Assemblierung (1.Pass) \\
+\hline
+\tty{FALSE} & Boolean & vordef. & 0 = logisch ,,falsch'' \\
+\hline
+\tty{HASFPU} & Boolean & dynam.(0) & Koprozessor-Befehle \\
+ & & & freigeschaltet ? \\
+\hline
+\tty{HASPMMU} & Boolean & dynam.(0) & MMU-Befehle frei- \\
+ & & & geschaltet ? \\
+\hline
+\tty{INEXTMODE} & Boolean & dynam.(0) & XM-Flag f"ur 4 Gbyte \\
+ & & & Adre"sraum gesetzt ? \\
+\hline
+\tty{INLWORDMODE} & Boolean & dynam.(0) & LW-Flag f"ur 32-Bit-Befehle \\
+ & & & gesetzt ? \\
+\hline
+\tty{INMAXMODE} & Boolean & dynam.(0) & Prozessor im Maximum- \\
+ & & & Modus ? \\
+\hline
+\tty{INSUPMODE} & Boolean & dynam.(0) & Prozessor im Supervisor- \\
+ & & & Modus ? \\
+\hline
+\tty{INSRCMODE} & Boolean & dynam.(0) & Prozessor im Quellmodus ? \\
+\hline
+\tty{FULLPMMU} & Boolean & dynam.(0/1) & voller PMMU-Befehlssatz ? \\
+\hline
+\tty{LISTON} & Boolean & dynam.(1) & Listing freigeschaltet ? \\
+\hline
+\end{tabular}\end{center}
+\caption{Vordefinierte Symbole - Teil 1\label{TabInternSyms1}}
+\end{table*}
+
+\begin{table*}
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+Name & Datentyp & Definition & Bedeutung \\
+\hline\hline
+\tty{MACEXP} & Boolean & dynam.(1) & Expansion von Makrokon- \\
+ & & & strukten im Listing \\
+ & & & freigeschaltet ? \\
+\hline
+\tty{MOMCPU} & Integer & dynam. & Nummer der momentan \\
+ & & (68008) & gesetzten Ziel-CPU \\
+\hline
+\tty{MOMCPUNAME} & String & dynam. & Name der momentan \\
+ & & (68008) & gesetzten Ziel-CPU \\
+\hline
+\tty{MOMFILE} & String & Spezial & augenblickliche Quelldatei \\
+ & & & (schlie"st Includes ein) \\
+\hline
+\tty{MOMLINE} & Integer & Spezial & aktuelle Zeilennummer in \\
+ & & & der Quelldatei \\
+\hline
+\tty{MOMPASS} & Integer & Spezial & Nummer des laufenden \\
+ & & & Durchgangs \\
+\hline
+\tty{MOMSECTION} & String & Spezial & Name der aktuellen Sektion \\
+ & & & oder Leerstring, fall au"ser- \\
+ & & & halb aller Sektionen \\
+\hline
+\tty{MOMSEGMENT} & String & Spezial & Name des mit \tty{SEGMENT} ein- \\
+ & & & gestellten Adre"sraumes \\
+\hline
+\tty{PADDING} & Boolean & dynam.(1) & Auff"ullen von Bytefeldern \\
+ & & & auf ganze Anzahl ? \\
+\hline
+\tty{RELAXED} & Boolean & dynam.(0) & Schreibweise von Integer-Kon- \\
+ & & & stanten in beliebiger Syntax \\
+ & & & erlaubt ? \\
+\hline
+\tty{PC} & Integer & Spezial & mom. Programmz"ahler \\
+ & & & (Thomson) \\
+\hline
+\tty{TIME} & String & vordef. & Zeit des Beginns der Assem- \\
+ & & & blierung (1. Pass) \\
+\hline
+\tty{TRUE} & Integer & vordef. & 1 = logisch ,,wahr'' \\
+\hline
+\tty{VERSION} & Integer & vordef. & Version von AS in BCD-Kodie- \\
+ & & & rung, z.B. 1331 hex f"ur \\
+ & & & Version 1.33p1 \\
+\hline
+\tty{WRAPMODE} & Integer & vordef. & verk"urzter Programmz"ahler \\
+ & & & angenommen? \\
+\hline
+\verb!*! & Integer & Spezial & mom. Programmz"ahler (Motorola, \\
+ & & & Rockwell, Microchip, Hitachi) \\
+\hline
+\tty{\$} & Integer & Spezial & mom. Programmz"ahler (Intel, \\
+ & & & Zilog, Texas, Toshiba, NEC, \\
+ & & & Siemens, AMD) \\
+\hline
+\end{tabular}\end{center}
+\caption{Vordefinierte Symbole - Teil 2\label{TabInternSyms2}}
+\end{table*}
+\par
+Boolean-Symbole sind eigentlich normale normale Integer-Symbole, mit
+dem Unterschied, da"s ihnen von AS nur zwei verschiedene Werte (0 oder
+1, entsprechend FALSE oder TRUE) zugewiesen werden. Spezialsymbole
+werden von AS nicht in der Symboltabelle abgelegt, sondern aus
+Geschwindigkeitsgr"unden direkt im Parser abgefragt. Sie tauchen daher
+auch nicht in der Symboltabelle des Listings auf. W"ahrend vordefinierte
+Symbole nur einmal am Anfang eines Passes besetzt werden, k"onnen sich
+die Werte dynamischer Symbole w"ahrend der Assemblierung mehrfach "andern,
+da sie mit anderen Befehlen vorgenommene Einstellungen widerspiegeln.
+\par
+Die hier aufgelistete Schreibweise ist diejenige, mit der man die
+Symbole auch im case-sensitiven Modus erreicht.
+\par
+Die hier aufgef"uhrten Namen sollte man f"ur eigene Symbole meiden;
+entweder kann man sie zwar definieren, aber nicht darauf zugreifen
+(bei Spezialsymbolen), oder man erh"alt eine Fehlermeldung wegen eines
+doppelt definierten Symboles. Im gemeinsten Fall f"uhrt die Neubelegung
+durch AS zu Beginn eines Passes zu einem Phasenfehler und einer
+Endlosschleife...
+
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Mitgelieferte Includes}
+
+Der Distribution von AS liegen eine Reihe von Include-Dateien bei. Neben
+Includes, die sich nur auf eine Prozessorfamilie beziehen (und deren
+Funktion sich demjenigen unmittelbar erschlie"st, der mit dieser Familie
+arbeitet), existieren aber auch ein paar Dateien, die prozessorunabh"angig
+sind und die eine Reihe n"utzlicher Funktionen implementieren. Die
+definierten Funktionen sollen hier kurz beschrieben werden:
+
+\section{BITFUNCS.INC}
+
+Diese Datei definiert eine Reihe bitorientierter Operationen, wie man sie
+bei anderen Assemblern vielleicht fest eingebaut sind. Bei AS werden sie
+jedoch mit Hilfe benutzerdefinierter Funktionen implementiert:
+
+\begin{itemize}
+\item{{\em mask(start,bits)} liefert einen Integer, in dem ab Stelle {\em
+ start} {\em bits} Bits gesetzt sind;}
+\item{{\em invmask(start,bits)} liefert das Einerkomplement zu {\em mask()};}
+\item{{\em cutout(x,start,bits)} liefert ausmaskierte {\em bits} Bits ab
+ Stelle {\em start} aus {\em x}, ohne sie auf Stelle 0 zu
+ verschieben;}
+\item{{\em hi(x)} liefert das zweitniedrigste Byte (Bit 8..15) aus {\em
+ x};}
+\item{{\em lo(x)} liefert das niederwertigste Byte (Bit 0..7) aus {\em
+ x};}
+\item{{\em hiword(x)} liefert das zweitniedrigste Wort (Bit 16..31) aus
+ {\em x};}
+\item{{\em loword(x)} liefert das niederwertigste Wort (Bit 0..15) aus
+ {\em x};}
+\item{{\em odd(x)} liefert TRUE, falls {\em x} ungerade ist;}
+\item{{\em even(x)} liefert TRUE, falls {\em x} gerade ist;}
+\item{{\em getbit(x,n)} extrahiert das Bit {\em n} aus {\em x} und liefert
+ es als 0 oder 1;}
+\item{{\em shln(x,size,n)} schiebt ein Wort {\em x} der L"ange {\em size}
+ Bits um {\em n} Stellen nach links;}
+\item{{\em shrn(x,size,n)} schiebt ein Wort {\em x} der L"ange {\em size}
+ Bits um {\em n} Stellen nach rechts;}
+\item{{\em rotln(x,size,n)} rotiert die untersten {\em size} Bits eines
+ Integers {\em x} um {\em n} Stellen nach links;}
+\item{{\em rotrn(x,size,n)} rotiert die untersten {\em size} Bits eines
+ Integers {\em x} um {\em n} Stellen nach rechts;}
+\end{itemize}
+
+\section{CTYPE.INC}
+
+Dieser Include ist das Pendant zu dem bei C vorhandenen Header {\tt
+ctype.h}, der Makros zur Klassifizierung von Zeichen anbietet. Alle
+Funktionen liefern entweder TRUE oder FALSE:
+
+\begin{itemize}
+\item{{\em isdigit(ch)} ist TRUE, falls {\em ch} eine Ziffer (0..9)
+ ist;}
+\item{{\em isxdigit(ch)} ist TRUE, falls {\em ch} eine g"ultige
+ Hexadezimal-Ziffer (0..9, A..F, a..f) ist;}
+\item{{\em isascii(ch)} ist TRUE, falls {\em ch} sich im Bereich
+ normaler ASCII-Zeichen ohne gesetztes Bit 7 bewegt;}
+\item{{\em isupper(ch)} ist TRUE, falls {\em ch} ein Gro"sbuchstabe
+ ist (Sonderzeichen ausgenommen);}
+\item{{\em islower(ch)} ist TRUE, falls {\em ch} ein Kleinbuchstabe
+ ist (Sonderzeichen ausgenommen);}
+\item{{\em isalpha(ch)} ist TRUE, falls {\em ch} ein Buchstabe ist
+ (Sonderzeichen ausgenommen);}
+\item{{\em isalnum(ch)} ist TRUE, falls {\em ch} ein Buchstabe oder
+ eine Ziffer ist);}
+\item{{\em isspace(ch)} ist TRUE, falls {\em ch} ein 'Leerzeichen'
+ (Space, Formfeed, Zeilenvorschub, Wagenr"ucklauf, Tabulator)
+ ist);}
+\item{{\em isprint(ch)} ist TRUE, falls {\em ch} ein druckbares
+ Zeichen ist (also kein Steuerzeichen bis Code 31);}
+\item{{\em iscntrl(ch)} ist das Gegenteil zu {\em isprint()};}
+\item{{\em isgraph(ch)} ist TRUE, falls {\em ch} ein druckbares
+ und {\it sichtbares} Zeichen ist;}
+\item{{\em ispunct(ch)} ist TRUE, falls {\em ch} ein druckbares
+ Sonderzeichen ist (d.h. weder Space, Buchstabe noch Ziffer);}
+\end{itemize}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Danksagungen}
+
+\begin{quote}{\it
+''If I have seen farther than other men, \\
+it is because I stood on the shoulders of giants.'' \\
+\hspace{2cm} --Sir Isaac Newton}
+\end{quote}
+\begin{quote}{\it
+''If I haven't seen farther than other men, \\
+it is because I stood in the footsteps of giants.'' \\
+\hspace{2cm} --unknown}
+\end{quote}
+\par
+Wenn man sich entschlie"st, ein solches Kapitel neu zu schreiben,
+nachdem es eigentlich schon zwei Jahre veraltet ist, l"auft man
+automatisch Gefahr, da"s dabei der eine oder andere gute Geist, der
+etwas zum bisherigen Gelingen dieses Projektes beigetragen hat,
+vergessen wird. Der
+allererste Dank geb"uhrt daher allen Personen, die ich in der
+folgenden Aufz"ahlung unfreiwillig unterschlagen habe!
+\par
+AS als Universalassembler, wie er jetzt besteht, ist auf Anregung von
+Bernhard (C.) Zschocke entstanden, der einen ,,studentenfreundlichen'',
+d.h. kostenlosen 8051-Assembler f"ur sein Mikroprozessorpraktikum
+brauchte und mich dazu bewegt hat, einen bereits bestehenden
+68000-Assembler zu erweitern. Von dortan nahm die Sache ihren Lauf...
+Das Mikroprozessorpraktikum an der RWTH Aachen hat auch immer die
+eifrigsten Nutzer der neuesten AS-Features (und damit Bug-Sucher)
+gestellt und damit einiges zur jetzigen Qualit"at von AS beigetragen.
+\par
+Das Internet und FTP haben sich als gro"se Hilfe bei der Meldung von
+Bugs und der Verbreitung von AS erwiesen. Ein Dank geht daher an
+die FTP-Administratoren (Bernd Casimir in Stuttgart, Norbert Breidohr
+in Aachen und J"urgen Mei"sburger in J"ulich). Insbesondere letzterer
+hat sich sehr engagiert, um eine praxisnahe L"osung im ZAM zu
+finden.
+\par
+Ach ja, wo wir schon im ZAM sind: Wolfgang E. Nagel hat zwar nichts
+direkt mit AS zu tun, immerhin ist er aber mein Chef und wirft
+st"andig vier Augen auf das, was ich tue. Bei AS scheint zumindest
+ein lachendes dabei zu sein...
+\par
+Ohne Datenb"ucher und Unterlagen zu Prozessoren ist ein Programm wie
+AS nicht zu machen. Ich habe von einer enormen Anzahl von Leuten
+Informationen bekommen, die von einem kleinen Tip bis zu ganzen
+Datenb"uchern reichen. Hier eine Aufz"ahlung (wie oben gesagt, ohne
+Garantie auf Vollst"andigkeit!):
+\par
+Ernst Ahlers, Charles Altmann, Rolf Buchholz, Bernd Casimir,
+Gunther Ewald, Stephan Hruschka, Peter Kliegelh"ofer, Ulf Meinke,
+Matthias Paul, Norbert Rosch, Steffen Schmid, Leonhard Schneider,
+Ernst Schwab, Michael Schwingen, Oliver Sellke, Christian Stelter,
+Oliver Thamm, Thorsten Thiele.
+\par
+...und ein geh"assiger Dank an Rolf-Dieter-Klein und Tobias Thiel, die
+mit ihren ASM68K demonstrierten, wie man es \bb{nicht} machen sollte und
+mich damit indirekt dazu angeregt haben, etwas besseres zu schreiben!
+\par
+So ganz allein habe ich AS nicht verzapft. AS enth"alt die
+OverXMS-Routinen von Wilbert van Leijen, um die Overlay-Module ins
+Extended Memory verlagern zu k"onnen. Eine wirklich feine Sache,
+einfach und problemlos anzuwenden!
+\par
+Die TMS320C2x/5x-Codegeneratoren sowie die Datei \tty{STDDEF2x.INC}
+stammen von Thomas Sailer, ETH Z"urich. Erstaunlich, an einem Wochenende
+hat er es geschafft, durch meinen Code durchzusteigen und den neuen
+Generator zu implementieren. Entweder waren das reichliche Nachtschichten
+oder ich werde langsam alt...
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{"Anderungen seit Version 1.3}
+
+\begin{itemize}
+\item{Version 1.31:
+ \begin{itemize}
+ \item{zus"atzlicher MCS-51-Prozessortyp 80515. Die Nummer wird
+ wiederum nur vom Assembler verwaltet. Die Datei STDDEF51.INC
+ wurde um die dazugeh"origen SFRs erweitert. \bb{ACHTUNG!}
+ Einige 80515-SFRs haben sich adre"sm"a"sig verschoben!}
+ \item{zus"atzlich Prozessor Z80 unterst"utzt;}
+ \item{schnellerer 680x0-Codegenerator.}
+ \end{itemize}}
+\item{Version 1.32:
+ \begin{itemize}
+ \item{Schreibweise von Zeropageadressen f"ur 65xx nicht mehr als
+ Adr.z, sondern wie beim 68xx als $<$Adr;}
+ \item{unterst"utzt die Prozessoren 6800, 6805, 6301 und 6811;}
+ \item{der 8051-Teil versteht jetzt auch \tty{DJNZ}, \tty{PUSH} und
+ \tty{POP} (sorry);}
+ \item{im Listing werden neben den Symbolen jetzt auch die definierten
+ Makros aufgelistet;}
+ \item{Befehle \tty{IFDEF}/\tty{IFNDEF} f"ur bedingte Assemblierung,
+ mit denen sich die Existenz eines Symboles abfragen l"a"st;}
+ \item{Befehle \tty{PHASE}/\tty{DEPHASE} zur Unterst"utzung von Code, der zur
+ Laufzeit auf eine andere Adresse verschoben werden soll;}
+ \item{Befehle \tty{WARNING}/\tty{ERROR}/\tty{FATAL}, um anwenderspezifische
+ Fehlermeldungen ausgeben zu k"onnen;}
+ \item{Die Datei STDDEF51.INC enth"alt zus"atzlich das Makro \tty{USING}
+ zur einfacheren Handhabung der Registerb"anke der MCS-51er;}
+ \item{Kommandozeilenoption \tty{u}, um Segmentbelegung anzuzeigen.}
+ \end{itemize}}
+\item{Version 1.33:
+ \begin{itemize}
+ \item{unterst"utzt den 6809;}
+ \item{zus"atzlich Stringvariablen;}
+ \item{Die Befehle \tty{TITLE}, \tty{PRTINIT}, \tty{PRTEXIT},
+ \tty{ERROR}, \tty{WARNING} und \tty{FATAL} erwarten jetzt
+ einen Stringausdruck als Parameter, Konstanten
+ m"ussen demzufolge nicht mehr in Hochkommas, sondern in
+ G"ansef"u"schen eingeschlossen werden. Analoges gilt f"ur \tty{DB},
+ \tty{DC.B} und \tty{BYT};}
+ \item{Befehl \tty{ALIGN} zur Ausrichtung des Programmz"ahlers bei Intel-
+ Prozessoren;}
+ \item{Befehl \tty{LISTING}, um die Erzeugung eines Listings ein- und
+ ausschalten zu k"onnen;}
+ \item{Befehl \tty{CHARSET} zur Definition eigener Zeichens"atze.}
+ \end{itemize}}
+\item{Version 1.34:
+ \begin{itemize}
+ \item{Wenn im ersten Pass Fehler auftreten, wird gar kein zweiter
+ Pass mehr durchgef"uhrt;}
+ \item{neues vordefiniertes Symbol \tty{VERSION}, welches die Version von
+ AS enth"alt;}
+ \item{Befehl \tty{MESSAGE}, um Durchsagen und Meldungen programmgesteuert
+ zu erzeugen;}
+ \item{Formelparser "uber Stringkonstanten zug"anglich;}
+ \item{Bei Fehler in Makroexpansionen wird zus"atzlich die laufende
+ Zeile im Makro angezeigt;}
+ \item{Funktion \tty{UPSTRING}, um einen String in Gro"sbuchstaben zu
+ wandeln.}
+ \end{itemize}}
+\item{Version 1.35:
+ \begin{itemize}
+ \item{Funktion \tty{TOUPPER}, um ein einzelnes Zeichen in Gro"sbuchstaben
+ zu wandeln;}
+ \item{Befehl \tty{FUNCTION}, um eigene Funktionen definieren zu k"onnen;}
+ \item{Kommandozeilenoption \tty{D}, um Symbole von au"sen definieren zu
+ k"onnen;}
+ \item{Fragt die Environment-Variable \tty{ASCMD} f"ur h"aufig gebrauchte
+ Optionen ab;}
+ \item{bei gesetzter \tty{u}-Option wird das Programm zus"atzlich auf doppelt
+ belegte Speicherbereiche abgepr"uft;}
+ \item{Kommandozeilenoption \tty{C}, um eine Querverweisliste zu erzeugen.}
+ \end{itemize}}
+\item{Version 1.36:
+ \begin{itemize}
+ \item{unterst"utzt zus"atzlich die Familien PIC 16C5x und
+ PIC17C4x;}
+ \item{im Listing wird zus"atzlich die Verschachtelungsebene bei
+ Include-Dateien angezeigt;}
+ \item{in der Querverweisliste wird zus"atzlich die Stelle angezeigt,
+ an der ein Symbol definiert wurde;}
+ \item{Kommandozeilenoption \tty{A}, um eine kompaktere Ablage der
+ Symboltabelle zu erzwingen.}
+ \end{itemize}}
+\item{Version 1.37:
+ \begin{itemize}
+ \item{unterst"utzt zus"atzlich die Prozessoren 8086, 80186, V30,
+ V35, 8087 und Z180;}
+ \item{Befehle \tty{SAVE} und \tty{RESTORE} zur besseren Umschaltung
+ von Flags;}
+ \item{Operatoren zur logischen Verschiebung und Bitspiegelung;}
+ \item{Kommandozeilenoptionen k"onnen mit einem Pluszeichen negiert
+ werden;}
+ \item{Filter \tty{AS2MSG} zur bequemen Arbeit mit AS unter Turbo-Pascal 7.0;}
+ \item{\tty{ELSEIF} darf ein Argument zur Bildung von
+ \tty{IF-THEN-ELSE}-Leitern haben;}
+ \item{Zur bequemeren bedingten Assemblierung zus"atzlich ein
+ \tty{CASE}-Konstrukt;}
+ \item{Selbstdefinierte Funktionen d"urfen mehr als ein Argument haben;}
+ \item{P2HEX kann nun auch Hexfiles f"ur 65er-Prozessoren erzeugen;}
+ \item{BIND, P2HEX und P2BIN haben jetzt die gleichen
+ Variationsm"oglichkeiten in der Kommandozeile wie AS;}
+ \item{Schalter \tty{i} bei P2HEX, um 3 Varianten f"ur den Ende-Record
+ einzustellen;}
+ \item{Neue Funktionen \tty{ABS} und \tty{SGN};}
+ \item{Neue Pseudovariablen \tty{MOMFILE} und \tty{MOMLINE};}
+ \item{Ausgabem"oglichkeit erweiterter Fehlermeldungen;}
+ \item{Befehle \tty{IFUSED} und \tty{IFNUSED}, um abzufragen, ob ein
+ Symbol bisher benutzt wurde;}
+ \item{Die Environment-Variablen \tty{ASCMD}, \tty{BINDCMD} usw. k"onnen auch
+ einen Dateinamen enthalten, in dem f"ur die Optionen mehr
+ Platz ist;}
+ \item{P2HEX erzeugt nun die von Microchip vorgegebenen Hex-Formate
+ (p4);}
+ \item{mit der Seitenl"angenangabe 0 k"onnen automatische
+ Seitenvorsch"ube im Listing vollst"andig unterdr"uckt werden
+ (p4);}
+ \item{neue Kommandozeilenoption \tty{P}, um die Ausgabe des Makroprozessors
+ in eine Datei zu schreiben (p4);}
+ \item{in der Kommandozeile definierte Symbole d"urfen nun auch mit
+ einem frei w"ahlbaren Wert belegt werden (p5).}
+ \end{itemize}}
+\item{Version 1.38:
+ \begin{itemize}
+ \item{Umstellung auf Mehrpass-Betrieb. Damit kann AS auch bei
+ Vorw"artsreferenzen immer den optimalen Code erzeugen;}
+ \item{Der 8051-Teil kennt nun auch die Befehle \tty{JMP} und \tty{CALL};}
+ \item{unterst"utzt zus"atzlich die Toshiba TLCS-900-Reihe (p1);}
+ \item{Befehl \tty{ASSUME}, um dem Assembler die Belegung der
+ Segmentregister des 8086 mitzuteilen (p2);}
+ \item{unterst"utzt zus"atzlich die ST6-Reihe von SGS-Thomson (p2);}
+ \item{..sowie die 3201x-Signalprozessoren von Texas Instruments (p2);}
+ \item{Option \tty{F} bei P2HEX, um die automatische Formatwahl "ubersteuern
+ zu k"onnen (p2);}
+ \item{P2BIN kann nun auch durch Angabe von Dollarzeichen Anfang und
+ Ende des Adre"sfensters selbstst"andig festlegen (p2);}
+ \item{Der 8048-Codegenerator kennt nun auch die 8041/42-
+ Befehlserweiterungen(p2);}
+ \item{unterst"utzt zus"atzlich die Zilog Z8-Mikrokontroller(p3).}
+ \end{itemize}}
+\item{Version 1.39:
+ \begin{itemize}
+ \item{Definitionsm"oglichkeit von Sektionen und lokalen Labels;}
+ \item{Kommandozeilenschalter \tty{h}, um Hexadezimalzahlenausgabe mit
+ Kleinbuchstaben zu erzwingen;}
+ \item{Variable \tty{MOMPASS}, um die Nummer des augenblicklichen Durchganges
+ abfragen zu k"onnen;}
+ \item{Kommandozeilenschalter \tty{t}, um einzelne Teile des Assemblerlistings
+ ausblenden zu k"onnen;}
+ \item{kennt zus"atzlich die L-Variante der TLCS-900-Reihe von Toshiba
+ und die MELPS-7700-Reihe von Mitsubishi (p1);}
+ \item{P2HEX akzeptiert nun auch Dollarzeichen f"ur Start-und Endadresse
+ (p2);}
+ \item{unterst"utzt zus"atzlich die TLCS90-Familie von Toshiba (p2);}
+ \item{P2HEX kann Daten zus"atzlich im Tektronix- und 16-Bit
+ Intel-Hex-Format ausgeben (p2);}
+ \item{bei Adre"s"uberschreitungen gibt P2HEX Warnungen aus (p2);}
+ \item{Include-Datei STDDEF96.INC mit Adre"sdefinitionen f"ur die
+ TLCS-900-Reihe (p3);}
+ \item{Befehl \tty{READ}, um Werte w"ahrend der Assemblierung interaktiv
+ einlesen zu k"onnen (p3);}
+ \item{Fehlermeldungen werden nicht mehr einfach auf die
+ Standardausgabe, sondern auf den von DOS daf"ur vorgesehenen
+ Kanal (STDERR) geschrieben (p3);}
+ \item{Der beim 6811-Teil fehlende \tty{STOP}-Befehl ist nun da (scusi,p3);}
+ \item{unterst"utzt zus"atzlich die $\mu$PD78(C)1x-Familie von NEC (p3);}
+ \item{unterst"utzt zus"atzlich den PIC16C84 von Microchip (p3);}
+ \item{Kommandozeilenschalter \tty{E}, um die Fehlermeldungen in eine Datei
+ umleiten zu k"onnen (p3);}
+ \item{Die Unklarheiten im 78(C)1x-Teil sind beseitigt (p4);}
+ \item{neben dem MELPS-7700 ist nun auch das ,,Vorbild'' 65816
+ vorhanden (p4);}
+ \item{Die ST6-Pseudoanweisung \tty{ROMWIN} wurde entfernt und
+ mit in den \tty{ASSUME}-Befehl eingegliedert (p4);}
+ \item{unterst"utzt zus"atzlich den 6804 von SGS-Thomson (p4);}
+ \item{durch die \tty{NOEXPORT}-Option in der Makrodefinition
+ kann nun f"ur jedes Makro einzeln festgelegt werden, ob es
+ in der MAC-Datei erscheinen soll oder nicht (p4);}
+ \item{Die Bedeutung von \tty{MACEXP} f"ur Expansionen von Makros hat
+ sich wegen der zus"atzlichen \tty{NOEXPAND}-Option in der
+ Makrodefinition leicht ge"andert (p4);}
+ \item{Durch die \tty{GLOBAL}-Option in der Makrodefinition k"onnen nun
+ zus"atzlich Makros definiert werden, die durch ihren
+ Sektionsnamen eindeutig gekennzeichnet sind (p4).}
+ \end{itemize}}
+\item{Version 1.40:
+ \begin{itemize}
+ \item{unterst"utzt zus"atzlich den DSP56000 von Motorola;}
+ \item{P2BIN kann nun auch das untere bzw. obere Wort aus
+ 32-Bit-W"ortern abtrennen;}
+ \item{unterst"utzt zus"atzlich die TLCS-870- und TLCS-47-Familie
+ von Toshiba(p1);}
+ \item{mit einem vorangestelltem ! kann man durch Makros
+ ,,verdeckte'' Maschinenbefehle wieder erreichen(p1);}
+ \item{mit der \tty{GLOBAL}-Anweisung lassen sich Symbolnamen
+ nun auch qualifiziert exportieren(p1);}
+ \item{mit der \tty{r}-Option kann man sich nun eine Liste der
+ Stellen erzeugen lassen, die zus"atzliche Durchl"aufe
+ erzwangen(p1);}
+ \item{bei der \tty{E}-Option kann nun die Dateiangabe weggelassen werden,
+ so da"s ein passender Default gew"ahlt wird(p1);}
+ \item{mit der \tty{t}-Option kann nun die Zeilennumerierung im Listing
+ abgeschaltet werden(p1);}
+ \item{Escapesequenzen sind nun auch in in ASCII geschriebenen
+ Integerkonstanten zul"assig(p1);}
+ \item{Mit dem Pseudobefehl \tty{PADDING} kann das Einf"ugen
+ von F"ullbytes im 680x0-Modus ein- und ausgeschaltet
+ werden (p2);}
+ \item{\tty{ALIGN} ist nun f"ur alle Zielplattformen erlaubt (p2);}
+ \item{kennt zus"atzlich die PIC16C64-SFRs (p2);}
+ \item{unterst"utzt zus"atzlich den 8096 von Intel (p2);}
+ \item{Bei \tty{DC} kann zus"atzlich ein Wiederholungsfaktor angegeben
+ werden (r3);}
+ \item{unterst"utzt zus"atzlich die TMS320C2x-Familie von Texas
+ Instruments (Implementierung von Thomas Sailer, ETH Z"urich,
+ r3); P2HEX ist auch entsprechend erweitert;}
+ \item{statt \tty{EQU} darf nun auch einfach ein Gleichheitszeichen
+ benutzt werden (r3);}
+ \item{zur Definition von Aufz"ahlungen zus"atzlich ein
+ \tty{ENUM}-Befehl (r3);}
+ \item{\tty{END} hat jetzt auch eine Wirkung (r3);}
+ \item{zus"atzliche Kommandozeilenoption \tty{n}, um zu Fehlermeldungen
+ zus"atzlich die internen Fehlernummern zu erhalten (r3);}
+ \item{unterst"utzt zus"atzlich die TLCS-9000er von Toshiba (r4)};
+ \item{unterst"utzt zus"atzlich die TMS370xxx-Reihe von Texas
+ Instuments, wobei als neuer Pseudobefehl \tty{DBIT}
+ hinzukam (r5);}
+ \item{kennt zus"atzlich die DS80C320-SFRs (r5);}
+ \item{der Makroprozessor kann nun auch Includes aus Makros
+ heraus einbinden, wozu das Format von Fehlermeldungen
+ aber leicht ge"andert werden mu"ste. Falls Sie AS2MSG
+ verwenden, ersetzen Sie es unbedingt durch die neue
+ Version! (r5)}
+ \item{unterst"utzt zus"atzlich den 80C166 von Siemens (r5);}
+ \item{zus"atzlich eine \tty{VAL}-Funktion, um Stringausdr"ucke auswerten
+ zu k"onnen (r5);}
+ \item{Mithilfe von in geschweiften Klammern eingeschlossenen
+ Stringvariablen lassen sich nun selber Symbole definieren
+ (r5);}
+ \item{kennt zus"atzlich die Eigenheiten des 80C167 von Siemens (r6);}
+ \item{jetzt gibt es f"ur die MELPS740-Reihe auch die
+ special-page-Adressierung (r6);}
+ \item{mit eckigen Klammern kann man explizit Symbole aus einer
+ bestimmten Sektion ansprechen. Die Hilfskonstruktion mit dem
+ Klammeraffen gibt es nicht mehr (r6)!}
+ \item{kennt zus"atzlich die MELPS-4500-Reihe von Mitsubishi (r7);}
+ \item{kennt zus"atzlich die H8/300 und H8/300H-Prozessoren von
+ Hitachi (r7);}
+ \item{die mit \tty{LISTING} und \tty{MACEXP} gemachten Einstellungen
+ lassen sich nun auch wieder aus gleichnamigen Symbolen auslesen
+ (r7);}
+ \item{kennt zus"atzlich den TMS320C3x von Texas Instruments (r8);}
+ \item{kennt zus"atzlich den SH7000 von Hitachi (r8);}
+ \item{der Z80-Teil wurde um die Unterst"utzung des Z380 erweitert (r9);}
+ \item{der 68K-Teil wurde um die feinen Unterschiede der
+ 683xx-Mikrokontroller erweitert (r9);}
+ \item{ein Label mu"s nun nicht mehr in der ersten Spalte beginnen,
+ wenn man es mit einem Doppelpunkt versieht (r9);}
+ \item{kennt zus"atzlich die 75K0-Reihe von NEC (r9);}
+ \item{mit dem neuen Kommandozeilenschalter o kann der Name
+ der Code-Datei neu festgelegt werden (r9);}
+ \item{der \verb!~~!-Operator ist in der Rangfolge auf einen
+ sinnvolleren Platz gerutscht (r9);}
+ \item{\tty{ASSUME} ber"ucksichtigt f"ur den 6809 jetzt auch das
+ DPR-Register und seine Auswirkungen (pardon, r9);}
+ \item{Der 6809-Teil kennt nun auch die versteckten
+ Erweiterungen des 6309 (r9);}
+ \item{Bin"arkonstanten k"onnen jetzt auch in C-artiger
+ Notation geschrieben werden (r9).}
+ \end{itemize}}
+\item{Version 1.41:
+ \begin{itemize}
+ \item{"uber das Symbol \tty{MOMSEGMENT} kann der momentan
+ gesetzte Adre"sraum abgefragt werden;}
+ \item{anstelle von \tty{SET} bzw. \tty{EVAL} kann jetzt auch
+ einfach \tty{:=} geschrieben werden;}
+ \item{mit der neuen Kommandozeilenoption \tty{q} kann ein ,,stiller''
+ Assemblerlauf erzwungen werden;}
+ \item{das Schl"usselwort \tty{PARENT} zum Ansprechen der
+ Vatersektion wurde um \tty{PARENT0...PARENT9} erweitert;}
+ \item{der PowerPC-Teil wurde um die Mikrokontroller-Versionen
+ MPC505 und PPC403 erweitert;}
+ \item{mit \tty{SET} oder \tty{EQU} definierte Symbole k"onnen
+ nun einem bestimmten Adre"sraum zugeordnet werden;}
+ \item{mit \tty{SET} oder \tty{EQU} definierte Symbole k"onnen
+ nun einem bestimmten Adre"sraum zugeordnet werden;}
+ \item{durch das Setzen der Environment-Variablen \tty{USEANSI}
+ kann die Verwendung von ANSI-Bildschirmsteuersequenzen
+ an-und ausgeschaltet werden (r1);}
+ \item{der SH7000-Teil kennt jetzt auch die SH7600-Befehlserweiterungen
+ (und sollte jetzt korrekte Displacements berechnen...) (r1).}
+ \item{im 65XX-Teil wird jetzt zwischen 65C02 und 65SC02 unterschieden
+ (r1);}
+ \item{neben der Variablen \tty{MOMCPU} gibt es jetzt auch den String
+ \tty{MOMCPUNAME}, der den Prozessornamen im Volltext enth"alt (r1).}
+ \item{P2HEX kennt jetzt auch die 32-Bit-Variante des
+ Intel-Hex-Formates (r1);}
+ \item{kennt jetzt auch die Einschr"ankungen des 87C750 (r2);}
+ \item{die Nummern f"ur fatale Fehlermeldungen wurden auf den Bereich
+ ab 10000 verschoben, um Platz f"ur normale Fehlermeldungen zu
+ schaffen (r2);}
+ \item{unbenutzte Symbole werden in der Symboltabelle jetzt mit einem
+ Stern gekennzeichnet (r2);}
+ \item{unterst"utzt zus"atzlich die 29K-Familie von AMD (r2);}
+ \item{unterst"utzt zus"atzlich die M16-Familie von Mitsubishi (r2);}
+ \item{unterst"utzt zus"atzlich die H8/500-Familie von Hitachi (r3);}
+ \item{die Anzahl von Datenbytes, die P2HEX pro Zeile ausgibt, ist
+ jetzt variierbar (r3);}
+ \item{der Pass, ab dem durch die \tty{-r}-Option erzeugte Warnungen
+ ausgegeben werden, ist einstellbar (r3);}
+ \item{der Makroprozessor kennt jetzt ein \tty{WHILE}-Statement,
+ mit dem ein Code-St"uck eine variable Anzahl wiederholt werden
+ kann (r3);}
+ \item{der \tty{PAGE}-Befehl erlaubt es nun auch, die Breite des
+ Ausgabemediums f"urs Listing anzugeben (r3);}
+ \item{Um neue Pseudo-Prozessortypen einf"uhren zu k"onnen, lassen
+ sich jetzt CPU-Aliasse definieren (r3);}
+ \item{unterst"utzt zus"atzlich die MCS/251-Familie von Intel (r3);}
+ \item{bei eingeschalteter Querverweisliste wird bei doppelt
+ definierten Symbolen die Stelle der ersten Definition
+ angezeigt (r3);}
+ \item{unterst"utzt zus"atzlich die TMS320C5x-Familie von Texas
+ Instruments (Implementierung von Thomas Sailer, ETH Z"urich,
+ r3);}
+ \item{die OS/2-Version sollte jetzt auch mit langen Dateinamen
+ klarkommen. Wenn man nicht jeden Mist selber kontrolliert...
+ (r3)}
+ \item{"uber den Befehl \tty{BIGENDIAN} kann im MCS-51/251-Modus
+ jetzt gew"ahlt werden, ob die Ablage von Konstanten im Big-
+ oder Little-Endian-Format erfolgen soll (r3);}
+ \item{es wird beim 680x0 jetzt zwischen dem vollen und eingeschr"ankten
+ MMU-Befehlssatz unterschieden; eine manuelle Umschaltung ist mit dem
+ \tty{FULLPMMU}-Befehl m"oglich (r3);}
+ \item{"uber die neue Kommandozeilenoption \tty{I} kann eine Liste
+ aller eingezogenen Include-Files mit ihrer Verschachtelung
+ ausgegeben werden (r3);}
+ \item{Beim \tty{END}-Statement kann jetzt zus"atzlich ein
+ Einsprungpunkt f"ur das Programm angegeben werden (r3).}
+ \item{unterst"utzt zus"atzlich die 68HC16-Familie von Motorola (r3);}
+ \item{P2HEX und P2BIN erlauben es jetzt, den Inhalt einer Code-Datei
+ adre"sm"a"sig zu verschieben (r4);}
+ \item{einem \tty{SHARED}-Befehl anh"angende Kommentare werden jetzt
+ in die Share-Datei mit "ubertragen (r4);}
+ \item{unterst"utzt zus"atzlich die 68HC12-Familie von Motorola (r4);}
+ \item{unterst"utzt zus"atzlich die XA-Familie von Philips (r4);}
+ \item{unterst"utzt zus"atzlich die 68HC08-Familie von Motorola (r4);}
+ \item{unterst"utzt zus"atzlich die AVR-Familie von Atmel (r4);}
+ \item{aus Kompatibilit"at zum AS11 von Motorola existieren zus"atzlich
+ die Befehle \tty{FCB}, \tty{FDB}, \tty{FCC} und \tty{RMB} (r5);}
+ \item{unterst"utzt zus"atzlich den M16C von Mitsubishi (r5);}
+ \item{unterst"utzt zus"atzlich den COP8 von National Semiconductor
+ (r5);}
+ \item{zwei neue Befehle zur bedingten Assemblierung: \tty{IFB} und
+ \tty{IFNB} (r5);}
+ \item{Mit dem \tty{EXITM}-Befehl ist es nun m"oglich, eine
+ Makroexpansion vorzeitig abzubrechen (r5);}
+ \item{unterst"utzt zus"atzlich den MSP430 von Texas Instruments
+ (r5);}
+ \item{\tty{LISTING} kennt zus"atzlich die Varianten
+ \tty{NOSKIPPED} und \tty{PURECODE}, um nicht assemblierten
+ Code aus dem Listing auszublenden (r5);}
+ \item{unterst"utzt zus"atzlich die 78K0-Familie von NEC (r5);}
+ \item{BIGENDIAN ist jetzt auch im PowerPC-Modus verf"ugbar (r5);}
+ \item{zus"atzlich ein \tty{BINCLUDE}-Befehl, um Bin"ardaten
+ einbinden zu k"onnen (r5);}
+ \item{zus"atzliche TOLOWER- und LOWSTRING-Funktionen, um
+ Gro"s- in Kleinbuchstaben umzuwandeln (r5);}
+ \item{es ist jetzt m"oglich, auch in anderen Segmenten als
+ CODE Daten abzulegen. Das Dateiformat wurde entsprechend
+ erweitert (r5);}
+ \item{der \tty{DS}-Befehl, mit dem man Speicherbereiche reservieren
+ kann, ist jetzt auch im Intel-Modus zul"assig (r5);}
+ \item{Mit der Kommandozeilenoption \tty{U} ist es jetzt
+ m"oglich, AS in einen case-sensitiven Modus umzuschalten,
+ in dem Namen von Symbolen, selbstdefinierten Funktionen,
+ Makros, Makroparametern sowie Sektionen nach Gro"s-
+ und Kleinschreibung unterschieden werden (r5);}
+ \item{\tty{SFRB} ber"ucksichtigt jetzt auch die Bildungsregeln
+ f"ur Bitadressen im RAM-Bereich; werden nicht bitadressierbare
+ Speicherstellen angesprochen, erfolgt eine Warnung (r5);}
+ \item{zus"atzliche Pseudobefehle \tty{PUSHV} und \tty{POPV}, um
+ Symbolwerte tempor"ar zu sichern (r5);}
+ \item{zus"atzliche Funktionen \tty{BITCNT, FIRSTBIT, LASTBIT} und
+ \tty{BITPOS} zur Bitverarbeitung (r5);}
+ \item{bei den CPU32-Prozessoren ist jetzt auch der 68360
+ ber"ucksichtigt (r5);}
+ \item{unterst"utzt zus"atzlich die ST9-Familie von SGS-Thomson (r6);}
+ \item{unterst"utzt zus"atzlich den SC/MP von National Semiconductor
+ (r6);}
+ \item{unterst"utzt zus"atzlich die TMS70Cxx-Familie von Texas
+ Instruments (r6);}
+ \item{unterst"utzt zus"atzlich die TMS9900-Familie von Texas
+ Instruments (r6);}
+ \item{unterst"utzt zus"atzlich die Befehlssatzerweiterungen
+ des 80296 (r6);}
+ \item{die unterst"utzten Z8-Derivate wurden erweitert
+ (r6);}
+ \item{ber"ucksichtigt zus"atzlich die Maskenfehler des 80C504
+ von Siemens (r6);}
+ \item{zus"atzliche Registerdefinitionsdatei f"ur die C50x-Prozessoren
+ von Siemens (r6);}
+ \item{unterst"utzt zus"atzlich die ST7-Familie von SGS-Thomson (r6);}
+ \item{die Intel-Pseudobefehle zur Datenablage sind jetzt
+ auch f"ur 65816 bzw. MELPS-7700 zul"assig (r6);}
+ \item{f"ur 65816/MELPS-7700 kann die Adre"sl"ange jetzt durch
+ Pr"afixe explizit festgelegt werden (r6);}
+ \item{unterst"utzt zus"atzlich die 8X30x-Familie von Signetics
+ (r6);}
+ \item{\tty{PADDING} ist nur noch f"ur die 680x0-Familie defaultm"a"sig
+ eingeschaltet (r7);}
+ \item{"uber das neu eingef"uhrte, vordefinierte Symbol
+ \tty{ARCHITECTURE} kann ausgelesen werden, f"ur welche
+ Plattform AS "ubersetzt wurde (r7);}
+ \item{Zus"atzliche Anweisungen \tty{STRUCT} und \tty{ENDSTRUCT} zur
+ Definition von Datenstrukturen (r7);}
+ \item{Hex- und Objekt-Dateien f"ur die AVR-Tools k"onnen jetzt
+ direkt erzeugt werden (r7);}
+ \item{\tty{MOVEC} kennt jetzt auch die 68040-Steuerregister (r7);}
+ \item{zus"atzliche \tty{STRLEN}-Funktion, um die L"ange eines
+ Strings zu ermitteln (r7);}
+ \item{M"oglichkeit zur Definition von Registersymbolen (r7, momentan
+ nur Atmel AVR);}
+ \item{kennt zus"atzlich die undokumentierten 6502-Befehle (r7);}
+ \item{P2HEX und P2BIN k"onnen jetzt optional die Eingabedateien
+ automatisch l"oschen (r7);}
+ \item{P2BIN kann der Ergebnisdatei optional zus"atzlich die
+ Startadresse voranstellen (r7);}
+ \item{unterst"utzt zus"atzlich die ColdFire-Familie von Motorola als
+ Variation des 680x0-Kerns (r7);}
+ \item{\tty{BYT/FCB, ADR/FDB} und \tty{FCC} erlauben jetzt auch den
+ von \tty{DC} her bekannten Wiederholungsfaktor (r7);}
+ \item{unterst"utzt zus"atzlich den M*Core von Motorola (r7);}
+ \item{der SH7000-Teil kennt jetzt auch die SH7700-Befehlserweiterungen
+ (r7);}
+ \item{der 680x0-Teil kennt jetzt auch die zus"atzlichen Befehle des
+ 68040 (r7);}
+ \item{der 56K-Teil kennt jetzt auch die Befehlserweiterungen bis zum
+ 56300 (r7).}
+ \item{Mit der neuen \tty{CODEPAGE}-Anweisung können jetzt auch
+ mehrere Zeichentabellen gleichzeitig verwaltet werden (r8);}
+ \item{Die Argumentvarianten f"ur \tty{CHARSET} wurden erweitert
+ (r8);}
+ \item{Neue String-Funktionen \tty{SUBSTR} und \tty{STRSTR} (r8);}
+ \item{zus"atzliches \tty{IRPC}-Statement im Makroprozessor (r8);}
+ \item{zus"atzlicher {\tt RADIX}-Befehl, um das Default-Zahlensystem
+ f"ur Integer-Konstanten festzulegen (r8);}
+ \item{statt {\tt ELSEIF} darf auch einfach {\tt ELSE} geschrieben
+ werden (r8);}
+ \item{statt $=$ darf als Gleichheitsoperator auch $==$ geschrieben
+ werden (r8);}
+ \item{\tty{BRANCHEXT} erlaubt es beim Philips XA jetzt, die
+ Sprungweite von kurzen Spr"ungen automatisch zu erweitern
+ (r8);}
+ \item{Debug-Ausgaben sind jetzt auch im NoICE-Format m"oglich (r8);}
+ \item{unterst"utzt zus"atzlich die i960-Familie von Intel (r8);}
+ \item{unterst"utzt zus"atzlich die $\mu$PD7720/7725-Signalprozssoren
+ von NEC (r8);}
+ \item{unterst"utzt zus"atzlich den $\mu$PD77230-Signalprozssor von
+ NEC (r8);}
+ \item{unterst"utzt zus"atzlich die SYM53C8xx-SCSI-Prozessoren von
+ Symbios Logic (r8);}
+ \item{unterst"utzt zus"atzlich den 4004 von Intel (r8);}
+ \item{unterst"utzt zus"atzlich die SC14xxx-Serie von National (r8);}
+ \item{unterst"utzt zus"atzlich die Befehlserweiterungen des PPC403GC
+ (r8);}
+ \item{zus"atzliche Kommandozeilenoption {\tt cpu}, um den
+ Zielprozessor-Default zu setzen (r8);}
+ \item{Key-Files k"onnen jetzt auch von der Kommandozeile aus
+ referenziert werden (r8);}
+ \item{zus"atzliche Kommandozeilenoption {\tt shareout}, um die
+ Ausgabedatei f"ur SHARED-Definitionen zu setzen (r8);}
+ \item{neuer Pseudobefehl {\tt WRAPMODE}, um AVR-Prozessoren mit
+ verk"urztem Programmz"ahler zu unterst"utzen (r8);}
+ \item{unterst"utzt zus"atzlich die C20x-Befehlsuntermenge im
+ C5x-Teil (r8);}
+ \item{hexadezimale Adre"angaben der Hilfsprogamme k"onnen jetzt
+ auch in C-Notation gemacht werden (r8);}
+ \item{Das Zahlensystem f"ur Integerergebnisse in \verb!\{...}!-
+ Ausdr"ucken ist jetzt per \tty{OUTRADIX} setzbar (r8);}
+ \item{Die Registersyntax f"ur 4004-Registerpaare wurde korrigiert
+ (r8);}
+ \item{unterst"utzt zus"atzlich die F$^{2}$MC8L-Familie von Fujitsu
+ (r8);}
+ \item{f"ur P2HEX kann jetzt die Minimall"ange f"ur S-Record-Adressen
+ angegeben werden (r8);}
+ \item{unterst"utzt zus"atzlich die ACE-Familie von Fairchild (r8);}
+ \item{{\tt REG} ist jetzt auch f"ur PowerPCs erlaubt (r8);}
+ \item{zus"atzlicher Schalter in P2HEX, um alle Adressen zu
+ verschieben (r8);}
+ \item{Mit dem Schalter \tty{x} kann man jetzt zus"atzlich in einer
+ zweiten Stufe bie betroffene Quellzeile ausgeben (r8).}
+ \end{itemize}}
+\end{itemize}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Hinweise zum Quellcode von AS}
+\label{ChapSource}
+
+Wie in der Einleitung erw"ahnt, gebe ich nach R"ucksprache den Quellcode
+von AS heraus. Im folgenden sollen einige Hinweise zu dessen Handhabung
+gegeben werden.
+
+%%---------------------------------------------------------------------------
+
+\section{Verwendete Sprache}
+
+Urspr"unglich war AS ein in Turbo-Pascal geschriebenes Programm. F"ur
+diese Entscheidung gab es Ende der 80er Jahre eine Reihe von Gr"unden:
+Zum einen war ich damit wesentlich vertrauter als mit jedem C-Compiler,
+zum anderen waren alle C-Compiler unter DOS verglichen mit der IDE von
+Turbo-Pascal ziemliche Schnecken. Anfang 1997 zeichnete sich jedoch ab,
+da"s sich das Blatt gewendet hatte: Zum einen hatte Borland beschlossen,
+die DOS-Entwickler im Stich zu lassen (nochmals ausdr"ucklich keinen
+sch"onen Dank, Ihr Pappnasen von Borland!), und Version 7.0 etwas namens
+'Delphi' nachfolgen lie"sen, was zwar wohl wunderbar f"ur
+Windows-Programme geeignet ist, die zu 90\% aus Oberfl"ache und zuf"allig
+auch ein bi"schen Funktion bestehen, f"ur kommandozeilenorientierte
+Progamme wie AS aber reichlich unbrauchbar ist. Zum anderen hatte sich
+bereits vor diesem Zeitpunkt mein betriebssystemm"a"siger Schwerpunkt
+deutlich in Richtung Unix verschoben, und auf ein Borland-Pascal f"ur
+Linux h"atte ich wohl beliebig lange warten k"onnen (an alle die, die
+jetzt sagen, Borland w"urde ja an soetwas neuerdings basteln: Leute, das
+ist {\em Vapourware}, und glaubt den Firmen nichts, solange Ihr nicht
+wirklich in den Laden gehen und es kaufen k"onnt!). Von daher war also
+klar, da"s der Weg in Richtung C gehen mu"ste.
+
+Nach der Erfahrung, wohin die Verwendung von Inselsystemen f"uhrt, habe
+ich bei der Umsetzung auf C Wert auf eine m"oglichst gro"se Portabilit"at
+gelegt; da AS jedoch z.B. Bin"ardateien in einem bestimmten Format
+erzeugen mu"s und an einigen Stellen betriebssystemspezifische Funktionen
+nutzt, gibt es einige Stellen, an denen man anpassen mu"s, wenn man AS zum
+ersten Mal auf einer neuen Plattform "ubersetzt.
+
+AS ist auf einen C-Compiler ausgelegt, der dem ANSI-Standard entspricht;
+C++ ist ausdr"ucklich nicht erforderlich. Wenn Sie nur einen Compiler
+nach dem veralteten Kernighan\&Ritchie-Standard besitzen, sollten Sie sich
+nach einem neuen Compiler umsehen; der ANSI-Standard ist seit 1989
+verabschiedet und f"ur jede aktuelle Plattform sollte ein ANSI-Compiler
+verf"ugbar sein, zur Not, indem man mit dem alten Compiler GNU-C baut. Im
+Quellcode sind zwar einige Schalter vorhanden, um den Code K\&R-n"aher zu
+machen, aber dies ist ein nicht offiziell unterst"utztes Feature, das ich
+nur intern f"ur ein ziemlich antikes Unix benutze. Alles weitere zum
+'Thema K\&R' steht in der Datei {\tt README.KR}.
+
+Der Sourcenbaum ist durch einige in der Pascal-Version nicht vorhandene
+Features (z.B. dynamisch ladbare Nachrichtendateien, Testsuite,
+automatische Generierung der Dokumentation aus {\em einem} Quellformat)
+deutlich komplizierter geworden. Ich werde versuchen, die Sache Schritt
+f"ur Schritt aufzudr"oseln:
+
+%%---------------------------------------------------------------------------
+
+\section{Abfangen von Systemabh"angigkeiten}
+
+Wie ich schon andeutete, ist AS (glaube ich jedenfalls...) auf
+Plattformunabh"angigkeit und leichte Portierbarkeit getrimmt. Dies
+bedeutet, da"s man die Platt\-form\-un\-ab\-h"an\-gig\-kei\-ten in
+m"oglichst wenige Dateien zusammenzieht. Auf diese Dateien werde ich im
+folgenden eingehen, und dieser Abschnitt steht ganz vorne, weil es sicher
+eines der wichtigsten ist:
+
+Die Generierung aller Komponenten von AS erfolgt "uber ein zentrales {\tt
+Makefile}. Damit dies funktioniert, mu"s man ihm ein passendes {\tt
+Makefile.def} anbieten, das die plattformabh"angigen Einstellungen wie
+z.B. Compilerflags vorgibt. Im Unterverzeichnis {\tt
+Makefile.def-samples} finden sich eine Reihe von Includes, die f"ur
+g"angige Plattformen funktionieren (aber nicht zwangsweise optimal sein
+m"ussen...). Wenn die von Ihnen benutzte Plattform nicht dabei ist,
+k"onnen Sie die Beispieldatei {\tt Makefile.def.tmpl} als Ausgangspunkt
+verwenden (und das Ergebnis mir zukommen lassen!).
+
+Ein weiterer Anlaufpunkt zum Abfangen von Systemabh"angigkeiten ist die
+Datei {\tt sysdefs.h}. Praktisch alle Compiler definieren eine Reihe von
+Pr"aprozessorsymbolen vor, die den benutzten Zielprozessor sowie das
+benutzte Betriebsystem beschreiben. Auf einer Sun Sparc unter Solaris
+mit den GNU-Compiler sind dies z.B. die Symbole \verb!__sparc! und
+\verb!__SVR4!. In {\tt sysdefs.h} werden diese Symbole genutzt, um f"ur
+die restlichen, systemunabh"angigen Dateien eine einheitliche Ungebung
+bereitzustellen. Insbesondere betrifft dies Integer-Datentypen einer
+bekannten L"ange, es kann aber auch die Nach- oder Redefinition von
+C-Funktionen betreffen, die auf einer bestimmten Plattform nicht oder
+nicht standardgem"a"s vorhanden sind. Was da so an Sachen anf"allt, liest
+man am besten selber nach. Generell sind die \verb!#ifdef!-Statements in
+zwei Ebenen gegliedert: Zuerst wird eine bestimmte Prozessorplattform
+ausgew"ahlt, dann werden in diesem Abschnitt die Betriebssysteme
+auseinandersortiert.
+
+Wenn Sie AS auf eine neue Plattform portieren, m"ussen Sie zwei f"ur diese
+Plattform typische Symbole finden und {\tt sysdefs.h} passend erweitern
+(und wieder bin ich an dem Ergebnis interessiert...).
+
+%%---------------------------------------------------------------------------
+
+\section{Systemunabh"angige Dateien}
+
+...stellen den g"o"sten Teil aller Module dar. Alle Funktionen im Detail
+zu beschreiben, w"urde den Rahmen dieser Beschreibung sprengen (wer hier
+mehr wissen will, steigt am besten selbst in das Studium der Quellen ein,
+so katastrophal ist mein Programmierstil nun auch wieder nicht...),
+deshalb hier nur eine kurze Auflistung, welche Module vorhanden sind und
+was f"ur Funktionen sie beinhalten:
+
+\subsection{Von AS genutzte Module}
+
+\subsubsection{as.c}
+
+Diese Datei ist die Wurzel von AS: Sie enth"alt die {\em main()}-Funktion
+von AS, die Verarbeitung aller Kommandozeilenoptionen, die "ubergeordnete
+Steuerung aller Durchl"aufe durch die Quelldateien sowie Teile des
+Makroprozessors.
+
+\subsubsection{asmallg.c}
+
+In diesem Modul werden all die Befehle bearbeitet, die f"ur alle Prozessoren
+definiert sind, z.B. \tty{EQU} und \tty{ORG}. Hier findet sich auch der
+\tty{CPU}-Befehl, mit dem zwischen den einzelnen Prozessoren hin- und
+hergeschaltet wird.
+
+\subsubsection{asmcode.c}
+
+In diesem Modul befindet sich die Verwaltung der Code-Ausgabedatei.
+Exportiert wird ein Interface, mit dem sich eine Code-Datei "offnen
+und schlie"sen l"a"st, und das Routinen zum Einschreiben (und
+Zur"ucknehmen) von Code anbietet. Eine wichtige Aufgabe dieses Moduls
+ist die Pufferung des Schreibvorgangs, die die Ausgabegeschwindigkeit
+erh"oht, indem der erzeugte Code in gr"o"seren Bl"ocken geschrieben wird.
+
+\subsubsection{asmdebug.c}
+
+Optional kann AS Debug-Informationen f"ur andere Tools wie Simulatoren
+oder Debugger erzeugen, die einen R"uckbezug auf den Quellcode erlauben,
+in diesem Modul gesammelt und nach Ende der Assemblierung in einem von
+mehreren Formaten ausgegeben werden k"onnen.
+
+\subsubsection{asmdef.c}
+
+Dieses Modul enth"alt lediglich Deklarationen von "uberall ben"otigten
+Konstanten und gemeinsam benutzten Variablen.
+
+\subsubsection{asmfnums.c}
+
+Intern vergibt AS f"ur jede benutzte Quelldatei eine fortlaufende Nummer,
+die zur schnellen Referenzierung benutzt wird. Die Vergabe dieser Nummern
+und die Umwandlung zwischen Nummer und Dateinamen passiert hier.
+
+\subsubsection{asmif.c}
+
+Hier befinden sich alle Routinen, die die bedingte Assemblierung steuern.
+Exportiert wird als wichtigste Variable das Flag \tty{IfAsm}, welches
+anzeigt, ob Codeerzeugung momentan ein- oder ausgeschaltet ist.
+
+\subsubsection{asminclist.c}
+
+In diesem Modul ist die Listenstruktur definiert, "uber die AS die
+Verschachtelung von Include-Dateien im Listing ausgeben kann.
+
+\subsubsection{asmitree.c}
+
+Wenn man in einer Code-Zeile das benutzende Mnemonic ermitteln will, ist
+das einfache Durchvergleichen mit allen vorhandenen Befehlen (wie es noch
+in vielen Codegeneratoren aus Einfachheit und Faulheit passiert) nicht
+unbedingt die effizienteste Variante. In diesem Modul sind zwei
+verbesserte Strukturen (Bin"arbaum und Hash-Tabelle) definiert, die eine
+effizientere Suche erm"oglichen und die einfache lineare Suche nach und
+nach abl"osen sollen...Priorit"at nach Bedarf...
+
+\subsubsection{asmmac.c}
+
+In diesem Modul finden sich die Routinen zur Speicherung und Abfrage von
+Makros. Der eigentliche Makroprozessor befindet sich (wie bereits
+erw"ahnt) in {\tt as.c}.
+
+\subsubsection{asmpars.c}
+
+Hier geht es ins Eingemachte: In diesem Modul werden die Symboltabellen
+(global und lokal) in zwei Bin"arb"aumen verwaltet. Au"serdem findet sich
+hier eine ziemlich gro"se Prozedur \tty{EvalExpression}, welche einen
+(Formel-)ausdruck analysiert und auswertet. Die Prozedur liefert das
+Ergebnis (Integer, Gleitkomma oder String) in einem varianten Record zur"uck.
+Zur Auswertung von Ausdr"ucken bei der Codeerzeugung sollten allerdings eher
+die Funktionen \tty{EvalIntExpression, EvalFloatExpression} und
+\tty{EvalStringExpression} verwendet werden. "Anderungen zum Einf"ugen neuer
+Prozessoren sind hier nicht erforderlich und sollten auch nur mit "au"serster
+"Uberlegung erfolgen, da man hier sozusagen an ,,die Wurzel'' von AS greift.
+
+\subsubsection{asmsub.c}
+
+Hier finden sich gesammelt einige h"aufig gebrauchte Unterroutinen, welche
+in erster Linie die Bereiche Fehlerbehandlung und 'gehobene'
+Stringverarbeitung abdecken.
+
+\subsubsection{bpemu.c}
+
+Wie am Anfang erw"ahnt, war AS urspr"unglich ein in Borland-Pascal
+geschriebenes Programm. Bei einigen intrinsischen Funktionen des
+Compilers war es einfacher, diese zu emulieren, anstatt alle betroffenen
+Stelle im Quellcode zu "andern. Na ja...
+
+\subsubsection{chunks.c}
+
+Dieses Modul definiert einen Datentyp, mit dem eine Liste von
+Adre"sbereichen verwaltet werden kann. Diese Funktion wird von AS
+f"ur die Belegungslisten ben"otigt, au"serdem benutzten P2BIN und
+P2HEX diese Listen, um vor "Uberlappungen zu warnen.
+
+\subsubsection{cmdarg.c}
+
+Dieses Modul implementiert den Mechanismus der Kommdozeilenparameter. Es
+ben"otigt eine Spezifikation der erlaubten Parameter, zerlegt die
+Kommadozeile und ruft die entsprechenden Callbacks auf. Der Mechanismus
+leistet im einzelnen folgendes:
+\begin{itemize}
+\item{Mitbearbeitung von Optionen in einer Environment-Variablen oder
+ entsprechenden Datei;}
+\item{R"uckgabe einer Menge, welche die noch nicht bearbeiteten
+ Kommandozeilenparameter beschreibt;}
+\item{Trenunng von positiven und negativen Schaltern;}
+\item{Eine Hintert"ur, falls die dar"uberliegende Entwicklungsumgebung die
+ Kommandozeile nur in Gro"s- oder Kleinschreibung "ubergibt.}
+\end{itemize}
+Dieses Modul wird nicht nur von AS, sondern auch von den Hilfsprogrammen
+\tty{BIND, P2HEX und P2BIN} verwendet.
+
+\subsubsection{codepseudo.c}
+
+Hier finden sich Pseudobefehle, die von mehreren Codegeneratoren verwendet
+werden. Dies ist einmal die Intel-Gruppe mit der \tty{DB..DT}-Gruppe,
+zum anderen die Pendants f"ur die 8/16-Bitter von Motorola oder Rockwell.
+Wer in diesem Bereich um einen Prozessor erweitern will, kann mit einem
+Aufruf den gr"o"sten Teil der Pseudobefehle erschlagen.
+
+\subsubsection{codevars.c}
+
+Aus Speicherersparnisgr"unden sind hier einige von diversen
+Codegeneratoren benutzen Variablen gesammelt.
+
+\subsubsection{endian.c}
+
+Doch noch ein bi"schen Maschinenabh"angigkeit, jedoch ein Teil, um den man
+sich nicht zu k"ummern braucht: Ob eine Maschine Little- oder
+Big-Endianess benutzt, wird in diesem Modul beim Programmstart automatisch
+bestimmt. Weiterhin wird gepr"uft, ob die in {\tt sysdefs.h} gemachten
+Typfestlegungen f"ur Integervariablen auch wirklich die korrekten L"angen
+ergeben.
+
+\subsubsection{headids.c}
+
+Gesammelt sind hier alle von AS unterst"utzten Zielprozessorfamilien, die
+daf"ur in Code-Dateien verwendeten Kennzahlen (siehe Kapitel
+\ref{SectCodeFormat}) sowie das von P2HEX defaultm"a"sig zu verwendende
+Ausgabeformat. Ziel dieser Tabelle ist es, Das Hinzuf"ugen eines neuen
+Prozessors m"oglichst zu zentralisieren, d.h. es sind im Gegensatz zu
+fr"uher keine weiteren Modifikationen an den Quellen der Hilfsprogramme
+mehr erforderlich.
+
+\subsubsection{ioerrs.c}
+
+Hier ist die Umwandlung von Fehlernummern in Klartextmeldungen abgelegt.
+Hoffentlich treffe ich nie auf ein System, auf dem die Nummern nicht als
+Makros definiert sind, dann kann ich n"amlich dieses Modul komplett
+umschreiben...
+
+\subsubsection{nlmessages.c}
+
+Die C-Version von AS liest alle Meldungen zur Laufzeit aus Dateien, nachdem
+die zu benutzende Sprache ermittelt wurde. Das Format der
+Nachrichtendateien ist kein einfaches, sondern ein spezielles, kompaktes,
+vorindiziertes Format, das zur "Ubersetzungszeit von einem Programm namens
+'rescomp' (dazu kommen wir noch) erzeugt wird. Dieses Modul ist das
+Gegenst"uck zu rescomp, die den korrekten Sprachenanteil einer Datei in ein
+Zeichenfeld einliest und Zugriffsfunktionen anbietet.
+
+\subsubsection{nls.c}
+
+In diesem Modul wird ermittelt, welche nationalen Einstellungen (Datums-
+und Zeitformat, L"andercode) zur Laufzeit vorliegen. Das ist leider eine
+hochgradig systemspezifische Sache, und momentan sind nur drei Methoden
+definiert: Die von MS-DOS, die von OS/2 und die typische Unix-Methode
+"uber die {\em locale}-Funktionen. F"ur alle anderen Systeme ist leider
+\verb!NO_NLS! angesagt...
+
+\subsubsection{stdhandl.c}
+
+Zum einen ist hier eine spezielle open-Funktion gelandet, die die
+Sonderstrings {\tt !0...!2} als Dateinamen kennt und daf"ur Duplikate der
+Standard-Dateihandles {\em stdin, stdout} und {\em stderr} erzeugt, zum
+anderen wird hier festgestellt, ob die Standardausgabe auf ein Ger"at oder
+eine Datei umgeleitet wurde. Das bedingt auf nicht-Unix-Systemen leider
+auch einige Speziall"osungen.
+
+\subsubsection{stringlists.c}
+
+Dies ist nur ein kleiner ,,Hack'', der Routinen zur Verwaltung von linearen
+Listen mit Strings als Inhalt definiert, welche z.B. im Makroprozessor von
+AS gebraucht werden.
+
+\subsubsection{strutil.c}
+
+Hier sind einige h"aufig genutzte String-Operationen gelandet.
+
+\subsubsection{version.c}
+
+Die momentan g"ultige Version ist f"ur AS und alle anderen Hilfsprogramme
+hier zentral gespeichert.
+
+\subsubsection{code????.c}
+
+Dies Module bilden den Hauptteil der AS-Quellen: jedes Modul beinhaltet
+den Codegenerator f"ur eine bestimmte Prozessorfamilie.
+
+\subsection{Zus"atzliche Module f"ur die Hilfsprogramme}
+
+\subsubsection{hex.c}
+
+Ein kleines Modul zur Umwandlung von Integerzahlen in
+Hexadezimaldarstellung. In C nicht mehr unbedingt erforderlich (au"ser
+zur Wandlung von {\em long long}-Variablen, was leider nicht alle {\tt
+printf()}'s unterst"utzen), aber es ist im Rahmen der Portierung eben auch
+stehengeblieben.
+
+\subsubsection{p2bin.c}
+
+Die Quellen von P2BIN.
+
+\subsubsection{p2hex.c}
+
+Die Quellen von P2HEX.
+
+\subsubsection{pbind.c}
+
+Die Quellen von BIND.
+
+\subsubsection{plist.c}
+
+Die Quellen von PLIST.
+
+\subsubsection{toolutils.c}
+
+Hier sind gesammelt die Unterroutinen, die von allen Hilfsprogrammen
+ben"otigt werden, z.B. f"ur das Lesen von Code-Dateien.
+
+\section{W"ahrend der Erzeugung von AS gebrauchte Module}
+
+\subsubsection{a2k.c}
+
+Dies ist ein Minimalfilter, das ANSI-C-Files in Kernighan-Ritchie
+umwandelt. Um es genau zu sagen: es werden nur die Funktionsk"opfe
+umgewandelt, und auch nur dann, wenn sie ungef"ahr so formatiert sind, wie
+es mein Schreibstil eben ist. Es komme also keiner auf die Idee, das
+w"are ein universeller C-Parser!
+
+\subsubsection{addcr.c}
+
+Ein kleiner Filter, der bei der Installation auf DOS- oder OS/2-Systemen
+gebraucht wird. Da DOS und OS/2 den Zeilenvorschub mit CR/LF vornehmen,
+Unix-Systeme jedoch nur mit LF, werden s"amtliche mitgelieferten
+Assembler-Includes bei der Installation durch diesen Filter geschickt.
+
+\subsubsection{bincmp.c}
+
+F"ur DOS und OS/2 "ubernimmt dieses Modul die Funktion die Funktion des
+{\em cmp}-Befehls, d.h. den bin"aren Vergleich von Dateien w"ahrend des
+Testlaufes. W"ahrend dies prinzipiell auch mit dem mitgelieferten {\em
+comp} m"oglich w"are, hat {\em bincmp} keine l"astigen interaktiven
+Abfragen (bei denen man erst einmal herausfinden mu"s, wie man sie auf
+allen Betriebssystemversionen abstellt...)
+
+\subsubsection{findhyphen.c}
+
+Dies ist das Untermodul in {\em tex2doc}, da"s f"ur die Silbentrennung von
+Worten sorgt. Der verwendete Algorithmus is schamlos von TeX
+abgekupfert.
+
+\subsubsection{grhyph.c}
+
+Die Definition der Silbentrennungsregeln f"ur die deutsche Sprache.
+
+\subsubsection{rescomp.c}
+
+Dies ist der 'Resourcencompiler' von AS, d.h. das Werkzeug, das die
+lesbaren Dateien mit Stringresourcen in ein schnelles, indiziertes Format
+umsetzt.
+
+\subsubsection{tex2doc.c}
+
+Ein Werkzeug, da"s die LaTeX-Dokumentation von AS in ein ASCII-Format
+umsetzt.
+
+\subsubsection{tex2html.c}
+
+Ein Werkzeug, da"s die LaTeX-Dokumentation von AS in ein HTML-Dokument
+umsetzt.
+
+\subsubsection{umlaut.c und unumlaut.c}
+
+Diese Progr"ammchen besorgen die Wandlung zwischen Sonderzeichenkodierung
+im ISO-Format (alle AS-Dateien verwenden im Auslieferungszustand die
+ISO8859-1-Kodierung f"ur Sonderzeichen) und Sonderzeichenkodierung im
+systemspezifischen Format. Neben einer Plain-ASCII7-Variante sind dies im
+Augenblick die IBM-Zeichens"atze 437 und 850.
+
+\subsubsection{ushyph.c}
+
+Die Definition der Silbentrennungsregeln f"ur die englische Sprache.
+
+%%---------------------------------------------------------------------------
+
+\section{Generierung der Nachrichtendateien}
+
+Wie bereits erw"ahnt, verwendet der C-Quellenbaum von AS ein dynamisches
+Ladeverfahren f"ur alle (Fehler-)Meldungen. Gegen"uber den
+Pascal-Quellen, in denen alle Meldungen in einem Include-File geb"undelt
+waren und so in die Programme hinein"ubersetzt wurden, macht es dieses
+Verfahren "uberfl"ussig, mehrere sprachliche Varianten von AS zur
+Verf"ugung zu stellen: es gibt nur noch eine Version, die beim
+Programmstart die zu benutzende Variante ermittelt und aus den
+Nachrichtendateien die entsprechende Komponente l"adt. Kurz zur
+Erinnerung: Unter DOS und OS/2 wird dazu die gew"ahlte {\tt
+COUNTRY}-Einstellung zu Rate gezogen, unter Unix werden die
+Environment-Variablen {\tt LC\_MESSAGES, LC\_ALL} und {\tt LANG} befragt.
+
+\subsection{Format der Quelldateien}
+
+Eine Quelldatei f"ur den Message-Compiler {\em rescomp} hat "ublicherweise
+die Endung {\tt .res}. Der Message-Compiler erzeugt aus dieser Datei ein
+oder zwei Dateien:
+\begin{itemize}
+\item{eine bin"are Datei, die zur Laufzeit von AS bzw. den Hilfsprogrammen
+ gelesen wird;}
+\item{optional eine weitere C-Header-Datei, die allen vorhandenen
+ Nachrichten eine Indexnummer zuweist. "Uber diese Indexnummern und
+ eine Indextabelle in der bin"aren Datei kann zur Laufzeit schnell
+ auf einzelne Meldungen zugegriffen werden.}
+\end{itemize}
+
+Die Quelldatei f"ur den Message-Compiler ist eine reine ASCII-Datei, also
+mit jedem beliebigen Editor bearbeitbar, und besteht aus einer Reihe von
+Steueranweisungen mit Parametern. Leerzeilen sowie Zeilen, die mit einem
+Semikolon beginnen, werden ignoriert. Das Inkludieren anderer Dateien ist
+"uber das {\tt Include}-Statement m"oglich:
+\begin{verbatim}
+Include <Datei>
+\end{verbatim}
+
+Am Anfang jeder Quelldatei m"ussen zwei Statements stehen, die die im
+folgenden definierten Sprachen beschreiben. Das wichtigere der beiden
+Statements ist {\tt Langs}, z.B.:
+\begin{verbatim}
+Langs DE(049) EN(001,061)
+\end{verbatim}
+beschreibt, da"s zwei Sprachen im folgenden definiert werden. Der erste
+Nachrichtensatz soll benutzt werden, wenn unter Unix die Sprache per
+Environment-Variablen auf {\tt DE} gestellt wurde bzw. unter DOS bzw. OS/2
+der Landescode 049 eingestellt wurde. Der zweite Satz kommt
+dementsprechend bei den Einstellungen {\tt EN} bzw. 061 oder 001 zum
+Einsatz. W"ahrend bei den 'Telefonnummern' mehrere Codes auf einen
+Nachrichtensatz verweisen k"onnen, ist die Zuordnung zu den
+Unix-Landescodes eineindeutig. Dies ist in der Praxis aber kein
+Beinbruch, weil die {\tt LANG}-Variablen unter Unix Unterversionen einer
+Sprache als Anh"angsel beschreiben, z.B. so:
+\begin{verbatim}
+de.de
+de.ch
+en.us
+\end{verbatim}
+AS vergleicht nur den Anfang der Strings und kommt so trotzdem zur
+richtigen Entscheidung.
+Das {\tt Default}-Statement gibt vor, welcher Sprachensatz verwendet
+werden soll, wenn entweder "uberhaupt keine Sprache gesetzt wurde oder
+eine Kennung verwendet wird, die nicht in der Liste von {\tt Langs}
+vorhanden ist. Typischerweise ist dies Englisch:
+\begin{verbatim}
+Default EN
+\end{verbatim}
+Nach diesen beiden Definitionen folgt eine beliebige Menge von {\tt
+Message}-Statements, d.h. Definitionen von Meldungen:
+\begin{verbatim}
+Message ErrName
+ ": Fehler "
+ ": error "
+\end{verbatim}
+Wurden {\em n} Sprachen im {\tt Langs}-Statement angek"undigt, so nimmt
+der Message-Compiler {\bf genau} die folgenden {\em n} Zeilen als die zu
+speichernden Strings. Es ist also nicht m"oglich, bei einzelnen
+Nachrichten bestimmte Sprachen fortzulassen, und eine auf die Strings
+folgende Leerzeile ist keinesfalls als Endemarkierung f"ur die Liste
+mi"szuverstehen; eingef"ugte Leerzeilen dienen einzig und allein der
+besseren Lesbarkeit. Was allerdings erlaubt ist, ist, einzelne Meldungen
+"uber mehrere Zeilen in der Quelldatei zu verteilen; alle Zeilen bis auf
+die letzte m"ussen dann mit einem Backslash als Fortsetzungszeichen enden:
+\begin{verbatim}
+Message TestMessage2
+ "Dies ist eine" \
+ "zweizeilige Nachricht"
+ "This is a" \
+ "two-line message"
+\end{verbatim}
+Wie bereits erw"ahnt, handelt es sich bei den Quelldateien um reine
+ASCII-Dateien; Sonderzeichen k"onnen in den Meldungstexten zwar
+eingetragen werden (und der Compiler wird sie auch so durchreichen), der
+gravierende Nachteil ist aber, da"s eine solche Datei nicht mehr voll
+portabel ist: Wird sie auf ein anderes System gebracht, das z.B. eine
+andere Kodierung f"ur Umlaute verwendet, bekommt der Anwender zur Laufzeit
+nur merkw"urdige Zeichen zu sehen...Sonderzeichern sollten daher immer mit
+Hilfe von speziellen Sequenzen geschrieben werden, die von HTML bzw. SGML
+entlehnt wurden (siehe Tabelle \ref{TabSpecChars}). Zeilenvorsch"ube
+k"onnen in eine Zeile wie von C her gewohnt mit \verb!\n! eingebracht
+werden.
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+Sequenz... & ergibt... \\
+\hline
+\hline
+\verb!&auml; &ouml; &uuml;! & "a "o "u (Umlaute)\\
+\verb!&Auml; &Ouml; &Uuml;! & "A "O "U \\
+\verb!&szlig;! & "s (scharfes s) \\
+\verb!&agrave; &egrave; &igrave; &ograve; &ugrave;! & \'a \'e \'i \'o \'u (Accent \\
+\verb!&Agrave; &Egrave; &Igrave; &Ograve; &Ugrave;! & \'A \'E \'I \'O \'U grave) \\
+\verb!&aacute; &eacute; &iacute; &oacute; &uacute;! & \`a \`e \`i \`o \`u (Accent \\
+\verb!&Aacute; &Eacute; &Iacute; &Oacute; &Uacute;! & \`A \`E \`I \`O \`I agiu) \\
+\verb!&acirc; &ecirc; &icirc; &ocirc; &ucirc;! & \^a \^e \^i \^o \^u (Accent \\
+\verb!&Acirc; &Ecirc; &Icirc; &Ocirc; &Ucirc;! & \^A \^E \^I \^O \^U circonflex) \\
+\verb!&ccedil; &Ccedil;! & \c{c} \c{C}(Cedilla) \\
+\verb!&ntilde; &Ntilde;! & \~n \~N \\
+\verb!&aring; &Aring;! & \aa \AA \\
+\verb!&aelig; &Aelig;! & \ae \AE \\
+\verb!&iquest; &iexcl;! & umgedrehtes ! oder ? \\
+\hline
+\end{tabular}\end{center}
+\caption{Sonderzeichenschreibweise des {\em rescomp}\label{TabSpecChars}}
+\end{table*}
+
+%%---------------------------------------------------------------------------
+
+\section{Dokumentationserzeugung}
+
+In einer Quellcodedistribution von AS ist diese Dokumentation nur als
+LaTeX-Dokument enthalten. Andere Formate werden aus dieser mit Hilfe von
+mitgelieferten Werkzeugen automatisch erzeugt. Zum einen reduziert dies
+den Umfang einer Quellcodedistribution, zum anderen m"ussen "Anderungen
+nicht an allen Formatversionen eines Dokumentes parallel vorgenommen
+werden, mit all den Gefahren von Inkonsistenzen.
+
+Als Quellformat wurde LaTeX verwendet, weil...weil...weil es eben schon
+immer vorhanden war. Zudem ist TeX fast beliebig portierbar und pa"st
+damit recht gut zum Anspruch von AS. Eine Standard-Distribution erlaubt
+damit eine 'ordentliche' Ausgabe auf so ziemlich jedem Drucker; f"ur eine
+Konvertierung in die fr"uher immer vorhandene ASCII-Version liegt der
+Konverter {\em tex2doc} bei; zus"atzlich einen Konverter {\em tex2html},
+so da"s man die Anleitung direkt ins Internet stellen kann.
+
+Die Erzeugung der Dokumentation wird mit einem schlichten
+\begin{verbatim}
+make docs
+\end{verbatim}
+angesto"sen; daraufhin werden die beiden erw"ahnten Hilfstools erzeugt,
+auf die TeX-Dokumentation angewandt und schlu"sendlich wird noch LaTeX
+selber aufgerufen. Dies nat"urlich f"ur alle Sprachen nacheinander...
+
+%%---------------------------------------------------------------------------
+
+\section{Testsuite}
+
+Da AS mit bin"aren Daten von genau vorgegebener Struktur umgeht, ist er
+naturgem"a"s etwas empfindlich f"ur System- und Compilerabh"angigkeiten.
+Um wenigstens eine gewisse Sicherheit zu geben, da"s alles korrekt
+durchgelaufen ist, liegt dem Assembler im Unterverzeichnis {\tt tests}
+eine Menge von Test-Assemblerquellen bei, mit denen man den frisch
+gebauten Assembler testen kann. Diese Testprogramme sind in erster Linie
+darauf getrimmt, Fehler in der Umsetzung des Maschinenbefehlssatzes zu
+finden, die besonders gern bei variierenden Wortl"angen auftreten.
+Maschinenunabh"angige Features wie der Makroprozessor oder bedingte
+Assemblierung werden eher beil"aufig getestet, weil ich davon ausgehe,
+da"s sie "uberall funktionieren, wenn sie bei mir funktionieren...
+
+Der Testlauf wird mit einem einfachen {\em make test} angesto"sen. Jedes
+Testprogramm wird assembliert, in eine Bin"ardatei gewandelt und mit einem
+Referenz-Image verglichen. Ein Test gilt als bestanden, wenn Referenz und
+die neu erzeugte Datei Bit f"ur Bit identisch sind. Am Ende wird
+summarisch die Assemblierungszeit f"ur jeden Test ausgegeben (wer will,
+kann mit diesen Ergebnissen die Datei {\tt BENCHES} erg"anzen), zusammen
+mit dem Erfolg oder Mi"serfolg. Jedem Fehler ist auf den Grund zu gehen,
+selbst wenn er bei einem Zielprozessor auftritt, den Sie nie nutzen
+werden! Es ist immer m"oglich, da"s dies auf einen Fehler hinweist, der
+auch bei anderen Zielprozessoren auftritt, nur zuf"allig nicht in den
+Testf"allen.
+
+%%---------------------------------------------------------------------------
+
+\section{Einh"angen eines neuen Zielprozessors}
+
+Der mit Abstand h"aufigste Grund, im Quellcode von AS etwas zu ver"andern,
+d"urfte wohl die Erweiterung um einen neuen Zielprozessor sein. Neben der
+Erg"anzung der Makefiles um das neue Modul ist lediglich eine Modifikation
+der Quellen an wenigen Stellen erforderlich, den Rest erledigt das neue
+Modul, indem es sich in der Liste der Codegeneratoren registriert. Im
+folgenden will ich kochbuchartig die zum Einh"angen erforderlichen
+Schritte beschreiben:
+
+\subsubsection{Festlegung des Prozessornamens}
+
+Der f"ur den Prozessor zu w"ahlende Name mu"s zwei Kriterien erf"ullen:
+\begin{enumerate}
+\item{Der Name darf noch nicht von einem anderen Prozessor belegt sein.
+ Beim Aufruf von AS ohne Parameter erh"alt man eine Liste der bereits
+ vorhandenen Namen.}
+\item{Soll der Prozessorname vollst"andig in der Variablen \tty{MOMCPU}
+ auftauchen, so darf er au"ser am Anfang keine Buchstaben au"serhalb
+ des Bereiches von A..F enthalten. In der Variablen \tty{MOMCPUNAME}
+ liegt aber zur Assemblierzeit immer der volle Name vor.
+ Sonderzeichen sind generell nicht erlaubt, Kleinbuchstaben
+ werden vom CPU-Befehl bei der Eingabe in Gro"sbuchtaben umgewandelt
+ und sind daher auch nicht im Prozessornamen sinnvoll.}
+\end{enumerate}
+
+Der erste Schritt der Registrierung ist die Eintragung des Prozessors oder
+der Prozessorfamilie in der Datei {\tt headids.c}. Wie bereits erw"ahnt,
+wird diese Datei von den Hilfsprogrammen mitbenutzt und spezifiziert die
+einer Prozessorfamilie zugeordnete Kenn-ID in Codedateien sowie das zu
+verwendende Hex-Format. Bei der Wahl der Kenn-ID w"urde ich mir etwas
+Absprache w"unschen...
+
+\subsubsection{Definition des Codegeneratormoduls}
+
+Das Modul, das f"ur den neuen Prozessor zust"andig sein soll, sollte einer
+gewissen Einheitlichkeit wegen den Namen \tty{code....} tragen, wobei
+\tty{.....} etwas mit dem Prozessornamen zu tun haben sollte. Den Kopf
+mit den Includes "ubernimmt man am besten direkt aus einem bereits
+vorhandenen Codegenerator.
+
+Mit Ausnahme einer Initialisierungsfunktion, die zu Anfang der {\tt
+main()}-Funktion im Modul {\tt as.c} aufgerufen werden mu"s, braucht das
+neue Modul keinerlei Funktionen oder Variablen zu exportieren, da die
+ganze Kommunikation zur Laufzeit "uber indirekte Spr"unge abgewickelt
+wird. Die dazu erforderlichen Registrierungen m"ussen in der
+Initialisierungsfunktion des Moduls vorgenommen werden, indem f"ur jeden
+von der Unit zu behandelnden Prozessortyp
+ein Aufruf der Funktion \tty{AddCPU} erfolgt:
+\begin{verbatim}
+ CPUxxxx = AddCPU("XXXX", SwitchTo_xxxx);
+\end{verbatim}
+\tty{'XXXX'} ist dabei der f"ur den Prozessor festgelegte Name, der sp"ater
+im Assemblerprogramm verwendet werden mu"s, um AS auf diesen Zielprozessor
+umzuschalten. \tty{SwitchTo\_xxxx} (im folgenden kurz als ,,Umschalter''
+bezeichnet) ist eine parameterlose Prozedur, die von AS aufgerufen wird,
+sobald auf diesen Prozessor umgeschaltet werden soll. Als Ergebnis liefert
+\tty{AddCPU} eine Zahlenwert, der als interne ,,Kennung'' f"ur diesen Prozessor
+fungiert. In der globalen Variablen \tty{MomCPU} wird st"andig die Kennung
+des momentan gesetzten Zielprozessors mitgef"uhrt. Der von \tty{AddCPU}
+gelieferte Wert sollte in einer privaten Variable des Typs \tty{CPUVar} (hier
+\tty{CPUxxxx} genannt) abgelegt werden. Falls ein Codegeneratormodul
+verschiedene Prozessoren (z.B. einer Familie) verwaltet, kann es so
+durch Vergleich von \tty{MomCPU} gegen diese Werte feststellen, welche
+Befehlsuntermenge momentan zugelassen ist.
+\par
+Dem Umschalter obliegt es, AS auf den neuen Zielprozessor ,,umzupolen''.
+Dazu m"ussen im Umschalter einige globale Variablen besetzt werden:
+\begin{itemize}
+\item{\tty{ValidSegs} : Nicht alle Prozessoren definieren alle von AS
+ unterst"utzten Adre"sr"aume. Mit dieser Menge legt man fest,
+ welche Untermenge f"ur den jeweiligen Prozessor von \tty{SEGMENT}-Befehl
+ zugelassen wird. Im mindesten mu"s das Code-Segment freigeschaltet
+ werden. Die Gesamtmenge aller vorhandenen Segmenttypen kann in der
+ Datei \tty{fileformat.h} nachgelesen werden (\tty{Seg}.....-Konstanten).}
+\item{\tty{SegInits} : Dieses Feld speichert die initialen (ohne \tty{ORG}-Befehl)
+ Startadressen in den einzelnen Segmenten. Nur in Ausnahmef"allen
+ (physikalisch "uberlappende, aber logisch getrennte Adre"sr"aume)
+ sind hier andere Werte als 0 sinnvoll.}
+\item{\tty{Grans} : Hiermit kann f"ur jedes Segment die Gr"o"se des kleinsten
+ adressierbaren Elements in Bytes festgelegt werden, d.h. die
+ Gr"o"se des Elements, f"ur das eine Adresse um eins erh"oht wird.
+ Bei den allermeisten Prozessoren (auch 16 oder 32 Bit) ist dies
+ ein Byte, nur z.B. Signalprozessoren und die PICs fallen aus dem
+ Rahmen.}
+\item{\tty{ListGrans} : Hiermit kann wieder f"ur alle Segmente getrennt
+ festgelegt werden, in was f"ur Gruppen die Bytes im Assemblerlisting
+ dargestellt werden sollen. Beim 68000 sind z.B. Befehle immer
+ ein mehrfaches von 2 Bytes lang, weshalb die entsprechende Variable
+ auf 2 gesetzt ist.}
+\item{\tty{SegLimits} : Dieses Feld legt die h"ochste Adresse f"ur jedes
+ Segment fest, z.B. 65535 f"ur einen 16-Bit-Adre"sraum. Dieses Feld
+ braucht nicht ausgef"ullt zu werden, wenn der Codegenerator die {\tt
+ ChkPC}-Methode selber "ubernimmt.}
+\item{\tty{ConstMode} : Diese Variable kann die Werte \tty{ConstModeIntel},
+ \tty{ConstModeMoto} oder \tty{ConstModeC} haben und bestimmt, in
+ welcher Form Zahlensysteme bei Integerkonstanten spezifiziert werden
+ sollen (sofern das Programm nicht vom Relaxed-Modus Gebrauch macht).}
+\item{\tty{PCSymbol} : Diese Variable enth"alt den String, mit dem aus dem
+ Assembler-Programm heraus der momentane Stand des Programmz"ahlers
+ abgefragt werden kann. F"ur Intel-Prozessoren ist dies z.B. ein
+ Dollarzeichen.}
+\item{\tty{TurnWords} : Falls der Prozessor ein Big-Endian-Prozessor sein
+ sollte und eines der Elemente von \tty{ListGrans} ungleich eins ist,
+ sollte dieses Flag auf True gesetzt werden, um korrekte Code-Dateien
+ zu erhalten.}
+\item{\tty{SetIsOccupied} : Einige Prozessoren verwenden \tty{SET} als
+ Maschinenbefehl. Ist diese Variable gesetzt, so gibt AS \tty{SET}
+ -Befehle an den Codegenerator weiter und verwendet stattdessen
+ \tty{EVAL}.}
+\item{\tty{HeaderID} : Dieses Byte enth"alt die Kennung, mit der in der Codedatei
+ die Prozessorfamilie gekennzeichnet wird (siehe Abschnitt
+ \ref{SectCodeFormat}). Um Zweideutigkeiten zu vermeiden,
+ bitte ich, den Wert mit mir abzusprechen. Bis auf weiteres sollten
+ keine Werte au"serhalb des Bereiches \$01..\$7f benutzt werden,
+ diese sind f"ur Sonderzwecke (wie z.B. eine zuk"unftige Erweiterung
+ um einen Linker) reserviert. Auch wenn dieser Wert in den meisten
+ "alteren Codegeneratoren hart gesetzt wird, ist es die heute
+ bevorzugte Methode, den Wert aus {\tt headids.h} per {\tt
+ FindFamilyByName} zu holen.}
+\item{\tty{NOPCode} : In bestimmten Situationen kann es sein, da"s AS unbenutzte
+ Bereiche im Code mit NOPs auff"ullen mu"s. Diese Variable beinhaltet
+ den dazu erforderlichen Code.}
+\item{\tty{DivideChars} : Dieser String enth"alt all jene Zeichen, die als
+ Trennzeichen f"ur die Parameter eines Assemblerbefehls zugelassen
+ sind. Nur f"ur extreme Ausrei"ser (wie den DSP56) sollte sich in
+ diesem String etwas anderes finden als ein Komma.}
+\item{\tty{HasAttrs} : Einige Prozessoren wie die 68k-Reihe teilen einen
+ Maschinenbefehl durch einen Punkt noch weiter in Mnemonic und
+ Attribut auf. Ist dies beim neuen Prozessor auch der Fall, so
+ ist dieses Flag auf True zu setzen. AS liefert dann die Einzelteile
+ in den Variablen \tty{OpPart} und \tty{AttrPart}. Setzt man es
+ dagegen auf False, so bleibt der Befehl in \tty{OpPart} zusammen,
+ und \tty{AttrPart} ist immer leer. Sofern der Prozessor keine
+ Attribute verwendet, sollte man \tty{HasAttrs} auf jeden Fall auf False
+ setzen, da man sich sonst die M"oglichkeit nimmt, Makros mit einem
+ Punkt im Namen (z.B. zur Emulation anderer Assembler) zu definieren.}
+\item{\tty{AttrChars} : Falls \tty{HasAttrs} gesetzt wurde, m"ussen in diesem
+ String alle Zeichen eingetragen werden, die das Attribut vom Befehl
+ trennen k"onnen. Meist ist dies nur der Punkt.}
+\end{itemize}
+Gehen Sie nicht davon aus, da"s eine dieser Variablen einen vordefinierten
+Wert hat, sondern besetzen Sie \bb{ALLE} Felder neu!!
+
+Neben diesen Variablen m"ussen noch einige Funktionszeiger besetzt wird,
+mit denen der Codegenerator sich in AS einbindet:
+\begin{itemize}
+\item{\tty{MakeCode} : Diese Routine wird nach der Zerlegung einer Zeile
+ in Mnemonic und Parameter aufgerufen. Das Mnemonic liegt in der
+ Variablen \tty{OpPart}, die Parameter in dem Feld \tty{ArgStr}.
+ Die Zahl der Parameter kann aus der Variablen \tty{ArgCnt} ausgelesen
+ werden. Das bin"are Ergebnis mu"s in dem Byte-Feld \tty{BAsmCode}
+ abgelegt werden, dessen L"ange in der Variablen \tty{CodeLen}. Falls
+ der Prozessor wortorientiert wie der 68000 oder viele Signalprozessoren
+ ist, kann Feld auch wortweise als \tty{WAsmCode} adressiert werden.
+ F"ur ganz extreme F"alle gibt es auch noch \tty{DAsmCode}... Die
+ Codel"ange wird ebenfalls in solchen Einheiten angegeben.}
+\item{\tty{SwitchFrom}: Diese parameterlose Prozedur erlaubt dem
+ Codegeneratormodul, noch ,,Aufr"aumarbeiten'' durchzuf"uhren,
+ wenn auf einen anderen Zielprozessor umgeschaltet wird. So
+ kann man an dieser Stelle z.B. Speicher freigeben, der im
+ Umschalter belegt wurde und nur ben"otigt wird, w"ahrend dieses
+ Codegeneratormodul aktiv ist. Im einfachsten Fall zeigt diese
+ Prozedurvariable auf eine leere Prozedur. Ein Beispiel f"ur die
+ Anwendung dieser Prozedur finden Sie im Modul \tty{CODE370}, das
+ seine Codetabellen dynamisch erzeugt und wieder freigibt.}
+\item{\tty{IsDef} : Bestimmte Prozessoren kennen neben \tty{EQU} noch weitere
+ Pseudobefehle, bei denen ein in der ersten Spalte stehender
+ Symbolname kein Label darstellt, z.B. \tty{BIT} beim 8051. Diese
+ Funktion mu"s TRUE zur"uckliefern, falls ein solcher, zus"atzlicher
+ Befehl vorliegt. Im einfachsten Fall braucht nur FALSE
+ zur"uckgeliefert zu werden.}
+\end{itemize}
+
+Optional kann ein Codegenerator auch noch folgende weitere Funktionszeiger
+besetzen:
+\begin{itemize}
+\item{\tty{ChkPC} : Obwohl AS die Programmz"ahler intern durchg"angig mit
+ 32 oder 64 Bit verwaltet, benutzen die meisten Prozessoren nur einen
+ kleineren Adre"sraum. Diese Funktion liefert AS Informationen, ob
+ der momentane Programmz"ahler den erlaubten Bereich "uberschritten
+ hat. Bei Prozessoren mit mehreren Adre"sr"aumen kann diese Routine
+ nat"urlich deutlich komplizierter ausfallen. Ein Beispiel daf"ur
+ findet sich z.B. im Modul \tty{code16c8x.c}. Falls alles in Ordnung ist,
+ mu"s die Funktion TRUE zur"uckliefern, ansonsten FALSE.
+ Diese Funktion mu"s ein Codegenerator nur implementieren, wenn er
+ das Feld {\tt SegLimits} nicht belegt. Das kann z.B. notwendig
+ werden, wenn der g"ultige Adre"sbereich eines Segments nicht
+ zusammenh"angend ist.}
+\item{\tty{InternSymbol} : Manche Prozessoren, z.B. solche mit einer
+ Registerbank im internen RAM, defineren diese 'Register' als Symbole
+ vor, und es w"urde wenig Sinn machen, diese in einer separaten
+ Include-Datei mit 256 oder m"oglicherweise noch mehr {\tt EQU}s
+ zu definieren. Mit dieser Funktion erh"alt man Zugang zum Formel-
+ Parser von AS: Sie erh"alt den Ausdruck als ASCII-String, und wenn
+ sie eines der 'eingebauten Symbole' erkennt, besetzt sie die
+ "ubergebene Struktur des Typs {\em TempResult} entsprechend. Falls
+ die "Uberpr"ufung nicht erfolgreich war, mu"s deren Element {\tt
+ Typ} auf {\tt TempNone} gesetzt werden. Die Routine sollte im
+ Falle eines Mi"serfolges {\em keine} Fehlermeldungen ausgeben, weil
+ dies immer noch anderweitig g"ultige Symbole sein k"onnen. Seien
+ Sie extrem vorsichtig mit dieser Routine, da sie einen Eingriff in
+ den Parser darstellt!}
+\end{itemize}
+
+Wer will, kann sich "ubrigens auch mit einem Copyright-Eintrag verewigen,
+indem er in der Initialisierung des Moduls (bei den \tty{AddCPU}-Befehlen)
+einen Aufruf der Prozedur \tty{AddCopyright} einf"ugt, in der folgenden
+Art:
+\begin{verbatim}
+ AddCopyright("Intel 80986-Codegenerator (C) 2010 Hubert Simpel");
+\end{verbatim}
+Der "ubergebene String wird dann nach dem Programmstart zus"atzlich zu
+der Standardmeldung ausgegeben.
+
+Bei Bedarf kann sich das Modul im Initialisierungsteil noch in die
+Kette aller Funktionen eintragen, die vor Beginn eines Durchlaufes
+durch den Quelltext ausgef"uhrt werden. Dies ist z.B. immer dann der
+Fall, wenn die Code-Erzeugung im Modul abh"angig vom Stand bestimmter,
+durch Pseudobefehle beeinflu"sbarer Flags ist. Ein h"aufig auftretender
+Fall ist z.B., da"s ein Prozessor im User- oder Supervisor-Modus
+arbeiten kann, wobei im User-Modus bestimmte Befehle gesperrt
+sind. Im Assembler-Quelltext k"onnte dieses Flag, das angibt, in welchem
+Modus der folgende Code ausgef"uhrt wird, durch einen Pseudobefehl
+umgeschaltet werden. Es ist aber dann immer noch eine Initialisierung
+erforderlich, die sicherstellt, da"s in allen Durchl"aufen ein identischer
+Ausgangszustand vorliegt. Der "uber den Funktionszeiger \tty{InitPassProc}
+angebotene Haken bietet die M"oglichkeit, derartige Initialisierungen
+vorzunehmen. Das verwendete Prinzip "ahnelt dabei dem Einh"angen in
+einen Interruptvektor: In der Initialisierung der Unit wird der alte Wert
+von \tty{InitPassProc} gesichert. Danach kann \tty{InitPassProc} auf
+die hinzuzuf"ugende Funktion (parameterlos, kein R"uckgabewert) umgebogen
+werden. Die neue Routine ruft dann zuerst die alte Initialisierungsroutine
+auf und f"uhrt danach ihre eigenen Operationen durch.
+
+Analog zu \tty{InitPassProc} funktioniert die "uber \tty{CleanUpProc}
+aufgebaute Funktionskette, die es den Codegeneratoren erlaubt, nach dem
+Abschlu"s der Assemblierung noch Aufr"aumarbeiten (z.B. das Freigeben von
+Literaltabellen o."a.) durchzuf"uhren. Dies ist sinnvoll, wenn mehrere
+Dateien mit einem Aufruf assembliert werden, sonst h"atte man noch
+,,M"ull'' aus einem vorigen Lauf in den Tabellen. Momentan nutzt kein
+Modul diese M"oglichkeit.
+
+\subsubsection{Schreiben des Codegenerators selber}
+
+Nach diesen Pr"aliminarien ist nun endlich eigene Kreativit"at gefragt:
+Wie Sie es schaffen, aus dem Mnemonic und den Argumenten die Code-Bytes zu
+erzeugen, ist weitgehend Ihnen "uberlassen. Zur Verf"ugung stehen daf"ur
+nat"urlich "uber den Formelparser die Symboltabellen sowie die Routinen
+aus
+\tty{asmsub.c} und \tty{asmpars.c}. Ich kann hier nur einige generelle
+Hinweise geben:
+\begin{itemize}
+\item{Versuchen Sie, die Prozessorbefehle in Gruppen aufzusplitten, die
+ gleiche Operanden erwarten und sich nur in einigen Kennbits
+ unterscheiden. Alle argumentlosen Befehle kann man z.B. so in einer
+ Tabelle abhandeln.}
+\item{Die meisten Prozessoren haben ein festes Repertoire von
+ Adressierungsarten. Verlagern Sie das Parsing eines Adre"sausdrucks
+ in eine getrennte Unterroutine.}
+\item{Die Routine \tty{WrError} definiert eine Vielzahl von m"oglichen
+ Fehlermeldungen und ist bei Bedarf leicht erweiterbar. Nutzen Sie
+ das! Bei allen Fehler nur lapidar einen ,,Syntaxfehler'' zu melden,
+ n"utzt niemandem!}
+\end{itemize}
+Mit Sicherheit wird auch das Studium der vorhandenen Module weiterhelfen.
+
+\subsubsection{"Anderungen f"ur die Dienstprogramme}
+
+Eine winzige "Anderung ist auch noch an den Quellen der Dienstprogramme
+n"otig, und zwar in der Routine {\tt Granularity()} in {\tt toolutils.c}:
+Falls eines der Adre"sr"aume dieses Prozessors eine andere Granularit"at
+als 1 hat, mu"s dort die Abfrage passend erg"anzt werden, sonst verz"ahlen
+sich PLIST, P2BIN und P2HEX...
+
+%%---------------------------------------------------------------------------
+
+\section{Lokalisierung auf eine neue Sprache}
+
+Sie haben Interesse an diesem Thema? Wunderbar! Das ist eine Sache, die
+von Programmierern gerne au"sen vor gelassen wird, insbesondere, wenn sie
+aus dem Land der unbegrenzten M"oglichkeiten kommen...
+
+Die Lokalisierung auf eine neue Sprache gliedert sich in zwei Teile: Die
+Anpassung der Programmmeldungen sowie die "Ubersetzung der Anleitung.
+Letzteres ist sicherlich eine Aufgabe herkulischen Ausma"ses, aber die
+Anpassung der Programmeldungen solle in ein bis zwei Nachmittagen "uber
+die B"uhne zu bekommen sein, wenn man sowohl die neue als auch eine der
+bisher vorhandenen Sprachen gut kennt. Leider ist die "Ubersetzung auch
+nichts, was man St"uck f"ur St"uck machen kann, denn der
+Ressourcencompiler kann im Moment nicht mit einer variablen Zahl von
+Sprachen in den verschiedenen Meldungen umgehen, es hei"st also 'alles
+oder nichts'.
+
+Als erstes erg"anzt man in {\tt header.res} die neue Sprache. Die f"ur
+die Sprache passende zweibuchstabige Abk"urzung holt man sich vom
+n"achsten Unix-System (wenn man nicht ohnehin darauf arbeitet...), die
+internationale Vorwahl aus dem n"achsten DOS-Handbuch.
+
+Im zweiten Schritt geht man jetzt durch alle anderen {\tt .res}-Dateien
+und erg"anzt die {\tt Message}-Statements. Nocheinmal sei darauf
+hingewiesen, Sonderzeichen in der HTML-artigen Schreibweise und nicht
+direkt einzusetzen!
+
+Wenn dies geschafft ist, kann man mit einem {\em make} alle betroffenen
+Teile neu bauen und erh"alt danach einen Assembler, der eine Sprache mehr
+schickt. Bitte nicht vergessen, die Ergebnisse an mich weiterzuleiten,
+damit mit der n"achsten Release alle etwas davon haben :-)
+
+%%===========================================================================
+
+\cleardoublepage
+
+\begin{thebibliography}{99}
+
+\bibitem{Williams} Steve Williams: \\
+ {\em 68030 Assembly Language Reference. \/} \\
+ Addison-Wesley, Reading, Massachusetts, 1989
+
+\bibitem{AMD29K} Advanced Micro Devices: \\
+ {\em AM29240, AM29245, and AM29243 RISC Microcontrollers. \/} \\
+ 1993
+
+\bibitem{AtAVR} Atmel Corp.: \\
+ {\em AVR Enhanced RISC Microcontroller Data Book.\/} \\
+ May 1996
+
+\bibitem{AVRObj} Atmel Corp.: \\
+ {\em 8-Bit AVR Assembler and Simulator Object File
+ Formats (Preliminary).\/} \\
+ (Teil der AVR-Tools-Dokumentation)
+
+\bibitem{CMD816} CMD Microcircuits: \\
+ {\em G65SC802 / G65SC816 CMOS 8/16-Bit
+ Microprocessor Family Data Sheet.\/}
+
+\bibitem{CPM68K} Digital Research : \\
+ {\em CP/M 68K Operating System User's Guide.\/} \\
+ 1983
+
+\bibitem{Cyrix} Cyrix Corp. : \\
+ {\em FasMath 83D87 User's Manual.\/} \\
+ 1990
+
+\bibitem{Dallas320} Dallas Semiconductor: \\
+ {\em DS80C320 High-Speed Micro User's Guide.\/} \\
+ Version 1.30, 1/94
+
+\bibitem{Fair1101} Fairchild Semiconductor: \\
+ {\em ACE1101 Data Sheet.\/} \\
+ Preliminary, May 1999
+
+\bibitem{Fair1202} Fairchild Semiconductor: \\
+ {\em ACE1202 Data Sheet.\/} \\
+ Preliminary, May 1999
+
+\bibitem{Fair8004} Fairchild Semiconductor: \\
+ {\em ACEx Guide to Developer Tools.\/}
+ AN-8004, Version 1.3 September 1998
+
+\bibitem{FujitsuCD} Fujitsu Limited: \\
+ {\em June 1998 Semiconductor Data Book.\/} \\
+ CD00-00981-1E
+
+\bibitem{Hit180} Hitachi Ltd. : \\
+ {\em 8-/16-Bit Microprocessor Data Book.\/} \\
+ 1986
+
+\bibitem{Hit63} Trevor J.Terrel \& Robert J. Simpson : \\
+ {\em Understanding HD6301X/03X CMOS Microprocessor Systems. \/} \\
+ erschienen bei Hitachi
+
+\bibitem{HitH8_3} Hitachi Microcomputer: \\
+ {\em H8/300H Series Programming Manual.\/} \\
+ (21-032, keine Jahresangabe)
+
+\bibitem{SH7000} Hitachi Semiconductor Design \& Development Center: \\
+ {\em SH Microcomputer Hardware Manual (Preliminary).\/}
+
+\bibitem{SH7700} Hitachi Semiconductor and IC Div.: \\
+ {\em SH7700 Series Programming Manual.\/} \\
+ 1st Edition, September 1995
+
+\bibitem{HitH8_5} Hitachi Semiconductor and IC Div.: \\
+ {\em H8/500 Series Programming Manual.} \\
+ (21-20, 1st Edition Feb. 1989)
+
+\bibitem{HitH8_532} Hitachi Ltd.: \\
+ {\em H8/532 Hardware Manual.} \\
+ (21-30, keine Jahresangabe)
+
+\bibitem{HitH8_534} Hitachi Ltd.: \\
+ {\em H8/534, H8/536 Hardware Manual.} \\
+ (21-19A, keine Jahresangabe)
+
+\bibitem{PPC403} IBM Corp.: \\
+ {\em PPC403GA Embedded Controller User's Manual.\/} \\
+ First Edition, September 1994
+
+\bibitem{IntEmb} Intel Corp. : {\em Embedded Controller Handbook.\/} \\
+ 1987
+
+\bibitem{IntMic} Intel Corp. : \\
+ {\em Microprocessor and Peripheral Handbook.\/} \\
+ Volume I Microprocessor, 1988
+
+\bibitem{Int960} Intel Corp. : \\
+ {\em 80960SA/SB Reference Manual.\/} \\
+ 1991
+
+\bibitem{Int196} Intel Corp.: \\
+ {\em 8XC196NT Microcontroller User's Manual.\/} \\
+ June 1995
+
+\bibitem{Int251} Intel Corp.: \\
+ {\em 8XC251SB High Performance CHMOS Single-Chip
+ Microcontroller.\/} \\
+ Sept. 1995, Order Number 272616-003
+
+\bibitem{Int296} Intel Corp.: \\
+ {\em 80296SA Microcontroller User's Manual.\/} \\
+ Sept. 1996
+
+\bibitem{Kaku} Hirotsugu Kakugawa: \\
+ {\em A memo on the secret features of 6309.} \\
+ (erh"altlich "uber WWW: \\
+ http://www.cs.umd.edu/users/fms/comp/CPUs/6309.txt)
+
+\bibitem{MicroChip} Microchip Technology Inc.: \\
+ {\em Microchip Data Book.\/} \\
+ 1993 Edition
+
+\bibitem{Mit41} Mitsubishi Electric: \\
+ {\em Single-Chip 8-Bit Microcomputers\/} \\
+ Vol.2, 1987
+
+\bibitem{Mit16} Mitsubishi Electric: \\
+ {\em Single-Chip 16-Bit Microcomputers.\/} \\
+ Enlarged edition, 1991
+
+\bibitem{Mit8} Mitsubishi Electric: \\
+ {\em Single-Chip 8 Bit Microcomputers.\/} \\
+ Vol.2, 1992
+
+\bibitem{Mit4500} Mitsubishi Electric: \\
+ {\em M34550Mx-XXXFP Users's Manual.\/} \\
+ Jan. 1994
+
+\bibitem{MitM16} Mitsubishi Electric: \\
+ {\em M16 Family Software Manual.\/} \\
+ First Edition, Sept. 1994
+
+\bibitem{MitM16C} Mitsubishi Electric: \\
+ {\em M16C Software Manual.\/} \\
+ First Edition, Rev. C, 1996
+
+\bibitem{Mit30600} Mitsubishi Electric: \\
+ {\em M30600-XXXFP Data Sheet.\/} \\
+ First Edition, April 1996
+
+\bibitem{GreenM16} Dokumentation zum M16/M32-Entwicklungspaket
+ von Green Hills Software
+
+\bibitem{MotMic} Motorola Inc. : \\
+ {\em Microprocessor, Microcontroller
+ and Peripheral Data. \/} \\
+ Vol. I+II, 1988
+
+\bibitem{Mot81} Motorola Inc. : \\
+ {\em MC68881/882 Floating Point Coprocessor
+ User's Manual. \/} \\
+ Prentice-Hall, Englewood Cliffs, Second Edition 1989
+
+\bibitem{Mot51} Motorola Inc. : \\
+ {\em MC68851 Paged Memory Management Unit
+ User's Manual. \/} \\
+ Prentice-Hall, Englewood Cliffs, Second Edition 1989
+
+\bibitem{Mot32} Motorola Inc.: \\
+ {\em CPU32 Reference Manual.\/} \\
+ Rev. 1, 1990
+
+\bibitem{Mot56} Motorola Inc.: \\
+ {\em DSP56000/DSP56001 Digital Signal Processor User's Manual.\/} \\
+ Rev. 2, 1990
+
+\bibitem{Mot340} Motorola Inc.: \\
+ {\em MC68340 Technical Summary.\/} \\
+ Rev. 2, 1991
+
+\bibitem{Mot16} Motorola Inc.: \\
+ {\em CPU16 Reference Manual.\/} \\
+ Rev. 1, 1991
+
+\bibitem{Mot68K} Motorola Inc.: \\
+ {\em Motorola M68000 Family Programmer's
+ Reference Manual.\/} \\
+ 1992
+
+\bibitem{Mot332} Motorola Inc.: \\
+ {\em MC68332 Technical Summary.\/} \\
+ Rev. 2, 1993
+
+\bibitem{Mot601} Motorola Inc.: \\
+ {\em PowerPC 601 RISC Microprocessor User's Manual.\/} \\
+ 1993
+
+\bibitem{Mot505} Motorola Inc.: \\
+ {\em PowerPC(tm) MPC505 RISC Microcontroller Technical
+ Summary.\/} \\
+ 1994
+
+\bibitem{Mot12} Motorola Inc.: \\
+ {\em CPU12 Reference Manual.\/} \\
+ 1st. edition, 1996
+
+\bibitem{Mot08} Motorola Inc.: \\
+ {\em CPU08 Reference Manual.\/} \\
+ Rev. 1 (keine Jahresangabe im PDF-File)
+
+\bibitem{Mot360} Motorola Inc.: \\
+ {\em MC68360 User's Manual.\/}
+
+\bibitem{MotCold} Motorola Inc.: \\
+ {\em MCF 5200 ColdFire Family Programmer's Reference
+ Manual.\/} \\
+ 1995
+
+\bibitem{MotMCore} Motorola Inc.: \\
+ {\em M*Core Programmer's Reference Manual.\/} \\
+ 1997
+
+\bibitem{Mot56300} Motorola Inc.: \\
+ {\em DSP56300 24-Bit Digital Signal Processor
+ Family Manual.\/} \\
+ Rev. 0 (keine Jahresangabe im PDF-File)
+
+\bibitem{SCMP} National Semiconductor: \\
+ {\em SC/MP Programmier- und Assembler-Handbuch.\/} \\
+ Publication Number 4200094A, Aug. 1976
+
+\bibitem{AsmCop} National Semiconductor: \\
+ {\em COP800 Assembler/Linker/Librarian User's Manual.\/} \\
+ Customer Order Number COP8-ASMLNK-MAN,
+ NSC Publication Number 424421632-001B,
+ August 1993
+
+\bibitem{Cop87L84} National Semiconductor: \\
+ {\em COP87L84BC microCMOS One-Time-Programmable (OTP)
+ Microcontroller.} \\
+ Preliminary, March 1996
+
+\bibitem{Nat14xxx} National Semiconductor: \\
+ {\em SC14xxx DIP commands Reference guide.} \\
+ Application Note AN-D-031, Version 0.4, 28.12.1998
+
+\bibitem{NECV} NEC Corp.: \\
+ {\em $\mu$pD70108 / $\mu$pD70116 / $\mu$pD70208 /
+ $\mu$pD70216 / $\mu$pD72091 Data Book.\/} \\
+ (keine Jahresangabe)
+
+\bibitem{NEC78} NEC Electronics Europe GmbH: \\
+ {\em User's Manual $\mu$COM-87
+ AD Family.\/} \\
+ (keine Jahresangabe)
+
+\bibitem{NEC75} NEC Corp.: \\
+ {\em $\mu$COM-75x Family 4-bit CMOS Microcomputer User's
+ Manual.\/} \\
+ Vol. I+II (keine Jahresangabe)
+
+\bibitem{NECSig} NEC Corp.: \\
+ {\em Digital Signal Processor Product Description.\/} \\
+ PDDSP.....067V20 (keine Jahresangabe)
+
+\bibitem{NEC78K0} NEC Corp.: \\
+ {\em $\mu$PD78070A, 78070AY 8-Bit Single-Chip Microcontroller
+ User's Manual.\/} \\
+ Document No. U10200EJ1V0UM00 (1st edition), August 1995
+
+\bibitem{NEC7814} NEC Corp.: \\
+ {\em Data Sheet $\mu$PD78014.\/}
+
+\bibitem{PhilXA} Philips Semiconductor: \\
+ {\em 16-bit 80C51XA Microcontrollers (eXtended
+ Architecture).\/} \\
+ Data Handbook IC25, 1996
+
+\bibitem{SGS04} SGS-Thomson Microelectronics: \\
+ {\em 8 Bit MCU Families EF6801/04/05 Databook.\/} \\
+ 1st edition, 1989
+
+\bibitem{SGS62} SGS-Thomson Microelectronics: \\
+ {\em ST6210/ST6215/ST6220/ST6225 Databook.\/} \\
+ 1st edition, 1991
+
+\bibitem{ST7Man} SGS-Thomson Microelectronics: \\
+ {\em ST7 Family Programming Manual.\/} \\
+ June 1995
+
+\bibitem{SGS9} SGS-Thomson Microelectronics: \\
+ {\em ST9 Programming Manual.\/} \\
+ 3rd edition, 1993
+
+\bibitem{Siem166} Siemens AG: \\
+ {\em SAB80C166/83C166 User's Manual.\/} \\
+ Edition 6.90
+
+\bibitem{Siem167} Siemens AG: \\
+ {\em SAB C167 Preliminary User's Manual.\/} \\
+ Revision 1.0, July 1992
+
+\bibitem{Siem502} Siemens AG: \\
+ {\em SAB-C502 8-Bit Single-Chip Microcontroller User's
+ Manual.\/} \\
+ Edition 8.94
+
+\bibitem{Siem501} Siemens AG: \\
+ {\em SAB-C501 8-Bit Single-Chip Microcontroller User's
+ Manual.\/} \\
+ Edition 2.96
+
+\bibitem{Siem504} Siemens AG: \\
+ {\em C504 8-Bit CMOS Microcontroller User's Manual.\/} \\
+ Edition 5.96
+
+\bibitem{Syb68K} C.Vieillefond: \\
+ {\em Programmierung des 68000.\/} \\
+ Sybex-Verlag D"usseldorf, 1985
+
+\bibitem{Sym8xx} Symbios Logic Inc: \\
+ {\em Symbios Logic PCI-SCSI-I/O Processors Programming
+ Guide.\/} \\
+ Version 2.0, 1995/96
+
+\bibitem{Ti990} Texas Instruments: \\
+ {\em Model 990 Computer/TMS9900 Microprocessor
+ Assembly Language Programmer's Guide.\/} \\
+ 1977, Manual No. 943441-9701
+
+\bibitem{Ti9900} Texas Instruments: \\
+ {\em TMS9995 16-Bit Microcomputer
+ Preliminary Data Manual.\/} \\
+ 1981
+
+\bibitem{TiC10} Texas Instruments: \\
+ {\em First-Generation TMS320 User's
+ Guide.\/} \\
+ 1988, ISBN 2-86886-024-9
+
+\bibitem{Ti7000} Texas Instruments: \\
+ {\em TMS7000 family Data Manual.\/} \\
+ 1991, DB103
+
+\bibitem{TiC30} Texas Instruments: \\
+ {\em TMS320C3x User's Guide.\/} \\
+ Revision E, 1991
+
+\bibitem{TiC20} Texas Instruments: \\
+ {\em TMS320C2x User's Guide.\/} \\
+ Revision C, Jan. 1993
+
+\bibitem{Ti370} Texas Instruments: \\
+ {\em TMS370 Family Data Manual.\/} \\
+ 1994, SPNS014B
+
+\bibitem{Ti430FamSoft} Texas Instruments: \\
+ {\em MSP430 Family Software User's
+ Guide.\/} \\
+ 1994, SLAUE11
+
+\bibitem{Ti430Met} Texas Instruments: \\
+ {\em MSP430 Metering Application.\/} \\
+ 1996, SLAAE10A
+
+\bibitem{Ti430FamArch} Texas Instruments: \\
+ {\em MSP430 Family Architecture User's
+ Guide.\/} \\
+ 1995, SLAUE10A
+
+\bibitem{TiC60} Texas Instruments: \\
+ {\em TMS320C62xx CPU and Instruction Set Reference
+ Manual.\/} \\
+ Jan. 1997, SPRU189A
+
+\bibitem{TiC20x} Texas Instruments: \\
+ {\em TMS320C20x User's Guide.\/} \\
+ April 1999, SPRU127C
+
+\bibitem{Tosh90} Toshiba Corp.: \\
+ {\em 8-Bit Microcontroller TLCS-90
+ Development System Manual.\/} \\
+ 1990
+
+\bibitem{Tosh870} Toshiba Corp.: \\
+ {\em 8-Bit Microcontroller TLCS-870 Series Data Book.\/} \\
+ 1992
+
+\bibitem{Tosh900} Toshiba Corp.: \\
+ {\em 16-Bit Microcontroller TLCS-900 Series
+ Users Manual.\/} \\
+ 1992
+
+\bibitem{Tosh900L} Toshiba Corp.: \\
+ {\em 16-Bit Microcontroller TLCS-900 Series
+ Data Book: \\ TMP93CM40F/TMP93CM41F.\/} \\
+ 1993
+
+\bibitem{Tosh47} Toshiba Corp.: \\
+ {\em 4-Bit Microcontroller TLCS-47E/47/470/470A
+ Development System Manual.\/} \\
+ 1993
+
+\bibitem{Tosh9000} Toshiba Corp.: \\
+ {\em TLCS-9000/16 Instruction Set Manual Version 2.2.\/} \\
+ 10. Feb 1994
+
+\bibitem{Val8X} Valvo GmbH: \\
+ {\em Bipolare Mikroprozessoren und bipolare
+ LSI-Schaltungen.\/} \\
+ Datenbuch, 1985, ISBN 3-87095-186-9
+
+\bibitem{Zilog} Datenbl"atter der Firma Zilog zur Z80-Familie
+
+\bibitem{ZilZ8} Zilog Inc.: \\
+ {\em Z8 Microcontrollers Databook.\/} \\
+ 1992
+
+\bibitem{ZilZ8_2} Zilog Inc.: \\
+ {\em Discrete Z8 Microcontrollers Databook.} \\
+ (keine Jahresangabe)
+
+\bibitem{ZilZ380} Zilog Inc.: \\
+ {\em Z380 CPU Central Processing Unit User's Manual.\/} \\
+ (keine Jahresangabe)
+
+\end{thebibliography}
+
+\cleardoublepage
+
+\printindex
+
+\end{document}
+
diff --git a/doc_DE/dina4.sty b/doc_DE/dina4.sty
new file mode 100644
index 0000000..8056638
--- /dev/null
+++ b/doc_DE/dina4.sty
@@ -0,0 +1,135 @@
+%%
+%% This is file `a4.sty' generated
+%% on <1991/2/13> with the docstrip utility (v1.1k).
+%%
+%% The original source file was `a4.doc'.
+%%
+%%
+%% Copyright (C) 1990 by Johanes Braams. All rights reserved.
+%%
+%% IMPORTANT NOTICE:
+%%
+%% You are not allowed to change this file. You may however copy this file
+%% to a file with a different name and then change the copy.
+%%
+%% You are NOT ALLOWED to distribute this file alone. You are NOT ALLOWED
+%% to take money for the distribution or use of this file (or a changed
+%% version) except for a nominal charge for copying etc.
+%%
+%% You are allowed to distribute this file under the condition that it is
+%% distributed together with all files mentioned below.
+%%
+%% If you receive only some of these files from someone, complain!
+%%
+%% Error Reports in case of UNCHANGED versions to
+%%
+%% J. Braams
+%% PTT Research, dr Neher Laboratorium
+%% P.O. box 421
+%% 2260 AK Leidschendam
+%% The Netherlands
+%% Internet: <JL_Braams@pttrnl.nl>
+%%
+\def\fileversion{1.2a}
+\def\filedate{30 Nov 90}
+\def\docdate {26 Feb 90}
+%% \CheckSum{134}
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+\wlog{Style option `A4' \fileversion\space<\filedate> (NP and JLB)}
+\wlog{English documentation\space\space\space<\docdate> (JLB)}
+\topmargin 0pt
+\ifcase \@ptsize
+ \textheight 53\baselineskip
+\or
+ \textheight 46\baselineskip
+\or
+ \textheight 42\baselineskip
+\fi
+\advance\textheight by \topskip
+\ifcase \@ptsize
+ \textwidth 5.00in
+ \marginparwidth 1.00in
+ \if@twoside
+ \oddsidemargin 0.55in
+ \evensidemargin 0.75in
+ \else
+ \oddsidemargin 0.55in
+ \evensidemargin 0.55in
+ \fi
+\or
+ \textwidth 5.20in
+ \marginparwidth 1.00in
+ \if@twoside
+ \oddsidemargin 0.45in
+ \evensidemargin 0.65in
+ \else
+ \oddsidemargin 0.45in
+ \evensidemargin 0.45in
+ \fi
+\or
+ \textwidth 5.70in
+ \marginparwidth 0.80in
+ \if@twoside
+ \oddsidemargin 0.20in
+ \evensidemargin 0.40in
+ \else
+ \oddsidemargin 0.20in
+ \evensidemargin 0.20in
+ \fi
+\fi
+\def\WideMargins{%
+ \newdimen\ExtraWidth
+ \ifcase \@ptsize
+ \ExtraWidth = 0.5in
+ \@widemargins
+ \or
+ \ExtraWidth = 0.5in
+ \@widemargins
+ \or
+ \ExtraWidth = 0.7in
+ \@widemargins
+ \fi\let\WideMargins\relax\let\@widemargins\relax}
+{\def\do{\noexpand\do\noexpand}
+ \xdef\@preamblecmds{\@preamblecmds \do\WideMargins}
+}
+\def\@widemargins{%
+ \global\advance\textwidth by -\ExtraWidth
+ \global\advance\marginparwidth by \ExtraWidth
+ \if@twoside
+ \tw@sidedwidemargins
+ \else
+ \@nesidedwidemargins
+ \fi}
+\def\tw@sidedwidemargins{%
+ \if@reversemargin
+ \@tempdima=\evensidemargin
+ \advance\@tempdima by -\oddsidemargin
+ \advance\oddsidemargin by \ExtraWidth
+ \advance\oddsidemargin by \@tempdima
+ \advance\evensidemargin by -\@tempdima
+ \else
+ \advance\evensidemargin by \ExtraWidth
+ \fi}
+\def\@nesidedwidemargins{%
+ \if@reversemargin
+ \advance\oddsidemargin by \ExtraWidth
+ \advance\evensidemargin by \ExtraWidth
+ \fi}
+\endinput
+%%
+%% End of file `a4.sty'.
diff --git a/doc_DE/pscomm.tex b/doc_DE/pscomm.tex
new file mode 100644
index 0000000..e2b4c4b
--- /dev/null
+++ b/doc_DE/pscomm.tex
@@ -0,0 +1,16 @@
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+= \> := \> ALIGN \> BINCLUDE \> CASE \\
+CHARSET \> CPU \> DEPHASE \> ELSE \> ELSECASE \\
+ELSEIF \> END \> ENDCASE \> ENDIF \> ENDM \\
+ENDSECTION \> ENDSTRUCT \> ENUM \> ERROR \> EQU \\
+EXITM \> FATAL \> FORWARD \> FUNCTION \> GLOBAL \\
+IF \> IFB \> IFDEF \> IFEXIST \> IFNB \\
+IFNDEF \> IFNEXIST \> IFNUSED \> IFUSED \> INCLUDE \\
+IRP \> LABEL \> LISTING \> MACEXP \> MACRO \\
+MESSAGE \> NEWPAGE \> ORG \> PAGE \> PHASE \\
+POPV \> PUSHV \> PRTEXIT \> PRTINIT \> PUBLIC \\
+READ \> RELAXED \> REPT \> RESTORE \> SAVE \\
+SECTION \> SEGMENT \> SHARED \> STRUCT \> SWITCH \\
+TITLE \> WARNING \> WHILE \\
+\end{tabbing}}
diff --git a/doc_DE/pscpu.tex b/doc_DE/pscpu.tex
new file mode 100644
index 0000000..05bf628
--- /dev/null
+++ b/doc_DE/pscpu.tex
@@ -0,0 +1,420 @@
+\subsubsection{Motorola 680x0}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DC[.$<$size$>$]\> DS[.$<$size$>$] \> FULLPMMU \> FPU \> PADDING \\
+PMMU \> SUPMODE \\
+\end{tabbing}}
+
+\subsubsection{Motorola 56xxx}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DC \> DS \> XSFR \> YSFR \\
+\end{tabbing}}
+
+\subsubsection{PowerPC}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+BIGENDIAN \> DB \> DD \> DQ \> DS \\
+DT \> DW \> REG \> SUPMODE \\
+\end{tabbing}}
+
+\subsubsection{Motorola M-Core}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DC[.$<$size$>$] \> DS[.$<$size$>$] \> REG \> SUPMODE \\
+\end{tabbing}}
+
+\subsubsection{Motorola 68xx/Hitachi 6309}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ADR \> BYT \> DC[.$<$size$>$] \> DFS \> DS[.$<$size$>$] \\
+FCB \> FCC \> FDB \> PADDING \> RMB \\
+\end{tabbing}}
+
+\subsubsection{Motorola 6805/68HC08}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ADR \> BYT \> DFS \> FCB \> FCC \\
+FDB \> RMB \\
+\end{tabbing}}
+
+\subsubsection{Motorola 6809/Hitachi 6309}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ADR \> ASSUME \> BYT \> DFS \> FCB \\
+FCC \> FDB \> RMB \\
+\end{tabbing}}
+
+\subsubsection{Motorola 68HC12}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ADR \> BYT \> DC[.$<$size$>$] \> DFS \> DS[.$<$size$>$] \\
+FCB \> FCC \> FDB \> PADDING \> RMB \\
+\end{tabbing}}
+
+\subsubsection{Motorola 68HC16}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ADR \> ASSUME \> BYT \> DFS \> FCB \\
+FCC \> FDB \> RMB \\
+\end{tabbing}}
+
+\subsubsection{Hitachi H8/300(L/H)}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DC[.$<$size$>$] \> DS[.$<$size$>$] \> MAXMODE \> PADDING \\
+\end{tabbing}}
+
+\subsubsection{Hitachi H8/500}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> DC[.$<$size$>$] \> DS[.$<$size$>$] \> MAXMODE \> PADDING \\
+\end{tabbing}}
+
+\subsubsection{Hitachi SH7x00}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+COMPLITERALS \> DC[.$<$size$>$] \> DS[.$<$size$>$] \> LTORG \> PADDING \\
+SUPMODE \\
+\end{tabbing}}
+
+\subsubsection{65xx/MELPS-740}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ADR \> ASSUME \> BYT \> DFS \> FCB \\
+FCC \> FDB \> RMB \\
+\end{tabbing}}
+
+\subsubsection{65816/MELPS-7700}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ADR \> ASSUME \> BYT \> DB \> DD \\
+DQ \> DS \> DT \> DW \> DFS \\
+FCB \> FCC \> FDB \> RMB \\
+\end{tabbing}}
+
+\subsubsection{Mitsubishi MELPS-4500}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DATA \> RES \> SFR \\
+\end{tabbing}}
+
+\subsubsection{Mitsubishi M16}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{Mitsubishi M16C}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{Intel 4004}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DATA \> DS \> REG \\
+\end{tabbing}}
+
+\subsubsection{Intel MCS-48}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{Intel MCS-(2)51}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+BIGENDIAN \> BIT \> DB \> DD \> DQ \\
+DS \> DT \> DW \> PORT \> SFR \\
+SFRB \> SRCMODE \\
+\end{tabbing}}
+
+\subsubsection{Intel MCS-96}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> DB \> DD \> DQ \> DS \\
+DT \> DW \\
+\end{tabbing}}
+
+\subsubsection{Intel 8080/8085}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DATA \> DS \\
+\end{tabbing}}
+
+\subsubsection{Intel 8080/8085}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \> PORT \\
+\end{tabbing}}
+
+\subsubsection{Intel i960}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \> \> FPU \> SPACE \> SUPMODE \\
+WORD \\
+\end{tabbing}}
+
+\subsubsection{Signetics 8X30x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+LIV \> RIV \\
+\end{tabbing}}
+
+\subsubsection{Philips XA}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> BIT \> DB \> DC[.$<$size$>$] \> DD \\
+DQ \> DS[.$<$size$>$] \> DT \> DW \> PADDING \\
+PORT \> SUPMODE \\
+\end{tabbing}}
+
+\subsubsection{Atmel AVR}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DATA \> PORT \> REG \> RES \\
+\end{tabbing}}
+
+\subsubsection{AMD 29K}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> DB \> DD \> DQ \> DS \\
+DT \> DW \> EMULATED \> SUPMODE \\
+\end{tabbing}}
+
+\subsubsection{Siemens 80C166/167}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> BIT \> DB \> DD \> DQ \\
+DS \> DT \> DW \> REG \\
+\end{tabbing}}
+
+\subsubsection{Zilog Zx80}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DEFB \> DEFW \> DQ \\
+DS \> DT \> DW \> EXTMODE \> LWORDMODE \\
+\end{tabbing}}
+
+\subsubsection{Zilog Z8}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \> SFR \\
+\end{tabbing}}
+
+\subsubsection{Toshiba TLCS-900}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \> MAXIMUM \> SUPMODE \\
+\end{tabbing}}
+
+\subsubsection{Toshiba TLCS-90}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{Toshiba TLCS-870}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{Toshiba TLCS-47(0(A))}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> DB \> DD \> DQ \> DS \\
+DT \> DW \> PORT \\
+\end{tabbing}}
+
+\subsubsection{Toshiba TLCS-9000}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{Microchip PIC16C5x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DATA \> RES \> SFR \> ZERO \\
+\end{tabbing}}
+
+\subsubsection{Microchip PIC16C8x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DATA \> RES \> SFR \> ZERO \\
+\end{tabbing}}
+
+\subsubsection{Microchip PIC17C42}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DATA \> RES \> SFR \> ZERO \\
+\end{tabbing}}
+
+\subsubsection{SGS-Thomson ST6}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASCII \> ASCIZ \> ASSUME \> BYTE \> BLOCK \\
+SFR \> WORD \\
+\end{tabbing}}
+
+\subsubsection{SGS-Thomson ST7}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DC[.$<$size$>$] \> DS[.$<$size$>$] \> PADDING \\
+\end{tabbing}}
+
+\subsubsection{SGS-Thomson ST9}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> BIT \> DB \> DD \> DQ \\
+DS \> DT \> DW \> REG \\
+\end{tabbing}}
+
+\subsubsection{6804}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ADR \> BYT \> DFS \> FCB \> FCC \\
+FDB \> RMB \> SFR \\
+\end{tabbing}}
+
+\subsubsection{Texas TM3201x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DATA \> PORT \> RES \\
+\end{tabbing}}
+
+\subsubsection{Texas TM32C02x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+BFLOAT \> BSS \> BYTE \> DATA \> DOUBLE \\
+EFLOAT \> TFLOAT \> LONG \> LQxx \> PORT \\
+Qxx \> RES \> RSTRING \> STRING \> WORD \\
+\end{tabbing}}
+
+\subsubsection{Texas TMS320C3x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> BSS \> DATA \> EXTENDED \> SINGLE \\
+WORD \\
+\end{tabbing}}
+
+\subsubsection{Texas TM32C020x/TM32C05x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+BFLOAT \> BSS \> BYTE \> DATA \> DOUBLE \\
+EFLOAT \> TFLOAT \> LONG \> LQxx \> PORT \\
+Qxx \> RES \> RSTRING \> STRING \> WORD \\
+\end{tabbing}}
+
+\subsubsection{Texas TMS9900}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+BSS \> BYTE \> PADDING \> WORD \\
+\end{tabbing}}
+
+\subsubsection{Texas TMS70Cxx}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{Texas TMS370}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DBIT \> DD \> DQ \> DS \\
+DT \> DW \\
+\end{tabbing}}
+
+\subsubsection{Texas MSP430}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+BSS \> BYTE \> PADDING \> WORD \\
+\end{tabbing}}
+
+\subsubsection{National SC/MP}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{National COP8}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ADDR \> ADDRW \> BYTE \> DB \> DD \\
+DQ \> DS \> DSB \> DSW \> DT \\
+FB \> FW \> SFR \> WORD \\
+\end{tabbing}}
+
+\subsubsection{National COP8}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DC \> DC8 \> DS \> DS8 \> DS16 \\
+DW \> DW16 \\
+\end{tabbing}}
+
+
+\subsubsection{Fairchild ACE}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{NEC $\mu$PD78(C)1x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> DB \> DD \> DQ \> DS \\
+DT \> DW \\
+\end{tabbing}}
+
+\subsubsection{NEC 75K0}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+ASSUME \> BIT \> DB \> DD \> DQ \\
+DS \> DT \> DW \> SFR \\
+\end{tabbing}}
+
+\subsubsection{NEC 78K0}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
+
+\subsubsection{NEC $\mu$PD772x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DATA \> RES \\
+\end{tabbing}}
+
+\subsubsection{NEC $\mu$PD772x}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DS \> DW \\
+\end{tabbing}}
+
+\subsubsection{Symbios Logic SYM53C8xx}
+{\tt\begin{tabbing}
+\end{tabbing}}
+
+\subsubsection{Fujitsu F$^{2}$MC8L}
+{\tt\begin{tabbing}
+\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\hspace{3cm}\=\kill
+DB \> DD \> DQ \> DS \> DT \\
+DW \\
+\end{tabbing}}
diff --git a/doc_DE/tabids.tex b/doc_DE/tabids.tex
new file mode 100644
index 0000000..e5df02f
--- /dev/null
+++ b/doc_DE/tabids.tex
@@ -0,0 +1,33 @@
+\$01 & 680x0, 6833x & \$03 & M*Core \\
+\$05 & PowerPC & \$09 & DSP56xxx \\
+\$11 & 65xx/MELPS-740 & \$12 & MELPS-4500 \\
+\$13 & M16 & \$14 & M16C \\
+\$15 & F$^{2}$MC8L & \$19 & 65816/MELPS-7700 \\
+\$21 & MCS-48 & \$25 & SYM53C8xx \\
+\$29 & 29xxx & \$2a & i960 \\
+\$31 & MCS-51 & \$32 & ST9 \\
+\$33 & ST7 & \$39 & MCS-96/196/296 \\
+\$3a & 8X30x & \$3b & AVR \\
+\$3c & XA & \$3f & 4004/4040 \\
+\$41 & 8080/8085 & \$42 & 8086..V35 \\
+\$47 & TMS320C6x & \$48 & TMS9900 \\
+\$49 & TMS370xxx & \$4a & MSP430 \\
+\$4c & 80C166/167 & \$51 & Z80/180/380 \\
+\$52 & TLCS-900 & \$53 & TLCS-90 \\
+\$54 & TLCS-870 & \$55 & TLCS-47 \\
+\$56 & TLCS-9000 & \$61 & 6800, 6301 oder 6811 \\
+\$62 & 6805/HC08 & \$63 & 6809 \\
+\$64 & 6804 & \$65 & 68HC16 \\
+\$66 & 68HC12 & \$67 & ACE \\
+\$68 & H8/300(H) & \$69 & H8/500 \\
+\$6c & SH7000 & \$6d & SC14xxx \\
+\$6e & SC/MP & \$6f & COP8 \\
+\$70 & PIC16C8x & \$71 & PIC16C5x \\
+\$72 & PIC17C4x & \$73 & TMS-7000 \\
+\$74 & TMS3201x & \$75 & TMS320C2x \\
+\$76 & TMS320C3x & \$77 & TMS320C20x/TMS320C5x \\
+\$78 & ST6 & \$79 & Z8 \\
+\$7a & $\mu$PD78(C)10 & \$7b & 75K0 \\
+\$7c & 78K0 & \$7d & $\mu$PD7720 \\
+\$7e & $\mu$PD7725 & \$7f & $\mu$PD77230 \\
+\hline
diff --git a/doc_DE/taborg1.tex b/doc_DE/taborg1.tex
new file mode 100644
index 0000000..dfbdcea
--- /dev/null
+++ b/doc_DE/taborg1.tex
@@ -0,0 +1,48 @@
+68xxx & 4G & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+DSP56000/ & 64K/ & --- & --- & 64K/ & 64K/ & --- & --- & --- & --- \\
+DSP56300 & 16M & & & 16M & 16M & & & & \\
+\hline
+PowerPC & 4G & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+M*Core & 4G & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+6800,6301,& 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+6811, & & & & & & & & & \\
+\hline
+6805/HC08 & 8K & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+6809, & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+6309 & & & & & & & & & \\
+\hline
+68HC12 & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+68HC16 & 1M & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+H8/300 & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+H8/300H & 16M & & & & & & & & \\
+\hline
+H8/500 & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+(Min) & & & & & & & & & \\
+
+H8/500 & 16M & --- & --- & --- & --- & --- & --- & --- & --- \\
+(Max) & & & & & & & & & \\
+\hline
+SH7000/ & 4G & --- & --- & --- & --- & --- & --- & --- & --- \\
+7600/7700 & & & & & & & & & \\
+\hline
+6502, & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+MELPS740 & & & & & & & & & \\
+\hline
+65816, & 16M & --- & --- & --- & --- & --- & --- & --- & --- \\
+MELPS & & & & & & & & & \\
+7700 & & & & & & & & & \\
+\hline
+MELPS & 8K & 416 & --- & --- & --- & --- & --- & --- & --- \\
+4500 & & & & & & & & & \\
+\hline
+M16 & 4G & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+M16C & 1M & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+4004 & 4K & 256 & --- & --- & --- & --- & --- & --- & --- \\
diff --git a/doc_DE/taborg2.tex b/doc_DE/taborg2.tex
new file mode 100644
index 0000000..e8851b1
--- /dev/null
+++ b/doc_DE/taborg2.tex
@@ -0,0 +1,49 @@
+MCS-48, & 4K & --- & 256 & 256 & --- & --- & --- & --- & --- \\
+MCS-41 & & & & & & & & & \\
+MCS-51 & 64K & 256 & 256 * & 64K & --- & 256 & --- & --- & --- \\
+ & & & In. 80H & & & & & & \\
+\hline
+MCS-251 & 16M & --- & --- & --- & --- & --- & 512 & --- & --- \\
+\hline
+MCS-(1)96 & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+196N/296 & 16M & & & & & & & & \\
+\hline
+8080, & 64K & --- & --- & --- & --- & --- & 256 & --- & --- \\
+\hline
+80x86, & 64K & 64K & --- & 64K & --- & --- & 64K & --- & --- \\
+\hline
+68xx0 & 4G & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+8X30x & 8K & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+XA & 16M & 16M & --- & --- & --- & --- & 2K & --- & --- \\
+ & & & & & & & In. 1K & & \\
+\hline
+AVR & 8K & 64K & --- & --- & --- & --- & 64 & --- & --- \\
+\hline
+29XXX & 4G & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+80C166, & 256K & --- & --- & --- & --- & --- & --- & --- & --- \\
+80C167 & 16M & & & & & & & & \\
+\hline
+Z80, & 64K & --- & --- & --- & --- & --- & 256 & --- & --- \\
+Z180, & 512K + & & & & & & 256 & & \\
+Z380 & 4G & & & & & & 4G & & \\
+\hline
+Z8 & 64K & 256 & --- & 64K & --- & --- & --- & --- & --- \\
+\hline
+TLCS- & 16M & --- & --- & --- & --- & --- & --- & --- & --- \\
+900(L) & & & & & & & & & \\
+\hline
+TLCS-90 & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+TLCS- & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+870 & & & & & & & & & \\
+\hline
+TLCS-47 & 64K & 1K & --- & --- & --- & --- & 16 & --- & --- \\
+\hline
+TLCS- & 16M & --- & --- & --- & --- & --- & --- & --- & --- \\
+9000 & & & & & & & & & \\
+\hline
+PIC & 2K & 32 & --- & --- & --- & --- & --- & --- & --- \\
+16C5x & & & & & & & & & \\
diff --git a/doc_DE/taborg3.tex b/doc_DE/taborg3.tex
new file mode 100644
index 0000000..9842884
--- /dev/null
+++ b/doc_DE/taborg3.tex
@@ -0,0 +1,51 @@
+PIC & 2K & 32 & --- & --- & --- & --- & --- & --- & --- \\
+16C5x & & & & & & & & & \\
+PIC & & & & & & & & & \\
+16C64, & 8K & 512 & --- & --- & --- & --- & --- & --- & --- \\
+16C86 & & & & & & & & & \\
+\hline
+PIC & 64K & 256 & --- & --- & --- & --- & --- & --- & --- \\
+17C42 & & & & & & & & & \\
+\hline
+ST6 & 4K & 256 & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+ST7 & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+ST9 & 64K & 64K & --- & --- & --- & --- & --- & 256 & --- \\
+\hline
+6804 & 4K & 256 & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+32010 & 4K & 144 & --- & --- & --- & --- & 8 & --- & --- \\
+32015 & 4K & 256 & & & & & 8 & & \\
+\hline
+320C2x & 64K & 64K & --- & --- & --- & --- & 16 & --- & --- \\
+\hline
+320C3x & 16M & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+320C5x/ & 64K & 64K & --- & --- & --- & --- & 64K & --- & --- \\
+320C20x & & & & & & & & & \\
+\hline
+TMS & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+9900 & & & & & & & & & \\
+\hline
+TMS & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+70Cxx & & & & & & & & & \\
+\hline
+370xxx & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+ & & & & & & & & & \\
+\hline
+MSP430 & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+ & & & & & & & & & \\
+\hline
+SC/MP & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+COP8 & 8K & 256 & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+ACE & 4K & 256 & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+$\mu$PD & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
+78(C)10 & & & & & & & & & \\
+\hline
+75K0 & 16K & 4K & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+78K0 & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
diff --git a/doc_DE/taborg4.tex b/doc_DE/taborg4.tex
new file mode 100644
index 0000000..a8d826e
--- /dev/null
+++ b/doc_DE/taborg4.tex
@@ -0,0 +1,11 @@
+7720 & 512 & 128 & --- & --- & --- & --- & --- & --- & 512 \\
+ & & & & & & & & & \\
+\hline
+7725 & 2K & 256 & --- & --- & --- & --- & --- & --- & 1024 \\
+ & & & & & & & & & \\
+\hline
+77230 & 8K & --- & --- & 512 & 512 & --- & --- & --- & 1K \\
+\hline
+53C8XX & 4G & --- & --- & --- & --- & --- & --- & --- & --- \\
+\hline
+F$^{2}$MC8L & 64K & --- & --- & --- & --- & --- & --- & --- & --- \\
diff --git a/doc_EN/Makefile b/doc_EN/Makefile
new file mode 100644
index 0000000..fdedff7
--- /dev/null
+++ b/doc_EN/Makefile
@@ -0,0 +1,36 @@
+INCFILES = ../doc_DE/taborg*.tex ../doc_DE/pscpu.tex ../doc_DE/pscomm.tex
+
+all: as.doc as.html as.ps
+
+as.ps: as.dvi
+ dvips as -o
+
+as.dvi: as.tex $(INCFILES)
+ latex as
+ latex as
+ makeindex as
+ latex as
+
+as.doc: as.tex $(INCFILES) $(TEX2DOC)
+ $(TEX2DOC) as.tex as.doc
+ $(TEX2DOC) as.tex as.doc
+
+as.html: as.tex $(INCFILES) $(TEX2HTML)
+ $(TEX2HTML) as.tex as.html
+ $(TEX2HTML) as.tex as.html
+
+clean:
+ $(RM) as.dvi
+ $(RM) as.ps
+ $(RM) as.i*
+ $(RM) *log
+ $(RM) as.aux
+ $(RM) as.toc
+ $(RM) *~
+ $(RM) DEADJOE
+ $(RM) as.doc
+ $(RM) as.dtoc
+ $(RM) as.daux
+ $(RM) as.html
+ $(RM) as.htoc
+ $(RM) as.haux
diff --git a/doc_EN/as.tex b/doc_EN/as.tex
new file mode 100644
index 0000000..d7215de
--- /dev/null
+++ b/doc_EN/as.tex
@@ -0,0 +1,11521 @@
+%% Hello altogether,
+%%
+%% this is a release of the english AS manual. I haven't
+%% done the entire translation myself, large parts of it are the work of some
+%% other people around the net who deserve my deep appreciation for this job.
+%% My parts of the translation are the results of a brute-force attempt,
+%% so there are surely tons of spelling errors and passages that will
+%% make people with english as their mother tongue either laugh or cry...
+
+%% Alfred Arnold
+
+%% translation by: Oliver Sellke (OSIP, D-65199 Wiesbaden)
+%% (proof-read in parts by Stefan Hilse, Wiesbaden)
+%% Alfred Arnold
+%% Stephan Kanthak
+%% Vittorio De Tomasi
+%%
+%% thanks to the authors of:
+%% FB-translator
+%% GNU-ispell
+%%
+%% ------------------------------------------------------------------------------
+
+%%TITLE User's Manual for Macro Assembler AS
+\documentstyle[12pt,twoside,makeidx]{report}
+\pagestyle{headings}
+\sloppy
+%%\textwidth 15cm
+%%\evensidemargin 0.5cm
+%%\oddsidemargin 0.5cm
+\topsep 1mm
+\parskip 0.3cm plus0.25cm minus0.25cm
+\parindent 0cm
+
+\newcommand{\ii}[1]{{\it #1}}
+\newcommand{\bb}[1]{{\bf #1}}
+\newcommand{\tty}[1]{{\tt #1}}
+\newcommand{\tin}[1]{{\scriptsize #1}}
+\newcommand{\ttindex}[1]{\index{#1@{\tt #1}}}
+
+\font\mengft=cmss9 scaled \magstep1
+\def \rz{\hbox{\mengft{I \hskip -1.7mm R}}}
+
+\makeindex
+
+%%===========================================================================
+
+\begin{document}
+
+\thispagestyle{empty}
+
+\
+\vspace{7cm}\par
+
+\begin{raggedright}
+{\large Alfred Arnold, Stefan Hilse, Stephan Kanthak, Oliver
+ Sellke, Vittorio De Tomasi}
+\vspace{1cm}\par
+{\huge Macro Assembler AS V1.41r8}\\
+\rule{9.5cm}{0.3mm}\\
+\vspace{2mm}\par
+{\huge User's Manual}
+
+\vspace{1cm}\par
+
+{\large Edition November 1999}
+\end{raggedright}
+
+\clearpage
+\thispagestyle{empty}
+
+\ \vspace{5cm}
+
+{\em IBM, PPC403Gx, OS/2, and PowerPC} are registered trademarks of IBM
+Corporation.
+
+{\em Intel, MCS-48, MCS-51, MCS-251, MCS-96, MCS-196 und MCS-296} are
+registered trademarks of Intel Corp. .
+
+{\em Motorola and ColdFire} are registered trademarks of Motorola Inc. .
+
+{\em UNIX} is a registered trademark of X/Open Company.
+
+{\em Linux} is a registered trademark of Linus Thorvalds.
+
+{\em Microsoft, Windows, and MS-DOS} are registered trademarks of
+Microsoft Corporation.
+
+All other trademarks not explicitly mentioned in this section and used in
+this manual are properties of their respective owners.
+
+\vspace{7cm}
+
+This document has been processed with the LaTeX typesetting system using
+Digital Unix, Linux, and OS/2 operating systems running on AMD K6 and
+DEC Alpha processors.
+
+\clearpage
+
+%%===========================================================================
+
+{\parskip 0cm plus0.1cm \tableofcontents}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Introduction}
+
+This instruction is meant for those people who are already very familiar
+with Assembler and who like to know how to work with AS. It is rather a
+reference than a user's manual and so it neither tries to explain the
+''language assembler'' nor the processors. I have listed further
+literature in the bibliography which was substantial in the implementation
+of the different code generators. There is no book I know where you can
+learn Assembler from the start, so I generally learned this by ''trial and
+error''.
+
+%%---------------------------------------------------------------------------
+
+\section{License Agreement}
+\label{SectLicense}
+
+Before we can go ''in medias res'', first of all the inevitable prologue:
+
+I publish AS, in the present version, as ''Public Domain''.
+This means, the program and overlay files and also the
+utility and tool programs appended may be copied and use for free (of
+charge). There are no plans to convert AS into a commercial or
+shareware program. This permission however is valid only under the
+following premises:
+\begin{enumerate}
+\item{The start message of the programs - especially the copyright
+ message - must not be removed or overwritten.}
+\item{The compensation charged for copying and shipping must not
+ exceed D(E)M 20,-- (around US\$ 14.00).}
+\end{enumerate}
+
+On request the source code of this program can also be made available.
+Programs or derivates structured hereon must be passed-on under the
+same conditions as this program.
+
+I explicitly encourage you to spread this program by disc or
+mailbox, BBS, resp. Internet!
+
+May be, you have got this program as enclosure to a commercial
+program. The license agreement for the commercial program in no case
+applies to AS.
+
+If you took so much pleasure in this assembler that you like to
+send me some money, I would ask you kindly to give the amount
+to Greenpeace.
+
+I have been trying to make the programs as bug free as possible.
+But since there is principally no bug free software (the only people
+making no mistakes are lying in the cemetery!), I do not take any
+warranty for the function of the assembler in a particular environment
+(hard or software) or liability for damages. Naturally I will always
+be thankful for bug-reports or improvements and will work on the fixing.
+
+To accelerate the error diagnose and correction, please add the
+following details to the bug report:
+\begin{itemize}
+\item{hardware: \begin{itemize}
+ \item{processor type (with/without coprocessor)}
+ \item{amount of memory installed}
+ \item{video card}
+ \item{hard-disk type(s) and their interface(s)}
+ \end{itemize}}
+\item{software: \begin{itemize}
+ \item{operating system (MS-DOS, Novell-DOS, DR-DOS, OS/2,
+ Windows) and version}
+ \item{resident (TSR) programs installed}
+ \item{version of AS including dates of the \tty{EXE}-files}
+ \end{itemize}}
+\item{if possible, the source file, in which the bug occurs}
+\end{itemize}
+You can contact me as follows:
+\begin{itemize}
+\item{by Surface Mail: \begin{description}
+ \item{Alfred Arnold}
+ \item{Hirschgraben 29}
+ \item{D-52062 Aachen}
+ \item{Germany}
+ \end{description}}
+\item{by E-Mail: \tty{alfred@ccac.rwth-aachen.de}}
+\end{itemize}
+If someone likes to meet me personally to ask questions and lives
+near Aachen (= Aix-la-Chapelle), you will be able to meet me there.
+You can do this most probably on thursdays from 7pm to 9pm at the
+computerclub inside the RWTH Aachen (Eilfschornsteinstrasse 16,
+cellar of philosophers' building, backdoor entry).
+
+Please don't call me by phone. First, complex relations are
+extremely hard to discuss at phone. Secondly, the telephone
+companies are already rich enough...
+
+The latest german version of AS (DOS,DPMI,OS/2) is available from
+the following FTP-Server:
+\begin{verbatim}
+ ftp.uni-stuttgart.de, directory
+ pub/systems/msdos/programming/as
+\end{verbatim}
+The sources of the C version can be fetched from the following server:
+\begin{verbatim}
+ sunsite.unc.edu, directory
+ pub/Linux/devel/lang/assemblers/asl-<version>.tar.gz
+\end{verbatim}
+..and of course thereby from every Sunsite mirror of the world!
+
+Whoever has no access to an FTP-Server can ask me to send the assembler
+by mail. Only requests containing floppies (2 pieces 1.44 Mbytes, for
+720Kbytes/1.2Mbytes format 4/3 pieces) and a self-addressed, (correctly)
+stamped envelope will be answered. Don't send any money!
+
+Now, after this inevitable introduction we can turn to the actual
+documentation:
+
+%%---------------------------------------------------------------------------
+
+\section{General Capabilities of the Assembler}
+
+In contrast to ordinary assemblers, AS offers the possibility to
+generate code for totally different processors. At the moment, the
+following processor families have been implemented:
+\begin{itemize}
+\item{Motorola 68000..68040,683xx incl. coprocessor and MMU}
+\item{Motorola ColdFire}
+\item{Motorola DSP5600x,DSP56300}
+\item{Motorola M-Core}
+\item{Motorola/IBM MPC601/MPC505/PPC403}
+\item{Motorola 6800, 6805, 68HC08, 6809, 68(HC)11 68HC12, 68HC16, and Hitachi
+ 6301}
+\item{Hitachi 6309}
+\item{Hitachi H8/300(H)}
+\item{Hitachi H8/500}
+\item{Hitachi SH7000/7600/7700}
+\item{Rockwell 6502 and 65(S)C02}
+\item{CMD 65816}
+\item{Mitsubishi MELPS-740}
+\item{Mitsubishi MELPS-7700}
+\item{Mitsubishi MELPS-4500}
+\item{Mitsubishi M16}
+\item{Mitsubishi M16C}
+\item{Intel 4004}
+\item{Intel MCS-48/41}
+\item{Intel MCS-51/251}
+\item{Intel MCS-96/196(Nx)/296}
+\item{Intel 8080/8085}
+\item{Intel i960}
+\item{Signetics 8X30x}
+\item{Philips XA}
+\item{Atmel AVR}
+\item{AMD 29K}
+\item{Siemens 80C166/167}
+\item{Zilog Z80, Z180, Z380}
+\item{Zilog Z8}
+\item{Toshiba TLCS-900(L)}
+\item{Toshiba TLCS-90}
+\item{Toshiba TLCS-870}
+\item{Toshiba TLCS-47}
+\item{Toshiba TLCS-9000}
+\item{Microchip PIC16C54..16C57}
+\item{Microchip PIC16C84/PIC16C64}
+\item{Microchip PIC17C42}
+\item{SGS-Thomson ST6}
+\item{SGS-Thomson ST7}
+\item{SGS-Thomson ST9}
+\item{SGS-Thomson 6804}
+\item{Texas Instruments TMS32010/32015}
+\item{Texas Instruments TMS3202x}
+\item{Texas Instruments TMS320C3x}
+\item{Texas Instruments TMS320C20x/TMS320C5x}
+\item{Texas Instruments TMS320C6x}
+\item{Texas Instruments TMS9900}
+\item{Texas Instruments TMS7000}
+\item{Texas Instruments TMS370xxx}
+\item{Texas Instruments MSP430}
+\item{National Semiconductor SC/MP}
+\item{National Semiconductor COP8}
+\item{National Semiconductor SC144xx}
+\item{Fairchild ACE}
+\item{NEC $\mu$PD 78(C)1x}
+\item{NEC $\mu$PD 75xxx (alias 75K0)}
+\item{NEC $\mu$PD 78xxx (alias 78K0)}
+\item{NEC $\mu$PD7720/7725}
+\item{NEC $\mu$PD77230}
+\item{Symbios Logic SYM53C8xx (yes, they are programmable!)}
+\item{Fujitsu F$^2$MC8L}
+\end{itemize}
+under work / planned / in consideration :
+\begin{itemize}
+\item{Intel 4004/8008}
+\item{Analog Devices ADSP21xx}
+\item{SGS-Thomson ST20}
+\item{Texas Instruments TMS320C4x}
+\item{Texas Instruments TMS320C8x}
+\item{Toshiba TC9331}
+\end{itemize}
+I'm currently searching for documentation about the following
+families:
+\begin{itemize}
+\item{NEC 78K4}
+\item{the complete set of OKI controllers}
+\end{itemize}
+unloved, but now, however, present :
+\begin{itemize}
+\item{Intel 80x86, 80186, Nec V30\&V35 incl. coprocessor 8087}
+\end{itemize}
+The switch to a different code generator is allowed even within one
+file, and as often as one wants!
+
+The reason for this flexibility is that AS has a history, which may also
+be recognized by looking at the version number. AS was created as an
+extension of a macro assembler for the 68000 family. On special request, I
+extended the original assembler so that it was able to translate 8051
+mnemonics. On this way (decline ?!) from the 68000 to 8051, some other
+processors were created as by-products. All others were added over time
+due to user requests. So At least for the processor-independent core of
+AS, one may assume that it is well-tested and free of obvious bugs.
+However, I often do not have the chance to test a new code generator in
+practice (due to lack of appropriate hardware), so surprises are not
+impossible when working with new features. You see, the things stated in
+section \ref{SectLicense} have a reason...
+
+This flexibility implies a somewhat exotic code format, therefore I
+added some tools to work with it. Their description can be found in
+chapter \ref{ChapTools}.
+
+AS is a macro assembler, which means that the programmer has the
+possibility to define new ''commands'' by means of macros.
+Additionally it masters conditional assembling. Labels inside macros
+are automatically processed as being local.
+
+For the assembler, symbols may have either integer, string or floating
+point values. These will be stored - like interim values in formulas -
+with a width of 32 bits for integer values, 80 or 64 bits for floating
+point values, and 255 characters for strings. For a couple of micro
+controllers, there is the possibility to classify symbols by segmentation.
+So the assembler has a (limited) possibility to recognize accesses to
+wrong address spaces.
+
+The assembler does not know explicit limits in the nesting depth of
+include files or macros; a limit is only given by the program stack
+restricting the recursion depth. Nor is there a limit for the
+symbol length, which is only restricted by the maximum line length.
+
+From version 1.38 on, AS is a multipass-assembler. This pompous term
+means no more than the fact that the number of passes through the
+source code need not be exactly two. If the source code does not
+contain any forward references, AS needs only one pass. In case AS
+recognizes in the second pass that it must use a shorter or longer
+instruction coding, it needs a third (fourth, fifth...) pass to
+process all symbol references correctly. There is nothing more behind
+the term ''multipass'', so it will not be used further more in this
+documentation.
+
+After so much praise a bitter pill: AS cannot generate linkable code.
+An extension with a linker needs considerable effort and is not planned
+at the moment.
+
+As regards ''release of sources'': the sources of AS are not
+presented in a form which allows easy understanding (== no
+comments). So I will emit sources only in case somebody really wants
+to work on it (e.g. to port AS into another computer system) and the
+derivates become again Public Domain. Particularly I want to prevent
+that someone changes 5 lines (most popular the copyright entry) and
+sell the result commercially as ''his own'' program.
+
+%%---------------------------------------------------------------------------
+
+\section{Supported Platforms}
+
+Though AS started as a pure DOS \marginpar{{\em DOS}} program, there are a
+couple of versions available that are able to exploit a bit more than the
+Real Mode of an Intel CPU. Their usage is kept as compatible to the DOS
+version as possible, but there are of course differences concerning
+installation and embedding into the operating system in question.
+Sections in this manual that are only valid for a specific version of AS
+are marked with a corresponding sidemark (at this paragraph for the DOS
+version) aheaded to the paragraph. In detail, the following further
+versions exist (distributed as separate packages):
+
+In case you run \marginpar{{\em DPMI}}into memory problems when assembling
+large and complex programs under DOS, there is a DOS version that runs in
+protected mode via a DOS extender and can therefore make use of the whole
+extended memory of an AT. The assembly becomes significantly slower by
+the extender, but at least it works...
+
+There is a native OS/2 \marginpar{{\em OS/2}} version of AS for friends of
+IBM's OS/2 operating system. This is currently only a 16-bit version, but
+at least this way saves the roundtrips via DOS boxes and one does not have
+any problems any more with longer file names.
+
+You can leave \marginpar{{\em UNIX}} the area of PCs-only with the C
+version of AS that was designed to be compilable on a large number of UNIX
+systems (this includes OS/2 with the emx compiler) without too much of
+tweaking. In contrast to the previously mentioned versions, the C version
+is delivered in source code, i.e. one has to create the binaries by
+oneself using a C compiler. This is by far the simpler way (for me) than
+providing a dozen of precompiled binaries for machines I sometimes only
+have limited access to...
+
+People who have read \marginpar{{\em ???}} this enumeration up to this
+point will notice that world's best-selling operating system coming from
+Redmont is missing in this enumeration. People who know me personally
+will know that I do not regard Windows to be a pat solution (regardless if
+its 3.X, 95, or NT). Frankly said, I am a 'windows hater'. A large
+number of people will now regard this to be somewhere between obsolete and
+ridiculous, and they will tell me that I withhold AS from a large part of
+potential users, but they will have to live with it: I primarily continue
+to improve AS because I have fun doing it; AS is a non-commercial project
+and I therefore take the freedom not to look at potential market shares. I
+select platforms for me where I have fun programming, and I definitely do
+not have any fun when programming for Windows! By the way, there was a
+time when I had to write Windows programs so I do not simply jabber
+without having an idea what I am talking about. If someone wants to port
+AS into this direction, I will not stand in his way, but (s)he should not
+expect anything more from me than providing sources (which is why (s)he
+will have to deal with questions like 'why does AS not work any more after
+I changed the JUNK-CAD 18.53 registry entry from upper to lower case?').
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Assembler Usage}
+
+\begin{quote}\begin{raggedright}{\it
+Scotty: Captain, we din\verb!'! can reference it! \\
+Kirk: Analysis, Mr. Spock? \\
+Spock: Captain, it doesn\verb!'!t appear in the symbol table. \\
+Kirk: Then it\verb!'!s of external origin? \\
+Spock: Affirmative. \\
+Kirk: Mr. Sulu, go to pass two. \\
+Sulu: Aye aye, sir, going to pass two. \\
+}\end{raggedright}\end{quote}
+
+%%---------------------------------------------------------------------------
+
+\section{Hardware Requirements}
+
+The hardware requirements of AS vary substantially from version to
+version:
+
+The DOS version \marginpar{{\em DOS}} will principally run on any
+IBM-compatible PC, ranging from a PC/XT with 4-dot-little megahertz up to
+a Pentium. However, similar to other programs, the fun using AS increases
+the better your hardware is. An XT user without a hard drive will
+probably have significant trouble placing the overlay file on a floppy
+because it is larger than 500 Kbytes...the PC should therefore have at
+least a hard drive, allowing acceptable loading times. AS is not very
+advanced in its main memory needs: the program itself allocates less than
+300 Kbytes main memory, AS should therefore work on machines with at least
+512 Kbytes of memory.
+
+The version of AS \marginpar{{\em DPMI}} compiled for the DOS Protected
+Mode Interface (DPMI) requires at least 1 Mbyte of free extended memory.
+A total memory capacity of at least 2 Mbytes is therefore the absolute
+minimum given one does not have other tools in the XMS (like disk caches,
+RAM disks, or a hi-loaded DOS); the needs will rise then appropriately.
+If one uses the DPMI version in a DOS box of OS/2, one has to assure that
+DPMI has been enabled via the box's DOS settings (set to \tty{on} or
+\tty{auto}) and that a sufficient amount of XMS memory has been assigned
+to the box. The virtual memory management of OS/2 will free you
+from thinking about the amount of free real memory.
+
+The hardware requirements of the OS/2 \marginpar{{\em OS/2}} version
+mainly result from the needs of the underlying operating system, i.e. at
+minimum an 80386SX processor, 8 Mbytes of RAM (resp. 4 Mbytes without the
+graphical user interface) and 100..150 Mbytes of hard disk space. AS2 is
+only a 16-bit application and therefore it should also work on older OS/2
+versions (thereby reducing the processor needs to at least an 80286
+processor); I had however no chance to test this.
+
+The C version of AS \marginpar{{\em UNIX}} is delivered as source code and
+therefore requires a UNIX or OS/2 system equipped with a C compiler. The
+compiler has to fulfill the ANSI standard (GNU-C for example is
+ANSI-compliant). You can look up in the \tty{README} file whether your
+UNIX system has already been tested so that the necessary definitions have
+been made. You should reserve about 15 Mbytes of free hard disk space for
+compilation; this value (and the amount needed after compilation to store
+the compiled programs) strongly differs from system to system, so you
+should take this value only as a rough approximation.
+
+%%---------------------------------------------------------------------------
+
+\section{Delivery}
+
+Principally, you can obtain AS in one of two forms: as a {\em binary} or a
+{\em source} distribution. In case of a binary distribution, one gets AS,
+the accomanying tools and auxiliary files readily compiled, so you can
+immediately start to use it after unpacking the archive to the desired
+destination on your hard drive.
+Binary distibutions are made for widespread platforms, where either the
+majority of users does not have a compiler or the compilation is tricky
+(currently, this includes DOS and OS/2). A source distribution in
+contrast contains the complete set of C sources to generate AS; it is
+ultimately a snapshot of the source tree I use for development on AS. The
+generation of AS from the sources and their structure is described in
+detail in appendix \ref{ChapSource}, which is why at this place, only the
+contents and installation of a binary distribution will be described:
+
+The contents of the archive is separated into several subdirectories,
+therefore you get a directory subtree immediately after unpacking without
+having to sort out things manually. The individual directories contain
+the following groups of files:
+\begin{itemize}
+\item{{\tt BIN}: executable programs, text resources;}
+\item{{\tt INCLUDE}: include files for assembler programs, e.g. register
+ definitions or standard macros;}
+\item{{\tt MAN}: quick references for the individual programs in Unix
+ 'man' format.}
+\end{itemize}
+A list of the files found in every binary distribution is given in tables
+\ref{TabCommonPackageList1} to \ref{TabCommonPackageList3}. In case a
+file listed in one of these (or the following) tables is missing, someone
+took a nap during copying (probably me)...
+
+\begin{table*}[htp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+File & function \\
+\hline
+\hline
+{\bf Directory BIN} & \\
+\hline
+AS.EXE & executable of assembler \\
+PLIST.EXE & lists contents of code files \\
+PBIND.EXE & merges code files \\
+P2HEX.EXE & converts code files to hex files \\
+P2BIN.EXE & converts code files to binary files \\
+AS.MSG & text resources for AS \\
+PLIST.MSG & text resources for PLIST \\
+PBIND.MSG & text resources for PBIND \\
+P2HEX.MSG & text resources for P2HEX \\
+P2BIN.MSG & text resources for P2BIN \\
+TOOLS.MSG & common text resources for all tools \\
+CMDARG.MSG & common text resources for all programs \\
+DECODECMD.MSG & \\
+IOERRS.MSG & \\
+\hline
+\hline
+{\bf Directory DOC} & \\
+\hline
+AS\_DE.DOC & german documentation, ASCII format \\
+AS\_DE.HTML & german documentation, HTML format \\
+AS\_DE.TEX & german documentation, LaTeX format \\
+AS\_EN.DOC & english documentation, ASCII format \\
+AS\_EN.HTML & english documentation, HTML format \\
+AS\_EN.TEX & english documentation, LaTeX format \\
+\hline
+\hline
+{\bf Directory INCLUDE} & \\
+\hline
+BITFUNCS.INC & functions for bit manipulation \\
+CTYPE.INC & functions for classification of \\
+ & characters \\
+80C50X.INC & register addresses SAB C50x \\
+80C552.INC & register addresses 80C552 \\
+H8\_3048.INC & register addresses H8/3048 \\
+REG166.INC & addresses and instruction macros 80C166/167 \\
+REG251.INC & addresses and bits 80C251 \\
+REG29K.INC & peripheral addresses AMD 2924x \\
+\hline
+\end{tabular}\end{center}
+\caption{Standard Contents of a Binary Distribution - Part 1
+ \label{TabCommonPackageList1}}
+\end{table*}
+\begin{table*}[htp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+File & Function \\
+\hline
+\hline
+{\bf Directory INCLUDE} & \\
+\hline
+REG53X.INC & register addresses H8/53x \\
+REG683XX.INC & register addresses 68332/68340/68360 \\
+REG7000.INC & register addresses TMS70Cxx \\
+REG78K0.INC & register addresses 78K0 \\
+REG96.INC & register addresses MCS-96 \\
+REGACE.INC & register addresses ACE \\
+REGAVR.INC & register and bit addresses AVR family \\
+REGCOP8.INC & register addresses COP8 \\
+REGHC12.INC & register addresses 68HC12 \\
+REGM16C.INC & register addresses Mitsubishi M16C \\
+REGMSP.INC & register addresses TI MSP430 \\
+REGST9.INC & register and Makrodefinitionen ST9 \\
+REGZ380.INC & register addresses Z380 \\
+STDDEF04.INC & register addresses 6804 \\
+STDDEF16.INC & instruction macros and register addresses \\
+ & PIC16C5x \\
+STDDEF17.INC & register addresses PIC17C4x \\
+STDDEF18.INC & register addresses PIC16C8x \\
+STDDEF2X.INC & register addresses TMS3202x \\
+STDDEF37.INC & register and bit addresses TMS370xxx \\
+STDDEF3X.INC & peripheral addresses TMS320C3x \\
+STDDEF47.INC & instruction macros TLCS-47 \\
+STDDEF51.INC & definition of SFRs and bits for \\
+ & 8051/8052/80515 \\
+STDDEF56K.INC & register addresses DSP56000 \\
+STDDEF5X.INC & peripheral addresses TMS320C5x \\
+STDDEF60.INC & instruction macros and register addresses \\
+ & PowerPC \\
+STDDEF62.INC & register addresses and Makros ST6 \\
+STDDEF75.INC & register addresses 75K0 \\
+\hline
+\end{tabular}\end{center}
+\caption{Standard Contents of a Binary Distribution - Part 2
+ \label{TabCommonPackageList2}}
+\end{table*}
+\begin{table*}[htp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+File & Function \\
+\hline
+\hline
+{\bf Directory INCLUDE} & \\
+\hline
+STDDEF87.INC & register and memory addresses TLCS-870 \\
+STDDEF90.INC & register and memory addresses TLCS-90 \\
+STDDEF96.INC & register and memory addresses TLCS-900 \\
+STDDEFXA.INC & SFR and bit addresses Philips XA \\
+STDDEFZ8.INC & register addresses Z8 family \\
+\hline
+\hline
+{\bf Directory LIB} & \\
+\hline
+\hline
+{\bf Directory MAN} & \\
+\hline
+ASL.1 & quick reference for AS \\
+PLIST.1 & quick reference for PLIST \\
+PBIND.1 & quick reference for PBIND \\
+P2HEX.1 & quick reference for P2HEX \\
+P2BIN.1 & quick reference for P2BIN \\
+\hline
+\end{tabular}\end{center}
+\caption{Standard Contents of a Binary Distribution - Part 3
+ \label{TabCommonPackageList3}}
+\end{table*}
+
+
+Depending on the platform, a binary distribution however may contain more
+files to allow operation, like files necessary for DOS extenders. In case
+of the DOS DPMI version \marginpar{{\em DPMI}}, the extensions listed in
+table \ref{TabDPMIPackageList} result. Just to mention it: it is
+perfectly O.K. to replace the tools with their counterparts from a DOS
+binary distribution; on the on hand, they execute significantly faster
+without the extender's overhead, and on the other hand, they do not need
+the extended memory provided by the extender.
+
+\begin{table*}[htp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+File & Function \\
+\hline
+\hline
+{\bf Directory BIN} & \\
+\hline
+DPMI16BI.OVL & DPMI server for the assembler \\
+RTM.EXE & runtime module of the extender \\
+\hline
+\end{tabular}\end{center}
+\caption{Additional Files in a DPMI Binary Distribution
+ \label{TabDPMIPackageList}}
+\end{table*}
+
+An OS/2 binary distribution \marginpar{{\em OS/2}} contains in addition to
+the base files a set of DLLs belonging to the runtime environment of the
+emx compiler used to build AS (table \ref{TabOS2PackageList}). In case
+you already have these DLLs (or newer versions of them), you may delete
+these and use your ones insted.
+
+\begin{table*}[htp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+File & function \\
+\hline
+\hline
+{\bf Directory BIN} & \\
+\hline
+EMX.DLL & runtime libraries for AS and \\
+EMXIO.DLL & its tools \\
+EMXLIBC.DLL & \\
+EMXWRAP.DLL & \\
+\hline
+\end{tabular}\end{center}
+\caption{Additional Files in an OS/2 binary distribution
+ \label{TabOS2PackageList}}
+\end{table*}
+
+%%---------------------------------------------------------------------------
+
+\section{Installation}
+
+There is no need for a \marginpar{{\em DOS}} special installation prior to
+usage of AS. It is sufficient to unpack the archive in a fitting place
+and to add a few minor settings. For example, this is an installation a
+user used to UNIX-like operating systems might choose:
+
+Create a directory \verb!c:\as! an (I will assume in the following that
+you are going to install AS on drive C), change to this directory and
+unpack the archiv, keeping the path names stored in the archive (when
+using PKUNZIP, the command line option \verb!-d! is necessary for that).
+You now should have the following directory tree:
+\begin{verbatim}
+c:\as
+c:\as\bin
+c:\as\include
+c:\as\lib
+c:\as\man
+c:\as\doc
+c:\as\demos
+\end{verbatim}
+Now, append the directory \verb!c:\as\bin! to the \tty{PATH} statement in
+your \tty{AUTOEXEC.BAT}, which allows the system to find AS and its tools.
+With your favourite text editor, create a file named \tty{AS.RC} in the
+\tty{lib} directory with the following contents:
+\begin{verbatim}
+-i c:\as\include
+\end{verbatim}
+This so-called {\em key file} tells AS where to search for its include
+files. The following statement must be added to your \tty{AUTOEXEC.BAT}
+to tell AS to read this file:
+\begin{verbatim}
+set ASCMD=@c:\as\lib\as.rc
+\end{verbatim}
+There are many more things you can preset via the key file; they are
+listed in the following section.
+
+The installation of the DPMI version \marginpar{{\em DPMI}} should
+principally take the same course as for the pure DOS version; as soon as
+the PATH contains the {\tt bin} directory, the DOS extender's files will
+be found automatically and you should not notice anything of this
+mechanism (except for the longer startup time...). When working on an
+80286-based computer, it is theoretically possible tha you get confronted
+with the following message upon the first start:
+\begin{verbatim}
+ machine not in database (run DPMIINST)
+\end{verbatim}
+Since the DPMIINST tool ins not any more included in newer versions of
+Borland's DOS extender, I suppose that this is not an item any more...in
+case you run into this, contact me!
+
+The installation of the OS/2 version \marginpar{{\em OS/2}} can generally
+be done just like for the DOS version, with the addition that the DLLs
+have to be made visible for the operating system. In case you do not want
+to extend the {\tt LIBPATH} entry in your {\tt CONFIG.SYS}, it is of
+course also valid to move the DLLs into a directory already listed in {\tt
+LIBPATH}.
+
+As already mentioned, the installation instructions in this section limit
+themselves to binary distributions. Since an installation under Unix
+\marginpar{{\em UNIX}} is currently alway a source-based installation, the
+only hint I can give here is a reference to appendix \ref{ChapSource}.
+
+%%---------------------------------------------------------------------------
+
+\section{Start-Up Command, Parameters}
+\label{SectCallConvention}
+
+AS is a command line driven program, i.e. all parameters and file
+options are to be given in the command line.
+
+A couple of message files belongs to AS (recognizable by their suffix {\tt
+MSG}) AS accesses to dynamically load the messages appropriate for the
+national language. AS searches the following directories for these files:
+\begin{itemize}
+\item{the current directory;}
+\item{the EXE-file's directory;}
+\item{the directory named in the {\tt AS\_MSGPATH} environment variable,
+ or alternitavely the directories listed in the {\tt PATH} environment
+ variable;}
+\item{the directory compiled into AS via the {\tt LIBDIR} macro.}
+\end{itemize}
+These files are {\em indispensable} for a proper operation of AS, i.e. AS
+will terminate immediately if these files are not found.
+
+The language selection (currently only German and English) is based on the
+{\tt COUNTRY} setting under DOS and OS/2 respectively on the {\tt LANG}
+environment variable under Unix.
+
+In order to fulfill \marginpar{{\em DOS}} AS's memory requirements under
+DOS, the various code generator modules of the DOS version were moved into
+an overlay which is part of the EXE file. A separate OVR file like in
+earlier versions of AS therefore dose not exist any more, AS will however
+still attempt to reduce the overlaying delays by using eventually
+available EMS or XMS memory. In case this results in
+trouble, you may suppress usage of EMS or XMS by setting the environment
+variable \tty{USEXMS} or \tty{USEEMS} to \tty{n}. E.g., it is possible to
+suppress the using of XMS by the command:
+\begin{verbatim}
+ SET USEXMS=n
+\end{verbatim}
+Since AS performs all in- and output via the operating system (and
+therefore it should run also on not 100\% compatible DOS-PC's) and
+needs some basic display control, it emits ANSI control sequences
+during the assembly.
+In case you \marginpar{{\em DOS/}} should see strange characters in the
+messages displayed by AS, your \tty{CONFIG.SYS} is obviously lacking a
+line like this:
+\begin{verbatim}
+ device=ansi.sys
+\end{verbatim}
+but the further \marginpar{{\em DPMI}} functions of AS will not be
+influenced hereby. Alternatively you are able to suppress the output of
+ANSI sequences completely by setting the environment variable
+\tty{USEANSI} to \tty{n}.
+
+The DOS extender of the DPMI version \marginpar{{\em DPMI}} can be
+influenced in its memory allocation strategies by a couple of environment
+variables; if you need to know their settings, you may look up them in the
+file \tty{DPMIUSER.DOC}. ASX is additionally able to extend the available
+memory by a swap file. To do this, set up an environment variable
+\tty{ASXSWAP} in the following way:
+\begin{verbatim}
+ SET ASXSWAP=<size>[,file name]
+\end{verbatim}
+The size specification has to be done in megabytes and \bb{has} to be done.
+The file name in contrast is optional; if it is missing, the file is
+named \tty{ASX.TMP} and placed in the current directory. In any case, the
+swap file is deleted after program end.
+
+The command line parameters can roughly be divided into three categories:
+switches, key file references (see below) and file specifications.
+Parameters of these two categories may be arbitrarily mixed in the command
+line. The assembler evaluates at first all parameters and then assembles
+the specified files. From this follow two things:
+\begin{itemize}
+\item{the specified switches affect all specified source files. If
+ several source files shall be assembled with different switches,
+ this has to be done in separate runs.}
+\item{it is possible to assemble more than one file in one shot and to
+ bring it to the top, it is allowed that the file specs contain
+ wildcards.}
+\end{itemize}
+Parameter switches are recognized by AS by starting with
+a slash (/) or hyphen (-). There are switches that are only one
+character long and additionally switches composed of a whole word.
+Whenever AS cannot interpret a switch as a whole word, it tries to
+interprete every letter as an individual switch. For example, if you
+write
+\begin{verbatim}
+ -queit
+\end{verbatim}
+instead of
+\begin{verbatim}
+ -quiet
+\end{verbatim}
+AS will take the letters \tty{q, u, e, i}, and \tty{t} as individual
+switches. Multiple-letter switches additionally have the difference to
+single-letter switches that AS will accept an arbitrary mixture of upper
+and lower casing, whereas single-letter switches may have a different
+meaning depending on whether upper or lower case is used.
+
+At the moment, the following switches are defined:
+\ttindex{SHARED}
+\begin{itemize}
+\item{\tty{l}: sends assembler listing to console terminal (mostly screen).
+ In case several passes have to be done, the listing of all
+ passes will be send to the console (in opposite to the next
+ option).}
+\item{\tty{L}: writes assembler listing into a file. The list file will get
+ the same name as the source file, only the extension is
+ replaced by \tty{LST}.}
+\item{\tty{o}: Sets the new name of the code file generated by AS. If this
+ option is used multiple times, the names will be assigned, one
+ after the other, to the source files which have to be
+ assembled. A negation (see below) of this option in
+ connection with a name erases this name from the list. A
+ negation without a name erases the whole list.}
+\item{\tty{SHAREOUT}:ditto for a SHARE file eventually to be created.}
+\item{\tty{c}: SHARED-variables will be written in a format which permits
+ an easy integration into a C-source file. The extension of
+ the file is \tty{H}.}
+\item{\tty{p}: SHARED-variables will be written in a format which permits
+ easy integration into the CONST-block of a Pascal program.
+ The extension of the file is \tty{INC}.}
+\item{\tty{a}: SHARED-variables will be written in a format which permits
+ easy integration into an assembler source file. The
+ extension of the file is \tty{INC}.}
+\end{itemize}
+Concerning effect and function of the SHARED-symbols please see
+chapters \ref{ChapShareMain} resp. \ref{ChapShareOrder}.
+\begin{itemize}
+\item{\tty{g}: This switch instructs AS to create an additional file that
+ contains debug information for the program. Allowed formats are the
+ AS-specific \tty{MAP} format, a \tty{NoICE}-compatible command file,
+ and the \tty{Atmel} format used by the AVR tools. The information
+ stored in the MAP format is comprised of a symbol table and a table
+ describing the assignment of source lines to machine addresses. A
+ more detailed description of the MAP format can be found in section
+ \ref{SectDebugFormat} The file's extension is \tty{MAP}, \tty{NOI},
+ resp. \tty{OBJ}, depending on the chosen format. If no explicit
+ format specification is done, the MAP format is chosen.}
+\item{\tty{w}: suppress issue of warnings;}
+\item{\tty{E [file]}: error messages and warnings produced by AS will be
+ redirected to a file. Instead of a file, the 5 standard
+ handles (STDIN..STDPRN) can also be specified as
+ \tty{!0} to \tty{!4} . Default is \tty{!2}, meaning STDERR. If the
+ file option is left out, the name of the error file
+ is the same as of the source file, but with the
+ extension \tty{LOG}.}
+\item{\tty{q}: This switch suppresses all messages of AS, the exceptions are
+ error messages and outputs which are are forced from the
+ source file. The time needed for assembly is slightly reduced
+ hereby and if you call AS from a shell there is no redirection
+ required. The disadvantage is that you may ''stay in the dark''
+ for several minutes ... It is valid to write \tty{quiet} instead
+ of \tty{q}.}
+\item{\tty{h}: write hexadecimal numbers in lowercase instead of capital
+ letters. This option is primarily a question of personal
+ taste.}
+\item{\tty{i $<$path list$>$}: issues a list of directories where the
+ assembler shall automatically search for include
+ files, in case it didn't find a file in the
+ current directory. The different directories
+ have to be separated by semicolons.}
+\item{\tty{u}: calculate a list of areas which are occupied in the segments.
+ This option is effective only in case a listing is
+ produced. This option requires considerable additional
+ memory and computing performance. In normal operation it
+ should be switched off.}
+\item{\tty{C}: generates a list of cross references. It lists which (global)
+ symbols are used in files and lines. This list will also be
+ generated only in case a listing is produced. This option
+ occupies, too, additional memory capacity during assembly.}
+\item{\tty{s}: issues a list of all sections (see chapter
+ \ref{ChapLocSyms}). The nesting is indicated by indentations
+ (Pascal like).}
+\item{\tty{t}: by means of this switch it is possible to separate single
+ components of the standard issued assembler-listing. The assignment
+ of bits to parts can be found in the next section, where the exact
+ format of the assembly listing is explained.}
+\item{\tty{D}: defines symbols. The symbols which are specified behind this
+ option and separated by commas are written to the
+ global symbol table before starting the assembly. As default
+ these symbols are written as integer numbers with the
+ value TRUE, by means of an appended equal sign, however, you
+ can select other values. The expression following the equals
+ sign may include operators or internal functions, but \bb{not}
+ any further symbols, even if these should have been defined
+ before in the list! Together with the commands for
+ conditional assembly (see there) you may produce different
+ program versions out of one source file by command line
+ inputs.}
+\item{\tty{A}: stores the list of global symbols in another, more compact
+ form. Use this option if the assembler crashes with a stack
+ overflow because of too long symbol tables. Sometimes this
+ option can increase the processing speed of the assembler, but
+ this depends on the sources.}
+\item{\tty{x}: Sets the level of detail for error messages. The level
+ is increased resp. decreased by one each time this option is given.
+ While on level 0 (default) only the error message itself is printed,
+ an extended message is added beginning at level 1 that should
+ simplify the identification of the error's cause. Appendix
+ \ref{ChapErrMess} lists which error messages carry which extended
+ messages. At level 2 (maximum), the source line containing the
+ error is additionally printed.}
+\item{\tty{n}: If this option is set, the error messages will be issued
+ additionally with their error number (see appendix
+ \ref{ChapErrMess}). This is primarily intended for use with shells
+ or IDE's to make the identification of errors easier by those
+ numbers.}
+\item{\tty{U}: This option switches AS to the case-sensitive mode, i.e.
+ upper and lower case in the names of symbols, sections, macros,
+ character sets, and user-defined functions will be distinguished.
+ This is not the case by default.}
+\item{\tty{P}: Instructs AS to write the source text processed by macro
+ processor and conditional assembly into a file. Additional
+ blank and pure comment lines are missing in this file. The
+ extension of this file is \tty{I}.}
+\item{\tty{M}: If this switch is given, AS generates a file, that contains
+ definitions of macros defined in the source file that did not
+ use the \tty{NOEXPORT} option. This new file has the same name as
+ the source file, only the extension is modified into \tty{MAC}.}
+\item{\tty{G}: this switch defines whether AS should produce code or not.
+ If switched off, the processing will be stopped after the macro
+ processor. This switch is activated by default (logically,
+ otherwise you would not get a code file). This switch can be
+ used in conjunction with the \tty{P} switch, if only the macro
+ processor of AS shall be used.}
+\item{\tty{r [n]}: issue warnings if situations occur that force a further
+ pass. This information can be used to reduce the number of
+ passes. You may optionally specify the number of the
+ first pass where issuing of such messages shall start.
+ Without this argument, warnings will come starting with
+ the first pass. Be prepared for a bunch of messages!!}
+\item{\tty{cpu $<$name$>$}: this switch allows to set the target processor
+ AS shall generate code for, in case the source file does not contain
+ a {\tt CPU} instruction and is not 68008 code.}
+\item{\tty{alias $<$new$>$=$<$old$>$}:
+ defines the processor type \tty{$<$new$>$} to be an alias for the
+ type \tty{$<$old$>$}. See section \ref{SectAlias} for the sense of
+ processor aliases.}
+\end{itemize}
+As long as switches require no arguments and their concatenation does
+not result in a multi-letter switch, it is possible to specify several
+switches at one time, as in the following example :
+\begin{verbatim}
+ as test*.asm firstprog -cl /i c:\as\8051\include
+\end{verbatim}
+All files \tty{TEST*.ASM} as well as the file \tty{FIRSTPROG.ASM} will be
+assembled, whereby listings of all files are displayed on the
+console terminal. Additional sharefiles will be generated in the C-
+format. The assembler should search for additional include files
+in the directory \verb!C:\AS\8051\INCLUDE!.
+
+This example shows that the assembler assumes \tty{ASM} as the default
+extension for source files.
+
+A bit of caution should be applied when using switches that have
+optional arguments: if a file specification immediately follows such
+aswitch without the optional argument, AS will try to interprete the
+file specification as argument - what of course fails:
+\begin{verbatim}
+ as -g test.asm
+\end{verbatim}
+The solution in this case would either be to move the -g option the
+end or to specify an explicit MAP argument.
+
+
+Beside from specifying options in the command line, permanently
+needed options may be placed in the environment variable \tty{ASCMD}. For
+example, if someone always wants to have assembly listings and has a
+fixed directory for include files, he can save a lot of typing with
+the following command:
+\begin{verbatim}
+ set ascmd=-L -i c:\as\8051\include
+\end{verbatim}
+The environment options are processed before the command line,
+so options in the command line can override contradicting ones in the
+environment variable.
+
+In the case of very long path names, space in the \tty{ASCMD} variable may
+become a problem. For such cases a key file may be the alternative,
+in which the options can be written in the same way as in the command
+line or the \tty{ASCMD}-variable. But this file may contain several lines
+each with a maximum length of 255 characters. In a key file it is
+important, that for options which require an argument, switches and
+argument have to be written in the \bb{same} line. AS gets informed of
+the name of the key file by a \tty{@} aheaded in the \tty{ASCMD} variable,
+e.g.
+\begin{verbatim}
+set ASCMD=@c:\as\as.key
+\end{verbatim}
+In order to neutralize options in the \tty{ASCMD} variable (or in the
+key file), prefix the option with a plus sign. For example, if you
+do not want to generate an assembly listing in an individual case,
+the option can be retracted in this way:
+\begin{verbatim}
+as +L <file>
+\end{verbatim}
+Naturally it is not consequently logical to deny an option by a
+plus sign.... UNIX soit qui mal y pense.
+
+References to key files may not only come from the {\tt ASCMD} variable,
+but also directly from the command line. Similarly to the {\tt ASCMD}
+variable, prepend the file's name with a \@ character:
+\begin{verbatim}
+ as @<file> ....
+\end{verbatim}
+The options read from a key file in this situation are processed as if
+they had been written out in the command line in place of the reference,
+{\em not} like the key file referenced by the {\tt ASCMD} variable that is
+processed prior to the command line options.
+
+Referencing a key file from a key file itself is not allowed and will be
+answered wit an error message by AS.
+
+In case that you like to start AS from another program or a shell and
+this shell hands over only lower-case or capital letters in the
+command line, the following workaround exists: if a tilde (\verb!~!) is put
+in front of an option letter, the following letter is always
+interpreted as a lower-case letter. Similarly a \tty{\#} demands the
+interpretation as a capital letter. For example, the following
+transformations result for:
+\begin{verbatim}
+ /~I ---> /i
+ -#u ---> -U
+\end{verbatim}
+In dependence of the assembly's outcome, the assembler ends with
+the following return codes:
+\begin{description}
+\item[0]{error free run, at maximum warnings occurred}
+\item[1]{The assembler displayed only its command-line parameters and
+ terminated immediately afterwards.}
+\item[2]{Errors occurred during assembly, no code file has been produced.}
+\item[3]{A fatal error occurred what led to immediate termination of the run.}
+\item[4]{An error occurred already while starting the assembler.
+ This may be a parameter error or a faulty overlay file.}
+\item[255]{An internal error occurred during initialization that should not
+ occur in any case...reboot, try again, and contact me if the
+ problem is reproducible!}
+\end{description}
+Similar to UNIX, OS/2 \marginpar{{\em OS/2}} extends an application's data
+segment on demand when the application really needs the memory.
+Therefore, an output like
+\begin{verbatim}
+ 511 KByte available memory
+\end{verbatim}
+does not indicate a shortly to come system crash due to memory lack,
+it simply shows the distance to the limit when OS/2 will push up the
+data segment's size again...
+
+As there is no compatible way in C \marginpar{{\em UNIX}} under different
+operating systens to find out the amount of available memory resp. stack,
+both lines are missing completely from the statistics the C version prints.
+
+%%---------------------------------------------------------------------------
+
+\section{Format of the Input Files}
+\label{AttrTypes}
+
+Like most assemblers, AS expects exactly one instruction per line
+(blank lines are naturally allowed as well). The lines must not be
+longer than 255 characters, additional characters are discarded.
+
+A single line has following format:
+\begin{verbatim}
+[label[:]] <mnemonic>[.attr] [param[,param..]] [;comment]
+\end{verbatim}
+The colon for the label is optional, in case the label starts in the
+first column (the consequence is that a mnemonic must not start in
+column 1). It is necessary to set the colon in case the label does
+not start in the first column so that AS is able to distinguish it
+from a mnemonic. In the latter case, there must be at least one space
+between colon and mnemonic if the processor belongs to a family that
+supports an attribute that denotes an instruction format and is
+separated from the mnemonic by a colon. This restriction is
+necessary to avoid ambiguities: a distinction between a mnemonic with
+format and a label with mnemonic would otherwise be impossible.
+
+Some signal processor families from Texas Instruments optionally use a
+double line (\verb!||!) in place of the label to signify the prallel
+execution with the previous instruction(s). If these two assembler
+instructions become a single instruction word at machine level (C3x), an
+additional label in front of the second instruction of course does not
+make sense and is not allowed. The situation is different for the C6x
+with its instruction packets of variable length: If someone wants to jump
+into the middle of an instruction packet (bad style, if you ask me...), he
+has to place the necessary label {\em before} into a separate line. The
+same is valid for conditions, which however may be combined with the
+double line in a single source line.
+
+The attribute is used by a couple of processors to specify variations or
+different codings of a certain instruction. The most prominent usage of
+the attibute is is the specification of the operand size, for example in
+the case of the 680x0 family (table \ref{TabAttrs}).
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+attribute & arithmetic-logic instruction & jump instruction\\
+\hline
+\hline
+B & byte (8 bits) & --------- \\
+W & word (16 bits) & --------- \\
+L & long word (32 bits) & 16-bit-displacement \\
+Q & quad word (64 bits) & --------- \\
+S & single precision (32 bits) & 8-bit-displacement \\
+D & double precision (64 bits) & --------- \\
+X & extended precision (80/96 bits) & 32-bit-displacement \\
+P & decimal floating point (80/96 bits) & --------- \\
+\hline
+\end{tabular}\end{center}
+\caption{Allowed Attributes (Example 680x0) \label{TabAttrs}}
+\end{table*}
+\par
+Since this manual is not also meant as a user's manual for the processor
+families supported by AS, this is unfortunately not the place to enumerate
+all possible attributes for all families. It should however be mentioned
+that in general, not all instructions of a given instruction set allow all
+attributes and that the omission of an attribute generally leads to the
+usage of the ''natural'' operand size of a processor family. For more
+thorough studies, consult a reasonable programmer's manual, e.g.
+\cite{Williams} for the 68K's.
+
+In the case of TLCS-9000, H8/500, and M16(C), the attribute serves
+both as an operand size specifier (if it is not obvious from the
+operands) and as a description of the instruction format to be used.
+A colon has to be used to separate the format from the operand size,
+e.g. like this:
+\begin{verbatim}
+ add.w:g rw10,rw8
+\end{verbatim}
+This example does not show that there may be a format specification
+without an operand size. In contrast, if an operand size is used
+without a format specification, AS will automatically use the
+shortest possible format. The allowed formats and operand sizes
+again depend on the machine instruction and may be looked up e.g. in
+\cite{Tosh900}, \cite{HitH8_5}, \cite{MitM16}, resp. \cite{MitM16C}.
+
+The number of instruction parameters depends on the mnemonic and is
+principally located between 0 and 20. The separation of the parameters
+from each other is to be performed only by commas (exception: DSP56xxx,
+its parallel data transfers are separated with blanks). Commas that
+are included in brackets or quotes, of course, are not taken into
+consideration.
+
+Instead of a comment at the end, the whole line can consist of
+comment if it starts in the first column with a semicolon.
+
+To separate the individual components you may also use tabulators
+instead of spaces.
+
+%%---------------------------------------------------------------------------
+
+\section{Format of the Listing}
+
+The listing produced by AS using the command line options i or I is
+roughly divisible into the following parts :
+\begin{enumerate}
+\item{issue of the source code assembled;}
+\item{symbol list;}
+\item{usage list;}
+\item{cross reference list.}
+\end{enumerate}
+The two last ones are only generated if they have been demanded by
+additional command line options.
+
+In the first part, AS lists the complete contents of all source files
+including the produced code. A line of this listing has the following
+form:
+\begin{verbatim}
+[<n>] <line>/<address> <code> <source>
+\end{verbatim}
+In the field \tty{n}, AS displays the include nesting level. The main file
+(the file where assembly was started) has the depth 0, an included
+file from there has depth 1 etc.. Depth 0 is not displayed.
+
+In the field \tty{line}, the source line number of the referenced file is
+issued. The first line of a file has the number 1. The address at
+which the code generated from this line is written follows after the
+slash in the field \tty{address}.
+
+The code produced is written behind \tty{address} in the field \tty{code},
+in hexadecimal notation. Depending on the processor type and actual
+segment the values are formatted either as bytes or 16/32-bit-words.
+If more code is generated than the field can take, additional lines
+will be generated, in which case only this field is used.
+
+Finally, in the field \tty{source}, the line of the source file is issued in
+its original form.
+
+The symbol table was designed in a way that it can be displayed on an
+80-column display whenever possible. For symbols of ''normal length'',
+a double column output is used. If symbols exceed (with their name
+and value) the limit of 40 columns (characters), they will be issued
+in a separate line. The output is done in alphabetical order.
+Symbols that have been defined but were never used are marked with a
+star (*) as prefix.
+
+The parts mentioned so far as well as the list of all macros/functions
+defined can be selectively masked out from the listing.
+This can be done by the already mentioned command line switch \tty{-t}.
+There is an internal byte inside AS whose bits represent which parts
+are to be written. The assignment of bits to parts of the listing is
+listed in table \ref{TabTBits}.
+\par
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+bit & part \\
+\hline
+\hline
+0 & source file(s) + produced code \\
+1 & symbol table \\
+2 & macro list \\
+3 & function list \\
+4 & line numbering \\
+5 & register symbol list \\
+7 & character set table \\
+\hline
+\end{tabular}\end{center}
+\caption{Assignment of Bits to Listing Components\label{TabTBits}}
+\end{table*}
+All bits are set to 1 by default, when using the switch
+\begin{verbatim}
+-t <mask>
+\end{verbatim}
+Bits set in \tty{$<$mask$>$} are cleared, so that the respective listing
+parts are suppressed. Accordingly it is possible to switch on single
+parts again with a plus sign, in case you had switched off too much
+with the \tty{ASCMD} variable... If someone wants to have, for example,
+only the symbol table, it is enough to write:
+\begin{verbatim}
+-t 2
+\end{verbatim}
+The usage list issues the occupied areas hexadecimally for every
+single segment. If the area has only one address, only this is written,
+otherwise the first and last address.
+
+The cross reference list issues any defined symbol in alphabetical
+order and has the following form:
+\begin{verbatim}
+ symbol <symbol name> (=<value>,<file>/<line>):
+ file <file 1>:
+ <n1>[(m1)] ..... <nk>[(mk)]
+ .
+ .
+ file <file l>:
+ <n1>[(m1)] ..... <nk>[(mk)]
+\end{verbatim}
+The cross reference list lists for every symbol in which files and lines
+it has been used. If a symbol was used several times in the same line,
+this would be indicated by a number in brackets behind the line number.
+If a symbol was never used, it would not appear in the list; The same is
+true for a file that does not contain any references for the symbol in
+question.
+
+\bb{CAUTION!} AS can only print the listing correctly if it was
+previously informed about the output media's page length and width!
+This has to be done with the \tty{PAGE} instruction (see there). The
+preset default is a length of 60 lines and an unlimited line width.
+
+%%---------------------------------------------------------------------------
+
+\section{Symbol Conventions}
+\label{SectSymConv}
+
+Symbols are allowed to be up to 255 characters long (as hinted already
+in the introduction) and are being distinguished on the whole
+length, but the symbol names have to meet some conventions:
+
+Symbol names are allowed to consist of a random combination of
+letters, digits, underlines and dots, whereby the first character must
+not be a digit. The dot is only allowed to meet the MCS-51 notation of
+register bits and should - as far as possible - not be used in own symbol
+names. To separate symbol names in any case the underline (\tty{\_}) and not
+the dot (\tty{.}) should be used .
+
+AS is by default not case-sensitive, i.e. it does not matter whether
+one uses upper or lower case characters. The command line switch \tty{U}
+however allows to switch AS into a mode where upper and lower case
+makes a difference. The predefined symbol \tty{CASESENSITIVE} signifies
+whether AS has been switched to this mode: TRUE means case-sensitiveness,
+and FALSE its absence.
+
+Table \ref{TabPredefined} shows the most important symbols which are
+predefined by AS.
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+name & meaning \\
+\hline
+\hline
+TRUE & logically ''true'' \\
+FALSE & logically ''false'' \\
+CONSTPI & Pi (3.1415.....) \\
+VERSION & version of AS in BCD-coding, \\
+ & e.g. 1331 hex for version 1.33p1 \\
+ARCHITECTURE & target platform AS was compiled for, in \\
+ & the style processor-manufacturer-operating \\
+ & system \\
+DATE & date and \\
+TIME & time of the assembly (start) \\
+MOMCPU & current target CPU \\
+ & (see the CPU instruction) \\
+MOMFILE & current source file \\
+MOMLINE & line number in source file \\
+MOMPASS & number of the currently running pass \\
+MOMSECTION & name of the current section \\
+ & or an empty string \\
+\verb!*!, \$ resp. PC & current value of program counter \\
+\hline
+\end{tabular}\end{center}
+\caption{Predefined Symbols\label{TabPredefined}}
+\end{table*}
+\bb{CAUTION!} While it does not matter in case-sensitive mode which
+combination of upper and lower case to use to reference predefined
+symbols, one has to use exactly the version given above (only upper
+case) when AS is in case-sensitive mode!
+
+Additionally some pseudo instructions define symbols that reflect the
+value that has been set with these instructions. Their descriptions
+are explained at the individual commands belonging to them.
+
+A hidden feature (that has to be used with care) is that symbol names
+may be assembled from the contents of string symbols. This can be
+achieved by framing the string symbol's name with braces and
+inserting it into the new symbol's name. This allows for example to
+define a symbol's name based on the value of another symbol:
+\begin{verbatim}
+cnt set cnt+1
+temp equ "\{CNT}"
+ jnz skip{temp}
+ .
+ .
+skip{temp}: nop
+\end{verbatim}
+\bb{CAUTION:} The programmer has to assure that only valid symbol names
+are generated!
+
+A complete list of all symbols predefined by AS can be found in
+appendix \ref{AppInternSyms}.
+
+Apart from its value, every symbol also owns a marker which signifies to
+which {\em segment} it belongs. Such a distinction is mainly needed for
+processors that have more than one address space. The additional
+information allows AS to issue a warning when a wrong instruction is used
+to access a symbol from a certain address space. A segment attribute is
+automatically added to a symbol when is gets defined via a label or a
+special instruction like \tty{BIT}; a symbol defined via the ''allround
+instructions'' \tty{SET} resp. \tty{EQU} is however ''typeless'', i.e. its
+usage will never trigger warnings. A symbol's segment attribute may be
+queried via the buit-in function \tty{SYMTYPE}, e.g.:
+\begin{verbatim}
+Label:
+ .
+ .
+Attr equ symtype(Label) ; results in 1
+\end{verbatim}
+The individual segment types have the assigned numbers listed in table
+\ref{TabSegNums}. Register symbols which do not really fit into the order
+of normal symbols are explained in section \ref{SectRegSyms}. The
+\tty{SYMTYPE} function delivers -1 as result when called with an undefined
+symbol as argument.
+\begin{table}[htb]
+\begin{center}
+\begin{tabular}{|l|c|}
+\hline
+segment & return value \\
+\hline
+$<$none$>$ & 0 \\
+CODE & 1 \\
+DATA & 2 \\
+IDATA & 3 \\
+XDATA & 4 \\
+YDATA & 5 \\
+BITDATA & 6 \\
+IO & 7 \\
+REG & 8 \\
+ROMDATA & 9 \\
+$<$register symbol$>$ & 128 \\
+\hline
+\end{tabular}
+\end{center}
+\caption{return values of the \tty{SYMTYPE} function\label{TabSegNums}}
+\end{table}
+
+%%---------------------------------------------------------------------------
+
+\section{Formula Expressions}
+
+In most places where the assembler expects numeric inputs, it is
+possible to specify not only simple symbols or constants, but also
+complete formula expressions. The components of these formula
+expressions can be either single symbols and constants. Constants may be
+either integer, floating point, or string constants.
+
+\subsection{Integer Constants}
+\label{SectIntConsts}
+
+Integer constants describe non-fractional numbers. They may either be
+written as a sequence of digits or as a sequence of characters enclosed in
+{\em single} quotation marks. In case they are written as a sequence of
+digits, this may be done in different numbering systems (table
+\ref{TabSystems}).
+\par
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|c|c|c|}
+\hline
+ & Intel mode & Motorola mode & C mode \\
+ & (Intel, Zilog, & (Rockwell, Motorola, & (PowerPC, \\
+ & Thomson Texas, & Microchip, Thomson, & AMD 29K, \\
+ & Toshiba, NEC, & Hitachi, Atmel) & National, \\
+ & Siemens, Philips, & & Symbios) \\
+ & Fujitsu, Fairchild) & & \\
+\hline
+\hline
+decimal & direct & direct & direct \\
+hexadecimal & followed by H & aheaded \$ & aheaded 0x \\
+binary & followed by B & aheaded \% & aheaded 0b \\
+octal & followed by O & aheaded @ & aheaded 0 \\
+\hline
+\end{tabular}\end{center}
+\caption{Possible Numbering Systems\label{TabSystems}}
+\end{table*}
+In case the numbering system has not been explicitly stated by adding the
+special control characters listed in the table, AS assumes the base given
+with the {\tt RADIX} statement (which has itself 10 as default). This
+statement allows to set up 'unusual' numbering systems, i.e. others than
+2, 8, 10, or 16.
+
+Valid digits are numbers from 0 to 9 and letters from A to Z (value 10 to
+35) up to the numbering system's base minus one. The usage of letters in
+integer constants however brings along some ambiguities since symbol names
+also are sequences of numbers and letters: a symbol name must not start
+with a character from 0 to 9. This means that an integer constant which
+is not clearly marked a such with a special prefix character never mav
+begin with a letter. One has to add an additional, otherwise superfluous
+zero in front in such cases. The most prominent case is the writing of
+hexadecimal constants in Intel mode: If the leftmost digit is between A
+and F, the trailing H doesn't help anything, an additional 0 has to be
+prefixed (e.g. 0F0H instead of F0H). The Motorola and C syntaxes whis
+both mark the numbering system at the front of a constant do not have this
+problem (\ii{hehehe..}).
+
+Quite tricky is furthermore that the higher the default numbering system
+set via {\tt RADIX} becomes, the more letters used to denote numbering
+systems in Intel and C syntax become 'eaten'. For example, you cannot
+write binary constants anymore after a {\tt RADIX 16}, and starting at
+{\tt RADIX 18}, the Intel syntax even doesn't allow to write hexadecimal
+constants any more. Therefore {\bf CAUTION!}
+
+With the help of the \tty{RELAXED} instruction (see section \ref{SectRELAXED}),
+the strict assignment of a syntax to a certain target processor can be
+removed. The result is that an arbitrary syntax may be used (loosing
+compatibility to standard assemblers). This option is however turned off
+by default.
+
+Integer constants may also be written as ASCII values, like in
+the following examples:
+\begin{verbatim}
+'A' ==$41
+'AB' ==$4142
+'ABCD' ==$41424344
+\end{verbatim}
+It is important to write the characters in {\em single quotes}, to
+distinguish them from string constants (discussed somewhat later).
+
+\subsection{Floating Point Constants}
+
+Floating point constants are to be written in the usual scientific
+notation, which is known in the most general form:
+\begin{verbatim}
+ [-]<integer digits>[.post decimal positions][E[-]exponent]
+\end{verbatim}
+\bb{CAUTION!} The assembler first tries to interprete a constant as an
+integer constant and makes a floating-point format try only in case
+the first one failed. If someone wants to enforce the evaluation as
+a floating point number, this can be done by dummy post decimal
+positions, e.g. \tty{2.0} instead of \tty{2}.
+
+\subsection{String Constants}
+\label{SectStringConsts}
+
+String constants have to be included in {\em double quotation} marks (to
+distinguish them from the abovementioned ASCII-integers). In order to
+make it possible to write quotation marks and special characters without
+trouble in string constants, an ''escape mechanism'' has been implemented,
+which should sound familiar for C programmers:
+
+The assembler understands a backslash (\verb!\!) with a following decimal
+number of three digits maximum in the string as a character with the
+according decimal ASCII value. The numerical value may alternitavely be
+written in hexadecimal or octal notation if it is prefixed with an x resp.
+a 0. In case of hexadecimal notation, the maximum number of digits is
+limited to 2. For example, it is possible to include an ETC character by
+writing {\tt\verb!\!3}. But be careful with the definition of NUL
+characters! The C \marginpar{{\em UNIX}} version currently uses C strings
+to store strings internally. As C strings use a NUL character for
+termination, the usage of NUL characters in strings is currently not
+portable!
+
+Some frequently used control characters can also be reached with the
+following abbreviations:
+\begin{verbatim}
+\b : Backspace \a : Bell \e : Escape
+\t : Tabulator \n : Linefeed \r : Carriage Return
+\\ : Backslash \' or \H : Apostrophe
+\" or \I : Quotation marks
+\end{verbatim}
+Both upper and lower case characters may be used for the
+identification letters.
+
+By means of this escape character, you can even work formula
+expressions into a string, if they are enclosed by braces: e.g.
+\begin{verbatim}
+ message "root of 81 : \{sqrt(81)}"
+\end{verbatim}
+results in
+\begin{verbatim}
+ root of 81 : 9
+\end{verbatim}
+AS chooses with the help of the formula result type the correct
+output format, further string constants, however, are to be avoided
+in the expression. Otherwise the assembler will get mixed up at the
+transformation of capitals into lower case letters. Integer results will
+by default be written in hexadecimal notation, which may be changed via
+the \tty{OUTRADIX} instruction.
+
+Except for the insertion of formula expressions, you can use this
+''escape-mechanism'' as well in ASCII defined integer constants,
+like this:
+\begin{verbatim}
+ move.b #'\n',d0
+\end{verbatim}
+However, everything has its limits, because the parser with higher
+priority, which disassembles a line into op-code and parameters, does
+not know what it is actually working with, e.g. here:
+\begin{verbatim}
+ move.l #'\'abc',d0
+\end{verbatim}
+After the third apostrophe, it will not find the comma any more,
+because it presumes that it is the start of a further character
+constant. An error message about a wrong parameter number is the result.
+A workaround would be to write e.g., \verb!\i! instead of \verb!\'!.
+
+\subsection{Evaluation}
+
+The calculation of intermediary results within formula expressions is
+always done with the highest available resolution, i.e. 32 bits for
+integer numbers, 80 bit for floating point numbers and 255 characters
+for strings. An possible test of value range overflows is done only
+on the final result.
+
+The portable C version \marginpar{{\em UNIX}} only supports floating
+point values up to 64 bits (resulting in a maximum value of roughly
+$10^{308}$), but in turn features integer lengths of 64 bits on some
+platforms.
+
+\subsection{Operators}
+
+The assembler provides the operands listed in table \ref{TabOps} for
+combination.
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|c|l|c|c|c|c|c|}
+\hline
+operand & function & \#operands & integer & float & string & rank \\
+\hline
+\hline
+$<>$ & inequality & 2 & yes & yes & yes & 14 \\
+$>=$ & greater or equal & 2 & yes & yes & yes & 14 \\
+$<=$ & less or equal & 2 & yes & yes & yes & 14 \\
+$<$ & truly smaller & 2 & yes & yes & yes & 14 \\
+$>$ & truly greater & 2 & yes & yes & yes & 14 \\
+$=$ & equality & 2 & yes & yes & yes & 14 \\
+$==$ & alias for $=$ & & & & & \\
+ & & & & & & \\
+$!!$ & log. XOR & 2 & yes & no & no & 13 \\
+$||$ & log. OR & 2 & yes & no & no & 12 \\
+\&\& & log. AND & 2 & yes & no & no & 11 \\
+\verb! ~~ ! & log. NOT & 1 & yes & no & no & 2 \\
+ & & & & & & \\
+- & difference & 2 & yes & yes & no & 10 \\
++ & sum & 2 & yes & yes & yes & 10 \\
+\# & modulo division & 2 & yes & no & no & 9 \\
+/ & quotient & 2 & yes*) & yes & no & 9 \\
+\verb! * ! & product & 2 & yes & yes & no & 9 \\
+\verb! ^ ! & power & 2 & yes & yes & no & 8 \\
+ & & & & & & \\
+$!$ & binary XOR & 2 & yes & no & no & 7 \\
+$|$ & binary OR & 2 & yes & no & no & 6 \\
+\& & binary AND & 2 & yes & no & no & 5 \\
+$><$ & mirror of bits & 2 & yes & no & no & 4 \\
+$>>$ & log. shift right & 2 & yes & no & no & 3 \\
+$<<$ & log. shift left & 2 & yes & no & no & 3 \\
+\verb! ~ ! & binary NOT & 1 & yes & no & no & 1 \\
+\hline
+\multicolumn{7}{|l|}{*) remainder will be discarded} \\
+\hline
+\end{tabular}\end{center}
+\caption{Operators Predefined by AS\label{TabOps}}
+\end{table*}
+''Rank'' is the priority of an operator at the separation of expressions
+into subexpressions. The operator with the highest rank will be
+evaluated at the very end. The order of evaluation can be defined by
+new bracketing.
+
+The compare operators deliver TRUE in case the condition fits,
+and FALSE in case it doesn't. For the logical operators an expression
+is TRUE in case it is not 0, otherwise it is FALSE.
+
+The mirroring of bits probably needs a little bit of explanation: the
+operator mirrors the lowest bits in the first operand and leaves the
+higher priority bits unchanged. The number of bits which is to be
+mirrored is given by the right operand and may be between 1 and 32 .
+
+A small pitfall is hidden in the binary complement: As the
+computation is always done with 32 resp. 64 bits, its application on
+e.g. 8-bit masks usually results in values taht do not fit into 8-bit
+numbers any more due to the leading ones. A binary AND with a
+fitting mask is therefore unavoidable!
+
+\subsection{Functions}
+
+In addition to the operators, the assembler defines another line of
+primarily transcendental functions with floating point arguments which are
+listed in tables \ref{TabFuncs1} and \ref{TabFuncs2}.
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+name & meaning & argument & result \\
+\hline
+\hline
+SQRT & square root & $arg \geq 0$ & floating point \\
+ & & & \\
+SIN & sine & $arg \in \rz$ & floating point \\
+COS & cosine & $arg \in \rz$ & floating point \\
+TAN & tangent & $arg \neq (2n+1)*\frac{\pi}{2}$ & floating point \\
+COT & cotangent & $arg \neq n*\pi$ & floating point \\
+ & & & \\
+ASIN & inverse sine & $\mid arg \mid \leq 1$ & floating point \\
+ACOS & inverse cosine & $\mid arg \mid \leq 1$ & floating point \\
+ATAN & inverse tangent & $arg \in \rz$ & floating point \\
+ACOT & inverse cotangent & $arg \in \rz$ & floating point \\
+ & & & \\
+EXP & exponential function & $arg \in \rz$ & floating point \\
+ALOG & 10 power of argument & $arg \in \rz$ & floating point \\
+ALD & 2 power of argument & $arg \in \rz$ & floating point \\
+SINH & hyp. sine & $arg \in \rz$ & floating point \\
+COSH & hyp. cosine & $arg \in \rz$ & floating point \\
+TANH & hyp. tangent & $arg \in \rz$ & floating point \\
+COTH & hyp. cotangent & $arg \neq 0$ & floating point \\
+ & & & \\
+LN & nat. logarithm & $arg > 0$ & floating point \\
+LOG & dec. logarithm & $arg > 0$ & floating point \\
+LD & bin. logarithm & $arg > 0$ & floating point \\
+ASINH & inv. hyp. Sine & $arg \in \rz$ & floating point \\
+ACOSH & inv. hyp. Cosine & $arg \geq 1$ & floating point \\
+ATANH & inv. hyp. Tangent & $arg < 1$ & floating point \\
+ACOTH & inv. hyp. Cotangent & $arg > 1$ & floating point \\
+ & & & \\
+INT & integer part & $arg \in \rz$ & floating point \\
+\hline
+BITCNT & number of one's & integer & integer \\
+FIRSTBIT & lowest 1-bit & integer & integer \\
+\hline
+\end{tabular}\end{center}
+\caption{Functions Predefined by AS - Part 1 (Integer and
+ Floating Point Functions \label{TabFuncs1}}
+\end{table*}
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+name & meaning & argument & result \\
+\hline
+\hline
+LASTBIT & highest 1-bit & integer & integer \\
+BITPOS & unique 1-bit & integer & integer \\
+ & & & \\
+SGN & sign (0/1/-1) & floating point & integer \\
+ & & or integer & \\
+ABS & absolute value & integer or & integer or \\
+ & & floating point & floating point \\
+TOUPPER & matching capital & integer & integer \\
+TOLOWER & matching lower case & integer & integer \\
+ & & & \\
+UPSTRING & changes all & string & string \\
+ & characters & & \\
+ & into capitals & & \\
+ & & & \\
+LOWSTRING & changes all & string & string \\
+ & characters & & \\
+ & into to lower case & & \\
+ & & & \\
+STRLEN & returns the length & string & integer \\
+ & of a string & & \\
+ & & & \\
+SUBSTR & extracts parts of a & string, & string \\
+ & string & integer, & \\
+ & & integer & \\
+STRSTR & searches a substring & string, & integer \\
+ & in a string & string & \\
+VAL & evaluates contents & string & depends on \\
+ & as expression & & argument \\
+\hline
+\end{tabular}\end{center}
+\caption{Functions Predefined by AS - Part 2 (Integer and
+ String Functions \label{TabFuncs2}}
+\end{table*}
+The functions \tty{FIRSTBIT}, \tty{LASTBIT}, and \tty{BITPOS} return -1 as
+result if no resp. not exactly one bit is set. \tty{BITPOS} additionally
+issues an error message in such a case.
+
+The string function \tty{SUBSTR} expects the source string as first
+parameter, the start position as second and the number of characters to be
+extracted as third parameter (a 0 means to extract all characters up to
+the end). \tty{STRSTR} returns the first occurence of the second string
+within the first one resp. -1 if the search pattern was not found. Both
+functions number characters in a string starting at 0!
+
+If a function expects floating point arguments, this does not mean it
+is impossible to write e.g.
+\begin{verbatim}
+ sqr2 equ sqrt(2)
+\end{verbatim}
+In such cases an automatic type conversion is engaged. In the reverse
+case the \tty{INT}-function has to be applied to convert a floating point
+number to an integer. When using this function, you have to pay
+attention that the result produced always is a signed integer and
+therefore has a value range of approximately +/-2.0E9.
+
+When AS is switched to case-sensitive mode, predefined functions may be
+accessed with an arbitrary combination of upper and lower case (in
+contrast to predefined symbols). However, in the case of user-defined
+functions (see section \ref{SectFUNCTION}), a distinction between upper
+and lower case is made. This has e.g. the result that if one defines a
+function \tty{Sin}, one can afterwards access this function via \tty{Sin}, but all
+other combinations of upper and lower case will lead to the predefined
+function.
+
+For a correct conversion \marginpar{{\em DOS/DPMI}} of lower case letters
+into capital letters a DOS version $\geq$ 3.30 is required.
+
+%%---------------------------------------------------------------------------
+
+\section{Forward References and Other Disasters}
+
+This section is the result of a significant amount of hate on the
+(legal) way some people program. This way can lead to trouble in
+conjunction with AS in some cases. The section will deal with
+so-called 'forward references'. What makes a forward reference
+different from a usual reference? To understand the difference, take
+a look at the following programming example (please excuse my bias
+for the 68000 family that is also present in the rest of this
+manual):
+\begin{verbatim}
+ move.l d0,#10
+loop: move.l d1,(a1)
+ beq skip
+ neg.l d1
+skip: move.l (a1+),d1
+ dbra d0,loop
+\end{verbatim}
+If one overlooks the loop body with its branch statement, a program
+remains that is extremely simple to assemble: the only reference is
+the branch back to the body's beginning, and as an assembler
+processes a program from the beginning to the end, the symbol's value
+is already known before it is needed the first time. If one has a
+program that only contains such backward references, one has the nice
+situation that only one pass through the source code is needed to
+generate a correct and optimal machine code. Some high level
+languages like Pascal with their strict rule that everything has to
+be defined before it is used exploit exactly this property to speed
+up the compilation.
+
+Unfortunately, things are not that simple in the case of assembler,
+because one sometimes has to jump forward in the code or there are
+reasons why one has to move variable definitions behind the code.
+For our example, this is the case for the conditional branch that is
+used to skip over another instruction. When the assembler hits the
+branch instruction in the first pass, it is confronted with the
+situation of either leaving blank all instruction fields related to
+the target address or offering a value that ''hurts noone'' via the
+formula parser (which has to evaluate the address argument). In case
+of a ''simple'' assembler that supports only one target architecture
+with a relatively small number of instructions to treat, one will
+surely prefer the first solution, but the effort for AS with its
+dozens of target architectures would have become extremely high.
+Only the second way was possible: If an unknown symbol is detected in
+the first pass, the formula parser delivers the program counter's
+current value as result! This is the only value suitable to offer an
+address to a branch instruction with unknown distance length that
+will not lead to errors. This answers also a frequently asked
+question why a first-pass listing (it will not be erased e.g. when AS
+does not start a second pass due to additional errors) partially
+shows wrong addresses in the generated binary code - they are the
+result of unresolved forward references.
+
+The example listed above however uncovers an additional difficulty of
+forward references: Depending on the distance of branch instruction
+and target in the source code, the branch may be either long or
+short. The decision however about the code length - and therefore
+about the addresses of following labels - cannot be made in the first
+pass due to missing knowledge about the target address. In case the
+programmer did not explicitly mark whether a long or short branch
+shall be used, genuine 2-pass assemblers like older versions of MASM
+from Microsoft ''solve'' the problem by reserving space for the longest
+version in the first pass (all label addresses have to be fixed after
+the first pass) and filling the remaining space with \tty{NOP}s in the
+second pass. AS versions up to 1.37 did the same before I switched
+to the multipass principle that removes the strict separation into
+two passes and allows an arbitrary number of passes. Said in detail,
+the optimal code for the assumed values is generated in the first
+pass. In case AS detects that values of symbols changed in the second
+pass due to changes in code lengths, simply a third pass is done, and
+as the second pass'es new symbol values might again shorten or
+lengthen the code, a further pass is not impossible. I have seen
+8086 programs that needed 12 passes to get everything correct and
+optimal. Unfortunately, this mechanism does not allow to specify a
+maximum number passes; I can only advise that the number of passes
+goes down when one makes more use of explicit length specifications.
+
+Especially for large programs, another situation might arise: the
+position of a forward directed branch has moved so much in the second
+pass relative to the first pass that the old label value still valid
+is out of the allowed branch distance. AS knows of such situations
+and suppresses all error messages about too long branches when it is
+clear that another pass is needed. This works for 99\% of all cases,
+but there are also constructs where the first critical instruction
+appears so early that AS had no chance up to now to recognize that
+another pass is needed. The following example constructs such a
+situation with the help of a forward reference (and was the reason
+for this section's heading...):
+\begin{verbatim}
+ cpu 6811
+
+ org $8000
+ beq skip
+ rept 60
+ ldd Var
+ endm
+skip: nop
+
+Var equ $10
+\end{verbatim}
+Due to the address position, AS assumes long addresses in the first
+pass for the \tty{LDD} instructions, what results in a code length of 180
+bytes and an out of branch error message in the second pass (at the
+point of the \tty{BEQ} instruction, the old value of \tty{skip} is still valid,
+i.e. AS does not know at this point that the code is only 120 bytes
+long in reality) is the result. The error can be avoided in three
+different ways:
+\begin{enumerate}
+\item{Explicitly tell AS to use short addressing for the \tty{LDD}
+ instructions (\tty{ldd <Var})}
+\item{Remove this damned, rotten forward reference and place the \tty{EQU}
+ statement at the beginning where it has to be (all right, I'm
+ already calming down...)}
+\item{For real die-hards: use the \tty{-Y} command line option. This
+ option tells AS to forget the error message when the address
+ change has been detected. Not pretty, but...}
+\end{enumerate}
+Another tip regarding the \tty{EQU} instruction: AS cannot know in which
+context a symbol defined with \tty{EQU} will be used, so an \tty{EQU} containing
+forward references will not be done at all in the first pass. Thus,
+if the symbol defined with \tty{EQU} gets forward-referenced in the second
+pass:
+\begin{verbatim}
+ move.l #sym2,d0
+sym2 equ sym1+5
+sym1 equ 0
+\end{verbatim}
+one gets an error message due to an undefined symbol in the second
+pass...but why on earth do people do such things?
+
+Admittedly, this was quite a lengthy excursion, but I thought it was
+necessary. Which is the essence you should learn from this section?
+\begin{enumerate}
+\item{AS always tries to generate the shortest code possible. A
+ finite number of passes is needed for this. If you do not tweak
+ AS extremely, AS will know no mercy...}
+\item{Whenever sensible and possible, explicitly specify branch and
+ address lengths. There is a chance of significantly reducing the
+ number of passes by this.}
+\item{Limit forward references to what is absolutely needed. You make
+ your and AS's live much easier this way!}
+\end{enumerate}
+
+%%---------------------------------------------------------------------------
+
+\section{Register Symbols}
+\label{SectRegSyms} \ttindex{register symbols}
+
+{\em valid for: PowerPC, M-Core, 4004, 80C16x, AVR}
+
+Sometimes it is desirable not only to assign symbolic names to memory
+addresses or constants, but also to a register, to emphasize its function
+in a certain program section. This is no problem for processors that
+treat registers simply as another address space, as this allows to use
+numeric expressions and one can use simple \tty{EQU}s to define such
+symbols. (e.g. for the MCS-96 or TMS70000). However, for most
+processors, register identifiers are fixed literals which are seperately
+treated by AS for speed reasons. A special mechanism is therefore
+necessary to define symbolic register names. A register symbol is usually
+defined via the \tty{REG} instruction, which has otherwise the same syntax
+as an \tty{EQU} definition. This however has a couple of restrictions: A
+register symbol is a pure character string stored 'as is' which may
+exclusively be used this way. For example, no arithmetic is allowed to
+calculate a register's successor, like in the following example:
+\begin{verbatim}
+myreg reg r17 ; definition of register symbol
+ addi myreg+1,3 ; does not work!
+\end{verbatim}
+Additionally, a register symbol has to be defined prior to ist first
+usage; a forward reference would have the result that AS suspects a
+forward reference to a memory location in case a register symbol is not
+found. Since the usage of memory operands is far more limited on most
+processors, a bunch of errors would be the result...
+
+Analogous to ordinary symbols, register symbols are local to sections and
+it is possible to access a register symbol from a specific section by
+appending the section's name enclosed in brackets. Due to the missing
+ability to do forward references, there is nothing like a \tty{FORWARD}
+directive, and an export by something comparable to \tty{PUBLIC} or
+\tty{GLOBAL} is also not possible since register symbols generally have
+their meaning in a small context.
+
+If there is both an ordinary and a register symbol of same name present in
+a context, the register symbol will be preferred. This is however not the
+case when the name is embedded into a complex expression (parentheses are
+sufficient!), the normal symbol will be used then.
+
+%%---------------------------------------------------------------------------
+
+\section{Sharefile}
+\label{ChapShareMain}
+\ttindex{SHARED}
+
+This function is a by-product from the old pure-68000 predecessors of
+AS, I have kept them in case someone really needs it. The basic
+problem is to access certain symbols produced during assembly,
+because possibly someone would like to access the memory of the
+target system via this address information. The assembler allows to
+export symbol values by means of \tty{SHARED} pseudo commands (see there).
+For this purpose, the assembler produces a text file with the required
+symbols and its values in the second pass. This file may be included
+into a higher-level language or another assembler program. The
+format of the text file (C, Pascal or Assembler) can be set by the
+command line switches \tty{p, c} or, \tty{a}.
+
+\bb{CAUTION!} If none of the switches is given, no file will be
+generated and it makes no difference if \tty{SHARED}-commands are in the
+source text or not!
+
+When creating a Sharefile, AS does not check if a file with the
+same name already exists, such a file will be simply overwritten.
+In my opinion a request does not make sense, because AS would
+ask at each run if it should overwrite the old version of the
+Sharefile, and that would be really annoying...
+
+%%---------------------------------------------------------------------------
+
+\section{Processor Aliases}
+\label{SectAlias}
+
+Common microcontroller families are like rabbits: They become more at
+a higher speed than you can provide support for them. Especially the
+development of processor cores as building blocks for ASICs and of
+microcontroller families with user-definable peripherals has led to a
+steeply rising number of controllers that only deviate from a
+well-known type by a slightly modified peripheral set. But the
+distinction among them is still important, e.g. for the design of
+include files that only define the appropriate subset of peripherals.
+I have struggled up to now to integrate the most important
+reperesentatives of a processor family into AS (and I will continue
+to do this), but sometimes I just cannot keep pace with the
+development...there was an urgent need for a mechanism to extend the
+list of processors by the user.
+
+The result are processor aliases: the alias command line option allows to
+define a new processor type, whose instruction set is equal to another
+processor built into AS. After switching to this processor via the
+\tty{CPU} instruction, AS behaves exactly as if the original processor had
+been used, with a single difference: the variables \tty{MOMCPU} resp.
+\tty{MOMCPUNAME} are set to the alias name, which allows to use the new
+name for differentiation, e.g. in include files.
+
+There were two reasons to realize the definition of aliases by the
+command line and not by pseudo instructions: first, it would anyway be
+difficult to put the alias definitions together with register definitions
+into a single include file, because a program that wants to use such a
+file would have to include it before and after the CPU instruction - an
+imagination that lies somewhere between inelegant and impossible. Second,
+the definition in the command line allows to put the definitions in a key
+file that is executed automatically at startup via the \tty{ASCMD}
+variable, without a need for the program to take any further care about
+this.
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Pseudo Instructions}
+
+Not all pseudo instructions are defined for all processors. A note
+that shows the range of validity is therefore prepended to every
+individual description.
+
+%%---------------------------------------------------------------------------
+
+\section{Definitions}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SET and EQU}
+\ttindex{SET}\ttindex{EQU}
+
+{\em valid for: all processors}
+
+\tty{SET} and \tty{EQU} allow the definition of typeless constants, i.e. they
+will not be assigned to a segment and their usage will not generate warnings
+because of segment mixing. \tty{EQU} defines constants which can not be
+modified (by \tty{EQU}) again, but \tty{SET} permits the definition of
+variables, which can be modified during the assembly. This is useful e.g.
+for the allocation of resources like interrupt vectors, as shown in the
+following example:
+\begin{verbatim}
+VecCnt set 0 ; somewhere at the beginning
+ .
+ .
+ .
+DefVec macro Name ; allocate a new vector
+Name equ VecCnt
+VecCnt set VecCnt+4
+ endm
+ .
+ .
+ .
+ DefVec Vec1 ; results in Vec1=0
+ DefVec Vec2 ; results in Vec2=4
+\end{verbatim}
+constants and variables are internally stored in the same way, the only
+difference is that they can be modified by \tty{SET} and not by
+\tty{EQU}. It is therefore possible to define a symbol with \tty{EQU} and
+to change it with \tty{SET} (even if this is not its real business).
+There is also another reason to avoid this explicitly: In contrast to
+\tty{SET}, \tty{EQU} checks whether the newly assigned value is different
+to from a value that previously might have existed. As the value should
+not change for constants defined with \tty{EQU}, AS assumes a phase error
+and starts another pass...for example, if one would use \tty{EQU} instead of
+\tty{SET} to initialize the counter in the previous example, AS would not
+quarrel as a single reassignment per pass is valid (this line is executed
+only $n$ times in $n$ passes), but endless repassing would be the result as
+the counter's initial value is always different to the final value in the
+previous pass.
+
+\tty{EQU/SET} allow to define constants of all possible types, e.g.
+\begin{verbatim}
+IntTwo equ 2
+FloatTwo equ 2.0
+\end{verbatim}
+Some processors unfortunately have already a \tty{SET} instruction. For
+these targets, \tty{EVAL} must be used instead of \tty{SET}.
+
+A simple equation sign may be used instead of \tty{EQU}. Similarly, one
+may simply write \tty{:=} instead of \tty{SET} resp. \tty{EVAL}.
+
+Symbols defined with \tty{SET} or \tty{EQU} are typeless by default, but
+optionally a segment name (\tty{CODE, DATA, IDATA, XDATA, YDATA, BITDATA,
+IO}, or \tty{REG}) or \tty{MOMSEGMENT} for the currently active segment
+may be given as a second parameter, allowing to assign the symbol to a
+specific address space. AS does not check at this point if the used
+address space exists on the currently active target processor!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SFR and SFRB}
+\ttindex{SFR}\ttindex{SFRB}
+
+{\em valid for: various, \tty{SFRB} only MCS-51}
+
+These instructions act like \tty{EQU}, but symbols defined with them are
+assigned to the directly addressable data segment, i.e. they serve
+preferential for the definition of RAM-cells and (as the name lets guess)
+hardware registers mapped into the data area. The allowed range of values
+is equal to the range allowed for \tty{ORG} in the data segment (see
+section \ref{SectORG}). The difference between \tty{SFR} and \tty{SFRB}
+is that \tty{SFRB} marks the register as bit addressable, which is why AS
+generates 8 additional symbols which will be assigned to the bit segment
+and carry the names xx.0 to xx.7, e.g.
+\begin{verbatim}
+PSW sfr 0d0h ; results in PSW = D0H (data segment)
+
+PSW sfrb 0d0h ; results in extra PSW.0 = D0H (bit)
+ ; to PSW.7 = D7H (bit)
+\end{verbatim}
+The \tty{SFRB} instruction is not any more defined for the 80C251 as it
+allows direct bit access to all SFRs without special bit symbols; bits
+like \tty{PSW.0} to \tty{PSW.7} are automatically present.
+
+Whenever a bit-addressable register is defined via \tty{SFRB}, AS checks
+if the memory address is bit addressable (range 20h..3fh resp. 80h, 88h,
+90h, 98h...0f8h). If it is not bit-addressable, a warning is issued and
+the generated bit symbols are undefined.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{XSFR and YSFR}
+\ttindex{XSFR}\ttindex{YSFR}
+
+{\em valid for: DSP56xxx}
+
+Also the DSP56000 has a few peripheral registers memory-mapped to the RAM,
+but the affair becomes complicated because there are two data areas, the
+X- and Y-area. This architecture allows on the one hand a higher
+parallelism, but forces on the other hand to divide the normal \tty{SFR}
+instruction into the two above mentioned variations. They works
+identically to \tty{SFR}, just that \tty{XSFR} defines a symbol in the X-
+addressing space and YSFR a corresponding one in the Y-addressing space.
+The allowed value range is 0..\$ffff.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LABEL}
+\ttindex{LABEL}
+
+{\em valid for: all processors}
+
+The function of the \tty{LABEL} instruction is identical to \tty{EQU}, but
+the symbol does not become typeless, it gets the attribute ''code''.
+\tty{LABEL} is needed exactly for one purpose: Labels are normally local
+in macros, that means they are not accessible outside of a macro. With an
+\tty{EQU} instruction you could get out of it nicely, but the phrasing
+\begin{verbatim}
+<name> label $
+\end{verbatim}
+generates a symbol with correct attributes.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BIT}
+\ttindex{BIT}
+
+{\em valid for: MCS/(2)51, XA, 80C166, 75K0, ST9}
+
+\tty{BIT} serves to equate a single bit of a memory cell with a symbolic
+name. This instruction varies from target platform to target platform due
+to the different ways in which processors handle bit manipulation and
+addressing:
+
+The MCS/51 family has an own address space for bit operands. The function
+of \tty{BIT} is therefore quite similar to \tty{SFR}, i.e. a simple integer
+symbol with the specified value is generated and assigned to the
+\tty{BDATA} segment. For all other processors, bit addressing is done in
+a two-dimensional fashion with address and bit position. In these cases,
+AS packs both parts into an integer symbol in a way that depends on the
+currently active target processor and separates both parts again when the
+symbol is used. The latter is is also valid for the 80C251: While an
+instruction like
+\begin{verbatim}
+My_Carry bit PSW.7
+\end{verbatim}
+would assign the value 0d7h to \tty{My\_Carry} on an 8051, a value of
+070000d0h would be generated on an 80C251, i.e. the address is located in
+bits 0..7 and the bit position in bits 24..26. This procedure is equal to
+the way the \tty{DBIT} instruction handles things on a TMS370 and is also
+used on the 80C166, with the only difference that bit positions may range
+from 0..15:
+\begin{verbatim}
+MSB BIT r5.15
+\end{verbatim}
+On a Philips XA, the bit's address is located in bits 0..9 just with
+the same coding as used in machine instructions, and the 64K bank of
+bits in RAM memory is placed in bits 16..23.
+
+The \tty{BIT} instruction of the 75K0 family even goes further: As bit
+expressions may not only use absolute base addresses, even expressions
+like
+\begin{verbatim}
+bit1 BIT @h+5.2
+\end{verbatim}
+are allowed.
+
+The ST9 in turn allows to invert bits, what is also allowed in the
+\tty{BIT} instruction:
+\begin{verbatim}
+invbit BIT r6.!3
+\end{verbatim}
+More about the ST9's \tty{BIT} instruction can be found in the processor
+specific hints.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DBIT}
+\ttindex{DBIT}
+
+{\em valid for: TMS 370xxx}
+
+Though the TMS370 series does not have an explicit bit segment, single bit
+symbols may be simulated with this instruction. \tty{DBIT} requires two
+operands, the address of the memory cell that contains the bit and the
+exact position of the bit in the byte. For example,
+\begin{verbatim}
+INT3 EQU P019
+INT3_ENABLE DBIT 0,INT3
+\end{verbatim}
+defines the bit that enables interrupts via the INT3 pin. Bits defined
+this way may be used in the instructions \tty{SBIT0, SBIT1, CMPBIT,
+JBIT0}, and \tty{JBIT}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PORT}
+\ttindex{PORT}
+
+{\em valid for: 8080/8085/8086, XA, Z80, 320xx, TLCS-47, AVR}
+
+\tty{PORT} works similar to \tty{EQU}, just the symbol becomes assigned to the
+I/O-address range. Allowed values are 0..7 at the 3201x, 0..15 at the
+320C2x, 0..65535 at the 8086, 0..63 at the AVR, and 0..255 at the rest.
+
+Example : an 8255 PIO is located at address 20H:
+\begin{verbatim}
+PIO_port_A port 20h
+PIO_port_B port PIO_port_A+1
+PIO_port_C port PIO_port_A+2
+PIO_ctrl port PIO_port_A+3
+\end{verbatim}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{REG}
+\ttindex{REG}
+
+{\em valid for: AVR, M*Core, ST9, 80C16x}
+
+Though it always has the same syntax, this instruction has a slightly
+different meaning from processor to processor: If the processor uses a
+separate addressing space for registers, \tty{REG} has the same effect as
+a simple \tty{EQU} for this address space (e.g. for the ST9). \tty{REG}
+defines register symbols for all other processors whose function is
+described in section \ref{SectRegSyms}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LIV and RIV}
+\ttindex{LIV}\ttindex{RIV}
+
+{\em valid for: 8X30x}
+
+\tty{LIV} and \tty{RIV} allow to define so-called ''IV bus objects''.
+These are
+groups of bits located in a peripheral memory cell with a length of 1
+up to 8 bits, which can afterwards be referenced symbolically. The
+result is that one does not anymore have to specify address,
+position, and length separately for instructions that can refer to
+peripheral bit groups. As the 8X30x processors feature two
+peripheral address spaces (a ''left'' and a ''right'' one), there are two
+separate pseudo instructions. The parameters of these instructions
+are however equal: three parameters have to be given that specify
+address, start position and length. Further hints for the usage of
+bus objects can be found in section \ref{8X30xSpec} .
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{CHARSET}
+\ttindex{CHARSET}
+
+{\em valid for: all processors}
+
+Single board systems, especially when driving LCDs, frequently use
+character sets different to ASCII. So it is probably purely coincidental
+that the umlaut coding corresponds with the one used by the PC. To avoid
+error-prone manual encoding, the assembler contains a translation table
+for characters which assigns a target character to each source-code. To
+modify this table (which initial translates 1:1), one has to use the
+\tty{CHARSET} instruction. \tty{CHARSET} may be used with different
+numbers and types of parameters. If there is only a single parameter, it
+has to be a string expression which is interpreted as a file name by AS.
+AS reads the first 256 bytes from this table and copies them into the
+translation table. This allows to activate complex, externally generated
+tables with a single statement. For all other variants, the first
+parameter has to be an integer in the range of 0 to 255 which designates
+the start index of the entries to be modified in the translation table.
+One or two parameters follow, giving the type of modification:
+
+A single additional integer modies exactly one entry. For example,
+\begin{quote}{\tt
+ CHARSET '\"a',128
+}\end{quote}
+means that the target system codes the '\"a' into the number 128
+(80H). If however two more integers are given, the first one describes
+the last entry to be modified, and the second the new value of the first
+table entry. All entries up to the index end are loaded sequentially.
+For example, in case that the target system does not support lower-case
+characters, a simple
+\begin{verbatim}
+ CHARSET 'a','z','A'
+\end{verbatim}
+translates all lower-case characters automatically into the
+matching capital letters.
+
+For the last variant, a string follows the start index and contains the
+characters to be placed in the table. The last example therefore may also
+be written as
+\begin{verbatim}
+ CHARSET 'a',"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+\end{verbatim}
+
+\tty{CHARSET} may also be called without any parameters, which however has
+a drastical effect: the translation table is reinitialized to its initial
+state, i.e. all character translations are removed.
+
+\bb{CAUTION!} \tty{CHARSET} not only affects string constants stored in
+memory, but also integer constants written as ''ASCII''. This means that
+an already modified translation table can lead to other results in the
+above mentioned examples!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{CODEPAGE}
+\ttindex{CODEPAGE}
+
+{\em valid for: all processors}
+
+Though the \tty{CHARSET} statement gives unlimited freedom in the
+character assignment between host and target platform, switching among
+different character {\em sets} can become quite tedious if several
+character sets have to be supported on the target platform. The
+\tty{CODEPAGE} instruction however allows to define and keep different
+character sets and to switch with a single statement among them.
+\tty{CODEPAGE} expects one or two arguments: the name of the set to be
+used hereafter and optionally the name of another table that defines its
+initial contents (the second parameter therefore only has a meaning for
+the first switch to the table when AS automatically creates it). If the
+second parameter is missing, the initial contents of the new table are
+copied from the previously active set. All subsequent \tty{CHARSET}
+statements {\em only} modify the new set.
+
+At the beginning of a pass, AS automatically creates a single character
+set with the name \tty{STANDARD} with a one-to-one translation. If no
+\tty{CODEPAGE} instructions are used, all settings made via \tty{CHARSET}
+refer to this table.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ENUM}
+\ttindex{ENUM}
+
+{\em valid for: all processors}
+
+Similar to the same-named instruction known from C, \tty{ENUM} is used to
+define enumeration types, i.e. a sequence of integer constants that
+are assigned sequential values starting at 0. The parameters are the
+names of the symbols, like in the following example:
+\begin{verbatim}
+ ENUM SymA,SymB,SymC
+\end{verbatim}
+This instruction will assign the values 0, 1, and 2 to the symbols
+\tty{SymA, SymB,} and \tty{SymC}.
+
+\tty{ENUM} instructions are always single-line instructions, i.e. the
+enumeration will again start at zero when a new \tty{ENUM} instruction is
+found. Multi-line enumerations may however be achieved with a small trick
+that exploits the fact that the internal counter can be set to a new value
+with an explicit assignment, like in the following case:
+\begin{verbatim}
+ ENUM January=1,February,March,April,May,June
+\end{verbatim}
+The numeric values 1..6 are assigned to month names. One can
+continue the enumeration in the following way:
+\begin{verbatim}
+ ENUM July=June+1,August,September,October
+ ENUM November=October+1,December
+\end{verbatim}
+A definition of a symbol with \tty{ENUM} is equal to a definition with
+\tty{EQU}, i.e. it is not possible to assign a new value to a symbol that
+already exists.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{STRUCT and ENDSTRUCT}
+\ttindex{STRUCT}\ttindex{ENDSTRUCT}
+
+{\em valid for: all processors}
+
+Even for assembler programs, there is from time to time the need to
+define complex data structures similar to high-level languages. AS
+supports this via the instructions \tty{STRUCT} and \tty{ENDSTRUCT} that begin
+resp. finish the definition of such a structure. The operation is
+simple: Upon occurrence of a \tty{STRUCT}, the current value of the program
+counter is saved and the PC is reset to zero. By doing so, all
+labels placed obtain the offset values of the structure's members.
+The reservation of space for the individual fields is done with the
+instructions used on the currently active processor to reserve memory
+space, e.g. \tty{DS.x} for Motorolas and \tty{DB} \& co. for Intels. The label
+prepended to \tty{STRUCT} (not optional) is the record's name and may
+optionally be repeated for the \tty{ENDSTRUCT} statement. \tty{ENDSTRUCT}
+furthermore places the record's total length in the symbol
+\tty{$<$Name\_len$>$}
+(one may force the usage of another symbol by giving its name as an
+argument to \tty{ENDSTRUCT}). For example, in the definition
+\begin{verbatim}
+Rec STRUCT
+Ident db ?
+Pad db ?
+Pointer dd ?
+Rec ENDSTRUCT
+\end{verbatim}
+the symbol \tty{Rec\_len} would obtain the value 6. \bb{CAUTION!} Inside
+of a structure definition, no instructions may be used that generate code,
+as this is a pure placement of elements in the address space!
+
+\tty{STRUCT} definitions may be nested; after the inner \tty{STRUCT} definition
+has been ended, the address counter of the outer structure will be
+automatically incremented by the inner structure's size (the counting
+inside the inner structure of course starts at zero).
+
+To avoid ambiguities when fields in different structures have same
+names, AS by default prepends the structures name to the field names,
+separated by an underbar. For the example listed above, the symbols
+\tty{Rec\_Ident, Rec\_Pad,} and \tty{Rec\_Pointer} would be created. This
+behaviour can be suppressed by giving \tty{NOEXTNAMES} as a parameter to
+the \tty{STRUCT} statement. This works in the same sense for nested
+structure definitions, i.e. field names are extended by the names of all
+structures that did not obtain a \tty{NOEXTNAMES} directive.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PUSHV and POPV}
+\ttindex{PUSHV}\ttindex{POPV}
+
+{\em valid for: all processors}
+
+\tty{PUSHV} and \tty{POPV} allow to temporarily save the value of a symbol
+(that is not macro-local) and to restore it at a later point of time. The
+storage is done on stacks, i.e. Last-In-First-Out memory structures. A
+stack has a name that has to fulfill the general rules for symbol names
+and it exists as long as it contains at least one element: a stack that
+did not exist before is automatically created upon \tty{PUSHV}, and a
+stack becoming empty upon a \tty{POPV} is deleted automatically. The name
+of the stack that shall be used to save or restore symbols is the first
+parameter of \tty{PUSH} resp. \tty{POPV}, followed by a list of symbols as
+further parameters. All symbols referenced in the list already have to
+exist, it is therefore \bb{not} possible to implicitly define symbols with
+a \tty{POPV} instruction.
+
+Stacks are a global resource, i.e. their names are not local to
+sections.
+
+It is important to note that symbol lists are \bb{always} processed from
+left to right. Someone who wants to pop several variables from a stack
+with a \tty{POPV} therefore has to use the exact reverse order used in the
+corresponding \tty{PUSHV}!
+
+The name of the stack may be left blank, like this:
+\begin{verbatim}
+ pushv ,var1,var2,var3
+ .
+ .
+ popv ,var3,var2,var1
+\end{verbatim}
+AS will then use a predefined internal default stack.
+
+AS checks at the end of a pass if there are stacks that are not empty and
+issues their names together with their ''filling level''. This allows to
+find out if there are any unpaired \tty{PUSHVs} or \tty{POPVs}. However,
+it is in no case possible to save values in a stack beyond the end of a
+pass: all stacks are cleared at the beginning of a pass!
+
+%%---------------------------------------------------------------------------
+
+\section{Code Modification}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ORG}
+\label{SectORG}
+\ttindex{ORG}
+
+{\em valid for: all processors}
+
+\tty{ORG} allows to load the internal address counter (of the assembler)
+with a new value. The value range depends on the currently selected
+segment and on the processor type (tables \ref{TabORG1} to \ref{TabORG4}).
+The lower bound is always zero, and the upper bound is the given value
+minus 1:
+\small
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
+\hline
+\tin{processor} & \tin{CODE} & \tin{DATA} & \tin{IDATA} & \tin{XDATA} & \tin{YDATA} & \tin{BITDATA} & \tin{IO} & \tin{REG} & \tin{ROMDATA} \\
+\hline
+\hline
+\input{../doc_DE/taborg1.tex}
+\hline
+\end{tabular}\end{center}
+\caption{Address Ranges for \tty{ORG} --- Part 1\label{TabORG1}}
+\end{table*}
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
+\hline
+\tin{processor} & \tin{CODE} & \tin{DATA} & \tin{IDATA} & \tin{XDATA} & \tin{YDATA} & \tin{BITDATA} & \tin{IO} & \tin{REG} & \tin{ROMDATA} \\
+\hline
+\hline
+\input{../doc_DE/taborg2.tex}
+\hline
+\multicolumn{10}{|l|}{*) As the 8051 does not have any RAM beyond 80h, this value has to be} \\
+\multicolumn{10}{|l|}{ adapted with ORG for the 8051 as target processor!!}\\
+\hline
+\multicolumn{10}{|l|}{+) As the Z180 still can address only 64K logically, the whole}\\
+\multicolumn{10}{|l|}{ address space can only be reached via \tty{PHASE} instructions!}\\
+\hline
+\end{tabular}\end{center}
+\caption{Address Ranges for \tty{ORG} --- Part 2\label{TabORG2}}
+\end{table*}
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
+\hline
+\tin{processor} & \tin{CODE} & \tin{DATA} & \tin{IDATA} & \tin{XDATA} & \tin{YDATA} & \tin{BITDATA} & \tin{IO} & \tin{REG} & \tin{ROMDATA} \\
+\hline
+\hline
+\input{../doc_DE/taborg3.tex}
+\hline
+\end{tabular}\end{center}
+\caption{Address Ranges for \tty{ORG} --- Part 3\label{TabORG3}}
+\end{table*}
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
+\hline
+\tin{processor} & \tin{CODE} & \tin{DATA} & \tin{IDATA} & \tin{XDATA} & \tin{YDATA} & \tin{BITDATA} & \tin{IO} & \tin{REG} & \tin{ROMDATA} \\
+\hline
+\hline
+\input{../doc_DE/taborg4.tex}
+\hline
+\end{tabular}\end{center}
+\caption{Address Ranges for \tty{ORG} --- Part 4\label{TabORG4}}
+\end{table*}
+\normalsize
+
+In case that different variations in a processor family have address
+spaces of different size, the maximum range is listed for each.
+
+\tty{ORG} is mostly needed to give the code a new starting address or to
+put different, non-continuous code parts into one source file. In case
+there is no explicit other value listet in a table entry, the initial
+address for this segment (i.e. the start address used without {\tt ORG})
+is 0.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{CPU}
+\ttindex{CPU}
+
+{\em valid for: all processors}
+
+This command rules for which processor the further code shall be
+generated. Instructions of other processor families are not
+accessible afterwards and will produce error messages!
+
+The processors can roughly be distinguished in families, inside the
+families different types additionally serve for a detailed
+distinction:
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+a) \> 68008 $\rightarrow$ 68000 $\rightarrow$ 68010 $\rightarrow$ 68012 $\rightarrow$ \\
+ \> MCF5200 $\rightarrow$ 68332 $\rightarrow$ 68340 $\rightarrow$ 68360 $\rightarrow$ \\
+ \> 68020 $\rightarrow$ 68030 $\rightarrow$ 68040
+\end{tabbing}
+\end{quote}
+The differences in this family lie in additional instructions and
+addressing modes (starting from the 68020). A small exception is the step
+to the 68030 that misses two instructions: \tty{CALLM} and \tty{RTM}. The
+three representors of the 683xx family have the same processor core (a
+slightly reduced 68020 CPU), however completely different peripherals.
+MCF5200 represents the ColdFire family from Motorola, RISC processors
+downwardly binary compatible to the 680x0. For the 68040, additional
+control registers (reachable via \tty{MOVEC}) and instructions for control
+of the on-chip MMU and caches were added.
+%%-----------
+\begin{quote}
+b) 56000 $\longrightarrow$ 56002 $\longrightarrow$ 56300
+\end{quote}
+While the 56002 only adds instructions for incrementing and decrementing
+the accumulators, the 56300 core is almost a new processor: all address
+spaces are enlarged from 64K words to 16M and the number of instructions
+almost has been doubled.
+%%-----------
+\begin{quote}
+c) PPC403 $\rightarrow$ MPPC403 $\rightarrow$ MPC505 $\rightarrow$ MPC601 $\rightarrow$ RS6000
+\end{quote}
+The PPC403 is a reduced version of the PowerPC line without a floating
+point unit, which is why all floating point instructions are disabled for
+him; in turn, some microcontroller-specific instructions have been added
+which are unique in this family. The GC variant of the PPC403
+incorporates an additional MMU and has therefore some additional
+instructions for its control. The MPC505 (a microcontroller variant
+without a FPU) only differ in its peripheral registers from the 601 as
+long as I do not know it better - \cite{Mot505} is a bit reluctant in this
+respect... The RS6000 line knows a few instructions more (that are
+emulated on many 601-based systems), IBM additionally uses different
+mnemonics for their pure workstation processors, as a reminiscence of 370
+mainframes...
+%%-----------
+\begin{quote}
+d) MCORE
+\end{quote}
+%%-----------
+\begin{quote}
+e) 6800 $\rightarrow$ 6301 $\rightarrow$ 6811
+\end{quote}
+While the 6301 only offers a few additional instructions, the 6811
+delivers a second index register and much more instructions.
+%%-----------
+\begin{quote}
+f) 6809/6309 and 6805/68HC08
+\end{quote}
+These processors are partially source-code compatible to the other
+68xx processors, but they have a different binary code format and a
+significantly reduced (6805) resp. enhanced (6809) instruction set.
+The 6309 is a CMOS version of the 6809 which is officially only
+compatible to the 6809, but inofficially offers more registers and a
+lot of new instructions (see \cite{Kaku}).
+%%-----------
+\begin{quote}
+g) 68HC12
+\end{quote}
+%%-----------
+\begin{quote}
+h) 68HC16
+\end{quote}
+%%-----------
+\begin{quote}
+i) HD6413308 $\rightarrow$ HD6413309
+\end{quote}
+These both names represent the 300 and 300H variants of the H8
+family; the H version owns a larger address space (16Mbytes instead
+of 64Kbytes), double-width registers (32 bits), and knows a few more
+instructions and addressing modes. It is still binary upward
+compatible.
+%%-----------
+\begin{quote}
+j) HD6475328 $\rightarrow$ HD6475348 $\rightarrow$ HD6475368 $\rightarrow$ HD6475388
+\end{quote}
+These processors all share the same CPU core; the different types are
+only needed to include the correct subset of registers in the file
+\tty{REG53X.INC}.
+%%-----------
+\begin{quote}
+k) SH7000 $\rightarrow$ SH7600 $\longrightarrow$ SH7700
+\end{quote}
+The processor core of the 7600 offers a few more instructions that
+close gaps in the 7000's instruction set (delayed conditional and
+relative and indirect jumps, multiplications with 32-bit operands and
+multiply/add instructions). The 7700 series (also known as SH3)
+furthermore offers a second register bank, better shift instructions, and
+instructions to control the cache.
+%%-----------
+\begin{quote}
+l) 6502 $\rightarrow$ 65(S)C02 / MELPS740 / 6502UNDOC
+\end{quote}
+The CMOS version defines some additional instructions, as well as a number of
+some instruction/addressing mode combinations were added which were not
+possible on the 6502. The Mitsubishi micro controllers in opposite expand
+the 6502 instruction set primarily to bit operations and multiplication /
+division instructions. Except for the unconditional jump and instructions
+to increment/decrement the accumulator, the instruction extensions are
+orthogonal. The 65SC02 lacks the bit manipulation instructions of the
+65C02. The 6502UNDOC processor type enables access to the "undocumented"
+6502 instructions, i.e. the operations that result from the usage of bit
+combinations in the opcode that are not defined as instructions. The
+variants supported by AS are listed in the appendix containing processor-specific
+hints.
+%%-----------
+\begin{quote}
+m) MELPS7700, 65816
+\end{quote}
+Apart from a '16-bit-version' of the 6502's instruction set, these
+processors both offer some instruction set extensions. These are
+however orthogonal as they are oriented along their 8-bit
+predecessors (65C02 resp. MELPS-740). Partially, different
+mnemonics are used for the same operations.
+%%-----------
+\begin{quote}
+n) MELPS4500
+\end{quote}
+%%-----------
+\begin{quote}
+o) M16
+\end{quote}
+%%-----------
+\begin{quote}
+p) M16C
+\end{quote}
+%%-----------
+\begin{quote}
+q) 4004
+\end{quote}
+%%-----------
+\begin{quote}
+r) 8021, 8022, 8039, 80C39, 8048, 80C48, 8041, 8042
+\end{quote}
+For the ROM-less versions 8039 and 80C39, the commands which are
+using the BUS (port 0) are forbidden. The 8021 and 8022 are special
+versions with a strongly shrinked instruction set, for which the 8022
+has two A/D- converters and the necessary control-commands. It is
+possible to transfer the CMOS-versions with the \tty{IDL}-command into a
+stop mode with lower current consumption. The 8041 and 8042 have
+some additional instructions for controlling the bus interface, but
+in turn a few other commands were omitted. Moreover, the code
+address space of these processors is not externally extendable,
+and so AS limits the code segment of these processors to 1 resp. 2
+Kbytes.
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+s) \> 87C750 $\rightarrow$ 8051, 8052, 80C320, 80C501, 80C502, \\
+ \> 80C504, 80515, and 80517 $\rightarrow$ 80C251
+\end{tabbing}
+\end{quote}
+The 87C750 can only access a maximum of 2 Kbytes program memory which is
+why it lacks the \tty{LCALL} and \tty{LJMP} instructions. AS does not
+make any distinction among the processors in the middle, instead it only
+stores the different names in the \tty{MOMCPU} variable (see below), which
+allows to query the setting with \tty{IF} instructions. An exception is
+the 80C504 that has a mask flaw in its current versions. This flaw shows
+up when an \tty{AJMP} or \tty{ACALL} instruction starts at the second last
+address of a 2K page. AS will automatically use long instructions or
+issues an error message in such situations. The 80C251 in contrast
+represents a drastic progress in the the direction 16/32 bits, larger
+address spaces, and a more orthogonal instruction set.
+%%-----------
+\begin{quote}
+t) 8096 $\rightarrow$ 80196 $\rightarrow$ 80196N $\rightarrow$ 80296
+\end{quote}
+Apart from a different set of SFRs (which however strongly vary from
+version to version), the 80196 knows several new instructions and
+supports a 'windowing' mechanism to access the larger internal RAM.
+The 80196N family extends the address space to 16 Mbytes and
+introduces a set of instructions to access addresses beyond 64Kbytes.
+The 80296 extends the CPU core by instructions for signal processing
+and a second windowing register, however removes the Peripheral
+Transaction Server (PTS) and therefore looses again two machine
+instructions.
+%%-----------
+\begin{quote}
+u) 8080 and 8085
+\end{quote}
+The 8085 knows the additional commands \tty{RIM} and \tty{SIM} for
+controlling the interrupt mask and the two I/O-pins.
+%%-----------
+\begin{quote}
+v) 8086 $\rightarrow$ 80186 $\rightarrow$ V30 $\rightarrow$ V35
+\end{quote}
+Only new instructions are added in this family. The corresponding
+8-bit versions are not mentioned due to their instruction
+compatibility, so one e.g. has to choose 8086 for an 8088-based
+system.
+%%-----------
+\begin{quote}
+w) 80960
+\end{quote}
+%%-----------
+\begin{quote}
+x) 8X300 $\rightarrow$ 8X305
+\end{quote}
+The 8X305 features a couple of additional registers that miss on the
+8X300. Additionally, it can do new operations with these registers
+(like direct writing of 8 bit values to peripheral addresses).
+%%-----------
+\begin{quote}
+y) XAG1, XAG2, XAG3
+\end{quote}
+These processors only differ in the size of their internal ROM which
+is defined in \tty{STDDEFXA.INC}.
+%%-----------
+\begin{quote}
+z) AT90S1200 $\rightarrow$ AT90S2313 $\rightarrow$ AT90S4414 $\rightarrow$
+ AT90S8515
+\end{quote}
+The first member of the AVR series represents a minimum configuration
+without RAM memory and therefore lacks load/store instructions. The
+other two processors only differ in their memory equipment and
+on-chip peripherals, what is differentiated in \tty{REGAVR.INC}.
+%%-----------
+\begin{quote}
+aa) AM29245 $\rightarrow$ AM29243 $\rightarrow$ AM29240 $\rightarrow$ AM29000
+\end{quote}
+The further one moves to the right in this list, the fewer the
+instructions become that have to be emulated in software. While e.g.
+the 29245 not even owns a hardware multiplier, the two representors in
+the middle only lack the floating point instructions. The 29000
+serves as a 'generic' type that understands all instructions in
+hardware.
+%%-----------
+\begin{quote}
+ab) 80C166 $\rightarrow$ 80C167,80C165,80C163
+\end{quote}
+80C167 and 80C165/163 have an address space of 16 Mbytes instead of 256
+Kbytes, and furthermore they know some additional instructions for
+extended addressing modes and atomic instruction sequences. They are
+'second generation' processors and differ from each other only in the
+amount of on-chip peripherals.
+%%-----------
+\begin{quote}
+ac) Z80 $\rightarrow$ Z80UNDOC $\rightarrow$ Z180 $\rightarrow$ Z380
+\end{quote}
+While there are only a few additional instructions for the Z180, the
+Z380 owns 32-bit registers, a linear address space of 4 Gbytes, a
+couple of instruction set extensions that make the overall
+instruction set considerably more orthogonal, and new addressing
+modes (referring to index register halves, stack relative). These
+extensions partially already exist on the Z80 as undocumented
+extensions and may be switched on via the Z80UNDOC variant. A list
+with the additional instructions can be found in the chapter
+with processor specific hints.
+%%-----------
+\begin{quote}
+ad) Z8601, Z8604, Z8608, Z8630, Z8631
+\end{quote}
+These processors again only differ in internal memory size and
+on-chip peripherals, i.e. the choice does not have an effect on the
+supported instruction set.
+%%-----------
+\begin{quote}
+ae) 96C141, 93C141
+\end{quote}
+These two processors represent the two variations of the processor
+family: TLCS-900 and TLCS-900L. The differences of these two variations
+will be discussed in detail in section \ref{TLCS900Spec}.
+%%-----------
+\begin{quote}
+af) 90C141
+\end{quote}
+%%-----------
+\begin{quote}
+ag) 87C00, 87C20, 87C40, 87C70
+\end{quote}
+The processors of the TLCS-870 series have an identical CPU core, but
+different peripherals depending on the type. In part registers with
+the same name are located at different addresses. The file
+\tty{STDDEF87.INC} uses, similar to the MCS-51-family, the distinction
+possible by different types to provide the correct symbol set
+automatically.
+%%-----------
+\begin{quote}
+ah) 47C00 $\rightarrow$ 470C00 $\rightarrow$ 470AC00
+\end{quote}
+These three variations of the TLCS-47-family have on-chip RAM and ROM
+of different size, which leads to several bank switching instructions
+being added or suppressed.
+%%-----------
+\begin{quote}
+ai) 97C241
+\end{quote}
+%%-----------
+\begin{quote}
+aj) 16C54 $\rightarrow$ 16C55 $\rightarrow$ 16C56 $\rightarrow$ 16C57
+\end{quote}
+These processors differ by the available code area, i.e. by the address
+limit after which AS reports overruns.
+%%-----------
+\begin{quote}
+ak) 16C84, 16C64
+\end{quote}
+Analog to the MCS-51 family, no distinction is made in the code generator,
+the different numbers only serve to include the correct SFRs in
+\tty{STDDEF18.INC}.
+%%-----------
+\begin{quote}
+al) 17C42
+\end{quote}
+%%-----------
+\begin{quote}
+am) ST6210/ST6215$\rightarrow$ST6220/ST6225
+\end{quote}
+The only distinction AS makes between the two pairs is the smaller
+addressing space (2K instead 4K) of the first ones. The detailed
+distinction serves to provide an automatic distinction in the source
+file which hardware is available (analog to the 8051/52/515).
+%%-----------
+\begin{quote}
+an) ST7
+\end{quote}
+%%-----------
+\begin{quote}
+ao) ST9020, ST9030, ST9040, ST9050
+\end{quote}
+These 4 names represent the four ''sub-families'' of the ST9 family,
+which only differ in their on-chip peripherals. Their processor
+cores are identical, which is why this distinction is again only used
+in the include file containing the peripheral addresses.
+%%-----------
+\begin{quote}
+ap) 6804
+\end{quote}
+%%-----------
+\begin{quote}
+aq) 32010$\rightarrow$32015
+\end{quote}
+The TMS32010 owns just 144 bytes of internal RAM, and so AS limits
+addresses in the data segment just up to this amount. This restriction
+does not apply for the 32015, the full range from 0..255 can be used.
+%%-----------
+\begin{quote}
+ar) 320C25 $\rightarrow$ 320C26 $\rightarrow$ 320C28
+\end{quote}
+These processors only differ slightly in their on-chip peripherals
+and in their configuration instructions.
+%%-----------
+\begin{quote}
+as) 320C30, 320C31
+\end{quote}
+The 320C31 is a reduced version with the same instruction set,
+however fewer peripherals. The distinction is exploited in
+\tty{STDDEF3X.INC}.
+%%-----------
+\begin{quote}
+at) 320C203 $\rightarrow$ 320C50, 320C51, 320C53
+\end{quote}
+The first one represents the C20x family of signal processors which
+implement a subset of the C5x instruction set. The distinction among the
+C5x processors is currently not used by AS.
+%%-----------
+\begin{quote}
+au) TMS9900
+\end{quote}
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+av) \> TMS70C00, TMS70C20, TMS70C40,\\
+ \> TMS70CT20, TMS70CT40,\\
+ \> TMS70C02, TMS70C42, TMS70C82,\\
+ \> TMS70C08, TMS70C48\\
+\end{tabbing}
+\end{quote}
+All members of this family share the same CPU core, they therefore do not
+differ in their instruction set. The differences manifest only in the
+file \tty{REG7000.INC} where address ranges and peripheral addresses are
+defined. Types listed in the same row have the same amount of internal
+RAM and the same on-chip peripherals, they differ only in the amount of
+integrated ROM.
+%%-----------
+\begin{quote}
+aw) 370C010, 370C020, 370C030, 370C040 and 370C050
+\end{quote}
+Similar to the MCS-51 family, the different types are only used to
+differentiate the peripheral equipment in \tty{STDDEF37.INC}; the
+instruction set is always the same.
+%%-----------
+\begin{quote}
+ax) MSP430
+\end{quote}
+%%-----------
+\begin{quote}
+ay) SC/MP
+\end{quote}
+%%-----------
+\begin{quote}
+az) COP87L84
+\end{quote}
+This is the only member of National Semiconductor's COP8 family that
+is currently supported. I know that the family is substantially
+larger and that there are representors with differently large
+instruction sets which will be added when a need occurs. It is a
+beginning, and National's documentation is quite extensive...
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+ba) \> SC14400, SC14401, SC14402, SC14404, SC14405, \\
+ \> SC14420, SC14421, SC14422, SC14424 \\
+\end{tabbing}
+\end{quote}
+This series of DECT controllers differentiates itself by the amount of
+instructions, since each of them supports different B field formats and
+their architecture has been optimized over time.
+%%-----------
+\begin{quote}
+bb) 7810$\rightarrow$78C10
+\end{quote}
+The NMOS version has no stop-mode; the respective command and the ZCM
+register are omitted. \bb{CAUTION!} NMOS and CMOS version partially
+differ in the reset values of some registers!
+%%-----------
+\begin{quote}
+\begin{tabbing}
+\hspace{0.7cm} \= \kill
+bc) \> 75402,\\
+ \> 75004, 75006, 75008,\\
+ \> 75268,\\
+ \> 75304, 75306, 75308, 75312, 75316,\\
+ \> 75328,\\
+ \> 75104, 75106, 75108, 75112, 75116,\\
+ \> 75206, 75208, 75212, 75216,\\
+ \> 75512, 75516\\
+\end{tabbing}
+\end{quote}
+This 'cornucopia' of processors differs only by the RAM size in one
+group; the groups themselves again differ by their on-chip
+peripherals on the one hand and by their instruction set's power on
+the other hand.
+%%-----------
+\begin{quote}
+bd) 78070
+\end{quote}
+This is currently the only member of NEC's 78K0 family I am familiar
+with. Similar remarks like for the COP8 family apply!
+%%-----------
+\begin{quote}
+be) 7720 $\rightarrow$ 7725
+\end{quote}
+The $\mu$PD7725 offers larger address spaces and som more instructions
+compared to his predecessor. {\bf CAUTION!} The processors are not binary
+compatible to each other!
+%%-----------
+\begin{quote}
+bf) 77230
+\end{quote}
+%%-----------
+\begin{quote}
+\begin{tabbing}
+bh) \= SYM53C810, SYM53C860, SYM53C815, SYM53C825, \\
+ \> SYM53C875, SYM53C895
+\end{tabbing}
+\end{quote}
+The simpler members of this family of SCSI processors lack some
+instruction variants, furthermore they are different in their set of
+internal registers.
+%%-----------
+\begin{quote}
+bh) MB89190
+\end{quote}
+This processor type represents Fujitsu's F$^{2}$MC8L series.
+
+The \tty{CPU} instruction needs the processor type as a simple constant, a
+calculation like:
+\begin{verbatim}
+ CPU 68010+10
+\end{verbatim}
+is not allowed. Valid calls are e.g.
+\begin{verbatim}
+ CPU 8051
+\end{verbatim}
+or
+\begin{verbatim}
+ CPU 6800
+\end{verbatim}
+Regardless of the processor type currently set, the integer variable
+\tty{MOMCPU} contains the current status as a hexadecimal number. For
+example, \tty{MOMCPU}=\$68010 for the 68010 or \tty{MOMCPU}=80C48H for the
+80C48. As one cannot express all letters as hexadecimal digits (only A..F
+are possible), all other letters must must be omitted in the hex notation;
+for example, \tty{MOMCPU}=80H for the Z80.
+
+You can take advantage of this feature to generate different code
+depending on the processor type. For example, the 68000 does not have a
+machine instruction for a subroutine return with stack correction. With
+the variable \tty{MOMCPU} you can define a macro that uses the machine
+instruction or emulates it depending on the processor type:
+\begin{verbatim}
+myrtd macro disp
+ if MOMCPU<$68010 ; emulate for 68008 & 68000
+ move.l (sp),disp(sp)
+ lea disp(sp),sp
+ rts
+ elseif
+ rtd #disp ; direct use on >=68010
+ endif
+ endm
+
+
+ cpu 68010
+ myrtd 12 ; results in RTD #12
+
+ cpu 68000
+ myrtd 12 ; results in MOVE../LEA../RTS
+\end{verbatim}
+As not all processor names are built only out of numbers and letters
+from A..F, the full name is additionally stored in the string
+variable named \tty{MOMCPUNAME}.
+
+The assembler implicitly switches back to the \tty{CODE} segment when a
+\tty{CPU} instruction is executed. This is done because \tty{CODE} is the
+only segment all processors support.
+
+The default processor type is 68008, unless it has been changed via the
+command line option with same name.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SUPMODE, FPU, PMMU}
+\ttindex{SUPMODE}\ttindex{FPU}\ttindex{PMMU}
+
+{\em\begin{tabbing}
+ valid for: \= 680x0, FPU also for 80x86, i960, SUPMODE also for \\
+ \> TLCS-900, SH7000, i960, 29K, XA, PowerPC, M*Core, \\
+ \> and TMS9900
+\end{tabbing}}
+
+These three switches allow to define which parts of the instruction set
+shall be disabled because the necessary preconditions are not valid for
+the following piece of code. The parameter for these instructions may be
+either \tty{ON} or \tty{OFF}, the current status can be read out of a
+variable which is either TRUE or FALSE.
+
+The commands have the following meanings in detail:
+\begin{itemize}
+\item{\tty{SUPMODE}: allows or prohibits commands, for whose execution the
+ processor has to be within the supervisor mode. The status
+ variable is called \tty{INSUPMODE}.}
+\item{\tty{FPU}: allows or prohibits the commands of the numerical
+ coprocessors 8087 resp. 68881 or 68882. The status variable
+ is called \tty{FPUAVAIL}.}
+\item{\tty{PMMU}: allows or prohibits the commands of the memory
+ management unit 68851 resp. of the built-in MMU of the 68030.
+ \bb{CAUTION!} The 68030-MMU supports only a relatively small subset
+ of the 68851 instructions. The assembler cannot test this!
+ The status variable is called \tty{PMMUAVAIL}.}
+\end{itemize}
+The usage of of instructions prohibited in this manner will generate a
+warning at \tty{SUPMODE}, at \tty{PMMU} and \tty{FPU} a real error
+message.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FULLPMMU}
+\ttindex{FULLPMMU}
+
+{\em valid for: 680x0}
+
+Motorola integrated the MMU into the processor starting with the 68030, but
+the built-in FPU is equipped only with a relatively small subset of the
+68851 instruction set. AS will therefore disable all extended MMU
+instructions when the target processor is 68030 or higher. It is however
+possible that the internal MMU has been disabled in a 68030-based system
+and the processor operates with an external 68851. One can the use a
+\tty{FULLPMMU ON} to tell AS that the complete MMU instruction set is
+allowed. Vice versa, one may use a \tty{FULLPMMU OFF} to disable all
+additional instruction in spite of a 68020 target platform to assure that
+portable code is written. The switch between full and reduced instruction
+set may be done as often as needed, and the current setting may be read
+from a symbol with the same name. \bb{CAUTION!} The \tty{CPU} instruction
+implicitly sets or resets this switch when its argument is a 68xxx
+processor! \tty{FULLPMMU} therefore has to be written after the \tty{CPU}
+instruction!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PADDING}
+\ttindex{PADDING}
+
+{\em valid for: 680x0, M*Core, XA, H8, SH7000, MSP430, TMS9900, ST7}
+
+Processors of the 680x0 family are quite critical regarding odd addresses:
+instructions must not start on an odd address, and data accesses to odd
+addresses are only allowed bytewise up to the 68010. The H8/300 family
+simply resets the lowest address bit to zero when accessing odd addresses,
+the 500 in contrast 'thanks' with an exception... AS therefore tries to
+round up data structures built with \tty{DC} or \tty{DS} to an even number
+of bytes. This however means for \tty{DC.B} and \tty{DS.B} that a padding
+byte may have to be added. This behaviour can be turned on and off via
+the \tty{PADDING} instruction. Similar to the previous instructions, the
+argument may be either \tty{ON} or \tty{OFF}, and the current setting may
+be read from a symbol with the same name. \tty{PADDING} is by default only
+enabled for the 680x0 family, it has to be turned on explicitly for all
+other families!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{MAXMODE}
+\ttindex{MAXMODE}
+
+{\em valid for: TLCS-900, H8}
+
+The processors of the TLCS-900-family are able to work in 2 modes, the
+minimum and maximum mode. Depending on the actual mode, the execution
+environment and the assembler are a little bit different. Along with this
+instruction and the parameter \tty{ON} or \tty{OFF}, AS is informed that the
+following code will run in maximum resp. minimum mode. The actual setting
+can be read from the variable \tty{INMAXMODE}. Presetting is \tty{OFF},
+i.e. minimum mode.
+
+Similarly, one uses this instruction to tell AS in H8 mode whether the
+address space is 64K or 16 Mbytes. This setting is always \tty{OFF} for
+the 'small' 300 version and cannot be changed.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{EXTMODE and LWORDMODE}
+\ttindex{EXTMODE}\ttindex{LWORDMODE}
+
+{\em valid for: Z380}
+
+The Z380 may operate in altogether 4 modes, which are the result of
+setting two flags: The XM flag rules whether the processor shall operate
+wit an address space of 64 Kbytes or 4 Gbytes and it may only be set to 1
+(after a reset, it is set to 0 for compatibility with the Z80). The LW
+flag in turn rules whether word operations shall work with a word size of
+16 or 32 bits. The setting of these two flags influences range checks of
+constants and addresses, which is why one has to tell AS the setting of
+these two flags via these instructions. The default assumption is that
+both flags are 0, the current setting (\tty{ON} or \tty{OFF}) may be read
+from the predefined symbols \tty{INEXTMODE} resp. \tty{INLWORDMODE.}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SRCMODE}
+\ttindex{SRCMDE}
+
+{\em valid for: MCS-251}
+
+Intel substantially extended the 8051 instruction set with the 80C251, but
+unfortunately there was only a single free opcode for all these new
+instructions. To avoid a processor that will be eternally crippled by a
+prefix, Intel provided two operating modes: the binary and the source
+mode. The new processor is fully binary compatible to the 8051 in binary
+mode, all new instructions require the free opcode as prefix. In source
+mode, the new instructions exchange their places in the code tables with
+the corresponding 8051 instructions, which in turn then need a prefix.
+One has to inform AS whether the processor operates in source mode
+(\tty{ON}) or binary mode (\tty{OFF}) to enable AS to add prefixes when
+required. The current setting may be read from the variable
+\tty{INSRCMODE}. The default is \tty{OFF}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BIGENDIAN}
+\ttindex{BIGENDIAN}
+
+{\em valid for: MCS-51/251, PowerPC}
+
+Intel broke with its own principles when the 8051 series was designed: in
+contrast to all traditions, the processor uses big-endian ordering for all
+multi-byte values! While this was not a big deal for MCS-51 processors
+(the processor could access memory only in 8-bit portions, so everyone was
+free to use whichever endianess one wanted), it may be a problem for the
+251 as it can fetch whole (long-)words from memory and expects the MSB to
+be first. As this is not the way of constant disposal earlier versions of
+AS used, one can use this instruction to toggle between big and
+little endian mode for the instructions \tty{DB, DW, DD, DQ,} and
+\tty{DT}. \tty{BIGENDIAN OFF} (the default) puts the LSB first into
+memory as it used to be on earlier versions of AS, \tty{BIGENDIAN ON}
+engages the big-endian mode compatible to the MCS-251. One may of course
+change this setting as often as one wants; the current setting can be read
+from the symbol with the same name.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{WRAPMODE}
+\ttindex{WRAPMODE}
+
+{\em valid for: Atmel AVR}
+
+After this switch has been set to {\tt ON}, AS will assume that the
+processor's program counter does not have the full length of 16 bits given
+by the architecture, but instead a length that is exactly sufficient to
+address the internal ROM. For example, in case of the AT90S8515, this
+means 12 bits, corresponding to 4 Kwords or 8 Kbytes. This assumption
+allows relative branches from the ROM's beginning to the end and vice
+versa which would result in an out-of-branch error when using strict
+arithmetics. Here, they work because the carry bits resulting from the
+target address computation are discarded. Assure that the target
+processor you are using works in the outlined way before you enable this
+option! In case of the abovementioned AT90S8515, this option is even
+necessary because it is the only way to perform a direct jump through
+the complete address space...
+
+This switch is set to {\tt OFF} by default, and its current setting may be
+read from a symbol with same name.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SEGMENT}
+\ttindex{SEGMENT}
+
+{\em valid for: all processors}
+
+Some microcontrollers and signal processors know various address ranges,
+which do not overlap with each other and require also different
+instructions and addressing modes for access. To manage these ones also,
+the assembler provides various program counters, you can switch among
+them to and from by the use of the \tty{SEGMENT} instruction. For subroutines
+included with \tty{INCLUDE}, this e.g. allows to define data used by the
+main program or subroutines near to the place they are used. In detail,
+the following segments with the following names are supported:
+\begin{itemize}
+\item{\tty{CODE}: program code;}
+\item{\tty{DATA}: directly addressable data (including SFRs);}
+\item{\tty{XDATA}: data in externally connected RAM or
+ X-addressing space of the DSP56xxx or ROM data for the $\mu$PD772x;}
+\item{\tty{YDATA}: Y-addressing space of the DSP56xxx;}
+\item{\tty{IDATA}: indirectly addressable (internal) data; }
+\item{\tty{BITDATA}: the part of the 8051-internal RAM that is bitwise
+ addressable;}
+\item{\tty{IO}: I/O-address range;}
+\item{\tty{REG}: register bank of the ST9;}
+\item{\tty{ROMDATA}: constant ROM of the NEC signal processors.}
+\end{itemize}
+See also section \ref{SectORG} (\tty{ORG}) for detailed information about
+address ranges and initial values of the segments. Depending on the
+processor family, not all segment types will be permitted.
+
+The bit segment is managed as if it would be a byte segment, i.e. the
+addresses will be incremented by 1 per bit.
+
+Labels get the same type as attribute as the segment that was active
+when the label was defined. So the assembler has a limited ability
+to check whether you access symbols of a certain segment with wrong
+instructions. In such cases the assembler issues a warning.
+
+Example:
+\begin{verbatim}
+ CPU 8051 ; MCS-51-code
+
+ segment code ; test code
+
+ setb flag ; no warning
+ setb var ; warning : wrong segment
+
+ segment data
+
+var db ?
+
+ segment bitdata
+
+flag db ?
+\end{verbatim}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PHASE and DEPHASE}
+\ttindex{PHASE}\ttindex{DEPHASE}
+
+{\em valid for: all processors}
+
+For some applications (especially on Z80 systems), the code must be moved
+to another address range before execution. If the assembler didn't know
+about this, it would align all labels to the load address (not the start
+address). The programmer is then forced to write jumps within this area
+either independent of location or has to add the offset at each symbol
+manually. The first one is not possible for some processors, the last one
+is extremely error-prone. With the commands \tty{PHASE} and
+\tty{DEPHASE}, it is possible to inform the assembler at which address the
+code will really be executed on the target system:
+\begin{verbatim}
+ phase <address>
+\end{verbatim}
+informs the assembler that the following code shall be executed at the
+specified address. The assembler calculates thereupon the difference to
+the real program counter and adds this difference for the following
+operations:
+\begin{itemize}
+\item{address values in the listing}
+\item{filing of label values}
+\item{program counter references in relative jumps and address expressions}
+\item{readout of the program counter via the symbols * or \$}
+\end{itemize}
+this ''shifting'' is switched off by the instruction
+\begin{verbatim}
+ dephase
+\end{verbatim}
+The assembler manages phase values for all defined segments, although
+this instruction pair only makes real sense in the code segment.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SAVE and RESTORE}
+\ttindex{SAVE}\ttindex{RESTORE}
+
+{\em valid for: all processors}
+
+The command \tty{SAVE} forces the assembler to push the contents of
+following variables onto an internal stack:
+\begin{itemize}
+\item{currently selected processor type (set by \tty{CPU});}
+\item{currently active memory area (set by \tty{SEGMENT});}
+\item{the flag whether listing is switched on or off (set by \tty{LISTING});}
+\item{the flag whether expansions of following macros shall be issued in
+ the assembly listing (set by \tty{MACEXP}).}
+\item{currently active character translation table (set by
+ \tty{CODEPAGE}).}
+\end{itemize}
+The counterpart \tty{RESTORE} pops the values saved last from this stack.
+These two commands were primarily designed for include files, to change
+the above mentioned variables in any way inside of these files, without
+loosing their original content. This may be helpful e.g. in include files
+with own, fully debugged subroutines, to switch the listing generation
+off:
+\begin{verbatim}
+ SAVE ; save old status
+
+ LISTING OFF ; save paper
+
+ . ; the actual code
+ .
+
+ RESTORE ; restore
+\end{verbatim}
+In opposite to a simple \tty{LISTING OFF .. ON}-pair, the correct status
+will be restored, in case the listing generation was switched off already
+before.
+
+The assembler checks if the number of \tty{SAVE}-and
+\tty{RESTORE}-commands corresponds and issues error messages in the
+following cases:
+\begin{itemize}
+\item{\tty{RESTORE}, but the internal stack is empty;}
+\item{the stack not empty at the end of a pass.}
+\end{itemize}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ASSUME}
+\ttindex{ASSUME}
+
+{\em valid for: various}
+
+This instruction allows to tell AS the current setting of certain
+registers whose contents cannot be described with a simple \tty{ON} or
+\tty{OFF}. These are typically registers that influence addressing modes
+and whose contents are important to know for AS in order to generate
+correct addressing. It is important to note that \tty{ASSUME} only
+informs AS about these, \bb{no} machine code is generated that actually
+loads these values into the appropriate registers!
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{6809}
+
+In contrast to its 'predecessors' like the 6800 and 6502, the position of
+the direct page, i.e. the page of memory that can be reached with
+single-byte addresses, can be set freely. This is done via the 'direct
+page register' that sets the page number. One has to assign a
+corresponding value to this register via \tty{ASSUME} is the contents are
+different from the default of 0, otherwise wrong addresses will be
+generated!
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{68HC16}
+
+The 68HC16 employs a set of bank registers to address a space of 1
+Mbyte with its registers that are only 16 bits wide. These registers
+supply the upper 4 bits. Of these, the EK register is responsible
+for absolute data accesses (not jumps!). AS checks for each absolute
+address whether the upper 4 bits of the address are equal to the
+value of EK specified via \tty{ASSUME}. AS issues a warning if they
+differ. The default for EK is 0.
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{H8/500}
+
+In maximum mode, the extended address space of these processors is
+addressed via a couple of bank registers. They carry the names DP
+(registers from 0..3, absolute addresses), EP (register 4 and 5), and TP
+(stack). AS needs the current value of DP to check if absolute addresses
+are within the currently addressable bank; the other two registers are
+only used for indirect addressing and can therefore not be monitored; it
+is a question of personal taste whether one specifies their values or not.
+The BR register is in contrast important because it rules which 256-byte
+page may be accessed with short addresses. It is common for all registers
+that AS does not assume \bb{any} default value for them as they are
+undefined after a CPU reset. Everyone who wants to use absolute addresses
+must therefore assign values to at least DR and DP!
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{MELPS740}
+
+Microcontrollers of this series know a ''special page'' addressing mode
+for the \tty{JSR} instruction that allows a shorter coding for jumps into
+the last page of on-chip ROM. The size of this ROM depends of course
+on the exact processor type, and there are more derivatives than it
+would be meaningful to offer via the CPU instruction...we therefore
+have to rely on \tty{ASSUME} to define the address of this page, e.g.
+\begin{verbatim}
+ ASSUME SP:$1f
+\end{verbatim}
+in case the internal ROM is 8K.
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{MELPS7700/65816}
+
+These processors contain a lot of registers whose contents AS has to know
+in order to generate correct machine code. These are the registers
+in question:
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+name & function & value range & default \\
+\hline
+\hline
+DT & data bank & 0-\$ff & 0 \\
+PG & code Bank & 0-\$ff & 0 \\
+DPR & directly addr. page & 0-\$ffff & 0 \\
+X & index register width & 0 or 1 & 0 \\
+M & accumulator width & 0 or 1 & 0 \\
+\hline
+\end{tabular}\end{center}
+\par
+To avoid endless repetitions, see section \ref{MELPS7700Spec} for
+instructions how to use these registers. The handling is otherwise
+similar to the 8086, i.e. multiple values may be set with one instruction
+and no code is generated that actually loads the registers with the given
+values. This is again up to the programmer!
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{MCS-196/296}
+
+Starting with the 80196, all processors of the MCS-96 family have a
+register 'WSR' that allows to map memory areas from the extended
+internal RAM or the SFR range into areas of the register file which
+may then be accessed with short addresses. If one informs AS about
+the value of the WSR register, it can automatically find out whether
+an absolute address can be addressed with a single-byte address via
+windowing; consequently, long addresses will be automatically generated
+for registers covered by windowing. The 80296 contains an additional
+register WSR1 to allow simultaneous mapping of two memory areas into
+the register file. In case it is possible to address a memory cell
+via both areas, AS will always choose the way via WSR!
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{8086}
+
+The 8086 is able to address data from all segments in all
+instructions, but it however needs so-called ''segment prefixes'' if
+another segment register than DS shall be used. In addition it is
+possible that the DS register is adjusted to another segment, e.g. to
+address data in the code segment for longer parts of the program. As
+AS cannot analyze the code's meaning, it has to informed via this
+instruction to what segments the segment registers point at the
+moment, e.g.:
+\begin{verbatim}
+ ASSUME CS:CODE, DS:DATA .
+\end{verbatim}
+It is possible to assign assumptions to all four segment registers in
+this way. This instruction produces \bb{no} code, so the program itself
+has to do the actual load of the registers with the values.
+
+The usage of this instruction has on the one hand the result that AS is
+able to automatically put ahead prefixes at sporadic accesses into the
+code segment, or on the other hand, one can inform AS that the DS-register
+was modified and you can save explicit \tty{CS:}-instructions.
+
+Valid arguments behind the colon are \tty{CODE}, \tty{DATA} and
+\tty{NOTHING}. The latter value informs AS that a segment register
+contains no usable value (for AS). The following values are
+preinitialized:
+\begin{verbatim}
+ CS:CODE, DS:DATA, ES:NOTHING, SS:NOTHING
+\end{verbatim}
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{XA}
+
+The XA family has a data address space of 16 Mbytes, a process however
+can always address within a 64K segment only that is given by the DS
+register. One has to inform AS about the current value of this
+register in order to enable it to check accesses to absolute
+addresses.
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{29K}
+
+The processors of the 29K family feature a register RBP that allows
+to protect banks of 16 registers against access from user mode. The
+corresponding bit has to be set to achieve the protection. \tty{ASSUME}
+allows to tell AS which value RBP currently contains. AS can warn
+this way in case a try to access protected registers from user mode
+is made.
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{80C166/167}
+
+Though none of the 80C166/167's registers is longer than sixteen bits,
+this processor has 18/24 address lines and can therefore address up
+to 256Kbytes/16Mbytes. To resolve this contradiction, it neither
+uses the well-known (and ill-famed) Intel method of segmentation nor
+does it have inflexible bank registers...no, it uses paging! To accomplish
+this, the logical address space of 64 Kbytes is split into 4 pages of
+16 Kbytes, and for each page there is a page register (named
+DPP0..DPP3) that rules which of the 16/1024 physical pages shall be
+mapped to this logical page. AS always tries to present the address
+space with a size of 256Kbytes/16MBytes in the sight of the
+programmer, i.e. the physical page is taken for absolute accesses and
+the setting of bits 14/15 of the logical address is deduced. If no
+page register fits, a warning is issued. AS assumes by default that
+the four registers linearly map the first 64 Kbytes of memory, in the
+following style:
+\begin{verbatim}
+ ASSUME DPP0:0,DPP1:1,DPP2:2,DPP3:3
+\end{verbatim}
+The 80C167 knows some additional instructions that can override the
+page registers' function. The chapter with processor-specific hints
+describes how these instructions influence the address generation.
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{TLCS-47}
+
+The direct data address space of these processors (it makes no
+difference whether you address directly or via the HL register) has a
+size of only 256 nibbles. Because the ''better'' family members have
+up to 1024 nibbles of RAM on chip, Toshiba was forced to introduce a
+banking mechanism via the DMB register. AS manages the data segment
+as a continuous addressing space and checks at any direct addressing
+if the address is in the currently active bank. The bank AS
+currently expects can be set by means of
+\begin{verbatim}
+ ASSUME DMB:<0..3>
+\end{verbatim}
+The default value is 0.
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{ST6}
+\label{ST6Assume}
+
+The microcontrollers of the ST62 family are able to map a part (64 bytes)
+of the code area into the data area, e.g. to load constants from the ROM.
+This means also that at one moment only one part of the ROM can be
+addressed. A special register rules which part it is. AS cannot check
+the contents of this register directly, but it can be informed by this
+instruction that a new value has been assigned to the register. AS then
+can test and warn if necessary, in case addresses of the code segment are
+accessed, which are not located in the ''announced'' window. If, for
+example, the variable \tty{VARI} has the value 456h, so
+\begin{verbatim}
+ ASSUME ROMBASE:VARI>>6
+\end{verbatim}
+sets the AS-internal variable to 11h, and an access to \tty{VARI}
+generates an access to address 56h in the data segment.
+
+It is possible to assign a simple \tty{NOTHING} instead of a value, e.g.
+if the bank register is used temporarily as a memory cell. This value is
+also the default.
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{ST9}
+
+The ST9 family uses exactly the same instructions to address code and
+data area. It depends on the setting of the flag register's DP flag
+which address space is referenced. To enable AS to check if one
+works with symbols from the correct address space (this of course
+\bb{only} works with absolute accesses!), one has to inform AS whether the
+DP flag is currently 0 (code) or 1 (data). The initial value of this
+assumption is 0.
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{320C3x}
+
+As all instruction words of this processor family are only 32 bits
+long (of which only 16 bits were reserved for absolute addresses),
+the missing upper 8 bits have to be added from the DP register. It
+is however still possible to specify a full 24-bit address when
+addressing, AS will check then whether the upper 8 bits are equal to
+the DP register's assumed values. \tty{ASSUME} is different to the
+\tty{LDP} instruction in the sense that one cannot specify an arbitrary
+address out of the bank in question, one has to extract the upper bits by
+hand:
+\begin{verbatim}
+ ldp @addr
+ assume dp:addr>>16
+ .
+ .
+ ldi @addr,r2
+\end{verbatim}
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{$\mu$PD78(C)10}
+
+These processors have a register (V) that allows to move the ''zero
+page'', i.e. page of memory that is addressable by just one byte,
+freely in the address space, within page limits. By reasons of
+comforts you don't want to work with expressions such as
+\begin{verbatim}
+ inrw Lo(counter)
+\end{verbatim}
+so AS takes over this job, but only under the premise that it is informed
+via the \tty{ASSUME}-command about the contents of the V register. If an
+instruction with short addressing is used, it will be checked if the upper
+half of the address expression corresponds to the expected content. A
+warning will be issued if both do not match.
+
+%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+\subsubsection{75K0}
+
+As the whole address space of 12 bits could not be addressed even by
+the help of register pairs (8 bits), NEC had to introduce banking
+(like many others too...): the upper 4 address bits are fetched from
+the MBS register (which can be assigned values from 0 to 15 by the
+\tty{ASSUME} instruction), which however will only be regarded if the MBE
+flag has been set to 1. If it is 0 (default), the lowest and highest
+128 nibbles of the address space can be reached without banking. The
+\tty{ASSUME} instruction is undefined for the 75402 as it contains neither
+a MBE flag nor an MBS register; the initial values cannot be changed
+therefore.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{EMULATED}
+
+{\em valid for: 29K}
+
+AMD defined the 29000's series exception handling for undefined
+instructions in a way that there is a separate exception vector for
+each instruction. This allows to extend the instruction set of a
+smaller member of this family by a software emulation. To avoid that
+AS quarrels about these instructions as being undefined, the
+\tty{EMULATED} instruction allows to tell AS that certain instructions are
+allowed in this case. The check if the currently set processors knows the
+instruction is then skipped. For example, if one has written a module
+that supports 32-bit IEEE numbers and the processor does not have a FPU,
+one writes
+\begin{verbatim}
+ EMULATED FADD,FSUB,FMUL,FDIV
+ EMULATED FEQ,FGE,FGT,SQRT,CLASS
+\end{verbatim}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BRANCHEXT}
+\ttindex{BRANCHEXT}
+
+{\em valid for: XA}
+
+{\tt BRANCHEXT} with either \tty{ON} or \tty{OFF} as argument tells AS
+whether short branches that are only available with an 8-bit displacement
+shall automatically be 'extended', for example by replacing a single
+instruction like
+\begin{verbatim}
+ bne target
+\end{verbatim}
+with a longer sequence of same functionality, in case the branc target is
+out of reach for the instruction's displacement. For example, the
+replacement sequence for {\tt bne} would be
+\begin{verbatim}
+ beq skip
+ jmp target
+skip:
+\end{verbatim}
+In case there is no fitting 'opposite' for an instruction, the sequence
+may become even longer, e.g. for {\tt jbc}:
+\begin{verbatim}
+ jbc dobr
+ bra skip
+dobr: jmp target
+skip:
+\end{verbatim}
+This feature however has the side effect that there is no unambigious
+assignment between machine and assembly code any more. Furthermore,
+additional passes may be the result if there are forward branches. One
+should therefore use this feature with caution!
+
+%%---------------------------------------------------------------------------
+
+\section{Data Definitions}
+
+The instructions described in this section partially overlap in their
+functionality, but each processor family defines other names for the
+same function. To stay compatible with the standard assemblers, this
+way of implementation was chosen.
+
+If not explicitly mentioned otherwise, all instructions for data
+deposition (not those for reservation of memory!) allow an arbitrary
+number of parameters which are being processed from left to right.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DC[.Size]}
+\ttindex{DC}
+
+{\em valid for: 680x0, M*Core, 68xx, H8, SH7x00, DSP56xxx, XA, ST7}
+
+
+This instruction places one or several constants of the type
+specified by the attribute into memory. The attributes are the same ones as
+defined in section \ref{AttrTypes}, and there is additionally the
+possibility for byte constants to place string constants in memory, like
+\begin{verbatim}
+String dc.B "Hello world!\0"
+\end{verbatim}
+The parameter count may be between 1 and 20. A repeat count enclosed
+in brackets may additionally be prefixed to each parameter; for
+example, one can for example fill the area up to the next page
+boundary with zeroes with a statement like
+\begin{verbatim}
+ dc.b [(*+255)&$ffffff00-*]0
+\end{verbatim}
+\bb{CAUTION!} This function easily allows to reach the limit of 1 Kbyte
+of generated code per line!
+
+The assembler can automatically add another byte of data in case the byte sum
+should become odd, to keep the word alignment. This behaviour may be
+turned on and off via the \tty{PADDING} instruction.
+
+Decimal floating point numbers stored with this instruction (\tty{DC.P...})
+can cover the whole range of extended precision, one however has to
+pay attention to the detail that the coprocessors currently available
+from Motorola (68881/68882) ignore the thousands digit of the
+exponent at the read of such constants!
+
+The default attribute is \tty{W}, that means 16-bit-integer numbers.
+
+For the DSP56xxx, the data type is fixed to integer numbers (an attribute is
+therefore neither necessary nor allowed), which may be in the range
+of -8M up to 16M-1. String constants are also allowed, whereby three characters
+are packed into each word.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DS[.Size]}
+\ttindex{DS}
+
+{\em valid for: 680x0, M*Core, 68xx, H8, SH7x00, DSP56xxx, XA,, ST7}
+
+On the one hand, this instruction enables to reserve memory space for
+the specified count of numbers of the type given by the attribute.
+Therefore,
+\begin{verbatim}
+ DS.B 20
+\end{verbatim}
+for example reserves 20 bytes of memory, but
+\begin{verbatim}
+ DS.X 20
+\end{verbatim}
+reserves 240 bytes!
+
+The other purpose is the alignment of the program counter which is
+achieved by a count specification of 0. In this way, with a
+\begin{verbatim}
+ DS.W 0 ,
+\end{verbatim}
+the program counter will be rounded up to the next even address, with
+a
+\begin{verbatim}
+ DS.D 0
+\end{verbatim}
+in contrast to the next double word boundary. Memory cells possibly
+staying unused thereby are neither zeroed nor filled with NOPs, they
+simply stay undefined.
+
+The default for the operand length is - as usual - \tty{W}, i.e. 16 bits.
+
+For the 56xxx, the operand length is fixed to words (of 24 bit),
+attributes therefore do not exist just as in the case of \tty{DC}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DB,DW,DD,DQ, and DT}
+\ttindex{DB}\ttindex{DW}\ttindex{DD}\ttindex{DQ}\ttindex{DT}
+
+{\em\begin{tabbing}
+valid for: \= Intel, Zilog, Toshiba, NEC, TMS370, Siemens, AMD, \\
+ \> MELPS7700/65816, M16(C), National, ST9, TMS70Cxx, \\
+ \> $\mu$PD77230, Fairchild
+\end{tabbing}}
+
+These commands are - one could say - the Intel counterpart to \tty{DS} and
+\tty{DC}, and as expected, their logic is a little bit different: First,
+the specification of the operand length is moved into the mnemonic:
+\begin{itemize}
+\item{\tty{DB}: byte or ASCII string similar to \tty{DC.B}}
+\item{\tty{DW}: 16-bit integer}
+\item{\tty{DD}: 32-bit integer or single precision}
+\item{\tty{DQ}: double precision (64 bits)}
+\item{\tty{DT}: extended precision (80 bits)}
+\end{itemize}
+Second, the distinction between constant definition and memory
+reservation is done by the operand. A reservation of memory is
+marked by a \tty{?} :
+\begin{verbatim}
+ db ? ; reserves a byte
+ dw ?,? ; reserves memory for 2 words (=4 byte)
+ dd -1 ; places the constant -1 (FFFFFFFFH) !
+\end{verbatim}
+Reserved memory and constant definition \bb{must not} be mixed within one
+instruction:
+\begin{verbatim}
+ db "hello",? ; --> error message
+\end{verbatim}
+Additionally, the \tty{DUP} Operator permits the repeated placing of
+constant sequences or the reservation of whole memory blocks:
+\begin{verbatim}
+ db 3 dup (1,2) ; --> 1 2 1 2 1 2
+ dw 20 dup (?) ; reserves 40 bytes of memory
+\end{verbatim}
+As you can see, the \tty{DUP}-argument must be enclosed in parentheses,
+which is also why it may consist of several components, that may
+themselves be \tty{DUP}s...the stuff therefore works recursively.
+\tty{DUP} is however also a place where one can get in touch with another
+limit of the assembler: a maximum of 1024 bytes of code or data may be
+generated in one line. This is not valid for the reservation of memory,
+only for the definition of constant arrays!
+
+In order to be compatible to the M80, \tty{DEFB/DEFW} may be used instead of
+\tty{DB/DW} in Z80-mode.
+
+Similarly, \tty{BYTE/ADDR} resp. \tty{WORD/ADDRW} in COP8 mode are an
+alias for \tty{DB} resp. \tty{DW}, with the pairs differing in byte order:
+instructions defined by National for address storage use big endian,
+\tty{BYTE} resp. \tty{WORD} in contrast use little endian.
+
+The NEC 77230 is special with its \tty{DW} instruction: It more works like
+the \tty{DATA} statement of its smaller brothers, but apart from string
+and integer arguments, it also accepts floating point values (and stores
+them in the processor's proprietary 32-bit format). There is {\em no}
+\tty{DUP} operator!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DS, DS8}
+\ttindex{DS}
+\ttindex{DS8}
+
+{\em\begin{tabbing}
+valid for: \= Intel, Zilog, Toshiba, NEC, TMS370, Siemens, AMD, \\
+ \> M16(C), National, ST9, TMS7000
+\end{tabbing}}
+
+With this instruction, you can reserve a memory area:
+\begin{verbatim}
+ DS <count>
+\end{verbatim}
+It is an abbreviation of
+\begin{verbatim}
+ DB <count> DUP (?)
+\end{verbatim}
+Although this could easily be made by a macro, some people grown up
+with Motorola CPUs (Hi Michael!) suggest \tty{DS} to be a built-in
+instruction...I hope they are satisfied now \tty{;-)}
+
+{\tt DS8} is defined as an alias for {\tt DS} on the National SC14xxx.
+Beware that the code memory of these processors is organized in words of
+16 bits, it is therefore impossible to reserve individual bytes. In case
+the argument of {\tt DS} is odd, it will be rounded up to the next even
+number.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BYT or FCB}
+\ttindex{BYT}\ttindex{FCB}
+
+{\em valid for: 6502, 68xx}
+
+By this instruction, byte constants or ASCII strings are placed in
+65xx/68xx-mode, it therefore corresponds to \tty{DC.B} on the 68000 or
+\tty{DB} on Intel. Similarly to \tty{DC}, a repetition factor enclosed
+in brackets ([..]) may be prepended to every single parameter.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BYTE}
+\ttindex{BYTE}
+
+{\em valid for: ST6, 320C2(0)x, 320C5x, MSP, TMS9900}
+
+Ditto. Note that when in 320C2(0)x/5x mode, the assembler assumes that
+a label on the left side of this instruction has no type, i.e. it
+belongs to no address space. This behaviour is explained in the
+processor-specific hints.
+
+The \tty{PADDING} instruction allows to set whether odd counts of bytes
+shall be padded with a zero byte in MSP/TMS9900 mode.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DC8}
+\ttindex{DC8}
+
+{\em valid for: SC144xx}
+
+This statement is an alias for {\tt DB}, i.e. it may be used to dump byte
+constants or strings to memory.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ADR or FDB}
+\ttindex{ADR}\ttindex{FDB}
+
+{\em valid for: 6502, 68xx}
+
+\tty{ADR} resp. \tty{FDB} stores word constants when in 65xx/68xx mode.
+It is therefore the equivalent to \tty{DC.W} on the 68000 or \tty{DW} on
+Intel platforms. Similarly to \tty{DC}, a repetition factor enclosed
+in brackets ([..]) may be prepended to every single parameter.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{WORD}
+\ttindex{WORD}
+
+{\em valid for: ST6, i960, 320C2(0)x, 320C3x, 320C5x, MSP}
+
+If assembling for the 320C3x or i960, this command stores 32-bit words,
+16-bit words for the other families. Note that when in 320C2(0)x/5x mode,
+the assembler assumes that a label on the left side of this instruction
+has no type, i.e. it belongs to no address space. This behaviour is
+explained at the discussion on processor-specific hints.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DW16}
+\ttindex{DW16}
+
+{\em valid for: SC144xx}
+
+This instruction is for SC144xx targets a way to dump word (16 bit)
+constants to memory. {\tt CAUTION!!} It is therefore an alias for {\tt
+DW}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LONG}
+\ttindex{LONG}
+
+{\em valid for: 320C2(0)x, 320C5x}
+
+LONG stores a 32-bit integer to memory with the order LoWord-HiWord.
+Note that when in 320C2(0)x/5x mode, the assembler assumes that a label
+on the left side of this instruction has no type, i.e. it belongs to
+no address space. This behaviour is explained in the
+processor-specific hints.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SINGLE and EXTENDED}
+\ttindex{SINGLE}\ttindex{EXTENDED}
+
+{\em valid for: 320C3x}
+
+Both commands store floating-point constants to memory. They are \bb{not}
+in IEEE-format. Instead the processor-specific formats with 32 and 40 bit
+are used. In case of \tty{EXTENDED} the resulting constant occupies two
+memory words. The most significant 8 bits (the exponent) are written to
+the first word while the other ones (the mantissa) are copied into the second
+word.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FLOAT and DOUBLE}
+\ttindex{FLOAT}\ttindex{DOUBLE}
+
+{\em valid for: 320C2(0)x, 320C5x}
+
+These two commands store floating-point constants in memory using the
+standard IEEE 32-bit and 64-bit IEEE formats. The least significant
+byte is copied to the first allocated memory location. Note that
+when in 320C2(0)x/5x mode the assembler assumes that all labels on the
+left side of an instruction have no type, i.e. they belong to no
+address space. This behaviour is explained in the processor-specific
+hints.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{EFLOAT, BFLOAT, and TFLOAT}
+\ttindex{EFLOAT}\ttindex{BFLOAT}\ttindex{TFLOAT}
+
+{\em valid for: 320C2(0)x, 320C5x}
+
+Another three floating point commands. All of them support non-IEEE
+formats, which should be easily applicable on signal processors:
+\begin{itemize}
+\item{\tty{EFLOAT}: mantissa with 16 bits, exponent with 16 bits}
+\item{\tty{BFLOAT}: mantissa with 32 bits, exponent with 16 bits}
+\item{\tty{DFLOAT}: mantissa with 64 bits, exponent with 32 bits}
+\end{itemize}
+The three commands share a common storage strategy. In all cases the
+mantissa precedes the exponent in memory, both are stored as 2's
+complement with the least significant byte first. Note that when in
+320C2(0)x/5x mode the assembler assumes that all labels on the left side
+of an instruction have no type, i.e. they belong to no address
+space. This behaviour is explained in the processor-specific hints.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{Qxx and LQxx}
+\ttindex{Qxx}\ttindex{LQxx}
+
+{\em valid for: 320C2(0)x, 320C5x}
+
+\tty{Qxx} and \tty{LQxx} can be used to generate constants in a fixed
+point format. \tty{xx} denotes a 2-digit number. The operand is first
+multiplied by $2^{xx}$ before converting it to binary notation. Thus
+\tty{xx} can be viewed as the number of bits which should be reserved for
+the fractional part of the constant in fixed point format. \tty{Qxx}
+stores only one word (16 bit) while \tty{LQxx} stores two words (low word
+first):
+\begin{verbatim}
+ q05 2.5 ; --> 0050h
+ lq20 ConstPI ; --> 43F7h 0032h
+\end{verbatim}
+Please do not flame me in case I calculated something wrong on my
+HP28...
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DATA}
+\ttindex{DATA}
+
+{\em valid for: PIC, 320xx, AVR, MELPS-4500, 4004, $\mu$PD772x}
+
+This command stores data in the current segment. Both integer values as
+well as character strings are supported. On 16C5x/16C8x, 17C4x in data
+segment and on the 4500, characters occupy one word. On AVR, 17C4x in
+code segment, $\mu$PD772x in the data segments, and on 3201x/3202x, in
+general two characters fit into one word (LSB first). The $\mu$PD77C25
+can hold three bytees per word in the code segment. When in 320C3x, mode
+the assembler puts four characters into one word (MSB first). In contrast
+to this characters occupy two memory locations in the data segment of the
+4500, similar in the 4004. The range of integer values corresponds to the
+word width of each processor in a specific segment. This means that
+\tty{DATA} has the same result than \tty{WORD} on a 320C3x (and that of
+\tty{SINGLE} if AS recognizes the operand as a floating-point constant).
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ZERO}
+\ttindex{ZERO}
+
+{\em valid for: PIC}
+
+Generates a continuous string of zero words in memory. The length is
+given by the argument and must not exceed 512.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FB and FW}
+\ttindex{FB}\ttindex{FW}
+
+{\em valid for: COP8}
+
+These instruction allow to fill memory blocks with a byte or word
+constant. The first operand specifies the size of the memory block
+while the second one sets the filling constant itself. The maximum
+supported block size is 1024 elements for \tty{FB} and 512 elements for
+\tty{FW}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ASCII and ASCIZ}
+\ttindex{ASCII}\ttindex{ASCIZ}
+
+{\em valid for: ST6}
+
+Both commands store string constants to memory. While \tty{ASCII} writes
+the character information only, \tty{ASCIZ} additionally appends a zero to
+the end of the string.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{STRING and RSTRING}
+\ttindex{STRING}\ttindex{RSTRING}
+
+{\em valid for: 320C2(0)x, 320C5x}
+
+These commands are functionally equivalent to \tty{DATA}, but integer
+values are limited to the range of byte values. This enables two
+characters or numbers to be packed together into one word. Both commands
+only differ in the order they use to write bytes: \tty{STRING} stores the
+upper one first then the lower one, \tty{RSTRING} does this vice versa.
+Note that when in 320C2(0)x/5x mode the assembler assumes that a label on the
+left side of this instruction has no type, i.e. it belongs to no address
+space. This behaviour is explained in the processor-specific hints.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FCC}
+\ttindex{FCC}
+
+{\em valid for: 6502, 68xx}
+
+When in 65xx/68xx mode, string constants are generated using this
+instruction. In contrast to the original assembler AS11 from Motorola
+(this is the main reason why AS understands this command, the
+functionality is contained within the \tty{BYT} instruction) you must
+enclose the string argument by double quotation marks instead of single
+quotation marks or slashes. Similarly to \tty{DC}, a repetition factor
+enclosed in brackets ([..]) may be prepended to every single parameter.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DFS or RMB}
+\ttindex{DFS}\ttindex{RMB}
+
+{\em valid for: 6502, 68xx}
+
+Reserves a memory block when in 6502/68xx mode. It is therefore the
+equivalent to \tty{DS.B} on the 68000 or \tty{DB ?} on Intel platforms.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BLOCK}
+\ttindex{BLOCK}
+
+{\em valid for: ST6}
+
+Ditto.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SPACE}
+\ttindex{SPACE}
+
+{\em valid for: i960}
+
+Ditto.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{RES}
+\ttindex{RES}
+
+{\em valid for: PIC, MELPS-4500, 3201x, 320C2(0)x, 320C5x, AVR, $\mu$PD772x}
+
+This command allocates memory. When used in code segments the
+argument counts words (10/12/14/16 bit). In data segments it counts
+bytes for PICs, nibbles for 4500's and words for the TI devices.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BSS}
+\ttindex{BSS}
+
+{\em valid for: 320C2(0)x, 320C3x, 320C5x, MSP}
+
+\tty{BSS} works like \tty{RES}, but when in 320C2(0)x/5x mode, the assembler
+assumes that a label on the left side of this instruction has no type, i.e
+it belongs to no address space. This behaviour is explained in the
+processor-specific hints.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DSB and DSW}
+\ttindex{DSB}\ttindex{DSW}
+
+{\em valid for: COP8}
+
+Both instructions allocate memory and ensure compatibility to ASMCOP from
+National. While \tty{DSB} takes the argument as byte count, \tty{DSW}
+uses it as word count (thus it allocates twice as much memory than
+\tty{DSB}).
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{DS16}
+\ttindex{DS16}
+
+{\em valid for: SC144xx}
+
+This instruction reserves memory in steps of full words, i.e. 16 bits. It
+is an alias for {\tt DW}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{ALIGN}
+\ttindex{ALIGN}
+
+{\em valid for: all processors}
+
+Takes the argument to align the program counter to a certain address
+boundary. AS increments the program counter to the next multiple of the
+argument. So, \tty{ALIGN} corresponds to \tty{DS.x} on 68000, but is much
+more flexible at the same time.
+
+Example:
+\begin{verbatim}
+ align 2
+\end{verbatim}
+aligns to an even address (PC mod 2 = 0). The contents of the
+skipped addresses is left undefined.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LTORG}
+\ttindex{LTORG}
+
+{\em valid for: SH7x00}
+
+Although the SH7000 processor can do an immediate register load with
+8 bit only, AS shows up with no such restriction. This behaviour is
+instead simulated through constants in memory. Storing them in
+the code segment (not far away from the register load instruction)
+would require an additional jump. AS Therefore gathers the constants
+an stores them at an address specified by \tty{LTORG}. Details are
+explained in the processor-specific section somewhat later.
+
+%%---------------------------------------------------------------------------
+
+\section{Macro Instructions}
+
+{\em valid for: all processors}
+
+Now we finally reach the things that make a macro assembler different
+from an ordinary assembler: the ability to define macros (guessed
+it !?).
+
+When speaking about 'macros', I generally mean a sequence of (machine
+or pseudo) instructions which are united to a block by special
+statements and can then be treated in certain ways. The assembler
+knows the following statements to work with such blocks:
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{MACRO}
+\ttindex{MACRO}\ttindex{ENDM}
+
+is probably the most important instruction for macro programming.
+The instruction sequence
+\begin{verbatim}
+<name> MACRO [parameter list]
+ <instructions>
+ ENDM
+\end{verbatim}
+defines the macro \tty{$<$name$>$} to be the enclosed instruction sequence.
+This definition by itself does not generate any code! In turn, from
+now on the instruction sequence can simply be called by the name, the
+whole construct therefore shortens and simplifies programs. A
+parameter list may be added to the macro definition to make things
+even more useful. The parameters' names have to be separated by
+commas (as usual) and have to conform to the conventions for symbol
+names (see section \ref{SectSymConv}) - like the macro name itself.
+
+A switch to case-sensitive mode influences both macro names and
+parameters.
+
+Similar to symbols, macros are local, i.e. they are only known in a
+section and its subsections when the definition is done from within
+a section. This behaviour however can be controlled in wide limits
+via the options \tty{PUBLIC} and \tty{GLOBAL} described below.
+
+Apart from the macro parameters themselves, the parameter list may
+contain control parameters which influence the processing of the
+macro. These parameters are distinguished from normal parameters by
+being enclosed in braces. The following control parameters are
+defined:
+\begin{itemize}
+\item{\tty{EXPAND/NOEXPAND}: rule whether the enclosed code shall
+ be written to the listing when the macro is expanded. The
+ default is the value set by the pseudo instruction \tty{MACEXP}.}
+\item{\tty{PUBLIC[:section name]}: assigns the macro to a parent section
+ instead of the current section. A section can make macros
+ accessible for the outer code this way. If the section
+ specification is missing, the macro becomes completely global, i.e.
+ it may be referenced from everywhere.}
+\item{\tty{GLOBAL[:section name]}: rules that in addition to the macro
+ itself, another macro shall be generated that has the same contents
+ but is assigned to the specified section. Its name is constructed by
+ concatenating the current section's name to the macro name. The
+ section specified must be a parent section of the current section;
+ if the specification is missing, the additional macro becomes
+ globally visible. For example, if a macro \tty{A} is defined in a
+ section \tty{B} that is a child section of section \tty{C}, an additional
+ global macro named \tty{C\_B\_A} would be generated. In contrast, if
+ \tty{C} had been specified as target section, the macro would be named \tty{B\_A}
+ and be assigned to section \tty{C}. This option is turned off by default
+ and it only has an effect when it is used from within a section.
+ The macro defined locally is not influenced by this option.}
+\item{\tty{EXPORT/NOEXPORT}: rules whether the definition of this macro
+ shall be written to a separate file in case the \tty{-M} command line
+ option was given. This way, definitions of 'private' macros may
+ be mapped out selectively. The default is FALSE, i.e. the
+ definition will not be written to the file. The macro will be
+ written with the concatenated name if the \tty{GLOBAL} option was
+ additionally present.}
+\end{itemize}
+The control parameters described above are removed from the parameter
+list by AS, i.e. they do not have a further influence on processing
+and usage.
+
+When a macro is called, the parameters given for the call are
+textually inserted into the instruction block and the resulting
+assembler code is assembled as usual. Zero length parameters are
+inserted in case too few parameters are specified. It is important
+to note that string constants are not protected from macro
+expansions. The old IBM rule:
+\begin{quote}{\it
+ It's not a bug, it's a feature!
+}\end{quote}
+applies for this detail. The gap was left to allow checking of
+parameters via string comparisons. For example, one can analyze a
+macro parameter in the following way:
+\begin{verbatim}
+mul MACRO para,parb
+ IF UpString("PARA")<>"A"
+ MOV a,para
+ ENDIF
+ IF UpString("PARB")<>"B"
+ MOV b,parb
+ ENDIF
+ mul ab
+ ENDM
+\end{verbatim}
+It is important for the example above that the assembler converts all
+parameter names to upper case when operating in case-insensitive
+mode, but this conversion never takes place inside of string constants.
+Macro parameter names therefore have to be written in upper case when
+they appear in string constants.
+
+The same naming rules as for usual symbols also apply for macro
+parameters, with the exception that only letters and numbers are
+allowed, i.e. dots and underscores are forbidden. This constraint
+has its reason in a hidden feature: the underscore allows to
+concatenate macro parameter names to a symbol, like in the following
+example:
+\begin{verbatim}
+concat macro part1,part2
+ call part1_part2
+ endm
+\end{verbatim}
+The call
+\begin{verbatim}
+ concat module,function
+\end{verbatim}
+will therefore result in
+\begin{verbatim}
+ call module_function
+\end{verbatim}
+A small example to remove all clarities ;-)
+
+A programmer braindamaged by years of programming Intel processors
+wants to have the instructions \tty{PUSH/POP} also for the 68000. He
+solves the 'problem' in the following way:
+\begin{verbatim}
+push macro op
+ move op,-(sp)
+ endm
+
+pop macro op
+ move (sp)+,op
+ endm
+\end{verbatim}
+If one writes
+\begin{verbatim}
+ push d0
+ pop a2 ,
+\end{verbatim}
+this results in
+\begin{verbatim}
+ move.w d0,-(sp)
+ move.w (sp)+,a2
+\end{verbatim}
+A macro definition must not cross include file boundaries.
+
+Labels defined in macros always are regarded as being local, an explicit
+\tty{LOCAL} instruction is therefore not necessary (it even does not
+exist). In case there is a reason to make a label global, one may define
+it with \tty{LABEL} which always creates global symbols (similar to \tty{BIT,
+SFR...}):
+\begin{verbatim}
+<Name> label $
+\end{verbatim}
+When parsing a line, the assembler first checks the macro list
+afterwards looks for processor instructions, which is why macros
+allow to redefine processor instructions. However, the definition
+should appear previously to the first invocation of the instruction
+to avoid phase errors like in the following example:
+\begin{verbatim}
+ bsr target
+
+bsr macro targ
+ jsr targ
+ endm
+
+ bsr target
+\end{verbatim}
+In the first pass, the macro is not known when the first \tty{BSR}
+instruction is assembled; an instruction with 4 bytes of length is
+generated. In the second pass however, the macro definition is
+immediately available (from the first pass), a \tty{JSR} of 6 bytes length
+is therefore generated. As a result, all labels following are too low
+by 2 and phase errors occur for them. An additional pass is
+necessary to resolve this.
+
+Because a machine or pseudo instruction becomes hidden when a macro
+of same name is defined, there is a backdoor to reach the original
+meaning: the search for macros is suppressed if the name is prefixed
+with an exclamation mark (!). This may come in handy if one wants to
+extend existing instructions in their functionality, e.g. the
+TLCS-90's shift instructions:
+\begin{verbatim}
+srl macro op,n ; shift by n places
+ rept n ; n simple instructions
+ !srl op
+ endm
+ endm
+\end{verbatim}
+From now on, the \tty{SRL} instruction has an additional parameter...
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{IRP}
+\ttindex{IRP}
+
+is a simplified macro definition for the case that an instruction sequence
+shall be applied to a couple of operands and the the code is not needed
+any more afterwards. \tty{IRP} needs a symbol for the operand as its
+first parameter, and an (almost) arbitrary number of parameters that are
+sequentially inserted into the block of code. For example, one can write
+\begin{verbatim}
+ irp op, acc,b,dpl,dph
+ push op
+ endm
+\end{verbatim}
+to push a couple of registers to the stack, what results in
+\begin{verbatim}
+ push acc
+ push b
+ push dpl
+ push dph
+\end{verbatim}
+Again, labels used are automatically local for every pass.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{IRPC}
+\ttindex{IRPC}
+
+\tty{IRPC} is a variant of \tty{IRP} where the first argument's occurences
+in the lines up to \tty{ENDM} are successively replaced by the characters
+of a string instead of further parameters. For example, an especially
+complicated way of placing a string into memory would be:
+\begin{verbatim}
+ irpc char,"Hello World"
+ db 'CHAR'
+ endm
+\end{verbatim}
+\bb{CAUTION!} As the example already shows, \tty{IRPC} only inserts the
+pure character; it is the programmer's task to assure that valid code
+results (in this example by inserting quotes, including the detail that no
+automatic conversion to uppercase characters is done).
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{REPT}
+\ttindex{REPT}
+
+is the simplest way to employ macro constructs. The code between
+\tty{REPT} and \tty{ENDM} is assembled as often as the integer argument of
+\tty{REPT} specifies. This statement is commonly used in small loops to
+replace a programmed loop to save the loop overhead.
+
+An example for the sake of completeness:
+\begin{verbatim}
+ rept 3
+ rr a
+ endm
+\end{verbatim}
+rotates the accumulator to the right by three digits.
+
+In case \tty{REPT}'s argument is equal to or smaller than 0, no expansion
+at all is done. This is different to older versions of AS which used to
+be a bit 'sloppy' in this respect and always made a single expansion.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{WHILE}
+\ttindex{WHILE}
+
+\tty{WHILE} operates similarly to \tty{REPT}, but the fixed number of
+repetitions given as an argument is replaced by a boolean expression. The
+code framed by \tty{WHILE} and \tty{ENDM} is assembled until the
+expression becomes logically false. This may mean in the extreme case
+that the enclosed code is not assembled at all in case the expression was
+already false when the construct was found. On the other hand, it may
+happen that the expression stays true forever and AS will run
+infinitely...one should apply therefore a bit of accuracy when one uses
+this construct, i.e. the code must contain a statement that influences the
+condition, e.g. like this:
+\begin{verbatim}
+cnt set 1
+sq set cnt*cnt
+ while sq<=1000
+ dc.l sq
+cnt set cnt+1
+sq set cnt*cnt
+ endm
+\end{verbatim}
+This example stores all square numbers up to 1000 to memory.
+
+Currently there exists a little ugly detail for \tty{WHILE}: an additional
+empty line that was not present in the code itself is added after the last
+expansion. This is a 'side effect' based on a weakness of the macro
+processor and it is unfortunately not that easy to fix. I hope noone
+minds...
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{EXITM}
+\ttindex{EXITM}
+
+\tty{EXITM} offers a way to terminate a macro expansion or one of the
+instructions \tty{REPT, IRP,} or \tty{WHILE} prematurely. Such an option
+helps for example to replace encapsulations with \tty{IF-ENDIF}-ladders in
+macros by something more readable. Of course, an \tty{EXITM} itself
+always has to be conditional, what leads us to an important detail: When
+an \tty{EXITM} is executed, the stack of open \tty{IF} and
+\tty{SWITCH} constructs is reset to the state it had just before the macro
+expansion started. This is imperative for conditional \tty{EXITM}'s as
+the \tty{ENDIF} resp. \tty{ENDCASE} that frames the \tty{EXITM} statement
+will not be reached any more; AS would print an error message without this
+trick. Please keep also in mind that \tty{EXITM} always only terminates
+the innermost construct if macro constructs are nested! If one want to
+completely break out of a nested construct, one has to use additional
+\tty{EXITM}'s on the higher levels!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FUNCTION}
+\label{SectFUNCTION}
+\ttindex{FUNCTION}
+
+Though \tty{FUNCTION} is not a macro statement in the inner sense, I will
+describe this instruction at this place because it uses similar principles
+like macro replacements.
+
+This instruction is used to define new functions that may then be
+used in formula expressions like predefined functions. The
+definition must have the following form:
+\begin{verbatim}
+<name> FUNCTION <arg>,..,<arg>,<expression>
+\end{verbatim}
+The arguments are the values that are 'fed into' the function. The
+definition uses symbolic names for the arguments. The assembler
+knows by this that where to insert the actual values when the
+function is called. This can be seen from the following example:
+\begin{verbatim}
+isdigit FUNCTION ch,(ch>='0')&&(ch<='9')
+\end{verbatim}
+This function checks whether the argument (interpreted as a character) is
+a number in the currently valid character set (the character set can be
+modified via \tty{CHARSET}, therefore the careful wording).
+
+The arguments' names (\tty{CH} in this case) must conform to the stricter
+rules for macro parameter names, i.e. the special characters . and \_
+are not allowed.
+
+User-defined functions can be used in the same way as builtin
+functions, i.e. with a list of parameters, separated by commas,
+enclosed in parentheses:
+\begin{verbatim}
+ IF isdigit(char)
+ message "\{char} is a number"
+ ELSEIF
+ message "\{char} is not a number"
+ ENDIF
+\end{verbatim}
+When the function is called, all parameters are calculated once and
+are then inserted into the function's formula. This is done to
+reduce calculation overhead and to avoid side effects. The
+individual arguments have to be separated by commas when a function
+has more than one parameter.
+
+\bb{CAUTION!} Similar to macros, one can use user-defined functions to
+override builtin functions. This is a possible source for phase
+errors. Such definitions therefore should be done before the first
+call!
+
+The result's type may depend on the type of the input arguments as
+the arguments are textually inserted into the function's formula.
+For example, the function
+\begin{verbatim}
+double function x,x+x
+\end{verbatim}
+may have an integer, a float, or even a string as result, depending
+on the argument's type!
+
+When AS operates in case-sensitive mode, the case matters when
+defining or referencing user-defined functions, in contrast to
+builtin functions!
+
+%%---------------------------------------------------------------------------
+
+\section{Conditional Assembly}
+
+{\em valid for: all processors}
+
+The assembler supports conditional assembly with the help of statements
+like \tty{IF...} resp. \tty{SWITCH...} . These statements work at
+assembly time allowing or disallowing the assembly of program parts based
+on conditions. They are therefore not to be compared with IF statements
+of high-level languages (though it would be tempting to extend assembly
+language with structurization statements of higher level languages...).
+
+The following constructs may be nested arbitrarily (until a memory
+overflow occurs).
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{IF / ELSEIF / ENDIF}
+\ttindex{IF}
+\ttindex{ENDIF}
+\ttindex{ELSEIF}\ttindex{ELSE}
+
+\tty{IF} is the most common and most versatile construct. The general
+style of an \tty{IF} statement is as follows:
+\begin{verbatim}
+ IF <expression 1>
+ .
+ .
+ <block 1>
+ .
+ .
+ ELSEIF <expression 2>
+ .
+ .
+ <block 2>
+ .
+ .
+ (possibly more ELSEIFs)
+
+ .
+ .
+ ELSEIF
+ .
+ .
+ <block n>
+ .
+ .
+ ENDIF
+\end{verbatim}
+\tty{IF} serves as an entry, evaluates the first expression, and assembles
+block 1 if the expression is true (i.e. not 0). All further
+\tty{ELSEIF}-blocks will then be skipped. However, if the expression is
+false, block 1 will be skipped and expression 2 is evaluated. If this
+expression turns out to be true, block 2 is assembled. The number of
+\tty{ELSEIF} parts is variable and results in an \tty{IF-THEN-ELSE} ladder
+of an arbitrary length. The block assigned to the last \tty{ELSEIF}
+(without argument) only gets assembled if all previous expressions
+evaluated to false; it therefore forms a 'default' branch. It is
+important to note that only \bb{one} of the blocks will be assembled: the
+first one whose \tty{IF/ELSEIF} had a true expression as argument.
+
+The \tty{ELSEIF} parts are optional, i.e. \tty{IF} may directly be
+followed by an \tty{ENDIF}. An \tty{ELSEIF} without parameters must be
+the last branch.
+
+\tty{ELSEIF} always refers to the innermost, unfinished \tty{IF} construct
+in case \tty{IF}'s are nested.
+
+\ttindex{IFDEF}\ttindex{IFNDEF}\ttindex{IFUSED}\ttindex{IFNUSED}
+\ttindex{IFEXIST}\ttindex{IFNEXIST}\ttindex{IFB}\ttindex{IFNB}
+In addition to \tty{IF}, the following further conditional statements are
+defined:
+\begin{itemize}
+\item{\tty{IFDEF $<$symbol$>$}: true if the given symbol has been defined.
+ The definition has to appear before \tty{IFDEF}.}
+\item{\tty{IFNDEF $<$symbol$>$}: counterpart to \tty{IFDEF}.}
+\item{\tty{IFUSED $<$symbol$>$}: true if if the given symbol has been
+ referenced at least once up to now.}
+\item{\tty{IFNUSED $<$symbol$>$}: counterpart to \tty{IFUSED}.}
+\item{\tty{IFEXIST $<$name$>$}: true if the given file exists. The same
+ rules for search paths and syntax apply as for the
+ \tty{INCLUDE} instruction (see section \ref{SectInclude}).}
+\item{\tty{IFNEXIST $<$name$>$}: counterpart to \tty{IFEXIST}.}
+\item{\tty{IFB $<$arg-list$>$}: true if all arguments of the parameter
+ list are empty strings.}
+\item{\tty{IFNB $<$arg-list$>$}: counterpart to \tty{IFB}.}
+\end{itemize}
+
+It is valid to write {\tt ELSE} instead of {\tt ELSEIF} since everybody
+seems to be used to it...
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SWITCH / CASE / ELSECASE / ENDCASE}
+\ttindex{SWITCH}\ttindex{CASE}\ttindex{ELSECASE}\ttindex{ENDCASE}
+
+\tty{CASE} is a special case of \tty{IF} and is designed for situations
+when an expression has to be compared with a couple of values. This could
+of course also be done with a series of \tty{ELSEIF}s, but the following
+form
+\begin{verbatim}
+ SWITCH <expression>
+ .
+ .
+ CASE <value 1>
+ .
+ <block 1>
+ .
+ CASE <value 2>
+ .
+ <block 2>
+ .
+ (further CASE blocks)
+ .
+ CASE <value n-1>
+ .
+ <block n-1>
+ .
+ ELSECASE
+ .
+ <block n>
+ .
+ ENDCASE
+\end{verbatim}
+has the advantage that the expression is only written once and also only
+gets evaluated once. It is therefore less error-prone and slightly faster
+than an \tty{IF} chain, but obviously not as flexible.
+
+It is possible to specify multiple values separated by commas to a
+\tty{CASE} statement in order to assemble the following block in multiple
+cases. The \tty{ELSECASE} branch again serves as a 'trap' for the case
+that none of the \tty{CASE} conditions was met. AS will issue a warning
+in case it is missing and all comparisons fail.
+
+Even when value lists of \tty{CASE} branches overlap, only \bb{one} branch
+is executed, which is the first one in case of ambiguities.
+
+\tty{SWITCH} only serves to open the whole construct; an arbitrary number
+of statements may be between \tty{SWITCH} and the first \tty{CASE} (but
+don't leave other \tty{IF}s open!), for the sake of better readability
+this should however not be done.
+
+%%---------------------------------------------------------------------------
+
+\section{Listing Control}
+
+{\em valid for: all processors}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PAGE}
+\ttindex{PAGE}
+
+\tty{PAGE} is used to tell AS the dimensions of the paper that is used to
+print the assembly listing. The first parameter is thereby the
+number of lines after which AS shall automatically output a form
+feed. One should however take into account that this value does \bb{not}
+include heading lines including an eventual line specified with
+\tty{TITLE}. The minimum number of lines is 5, and the maximum value is
+255. A specification of 0 has the result that AS will not do any form
+feeds except those triggered by a \tty{NEWPAGE} instruction or those
+implicitly engaged at the end of the assembly listing (e.g. prior to the
+symbol table).
+
+The specification of the listing's length in characters is an
+optional second parameter and serves two purposes: on the one hand,
+the internal line counter of AS will continue to run correctly when a
+source line has to be split into several listing lines, and on
+the other hand there are printers (like some laser printers) that do
+not automatically wrap into a new line at line end but instead simply
+discard the rest. For this reason, AS does line breaks by itself,
+i.e. lines that are too long are split into chunks whose lengths are
+equal to or smaller than the specified width. This may lead to
+double line feeds on printers that can do line wraps on their own if
+one specifies the exact line width as listing width. The solution
+for such a case is to reduce the assembly listing's width by 1. The
+specified line width may lie between 5 and 255 characters; a line
+width of 0 means similarly to the page length that AS shall not do
+any splitting of listing lines; lines that are too long of course
+cannot be taken into account of the form feed then any more.
+
+The default setting for the page length is 60 lines, the default for the
+line width is 0; the latter value is also assumed when \tty{PAGE} is
+called with only one parameter.
+
+\bb{CAUTION!} There is no way for AS to check whether the specified
+listing length and width correspond to the reality!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{NEWPAGE}
+\ttindex{NEWPAGE}
+
+\tty{NEWPAGE} can be used to force a line feed though the current line is
+not full up to now. This might be useful to separate program parts
+in the listing that are logically different. The internal line
+counter is reset and the page counter is incremented by one. The
+optional parameter is in conjunction with a hierarchical page
+numbering AS supports up to a chapter depth of 4. 0 always refers to
+the lowest depth, and the maximum value may vary during the assembly
+run. This may look a bit puzzling, as the following example shows:
+\begin{quote}\begin{tabbing}
+\hspace{2.5cm} \= \hspace{4.5cm} \= \kill
+page 1, \> instruction \tty{NEWPAGE 0} \> $\rightarrow$ page 2 \\
+page 2, \> instruction \tty{NEWPAGE 1} \> $\rightarrow$ page 2.1 \\
+page 2.1, \> instruction \tty{NEWPAGE 1} \> $\rightarrow$ page 3.1 \\
+page 3.1, \> instruction \tty{NEWPAGE 0} \> $\rightarrow$ page 3.2 \\
+page 3.2, \> instruction \tty{NEWPAGE 2} \> $\rightarrow$ page 4.1.1 \\
+\end{tabbing}\end{quote}
+\tty{NEWPAGE $<$number$>$} may therefore result in
+changes in different digits, depending on the current chapter depth. An
+automatic form feed due to a line counter overflow or a \tty{NEWPAGE}
+without parameter is equal to \tty{NEWPAGE 0}. Previous to the output of
+the symbol table, an implicit \tty{NEWPAGE $<$maximum up to now$>$} is
+done to start a new 'main chapter'.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{MACEXP}
+\ttindex{MACEXP}
+
+One can achieve by the statement
+\begin{verbatim}
+ macexp off
+\end{verbatim}
+that only the macro call and not the expanded text is listed for
+macro expansions. This is sensible for macro intensive codes to
+avoid that the listing grows beyond all bounds. The full listing can
+be turned on again with a
+\begin{verbatim}
+ macexp on .
+\end{verbatim}
+This is also the default.
+
+There is a subtle difference between the meaning of \tty{MACEXP} for
+macros and for all other macro-like constructs (e.g. \tty{REPT}): while a
+macro contain an internal flag that rules whether expansions of this macro
+shall be listed or not, \tty{MACEXP} directly influences all other
+constructs that are resolved 'in place'. The reason for this
+differentiation is that there may be macros that are tested and their
+expansion is therefore unnecessary, but all other macros still shall be
+expanded. \tty{MACEXP} serves as a default for the macro's internal flag
+when it is defined, and it may be overridden by the \tty{NOEXPAND} resp.
+\tty{EXPAND} directives.
+
+The current setting may be read from the symbol \tty{MACEXP}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{LISTING}
+\ttindex{LISTING}
+
+works like \tty{MACEXP} and accepts the same parameters, but is much more
+radical: After a
+\begin{verbatim}
+ listing off ,
+\end{verbatim}
+nothing at all will be written to the listing. This directive makes sense
+for tested code parts or include files to avoid a paper consumption going
+beyond all bounds. \bb{CAUTION!} If one forgets to issue the counterpart
+somewhere later, even the symbol table will not be written any more! In
+addition to \tty{ON} and \tty{OFF}, \tty{LISTING} also accepts
+\tty{NOSKIPPED} and \tty{PURECODE} as arguments. Program parts that were
+not assembled due to conditional assembly will not be written to the
+listing when \tty{NOSKIPPED} is set, while \tty{PURECODE} - as the name
+indicates - even suppresses the \tty{IF} directives themselves in the
+listing. These options are useful if one uses macros that act differently
+depending on parameters and one only wants to see the used parts in the
+listing.
+
+The current setting may be read from the symbol \tty{LISTING} (0=\tty{OFF},
+1=\tty{ON}, 2=\tty{NOSKIPPED}, 3=\tty{PURECODE}).
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PRTINIT and PRTEXIT}
+\ttindex{PRTINIT}\ttindex{PRTEXIT}
+
+Quite often it makes sense to switch to another printing mode (like
+compressed printing) when the listing is sent to a printer and to
+deactivate this mode again at the end of the listing. The output of
+the needed control sequences can be automated with these instructions
+if one specifies the sequence that shall be sent to the output device
+prior to the listing with \tty{PRTINIT $<$string$>$} and similarly the
+deinitialization string with \tty{PRTEXIT $<$string$>$}.
+\tty{$<$string$>$} has to be a string expression in both cases. The syntax
+rules for string constants allow to insert control characters into the
+string without too much tweaking.
+
+When writing the listing, the assembler does \bb{not} differentiate where
+the listing actually goes, i.e. printer control characters are sent to the
+screen without mercy!
+
+Example:
+
+For Epson printers, it makes sense to switch them to compressed
+printing because listings are so wide. The lines
+\begin{verbatim}
+ prtinit "\15"
+ prtexit "\18"
+\end{verbatim}
+assure that the compressed mode is turned on at the beginning of the
+listing and turned off afterwards.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{TITLE}
+\ttindex{TITLE}
+
+The assembler normally adds a header line to each page of the listing
+that contains the source file's name, date, and time. This
+statement allows to extend the page header by an arbitrary additional
+line. The string that has to be specified is an arbitrary string
+expression.
+
+Example:
+
+For the Epson printer already mentioned above, a title line shall be
+written in wide mode, which makes it necessary to turn off the
+compressed mode before:
+\begin{verbatim}
+ title "\18\14Wide Title\15"
+\end{verbatim}
+(Epson printers automatically turn off the wide mode at the end of a
+line.)
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{RADIX}
+\ttindex{RADIX}
+
+\tty{RADIX} with a numerical argument between 2 and 36 sets the default
+numbering system for integer constants, i.e. the numbering system used if
+nothing else has been stated explicitly. The default is 10, and there are
+some possible pitfalls to keep in mind which are described in section
+\ref{SectIntConsts}.
+
+Independent of the current setting, the argument of {\tt RADIX} is {\em
+always decimal}; furthermore, no symbolic or formula expressions may be
+used as argument. Only use simple constant numbers!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{OUTRADIX}
+\ttindex{OUTRADIX}
+
+\tty{OUTRADIX} can in a certain way be regarded as the opposite to
+\tty{RADIX}: This statement allows to configure which numbering system to
+use for integer results when \verb!\{...}! constructs are used in string
+constants (see section \ref{SectStringConsts}). Valid arguments range
+again from 2 to 36, while the default is 16.
+
+%%---------------------------------------------------------------------------
+
+\section{Local Symbols}
+\label{ChapLocSyms}
+
+{\em valid for: all processors}
+
+local symbols and the section concept introduced with them are a
+completely new function that was introduced with version 1.39. One
+could say that this part is version ''1.0'' and therefore probably not
+the optimum. Ideas and (constructive) criticism are therefore
+especially wanted. I admittedly described the usage of sections how
+I imagined it. It is therefore possible that the reality is not
+entirely equal to the model in my head. I promise that in case of
+discrepancies, changes will occur that the reality gets adapted to
+the documentation and not vice versa (I was told that the latter
+sometimes takes place in larger companies...).
+
+AS does not generate linkable code (and this will probably not change
+in the near future \tty{:-(}). This fact forces one to always assemble a
+program in a whole. In contrast to this technique, a separation into
+linkable modules would have several advantages:
+\begin{itemize}
+\item{shorter assembly times as only the modified modules have to be
+ reassembled;}
+\item{the option to set up defined interfaces among modules by definition
+ of private and public symbols;}
+\item{the smaller length of the individual modules reduces the number of
+ symbols per module and therefore allows to use shorter symbol names
+ that are still unique.}
+\end{itemize}
+Especially the last item was something that always nagged me: once
+there was a label's name defined at the beginning of a 2000-lines
+program, there was no way to reuse it somehow - even not at the
+file's other end where routines with a completely different context
+were placed. I was forced to use concatenated names in the style of
+\begin{verbatim}
+ <subprogram name>_<symbol name>
+\end{verbatim}
+that had lengths ranging from 15 to 25 characters and made the
+program difficult to overlook. The concept of section described in
+detail in the following text was designed to cure at least the second
+and third item of the list above. It is completely optional: if you
+do not want to use sections, simply forget them and continue to work
+like you did with previous versions of AS.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{Basic Definition (SECTION/ENDSECTION)}
+\ttindex{SECTION}\ttindex{ENDSECTION}
+
+A section represents a part of the assembler program enclosed by
+special statements and has a unique name chosen by the programmer:
+\begin{verbatim}
+ .
+ .
+ <other code>
+ .
+ .
+ SECTION <section's name>
+ .
+ .
+ <code inside of the section>
+ .
+ .
+ ENDSECTION [section's name]
+ .
+ .
+ <other code>
+ .
+ .
+\end{verbatim}
+The name of a section must conform to the conventions for s symbol
+name; AS stores section and symbol names in separate tables which is
+the reason why a name may be used for a symbol and a section at the
+same time. Section names must be unique in a sense that there must
+not be more than one section on the same level with the same name (I
+will explain in the next part what ''levels'' mean). The argument of
+\tty{ENDSECTION} is optional, it may also be omitted; if it is omitted, AS
+will show the section's name that has been closed with this
+\tty{ENDSECTION}. Code inside a section will be processed by AS exactly
+as if it were outside, except for three decisive differences:
+\begin{itemize}
+\item{Symbols defined within a section additionally get an internally
+ generated number that corresponds to the section. These symbols
+ are not accessible by code outside the section (this can be
+ changed by pseudo instructions, later more about this).}
+\item{The additional attribute allows to define symbols of the same
+ name inside and outside the section; the attribute makes it
+ possible to use a symbol name multiple times without getting error
+ messages from AS.}
+\item{If a symbol of a certain name has been defined inside and outside
+ of a section, the ''local'' one will be preferred inside the
+ section, i.e. AS first searches the symbol table for a symbol of
+ the referenced name that also was assigned to the section. A
+ search for a global symbol of this name only takes place if the
+ first search fails.}
+\end{itemize}
+This mechanism e.g. allows to split the code into modules as one
+might have done it with linkable code. A more fine-grained approach
+would be to pack every routine into a separate section. Depending on
+the individual routines' lengths, the symbols for internal use may
+obtain very short names.
+
+AS will by default not differentiate between upper and lower case in
+section names; if one however switches to case-sensitive mode, the
+case will be regarded just like for symbols.
+
+The organization described up to now roughly corresponds to what is
+possible in the C language that places all functions on the same
+level. However, as my ''high-level'' ideal was Pascal and not C, I
+went one step further:
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{Nesting and Scope Rules}
+
+It is valid to define further sections within a section. This is
+analog to the option given in Pascal to define procedures inside a
+procedure or function. The following example shows this:
+\begin{verbatim}
+sym EQU 0
+
+ SECTION ModuleA
+
+ SECTION ProcA1
+
+sym EQU 5
+
+ ENDSECTION ProcA1
+
+ SECTION ProcA2
+
+sym EQU 10
+
+ ENDSECTION ProcA2
+
+ ENDSECTION ModuleA
+
+
+ SECTION ModuleB
+
+sym EQU 15
+
+ SECTION ProcB
+
+ ENDSECTION ProcB
+
+ ENDSECTION ModuleB
+\end{verbatim}
+When looking up a symbol, AS first searches for a symbol assigned to
+the current section, and afterwards traverses the list of parent
+sections until the global symbols are reached. In our example, the
+individual sections see the values given in table \ref{TabSymErg} for
+the symbol \tty{sym}:
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+section & value & from section... \\
+\hline
+\hline
+Global & 0 & Global \\
+\hline
+\tty{ModuleA} & 0 & Global \\
+\hline
+\tty{ProcA1} & 5 & \tty{ProcA1} \\
+\hline
+\tty{ProcA2} & 10 & \tty{ProcA2} \\
+\hline
+\tty{ModuleB} & 15 & \tty{ModuleB} \\
+\hline
+\tty{ProcB} & 15 & \tty{ModuleB} \\
+\hline
+\end{tabular}\end{center}
+\caption{Valid values for the Individual Sections\label{TabSymErg}}
+\end{table*}
+This rule can be overridden by explicitly appending a section's name
+to the symbol's name. The section's name has to be enclosed in
+brackets:
+\begin{verbatim}
+ move.l #sym[ModulB],d0
+\end{verbatim}
+Only sections that are in the parent section path of the current
+section may be used. The special values \tty{PARENT0..PARENT9} are allowed
+to reference the n-th ''parent'' of the current section; \tty{PARENT0} is
+therefore equivalent to the current section itself, \tty{PARENT1} the
+direct parent and so on. \tty{PARENT1} may be abbreviated as \tty{PARENT}. If
+no name is given between the brackets, like in this example:
+\begin{verbatim}
+ move.l #sym[],d0 ,
+\end{verbatim}
+one reaches the global symbol. \bb{CAUTION!} If one explicitly
+references a symbol from a certain section, AS will only seek for
+symbols from this section, i.e. the traversal of the parent sections
+path is omitted!
+
+Similar to Pascal, it is allowed that different sections have
+subsections of the same name; the principle of locality avoids
+irritations. One should IMHO still use this feature as seldom as
+possible: Symbols listed in the symbol resp. cross reference list are
+only marked with the section they are assigned to, not with the
+''section hierarchy'' lying above them (this really would have busted
+the available space); a differentiation is made very difficult this
+way.
+
+As a \tty{SECTION} instruction does not define a label by itself, the
+section concept has an important difference to Pascal's concept of
+nested procedures: a pascal procedure can automatically ''see'' its
+subprocedures(functions), AS requires an explicit definition of an
+entry point. This can be done e.g. with the following macro pair:
+\begin{verbatim}
+proc MACRO name
+ SECTION name
+name LABEL $
+ ENDM
+
+endp MACRO name
+ ENDSECTION name
+ ENDM
+\end{verbatim}
+This example also shows that the locality of labels inside macros
+is not influenced by sections. It makes the trick with the \tty{LABEL}
+instruction necessary.
+
+This does of course not solve the problem completely. The label is
+still local and not referencable from the outside. Those who think
+that it would suffice to place the label in front of the \tty{SECTION}
+statement should be quiet because they would spoil the bridge to the
+next theme:
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{PUBLIC and GLOBAL}
+\ttindex{PUBLIC}\ttindex{GLOBAL}
+
+The \tty{PUBLIC} statement allows to change the assignment of a symbol to
+a certain section. It is possible to treat multiple symbols with one
+statement, but I will use an example with only one symbol in the following
+(not hurting the generality of this discussion). In the simplest case,
+one declares a symbol to be global, i.e. it can be referenced from
+anywhere in the program:
+\begin{verbatim}
+ PUBLIC <name>
+\end{verbatim}
+As a symbol cannot be moved in the symbol table once it has been sorted
+in, this statement has to appear \bb{before} the symbol itself is
+defined. AS stores all \tty{PUBLICs} in a list and removes an entry from
+this list when the corresponding symbol is defined. AS prints errors at
+the end of a section in case that not all \tty{PUBLICs} have been
+resolved.
+
+Regarding the hierarchical section concept, the method of defining a
+symbol as purely global looks extremely brute. There is fortunately
+a way to do this in a bit more differentiated way: by appending a
+section name:
+\begin{verbatim}
+ PUBLIC <name>:<section>
+\end{verbatim}
+The symbol will be assigned to the referenced section and therefore also
+becomes accessible for all its subsections (except they define a symbol of
+the same name that hides the ''more global'' symbol). AS will naturally
+protest if several subsections try to export a symbol of same name to the
+same level. The special \tty{PARENTn} values mentioned in the previous
+section are also valid for \tty{$<$section$>$} to export a symbol exactly
+\tty{n} levels up in the section hierarchy. Otherwise only sections that
+are parent sections of the current section are valid for
+\tty{$<$section$>$}. Sections that are in another part of the section
+tree are not allowed. If several sections in the parent section path
+should have the same name (this is possible), the lowest level will be
+taken.
+
+This tool lets the abovementioned macro become useful:
+\begin{verbatim}
+proc MACRO name
+ SECTION name
+ PUBLIC name:PARENT
+name LABEL $
+ ENDM
+\end{verbatim}
+This setting is equal to the Pascal model that also only allows the
+''father'' to see its children, but not the ''grandpa''.
+
+AS will quarrel about double-defined symbols if more than one section
+attempts to export a symbol of a certain name to the same upper section.
+This is by itself a correct reaction, and one needs to ''qualify'' symbols
+somehow to make them distinguishable if these exports were deliberate. A
+\tty{GLOBAL} statement does just this. The syntax of \tty{GLOBAL} is
+identical to \tty{PUBLIC}, but the symbol stays local instead of being
+assigned to a higher section. Instead, an additional symbol of the same
+value but with the subsection's name appended to the symbol's name is
+created, and only this symbol is made public according to the section
+specification. If for example two sections \tty{A} and \tty{B} both
+define a symbol named \tty{SYM} and export it with a \tty{GLOBAL}
+statement to their parent section, the symbols are sorted in under the
+names \tty{A\_SYM} resp. \tty{B\_SYM} .
+
+In case that source and target section are separated by more than one
+level, the complete name path is prepended to the symbol name.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{FORWARD}
+\ttindex{FORWARD}
+
+The model described so far may look beautiful, but there is an
+additional detail not present in Pascal that may spoil the happiness:
+Assembler allows forward references. Forward references may lead to
+situations where AS accesses a symbol from a higher section in the
+first pass. This is not a disaster by itself as long as the correct
+symbol is used in the second pass, but accidents of the following
+type may happen:
+\begin{verbatim}
+loop: .
+ <code>
+ .
+ .
+ SECTION sub
+ . ; ***
+ .
+ bra.s loop
+ .
+ .
+loop: .
+ .
+ ENDSECTION
+ .
+ .
+ jmp loop ; main loop
+\end{verbatim}
+AS will take the global label \tty{loop} in the first pass and will
+quarrel about an out-of-branch situation if the program part at
+\tty{$<$code$>$} is long enough. The second pass will not be
+started at all. One way to avoid the ambiguity would be to
+explicitly specify the symbol's section:
+\begin{verbatim}
+ bra.s loop[sub]
+\end{verbatim}
+If a local symbol is referenced several times, the brackets can be saved
+by using a \tty{FORWARD} statement. The symbol is thereby explicitly
+announced to be local, and AS will only look in the local symbol table
+part when this symbol is referenced. For our example, the statement
+\begin{verbatim}
+ FORWARD loop
+\end{verbatim}
+should be placed at the position marked with \tty{***}.
+
+\tty{FORWARD} must not only be stated prior to a symbol's definition, but
+also prior to its first usage in a section to make sense. It does not
+make sense to define a symbol private and public; this will be regarded as
+an error by AS.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{Performance Aspects}
+
+The multi-stage lookup in the symbol table and the decision to which
+section a symbol shall be assigned of course cost a bit of time to
+compute. An 8086 program of 1800 lines length for example took 34.5
+instead of 33 seconds after a modification to use sections (80386 SX,
+16MHz, 3 passes). The overhead is therefore limited. As it has
+already been stated at the beginning, is is up to the programmer if
+(s)he wants to accept it. One can still use AS without sections.
+
+%%---------------------------------------------------------------------------
+
+\section{Miscellaneous}
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{SHARED}
+\label{ChapShareOrder}
+\ttindex{SHARED}
+
+{\em valid for: all processors}
+
+This statement instructs AS to write the symbols given in the
+parameter list (regardless if they are integer, float or string
+symbols) together with their values into the share file. It depends
+upon the command line parameters described in section
+\ref{SectCallConvention} whether such a file is generated at all and in
+which format it is written. If AS detects this instruction and no share
+file is generated, a warning is the result.
+
+\bb{CAUTION!} A comment possibly appended to the statement itself will be
+copied to the first line outputted to the share file (if \tty{SHARED}'s
+argument list is empty, only the comment will be written). In case a
+share file is written in C or Pascal format, one has to assure that
+the comment itself does not contain character sequences that close
+the comment (''*/'' resp. ''*)''). AS does not check for this!
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{INCLUDE}
+\label{SectInclude}
+\ttindex{INCLUDE}
+
+{\em valid for: all processors}
+
+This instruction inserts the file given as a parameter into the just as
+if it would have been inserted with an editor (the file name may
+optionally be enclosed with '' characters). This instruction is
+useful to split source files that would otherwise not fit into the
+editor or to create ''tool boxes''.
+
+In case that the file name does not have an extension, it will
+automatically be extended with \tty{INC}.
+
+Via the \tty{-i $<$path list$>$} option, one can specify a list of
+directories that will automatically be searched for the file. If the
+file is not found, a \bb{fatal} error occurs, i.e. assembly terminates
+immediately.
+
+For compatibility reasons, it is valid to enclose the file name in ''
+characters, i.e.
+\begin{verbatim}
+ include stddef51
+\end{verbatim}
+and
+\begin{verbatim}
+ include "stddef51.inc"
+\end{verbatim}
+are equivalent. \bb{CAUTION!} This freedom of choice is the reason why
+only a string constant but no string expression is allowed!
+
+The search list is ignored if the file name itself contains a path
+specification.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{BINCLUDE}
+\ttindex{BINCLUDE}
+
+{\em valid for: all processors}
+
+\tty{BINCLUDE} can be used to embed binary data generated by other programs
+into the code generated by AS (this might theoretically even be code
+created by AS itself...). \tty{BINCLUDE} has three forms:
+\begin{verbatim}
+ BINCLUDE <file>
+\end{verbatim}
+This way, the file is completely included.
+\begin{verbatim}
+ BINCLUDE <file>,<offset>
+\end{verbatim}
+This way, the file's contents are included starting at \tty{<offset>} up to
+the file's end.
+\begin{verbatim}
+ BINCLUDE <file>,<offset>,<length>
+\end{verbatim}
+This way, \tty{$<$length$>$} bytes are included starting at
+\tty{$<$offset$>$}.
+
+The same rules regarding search paths apply as for \tty{INCLUDE}.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{MESSAGE, WARNING, ERROR, and FATAL}
+\ttindex{MESSAGE}\ttindex{WARNING}\ttindex{ERROR}\ttindex{FATAL}
+{\em valid for: all processors}
+
+Though the assembler checks source files as strict as possible and
+delivers differentiated error messages, it might be necessary from
+time to time to issue additional error messages that allow an
+automatic check for logical error. The assembler distinguishes
+among three different types of error messages that are accessible to
+the programmer via the following three instructions:
+\begin{itemize}
+\item{\tty{WARNING}: Errors that hint at possibly wrong or inefficient
+ code. Assembly continues and a code file is generated.}
+\item{\tty{ERROR}: True errors in a program. Assembly continues to
+ allow detection of possible further errors in the same pass.
+ A code file is not generated.}
+\item{\tty{FATAL}: Serious errors that force an immediate termination
+ of assembly. A code file may be generated but will be incomplete.}
+\end{itemize}
+All three instructions have the same format for the message that shall
+be issued: an arbitrary (possibly computed?!) string expression which
+may therefore be either a constant or variable.
+
+These instructions generally only make sense in conjunction wit
+conditional assembly. For example, if there is only a limited
+address space for a program, one can test for overflow in the
+following way:
+\begin{verbatim}
+ROMSize equ 8000h ; 27256 EPROM
+
+ProgStart:
+ .
+ .
+ <the program itself>
+ .
+ .
+ProgEnd:
+
+ if ProgEnd-ProgStart>ROMSize
+ error "\athe program is too long!"
+ endif
+\end{verbatim}
+Apart from the instructions generating errors, there is also an
+instruction \tty{MESSAGE} that simply prints a message to the console
+resp. to the assembly listing. Its usage is equal to the other three
+instructions.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{READ}
+\ttindex{READ}
+
+{\em valid for: all processors}
+
+One could say that \tty{READ} is the counterpart to the previous
+instruction group: it allows to read values from the keyboard during
+assembly. You might ask what this is good for. I will break with
+the previous principles and put an example before the exact
+description to outline the usefulness of this instruction:
+
+A program needs for data transfers a buffer of a size that should be
+set at assembly time. One could store this size in a symbol defined
+with \tty{EQU}, but it can also be done interactively with \tty{READ}:
+\begin{verbatim}
+ IF MomPass=1
+ READ "buffer size",BufferSize
+ ENDIF
+\end{verbatim}
+Programs can this way configure themselves dynamically during assembly
+and one could hand over the source to someone who can assemble it
+without having to dive into the source code. The \tty{IF} conditional
+shown in the example should always be used to avoid bothering the
+user multiple times with questions.
+
+\tty{READ} is quite similar to \tty{SET} with the difference that the
+value is read from the keyboard instead of the instruction's arguments.
+This for example also implies that AS will automatically set the symbol's
+type (integer, float or string) or that it is valid to enter formula
+expressions instead of a simple constant.
+
+\tty{READ} may either have one or two parameters because the prompting
+message is optional. AS will print a message constructed from the
+symbol's name if it is omitted.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{RELAXED}
+\label{SectRELAXED}
+\ttindex{RELAXED}
+
+{\em valid for: all processors}
+
+By default, AS assigns a distinct syntax for integer constants to a
+processor family (which is in general equal to the manufacturer's
+specifications, as long as the syntax is not too bizarre...).
+Everyone however has his own preferences for another syntax and may
+well live with the fact that his programs cannot be translated any
+more with the standard assembler. If one places the instruction
+\begin{verbatim}
+ RELAXED ON
+\end{verbatim}
+right at the program's beginning, one may furtherly use any syntax
+for integer constants, even mixed in a program. AS tries to guess
+automatically for every expression the syntax that was used. This
+automatism does not always deliver the result one might have in mind,
+and this is also the reason why this option has to be enable
+explicitly: if there are no prefixes or postfixes that unambiguously
+identify either Intel or Motorola syntax, the C mode will be used.
+Leading zeroes that are superfluous in other modes have a meaning in
+this mode:
+\begin{verbatim}
+ move.b #08,d0
+\end{verbatim}
+This constant will be understood as an octal constant and will result
+in an error message as octal numbers may only contain digits from 0
+to 7. One might call this a lucky case; a number like 077 would
+result in trouble without getting a message about this. Without the
+relaxed mode, both expressions unambiguously would have been
+identified as decimal constants.
+
+The current setting may be read from a symbol with the same name.
+
+%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\subsection{END}
+\ttindex{END}
+
+{\em valid for: all processors}
+
+\tty{END} marks the end of an assembler program. Lines that eventually
+follow in the source file will be ignored. \bb{IMPORTANT:} \tty{END} may
+be called from within a macro, but the \tty{IF}-stack for conditional
+assembly is not cleared automatically. The following construct therefore
+results in an error:
+\begin{verbatim}
+ IF DontWantAnymore
+ END
+ ELSEIF
+\end{verbatim}
+\tty{END} may optionally have an integer expression as argument that marks
+the program's entry point. AS stores this in the code file with a special
+record and it may be post-processed e.g. with P2HEX.
+
+\tty{END} has always been a valid instruction for AS, but the only reason
+for this in earlier releases of AS was compatibility; \tty{END} had no
+effect.
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Processor-specific Hints}
+
+When writing the individual code generators, I strived for a maximum
+amount of compatibility to the original assemblers. However, I only did this
+as long as it did not mean an unacceptable additional amount of work.
+I listed important differences, details and pitfalls in the following
+chapter.
+
+%%---------------------------------------------------------------------------
+
+\section{6811}
+
+''Where can I buy such a beast, a HC11 in NMOS?'', some of you might
+ask. Well, of course it does not exist, but an H cannot be
+represented in a hexadecimal number (older versions of AS would not
+have accepted such a name because of this), and so I decided to omit
+all the letters...
+\par
+\begin{quote}{\it
+''Someone stating that something is impossible should be at least as
+ cooperative as not to hinder the one who currently does it.''
+}\end{quote}
+From time to time, one is forced to revise one's opinions. Some versions
+earlier, I stated at his place that I couldn't use AS's parser in a way
+that it is also possible to to separate the arguments of \tty{BSET/BCLR}
+resp. \tty{BRSET/BRCLR} with spaces. However, it seems that it can do
+more than I wanted to believe...after the n+1th request, I sat down once
+again to work on it and things seem to work now. You may use either
+spaces or commas, but not in all variants, to avoid ambiguities: for
+every variant of an instruction, it is possible to use only commas or a
+mixture of spaces and commas as Motorola seems to have defined it (their
+data books do not always have the quality of the corresponding
+hardware...):
+\begin{verbatim}
+ Bxxx abs8 #mask is equal to Bxxx abs8,#mask
+ Bxxx disp8,X #mask is equal to Bxxx disp8,X,#mask
+ BRxxx abs8 #mask addr is equal to BRxxx abs8,#mask,addr
+ BRxxx disp8,X #mask addr is equal to BRxxx disp8,X,#mask,addr
+\end{verbatim}
+In this list, \tty{xxx} is a synonym either for \tty{SET} or \tty{CLR};
+\tty{\#mask} is the bit mask to be applied (the \# sign is optional). Of
+course, the same statements are also valid for Y-indexed expression (not
+listed here).
+
+%%---------------------------------------------------------------------------
+
+\section{PowerPC}
+
+Of course, it is a bit crazy idea to add support in AS for a
+processor that was mostly designed for usage in work stations.
+Remember that AS mainly is targeted at programmers of single board
+computers. But things that today represent the absolute high end in
+computing will be average tomorrow and maybe obsolete the next day,
+and in the meantime, the Z80 as the 8088 have been retired as CPUs
+for personal computers and been moved to the embedded market;
+modified versions are marketed as microcontrollers. With the
+appearance of the MPC505 and PPC403, my suspicion has proven to be
+true that IBM and Motorola try to promote this architecture in as
+many fields as possible.
+
+However, the current support is a bit incomplete: Temporarily, the
+Intel-style mnemonics are used to allow storage of data and the more
+uncommon RS/6000 machine instructions mentioned in \cite{Mot601} are
+missing (hopefully noone misses them!). I will finish this as soon
+as information about them is available!
+
+%%---------------------------------------------------------------------------
+
+\section{DSP56xxx}
+
+Motorola, which devil rode you! Which person in your company had the
+''brilliant'' idea to separate the parallel data transfers with spaces!
+In result, everyone who wants to make his code a bit more readable,
+e.g. like this:
+\begin{verbatim}
+ move x:var9 ,r0
+ move y:var10,r3 ,
+\end{verbatim}
+is p****ed because the space gets recognized as a separator for
+parallel data transfers!
+
+Well...Motorola defined it that way, and I cannot change it. Using
+tabs instead of spaces to separate the parallel operations is also
+allowed, and the individual operations' parts are again separated
+with commas, as one would expect it.
+
+\cite{Mot56} states that instead of using \tty{MOVEC, MOVEM, ANDI} or
+\tty{ORI}, it is also valid to use the more general Mnemonics \tty{MODE,
+AND} or \tty{OR}.
+AS (currently) does not support this.
+
+%%---------------------------------------------------------------------------
+
+\section{H8/300}
+
+Regarding the assembler syntax of these processors, Hitachi generously
+copied from Motorola (that wasn't by far the worst choice...),
+unfortunately the company wanted to introduce its own format for
+hexadecimal numbers. To make it even worse, it is a format that uses
+unbalanced single quotes, just like Microchip does. This is something I
+could not (I even did not want to) reproduce with AS, as AS uses single
+quotes to surround ASCII character sequences. Instead, one has to write
+hexadecimal numbers in the well-known Motorola syntax: with a leading
+dollar sign.
+
+%%---------------------------------------------------------------------------
+
+\section{SH7000/7600/7700}
+
+Unfortunately, Hitachi once again used their own format for
+hexadecimal numbers, and once again I was not able to reproduce this
+with AS...please use Motorola syntax!
+
+When using literals and the \tty{LTORG} instruction, a few things have to
+be kept in mind if you do not want to suddenly get confronted with strange
+error messages:
+
+Literals exist due to the fact that the processor is unable to load
+constants out of a range of -128 to 127 with immediate addressing.
+AS (and the Hitachi assembler) hide this inability by the automatic
+placement of constants in memory which are then referenced via
+PC-relative addressing. The question that now arises is where to
+locate these constants in memory. AS does not automatically place a
+constant in memory when it is needed; instead, they are collected
+until an LTORG instruction occurs. The collected constants are then
+dumped en bloc, and their addresses are stored in ordinary labels
+which are also visible in the symbol table. Such a label's name is
+of the form
+\begin{verbatim}
+ LITERAL_s_xxxx_n .
+\end{verbatim}
+In this name, \tty{s} represents the literal's type. Possible values are
+\tty{W} for 16-bit constants, \tty{L} for 32-bit constants and \tty{F} for
+forward references where AS cannot decide in anticipation which size is
+needed. In case of \tty{s=W} or \tty{L}, \tty{xxxx} denotes the
+constant's value in a hexadecimal notation, whereas \tty{xxxx} is a simple
+running number for forward references (in a forward reference, one does
+not know the value of a constant when it is referenced, so one obviously
+cannot incorporate its value into the name). \tty{n} is a counter that
+signifies how often a literal of this value previously occurred in the
+current section. Literals follow the standard rules for localization by
+sections. It is therefore absolutely necessary to place literals that
+were generated in a certain section before the section is terminated!
+
+The numbering with \tty{n} is necessary because a literal may occur
+multiple times in a section. One reason for this situation is that
+PC-relative addressing only allows positive offsets; Literals that
+have once been placed with an \tty{LTORG} can therefore not be referenced
+in the code that follows. The other reason is that the displacement
+is generally limited in length (512 resp. 1024 bytes).
+
+An automatic \tty{LTORG} at the end of a program or previously to
+switching to a different target CPU does not occur; if AS detects unplaced
+literals in such a situation, an error message is printed.
+
+As the PC-relative addressing mode uses the address of the current
+instruction plus 4, it is not possible to access a literal that is
+stored directly after the instruction, like in the following example:
+\begin{verbatim}
+ mov #$1234,r6
+ ltorg
+\end{verbatim}
+This is a minor item since the CPU anyway would try to execute the
+following data as code. Such a situation should not occur in a real
+program...another pitfall is far more real: if PC-relative addressing
+occurs just behind a delayed branch, the program counter is already
+set to the destination address, and the displacement is computed
+relative to the branch target plus 2. Following is an example where
+this detail leads to a literal that cannot be addressed:
+\begin{verbatim}
+ bra Target
+ mov #$12345678,r4 ; is executed
+ .
+ .
+ ltorg ; here is the literal
+ .
+ .
+Target: mov r4,r7 ; execution continues here
+\end{verbatim}
+As \tty{Target}+2 is on an address behind the literal, a negative
+displacement would result. Things become especially hairy when one
+of the branch instructions \tty{JMP, JSR, BRAF, or BSRF} is used: as AS
+cannot calculate the target address (it is generated at runtime from
+a register's contents), a PC value is assumed that should never fit,
+effectively disabling any PC-relative addressing at this point.
+
+It is not possible to deduce the memory usage from the count and size
+of literals. AS might need to insert a padding word to align a long
+word to an address that is evenly divisible by 4; on the other hand,
+AS might reuse parts of a 32-bit literal for other 16-bit literals.
+Of course multiple use of a literal with a certain value will create
+only one entry. However, such optimizations are completely
+suppressed for forward references as AS does not know anything about
+their value.
+
+As literals use the PC-relative addressing which is only allowed for
+the \tty{MOV} instruction, the usage of literals is also limited to
+\tty{MOV} instructions. The way AS uses the operand size is a bit tricky:
+A specification of a byte or word move means to generate the shortest
+possible instruction that results in the desired value placed in the
+register's lowest 8 resp. 16 bits. The upper 24 resp. 16 bits are treated
+as ''don't care''. However, if one specifies a longword move or omits the
+size specification completely, this means that the complete 32-bit
+register should contain the desired value. For example, in the following
+sequence
+\begin{verbatim}
+ mov.b #$c0,r0
+ mov.w #$c0,r0
+ mov.l #$c0,r0 ,
+\end{verbatim}
+the first instruction will result in true immediate addressing, the
+second and third instruction will use a word literal: As bit 7 in
+the number is set, the byte instruction will effectively create the
+value \$FFFFFFC0 in the register. According to the convention, this
+wouldn't be the desired value in the second and third example.
+However, a word literal is also sufficient for the third case because
+the processor will copy a cleared bit 15 of the operand to bits
+16..31.
+
+As one can see, the whole literal stuff is rather complex; I'm sorry but
+there was no chance of making things simpler. It is unfortunately a
+part of its nature that one sometimes gets error messages about
+literals that were not found, which logically should not occur because
+AS does the literal processing completely on his own. However, if
+other errors occur in the second pass, all following labels will move
+because AS does not generate any code any more for statements that
+have been identified as erroneous. As literal names are partially built
+from other symbols' values, other errors might follow because literal
+names searched in the second pass differ from the names stored in the
+first pass and AS quarrels about undefined symbols...if such errors
+should occur, please correct all other errors first before you start
+cursing on me and literals...
+
+People who come out of the Motorola scene and want to use PC-relative
+addressing explicitly (e.g. to address variables in a position-independent
+way) should know that if this addressing mode is written like in the
+programmer's manual:
+\begin{verbatim}
+ mov.l @(Var,PC),r8
+\end{verbatim}
+\bb{no} implicit conversion of the address to a displacement will occur,
+i.e. the operand is inserted as-is into the machine code (this will
+probably generate a value range error...). If you want to use
+PC-relative addressing on the SH7x00, simply use ''absolute''
+addressing (which does not exist on machine level):
+\begin{verbatim}
+ mov.l Var,r8
+\end{verbatim}
+In this example, the displacement will be calculated correctly (of
+course, the same limitations apply for the displacement as it was the
+case for literals).
+
+%%---------------------------------------------------------------------------
+
+\section{MELPS-4500}
+
+The program memory of these microcontrollers is organized in pages of
+128 words. Honestly said, this organization only exists because there
+are on the one hand branch instructions with a target that must lie
+within the same page, and on the other hand ''long'' branches that can
+reach the whole address space. The standard syntax defined by
+Mitsubishi demands that page number and offset have to be written as
+two distinct arguments for the latter instructions. As this is
+quite inconvenient (except for indirect jumps, a programmer has no
+other reason to deal with pages), AS also allows to write the target
+address in a ''linear'' style, for example
+\begin{verbatim}
+ bl $1234
+\end{verbatim}
+instead of
+\begin{verbatim}
+ bl $24,$34 .
+\end{verbatim}
+
+%%---------------------------------------------------------------------------
+
+\section{6502UNDOC}
+
+Since the 6502's undocumented instructions naturally aren't listed in
+any data book, they shall be listed shortly at this place. Of
+course, you are using them on your own risk. There is no guarantee
+that all mask revisions will support all variants! They anyhow do
+not work for the CMOS successors of the 6502, since they allocated
+the corresponding bit combinations with "official" instructions...
+
+The following symbols are used:
+
+\begin{tabbing}
+\hspace{2cm} \= \kill
+\& \> binary AND \\
+| \> binary OR \\
+\verb!^! \> binary XOR \\
+$<<$ \> logical shift left \\
+$>>$ \> logical shift right \\
+$<<<$ \> rotate left \\
+$>>>$ \> rotate right \\
+$\leftarrow$ \> assignment \\
+ (..) \> contents of .. \\
+ {..} \> bits .. \\
+ A \> accumulator \\
+ X,Y \> index registers X,Y \\
+ S \> stack pointer \\
+ An \> accumulator bit n \\
+ M \> operand \\
+ C \> carry \\
+ PCH \> upper half of program counter \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{JAM} or \tty{KIL} or \tty{CRS} \\
+Function \> : \> none, prozessor is halted \\
+Addressing Modes \> : \> implicit \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{SLO} \\
+Function \> : \> $M\leftarrow((M)<<1)|(A)$ \\
+Addressing Modes \> : \> absolute long/short, X-indexed long/short, \\
+ \> \> Y-indexed long, X/Y-indirect \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{ANC} \\
+Function \> : \> $A\leftarrow(A)\&(M), C\leftarrow A7$ \\
+Addressing Modes \> : \> immediate \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{RLA} \\
+Function \> : \> $M\leftarrow((M)<<1)\&(A)$ \\
+Addressing Modes \> : \> absolute long/short, X-indexed long/short, \\
+ \> \> Y-indexed long, X/Y-indirect \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{SRE} \\
+Function \> : \> $M\leftarrow((M)>>1)$\verb!^!$(A)$ \\
+Addressing Modes \> : \> absolute long/short, X-indexed long/short, \\
+ \> \> Y-indexed long, X/Y-indirect \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{ASR} \\
+Function \> : \> $A\leftarrow((A)\&(M))>>1$ \\
+Addressing Modes \> : \> immediate \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{RRA} \\
+Function \> : \> $M\leftarrow((M)>>>1)+(A)+(C)$ \\
+Addressing Modes \> : \> absolute long/short, X-indexed long/short, \\
+ \> \> Y-indexed long, X/Y-indirect \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{ARR} \\
+Function \> : \> $A\leftarrow((A)\&(M))>>>1$ \\
+Addressing Modes \> : \> immediate \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{SAX} \\
+Function \> : \> $M\leftarrow(A)\&(X)$ \\
+Addressing Modes \> : \> absolute long/short, Y-indexed short, \\
+ \> \> Y-indirect \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{ANE} \\
+Function \> : \> $M\leftarrow((A)\&\$ee)|((X)\&(M))$ \\
+Addressing Modes \> : \> immediate \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{SHA} \\
+Function \> : \> $M\leftarrow(A)\&(X)\&(PCH+1)$ \\
+Addressing Modes \> : \> X/Y-indexed long \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{SHS} \\
+Function \> : \> $X\leftarrow(A)\&(X), S\leftarrow(X), M\leftarrow(X)\&(PCH+1)$ \\
+Addressing Modes \> : \> Y-indexed long \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{SHY} \\
+Function \> : \> $M\leftarrow(Y)\&(PCH+1)$ \\
+Addressing Modes \> : \> Y-indexed long \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{SHX} \\
+Function \> : \> $M\leftarrow(X)\&(PCH+1)$ \\
+Addressing Modes \> : \> X-indexed long \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{LAX} \\
+Function \> : \> $A,X\leftarrow(M)$ \\
+Addressing Modes \> : \> absolute long/short, Y-indexed long/short, \\
+ \> \> X/Y-indirect \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{LXA} \\
+Function \> : \> $X{04}\leftarrow(X){04}\&(M){04}$, \\
+ \> \> $A{04}\leftarrow(A){04}\&(M){04}$ \\
+Addressing Modes \> : \> immediate \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{LAE} \\
+Function \> : \> $X,S,A\leftarrow((S)\&(M))$ \\
+Addressing Modes \> : \> Y-indexed long \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{DCP} \\
+Function \> : \> $M\leftarrow(M)-1, Flags\leftarrow((A)-(M))$ \\
+Addressing Modes \> : \> absolute long/short, X-indexed long/short, \\
+ \> \> Y-indexed long, X/Y-indirect \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{SBX} \\
+Function \> : \> $X\leftarrow((X)\&(A))-(M)$ \\
+Addressing Modes \> : \> immediate \\
+\end{tabbing}
+
+\begin{tabbing}
+Addressing Modes \= : \= \kill
+Instruction \> : \> \tty{ISB} \\
+Function \> : \> $M\leftarrow(M)+1, A\leftarrow(A)-(M)-(C)$ \\
+Addressing Modes \> : \> absolute long/short, X-indexed long/short, \\
+ \> \> Y-indexed long, X/Y-indirect \\
+\end{tabbing}
+
+%%---------------------------------------------------------------------------
+
+\section{MELPS-740}
+
+Microcontrollers of this family have a quite nice, however well-hidden
+feature: If one sets bit 5 of the status register with the \tty{SET}
+instruction, the accumulator will be replaced with the memory cell
+addressed by the X register for all load/store and arithmetic
+instructions. An attempt to integrate this feature cleanly into the
+assembly syntax has not been made so far, so the only way to use it
+is currently the ''hard'' way (\tty{SET}...instructions with accumulator
+addressing...\tty{CLT}).
+
+Not all MELPS-740 processors implement all instructions. This is a
+place where the programmer has to watch out for himself that no
+instructions are used that are unavailable for the targeted
+processor; AS does not differentiate among the individual processors
+of this family. For a description of the details regarding special
+page addressing, see the discussion of the \tty{ASSUME} instruction.
+
+%%---------------------------------------------------------------------------
+
+\section{MELPS-7700/65816}
+\label{MELPS7700Spec}
+
+As it seems, these two processor families took disjunct development
+paths, starting from the 6502 via their 8 bit predecessors. Shortly
+listed, the following differences are present:
+\begin{itemize}
+\item{The 65816 does not have a B accumulator.}
+\item{The 65816 does not have instructions to multiply or divide.}
+\item{The 65816 misses the instructions \tty{SEB, CLB, BBC, BBS, CLM, SEM,
+ PSH, PUL} and \tty{LDM}. Instead, the instructions \tty{TSB, TRB, BIT, CLD,
+ SED, XBA, XCE} and \tty{STZ} take their places in the opcode table.}
+\end{itemize}
+The following instructions have identical function, yet different
+names:
+\par
+\begin{center}\begin{tabular}{|c|c||c|c|}
+\hline
+ 65816 & MELPS-7700 & 65816 & MELPS-7700 \\
+\hline
+\hline
+ \tty{REP} & \tty{CLP} & \tty{PHK} & \tty{PHG} \\
+ \tty{TCS} & \tty{TAS} & \tty{TSC} & \tty{TSA} \\
+ \tty{TCD} & \tty{TAD} & \tty{TDC} & \tty{TDA} \\
+ \tty{PHB} & \tty{PHT} & \tty{PLB} & \tty{PLT} \\
+ \tty{WAI} & \tty{WIT} & & \\
+\hline
+\end{tabular}\end{center}
+\par
+Especially tricky are the instructions \tty{PHB, PLB} and \tty{TSB}: these
+instructions have a totally different encoding and meaning on both
+processors!
+
+Unfortunately, these processors address their memory in a way that is
+IMHO even one level higher on the open-ended chart of perversity than
+the Intel-like segmentation: They do banking! Well, this seems to
+be the price for the 6502 upward-compatibility; before one can use AS
+to write code for these processors, one has to inform AS about the
+contents of several registers (using the \tty{ASSUME} instruction):
+
+The M flag rules whether the accumulators A and B should be used with
+8 bits (1) or 16 bits (0) width. Analogously, the X flag decides the
+width of the X and Y index registers. AS needs this information for
+the decision about the argument's width when immediate addressing
+(\verb!#<constant>!) occurs.
+
+The memory is organized in 256 banks of 64 KBytes. As all registers
+in the CPU core have a maximum width of 16 bits, the upper 8 bits
+have to be fetched from 2 special bank registers: DT delivers the
+upper 8 bits for data accesses, and PG extends the 16-bit program
+counter to 24 bits. A 16 bits wide register DPR allows to move the
+zero page known from the 6502 to an arbitrary location in the first
+bank. If AS encounters an address (it is irrelevant if this address
+is part of an absolute, indexed, or indirect expression), the
+following addressing modes will be tested:
+\begin{enumerate}
+\item{Is the address in the range of DPR..DPR+\$ff? If yes, use direct
+ addressing with an 8-bit address.}
+\item{Is the address contained in the page addressable via DT (resp.
+ PG for branch instructions)? If yes, use absolute addressing
+ with a 16-bit address.}
+\item{If nothing else helps, use long addressing with a 24-bit
+ address.}
+\end{enumerate}
+As one can see from this enumeration, the knowledge about the current
+values of DT, PG and DPR is essential for a correct operation of AS;
+if the specifications are incorrect, the program will probably do
+wrong addressing at runtime. This enumeration also implied that all
+three address lengths are available; if this is not the case, the
+decision chain will become shorter.
+
+The automatic determination of the address length described above may
+be overridden by the usage of prefixes. If one prefixes the address
+by a $<$, $>$, or $>>$ without a separating space, an address with 1, 2, or
+3 bytes of length will be used, regardless if this is the optimal
+length. If one uses an address length that is either not allowed for
+the current instruction or too short for the address, an error
+message is the result.
+
+To simplify porting of 6502 programs, AS uses the Motorola syntax for
+hexadecimal constants instead of the Intel/IEEE syntax that is
+the format preferred by Mitsubishi for their 740xxx series. I still
+think that this is the better format, and it looks as if the
+designers of the 65816 were of the same opinion (as the \tty{RELAXED}
+instruction allows the alternative use of Intel notation, this
+decision should not hurt anything). Another important detail for the
+porting of programs is that it is valid to omit the accumulator A as
+target for operations. For example, it is possible to simply write
+\verb!LDA #0! instead of \verb!LDA A,#0!.
+
+A real goodie in the instruction set are the instructions \tty{MVN} resp.
+\tty{MVP} to do block transfers. However, their address specification
+rules are a bit strange: bits 0--15 are stored in index registers,
+bits 16--23 are part of the instruction. When one uses AS, one
+simply specifies the full destination and source addresses. AS will
+then automatically grab the correct bits. This is a fine yet
+important difference Mitsubishi's assembler where you have to
+extract the upper 8 bits on your own. Things become really
+convenient when a macro like the following is used:
+\begin{verbatim}
+mvpos macro src,dest,len
+ if MomCPU=$7700
+ lda #len
+ elseif
+ lda #(len-1)
+ endif
+ ldx #(src&$ffff)
+ ldy #(dest&$ffff)
+ mvp dest,src
+ endm
+\end{verbatim}
+Caution, possible pitfall: if the accumulator contains the value n,
+the Mitsubishi chip will transfer n bytes, but the 65816 will
+transfer n+1 bytes!
+
+The \tty{PSH} and \tty{PUL} instructions are also very handy because they
+allow to save a user-defined set to be saved to the stack resp. to be
+restored from the stack. According to the Mitsubishi data book
+\cite{Mit16}, the bit mask has to be specified as an immediate operand, so
+the programmer either has to keep all bit$\leftrightarrow$register
+assignments in mind or he has to define some appropriate symbols. To make
+things simpler, I decided to extend the syntax at this point: It is valid
+to use a list as argument which may contain an arbitrary sequence of
+register names or immediate expressions. Therefore, the following
+instructions
+\begin{verbatim}
+ psh #$0f
+ psh a,b,#$0c
+ psh a,b,x,y
+
+\end{verbatim}
+are equivalent. As immediate expressions are still valid, AS stays
+upward compatible to the Mitsubishi assemblers.
+
+One thing I did not fully understand while studying the Mitsubishi
+assembler is the treatment of the \tty{PER} instruction: this instruction
+allows to push a 16-bit variable onto the stack whose address is
+specified relative to the program counter. Therefore, it is an
+absolute addressing mode from the programmer's point of view.
+Nevertheless, the Mitsubishi assembler requests immediate addressing,
+and the instructions argument is placed into the code just as-is.
+One has to calculate the address in his own, which is something
+symbolic assemblers were designed for to avoid...as I wanted to stay
+compatible, AS contains a compromise: If one chooses immediate
+addressing (with a leading \# sign), AS will behave like the original
+from Mitsubishi. But if the \# sign is omitted, as will calculate the
+difference between the argument's value and the current program
+counter and insert this difference instead.
+
+A similar situation exists for the \tty{PEI} instruction that pushes the
+contents of a 16-bit variable located in the zero page: Though the operand
+represents an address, once again immediate addressing is required. In
+this case, AS will simply allow both variants (i.e. with or without a \#
+sign).
+
+%%---------------------------------------------------------------------------
+
+\section{M16}
+
+The M16 family is a family of highly complex CISC processors with an
+equally complicated instruction set. One of the instruction set's
+properties is the detail that in an instruction with two operands,
+both operands may be of different sizes. The method of appending the
+operand size as an attribute of the instruction (known from Motorola
+and adopted from Mitsubishi) therefore had to be extended: it is
+valid to append attributes to the operands themselves. For example,
+the following instruction
+\begin{verbatim}
+ mov r0.b,r6.w
+\end{verbatim}
+reads the lowest 8 bits of register 0, sign-extends them to 32 bits
+and stores the result into register 6. However, as one does not need
+this feature in 9 out of 10 cases, it is still valid to append the
+operand size to the instruction itself, e.g.
+\begin{verbatim}
+ mov.w r0,r6
+\end{verbatim}
+Both variants may be mixed; in such a case, an operand size appended
+to an operand overrules the ''default''. An exception are instructions
+with two operands. For these instructions, the default for the
+source operand is the destination operand's size. For example, in
+the following example
+\begin{verbatim}
+ mov.h r0,r6.w
+\end{verbatim}
+register 0 is accessed with 32 bits, the size specification appended
+to the instruction is not used at all. If an instruction does not
+contain any size specifications, word size (\tty{w}) will be used.
+Remember: in contrast to the 68000 family, this means 32 bits instead
+of 16 bits!
+
+The chained addressing modes are also rather complex; the ability of
+AS to automatically assign address components to parts of the chain
+keeps things at least halfway manageable. The only way of influencing
+AS allows (the original assembler from Mitsubishi/Green Hills allows
+a bit more in this respect) is the explicit setting of displacement
+lengths by appending \tty{:4, :16} and \tty{:32}.
+
+%%---------------------------------------------------------------------------
+
+\section{4004}
+
+Another part of history...unfortunately, I wasn't able up to now to get my
+hands on official documentation for world's first microprocessor, and
+there are some details lacking: I'm not absolutely sure about the syntax
+for register pairs (for 8-bit operations). The current syntax is
+\tty{RnRm} with \tty{n} resp. \tty{m} being even integers in the range from
+0 to E resp. 1 to F. The equation {\tt m = n + 1} has to be true always.
+
+%%---------------------------------------------------------------------------
+
+\section{MCS-48}
+
+The maximum address space of these processors is 4 Kbytes large. This
+address space is not organized in a linear way (how could this be on an
+Intel CPU...). Instead, it is split into 2 banks of 2 Kbytes. The only
+way to change the program counter from one bank to the other are the
+instructions \tty{CALL} and \tty{JMP}, by setting the most significant bit
+of the address with the instructions \tty{SEL MB0} resp. \tty{SEL MB1}.
+
+To simplify jumps between these two banks, the instructions \tty{JMP} and
+\tty{CALL} contain an automatism that inserts one of these two instructions
+if the current program counter and the target address are in
+different banks. Explicit usage of these \tty{SEL MBx} instructions should
+therefore not be necessary (though it is possible), and it can puzzle
+the automatism, like in the following example:
+\begin{verbatim}
+ 000: SEL MB1
+ JMP 200h
+\end{verbatim}
+AS assumes that the MB flag is 0 and therefore does not insert a \tty{SEL
+MBO} instruction, with the result that the CPU jumps to address
+A00h.
+
+Furthermore, one should keep in mind that a jump instruction might
+become longer (3 instead of 2 bytes).
+
+%%---------------------------------------------------------------------------
+
+\section{MCS-51}
+
+The assembler is accompanied by the files \tty{STDDEF51.INC} resp.
+\tty{80C50X.INC} that define all bits and SFRs of the processors 8051,
+8052, and 80515 resp. 80C501, 502, and 504. Depending on the target
+processor setting (made with the \tty{CPU} statement), the correct subset
+will be included. Therefore, the correct order for the instructions
+at the beginning of a program is
+\begin{verbatim}
+ CPU <processor type>
+ INCLUDE stddef51.inc .
+\end{verbatim}
+Otherwise, the MCS-51 pseudo instructions will lead to error
+messages.
+
+As the 8051 does not have instructions to to push the registers 0..7
+onto the stack, one has to work with absolute addresses. However,
+these addresses depend on which register bank is currently active.
+To make this situation a little bit better, the include files define
+the macro \tty{USING} that accepts the symbols \tty{Bank0...Bank3} as arguments.
+In response, the macro will assign the registers' correct absolute
+addresses to the symbols \tty{AR0..AR7}. This macro should be used after
+every change of the register banks. The macro itself does \bb{not}
+generate any code to switch to the bank!
+
+The macro also makes bookkeeping about which banks have been used.
+The result is stored in the integer variable \tty{RegUsage}: bit 0
+corresponds to bank 0, bit 1 corresponds to bank 1. and so on. To
+output its contents after the source has been assembled, use
+something like the following piece of code:
+\begin{verbatim}
+ irp BANK,Bank0,Bank1,Bank2,Bank3
+ if (RegUsage&(2^BANK))<>0
+ message "bank \{BANK} has been used"
+ endif
+ endm
+\end{verbatim}
+The multipass feature introduced with version 1.38 allowed to introduce
+the additional instructions \tty{JMP} and \tty{CALL}. If branches are
+coded using these instructions, AS will automatically use the variant that
+is optimal for the given target address. The options are \tty{SJMP,
+AJMP}, or \tty{LJMP} for \tty{JMP} resp. \tty{ACALL} or \tty{LCALL} for
+\tty{CALL}. Of course it is still possible to use these variants
+directly, in case one wants to force a certain coding.
+
+%%---------------------------------------------------------------------------
+
+\section{MCS-251}
+
+When designing the 80C251, Intel really tried to make the move to
+the new family as smooth as possible for programmers. This
+culminated in the fact that old applications can run on the new
+processor without having to recompile them. However, as soon as one
+wants to use the new features, some details have to be regarded which
+may turn into hidden pitfalls.
+
+The most important thing is the absence of a distinct address space
+for bits on the 80C251. All SFRs can now be addressed bitwise,
+regardless of their address. Furthermore, the first 128 bytes of the
+internal RAM are also bit addressable. This has become possible
+because bits are not any more handled by a separate address space
+that overlaps other address spaces. Instead, similar to other
+processors, bits are addressed with a two-dimensional address that
+consists of the memory location containing the bit and the bit's
+location in the byte. One result is that in an expression like
+\tty{PSW.7}, AS will do the separation of address and bit position itself.
+Unlike to the 8051, it is not any more necessary to explicitly
+generate 8 bit symbols. This has the other result that the \tty{SFRB}
+instruction does not exist any more. If it is used in a program that
+shall be ported, it may be replaced with a simple \tty{SFR} instruction.
+
+Furthermore, Intel cleaned up the cornucopia of different address
+spaces on the 8051: the internal RAM (\tty{DATA} resp. \tty{IDATA}), the
+\tty{XDATA} space and the former \tty{CODE} space were unified to a single
+\tty{CODE} space that is now 16 Mbytes large. The internal RAM starts at
+address 0, the internal ROM starts at address ff0000h, which is the
+address code has to be relocated to. In contrast, the SFRs were moved to
+a separate address space (which AS refers to as the \tty{IO} segment).
+However, they have the same addresses in this new address space as they
+used to have on the 8051. The \tty{SFR} instructions knows of this
+difference and automatically assigns symbols to either the \tty{DATA} or
+\tty{IO} segment, depending on the target processor. As there is no
+\tty{BIT} segment any more, the \tty{BIT} instruction operates completely
+different: Instead of a linear address ranging from 0..255, a bit symbol
+now contains the byte's address in bit 0..7, and the bit position in bits
+24..26. Unfortunately, creating arrays of flags with a symbolic address
+is not that simple any more: On an 8051, one simply wrote:
+\begin{verbatim}
+ segment bitdata
+
+bit1 db ?
+bit2 db ?
+
+or
+
+defbit macro name
+name bit cnt
+cnt set cnt+1
+ endm
+\end{verbatim}
+On a 251, only the second way still works, like this:
+ \begin{verbatim}
+adr set 20h ; start address of flags
+bpos set 0 ; in the internal RAM
+
+defbit macro name
+name bit adr.bpos
+bpos set bpos+1
+ if bpos=8
+bpos set 0
+adr set adr+1
+ endif
+ endm
+\end{verbatim}
+Another small detail: Intel now prefers \tty{CY} instead of \tty{C} as a
+symbolic name for the carry, so you might have to rename an already
+existing variable of the same name in your program. However, AS will
+continue to understand also the old variant when using the instructions
+\tty{CLR, CPL, SETB, MOV, ANL,} or \tty{ORL}. The same is conceptually
+true for the additional registers \tty{R8..R15, WR0..WR30, DR0..DR28, DR56,
+DR60, DPX,} and \tty{SPX}.
+
+Intel would like everyone to write absolute addresses in a syntax of
+\tty{XX:YYYY}, where \tty{XX} is a 64K bank in the address space resp.
+signifies addresses in the I/O space with an \tty{S}. As one might guess,
+I am not amused about this, which is why it is legal to alternitavely use
+linear addresses in all places. Only the \tty{S} for I/O addresses is
+incircumventable, like in this case:
+\begin{verbatim}
+Carry bit s:0d0h.7
+\end{verbatim}
+Without the prefix, AS would assume an address in the \tty{CODE} segment,
+and only the first 128 bits in this space are bit-addressable...
+
+Like for the 8051, the generic branch instructions \tty{CALL} and
+\tty{JMP} exist that automatically choose the shortest machine code
+depending on the address layout. However, while \tty{JMP} also may use
+the variant with a 24-bit address, \tty{CALL} will not do this for a good
+reason: In contrast to \tty{ACALL} and \tty{LCALL}, \tty{ECALL} places an
+additional byte onto the stack. A \tty{CALL} instruction would result where
+you would not know what it will do. This problem does not exist for the
+\tty{JMP} instructions.
+
+There is one thing I did not understand: The 80251 is also able to
+push immediate operands onto the stack, and it may push either single
+bytes or complete words. However, the same mnemonic (\tty{PUSH}) is
+assigned to both variants - how on earth should an assembler know if
+an instruction like
+\begin{verbatim}
+ push #10
+\end{verbatim}
+shall push a byte or a word containing the value 10? So the current
+rule is that \tty{PUSH} always pushes a byte; if one wants to push a word,
+simply use \tty{PUSHW} instead of \tty{PUSH}.
+
+Another well-meant advise: If you use the extended instruction set,
+be sure to operate the processor in source mode; otherwise, all
+instructions will become one byte longer! The old 8051 instructions
+that will in turn become one byte longer are not a big matter: AS
+will either replace them automatically with new, more general
+instructions or they deal with obsolete addressing modes (indirect
+addressing via 8 bit registers).
+
+%%---------------------------------------------------------------------------
+
+\section{8086..V35}
+
+Actually, I had sworn myself to keep the segment disease of Intel's
+8086 out of the assembler. However, as there was a request and as
+students are more flexible than the developers of this processor
+obviously were, there is now a rudimentary support of these
+processors in AS. When saying, 'rudimentary', it does not mean that
+the instruction set is not fully covered. It means that the whole
+pseudo instruction stuff that is available when using MASM, TASM, or
+something equivalent does not exist. To put it in clear words, AS
+was not primarily designed to write assembler programs for PC's
+(heaven forbid, this really would have meant reinventing the wheel!);
+instead, the development of programs for single-board computers was
+the main goal (which may also be equipped with an 8086 CPU).
+
+For die-hards who still want to write DOS programs with AS, here is a
+small list of things to keep in mind:
+\begin{itemize}
+\item{Only \tty{COM} files may be created.}
+\item{Only use the \tty{CODE} segment, and place also all variables in
+ this segment.}
+\item{DOS initializes all segment registers to the code segment.
+ An \tty{ASSUME DS:DATA, SS:DATA} right at the program's beginning
+ is therefore necessary.}
+\item{DOS loads the code to a start address of 100h. An \tty{ORG} to this
+ address is absolutely necessary.}
+\item{The conversion to a binary file is done with P2BIN (see later in
+ this document), with an address filter of \tty{\$-\$}.}
+\end{itemize}
+For these processors, AS only supports a small programming model, i.e.
+there is \bb{one} code segment with a maximum of 64 Kbytes and a data
+segment of equal size for data (which cannot be set to initial values for
+\tty{COM} files). The \tty{SEGMENT} instruction allows to switch between
+these two segments. From this facts results that branches are always
+intrasegment branches if they refer to targets in this single code
+segment. In case that far jumps should be necessary, they are possible
+via \tty{CALLF} or \tty{JMPF} with a memory address or a
+\tty{Segment:Offset} value as argument.
+
+Another big problem of these processors is their assembler syntax,
+which is sometimes ambiguous and whose exact meaning can then only be
+deduced by looking at the current context. In the following example,
+either absolute or immediate addressing may be meant, depending on
+the symbol's type:
+\begin{verbatim}
+ mov ax,value
+\end{verbatim}
+When using AS, an expression without brackets always is interpreted
+as immediate addressing. For example, when either a variable's
+address or its contents shall be loaded, the differences listed in table
+\ref{TabMASM} are present between MASM and AS:
+\begin{table*}
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+assembler & address & contents \\
+\hline
+\hline
+MASM & \tty{mov ax,offset vari} & \tty{mov ax,vari} \\
+ & \tty{lea ax,vari} & \tty{mov ax,[vari]} \\
+ & \tty{lea ax,[vari]} & \\
+ & & \\
+AS & \tty{mov ax,vari} & \tty{mov ax,[vari]} \\
+ & \tty{lea ax,[vari]} & \\
+\hline
+\end{tabular}\end{center}
+\caption{Differences AS$\leftrightarrow$MASM Concerning Addressing
+ Syntax\label{TabMASM}}
+\end{table*}
+\par
+When addressing via a symbol, the assembler checks whether they are
+assigned to the data segment and tries to automatically insert an
+appropriate segment prefix. This happens for example when symbols
+from the code segment are accessed without specifying a \tty{CS} segment
+prefix. However, this mechanism can only work if the \tty{ASSUME}
+instruction (see there) has previously been applied correctly.
+
+The Intel syntax also requires to store whether bytes or words were
+stored at a symbol's address. AS will do this only when the \tty{DB} resp.
+\tty{DW} instruction is in the same source line as the label. For any
+other case, the operand size has to be specified explicitly with the
+\tty{BYTE PTR, WORD PTR,...} operators. As long as a register is the other
+operator, this may be omitted, as the operand size is then clearly
+given by the register's name.
+
+In an 8086-based system, the coprocessor is usually synchronized via
+via the processor's TEST input line which is connected to toe
+coprocessor's BUSY output line. AS supports this type of handshaking
+by automatically inserting a \tty{WAIT} instruction prior to every 8087
+instruction. If this is undesired for any reason, an \tty{N} has to be
+inserted after the \tty{F} in the mnemonic; for example,
+\begin{verbatim}
+ FINIT
+ FSTSW [vari]
+\end{verbatim}
+becomes
+\begin{verbatim}
+ FNINIT
+ FNSTSW [vari]
+\end{verbatim}
+This variant is valid for \bb{all} coprocessor instructions.
+
+%%---------------------------------------------------------------------------
+
+\section{8X30x}
+\label{8X30xSpec}
+
+The processors of this family have been optimized for an easy manipulation
+of bit groups at peripheral addresses. The instructions \tty{LIV} and
+\tty{RIV} were introduced to deal with such objects in a symbolic fashion.
+They work similar to \tty{EQU}, however they need three parameters:
+\begin{enumerate}
+\item{the address of the peripheral memory cell that contains the bit
+ group (0..255);}
+\item{the number of the group's first bit (0..7);}
+\item{the length of the group, expressed in bits (1..8).}
+\end{enumerate}
+\bb{CAUTION!} The 8X30x does not support bit groups that span over more
+than one memory address. Therefore, the valid value range for the
+length can be stricter limited, depending on the start position. AS
+does \bb{not} perform any checks at this point, you simply get strange
+results at runtime!
+
+Regarding the machine code, length and position are expressed vis a 3
+bit field in the instruction word and a proper register number (\tty{LIVx}
+resp. \tty{RIVx}). If one uses a symbolic object, AS will automatically
+assign correct values to this field, but it is also allowed to
+specify the length explicitly as a third operand if one does not work
+with symbolic objects. If AS finds such a length specification in
+spite of a symbolic operand, it will compare both lengths and issue
+an error if they do not match (the same will happen for the MOVE
+instruction if two symbolic operands with different lengths are used
+- the instruction simply only has a single length field...).
+
+Apart from the real machine instructions, AS defines similarly to its
+''idol'' MCCAP some pseudo instructions that are implemented as builtin
+macros:
+\begin{itemize}
+\item{\tty{NOP} is a shortform for \tty{MOVE AUX,AUX}}
+\item{\tty{HALT} is a shortform for \tty{JMP \verb!*!}}
+\item{\tty{XML ii} is a shortform for \tty{XMIT ii,R12} (only 8X305)}
+\item{\tty{XMR ii} is a shortform for \tty{XMIT ii,R13} (only 8X305)}
+\item{\tty{SEL $<$busobj$>$} is a shortform for \tty{XMIT $<$adr$>$,IVL/IVR},
+ i.e. it performs the necessary preselection to access $<$busobj$>$.}
+\end{itemize}
+The \tty{CALL} and \tty{RTN} instructions MCCAP also implements are
+currently missing due to sufficient documentation. The same is true for a
+set of pseudo instructions to store constants to memory. Time may change
+this...
+
+%%---------------------------------------------------------------------------
+
+\section{XA}
+
+Similar to its predecessor MCS/51, but in contrast to its
+'competitor' MCS/251, the Philips XA has a separate address space for
+bits, i.e. all bits that are accessible via bit instructions have a
+certain, one-dimensional address which is stored as-is in the machine
+code. However, I could not take the obvious opportunity to offer
+this third address space (code and data are the other two) as a
+separate segment. The reason is that - in contrast to the MCS/51 -
+some bit addresses are ambiguous: bits with an address from 256 to 511
+refer to the bits of memory cells 20h..3fh in the current data
+segment. This means that these addresses may correspond to different
+physical bits, depending on the current state. Defining bits with
+the help of \tty{DC} instructions - something that would be possible with a
+separate segment - would not make too much sense. However, the \tty{BIT}
+instruction still exists to define individual bits (regardless if
+they are located in a register, the RAM or SFR space) that can then
+be referenced symbolically. If the bit is located in RAM, the
+address of the 64K-bank is also stored. This way, AS can check
+whether the DS register has previously be assigned a correct value
+with an \tty{ASSUME} instruction.
+
+In contrast, nothing can stop AS's efforts to align potential branch
+targets to even addresses. Like other XA assemblers, AS does this by
+inserting \tty{NOP}s right before the instruction in question.
+
+%%---------------------------------------------------------------------------
+
+\section{AVR}
+
+In contrast to the AVR assembler, AS by default uses the Intel format
+to write hexadecimal contants instead of the C syntax. All right, I
+did not look into the (free) AVR assembler before, but when I started
+with the AVR part, there was hardly mor einformation about the AVR
+than a preliminary manual describing processor types that were never
+sold...this problem can be solved with a simple RELAXED ON.
+
+Optionally, AS can generate so-called "object files" for the AVRs (it
+also works for other CPUs, but it does not make any sense for them...).
+These are files containing code and source line info what e.g. allows
+a step-by-step execution on source level with the WAVRSIM simulator
+delivered by Atmel. Unfortunately, the simulator seems to have
+trouble with source file names longer than approx. 20 characters:
+Names are truncated and/or extended by strange special characters
+when the maximum length is exceeded. AS therefore stores file name
+specifications in object files without a path specification.
+Therefore, problems may arise when files like includes are not in the
+current directory.
+
+A small specialty are machine instructions that have already been defined
+by Atmel as part of the architecture, but up to now haven't been
+implemented in any of the family's members. The instructions in question
+are {\tt MUL, JMP,} and {\tt CALL}. Considering the latter ones, one may
+ask himself how to reach the 4 Kwords large address space of the AT90S8515
+when the 'next best' instructions {\tt RJMP} and {\tt RCALL} can only
+branch up to 2 Kwords forward or backward. The trick is named 'discarding
+the upper address bits' and described in detail with the {\tt WRAPMODE}
+statement.
+
+%%---------------------------------------------------------------------------
+
+\section{Z80UNDOC}
+
+As one might guess, Zilog did not make any syntax definitions for the
+undocumented instructions; furthermore, not everyone might know the
+full set. It might therefore make sense to list all instructions at
+this place:
+
+Similar to a Z380, it is possible to access the byte halves of IX and
+IY separately. In detail, these are the instructions that allow
+this:
+\begin{verbatim}
+ INC Rx LD R,Rx LD Rx,n
+ DEC Rx LD Rx,R LD Rx,Ry
+ ADD/ADC/SUB/SBC/AND/XOR/OR/CP A,Rx
+\end{verbatim}
+\tty{Rx} and \tty{Ry} are synonyms for \tty{IXL, IXU, IYL} or \tty{IYU}.
+Keep however in mind that in the case of \tty{LD Rx,Ry}, both registers
+must be part of the same index register.
+
+The coding of shift instructions leaves an undefined bit combination which
+is now accessible as the \tty{SLIA} instruction. \tty{SLIA} works like
+\tty{SLA} with the difference of entering a 1 into bit position 0. Like
+all other shift instructions, \tty{SLIA} also allows another undocumented
+variant:
+\begin{verbatim}
+ SLIA R,(XY+d)
+\end{verbatim}
+In this case, \tty{R} is an arbitrary 8-bit register (excluding index
+register halves...), and \tty{(XY+d)} is a normal indexed address. This
+operation has the additional effect of copying the result into the
+register. This also works for the \tty{RES} and \tty{SET} instructions:
+\begin{verbatim}
+ SET/RES R,n,(XY+d)
+\end{verbatim}
+Furthermore, two hidden I/O instructions exist:
+\begin{verbatim}
+ IN (C) resp. TSTI
+ OUT (C),0
+\end{verbatim}
+Their operation should be clear. \bb{CAUTION!} Noone can
+guarantee that all mask revisions of the Z80 execute these
+instructions, and the Z80's successors will react with traps if they
+find one of these instructions. Use them on your own risk...
+
+%%---------------------------------------------------------------------------
+
+\section{Z380}
+
+As this processor was designed as a grandchild of the still most popular
+8-bit microprocessor, it was a sine-qua-non design target to execute
+existing Z80 programs without modification (of course, they execute a bit
+faster, roughly by a factor of 10...). Therefore, all extended features
+can be enabled after a reset by setting two bits which are named XM
+(eXtended Mode, i.e. a 32-bit instead of a 16-bit address space)
+respectively LW (long word mode, i.e. 32-bit instead of 16-bit operands).
+One has to inform AS about their current setting with the instructions
+\tty{EXTMODE} resp. \tty{LWORDMODE}, to enable AS to check addresses and
+constants against the correct upper limits. The toggle between 32- and
+16-bit instruction of course only influences instructions that are
+available in a 32-bit variant. Unfortunately, the Z380 currently offers
+such variants only for load and store instructions; arithmetic can only be
+done in 16 bits. Zilog really should do something about this, otherwise
+the most positive description for the Z380 would be ''16-bit processor
+with 32-bit extensions''...
+
+The whole thing becomes complicated by the ability to override the operand
+size set by LW with the instruction prefixes \tty{DDIR W} resp.
+\tty{DDIR LW}. AS will note the occurrence of such instructions and will
+toggle setting for the instruction following directly. By the way, one
+should never explicitly use other \tty{DDIR} variants than \tty{W} resp.
+\tty{LW}, as AS will introduce them automatically when an operand is
+discovered that is too long. Explicit usage might puzzle AS. The
+automatism is so powerful that in a case like this:
+\begin{verbatim}
+ DDIR LW
+ LD BC,12345678h ,
+\end{verbatim}
+the necessary \tty{IW} prefix will automatically be merged into the previous
+instruction, resulting in
+\begin{verbatim}
+ DDIR LW,IW
+ LD BC,12345668h .
+\end{verbatim}
+The machine code that was first created for \tty{DDIR LW} is retracted and
+replaced, which is signified with an \tty{R} in the listing.
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-900(L)}
+\label{TLCS900Spec}
+
+These processors may run in two operating modes: on the one hand, in
+minimum mode, which offers almost complete source code compatibility
+to the Z80 and TLCS-90, and on the other hand in maximum mode, which
+is necessary to make full use of the processor's capabilities. The
+main differences between these two modes are:
+\begin{itemize}
+\item{width of the registers WA, BC, DE, and HL: 16 or 32 bits;}
+\item{number of register banks: 8 or 4;}
+\item{code address space: 64 Kbytes or 16 Mbytes;}
+\item{length of return addresses: 16 or 32 bits.}
+\end{itemize}
+To allow AS to check against the correct limits, one has to inform him
+about the current execution mode via the \tty{MAXMODE} instruction (see
+there). The default is the minimum mode.
+
+From this follows that, depending on the operating mode, the 16-bit
+resp. 32-bit versions of the bank registers have to be used for
+addressing, i.e. WA, BC, DE and HL for the minimum mode resp. XWA,
+XBC, XDE and XHL for the maximum mode. The registers XIX..XIZ and
+XSP are \bb{always} 32 bits wide and therefore always have to to be used
+in this form for addressing; in this detail, existing Z80 code
+definitely has to be adapted (not including that there is no I/O
+space and all I/O registers are memory-mapped...).
+
+The syntax chosen by Toshiba is a bit unfortunate in the respect of
+choosing an single quote (') to reference the previous register bank. The
+processor independent parts of AS already use this character to mark
+character constants. In an instruction like
+\begin{verbatim}
+ ld wa',wa ,
+\end{verbatim}
+AS will not recognize the comma for parameter separation. This
+problem can be circumvented by usage of an inverse single quote (`), for
+example
+\begin{verbatim}
+ ld wa`,wa
+\end{verbatim}
+Toshiba delivers an own assembler for the TLCS-900 series (TAS900),
+which is different from AS in the following points:
+
+\subsubsection{Symbol Conventions}
+
+\begin{itemize}
+\item{TAS900 differentiates symbol names only on the first 32
+ characters. In contrast, AS always stores symbol names with the
+ full length (up to 255 characters) and uses them all for
+ differentiation.}
+\item{TAS900 allows to write integer constants either in Intel or C
+ notation (with a 0 prefix for octal or a 0x prefix for hexadecimal
+ constants). By default, AS only supports the Intel notation.
+ With the help of the \tty{RELAXED} instruction, one also gets the C
+ notation (among other).}
+\item{AS does not distinguish between upper and lower case. In
+ contrast, TAS900 differentiates between upper- and lowercase
+ letters in symbol names. One needs to engage the \tty{-u} command
+ line option to force AS to do this.}
+\end{itemize}
+
+\subsubsection{Syntax}
+
+For many instructions, the syntax checking of AS is less strict than
+the checking of TAS900. In some (rare) cases, the syntax is slightly
+different. These extensions and changes are on the one hand for the
+sake of a better portability of existing Z80 codes, on the other hand
+they provide a simplification and better orthogonality of the
+assembly syntax:
+\begin{itemize}
+\item{In the case of \tty{LDA, JP}, and \tty{CALL}, TAS requires that address
+ expressions like \tty{XIX+5} must not be placed in parentheses, as it
+ is usually the case. For the sake of better orthogonality, AS
+ requires parentheses for \tty{LDA}. They are optional if \tty{JP} resp.
+ \tty{CALL} are used with a simple, absolute address.}
+\item{In the case of \tty{JP, CALL, JR}, and \tty{SCC}, AS leaves the choice to the
+ programmer whether to explicitly write out the default condition
+ \tty{T} (= true) as first parameter or not. TAS900 in contrast only
+ allows to use the default condition implicitly (e.g. \tty{jp (xix+5)}
+ instead of \tty{jp t,(xix+5))}.}
+\item{For the \tty{EX} instruction, AS allows operand combinations which are
+ not listed in \cite{Tosh900} but can be reduced to a standard
+ combination by swapping the operands. Combinations like \tty{EX f`,f}
+ or \tty{EX wa,(xhl)} become possible. In contrast, TAS900 limits to
+ the 'pure' combinations.}
+\item{AS allows to omit an increment resp. decrement of 1 when using the
+ instructions \tty{INC} and \tty{DEC}. TAS900 instead forces the programmer to
+ explicit usage of '1'.}
+\item{The similar is true for the shift instructions: If the operand is
+ a register, TAS900 requires that even a shift count of 1 has to
+ be written explicitly; however, when the operand is in memory,
+ the hardware limits the shift count to 1 which must not be written
+ in this case. With AS, a shift count of 1 is always optional and
+ valid for all types of operands.}
+\end{itemize}
+
+\subsubsection{Macro Processor}
+
+The macro processor of TAS900 is an external program that operates
+like a preprocessor. It consists of two components: The first one is
+a C-like preprocessor, and the second one is a special macro language
+(MPL) that reminds of high level languages. The macro processor of
+AS instead is oriented towards ''classic'' macro assemblers like MASM
+or M80 (both programs from Microsoft). It is a fixed component of
+AS.
+
+\subsubsection{Output Format}
+
+TAS900 generates relocatable code that allows to link separately
+compiled programs to a single application. AS instead generates
+absolute machine code that is not linkable. There are currently no
+plans to extend AS in this respect.
+
+\subsubsection{Pseudo Instructions}
+
+Due to the missing linker, AS lacks a couple of pseudo instructions
+needed for relocatable code TAS900 implements. The following
+instructions are available with equal meaning:
+\begin{quote}\tt
+ EQU, DB, DW, ORG, ALIGN, END, TITLE, SAVE, RESTORE
+\rm\end{quote}
+The latter two have an extended functionality for AS. Some TAS900
+pseudo instructions can be replaced with equivalent AS instructions (see
+table \ref{TabTAS900}).
+\par
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+TAS900 & AS & meaning/function \\
+\hline
+\hline
+\tty{DL} $<$Data$>$ & \tty{DD} $<$Data$>$ & define longword constants \\
+\hline
+\tty{DSB} $<$number$>$ & \tty{DB} $<$number$>$ \tty{DUP} (?) & reserve bytes of memory \\
+\hline
+\tty{DSW} $<$number$>$ & \tty{DW} $<$number$>$ \tty{DUP} (?) & reserve words of memory \\
+\hline
+\tty{DSD} $<$number$>$ & \tty{DD} $<$number$>$ \tty{DUP} (?) & reserve longwords of memory \\
+\hline
+\tty{\$MIN[IMUM]} & \tty{MAXMODE OFF} & following code runs \\
+ & & in minimum mode \\
+\hline
+\tty{\$MAX[IMUM]} & \tty{MAXMODE ON} & following code runs \\
+ & & in maximum mode \\
+\hline
+\tty{\$SYS[TEM]} & \tty{SUPMODE ON} & following code runs \\
+ & & in system mode \\
+\hline
+\tty{\$NOR[MAL]} & \tty{SUPMODE OFF} & following code runs \\
+ & & in user mode \\
+\hline
+\tty{\$NOLIST} & \tty{LISTING OFF} & turn off assembly listing \\
+\hline
+\tty{\$LIST} & \tty{LISTING ON} & turn on assembly listing \\
+\hline
+\tty{\$EJECT} & \tty{NEWPAGE} & start new page in listing \\
+\hline
+\end{tabular}\end{center}
+\caption{equivalent instructions TAS900$\leftrightarrow$AS\label{TabTAS900}}
+\end{table*}
+Toshiba manufactures two versions of the processor core, with the L
+version being an ''economy version''. AS will make the following
+differences between TLCS-900 and TLCS-900L:
+\begin{itemize}
+\item{The instructions \tty{MAX} and \tty{NORMAL} are not allowed for the L version;
+ the \tty{MIN} instruction is disabled for the full version.}
+\item{The L version does not know the normal stack pointer XNSP/NSP, but
+ instead has the interrupt nesting register INTNEST.}
+\end{itemize}
+The instructions \tty{SUPMODE} and \tty{MAXMODE} are not influenced, just as
+their initial setting \tty{OFF}. The programmer has to take care of the
+fact that the L version starts in maximum mode and does not have a
+normal mode. However, AS shows a bit of mercy against the L variant
+by suppressing warnings for privileged instructions.
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-90}
+
+Maybe some people might ask themselves if I mixed up the order a
+little bit, as Toshiba first released the TLCS-90 as an extended Z80
+and afterwards the 16-bit version TLCS-900. Well, I discovered the
+'90 via the '900 (thank you Oliver!). The two families are quite
+similar, not only regarding their syntax but also in their
+architecture. The hints for the '90 are therefore a subset of of the
+chapter for the '900: As the '90 only allows shifts, increments, and
+decrements by one, the count need not and must not be written as the
+first argument. Once again, Toshiba wants to omit parentheses for
+memory operands of \tty{LDA, JP, and CALL}, and once again AS requires them
+for the sake of orthogonality (the exact reason is of course that
+this way, I saved an extra in the address parser, but one does not
+say such a thing aloud).
+
+Principally, the TLCS-90 series already has an address space of 1
+Mbyte which is however only accessible as data space via the index
+registers. AS therefore does not regard the bank registers and
+limits the address space to 64 Kbytes. This should not limit too
+much as this area above is anyway only reachable via indirect
+addressing.
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-870}
+
+Once again Toshiba...a company quite productive at the moment!
+Especially this branch of the family (all Toshiba microcontrollers
+are quite similar in their binary coding and programming model) seems
+to be targeted towards the 8051 market: the method of separating the
+bit position from the address expression with a dot had its root in
+the 8051. However, it creates now exactly the sort of problems I
+anticipated when working on the 8051 part: On the one hand, the dot
+is a legal part of symbol names, but on the other hand, it is part of
+the address syntax. This means that AS has to separate address and
+bit position and must process them independently. Currently, I
+solved this conflict by seeking the dot starting at the \bb{end} of the
+expression. This way, the last dot is regarded as the separator, and
+further dots stay parts of the address. I continue to urge everyone
+to omit dots in symbol names, they will lead to ambiguities:
+\begin{verbatim}
+ LD CF,A.7 ; accumulator bit 7 to carry
+ LD C,A.7 ; constant 'A.7' to accumulator
+\end{verbatim}
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-47}
+
+This family of 4-bit microcontrollers should mark the low end of what
+is supportable by AS. Apart from the \tty{ASSUME} instruction for the data
+bank register (see there), there is only one thing that is worth
+mentioning: In the data and I/O segment, nibbles are reserved instead
+of byte (it's a 4-bitter...). The situation is similar to the bit
+data segment of the 8051, where a \tty{DB} reserves a single bit, with the
+difference that we are dealing with nibbles.
+
+Toshiba defined an ''extended instruction set'' for this processor
+family to facilitate the work with their limited instruction set. In
+the case of AS, it is defined in the include file \tty{STDDEF47.INC}.
+However, some instructions that could not be realized as macros are
+''builtins'' and are therefore also available without the include file:
+\begin{itemize}
+\item{the \tty{B} instruction that automatically chooses the optimal version
+ of the jump instruction (\tty{BSS; BS}, or \tty{BSL});}
+\item{\tty{LD} in the variant of \tty{HL} with an immediate operand;}
+\item{\tty{ROLC} and \tty{RORC} with a shift amplitude higher than one.}
+\end{itemize}
+
+%%---------------------------------------------------------------------------
+
+\section{TLCS-9000}
+
+This is the first time that I implemented a processor for AS which
+was not available at that point of time. Unfortunately, Toshiba
+decided to put this processor ''on ice'', so we won't see any silicon
+in the near future. This has of course the result that this part
+\begin{enumerate}
+\item{is a ''paper design'', i.e. there was so far no chance to test
+ it in the reality and}
+\item{the documentation for the '9000 I could get hold of \cite{Tosh9000}
+ were preliminary, so they could not deliver clarity on every
+ detail.}
+\end{enumerate}
+Therefore, errors in this code generator are quite possible (and will
+of course be fixed if it should ever become possible!). At least the
+few examples listed in \cite{Tosh9000} are assembled correctly.
+
+%%---------------------------------------------------------------------------
+
+\section{29xxx}
+
+As it was already described in the discussion of the \tty{ASSUME}
+instruction, AS can use the information about the current setting of
+the RBP register to detect accesses to privileged registers in user
+mode. This ability is of course limited to direct accesses (i.e.
+without using the registers IPA...IPC), and there is one more
+pitfall: as local registers (registers with a number $>$127) are
+addressed relative to the stack pointer, but the bits in RBP always
+refer to absolute numbers, the check is NOT done for local registers.
+An extension would require AS to know always the absolute value of
+SP, which would at least fail for recursive subroutines...
+
+%%---------------------------------------------------------------------------
+
+\section{80C16x}
+
+As it was already explained in the discussion of the \tty{ASSUME}
+instruction, AS tries to hide the fact that the processor has more
+physical than logical RAM as far as possible. Please keep in mind
+that the DPP registers are valid only for data accesses and only
+have an influence on absolute addressing, neither on indirect nor on indexed
+addresses. AS cannot know which value the computed address may take
+at runtime...
+The paging unit unfortunately does not operate for code accesses so
+one has to work with explicit long or short \tty{CALL}s, \tty{JMP}s, or
+\tty{RET}s. At least for the ''universal'' instructions \tty{CALL} and
+\tty{JMP}, AS will automatically use the shortest variant, but at least for the RET one
+should know where the call came from. \tty{JMPS} and \tty{CALLS} principally
+require to write segment and address separately, but AS is written in
+a way that it can split an address on its own, e.g. one can write
+\begin{verbatim}
+ jmps 12345h
+\end{verbatim}
+instead of
+\begin{verbatim}
+ jmps 1,2345h
+\end{verbatim}
+Unfortunately, not all details of the chip's internal instruction
+pipeline are hidden: if CP (register bank address), SP (stack), or
+one of the paging registers are modified, their value is not
+available for the instruction immediately following. AS tries to
+detect such situations and will issue a warning in such cases. Once
+again, this mechanism only works for direct accesses.
+
+Bits defined with the \tty{BIT} instruction are internally stored as a
+12-bit word, containing the address in bits 4..11 and the bit
+position in the four LSBs. This order allows to refer the next resp.
+previous bit by incrementing or decrementing the address. This will
+however not work for explicit bit specifications when a word boundary
+is crossed. For example, the following expression will result in a
+range check error:
+\begin{verbatim}
+ bclr r5.15+1
+\end{verbatim}
+We need a \tty{BIT} in this situation:
+\begin{verbatim}
+msb bit r5.15
+ .
+ .
+ bclr msb+1
+\end{verbatim}
+The SFR area was doubled for the 80C167/165/163: bit 12 flags that a bit
+lies in the second part. Siemens unfortunately did not foresee that
+256 SFRs (128 of them bit addressable) would not suffice for
+successors of the 80C166. As a result, it would be impossible to
+reach the second SFR area from F000H..F1DFH with short addresses or
+bit instructions if the developers had not included a toggle
+instruction:
+\begin{verbatim}
+ EXTR #n
+\end{verbatim}
+This instruction has the effect that for the next \tty{n} instructions
+($0<n<5$), it is possible to address the alternate SFR space instead of
+the normal one. AS does not only generate the appropriate machine
+code when it encounters this instruction. It also sets an internal
+flag that will only allow accesses to the alternate SFR space for
+the next \tty{n} instructions. Of course, they may not contain jumps...
+Of course, it is always possible to define bits from either area at
+any place, and it is always possible to reach all registers with
+absolute addresses. In contrast, short and bit addressing only works
+for one area at a time, attempts contradicting to this will result in
+an error message.
+
+The situation is similar for prefix instructions and absolute resp.
+indirect addressing: as the prefix argument and the address
+expression cannot always be evaluated at assembly time, chances for
+checking are limited and AS will limit itself to warnings...in
+detail, the situation is as follows:
+\begin{itemize}
+\item{fixed specification of a 64K bank with \tty{EXTS} or \tty{EXTSR}: the address
+ expression directly contains the lower 16 bits of the target
+ address. If the prefix and the following instruction have a
+ constant operand, AS will check if the the prefix argument and bits
+ 16..23 of the target address are equal.}
+\item{fixed specification of a 16K page with \tty{EXTP} or \tty{EXTPR}: the address
+ expression directly contains the lower 14 bits of the target
+ address. Bits 14 and 15 are fixed to 0, as the processor ignores
+ them in this mode. If the prefix and the following instruction
+ have a constant operand, AS will check if the the prefix argument
+ and bits 14..23 of the target address are equal.}
+\end{itemize}
+An example to clarify things a bit (the DPP registers have their
+reset values):
+\begin{verbatim}
+ extp #7,#1 ; range from 112K..128K
+ mov r0,1cdefh ; results in address 0defh in code
+ mov r0,1cdefh ; -->warning
+ exts #1,#1 ; range from 64K..128K
+ mov r0,1cdefh ; results in address 0cdefh in code
+ mov r0,1cdefh ; -->warning
+\end{verbatim}
+
+%%---------------------------------------------------------------------------
+
+\section{PIC16C5x/16C8x}
+
+Similar to the MCS-48 family, the PICs split their program memory
+into several banks because the opcode does not offer enough space for
+a complete address. AS uses the same automatism for the instructions
+\tty{CALL} and \tty{GOTO}, i.e. the PA bits in the status word are set according
+to the start and target address. However, this procedure is far more
+problematic compared to the 48's:
+\begin{enumerate}
+\item{The instructions are not any more one word long (up to three
+ words). Therefore, it is not guaranteed that they can be
+ skipped with a conditional branch.}
+\item{It is possible that the program counter crosses a page boundary
+ while the program sequence is executed. The setting of PA bits
+ AS assumes may be different from reality.}
+\end{enumerate}
+The instructions that operate on register W and another register
+normally require a second parameter that specifies whether the result
+shall be stored in W or the register. Under AS, it is valid to omit
+the second parameter. The assumed target then depends upon the
+operation's type: For unary operations, the result is by default
+stored back into the register. These instructions are:
+\begin{quote}{\tt
+ COMF, DECF, DECFSZ, INCF, INCFSZ, RLF, RRF, and SWAPF
+}\end{quote}
+The other operations by default regard W as an accumulator:
+\begin{quote}{\tt
+ ADDWF, ANDWF, IORWF, MOVF, SUBWF, and XORWF
+}\end{quote}
+The syntax defined by Microchip to write literals is quite obscure
+and reminds of the syntax used on IBM 360/370 systems (greetings from
+the stone-age...). To avoid introducing another branch into the
+parser, with AS one has to write constants in the Motorola syntax
+(optionally Intel or C in \tty{RELAXED} mode).
+
+%%---------------------------------------------------------------------------
+
+\section{PIC 17C4x}
+
+With two exceptions, the same hints are valid as for its two smaller
+brothers: the corresponding include file only contains register
+definitions, and the problems concerning jump instructions are much
+smaller. The only exception is the \tty{LCALL} instruction, which allows a
+jump with a 16-bit address. It is translated with the following
+''macro'':
+\begin{verbatim}
+ MOVLW <addr15..8>
+ MOWF 3
+ LCALL <addr0..7>
+\end{verbatim}
+
+%%---------------------------------------------------------------------------
+
+\section{ST6}
+
+These processors have the ability to map their code ROM pagewise into the
+data area. I am not keen on repeating the whole discussion of the
+\tty{ASSUME} instruction at this place, so I refer to the corresponding
+section (\ref{ST6Assume}) for an explanation how to read constants out of
+the code ROM without too much headache.
+
+Some builtin ''macros'' show up when one analyzes the instruction set a
+bit more in detail. The instructions I found are listed in table
+\ref{TabHid62} (there are probably even more...):
+\par
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+instruction & in reality \\
+\hline
+\hline
+\tty{CLR A} & \tty{SUB A,A} \\
+\tty{SLA A} & \tty{ADD A,A} \\
+\tty{CLR addr} & \tty{LDI addr,0} \\
+\tty{NOP} & \tty{JRZ PC+1} \\
+\hline
+\end{tabular}\end{center}
+\caption{Hidden Macros in the ST62's Instruction Set\label{TabHid62}}
+\end{table*}
+Especially the last case is a bit astonishing...unfortunately, some
+instructions are really missing. For example, there is an \tty{AND}
+instruction but no \tty{OR}...not to speak of an \tty{XOR}. For this reason, the
+include file \tty{STDDEF62.INC} contains also some helping macros
+(additionally to register definitions).
+
+The original assembler AST6 delivered by SGS-Thomson partially uses
+different pseudo instructions than AS. Apart from the fact that AS
+does not mark pseudo instructions with a leading dot, the following
+instructions are identical:
+\begin{verbatim}
+ ASCII, ASCIZ, BLOCK, BYTE, END, ENDM, EQU, ERROR, MACRO,
+ ORG, TITLE, WARNING
+\end{verbatim}
+Table \ref{TabAST6} shows the instructions which have AS counterparts
+with similar function.
+\par
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+AST6 & AS & meaning/function \\
+\hline
+\hline
+\tty{.DISPLAY} & \tty{MESSAGE} & output message \\
+\hline
+\tty{.EJECT} & \tty{NEWPAGE} & new page in assembly listing \\
+\hline
+\tty{.ELSE} & \tty{ELSEIF} & conditional assembly \\
+\hline
+\tty{.ENDC} & \tty{ENDIF} & conditional assembly \\
+\hline
+\tty{.IFC} & \tty{IF...} & conditional assembly \\
+\hline
+\tty{.INPUT} & \tty{INCLUDE} & insert include file \\
+\hline
+\tty{.LIST} & \tty{LISTING, MACEXP} & settings for listing \\
+\hline
+\tty{.PL} & \tty{PAGE} & page length of listing \\
+\hline
+\tty{.ROMSIZE} & \tty{CPU} & set target processor \\
+\hline
+\tty{.VERS} & \tty{VERSION} (symbol) & query version \\
+\hline
+\tty{.SET} & \tty{EVAL} & redefine variables \\
+\hline
+\end{tabular}\end{center}
+\caption{Equivalent Instructions AST6$\leftrightarrow$AS\label{TabAST6}}
+\end{table*}
+
+%%---------------------------------------------------------------------------
+
+\section{ST7}
+
+In \cite{ST7Man}, the \tty{.w} postfix to signify 16-bit addresses is only
+defined for memory indirect operands. It is used to mark that a
+16-bit address is stored at a zero page address. AS additionally
+allows this postfix for absolute addresses or displacements of
+indirect address expressions to force 16-bit displacements in spite
+of an 8-bit value (0..255).
+
+%%---------------------------------------------------------------------------
+
+\section{ST9}
+
+The ST9's bit addressing capabilities are quite limited: except for
+the \tty{BTSET} instruction, only bits within the current set of working
+registers are accessible. A bit address is therefore of the
+following style:
+\begin{verbatim}
+ rn.[!]b ,
+\end{verbatim}
+whereby \tty{!} means an optional complement of a source operand. If a bit
+is defined symbolically, the bit's register number is stored in bits
+7..4, the bit's position is stored in bits 3..1 and the optional
+complement is kept in bit 0. AS distinguishes explicit and symbolic
+bit addresses by the missing dot. A bit's symbolic name therefore
+must not contain a dot, thought it would be legal in respect to the
+general symbol name conventions. It is also valid to invert a
+symbolically referred bit:
+\begin{verbatim}
+bit2 bit r5.3
+ .
+ .
+ bld r0.0,!bit2
+\end{verbatim}
+This opportunity also allows to undo an inversion that was done at
+definition of the symbol.
+
+The include file \tty{REGST9.INC} defines the symbolic names of all on-chip
+registers and their associated bits. Keep however in mind that the
+bit definitions only work after previously setting the working
+register bank to the address of these peripheral registers!
+
+In contrast to the definition file delivered with the AST9 assembler
+from SGS-Thomson, the names of peripheral register names are only
+defined as general registers (\tty{R...}), not also as working registers
+(\tty{r...}). The reason for this is that AS does not support register
+aliases; a tribute to assembly speed.
+
+%%---------------------------------------------------------------------------
+
+\section{6804}
+
+To be honest: I only implemented this processor in AS to quarrel
+about SGS-Thomson's peculiar behaviour. When I first read the 6804's
+data book, the ''incomplete'' instruction set and the built-in macros
+immediately reminded me of the ST62 series manufactured by the same
+company. A more thorough comparison of the opcodes gave surprising
+insights: A 6804 opcode can be generated by taking the equivalent
+ST62 opcode and mirroring all the bits! So Thomson obviously did a
+bit of processor core recycling...which would be all right if they
+would not try to hide this: different peripherals, motorola instead
+of Zilog-style syntax, and the awful detail of \bb{not} mirroring operand
+fields in the opcode (e.g. bit fields containing displacements). The
+last item is also the reason that finally convinced me to support the
+6804 in AS. I personally can only guess which department at Thomson
+did the copy...
+
+In contrast to its ST62 counterpart, the include file for the 6804
+does not contain instruction macros that help a bit to deal with the
+limited machine instruction set. This is left as an exercise to the
+reader!
+
+%%---------------------------------------------------------------------------
+
+\section{TMS3201x}
+
+It seems that every semiconductor's ambition is to invent an own
+notation for hexadecimal numbers. Texas Instrument took an
+especially eccentric approach for these processors: a $>$ sign as
+prefix! The support of such a format in AS would have lead to
+extreme conflicts with AS's compare and shift operators. I therefore
+decided to use the Intel notation, which is what TI also uses for the
+340x0 series and the 3201x's successors...
+
+The instruction word of these processors unfortunately does not have
+enough bits to store all 8 bits for direct addressing. This is why
+the data address space is split into two banks of 128 words. AS
+principally regards the data address space as a linear segment of 256
+words and automatically clears bit 7 on direct accesses (an exception
+is the \tty{SST} instruction that can only write to the upper bank). The
+programmer has to take care that the bank flag always has the correct
+value!
+
+Another hint that is well hidden in the data book: The \tty{SUBC}
+instruction internally needs more than one clock for completion, but
+the control unit already continues to execute the next instruction.
+An instruction following \tty{SUBC} therefore may not access the
+accumulator. AS does not check for such conditions!
+
+%%---------------------------------------------------------------------------
+
+\section{TMS320C2x}
+
+As I did not write this code generator myself (that does not lower
+its quality by any standard), I can only roughly line out why there
+are some instructions that force a prefixed label to be untyped, i.e.
+not assigned to any specific address space: The 2x series of TMS
+signal processors has a code and a data segment which are both 64
+Kbytes large. Depending on external circuitry, code and data space may
+overlap, e.g. to allow storage of constants in the code area and
+access them as data. Data storage in the code segment may be
+necessary because older versions of AS assume that the data segment
+only consists of RAM that cannot have a defined power-on state in a
+single board system. They therefore reject storage of contents in
+other segments than \tty{CODE}. Without the feature of making symbols
+untyped, AS would punish every access to a constant in code space
+with a warning (''symbol out of wrong segment''). To say it in detail,
+the following instructions make labels untyped:
+\begin{quote}\tt
+ BSS, STRING, RSTRING, BYTE, WORD , LONG\\
+ FLOAT, DOUBLE, EFLOAT, BFLOAT and TFLOAT
+\rm\end{quote}
+If one needs a typed label in front of one of these instructions, one
+can work around this by placing the label in a separate line just
+before the pseudo instruction itself. On the other hand, it is
+possible to place an untyped label in front of another pseudo
+instruction by defining the label with \tty{EQU}, e.g.
+\begin{verbatim}
+<name> EQU $ .
+\end{verbatim}
+
+%%---------------------------------------------------------------------------
+
+\section{TMS320C3x}
+
+The syntax detail that created the biggest amount of headache for me
+while implementing this processor family is the splitting of parallel
+instructions into two separate source code lines. Fortunately, both
+instructions of such a construct are also valid single instructions.
+AS therefore first generates the code for the first instruction and
+replaces it by the parallel machine code when a parallel construct is
+encountered in the second line. This operation can be noticed in the
+assembly listing by the machine code address that does not advance
+and the double dot replaced with a \tty{R}.
+
+Compared to the TI assembler, AS is not as flexible regarding the
+position of the double lines that signify a parallel operation
+(\tty{||}): One either has to place them like a label (starting in the
+first column) or to prepend them to the second mnemonic. The line
+parser of AS will run into trouble if you do something else...
+
+%%---------------------------------------------------------------------------
+
+\section{TMS9900}
+
+Similar to most older TI microprocessor families, TI used an own
+format for hexadecimal and binary constants. AS instead favours the
+Intel syntax which is also common for newer processor designs from
+TI.
+
+The TI syntax for registers allows to use a simple integer number
+between 0 and 15 instead of a real name (\tty{Rx} or \tty{WRx}).
+This has two consequences:
+\begin{itemize}
+\item{\tty{R0...R15} resp. \tty{WR0..WR15} are simple predefined integer
+ symbols with values from 0 to 15, and the definition of register
+ aliases is a simple matter of \tty{EQU}.}
+\item{In contrast to several other processors, I cannot offer the
+ additional AS feature that allows to omit the character sigifying
+ absolute addressing (a \@ sign in this case). As a missing
+ character would mean register numbers (from 0 to 15) in this case,
+ it was not possible to offer the optional omission.}
+\end{itemize}
+Furthermore, TI sometimes uses \tty{Rx} to name registers and \tty{WRx}
+at other places...currently both variants are recognized by AS.
+
+%%---------------------------------------------------------------------------
+
+\section{TMS70Cxx}
+
+This processor family belongs to the older families developed by TI
+and therefore TI's assemblers use their proprietary syntax for
+hexadecimal resp. binary constants (a prefixed $<$ resp. \tty{?} character).
+As this format could not be realized for AS, the Intel syntax is used
+by default. This is the format TI to which also switched over when
+introducing the successors, of this family, the 370 series of
+microcontrollers. Upon a closer inspection of both's machine
+instruction set, one discovers that about 80\% of all instruction are
+binary upward compatible, and that also the assembly syntax is almost
+identical - but unfortunately only almost. TI also took the chance to
+make the syntax more orthogonal and simple. I tried to introduce
+the majority of these changes also into the 7000's instruction set:
+\begin{itemize}
+\item{It is valid to use the more common \tty{\#} sign for immediate addressing
+ instead of the percent sign.}
+\item{If a port address (\tty{P...}) is used as source or destination in a
+ \tty{AND, BTJO, BTJZ, MOV, OR}, or \tty{XOR} instruction, it is not necessary
+ to use the mnemonic variant with an appended \tty{P} - the general
+ form is sufficient.}
+\item{The prefixed \tty{@} sign for absolute or B-relative addressing may be
+ omitted.}
+\item{Instead of \tty{CMPA, CMP} with \tty{A} as target may be written.}
+\item{Instead of \tty{LDA} resp. \tty{STA}, one can simply use the
+ \tty{MOV} instruction with \tty{A} as source resp. destination.}
+\item{One can write \tty{MOVW} instead of \tty{MOVD}.}
+\item{It is valid to abbreviate \tty{RETS} resp. \tty{RETI} as \tty{RTS}
+ resp. \tty{RTI}.}
+\item{\tty{TSTA} resp. \tty{TSTB} may be written as \tty{TST A} resp.
+ \tty{TST B}.}
+\item{\tty{XCHB B} is an alias for \tty{TSTB}.}
+\end{itemize}
+An important note: these variants are only allowed for the TMS70Cxx -
+the corresponding 7000 variants are not allowed for the 370 series!
+
+%%---------------------------------------------------------------------------
+
+\section{TMS370xxx}
+
+Though these processors do not have specialized instructions for bit
+manipulation, the assembler creates (with the help of the \tty{DBIT}
+instruction - see there) the illusion as if single bits were
+addressable. To achieve this, the \tty{DBIT} instructions stores an
+address along with a bit position into an integer symbol which may
+then be used as an argument to the pseudo instructions \tty{SBIT0, SBIT1,
+CMPBIT, JBIT0}, and \tty{JBIT1}. These are translated into the instructions
+\tty{OR, AND, XOR, BTJZ}, and \tty{BTJO} with an appropriate bit mask.
+
+There is nothing magic about these bit symbols, they are simple
+integer values that contain the address in their lower and the bit
+position in their upper half. One could construct bit symbols
+without the \tty{DBIT} instruction, like this:
+\begin{verbatim}
+defbit macro name,bit,addr
+name equ addr+(bit<<16)
+ endm
+\end{verbatim}
+but this technique would not lead to the \tty{EQU}-style syntax defined by
+TI (the symbol to be defined replaces the label field in a line).
+\bb{CAUTION!} Though \tty{DBIT} allows an arbitrary address, the pseudo
+instructions can only operate with addresses either in the range from
+0..255 or 1000h..10ffh. The processor does not have an absolute
+addressing mode for other memory ranges...
+
+%%---------------------------------------------------------------------------
+
+\section{MSP430}
+\label{MSPSpec}
+
+The MSP was designed to be a RISC processor with a minimal power
+consumption. The set of machine instructions was therefore reduced
+to the absolute minimum (RISC processors do not have a microcode ROM
+so every additional instruction has to be implemented with additional
+silicon that increases power consumption). A number of instructions
+that are hardwired for other processors are therefore emulated with
+other instructions. For AS, these instructions are defined in the
+include file \tty{REGMSP.INC}. You will get error messages for more than
+half of the instructions defined by TI if you forget to include this
+file!
+
+%%---------------------------------------------------------------------------
+
+\section{COP8 \& SC/MP}
+\label{COP8Spec}
+
+National unfortunately also decided to use the syntax well known from
+IBM mainframes (and much hated by me..) to write non-decimal integer
+constants. Just like with other processors, this does not work with
+AS's parser. ASMCOP however fortunately also seems to allow the C
+syntax, which is why this became the default for the COP series and
+the SC/MP...
+
+%%---------------------------------------------------------------------------
+
+\section{SC144xxx}
+\label{SC144xxspec}
+
+Originally, National offered a relatively simple assembler for this series
+of DECT controllers. An much more powerful assembler has been announced
+by IAR, but it is not available up to now. However, since the development
+tools made by IAR are as much target-independent as possible, one can
+roughly estimate the pseudo instructions it will support by looking at
+other available target platforms. With this in mind, the (few)
+SC144xx-specific instructions {\tt DC, DC8, DW16, DS, DS8, DS16, DW} were
+designed. Of course, I didn't want to reinvent the wheel for pseudo
+instructions whose functionality is already part of the AS core.
+Therefore, here is a little table with equivalences. The statements
+\tty{ALIGN, END, ENDM, EXITM, MACRO, ORG, RADIX, SET,} and \tty{REPT} both
+exist for the IAR assembler and AS and have same functionality. Changes
+are needed for the following instructions:
+
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|}
+\hline
+IAR & AS & Funktion\\
+\hline
+\hline
+\tty{\#include} & \tty{include} & include file \\
+\tty{\#define} & \tty{SET, EQU} & define symbol \\
+\tty{\#elif, ELIF, ELSEIF} & \tty{ELSEIF} & start another \\
+ & & IF branch \\
+\tty{\#else, ELSE} & \tty{ELSE} & last branch of an IF \\
+ & & construct \\
+\tty{\#endif, ENDIF} & \tty{ENDIF} & ends an IF construct \\
+\tty{\#error} & \tty{ERROR, FATAL} & create error message \\
+\tty{\#if, IF} & \tty{IF} & start an IF construct \\
+\tty{\#ifdef} & \tty{IFDEF} & symbol defined ? \\
+\tty{\#ifndef} & \tty{IFNDEF} & symbol not defined ? \\
+\tty{\#message} & \tty{MESSAGE} & output message \\
+\tty{=, DEFINE, EQU} & \tty{=, EQU} & fixed value assignment \\
+\tty{EVEN} & \tty{ALIGN 2} & force PC to be equal \\
+\tty{COL, PAGSIZ} & \tty{PAGE} & set page size for listing \\
+\tty{ENDR} & \tty{ENDM} & end REPT construct \\
+\tty{LSTCND, LSTOUT} & \tty{LISTING} & control amount of listing \\
+\tty{LSTEXP, LSTREP} & \tty{MACEXP} & list expanded macros? \\
+\tty{LSTXRF} & \verb!<command line>! & generate cross reference \\
+\tty{PAGE} & \tty{NEWPAGE} & new page in listing \\
+\tty{REPTC} & \tty{IRPC} & repetition with character \\
+ & & replacement \\
+\hline
+\end{tabular}\end{center}
+\end{table*}
+
+There is no direct equivalent for {\tt CASEON}, {\tt CASEOFF,}
+\tty{LOCAL}, \tty{LSTPAG}, \tty{\#undef,} and {\tt REPTI}.
+
+A 100\% equivalent is of course impossible as long as there is no C-like
+preprocessor in AS. C-like comments unfortunately are also impossible
+at the moment. Caution: When modifying IAR codes for AS, do not forget to
+move converted preprocessor statements out of column 1 as AS reserves this
+column exclusively for labels!
+
+%%---------------------------------------------------------------------------
+
+\section{75K0}
+\label{75K0Spec}
+
+Similar to other processors, the assembly language of the 75 series
+also knows pseudo bit operands, i.e. it is possible to assign a
+combination of address and bit number to a symbol that can then be
+used as an argument for bit oriented instructions just like explicit
+expressions. The following three instructions for example generate
+the same code:
+\begin{verbatim}
+ADM sfr 0fd8h
+SOC bit ADM.3
+
+ skt 0fd8h.3
+ skt ADM.3
+ skt SOC
+\end{verbatim}
+AS distinguishes direct and symbolic bit accesses by the missing dot
+in symbolic names; it is therefore forbidden to use dots in symbol
+names to avoid misunderstandings in the parser.
+
+The storage format of bit symbols mostly accepts the binary coding in
+the machine instructions themselves: 16 bits are used, and there is
+a ''long'' and a ''short'' format. The short format can store the
+following variants:
+\begin{itemize}
+\item{direct accesses to the address range from 0FBxH to 0FFxH}
+\item{indirect accesses in the style of \tty{Addr.@L} (0FC0H $\leq$ \tty{Addr} $\leq$0FFFH)}
+\item{indirect accesses in the style of \tty{@H+d4.bit}}
+\end{itemize}
+The upper byte is set to 0, the lower byte contains the bit
+expression coded according to \cite{NEC75}. The long format in contrast
+only knows direct addressing, but it can cover the whole address space
+(given a correct setting of MBS and MBE). A long expression stores
+bits 0..7 of the address in the lower byte, the bit position in bits
+8 and 9, and a constant value of 01 in bits 10 and 11. The highest
+bits allow to distinguish easily between long and short addresses via
+a check if the upper byte is 0. Bits 12..15 contain bits 8..11 of
+the address; they are not needed to generate the code, but they have
+to be stored somewhere as the check for correct banking can only
+take place when the symbol is actually used.
+
+%%---------------------------------------------------------------------------
+
+\section{78K0}
+\label{78K0Spec}
+
+NEC uses different ways to mark absolute addressing in its data
+books:
+\begin{itemize}
+\item{absolute short: no prefix}
+\item{absolute long: prefix of \tty{!}}
+\item{PC relative: prefix of \tty{\$}}
+\end{itemize}
+Under AS, these prefixes are only necessary if one wants to force a
+certain addressing mode and the instruction allows different
+variants. Without a prefix, AS will automatically select the shortest
+variant. It should therefore rarely be necessary to use a prefix in
+practice.
+
+%%---------------------------------------------------------------------------
+
+\section{$\mu$PD772x}
+
+Both the 7720 and 7725 are provided by the same code generator and are
+extremely similar in their instruction set. One should however not
+beleive that they are binary compatible: To get space for the longer
+address fields and additional instructions, the bit positions of some
+fields in the instruction word have changed, and the instruction length
+has changed from 23 to 24 bits. The code format therefore uses different
+header ids for both CPUs.
+
+They both have in common that in addition to the code and data segment,
+there is also a ROM for storage of constants. In the case of AS, it is
+mapped onto the \tty{ROMDATA} segment!
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{File Formats}
+
+In this chapter, the formats of files AS generates shall be explained
+whose formats are not self-explanatory.
+
+%%---------------------------------------------------------------------------
+
+\section{Code Files}
+\label{SectCodeFormat}
+
+The format for code files generated by the assembler must be able to
+separate code parts that were generated for different target
+processors; therefore, it is a bit different from most other formats.
+Though the assembler package contains tools to deal with code files,
+I think is a question of good style to describe the format in short:
+
+If a code file contains multibyte values, they are stored in little
+endian order. This rule is already valid for the 16-bit magic word
+\$1489, i.e. every code file starts with the byte sequence \$89/\$14.
+
+This magic word is followed by an arbitrary number of ''records''. A
+record may either contain a continuous piece of the code or certain
+additional information. Even without switching to different
+processor types, a file may contain several code-containing records,
+in case that code or constant data areas are interrupted by reserved
+memory areas that should not be initialized. This way, the assembler
+tries to keep the file as short as possible.
+
+Common to all records is a header byte which defines the record's type
+and its contents. Written in a PASCALish way, the record structure
+can be described in the following way:
+\begin{verbatim}
+FileRecord = RECORD CASE Header:Byte OF
+ $00:(Creator:ARRAY[] OF Char);
+ $01..
+ $7f:(StartAdr : LongInt;
+ Length : Word;
+ Data : ARRAY[0..Length-1] OF Byte);
+ $80:(EntryPoint:LongInt);
+ $81:(Header : Byte;
+ Segment : Byte;
+ Gran : Byte;
+ StartAdr : LongInt;
+ Length : Word;
+ Data : ARRAY[0..Length-1] OF Byte);
+ END
+\end{verbatim}
+This description does not express fully that the length of data
+fields is variable and depends on the value of the \tty{Length} entries.
+
+A record with a header byte of \$81 is a record that may contain code
+or data from arbitrary segments. The first byte (\tty{Header}) describes
+the processor family the following code resp. data was generated for (see
+table \ref{TabHeader}).
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|c|l||c|l|}
+\hline
+header & family & header & family \\
+Header & Familie & Header & Familie \\
+\hline
+\hline
+\input{../doc_DE/tabids.tex}
+\end{tabular}\end{center}
+\caption{Header Bytes for the Different Processor
+ Families\label{TabHeader}}
+\end{table*}
+The \tty{Segment} field signifies the address space the following code
+belongs to. The assignment defined in table \ref{TabSegments} applies.
+\begin{table*}[htbp]
+\begin{center}\begin{tabular}{|c|l||c|l|}
+\hline
+number & segment & number & segment \\
+\hline
+\hline
+\$00 & $<$undefined$>$ & \$01 & \tty{CODE} \\
+\$02 & \tty{DATA} & \$03 & \tty{IDATA} \\
+\$04 & \tty{XDATA} & \$05 & \tty{YDATA} \\
+\$06 & \tty{BDATA} & \$07 & \tty{IO} \\
+\$08 & \tty{REG} & \$09 & \tty{ROMDATA} \\
+\hline
+\end{tabular}\end{center}
+\caption{Codings of the {\tt Segment} Field\label{TabSegments}}
+\end{table*}
+The \tty{Gran} field describes the code's ''granularity'', i.e. the size of
+the smallest addressable unit in the following set of data. This
+value is a function of processor type and segment and is an important
+parameter for the interpretation of the following two fields that
+describe the block's start address and its length: While the start
+address refers to the granularity, the \tty{Length} value is always
+expressed in bytes! For example, if the start address is \$300 and
+the length is 12, the resulting end address would be \$30b for a
+granularity of 1, however \$303 for a granularity of 4! Granularities
+that differ from 1 are rare and mostly appear in DSP CPU's that are
+not designed for byte processing. For example, a DSP56K's address
+space is organized in 64 Kwords of 16 bits. The resulting storage
+capacity is 128 Kbytes, however it is organized as $2^{16}$ words that
+are addressed with addresses 0,1,2,...65535!
+
+The start address is always 32 bits in size, independent of the
+processor family. In contrast, the length specification has only 16
+bits, i.e. a record may have a maximum length of 4+4+2+(64K-1) =
+65545 bytes.
+
+Data records with a Header ranging from \$01 to \$7f present a shortcut
+and preserve backward compatibility to earlier definitions of the
+file format: in their case, the Header directly defines the processor
+type, the target segment is fixed to \tty{CODE} and the granularity is
+implicitly given by the processor type, rounded up to the next power
+of two. AS prefers to use these records whenever data or code should
+go into the \tty{CODE} segment.
+
+A record with a Header of \$80 defines an entry point, i.e. the
+address where execution of the program should start. Such a record
+is the result of an \tty{END} statement with a corresponding address as
+argument.
+
+The last record in a file bears the Header \$00 and has only a string
+as data field. This string does not have an explicit length
+specification; its end is equal to the file's end. The string
+contains only the name of the program that created the file and has
+no further meaning.
+
+%%---------------------------------------------------------------------------
+
+\section{Debug Files}
+\label{SectDebugFormat}
+
+Debug files may optionally be generated by AS. They deliver important
+information for tools used after assembly, like disassemblers or
+debuggers. AS can generate debug files in one of three formats: On the
+one hand, the object format used by the AVR tools from Atmel respectively
+a NoICE-compatible command file, and on the other hand an own format. The
+first two are described in detail in \cite{AVRObj} resp. the NoICE
+documentations, which is why the following description limits itself to
+the AS-specific MAP format:
+
+The information in a MAP file is split into three groups:
+\begin{itemize}
+\item{symbol table}
+\item{memory usage per section}
+\item{machine addresses of source lines}
+\end{itemize}
+The second item is listed first in the file. A single entry in this
+list consists of two numbers that are separated by a \tty{:} character:
+\begin{verbatim}
+ <line number>:<address>
+\end{verbatim}
+Such an entry states that the machine code generated for the source
+statement in a certain line is stored at the mentioned address
+(written in hexadecimal notation). With such an information, a
+debugger can display the corresponding source lines while stepping
+through a program. As a program may consist of several include
+files, and due to the fact that a lot of processors have more than
+one address space (though admittedly only one of them is used to
+store executable code), the entries described above have to be
+sorted. AS does this sorting in two levels: The primary sorting
+criteria is the target segment, and the entries in one of these
+sections are sorted according to files. The sections resp.
+subsections are separated by special lines in the style of
+\begin{verbatim}
+Segment <segment name>
+\end{verbatim}
+resp.
+\begin{verbatim}
+File <file name> .
+\end{verbatim}
+The source line info is followed by the symbol table. Similar to the
+source line info, the symbol table is primarily sorted by the
+segments individual symbols are assigned to. In contrast to the
+source line info, an additional section \tty{NOTHING} exists which contains
+the symbols that are not assigned to any specific segment (e.g.
+symbols that have been defined with a simple \tty{EQU} statement). A
+section in the symbol table is started with a line of the following
+type:
+\begin{verbatim}
+Symbols in Segment <segment name>
+\end{verbatim}
+The symbols in a section are sorted according to the alphabetical
+order of their names, and one symbol entry consists of exactly one
+line. Such a line consists of 5 fields witch are separated by at
+least a single space:
+
+The first field is the symbol's name, possibly extended by a section
+number enclosed in brackets. Such a section number limits the
+range of validity for a symbol. The second field designates the
+symbol's type: \tty{Int} stands for integer values, \tty{Float} for floating
+point numbers, and \tty{String} for character arrays. The third field
+finally contains the symbol's value. If the symbol contains a
+string, it is necessary to use a special encoding for control
+characters and spaces. Without such a coding, spaces in a string
+could be misinterpreted as delimiters to the next field. AS uses the
+same syntax that is also valid for assembly source files: Instead of
+the character, its ASCII value with a leading backslash (\verb!\!) is
+inserted. For example, the string
+\begin{verbatim}
+ This is a test
+\end{verbatim}
+becomes
+\begin{verbatim}
+ This\032is\032\a\032test .
+\end{verbatim}
+The numerical value always has three digits and has to be interpreted
+as a decimal value. Naturally, the backslash itself also has to be
+coded this way.
+
+The fourth field specifies - if available - the size of the data
+structure placed at the address given by the symbol. A debugger may
+use this information to automatically display variables in their
+correct length when they are referred symbolically. In case AS does
+not have any information about the symbol size, this field simply
+contains the value -1.
+
+Finally,the fifth field states via the values 0 or 1 if the symbol
+has been used during assembly. A program that reads the symbol table
+can use this field to skip unused symbols as they are probably unused
+during the following debugging/disassembly session.
+
+The third section in a debug file describes the program's sections in
+detail. The need for such a detailed description arises from the
+sections' ability to limit the validity range of symbols. A symbolic
+debugger for example cannot use certain symbols for a reverse
+translation, depending on the current PC value. It may also have to
+regard priorities for symbol usage when a value is represented by
+more than one symbol. The definition of a section starts with a line
+of the following form:
+\begin{verbatim}
+Info for Section nn ssss pp
+\end{verbatim}
+\tty{nn} specifies the section's number (the number that is also used in
+the symbol table as a postfix for symbol names), \tty{ssss} gives its name
+and \tty{pp} the number of its parent section. The last information is
+needed by a retranslator to step upward through a tree of sections
+until a fitting symbol is found. This first line is followed by a
+number of further lines that describe the code areas used by this
+section. Every single entry (exactly one entry per line) either
+describes a single address or an address range given by a lower and
+an upper bound (separation of lower and upper bound by a minus sign).
+These bounds are ''inclusive'', i.e. the bounds themselves also belong
+to the area. Is is important to note that an area belonging to a
+section is not additionally listed for the section's parent sections
+(an exception is of course a deliberate multiple allocation of address
+areas, but you would not do this, would you?). On the one hand, this
+allows an optimized storage of memory areas during assembly. On the
+other hand, this should not be an obstacle for symbol backtranslation
+as the single entry already gives an unambiguous entry point for the
+symbol search path. The description of a section is ended by an
+empty line or the end of the debug file.
+
+Program parts that lie out of any section are not listed separately.
+This implicit ''root section'' carries the number -1 and is also used
+as parent section for sections that do not have a real parent
+section.
+
+It is possible that the file contains empty lines or comments (semi
+colon at line start). A program reading the file has to ignore such
+lines.
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Utility Programs}
+\label{ChapTools}
+
+To simplify the work with the assembler's code format a bit, I added
+some tools to aid processing of code files. These programs are
+released under the same license terms as stated in section
+\ref{SectLicense}!
+
+Common to all programs are the possible return codes they may deliver
+upon completion (see table \ref{TabToolReturns}).
+\par
+\begin{table*}[h]
+\begin{center}\begin{tabular}{|c|l|}
+\hline
+return code & error condition \\
+\hline
+\hline
+0 & no errors \\
+1 & error in command line parameters \\
+2 & I/O error \\
+3 & file format error \\
+\hline
+\end{tabular}\end{center}
+\caption{Return Codes of the Utility Programs\label{TabToolReturns}}
+\end{table*}
+Just like AS, all programs take their input from STDIN and write
+messages to STDOUT (resp. error messages to STDERR). Therefore,
+input and output redirections should not be a problem.
+
+In case that numeric or address specifications have to be given in
+the command line, they may also be written in hexadecimal notation
+when they are prefixed with a dollar character or a \tty{0x} like in C.
+(e.g. \verb!$10! or \verb!0x10! instead of 16).
+
+Unix shells however \marginpar{{\em UNIX}} assign a special meaning to the
+dollar sign, which makes it necessary to escape a dollar sign with a
+backslash. The \tty{0x} variant is definitely more comfortable in this case.
+
+Otherwise, calling conventions and variations are equivalent to those
+of AS (except for PLIST and AS2MSG); i.e. it is possible to store
+frequently used parameters in an environment variable (whose name is
+constructed by appending CMD to the program's name, i.e. \tty{BINDCMD} for
+BIND), to negate options, and to use all upper- resp. lower-case
+writing (for details on this, see section \ref{SectCallConvention}).
+
+Address specifications always relate to the granularity of the
+processor currently in question; for example, on a PIC, an address
+difference of 1 means a word and not a byte.
+
+%%---------------------------------------------------------------------------
+
+\section{PLIST}
+
+PLIST is the simplest one of the five programs supplied: its purpose
+is simply to list all records that are stored in a code file. As the
+program does not do very much, calling is quite simple:
+\begin{verbatim}
+ PLIST <file name>
+\end{verbatim}
+The file name will automatically be extended with the extension \tty{P} if
+it doesn't already have one.
+
+\bb{CAUTION!} At this place, no wildcards are allowed! If there is a
+necessity to list several files with one command, use the following
+''mini batch'':
+\begin{verbatim}
+ for %n in (*.p) do plist %n
+\end{verbatim}
+PLIST prints the code file's contents in a table style, whereby
+exactly one line will be printed per record. The individual rows
+have the following meanings:
+\begin{itemize}
+\item{code type: the processor family the code has been generated for.}
+\item{start address: absolute memory address that expresses the load
+ destination for the code.}
+\item{length: length of this code chunk in bytes.}
+\item{end address: last address of this code chunk. This address
+ is calculated as start address+length-1.}
+\end{itemize}
+All outputs are in hexadecimal notation.
+
+Finally, PLIST will print a copyright remark (if there is one in the
+file), together with a summaric code length.
+
+Simply said, PLIST is a sort of DIR for code files. One can use it
+to examine a file's contents before one continues to process it.
+
+%%---------------------------------------------------------------------------
+
+\section{BIND}
+
+BIND is a program that allows to concatenate the records of several
+code files into a single file. A filter function is available that
+can be used to copy only records of certain types. Used in this way,
+BIND can also be used to split a code file into several files.
+
+The general syntax of BIND is
+\begin{verbatim}
+ BIND <source file(s)> <target file> [options]
+\end{verbatim}
+Just like AS, BIND regards all command line arguments that do not
+start with a \tty{+, -} or \tty{/} as file specifications, of which the last one
+must designate the destination file. All other file specifications
+name sources, which may again contain wildcards.
+
+Currently, BIND defines only one command line option:
+\begin{itemize}
+\item{\tty{f $<$Header[,Header]$>$}: sets a list of record headers that should
+ be copied. Records with other header IDs will
+ not be copied. Without such an option, all
+ records will be copied. The headers given in
+ the list correspond to the \tty{HeaderID} field of the
+ record structure described in section \ref{SectCodeFormat}.
+ Individual headers in this list are separated
+ with commas.}
+\end{itemize}
+For example, to filter all MCS-51 code out of a code file, use BIND
+in the following way:
+\begin{verbatim}
+ BIND <source name> <target name> -f $31
+\end{verbatim}
+If a file name misses an extension, the extension \tty{P} will be added
+automatically.
+
+%%---------------------------------------------------------------------------
+
+\section{P2HEX}
+
+P2HEX is an extension of BIND. It has all command line options of BIND and
+uses the same conventions for file names. In contrary to BIND, the
+target file is written as a Hex file, i.e. as a sequence of lines
+which represent the code as ASCII hex numbers.
+
+P2HEX knows 8 different target formats, which can be selected via the
+command line parameter \tty{F}:
+\begin{itemize}
+\item{Motorola S-Records \tty{(-F Moto)}}
+\item{MOS Hex \tty{(-F MOS)}}
+\item{Intel Hex (Intellec-8, \tty{-F Intel)}}
+\item{16-Bit Intel Hex (MCS-86, \tty{-F Intel16)}}
+\item{32-Bit Intel Hex \tty{(-F Intel32)}}
+\item{Tektronix Hex \tty{(-F Tek)}}
+\item{Texas Instruments DSK \tty{(-F DSK)}}
+\item{Atmel AVR Generic (-F Atmel, see \cite{AVRObj})}
+\end{itemize}
+If no target format is explicitly specified, P2HEX will automatically
+choose one depending in the processor type: S-Records for Motorola
+CPUs, Hitachi, and TLCS-900, MOS for 65xx/MELPS, DSK for the 16 bit
+signal processors from Texas, Atmel Generic for the AVRs, and Intel Hex
+for the rest. Depending on the start addresses width, the S-Record
+format will use Records of type 1, 2, or 3, however, records in one
+group will always be of the same type. This automatism can be partially
+suppressed via the command line option
+\begin{verbatim}
+ -M <1|2|3>
+\end{verbatim}
+A value of 2 resp. 3 assures that that S records with a minimum type of 2
+resp. 3 will be used, while a value of 1 corresponds to the full
+automatism.
+
+The Intel, MOS and Tektronix formats are limited to 16 bit addresses, the
+16-bit Intel format reaches 4 bits further. Addresses that are to long
+for a given format will be reported by P2HEX with a warning; afterwards,
+they will be truncated (!).
+
+For the PIC microcontrollers, the switch
+\begin{verbatim}
+-m <0..3>
+\end{verbatim}
+allows to generate the three different variants of the Intel Hex
+format. Format 0 is INHX8M which contains all bytes in a
+Lo-Hi-Order. Addresses become double as large because the PICs have
+a word-oriented address space that increments addresses only by one
+per word. This format is also the default. With Format 1 (INHX16M),
+bytes are stored in their natural order. This is the format
+Microchip uses for its own programming devices. Format 2 (INHX8L)
+resp. 3 (INHX8H) split words into their lower resp. upper bytes.
+With these formats, P2HEX has to be called twice to get the complete
+information, like in the following example:
+\begin{verbatim}
+ p2hex test -m 2
+ rename test.hex test.obl
+ p2hex test -m 3
+ rename test.hex test.obh
+\end{verbatim}
+For the Motorola format, P2HEX additionally uses the S5 record type
+mentioned in \cite{CPM68K}. This record contains the number of data
+records (S1/S2/S3) to follow. As some programs might not know how to
+deal with this record, one can suppress it with the option
+\begin{verbatim}
+ +5 .
+\end{verbatim}
+In case a source file contains code record for different processors,
+the different hex formats will also show up in the target file - it
+is therefore strongly advisable to use the filter function.
+
+Apart form this filter function, P2HEX also supports an address
+filter, which is useful to split the code into several parts (e.g.
+for a set of EPROMs):
+\begin{verbatim}
+-r <start address>-<end address>
+\end{verbatim}
+The start address is the first address in the window, and the end
+address is the last address in the window, \bb{not} the first address
+that is out of the window. For example, to split an 8051 program
+into 4 2764 EPROMs, use the following commands:
+\begin{verbatim}
+p2hex <source file> eprom1 -f $31 -r $0000-$1fff
+p2hex <source file> eprom2 -f $31 -r $2000-$3fff
+p2hex <source file> eprom3 -f $31 -r $4000-$5fff
+p2hex <source file> eprom4 -f $31 -r $6000-$7fff
+\end{verbatim}
+By default, the address window is 32 Kbytes large and starts at
+address 0.
+
+\bb{CAUTION!} This type of splitting does not change the absolute
+addresses that will be written into the files! If the addresses in
+the individual hex files should rather start at 0, one can force this
+with the additional switch
+\begin{verbatim}
+ -a .
+\end{verbatim}
+On the other hand, to move the addresses to a different location, one may
+use the switch
+\begin{verbatim}
+ -R <value> .
+\end{verbatim}
+The value given is an {\em offset}, i.e. it is added to the addresses
+given in the code file.
+\par
+A special value for start and stop address arguments is a single
+dollar sign (\tty{\$}). This stands for the very first resp. last address
+that has been used in the code file. So, if you want to be sure
+that always the whole program is stored in the hex file, set the
+address filter
+\begin{verbatim}
+ -r $-$
+\end{verbatim}
+and you do not have to worry about address filters any more. Dollar
+signs and fixed addresses may of course me mixed. For example, the
+setting
+\begin{verbatim}
+ -r $-$7fff
+\end{verbatim}
+limits the upper end to 32 Kbytes.
+
+By using an offset, it is possible to move a file's contents to an
+arbitrary position. This offset is simply appended to a file's name,
+surrounded with parentheses. For example, if the code in a file
+starts at address 0 and you want to move it to address 1000 hex in the
+hex file, append \tty{(\$1000)} to the file's name (without spaces!).
+
+As the TI DSK format has the ability to distinguish between data and
+code, there is a switch
+\begin{verbatim}
+ -d <start>-<end>
+\end{verbatim}
+to designate the address range that should be written as data instead
+of code. For this option, single dollar signs are \bb{not} allowed! While
+this switch is only relevant for the DSK format, the option
+\begin{verbatim}
+ -e <address>
+\end{verbatim}
+is also valid for the Intel and Motorola formats. Its purpose is to
+set the entry address that will be inserted into the hex file. If
+such a command line parameter is missing, P2HEX will search a
+corresponding entry in the code file. If even this fails, no entry
+address will be written to the hex file (DSK/Intel) or the field
+reserved for the entry address will be set to 0 (Motorola).
+
+Unfortunately, one finds different statements about the last line of
+an Intel-Hex file in literature. Therefore, P2HEX knows three
+different variants that may be selected via the command-line
+parameter \tty{i} and an additional number:
+\begin{verbatim}
+ 0 :00000001FF
+ 1 :00000001
+ 2 :0000000000
+\end{verbatim}
+By default, variant 0 is used which seems to be the most common one.
+
+If the target file name does not have an extension, an extension of
+\tty{HEX} is supposed.
+
+By default, P2HEX will print a maximum of 16 data bytes per line,
+just as most other tools that output Hex files. If you want to
+change this, you may use the switch
+\begin{verbatim}
+-l <count> .
+\end{verbatim}
+The allowed range of values goes from 2 to 254 data bytes; odd values
+will implicitly be rounded down to an even count.
+
+In most cases, the temporary code files generated by AS are not of
+any further need after P2HEX has been run. The command line option
+\begin{verbatim}
+-k
+\end{verbatim}
+allows to instruct P2HEX to erase them automatically after
+conversion.
+
+In contrast to BIND, P2HEX will not produce an empty target file if
+only one file name (i.e. the target name) has been given. Instead,
+P2HEX will use the corresponding code file. Therefore, a minimal
+call in the style of
+\begin{verbatim}
+ P2HEX <name>
+\end{verbatim}
+is possible, to generate \tty{$<$name$>$.hex} out of \tty{$<$name$>$.p}.
+
+%%---------------------------------------------------------------------------
+
+\section{P2BIN}
+
+P2BIN works similar to P2HEX and offers the same options (except for
+the a and i options that do not make sense for binary files),
+however, the result is stored as a simple binary file instead of a
+hex file. Such a file is for example suitable for programming an
+EPROM.
+
+P2BIN knows three additional options to influence the resulting binary
+file:
+\begin{itemize}
+\item{\tty{l $<$8 bit number$>$}: sets the value that should be used to fill
+ unused memory areas. By default, the value
+ \$ff is used. This value assures that every
+ half-way intelligent EPROM burner will skip
+ these areas. This option allows to set different values,
+ for example if you want to
+ generate an image for the EPROM versions of
+ MCS-48 microcontrollers (empty cells of their
+ EPROM array contain zeroes, so \$00 would be
+ the correct value in this case).}
+\item{\tty{s}: commands the program to calculate a checksum
+ of the binary file. This sum is printed as
+ a 32-bit value, and the two's complement of
+ the least significant bit will be stored in
+ the file's last byte. This way, the modulus-
+ 256-sum of the file will become zero.}
+\item{\tty{m}: is designed for the case that a CPU with a
+ 16- or 32-bit data bus is used and the file
+ has to be split for several EPROMs. The
+ argument may have the following values:
+ \begin{itemize}
+ \item{\tty{ALL}: copy everything}
+ \item{\tty{ODD}: copy all bytes with an odd address}
+ \item{\tty{EVEN}: copy all bytes with an even address}
+ \item{\tty{BYTE0..BYTE3}: copy only bytes with an address of
+ 4n+0 .. 4n+3}
+ \item{\tty{WORD0, WORD1}: copy only the lower resp. upper 16-
+ bit word of a 32-bit word}
+ \end{itemize}}
+\end{itemize}
+To avoid confusions: If you use this option, the resulting binary file
+will become smaller because only a part of the source will be copied.
+Therefore, the resulting file will be smaller by a factor of 2 or 4
+compared to \tty{ALL}. This is just natural...
+
+In case the code file does not contain an entry address, one may set
+it via the \tty{-e} command line option just like with P2HEX. Upon
+request, P2BIN prepends the resulting image with this address. The
+command line option
+\begin{verbatim}
+-S
+\end{verbatim}
+activates this function. It expects a numeric specification ranging
+from 1 to 4 as parameter which specifies the length of the address
+field in bytes. This number may optionally be prepended wit a \tty{L} or
+\tty{B} letter to set the endian order of the address. For example, the
+specification \tty{B4} generates a 4 byte address in big endian order,
+while a specification of \tty{L2} or simply \tty{2} creates a 2 byte address
+in little endian order.
+
+%%---------------------------------------------------------------------------
+
+\section{AS2MSG}
+
+AS2MSG is not a tool in the real sense, it is a filter that was
+designed to simplify the work with the assembler for (fortunate)
+users of Borland Pascal 7.0. The DOS IDEs feature a 'tools' menu
+that can be extended with own programs like AS. The filter allows to
+directly display the error messages paired with a line
+specification delivered by AS in the editor window. A new entry has
+to be added to the tools menu to achieve this (Options/Tools/New).
+Enter the following values:
+\begin{verbatim}
+ - Title: ~m~acro assembler
+ - Program path: AS
+ - Command line:
+ -E !1 $EDNAME $CAP MSG(AS2MSG) $NOSWAP $SAVE ALL
+ - assign a hotkey if wanted (e.g. Shift-F7)
+\end{verbatim}
+The -E option assures that Turbo Pascal will not become puzzled by
+STDIN and STDERR.
+
+I assume that AS and AS2MSG are located in a directory listed in the
+\tty{PATH} variable. After pressing the appropriate hotkey (or selecting
+AS from the tools menu), as will be called with the name of the file
+loaded in the active editor window as parameter. The error messages
+generated during assembly are redirected to a special window that
+allows to browse through the errors. \tty{Ctrl-Enter} jumps to an
+erroneous line. The window additionally contains the statistics AS
+prints at the end of an assembly. These lines obtain the dummy line
+number 1.
+
+\tty{TURBO.EXE} (Real Mode) and \tty{BP.EXE} (Protected Mode) may be used for
+this way of working with AS. I recommend however BP, as this version
+does not have to 'swap' half of the DOS memory before before AS is
+called.
+
+%%===========================================================================
+\appendix
+
+\cleardoublepage
+\chapter{Error Messages of AS}
+\label{ChapErrMess}
+
+Here is a list of all error messages emitted by AS. Each error message is
+described by:
+\begin{itemize}
+\item{the internal error number (it is displayed only if AS is started with the
+ \tty{-n} option)}
+\item{the text of the error message}
+\item{error type:
+ \begin{itemize}
+ \item{Warning: informs the user that a possible error was
+ found, or that some inefficient binary code
+ could be generated. The assembly process is not
+ stopped.}
+ \item{Error: an error was detected. The assembly process
+ continues, but no binary code is emitted.}
+ \item{Fatal: unrecoverable error. The assembly process is
+ terminated.}
+ \end{itemize}}
+\item{reason of the error: the situation originating the error.}
+\item{argument: a further explanation of the error message.}
+\end{itemize}
+
+\par
+
+\newcommand{\errentry}[5]
+ {\item[#1]{#2
+ \begin{description}
+ \item[Type:]{\ \\#3}
+ \item[Reason:]{\ \\#4}
+ \item[Argument:]{\ \\#5}
+ \end{description}}
+ }
+
+\begin{description}
+\errentry{ 0}{useless displacement}
+ {warning}
+ {680x0, 6809 and COP8 CPUs: an address displacement of 0 was
+ given. An address expression without displacement is
+ generated, and a convenient number of NOPs are emitted
+ to avoid phasing errors.}
+ {none}
+\errentry{ 10}{short addressing possible}
+ {warning}
+ {680x0-, 6502 and 68xx CPUs: a given memory location can be
+ reached using short addressing. A short addressing
+ instruction is emitted, together with the required
+ number of NOPs to avoid phasing errors.}
+ {none}
+\errentry{ 20}{short jump possible}
+ {warning}
+ {680x0- and 8086 CPUs can execute jumps using a short or long
+ displacement. If a shorter jump was not explicitly
+ requested, in the
+ first pass room for the long jump is reserved. Then the code
+ for the shorter jump is emitted, and the remaining space is
+ filled with NOPs to avoid phasing errors.}
+ {none}
+\errentry{ 30}{no sharefile created, SHARED ignored}
+ {warning}
+ {A \tty{SHARED} directive was found, but on the command line no
+ options were specified, to generate a shared file.}
+ {none}
+\errentry{ 40}{FPU possibly cannot read this value ($>$=1E1000)}
+ {warning}
+ {The BCD-floating point format used by the 680x0-FPU
+ allows such a large exponent, but according to the latest
+ databooks, this cannot be fully interpreted. The
+ corresponding word is assembled, but the associated
+ function is not expected to produce the correct result.}
+ {none}
+\errentry{ 50}{privileged instruction}
+ {warning}
+ {A Supervisor-mode directive was used, that was not preceded
+ by an explicit \tty{SUPMODE ON} directive}
+ {none}
+\errentry{ 60}{distance of 0 not allowed for short jump (NOP created instead)}
+ {warning}
+ {A short jump with a jump distance equal to 0 is not allowed
+ by 680x0 resp. COP8 processors, since the associated code word is
+ used to identify long jump instruction. Instead of a
+ jump instruction, AS emits a NOP}
+ {none}
+\errentry{ 70}{symbol out of wrong segment}
+ {warning}
+ {The symbol used as an operand comes from an address space
+ that cannot be addressed together with the given instruction}
+ {none}
+\errentry{ 75}{segment not accessible}
+ {warning}
+ {The symbol used as an operand belongs to an address space
+ that cannot be accessed with any of the segment registers of
+ the 8086}
+ {The name of the inaccessible segment}
+\errentry{ 80}{change of symbol values forces additional pass}
+ {warning}
+ {A symbol changed value, with respect to previous pass. This
+ warning is emitted only if the \tty{-r} option is used.}
+ {name of the symbol that changed value.}
+\errentry{ 90}{overlapping memory usage}
+ {warning}
+ {The analysis of the usage list shows that part of the
+ program memory was used more than once. The reason can be an
+ excessive usage of \tty{ORG} directives.}
+ {none}
+\errentry{ 100}{none of the CASE conditions was true}
+ {warning}
+ {A \tty{SWITCH...CASE} directive without \tty{ELSECASE} clause was
+ executed, and none of the \tty{CASE} conditions was found
+ to be true.}
+ {none}
+\errentry{ 110}{page might not be addressable}
+ {warning}
+ {The symbol used as an operand was not found in the memory
+ page defined by an \tty{ASSUME} directive (ST6, 78(C)10).}
+ {none}
+\errentry{ 120}{register number must be even}
+ {warning}
+ {The CPU allows to concatenate only register pairs, whose
+ start address is even (RR0, RR2, ..., only for Z8).}
+ {none}
+\errentry{ 130}{obsolete instruction, usage discouraged}
+ {warning}
+ {The instruction used, although supported, was superseded by
+ a new instruction. Future versions of the CPU could no more
+ implement the old instruction.}
+ {none}
+\errentry{ 140}{unpredictable execution of this instruction}
+ {warning}
+ {The addressing mode used for this instruction is allowed,
+ however a register is used in such a way that its contents
+ cannot be predicted after the execution of the
+ instruction.}
+ {none}
+\errentry{ 150}{localization operator senseless out of a section}
+ {warning}
+ {An aheaded \@ must be used, so that it is
+ explicitly referred to the local symbols used in the
+ section. When the operator is used out of a section, there
+ are no local symbols, because this operator is useless in
+ this context.}
+ {none}
+\errentry{ 160}{senseless instruction}
+ {warning}
+ {The instruction used has no meaning, or it can be
+ substituted by an other instruction, shorter and more
+ rapidly executed.}
+ {none}
+\errentry{ 170}{unknown symbol value forces additional pass}
+ {warning}
+ {AS expects a forward definition of a symbol, i.e. a symbol
+ was used before it was defined. A further pass must be
+ executed. This warning is emitted only if the \tty{-r} option was
+ used.}
+ {none}
+\errentry{ 180}{address is not properly aligned}
+ {warning}
+ {An address was used that is not an exact multiple of the
+ operand size. Although the CPU databook forbids this, the
+ address could be stored in the instruction word, so AS
+ simply emits a warning.}
+ {none.}
+\errentry{ 190}{I/O-address must not be used here}
+ {warning}
+ {The addressing mode or the address used are correct, but the
+ address refers to the peripheral registers, and it
+ cannot be used in this circumstance.}
+ {none.}
+\errentry{ 200}{possible pipelining effects}
+ {warning}
+ {A register is used in a series of instructions, so that a
+ sequence of instructions probably does not generate the
+ desired result. This usually happens when a register is
+ used before its new content was effectively loaded in it.}
+ {the register probably causing the problem.}
+\errentry{ 210}{multiple use of address register in one instruction}
+ {warning}
+ {A register used for the addressing is used once more in the
+ same instruction, in a way that results in a modification
+ of the register value. The resulting address does not have a
+ well defined value.}
+ {the register used more than once.}
+\errentry{ 220}{memory location is not bit addressable}
+ {warning}
+ {Via a \tty{SFRB} statement, it was tried to declare a memory cell
+ as bit addressable which is not bit addressable due to the
+ 8051's architectural limits.}
+ {none}
+\errentry{ 230}{stack is not empty}
+ {warning}
+ {At the end of a pass, a stack defined by the program is
+ not empty.}
+ {the name of the stack and its remaining depth}
+\errentry{ 240}{NUL character in string, result is undefined}
+ {warning}
+ {A string constant contains a NUL character. Though this
+ works with the Pascal version, it is a problem for the
+ C version of AS since C itself terminates strings with
+ a NUL character. i.e. the string would have its end for
+ C just at this point...}
+ {none}
+\errentry{ 250}{instruction crosses page boundary}
+ {warning}
+ {The parts of a machine statement partiallly lie on
+ different pages. As the CPU's instruction counter does
+ not get incremented across page boundaries, the processor
+ would fetch at runtime the first byte of the old page
+ instead of the instruction's following byte; the program
+ would execute incorrectly.}
+ {none}
+\errentry{ 260}{range overflow}
+ {warning}
+ {A numeric value was out of the allowed range. AS brought
+ the value back into the allowed range by truncating upper
+ bits, but it is not guaranteed that meaningful and correct
+ code is generated by this.}
+ {none}
+\errentry{ 270}{negative argument for DUP}
+ {warning}
+ {The repetition argument of a DUP directive was smaller
+ than 0. Analogous to a count of exactly 0, no data is
+ stored.}
+ {none}
+\errentry{1000}{symbol double defined}
+ {error}
+ {A new value is assigned to a symbol, using a label or a
+ \tty{EQU, PORT, SFR, LABEL, SFRB} or \tty{BIT} instruction: however this
+ can be done only using \tty{SET/EVAL}.}
+ {the name of the offending symbol, and the line number where
+ it was defined for the first time, according to the symbol
+ table.}
+\errentry{1010}{symbol undefined}
+ {error}
+ {A symbol is still not defined in the symbol table, also
+ after a second pass.}
+ {the name of the undefined symbol.}
+\errentry{1020}{invalid symbol name}
+ {error}
+ {A symbol does not fulfill the requirements that symbols
+ must have to be considered valid by AS. Please pay
+ attention that more stringent syntax rules exist for
+ macros and function parameters.}
+ {the wrong symbol}
+\errentry{1090}{invalid format}
+ {error}
+ {The instruction format used does not exist for this
+ instruction.}
+ {the known formats for this command}
+\errentry{1100}{useless attribute}
+ {error}
+ {The instruction (processor or pseudo) cannot be used with a
+ point-suffixed attribute.}
+ {none}
+\errentry{1105}{attribute may only be one character long}
+ {error}
+ {The attribute following a point after an instruction must
+ not be longer or shorter than one character.}
+ {none}
+\errentry{1110}{wrong number of operands}
+ {error}
+ {The number of arguments issued for the instruction (processor or
+ pseudo) does not conform with the accepted number of
+ operands.}
+ {none}
+\errentry{1115}{wrong number of operations}
+ {error}
+ {The number of options given with this command is not
+ correct.}
+ {none}
+\errentry{1120}{addressing mode must be immediate}
+ {error}
+ {The instruction can be used only with immediate operands
+ (preceded by \tty{\#}).}
+ {none}
+\errentry{1130}{invalid operand size}
+ {error}
+ {Although the operand is of the right type, it does not have
+ the correct length (in bits).}
+ {none}
+\errentry{1131}{conflicting operand sizes}
+ {error}
+ {The operands used have different length (in bits)}
+ {none}
+\errentry{1132}{undefined operand size}
+ {error}
+ {It is not possible to estimate, from the opcode and from
+ the operands, the size of the operand (a trouble with
+ 8086 assembly). You must define it with a \tty{BYTE or WORD}
+ \tty{PTR} prefix.}
+ {none}
+\errentry{1135}{invalid operand type}
+ {error}
+ {an expression does not have a correct operand type
+ (integer/\-decimal/\-string)}
+ {the operand type}
+\errentry{1140}{too many arguments}
+ {error}
+ {No more than 20 arguments can be given to any instruction}
+ {none}
+\errentry{1200}{unknown opcode}
+ {error}
+ {An was used that is neither an AS instruction, nor a
+ known mnemonic for the current processor type.}
+ {none}
+\errentry{1300}{number of opening/closing brackets does not match}
+ {error}
+ {The expression parser found an expression enclosed by
+ parentheses, where the number of opening and closing
+ parentheses does not match.}
+ {the wrong expression}
+\errentry{1310}{division by 0}
+ {error}
+ {An expression on the right side of a division or modulus
+ operation was found to be equal to 0.}
+ {none}
+\errentry{1315}{range underflow}
+ {error}
+ {An integer word underflowed the allowed range.}
+ {the value of the word and the allowed minimum (in most
+ cases, maybe I will complete this one day...)}
+\errentry{1320}{range overflow}
+ {error}
+ {An integer word overflowed the allowed range.}
+ {the value of the world, and the allowed maximum (in most
+ cases, maybe I will complete this one day...)}
+\errentry{1325}{address is not properly aligned}
+ {error}
+ {The given address does not correspond with the size needed
+ by the data transfer, i.e. it is not an integral multiple of
+ the operand size. Not all processor types can use unaligned
+ data.}
+ {none}
+\errentry{1330}{distance too big}
+ {error}
+ {The displacement used for an address is too large.}
+ {none}
+\errentry{1340}{short addressing not allowed}
+ {error}
+ {The address of the operand is outside of the address space
+ that can be accessed using short-addressing mode.}
+ {none}
+\errentry{1350}{addressing mode not allowed here}
+ {error}
+ {the addressing mode used, although usually possible,
+ cannot be used here.}
+ {none}
+\errentry{1351}{number must be even}
+ {error}
+ {At this point, only even addresses are allowed, since the
+ low order bit is used for other purposes or it is reserved.}
+ {none}
+\errentry{1355}{addressing mode not allowed in parallel operation}
+ {error}
+ {The addressing mode(s) used are allowed in sequential,
+ but not in parallel instructions}
+ {none}
+\errentry{1360}{undefined condition}
+ {error}
+ {The branch condition used for a conditional jump does not
+ exist.}
+ {none}
+\errentry{1370}{jump distance too big}
+ {error}
+ {the jump instruction and destination are too apart to
+ execute the jump with a single step}
+ {none}
+\errentry{1375}{jump distance is odd}
+ {error}
+ {Since instruction must only be located at even addresses,
+ the jump distance between two instructions must always be
+ even, and the LSB of the jump distance is used otherwise.
+ This issue was not verified here. The reason is usually the
+ presence of an odd number of data in bytes or a wrong
+ \tty{ORG}.}
+ {none}
+\errentry{1380}{invalid argument for shifting}
+ {error}
+ {only a constant or a data register can be used for defining
+ the shift size. (only for 680x0)}
+ {none}
+\errentry{1390}{operand must be in range 1..8}
+ {error}
+ {constants for shift size or \tty{ADDQ} argument can be only
+ within the 1..8 range (only for 680x0)}
+ {none}
+\errentry{1400}{shift amplitude too big}
+ {error}
+ {(no more used)}
+ {none}
+\errentry{1410}{invalid register list}
+ {error}
+ {The register list argument of \tty{MOVEM} or \tty{FMOVEM} has a
+ wrong format (only for 680x0)}
+ {none}
+\errentry{1420}{invalid addressing mode for CMP}
+ {error}
+ {The operand combination used with the \tty{CMP} instruction is
+ not allowed (only for 680x0)}
+ {none}
+\errentry{1430}{invalid CPU type}
+ {error}
+ {The processor type used as argument for \tty{CPU} command is
+ unknown to AS.}
+ {the unknown processor type}
+\errentry{1440}{invalid control register}
+ {error}
+ {The control register used by a \tty{MOVEC} is not (yet) available
+ for the processor defined by the \tty{CPU} command.}
+ {none}
+\errentry{1445}{invalid register}
+ {error}
+ {The register used, although valid, cannot be used in this
+ context.}
+ {none}
+\errentry{1450}{RESTORE without SAVE}
+ {error}
+ {A \tty{RESTORE} command was found, that cannot be coupled with a
+ corresponding \tty{SAVE}.}
+ {none}
+\errentry{1460}{missing RESTORE}
+ {error}
+ {After the assembling pass, a \tty{SAVE} command was missing.}
+ {none.}
+\errentry{1465}{unknown macro control instruction}
+ {error}
+ {A macro option parameter is unknown to AS.}
+ {the dubious option.}
+\errentry{1470}{missing ENDIF/ENDCASE}
+ {error}
+ {after the assembling, some of the \tty{IF}- or \tty{CASE}- constructs
+ were found without the closing command}
+ {none}
+\errentry{1480}{invalid IF-structure}
+ {error}
+ {The command structure in a \tty{IF}- or \tty{SWITCH}- sequence is
+ wrong.}
+ {none}
+\errentry{1483}{section name double defined}
+ {error}
+ {In this program module a section with the same name still
+ exists.}
+ {the multiple-defined name}
+\errentry{1484}{unknown section}
+ {error}
+ {In the current scope, there are no sections with this name}
+ {the unknown name}
+\errentry{1485}{missing ENDSECTION}
+ {error}
+ {Not all the sections were properly closed.}
+ {none}
+\errentry{1486}{wrong ENDSECTION}
+ {error}
+ {The given \tty{ENDSECTION} does not refer to the most
+ deeply nested one.}
+ {none}
+\errentry{1487}{ENDSECTION without SECTION}
+ {error}
+ {An \tty{ENDSECTION} command was found, but the associated section
+ was not defined before.}
+ {none}
+\errentry{1488}{unresolved forward declaration}
+ {error}
+ {A symbol declared with a \tty{FORWARD} or \tty{PUBLIC} statement could
+ not be resolved.}
+ {the name of the unresolved symbol.}
+\errentry{1489}{conflicting FORWARD $<->$ PUBLIC-declaration}
+ {error}
+ {A symbol was defined both as public and private.}
+ {the name of the symbol.}
+\errentry{1490}{wrong numbers of function arguments}
+ {error}
+ {The number of arguments used for referencing a function
+ does not match the number of arguments defined in the
+ function definition.}
+ {none}
+\errentry{1495}{unresolved literals (missing LTORG)}
+ {error}
+ {At the end of the program, or just before switching to
+ another processor type, unresolved literals still remain.}
+ {none}
+\errentry{1500}{instruction not allowed on}
+ {error}
+ {Although the instruction is correct, it cannot be used with
+ the selected member of the CPU family.}
+ {none}
+\errentry{1505}{addressing mode not allowed on}
+ {error}
+ {Although the addressing mode used is correct, it cannot be
+ used with the selected member of the CPU family.}
+ {none}
+\errentry{1510}{invalid bit position}
+ {error}
+ {Either the number of bits specified is not allowed, or
+ the command is not completely specified.}
+ {none}
+\errentry{1520}{only ON/OFF allowed}
+ {error}
+ {This pseudo command accepts as argument either \tty{ON} or
+ \tty{OFF}}
+ {none}
+\errentry{1530}{stack is empty or undefined}
+ {error}
+ {It was tried to access a stack via a \tty{POPV} instruction
+ that was either never defined or already emptied.}
+ {the name of the stack in question}
+\errentry{1540}{not exactly one bit set}
+ {error}
+ {Not exactly one bit was set in a mask passed to the
+ \tty{BITPOS} function.}
+ {none}
+\errentry{1550}{ENDSTRUCT without STRUCT}
+ {error}
+ {An \tty{ENDSTRUCT} instruction was found though there is
+ currently no structure definition in progress.}
+ {none}
+\errentry{1551}{open structure definition}
+ {error}
+ {After end of assembly, not all \tty{STRUCT} instructions
+ have been closed with appropriate \tty{ENDSTRUCT}s.}
+ {the innermost, unfinished structure definition}
+\errentry{1552}{wrong ENDSTRUCT}
+ {error}
+ {the name parameter of an \tty{ENDSTRUCT} instruction does
+ not correspond to the innermost open structure
+ definition.}
+ {none}
+\errentry{1553}{phase definition not allowed in structure definition}
+ {error}
+ {What should I say about that? \tty{PHASE} inside a record
+ simply does not make sense and only leads to
+ confusion...}
+ {none}
+\errentry{1554}{invalid \tty{STRUCT} directive}
+ {error}
+ {Only \tty{EXTNAMES} resp. \tty{NOEXTNAMES} are allowed as
+ directives of a \tty{STRUCT} statement.}
+ {the unknown directive}
+\errentry{1600}{unexpected end of file}
+ {error}
+ {It was tried to read past the end of a file with a
+ \tty{BINCLUDE} statement.}
+ {none}
+\errentry{1700}{ROM-offset must be in range 0..63}
+ {error}
+ {The ROM table of the 680x0 coprocessor has only 64 entries.}
+ {none}
+\errentry{1710}{invalid function code}
+ {error}
+ {The only function code arguments allowed are SFC, DFC, a
+ data register, or a constant in the interval of 0..15 (only
+ for 680x0 MMU).}
+ {none}
+\errentry{1720}{invalid function code mask}
+ {error}
+ {Only a number in the interval 0..15 can be used as
+ function code mask (only for 680x0 MMU)}
+ {none}
+\errentry{1730}{invalid MMU register}
+ {error}
+ {The MMU does not have a register with this name (only for
+ 680x0 MMU).}
+ {none}
+\errentry{1740}{level must be in range 0..7}
+ {error}
+ {The level for \tty{PTESTW} and \tty{PTESTR} must be a constant in the
+ range of 0...7 (only for 680x0 MMU).}
+ {none}
+\errentry{1750}{invalid bit mask}
+ {error}
+ {The bit mask used for a bit field command has a wrong
+ format (only for 680x0).}
+ {none}
+\errentry{1760}{invalid register pair}
+ {error}
+ {The register here defined cannot be used in this context,
+ or there is a syntactic error (only for 680x0).}
+ {none}
+\errentry{1800}{open macro definition}
+ {error}
+ {An incomplete macro definition was found. Probably an
+ \tty{ENDM} was forgotten.}
+ {none}
+\errentry{1805}{EXITM not called from within macro}
+ {error}
+ {\tty{EXITM} is designed to terminate a macro expansion. This
+ instruction only makes sense within macros and an attempt
+ was made to call it in the absence of macros.}
+ {none}
+\errentry{1810}{more than 10 macro parameters}
+ {error}
+ {A macro cannot have more than 10 parameters}
+ {none}
+\errentry{1815}{macro double defined}
+ {error}
+ {A macro was defined more than once in a program section.}
+ {the multiply defined macro name.}
+\errentry{1820}{expression must be evaluatable in first pass}
+ {error}
+ {The command used has an influence on the length of the
+ emitted code, so that forward references cannot be resolved
+ here.}
+ {none}
+\errentry{1830}{too many nested IFs}
+ {error}
+ {(no more implemented)}
+ {none}
+\errentry{1840}{ELSEIF/ENDIF without IF}
+ {error}
+ {A \tty{ELSEIF}- or \tty{ENDIF}- command was found, that is not preceded
+ by an \tty{IF}- command.}
+ {none}
+\errentry{1850}{nested / recursive macro call}
+ {error}
+ {(no more implemented)}
+ {none}
+\errentry{1860}{unknown function}
+ {error}
+ {The function invoked was not defined before.}
+ {The name of the unknown function}
+\errentry{1870}{function argument out of definition range}
+ {error}
+ {The argument does not belong to the allowed argument range
+ associated to the referenced function.}
+ {none}
+\errentry{1880}{floating point overflow}
+ {error}
+ {Although the argument is within the range allowed to the
+ function arguments, the result is not valid}
+ {none}
+\errentry{1890}{invalid value pair}
+ {error}
+ {The base-exponent pair used in the expression cannot be
+ computed}
+ {none}
+\errentry{1900}{instruction must not start on this address}
+ {error}
+ {No jumps can be performed by the selected CPU from this
+ address.}
+ {none}
+\errentry{1905}{invalid jump target}
+ {error}
+ {No jumps can be performed by the selected CPU to this
+ address.}
+ {none}
+\errentry{1910}{jump target not on same page}
+ {error}
+ {Jump command and destination must be in the same memory
+ page.}
+ {none}
+\errentry{1920}{code overflow}
+ {error}
+ {An attempt was made to generate more than 1024 code or
+ data bytes in a single memory page.}
+ {none}
+\errentry{1925}{address overflow}
+ {error}
+ {The address space for the processor type actually used was
+ filled beyond the maximum allowed limit.}
+ {none}
+\errentry{1930}{constants and placeholders cannot be mixed}
+ {error}
+ {Instructions that reserve memory, and instructions that define
+ constants cannot be mixed in a single pseudo instruction.}
+ {none}
+\errentry{1940}{code must not be generated in structure definition}
+ {error}
+ {a \tty{STRUCT} construct is only designed to describe a
+ data structure and not to create one; therefore, no
+ instructions are allowed that generate code.}
+ {none}
+\errentry{1950}{parallel construct not possible here}
+ {error}
+ {Either these instructions cannot be executed in parallel,
+ or they are not close enough each other, to do parallel
+ execution.}
+ {none}
+\errentry{1960}{invalid segment}
+ {error}
+ {The referenced segment cannot be used here.}
+ {The name of the segment used.}
+\errentry{1961}{unknown segment}
+ {error}
+ {The segment referenced with a \tty{SEGMENT} command does not
+ exist for the CPU used.}
+ {The name of the segment used}
+\errentry{1962}{unknown segment register}
+ {error}
+ {The segment referenced here does not exist (8086 only)}
+ {none}
+\errentry{1970}{invalid string}
+ {error}
+ {The string has an invalid format.}
+ {none}
+\errentry{1980}{invalid register name}
+ {error}
+ {The referenced register does not exist, or it cannot
+ be used here.}
+ {none}
+\errentry{1985}{invalid argument}
+ {error}
+ {The command used cannot be performed with the \tty{REP}-prefix.}
+ {none}
+\errentry{1990}{indirect mode not allowed}
+ {error}
+ {Indirect addressing cannot be used in this way}
+ {none}
+\errentry{1995}{not allowed in current segment}
+ {error}
+ {(no more implemented)}
+ {none}
+\errentry{1996}{not allowed in maximum mode}
+ {error}
+ {This register can be used only in minimum mode}
+ {none}
+\errentry{1997}{not allowed in minimum mode}
+ {error}
+ {This register can be used only in maximum mode}
+ {none}
+\errentry{2000}{invalid combination of prefixes}
+ {error}
+ {The prefix combination here defined is not allowed, or it
+ cannot be translated into binary code}
+ {none}
+\errentry{2010}{invalid escape sequence}
+ {error}
+ {The special character defined using a backslash sequence
+ is not defined}
+ {none}
+\errentry{10001}{error in opening file}
+ {fatal}
+ {An error was detected while trying to open a file for input.}
+ {description of the I/O error}
+\errentry{10002}{error in writing listing}
+ {fatal}
+ {An error happened while AS was writing the listing file.}
+ {description of the I/O error}
+\errentry{10003}{file read error}
+ {fatal}
+ {An error was detected while reading a source file.}
+ {description of the I/O error}
+\errentry{10004}{file write error}
+ {fatal}
+ {While AS was writing a code or share file, an error happened.}
+ {description of the I/O error}
+\errentry{10006}{heap overflow}
+ {fatal}
+ {The memory available is not enough to store all the data
+ needed by AS. Try using the DPMI or OS/2 version of AS.}
+ {none}
+\errentry{10007}{stack overflow}
+ {fatal}
+ {The program stack crashed, because too complex formulas, or
+ a bad disposition of symbols and/or macros were used. Try
+ again, using AS with the option \tty{-A}.}
+ {none}
+\end{description}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{I/O Error Messages}
+
+The following error messages are generated not only by AS, but also by
+the auxiliary programs, like PLIST, BIND, P2HEX, and P2BIN. Only the most
+probable error messages are here explained. Should you meet an undocumented
+error message, then you probably met a program bug! Please inform us
+immediately about this!!
+
+\begin{description}
+\item[2]{file not found\\
+ The file requested does not exist, or it is stored on another
+ drive.}
+\item[3]{path not found\\
+ The path of a file does not exist, or it is on another drive.}
+\item[4]{too much open files\\
+ There are no more file handles available to DOS. Increase
+ their number changing the value associated to \tty{FILES=} in the file
+ \tty{CONFIG.SYS}.}
+\item[5]{file access not allowed\\
+ Either the network access rights do not allow the file access, or
+ an attempt was done to rewrite or rename a protected file.}
+\item[6]{invalid file handler}
+\item[12]{invalid access mode}
+\item[15]{invalid drive letter\\
+ The required drive does not exist.}
+\item[16]{The file cannot be deleted}
+\item[17]{RENAME cannot be done on this drive}
+\item[100]{Unexpected end of file\\
+ A file access tried to go beyond the end of file, although according
+ to its structure this should not happen. The file is probably
+ corrupted.}
+\item[101]{disk full\\
+ This is self explaining! Please, clean up !}
+\item[102]{ASSIGN failed}
+\item[103]{file not open}
+\item[104]{file not open for reading}
+\item[105]{file not open for writing}
+\item[106]{invalid numerical format}
+\item[150]{the disk is write-protected\\
+ When you don't use a hard disk as work medium storage, you should
+ sometimes remove the protecting tab from your diskette!}
+\item[151]{unknown device\\
+ you tried to access a peripheral unit that is unknown to DOS. This
+ should not usually happen, since the name should be automatically
+ interpreted as a filename.}
+\item[152]{drive not ready\\
+ close the disk drive door.}
+\item[153]{unknown DOS function}
+\item[154]{invalid disk checksum\\
+ A bad read error on the disk. Try again; if nothing changes,
+ reformat the floppy disk resp. begin to take care of your hard
+ disk!}
+\item[155]{invalid FCB}
+\item[156]{position error\\
+ the diskette/hard disk controller has not found a disk track. See
+ nr. 154 !}
+\item[157]{format unknown\\
+ DOS cannot read the diskette format}
+\item[158]{sector not found\\
+ As nr. 156, but the controller this time could not find a disk
+ sector in the track.}
+\item[159]{end of paper\\
+ You probably redirected the output of AS to a printer. Assembler
+ printout can be veeery long...}
+\item[160]{device read error\\
+ The operating system detected an unclassificable read error}
+\item[161]{device write error\\
+ The operating system detected an unclassificable write error}
+\item[162]{general failure error\\
+ The operating system has absolutely no idea of what happened to the
+ device.}
+\end{description}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Frequently Asked Questions}
+
+In this chapter, I tried to collect some questions that arise very often
+together with their answers. Answers to the problems presented in
+this chapter might also be found at other places in this manual, but
+one maybe does not find them immediately...
+
+\begin{description}
+\item[Q:]{I am fed up with DOS. Are there versions of AS for other
+ operating systems ?}
+\item[A:]{Apart from the protected mode version that offers more memory when
+ working under DOS, ports exist for OS/2 and Unix systems like
+ Linux (currently in test phase). Versions that help operating
+ system manufacturers located in Redmont to become even richer are
+ currently not planned. I will gladly make the sources of AS
+ available for someone else who wants to become active in this
+ direction. The C variant is probably the best way to start a
+ port into this direction. He should however not expect support
+ from me that goes beyond the sources themselves...}
+\vspace{0.3cm}
+\item[Q:]{Is a support of the XYZ processor planned for AS?}
+\item[A:]{New processors are appearing all the time and I am trying to keep
+ pace by extending AS. The stack on my desk labeled ''undone''
+ however never goes below the 4 inch watermark... Wishes coming
+ from users of course play an important role in the decision which
+ candidates will be done first. The internet and the rising amount
+ of documentation published in electronic form make the acquisition
+ of data books easier than it used to be, but it always becomes
+ difficult when more exotic or older architectures are wanted. If
+ the processor family in question is not in the list of families
+ that are planned (see chapter 1), adding a data book to a request
+ will have a highly positive influence. Borrowing books is also
+ fine.}
+\vspace{0.3cm}
+\item[Q:]{Having a free assembler is really fine, but I now also had use for
+ a disassembler...and a debugger...a simulator would also really be
+ cool!}
+\item[A:]{AS is a project I work on in leisure time, the time I have when I
+ do not have to care of how to make my living. AS already takes a
+ significant portion of that time, and sometimes I make a time-out
+ to use my soldering iron, enjoy a Tangerine Dream CD, watch TV, or
+ simply to fulfill some basic human needs... I once started to
+ write the concept of a disassembler that was designed to create
+ source code that can be assembled and that automatically
+ separates code and data areas. I quickly stopped this project
+ again when I realized that the remaining time simply did not
+ suffice. I prefer to work on one good program than to struggle for
+ half a dozen of mediocre apps. Regarded that way, the answer to
+ the question is unfortunately ''no''...}
+\vspace{0.3cm}
+\item[Q:]{The screen output of AS is messed up with strange characters, e.g.
+ arrows and brackets. Why?}
+\item[A:]{AS will by default use some ANSI control sequences for screen
+ control. These sequences will appear unfiltered on your screen
+ if you did not install an ANSI driver. Either install an ANSI
+ driver or use the DOS command \tty{SET USEANSI=N} to turn the
+ sequences off.}
+\vspace{0.3cm}
+\item[Q:]{AS suddenly terminates with a stack overflow error while
+ assembling my program. Did my program become to large?}
+\item[A:]{Yes and No. Your program's symbol table has grown a bit
+ unsymmetrically what lead to high recursion depths while accessing
+ the table. Errors of this type especially happen in the
+ 16-bit-OS/2 version of AS which has a very limited stack area.
+ Restart AS with the \tty{-A} command line switch. If this does not
+ help, too complex formula expression are also a possible cause of
+ stack overflows. In such a case, try to split the formula into
+ intermediate steps.}
+\vspace{0.3cm}
+\item[Q:]{It seems that AS does not assemble my program up to the end. It
+ worked however with an older version of AS (1.39).}
+\item[A:]{Newer versions of AS no longer ignore the \tty{END} statement; they
+ actually terminate assembly when an \tty{END} is encountered.
+ Especially older include files made by some users tended to
+ contain an \tty{END} statement at their end. Simply remove the
+ superfluous \tty{END} statements.}
+\vspace{0.3cm}
+\item[Q:]{I made an assembly listing of my program because I had some more
+ complicated assembly errors in my program. Upon closer
+ investigation of the listing, I found that some branches do not
+ point to the desired target but instead to themselves!}
+\item[A:]{This effect happens in case of forward jumps in the first pass.
+ The formula parser does not yet have the target address in its symbol
+ table, and as it is a completely independent module, it has to think of
+ a value that even does not hurt relative branches with short displacement
+ lengths. This is the current program counter itself...in the
+ second pass, the correct values would have appeared, but the second
+ pass did not happen due to errors in the first one. Correct the
+ other errors first so that AS gets into the second pass, and the
+ listing should look more meaningful again.}
+\vspace{0.3cm}
+\item[Q:]{Assembly of my program works perfectly, however I get an empty
+ file when I try to convert it with P2HEX or P2BIN.}
+\item[A:]{You probably did not set the address filter correctly. This
+ filter by default cuts out an area ranging from 0 to 32 Kbytes.
+ If you program contains memory chunks outside this range, they
+ will be ignored. If your code is completely beyond the 32K
+ barrier (this is commonplace for processors of the 65xx and 68xx
+ series), you will get the result you just described. Simply
+ set the address filter to a range that suits your needs (see the
+ chapter dealing with P2BIN/P2HEX).}
+\vspace{0.3cm}
+\item[Q:]{I cannot enter the dollar character when using P2BIN or P2HEX
+ under Unix. The automatic address range setting does not work, instead
+ I get strange error messages.}
+\item[A:]{Unix shells use the dollar character for expansion of shell
+ variables. If you want to pass a dollar character to an application,
+ prefix it with a backslash (\verb!\!). In the special case of the
+ address range specification for P2HEX and P2BIN, you may also use
+ \tty{0x} instead of the dollar character, which removes this prblen
+ completely.}
+\end{description}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Pseudo-Instructions Collected}
+
+This appendix is designed as a quick reference to look up all pseudo
+instructions provided by AS. The list is ordered in two parts: The
+first part lists the instructions that are always available, and this
+list is followed by lists that enumerate the instructions
+additionally available for a certain processor family.
+
+\subsubsection{Instructions that are always available}
+\input{../doc_DE/pscomm.tex}
+There is an additional \tty{SET} resp. \tty{EVAL} instruction (in case
+\tty{SET} is already a machine instruction).
+
+\input{../doc_DE/pscpu.tex}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Predefined Symbols}
+\label{AppInternSyms}
+
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+name & data type & definition & meaning \\
+\hline
+\hline
+ARCHITECTURE & string & predef. & target platform AS was \\
+ & & & compiled for, in the style \\
+ & & & processor-manufacturer- \\
+ & & & operating system \\
+BIGENDIAN & boolean & dyn.(0) & storage of constants MSB \\
+ & & & first ? \\
+CASESENSITIVE & boolean & normal & case sensitivity in symbol \\
+ & & & names ? \\
+CONSTPI & float & normal & constant Pi (3.1415.....) \\
+DATE & string & predef. & date of begin of assembly \\
+FALSE & boolean & predef. & 0 = logically ''false'' \\
+HASFPU & boolean & dyn.(0) & coprocessor instructions \\
+ & & & enabled ? \\
+HASPMMU & boolean & dyn.(0) & MMU instructions enabled ? \\
+INEXTMODE & boolean & dyn.(0) & XM flag set for 4 Gbyte \\
+ & & & address space ? \\
+INLWORDMODE & boolean & dyn.(0) & LW flag set for 32 bit \\
+ & & & instructions ? \\
+INMAXMODE & boolean & dyn.(0) & processor in maximum \\
+ & & & mode ? \\
+INSUPMODE & boolean & dyn.(0) & processor in supervisor \\
+ & & & mode ? \\
+\hline
+\end{tabular}\end{center}
+\caption{Predefined Symbols - Part 1\label{TabInternSyms1}}
+\end{table*}
+
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+name & data type & definition & meaning \\
+\hline\hline
+INSRCMODE & boolean & dyn.(0) & processor in source mode ? \\
+FULLPMMU & boolean & dyn.(0/1) & full PMMU instruction set \\
+ & & & allowed ? \\
+LISTON & boolean & dyn.(1) & listing enabled ? \\
+MACEXP & boolean & dyn.(1) & expansion of macro con- \\
+ & & & structs in listing enabled ? \\
+MOMCPU & integer & dyn. & number of target CPU \\
+ & & (68008) & currently set \\
+MOMCPUNAME & string & dyn. & name of target CPU \\
+ & & (68008) & currently set \\
+MOMFILE & string & special & current source file \\
+ & & & (including include files) \\
+MOMLINE & integer & special & current line number in \\
+ & & & source file \\
+MOMPASS & integer & special & number of current pass \\
+MOMSECTION & string & special & name of current section or \\
+ & & & empty string if out of any \\
+ & & & section \\
+MOMSEGMENT & string & special & name of address space \\
+ & & & currently selected \\
+ & & & with \tty{SEGMENT} \\
+ & & & \\
+\hline
+\end{tabular}\end{center}
+\caption{Predefined Symbols - Part 2\label{TabInternSyms2}}
+\end{table*}
+
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|l|l|}
+\hline
+name & data type & definition & meaning \\
+\hline\hline
+PADDING & boolean & dyn.(1) & pad byte field to even \\
+ & & & count ? \\
+RELAXED & boolean & dyn.(0) & any syntax allowed integer \\
+ & & & constants ? \\
+PC & integer & special & curr. program counter \\
+ & & & (Thomson) \\
+TIME & string & predef. & time of begin of assembly \\
+ & & & (1. pass) \\
+TRUE & integer & predef. & 1 = logically ''true'' \\
+VERSION & integer & predef. & version of AS in BCD \\
+ & & & coding, e.g. 1331 hex for \\
+ & & & version 1.33p1 \\
+WRAPMODE & Integer & predef. & shortened program counter \\
+ & & & assumed? \\
+* & integer & special & curr. program counter \\
+ & & & (Motorola, Rockwell, Micro- \\
+ & & & chip, Hitachi) \\
+\$ & integer & special & curr. program counter (Intel, \\
+ & & & Zilog, Texas, Toshiba, NEC, \\
+ & & & Siemens, AMD) \\
+\hline
+\end{tabular}\end{center}
+\caption{Predefined Symbols - Part 3\label{TabInternSyms3}}
+\end{table*}
+
+To be exact, boolean symbols are just ordinary integer symbols with the
+difference that AS will assign only two different values to them (0 or 1,
+corresponding to False or True). AS does not store special symbols
+in the symbol table. For performance reasons, they are realized with
+hardcoded comparisons directly in the parser. They therefore do not
+show up in the assembly listing's symbol table. Predefined symbols
+are only set once at the beginning of a pass. The values of dynamic
+symbols may in contrast change during assembly as they reflect
+settings made with related pseudo instructions. The values added in
+parentheses give the value present at the beginning of a pass.
+
+The names given in this table also reflect the valid way to reference
+these symbols in case-sensitive mode.
+
+The names listed here should be avoided for own symbols; either one
+can define but not access them (special symbols), or one will receive
+an error message due to a double-defined symbol. The ugliest case is
+when the redefinition of a symbol made by AS at the beginning of a
+pass leads to a phase error and an infinite loop...
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Shipped Include Files}
+
+The distribution of AS contains a couple of include files. Apart from
+include files that only refer to a specific processor family (and whose
+function should be immediately clear to someone who works with this
+family), there are a few processor-independent files which include useful
+functions. The functions defined in these files shall be explained
+briefly in the following sections:
+
+\section{BITFUNCS.INC}
+
+This file defines a couple of bit-oriented functions that might be
+hardwired for other assemblers. In the case of AS however, thaey are
+implemented with the help of user-defined functions:
+
+\begin{itemize}
+\item{{\em mask(start,bits)} returns an integer with {\em bits} bits set
+ starting at position {\em start};}
+\item{{\em invmask(start,bits)} returns one's complement to {\em
+ mask()};}
+\item{{\em cutout(x,start,bits)} returns {\em bits} bits masked out from
+ {\em x} starting at position {\em start} without shifting them to
+ position 0;}
+\item{{\em hi(x)} returns the second lowest byte (bits 8..15) of {\em
+ x};}
+\item{{\em lo(x)} returns the lowest byte (bits 8..15) of {\em x};}
+\item{{\em hiword(x)} returns the second lowest word (bits 16..31) of
+ {\em x};}
+\item{{\em loword(x)} returns the lowest word (bits 0..15) of {\em x};}
+\item{{\em odd(x)} returns TRUE if {\em x} is odd;}
+\item{{\em even(x)} returns TRUE if {\em x} is even;}
+\item{{\em getbit(x,n)} extracts bit {\em n} out of {\em x} and returns
+ it as 0 or 1;}
+\item{{\em shln(x,size,n)} shifts a word {\em x} of length {\em size} to
+ the left by {\em n} places;}
+\item{{\em shrn(x,size,n)} shifts a word {\em x} of length {\em size} to
+ the right by {\em n} places;}
+\item{{\em rotln(x,size,n)} rotates the lowest {\em size} bits of an
+ integer {\em x} to the left by {\em n} places;}
+\item{{\em rotrn(x,size,n)} rotates the lowest {\em size} bits of an
+ integer {\em x} to the right by {\em n} places;}
+\end{itemize}
+
+\section{CTYPE.INC}
+
+This include file is similar to the C include file {\tt ctype.h} which
+offers functions to classify characters. All functions deliver either
+TRUE or FALSE:
+
+\begin{itemize}
+\item{{\em isdigit(ch)} becomes TRUE if {\em ch} is a valid decimal
+ digit (0..9);}
+\item{{\em isxdigit(ch)} becomes TRUE if {\em ch} is a valid hexadecimal
+ digit (0..9, A..F, a..f);}
+\item{{\em isupper(ch)} becomes TRUE if {\em ch} is an uppercase
+ letter, excluding special national characters);}
+\item{{\em islower(ch)} becomes TRUE if {\em ch} is a lowercase
+ letter, excluding special national characters);}
+\item{{\em isalpha(ch)} becomes TRUE if {\em ch} is a letter, excluding
+ special national characters);}
+\item{{\em isalnum(ch)} becomes TRUE if {\em ch} is either a letter or
+ a valid decimal digit;}
+\item{{\em isspace(ch)} becomes TRUE if {\em ch} is an 'empty' character
+ (space, form feed, line feed, carriage return, tabulator);}
+\item{{\em isprint(ch)} becomes TRUE if {\em ch} is a printable character,
+ i.e. no control character up to code 31;}
+\item{{\em iscntrl(ch)} is the opposite to {\em isprint()};}
+\item{{\em isgraph(ch)} becomes TRUE if {\em ch} is a printable and
+ visible character;}
+\item{{\em ispunct(ch)} becomes TRUE if {\em ch} is a printable special
+ character (i.e. neither space nor letter nor number);}
+\end{itemize}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Acknowledgments}
+
+\begin{quote}\it
+''If I have seen farther than other men, \\
+it is because I stood on the shoulders of giants.'' \\
+\hspace{2cm} --Sir Isaac Newton
+\rm\end{quote}
+\begin{quote}\it
+''If I haven't seen farther than other men, \\
+it is because I stood in the footsteps of giants.'' \\
+\hspace{2cm} --unknown
+\rm\end{quote}
+\par
+If one decides to rewrite a chapter that has been out of date for two
+years, it is almost unavoidable that one forgets to mention some of
+the good ghosts who contributed to the success this project had up
+to now. The first ''thank you'' therefore goes to the people whose
+names I unwillingly forgot in the following enumeration!
+
+The concept of AS as a universal cross assembler came from Bernhard
+(C.) Zschocke who needed a ''student friendly'', i.e. free cross
+assembler for his microprocessor course and talked me into extending
+an already existing 68000 assembler. The rest is history...
+The microprocessor course held at RWTH Aachen also always provided the
+most engaged users (and bug-searchers) of new AS features and
+therefore contributed a lot to today's quality of AS.
+
+The internet and FTP have proved to be a big help for spreading AS and
+reporting of bugs. My thanks therefore go to the FTP admins (Bernd
+Casimir in Stuttgart, Norbert Breidor in Aachen, and J\"urgen Mei\ss\-burger
+in J\"ulich). Especially the last one personally engaged a lot to
+establish a practicable way in J\"ulich.
+
+As we are just talking about the ZAM: Though Wolfgang E. Nagel is not
+personally involved into AS, he is at least my boss and always puts
+at least four eyes on what I am doing. Regarding AS, there seems to
+be at least one that smiles...
+
+A program like AS cannot be done without appropriate data books and
+documentation. I received information from an enormous amount of
+people, ranging from tips up to complete data books. An enumeration
+follows (as stated before, without guarantee for completelessness!):
+
+Ernst Ahlers, Charles Altmann, Rolf Buchholz, Bernd Casimir,
+Gunther Ewald, Stephan Hruschka, Peter Kliegelh\"ofer, Ulf Meinke,
+Matthias Paul, Norbert Rosch, Steffen Schmid, Leonhard Schneider,
+Ernst Schwab, Michael Schwingen, Oliver Sellke, Christian Stelter,
+Oliver Thamm, Thorsten Thiele.
+
+...and an ironic ''thank you'' to Rolf-Dieter-Klein and Tobias Thiel who
+demonstrated with their ASM68K how one should \bb{not} do it and thereby
+indirectly gave me the impulse to write something better!
+
+I did not entirely write AS on my own. AS contains the OverXMS
+routines from Wilbert van Leijen which can move the overlay modules
+into the extended memory. A really nice library, easy to use without
+problems!
+
+The TMS320C2x/5x code generators and the file \tty{STDDEF2x.INC} come
+from Thomas Sailer, ETH Zurich. It's surprising, he only needed one
+weekend to understand my coding and to implement the new code generator.
+Either that was a long nightshift or I am slowly getting old...
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Changes since Version 1.3}
+
+\begin{itemize}
+\item{version 1.31:
+ \begin{itemize}
+ \item{additional MCS-51 processor type 80515. The number
+ is again only stored by the assembler. The file
+ \tty{STDDEF51.INC} was extended by the necessary SFRs.
+ \bb{CAUTION!} Some of the 80515 SFRs have moved to other
+ addresses!}
+ \item{additional support for the Z80 processor;}
+ \item{faster 680x0 code generator.}
+ \end{itemize}}
+\item{version 1.32:
+ \begin{itemize}
+ \item{syntax for zero page addresses for the 65xx family
+ was changed from \tty{addr.z} to \tty{$<$addr} (similar to 68xx);}
+ \item{additional support for the 6800, 6805, 6301, and
+ 6811 processors;}
+ \item{the 8051 part now also understands \tty{DJNZ, PUSH}, and
+ \tty{POP} (sorry);}
+ \item{the assembly listing now not also list the symbols
+ but also the macros that have been defined;}
+ \item{additional instructions \tty{IFDEF/IFNDEF} for conditional
+ assembly based on the existence of a symbol;}
+ \item{additional instructions \tty{PHASE/DEPHASE} to support code
+ that shall be moved at runtime to a different address;}
+ \item{additional instructions \tty{WARNING, ERROR}, and \tty{FATAL} to print
+ user-defined error messages;}
+ \item{the file \tty{STDDEF51.INC} additionally contains the macro
+ \tty{USING} to simplify working with the MCS-51's register
+ banks;}
+ \item{command line option \tty{u} to print segment usage;}
+ \end{itemize}}
+\item{version 1.33:
+ \begin{itemize}
+ \item{additionally supports the 6809 processor;}
+ \item{added string variables;}
+ \item{The instructions \tty{TITLE, PRTINIT, PRTEXIT, ERROR},
+ \tty{WARNING}, and \tty{FATAL} now expect a string expression.
+ Constants therefore now have to be enclosed in
+ '' instead of ' characters. This is also true
+ for \tty{DB}, \tty{DC.B}, and \tty{BYT};}
+ \item{additional instruction \tty{ALIGN} to align the program
+ counter for Intel processors;}
+ \item{additional instruction \tty{LISTING} to turn the generation
+ of an assembly listing on or off;}
+ \item{additional instruction \tty{CHARSET} for user-defined
+ character sets.}
+ \end{itemize}}
+\item{version 1.34:
+ \begin{itemize}
+ \item{the second pass is now omitted if there were errors
+ in the first pass;}
+ \item{additional predefined symbol \tty{VERSION} that contains
+ the version number of AS;}
+ \item{additional instruction \tty{MESSAGE} to generate additional
+ messages under program control;}
+ \item{formula parser is now accessible via string constants;}
+ \item{if an error in a macro occurs, additionally the line
+ number in the macro itself is shown;}
+ \item{additional function \tty{UPSTRING} to convert a string to
+ all upper-case.}
+ \end{itemize}}
+\item{version 1.35:
+ \begin{itemize}
+ \item{additional function \tty{TOUPPER} to convert a single
+ character to upper case;}
+ \item{additional instruction \tty{FUNCTION} for user-defined
+ functions;}
+ \item{additional command line option \tty{D} to define symbols
+ from outside;}
+ \item{the environment variable \tty{ASCMD} for commonly used
+ command line options was introduced;}
+ \item{the program will additionally be checked for double
+ usage of memory areas if the u option is enabled;}
+ \item{additional command line option \tty{C} to generate a cross
+ reference list.}
+ \end{itemize}}
+\item{version 1.36:
+ \begin{itemize}
+ \item{additionally supports the PIC16C5x and PIC17C4x
+ processor families;}
+ \item{the assembly listing additionally shows the nesting
+ depth of include files;}
+ \item{the cross reference list additionally shows the
+ definition point of a symbol;}
+ \item{additional command line option \tty{A} to force a more
+ compact layout of the symbol table.}
+ \end{itemize}}
+\item{version 1.37:
+ \begin{itemize}
+ \item{additionally supports the processors 8086, 80186,
+ V30, V35, 8087, and Z180;}
+ \item{additional instructions \tty{SAVE} and \tty{RESTORE} for an
+ easier switching of some flags;}
+ \item{additional operators for logical shifts and bit
+ mirroring;}
+ \item{command line options may now be negated with a
+ plus sign;}
+ \item{additional filter AS2MSG for a more comfortable
+ work with AS under Turbo-Pascal 7.0;}
+ \item{\tty{ELSEIF} now may have an argument for construction
+ of \tty{IF\--THEN\--ELSE} ladders;}
+ \item{additional \tty{CASE} construct for a more comfortable
+ conditional assembly;}
+ \item{user-defined functions now may have more than one
+ argument;}
+ \item{P2HEX can now additionally generate hex files in
+ a format suitable for 65xx processors;}
+ \item{BIND, P2HEX, and P2BIN now have the same scheme
+ for command line processing like AS;}
+ \item{additional switch \tty{i} for P2HEX to select one out
+ three possibilities for the termination record;}
+ \item{additional functions \tty{ABS} and \tty{SGN};}
+ \item{additional predefined symbols \tty{MOMFILE} and \tty{MOMLINE};}
+ \item{additional option to print extended error messages;}
+ \item{additional instruction \tty{IFUSED} and \tty{IFNUSED} to check
+ whether a symbol has been used so far;}
+ \item{The environment variables \tty{ASCMD, BINDCMD} etc. now
+ optionally may contain the name of a file that
+ provides more space for options;}
+ \item{P2HEX can now generate the hex formats specified
+ by Microchip (p4);}
+ \item{a page length specification of 0 now allows to
+ suppress automatic formfeeds in the assembly listing
+ completely (p4);}
+ \item{symbols defined in the command line now may be
+ assigned an arbitrary value (p5).}
+ \end{itemize}}
+\item{version 1.38:
+ \begin{itemize}
+ \item{changed operation to multipass mode. This enables
+ AS to generate optimal code even in case of forward
+ references;}
+ \item{the 8051 part now also knows the generic \tty{JMP} and
+ \tty{CALL} instructions;}
+ \item{additionally supports the Toshiba TLCS-900 series
+ (p1);}
+ \item{additional instruction \tty{ASSUME} to inform the assembler
+ about the 8086's segment register contents (p2);}
+ \item{additionally supports the ST6 series from
+ SGS-Thomson (p2);}
+ \item{..and the 3201x signal processors from Texas
+ Instruments (p2);}
+ \item{additional option \tty{F} for P2HEX to override the
+ automatic format selection (p2);}
+ \item{P2BIN now can automatically set the start resp.
+ stop address of the address window by specifying
+ dollar signs (p2);}
+ \item{the 8048 code generator now also knows the 8041/42
+ instruction extensions (p2);}
+ \item{additionally supports the Z8 microcontrollers (p3).}
+ \end{itemize}}
+\item{version 1.39:
+ \begin{itemize}
+ \item{additional opportunity to define sections and local
+ symbols;}
+ \item{additional command line switch \tty{h} to force hexadecimal
+ numbers to use lowercase;}
+ \item{additional predefined symbol \tty{MOMPASS} to read the
+ number of the currently running pass;}
+ \item{additional command line switch \tty{t} to disable
+ individual parts of the assembly listing;}
+ \item{additionally knows the L variant of the TLCS-900
+ series and the MELPS-7700 series from Mitsubishi
+ (p1);}
+ \item{P2HEX now also accepts dollar signs as start resp.
+ stop address (p2);}
+ \item{additionally supports the TLCS-90 family from
+ Toshiba (p2);}
+ \item{P2HEX now also can output data in Tektronix and
+ 16 bit Intel Hex format (p2);}
+ \item{P2HEX now prints warnings for address overflows
+ (p2);}
+ \item{additional include file \tty{STDDEF96.INC} with address
+ definitions for the TLCS-900 series (p3);}
+ \item{additional instruction \tty{READ} to allow interactive
+ input of values during assembly (p3);}
+ \item{error messages are written to the STDERR channel
+ instead of standard output (p3);}
+ \item{the \tty{STOP} instruction missing for the 6811 is now
+ available (scusi, p3);}
+ \item{additionally supports the $\mu$PD78(C)1x family from
+ NEC (p3);}
+ \item{additionally supports the PIC16C84 from NEC (p3);}
+ \item{additional command line switch \tty{E} to redirect error
+ messages to a file (p3);}
+ \item{The MELPS-7700's 'idol' 65816 is now also available
+ (p4);}
+ \item{the ST6 pseudo instruction \tty{ROMWIN} has been removed
+ was integrated into the \tty{ASSUME} instruction (p4);}
+ \item{additionally supports the 6804 from SGS-Thomson (p4);}
+ \item{via the \tty{NOEXPORT} option in a macro definition, it is
+ now possible to define individually for every macro
+ whether it shall appear in the \tty{MAC} file or not (p4);}
+ \item{the meaning of \tty{MACEXP} regarding the expansion of
+ macros has changed slightly due to the additional
+ \tty{NOEXPAND} option in the macro definition (p4);}
+ \item{The additional \tty{GLOBAL} option in the macro definition
+ now additionally allows to define macros that are
+ uniquely identified by their section name (p4).}
+ \end{itemize}}
+\item{version 1.40:
+ \begin{itemize}
+ \item{additionally supports the DSP56000 from Motorola;}
+ \item{P2BIN can now also extract the lower resp. upper
+ half of a 32-bit word;}
+ \item{additionally supports the TLCS-870 and TLCS-47
+ families from Toshiba (p1);}
+ \item{a prefixed \tty{!} now allows to reach machine instructions
+ hidden by a macro (p1);}
+ \item{the \tty{GLOBAL} instruction now allows to export symbols
+ in a qualified style (p1);}
+ \item{the additional \tty{r} command line switch now allows to
+ print a list of constructs that forced additional
+ passes (p1);}
+ \item{it is now possible to omit an argument to the \tty{E}
+ command line option; AS will then choose a fitting
+ default (p1);}
+ \item{the \tty{t} command line option now allows to suppress
+ line numbering in the assembly listing (p1);}
+ \item{escape sequences may now also be used in ASCII style
+ integer constants (p1);}
+ \item{the additional pseudo instruction \tty{PADDING} now allows
+ to enable or disable the insertion of padding bytes
+ in 680x0 mode (p2);}
+ \item{\tty{ALIGN} is now a valid instruction for all targets
+ (p2);}
+ \item{additionally knows the PIC16C64's SFRs (p2);}
+ \item{additionally supports the 8096 from Intel (p2);}
+ \item{\tty{DC} additionally allows to specify a repetition factor
+ (r3);}
+ \item{additionally supports the TMS320C2x family from Texas
+ Instruments (implementation done by Thomas Sailer, ETH
+ Zurich, r3); P2HEX has been extended appropriately;}
+ \item{an equation sign may be used instead of \tty{EQU} (r3);}
+ \item{additional \tty{ENUM} instruction to define enumerations
+ (r3);}
+ \item{\tty{END} now has a real effect (r3);}
+ \item{additional command line switch \tty{n} to get the internal
+ error numbers in addition to the error messages (r3);}
+ \item{additionally supports the TLCS-9000 series from
+ Toshiba (r4);}
+ \item{additionally supports the TMS370xxx series from Texas
+ Instruments, including a new \tty{DBIT} pseudo instruction
+ (r5);}
+ \item{additionally knows the DS80C320's SFR's (r5);}
+ \item{the macro processor is now also able to include files
+ from within macros. This required to modify the
+ format of error messages slightly. If you use
+ AS2MSG, replace it with the new version! (r5)}
+ \item{additionally supports the 80C166 from Siemens (r5);}
+ \item{additional \tty{VAL} function to evaluate string
+ expressions (r5);}
+ \item{it is now possible to construct symbol names with the
+ help of string expressions enclosed in braces (r5);}
+ \item{additionally knows the 80C167's peculiarities (r6);}
+ \item{the MELPS740's special page addressing mode is now
+ supported (r6);}
+ \item{it is now possible to explicitly reference a symbol
+ from a certain section by appending its name enclosed
+ in brackets. The construction with an \tty{@} sign has
+ been removed! (r6)}
+ \item{additionally supports the MELPS-4500 series from
+ Mitsubishi (r7);}
+ \item{additionally supports H8/300 and H8/300H series from
+ Hitachi (r7);}
+ \item{settings made with \tty{LISTING} resp. \tty{MACEXP} may now be
+ read back from predefined symbols with the same names
+ (r7);}
+ \item{additionally supports the TMS320C3x series from Texas
+ Instruments (r8);}
+ \item{additionally supports the SH7000 from Hitachi (r8);}
+ \item{the Z80 part has been extended to also support the
+ Z380 (r9);}
+ \item{the 68K part has been extended to know the
+ differences of the 683xx micro controllers (r9);}
+ \item{a label not any more has to be placed in the first
+ row if it is marked with a double dot (r9);}
+ \item{additionally supports the 75K0 series from NEC (r9);}
+ \item{the additional command line option o allows to set
+ a user-defined name for the code file (r9);}
+ \item{the \verb!~~! operator has been moved to a bit more senseful
+ ranking (r9);}
+ \item{\tty{ASSUME} now also knows the 6809's DPR register and its
+ implications (pardon, r9);}
+ \item{the 6809 part now also knows the 6309's secret
+ extensions (r9);}
+ \item{binary constants now also may be written in a C-like
+ notation (r9);}
+ \end{itemize}}
+\item{version 1.41:
+ \begin{itemize}
+ \item{the new predefined symbol \tty{MOMSEGMENT} allows to
+ inquire the currently active segment;}
+ \item{\tty{:=} is now allowed as a short form for \tty{SET/EVAL};}
+ \item{the new command line switch \tty{q} allows to force a
+ ''silent'' assembly;}
+ \item{the key word \tty{PARENT} to reference the parent section
+ has been extended by \tty{PARENT0..PARENT9};}
+ \item{the PowerPC part has been extended by the
+ microcontroller versions MPC505 and PPC403;}
+ \item{symbols defined with \tty{SET} or \tty{EQU} may now be assigned
+ to a certain segment (r1);}
+ \item{the SH7000 part now also knows the SH7600's
+ extensions (and should compute correct
+ displacements...) (r1);}
+ \item{the 65XX part now differentiates between the 65C02
+ and 65SC02 (r1);}
+ \item{additionally to the symbol \tty{MOMCPU}, there is now also
+ a string symbol \tty{MOMCPUNAME} that contains the
+ processor's full name (r1);}
+ \item{P2HEX now also knows the 32-bit variant of the Intel
+ hex format (r1);}
+ \item{additionally knows the 87C750's limitations (r2);}
+ \item{the internal numbers for fatal errors have been moved
+ to the area starting at 10000, making more space for
+ normal error messages (r2);}
+ \item{unused symbols are now marked with a star in the
+ symbol table (r2);}
+ \item{additionally supports the 29K family from AMD (r2);}
+ \item{additionally supports the M16 family from Mitsubishi
+ (r2);}
+ \item{additionally supports the H8/500 family from Hitachi
+ (r3);}
+ \item{the number of data bytes printed per line by P2HEX
+ can now be modified (r3);}
+ \item{the number of the pass that starts to output warnings
+ created by the \tty{r} command line switch is now variable
+ (r3);}
+ \item{the macro processor now knows a \tty{WHILE} statement that
+ allows to repeat a piece of code a variable number of
+ times (r3);}
+ \item{the \tty{PAGE} instruction now also allows to set the line
+ with of the assembly listing (r3);}
+ \item{CPU aliases may now be defined to define new pseudo
+ processor devices (r3);}
+ \item{additionally supports the MCS/251 family from Intel
+ (r3);}
+ \item{if the cross reference list has been enabled, the
+ place of the first definition is given for double
+ definitions of symbols (r3);}
+ \item{additionally supports the TMS320C5x family from Texas
+ Instruments (implementation done by Thomas Sailer,
+ ETH Zurich, r3);}
+ \item{the OS/2 version should now also correctly work with
+ long file names. If one doesn't check every s**t
+ personally... (r3);}
+ \item{the new pseudo instruction \tty{BIGENDIAN} now allows to
+ select in MCS-51/251 mode whether constants should
+ be stored in big endian or little endian format (r3);}
+ \item{the 680x0 part now differentiates between the full
+ and reduced MMU instruction set; a manual toggle can
+ be done via the \tty{FULLPMMU} instruction (r3);}
+ \item{the new command line option \tty{I} allows to print a list
+ of all include files paired with their nesting level
+ (r3);}
+ \item{additionally supports the 68HC16 family from Motorola
+ (r3);}
+ \item{the \tty{END} statement now optionally accepts an argument
+ as entry point for the program (r3);}
+ \item{P2BIN and P2HEX now allow to move the contents of a
+ code file to a different address (r4);}
+ \item{comments appended to a \tty{SHARED} instruction are now
+ copied to the share file (r4);}
+ \item{additionally supports the 68HC12 family from Motorola
+ (r4);}
+ \item{additionally supports the XA family from Philips
+ (r4);}
+ \item{additionally supports the 68HC08 family from Motorola
+ (r4);}
+ \item{additionally supports the AVR family from Atmel (r4);}
+ \item{to achieve better compatibility to the AS11 from
+ Motorola, the pseudo instructions \tty{FCB, FDB, FCC}, and
+ \tty{RMB} were added (r5);}
+ \item{additionally supports the M16C from Mitsubishi (r5);}
+ \item{additionally supports the COP8 from National
+ Semiconductor (r5);}
+ \item{additional instructions \tty{IFB} and \tty{IFNB} for conditional
+ assembly (r5);}
+ \item{the new \tty{EXITM} instruction now allows to terminate a
+ macro expansion (r5);}
+ \item{additionally supports the MSP430 from Texas
+ Instruments (r5);}
+ \item{\tty{LISTING} now knows the additional variants
+ \tty{NOSKIPPED} and \tty{PURECODE} to remove code that
+ was not assembled from the listing (r5);}
+ \item{additionally supports the 78K0 family from NEC (r5);}
+ \item{\tty{BIGENDIAN} is now also available in PowerPC mode
+ (r5);}
+ \item{additional \tty{BINCLUDE} instruction to include binary
+ files (r5);}
+ \item{additional \tty{TOLOWER} and \tty{LOWSTRING} functions to convert
+ characters to lower case (r5);}
+ \item{it is now possible to store data in other segments
+ than \tty{CODE}. The file format has been extended
+ appropriately (r5);}
+ \item{the \tty{DS} instruction to reserve memory areas is now
+ also available in Intel mode (r5);}
+ \item{the \tty{U} command line switch now allows to switch AS
+ into a case sensitive mode that differentiates
+ between upper and lower case in the names of symbols,
+ user-defined functions, macros, macro parameters, and
+ sections (r5);}
+ \item{\tty{SFRB} now also knows the mapping rules for bit
+ addresses in the RAM areas; warnings are generated
+ for addresses that are not bit addressable (r5);}
+ \item{additional instructions \tty{PUSHV} and \tty{POPV} to save symbol
+ values temporarily (r5);}
+ \item{additional functions \tty{BITCNT, FIRSTBIT, LASTBIT}, and
+ \tty{BITPOS} for bit processing (r5);}
+ \item{the 68360 is now also known as a member of the CPU32
+ processors (r5);}
+ \item{additionally supports the ST9 family from SGS-Thomson
+ (r6);}
+ \item{additionally supports the SC/MP from National
+ Semiconductor (r6);}
+ \item{additionally supports the TMS70Cxx family from Texas
+ Instruments (r6);}
+ \item{additionally supports the TMS9900 family from Texas
+ Instruments (r6);}
+ \item{additionally knows the 80296's instruction set
+ extensions (r6);}
+ \item{the supported number of Z8 derivatives has been
+ extended (r6);}
+ \item{additionally knows the 80C504's mask defects (r6);}
+ \item{additional register definition file for Siemens' C50x
+ processors (r6);}
+ \item{additionally supports the ST7 family from SGS-Thomson
+ (r6);}
+ \item{the Tntel pseudo instructions for data disposal are
+ now also valid for the 65816/MELPS-7700 (r6);}
+ \item{for the 65816/MELPS-7700, the address length may now
+ be set explicitly via prefixes (r6);}
+ \item{additionally supports the 8X30x family from Signetics
+ (r6);}
+ \item{from now on, \tty{PADDING} is enabled by default only
+ for the 680x0 family (r7);}
+ \item{the new predefined symbol \tty{ARCHITECTURE} can now be
+ used to query the platform AS was compiled for (r7);}
+ \item{additional statements \tty{STRUCT} and \tty{ENDSTRUCT}
+ to define data structures (r7);}
+ \item{hex and object files for the AVR tools may now be generated
+ directly (r7);}
+ \item{\tty{MOVEC} now also knows the 68040's control registers
+ (r7);}
+ \item{additional \tty{STRLEN} function to calculate the length
+ of a string (r7);}
+ \item{additional ability to define register symbols (r7 currently
+ only Atmel AVR);}
+ \item{additionally knows the 6502's undocumented instructions (r7);}
+ \item{P2HEX and P2BIN now optionally can erase the input files
+ automatically (r7);}
+ \item{P2BIN can additionally prepend the entry address to the
+ resulting image (r7);}
+ \item{additionally supports the ColdFire family from Motorola as a
+ variation of the 680x0 core (r7);}
+ \item{\tty{BYT/FCB, ADR/FDB}, and \tty{FCC} now also allow the
+ repetition factor known from DC (r7);}
+ \item{additionally supports Motorola's M*Core (r7);}
+ \item{the SH7000 part now also knows the SH7700's
+ extensions (r7);}
+ \item{the 680x0 part now also knows the 68040's additional
+ instructions (r7);}
+ \item{the 56K part now also knows the instruction set extensions
+ up to the 56300 (r7).}
+ \item{the new \tty{CODEPAGE} statement now allows to keep several
+ character sets in parallel (r8);}
+ \item{The argument variations for \tty{CHARSET} have been extended
+ (r8);}
+ \item{New string functions \tty{SUBSTR} and \tty{STRSTR} (r8);}
+ \item{additional \tty{IRPC} statement in the macro processor (r8);}
+ \item{additional \tty{RADIX} statement to set the default numbering
+ system for integer constants (r8);}
+ \item{instead of {\tt ELSEIF}, it is now valid to simply write {\tt
+ ELSE} (r8);}
+ \item{$==$ may be used as equality operator instead of $=$ (r8);}
+ \item{\tty{BRANCHEXT} for the Philips XA now allows to automatically
+ extend the reach of short branches (r8);}
+ \item{debug output is now also possible in NoICE format (r8);}
+ \item{additionally supports the i960 family from Intel (r8);}
+ \item{additionally supports the $\mu$PD7720/7725 signal processors
+ from NEC (r8);}
+ \item{additionally supports the $\mu$PD77230 signal processor from
+ NEC (r8);}
+ \item{additionally supports the SYM53C8xx SCSI processors from
+ Symbios Logic (r8);}
+ \item{additionally supports the 4004 from Intel (r8);}
+ \item{additionally supports the SC14xxx series of National (r8);}
+ \item{additionally supports the instruction extensions of the PPC
+ 403GC (r8);}
+ \item{additional command line option {\tt cpu} to set the default
+ target processor (r8);}
+ \item{key files now also may be referenced from the command line
+ (r8);}
+ \item{additional command line option {\tt shareout} to set the
+ output file for SHARED definitions (r8);}
+ \item{new statement {\tt WRAPMODE} to support AVR processors with
+ a shortened program counter (r8);}
+ \item{additionally supports the C20x instruction subset in the C5x
+ part (r8);}
+ \item{hexadecimal address specifications for the tools now may also
+ be made in C notation (r8);}
+ \item{the numbering system for integer results in \verb!\{...}!
+ expressions is now configurable via \tty{OUTRADIX} (r8);}
+ \item{the register syntax for 4004 register pairs has been corrected
+ (r8);}
+ \item{additionally supports the F$^{2}$MC8L family from Fujitsu
+ (r8);}
+ \item{P2HEX now allows to set the minimum address length for S
+ record addresses (r8);}
+ \item{additionally supports the ACE family from Fairchild (r8);}
+ \item{{\tt REG} is now also allowed for PowerPCs (r8);}
+ \item{additional switch in P2HEX to relocate all addresses (r8);}
+ \item{The switch \tty{x} now additionally allows a second level
+ of detailness to print the source line in question (r8).}
+ \end{itemize}}
+\end{itemize}
+
+%%===========================================================================
+
+\cleardoublepage
+\chapter{Hints for the AS Source Code}
+\label{ChapSource}
+
+As I already mentioned in the introduction, I release the source code of
+AS on request. The following shall give a few hints to their usage.
+
+%%---------------------------------------------------------------------------
+
+\section{Language Preliminaries}
+
+In the beginning, AS was a program written in Turbo-Pascal. This was
+roughly at the end of the eighties, and there were a couple of reasons for
+this choice: First, I was much more used to it than to any C compiler, and
+compared to Turbo Pascal's IDE, all DOS-based C compilers were just
+crawling along. In the beginning of 1997 however, it became clear that
+things had changed: One factor was that Borland had decided to let its
+confident DOS developers down (once again, explicitly no 'thank you', you
+boneheads from Borland!) and replaced version 7.0 of Borland Pascal with
+something called 'Delphi', which is probably a wonderful tool to develop
+Windows programs which consist of 90\% user interface and accidentaly a
+little bit of content, however completely useless for command-line driven
+programs like AS. Furthermore, my focus of operating systems had made a
+clear move towards Unix, and I probably could have waited arbitrarily long
+for a Borland Pascal for Linux (to all those remarking now that Borland
+would be working on something like that: this is {\em Vapourware}, don\'t
+believe them anything until you can go into a shop and actually buy it!).
+It was therefore clear that C was the way to go.
+
+After this eperience what results the usage of 'island systems' may have,
+I put a big emphasize on portability while doing the translation to C;
+however, since AS for example deals with binary data in an exactly format
+and uses operating systen-specific functions at some places which may need
+adaptions when one compliles AS the first time for a new platform.
+
+AS is tailored for a C compiler that conforms to the ANSI C standard; C++
+is explicitly not required. If you are still using a compiler conforming
+to the outdated Kernighan\&Ritchie standard, you should consider getting a
+newer compiler: The ANSI C standard has been fixed in 1989 and there
+should be an ANSI C compiler for every contemporary platform, maybe by
+using the old compiler to build GNU-C. Though there are some switches in
+the source code to bring it nearer to K\&R, this is not an officially
+supported feature which I only use internally to support a quite antique
+Unix. Everything left to say about K\&R is located in the file {\tt
+README.KR}.
+
+The inclusion of some additional features not present in the Pascal
+version (e.g. dynamically loadable message files, test suite, automatic
+generation of the documentation from {\em one} source format) has made the
+source tree substantially more complicated. I will attempt to unwire
+everything step by step:
+
+%%---------------------------------------------------------------------------
+
+\section{Capsuling System dependencies}
+
+As I already mentioned, As has been tailored to provide maximum platform
+independence and portability (at least I believe so...). This means
+packing all platform dependencies into as few files as possible. I will
+describe these files now, and this section is the first one because it is
+probably one of the most important:
+
+The Build of all components of AS takes place via a central {\tt
+Makefile}. To make it work, it has to be accompanied by a fitting {\tt
+Makefile.def} that gives the platform dependent settings like compiler
+flags. The subdirectory {\tt Makefile.def-samples} contains a couple of
+includes that work for widespread platforms (but which need not be
+optimal...). In case your platform is not among them, you may take the
+file {\tt Makefile.def.tmpl} as a starting point (and send me the
+result!).
+
+A further component to capure system dependencies is the file {\tt
+sysdefs.h}. Practically all compilers predefine a couple of preprocessor
+symbols that describe the target processor and the used operating system.
+For example, on a Sun Sparc under Solaris equipped with the GNU compiler,
+the symbols \verb!__sparc! and \verb!__SVR4!. {\tt sysdefs.h} exploits
+these symbols to provide a homogeneous environment for the remaining,
+system-independent files. Especially, this covers integer datatypes of a
+specific length, but it may also include the (re)definition of C functions
+which are not present or non-standard-like on a specific platform. It's
+best to read this files yourself if you like to know which things may
+occur... Generally, the \verb!#ifdef! statement are ordered in two
+levels: First, a specific processor platform is selected, the the
+operating systems are sorted out in such a section.
+
+If you port AS to a new platform, you have to find two symbols typical for
+this platform and extend {\tt sysdefs.h} accordingly. Once again, I'm
+interested in the result...
+
+%%---------------------------------------------------------------------------
+
+\section{System-Independent Files}
+
+...represent the largest part of all modules. Describing all functions in
+detail is beyond the scope of this description (those who want to know
+more probably start studying the sources, my programming style isn't that
+horrible either...), which is why I can only give a short list at this
+place with all modules their function:
+
+\subsection{Modules Used by AS}
+
+\subsubsection{as.c}
+
+This file is AS's root: it contains the {\em main()} function of AS, the
+processing of all command line options, the overall control of all passes
+and parts of the macro processor.
+
+\subsubsection{asmallg.c}
+
+This module processes all statements defined for all processor targets,
+e.g. \tty{EQU} and \tty{ORG}. The \tty{CPU} pseudo-op used to switch
+among different processor targets is also located here.
+
+\subsubsection{asmcode.c}
+
+This module contains the bookkeping needed for the code output file. It
+exports an interface that allows to open and close a code file and offers
+functions to write code to (or take it back from) the file. An important
+job of this module is to buffer the write process, which speeds up
+execution by writing the code in larger blocks.
+
+\subsubsection{asmdebug.c}
+
+AS can optionally generate debug information for other tools like
+simulators or debuggers, allowing a backward reference to the source code.
+They get collected in this module and can be output after assembly in one
+of several formats.
+
+\subsubsection{asmdef.c}
+
+This modules only contains declarations of constants used in different
+places and global variables.
+
+\subsubsection{asmfnums.c}
+
+AS assigns internally assigns incrementing numbers for each used source
+file. These numbers are used for quick referencing. Assignment of
+numbers and the conversion between names and numbers takes place here.
+
+\subsubsection{asmif.c}
+
+Here ara ll routines located controlling conditional assembly. The most
+important exported variable is a flag called \tty{IfAsm} which controls
+whether code generation is currently turned on or off.
+
+\subsubsection{asminclist.c}
+
+This module holds the definition of the list stucture that allows AS to
+print the nesting of include files to the assembly list file.
+
+\subsubsection{asmitree.c}
+
+When searching for the mnemonic used in a line of code, a simple linear
+comparison with all available machine instructions (as it is still done in
+most code generators, for reasons of simplicity and laziness) is not
+necessary the most effective method. This module defines two improved
+structures (binary tree and hash table) which provide a more efficient
+search and are destined to replace the simple linear search on a
+step-by-step basis...priorities as needed...
+
+\subsubsection{asmmac.c}
+
+Routines to store and execute macro constructs are located in this module.
+The real macro processor is (as already mentioned) in {\tt as.c}.
+
+\subsubsection{asmpars.c}
+
+Here we really go into the innards: This module stores the symbol tables
+(global and local) in two binary trees. Further more, there is a quite
+large procedure {\tt EvalExpression} which analyzes and evaluates a (formula)
+expression. The procedure returns the result (integer, floating point, or
+string) in a varaint record. However, to evaluate expressions during code
+generation, one should better use the functions \tty{EvalIntExpression,
+EvalFloatExpression}, and \tty{EvalStringExpression}. Modifications for
+tha esake of adding new target processors are unnecessary in this modules
+and should be done with extreme care, since you are touching something
+like 'AS's roots'.
+
+\subsubsection{asmsub.c}
+
+This module collects a couple of commonly used subroutines which primarily
+deal with error handling and 'advanced' string processing.
+
+\subsubsection{bpemu.c}
+
+As already mentioned at the beginning, AS originally was a program written
+in Borland Pascal. For some intrinsic functions of the compiler, it was
+simpler to emulate those than to touch all places in the source code where
+they are used. Well...
+
+\subsubsection{chunks.c}
+
+This module defines a data type to deal with a list of address ranges.
+This functionality is needed by AS for allocation lists; furthermore,
+P2BIN and P2HEX use such lists to warn about overlaps.
+
+\subsubsection{cmdarg.c}
+
+This module implements the overall mechanism of command line arguments.
+It needs a specification of allowed arguments, splits the command line and
+triggers the appropriate callbacks. In detail, the mechanism includes
+the following:
+\begin{itemize}
+\item{Processing of arguments located in an environment variable or
+ a corresponding file;}
+\item{Return of a set describing which command line arguments have not
+ been processed;}
+\item{A backdoor for situations when an overlaying IDE converts the passed
+ command line completely into upper or lower case.}
+\end{itemize}
+
+\subsubsection{codepseudo.c}
+
+You will find at this place pseudo instructions that are used by
+a subset of code generators. On the one hand, this is the Intel group of
+\tty{DB..DT}, and on the other hand their counterparts for 8/16 bit CPUs
+from Motorola or Rockwell. Someone who wants to extend AS by a
+processor fitting into one of these groups can get the biggest part
+of the necessary pseudo instructions with one call to this module.
+
+\subsubsection{codevars.c}
+
+For reasons of memory efficiency, some variables commonly used by diverse
+code generators.
+
+\subsubsection{endian.c}
+
+Yet another bit of machine dependence, however one you do not have to
+spend attention on: This module automatically checks at startup whether
+a host machine is little or big endian. Furthermore, checks are made if
+the type definitions made for integer variables in {\tt sysdefs.h} really
+result in the correct lengths.
+
+\subsubsection{headids.c}
+
+At this place, all processor families supported by AS are collected with
+their header IDs (see chapter \ref{SectCodeFormat}) and the output format
+to be used by default by P2HEX. The target of this table is to centralize
+the addition of a new processor as most as possible, i.e. in contrast to
+earlier versions of AS, no further modifications of tool sources are
+necessary.
+
+\subsubsection{ioerrs.c}
+
+The conversion from error numbers to clear text messages is located here.
+I hope I'll never hit a system that does not define the numbers as macros,
+because I would have to rewrite this module completely...
+
+\subsubsection{nlmessages.c}
+
+The C version of AS reads all messages from files at runtime after the
+language to be used is clear. The format of message files is not a simple
+one, but instead a special compact and preindexed format that is generated
+at runtime by a program called 'rescomp' (we will talk about it later).
+This module is the counterpart to rescomp that reads the correct language
+part into a character field and offers functions to access the messages.
+
+\subsubsection{nls.c}
+
+This module checks which country-dependent settings (date and time format,
+country code) are present at runtime. Unfortunately, this is a highly
+operating system-dependend task, and currently, there are only three
+methods defines: The MS-DOS method, the OS/2 method and the typical Unix
+method via {\em locale} functions. For all other systems, there is
+unfortunately currently only \verb!NO_NLS! available...
+
+\subsubsection{stdhandl.c}
+
+On the one hand, here is a special open function located knowing the
+special strings {\tt !0...!2} as file names and creating duplicates of the
+standard file handles {\em stdin, stdout,} and {\em stderr}. On the other
+hand, investiagations are done whether the standard output has been
+redirected to a device or a file. On no-Unix systems, this unfortunately
+also incorporates some special operations.
+
+\subsubsection{stringlists.c}
+
+This is just a little 'hack' that defines routines to deal with linear
+lists of strings, which are needed e.g. in the macro processor of AS.
+
+\subsubsection{strutil.c}
+
+Some commonly needed string operations have found their home here.
+
+\subsubsection{version.c}
+
+The currently valid version is centrally stored here for AS and all other
+tools.
+
+\subsubsection{code????.c}
+
+These modules form the main part of AS: each module contains the code
+generator for a specific processor family.
+
+\subsection{Additional Modules for the Tools}
+
+\subsubsection{hex.c}
+
+A small module to convert integer numbers to hexadecimal strings. It's
+not absolutely needed in C any more (except for the conversion of {\em
+long long} variables, which unfortunately not all {\tt printf()}'s
+support), but it somehow survived the porting from Pascal to C.
+
+\subsubsection{p2bin.c}
+
+The sources of P2BIN.
+
+\subsubsection{p2hex.c}
+
+The sources of P2HEX.
+
+\subsubsection{pbind.c}
+
+The sources of BIND.
+
+\subsubsection{plist.c}
+
+The sources of PLIST.
+
+\subsubsection{toolutils.c}
+
+All subroutines needed by several tools are collected here, e.g. for
+reading of code files.
+
+\section{Modules Needed During the Build of AS}
+
+\subsubsection{a2k.c}
+
+This is a minimal filter converting ANSI C source files to
+Kernighan-Ritchie style. To be exact: only function heads are converted,
+even this only when they are roughly formatted like my programming style.
+Noone should therefore think this were a universal C parser!
+
+\subsubsection{addcr.c}
+
+A small filter needed during installation on DOS- or OS/2-systems. Since
+DOS and OS/2 use a CR/LF for a newline, inc ontrast to the single LF of
+Unix systems, all assembly include files provided with AS are sent through
+this filter during assembly.
+
+\subsubsection{bincmp.c}
+
+For DOS and OS/2, this module takes the task of the {\em cmp} command,
+i.e. the binary comparison of files during the test run. While this would
+principally be possible with the {\em comp} command provided with the OS,
+{\em bincmp} does not have any nasty interactive questions (which seem to
+be an adventure to get rid of...)
+
+\subsubsection{findhyphen.c}
+
+This is the submodule in {\em tex2doc} providing hyphenation of words.
+The algorithm used for this is shamelessly stolen from TeX.
+
+\subsubsection{grhyph.c}
+
+The definition of hyphenation rules for the german language.
+
+\subsubsection{rescomp.c}
+
+This is AS's 'resource compiler', i.e. the tool that converts a readable
+file with string resources into a fast, indexed format.
+
+\subsubsection{tex2doc.c}
+
+A tool that converts the LaTeX documentation of AS into an ASCII format.
+
+\subsubsection{tex2html.c}
+
+A tool that converts the LaTeX documentation of AS into an HTML document.
+
+\subsubsection{umlaut.c and unumlaut.c}
+
+These tiny programs convert national special characters between their
+coding in ISO8859-1 (all AS files use this format upon delivery) and their
+system-specific coding. Apart from a plain ASCII7 variant, there are
+currently the IBM character sets 437 and 850.
+
+\subsubsection{ushyph.c}
+
+The definition of hyphenation rules for the english language.
+
+%%---------------------------------------------------------------------------
+
+\section{Generation of Message Files}
+
+As already mentioned, the C source tree of AS uses a dynamic load
+principle for all (error) messages. In contrast to the Pasacl sources
+where all messages were bundled in an include file and compiled into the
+programs, this method eliminates the need to provide AS in multiple
+language variants; there is only one version which checks for the
+langugage to be used upon runtime and loads the corresponding component
+from the message files. Just to remind: Under DOS and OS/2, the {\tt
+COUNTRY} setting is queried, while under Unix, the environment variables
+{\tt LC\_MESSAGES, LC\_ALL,} and {\tt LANG} are checked.
+
+\subsection{Format of the Source Files}
+
+A source file for the message compiler {\em rescomp} usually has the
+suffix {\tt .res}. The message compiler generates one or two files from a
+source:
+\begin{itemize}
+\item{a binary file which is read at runtime by AS resp. its tools}
+\item{optionally one further C header file assigning an index number to
+ all messages. These index numbers in combination with an index
+ table in the binary file allow a fast access to to individual
+ messages at runtime.}
+\end{itemize}
+
+The source file for the message compiler is a pure ASCII file and can
+therefore be modified with any editor. It consists of a sequence of
+control commands with parameters. Empty lines and lines beginning with a
+semicolon are ignored. Inclusion of other files is possible via the {\tt
+Include} statement:
+\begin{verbatim}
+Include <Datei>
+\end{verbatim}
+
+The first two statements in every source file must be two statements
+describing the languages defined in the following. The more important one
+is {\tt Langs}, e.g.:
+\begin{verbatim}
+Langs DE(049) EN(001,061)
+\end{verbatim}
+describes that two languages will be defined in the rest of the file. The
+first one shall be used under Unix when the language has been set to {\tt
+DE} via environment variable. Similarly, It shall be used under DOS and
+OS/2 when the country code was set to 049. Similarly, the second set
+shall be used for the settings {\tt DE} resp. 061 or 001. While multiple
+'telephone numbers' may point to a single language, the assignment to a
+Unix language code is a one-to-one correspondence. This is no problem in
+practice since the {\tt LANG} variables Unix uses describe subversions via
+appendices, e.g.:
+\begin{verbatim}
+de.de
+de.ch
+en.us
+\end{verbatim}
+AS only compares the beginning of the strings and therefore still comes to
+the right decision.
+The {\tt Default} statement defines the language that shall be used if
+either no language has been set at all or a language is used that is not
+mentioned in the asrgument list of {\tt Langs}. This is typically the
+english language:
+\begin{verbatim}
+Default EN
+\end{verbatim}
+These definitions are followed by an arbitrary number of {\tt Message}
+statements, i.e. definitions of messages:
+\begin{verbatim}
+Message ErrName
+ ": Fehler "
+ ": error "
+\end{verbatim}
+In case {\em n} languages were announced via the {\tt Langs} statement,
+the message compiler takes {\bf exactly} the following {\em n} as the
+strings to be stored. It is therefore impossible to leave out certain
+languages for individual messages, and an empty line following the strings
+should in no way be misunderstood as an end marker for the list; inserted
+lines between statements only serve purposes of better readability. It is
+however allowed to split individual messages across multiple lines in the
+source file; all lines except for the last one have to be ended with a
+backslash as continuation character:
+\begin{verbatim}
+Message TestMessage2
+ "Dies ist eine" \
+ "zweizeilige Nachricht"
+ "This is a" \
+ "two-line message"
+\end{verbatim}
+As already mentioned, source files are pure ASCII files; national special
+characters may be placed in message texts (and the compiler will correctly
+pass them to the resulting file), a big disadvantage however is that such
+a file is not fully portable any more: in case it is ported to another
+system using a different coding for national special characters, the user
+will probably be confronted with strange characters at runtime...special
+character should therefore always be written via special sequences
+borrowed from HTML resp. SGML (see table \ref{TabSpecChars}). Linefeeds
+can be inserted into a line via \verb!\n!, similar to C.
+\begin{table*}[htb]
+\begin{center}\begin{tabular}{|l|l|}
+\hline
+Sequenz... & ergibt... \\
+\hline
+\hline
+\verb!&auml; &ouml; &uuml;! & "a "o "u (Umlaute)\\
+\verb!&Auml; &Ouml; &Uuml;! & "A "O "U \\
+\verb!&szlig;! & "s (scharfes s) \\
+\verb!&agrave; &egrave; &igrave; &ograve; &ugrave;! & \'a \'e \'i \'o \'u (Accent \\
+\verb!&Agrave; &Egrave; &Igrave; &Ograve; &Ugrave;! & \'A \'E \'I \'O \'U grave) \\
+\verb!&aacute; &eacute; &iacute; &oacute; &uacute;! & \`a \`e \`i \`o \`u (Accent \\
+\verb!&Aacute; &Eacute; &Iacute; &Oacute; &Uacute;! & \`A \`E \`I \`O \`I agiu) \\
+\verb!&acirc; &ecirc; &icirc; &ocirc; &ucirc;! & \^a \^e \^i \^o \^u (Accent \\
+\verb!&Acirc; &Ecirc; &Icirc; &Ocirc; &Ucirc;! & \^A \^E \^I \^O \^U circonflex) \\
+\verb!&ccedil; &Ccedil;! & \c{c} \c{C}(Cedilla) \\
+\verb!&ntilde; &Ntilde;! & \~n \~N \\
+\verb!&aring; &Aring;! & \aa \AA \\
+\verb!&aelig; &Aelig;! & \ae \AE \\
+\verb!&iquest; &iexcl;! & umgedrehtes ! oder ? \\
+\hline
+\end{tabular}\end{center}
+\caption{Sonderzeichenschreibweise des {\em rescomp}\label{TabSpecChars}}
+\end{table*}
+
+%%---------------------------------------------------------------------------
+
+\section{Creation of Documentation}
+
+A source distribution of AS contains this documentation in LaTeX format
+only. Other formats are created from this one automatically via tools
+provided with AS. One reason is to reduce the size of the source
+distribution, another reason is that changes in the documentation only
+have to be made once, avoiding inconsistencies.
+
+LaTex was chosen as the master format because...because...because it's
+been there all the time before. Additionally, TeX is almost arbitrarily
+portable and fits quite well to the demands of AS. A standard
+distribution therefore allows a nice printout on about any printer; for a
+conversion to an ASCII file that used to be part of earlier distributions,
+the converter {\em tex2doc} is included, additionally the converter {\em
+tex2html} allowing to put the manual into the Web.
+
+Generation of the documentation is started via a simple
+\begin{verbatim}
+make docs
+\end{verbatim}
+The two converters mentioned are be built first, then applied to the TeX
+documentation and finally, LaTeX itself is called. All this of course for
+all languages...
+
+%%---------------------------------------------------------------------------
+
+\section{Test Suite}
+
+Since AS deals with binary data of a precisely defined structure, it is
+naturally sensitive for system and compiler dependencies. To reach at
+least a minimum amount of secureness that everything went right during
+compilation, a set of test sources is provided in the subdirectory {\tt
+tests} that allows to test the freshly built assembler. These programs
+are primarily trimmed to find faults in the translation of the machine
+instruction set, which are commonplace when integer lenghts vary.
+Target-independent features like the macro processors or conditional
+assembly are only casually tested, since I assume that they work
+everywhere when they work for me...
+
+The test run is started via a simple {\em make test}. Each test program
+is assembled, converted to a binary file, and compared to a reference
+image. A test is considered to be passed if and only if the reference
+image and the newly generated one are identical on a bit-by-bit basis. At
+the end of the test, the assembly time for every test is printed (those
+who want may extend the file BENCHES with these results), accompanied with
+a success or failure message. Track down every error that occurs, even if
+it occurs in a processor target you are never going to use! It is always
+possible that this points to an error that may also come up for other
+targets, but by coincidence not in the test cases.
+
+%%---------------------------------------------------------------------------
+
+\section{Adding a New Target Processor}
+
+The probably most common reason to modify the source code of AS is to add
+a new target processor. Apart from adding the new module to the
+Makefile, there are few places in other modules that need a modification.
+The new module will do the rest by registering itself in the list of code
+generators. I will describe the needed steps in a cookbook style in the
+following sections:
+
+\subsubsection{Choosing the Processor's Name}
+
+The name chosen for the new processor has to fulfill two criterias:
+\begin{enumerate}
+\item{The name must not be already in use by another processor. If one
+ starts AS without any parameters, a list of the names already in
+ use will be printed.}
+\item{If the name shall appear completely in the symbol \tty{MOMCPU}, it may
+ not contain other letters than A..F (except right at the
+ beginning). The variable \tty{MOMCPUNAME} however will always report
+ the full name during assembly. Special characters are generally
+ disallowed, lowercase letters will be converted by the \tty{CPU}
+ command to uppercase letters and are therefore senseless in the
+ processor name.}
+\end{enumerate}
+
+The first step for registration is making an entry for the new processor
+(family) in the file {\tt headids.c}. As already mentioned, this file is
+also used by the tools and specifies the code ID assigned to a processor
+family, along with the default hex file format to be used. I would like
+to have some coordination before choosing the ID...
+
+\subsubsection{Definition of the Code Generator Module}
+
+The unit's name that shall be responsible for the new processor
+should bear at least some similarity to the processor's name (just
+for the sake of uniformity) and should be named in the style of
+\tty{code....}. The head with include statements is best taken from
+another existing code generator.
+
+Except for an initialization function that has to be called at the
+begginning of the {\tt main()} function in module {\tt as.c}, the new
+module neither has to export variables nor functions as the complete
+communication is done at runtime via indirect calls. They are simply done
+by a call to the function
+\tty{AddCPU} for each processor type that shall be treated by this unit:
+\begin{verbatim}
+ CPUxxxx:=AddCPU('XXXX',SwitchTo_xxxx);
+\end{verbatim}
+\tty{'XXXX'} is the name chosen for the processor which later must be used
+in assembler programs to switch AS to this target processor.
+\tty{SwitchTo\_xxxx} (abbreviated as the ''switcher'' in the following) is
+a procedure without parameters that is called by AS when the switch to the
+new processor actually takes place. \tty{AddCPU} delivers an integer
+value as result that serves as an internal ''handle'' for the new
+processor. The global variable \tty{MomCPU} always contains the handle of
+the target processor that is currently set. The value returned by
+\tty{AddCPU} should be stored in a private variable of type \tty{CPUVar}
+(called \tty{CPUxxxx} in the example above). In case a code generator
+module implements more than one processor (e.g. several processors of a
+family), the module can find out which instruction subset is currently
+allowed by comparing \tty{MomCPU} against the stored handles.
+
+The switcher's task is to ''reorganize'' AS for the new target
+processor. This is done by changing the values of several global
+variables:
+\begin{itemize}
+\item{\tty{ValidSegs}: Not all processors have all address spaces defined
+ by AS. This set defines which subset the \tty{SEGMENT} instruction
+ will enable for the currently active target processor. At least the
+ \tty{CODE} segment has to be enabled. The complete set of allowed
+ segments can be looked up the file \tty{fileformat.h} (\tty{Seg....}
+ constants).}
+\item{\tty{SegInits}: This array stores the initial program counter values
+ for the individual segments (i.e. the values the program counters
+ will initially take when there is no \tty{ORG} statement). There are
+ only a few exceptions (like logically separated address spaces
+ that physically overlap) which justify other initial values than
+ 0.}
+\item{\tty{Grans}: This array specifies the size of the smallest addressable
+ element in bytes for each segment, i.e. the size of an element
+ that increases an address by 1. Most processors need a value of
+ 1, even if they are 16- or 32-bit processors, but the PICs and
+ signal processors are cases where higher values are required.}
+\item{\tty{ListGrans}: This array specifies the size of byte groups that shall
+ be shown in the assembly listing. For example, instruction words
+ of the 68000 are always 2 bytes long though the code segment's
+ granularity is 1. The \tty{ListGran} entry therefore has to be set to
+ 2.}
+\item{\tty{SegLimits}: This array stores the highest possible address for
+ each segment, e.g. 65535 for a 16-bit address space. This array
+ need not be filled in case the code generator takes over the
+ {\tt ChkPC} method.}
+\item{\tty{ConstMode}: This variable may take the values
+ \tty{ConstModeIntel}, \tty{ConstModeMoto}, or \tty{ConstModeC}
+ and rules which syntax has to be used to specify the base of
+ integer constants.}
+\item{\tty{PCSymbol}: This variable contains the string an assembler program
+ may use to to get the current value of the program counter.
+ Intel processors for example usually use a dollar sign.}
+\item{\tty{TurnWords}: If the target processor uses big-endian addressing and
+ one of the fields in \tty{ListGran} is larger than one, set this flag
+ to true to get the correct byte order in the code output file.}
+\item{\tty{SetIsOccupied}: Some processors have a \tty{SET} machine instruction.
+ AS will allow \tty{SET} instructions to pass through to the code
+ generator and instead use \tty{EVAL} if this flag is set.}
+\item{\tty{HeaderID}: This variable contains the ID that is used to mark the
+ current processor family in the the code output file (see the
+ description of the code format described by AS). I urge to
+ contact me before selecting the value to avoid ambiguities.
+ Values outside the range of \$01..\$7f should be avoided as they
+ are reserved for special purposes (like a future extension to
+ allow linkable code). Even though this value is still hard-coded
+ in most code generators, the preferred method is now to fetch this
+ value from {\tt headids.h} via {\tt FindFamilyByName}.}
+\item{\tty{NOPCode}: There are some situations where AS has to fill unused
+ code areas with NOP statements. This variable contains the
+ machine code of the NOP statement.}
+\item{\tty{DivideChars}: This string contains the characters that are valid
+ separation characters for instruction parameters. Only extreme
+ exotics like the DSP56 require something else than a single comma
+ in this string.}
+\item{\tty{HasAttrs}: Some processors like the 68k series additionally split
+ an instruction into mnemonic and attribute. If the new processor
+ also does something like that, set this flag to true and AS will
+ deliver the instructions' components readily split in the string
+ variables \tty{OpPart} and \tty{AttrPart}. If this flag is however set to
+ false, no splitting will take place and the instruction will be
+ delivered as a single piece in \tty{OpPart}. \tty{AttrPart} will stay empty
+ in this case. One really should set this flag to false if the
+ target processor does not have attributes as one otherwise looses
+ the opportunity to use macros with a name containing dots (e.g.
+ to emulate other assemblers).}
+\item{\tty{AttrChars}: In case \tty{HasAttrs} is true, this string has to contain
+ all characters that can separate mnemonic and attribute. In most
+ cases, this string only contains a single dot.}
+\end{itemize}
+Do not assume that any of these variables has a predefined value; set
+them \bb{all}!!
+
+Apart from these variables, some function pointers have to be set that
+form the link form AS to the ''active'' parts of the code
+generator:
+\begin{itemize}
+\item{\tty{MakeCode}: This routine is called after a source line has been
+ split into mnemonic and parameters. The mnemonic is stored into
+ the variable \tty{OpPart}, and the parameters can be looked up in the
+ array \tty{ArgStr}. The number of arguments may be read from
+ \tty{ArgCnt}.
+ The binary code has to be stored into the array \tty{BAsmCode}, its
+ length into \tty{CodeLen}. In case the processor is word oriented
+ like the 68000 (i.e. the \tty{ListGran} element corresponding to the
+ currently active segment is 2), the field may be addressed
+ wordwise via \tty{WAsmCode}. There is also \tty{DAsmCode} for extreme
+ cases... The code length has to be given in units corresponding
+ to the current segment's granularity.}
+\item{\tty{SwitchFrom}: This parameter-less procedure enables the code generator
+ module to do ''cleanups'' when AS switches to another target processor.
+ This hook allows e.g. to free memory that has been allocated in the
+ generator and that is not needed as long as the generator is not
+ active. It may point to an empty procedure in the simplest case.
+ One example for the usage of this hook is the module \tty{CODE370} that
+ builds its instruction tables dynamically and frees them again after
+ usage.}
+\item{\tty{IsDef}: Some processors know additional instructions that impose
+ a special meaning on a label in the first row like \tty{EQU} does. One
+ example is the \tty{BIT} instruction found in an 8051 environment. This
+ function has to return TRUE if such a special instruction is
+ present. In the simplest case (no such instructions), the routine
+ may return a constant FALSE.}
+\end{itemize}
+
+Optionally, the code generator may additionally set the following function
+pointers:
+\begin{itemize}
+\item{\tty{ChkPC} : Though AS internally treats all program counters as
+ either 32 or 64 bits, most processors use an address space that is
+ much smaller. This function informs AS whether the current program
+ counter has exceeded its allowed range. This routine may of course
+ be much more complicated in case the target processor has more than
+ one address space. One example is in module \tty{code16c8x.c}. In
+ case everything is fine, the function has to return TRUE, otherwise
+ FALSE. The code generator only has to implement this function if
+ it did not set up the array {\tt SegLimits}. This may e.g. become
+ necessary when the allowed range of addresses in a segment is
+ non-continuous.}
+\item{\tty{InternSymbol} : Some processorcs, e.g. such with a register
+ bank in their internal RAM, predefine such 'registers' as symbols,
+ and it wouldn't make much sense to define them in a separate include
+ file with 256 or maybe more {\tt EQU}s. This hook allows access to
+ the code generator of AS: It obtains an expression as an ASCII
+ string and sets up the passed structure of type {\em TempResult}
+ accordingly when one of these 'built-in' symbols is detected. The
+ element {\tt Typ} has to be set to {\tt TempNone} in case the check
+ failed. Errors messages from this routine should be avoided as
+ unidentified names could signify ordinary symbols (the parser will
+ check this afterwards). Be extreme careful with this routine as
+ it allows you to intervene into the parser's heart!}
+\end{itemize}
+
+By the way: People who want to become immortal may add a copyright
+string. This is done by adding a call to the procedure \tty{AddCopyright}
+in the module's initialization part (right next to the \tty{AddCPU} calls):
+\begin{verbatim}
+ AddCopyright(
+ "Intel 80986 code generator (C) 2010 Jim Bonehead");
+\end{verbatim}
+The string passed to \tty{AddCopyright} will be printed upon program start
+in addition to the standard message.
+
+If needed, the unit may also use its initialization part to hook into
+a list of procedures that are called prior to each pass of assembly.
+Such a need for example arises when the module's code generation
+depends on certain flags that can be modified via pseudo
+instructions. An example is a processor that can operate in either
+user or supervisor mode. In user mode, some instructions are
+disabled. The flag that tells AS whether the following code executes
+in user or supervisor mode might be set via a special pseudo
+instruction. But there must also be an initialization that assures
+that all passes start with the same state. The hook offered via
+\tty{InitPassProc} offers a chance to do such initializations. The
+principle is similar to the redirection of an interrupt vector: the
+unit saves the old value prior to pointing the procedure variable to
+its own routine (the routine must be parameter-less and \tty{FAR} coded).
+The new routine first calls the old chain of procedures and
+afterwards does its own operations.
+
+The function chain built up via \tty{CleanUpProc} works similar to
+\tty{InitPassProc}: It enables code generators to do clean-ups after
+assembly (e.g. freeing of literal tables). This makes sense when
+multiple files are assembled with a single call of AS. Otherwise, one
+would risk to have 'junk' in tables from the previous run. No module
+currently exploits this feature.
+
+\subsubsection{Writing the Code Generator itself}
+
+Now we finally reached the point where your creativity is challenged:
+It is up to you how you manage to translate mnemonic and parameters
+into a sequence of machine code. The symbol tables are of course
+accessible (via the formula parser) just like everything exported
+from \tty{ASMSUB}. Some general rules (take them as advises and not as
+laws...):
+\begin{itemize}
+\item{Try to split the instruction set into groups of instructions that
+ have the same operand syntax and that differ only in a few bits
+ of their machine code. For example, one can do all instructions
+ without parameters in a single table this way.}
+\item{Most processors have a fixed spectrum of addressing modes. Place
+ the parsing of an address expression in a separate routine so you
+ an reuse the code.}
+\item{The subroutine \tty{WrError} defines a lot of possible error codes and
+ can be easily extended. Use this! It is no good to simply issue
+ a ''syntax error'' on all error conditions!}
+\end{itemize}
+Studying other existing code generators should also prove to be
+helpful.
+
+\subsubsection{Modifications of Tools}
+
+A microscopic change to the tolls' sources is still necessary, namely to
+the routine {\tt Granularity()} in {\tt toolutils.c}: in case one of the
+processor's address spaces has a granularity different to 1, the swich
+statement in this place has to be adapted accordingly, otherwise PLIST,
+P2BIN, and P2HEX start counting wrong...
+
+\section{Localization to a New Language}
+
+You are interested in this topic? Wonderful! This is an issue that is
+often neglected by other programmers, especially when they come from the
+country on the other side of the big lake...
+
+The localization to a new language can be split into two parts: the
+adaption of program messages and the translation of the manual. The
+latter one is definitely a work of gigantic size, however, the adaption of
+program messages should be a work doable on two or three weekends, given
+that one knows both the new and one of the already present messages.
+Unfortunately, this translation cannot be done on a step-by-step basis
+because the resource compiler currently cannot deal with a variable amount
+of languages for different messages, so the slogan is 'all or nothing'.
+
+The first oeration is to add the new language to {\tt header.res}. The
+two-letter-abbreviation used for this language is best fetched from the
+nearest Unix system (in case you don't work on one anyway...), the
+international telephone prefix from a DOS manual.
+
+When this is complete, one can rebuild all necessary parts with a simple
+{\em make} and obtains an assembler that supports one more language. Do
+not forget to forward the results to me. This way, all users will benefit
+from this with the next release :-)
+
+%%===========================================================================
+
+\cleardoublepage
+\begin{thebibliography}{99}
+
+\bibitem{Williams} Steve Williams: \\
+ {\em 68030 Assembly Language Reference.\/} \\
+ Addison-Wesley, Reading, Massachusetts, 1989
+
+\bibitem{AMD29K} Advanced Micro Devices: \\
+ {\em AM29240, AM29245, and AM29243 RISC
+ Microcontrollers.\/} \\
+ 1993
+
+\bibitem{AtAVR} Atmel Corp.: \\
+ {\em AVR Enhanced RISC Microcontroller Data Book.\/} \\
+ May 1996
+
+\bibitem{AVRObj} Atmel Corp.: \\
+ {\em 8-Bit AVR Assembler and Simulator Object File
+ Formats (Preliminary).\/} \\
+ (part of the AVR tools documentation)
+
+\bibitem{CMD816} CMD Microcircuits: \\
+ {\em G65SC802/G65SC816 CMOS 8/16-Bit Microprocessor.\/} \\
+ Family Data Sheet.
+
+\bibitem{CPM68K} Digital Research: \\
+ {\em CP/M 68K Operating System User's Guide.\/} \\
+ 1983
+
+\bibitem{Cyrix} Cyrix Corp.: \\
+ {\em FasMath 83D87 User's Manual.\/} \\
+ 1990
+
+\bibitem{Dallas320} Dallas Semiconductor: \\
+ {\em DS80C320 High-Speed Micro User's Guide.\/} \\
+ Version 1.30, 1/94
+
+\bibitem{Fair1101} Fairchild Semiconductor: \\
+ {\em ACE1101 Data Sheet.\/} \\
+ Preliminary, May 1999
+
+\bibitem{Fair1202} Fairchild Semiconductor: \\
+ {\em ACE1202 Data Sheet.\/} \\
+ Preliminary, May 1999
+
+\bibitem{Fair8004} Fairchild Semiconductor: \\
+ {\em ACEx Guide to Developer Tools.\/}
+ AN-8004, Version 1.3 September 1998
+
+\bibitem{FujitsuCD} Fujitsu Limited: \\
+ {\em June 1998 Semiconductor Data Book.\/} \\
+ CD00-00981-1E
+
+\bibitem{Hit180} Hitachi Ltd.: \\
+ {\em 8-/16-Bit Microprocessor Data Book.\/} \\
+ 1986
+
+\bibitem{Hit63} Trevor J.Terrel \& Robert J. Simpson: \\
+ {\em Understanding HD6301X/03X CMOS Microprocessor
+ Systems.\/} \\
+ published by Hitachi
+
+\bibitem{HitH8_3} Hitachi Microcomputer: \\
+ {\em H8/300H Series Programming Manual.\/} \\
+ (21-032, no year of release given)
+
+\bibitem{SH7000} Hitachi Semiconductor Design \& Development Center: \\
+ {\em SH Microcomputer Hardware Manual
+ (Preliminary).\/}
+
+\bibitem{SH7700} Hitachi Semiconductor and IC Div.: \\
+ {\em SH7700 Series Programming Manual.\/} \\
+ 1st Edition, September 1995
+
+\bibitem{HitH8_5} Hitachi Semiconductor and IC Div.: \\
+ {\em H8/500 Series Programming Manual.\/} \\
+ (21-20, 1st Edition Feb. 1989)
+
+\bibitem{HitH8_532} Hitachi Ltd.: \\
+ {\em H8/532 Hardware Manual.\/} \\
+ (21-30, no year of release given)
+
+\bibitem{HitH8_534} Hitachi Ltd.: \\
+ {\em H8/534,H8/536 Hardware Manual.\/} \\
+ (21-19A, no year of release given)
+
+\bibitem{PPC403} IBM Corp.: \\
+ {\em PPC403GA Embedded Controller User's Manual.\/} \\
+ First Edition, September 1994
+
+\bibitem{IntEmb} Intel Corp.: \\
+ {\em Embedded Controller Handbook.\/} \\
+ 1987
+
+\bibitem{IntMic} Intel Corp.: \\
+ {\em Microprocessor and Peripheral Handbook, Volume I
+ Microprocessor.\/} \\
+ 1988
+
+\bibitem{Int960} Intel Corp. : \\
+ {\em 80960SA/SB Reference Manual.\/} \\
+ 1991
+
+\bibitem{Int196} Intel Corp.: \\
+ {\em 8XC196NT Microcontroller User's Manual.\/} \\
+ June 1995
+
+\bibitem{Int251} Intel Corp.: \\
+ {\em 8XC251SB High Performance CHMOS Single-Chip
+ Microcontroller.\/} \\
+ Sept. 1995, Order Number 272616-003
+
+\bibitem{Int296} Intel Corp.: \\
+ {\em 80296SA Microcontroller User's Manual.\/} \\
+ Sept. 1996
+
+\bibitem{Kaku} Hirotsugu Kakugawa: \\
+ {\em A memo on the secret features of 6309.\/} \\
+ (available via World Wide Web: \\
+ http://www.cs.umd.edu/users/fms/comp/CPUs/6309.txt)
+
+\bibitem{MicroChip} Microchip Technology Inc.: \\
+ {\em Microchip Data Book.\/} \\
+ 1993 Edition
+
+\bibitem{Mit41} Mitsubishi Electric: \\
+ {\em Single-Chip 8-Bit Microcomputers.\/} \\
+ Vol.2, 1987
+
+\bibitem{Mit16} Mitsubishi Electric: \\
+ {\em Single-Chip 16-Bit Microcomputers.\/} \\
+ Enlarged edition, 1991
+
+\bibitem{Mit8} Mitsubishi Electric: \\
+ {\em Single-Chip 8 Bit Microcomputers.\/} \\
+ Vol.2, 1992
+
+\bibitem{Mit4500} Mitsubishi Electric: \\
+ {\em M34550Mx-XXXFP Users's Manual.\/} \\
+ Jan. 1994
+
+\bibitem{MitM16} Mitsubishi Electric: \\
+ {\em M16 Family Software Manual.\/} \\
+ First Edition, Sept. 1994
+
+\bibitem{MitM16C} Mitsubishi Electric: \\
+ {\em M16C Software Manual.\/} \\
+ First Edition, Rev. C, 1996
+
+\bibitem{Mit30600} Mitsubishi Electric: \\
+ {\em M30600-XXXFP Data Sheet.\/} \\
+ First Edition, April 1996
+
+\bibitem{GreenM16} documentation about the M16/M32-developer's package
+ from Green Hills Software
+
+\bibitem{MotMic} Motorola Inc.: \\
+ {\em Microprocessor, Microcontroller and Peripheral
+ Data.\/} \\
+ Vol. I+II, 1988
+
+\bibitem{Mot81} Motorola Inc.: \\
+ {\em MC68881/882 Floating Point Coprocessor User's
+ Manual.\/} \\
+ Second Edition, Prentice-Hall, Englewood Cliffs 1989
+
+\bibitem{Mot51} Motorola Inc.: \\
+ {\em MC68851 Paged Memory Management Unit User's
+ Manual.\/} \\
+ Second Edition, Prentice-Hall, Englewood Cliffs 1989,1988
+
+\bibitem{Mot32} Motorola Inc.: \\
+ {\em CPU32 Reference Manual.\/} \\
+ Rev. 1, 1990
+
+\bibitem{Mot56} Motorola Inc.: \\
+ {\em DSP56000/DSP56001 Digital Signal Processor User's
+ Manual.\/} \\
+ Rev. 2, 1990
+
+\bibitem{Mot340} Motorola Inc.: \\
+ {\em MC68340 Technical Summary.\/} \\
+ Rev. 2, 1991
+
+\bibitem{Mot16} Motorola Inc.: \\
+ {\em CPU16 Reference Manual.\/} \\
+ Rev. 1, 1991
+
+\bibitem{Mot68K} Motorola Inc.: \\
+ {\em Motorola M68000 Family Programmer's
+ Reference Manual.\/} \\
+ 1992
+
+\bibitem{Mot332} Motorola Inc.: \\
+ {\em MC68332 Technical Summary.\/} \\
+ Rev. 2, 1993
+
+\bibitem{Mot601} Motorola Inc.: \\
+ {\em PowerPC 601 RISC Microprocessor User's Manual.\/} \\
+ 1993
+
+\bibitem{Mot505} Motorola Inc.: \\
+ {\em PowerPC(tm) MPC505 RISC Microcontroller Technical
+ Summary.\/} \\
+ 1994
+
+\bibitem{Mot12} Motorola Inc.: \\
+ {\em CPU12 Reference Manual.\/} \\
+ 1st edition, 1996
+
+\bibitem{Mot08} Motorola Inc.: \\
+ {\em CPU08 Reference Manual.\/} \\
+ Rev. 1 (no year of release given im PDF-File)
+
+\bibitem{Mot360} Motorola Inc.: \\
+ {\em MC68360 User's Manual.\/}
+
+\bibitem{MotCold} Motorola Inc.: \\
+ {\em MCF 5200 ColdFire Family Programmer's Reference
+ Manual.\/} \\
+ 1995
+
+\bibitem{MotMCore} Motorola Inc.: \\
+ {\em M*Core Programmer's Reference Manual.\/} \\
+ 1997
+
+\bibitem{Mot56300} Motorola Inc.: \\
+ {\em DSP56300 24-Bit Digital Signal Processor
+ Family Manual.\/} \\
+ Rev. 0 (no year of release given im PDF-File)
+
+\bibitem{SCMP} National Semiconductor: \\
+ {\em SC/MP Program\-mier- und
+ As\-sem\-bler-Hand\-buch.\/} \\
+ Publication Number 4200094A, Aug. 1976
+
+\bibitem{AsmCop} National Semiconductor: \\
+ {\em COP800 Assembler/Linker/Librarian User's
+ Manual.\/} \\
+ Customer Order Number COP8-ASMLNK-MAN \\
+ NSC Publication Number 424421632-001B \\
+ August 1993
+
+\bibitem{Cop87L84} National Semiconductor: \\
+ {\em COP87L84BC microCMOS One-Time-Programmable (OTP)
+ Microcontroller.\/} \\
+ Preliminary, March 1996
+
+\bibitem{Nat14xxx} National Semiconductor: \\
+ {\em SC14xxx DIP commands Reference guide.} \\
+ Application Note AN-D-031, Version 0.4, 12-28-1998
+
+\bibitem{NECV} NEC Corp.: \\
+ {\em $\mu$pD70108/$\mu$pD70116/$\mu$pD70208/$\mu$pD70216/$\mu$pD72091
+ Data Book.\/} \\
+ (no year of release given)
+
+\bibitem{NEC78K0} NEC Electronics Europe GmbH: \\
+ {\em User's Manual $\mu$COM-87 AD Family.\/} \\
+ (no year of release given)
+
+\bibitem{NEC75} NEC Corp.: \\
+ {\em $\mu$COM-75x Family 4-bit CMOS Microcomputer User's
+ Manual.\/} \\
+ Vol. I+II (no year of release given)
+
+\bibitem{NECSig} NEC Corp.: \\
+ {\em Digital Signal Processor Product Description.\/} \\
+ PDDSP.....067V20 (no year of release given)
+
+\bibitem{NEC78} NEC Corp.: \\
+ {\em $\mu$PD78070A, 78070AY 8-Bit Single-Chip Microcontroller
+ User's Manual.\/} \\
+ Document No. U10200EJ1V0UM00 (1st edition), August 1995
+
+\bibitem{NEC7814} NEC Corp.: \\
+ {\em Data Sheet $\mu$PD78014.\/}
+
+\bibitem{PhilXA} Philips Semiconductor: \\
+ {\em 16-bit 80C51XA Microcontrollers (eXtended
+ Architecture).\/} \\
+ Data Handbook IC25, 1996
+
+\bibitem{SGS04} SGS-Thomson Microelectronics: \\
+ {\em 8 Bit MCU Families EF6801/04/05 Databook.\/}\\
+ 1st edition, 1989
+
+\bibitem{SGS62} SGS-Thomson Microelectronics: \\
+ {\em ST6210/ST6215/ST6220/ST6225 Databook.\/} \\
+ 1st edition, 1991
+
+\bibitem{ST7Man} SGS-Thomson Microelectronics: \\
+ {\em ST7 Family Programming Manual.\/} \\
+ June 1995
+
+\bibitem{SGS9} SGS-Thomson Microelectronics: \\
+ {\em ST9 Programming Manual.\/} \\
+ 3rd edition, 1993
+
+\bibitem{Siem166} Siemens AG: \\
+ {\em SAB80C166/83C166 User's Manual.\/} \\
+ Edition 6.90
+
+\bibitem{Siem167} Siemens AG: \\
+ {\em SAB C167 Preliminary User's Manual.\/} \\
+ Revision 1.0, July 1992
+
+\bibitem{Siem502} Siemens AG: \\
+ {\em SAB-C502 8-Bit Single-Chip Microcontroller User's
+ Manual.\/} \\
+ Edition 8.94
+
+\bibitem{Siem501} Siemens AG: \\
+ {\em SAB-C501 8-Bit Single-Chip Microcontroller User's
+ Manual.\/} \\
+ Edition 2.96
+
+\bibitem{Siem504} Siemens AG: \\
+ {\em C504 8-Bit CMOS Microcontroller User's Manual.\/} \\
+ Edition 5.96
+
+\bibitem{Syb68K} C.Vieillefond: \\
+ {\em Programmierung des 68000.\/} \\
+ Sybex-Verlag D\"usseldorf, 1985
+
+\bibitem{Sym8xx} Symbios Logic Inc: \\
+ {\em Symbios Logic PCI-SCSI-I/O Processors Programming
+ Guide.\/} \\
+ Version 2.0, 1995/96
+
+\bibitem{Ti990} Texas Instruments: \\
+ {\em Model 990 Computer/TMS9900 Microprocessor
+ Assembly Language Programmer's Guide.\/} \\
+ 1977, Manual No. 943441-9701
+
+\bibitem{Ti9900} Texas Instruments: \\
+ {\em TMS9995 16-Bit Microcomputer.\/} \\
+ Preliminary Data Manual
+ 1981
+
+\bibitem{TiC10} Texas Instruments: \\
+ {\em First-Generation TMS320 User's Guide.\/} \\
+ 1988, ISBN 2-86886-024-9
+
+\bibitem{Ti7000} Texas Instruments: \\
+ {\em TMS7000 family Data Manual.\/} \\
+ 1991, DB103
+
+\bibitem{TiC30} Texas Instruments: \\
+ {\em TMS320C3x User's Guide.\/} \\
+ Revision E, 1991
+
+\bibitem{TiC20} Texas Instruments: \\
+ {\em TMS320C2x User's Guide.\/} \\
+ Revision C, Jan. 1993
+
+\bibitem{Ti370} Texas Instruments: \\
+ {\em TMS370 Family Data Manual.\/} \\
+ 1994, SPNS014B
+
+\bibitem{Ti430FamSoft} Texas Instruments: \\
+ {\em MSP430 Family Software User's Guide.\/} \\
+ 1994, SLAUE11
+
+\bibitem{Ti430Met} Texas Instruments: \\
+ {\em MSP430 Metering Application.\/} \\
+ 1996, SLAAE10A
+
+\bibitem{Ti430FamArch} Texas Instruments: \\
+ {\em MSP430 Family Architecture User's Guide.\/} \\
+ 1995, SLAUE10A
+
+\bibitem{TiC60} Texas Instruments: \\
+ {\em TMS320C62xx CPU and Instruction Set Reference
+ Manual.\/} \\
+ Jan. 1997, SPRU189A
+
+\bibitem{TiC20x} Texas Instruments: \\
+ {\em TMS320C20x User's Guide.\/} \\
+ April 1999, SPRU127C
+
+\bibitem{Tosh90} Toshiba Corp.: \\
+ {\em 8-Bit Microcontroller TLCS-90 Development System
+ Manual.\/} \\
+ 1990
+
+\bibitem{Tosh870} Toshiba Corp.: \\
+ {\em 8-Bit Microcontroller TLCS-870 Series Data
+ Book.\/} \\
+ 1992
+
+\bibitem{Tosh900} Toshiba Corp.: \\
+ {\em 16-Bit Microcontroller TLCS-900 Series Users
+ Manual.\/} \\
+ 1992
+
+\bibitem{Tosh900L} Toshiba Corp.: \\
+ {\em 16-Bit Microcontroller TLCS-900 Series Data Book:
+ TMP93CM40F/ TMP93CM41F.\/} \\
+ 1993
+
+\bibitem{Tosh47} Toshiba Corp.: \\
+ {\em 4-Bit Microcontroller TLCS-47E/47/470/470A Development
+ System Manual.\/} \\
+ 1993
+
+\bibitem{Tosh9000} Toshiba Corp.: \\
+ {\em TLCS-9000/16 Instruction Set Manual Version
+ 2.2.\/} \\
+ 10. Feb 1994
+
+\bibitem{Val8X} Valvo GmbH: \\
+ {\em Bipolare Mikroprozessoren und bipolare
+ LSI-Schaltungen.\/} \\
+ Datenbuch, 1985, ISBN 3-87095-186-9
+
+\bibitem{Zilog} data sheets from Zilog about the Z80 family
+
+\bibitem{ZilZ8} Zilog Inc.: \\
+ {\em Z8 Microcontrollers Databook.\/} \\
+ 1992
+
+\bibitem{ZilZ8_2} Zilog Inc.: \\
+ {\em Discrete Z8 Microcontrollers Databook.\/} \\
+ (no year of release given)
+
+\bibitem{ZilZ380} Zilog Inc.: \\
+ {\em Z380 CPU Central Processing Unit User's
+ Manual.\/} \\
+ (no year of release given)
+
+\end{thebibliography}
+
+\cleardoublepage
+
+\printindex
+
+\end{document}
diff --git a/endian.c b/endian.c
new file mode 100644
index 0000000..cf68dd6
--- /dev/null
+++ b/endian.c
@@ -0,0 +1,333 @@
+/* endian.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Little/Big-Endian-Routinen */
+/* */
+/* Historie: 30. 5.1996 Grundsteinlegung */
+/* 6. 7.1997 Dec32BlankString dazu */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "endian.h"
+
+/*****************************************************************************/
+
+Boolean BigEndian;
+
+char *Integ16Format,*Integ32Format,*Integ64Format;
+char *IntegerFormat,*LongIntFormat,*QuadIntFormat;
+char *LargeIntFormat;
+
+/*****************************************************************************/
+
+ void WSwap(void *Field, int Cnt)
+BEGIN
+ register unsigned char *Run=(unsigned char *) Field,Swap;
+ register int z;
+
+ for (z=0; z<Cnt/2; z++,Run+=2)
+ BEGIN
+ Swap=Run[0]; Run[0]=Run[1]; Run[1]=Swap;
+ END
+END
+
+ void DSwap(void *Field, int Cnt)
+BEGIN
+ register unsigned char *Run=(unsigned char *) Field,Swap;
+ register int z;
+
+ for (z=0; z<Cnt/4; z++,Run+=4)
+ BEGIN
+ Swap=Run[0]; Run[0]=Run[3]; Run[3]=Swap;
+ Swap=Run[1]; Run[1]=Run[2]; Run[2]=Swap;
+ END
+END
+
+ void QSwap(void *Field, int Cnt)
+BEGIN
+ register unsigned char *Run=(unsigned char *) Field,Swap;
+ register int z;
+
+ for (z=0; z<Cnt/8; z++,Run+=8)
+ BEGIN
+ Swap=Run[0]; Run[0]=Run[7]; Run[7]=Swap;
+ Swap=Run[1]; Run[1]=Run[6]; Run[6]=Swap;
+ Swap=Run[2]; Run[2]=Run[5]; Run[5]=Swap;
+ Swap=Run[3]; Run[3]=Run[4]; Run[4]=Swap;
+ END
+END
+
+ void DWSwap(void *Field, int Cnt)
+BEGIN
+ register unsigned char *Run=(unsigned char *) Field,Swap;
+ register int z;
+
+ for (z=0; z<Cnt/4; z++,Run+=4)
+ BEGIN
+ Swap=Run[0]; Run[0]=Run[2]; Run[2]=Swap;
+ Swap=Run[1]; Run[1]=Run[3]; Run[3]=Swap;
+ END
+END
+
+ void QWSwap(void *Field, int Cnt)
+BEGIN
+ register unsigned char *Run=(unsigned char *) Field,Swap;
+ register int z;
+
+ for (z=0; z<Cnt/8; z++,Run+=8)
+ BEGIN
+ Swap=Run[0]; Run[0]=Run[6]; Run[6]=Swap;
+ Swap=Run[1]; Run[1]=Run[7]; Run[7]=Swap;
+ Swap=Run[2]; Run[2]=Run[4]; Run[4]=Swap;
+ Swap=Run[3]; Run[3]=Run[5]; Run[5]=Swap;
+ END
+END
+
+ void Double_2_ieee4(Double inp, Byte *dest, Boolean NeedsBig)
+BEGIN
+#ifdef IEEEFLOAT
+ Single tmp=inp;
+ memcpy(dest,&tmp,4);
+ if (BigEndian!=NeedsBig) DSwap(dest,4);
+#endif
+#ifdef VAXFLOAT
+ Single tmp=inp/4;
+ memcpy(dest,&tmp,4);
+ WSwap(dest,4);
+ if (NOT NeedsBig) DSwap(dest,4);
+#endif
+END
+
+ void Double_2_ieee8(Double inp, Byte *dest, Boolean NeedsBig)
+BEGIN
+#ifdef IEEEFLOAT
+ memcpy(dest,&inp,8);
+ if (BigEndian!=NeedsBig) QSwap(dest,8);
+#endif
+#ifdef VAXFLOAT
+ Byte tmp[8];
+ Word Exp;
+ int z;
+ Boolean cont;
+
+ memcpy(tmp,&inp,8);
+ WSwap(tmp,8);
+ Exp=((tmp[0]<<1)&0xfe)+(tmp[1]>>7);
+ Exp+=894; /* =1023-192 */
+ tmp[1]&=0x7f;
+ if ((tmp[7]&7)>4)
+ BEGIN
+ for (tmp[7]+=8,cont=tmp[7]<8,z=0; cont AND z>1; z--)
+ BEGIN
+ tmp[z]++; cont=(tmp[z]==0);
+ END
+ if (cont)
+ BEGIN
+ tmp[1]++; if (tmp[1]>127) Exp++;
+ END
+ END
+ dest[7]=(tmp[0]&0x80)+((Exp>>4)&0x7f);
+ dest[6]=((Exp&0x0f)<<4)+((tmp[1]>>3)&0x0f);
+ for (z=5; z>=0; z--)
+ dest[z]=((tmp[6-z]&7)<<5)|((tmp[7-z]>>3)&0x1f);
+ if (NeedsBig) QSwap(dest,8);
+#endif
+END
+
+ void Double_2_ieee10(Double inp, Byte *dest, Boolean NeedsBig)
+BEGIN
+ Byte Buffer[8];
+ Byte Sign;
+ Word Exponent;
+ int z;
+
+#ifdef IEEEFLOAT
+ Boolean Denormal;
+
+ memcpy(Buffer,&inp,8); if (BigEndian) QSwap(Buffer,8);
+ Sign=(Buffer[7]&0x80);
+ Exponent=(Buffer[6]>>4)+(((Word) Buffer[7]&0x7f)<<4);
+ Denormal=(Exponent==0);
+ if (Exponent==2047) Exponent=32767;
+ else Exponent+=(16383-1023);
+ Buffer[6]&=0x0f; if (NOT Denormal) Buffer[6]|=0x10;
+ for (z=7; z>=2; z--)
+ dest[z]=((Buffer[z-1]&0x1f)<<3)|((Buffer[z-2]&0xe0)>>5);
+ dest[1]=(Buffer[0]&0x1f)<<3;
+ dest[0]=0;
+#endif
+#ifdef VAXFLOAT
+ memcpy(Buffer,&inp,8); WSwap(Buffer,8);
+ Sign=(*Buffer)&0x80;
+ Exponent=((*Buffer)<<1)+((Buffer[1]&0x80)>>7);
+ Exponent+=(16383-129);
+ Buffer[1]|=0x80;
+ for (z=1; z<8; z++) dest[z]=Buffer[8-z];
+ dest[0]=0;
+#endif
+ dest[9]=Sign|((Exponent>>8)&0x7f);
+ dest[8]=Exponent&0xff;
+ if (NeedsBig)
+ for (z=0; z<5; z++)
+ BEGIN
+ Sign=dest[z]; dest[z]=dest[9-z]; dest[9-z]=Sign;
+ END
+END
+
+
+ Boolean Read2(FILE *file, void *Ptr)
+BEGIN
+ if (fread(Ptr,1,2,file)!=2) return False;
+ if (BigEndian) WSwap(Ptr,2);
+ return True;
+END
+
+ Boolean Read4(FILE *file, void *Ptr)
+BEGIN
+ if (fread(Ptr,1,4,file)!=4) return False;
+ if (BigEndian) DSwap(Ptr,4);
+ return True;
+END
+
+ Boolean Read8(FILE *file, void *Ptr)
+BEGIN
+ if (fread(Ptr,1,8,file)!=8) return False;
+ if (BigEndian) QSwap(Ptr,8);
+ return True;
+END
+
+
+
+ Boolean Write2(FILE *file, void *Ptr)
+BEGIN
+ Boolean OK;
+
+ if (BigEndian) WSwap(Ptr,2);
+ OK=(fwrite(Ptr,1,2,file)==2);
+ if (BigEndian) WSwap(Ptr,2);
+ return OK;
+END
+
+ Boolean Write4(FILE *file, void *Ptr)
+BEGIN
+ Boolean OK;
+
+ if (BigEndian) DSwap(Ptr,4);
+ OK=(fwrite(Ptr,1,4,file)==4);
+ if (BigEndian) DSwap(Ptr,4);
+ return OK;
+END
+
+ Boolean Write8(FILE *file, void *Ptr)
+BEGIN
+ Boolean OK;
+
+ if (BigEndian) QSwap(Ptr,8);
+ OK=(fwrite(Ptr,1,8,file)==8);
+ if (BigEndian) QSwap(Ptr,8);
+ return OK;
+END
+
+
+ static void CheckSingle(int Is, int Should, char *Name)
+BEGIN
+ if (Is!=Should)
+ BEGIN
+ fprintf(stderr,"Configuration error: Sizeof(%s) is %d, should be %d\n",
+ Name,Is,Should);
+ exit(255);
+ END
+END
+
+ static void CheckDataTypes(void)
+BEGIN
+ if (sizeof(int)<2)
+ BEGIN
+ fprintf(stderr,"Configuration error: Sizeof(int) is %d, should be >=2\n",
+ (int) sizeof(int));
+ exit(255);
+ END
+ CheckSingle(sizeof(Byte), 1,"Byte");
+ CheckSingle(sizeof(ShortInt),1,"ShortInt");
+#ifdef HAS16
+ CheckSingle(sizeof(Word), 2,"Word");
+ CheckSingle(sizeof(Integer), 2,"Integer");
+#endif
+ CheckSingle(sizeof(LongInt), 4,"LongInt");
+ CheckSingle(sizeof(LongWord),4,"LongWord");
+#ifdef HAS64
+ CheckSingle(sizeof(QuadInt), 8,"QuadInt");
+ CheckSingle(sizeof(QuadWord),8,"QuadWord");
+#endif
+ CheckSingle(sizeof(Single), 4,"Single");
+ CheckSingle(sizeof(Double), 8,"Double");
+END
+
+
+ static char *AssignSingle(int size)
+BEGIN
+ if (size==sizeof(short)) return "%d";
+ else if (size==sizeof(int)) return "%d";
+ else if (size==sizeof(long)) return "%ld";
+#ifndef NOLONGLONG
+ else if (size==sizeof(long long)) return "%lld";
+#endif
+ else
+ BEGIN
+ fprintf(stderr,
+ "Configuration error: cannot assign format string for integer of size %d\n",size);
+ exit(255);
+ return "";
+ END
+END
+
+ static void AssignFormats(void)
+BEGIN
+#ifdef HAS16
+ IntegerFormat=Integ16Format=AssignSingle(2);
+#endif
+ LongIntFormat=Integ32Format=AssignSingle(4);
+#ifdef HAS64
+ QuadIntFormat=Integ64Format=AssignSingle(8);
+#endif
+ LargeIntFormat=AssignSingle(sizeof(LargeInt));
+END
+
+ char *Dec32BlankString(LongInt number, int Stellen)
+BEGIN
+ char Format[10];
+ static char Erg[255];
+
+ sprintf(Format,"%%%d%s",Stellen,LongIntFormat+1);
+ sprintf(Erg,Format,number);
+
+ return Erg;
+END
+
+
+ void endian_init(void)
+BEGIN
+ union
+ {
+ unsigned char field[sizeof(int)];
+ int test;
+ } TwoFace;
+
+ CheckDataTypes(); AssignFormats();
+
+ memset(TwoFace.field,0,sizeof(int));
+ TwoFace.field[0]=1;
+ BigEndian=((TwoFace.test)!=1);
+ /*if (BigEndian)
+ BEGIN
+ fprintf(stderr,"Warning: Big endian machine!\n");
+ fprintf(stderr,"AS is so far not adapted for big-endian-machines!\n");
+ END*/
+END
+
+
diff --git a/endian.h b/endian.h
new file mode 100644
index 0000000..ce8e5ff
--- /dev/null
+++ b/endian.h
@@ -0,0 +1,54 @@
+/* endian.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Little/Big-Endian-Routinen */
+/* */
+/* Historie: 30. 5.1996 Grundsteinlegung */
+/* 6. 7.1997 Dec32BlankString dazu */
+/* */
+/*****************************************************************************/
+
+extern Boolean BigEndian;
+
+extern char *Integ16Format,*Integ32Format,*Integ64Format;
+extern char *IntegerFormat,*LongIntFormat,*QuadIntFormat;
+extern char *LargeIntFormat;
+
+
+extern void WSwap(void *Field, int Cnt);
+
+extern void DSwap(void *Field, int Cnt);
+
+extern void QSwap(void *Field, int Cnt);
+
+extern void DWSwap(void *Field, int Cnt);
+
+extern void QWSwap(void *Field, int Cnt);
+
+
+extern void Double_2_ieee4(Double inp, Byte *dest, Boolean NeedsBig);
+
+extern void Double_2_ieee8(Double inp, Byte *dest, Boolean NeedsBig);
+
+extern void Double_2_ieee10(Double inp, Byte *dest, Boolean NeedsBig);
+
+
+extern Boolean Read2(FILE *file, void *Ptr);
+
+extern Boolean Read4(FILE *file, void *Ptr);
+
+extern Boolean Read8(FILE *file, void *Ptr);
+
+
+extern Boolean Write2(FILE *file, void *Ptr);
+
+extern Boolean Write4(FILE *file, void *Ptr);
+
+extern Boolean Write8(FILE *file, void *Ptr);
+
+
+extern char *Dec32BlankString(LongInt number, int Stellen);
+
+
+extern void endian_init(void);
diff --git a/equs.h b/equs.h
new file mode 100644
index 0000000..6d74679
--- /dev/null
+++ b/equs.h
@@ -0,0 +1,6 @@
+/* equs.asm-Includefile für C-Programm */
+#define SEGTEST 0x157 /* Kommentar kommt mit */
+#define FTEST 0.52359877559829893
+#define STEST "Hello World"
+#define UTEST 0x1
+/* Ende Includefile für C-Programm */
diff --git a/fileformat.h b/fileformat.h
new file mode 100644
index 0000000..30bf85a
--- /dev/null
+++ b/fileformat.h
@@ -0,0 +1,40 @@
+/* fileformat.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Definition von Konstanten fuer das P-Format */
+/* */
+/* Historie: 3.12.1996 Grundsteinlegung */
+/* 11. 9.1998 ROMDATA-Segment hinzugenommen */
+/* 12. 7.1999 RelocRec-Typ hinzugenommen */
+/* */
+/*****************************************************************************/
+
+#ifndef _FILEFORMATS_H
+#define _FILEFORMATS_H
+
+#define FileMagic 0x1489
+
+#define FileHeaderEnd 0x00 /* Dateiende */
+#define FileHeaderStartAdr 0x80 /* Einsprungadresse absolut */
+#define FileHeaderDataRec 0x81 /* normaler Datenrecord */
+#define FileHeaderRelocRec 0x82 /* normaler Datenrecord mit Relokationsinformationen */
+
+#define SegNone 0
+#define SegCode 1
+#define SegData 2
+#define SegIData 3
+#define SegXData 4
+#define SegYData 5
+#define SegBData 6
+#define SegIO 7
+#define SegReg 8
+#define SegRData 9
+
+#define PCMax SegRData
+
+enum {RelocNone, Reloc8, RelocL16, RelocM16, RelocL24, RelocM24,
+ RelocL32, RelocM32, RelocL64, RelocH64,
+ RelocVar = 0x80};
+
+#endif
diff --git a/findhyphen.c b/findhyphen.c
new file mode 100644
index 0000000..25dfd1b
--- /dev/null
+++ b/findhyphen.c
@@ -0,0 +1,270 @@
+/* findhyphen.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Zerlegung von Worten in Silben gemaess dem TeX-Algorithmus */
+/* */
+/* Historie: 17.2.1998 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#undef DEBUG
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "strutil.h"
+
+#ifdef DEBUG
+#include "ushyph.h"
+#endif
+
+/*****************************************************************************/
+
+#define LCNT (26+1+4)
+#define SEPCNT 10
+
+typedef struct _THyphenNode
+ {
+ Byte sepcnts[SEPCNT];
+ struct _THyphenNode *Daughters[LCNT];
+ } THyphenNode,*PHyphenNode;
+
+typedef struct _THyphenException
+ {
+ struct _THyphenException *next;
+ char *word;
+ int poscnt,*posis;
+ } THyphenException,*PHyphenException;
+
+#define INTCHR_AE '\344'
+#define INTCHR_OE '\366'
+#define INTCHR_UE '\374'
+#define INTCHR_SZ '\337'
+
+/*****************************************************************************/
+
+static PHyphenNode HyphenRoot=Nil;
+static PHyphenException FirstException=Nil;
+
+/*****************************************************************************/
+
+ char mytolower(char ch)
+BEGIN
+ return tolower(((unsigned int) ch)&0xff);
+END
+
+#if 0
+char b[10];
+
+ static void PrintNode(PHyphenNode Node, int Level)
+BEGIN
+ int z;
+
+ for (z=1; z<Level; z++) putchar(' ');
+ for (z=1; z<=Level; z++) putchar(b[z]);
+ for (z=0; z<SEPCNT; z++) if (Node->sepcnts[z]>0) break;
+ if (z<SEPCNT) putchar('!'); printf(" %p",Node);
+ puts("");
+ for (z=0; z<LCNT; z++)
+ if (Node->Daughters[z]!=Nil)
+ BEGIN
+ b[Level+1]=z+'a'-1; PrintNode(Node->Daughters[z],Level+1);
+ END
+END
+#endif
+
+ static int GetIndex(char ch)
+BEGIN
+ if ((mytolower(ch)>='a'-1) AND (mytolower(ch)<='z')) return (mytolower(ch)-('a'-1));
+ else if (ch=='.') return 0;
+#ifndef CHARSET_ASCII7
+ else if ((ch==*CH_ae) OR (ch==*CH_Ae) OR (ch==INTCHR_AE)) return 27;
+ else if ((ch==*CH_oe) OR (ch==*CH_Oe) OR (ch==INTCHR_OE)) return 28;
+ else if ((ch==*CH_ue) OR (ch==*CH_Ue) OR (ch==INTCHR_UE)) return 29;
+ else if ((ch==*CH_sz) OR (ch==INTCHR_SZ)) return 30;
+#endif
+ else { printf("unallowed character %d\n",ch); return -1; }
+END
+
+ static void InitHyphenNode(PHyphenNode Node)
+BEGIN
+ int z;
+
+ for (z=0; z<LCNT; Node->Daughters[z++]=Nil);
+ for (z=0; z<SEPCNT; Node->sepcnts[z++]=0);
+END
+
+ void BuildTree(char **Patterns)
+BEGIN
+ char **run,ch,*pos,sing[500],*rrun;
+ Byte RunCnts[SEPCNT];
+ int z,l,rc,index;
+ PHyphenNode Lauf;
+
+ HyphenRoot=(PHyphenNode) malloc(sizeof(THyphenNode));
+ InitHyphenNode(HyphenRoot);
+
+ for (run=Patterns; *run!=NULL; run++)
+ BEGIN
+ strcpy(sing,*run); rrun=sing;
+ do
+ BEGIN
+ pos=strchr(rrun,' '); if (pos!=Nil) *pos='\0';
+ l=strlen(rrun); rc=0; Lauf=HyphenRoot;
+ for (z=0; z<SEPCNT; RunCnts[z++]=0);
+ for (z=0; z<l; z++)
+ BEGIN
+ ch=rrun[z];
+ if ((ch>='0') AND (ch<='9')) RunCnts[rc]=ch-'0';
+ else
+ BEGIN
+ index=GetIndex(ch);
+ if (Lauf->Daughters[index]==Nil)
+ BEGIN
+ Lauf->Daughters[index]=(PHyphenNode) malloc(sizeof(THyphenNode));
+ InitHyphenNode(Lauf->Daughters[index]);
+ END
+ Lauf=Lauf->Daughters[index]; rc++;
+ END
+ END
+ memcpy(Lauf->sepcnts,RunCnts,sizeof(Byte)*SEPCNT);
+ if (pos!=Nil) rrun=pos+1;
+ END
+ while (pos!=Nil);
+ END
+END
+
+ void AddException(char *Name)
+BEGIN
+ char tmp[300],*dest,*src;
+ int pos[100];
+ PHyphenException New;
+
+ New=(PHyphenException) malloc(sizeof(THyphenException));
+ New->next=FirstException;
+ New->poscnt=0; dest=tmp;
+ for (src=Name; *src!='\0'; src++)
+ if (*src=='-') pos[New->poscnt++]=dest-tmp;
+ else *(dest++)=*src;
+ *dest='\0';
+ New->word=strdup(tmp);
+ New->posis=(int *) malloc(sizeof(int)*New->poscnt);
+ memcpy(New->posis,pos,sizeof(int)*New->poscnt);
+ FirstException=New;
+END
+
+ void DestroyNode(PHyphenNode Node)
+BEGIN
+ int z;
+
+ for (z=0; z<LCNT; z++)
+ if (Node->Daughters[z]!=Nil) DestroyNode(Node->Daughters[z]);
+ free(Node);
+END
+
+ void DestroyTree(void)
+BEGIN
+ PHyphenException Old;
+
+ if (HyphenRoot!=Nil) DestroyNode(HyphenRoot); HyphenRoot=Nil;
+
+ while (FirstException!=Nil)
+ BEGIN
+ Old=FirstException; FirstException=Old->next;
+ free(Old->word); if (Old->poscnt>0) free(Old->posis);
+ END
+END
+
+ void DoHyphens(char *word, int **posis, int *posicnt)
+BEGIN
+ char Field[300];
+ Byte Res[300];
+ int z,z2,z3,l;
+ PHyphenNode Lauf;
+ PHyphenException Ex;
+
+ for (Ex=FirstException; Ex!=Nil; Ex=Ex->next)
+ if (strcasecmp(Ex->word,word)==0)
+ BEGIN
+ *posis=(int *) malloc(sizeof(int)*Ex->poscnt);
+ memcpy(*posis,Ex->posis,sizeof(int)*Ex->poscnt);
+ *posicnt=Ex->poscnt;
+ return;
+ END
+
+ l=strlen(word); *posicnt=0;
+ *Field='a'-1;
+ for (z=0; z<l; z++)
+ BEGIN
+ Field[z+1]=tolower((unsigned int) word[z]);
+ if (GetIndex(Field[z+1])<=0) return;
+ END
+ Field[l+1]='a'-1; l+=2;
+ for (z=0; z<=l+1; Res[z++]=0);
+
+ if (HyphenRoot==Nil) return;
+
+ for (z=0; z<l; z++)
+ BEGIN
+ Lauf=HyphenRoot;
+ for (z2=z; z2<l; z2++)
+ BEGIN
+ Lauf=Lauf->Daughters[GetIndex(Field[z2])];
+ if (Lauf==Nil) break;
+#ifdef DEBUG
+ for (z3=0; z3<SEPCNT; z3++) if (Lauf->sepcnts[z3]>0) break;
+ if (z3<SEPCNT)
+ BEGIN
+ printf("Apply pattern ");
+ for (z3=z; z3<=z2; putchar(Field[z3++]));
+ printf(" at position %d with values",z);
+ for (z3=0; z3<SEPCNT; printf(" %d",Lauf->sepcnts[z3++]));
+ puts("");
+ END
+#endif
+ for (z3=0; z3<=z2-z+2; z3++)
+ if (Lauf->sepcnts[z3]>Res[z+z3]) Res[z+z3]=Lauf->sepcnts[z3];
+ END
+ END
+
+#ifdef DEBUG
+ for (z=0; z<l; z++) printf(" %c",Field[z]); puts("");
+ for (z=0; z<=l; z++) printf("%d ",Res[z]); puts("");
+ for (z=0; z<l-2; z++)
+ BEGIN
+ if ((z>0) AND ((Res[z+1])&1)) putchar('-');
+ putchar(Field[z+1]);
+ END
+ puts("");
+#endif
+
+ *posis=(int *) malloc(sizeof(int)*l); *posicnt=0;
+ for (z=3; z<l-2; z++)
+ if ((Res[z]&1)==1) (*posis)[(*posicnt)++]=z-1;
+ if (*posicnt==0)
+ BEGIN
+ free(*posis); *posis=Nil;
+ END
+END
+
+/*****************************************************************************/
+
+#ifdef DEBUG
+ int main(int argc, char **argv)
+BEGIN
+ int z,z2,cnt,*posis,posicnt;
+
+ BuildTree(USHyphens);
+ for (z=1; z<argc; z++)
+ BEGIN
+ DoHyphens(argv[z],&posis,&cnt);
+ for (z2=0; z2<cnt; printf("%d ",posis[z2++])); puts("");
+ if (posicnt>0) free(posis);
+ END
+/* DoHyphens("hyphenation");
+ DoHyphens("concatenation");
+ DoHyphens("supercalifragilisticexpialidocous");*/
+END
+#endif
diff --git a/findhyphen.h b/findhyphen.h
new file mode 100644
index 0000000..9086e1c
--- /dev/null
+++ b/findhyphen.h
@@ -0,0 +1,9 @@
+extern char mytolower(char ch);
+
+extern void BuildTree(char **Patterns);
+
+extern void AddException(char *Name);
+
+extern void DoHyphens(char *word, int **posis, int *posicnt);
+
+extern void DestroyTree(void);
diff --git a/grhyph.c b/grhyph.c
new file mode 100644
index 0000000..56d878e
--- /dev/null
+++ b/grhyph.c
@@ -0,0 +1,569 @@
+/* grhyph.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Trennungsmuster deutsch */
+/* abgeleitet von 'ghyph31.tex' aus TeX */
+/* */
+/* Historie: 16. 2.1998 Konvertierung */
+/* 2. 7.1998 für MSDOS auskommentiert */
+/* */
+/*****************************************************************************/
+
+#include <stdio.h>
+
+/*
+% This is `ghyph31.tex' as of 13. Feb 94.
+%
+% Copyright (C) 1988,1991 Rechenzentrum der Ruhr-Universitaet Bochum
+% [german hyphen patterns]
+% Copyright (C) 1993,1994 Bernd Raichle/DANTE e.V.
+% [macros, adaption for TeX 2]
+%
+% General permission for use and non-profit redistribution is granted.
+% For special commercial use, contact the below address.
+%
+% Commercial use is generally granted, if a reference copy
+% - for use by the Rechenzentrum of the Ruhr-Universitaet -
+% is received.
+%
+%
+% This file contains 5719 german hyphen patterns with umlauts
+% in the recommended version of September 27, 1990.
+% It is an experimental version for testing the integration of
+% umlauts and `es-zett', but without `c-k' and triple consonants.
+%
+% For use with TeX generated by
+%
+% Norbert Schwarz
+% Rechenzentrum Ruhr-Universitaet Bochum
+% Universitaetsstrasse 150
+% D-44721 Bochum, FRG
+%
+% Email (X.400):
+% Norbert.Schwarz@RUBA.RZ.RUHR-UNI-BOCHUM.DBP.DE
+%
+%
+% Adaption of these patterns for TeX, Version 2.x and 3.x and
+% all fonts in `Cork'/EC/DC and/or CM encoding by
+%
+% Bernd Raichle
+% Stettener Str. 73
+% D-73732 Esslingen, FRG
+% Email: raichle@Informatik.Uni-Stuttgart.DE
+%
+%
+% Error reports in case of UNCHANGED versions to
+%
+% DANTE e.V., Koordinator `german.sty'
+% Postfach 10 18 40
+% D-69008 Heidelberg, FRG
+% Email: german@Dante.DE
+%
+% or one of the addresses given above.
+%
+% Changes:
+% 1990-09-27 First version of `ghyphen3.tex' (Norbert Schwarz)
+% 1991-02-13 PC umlauts changed to ^^xx (Norbert Schwarz)
+% 1993-08-27 Umlauts/\ss changed to "a/\3 macros, added macro
+% definitions and additional logic to select correct
+% patterns/encoding (Bernd Raichle)
+% 1994-02-13 Release of `ghyph31.tex'
+%
+%
+% For more informations see the additional documentation
+% at the end of this file.
+%
+% -----------------------------------------------------------------
+%
+\message{German Hyphenation Patterns `ghyphen' Version 3.1a <94/02/13>}
+%
+\begingroup
+\ifnum 0\ifx\inputlineno\undefined \else
+ \ifnum\inputlineno<1 \else 1\fi\fi<1
+ \let\x=\endgroup
+\else
+ \def\x{\endgroup
+%
+% The following commands ensure correct \catcodes, \lccodes and
+% \uccodes if your TeX implementations uses these character codes.
+%
+\catcode"E4=11 \catcode"C4=11 % \"a \"A
+\catcode"F6=11 \catcode"D6=11 % \"o \"O
+\catcode"FC=11 \catcode"DC=11 % \"u \"U
+\catcode"FF=11 \catcode"DF=11 % \ss SS
+%
+\lccode"C4="E4 \uccode"C4="C4 \lccode"E4="E4 \uccode"E4="C4
+\lccode"D6="F6 \uccode"D6="D6 \lccode"F6="F6 \uccode"F6="D6
+\lccode"DC="FC \uccode"DC="DC \lccode"FC="FC \uccode"FC="DC
+\lccode"DF="FF \uccode"DF="DF \lccode"FF="FF \uccode"FF="DF
+%
+}
+\fi
+% Now execute the changes of the above \*codes for TeX 3.x
+\x
+
+
+%
+% Next we define some commands, which are used inside the patterns.
+% To keep them local, we enclose the rest of the file in a group
+% (The \patterns command globally changes the hyphenation trie!).
+%
+\begingroup
+%
+% Because we use ^^e4, ^^f6, ... in the following definition,
+% we have to ensure that the catcodes of ^^e and ^^f are ok
+% for TeX 2. (The macro is not used for TeX 2.)
+\catcode"0E=12 \catcode"0F=12
+%
+% And we have to change the \lccode of ^^Y to make sure that
+% we can include this character in the hyphenation patterns.
+\catcode`\^^Y=11 \lccode`\^^Y=`\^^Y
+%
+% Define a simple " macro...
+\catcode`\"=13
+\def"#1{\ifx#1a^^e4\else \ifx#1o^^f6\else
+ \ifx#1u^^fc\else
+ \errmessage{Hyphenation pattern file corrupted!}%
+ \fi\fi\fi}
+%
+% ... and define a macro to allow the use of this file
+% with TeX 2 and TeX 3.
+\ifnum 0\ifx\inputlineno\undefined \else
+ \ifnum\inputlineno<1 \else 1\fi\fi<1
+ % for TeX 2:
+ % ignore the patterns with umlauts
+ \def\n#1{}
+ % ignore the duplicated patterns with \ss
+ \def\c#1{}
+ % define \3 to be code ^^Y
+ \def\3{^^Y}
+\else
+ % for TeX 3:
+ % patterns with umlauts are ok
+ \def\n#1{#1}
+ % duplicated patterns are ok (for CM fonts)
+ \def\c#1{#1}
+ % >>>>>> UNCOMMENT the next line, if you do not want
+ % >>>>>> to use fonts with CM layout
+ %\def\c#1{}
+ % define \3 to be code `\^^ff (\ss in DC/EC font layout)
+ % define \9 to be code `\^^Y (\ss in CM font layout)
+ \def\3{^^ff}
+ \def\9{^^Y}
+\fi
+*/
+
+#ifndef __MSDOS__
+char *GRHyphens[]={
+ ".aa6l .ab3a4s .ab3ei .abi2 .ab3it .ab1l .ab1r .ab3u .ad3o4r .alti6 .ana3c .an5alg .an1e .ang8s .an1s .ap1p .ar6sc .ar6ta .ar6tei .as2z",
+ ".au2f1 .au2s3 .be5erb .be3na .ber6t5r .bie6r5 .bim6s5t .brot3 .bru6s .ch6 .che6f5 .da8c .da2r .dar5in .dar5u .den6ka .de5r6en .des6pe",
+ ".de8spo .de3sz .dia3s4 .dien4 .dy2s1 .ehren5 .eine6 .ei6n5eh .ei8nen .ein5sa .en6der .en6d5r .en3k4 .en8ta8 .en8tei .en4t3r .epo1 .er6ban",
+ ".er6b5ei .er6bla .er6d5um .er3ei .er5er .er3in .er3o4b .erwi5s .es1p .es8t .ex1a2 .ex3em .fal6sc .fe6st5a .flu4g3 .furch8 .ga6ner .ge3n4a",
+ ".ge5rö .ges6 .halb5 .halbe6 .hal6br .haup4 .hau4t .heima6 .he4r3e .her6za .he5x .hin3 .hir8sc .ho4c .hu3sa .hy5o .ibe5 .ima6ge .in1",
+ ".ini6 .is5chi .jagd5 .kal6k5o .ka6ph .ki4e .kop6f3 .kraf6 .kü5ra .lab6br .liie6 .lo6s5k .lö4s3t .ma5d .mi2t1 .no6th .no6top",
+ ".obe8ri .ob1l .obs2 .ob6st5e .or3c .ort6s5e .ost3a .oste8r .pe4re .pe3ts .ph6 .po8str .rau4m3 .re5an .ro8q .ru5the .rü5be",
+ ".rü8stet .sch8 .se6e .se5n6h .se5ra .si2e .spi6ke .st4 .sy2n .tages5 .tan6kl .ta8th .te6e .te8str .to6der .to8nin .to6we .um1",
+ ".umpf4 .un1 .une6 .unge5n .ur1c .ur5en .ve6rin .vora8 .wah6l5 .we8ges .wo6r .wor3a .wun4s .zi4e .zuch8 .ände8re .öch8 aa1c aa2gr",
+ "aal5e aa6r5a a5arti aa2s1t aat2s 6aba ab3art 1abdr 6abel aben6dr ab5erk ab5err ab5esse 1abf 1abg 1abhä ab1ir 1abko a1bl ab1la",
+ "5ablag a6blaß ab4ler ab1lu a8blä 5a6blö abma5c 1abn ab1ra ab1re 5a6brec ab1ro ab1s ab8sk abs2z 3abtei ab1ur 1abw",
+ "5abze 5abzu ab1än abäu8 a4ce. a5chal ach5art ach5au a1che a8chent ach6er. a6ch5erf a1chi ach1l ach3m ach5n a1cho ach3re a1chu",
+ "ach1w a1chy ach5äf ack1o acks6t ack5sta a1d 8ad. a6d5ac ad3ant ad8ar 5addi a8dein ade5o8 adi5en 1adj 1adle ad1op a2dre 3adres adt1",
+ "1adv a6dä a1e2d ae1r a1er. 1aero 8afa a3fal af1an a5far a5fat af1au a6fentl a2f1ex af1fr af5rau af1re 1afri af6tent af6tra aft5re",
+ "a6f5um 8afä ag5abe 5a4gent ag8er ages5e 1aggr ag5las ag1lo a1gn ag2ne 1agog a6g5und a1ha a1he ah5ein a4h3erh a1hi ahl1a ah1le ah4m3ar",
+ "ahn1a a5ho ahra6 ahr5ab ah1re ah8rei ahren8s ahre4s3 ahr8ti ah1ru a1hu ah8ö ai3d2s ai1e aif6 a3inse ai4re. a5isch. ais8e a3ismu ais6n",
+ "aiso6 a1j 1akad a4kade a1ke a1ki 1akko 5akro1 a5lal al5ans 3al8arm al8beb al8berw alb5la 3album al1c a1le a6l5e6be a4l3ein a8lel a8lerb",
+ "a8lerh a6lert 5a6l5eth 1algi al4gli al3int al4lab al8lan al4l3ar alle3g a1lo a4l5ob al6schm al4the altist5 al4t3re 8a1lu alu5i a6lur",
+ "alu3ta a1lä a6mate 8ame. 5a6meise am6m5ei am6mum am2n ampf3a am6schw am2ta a1mu a1mä a3nac a1nad anadi5e an3ako an3alp 3analy",
+ "an3ame an3ara a1nas an5asti a1nat anat5s an8dent ande4s3 an1ec an5eis an1e2k 4aner. a6n5erd a8nerf a6n5erke 1anfa 5anfert 1anfä 3angab",
+ "5angebo an3gli ang6lis an2gn 3angri ang5t6 5anhä ani5g ani4ka an5i8on an1kl an6kno an4kro 1anl anma5c anmar4 3annah anne4s3 a1no",
+ "5a6n1o2d 5a6n3oma 5a6nord 1anr an1sa 5anschl an4soz an1st 5anstal an1s2z 5antenn an1th 5anwä a5ny an4z3ed 5anzeig 5anzieh 3anzug",
+ "an1ä 5anäs a1nö anö8d a1os a1pa 3apfel a2ph1t aph5ä6 a1pi 8apl apo1c apo1s a6poste a6poth 1appa ap1pr a1pr",
+ "a5pä a3pü a1ra a4r3af ar3all 3arbei 2arbt ar1c 2a1re ar3ein ar2gl 2a1ri ari5es ar8kers ar6les ar4nan ar5o6ch ar1o2d a1rol ar3ony",
+ "a8ror a3ros ar5ox ar6schl 8artei ar6t5ri a1ru a1ry 1arzt arz1w ar8zä arä8m arö6 ar5öm ar1ü2 a1sa a6schec",
+ "asch5l asch3m a6schn a3s4hi as1pa asp5l a8steb as5tev 1asth a6stoc a1str ast3re 8a1ta ata5c ata3la a6tapf ata5pl a1te a6teli aten5a",
+ "ate5ran 6atf 6atg a1th at3hal 1athl 2a1ti 5atlant 3atlas 8atmus 6atn a1to a6t5ops ato6ra a6t5ort. 4a1tr a6t5ru at2t1h at5t6hä 6a1tu",
+ "atz1w a1tä a1tü au1a au6bre auch3a au1e aue4l 5aufent 3auffü 3aufga 1aufn auf1t 3auftr 1aufw 3auge. au4kle aule8s 6aum",
+ "au8mar aum5p 1ausb 3ausd 1ausf 1ausg au8sin 3auss au4sta 1ausw 1ausz aut5eng au1th 1auto auße8 a1v ave5r6a aver6i a1w a6wes a1x",
+ "a2xia a6xio a1ya a1z azi5er. 8aß 1ba 8ba8del ba1la ba1na ban6k5r ba5ot bardi6n ba1ro basten6 bau3sp 2b1b bb6le b2bli 2b1c 2b1d",
+ "1be be1a be8at. be1ch 8becht 8becke. be5el be1en bee8rei be5eta bef2 8beff be1g2 behö8 bei1s 6b5eisen bei3tr b8el bel8o belu3t be3nac",
+ "bend6o be6ners be6nerw be4nor ben4se6 bens5el be1nä be1nü be1o2 b8er. be1ra be8rac ber8gab. ber1r be1rü bes8c bes5erh",
+ "bes2p be5tha bet5sc be1un be1ur 8bex be6zwec 2b1f8 bfe6st5e 2b1g2 bga2s5 bge1 2b1h bhole6 1bi bi1bl b6ie bi1el bi1la bilä5 bi1na",
+ "bi4nok bi5str bi6stu bi5tr bit4t5r b1j 2b1k2 bkü6 bl8 b6la. 6b1lad 6blag 8blam 1blat b8latt 3blau. b6lav 3ble. b1leb b1led",
+ "8b1leg 8b1leh 8bleid 8bleih 6b3lein blei3s ble4m3o 4blich b4lind 8bling b2lio 5blit b4litz b1loh 8b1los 1blu 5blum 2blun blut3a blut5sc",
+ "3blä bläs5c 5blö 3blü blü8sc 2b1m 2b1n 1bo bo1ch bo5d6s boe5 8boff 8bonk bo1ra b1ort 2b1p2 b1q 1br brail6 brast8",
+ "bre4a b5red 8bref 8b5riem b6riga bro1s b1rup b2ruz 8bröh brös5c 8bs b1sa b8sang b2s1ar b1sc bs3erl bs3erz b8sof b1s2p",
+ "bst1h b3stru b5stä b6sun 2b1t b2t1h 1bu bu1ie bul6k b8ure bu6sin 6b1v 2b1w 1by1 by6te. 8b1z bzi1s 1bä b5ä6s5 1bü",
+ "b6ü5bere büge6 bügel5e bür6sc 1ca cag6 ca5la ca6re ca5y c1c 1ce celi4c celich5 ce1ro c8h 2ch. 1chae ch1ah ch3akt cha6mer",
+ "8chanz 5chara 3chari 5chato 6chb 1chef 6chei ch3eil ch3eis 6cherkl 6chf 4chh 5chiad 5chias 6chins 8chj chl6 5chlor 6ch2m 2chn6 ch8nie",
+ "5cho. 8chob choi8d 6chp ch3ren ch6res ch3rü 2chs 2cht cht5ha cht3hi 5chthon ch6tin 6chuh chu4la 6ch3unt chut6t 8chw 1ci ci5tr c2k",
+ "2ck. ck1ei 4ckh ck3l ck3n ck5o8f ck1r 2cks ck5stra ck6s5u c2l 1c8o con6ne 8corb cos6t c3q 1c6r 8c1t 1cu 1cy 5cä1 cö5 1da.",
+ "8daas 2dabg 8dabr 6dabt 6dabw 1dac da2gr 6d5alk 8d5amt dan6ce. dani5er dan8ker 2danl danla6 6dans 8danzi 6danzu d1ap da2r1a8 2d1arb",
+ "d3arc dar6men 4d3art 8darz 1dat 8datm 2d1auf 2d1aus 2d1b 2d1c 2d1d d5de d3d2h ddämme8 1de 2deal de5an de3cha de1e defe6 6deff 2d1ehr",
+ "5d4eic de5isc de8lar del6s5e del6spr de4mag de8mun de8nep dene6r 8denge. 8dengen de5o6d 2deol de5ram 8derdb der5ein de1ro der1r d8ers",
+ "der5um de4s3am de4s3an de4sau de6sil de4sin de8sor de4spr de2su 8deul de5us. 2d1f df2l 2d1g 2d1h 1di dia5c di5ara dice5 di3chr di5ena di1gn",
+ "di1la dil8s di1na 8dind 6dinf 4d3inh 2d1ins di5o6d di3p4t di8sen dis1p di5s8per di6s5to dis5tra di8tan di8tin d1j 6dje 2dju 2d1k 2d1l 2d1m",
+ "2d1n6 dni6 dnje6 1do 6d5obe do6berf 6d5ony do3ran 6dord 2d1org dor4t3h do6ste 6doth dott8e 2d1p d5q dr4 1drah 8drak d5rand 6dre. 4drech",
+ "d6reck 4d3reg 8d3reic d5reife 8drem 8d1ren 2drer 8dres. 6d5rh 1dria d1ric 8drind droi6 dro5x 1dru 8drut drös5c 1drü drü5b",
+ "drü8sc 2ds d1sa d6san dsat6 d1sc 5d6scha. 5dschik dse8e d8serg 8dsl d1sp d4spak ds2po d8spä d1st d1sü 2dt d1ta d1te d1ti",
+ "d1to dt1s6 d1tu d5tä 1du du5als du1b6 du1e duf4t3r 4d3uh du5ie 8duml 8dumw 2d1und du8ni 6d5unt dur2c durch3 6durl 6dursa 8durt du1s",
+ "du8schr 2d1v 2d1w dwa8l 2d1z 1dä 6däh 8dänd dä6r dö8bl d5öl dör6fl dö8sc d5ö4st dös3te",
+ "1dü ea4ben e1ac e1ah e1akt e1al. e5alf e1alg e5a8lin e1alk e1all e5alp e1alt e5alw e1am e1and ea6nim e1ar. e5arf e1ark e5arm e3art",
+ "e5at. e6ate e6a5t6l e8ats e5att e6au. e1aus e1b e6b5am ebens5e eb4lie eb4ser eb4s3in e1che e8cherz e1chi ech3m 8ech3n ech1r ech8send",
+ "ech4su e1chu eck5an e5cl e1d ee5a ee3e ee5g e1ei ee5isc eei4s3t ee6lend e1ell ee5lö e1erd ee3r4e ee8reng eere6s5 ee5rä",
+ "ee6tat e1ex e1f e6fau e8fe8b 3effek ef3rom ege6ra eglo6si 1egy e1ha e6h5ach eh5ans e6hap eh5auf e1he e1hi ehl3a eh1le ehl5ein eh1mu ehn5ec",
+ "e1ho ehr1a eh1re ehre6n eh1ri eh1ru ehr5um e1hu eh1w e1hy e1hä e1hö e3hüt ei1a eia6s ei6bar eich3a eich5r ei4dar ei6d5ei",
+ "ei8derf ei3d4sc ei1e 8eifen 3eifri 1eign eil1d ei6mab ei8mag ein1a4 ei8nat ei8nerh ei8ness ei6nete ein1g e8ini ein1k ei6n5od ei8nok ei4nor",
+ "e3insä ei1o e1irr ei5ru ei8sab ei5schn ei6s5ent ei8sol ei4t3al eit3ar eit1h ei6thi ei8tho eit8samt ei6t5um e1j 1ekd e1ke e1ki e1k2l",
+ "e1kn ekni4 e1la e2l1al 6elan e6lanf e8lanl e6l5ans el3arb el3arm e6l3art 5e6lasti e6lauge elbst5a e1le 6elef ele6h e6l5ehe e8leif",
+ "e6l5einh 1elek e8lel 3eleme e6lemen e6lente el5epi e4l3err e6l5ersc elf2l elg2 e6l5ins ell8er 4e1lo e4l3ofe el8soh el8tent 5eltern e1lu",
+ "elut2 e1lä e1lü em8dei em8meis 4emo emo5s 1emp1f 1empt 1emto e1mu emurk4 emurks5 e1mä en5a6ben en5achs en5ack e1nad en5af",
+ "en5all en3alt en1am en3an. en3ant en3anz en1a6p en1ar en1a6s 6e1nat en3auf en3aus en2ce enda6l end5erf end5erg en8dess 4ene. en5eck",
+ "e8neff e6n5ehr e6n5eim en3eis 6enem. 6enen e4nent 4ener. e8nerd e6n3erf e4nerg 5energi e6n5erla en5ers e6nerst en5erw 6enes e6n5ess",
+ "e2nex en3glo 2eni enni6s5 ennos4 enns8 e1no e6nober eno8f en5opf e4n3ord en8sers ens8kl en1sp ens6por en5t6ag enta5go en8terbu en6tid",
+ "3entla ent5ric 5entwic 5entwu 1entz enu5i e3ny en8zan en1öf e1nös e1nüg eo1c e5o6fe e5okk e1on. e3onf e5onk e5onl e5onr",
+ "e5opf e5ops e5or. e1ord e1org eo5r6h eo1t e1pa e8pee e6p5e6g ep5ent e1p2f e1pi 5epid e6pidem e1pl 5epos e6pos. ep4p3a e1pr e1pä e1q",
+ "e1ra. er5aal 8eraba e5rabel er5a6ben e5rabi er3abs er3ach era5e era5k6l er3all er3amt e3rand e3rane er3ans e5ranz. e1rap er3arc",
+ "e3rari er3a6si e1rat erat3s er3auf e3raum 3erbse er1c e1re 4e5re. er3eck er5egg er5e2h 2erei e3rei. e8reine er5einr 6eren. e4r3enm",
+ "4erer. e6r5erm er5ero er5erst e4r3erz er3ess 5erfül er8gan. 5ergebn er2g5h 5ergänz 5erhöhu 2e1ri eri5ak e6r5iat e4r3ind",
+ "e6r5i6n5i6 er5ins e6r5int er5itio er1kl 3erklä 5erlös. ermen6s er6nab 3ernst 6e1ro. e1rod er1o2f e1rog 6e3roi ero8ide e3rol",
+ "e1rom e1ron e3rop8 e2r1or e1ros e1rot er5ox ersch4 5erstat er6t5ein er2t1h er5t6her 2e1ru eruf4s3 e4r3uhr er3ums e5rus 5erwerb e1ry er5zwa",
+ "er3zwu erä8m er5äs erö8 e3rös. e6r1ü2b e1sa esa8b e8sap e6s5a6v e1sc esch4l ese1a es5ebe eserve5 e8sh es5ill",
+ "es3int es4kop e2sl eso8b e1sp espei6s5 es2po es2pu 5essenz e6stabs e6staf e6st5ak est3ar e8stob e1str est5res es3ur e2sz e1sü e1ta",
+ "et8ag etari5e eta8ta e1te eten6te et5hal e5thel e1ti 1etn e1to e1tr et3rec e8tscha et8se et6tei et2th et2t1r e1tu etu1s et8zent et8zw",
+ "e1tä e1tö e1tü eu1a2 eu1e eue8rei eu5fe euin5 euk2 e1um. eu6nio e5unter eu1o6 eu5p 3europ eu1sp eu5str eu8zo e1v eval6s",
+ "eve5r6en ever4i e1w e2wig ex1or 1exp 1extr ey3er. e1z e1ä2 e5ö8 e1ü e8ßes fa6ch5i fade8 fa6del fa5el.",
+ "fal6lo falt8e fa1na fan4gr 6fanl 6fap far6ba far4bl far6r5a 2f1art fa1sc fau8str fa3y 2f1b2 6f1c 2f1d 1fe 2f1eck fe6dr feh6lei f6eim",
+ "8feins f5eis fel5en 8feltern 8femp fe5rant 4ferd. ferri8 fe8stof fe6str fe6stum fe8tag fet6ta fex1 2ff f1fa f6f5arm f5fe ffe5in ffe6la",
+ "ffe8ler ff1f f1fla ff3lei ff4lie ff8sa ff6s5ta 2f1g2 fgewen6 4f1h 1fi fid4 fi3ds fieb4 fi1la fi8lei fil4m5a f8in. fi1na 8finf fi8scho fi6u",
+ "6f1j 2f1k2 f8lanz fl8e 4f3lein 8flib 4fling f2lix 6f3lon 5flop 1flor 5f8läc 3flöt 2f1m 2f1n 1fo foh1 f2on fo6na 2f1op fo5ra",
+ "for8mei for8str for8th for6t5r fo5ru 6f5otte 2f1p8 f1q fr6 f5ram 1f8ran f8raß f8re. frei1 5frei. f3reic f3rest f1rib",
+ "8f1ric 6frig 1fris fro8na fräs5t 2fs f1sc f2s1er f5str fs3tät 2ft f1tak f1te ft5e6h ftere6 ft1h f1ti f5to f1tr ft5rad",
+ "ft1sc ft2so f1tu ftwi3d4 ft1z 1fu 6f5ums 6funf fun4ka fu8ßend 6f1v 2f1w 2f1z 1fä fä1c 8färm 6fäug",
+ "fä8ß föde3 8föf 3för 1fü fün4f3u 1ga ga6bl 6gabw 8gabz g3a4der ga8ho ga5isc 4gak ga1la",
+ "6g5amt ga1na gan5erb gan6g5a ga5nj 6ganl 8gansc 6garb 2g1arc 2g1arm ga5ro 6g3arti ga8sa ga8sc ga6stre 2g1atm 6g5auf gau5fr g5aus 2g1b g5c",
+ "6gd g1da 1ge ge1a2 ge6an ge8at. ge1e2 ge6es gef2 8geff ge1g2l ge1im 4g3eise geist5r gel8bra gelt8s ge5lö ge8nin gen3k 6g5entf",
+ "ge3nä ge1or ge1ra ge6rab ger8au 8gerhö ger8ins ge1ro 6g5erz. ge1rä ge1rü ge1s ges2p ge5unt 4g3ex3 2g1f8 2g1g g1ha 6g1hei",
+ "5ghel. g5henn 6g1hi g1ho 1ghr g1hö 1gi gi5la gi8me. gi1na 4g3ins gi3str g1j 2g1k 8gl. 1glad g5lag glan4z3 1glas 6glass 5glaub",
+ "g3lauf 1gle. g5leb 3gleic g3lein 5gleis 1glem 2gler 8g3leu gli8a g2lie 3glied 1g2lik 1g2lim g6lio 1gloa 5glom 1glon 1glop g1los g4loss",
+ "g5luf 1g2ly 1glü 2g1m gn8 6gn. 1gna 8gnach 2gnah g1nas g8neu g2nie g3nis 1gno 8gnot 1go goe1 8gof 2gog 5gogr 6g5oh goni5e 6gonist",
+ "go1ra 8gord 2g1p2 g1q 1gr4 g5rahm gra8m gra4s3t 6g1rec gre6ge 4g3reic g5reit 8grenn gri4e g5riem 5grif 2grig g5ring 6groh 2grot gro6ß",
+ "4grut 2gs gs1ab g5sah gs1ak gs1an gs8and gs1ar gs1au g1sc gs1ef g5seil gs5ein g2s1er gs1in g2s1o gso2r gs1pr g2s1u 2g1t g3te",
+ "g2t1h 1gu gu5as gu2e 2gue. 6gued 4g3uh 8gums 6g5unt gu1s gut3h gu2tu 4g1v 2g1w gy1n g1z 1gä 8gä8m 6gärm 1gö 1gü",
+ "6güb 1haa hab8r ha8del hade4n 8hae ha5el. haf6tr 2hal. ha1la hal4b5a 6hale 8han. ha1na han6dr han6ge. 2hani h5anth 6hanz 6harb",
+ "h3arbe h3arme ha5ro ha2t1h h1atm hau6san ha8ß h1b2 h1c h1d he2bl he3cho h3echt he5d6s 5heft h5e6he. hei8ds h1eif 2hein he3ism",
+ "he5ist. heit8s3 hek6ta hel8lau 8helt he6mer 1hemm 6h1emp hen5end hen5klo hen6tri he2nu 8heo he8q her3ab he5rak her3an 4herap her3au",
+ "h3erbi he1ro he8ro8b he4r3um her6z5er he4spe he1st heta6 het5am he5th heu3sc he1xa hey5e h1f2 h1g hgol8 h1h h1iat hie6r5i hi5kt hil1a2",
+ "hil4fr hi5nak hin4ta hi2nu hi5ob hirn5e hir6ner hi1sp hi1th hi5tr 5hitz h1j h6jo h1k2 hlabb4 hla4ga hla6gr h5lai hl8am h1las h1laß",
+ "hl1c h1led h3lein h5ler. h2lif h2lim h8linf hl5int h2lip h2lit h4lor h3lose h1läs hme5e h2nee h2nei hn3eig h2nel hne8n",
+ "hne4p3f hn8erz h6netz h2nip h2nit h1nol hn5sp h2nuc h2nud h2nul hoch1 1hoh hoh8lei 2hoi ho4l3ar 1holz h2on ho1ra 6horg 5horn. ho3sl hos1p",
+ "ho4spi h1p hpi6 h1q 6hr h1rai h8rank h5raum hr1c hrcre8 h1red h3reg h8rei. h4r3erb h8rert hrg2 h1ric hr5ins h2rom hr6t5erl hr2t1h hr6t5ra",
+ "hr8tri h6rum hr1z hs3ach h6s5amt h1sc h6s5ec h6s5erl hs8erle h4sob h1sp h8spaß h8spel hs6po h4spun h1str h4s3tum hs3und",
+ "h1sü h5ta. h5tab ht3ac ht1ak ht3ang h5tanz ht1ar ht1at h5taub h1te h2t1ec ht3eff ht3ehe h4t3eif h8teim h4t3ein ht3eis h6temp h8tentf",
+ "hte8ren h6terfü h8tergr h4t3erh h6t5ersc h8terst h8tese h8tess h2t1eu h4t3ex ht1he ht5hu h1ti ht5rak hts3ah ht1sc ht6sex ht8sk ht8so",
+ "h1tu htz8 h5tüm hub5l hu6b5r huh1l h5uhr. huld5a6 hu8lent hu8lä h5up. h1v h5weib h3weis h1z hä8kl häl8s",
+ "häma8tu8 hä8sche. hät1s häu4s3c 2hö. 2höe 8höi hö6s hös5c hühne6 hül4s3t",
+ "hütte8re i5adn i1af i5ak. i1al. i1al1a i1alb i1ald i5alei i1alf i1alg i3alh i1alk i1all i1alp i1alr i1als i1alt i1alv i5alw i3alz",
+ "i1an. ia5na i3and ian8e ia8ne8b i1ang i3ank i5ann i1ant i1anz i6apo i1ar. ia6rab i5arr i1as. i1asm i1ass i5ast. i1at. i5ats i1au i5azz",
+ "i6b5eig i6b5eis ib2le i4blis i6brig i6b5unt i6büb i1che ich5ei i6cherb i1chi ich5ins ich1l ich3m ich1n i1cho icht5an icht3r i1chu",
+ "ich1w ick6s5te ic5l i1d id3arm 3ideal ide8na 3ideol ide5rö i6diot id5rec id1t ie1a ie6b5ar iebe4s3 ie2bl ieb1r ie8bra ie4bre ie8bä",
+ "ie2dr ie1e8 ie6f5ad ief5f ie2f1l ie4fro ief1t i1ei ie4l3ec ie8lei ie4lek i3ell i1en. i1end ien6e i3enf i5enn ien6ne. i1enp i1enr",
+ "i5ensa ien8stal i5env i1enz ie5o ier3a4b ie4rap i2ere ie4rec ie6r5ein ie6r5eis ier8er i3ern. ie8rum ie8rund ie6s5che ie6tau ie8tert ie5the",
+ "ie6t5ri i1ett ie5un iex5 2if i1fa if5ang i6fau if1fr if5lac i5f6lie i1fre ift5a if6t5r ig3art 2ige i8gess ig5he i5gla ig2ni i5go ig3rot",
+ "ig3s2p i1ha i8ham i8hans i1he i1hi ih1n ih1r i1hu i8hum ih1w 8i1i ii2s ii2t i1j i1k i6kak i8kerz i6kes ik4ler i6k5unt 2il i5lac i1lag il3ans",
+ "i5las i1lau il6auf i1le ile8h i8lel il2fl il3ipp il6l5enn i1lo ilt8e i1lu i1lä i8mart imb2 i8mele i8mid imme6l5a i1mu i1mä",
+ "i5mö ina5he i1nat in1au inau8s 8ind. in4d3an 5index ind2r 3indus i5nec i2n1ei i8nerw 3infek 1info 5ingeni ing5s6o 5inhab ini5er. 5inj",
+ "in8kät in8nan i1no inoi8d in3o4ku in5sau in1sp 5inspe 5instit 5instru ins4ze 5intere 5interv in3the in5t2r i5ny inä2 i1när",
+ "in1äs inö8 in5öd i1nös 2io io1a8 io1c iode4 io2di ioi8 i1ol. i1om. i1on. i5onb ion2s1 i1ont i5ops i5o8pt i1or.",
+ "i3oral io3rat i5orc i1os. i1ot. i1o8x 2ip i1pa i1pi i1p2l i1pr i1q i1ra ir6bl i1re i1ri ir8me8d ir2m1o2 ir8nak i1ro ir5rho ir6schl",
+ "ir6sch5r i5rus i5ry i5rä i1sa i8samt i6sar i2s1au i8scheh i8schei isch5m isch3r ischä8 is8ele ise3ra i4s3erh is3err isi6de i8sind",
+ "is4kop ison5e is6por i8s5tum i5sty i5sö i1ta it5ab. i2t1a2m i8tax i1te i8tersc i1thi i1tho i5thr it8hä i1ti i8ti8d iti6kl",
+ "itmen4 i1to i8tof it3ran it3rau i1tri itri5o it1sc it2se it5spa it8tru i1tu it6z5erg it6z1w i1tä itä6r5e ität2 itäts5",
+ "i1tü i1u iu6r 2i1v i6vad iva8tin i8vei i6v5ene i8verh i2vob i8vur i1w iwi2 i5xa i1xe i1z ize8n i8zir i6z5w iä8m i1ä6r",
+ "i5ät. i5äv i1ö8 iü8 i6ß5ers ja5la je2t3r 6jm 5jo jo5as jo1ra jou6l ju5cha jugen4 jugend5 jung5s6 ju1s",
+ "3jä 1ka 8kachs 8kakz ka1la kal5d kam5t ka1na 2kanl 8kapf ka6pl ka5r6a 6k3arbe ka1ro kar6p5f 4k3arti 8karz ka1rä kasi5e ka6teb",
+ "kat8ta kauf6s kau3t2 2k1b 2k1c 4k1d kehr6s kehrs5a 8keic 2k1eig 6k5ein 6k5eis ke6lar ke8leis ke8lo 8kemp k5ente. k3entf 8k5ents 6kentz ke1ra",
+ "k5erlau 2k1f8 2k1g 2k1h ki5fl 8kik king6s5 6kinh ki5os ki5sp ki5th 8ki8ö 2k1k2 kl8 1kla 8klac k5lager kle4br k3leib 3kleid kle5isc",
+ "4k3leit k3lek 6k5ler. 5klet 2klic 8klig k2lim k2lin 5klip 5klop k3lor 1klä 2k1m kmani5e kn8 6kner k2ni knä8 1k2o ko1a2 ko6de.",
+ "ko1i koi8t ko6min ko1op ko1or ko6pht ko3ra kor6d5er ko5ru ko5t6sc k3ou 3kow 6k5ox 2k1p2 k1q 1kr8 4k3rad 2k1rec 4k3reic kre5ie 2krib 6krig",
+ "2krip 6kroba 2ks k1sa k6sab ksal8s k8samt k6san k1sc k2s1ex k5spat k5spe k8spil ks6por k1spr kst8 k2s1uf 2k1t kta8l kt5a6re k8tein kte8re",
+ "k2t1h k8tinf kt3rec kt1s 1ku ku1ch kuck8 k3uhr ku5ie kum2s1 kunfts5 kun2s kunst3 ku8rau ku4ro kurz1 ku1st 4kusti ku1ta ku8ß",
+ "6k1v 2k1w ky5n 2k1z 1kä kä4m 4k3ämi käse5 1kö kö1c kö1s 1kü kü1c kür6sc kü1s 1la.",
+ "8labf 8labh lab2r 2l1abs lach3r la8dr 5ladu 8ladv 6laff laf5t la2gn 5laken 8lamb la6mer 5lampe. 2l1amt la1na 1land lan4d3a lan4d3r lan4gr",
+ "8lanme 6lann 8lanw 6lanä 8lappa lap8pl lap6pr l8ar. la5ra lar4af la8rag la8ran la6r5a6s l3arbe la8rei 6larm. la8sa la1sc la8sta lat8i",
+ "6l5atm 4lauss 4lauto 1law 2lb l8bab l8bauf l8bede l4b3ins l5blo lbst5an lbst3e 8lc l1che l8chert l1chi lch3m l5cho lch5w 6ld l4d3ei",
+ "ld1re l6düb le2bl le8bre lecht6s5 led2r 6leff le4gas 1lehr lei6br le8inf 8leinn 5leistu 4lektr le6l5ers lemo2 8lemp l8en. 8lends",
+ "6lendun le8nend len8erw 6l5ents 4l3entw 4lentz 8lenzy 8leoz 6lepi le6pip 8lepo 1ler l6er. 8lerbs 6l5erde le8reis le8rend le4r3er 4l3erg",
+ "l8ergr 6lerkl 6l5erzie 8lerö 8lesel lesi5e le3sko le3tha let1s 5leuc 4leuro leu4s3t le5xe 6lexp l1f 2l1g lgend8 l8gh lglie3 lglied6",
+ "6l1h 1li li1ar li1as 2lick li8dr li1en lien6n li8ers li8ert 2ließ 3lig li8ga8b li1g6n li1l8a 8limb li1na 4l3indu lings5",
+ "4l3inh 6linj link4s3 4linkt 2lint 8linv lion5s6t 4lipp 5lipt 4lisam livi5e 6l1j 6l1k l8keim l8kj lk2l lko8f lkor8 lk2sa lk2se 6ll l1la",
+ "ll3a4be l8labt ll8anl ll1b ll1c ll1d6 l1le l4l3eim l6l5eise ller3a l4leti l5lip l1lo ll3ort ll5ov ll6spr llte8 l1lu ll3urg l1lä",
+ "l5lü l6lüb 2l1m l6m5o6d 6ln l1na l1no 8lobl lo6br 3loch. l5o4fen 5loge. 5lohn 4l3ohr 1lok l2on 4l3o4per lo1ra 2l1ord 6lorg",
+ "4lort lo1ru 1los. lo8sei 3losig lo6ve lowi5 6l1p lp2f l8pho l8pn lp4s3te l2pt l1q 8l1r 2ls l1sa l6sarm l1sc l8sec l6s5erg l4s3ers l8sh",
+ "l5s6la l1sp ls4por ls2pu l1str l8suni l1sü 2l1t lt5amp l4t3ein l5ten l6t5eng l6t5erp l4t3hei lt3her l2t1ho l6t5i6b lti1l l8trö",
+ "lt1sc lt6ser lt4s3o lt5ums lu8br lu2dr lu1en8 8lu8fe luft3a luf8tr lu6g5r 2luh l1uhr lu5it 5luk 2l1umf 2l1umw 1lun 6l5u6nio 4l3unte lu5ol",
+ "4lurg 6lurs l3urt lu4sto lu3str lu6st5re lu8su lu6tal lu6t5e6g lu8terg lu3the lu6t5or lu2t1r lu6ß5 l1v lve5r6u 2l1w 1ly lya6",
+ "6lymp ly1no l8zess l8zo8f l3zwei lz5wu 3länd lä5on lä6sc lät1s 5läuf 2läug läu6s5c lä5v",
+ "l1öl 1lös lö1ß6t 6l1übe 1ma 8mabg ma5chan mad2 ma5el 4magg mag8n ma1la ma8lau mal5d 8malde mali5e",
+ "malu8 ma8lut 2m1amp 3man mand2 man3ds 8mangr mani5o 8m5anst 6mappa 4m3arbe mar8kr ma1r4o mar8schm 3mas ma1sc ma1tö 4m5auf ma5yo 2m1b",
+ "mb6r 2m1c 2m1d md6sä 1me me1ch me5isc 5meld mel8sa 8memp me5nal men4dr men8schl men8schw 8mentsp me1ra mer4gl me1ro 3mes me6s5ei me1th",
+ "me8ß 2m1f6 2m1g 2m1h 1mi mi1a mi6ale mi1la 2m1imm mi1na mi5nü mi4s3an mit1h mi5t6ra 3mitt mitta8 mi6ß5 6mj",
+ "2m1k8 2m1l 2m1m m6mad m6m5ak m8menth m8mentw mme6ra m2mn mm5sp mm5ums mmut5s m8män m1n8 m5ni 1mo mo5ar mo4dr 8mof mo8gal mo4kla mol5d",
+ "m2on mon8do mo4n3od mont8a 6m5ony mopa6 mo1ra mor8d5a mo1sc mo1sp 5mot moy5 2mp m1pa mpfa6 mpf3l mphe6 m1pi mpin6 m1pl mp2li m2plu mpo8ste",
+ "m1pr mprä5 mp8th mput6 mpu5ts m1pö 8m1q 2m1r 2ms ms5au m1sc msch4l ms6po m3spri m1str 2m1t mt1ar m8tein m2t1h mt6se mt8sä",
+ "mu5e 6m5uh mumi1 1mun mun6dr muse5e mu1ta 2m1v mvol2 mvoll3 2m1w 1my 2m1z mä6kl 1män mä1s mä5tr mäu4s3c 3mäß",
+ "möb2 6möl 1mü 5mün 3müt 1na. n5ab. 8nabn n1abs n1abz na6bä na2c nach3e 3nacht 1nae na5el",
+ "n1afr 1nag 1n2ah na8ha na8ho 1nai 6nair na4kol n1akt nal1a 8naly 1nama na4mer na1mn n1amp 8n1amt 5nanc nan6ce n1and n6and. 2n1ang 1nani",
+ "1nann n1ans 8nanw 5napf. 1n2ar. na2ra 2n1arc n8ard 1nari n8ark 6n1arm 5n6ars 2n1art n8arv 6natm nat6s5e 1naue 4nauf n3aug 5naui n5auk",
+ "na5um 6nausb 6nauto 1nav 2nax 3naz 1naß n1b2 nbau5s n1c nche5e nch5m 2n1d nda8d n2d1ak nd5ans n2d1ei nde8lac ndel6sa n8derhi",
+ "nde4se nde8stal n2dj ndnis5 n6d5or6t nd3rec nd3rot nd8samt nd6sau ndt1h n8dumd 1ne ne5as ne2bl 6n5ebn 2nec 5neei ne5en ne1g4l 2negy",
+ "4n1ein 8neis 4n3e4lem 8nemb 2n1emp nen1a 6n5energ nen3k 8nentb 4n3en3th 8nentl 8n5entn 8n5ents ne1ra ne5r8al ne8ras 8nerbi 6n5erde.",
+ "nere5i6d nerfor6 6n5erhö 8nerlö 2n1err n8ers. 6n5ertra 2n1erz nesi3e net1h neu4ra neu5sc 8neuß n1f nf5f nf2l",
+ "nflei8 nf5lin nft8st n8g5ac ng5d ng8en nge8ram ngg2 ng1h n6glic ng3rip ng8ru ng2se4 ng2si n2g1um n1gy n8gäl n1h nhe6r5e 1ni ni1bl",
+ "ni5chä ni8dee n6ie ni1en nie6s5te niet5h ni8etn 4n3i6gel n6ik ni1la 2n1imp ni5na 2n1ind 8ninf 6n5inh ni8nit 6n5inn 2n1ins 4n1int",
+ "n6is ni3str ni1th ni1tr n1j n6ji n8kad nk5ans n1ke n8kerla n1ki nk5inh n5klö n1k2n n8k5not nk3rot n8krü nk5spo nk6t5r n8kuh",
+ "n6küb n5l6 nli4mi n1m nmen4s n1na n8nerg nni5o n1no nn4t3ak nnt1h nnu1e n1ny n1nä n1nö n1nü no5a no4b3la 4n3obs 2nobt",
+ "noche8 no6die no4dis no8ia no5isc 6n5o6leu no4mal noni6er 2n1onk n1ony 4n3o4per 6nopf 6nopti no3ra no4ram nor6da 4n1org 2n1ort n6os no1st",
+ "8nost. no8tan no8ter noty6pe 6n5ox n1p2 n1q n1r nrös3 6ns n1sac ns3ang n1sc n8self n8s5erf n8serg n6serk ns5erw n8sint n1s2pe n1spr",
+ "n6s5tat. n5s6te. n6stob n1str n1ta n4t3a4go nt5anh nt3ark nt3art n1te nt3eis nte5n6ar nte8nei nter3a nte6rei nt1ha nt6har n3ther nt5hie",
+ "n3thus n1ti nti1c n8tinh nti1t ntlo6b ntmen8 n1to nt3o4ti n1tr ntra5f ntra5ut nt8rea nt3rec nt8rep n4t3rin nt8rop n4t3rot n4trü nt1s",
+ "nts6an nt2sk n1tu nt1z n1tä n1tö n8töl n1tü 1nu nu1a nu5el nu5en 4n1uhr nu5ie 8numl 6n5ums 6n5umw 2n1und 6nuni 6n5unr",
+ "2n1unt 2nup 2nu6r n5uri nu3skr nu5ta n1v 8n1w 1nys n1za n6zab n2z1ar n6zaus nzi4ga n8zof n6z5unt n1zw n6zwir 1näc 5näe 5näi",
+ "n8äl nä6m nä6re n5ärz 5näus n1öl 1nöt n5öz 5nü. 6n1ü2b 5nüß",
+ "o5ab. oa2l o8ala o1a2m o1an ob1ac obe4ra o6berh 5o4bers o4beru obe6ser 1obj o1bl o2bli ob5sk 3obst. ob8sta obst5re ob5sz o1che",
+ "oche8b o8chec o3chi och1l och3m ocho8f o3chro och3to o3chu och1w o1d o2d1ag od2dr ode5i ode6n5e od1tr o5e6b o5e6der. oe8du o1ef o1e2l",
+ "o1e2p o1er. o5e8x o1fa of8fan 1offi of8fin of6f5la o5fla o1fr 8o1g og2n o1ha o1he o6h5eis o1hi ohl1a oh1le oh4l3er 5ohm. oh2ni o1ho",
+ "oh1re oh1ru o1hu oh1w o1hy o1hä o5ia o1id. o8idi oi8dr o5ids o5isch. oiset6 o1ism o3ist. o5i6tu o1j o1k ok2l ok3lau o8klä",
+ "1okta o1la old5am old5r o1le ole5in ole1r ole3u ol6gl ol2kl olk4s1 ol8lak ol8lauf. ol6lel ol8less o1lo ol1s ol6sk o1lu oly1e2 5olym",
+ "o2mab om6an o8mau ombe4 o8merz om5sp o1mu o8munt o1mä o1mö o1na ona8m on1ax on8ent o6n5erb 8oni oni5er. on1k on6n5a6b o1no ono1c",
+ "o4nokt 1ons onts8 o1nä oo8f 1oog oo2pe oo2sa o1pa 3o4pera o3pfli opf3lo opf3r o1pi o1pl o2pli o5p6n op8pa op6pl o1pr o3p4ter 1opti",
+ "o1pä o5pö o1q o1ra. o3rad o8radd 1oram o6rang o5ras o8rauf or5cha or4d3a4m or8dei or8deu 1ordn or4dos o1re o5re. ore2h o8r5ein",
+ "ore5isc or6enn or8fla or8fli 1orga 5orgel. or2gl o1ri 5o6rient or8nan or8nä o1ro or1r2h or6t5an or8tau or8tere o1rus o1ry o1rä",
+ "or1ü2 o1sa osa3i 6ose o8serk o1sk o6ske o6ski os2kl os2ko os2kr osni5e o2s1o2d o3s4per o4stam o6stau o3stra ost3re osu6 o6s5ur o5s6ze",
+ "o1ta ot3auf o6taus o1te o6terw o1th othe5u o2th1r o1ti o1to oto1a ot1re o1tri o1tro ot1sc o3tsu ot6t5erg ot2t3h ot2t5r ot8tö o1tu",
+ "ou3e ouf1 ou5f6l o5u6gr ou5ie ou6rar ou1t6a o1v o1wa o1we o6wer. o1wi owid6 o1wo o5wu o1xe oy5al. oy1e oy1i o5yo o1z oza2r 1o2zea ozo3is",
+ "oö8 oß5elt oß1t 3paa pa6ce 5pad pag2 1pak pa1la pa8na8t pani5el pa4nor pan1s2 1pap pap8s pa8rei par8kr paro8n",
+ "par5o6ti part8e 5partei 3partn pas6sep pa4tha 1pau 6paug pau3sc p1b 8p5c 4p1d 1pe 4peic pe5isc 2pek pen3k pen8to8 p8er pe1ra pere6 per5ea",
+ "per5eb pe4rem 2perr per8ran 3pers 4persi pe3rü pe4sta pet2s p2f1ec p4fei pf1f pf2l 5pflanz pf8leg pf3lei 2pft pf3ta p1g 1ph 2ph.",
+ "2p1haf 6phb 8phd 6p5heit ph5eme 6phg phi6e 8phk 6phn p5holl pht2 ph3tha 4ph3the phu6 6phz pi1en pi5err pi1la pi1na 5pinse pioni8e 1pis",
+ "pi1s2k pi1th p1k pl8 5pla p2lau 4plei p3lein 2pler 6p5les 2plig p6lik 6p5ling p2liz plo8min 6p1m p1n 1p2o 8poh 5pol po8lan poly1 po3ny po1ra",
+ "2porn por4t3h po5rö 5poti p1pa p6p5ei ppe6la pp5f p2p1h p1pi pp1l ppp6 pp5ren pp1s p5pö pr6 3preis 1pres 2p3rig 5prinz 1prob 1prod",
+ "5prog pro8pt pro6t5a prote5i 8proß prä3l 1präs präte4 1prüf p5schl 2pst 1p2sy p1t p8to8d pt1s 5p6ty 1pu",
+ "pu1b2 2puc pu2dr puf8fr 6p5uh pun8s pu8rei pu5s6h pu1ta p1v p3w 5py py5l p1z pä6der p5ä6m pä8nu 8pär pät5h",
+ "pät1s qu6 1qui 8rabk ra6bla 3rable ra2br r1abt 6rabz ra4dan ra2dr 5rafal ra4f3er ra5gla ra2g3n 6raha ral5am 5rald 4ralg ra8lins 2rall",
+ "ral5t 8ramei r3anal r6and ran8der ran4dr 8ranf 6ranga 5rangi ran8gli r3angr rans5pa 8ranw r8anz. ra5or 6rapf ra5pl rap6s5er 2r1arb 1rarh",
+ "r1arm ra5ro 2r1art 6r1arz ra8tei ra6t5he 6ratl ra4t3ro r5atta raue4n 6raus. r5austa rau8tel raut5s ray1 r1b rb5lass r6bler rb4lie rbon6n",
+ "r8brecht rb6s5tä r8ces r1che rch1l rch3m rch3re rch3tr rch1w 8rd r1da r8dachs r8dap rda5ro rde5ins rdio5 r8dir rd3ost r1dr r8drau 1re.",
+ "re1ak 3reakt re3als re6am. re1as 4reben re6bl rech5a r8edi re3er 8reff 3refl 2reh 5reha r4ei. reich6s5 8reier 6reign re5imp 4r3eina",
+ "6r3einb 6reing 6r5einn 6reinr 4r3eins r3eint reli3e 8r5elt 6rempf 2remt ren5a6b ren8gl r3enni 1reno 5rente 4r3enth 8rentl 4r3entw 8rentz",
+ "ren4zw re1on requi5 1rer rer4bl 6rerbs 4r3erd 8rerhö 8rerkl 4r3erla 8rerlö 4r3erns 6r5ernä rer5o 6r5erreg r5ertr r5erwec",
+ "r5erö re2sa re8schm 2ress re5u8ni 6rewo 2r1ex r1f r8ferd rf4lie 8r1g r8gah rge4bl rge5na rgest4 rg6ne r2gni2 r8gob r4g3ret rg8sel r1h8",
+ "r2hy 5rhyt ri1ar ri5cha rid2g r2ie rieg4s5 ri8ei ri1el ri6ele ri1en ri3er. ri5ers. ri6fan ri8fer ri8fr 1r2ig ri8kn ri5la rimä8",
+ "ri1na r8inde rin4ga rin6gr 1rinn 6rinner rino1 r8insp 4rinst ri1nä ri5o6ch ri1o2d ri3o6st 2r1ir r2is ri3sko ri8spr ri8stü",
+ "ri5sv r2it 6r5i6tal ri5tr ri6ve. 8r1j 6rk r1ke rkehrs5 r1ki r3klin r1k2n rk3str rk4t3an rk6to r6kuh rkä4s3t r1l r5li rline5a 6r1m",
+ "r6manl rma4p r4m3aph r8minf r8mob rm5sa 2rn r1na rna8be r5ne rn2ei r6neif r6nex r6nh rn1k r1no r6n5oc rn1sp r1nä r1nü ro6bern",
+ "6robs ro1ch 3rock. ro5de ro1e 4rofe ro8hert 1rohr ro5id ro1in ro5isc 6rolym r2on 6roog ro6phan r3ort ro1s2p ro5s6w ro4tau ro1tr ro6ts 5rout",
+ "r1p rpe8re rp2f r2ps r2pt r1q 2rr r1ra r1re rrer6 rr6hos r5rhö r1ri r1ro rro8f rr8or rror5a r1ru r3ry r1rä r1rö r1rü",
+ "2r1s r6sab r4sanf rse6e rse5na r2sh r6ska r6ski rs2kl r8sko r2sl rs2p r6stauf r8sterw r8stran rswi3d4 r2sz 2r1t rt3art r8taut r5tei rt5eige",
+ "r8tepe r4t3erh r8terla r4t3hei r5t6hu r4t3int rt5reif rt1sc rt6ser rt6s5o rt6s5u rt5und r8turt rube6 ru1en 1r4uf ruf4st ru1ie 2r1umg",
+ "2r1uml 2rums run8der run4d5r 6rundz 6runf 8runs 2r1unt 2r1ur r6us ru6sta ru3str ru6tr 1ruts r1v rven1 rvi2c r1w r1x r1za rz5ac r6z5al",
+ "r8z1ar r8zerd r6z5erf rz8erh rz4t3h r8zum rä4ste räu8sc r1öf 5röhr rö5le 3röll 5römis r1ör",
+ "rö2sc 3rümp 1sa. 1saa s3a4ben sa2bl 2s1abs 6s1abt 6sabw 3sack. 6s3a4der 1saf sa1fa 4s1aff sa5fr 1sag 1sai sa1i2k1 4s1akt 1sal",
+ "sa1la 4s3alpi 6salter salz3a 1sam s5anb san2c 1sand s5angeh 6sanl 2s1ans 6s3antr 8s1anw s1ap s6aph 8sapo sap5p6 s8ar. 2s1arb 3sarg",
+ "s1arm sa5ro 2s1art 6s1arz 1sas 1sat sat8a 2s1atl sa8tom 3s8aue s5auff sau5i s6aur 2s1aus 5s6ause 2s1b2 2sca s4ce 8sch. 3scha. 5schade",
+ "3schaf 3schal sch5ame 8schanc 8schb 1sche 6schef 8schex 2schf 2schg 2schh 1schi 2schk 5schlag 5schlu 6schmäß",
+ "6schnaß 1scho 6schord 6schp 3schri 8schric 8schrig 8schrou 6schs 2scht sch3ta sch3tr 1schu 8schunt 6schv 2schz 5schö",
+ "5schü 2sco scre6 6scu 2s1d 1se se5an se1ap se6ben se5ec see5i6g se3erl 8seff se6han se8hi se8hö 6s5eid. 2s1eig s8eil 5sein.",
+ "sei5n6e 6s5einh 3s8eit 3sel. se4lar selb4 6s3e4lem se8lerl 2s1emp sen3ac se5nec 6s5ents 4sentz s8er. se8reim ser5inn 8sermä",
+ "8s5erzi 6seröf se1um 8sexa 6sexp 2s1f2 sfal8ler 2s3g2 sge5b2 s1h s8hew 5s6hip 5s4hop 1si 2siat si1b sicht6s 6s5i6dee siege6s5 si1en",
+ "si5err si1f2 si1g2n si6g5r si8kau sik1i si4kin si2kl si8kü si1la sil6br si1na 2s1inf sin5gh 2s1inh sinne6s5 2s1ins si5ru si5str 4s1j",
+ "s1k2 6sk. 2skau skel6c skelch5 s6kele 1s2ki. 3s4kin. s6kiz s8kj 6skn 2skow 3skrib 3skrip 2sku 8skü s1l s8lal slei3t s4low 2s1m",
+ "s1n 6sna 6snot 1so so1ch 2s1odo so4dor 6s5o4fen solo3 s2on so5of 4sope so1ra 2s1ord 4sorga sou5c so3un 4s3ox sp2 8spaa 5spal 1span 2spap",
+ "s2pec s4peis 1spek s6perg 4spers s6pes 2s1pf 8sphi 1s2phä 1spi spi4e 6s5pig 6spinse 2spis 2spla 2spol 5s6pom 6s5pos 6spoti 1spra",
+ "3s8prec 6spreis 5spring 6sprob 1spru s2pul 1s2pur 6spy 5spän 1spü s1q 2s1r 2s1s2 sse8nu ssini6s ssoi6r 2st. 1sta 4stafe 2stag",
+ "sta3la 6stale 4stalg 8stalk 8stamt 6st5anf 4stans 6stanw 6starb sta4te 6staus 2stb 6stc 6std 1ste 4steil 3s2tel st3elb 8stemb 6steppi 8stese",
+ "8stesse 6stf 2stg 2sth st1ha st3hei s8t1hi st1ho st5hu 1sti sti4el 4stigm sti3na 6stind 4stinf sti8r 2stk 2stl 2stm 1sto 6stoll. 4st3ope",
+ "6stopf. 6stord 6stp 5stra. 4strai 3s4tral 6s5traum 3straß 3strec 6s3tref 8streib 5streif 6streno 6stres 6strev",
+ "5s6tria 6strig 5strik 8strisi 3s4troa s8troma st5rose 4struf 3strum 6sträg 2st1s6 2stt 1stu stu5a 4stuc 2stue 8stun. 2stv 2stw s2tyl",
+ "6stz 1stä 8stäg 1stö 1stü 8stüch 4stür. 1su su2b1 3suc su1e su2fe su8mar 6sumfa 8sumk 2s1unt sup1p2 6s5u6ran",
+ "6surte 2s1v 2s1w 1sy 8syl. sy5la syn1 sy2na syne4 s1z s4zend 5s6zene. 8szu 1sä 6s5änd 6säugi 6säuß",
+ "5söm 2s1ü2b 1süc sü8di 1sün 5süß taats3 4tab. taba6k ta8ban tab2l ta6bre 4tabs t3absc",
+ "8tabz 6t3acht ta6der 6tadr tad6s tad2t 1tafe4 1tag ta6ga6 ta8gei tage4s tag6s5t tah8 tahl3 tai6ne. ta5ir. tak8ta tal3au 1tale ta8leng",
+ "tal5ert 6t5a6mer 6tamp tampe6 2t1amt tan5d6a tan8dr tands5a tani5e 6tanl 2tanr t3ans 8t5antr tanu6 t5anw 8tanwa tan8zw ta8rau 6tarbe",
+ "1tari 2tark 2t1arm ta1ro 2tart t3arti 6tarz ta1sc ta6sien ta8stem ta8sto t5aufb 4taufn 8taus. 5tause 8tausf 6tausg t5ausl 2t1b2 2t1c",
+ "t6chu 2t1d te2am tea4s te8ben 5techn 4teff te4g3re te6hau 2tehe te4hel 2t1ehr te5id. teig5l 6teign tei8gr 1teil 4teinh t5einhe 4teis t5eisen",
+ "8teiw te8lam te4lar 4telek 8telem te6man te6n5ag ten8erw ten5k tens4p ten8tro 4t3entw 8tentz te6pli 5teppi ter5a6b te3ral ter5au 8terbar",
+ "t5erbe. 6terben 8terbs 4t3erbt t5erde. ter5ebe ter5ein te8rers terf4 8terhö 6terklä ter8nor ter6re. t8erscha t5e6sel te8stau",
+ "t3euro te1xa tex3e 8texp tex6ta 2t1f2 2t1g2 2th. th6a 5tha. 2thaa 6t1hab 6t5haf t5hah 8thak 3thal. 6thals 6t3hand 2t1hau 1the. 3t4hea",
+ "t1heb t5heil t3heit t3helf 1theo 5therap 5therf 6t5herz 1thes 1thet 5thi. 2t1hil t3him 8thir 3this t5hj 2th1l 2th1m th1n t5hob t5hof",
+ "4tholz 6thopti 1thr6 4ths t1hum 1thy 4t1hä 2t1hö t1hü ti1a2m ti1b tie6fer ti1en ti8gerz tig3l ti8kin ti5lat 1tilg t1ind",
+ "tin4k3l ti3spa ti5str 5tite ti5tr ti8vel ti8vr 2t1j 2t1k2 2t1l tl8a 2t1m8 2t1n 3tobe 8tobj to3cha 5tocht 8tock tode4 to8del to8du to1e",
+ "6t5o6fen to1in toi6r 5toll. to8mene t2ons 2t1ony to4per 5topf. 6topt to1ra to1s to6ska tos2l 2toti to1tr t8ou 2t1p2 6t1q tr6 tra5cha",
+ "tra8far traf5t 1trag tra6gl tra6gr t3rahm 1trai t6rans tra3sc tra6st 3traue t4re. 2trec t3rech t8reck 6t1red t8ree 4t1reg 3treib 4treif",
+ "8t3reis 8trepo tre6t5r t3rev 4t3rez 1trib t6rick tri6er 2trig t8rink tri6o5d trizi5 tro1a 3troc trocke6 troi8d tro8man. tro3ny 5tropf",
+ "6t5rosa t5roß 5trub 5trup trut5 1träg 6t1röh 5trüb trü3bu t1rüc t1rüs 2ts ts1ab t1sac tsa8d",
+ "ts1ak t6s5alt ts1an ts1ar ts3auf t3schr t5schä tse6e tsee5i tsein6s ts3ent ts1er t8serf t4serk t8sh 5t6sik t4s3int ts5ort.",
+ "t5s6por t6sprei t1st t6s5tanz ts1th t6stit t4s3tor 1t2sua t2s1uf t8sum. t2s1u8n t2s1ur 2t1t tt5eif tte6sa tt1ha tt8ret tt1sc tt8ser",
+ "tt5s6z 1tuc tuch5a 1tu1e 6tuh t5uhr tu1i tu6it 1tumh 6t5umr 1tums 8tumt 6tund 6tunf 2t1unt tu5ra tu6rau tu6re. tu4r3er 2t1v 2t1w 1ty1",
+ "ty6a ty8la 8tym 6ty6o 2tz tz5al tz1an tz1ar t8zec tzeh6 tzehn5 t6z5ei. t6zor t4z3um t6zäu 5täg 6täh t5ält t8än",
+ "täre8 8tä8st 6täuß t5öffen 8tö8k 1tön 4tüb t6ü5ber. 5tüch 1tür.",
+ "u3al. u5alb u5alf u3alh u5alk u3alp u3an. ua5na u3and u5ans u5ar. ua6th u1au ua1y u2bab ubi5er. u6b5rit ubs2k u5bö u8büb 2uc",
+ "u1che u6ch5ec u1chi uch1l uch3m uch5n uch1r uch5to ucht5re u1chu uch1w uck1a uck5in u1d ud4a u1ei u6ela uene8 u6ep u1er uer1a ue8rerl uer5o",
+ "u8esc u2est u8ev u1fa u2f1ei u4f3ent u8ferh uf1fr uf1l uf1ra uf1re uf1rä uf1rü uf1s2p uf1st uft1s u8gabt u8gad u6gap ugeb8 u8gn",
+ "ugo3s4 u1ha u1he u1hi uh1le u1ho uh1re u1hu uh1w u1hä u1hö 6ui ui5en u1ig u3ins uin8tes u5isch. u1j 6uk u1ke u1ki u1kl u8klu",
+ "u1k6n u5ky u1la uld8se u1le ul8lac ul6lau ul6le6l ul6lo ulni8 u1lo ulo6i ult6a ult8e u1lu ul2vr u1lä u1lö 3umfan 5umlau umo8f",
+ "um8pho u1mu umu8s u5mö u1n1a un2al un6at unau2 6und. 5undein un4d3um 3undzw undü8 un8düb une2b un1ec une2h un3eis 3unfal",
+ "1unfä 5ungea 3unglü ung2s1 un8gä 1u2nif un4it un8kro unk5s u1no unpa2 uns2p unvol4 unvoll5 u5os. u1pa u1pi u1p2l u1pr",
+ "up4s3t up2t1a u1q u1ra ur5abs ura8d ur5ah u6rak ur3alt u6rana u6r5ans u8rap ur5a6ri u8ratt u1re ur3eig ur8gri u1ri ur5ins 3urlau urmen6",
+ "ur8nan u1ro 3ursac ur8sau ur8sei ur4sk 3urtei u1ru uru5i6 uru6r u1ry ur2za ur6zä ur5ä6m u5rö u1rü urück3 u1sa",
+ "usa4gi u2s1ar u2s1au u8schec usch5wi u2s1ei use8kel u8sl u4st3a4b us3tau u3s4ter u2s1uf u8surn ut1ac u1tal uta8m u1tan ut1ar u1tas ut1au",
+ "u1te u8teic u4tent u8terf u6terin u4t3hei ut5ho ut1hu u1ti utine5 uti6q u1to uto5c u1tr ut1sa ut1s6p ut6stro u1tu utz5w u1u u1v uve5n",
+ "uve3r4ä u1w u1xe u5ya uy5e6 u1yi u2z1eh u8zerh u5ö uße6n ußen5e 8vanb 6vang 6varb var8d va6t5a va8tei",
+ "va2t1r 2v1b 6v5c 6vd 1ve 6ve5g6 ver1 ver5b verb8l ve2re2 verg8 ve2ru8 ve1s ve2s3p ve3xe 2v1f 2v1g 6v5h vi6el vie6w5 vi1g4 vi8leh vil6le.",
+ "8vint vi1ru vi1tr 2v1k 2v1l 2v1m 4v5n 8vo8f voi6le vol8lend vol8li v2or1 vo2re vo8rin vo2ro 2v1p 8vra v6re 2v1s 2v1t 2v1v 4v3w 2v1z",
+ "waffe8 wa6g5n 1wah wah8n wa5la wal8din wal6ta wan4dr 5ware wa8ru war4za 1was w5c w1d 5wech we6fl 1weg we8geng weg5h weg3l we2g1r",
+ "weh6r5er 5weise weit3r wel2t welt3r we6rat 8werc 5werdu wer4fl 5werk. wer4ka wer8ku wer4ta wer8term we2sp we8stend we6steu we8str",
+ "we8stö wet8ta wich6s5t 1wid wi2dr wiede4 wieder5 wik6 wim6ma win4d3r 5wirt wisch5l 1wj 6wk 2w1l 8w1n wo1c woche6 wol6f wor6t5r 6ws2",
+ "w1sk 6w5t 5wunde. wun6gr wu1sc wu2t1 6w5w wy5a wärme5 wä1sc 1xag x1ak x3a4men 8xamt x1an 8x1b x1c 1xe. x3e4g 1xen xe1ro x1erz",
+ "1xes 8xf x1g 8x1h 1xi 8xid xi8so 4xiste x1k 6x1l x1m 8xn 1xo 8x5o6d 8x3p2 x1r x1s6 8x1t x6tak x8terf x2t1h 1xu xu1e x5ul 6x3w x1z 5ya.",
+ "y5an. y5ank y1b y1c y6cha y4chia y1d yen6n y5ern y1g y5h y5in y1j y1k2 y1lak yl1al yla8m y5lax y1le y1lo y5lu y8mn ym1p2 y3mu y1na yno2d",
+ "yn1t y1on. y1o4p y5ou ypo1 y1pr y8ps y1r yri3e yr1r2 y1s ys5iat ys8ty y1t y3w y1z yä8m z5a6b zab5l 8za6d 1zah za5is 4z3ak 6z1am 5zange.",
+ "8zanl 2z1ara 6z5as z5auf 3zaun 2z1b 6z1c 6z1d 1ze ze4dik 4z3eff 8zein zei4ta zei8ters ze6la ze8lec zel8th 4zemp 6z5engel zen8zin 8zergä",
+ "zer8i ze1ro zers8 zerta8 zer8tab zer8tag 8zerz ze8ste zeu6gr 2z1ex 2z1f8 z1g 4z1h 1zi zi1en zi5es. 4z3imp zi1na 6z5inf 6z5inni zin6s5er",
+ "8zinsuf zist5r zi5th zi1tr 6z1j 2z1k 2z1l 2z1m 6z1n 1zo zo6gl 4z3oh zo1on zor6na8 4z1p z5q 6z1r 2z1s8 2z1t z4t3end z4t3hei z8thi 1zu zu3al",
+ "zu1b4 zu1f2 6z5uhr zun2a 8zunem zunf8 8zungl zu1o zup8fi zu1s8 zu1z 2z1v zw8 z1wal 5zweck zwei3s z1wel z1wer z6werg 8z5wes 1zwi zwi1s",
+ "6z1wo 1zy 2z1z zz8a zzi1s 1zä 1zö 6zöl. zö1le 1zü 2z1ü2b ä1a6 äb1l ä1che ä3chi",
+ "äch8sc äch8sp ä5chu äck5a äd1a äd5era ä6d5ia ä1e ä5fa äf1l äft6s äg1h",
+ "äg3le ä6g5nan äg5str ä1he ä1hi äh1le äh5ne 1ähnl äh1re äh5ri äh1ru ä1hu",
+ "äh1w 6äi ä1isc ä6ische ä5ism ä5j ä1k äl1c ä1le ä8lei äl6schl ämi1e",
+ "äm8n äm8s ä5na 5änderu äne5i8 äng3l änk5l ä1no än6s5c ä1pa äp6s5c 3äq",
+ "är1c ä1re äre8m 5ärgern är6gl ä1ri 3ärmel ä1ro ärt6s5 ä1ru 3ärztl ä5rö",
+ "ä6s5chen äsen8s äs1th äta8b ä1te äteri4 äter5it ä6thy ä1ti 3ätk ä1to ät8schl",
+ "äts1p ä5tu äub1l äu1e 1äug äu8ga äu5i ä1um. ä1us. 1äuß ä1z",
+ "ö1b ö1che ö5chi öch8stei öch8str öcht6 5ö6dem 5öffn ö1he öh1l8 öh1re ö1hu",
+ "ö1is ö1ke 1ö2ko 1öl. öl6k5l öl8pl ö1mu ö5na önig6s3 ö1no ö5o6t öpf3l",
+ "öp6s5c ö1re ör8gli ö1ri ör8tr ö1ru 5österr ö1te ö5th ö1ti ö1tu ö1v ö1w",
+ "öwe8 ö2z üb6e2 3ü4ber1 üb1l üb1r 5ü2bu ü1che ü1chi ü8ch3l üch6s5c ü8ck",
+ "ück1a ück5ers üd1a2 ü6deu üdi8t ü2d1o4 üd5s6 üge4l5a üg1l üh5a ü1he ü8heh",
+ "ü6h5erk üh1le üh1re üh1ru ü1hu üh1w ü3k ü1le ül4l5a ül8lo ül4ps ül6s5c",
+ "ü1lu ün8da ün8fei ünk5l ün8za ün6zw ü5pi ü1re ü8rei ür8fl ür8fr ür8geng",
+ "ü1ri ü1ro ür8sta ür8ster ü1ru üse8n ü8sta ü8stes ü6s5tete ü3ta ü1te ü1ti",
+ "üt8tr ü1tu üt8zei ü1v ß1a8 5ßa. ß8as ß1b8 ß1c ß1d 1ße ß5ec 8ße8g 8ße8h",
+ "2ß1ei 8ßem ß1f8 ß1g ß1h 1ßi ß1k ß1l ß1m ßmana8 ß1n ß1o ß1p8 ß5q ß1r ß1s2 ßst8 ß1ta",
+ "ß1te ßt3hei ß1ti ß5to ß1tr 1ßu8 6ß5um ß1v ß1w ß1z ß1z",
+ NULL};
+#endif
+
+/*
+\endgroup
+\relax\endinput
+%
+% -----------------------------------------------------------------
+%
+% =============== Additional Documentation ===============
+%
+%
+% Older Versions of German Hyphenation Patterns:
+% ----------------------------------------------
+%
+% All older versions of `ghyphen.tex' distributed as
+%
+% ghyphen.tex/germhyph.tex as of 1986/11/01
+% ghyphen.min/ghyphen.max as of 1988/10/10
+% ghyphen3.tex as of 90/09/27 & 91/02/13
+%
+% are out of date and it is recommended to replace them
+% with the new version `ghyph31.tex'.
+%
+% If you are using `ghyphen.min' (a minor version of `ghyphen')
+% because of limited trie memory space, try this version and if
+% the space is exceeded get a newer TeX implementation with
+% larger or configurable trie memory sizes.
+%
+%
+%
+% Trie Memory Requirements/Space for Hyphenation Patterns:
+% --------------------------------------------------------
+%
+% To load this set of german hyphenation patterns the parameters
+% of TeX has to have at least these values:
+%
+% TeX 3.x:
+% IniTeX: trie_size >= 9733 trie_op_size >= 207
+% VirTeX: trie_size >= 8375 trie_op_size >= 207
+%
+% TeX 2.x:
+% IniTeX: trie_size >= 8675 trie_op_size >= 198
+% VirTeX: trie_size >= 7560 trie_op_size >= 198
+%
+% If you want to load more than one set of hyphenation patterns
+% (in TeX 3.x), the parameters have to be set to a value larger
+% than or equal to the sum of all required values for each set.
+%
+%
+% Setting Trie Memory Parameters:
+% -------------------------------
+%
+% Some implementations allow the user to change the default value
+% of a set of the internal TeX parameters including the trie memory
+% size parameter specifying the used memory for the hyphenation
+% patterns.
+%
+% emTeX (PC):
+% You can set the used memory size of the trie using the
+% `-mt<number>' option on the command line or in the
+% TEXOPTIONS environment variable.
+%
+% PasTeX (Amiga):
+% The values for the parameters can be set using the keywords
+% `triesize', `itriesize' and `trieopsize' in the configuration
+% file.
+%
+% others (binaries only):
+% See the documentation of the implementation if it is possible
+% and how to change these values without recompilation.
+%
+% others (with sources, e.g. PublicTeX (PC), web2c (Unix et.al.)):
+% If the trie memory is too small, you have to recompile TeX
+% using larger values for `trie_size' and `trie_op_size'.
+% Modify the change file pctex.ch/ctex.ch and recompile TeX.
+% For details see the documentation included in the sources.
+%
+%
+%
+% Necessary Settings in TeX macro files:
+% --------------------------------------
+%
+% \lefthyphenmin, \righthyphenmin:
+% You can set both parameters to 2.
+%
+% \lccode <char>:
+% To get correct hyphenation points within words containing
+% umlauts or \ss, it's necessary to assign values > 0 to the
+% appropriate \lccode <char> positions.
+%
+% These changes are done when reading this file (\lccode for umlauts)
+% or are included in the language switching mechanism of `german.sty'
+% (\lccode change for \ss, \left-/\righthyphenmin settings).
+%
+%
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+\endinput
+%%
+%% End of file `ghyph31.tex'.
+*/
diff --git a/grhyph.h b/grhyph.h
new file mode 100644
index 0000000..bbec6d1
--- /dev/null
+++ b/grhyph.h
@@ -0,0 +1,12 @@
+/* grhyph.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Trennungsmuster deutsch */
+/* abgeleitet von 'ghyph31.tex' aus TeX */
+/* */
+/* Historie: 16.2.1998 Konvertierung */
+/* */
+/*****************************************************************************/
+
+extern char *GRHyphens[];
diff --git a/header.res b/header.res
new file mode 100644
index 0000000..3434d04
--- /dev/null
+++ b/header.res
@@ -0,0 +1,6 @@
+;-----------------------------------------------------------------------------
+; Muss mehr werden!
+
+Langs DE(049) EN(001)
+Default EN
+
diff --git a/headids.c b/headids.c
new file mode 100644
index 0000000..32275b7
--- /dev/null
+++ b/headids.c
@@ -0,0 +1,124 @@
+/* headids.c */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Hier sind alle Prozessor-IDs mit ihren Eigenschaften gesammelt */
+/* */
+/* Historie: 29. 8.1998 angelegt */
+/* Intel i960 */
+/* 30. 8.1998 NEC uPD7725 */
+/* 6. 9.1998 NEC uPD77230 */
+/* 30. 9.1998 Symbios SYM53C8xx */
+/* 29.11.1998 Intel 4004 */
+/* 3.12.1998 Intel 8008 */
+/* 25. 3.1999 National SC14xxx */
+/* 4. 7.1999 Fujitsu F2MC */
+/* 10. 8.1999 Fairchild ACE */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+#include <string.h>
+
+#include "headids.h"
+
+/*---------------------------------------------------------------------------*/
+
+static TFamilyDescr Descrs[]=
+ {
+ {"680x0" , 0x0001, MotoS },
+ {"DSP56000" , 0x0009, MotoS },
+ {"MPC601" , 0x0005, MotoS },
+ {"M-CORE" , 0x0003, MotoS },
+ {"68xx" , 0x0061, MotoS },
+ {"6805/HC08" , 0x0062, MotoS },
+ {"6809" , 0x0063, MotoS },
+ {"68HC12" , 0x0066, MotoS },
+ {"68HC16" , 0x0065, MotoS },
+ {"H8/300(H}" , 0x0068, MotoS },
+ {"H8/500" , 0x0069, MotoS },
+ {"SH7x00" , 0x006c, MotoS },
+ {"65xx" , 0x0011, MOSHex },
+ {"MELPS-7700", 0x0019, MOSHex },
+ {"MELPS-4500", 0x0012, IntHex },
+ {"M16" , 0x0013, IntHex32},
+ {"M16C" , 0x0014, IntHex },
+ {"MCS-48" , 0x0021, IntHex },
+ {"MCS-(2)51" , 0x0031, IntHex },
+ {"MCS-96/196", 0x0039, IntHex },
+ {"4004/4040" , 0x003f, IntHex },
+ {"8008" , 0x003e, IntHex },
+ {"8080/8085" , 0x0041, IntHex },
+ {"8086" , 0x0042, IntHex16},
+ {"i960" , 0x002a, IntHex32},
+ {"8X30x" , 0x003a, IntHex },
+ {"XA" , 0x003c, IntHex16},
+ {"AVR" , 0x003b, Atmel },
+ {"29xxx" , 0x0029, IntHex32},
+ {"80C166/167", 0x004c, IntHex16},
+ {"Zx80" , 0x0051, IntHex },
+ {"Z8" , 0x0079, IntHex },
+ {"TLCS-900" , 0x0052, MotoS },
+ {"TLCS-90" , 0x0053, IntHex },
+ {"TLCS-870" , 0x0054, IntHex },
+ {"TLCS-47xx" , 0x0055, IntHex },
+ {"TLCS-9000 ", 0x0056, MotoS },
+ {"16C8x" , 0x0070, IntHex },
+ {"16C5x" , 0x0071, IntHex },
+ {"17C4x" , 0x0072, IntHex },
+ {"ST6" , 0x0078, IntHex },
+ {"ST7" , 0x0033, IntHex },
+ {"ST9" , 0x0032, IntHex },
+ {"6804" , 0x0064, MotoS },
+ {"TMS3201x" , 0x0074, TiDSK },
+ {"TMS3202x" , 0x0075, TiDSK },
+ {"TMS320C3x" , 0x0076, IntHex32},
+ {"TMS320C5x" , 0x0077, TiDSK },
+ {"TMS320C6x" , 0x0047, IntHex32},
+ {"TMS9900" , 0x0048, IntHex },
+ {"TMS7000" , 0x0073, IntHex },
+ {"TMS370xx" , 0x0049, IntHex },
+ {"MSP430" , 0x004a, IntHex },
+ {"SC/MP" , 0x006e, IntHex },
+ {"COP8" , 0x006f, IntHex },
+ {"SC14XXX" , 0x006d, IntHex },
+ {"ACE" , 0x0067, IntHex },
+ {"78(C)1x" , 0x007a, IntHex },
+ {"75K0" , 0x007b, IntHex },
+ {"78K0" , 0x007c, IntHex },
+ {"7720" , 0x007d, IntHex },
+ {"7725" , 0x007e, IntHex },
+ {"77230" , 0x007f, IntHex },
+ {"SYM53C8xx" , 0x0025, IntHex },
+ {"F2MC8" , 0x0015, IntHex },
+ {Nil , 0xffff, Default }
+ };
+
+/*---------------------------------------------------------------------------*/
+
+ PFamilyDescr FindFamilyByName(char *Name)
+BEGIN
+ PFamilyDescr Run;
+
+ for (Run=Descrs; Run->Name!=Nil; Run++)
+ if (strcmp(Name,Run->Name)==0) return Run;
+
+ return Nil;
+END
+
+ PFamilyDescr FindFamilyById(Word Id)
+BEGIN
+ PFamilyDescr Run;
+
+ for (Run=Descrs; Run->Name!=Nil; Run++)
+ if (Id==Run->Id) return Run;
+
+ return Nil;
+END
+
+/*---------------------------------------------------------------------------*/
+
+ void headids_init(void)
+BEGIN
+END
diff --git a/headids.h b/headids.h
new file mode 100644
index 0000000..e9e8bfb
--- /dev/null
+++ b/headids.h
@@ -0,0 +1,28 @@
+/* headids.h */
+/*****************************************************************************/
+/* Makroassembler AS */
+/* */
+/* Hier sind alle Prozessor-IDs mit ihren Eigenschaften gesammelt */
+/* */
+/* Historie: 29. 8.1998 angelegt */
+/* */
+/*****************************************************************************/
+
+/* Hex-Formate */
+
+typedef enum {Default,MotoS,
+ IntHex,IntHex16,IntHex32,
+ MOSHex,TekHex,TiDSK,Atmel} THexFormat;
+
+typedef struct
+ {
+ char *Name;
+ Word Id;
+ THexFormat HexFormat;
+ } TFamilyDescr,*PFamilyDescr;
+
+extern PFamilyDescr FindFamilyByName(char *Name);
+
+extern PFamilyDescr FindFamilyById(Word Id);
+
+extern void headids_init(void);
diff --git a/hex.c b/hex.c
new file mode 100644
index 0000000..7355bf5
--- /dev/null
+++ b/hex.c
@@ -0,0 +1,72 @@
+/* hex.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Dezimal-->Hexadezimal-Wandlung, Grossbuchstaben */
+/* */
+/* Historie: 2. 6.1996 */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+
+#include "hex.h"
+
+#define BUFFERCNT 8
+
+ char *HexNibble(Byte inp)
+BEGIN
+ static char Buffers[BUFFERCNT][3],*ret;
+ static int z=0;
+
+ sprintf(Buffers[z],"%01x",inp&0xf);
+ for (ret=Buffers[z]; *ret!='\0'; ret++) *ret=toupper(*ret);
+ ret=Buffers[z];
+ z=(z+1)%BUFFERCNT;
+ return ret;
+END
+
+ char *HexByte(Byte inp)
+BEGIN
+ static char Buffers[BUFFERCNT][4],*ret;
+ static int z=0;
+
+ sprintf(Buffers[z],"%02x",inp&0xff);
+ for (ret=Buffers[z]; *ret!='\0'; ret++) *ret=toupper(*ret);
+ ret=Buffers[z];
+ z=(z+1)%BUFFERCNT;
+ return ret;
+END
+
+ char *HexWord(Word inp)
+BEGIN
+ static char Buffers[BUFFERCNT][6],*ret;
+ static int z=0;
+
+ sprintf(Buffers[z],"%04x",inp&0xffff);
+ for (ret=Buffers[z]; *ret!='\0'; ret++) *ret=toupper(*ret);
+ ret=Buffers[z];
+ z=(z+1)%BUFFERCNT;
+ return ret;
+END
+
+ char *HexLong(LongWord inp)
+BEGIN
+ static char Buffers[BUFFERCNT][10],*ret;
+ static int z=0;
+
+#ifdef __STDC__
+ sprintf(Buffers[z],"%08x",inp&0xffffffffu);
+#else
+ sprintf(Buffers[z],"%08x",inp&0xffffffff);
+#endif
+ for (ret=Buffers[z]; *ret!='\0'; ret++) *ret=toupper(*ret);
+ ret=Buffers[z];
+ z=(z+1)%BUFFERCNT;
+ return ret;
+END
+
+ void hex_init(void)
+BEGIN
+END
diff --git a/hex.h b/hex.h
new file mode 100644
index 0000000..af9cb34
--- /dev/null
+++ b/hex.h
@@ -0,0 +1,19 @@
+/* hex.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Dezimal-->Hexadezimal-Wandlung, Grossbuchstaben */
+/* */
+/* Historie: 2. 6.1996 */
+/* */
+/*****************************************************************************/
+
+extern char *HexNibble(Byte inp);
+
+extern char *HexByte(Byte inp);
+
+extern char *HexWord(Word inp);
+
+extern char *HexLong(LongWord inp);
+
+extern void hex_init(void);
diff --git a/include/80c50x.inc b/include/80c50x.inc
new file mode 100644
index 0000000..e4a934b
--- /dev/null
+++ b/include/80c50x.inc
@@ -0,0 +1,257 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei 80C50x.INC *
+;* *
+;* Sinn : enthält SFR- und Bitdefinitionen für die SAB C50x-Prozessoren *
+; (Ableitung aus STDDEF51.INC) *
+;* *
+;* letzte Änderungen : 26. 3.1997 Grundsteinlegung *
+;* 8. 6.1997 Korrekturen von Herrn Schmid *
+;* *
+;****************************************************************************
+
+ ifndef reg50xinc ; verhindert Mehrfacheinbindung
+
+reg50xinc equ 1
+
+ if (MOMCPUNAME<>"80C501")&&(MOMCPUNAME<>"80C502")&&(MOMCPUNAME<>"80C504")
+ fatal "Falscher Prozessortyp eingestellt: nur 80C501, 80C502 oder 80C504 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "SAB C50x-SFR-Definitionen (C) 1993 Alfred Arnold, Steffen Schmid"
+ message "binde \{MOMCPUNAME}-SFRs ein"
+ endif
+
+;----------------------------------------------------------------------------
+; Prozessorkern
+
+ACC SFRB 0e0h ; Akkumulator
+B SFRB 0f0h ; Hilfsakku für MUL/DIV
+SP SFR 81h ; Stapelzeiger
+DPL SFR 82h ; Datenzeiger Bit 0..7
+DPH SFR 83h ; " Bit 8..15
+PSW SFRB 0d0h ; Statuswort
+CY BIT PSW.7
+AC BIT PSW.6
+F0 BIT PSW.5
+RS1 BIT PSW.4
+RS0 BIT PSW.3
+OV BIT PSW.2
+P BIT PSW.0
+SYSCON SFR 0b1h ; Systemkonfiguration
+PCON SFR 87h ; "Power-Management"
+PCON1 SFRB 88h
+EWPD BIT PCON1.7 ; Freigabe Wake-Up durch INT0
+
+ if MOMCPUNAME="80C502"
+XPAGE SFR 91h ; XRAM-Ansteuerung 80C502
+XCON SFR 94h
+DPSEL SFR 92h
+ endif
+
+;----------------------------------------------------------------------------
+; Ports
+
+P0 SFRB 80h ; I/O-Ports
+P1 SFRB 90h
+P2 SFRB 0a0h
+P3 SFRB 0b0h
+T2EX BIT P1.1
+T2 BIT P1.0
+ if MOMCPUNAME="80C504"
+P1ANA SFRB 90h ; Selektion Port 1/3 als analoge Eingabe
+P3ANA SFRB 0b0h
+EAN0 BIT P1ANA.0
+EAN1 BIT P1ANA.1
+EAN2 BIT P1ANA.2
+EAN3 BIT P1ANA.3
+EAN4 BIT P1ANA.2
+EAN5 BIT P1ANA.3
+EAN6 BIT P1ANA.4
+EAN7 BIT P1ANA.5
+ endif
+RD BIT P3.7 ; Port 3: Schreibleitung
+WR BIT P3.6 ; Leseleitung
+T1 BIT P3.5 ; Testleitung 1
+T0 BIT P3.4 ; Testleitung 0
+INT1 BIT P3.3 ; ext. Interrupt 1
+INT0 BIT P3.2 ; ext. Interrupt 0
+TXD BIT P3.1 ; ser. Ausgang
+RXD BIT P3.0 ; ser. Eingang
+
+;----------------------------------------------------------------------------
+; serielles
+
+SCON SFRB 98h ; ser. Schnittstelle: Steuerregister
+SM0 BIT SCON.7 ; Betriebsarten
+SM1 BIT SCON.6
+SM2 BIT SCON.5
+REN BIT SCON.4 ; Empfangssperre
+TB8 BIT SCON.3 ; 9. zu sendendes Bit
+RB8 BIT SCON.2 ; 9. empfangenes Bit
+TI BIT SCON.1 ; Senderinterruptflag
+RI BIT SCON.0 ; Empfängerinterruptflag
+SBUF SFR 99h ; " " Datenregister
+ if MOMCPUNAME="80C502"
+SRELL SFR 0aah ; Wert für Baudratengenerator
+SRELH SFR 0bah
+BAUD SFRB 0d8h
+BD BIT BAUD.7 ; Baudratengenerator aktivieren
+ ENDIF
+
+;----------------------------------------------------------------------------
+; Timer
+
+TCON SFRB 88h ; Timer 0/1 Steuerregister
+TF1 BIT TCON.7 ; Überlauf Timer 1
+TR1 BIT TCON.6 ; Timer 1 laufenlassen
+TF0 BIT TCON.5 ; Überlauf Timer 0
+TR0 BIT TCON.4 ; Timer 0 laufenlassen
+IE1 BIT TCON.3 ; Externer Interrupt 1 aufgetreten
+IT1 BIT TCON.2 ; Einstellung Triggerflanke externer Interrupt 1
+IE0 BIT TCON.1 ; Externer Interrupt 0 aufgetreten
+IT0 BIT TCON.0 ; Einstellung Triggerflanke externer Interrupt 0
+TMOD SFR 89h ; Timer 0/1 Betriebsartenregister
+TL0 SFR 8ah ; Daten Timer 0
+TL1 SFR 8bh
+TH0 SFR 8ch ; Daten Timer 1
+TH1 SFR 8dh
+T2CON SFRB 0c8h ; Steuerregister Timer 2
+TL2 SFR 0cch ; Daten Timer 2
+TH2 SFR 0cdh
+RC2L SFR 0cah ; Capture-Register
+RC2H SFR 0cbh
+TF2 BIT T2CON.7 ; Overflow Timer 2
+EXF2 BIT T2CON.6 ; Reload aufgetreten
+RCLK BIT T2CON.5 ; Timer 2 liefert RxD-Takt
+TCLK BIT T2CON.4 ; Timer 2 liefert TxD-Takt
+EXEN2 BIT T2CON.3 ; externer Enable Timer 2
+TR2 BIT T2CON.2 ; Timer 2 starten
+CT2 BIT T2CON.1 ; Timer 2 als Zähler
+CPRL2 BIT T2CON.0 ; Capture erlauben
+
+;---------------------------------------------------------------------------
+; Watchdog
+
+ if MOMCPU>=80C504h
+WDCON SFRB 0c0h ; Watchdog Steuerung
+SWDT BIT WDCON.0 ; Watchdog starten
+WDT BIT WDCON.1 ; Watchdog zurücksetzen
+WDTS BIT WDCON.2 ; Watchdog-Reset-Flagge
+OWDS BIT WDCON.3 ; dito Oszillator-Watchdog
+WDTREL SFR 86h
+ endif
+
+;---------------------------------------------------------------------------
+; Capture/Compare-Einheit
+
+ if MOMCPUNAME="80C504"
+CT1CON SFR 0e1h ; Steuerung Vergleicher 1
+CCPL SFR 0deh ; Periode Vergleicher 1
+CCPH SFR 0dfh
+CT1OFL SFR 0e6h ; Offset Vergleicher 1
+CT1OFH SFR 0e7h
+CMSEL0 SFR 0e3h ; Modus
+CMSEL1 SFR 0e4h
+COINI SFR 0e2h ; Initialisierung Vergleicherausgang
+TRCON SFR 0cfh ; Trap-Freigabe
+CCL0 SFR 0c2h ; Vergleichs-/Fangwert 0
+CCH0 SFR 0c3h
+CCL1 SFR 0c4h ; Vergleichs-/Fangwert 1
+CCH1 SFR 0c5h
+CCL2 SFR 0c6h ; Vergleichs-/Fangwert 2
+CCH2 SFR 0c7h
+CCIR SFR 0e5h ; Interruptflags
+CCIE SFR 0d6h ; Interruptmasken
+CT2CON SFR 0c1h ; Steuerung Vergleicher 2
+CP2L SFR 0d2h ; Periode Vergleicher 2
+CP2H SFR 0d3h
+CMP2L SFR 0d4h ; Vergleichs-/Fangwert Timer 2
+CMP2H SFR 0d5h
+BCON SFR 0d7h ; Steuerung Blockkommunikation
+ endif
+
+;---------------------------------------------------------------------------
+; A/D-Wandler
+
+ if MOMCPUNAME="80C504"
+ADCON0 SFRB 0d8h ; Konfiguration
+IADC BIT ADCON0.5 ; Interruptflagge (Ende Konversion)
+BSY BIT ADCON0.4 ; Busy-Flag
+ADM BIT ADCON0.3 ; einfache/kontinuierliche Wandlung
+MX2 BIT ADCON0.2 ; Kanalwahl
+MX1 BIT ADCON0.1
+MX0 BIT ADCON0.0
+ADCON1 SFR 0dch
+ADDATH SFR 0d9h ; Daten
+ADDATL SFR 0dah
+ endif
+
+;-------------------------------------------------------------------------
+; Interruptsteuerregister:
+
+IEN0 SFRB 0a8h ; Freigaben
+IE SFRB IEN0
+EA BIT IEN0.7 ; generelle Sperre
+ET2 BIT IEN0.5 ; Timer 2
+ES BIT IEN0.4 ; ser. Schnittstelle
+ET1 BIT IEN0.3 ; Überlauf Timer 1
+EX1 BIT IEN0.2 ; ext. Interrupt 1
+ET0 BIT IEN0.1 ; Timer 0 Überlauf
+EX0 BIT IEN0.0 ; ext. Interrupt 0
+IP0 SFRB 0b8h ; Prioritäten
+IP SFRB IP0
+PT2 BIT IP0.5 ; siehe Freigabebits
+PS BIT IP0.4
+PT1 BIT IP0.3
+PX1 BIT IP0.2
+PT0 BIT IP0.1
+PX0 BIT IP0.0
+ if MOMCPUNAME="80C504"
+IEN1 SFR 0a9h
+IP1 SFR 0b9h
+ITCON SFR 09ah ; Triggerbedingungen
+ endif
+
+;---------------------------------------------------------------------------
+; Da man die Register beim 8051 nicht direkt pushen und poppen kann, muß man
+; dies über direkte Adressen tun. Da dazu die Kenntnis der gewählten Regis-
+; terbank erforderlich ist, steht hier das Makro USING zur Verfügung, wel-
+; ches in den Symbolen AR0..AR7 die momentanen Registeradressen ablegt.
+; USING erwartet als Parameter die gewählte Banknummer.
+
+Bank0 equ 0 ; nur der Schönheit halber...
+Bank1 equ 1
+Bank2 equ 2
+Bank3 equ 3
+
+using macro bank
+ if (bank<0)||(bank>3) ; nur 0..3 erlaubt
+ error "Falsche Banknummer: \{BANK}"
+ endif
+
+ ifdef RegUsage ; Buchführung über benutzte Bänke
+RegUsage set RegUsage|(2^bank)
+ elseif
+RegUsage set 2^bank
+ endif
+
+ar0 set bank*8 ; Symbole besetzen
+ar1 set ar0+1
+ar2 set ar0+2
+ar3 set ar0+3
+ar4 set ar0+4
+ar5 set ar0+5
+ar6 set ar0+6
+ar7 set ar0+7
+ endm
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/80c552.inc b/include/80c552.inc
new file mode 100644
index 0000000..8a24517
--- /dev/null
+++ b/include/80c552.inc
@@ -0,0 +1,228 @@
+; 83C552 processor definition file
+; ================================
+
+; NOTE: 80c552 is not a predefined processor type in AS.
+; to use this file, add '-alias 80c552=8052' to the command line
+; or key file
+
+ if MOMCPUNAME<>"80C552"
+ fatal "80C552.INC: Falscher Prozessortyp, nur 80C552 erlaubt"
+ endif
+
+ if MOMPASS=1
+ message "80C552-Registerdefinitionen"
+ message "(C) 1996 Alfred Arnold"
+ endif
+
+;-----------------------------------------------------------------------------
+
+ACC sfrb 0E0H
+B sfrb 0F0H
+SP sfr 081H
+DPL sfr 082H
+DPH sfr 083H
+
+PSW sfrb 0D0H
+P bit PSW.0
+F1 bit PSW.1
+OV bit PSW.2
+RS0 bit PSW.3
+RS1 bit PSW.4
+F0 bit PSW.5
+AC bit PSW.6
+CY bit PSW.7
+
+;-----------------------------------------------------------------------------
+
+PCON sfr 087H
+
+;-----------------------------------------------------------------------------
+
+IEN0 sfrb 0A8H
+EX0 bit IEN0.0
+ET0 bit IEN0.1
+EX1 bit IEN0.2
+ET1 bit IEN0.3
+ES0 bit IEN0.4
+ES1 bit IEN0.5
+EAD bit IEN0.6
+EA bit IEN0.7
+
+IEN1 sfrb 0E8H
+ECT0 bit IEN1.0
+ECT1 bit IEN1.1
+ECT2 bit IEN1.2
+ECT3 bit IEN1.3
+ECM0 bit IEN1.4
+ECM1 bit IEN1.5
+ECM2 bit IEN1.6
+ET2 bit IEN1.7
+
+IP0 sfrb 0B8H
+PX0 bit IP0.0
+PT0 bit IP0.1
+PX1 bit IP0.2
+PT1 bit IP0.3
+PS0 bit IP0.4
+PS1 bit IP0.5
+PAD bit IP0.6
+
+IP1 sfrb 0F8H
+PCT0 bit IP1.0
+PCT1 bit IP1.1
+PCT2 bit IP1.2
+PCT3 bit IP1.3
+PCM0 bit IP1.4
+PCM1 bit IP1.5
+PCM2 bit IP1.6
+PT2 bit IP1.7
+
+;-----------------------------------------------------------------------------
+
+P0 sfrb 080H
+
+P1 sfrb 090H
+CT0I bit P1.0
+CT1I bit P1.1
+CT2I bit P1.2
+CT3I bit P1.3
+T2 bit P1.4
+RT2 bit P1.5
+SCL bit P1.6
+SDA bit P1.7
+
+P2 sfrb 0A0H
+
+P3 sfrb 0B0H
+RXD bit P3.0
+TXD bit P3.1
+INT0 bit P3.2
+INT1 bit P3.3
+T0 bit P3.4
+T1 bit P3.5
+WR bit P3.6
+RD bit P3.7
+
+P4 sfrb 0C0H
+CMSR0 bit P4.0
+CMSR1 bit P4.1
+CMSR2 bit P4.2
+CMSR3 bit P4.3
+CMSR4 bit P4.4
+CMSR5 bit P4.5
+CMT0 bit P4.6
+CMT1 bit P4.7
+
+P5 sfr 0C4H
+
+;-----------------------------------------------------------------------------
+
+TCON sfrb 088H
+IT0 bit TCON.0
+IE0 bit TCON.1
+IT1 bit TCON.2
+IE1 bit TCON.3
+TR0 bit TCON.4
+TF0 bit TCON.5
+TR1 bit TCON.6
+TF1 bit TCON.7
+
+TMOD sfr 089H
+TL0 sfr 08AH
+TL1 sfr 08BH
+TH0 sfr 08CH
+TH1 sfr 08DH
+
+CML0 sfr 0A9H
+CML1 sfr 0AAH
+CML2 sfr 0ABH
+CTL0 sfr 0ACH
+CTL1 sfr 0ADH
+CTL2 sfr 0AEH
+CTL3 sfr 0AFH
+
+TM2IR sfrb 0C8H
+CTI0 bit TM2IR.0
+CTI1 bit TM2IR.1
+CTI2 bit TM2IR.2
+CTI3 bit TM2IR.3
+CMI0 bit TM2IR.4
+CMI1 bit TM2IR.5
+CMI2 bit TM2IR.6
+T2OV bit TM2IR.7
+
+CMH0 sfr 0C9H
+CMH1 sfr 0CAH
+CMH2 sfr 0CBH
+CTH0 sfr 0CCH
+CTH1 sfr 0CDH
+CTH2 sfr 0CEH
+CTH3 sfr 0CFH
+
+TM2CON sfr 0EAH
+CTCON sfr 0EBH
+TML2 sfr 0ECH
+TMH2 sfr 0EDH
+
+;-----------------------------------------------------------------------------
+
+S0CON sfrb 098H
+RI bit S0CON.0
+TI bit S0CON.1
+RB8 bit S0CON.2
+TB8 bit S0CON.3
+REN bit S0CON.4
+SM2 bit S0CON.5
+SM1 bit S0CON.6
+SM0 bit S0CON.7
+
+S0BUF sfr 099H
+
+S1CON sfrb 0D8H
+CR0 bit S1CON.0
+CR1 bit S1CON.1
+AA bit S1CON.2
+SI bit S1CON.3
+ST0 bit S1CON.4
+STA bit S1CON.5
+ENS1 bit S1CON.6
+CR2 bit S1CON.7
+
+S1STA sfr 0D9H
+S1DAT sfr 0DAH
+S1ADR sfr 0DBH
+
+;-----------------------------------------------------------------------------
+
+;-----------------------------------------------------------------------------
+
+ADCON sfr 0C5H
+ADCH sfr 0C6H
+
+;-----------------------------------------------------------------------------
+
+STE sfr 0EEH
+RTE sfr 0EFH
+PWM0 sfr 0FCH
+PWM1 sfr 0FDH
+PWMP sfr 0FEH
+T3 sfr 0FFH
+
+;-----------------------------------------------------------------------------
+
+RESET label 000H
+EXTI0 label 003H
+TIMER0 label 00BH
+EXTI1 label 013H
+TIMER1 label 01BH
+SINT label 023H
+I2CBUS label 02BH
+T2CAP0 label 033H
+T2CAP1 label 03BH
+T2CAP2 label 043H
+T2CAP3 label 04BH
+ADCONV label 053H
+T2CMP0 label 05BH
+T2CMP1 label 063H
+T2CMP2 label 06BH
+T2OVER label 073H
diff --git a/include/bitfuncs.inc b/include/bitfuncs.inc
new file mode 100644
index 0000000..fc9706b
--- /dev/null
+++ b/include/bitfuncs.inc
@@ -0,0 +1,85 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.39 - Datei BITFUNCS.INC *
+;* *
+;* Sinn : enthält Funktionen zur Bitmanipulation *
+;* *
+;* letzte Änderungen : 30. 5.1993 *
+;* 11. 9.1993 Meldung nur im 1.Pass *
+;* *
+;****************************************************************************
+
+ ifndef bitfuncsinc ; verhindert Mehrfacheinbindung
+
+bitfuncsinc equ 1
+
+ if mompass=1
+ message "Standardbitfunktionen (C) 1993 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; erstmal einige Unterfunktionen:
+
+; liefert eine Maske in der ab 'start' 'bits' Bit gesetzt sind, z.B. zum
+; Ausmaskieren einzelner Bits:
+
+mask function start,bits,((1<<bits)-1)<<start
+
+; das gleiche invers zum Löschen von Bitgruppen:
+
+invmask function start,bits,~mask(start,bits)
+
+; liefert die Bits 'start' bis 'start'+'bits'-1 aus 'x':
+
+cutout function x,start,bits,x&mask(start,bits)
+
+;----------------------------------------------------------------------------
+; einige häufig gebrauchte Sondermasken:
+
+; oberes Byte eines 16-Bit-Wortes:
+
+hi function x,(x>>8)&255
+
+; dito unteres Byte:
+
+lo function x,x&255
+
+; obere Hälfte aus einem 32-Bit-Wort:
+
+hiword function x,(x>>16)&65535
+
+; dito untere Hälfte:
+
+loword function x,x&65535
+
+; Boolean-Funktionen, ob eine Zahl gerade oder ungerade ist:
+
+odd function x,(x&1)=1
+even function x,(x&1)=0
+
+; liefert Bit 'n' aus 'x':
+
+getbit function x,n,(x>>n)&1
+
+;----------------------------------------------------------------------------
+; Schiebefunktionen:
+
+; Schieben eines 'size'-Bit-Wortes um 'n' Stellen nach links oder rechts:
+
+shln function x,size,n,(x<<n)&mask(0,size)
+shrn function x,size,n,(x>>n)&mask(0,size-n)
+
+; Rotation eines 'size'-Bit-Wortes um 'n' Stellen nach links oder rechts;
+; der erste Term läßt die restlichen Bits unverändert und kann bei Bedarf
+; gelöscht werden:
+
+rotln function x,size,n,cutout(x,size,32-size)|shln(x,size,n)|shrn(x,size,size-n)
+rotrn function x,size,n,cutout(x,size,32-size)|shrn(x,size,n)|shln(x,size,size-n)
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/ctype.inc b/include/ctype.inc
new file mode 100644
index 0000000..9eee3cd
--- /dev/null
+++ b/include/ctype.inc
@@ -0,0 +1,94 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei CTYPE.INC *
+;* *
+;* Sinn : enthält Funktionen zur Untersuchung von Zeichen *
+;* *
+;* letzte Änderungen : 20. 3.1993 *
+;* 11. 9.1993 Meldung nur im 1.Pass *
+;* 19. 2.1994 Funktionen vervollständigt, *
+;* isascii dem C-Standard angepaßt *
+;* *
+;* ACHTUNG! isalpha berücksichtigt keine landesspezifischen Sonderzeichen! *
+;* *
+;****************************************************************************
+
+ ifndef ctypeinc ; verhindert Mehrfacheinbindung
+
+ctypeinc equ 1
+
+ if mompass=1
+ message "Standardzeichenfunktionen (C) 1993 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument eine Ziffer ist:
+
+isdigit function ch,(ch>='0')&&(ch<='9')
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument eine hexadezimale Ziffer ist:
+
+isxdigit function ch,(isdigit(ch))||((toupper(ch)>='A')&&(toupper(ch)<='F'))
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument im Bereich normaler ASCII-Zeichen liegt:
+
+isascii function ch,(ch>=0)&&(ch<128)
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument ein Großbuchstabe ist:
+
+isupper function ch,(ch>='A')&&(ch<='Z')
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument ein Kleinbuchstabe ist:
+
+islower function ch,(ch>='a')&&(ch<='z')
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument ein Buchstabe ist:
+
+isalpha function ch,(toupper(ch)>='A')&&(toupper(ch)<='Z')
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument Ziffer oder Buchstabe ist:
+
+isalnum function ch,isdigit(ch)||isalpha(ch)
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument ein Leerzeichen ist:
+; Hinweis: 11=vertikaler Tabulator
+
+isspace function ch,(ch=' ')||(ch=12)||(ch='\n')||(ch='\r')||(ch='\t')||(ch=11)
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument ein druckbares Zeichen ist:
+; strenggenommen müßte man DEL (127) ausnehmen, aber auf dem PC ist das ein
+; druckbares Zeichen
+
+isprint function ch,(ch>31)&&(ch<255)
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument ein Steuerzeichen ist:
+
+iscntrl function ch,~~isprint(ch)
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument ein druckbares, sichtbares Zeichen ist:
+
+isgraph function ch,isprint(ch)&&(~~isspace(ch))
+
+;----------------------------------------------------------------------------
+; liefert TRUE, falls das Argument ein Sonderzeichen ist:
+
+ispunct function ch,isprint(ch)&&(~~isspace(ch))&&(~~isalnum(ch))
+
+ endif
+
+ restore ; wieder erlauben
+
+
diff --git a/include/h8_3048.inc b/include/h8_3048.inc
new file mode 100644
index 0000000..659e4c9
--- /dev/null
+++ b/include/h8_3048.inc
@@ -0,0 +1,560 @@
+ save
+ listing off
+; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REG3048.INC *
+;* *
+;* Sinn : enthält SFR-, Makro- und Adreadefinitionen für H8/3048 *
+;* *
+;* letzte Änderungen : 24.10.1995 *
+;* *
+;****************************************************************************
+
+ ifndef reg3048inc ; verhindert Mehrfacheinbindung
+
+reg532inc equ 1
+
+ if (MOMCPUNAME<>"HD6413309")&&(MOMCPUNAME<>"H8/300H")
+ fatal "Falscher Prozessortyp eingestellt: nur H8/300H erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "H8/3048-SFR-Definitionen, (C) 1995 Christian Stelter"
+ endif
+
+
+;-----------------------------------------------------------------------------
+; MCU-Operating-Modes: (Sec.3 p.55-68 & Sec.20 p.615-628)
+
+
+MDCR equ $fff1 ; Arbeitsmodus CPU
+SYSCR equ $fff2 ; Standby-Modusregister
+MSTCR equ $ff5e ; Module standby control register
+
+;MDCR-Register
+
+MD0 equ 0
+MD1 equ 1
+MD2 equ 2
+
+
+;SYSCR-Register
+
+SSBY equ 7 ; Software-Standby
+STS2 equ 6 ; Standby-Timer Select
+STS1 equ 5
+STS0 equ 4
+UE equ 3 ; User bit enable
+NMIEG equ 2 ; NMI-edge
+RAME equ 0 ; internes RAM freigeben
+
+
+;MSTCR-Register
+
+PSTOP equ 7 ; Phi-clock stop
+MSTOP5 equ 5 ; Module standby
+MSTOP4 equ 4
+MSTOP3 equ 3
+MSTOP2 equ 2
+MSTOP1 equ 1
+MSTOP0 equ 0
+
+
+
+
+
+
+;-----------------------------------------------------------------------------
+; Bus-Controller (Sec.6 p.107-142)
+
+
+ABWCR equ $ffec ; Bus width control register
+
+ASTCR equ $ffed ; Access state control register
+
+WCR equ $ffee ; Wait control register
+WMS0 equ 2 ; Modus
+WMS1 equ 3
+WC0 equ 0 ; Anzahl Waitstates
+WC1 equ 1
+
+WCER equ $ffef ; Wait state controller enable reg.
+
+BRCR equ $fff3 ; Bus release control register
+A23E equ 7 ; Address 23 enable
+A22E equ 6 ; 22
+A21E equ 5 ; 21
+BRLE equ 0 ; Bus release enable
+
+
+CSCR equ $ff5f ; Chip select control register
+CS7E equ 7 ; Chip-select 7 enabel
+CS6E equ 6
+CS5E equ 5
+CS4E equ 4
+
+
+
+
+
+;-----------------------------------------------------------------------------
+; Interrupt-Controller:
+
+ISCR equ $fff4 ; IRQ sense control register
+IER equ $fff5 ; IRQ enable register
+ISR equ $fff6 ; IRQ status register
+IPRA equ $fff8 ; Prioritätssteuerung
+IPRB equ $fff9 ;
+
+
+;-----------------------------------------------------------------------------
+; Lage Exception und Interrupt-Vektoren: (Sec.4 p.69-78)
+;
+
+__defvec macro Name,Num
+Name equ Num<<2
+ endm
+
+ __defvec Reset,0
+ __defvec NMI,7
+ __defvec TRAP0,8
+ __defvec TRAP1,9
+ __defvec TRAP2,10
+ __defvec TRAP3,11
+ __defvec IRQ0,12
+ __defvec IRQ1,13
+ __defvec IRQ2,14
+ __defvec IRQ3,15
+ __defvec IRQ4,16
+ __defvec IRQ5,17
+ __defvec WOVI,20
+ __defvec CMI,21
+ __defvec IMIA0,24
+ __defvec IMIB0,25
+ __defvec OVI0,26
+ __defvec IMIA1,28
+ __defvec IMIB1,29
+ __defvec OVI1,30
+ __defvec IMIA2,32
+ __defvec IMIB2,33
+ __defvec OVI2,34
+ __defvec IMIA3,36
+ __defvec IMIB3,37
+ __defvec OVI3,38
+ __defvec IMIA4,40
+ __defvec IMIB4,41
+ __defvec OVI4,42
+ __defvec DEND0A,44
+ ;__defvec DEND0A,45
+ __defvec DEND1B,46
+ ;__defvec DEND1B,47
+ __defvec ERI0,52
+ __defvec RXI0,53
+ __defvec TXI0,54
+ __defvec TEI0,55
+ __defvec ERI1,56
+ __defvec RXI1,57
+ __defvec TXI1,58
+ __defvec TEI1,59
+ __defvec ADI,60
+
+
+;-----------------------------------------------------------------------------
+; DMA-Controller (Sec.6 p.181-238)
+
+DTEA equ $fff4 ; Freigabe Datentransfers
+DTEB equ $fff5
+DTEC equ $fff6
+DTED equ $fff7
+
+__defdma macro Base,Name
+MAR{Name}AR equ Base ; Memory address register AR
+MAR{Name}ER equ Base+1 ; Memory address register AE
+MAR{Name}AL equ Base+2 ; Memory address register AL
+MAR{Name}AH equ Base+3 ; Memory address register AH
+ETCR{Name}AH equ Base+4 ; Execute transfer count register AH
+ETCR{Name}AL equ Base+5 ; AL
+IOAR{Name}A equ Base+6 ; I/O address register A
+DTCR{Name}A equ Base+7 ; Data transfer control register A
+MAR{Name}BR equ Base+8 ; Memory address register BR
+MAR{Name}BE equ Base+9 ; Memory address register BE
+MAR{Name}BH equ Base+10 ; Memory address register BH
+MAR{Name}BL equ Base+11 ; Memory address register BL
+ETCR{Name}BH equ Base+12 ; Excute transfer count register BH
+ETCR{Name}BL equ Base+13 ; Excute transfer count register BL
+IOAR{Name}B equ Base+14 ; I/O address register B
+DTCR{Name}B equ Base+15 ; Data transfer control register
+ endm
+
+ __defdma $ff20,"0"
+ __defdma $ff30,"1"
+
+
+
+; DTCR-Register
+
+; short address-mode
+DTE equ 7 ; Data transfer enable
+DTSZ equ 6 ; Data transfer size
+DTID equ 5 ; Data transfer inc/dec
+RPE equ 4 ; Repeat enable
+DTIE equ 3 ; Data transfer interrupt enable
+DTS2 equ 2 ; Data transfer select
+DTS1 equ 1
+DTS0 equ 0
+
+; full address mode
+SAID equ 5 ; Source address inc/dec
+SAIE equ 4 ; Source address inc/dec enable
+DTS2A equ 2 ; Data transfer select
+DTS1A equ 1
+DTS0A equ 0
+
+; DTCRB-Register
+DTME equ 7 ; Data transfer master enable
+DAID equ 5 ; Destination address inc/dec bit
+DAIE equ 4 ; enable
+TMS equ 3 ; Transfer mode select
+DTS2B equ 2 ; Data transfer select
+DTS1B equ 1
+DTS0B equ 0
+
+
+
+
+;-----------------------------------------------------------------------------
+; I/O-Ports: (Sec.9 p.239-280)
+
+P1DDR equ $ffc0 ; Datenrichtung Port 1
+P1DR equ $ffc2 ; Daten Port 1
+
+P2DDR equ $ffc1 ; Datenrichtung Port 2
+P2DR equ $ffc3 ; Daten Port 2
+P2PCR equ $ffd8 ; Input pull-up control register port 3
+
+P3DDR equ $ffc4 ; Datenrichtung Port 3
+P3DR equ $ffc6 ; Daten Port 3
+
+P4DDR equ $ffc5 ; Datenrichtung Port 4
+P4DR equ $ffc7 ; Daten Port 4
+P4PCR equ $ffda ; Input pull-up control register port 4
+
+P5DDR equ $ffc8 ; Datenrichtung Port 5
+P5DR equ $ffca ; Daten Port 5
+P5PCR equ $ffcb ; Input pull-up control register port 5
+
+P6DDR equ $ffc9 ; Datenrichtung Port 6
+P6DR equ $ffcb ; Daten Port 6
+
+P8DDR equ $ffcd ; Datenrichtung Port 8
+P8DR equ $ffcf ; Daten Port 8
+
+P9DDR equ $ffd0 ; Datenrichtung Port 9
+P9DR equ $ffd2 ; Daten Port 9
+
+PADDR equ $ffd1 ; Datenrichtung Port A
+PADR equ $ffd3 ; Daten Port A
+
+PBDDR equ $ffd4 ; Datenrichtung Port B
+PBDR equ $ffd6 ; Daten Port B
+
+;------------------------------------------------------------------------------
+;Integrated Timer Unit (ITU): (Sec.10 p.281-380)
+
+
+
+;common
+TSTR equ $ff60 ; Timer start register
+TSNC equ $ff61 ; Timer synchro register
+TMDR equ $ff62 ; Timer mode register
+TFCR equ $ff63 ; Timer function control register
+TOER equ $ff90 ; Timer output master enable register
+TOCR equ $ff91 ; Timer output control register
+
+
+
+__deftimer macro Base,Name
+TCR{Name} equ Base ; Timer control register
+TIOR{Name} equ Base+1 ; Timer I/O control register
+TIER{Name} equ Base+2 ; Timer interrupt enable register
+TSR{Name} equ Base+3 ; Timer status register
+TCNT{Name}H equ Base+4 ; Timer counter H
+TCNT{Name}L equ Base+5 ; Timer counter L
+GRA{Name}H equ Base+6 ; General register A (high)
+GRA{Name}L equ Base+7 ; General register A (low)
+GRB{Name}H equ Base+8 ; General register B (high)
+GRB{Name}L equ Base+9 ; General register B (low)
+ endm
+
+ __deftimer $ff64,"0"
+ __deftimer $ff6e,"1"
+ __deftimer $ff78,"2"
+ __deftimer $ff82,"3"
+
+BRA3H equ $ff8c ; Buffer register A3 (high)
+BRA3L equ $ff8d ; Buffer register A3 (low)
+BRB3H equ $ff8e ; Buffer register B3 (high)
+BRB3L equ $ff8f ; Buffer register B3 (low)
+
+ __deftimer $ff82,"4"
+
+BRA4H equ $ff9c ; Buffer register A4 (high)
+BRA4L equ $ff9d ; Buffer register A4 (low)
+BRB4H equ $ff9e ; Buffer register B4 (high)
+BRB4L equ $ff9f ; Buffer register B4 (low)
+
+
+
+
+;TMDR-Register
+
+MDF equ 6 ; Phase counting mode flag
+FDIR equ 5 ; Flag direction
+PWM4 equ 4 ; PWM mode
+PWM3 equ 3
+PWM2 equ 2
+PWM1 equ 1
+PWM0 equ 0
+
+
+;TFCR-Register
+
+CMD1 equ 5 ; Combination mode
+CMD0 equ 4
+BFB4 equ 3 ; Buffer mode B4
+BFA4 equ 2 ; Buffer mode A4
+BFB3 equ 1 ; Buffer mode B3
+BFA3 equ 0 ; Buffer mode A3
+
+
+;TOER-Register
+
+EXB4 equ 5 ; Master enable TOCXB4
+EXA4 equ 4 ; Master enable TOCXA4
+EB3 equ 3 ; Master enable TIOCB3
+EB4 equ 2 ; Master enable TIOCB4
+EA4 equ 1 ; Master enable TIOCA4
+EA3 equ 0 ; Master enable TIOCA3
+
+
+;TOCR-Register
+
+XTGD equ 4 ; External trigger disable
+OLS4 equ 1 ; Output level select 4
+OLS3 equ 0 ; Output level select 3
+
+
+;TCR-Register
+
+CCLR1 equ 6 ; Counter clear
+CCLR0 equ 5
+CKEG1 equ 4 ; Counter edge
+CKEG0 equ 3
+TPSC2 equ 2 ; Timer prescaler
+TPSC1 equ 1
+TPSC0 equ 0
+
+
+;TIOR-Register
+
+IOB2 equ 6 ; I/O control B2
+IOB1 equ 5 ; I/O control B1
+IOB0 equ 4 ; I/O control B0
+IOA2 equ 2 ; I/O control A2
+IOA1 equ 1 ; I/O control A1
+IOA0 equ 0 ; I/O control A0
+
+
+;TSR-Register
+
+OVF equ 2 ; Overflow flag
+IMFB equ 1 ; Input capture / compare match flag B
+IMFA equ 0 ; Input capture / compare match flag A
+
+
+;TIER-Register
+
+OVIE equ 2 ; Overflow interrupt enable
+IMIEB equ 1 ; Input capture / compare match interrupt enable B
+IMIEA equ 0 ; Input capture / compare match interrupt enable A
+
+;-----------------------------------------------------------------------------
+;Programmable Timing Pattern Controller (Sec.11 p.381-406)
+
+TPMR equ $ffa0 ; TPC output mode register
+TPCR equ $ffa1 ; TPC output control register
+NDERB equ $ffa2 ; Next data enable register B
+NDERA equ $ffa3 ; Next data enable register A
+NDRA equ $ffa5 ; Next data register A
+NDRB equ $ffa4 ; Next data register B
+NDRA1 equ $ffa5 ; Next data register A group 1
+NDRA0 equ $ffa7 ; Next data register A group 0
+NDRB3 equ $ffa4 ; Next data register B group 3
+NDRB2 equ $ffa6 ; Next data register B group 2
+
+;-----------------------------------------------------------------------------
+; Watchdog: (Sec.12 p.407-422)
+
+WDT_TCSR equ $ffa8 ; Timer control/status register
+WDT_TCNT equ $ffa9 ; Timer counter
+WDT_RSTCSR equ $ffab ; Reset control/status register
+WDT_RSTCSRW equ $ffaa ; dito, zum setzen wordzugriffe (p.415)
+
+
+;TCSR-Register
+
+WDT_OVF equ 7 ; Overflow Flag
+WDT_WTIT equ 6 ; Timer mode select
+WDT_TME equ 5 ; Timer enable
+WDT_CKS2 equ 2 ; Clock select
+WDT_CKS1 equ 1
+WDT_CKS0 equ 0
+
+
+;RSTCSR-Register
+
+WDT_WRST equ 7 ; Watchdog timer reset
+WDT_RSTOE equ 6 ; Reset output enable
+
+
+;-----------------------------------------------------------------------------
+; serielle Schnittstelle: (Sec.13 p.423-482)
+__defSCI macro Base,Name
+SMR{Name} equ Base ; Serial mode register
+BRR{Name} equ Base+1 ; Bit rate register
+SCR{Name} equ Base+2 ; Serial control register
+TDR{Name} equ Base+3 ; Transmit data register
+SSR{Name} equ Base+4 ; Serial status register
+RDR{Name} equ Base+5 ; Receive data register
+ endm
+
+ __defSCI $ffb0,"0"
+ __defSCI $ffb8,"1"
+
+;SMR-Register
+
+CA equ 7 ; Communication mode
+CHR equ 6 ; Character length
+PE equ 5 ; Parity enable
+OE equ 4 ; Parity mode
+STOP equ 3 ; Stop bit length
+MP equ 2 ; Multiprocessor mode
+CKS1 equ 1 ; Clock select 1
+CKS0 equ 0
+
+
+;SCR-Register
+
+TIE equ 7 ; Transmit interrupt enable
+RIE equ 6 ; Receive " "
+TE equ 5 ; Transmit enable
+RE equ 4 ; Receive enable
+MPIE equ 3 ; Multiprozessor interrupt enable
+TEIE equ 2 ; Transmit-end interrupt enable
+CKE1 equ 1 ; Clock enable 1
+CKE0 equ 0 ;
+
+
+;SSR-Register
+
+TDRE equ 7 ; Transmit data register empty
+RDRF equ 6 ; Receive data register full
+ORER equ 5 ; Overrun error
+FER equ 4 ; Framing error
+PER equ 3 ; Parity error
+TEND equ 2 ; Transmit end
+MPB equ 1 ; Multiprocessor bit
+MPBT equ 0 ; Multiprocessor bit transfer
+
+
+
+;-----------------------------------------------------------------------------
+;Smart Card interface
+
+
+
+;not implemented yet
+
+
+
+;-----------------------------------------------------------------------------
+; A/D-Wandler: (Sec.15 p.505-526)
+
+ADDRA equ $ffe0
+ADDRAH equ $ffe0 ;
+ADDRAL equ $ffe1 ;
+
+ADDRB equ $ffe2
+ADDRBH equ $ffe2
+ADDRBL equ $ffe3
+
+ADDRC equ $ffe4
+ADDRCH equ $ffe4
+ADDRCL equ $ffe5
+
+
+ADDRD equ $ffe6
+ADDRDH equ $ffe6
+ADDRDL equ $ffe7
+
+
+
+ADCSR equ $ffe8 ; Steuer/Statusregister:
+
+ADF equ 7 ; Wandlung abgeschlossen
+ADIE equ 6 ; Interrupt bei Wandelende?
+ADST equ 5 ; Wandlung starten
+SCAN equ 4 ; Scan-Modus
+CKS equ 3 ; Wandlungszeit
+CH2 equ 2 ; Kanalauswahl
+CH1 equ 1
+CH0 equ 0
+
+
+ADCR equ $ffe9 ; A/D control register
+
+TRGE equ 7 ; Trigger enable
+
+
+;-----------------------------------------------------------------------------
+;D/A-Wandler (Sec.16 p.527-533)
+
+DADR0 equ $ffdc ; D/A data register 0
+DADR1 equ $ffdd ; D/A data register 1
+DACR equ $ffde ; D/A control register
+DASTCR equ $ff5c ; D/A standby control register
+
+
+;DACR-Register
+
+DAOE1 equ 7 ; D/A output enable
+DAOE0 equ 6
+DAE equ 5 ; D/A enable
+
+
+;DASTCR-Register
+
+DASTE equ 0 ; D/A standby enable
+
+
+
+
+;-----------------------------------------------------------------------------
+;Clock-Pulse Generator (Sec.19 p.607-614)
+
+DIVCR equ $ff5d ; Divison control register
+
+
+DIV1 equ 1
+DIV0 equ 0
+
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+ endif
+ restore
+
diff --git a/include/reg166.inc b/include/reg166.inc
new file mode 100644
index 0000000..e15cb73
--- /dev/null
+++ b/include/reg166.inc
@@ -0,0 +1,780 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei REG166.INC *
+;* *
+;* Sinn : enthält SFR-, Makro- und Adreßdefinitionen für 80C166/167 *
+;* OK, der Name fällt aus dem Rahmen, aber STDDEF16.INC war schon *
+;* belegt... *
+;* *
+;* letzte Änderungen : 23. 6.1994 *
+;* 27. 6.1994 Makros *
+;* 28. 6.1994 Bitadressen *
+;* 9. 7.1994 Interrupt-Register-Korrektur *
+;* 10. 7.1994 80C167-Register *
+;* 10.12.1994 Korrekturen/Erweiterungen 80C166 *
+;* (Hinweis von A. Kipper/A.Bergmann) *
+;* *
+;****************************************************************************
+
+ ifndef reg166inc ; verhindert Mehrfacheinbindung
+
+reg166inc equ 1
+
+ if (MOMCPU<>8438118)&&(MOMCPU<>8438119)
+ fatal "Falscher Prozessortyp eingestellt: nur 80C166 oder 80C167 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "80C166/167-SFR-Definitionen (C) 1994 Alfred Arnold"
+ message "binde \{MOMCPU}-SFRs ein"
+ endif
+
+; damit's etwas kürzer wird:
+
+DefIntBits macro BASE,adr,{NoExpand} ; Interruptregister+Bits darin def.
+tmpstr166 set "BASE"
+{tmpstr166}IC equ adr
+{tmpstr166}_GLVL bit {tmpstr166}IC.0 ; Gruppenpriorität
+{tmpstr166}_ILVL bit {tmpstr166}IC.2 ; Interruptpriorität
+{tmpstr166}IE bit {tmpstr166}IC.6 ; Interruptfreigabe
+{tmpstr166}IR bit {tmpstr166}IC.7 ; Interruptanzeige
+ endm
+
+;----------------------------------------------------------------------------
+; Spezialregister:
+; Bitadressen nur für bitadressierbare Register !
+; bei Bitfeldern nur Startbit !
+
+ if MOMCPU=80C167H
+SYSCON equ 0ff12h ; Systemkonfiguration
+WRCFG bit SYSCON.7 ; /WRL und /WRH statt /WR und /BHE
+ROMS1 bit SYSCON.12 ; Lage internes ROM
+ elseif
+SYSCON equ 0ff0ch
+MCTC bit SYSCON.0 ; Speicherzykluslänge
+RWDC bit SYSCON.4 ; Schreib/Lese-Verzögerung
+MTTC bit SYSCON.5 ; Tri-State-Zeit
+BTYP bit SYSCON.6 ; Status der EBC-Pins
+RDYEN bit SYSCON.12 ; /READY freigeben
+ endif
+CLKEN bit SYSCON.8 ; CLKOUT freigeben
+BYTDIS bit SYSCON.9 ; /BHE freigeben
+ROMEN bit SYSCON.10 ; internes ROM freigeben
+SGTDIS bit SYSCON.11 ; Adreßraum auf 64K beschränken
+STKSZ bit SYSCON.13 ; Maximalgröße Stack
+
+ if MOMCPU=80C167H
+RP0H equ 0f108h ; Systemanlaufregister (nur Lesen)
+CSSEL bit RP0H.1 ; Anzahl CS-Leitungen
+SALSEL bit RP0H.3 ; Anzahl Adreßleitungen ab A16
+ endif
+
+PSW equ 0ff10h ; Flagregister
+N bit PSW.0 ; negatives Ergebnis ?
+C bit PSW.1 ; Carry ?
+V bit PSW.2 ; Overflow ?
+Z bit PSW.3 ; Ergebnis Null ?
+E bit PSW.4 ; Tabellenende ?
+MULIP bit PSW.5 ; Multiplikation/Division unterbrochen ?
+USR0 bit PSW.6 ; benutzerdefiniert
+IEN bit PSW.11 ; Interrupts freigeben
+ILVL bit PSW.12 ; mom. bediente Interruptebene
+
+TFR equ 0ffach ; Trap Flagregister
+ILLBUS bit TFR.0 ; externer Bus benutzt, aber nicht konfiguriert
+ILLINA bit TFR.1 ; Codezugriff auf ungerade Adresse
+ILLOPA bit TFR.2 ; Wortzugriff auf ungerade Adresse
+PRTFLT bit TFR.3 ; Schutzverletzung
+UNDOPC bit TFR.7 ; undefinierter Maschinenbefehl
+STKUF bit TFR.13 ; Stack-Unterlauf
+STKOF bit TFR.14 ; Stack-Überlauf
+NMI bit TFR.15 ; nicht maskierbarer Interrupt
+ if MOMCPU=80C167H
+EXICON equ 0f1c0h ; Steuerung externer Interrupt-Controller
+EXI0ES bit EXICON.0 ; Flankensteuerung Interrupt 0
+EXI1ES bit EXICON.2 ; Flankensteuerung Interrupt 1
+EXI2ES bit EXICON.4 ; Flankensteuerung Interrupt 2
+EXI3ES bit EXICON.6 ; Flankensteuerung Interrupt 3
+EXI4ES bit EXICON.8 ; Flankensteuerung Interrupt 4
+EXI5ES bit EXICON.10 ; Flankensteuerung Interrupt 5
+EXI6ES bit EXICON.12 ; Flankensteuerung Interrupt 6
+EXI7ES bit EXICON.14 ; Flankensteuerung Interrupt 7
+ endif
+
+DPP0 equ 0fe00h ; Pagingregister
+DPP1 equ 0fe02h
+DPP2 equ 0fe04h
+DPP3 equ 0fe06h
+
+CSP equ 0fe08h ; Bits 16.. Programmzähler
+
+MDH equ 0fe0ch ; Multiplizier/Dividierregister
+MDL equ 0fe0eh
+MDC equ 0ff0eh ; Steuerung Multiplizierer/Dividierer
+MDRIU bit MDC.4 ; Multiplizierer in Benutzung
+
+CP equ 0fe10h ; Registerkontextzeiger
+
+SP equ 0fe12h ; Stackpointer
+STKOV equ 0fe14h ; obere Grenze Stackpointer
+STKUN equ 0fe16h ; untere Grenze Stackpointer
+
+ZEROS equ 0ff1ch ; konstant Nullen
+ONES equ 0ff1eh ; konstant Einsen
+
+;----------------------------------------------------------------------------
+; Speicher-Interface
+
+ if MOMCPU=80C167H
+ADDRSEL1 equ 0fe18h ; Adreßdekoder Register 1..4
+ADDRSEL2 equ 0fe1ah
+ADDRSEL3 equ 0fe1ch
+ADDRSEL4 equ 0fe1eh
+
+BUSCON0 equ 0ff0ch ; Buskonfiguration Register 0..4
+MCTC0 bit BUSCON0.0 ; Speicherzykluslänge
+RWDC0 bit BUSCON0.4 ; Schreib/Leseverzögerung
+MTTC0 bit BUSCON0.5 ; Tri-State-Zeit
+BTYP0 bit BUSCON0.6 ; Status EBC-Pins
+ALECTL0 bit BUSCON0.9 ; ALE Verlängerung
+BUSACT0 bit BUSCON0.10 ; Bus aktiv-Steuerbit
+RDYEN0 bit BUSCON0.12 ; /READY benutzen
+BUSCON1 equ 0ff14h
+MCTC1 bit BUSCON1.0 ; Speicherzykluslänge
+RWDC1 bit BUSCON1.4 ; Schreib/Leseverzögerung
+MTTC1 bit BUSCON1.5 ; Tri-State-Zeit
+BTYP1 bit BUSCON1.6 ; Status EBC-Pins
+ALECTL1 bit BUSCON1.9 ; ALE Verlängerung
+BUSACT1 bit BUSCON1.10 ; Bus aktiv-Steuerbit
+RDYEN1 bit BUSCON1.12 ; /READY benutzen
+CSREN1 bit BUSCON1.14 ; Arbeitsweise CS-Pins
+CSWEN1 bit BUSCON1.15
+BUSCON2 equ 0ff16h
+MCTC2 bit BUSCON2.0 ; s.o.
+RWDC2 bit BUSCON2.4
+MTTC2 bit BUSCON2.5
+BTYP2 bit BUSCON2.6
+ALECTL2 bit BUSCON2.9
+BUSACT2 bit BUSCON2.10
+RDYEN2 bit BUSCON2.12
+CSREN2 bit BUSCON2.14
+CSWEN2 bit BUSCON2.15
+BUSCON3 equ 0ff18h
+MCTC3 bit BUSCON3.0
+RWDC3 bit BUSCON3.4
+MTTC3 bit BUSCON3.5
+BTYP3 bit BUSCON3.6
+ALECTL3 bit BUSCON3.9
+BUSACT3 bit BUSCON3.10
+RDYEN3 bit BUSCON3.12
+CSREN3 bit BUSCON3.14
+CSWEN3 bit BUSCON3.15
+BUSCON4 equ 0ff1ah
+MCTC4 bit BUSCON4.0
+RWDC4 bit BUSCON4.4
+MTTC4 bit BUSCON4.5
+BTYP4 bit BUSCON4.6
+ALECTL4 bit BUSCON4.9
+BUSACT4 bit BUSCON4.10
+RDYEN4 bit BUSCON4.12
+CSREN4 bit BUSCON4.14
+CSWEN4 bit BUSCON4.15
+
+ DefIntBits XP0,0f186h ; Interruptsteuerung Peripheriegerät 0
+ DefIntBits XP1,0f18eh ; Interruptsteuerung Peripheriegerät 1
+ DefIntBits XP2,0f196h ; Interruptsteuerung Peripheriegerät 2
+ DefIntBits XP3,0f19eh ; Interruptsteuerung Peripheriegerät 3
+ endif
+
+;----------------------------------------------------------------------------
+; Ports:
+
+ if MOMCPU=80C167H
+P0L equ 0ff00h ; Port 0 Datenregister
+P0H equ 0ff02h
+DP0L equ 0f100h ; Port 0 Datenrichtungsregister
+DP0H equ 0f102h
+ elseif
+P0 equ 0ff00h
+DP0 equ 0ff02h
+ endif
+
+ if MOMCPU=80C167H
+P1L equ 0ff04h ; Port 1 Datenregister
+P1H equ 0ff06h
+DP1L equ 0f104h ; Port 1 Datenrichtungsregister
+DP1H equ 0f106h
+ elseif
+P1 equ 0ff04h
+DP1 equ 0ff06h
+ endif
+
+P2 equ 0ffc0h ; Port 2 Datenregister
+DP2 equ 0ffc2h ; Port 2 Datenrichtungsregister
+ if MOMCPU=80C167H
+ODP2 equ 0f1c2h ; Port 2 Open-Drain-Einstellung
+ endif
+
+P3 equ 0ffc4h ; Port 3 Datenregister
+DP3 equ 0ffc6h ; Port 3 Datenrichtungsregister
+ if MOMCPU=80C167H
+ODP3 equ 0f1c6h ; Port 3 Open-Drain-Einstellung
+ endif
+
+ if MOMCPU=80C167H
+P4 equ 0ffc8h ; Port 4 Datenregister
+DP4 equ 0ffcah ; Port 4 Datenrichtungsregister
+ elseif
+P4 equ 0ff08h
+DP4 equ 0ff0ah
+ endif
+
+P5 equ 0ffa2h ; Port 5 Datenregister (nur Eingang)
+
+ if MOMCPU=80C167H
+P6 equ 0ffcch ; Port 6 Datenregister
+DP6 equ 0ffceh ; Port 6 Datenrichtungsregister
+ODP6 equ 0f1ceh ; Port 6 Open-Drain-Einstellung
+
+P7 equ 0ffd0h ; Port 7 Datenregister
+DP7 equ 0ffd2h ; Port 7 Datenrichtungsregister
+ODP7 equ 0f1d2h ; Port 7 Open-Drain-Einstellung
+
+P8 equ 0ffd4h ; Port 8 Datenregister
+DP8 equ 0ffd6h ; Port 8 Datenrichtungsregister
+ODP8 equ 0f1d6h ; Port 8 Open-Drain-Einstellung
+ endif
+
+;----------------------------------------------------------------------------
+; Timer:
+
+T0 equ 0fe50h ; CAPCOM Timer 0
+T0REL equ 0fe54h ; Timer 0 Reload Register
+T01CON equ 0ff50h ; Steuerregister Timer 0+1
+T0I bit T01CON.0 ; Timer 0 Eingangssignalwahl
+T0M bit T01CON.3 ; Timer 0 Modus
+T0R bit T01CON.6 ; Timer 0 starten/stoppen
+T1I bit T01CON.8 ; Timer 1 Eingangssignalwahl
+T1M bit T01CON.11 ; Timer 1 Modus
+T1R bit T01CON.14 ; Timer 1 starten/stoppen
+ DefIntBits T0,0ff9ch ; Timer 0 Interruptsteuerung
+
+T1 equ 0fe52h ; CAPCOM Timer 1
+T1REL equ 0fe56h ; Timer 1 Reload Register
+ DefIntBits T1,0ff9eh ; Timer 1 Interruptsteuerung
+
+T2 equ 0fe40h ; Timer 2
+T2CON equ 0ff40h ; Steuerregister Timer 2
+T2I bit T2CON.0 ; Eingangssignal Timer 2
+T2M bit T2CON.3 ; Modus Timer 2
+T2R bit T2CON.6 ; Timer 2 starten/stoppen
+T2UD bit T2CON.7 ; Timer 2 Zählrichtung
+ if MOMCPU=80C167H
+T2UDE bit T2CON.8 ; Timer 2 externe Zählrichtungswahl
+ endif
+ DefIntBits T2,0ff60h ; Timer 2 Interruptsteuerung
+
+T3 equ 0fe42h ; Timer 3
+T3CON equ 0ff42h ; Steuerregister Timer 3
+T3I bit T3CON.0 ; Eingangssignal Timer 3
+T3M bit T3CON.3 ; Modus Timer 3
+T3R bit T3CON.6 ; Timer 3 starten/stoppen
+T3UD bit T3CON.7 ; Timer 3 Zählrichtung
+T3UDE bit T3CON.8 ; Timer 3 externe Zählrichtungswahl
+T3OE bit T3CON.9 ; Timer 3 Ausgang freischalten
+T3OTL bit T3CON.10 ; Timer 3 übergelaufen ?
+ DefIntBits T3,0ff62h ; Timer 3 Interruptsteuerung
+
+T4 equ 0fe44h ; Timer 4
+T4CON equ 0ff44h ; Steuerregister Timer 4
+T4I bit T4CON.0 ; Eingangssignal Timer 4
+T4M bit T4CON.3 ; Modus Timer 4
+T4R bit T4CON.6 ; Timer 4 starten/stoppen
+T4UD bit T4CON.7 ; Timer 4 Zählrichtung
+ if MOMCPU=80C167H
+T4UDE bit T4CON.8 ; Timer 4 externe Zählrichtungswahl
+ endif
+ DefIntBits T4,0ff64h ; Timer 4 Interruptsteuerung
+
+T5 equ 0fe46h ; Timer 5
+T5CON equ 0ff46h ; Steuerregister Timer 5
+T5I bit T5CON.0 ; Eingangssignal Timer 5
+T5M bit T5CON.3 ; Modus Timer 5
+T5R bit T5CON.6 ; Timer 5 starten/stoppen
+T5UD bit T5CON.7 ; Timer 5 Zählrichtung
+ if MOMCPU=80C167H
+T5UDE bit T5CON.8 ; Timer 5 externe Zählrichtungswahl
+ endif
+CI bit T5CON.12 ; CAPREL Eingangswahl
+T5CLR bit T5CON.14 ; Timer 5 bei Fang löschen ?
+T5SC bit T5CON.15 ; Timer 5 Fangen freigeben
+ DefIntBits T5,0ff66h ; Timer 5 Interruptsteuerung
+
+T6 equ 0fe48h ; Timer 6
+T6CON equ 0ff48h ; Steuerregister Timer 6
+T6I bit T6CON.0 ; Eingangssignal Timer 6
+ if MOMCPU=80C167H
+T6M bit T6CON.3 ; Modus Timer 6
+ endif
+T6R bit T6CON.6 ; Timer 6 starten/stoppen
+T6UD bit T6CON.7 ; Timer 6 Zählrichtung
+ if MOMCPU=80C167H
+T6UDE bit T6CON.8 ; Timer 6 externe Zählrichtungswahl
+ endif
+T6OE bit T6CON.9 ; Timer 6 Ausgang freischalten
+T6OTL bit T6CON.10 ; Timer 6 übergelaufen ?
+T6SR bit T6CON.15 ; Timer 6 Reload
+ DefIntBits T6,0ff68h ; Timer 6 Interruptsteuerung
+
+ if MOMCPU=80C167H
+T7 equ 0f050h ; Timer 7
+T7REL equ 0f054h ; Timer 7 Reload Register
+T78CON equ 0ff20h ; Steuerregister Timer 7+8
+ DefIntBits T7,0f17ah ; Timer 0 Interruptsteuerung
+
+T8 equ 0f052h ; CAPCOM Timer 8
+T8REL equ 0f056h ; Timer 8 Reload Register
+ DefIntBits T8,0f17ch ; Timer 8 Interruptsteuerung
+ endif
+
+;-----------------------------------------------------------------------
+; Capture/Compare-Einheit:
+
+CAPREL equ 0fe4ah ; Capture/Reload-Register
+CC0 equ 0fe80h ; CAPCOM Register
+CC1 equ 0fe82h
+CC2 equ 0fe84h
+CC3 equ 0fe86h
+CC4 equ 0fe88h
+CC5 equ 0fe8ah
+CC6 equ 0fe8ch
+CC7 equ 0fe8eh
+CC8 equ 0fe90h
+CC9 equ 0fe92h
+CC10 equ 0fe94h
+CC11 equ 0fe96h
+CC12 equ 0fe98h
+CC13 equ 0fe9ah
+CC14 equ 0fe9ch
+CC15 equ 0fe9eh
+ if MOMCPU=80C167H
+CC16 equ 0fe60h ; zus. CAPCOM Register
+CC17 equ 0fe62h
+CC18 equ 0fe64h
+CC19 equ 0fe66h
+CC20 equ 0fe68h
+CC21 equ 0fe6ah
+CC22 equ 0fe6ch
+CC23 equ 0fe6eh
+CC24 equ 0fe70h
+CC25 equ 0fe72h
+CC26 equ 0fe74h
+CC27 equ 0fe76h
+CC28 equ 0fe78h
+CC29 equ 0fe7ah
+CC30 equ 0fe7ch
+CC31 equ 0fe7eh
+ endif
+
+CCM0 equ 0ff52h ; CAPCOM Modusregister
+CCMOD0 bit CCM0.0 ; CC0 Modusauswahl
+ACC0 bit CCM0.3 ; CC0 Timer 0/1 zuordnen
+CCMOD1 bit CCM0.4 ; CC1 Modusauswahl
+ACC1 bit CCM0.7 ; CC1 Timer 0/1 zuordnen
+CCMOD2 bit CCM0.8 ; CC2 Modusauswahl
+ACC2 bit CCM0.11 ; CC2 Timer 0/1 zuordnen
+CCMOD3 bit CCM0.12 ; CC3 Modusauswahl
+ACC3 bit CCM0.15 ; CC3 Timer 0/1 zuordnen
+
+CCM1 equ 0ff54h
+CCMOD4 bit CCM1.0 ; CC4 Modusauswahl
+ACC4 bit CCM1.3 ; CC4 Timer 0/1 zuordnen
+CCMOD5 bit CCM1.4 ; CC5 Modusauswahl
+ACC5 bit CCM1.7 ; CC5 Timer 0/1 zuordnen
+CCMOD6 bit CCM1.8 ; CC6 Modusauswahl
+ACC6 bit CCM1.11 ; CC6 Timer 0/1 zuordnen
+CCMOD7 bit CCM1.12 ; CC7 Modusauswahl
+ACC7 bit CCM1.15 ; CC7 Timer 0/1 zuordnen
+
+CCM2 equ 0ff56h
+CCMOD8 bit CCM2.0 ; CC8 Modusauswahl
+ACC8 bit CCM2.3 ; CC8 Timer 0/1 zuordnen
+CCMOD9 bit CCM2.4 ; CC9 Modusauswahl
+ACC9 bit CCM2.7 ; CC9 Timer 0/1 zuordnen
+CCMOD10 bit CCM2.8 ; CC10 Modusauswahl
+ACC10 bit CCM2.11 ; CC10 Timer 0/1 zuordnen
+CCMOD11 bit CCM2.12 ; CC11 Modusauswahl
+ACC11 bit CCM2.15 ; CC11 Timer 0/1 zuordnen
+
+CCM3 equ 0ff58h
+CCMOD12 bit CCM3.0 ; CC12 Modusauswahl
+ACC12 bit CCM3.3 ; CC12 Timer 0/1 zuordnen
+CCMOD13 bit CCM3.4 ; CC13 Modusauswahl
+ACC13 bit CCM3.7 ; CC13 Timer 0/1 zuordnen
+CCMOD14 bit CCM3.8 ; CC14 Modusauswahl
+ACC14 bit CCM3.11 ; CC14 Timer 0/1 zuordnen
+CCMOD15 bit CCM3.12 ; CC15 Modusauswahl
+ACC15 bit CCM3.15 ; CC15 Timer 0/1 zuordnen
+
+CCM4 equ 0ff22h
+CCMOD16 bit CCM4.0 ; CC16 Modusauswahl
+ACC16 bit CCM4.3 ; CC16 Timer 0/1 zuordnen
+CCMOD17 bit CCM4.4 ; CC17 Modusauswahl
+ACC17 bit CCM4.7 ; CC17 Timer 0/1 zuordnen
+CCMOD18 bit CCM4.8 ; CC18 Modusauswahl
+ACC18 bit CCM4.11 ; CC18 Timer 0/1 zuordnen
+CCMOD19 bit CCM4.12 ; CC19 Modusauswahl
+ACC19 bit CCM4.15 ; CC19 Timer 0/1 zuordnen
+
+CCM5 equ 0ff24h
+CCMOD20 bit CCM5.0 ; CC20 Modusauswahl
+ACC20 bit CCM5.3 ; CC20 Timer 0/1 zuordnen
+CCMOD21 bit CCM5.4 ; CC21 Modusauswahl
+ACC21 bit CCM5.7 ; CC21 Timer 0/1 zuordnen
+CCMOD22 bit CCM5.8 ; CC22 Modusauswahl
+ACC22 bit CCM5.11 ; CC22 Timer 0/1 zuordnen
+CCMOD23 bit CCM5.12 ; CC23 Modusauswahl
+ACC23 bit CCM5.15 ; CC23 Timer 0/1 zuordnen
+
+CCM6 equ 0ff26h
+CCMOD24 bit CCM6.0 ; CC24 Modusauswahl
+ACC24 bit CCM6.3 ; CC24 Timer 0/1 zuordnen
+CCMOD25 bit CCM6.4 ; CC25 Modusauswahl
+ACC25 bit CCM6.7 ; CC25 Timer 0/1 zuordnen
+CCMOD26 bit CCM6.8 ; CC26 Modusauswahl
+ACC26 bit CCM6.11 ; CC26 Timer 0/1 zuordnen
+CCMOD27 bit CCM6.12 ; CC27 Modusauswahl
+ACC27 bit CCM6.15 ; CC27 Timer 0/1 zuordnen
+
+CCM7 equ 0ff28h
+CCMOD28 bit CCM7.0 ; CC28 Modusauswahl
+ACC28 bit CCM7.3 ; CC28 Timer 0/1 zuordnen
+CCMOD29 bit CCM7.4 ; CC29 Modusauswahl
+ACC29 bit CCM7.7 ; CC29 Timer 0/1 zuordnen
+CCMOD30 bit CCM7.8 ; CC30 Modusauswahl
+ACC30 bit CCM7.11 ; CC30 Timer 0/1 zuordnen
+CCMOD31 bit CCM7.12 ; CC31 Modusauswahl
+ACC31 bit CCM7.15 ; CC31 Timer 0/1 zuordnen
+
+ DefIntBits CR,0ff6ah ; CAPREL Interruptsteuerregister
+
+ DefIntBits CC0,0ff78h ; Interruptsteuerung CAPCOM-Kanäle
+ DefIntBits CC1,0ff7ah
+ DefIntBits CC2,0ff7ch
+ DefIntBits CC3,0ff7eh
+ DefIntBits CC4,0ff80h
+ DefIntBits CC5,0ff82h
+ DefIntBits CC6,0ff84h
+ DefIntBits CC7,0ff86h
+ DefIntBits CC8,0ff88h
+ DefIntBits CC9,0ff8ah
+ DefIntBits CC10,0ff8ch
+ DefIntBits CC11,0ff8eh
+ DefIntBits CC12,0ff90h
+ DefIntBits CC13,0ff92h
+ DefIntBits CC14,0ff94h
+ DefIntBits CC15,0ff96h
+ if MOMCPU=80C167H
+ DefIntBits CC16,0f160h ; Interruptsteuerung zus. CAPCOM-Kanäle
+ DefIntBits CC17,0f162h
+ DefIntBits CC18,0f164h
+ DefIntBits CC19,0f166h
+ DefIntBits CC20,0f168h
+ DefIntBits CC21,0f16ah
+ DefIntBits CC22,0f16ch
+ DefIntBits CC23,0f16eh
+ DefIntBits CC24,0f170h
+ DefIntBits CC25,0f172h
+ DefIntBits CC26,0f174h
+ DefIntBits CC27,0f176h
+ DefIntBits CC28,0f178h
+ DefIntBits CC29,0f184h
+ DefIntBits CC30,0f18ch
+ DefIntBits CC31,0f194h
+ endif
+
+PECC0 equ 0fec0h ; PEC Kanalsteuerregister
+PECC1 equ 0fec2h
+PECC2 equ 0fec4h
+PECC3 equ 0fec6h
+PECC4 equ 0fec8h
+PECC5 equ 0fecah
+PECC6 equ 0fecch
+PECC7 equ 0feceh
+
+SRCP0 equ 0fde0h ; hoffentlich gilt das auch so für
+SRCP1 equ 0fde4h ; den 167er, ich habe momentan näm-
+SRCP2 equ 0fde8h ; lich nicht das Datenbuch zur Hand...
+SRCP3 equ 0fdech
+SRCP4 equ 0fdf0h
+SRCP5 equ 0fdf4h
+SRCP6 equ 0fdf8h
+SRCP7 equ 0fdfch
+DSTP0 equ 0fde2h
+DSTP1 equ 0fde6h
+DSTP2 equ 0fdeah
+DSTP3 equ 0fdeeh
+DSTP4 equ 0fdf2h
+DSTP5 equ 0fdf6h
+DSTP6 equ 0fdfah
+DSTP7 equ 0fdfeh
+
+;----------------------------------------------------------------------------
+; Pulsweitenmodulator:
+
+ if MOMCPU=80C167H
+PP0 equ 0f038h ; PWM Periode 0
+PT0 equ 0f030h ; PWM Zähler 0
+PW0 equ 0fe30h ; PWM Pulsweite 0
+PP1 equ 0f03ah ; PWM Periode 1
+PT1 equ 0f032h ; PWM Zähler 1
+PW1 equ 0fe30h ; PWM Pulsweite 1
+PP2 equ 0f03ch ; PWM Periode 2
+PT2 equ 0f034h ; PWM Zähler 2
+PW2 equ 0fe30h ; PWM Pulsweite 2
+PP3 equ 0f03eh ; PWM Periode 3
+PT3 equ 0f036h ; PWM Zähler 3
+PW3 equ 0fe30h ; PWM Pulsweite 3
+PWMCON0 equ 0ff30h ; PWM Seuerregister 0
+PTR0 bit PWMCON0.0 ; PT0 laufen lassen
+PTR1 bit PWMCON0.1 ; PT1 laufen lassen
+PTR2 bit PWMCON0.2 ; PT2 laufen lassen
+PTR3 bit PWMCON0.3 ; PT3 laufen lassen
+PTI0 bit PWMCON0.4 ; PT0 Eingangswahl
+PTI1 bit PWMCON0.5 ; PT1 Eingangswahl
+PTI2 bit PWMCON0.6 ; PT2 Eingangswahl
+PTI3 bit PWMCON0.7 ; PT3 Eingangswahl
+PIE0 bit PWMCON0.8 ; PT0 Interupts freigeben
+PIE1 bit PWMCON0.9 ; PT1 Interupts freigeben
+PIE2 bit PWMCON0.10 ; PT2 Interupts freigeben
+PIE3 bit PWMCON0.11 ; PT3 Interupts freigeben
+PIR0 bit PWMCON0.12 ; PT0 Interupt aufgetreten
+PIR1 bit PWMCON0.13 ; PT1 Interupt aufgetreten
+PIR2 bit PWMCON0.14 ; PT2 Interupt aufgetreten
+PIR3 bit PWMCON0.15 ; PT3 Interupt aufgetreten
+PWMCON1 equ 0ff32h ; PWM Seuerregister 1
+PEN0 bit PWMCON1.0 ; PT0 Ausgang freigeben
+PEN1 bit PWMCON1.1 ; PT1 Ausgang freigeben
+PEN2 bit PWMCON1.2 ; PT2 Ausgang freigeben
+PEN3 bit PWMCON1.3 ; PT3 Ausgang freigeben
+PM0 bit PWMCON1.4 ; PT0 Modus
+PM1 bit PWMCON1.5 ; PT1 Modus
+PM2 bit PWMCON1.6 ; PT2 Modus
+PM3 bit PWMCON1.7 ; PT3 Modus
+PB01 bit PWMCON1.12 ; PT0&1 Burst-Modus
+PS2 bit PWMCON1.14 ; PT2 Einzelimpulsmodus
+PS3 bit PWMCON1.15 ; PT3 Einzelimpulsmodus
+ DefIntBits PWM,0f17eh ; PWM Interruptsteuerung
+ endif
+
+;----------------------------------------------------------------------------
+; A/D-Wandler:
+
+ADDAT equ 0fea0h ; A/D-Wandler Ergebnis
+ if MOMCPU=80C167H
+ADDAT2 equ 0f0a0h ; A/D-Wandler Ergebnis 2
+ endif
+ DefIntBits ADC,0ff98h ; A/D-Wandler Interruptsteuerung für Wandlungsende
+ DefIntBits ADE,0ff9ah ; A/D-Wandler Interruptsteuerung für Fehler
+ADCON equ 0ffa0h ; A/D-Wandler Steuerregister
+ADCH bit ADCON.0 ; A/D-Wandler Kanalwahl
+ADM bit ADCON.4 ; A/D-Wandler Modus
+ADST bit ADCON.7 ; A/D-Wandlung starten
+ADBSY bit ADCON.8 ; A/D-Wandler beschäftigt
+ if MOMCPU=80C167H
+ADWR bit ADCON.9 ; A/D-Wandler erst wieder starten, wenn gelesen
+ADCIN bit ADCON.10 ; A/D-Wandler Kanalinjektion (??...)
+ADCRQ bit ADCON.11 ; A/D-Wandler Kanalinjektion angefordert
+ endif
+
+;----------------------------------------------------------------------------
+; Watchdog:
+
+WDT equ 0feaeh ; Watchdog-Zähler
+WDTCON equ 0ffaeh ; Watchdog Steuerregister
+WDTIN bit WDTCON.0 ; Watchdog Eingangsfrequenz
+WDTR bit WDTCON.1 ; Reset durch Watchdog ?
+WDTREL bit WDTCON.8 ; Reload-Wert Watchdog
+
+;----------------------------------------------------------------------------
+; Serielles:
+
+S0TBUF equ 0feb0h ; SIO0 Senderegister
+S0RBUF equ 0feb2h ; SIO0 Empfangsregister
+S0BG equ 0feb4h ; SIO0 Baudrateneinstellung
+ DefIntBits S0T,0ff6ch ; Interruptsteuerung Sendeteil SIO0
+ DefIntBits S0R,0ff6eh ; Interruptsteuerung Empfangsteil SIO0
+ DefIntBits S0E,0ff70h ; Interruptsteuerung Fehlererkennung SIO0
+S0CON equ 0ffb0h ; Steuerregister SIO0
+S0M bit S0CON.0 ; SIO0 Modus
+S0STP bit S0CON.3 ; SIO0 Anzahl Stopbits
+S0REN bit S0CON.4 ; SIO0 Empfänger freigeben
+S0PEN bit S0CON.5 ; SIO0 mit Parität
+S0FEN bit S0CON.6 ; SIO0 mit Rahmenprüfung
+S0OEN bit S0CON.7 ; SIO0 mit Überlaufprüfung
+S0PE bit S0CON.8 ; SIO0 Paritätsfehler
+S0FE bit S0CON.9 ; SIO0 Rahmenfehler
+S0OE bit S0CON.10 ; SIO0 Überlauffehler
+ if MOMCPU=80C167H
+S0ODD bit S0CON.12 ; SIO0 Odd Parity
+S0BRS bit S0CON.13 ; SIO0 Baudratenfaktor
+ endif
+S0LB bit S0CON.14 ; SIO0 Rückkopplung
+S0R bit S0CON.15 ; SIO0 Baudratengenerator freigeben
+
+ if MOMCPU=80C167H
+SSCTB equ 0f0b0h ; SSC Senderegister
+SSCRB equ 0f0b2h ; SSC Empfangsregister
+SSCBR equ 0f0b4h ; SSC Baudrateneinstellung
+ DefIntBits SSCT,0ff72h ; Interruptsteuerung Sendeteil SSC
+ DefIntBits SSCR,0ff74h ; Interruptsteuerung Empfangsteil SSC
+ DefIntBits SSCE,0ff76h ; Interruptsteuerung Fehlererkennung SSC
+SSCCON equ 0ffb2h ; Steuerregister SSC
+SSCBM bit SSCCON.0 ; Wortbreite
+SSCBC bit SSCCON.0 ; Bitzahl
+SSCHB bit SSCCON.4 ; Startbitsteuerung
+SSCPH bit SSCCON.5 ; Taktphase
+SSCP0 bit SSCCON.6 ; Taktpolarität
+SSCTEN bit SSCCON.8 ; Sendefehler freigeben
+SSCTE bit SSCCON.8 ; Sendefehler aufgetreten ?
+SSCREN bit SSCCON.9 ; Empfangsfehler freigeben
+SSCRE bit SSCCON.9 ; Empfangsfehler aufgetreten ?
+SSCPEN bit SSCCON.10 ; Phasenfehler freigeben
+SSCPE bit SSCCON.10 ; Phasenfehler aufgetreten ?
+SSCBEN bit SSCCON.11 ; Baudratenfehler freigeben
+SSCBE bit SSCCON.11 ; Baudratenfehler freigegeben ?
+SSCBSY bit SSCCON.12 ; SSC beschäftigt ?
+SSCMS bit SSCCON.14 ; SSC als Master betreiben
+SSCEN bit SSCCON.15 ; SSC freigeben
+ elseif
+S1TBUF equ 0feb8h ; SIO1 Senderegister
+S1RBUF equ 0febah ; SIO1 Empfangsregister
+S1BG equ 0febch ; SIO1 Baudrateneinstellung
+ DefIntBits S1T,0ff72h ; Interruptsteuerung Sendeteil SIO1
+ DefIntBits S1R,0ff74h ; Interruptsteuerung Empfangsteil SIO1
+ DefIntBits S1E,0ff76h ; Interruptsteuerung Fehlererkennung SIO1
+S1CON equ 0ffb8h ; Steuerregister SIO1
+S1M bit S1CON.0 ; SIO1 Modus
+S1STP bit S1CON.3 ; SIO1 Anzahl Stopbits
+S1REN bit S1CON.4 ; SIO1 Empfänger freigeben
+S1PEN bit S1CON.5 ; SIO1 mit Parität
+S1FEN bit S1CON.6 ; SIO1 mit Rahmenprüfung
+S1OEN bit S1CON.7 ; SIO1 mit Überlaufprüfung
+S1PE bit S1CON.8 ; SIO1 Paritätsfehler
+S1FE bit S1CON.9 ; SIO1 Rahmenfehler
+S1OE bit S1CON.10 ; SIO1 Überlauffehler
+S1LB bit S1CON.14 ; SIO1 Rückkopplung
+S1R bit S1CON.15 ; SIO1 Baudratengenerator freigeben
+ endif
+
+;----------------------------------------------------------------------------
+; Vektoren/Sonderadressen
+
+RESET equ 000h ; Reseteinsprung
+NMITRAP equ 008h ; NMI-Einsprung
+STOTRAP equ 010h ; Einsprung Stacküberlauf
+STUTRAP equ 018h ; Einsprung Stackunterlauf
+BTRAP equ 028h ; undef. Opcode, Protection Fault,
+ ; unerlaubter Wortzugriff, ungültige Instruktionsadresse,
+ ; ungültiger Buszugriff
+CC0INT equ 040h ; Interrupteinsprünge CAPCOM
+CC1INT equ 044h
+CC2INT equ 048h
+CC3INT equ 04ch
+CC4INT equ 050h
+CC5INT equ 054h
+CC6INT equ 058h
+CC7INT equ 05ch
+CC8INT equ 060h
+CC9INT equ 064h
+CC10INT equ 068h
+CC11INT equ 06ch
+CC12INT equ 070h
+CC13INT equ 074h
+CC14INT equ 078h
+CC15INT equ 07ch
+T0INT equ 080h ; Interrupteinsprung Timer 0
+T1INT equ 084h ; Interrupteinsprung Timer 1
+T2INT equ 088h ; Interrupteinsprung Timer 2
+T3INT equ 08ch ; Interrupteinsprung Timer 3
+T4INT equ 090h ; Interrupteinsprung Timer 4
+T5INT equ 094h ; Interrupteinsprung Timer 5
+T6INT equ 098h ; Interrupteinsprung Timer 6
+CRINT equ 09ch ; Interrupteinsprung CAPREL
+ADCINT equ 0a0h ; Interrupteinsprung A/D-Wandlung fertig
+ADEINT equ 0a4h ; Interrupteinsprung A/D-Wandler-Überlauf
+S0TINT equ 0a8h ; Interrupteinsprung SIO0 wieder sendebereit
+S0RINT equ 0ach ; Interrupteinsprung SIO0 hat Zeichen empfangen
+S0EINT equ 0b0h ; Interrupteinsprung SIO0 hat Fehler erkannt
+S1TINT equ 0b4h ; Interrupteinsprung SIO1 wieder sendebereit
+S1RINT equ 0b8h ; Interrupteinsprung SIO1 hat Zeichen empfangen
+S1EINT equ 0bch ; Interrupteinsprung SIO1 hat Fehler erkannt
+
+
+;----------------------------------------------------------------------------
+; Speicherbereiche
+
+ if MOMCPU=80C167H
+IRAM equ 0f600h ; Beginn internes RAM
+ elseif
+IRAM equ 0fa00h
+ endif
+IRAMEND equ 0fdffh ; Ende " "
+
+BITRAM equ 0fd00h ; Beginn bitadressierbarer RAM-Bereich
+BITRAMEND equ 0fdffh ; Ende " " "
+
+ if MOMCPU=80C167H
+PECPTR equ 0fce0h ; Begin PEC-Vektoren (optional)
+PECPTREND equ 0fcffh ; Ende " "
+ elseif
+PECPTR equ 0fde0h
+PECPTREND equ 0fdffh
+ endif
+
+SFRSTART equ 0fe00h ; Beginn SFR-Bereich
+SFREND equ 0ffdfh ; Ende SFR-Bereich
+ if MOMCPU=80C167H
+ESFRSTART equ 0f000h ; Beginn erweiterter SFR-Bereich
+ESFREND equ 0f1dfh ; Ende erweiterter SFR-Bereich
+ endif
+
+IROM equ 0 ; Begin internes ROM
+ if MOMCPU=80C167H
+IROMEND equ 07fffh ; Ende internes ROM (n. voll ausgebaut)
+ elseif
+IROMEND equ 01fffh
+ endif
+
+;----------------------------------------------------------------------------
+; Bequemlichkeitsmakros
+
+clr macro op ; Operand auf 0 setzen
+ and op,#0
+ endm
+
+bchg macro op ; Bit invertieren
+ bmovn op,op
+ endm
+
+dec macro op ; um eins runter
+ sub op,#1
+ endm
+
+inc macro op ; um eins rauf
+ add op,#1
+ endm
+
+swapb macro op ; Bytes tauschen
+ ror op,#8
+ endm
+
+;----------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
diff --git a/include/reg251.inc b/include/reg251.inc
new file mode 100644
index 0000000..a1c5210
--- /dev/null
+++ b/include/reg251.inc
@@ -0,0 +1,225 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REG251.INC *
+;* *
+;* Sinn : enthält SFR- und Bitdefinitionen für MCS-251-Prozessoren *
+;* *
+;* letzte Änderungen : 30.12.1995 *
+;* *
+;****************************************************************************
+
+ ifndef reg251inc ; verhindert Mehrfacheinbindung
+
+reg251inc equ 1
+
+ if MOMCPUNAME<>"80C251"
+ fatal "Falscher Prozessortyp eingestellt: nur 80C251 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "MCS-251-SFR-Definitionen (C) 1995 Alfred Arnold"
+ message "binde \{MOMCPU}-SFRs ein"
+ endif
+
+;----------------------------------------------------------------------------
+; CPU-Kern:
+; ACC = A = R11
+; B = R10
+; SP/SPH = SPX = DR60
+; DPL/DPH/DPXL = DPX = DR56
+; CY wird von AS selbst benutzt
+
+ACC port 0e0h ; Akkumulator
+
+B port 0f0h ; B-Register
+
+PSW port 0d0h ; 8051-kompatibles PSW
+CARRY bit PSW.7 ; Carry
+AC bit PSW.6 ; Auxiliary-Carry
+F0 bit PSW.5 ; Flag 0
+RS1 bit PSW.4 ; Register-Bank-Auswahl
+RS0 bit PSW.3
+OV bit PSW.2 ; Overflow-Flag
+UD bit PSW.1 ; User-Flag
+P bit PSW.0 ; Parity-Flag
+
+PSW1 port 0d1h ; erweitertes PSW (Bits 2-4,6-7 wie in PSW)
+N bit PSW1.5 ; Negatives Ergebnis?
+Z bit PSW1.1 ; Ergebnis 0 ?
+
+SP port 81h ; Stackpointer (Bit 0..7)
+SPH port 0bdh ; Stackpointer (Bit 8..15)
+DPL port 082h ; Datenzeiger (Bit 0..7)
+DPH port 083h ; Datenzeiger (Bit 8..15)
+DPXL port 084h ; Datenzeiger (Bit 15..23)
+
+PCON port 087h ; Power-Down-Modi u.a.
+SMOD1 bit PCON.7 ; Verdopplung Baudrate in Modus 1..3
+SMOD0 bit PCON.6 ; Umschaltung SCON.7 als FE/SM0
+POF bit PCON.4 ; war Spannung weg ?
+GF1 bit PCON.3 ; General Flag 1
+GF0 bit PCON.2 ; General Flag 0
+PD bit PCON.1 ; in Powerdown-Modus schalten
+IDL bit PCON.0 ; in Idle-Modus schalten
+
+IE port 0a8h ; Interrupt-Freigaben (eigentlich IE0,
+ ; aber das ist schon belegt
+EA bit IE.7 ; generelle Interruptsperre
+EC bit IE.6 ; PCA-Interrupts freigeben
+ET2 bit IE.5 ; Interrupts Timer 2 freigeben
+ES bit IE.4 ; Interrupts ser. Schnittstelle freigeben
+ET1 bit IE.3 ; Interrupt Timer 1 freigeben
+EX1 bit IE.2 ; externen Interrupt 1 freigeben
+ET0 bit IE.1 ; Interrupt Timer 0 freigeben
+EX0 bit IE.0 ; externen Interrupt 0 freigeben
+
+IPH0 port 0b7h ; Interrupt-Prioritäten
+IPL0 port 0b8h
+
+;----------------------------------------------------------------------------
+; Ports mit Extrafunktionen:
+
+P0 port 080h ; Port 0
+
+P1 port 090h ; Port 1
+T2 bit P1.0 ; Ein/Ausgabe Timer 2
+T2EX bit P1.1 ; Trigger Timer 2
+ECI bit P1.2 ; externer Takt PCA
+CEX0 bit P1.3 ; Ein/Ausgabe PCA-Modul 0
+CEX1 bit P1.4 ; Ein/Ausgabe PCA-Modul 1
+CEX2 bit P1.5 ; Ein/Ausgabe PCA-Modul 2
+CEX3 bit P1.6 ; Ein/Ausgabe PCA-Modul 3
+CEX4 bit P1.7 ; Ein/Ausgabe PCA-Modul 4
+
+P2 port 0a0h ; Port 2
+
+P3 port 0b0h ; Port 3
+RXD bit P3.0 ; serielle Empfangsleitung
+TXD bit P3.1 ; serielle Sendeleitung
+INT0 bit P3.2 ; externer Interrupt 0
+INT1 bit P3.3 ; externer Interrupt 1
+T0 bit P3.4 ; Takteingang Timer 0
+T1 bit P3.5 ; Takteingang Timer 1
+WR bit P3.6 ; Leseleitung
+RD bit P3.7 ; Schreibleitung
+
+;----------------------------------------------------------------------------
+; serieller Port:
+
+SCON port 098h ; Konfiguration
+FE bit SCON.7 ; fehlerhaftes Stopbit ?
+SM0 bit SCON.7 ; Modusauswahl
+SM1 bit SCON.6
+SM2 bit SCON.5
+REN bit SCON.4 ; Empfänger freigeben
+TB8 bit SCON.3 ; Sendedatenbit 8
+RB8 bit SCON.2 ; Empfangsdatenbit 8
+TI bit SCON.1 ; Zeichen vollständig versandt ?
+RI bit SCON.0 ; Zeichen vollständig empfangen ?
+
+SBUF port 099h ; Datenregister
+SADEN port 0b9h ; Slave-Adreßmaske
+SADDR port 0a9h ; Slave-Adresse
+
+;----------------------------------------------------------------------------
+; Zähler/Watchdog:
+
+TL0 port 08ah ; Zählwert Zähler 0
+TH0 port 08ch
+TL1 port 08bh ; Zählwert Zähler 1
+TH1 port 08dh
+
+TCON port 088h ; Steuerung Zähler 0/1
+TF1 bit TCON.7 ; Überlauf Timer 1 ?
+TR1 bit TCON.6 ; Timer 1 starten/stoppen
+TF0 bit TCON.5 ; Überlauf Timer 0 ?
+TR0 bit TCON.4 ; Timer 0 starten/stoppen
+IE1 bit TCON.3 ; externer Interrupt 1 augetreten ?
+IT1 bit TCON.2 ; Flanken/Pegeltriggerung ext. Interrupt 1
+IE0 bit TCON.1 ; externer Interrupt 0 augetreten ?
+IT0 bit TCON.0 ; Flanken/Pegeltriggerung ext. Interrupt 0
+
+TMOD port 089h ; Steuerung/Modus Zähler 0/1
+M00 bit TMOD.0 ; Modus Timer 0
+M10 bit TMOD.1
+CT0 bit TMOD.2 ; Zähler/Timerumschaltung Timer 0
+GATE0 bit TMOD.3 ; Freigabemodus Timer 0
+M01 bit TMOD.4 ; Modus Timer 1
+M11 bit TMOD.5
+CT1 bit TMOD.6 ; Zähler/Timerumschaltung Timer 1
+GATE1 bit TMOD.7 ; Freigabemodus Timer 1
+
+
+TL2 port 0cch ; Zählwert Zähler 2
+TH2 port 0cdh
+
+T2CON port 0c8h ; Steuerung Zähler 2
+TF2 bit T2CON.7 ; Überlauf Timer 2 ?
+EXF2 bit T2CON.6 ; Flanke an T2EX aufgetreten ?
+RCLK bit T2CON.5 ; Timer 2 oder 1 für seriellen Empfangstakt nutzen ?
+TCLK bit T2CON.4 ; Timer 2 oder 1 für seriellen Sendetakt nutzen ?
+EXEN2 bit T2CON.3 ; Fang durch T2EX freigeben
+TR2 bit T2CON.2 ; Timer 2 starten/stoppen
+CT2 bit T2CON.1 ; Zähler/Timerumschaltung Timer 2
+CPRL2 bit T2CON.0 ; Fang oder Neuladen durch T2EX
+
+T2MOD port 0c9h ; Steuerung/Modus Zähler 2
+T2OE bit T2MOD.1 ; Ausgabe Timer 2 an T2 freigeben
+DCEN bit T2MOD.0 ; Zählrichtung Timer 2
+
+RCAP2L port 0cah ; Reload/Capture-Wert Timer 2
+RCAP2H port 0cbh
+WDTRST port 0a6h ; Watchdog zurücksetzen
+
+;----------------------------------------------------------------------------
+; Zählerfeld:
+
+CCON port 0d8h ; Steuerregister
+CF bit CCON.7 ; Überlauf PCA ?
+CR bit CCON.6 ; PCA-Timer starten/stoppen
+CCF4 bit CCON.4 ; Hat PCA-Modul 4..0 angesprochen ?
+CCF3 bit CCON.3
+CCF2 bit CCON.2
+CCF1 bit CCON.1
+CCF0 bit CCON.0
+
+CMOD port 0d9h ; Modusregister
+CIDL bit CMOD.7 ; PCA während Idle-Mode abschalten
+WDTE bit CMOD.6 ; Watchdog-Ausgabe an PCA-Modul 4 freigeben
+CPS1 bit CMOD.2 ; PCA-Taktauswahl
+CPS0 bit CMOD.1
+ECF bit CMOD.0 ; Interruptfreigabe
+
+CL port 0e9h ; Zählwert
+CH port 0f9h
+
+__defpcamodule macro Offset,NUM
+CCAPM{NUM} port 0d0h+Offset ; Modusregister
+ECOM{NUM} bit CCAPM0.6 ; Komparator Modul x einschalten
+CAPP{NUM} bit CCAPM0.5 ; Fangfunktion Modul x einschalten (pos. Flanke)
+CAPN{NUM} bit CCAPM0.4 ; Fangfunktion Modul x einschalten (neg. Flanke)
+MAT{NUM} bit CCAPM0.3 ; Interrupt bei Gleichheit Modul x einschalten
+TOG{NUM} bit CCAPM0.2 ; High-Speed-Output-Modus Modul x einschalten
+PWM{NUM} bit CCAPM0.1 ; PWM-Modus Modul x einschalten
+ECCF{NUM} bit CCAPM0.0 ; Interrupts durch CCFx einschalten
+CCAP{NUM}L port 0e0h+Offset ; Vergleichs/Fangwert Modul x
+CCAP{NUM}H port 0f0h+Offset
+ endm
+
+ __defpcamodule 0ah,"0"
+ __defpcamodule 0bh,"1"
+ __defpcamodule 0ch,"2"
+ __defpcamodule 0dh,"3"
+ __defpcamodule 0eh,"4"
+
+;----------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
+
diff --git a/include/reg29k.inc b/include/reg29k.inc
new file mode 100644
index 0000000..daec680
--- /dev/null
+++ b/include/reg29k.inc
@@ -0,0 +1,127 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REG29K.INC *
+;* *
+;* Sinn : enthält Adreßdefinitionen für die 2924x-Prozessoren *
+;* *
+;* letzte Änderungen : 20. 7.1995 *
+;* *
+;****************************************************************************
+
+ ifndef reg29kinc ; verhindert Mehrfacheinbindung
+
+reg29kinc equ 1
+
+ if (MOMCPU<>168512)&&(MOMCPU<>168515)&&(MOMCPU<>168517)
+ fatal "Falscher Prozessortyp eingestellt: nur AM29240, AM29243 oder AM29245 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "AM2924x-SFR-Definitionen (C) 1995 Alfred Arnold"
+ message "binde AM\{MOMCPU}-SFRs ein"
+ endif
+
+;----------------------------------------------------------------------------
+; Registerbasis
+
+RegBase equ 0x80000000
+
+;----------------------------------------------------------------------------
+; ROM-Controller
+
+RMCT equ RegBase+0x00 ; ROM-Steuerregister
+RMCF equ RegBase+0x04 ; ROM-Konfigurationsregister
+
+;----------------------------------------------------------------------------
+; DRAM-Controller
+
+DRCT equ RegBase+0x08 ; DRAM-Steuerregister
+DRCF equ RegBase+0x0c ; DRAM-Konfigurationsregister
+
+;----------------------------------------------------------------------------
+; PIA
+
+PICT0 equ RegBase+0x20 ; PIA Steuerregister 0
+PICT1 equ RegBase+0x24 ; PIA Steuerregister 1
+
+;----------------------------------------------------------------------------
+; DMA-Controller
+
+DMCT0 equ RegBase+0x30 ; Steuerregister Kanal 0
+DMAD0 equ RegBase+0x34 ; Adreßregister Kanal 0
+TAD0 equ RegBase+0x70 ; Queued-Adreßregister Kanal 0
+DMCN0 equ RegBase+0x38 ; Zählregister Kanal 0
+TCN0 equ RegBase+0x3c ; Queued-Zählregister Kanal 0
+DMCT1 equ RegBase+0x40 ; Steuerregister Kanal 1
+DMAD1 equ RegBase+0x44 ; Adreßregister Kanal 1
+TAD1 equ RegBase+0x74 ; Queued-Adreßregister Kanal 1
+DMCN1 equ RegBase+0x48 ; Zählregister Kanal 1
+TCN1 equ RegBase+0x4c ; Queued-Zählregister Kanal 1
+ if MOMCPU<>0x29245
+DMCT2 equ RegBase+0x50 ; Steuerregister Kanal 2
+DMAD2 equ RegBase+0x54 ; Adreßregister Kanal 2
+TAD2 equ RegBase+0x78 ; Queued-Adreßregister Kanal 2
+DMCN2 equ RegBase+0x58 ; Zählregister Kanal 2
+TCN2 equ RegBase+0x5c ; Queued-Zählregister Kanal 2
+DMCT3 equ RegBase+0x60 ; Steuerregister Kanal 3
+DMAD3 equ RegBase+0x64 ; Adreßregister Kanal 3
+TAD3 equ RegBase+0x7c ; Queued-Adreßregister Kanal 3
+DMCN3 equ RegBase+0x68 ; Zählregister Kanal 3
+TCN3 equ RegBase+0x6c ; Queued-Zählregister Kanal 3
+ endif
+
+;----------------------------------------------------------------------------
+; PIO
+
+POCT equ RegBase+0xd0 ; PIO-Steuerregister
+PIN equ RegBase+0xd4 ; PIO-Eingangsregister
+POUT equ RegBase+0xd8 ; PIO-Ausgangsregister
+POEN equ RegBase+0xdc ; PIO-Richtungssteuerung
+
+;----------------------------------------------------------------------------
+; Parallelport
+
+PPCT equ RegBase+0xc0 ; Steuerregister
+PPST equ RegBase+0xc8 ; Statusrtegister
+PPDT equ RegBase+0xc4 ; Datenregister
+
+;----------------------------------------------------------------------------
+; serielle Ports
+
+SPCTA equ RegBase+0x80 ; Steuerregister Kanal A
+SPSTA equ RegBase+0x84 ; Statusregister Kanal A
+SPTHA equ RegBase+0x88 ; Senderegister Kanal A
+SPRBA equ RegBase+0x8c ; Empfangsregister Kanal A
+BAUDA equ RegBase+0x90 ; Baudratenregister Kanal A
+ if MOMCPU<>0x29245
+SPCTB equ RegBase+0xa0 ; Steuerregister Kanal A
+SPSTB equ RegBase+0xa4 ; Statusregister Kanal A
+SPTHB equ RegBase+0xa8 ; Senderegister Kanal A
+SPRBB equ RegBase+0xac ; Empfangsregister Kanal A
+BAUDB equ RegBase+0xb0 ; Baudratenregister Kanal A
+ endif
+
+;----------------------------------------------------------------------------
+; Video-Interface
+
+ if MOMCPU<>0x29243
+VCT equ RegBase+0xe0 ; Steuerregister
+TOP equ RegBase+0xe4 ; Zeilennummer oberer Rand
+SIDE equ RegBase+0xe8 ; Spaltennummer linker/rechter Rand
+VDT equ RegBase+0xec ; Datenregister
+ endif
+
+;----------------------------------------------------------------------------
+; Interrupt-Steuerung
+
+ICT equ RegBase+0x28 ; Steuerregister
+IMASK equ RegBase+0x2c ; Maskenregister
+
+
+ endif
+
+ restore
diff --git a/include/reg53x.inc b/include/reg53x.inc
new file mode 100644
index 0000000..9a382b8
--- /dev/null
+++ b/include/reg53x.inc
@@ -0,0 +1,344 @@
+ save
+; listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REG53x.INC *
+;* *
+;* Sinn : enthält Register- und Adreßdefinitionen für H8/53x *
+;* *
+;* letzte Änderungen : 12.11.1995 *
+;* *
+;****************************************************************************
+
+ ifndef reg53xinc ; verhindert Mehrfacheinbindung
+
+reg53xinc equ 1
+
+ if (MOMCPUNAME<>"HD6475328")&&(MOMCPUNAME<>"HD6475348")&&(MOMCPUNAME<>"HD6475368")&&(MOMCPUNAME<>"HD6475388")
+ fatal "Falscher Prozessortyp eingestellt: nur HD6475328, HD6475348, HD6475368 oder HD6475388 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "H8/53x-Definitionen (C) 1994 Alfred Arnold"
+ endif
+
+__cpunum equ MOMCPU-$6475000 ; ist halt bequemer...
+
+ if __cpunum=$328 ; Peripherie verschiebt sich beim
+__regbase equ $ff00 ; H8/532 um eine Seite nach oben
+ elseif
+__regbase equ $fe00
+ endif
+
+;----------------------------------------------------------------------------
+; Adressen:
+
+ if __cpunum=$328
+IRAM equ $fb80 ; Anfang internes RAM (1 kByte)
+IRAMEND equ $ff7f ; Ende internes RAM
+ elseif
+IRAM equ $f680 ; Anfang internes RAM (2 kByte)
+IRAMEND equ $fe7f ; Ende internes RAM
+ endif
+
+IROM equ $0000 ; Anfang internes ROM
+ if __cpunum=$368
+IROMEND equ $f67f ; Ende internes ROM (62 kByte)
+ elseif
+IROMEND equ $7fff ; Ende internes ROM (32 kByte)
+ endif
+
+
+;----------------------------------------------------------------------------
+; CPU-Konfiguration:
+
+ if __cpunum=$328
+__sysbase equ $fff8
+ elseif
+__sysbase equ $ff10
+ endif
+
+WCR equ __sysbase+0 ; Wait-state control register
+WC0 equ 0 ; Anzahl Wartezyklen (rw)
+WC1 equ 1
+WMS0 equ 2 ; Wartemodus (rw)
+WMS1 equ 3
+
+RAMCR equ __sysbase+1 ; RAM control register
+RAME equ 7 ; Freigabe internes RAM
+
+MDCR equ __sysbase+2 ; Mode control register
+MDS0 equ 0 ; Modusauswahl (r)
+MDS1 equ 1
+MDS2 equ 2
+
+SBYCR equ __sysbase+3 ; Software standby control register
+SSBY equ 7 ; Sleep/Standby-Moduswahl (rw)
+
+;----------------------------------------------------------------------------
+; Interruptsteuerung:
+
+ if __cpunum=$328
+IPRA equ $fff0 ; Interrupt-Priorität IRQ1 / IRQ0 (rw)
+IPRB equ $fff1 ; Interrupt-Priorität FRT2 / FRT1 (rw)
+IPRC equ $fff2 ; Interrupt-Priorität 8-Bit-Timer / FRT3 (rw)
+IPRD equ $fff3 ; Interrupt-Priorität AD-Wandler / SCI (rw)
+ elseif
+IPRA equ $ff00 ; Interrupt-Priorität IRQ1 / IRQ0|I.-Timer (rw)
+IPRB equ $ff01 ; Interrupt-Priorität IRQ5|IRQ4 / IRQ3|IRQ2 (rw)
+IPRC equ $ff02 ; Interrupt-Priorität FRT2 / FRT1 (rw)
+IPRD equ $ff03 ; Interrupt-Priorität 8-Bit-Timer / FTR3 (rw)
+IPRE equ $ff04 ; Interrupt-Priorität SCI2 / SCI1 (rw)
+IPRF equ $ff05 ; Interrupt-Priorität - / AD-Wandler
+ endif
+
+;----------------------------------------------------------------------------
+; Data Transfer Controller:
+
+ if __cpunum=$328
+DTEA equ $fff4 ; Umschaltung normaler/DTC-Interrupt
+DTEB equ $fff5 ; (Belegung der Nibbles analog zu IPRx)
+DTEC equ $fff6
+DTED equ $fff7
+ elseif
+DTEA equ $ff08
+DTEB equ $ff09
+DTEC equ $ff0a
+DTED equ $ff0b
+DTEE equ $ff0c
+DTEF equ $ff0d
+ endif
+
+;----------------------------------------------------------------------------
+; Ports:
+
+__portbase equ __regbase+$80
+
+P1DR equ __portbase+2 ; Datenregister Port 1 (rw/r)
+P1DDR equ __portbase+0 ; Datenrichtungsregister Port 1 (w)
+ if __cpunum=$328
+P1CR equ $fffc ; Steuerregister Port 1 (rw)
+ elseif
+SYSCR1 equ $fefc ; Systemsteuerregister 1 (rw)
+ endif
+BRLE equ 3 ; P1CR/SYSCR1: Bus-Release-Modus
+NMIEG equ 4 ; Flanke, auf die NMI-Eingang triggert
+IRQ0E equ 5 ; Nutzung P15 als IRQ0 ?
+IRQ1E equ 6 ; Nutzung P16 als IRQ1 ?
+
+P2DR equ __portbase+3 ; Datenregister Port 2 (rw)
+P2DDR equ __portbase+1 ; Datenrichtungsregister Port 2 (w)
+
+P3DR equ __portbase+6 ; Datenregister Port 3 (rw)
+P3DDR equ __portbase+4 ; Datenrichtungsregister Port 3 (w)
+
+P4DR equ __portbase+7 ; Datenregister Port 4 (rw)
+P4DDR equ __portbase+5 ; Datenrichtungsregister Port 4 (w)
+
+P5DR equ __portbase+10 ; Datenregister Port 5 (rw)
+P5DDR equ __portbase+8 ; Datenrichtungsregister Port 5 (w)
+
+P6DR equ __portbase+11 ; Datenregister Port 6 (rw)
+P6DDR equ __portbase+9 ; Datenrichtungsregister Port 6 (w)
+ if __cpunum<>$328
+SYSCR2 equ $fefd ; Systemsteuerregister 2 (w)
+P9SCI2E equ 0 ; P92..P94 für SCI2 nutzen ?
+P9PWME equ 1 ; P92..P94 für PWM nutzen ?
+P6PWME equ 2 ; P61..P63 als PWM-Ausgang nutzen ?
+IRQ2E equ 3 ; Nutzung P60 als IRQ2 ?
+IRQ3E equ 4 ; Nutzung P61 als IRQ3 ?
+IRQ4E equ 5 ; Nutzung P62 als IRQ4 ?
+IRQ5E equ 6 ; Nutzung P63 als IRQ5 ?
+ endif
+
+P7DR equ __portbase+14 ; Datenregister Port 7 (rw)
+P7DDR equ __portbase+12 ; Datenrichtungsregister Port 7 (w)
+
+P8DR equ __portbase+15 ; Datenregister Port 8 (r)
+
+ if __cpunum=$388
+P9DR equ __portbase+18 ; Datenregister Port 9 (r)
+
+PADR equ __portbase+19 ; Datenregister Port A (rw)
+PADDR equ __portbase+17 ; Datenrichtungsregister Port A (w)
+
+PBDR equ __portbase+22 ; Datenregister Port B (rw)
+PBDDR equ __portbase+20 ; Datenrichtungsregister Port B (w)
+PBPCR equ __portbase+24 ; Pullup-Register Port B (w)
+
+PCDR equ __portbase+23 ; Datenregister Port C (rw)
+PCDDR equ __portbase+21 ; Datenrichtungsregister Port C (w)
+PCPCR equ __portbase+25 ; Pullup-Register Port C (w)
+ elseif __cpunum=$328
+P9DR equ __portbase+$7f ; Datenregister Port 9 (rw)
+P9DDR equ __portbase+$7e ; Datenrichtungsregister Port 9 (w)
+ elseif
+P9DR equ __portbase+$ff ; Datenregister Port 9 (rw)
+P9DDR equ __portbase+$fe ; Datenrichtungsregister Port 9 (w)
+ endif
+
+;----------------------------------------------------------------------------
+; Timer:
+
+__deftimer macro Base,NAME
+TCR{NAME} equ Base+0 ; Steuerregister (rw)
+TCSR{NAME} equ Base+1 ; Steuer/Statusregister (rw/r)
+FRC{NAME} equ Base+2 ; Zählerregister (rw, 16 Bit)
+OCRA{NAME} equ Base+4 ; Vergleicher A (rw, 16 Bit)
+OCRB{NAME} equ Base+6 ; Vergleicher B (rw, 16 Bit)
+ICR{NAME} equ Base+8 ; Eingabe-Fangregister (r, 16 Bit)
+ endm
+
+ __deftimer __regbase+$90,"1"
+ __deftimer __regbase+$a0,"2"
+ __deftimer __regbase+$b0,"3"
+
+CKS0 equ 0 ; TCRx: Taktquellenwahl (rw)
+CKS1 equ 1
+OEA equ 2 ; Vergleichsergebnis OCRA ausgeben ? (rw)
+OEB equ 3 ; Vergleichsergebnis OCRB ausgeben ? (rw)
+OVIE equ 4 ; Interrupt bei FRC-Überlauf auslösen? (rw)
+OCIEA equ 5 ; Interrupt bei Gleichheit mit OCRA auslösen? (rw)
+OCIEB equ 6 ; Interrupt bei Gleichheit mit OCRB auslösen? (rw)
+ICIE equ 7 ; Interrupt bei ICR-Fang auslösen? (rw)
+
+CCLRA equ 0 ; TCSRx: FRC bei Gleichheit mit OCRA rücksetzen ? (rw)
+IEDG equ 1 ; Eingabefang bei welcher Flanke ? (rw)
+OLVLA equ 2 ; Polarität für OCRA-Ausgangssignal (rw)
+OLVLB equ 3 ; Polarität für OCRB-Ausgangssignal (rw)
+OVF equ 4 ; FRC-Überlauf aufgetreten ? (r)
+OCFA equ 5 ; war FRC=OCRA ? (r)
+OCFB equ 6 ; war FRC=OCRB ? (r)
+ICF equ 7 ; Eingabe-Fang aufgetreten ? (r)
+
+; 8-Bit-Timer:
+
+__tcntbase equ __regbase+$d0
+
+TCR4 equ __tcntbase+0 ; Steuerregister (rw)
+CKS2 equ 2 ; Taktauswahl (Rest identisch zu FRCx)
+CCLR0 equ 3 ; Rücksetzmodus
+CCLR1 equ 4
+OVIE_4 equ 5 ; Interrupt bei Überlauf auslösen ?
+CMIEA equ 6 ; Interrupt bei TCNT=TCORA?
+CMIEB equ 7 ; Interrupt bei TCNT=TCORB?
+
+TCSR4 equ __tcntbase+1 ; Steuer/Statusregister (rw/r)
+OS0 equ 0 ; Auswirkung von TCORA=TCNT auf TMO
+OS1 equ 1
+OS2 equ 2 ; Auswirkung von TCORB=TCNT auf TMO
+OS3 equ 3
+OVF_4 equ 5 ; Überlauf aufgetreten
+CMFA equ 6 ; TCNT=TCORA aufgetreten
+CMFB equ 7 ; TCNT=TCORB aufgetreten
+
+TCORA equ __tcntbase+2 ; Zeitkonstante 1 (rw)
+TCORB equ __tcntbase+3 ; Zeitkonstante 2 (rw)
+TCNT equ __tcntbase+4 ; Zählwert (rw)
+
+;----------------------------------------------------------------------------
+; Pulsweitenmodulatoren:
+
+__defpwm macro Base,NAME
+PW{NAME}_TCR equ Base ; Steuerregister (rw)
+PW{NAME}_DTR equ Base+1 ; Pulsweitenregister (rw)
+PW{NAME}_TCNT equ Base+2 ; Zählwert (rw)
+ endm
+
+ __defpwm __regbase+$c0,"1"
+ __defpwm __regbase+$c4,"2"
+ __defpwm __regbase+$c8,"3"
+
+OS equ 6 ; PWx_TCR: Logik des Ausgangs
+OE equ 7 ; Ausgang freischalten
+
+;----------------------------------------------------------------------------
+; Watchdog:
+
+__wdtbase equ __regbase+$ec
+
+WDT_TCSR_R equ __wdtbase+0 ; Steuer/Statusregister (unterschied-
+WDT_TCSR_W equ __wdtbase+1 ; liche Schreib/Leseadressen)
+TME equ 5 ; Timer freigeben
+WTIT equ 6 ; Watchdog/Timermodus
+WDT_OVF equ 7 ; Watchdog-Überlauf ?
+
+WDT_TCNT equ __wdtbase+1 ; Zählregister (rw)
+
+ if __cpunum<>$328
+RSTCSR_W equ $ff14 ; Reset-Register (unterschiedliche
+RSTCSR_R equ $ff15 ; Schreib/Leseadressen)
+RSTOE equ 6 ; Watchdog-Reset nach außen geben ?
+WRST equ 7 ; Reset durch Watchdog ?
+ endif
+
+;----------------------------------------------------------------------------
+; serielle Schnittstelle:
+
+__defsci macro Base,NAME
+SMR{NAME} equ Base+0 ; Modusregister (rw)
+BRR{NAME} equ Base+1 ; Bitratenregister (rw)
+SCR{NAME} equ Base+2 ; Steuerregister (rw)
+TDR{NAME} equ Base+3 ; Sendedaten (rw)
+SSR{NAME} equ Base+4 ; Statusregister (rw)
+RDR{NAME} equ Base+5 ; Empfangsdaten (r)
+ endm
+
+ if __cpunum=$328
+ __defsci __regbase+$d8,""
+ elseif
+ __defsci __regbase+$d8,"1"
+ __defsci __regbase+$f0,"2"
+ endif
+
+STOP equ 3 ; SMRx: #Stopp-Bits
+O_E equ 4 ; odd/even Parity
+PE equ 5 ; mit/ohne Parität
+CHR equ 6 ; 7/8 Datenbits
+C_A equ 7 ; synchron/asynchron
+
+CKE0 equ 0 ; SCRx: bei synchroner Kommunikation Takt an SCK ausgeben ?
+CKE1 equ 1 ; Takt intern/extern (-->SCK Ein-oder Ausgang) ?
+RE equ 4 ; Empfänger freigeben
+TE equ 5 ; Sender freigeben
+RIE equ 6 ; Empfangs-Interrupt freigeben
+TIE equ 7 ; Sende-Interrupt freigeben
+
+PER equ 3 ; SSRx: Paritäts-Fehler
+FER equ 4 ; ungültiger Rahmen
+ORER equ 5 ; Empfänger-Überlauf
+RDRF equ 6 ; Empfänger voll ?
+TDRE equ 7 ; Sender leer ?
+
+;----------------------------------------------------------------------------
+; A/D-Wandler
+
+__adbase equ __regbase+$e0
+
+ADDRA equ __adbase+0 ; Wandelergebnis Kanal A (r, 16Bit)
+ADDRB equ __adbase+2 ; Wandelergebnis Kanal B (r, 16Bit)
+ADDRC equ __adbase+4 ; Wandelergebnis Kanal C (r, 16Bit)
+ADDRD equ __adbase+6 ; Wandelergebnis Kanal D (r, 16Bit)
+
+ADCSR equ __adbase+8 ; Steuer/Statusregister (rw)
+CH0 equ 0 ; Kanalauswahl
+CH1 equ 1
+CH2 equ 2
+CKS equ 3 ; Wandelzeit 274/138 Takte
+SCAN equ 4 ; Single Channel/Scan-Modus
+ADST equ 5 ; Wandler starten/stoppen
+ADIE equ 6 ; Interrupt bei Wandelende auslösen ?
+ADF equ 7 ; Wandlung abgeschlossen ?
+
+ if __cpunum<>$328
+ADCR equ __adbase+9 ; Steuerregister (rw)
+TRGE equ 7 ; externer Trigger ?
+ endif
+
+;----------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
diff --git a/include/reg683xx.inc b/include/reg683xx.inc
new file mode 100644
index 0000000..f2dd8ef
--- /dev/null
+++ b/include/reg683xx.inc
@@ -0,0 +1,700 @@
+ save
+ listing off ; kein Listing über diesen File
+ macexp off ; spart noch ein bißchen Zeit
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei REG96.INC *
+;* *
+;* Sinn : enthält Registeradreßdefinitionen für 68332 und 68340 *
+;* *
+;* letzte Änderungen : 18.11.1994 *
+;* *
+;****************************************************************************
+
+ ifndef reg68332inc ; verhindert Mehrfacheinbindung
+
+reg6833xinc equ 1
+
+ if (MOMCPUNAME<>"68332")&&(MOMCPUNAME<>"68340")&&(MOMCPUNAME<>"68360")
+ fatal "Falscher Prozessortyp eingestellt: nur 68332 oder 68340 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "CPU32-Register-Definitionen (C) 1994 Alfred Arnold"
+ message "binde \{MOMCPU}-Register ein"
+ endif
+
+;-----------------------------------------------------------------------------
+; Basis ist entweder $fffa00 oder $7fa000, das muß man vorher setzen
+; (oder mit dem Default leben :-)
+; beim 68340 kann man ganz frei wählen
+; Da der 68332 A31..A24 nicht herausführt, könnte man evtl. auch die Register
+; ab $fffffa00 erreichen und kurze Adressen verwenden. Das müßte man mal
+; ausprobieren...alternativ kann man man aber auch die Basis auf 0 setzen,
+; bevor man diese Datei einbindet und dann die Symbole registerrelativ
+; verwenden.
+
+ ifndef SIMBase
+ if MOMCPU=$68332
+SIMBase equ $fffa00
+ elseif
+SIMBase equ $000000
+ endif
+ endif
+
+;=============================================================================
+; Da sich 68360, 68340 und 68332 sehr deutlich im Registermodell unterscheiden,
+; habe ich mir keine Mühe gemacht, Register für Register auseinanderzufieseln,
+; was gemeinsam ist und was nicht
+
+ switch MOMCPUNAME
+
+;-----------------------------------------------------------------------------
+
+ case "68360"
+
+;-----------------------------------------------------------------------------
+
+MBAR equ $0003ff00 ; [L] Startadresse Peripherie (CPU-Space!)
+MBARE equ $0003ff04 ; [L] Sperrung/Freigabe MBAR
+
+RegBase equ SIMBase+$1000 ; Startadresse Rgister
+
+MCR equ RegBase+$0000 ; [L] Modulkonfiguration SIM
+
+AVR equ RegBase+$0008 ; [B] Freigabe Autovektor-Interrupts
+RSR equ RegBase+$0009 ; [B] Reset-Status
+CLK0CR equ RegBase+$000c ; [B] Steuerung Taktausgang 2 & 1
+PLLCR equ RegBase+$0010 ; [W] PLL-Steuerung
+CDVCR equ RegBase+$0014 ; [W] Steuerung "langsamer" Takt
+PEPAR equ RegBase+$0016 ; [W] Zuordnung der I/O-Pins Port E
+SYPCR equ RegBase+$0022 ; [B] Systemmonitore, Bustimimg
+SWIV equ RegBase+$0023 ; [B] Interruptvektor Watchdog
+PICR equ RegBase+$0026 ; [W] Interruptebene+ -vektor period. Interrupt
+PITR equ RegBase+$002a ; [W] Zählwert & Vorteiler period. Interrupt
+SWSR equ RegBase+$002f ; [B] Watchdog rücksetzen
+BKAR equ RegBase+$0030 ; [L] Breakpoint-Adresse
+BKCR equ RegBase+$0034 ; [L] Breakpoint-Steuerung
+
+GMR equ RegBase+$0040 ; [L] globale Steuerung Memory-Controller
+MSTAT equ RegBase+$0044 ; [W] Status Memory-Controller
+BR0 equ RegBase+$0050 ; [L] SRAM/DRAM-Basis CS0
+OR0 equ RegBase+$0054 ; [L] Optionen DRAM/SRAM CS0
+BR1 equ RegBase+$0060 ; [L] SRAM/DRAM-Basis CS1
+OR1 equ RegBase+$0064 ; [L] Optionen DRAM/SRAM CS1
+BR2 equ RegBase+$0070 ; [L] SRAM/DRAM-Basis CS2
+OR2 equ RegBase+$0074 ; [L] Optionen DRAM/SRAM CS2
+BR3 equ RegBase+$0080 ; [L] SRAM/DRAM-Basis CS3
+OR3 equ RegBase+$0084 ; [L] Optionen DRAM/SRAM CS3
+BR4 equ RegBase+$0090 ; [L] SRAM/DRAM-Basis CS4
+OR4 equ RegBase+$0094 ; [L] Optionen DRAM/SRAM CS4
+BR5 equ RegBase+$00a0 ; [L] SRAM/DRAM-Basis CS5
+OR5 equ RegBase+$00a4 ; [L] Optionen DRAM/SRAM CS5
+BR6 equ RegBase+$00b0 ; [L] SRAM/DRAM-Basis CS6
+OR6 equ RegBase+$00b4 ; [L] Optionen DRAM/SRAM CS6
+BR7 equ RegBase+$00c0 ; [L] SRAM/DRAM-Basis CS7
+OR7 equ RegBase+$00c4 ; [L] Optionen DRAM/SRAM CS7
+
+;-----------------------------------------------------------------------------
+; Communications Controller:
+
+RAMBase equ SIMBase ; [ ] RAM-Basisadresse
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; IDMA:
+
+IDMA1Base equ RAMBase+$0e70
+IDMA2Base equ RAMBase+$0f70
+
+ICCR equ RegBase+$0500 ; [W] Konfiguration IDMA-Kanäle
+CMR1 equ RegBase+$0504 ; [W] Modus IDMA1
+CMR2 equ RegBase+$0526 ; [W] Modus IDMA2
+__defidma macro NAME,Adr,IDMABase
+SAPR{NAME} equ Adr ; [L] Quelladresse bei Speicherkopieraktionen
+DAPR{NAME} equ Adr+4 ; [L] Zieladresse " "
+BCR{NAME} equ Adr+8 ; [L] Zählregister IDMA
+FCR{NAME} equ Adr+12 ; [B] Funktionscodes
+CMAR{NAME} equ Adr+14 ; [B] Kanalmaske
+CSR{NAME} equ Adr+16 ; [B] Kanalstatus IDMA
+IDMA{NAME}_IBASE equ IDMABase+0 ; [W] Basisadresse Deskriptor
+IDMA{NAME}_IBPTR equ IDMABase+0 ; [W] Pointer Deskriptor
+IDMA{NAME}_ISTATE equ IDMABase+0 ; [L] int. Status
+IDMA{NAME}_ITEMP equ IDMABase+0 ; [L] temp. Speicher
+ endm
+ __defidma "1",RegBase+$508
+ __defidma "2",RegBase+$528
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; SDMA:
+
+SDSR equ RegBase+$051c ; [B] Status SDMA
+SDCR equ RegBase+$051e ; [W] Konfiguration SDMA-Kanäle
+SDAR equ RegBase+$0520 ; [L] SDMA-Adreßregister
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; CPIC:
+
+CICR equ RegBase+$0540 ; [L] Interrupt-Konfiguration
+CIPR equ RegBase+$0544 ; [L] Interrupt-Anzeigen
+CIMR equ RegBase+$0548 ; [L] Interrupt-Masken
+CISR equ RegBase+$054c ; [L] Anzeige, ob Interrupts in Bearbeitung
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; PIO:
+
+PADIR equ RegBase+$0550 ; [W] Datenrichtungsregister Port A
+PAPAR equ RegBase+$0552 ; [W] Zuordnung Port A
+PAODR equ RegBase+$0554 ; [W] Steuerbits Port A als open drain
+PADAT equ RegBase+$0556 ; [W] Datenregister Port A
+
+PCDIR equ RegBase+$0560 ; [W] Datenrichtungsregister Port C
+PCPAR equ RegBase+$0562 ; [W] Zuordnung Port C
+PCSO equ RegBase+$0564 ; [W] Special Options Port C
+PCDAT equ RegBase+$0566 ; [W] Datenregister Port C
+PCINT equ RegBase+$0568 ; [W] Interruptsteuerung Port C
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; TIMER:
+
+TimerBase equ RAMBase+$0db0
+
+TGCR equ RegBase+$0560 ; [W] globale Konfiguration Timer
+TMR1 equ RegBase+$0590 ; [W] Modus Timer 1
+TRR1 equ RegBase+$0594 ; [W] Referenzwert Timer 1
+TCR1 equ RegBase+$0598 ; [W] Fangwert Timer 1
+TCN1 equ RegBase+$059c ; [W] Zählwert Timer 1
+TER1 equ RegBase+$05b0 ; [W] Ereignismeldung Timer 1
+TMR2 equ RegBase+$0592
+TRR2 equ RegBase+$0596
+TCR2 equ RegBase+$059a
+TCN2 equ RegBase+$059e
+TER2 equ RegBase+$05b2
+TMR3 equ RegBase+$05a0
+TRR3 equ RegBase+$05a4
+TCR3 equ RegBase+$05a8
+TCN3 equ RegBase+$05ac
+TER3 equ RegBase+$05b4
+TMR4 equ RegBase+$05a2
+TRR4 equ RegBase+$05a6
+TCR4 equ RegBase+$05aa
+TCN4 equ RegBase+$05ae
+TER4 equ RegBase+$05b6
+TIMER_TM_BASE equ TimerBase+$00 ; [W] Basisadresse Tabelle
+TIMER_TM_ptr equ TimerBase+$02 ; [W] Zeiger Tabelle
+TIMER_R_TMR equ TimerBase+$04 ; [W] Modus
+TIMER_R_TMV equ TimerBase+$06 ; [W] Valid-Register
+TIMER_TM_cmd equ TimerBase+$08 ; [L] Kommandoregister
+TIMER_TM_cnt equ TimerBase+$0c ; [L] interner Zähler
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; CP:
+
+MiscBase equ RAMBase+$0cb0
+
+CR equ RegBase+$05c0 ; [W] Kommandoregister
+RCCR equ RegBase+$05c4 ; [W] Konfiguration RISC-Controller
+RTER equ RegBase+$05d6 ; [W] Timer-Events
+RTMR equ RegBase+$05da ; [W] Timer-Maske
+CP_REV_num equ MiscBase ; [W] Revisionsnummer Mikrocode
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; BRG:
+
+BRGC1 equ RegBase+$05f0 ; [L] Konfiguration Baudratengenerator 1
+BRGC2 equ RegBase+$05f4
+BRGC3 equ RegBase+$05f8
+BRGC4 equ RegBase+$05fc
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; SCC:
+
+SCC1Base equ RAMBase+$0c00
+SCC2Base equ RAMBase+$0d00
+SCC3Base equ RAMBase+$0e00
+SCC4Base equ RAMBase+$0f00
+
+__defscc macro NAME,Adr,SCCBase
+GSMR_L{NAME} equ Adr+0 ; [Q] Modus
+GSMR_H{NAME} equ Adr+4
+PSMR{NAME} equ Adr+8 ; [W] protokollspez. Modus
+TODR{NAME} equ Adr+12 ; [W] Sendestart erzwingen
+DSR{NAME} equ Adr+14 ; [W] Synchronisationsmuster SCCx
+SCCE{NAME} equ Adr+16 ; [W] Ereignisregister UART
+SCCM{NAME} equ Adr+20 ; [W] UART Ereignismaske
+SCCS{NAME} equ Adr+23 ; [B] UART Status
+SCC{NAME}_RBASE equ SCCBase+$00 ; [W] Startadresse Empfangspuffer
+SCC{NAME}_TBASE equ SCCBase+$02 ; [W] Startadresse Sendepuffer
+SCC{NAME}_RFCR equ SCCBase+$04 ; [B] Adreßraum Empfangen
+SCC{NAME}_TFCR equ SCCBase+$05 ; [B] Adreßraum Senden
+SCC{NAME}_MRBLR equ SCCBase+$06 ; [W] Länge Empfangspuffer
+SCC{NAME}_RSTATE equ SCCBase+$08 ; [L] Status Empfänger
+SCC{NAME}_RBPTR equ SCCBase+$10 ; [W] Adreßzeiger Empfangen
+SCC{NAME}_TSTATE equ SCCBase+$18 ; [L] Status Sender
+SCC{NAME}_TBPTR equ SCCBase+$20 ; [W] Adreßzeiger Senden
+SCC{NAME}_RCRC equ SCCBase+$28 ; [L] Empfangs-CRC
+SCC{NAME}_TCRC equ SCCBase+$2c ; [L] Sende-CRC
+SCC{NAME}_MAX_IDL equ SCCBase+$38 ; [W] --UART-- Maximalzahl Idle-Zeichen
+SCC{NAME}_IDLC equ SCCBase+$3a ; [W] temp. Idle-Zähler
+SCC{NAME}_BRKCR equ SCCBase+$3c ; [W] Anzahl Sende-Breaks
+SCC{NAME}_PAREC equ SCCBase+$3e ; [W] Paritätsfehlerzähler
+SCC{NAME}_FRMEC equ SCCBase+$40 ; [W] Rahmungs-Fehlerzähler
+SCC{NAME}_NOSEC equ SCCBase+$42 ; [W] Rauschzähler
+SCC{NAME}_BRKEC equ SCCBase+$44 ; [W] Break-Bedingung
+SCC{NAME}_BRKLN equ SCCBase+$46 ; [W] Länge des letzten Breaks
+SCC{NAME}_UADDR1 equ SCCBase+$48 ; [W] Slave-Adressen
+SCC{NAME}_UADDR2 equ SCCBase+$4a ; [W]
+SCC{NAME}_RTEMP equ SCCBase+$4c ; [W] temp. Speicher
+SCC{NAME}_TOSEQ equ SCCBase+$4e ; [W] out-of-sequence Zeichen
+SCC{NAME}_CHARACTER1 equ SCCBase+$50 ; [W] Zeichen, die Interrupts erzeugen
+SCC{NAME}_CHARACTER2 equ SCCBase+$52 ; [W]
+SCC{NAME}_CHARACTER3 equ SCCBase+$54 ; [W]
+SCC{NAME}_CHARACTER4 equ SCCBase+$56 ; [W]
+SCC{NAME}_CHARACTER5 equ SCCBase+$58 ; [W]
+SCC{NAME}_CHARACTER6 equ SCCBase+$5a ; [W]
+SCC{NAME}_CHARACTER7 equ SCCBase+$5c ; [W]
+SCC{NAME}_CHARACTER8 equ SCCBase+$5e ; [W]
+SCC{NAME}_RCCM equ SCCBase+$60 ; [W] Maske Empfangszeichen
+SCC{NAME}_RCCR equ SCCBase+$62 ; [W] Empfangszeichen
+SCC{NAME}_RLBC equ SCCBase+$64 ; [W] letztes Break-Zeichen
+SCC{NAME}_C_MASK equ SCCBase+$34 ; [L] --HDLC-- CRC-Polynom
+SCC{NAME}_C_PRES equ SCCBase+$38 ; [L] CRC-Startwert
+SCC{NAME}_DISFC equ SCCBase+$3c ; [W] Zähler für verworfene Rahmen
+SCC{NAME}_CRCEC equ SCCBase+$3e ; [W] Zähler für CRC-Fehler
+SCC{NAME}_ABTSC equ SCCBase+$40 ; [W] Zähler für Abbrüche
+SCC{NAME}_NMARC equ SCCBase+$42 ; [W] Zähler für unpassende Adressen
+SCC{NAME}_RETRC equ SCCBase+$44 ; [W] Zähler für Retransmissionen
+SCC{NAME}_MFLR equ SCCBase+$46 ; [W] Maximalrahmenlänge
+SCC{NAME}_MAX_cnt equ SCCBase+$48 ; [W] Längenzähler
+SCC{NAME}_RFTHR equ SCCBase+$4a ; [W] Schwelle für empfangene Rahmenzahl
+SCC{NAME}_RFCNT equ SCCBase+$4c ; [W] empfangene Rahmen
+SCC{NAME}_HMASK equ SCCBase+$4e ; [W] Adreßmaske
+SCC{NAME}_HADDR1 equ SCCBase+$50 ; [W] Adressen
+SCC{NAME}_HADDR2 equ SCCBase+$52 ; [W]
+SCC{NAME}_HADRR3 equ SCCBase+$54 ; [W]
+SCC{NAME}_HADDR4 equ SCCBase+$56 ; [W]
+SCC{NAME}_TMP equ SCCBase+$58 ; [W] Temporärspeicher
+SCC{NAME}_TMP_MB equ SCCBase+$5a ; [W] "
+SCC{NAME}_CRCC equ SCCBase+$34 ; [L] --BISYNC-- temp. Wert CRC
+SCC{NAME}_PRCRC equ SCCBase+$38 ; [W] Empfangs-Vorgabe-CRC
+SCC{NAME}_PTCRC equ SCCBase+$3a ; [W] Sende-Vorgabe-CRC
+SCC{NAME}_B_PAREC equ SCCBase+$3c ; [W] Zähler Empfangs-Paritäts-Fehler
+SCC{NAME}_BSYNC equ SCCBase+$3e ; [W] SYNC-Zeichen
+SCC{NAME}_BDLE equ SCCBase+$40 ; [W] DLE-Zeichen
+SCC{NAME}_B_CHARACTER1 equ SCCBase+$42 ; [W] Steuerzeichen
+SCC{NAME}_B_CHARACTER2 equ SCCBase+$44 ; [W]
+SCC{NAME}_B_CHARACTER3 equ SCCBase+$46 ; [W]
+SCC{NAME}_B_CHARACTER4 equ SCCBase+$48 ; [W]
+SCC{NAME}_B_CHARACTER5 equ SCCBase+$4a ; [W]
+SCC{NAME}_B_CHARACTER6 equ SCCBase+$4c ; [W]
+SCC{NAME}_B_CHARACTER7 equ SCCBase+$4e ; [W]
+SCC{NAME}_B_CHARACTER8 equ SCCBase+$50 ; [W]
+SCC{NAME}_B_RCCM equ SCCBase+$52 ; [W] Empfangssteuerzeichenmaske
+SCC{NAME}_CRC_P equ SCCBase+$30 ; [L] --Transparent-- CRC-Vorgabe
+SCC{NAME}_CRC_C equ SCCBase+$34 ; [L] CRC-Konstante
+SCC{NAME}_E_C_PRES equ SCCBase+$30 ; [L] --Ethernet-- CRC-Vorgabe
+SCC{NAME}_E_C_MASK equ SCCBase+$34 ; [L] CRC-Maske
+SCC{NAME}_E_CRCEC equ SCCBase+$38 ; [L] CRC-Fehlerzähler
+SCC{NAME}_ALEC equ SCCBase+$3c ; [L] Alignment-Fehlerzähler
+SCC{NAME}_E_DISFC equ SCCBase+$40 ; [L] Zähler verworfene Rahmen
+SCC{NAME}_PADS equ SCCBase+$44 ; [W] Padding-Zeichen kurze Rahmen
+SCC{NAME}_RET_Lim equ SCCBase+$46 ; [W] Maximalzahl Retries
+SCC{NAME}_RET_cnt equ SCCBase+$48 ; [W] Momentanzahl Retries
+SCC{NAME}_E_MFLR equ SCCBase+$4a ; [W] Maximalrahmenlänge
+SCC{NAME}_MINFLR equ SCCBase+$4c ; [W] Minimalrahmenlänge
+SCC{NAME}_MAXD1 equ SCCBase+$4e ; [W] Maximallänge DMA1
+SCC{NAME}_MAXD2 equ SCCBase+$50 ; [W] Maximallänge DMA2
+SCC{NAME}_MAXD equ SCCBase+$52 ; [W] Rx Max DMA
+SCC{NAME}_DMA_cnt equ SCCBase+$54 ; [W] DMA-Zähler Empfang
+SCC{NAME}_MAX_b equ SCCBase+$56 ; [W] Max BD Byte Count
+SCC{NAME}_GADDR1 equ SCCBase+$58 ; [W] Group Address Filter
+SCC{NAME}_GADDR2 equ SCCBase+$5a ; [W]
+SCC{NAME}_GADDR3 equ SCCBase+$5c ; [W]
+SCC{NAME}_GADDR4 equ SCCBase+$5e ; [W]
+SCC{NAME}_TBUF0.data0 equ SCCBase+$60 ; [L] Save Areas - current frame
+SCC{NAME}_TBUF0.data1 equ SCCBase+$64 ; [L]
+SCC{NAME}_TBUF0.rba0 equ SCCBase+$68 ; [L]
+SCC{NAME}_TBUF0.crc equ SCCBase+$6c ; [L]
+SCC{NAME}_TBUF0.bcnt equ SCCBase+$70 ; [W]
+SCC{NAME}_PADDR1_H equ SCCBase+$72 ; [W] phys. Adresse
+SCC{NAME}_PADDR1_M equ SCCBase+$74 ; [W]
+SCC{NAME}_PADDR1_L equ SCCBase+$76 ; [W]
+SCC{NAME}_P_Per equ SCCBase+$78 ; [W] Persistenz
+SCC{NAME}_RFBD_ptr equ SCCBase+$7a ; [W] Rx First BD Counter
+SCC{NAME}_TFBD_ptr equ SCCBase+$7c ; [W] Tx First BD Pointer
+SCC{NAME}_TLBD_ptr equ SCCBase+$7e ; [W] Tx Last BD Pointer
+SCC{NAME}_TBUF1.data0 equ SCCBase+$80 ; [L] Save Areas - next frame
+SCC{NAME}_TBUF1.data1 equ SCCBase+$84 ; [L]
+SCC{NAME}_TBUF1.rba0 equ SCCBase+$88 ; [L]
+SCC{NAME}_TBUF1.crc equ SCCBase+$8c ; [L]
+SCC{NAME}_TBUF1.bcnt equ SCCBase+$90 ; [W]
+SCC{NAME}_TX_len equ SCCBase+$92 ; [W] Tx Frame Length Counter
+SCC{NAME}_IADDR1 equ SCCBase+$94 ; [W] Individual address filters
+SCC{NAME}_IADDR2 equ SCCBase+$96 ; [W]
+SCC{NAME}_IADDR3 equ SCCBase+$98 ; [W]
+SCC{NAME}_IADDR4 equ SCCBase+$9a ; [W]
+SCC{NAME}_BOFF_CNT equ SCCBase+$9c ; [W] Backoff Zähler
+SCC{NAME}_TADDR_H equ SCCBase+$9e ; [W] temp. Adresse
+SCC{NAME}_TADDR_M equ SCCBase+$9a ; [W]
+SCC{NAME}_TADDR_L equ SCCBase+$a0 ; [W]
+ endm
+ __defscc "1",RegBase+$0600,SCC1Base
+ __defscc "2",RegBase+$0620,SCC2Base
+ __defscc "3",RegBase+$0640,SCC3Base
+ __defscc "4",RegBase+$0660,SCC4Base
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; SMC:
+
+SMC1Base equ RAMBase+$0e80
+SMC2Base equ RAMBase+$0f80
+
+__defsmc macro NAME,Adr,SMCBase
+SMCMR{NAME} equ Adr+0 ; [W] Transparentmodus
+SMCE{NAME} equ Adr+4 ; [B] Ereignisregister
+SMCM{NAME} equ Adr+8 ; [W] Modus
+SMC{NAME}_RBASE equ SMCBase+$00 ; [W] Empfangspufferdeskriptoradresse
+SMC{NAME}_TBASE equ SMCBase+$02 ; [W] Sendepufferdeskriptoradresse
+SMC{NAME}_RFCR equ SMCBase+$04 ; [B] Empfangs-Funktionscode
+SMC{NAME}_TFCR equ SMCBase+$05 ; [B] Sende-Funktionscode
+SMC{NAME}_MRBLR equ SMCBase+$06 ; [W] Maximallänge Empfangspuffer
+SMC{NAME}_RSTATE equ SMCBase+$08 ; [L] interner Empfängerstatus
+SMC{NAME}_RBPTR equ SMCBase+$10 ; [W] Rx Buffer descriptor pointer
+SMC{NAME}_TSTATE equ SMCBase+$18 ; [L] interner Senderstatus
+SMC{NAME}_TBPTR equ SMCBase+$20 ; [W] Tx Buffer Descriptor Pointer
+SMC{NAME}_MAX_IDL equ SMCBase+$28 ; [W] --UART-- MAximalzahl Idle-Zeichen
+SMC{NAME}_IDLC equ SMCBase+$28 ; [W] Idle-Zähler
+SMC{NAME}_BRKLN equ SMCBase+$28 ; [W] Länge letztes Break-Zeichen
+SMC{NAME}_BRKEC equ SMCBase+$28 ; [W] Receive Break Condition Counter
+SMC{NAME}_BRKCR equ SMCBase+$28 ; [W] Sende-Break-Zähler
+SMC{NAME}_R_mask equ SMCBase+$28 ; [W] temp. Bitmaske
+SMC{NAME}_M_RxBD equ SMCBase+$00 ; [W] --GCI-- Monitor Channel Rx
+SMC{NAME}_M_TxBD equ SMCBase+$02 ; [W] Monitor Channel Tx
+SMC{NAME}_CI_RxBD equ SMCBase+$04 ; [W] C/I Channel Rx
+SMC{NAME}_CI_TxBD equ SMCBase+$06 ; [W] C/I Channel Tx
+SMC{NAME}_M_RxD equ SMCBase+$0c ; [W] Monitor Rx Data
+SMC{NAME}_M_TxD equ SMCBase+$0e ; [W] Monitor Tx Data
+SMC{NAME}_CI_RxD equ SMCBase+$10 ; [W] C/I Rx Data
+SMC{NAME}_CI_TxD equ SMCBase+$12 ; [W] C/I Tx Data
+ endm
+ __defsmc "1",RegBase+$0682,SMC1Base
+ __defsmc "2",RegBase+$0692,SMC2Base
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; SPI:
+
+SPIBase equ RAMBase+$0d80
+
+SPMODE equ RegBase+$06a0 ; [W] Modusregister
+SPIE equ RegBase+$06a6 ; [B] Ereignisregister
+SPIM equ RegBase+$06aa ; [B] Maskenregister
+SPICOM equ RegBase+$06ad ; [B] Kommandoregister
+SPI_RBASE equ SPIBase+$00 ; [W] Empfangsdeskriptoradresse
+SPI_TBASE equ SPIBase+$02 ; [W] Sendedeskriptoradresse
+SPI_RFCR equ SPIBase+$04 ; [B] Empfangsfunktionscode
+SPI_TFCR equ SPIBase+$05 ; [B] Sendefunktionscode
+SPI_MRBLR equ SPIBase+$06 ; [W] Maximallänge Empfangspuffer
+SPI_RSTATE equ SPIBase+$08 ; [L] Empfängerstatus
+SPI_RBPTR equ SPIBase+$10 ; [W] mom. aktiver Empfangsdeskriptor
+SPI_TSTATE equ SPIBase+$18 ; [L] Senderstatus
+SPI_TBPTR equ SPIBase+$20 ; [W] mom. aktiver Sendedeskriptor
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; PIP:
+
+PIPBase equ SMC2Base
+
+PIPC equ RegBase+$06b2 ; [W] Konfigurationsregister
+PTPR equ RegBase+$06b6 ; [W] Timing-Parameter
+PIPE equ SMCE2 ; [B] Ereignisregister, überlagert!!
+PBDIR equ RegBase+$06b8 ; [L] Datenrichtungsregister Port B
+PBPAR equ RegBase+$06bc ; [L] Zuordnung Port B
+PBODR equ RegBase+$06c2 ; [W] Steuerbits Port B als open drain
+PBDAT equ RegBase+$06c4 ; [L] Datenregister Port B
+PIP_RBASE equ PIPBase+$00 ; [W] Empfangsdeskriptoradresse
+PIP_TBASE equ PIPBase+$02 ; [W] Sendedeskriptoradresse
+PIP_CFCR equ PIPBase+$04 ; [B] Funktionscode
+PIP_SMASK equ PIPBase+$05 ; [B] Statusmaske
+PIP_MRBLR equ PIPBase+$06 ; [W] Maximallänge Empfangspuffer
+PIP_RSTATE equ PIPBase+$08 ; [L] Empfängerstatus
+PIP_R_PTR equ PIPBase+$0c ; [L] int. Empfangsdatenzeiger
+PIP_RBPTR equ PIPBase+$10 ; [W] mom. Empfangsdeskriptor
+PIP_R_CNT equ PIPBase+$12 ; [W] Empfangs-Byte-Zähler
+PIP_RTEMP equ PIPBase+$14 ; [L] temp. Speicher
+PIP_TSTATE equ PIPBase+$18 ; [L] Senderstatus
+PIP_T_PTR equ PIPBase+$1c ; [L] mom. Sendedatenzeiger
+PIP_TBPTR equ PIPBase+$20 ; [W] mom. Sendedeskriptor
+PIP_T_CNT equ PIPBase+$22 ; [W] Sende-Byte-Zähler
+PIP_TTEMP equ PIPBase+$24 ; [L] temp. Speicher
+PIP_MAX_SL equ PIPBase+$28 ; [W] max. Ruhezeit
+PIP_SL_CNT equ PIPBase+$2a ; [W] Ruhezähler
+PIP_CHARACTER1 equ PIPBase+$2c ; [W] Steuerzeichen
+PIP_CHARACTER2 equ PIPBase+$2e
+PIP_CHARACTER3 equ PIPBase+$30
+PIP_CHARACTER4 equ PIPBase+$32
+PIP_CHARACTER5 equ PIPBase+$34
+PIP_CHARACTER6 equ PIPBase+$36
+PIP_CHARACTER7 equ PIPBase+$38
+PIP_CHARACTER8 equ PIPBase+$3a
+PIP_RCCM equ PIPBase+$3c ; [W] Steuerzeichenmaske
+PIP_RCCR equ PIPBase+$3e ; [W] Steuerzeichenregister
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; SI:
+
+SIMODE equ RegBase+$06e0 ; [L] Modus serielles Interface
+SIGMR equ RegBase+$06e4 ; [B] globale Moduseinstellung
+SISTR equ RegBase+$06e6 ; [B] Adresse Router-RAM
+SICMR equ RegBase+$06e7 ; [B] Kommandoregister serielles Interface
+SICR equ RegBase+$06ec ; [L] Taktverteilung serielles Interface
+SIRP equ RegBase+$06f2 ; [L] RAM-Zeiger
+SIRAM equ RegBase+$0700 ; [ ] Routing-RAM
+
+;=============================================================================
+
+ case "68340"
+
+;-----------------------------------------------------------------------------
+; die Kommentare fallen hier evtl. etwas spartanischer aus, weil der Technical
+; Summary von Motorola für den 68340 noch nicht so ins Detail geht.
+
+SIMBAR equ $0003ff00 ; [L] Einstellung Peripherieadressen
+
+MCR equ SIMBase+$000 ; [W] Modulkonfiguration SIM
+
+SYNCR equ SIMBase+$004 ; [W] Steuerung Taktfrequenz-Synthi
+AVR equ SIMBase+$006 ; [B] Auto-Vektoren
+RSR equ SIMBase+$007 ; [B] Reset Status
+
+PORTA equ SIMBase+$011 ; [B] Datenregister Port A
+DDRA equ SIMBase+$013 ; [B] Datenrichtungsregister Port A
+PPRA1 equ SIMBase+$015 ; [B] Festlegung der Funktionen der...
+PPRA2 equ SIMBase+$017 ; [B] ...Leitungen von Port A
+PORTB equ SIMBase+$019 ; [B] Datenregister Port B
+PORTB1 equ SIMBase+$01b ; [B] dito
+DDRB equ SIMBase+$01d ; [B] Datenrichtungsregister Port B
+PPRARB equ SIMBase+$01f ; [B] Festlegung Port B-Leitungen
+SWIV equ SIMBase+$020 ; [B] Software-Vektoren
+SYPCR equ SIMBase+$021 ; [B] Systemschutz
+PICR equ SIMBase+$022 ; [W] Steuerung PIT
+PITR equ SIMBase+$024 ; [W] Datenregister PIT
+SWSR equ SIMBase+$027 ; [B] Software Service
+
+;-----------------------------------------------------------------------------
+; Chip Selects:
+
+__cnt set 0
+ rept 4
+__name set "\{__CNT}"
+CS{__name}AM1 set SIMBase+$040+__cnt*8 ; [W] Adressmaske 1 CSn
+CS{__name}AM2 set SIMBase+$042+__cnt*8 ; [W] Adressmaske 2 CSn
+CS{__name}BA1 set SIMBase+$044+__cnt*8 ; [W] Basisadresse 1 CSn
+CS{__name}BA2 set SIMBase+$046+__cnt*8 ; [W] Basisadresse 2 CSn
+__cnt set __cnt+1
+ endm
+
+;-----------------------------------------------------------------------------
+; DMA:
+
+DMABase equ SIMBase+$780
+DMAMCR1 equ DMABase+$000 ; [W] Modulkonfiguration DMA-Kanal 1
+DMAINTR1 equ DMABase+$004 ; [W] Interrupts DMA-Kanal 1
+DMACCR1 equ DMABase+$008 ; [W] Steuerregister DMA-Kanal 1
+DMACSR1 equ DMABase+$00a ; [B] Statusregister DMA-Kanal 1
+DMAFCR1 equ DMABase+$00b ; [B] Funktionscoderegister DMA-Kanal 1
+DMASAR1 equ DMABase+$00c ; [L] Quelladresse DMA-Kanal 1
+DMADAR1 equ DMABase+$010 ; [L] Zieladresse DMA-Kanal 1
+DMABTC1 equ DMABase+$014 ; [L] Bytezähler DMA-Kanal 1
+DMAMCR2 equ DMABase+$020 ; Kanal 2 genauso, nur $20 weiter
+DMAINTR2 equ DMABase+$024
+DMACCR2 equ DMABase+$028
+DMACSR2 equ DMABase+$02a
+DMAFCR2 equ DMABase+$02b
+DMASAR2 equ DMABase+$02c
+DMADAR2 equ DMABase+$030
+DMABTC2 equ DMABase+$034
+
+;-----------------------------------------------------------------------------
+; serielles:
+
+SMBase equ SIMBase+$700
+SMMCR equ SMBase+$000 ; [W] Modulkonfiguration SM
+SMILR equ SMBase+$004 ; [B] Interruptebene
+SMIVR equ SMBase+$005 ; [B] Interruptvektor
+SMIPCR equ SMBase+$014 ; [BR] Anzeige, ob Pegelwechsel an Leitungen
+SMACR equ SMBase+$014 ; [BW] Hilfssteuerregister
+SMISR equ SMBase+$015 ; [BR] Interruptanzeigen
+SMIER equ SMBase+$015 ; [BW] Interuptfreigaben
+SMOPCR equ SMBase+$01d ; [BW] Steuerung Ausgabeports
+SMIP equ SMBase+$01d ; [BR] Status Eingabeports
+SMOPS equ SMBase+$01e ; [BW] Portbits einzeln setzen
+SMOPR equ SMBase+$01f ; [BW] Portbits einzeln zurücksetzen
+SMMR1A equ SMBase+$010 ; [B] Modusregister 1 Kanal A
+SMMR2A equ SMBase+$020 ; [B] Modusregister 2 Kanal A
+SMCSRA equ SMBase+$011 ; [BR] Taktauswahl Kanal A
+SMSRA equ SMBase+$011 ; [BW] Statusregister Kanal A
+SMCRA equ SMBase+$012 ; [BW] Kommandoregister Kanal A
+SMRBA equ SMBase+$013 ; [BR] Empfangsdatenregister Kanal A
+SMTBA equ SMBase+$013 ; [BW] Sendedatenregister Kanal A
+SMMR1B equ SMBase+$018 ; [B] Modusregister 1 Kanal B
+SMMR2B equ SMBase+$021 ; [B] Modusregister 2 Kanal B
+SMCSRB equ SMBase+$019 ; [BR] Taktauswahl Kanal B
+SMSRB equ SMBase+$019 ; [BW] Statusregister Kanal B
+SMCRB equ SMBase+$01a ; [BW] Kommandoregister Kanal B
+SMRBB equ SMBase+$01b ; [BR] Empfangsdatenregister Kanal B
+SMTBB equ SMBase+$01b ; [BW] Sendedatenregister Kanal B
+
+;-----------------------------------------------------------------------------
+; Timer:
+
+TMBase equ SIMBase+$600
+TM1MCR equ TMBase+$000 ; [W] Modulkonfiguration Timer 1
+TM1IR equ TMBase+$004 ; [W] Interruptkonfiguration Timer 1
+TM1CR equ TMBase+$006 ; [W] Steuerung Timer 1
+TM1SR equ TMBase+$008 ; [W] Status/Vorteiler Timer 1
+TM1CNTR equ TMBase+$00a ; [W] Zählregister Timer 1
+TM1PREL1 equ TMBase+$00c ; [W] Vorbelegung 1 Timer 1
+TM1PREL2 equ TMBase+$00e ; [W] Vorbelegung 2 Timer 1
+TM1COM equ TMBase+$010 ; [W] Vergleichsregister Timer 1
+TM2MCR equ TMBase+$040 ; dito Kanal 2
+TM2IR equ TMBase+$044
+TM2CR equ TMBase+$046
+TM2SR equ TMBase+$048
+TM2CNTR equ TMBase+$04a
+TM2PREL1 equ TMBase+$04c
+TM2PREL2 equ TMBase+$04e
+TM2COM equ TMBase+$050
+
+;=============================================================================
+; ab hier 68332-Register
+
+ case "68332"
+
+;-----------------------------------------------------------------------------
+; die fundamentalen SIM-Steuerregister
+
+SIMCR equ SIMBase+$00 ; [W] MCU-Konfiguration
+SIYPCR equ SIMBase+$21 ; [W] Watchdog, Bus-Monitorsteuerung
+SWSR equ SIMBase+$27 ; [B] Watchdog zurücksetzen (mit $55/$aa)
+PICR equ SIMBase+$22 ; [W] Interruptsteuerung Timer
+PITR equ SIMBase+$24 ; [W] Zählwert Timer
+
+;-----------------------------------------------------------------------------
+; der Synthesizer für den Prozessortakt
+
+SYNCR equ SIMBase+$04 ; [W] Taktfrequenz-Synthesizer-Steuerung
+
+;-----------------------------------------------------------------------------
+; die Chip-Select-Ausgänge
+
+CSPAR0 equ SIMBase+$44 ; [W] Steuerung der Ausgänge CSBOOT,CS0..CS5
+CSPAR1 equ SIMBase+$46 ; [W] Steuerung der Ausgänge CS6..CS10
+CSBARBT equ SIMBase+$48 ; [W] Startadresse Boot-ROM
+CSORBT equ SIMBase+$4a ; [W] Optionen Boot-ROM
+__cnt set 0
+ rept 10 ; nur 0..9 so erzeugen, damit keine Hex-Namen
+__name set "\{__CNT}"
+CSBAR{__name} equ SIMBase+$4c+__cnt*4 ; [W] Startadresse CSn
+CSOR{__name} equ SIMBase+$4e+__cnt*4 ; [W] Optionen CSn
+__cnt set __cnt+1
+ endm
+CSBAR10 equ SIMBase+$74 ; [W] Startadresse CS10
+CSOR10 equ SIMBase+$76 ; [W] Optionen CS10
+
+;-----------------------------------------------------------------------------
+; Nutzung der SIM-Bits als einfache I/O-Ports
+
+PORTC equ SIMBase+$41 ; [B] Datenbits Port C
+PORTE0 equ SIMBase+$11 ; [B] Datenbits Port E
+PORTE1 equ SIMBase+$13 ; [B] dito
+DDRE equ SIMBase+$15 ; [B] Datenrichtungsbits Port E
+PEPAR equ SIMBase+$17 ; [B] Steuerung Port E-Pins als Ports oder Bussignale
+PORTF0 equ SIMBase+$19 ; [B] Datenbits Port F
+PORTF1 equ SIMBase+$1b ; [B] dito
+DDRF equ SIMBase+$1d ; [B] Datenrichtungsbits Port F
+PFPAR equ SIMBase+$1f ; [B] Steuerung Port F-Pins als Ports oder Bussignale
+
+;-----------------------------------------------------------------------------
+; Register für den Boundary-Scan-Test des SIM (for Motorola use only...)
+
+SIMTR equ SIMBase+$02 ; [W] Testregister SIM
+SIMTRE equ SIMBase+$08 ; [W] Testregister E-Takt
+TSTMSRA equ SIMBase+$30 ; [W] Schieberegister A (Boundary Scan)
+TSTMSRB equ SIMBase+$32 ; [W] Schieberegister B (Boundary Scan)
+TSTSC equ SIMBase+$34 ; [W] Register Schiebezahl
+TSTRC equ SIMBase+$36 ; [W] Register Wiederholungszahl
+CREG equ SIMBase+$38 ; [W] Steuerregister Boundary Scan
+DREG equ SIMBase+$3a ; [W] verteiltes Register (?!)
+
+;-----------------------------------------------------------------------------
+; programmierbare Zeitgeber:
+
+TPUBase equ SIMBase+$400 ; Basisadresse TPU-Registersatz
+TPUMCR equ TPUBase+$00 ; [W] Basiskonfiguration TPU
+TICR equ TPUBase+$08 ; [W] Interruptsteuerung TPU
+CIER equ TPUBase+$0a ; [W] TPU Interrupt-Freigaben
+CISR equ TPUBase+$20 ; [W] TPU Interrupt-Anzeigen
+CFSR0 equ TPUBase+$0c ; [W] TPU Betriebsarten Kanal 12..15
+CFSR1 equ TPUBase+$0e ; [W] TPU Betriebsarten Kanal 8..11
+CFSR2 equ TPUBase+$10 ; [W] TPU Betriebsarten Kanal 4.. 7
+CFSR3 equ TPUBase+$12 ; [W] TPU Betriebsarten Kanal 0.. 3
+HSQR0 equ TPUBase+$14 ; [W] TPU Sub-Betriebsarten Kanal 8..15
+HSQR1 equ TPUBase+$16 ; [W] TPU Sub-Betriebsarten Kanal 0.. 7
+HSRR0 equ TPUBase+$18 ; [W] TPU Service-Anfragebits Kanal 8..15
+HSRR1 equ TPUBase+$1a ; [W] TPU Service-Anfragebits Kanal 0.. 7
+CPR0 equ TPUBase+$1c ; [W] TPU Priorität Kanal 8..15
+CPR1 equ TPUBase+$1e ; [W] TPU Priorität Kanal 0.. 7
+DSCR equ TPUBase+$04 ; [W] Register für Entwicklung und Test ?!
+DSSR equ TPUBase+$06 ; eine genauere Beschreibung habe ich
+LR equ TPUBase+$22 ; leider nicht...
+SGLR equ TPUBase+$24 ;
+DCNR equ TPUBase+$26 ;
+TCR equ TPUBase+$02 ;
+
+;-----------------------------------------------------------------------------
+; das Kommando-RAM für die TPU:
+
+TPURAMBase equ SIMBase+$100 ; Basisadresse TPURAM-Steuerregister
+TRAMMCR equ TPURAMBase+$00 ; [B] Basiskonfiguration TPURAM
+TRAMTST equ TPURAMBase+$02 ; [W] Testregister TPURAM
+TRAMBAR equ TPURAMBase+$04 ; [W] Basisadresse TPURAM
+
+;-----------------------------------------------------------------------------
+; serielles:
+
+QSMBase equ SIMBase+$200 ; Basisadresse serielle E/A-Einheit
+QSMCR equ QSMBase+$00 ; [W] Basiskonfiguration QSM
+QTEST equ QSMBase+$02 ; [W] QSM Testregister
+QILR equ QSMBase+$04 ; [B] QSM Interruptprioritäten
+QIVR equ QSMBase+$05 ; [B] QSM Interruptvektor
+PORTQS equ QSMBase+$14 ; [W] Datenbits QSM paralleler Port
+PQSPAR equ QSMBase+$16 ; [B] Umschaltung Portbits QSM/paralleler Port
+DDRQS equ QSMBase+$17 ; [B] Datenrichtungsregister Port QSM
+SPCR0 equ QSMBase+$18 ; [W] Steuerregister 0 QSPI
+SPCR1 equ QSMBase+$1a ; [W] Steuerregister 1 QSPI
+SPCR2 equ QSMBase+$1c ; [W] Steuerregister 2 QSPI
+SPCR3 equ QSMBase+$1e ; [B] Steuerregister 3 QSPI
+SPSR equ QSMBase+$1f ; [B] Statusregister QSPI
+__cnt set 0 ; Definition QSPI-RAM
+ rept 16
+__name set "\{__CNT}"
+RR{__name} equ QSMBase+$100+__cnt*2 ; [W] Daten-RAM Empfangsseite
+TR{__name} equ QSMBase+$120+__cnt*2 ; [W] Daten-RAM Sendeseite
+CR{__name} equ QSMBase+$140+__cnt ; [B] Befehls-RAM
+__cnt set __cnt+1
+ endm
+SCCR0 equ QSMBase+$08 ; [W] Steuerregister 0 SCI
+SCCR1 equ QSMBase+$0a ; [W] Steuerregister 1 SCI
+SCSR equ QSMBase+$0c ; [W] Statusregister SCI
+SCDR equ QSMBase+$0e ; [W] Datenregister SCI
+
+;-----------------------------------------------------------------------------
+
+ endcase ; von Prozessorunterscheidung
+
+ endif ; von ifdef ...
+
+ restore ; wieder erlauben
+
+
diff --git a/include/reg7000.inc b/include/reg7000.inc
new file mode 100644
index 0000000..120b86f
--- /dev/null
+++ b/include/reg7000.inc
@@ -0,0 +1,120 @@
+ save
+; listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REG7000.INC *
+;* *
+;* Sinn : enthält SFR- und Bitdefinitionen für die TMS70Cxx-Prozessoren *
+;* *
+;* letzte Änderungen : 15. 2.1997 *
+;* *
+;****************************************************************************
+
+ ifndef reg7000inc ; verhindert Mehrfacheinbindung
+
+reg7000inc equ 1
+
+ switch MOMCPUNAME
+ case "TMS70C40"
+IROM equ 0f000h
+__group equ 1
+ case "TMS70C20"
+IROM equ 0f800h
+__group equ 1
+ case "TMS70C00"
+IROM equ 10000h
+__group equ 1
+ case "TMS70CT40"
+IROM equ 0f000h
+__group equ 2
+ case "TMS70CT20"
+IROM equ 0f800h
+__group equ 2
+ case "TMS70C82"
+IROM equ 0e000h
+__group equ 3
+ case "TMS70C42"
+IROM equ 0f000h
+__group equ 3
+ case "TMS70C02"
+IROM equ 0f800h
+__group equ 3
+ case "TMS70C48"
+IROM equ 0f000h
+__group equ 4
+ case "TMS70C08"
+IROM equ 10000h
+__group equ 4
+ elsecase
+ fatal "Fehler: nur TMS70Cxx-Prozessoren erlaubt!"
+ endcase
+
+ if MOMPASS=1
+ message "TMS7000-Register-Definitionen (C) 1997 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; Speicherbereiche
+
+IRAM equ 0
+IROMEND equ 0ffffh
+ if __group<=2
+IRAMEND equ 127
+ elseif
+IRAMEND equ 255
+ endif
+
+;----------------------------------------------------------------------------
+; Peripherie
+
+IOCNT0 equ p0 ; I/O Control Register 0
+APORT equ p4 ; Port A Data
+BPORT equ p6 ; Port B Data
+CPORT equ p8 ; Port C Data
+CDDR equ p9 ; Port C Data Direction Register
+DPORT equ p10 ; Port D Data
+DDDR equ p11 ; Port D Data Direction Register
+
+ if __group<=2
+T1DATA equ p2 ; Timer 1 Data
+T1CTL equ p3 ; Timer 1 Control
+ endif
+
+ if __group>=3
+IOCNT2 equ p1 ; I/O Control Register 2
+IOCNT1 equ p2 ; I/O Control Register 1
+ADDR equ p5 ; Port A Data Direction Register
+T1MSDATA equ p12 ; Timer 1 MSB Dec. Reload / Readout Latch
+T1LSDATA equ p13 ; Timer 1 LSB Reload / Dec. Value
+T1CTL1 equ p14 ; Timer 1 Control Register 1 / MSB Readout Latch
+T1CTL0 equ p15 ; Timer 1 Control Register 0 / LSB Capture Latch
+T2MSDATA equ p16 ; Timer 2 MSB Dec. Reload / Readout Latch
+T2LSDATA equ p17 ; Timer 2 LSB Reload / Dec. Value
+T2CTL1 equ p18 ; Timer 2 Control Register 1 / MSB Readout Latch
+T2CTL0 equ p19 ; Timer 2 Control Register 0 / LSB Capture Latch
+SMODE equ p20 ; Serial Port Mode Control Register
+SCTL0 equ p21 ; Serial Port Control Register 0
+SSTAT equ p22 ; Serial Port Status Register
+T3DATA equ p23 ; Timer 3 Reload Reg. / Decr. Value
+SCTL1 equ p24 ; Serial Port Control Register 1
+RXBUF equ p25 ; Receiver Buffer
+TXBUF equ p26 ; Transmitter Buffer
+ endif
+
+ if __group=4
+EPORT equ p28 ; Port E Data
+EDDR equ p29 ; Port E Data Direction Register
+FPORT equ p30 ; Port F Data
+FDDR equ p31 ; Port F Data Direction Register
+GPORT equ p32 ; Port G Data
+GDDR equ p33 ; Port G Data Direction Register
+ endif
+
+;----------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
+
diff --git a/include/reg78k0.inc b/include/reg78k0.inc
new file mode 100644
index 0000000..914befa
--- /dev/null
+++ b/include/reg78k0.inc
@@ -0,0 +1,245 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REG78K0.INC *
+;* *
+;* Sinn : enthält Registerdefinitionen für 78K0 (uPD78070A) *
+;* *
+;* letzte Änderungen : 1.10.1996 *
+;* *
+;****************************************************************************
+
+ ifndef regz78k0inc ; verhindert Mehrfacheinbindung
+
+reg8k0inc equ 1
+
+ if (MOMCPUNAME<>"78070")
+ fatal "Falscher Prozessortyp eingestellt: nur 78070 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "78K0-Register-Definitionen (C) 1996 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; CPU-Kern
+
+SP equ 0ff1ch ; Stackpointer
+
+PSW equ 0ff1eh ; Statuswort
+
+;----------------------------------------------------------------------------
+; Taktgenerator
+
+PCC equ 0fffbh ; Steuerung Prozessortakt
+
+OSMS equ 0fff2h ; Taktteiler ein/ausschalten
+
+OSTS equ 0fffah ; Wartezeit, um nach STOP-Auflösung
+
+;----------------------------------------------------------------------------
+; Bus-Interface
+
+EBTS equ 0ff3fh ; Multiplex an/aus (fest auf aus)
+
+IMS equ 0fff0h ; Größe internes RAM (fest 1K)
+
+MM equ 0fff8h ; Wait-State-Steuerung
+
+;----------------------------------------------------------------------------
+; Interrupt-Steuerung
+
+INTM0 equ 0ffech ; Flankenwahl INTP0...INTP2
+INTM1 equ 0ffedh ; Flankenwahl INTP3...INTP6
+SCS equ 0ff47h ; Auswahl Abtastrate INTP0
+
+IF0L equ 0ffe0h ; Interrupts aufgetreten ?
+IF0H equ 0ffe1h
+IF0 equ IF0L
+IF1L equ 0ffe2h
+
+MK0L equ 0ffe4h ; Maskierungsregister
+MK0H equ 0ffe5h
+MK0 equ IF0L
+MK1L equ 0ffe6h
+
+PR0L equ 0ffe8h ; Prioritäten
+PR0H equ 0ffe9h
+PR0 equ IF0L
+PR1L equ 0ffeah
+
+;----------------------------------------------------------------------------
+; Ports
+
+P0 equ 0ff00h ; Datenregister Port 0
+PM0 equ 0ff20h ; Datenrichtungsregister Port 0
+
+P1 equ 0ff01h ; Datenregister Port 1
+PM1 equ 0ff21h ; Datenrichtungsregister Port 1
+
+P2 equ 0ff02h ; Datenregister Port 2
+PM2 equ 0ff22h ; Datenrichtungsregister Port 2
+
+P3 equ 0ff03h ; Datenregister Port 3
+PM3 equ 0ff23h ; Datenrichtungsregister Port 3
+
+P6 equ 0ff06h ; Datenregister Port 6
+PM6 equ 0ff26h ; Datenrichtungsregister Port 6
+
+P7 equ 0ff07h ; Datenregister Port 7
+PM7 equ 0ff27h ; Datenrichtungsregister Port 7
+
+P9 equ 0ff09h ; Datenregister Port 9
+PM9 equ 0ff29h ; Datenrichtungsregister Port 9
+
+P10 equ 0ff0ah ; Datenregister Port 10
+PM10 equ 0ff2ah ; Datenrichtungsregister Port10
+
+P12 equ 0ff0ch ; Datenregister Port 12
+PM12 equ 0ff2ch ; Datenrichtungsregister Port 12
+
+P13 equ 0ff0dh ; Datenregister Port 13
+PM13 equ 0ff2dh ; Datenrichtungsregister Port 13
+
+PUOH equ 0fff3h ; Pull-Up-Register Port 0..7
+PUOL equ 0fff7h ; Pull-Up-Register Port 8..13
+
+;----------------------------------------------------------------------------
+; Timer
+
+TM0 equ 0ff14h ; Zählwert Timer 0
+CR00 equ 0ff10h ; Vergleichs/Fangregister 0 Timer 0
+CR01 equ 0ff12h ; Vergleichs/Fangregister 1 Timer 0
+TCL0 equ 0ff40h ; Taktauswahl Timer 0
+TMC0 equ 0ff48h ; Betriebsart Timer 0
+CRC0 equ 0ff4ch ; Steuerung Fang/Vergleichsregister Timer 0
+TOC0 equ 0ff4eh ; Ausgabesteuerung Timer 0
+
+TM1 equ 0ff18h ; Zählwert Timer 1
+CR10 equ 0ff16h ; Vergleichs/Fangregister Timer 1
+TCL1 equ 0ff41h ; Taktauswahl Timer 1
+TMC1 equ 0ff49h ; Betriebsart Timer 1
+
+TM2 equ 0ff19h ; Zählwert Timer 2
+CR20 equ 0ff17h ; Vergleichs/Fangregister Timer 2
+TCL2 equ 0ff42h ; Taktauswahl Timer 2 / Uhren-Timer / Watchdog / Summer
+TMC2 equ 0ff4ah ; Betriebsart Timer 2 / Uhren-Timer
+
+TMS equ TM1 ; Zählwert Timer 1+2 im 16-Bit-Modus
+TOC1 equ 0ff4fh ; Ausgabesteuerung Timer 1+2
+
+TM5 equ 0ff51h ; Zählwert Timer 5
+CR50 equ 0ff50h ; Vergleichsregister Timer 5
+TCL5 equ 0ff52h ; Taktauswahl Timer 5
+TMC5 equ 0ff53h ; Betriebsart Timer 5
+
+TM6 equ 0ff55h ; Zählwert Timer 6
+CR60 equ 0ff54h ; Vergleichsregister Timer 6
+TCL6 equ 0ff56h ; Taktauswahl Timer 6
+TMC6 equ 0ff57h ; Betriebsart Timer 6
+
+;----------------------------------------------------------------------------
+; Watchdog
+
+WDTM equ 0fff9h ; Betriebsart
+
+;----------------------------------------------------------------------------
+; serielle Schnittstelle
+
+; Kanal 0
+SIO0 equ 0ff1ah ; Datenregister
+SVA equ 0ff62h ; Slave-Adresse
+TCL3 equ 0ff43h ; Taktauswahl Kanal 0/1
+CSIM0 equ 0ff60h ; Betriebsart
+SBIC equ 0ff61h ; Bus-Steuerung
+SINT equ 0ff63h ; Interrupt-Timing
+
+; Kanal 1
+SIO1 equ 0ff1bh ; Datenregister
+ADTP equ 0ff6ah ; Adreßzeiger bei Blockempfang/versand
+CSIM1 equ 0ff68h ; Betriebsart
+ADTC equ 0ff69h ; Steuerung Blockbetrieb
+ADTI equ 0ff6bh ; Geschwindigkeit Blockversand
+
+; Kanal 2
+TXS equ 0ff74h ; Datenregister
+RXB equ 0ff74h
+SIO2 equ TXS
+ASIM equ 0ff70h ; Schnittstellenparameter
+ASIS equ 0ff71h ; Statusregister
+CSIM2 equ 0ff72h ; Betriebsart
+BRGC equ 0ff73h ; Baudratenwahl
+
+;----------------------------------------------------------------------------
+; A/D-Wandler
+
+ADCR equ 0ff1fh ; Ergebnisregister Wandlung
+
+ADM equ 0ff80h ; Betriebsart
+
+ADIS equ 0ff84h ; Umschaltung Ports als Analogeingänge
+
+;----------------------------------------------------------------------------
+; D/A-Wandler
+
+DACS0 equ 0ff90h ; Analogwert Wandler 0
+
+DACS1 equ 0ff91h ; Analogwert Wandler 1
+
+DAM equ 0ff96h ; Betriebsart
+
+;----------------------------------------------------------------------------
+; Echtzeitausgabe
+
+RTBL equ 0ff30h ; Ausgabedaten
+RTBH equ 0ff31h
+RTPM equ 0ff34h ; Betriebsart
+RTPC equ 0ff36h ; Steuerung
+
+;----------------------------------------------------------------------------
+; Vektoradressen
+
+Vec_Reset equ 0000h ; Reset
+Vec_INTWDT equ 0004h ; Watchdog
+Vec_INTP0 equ 0006h ; externe Interrupts
+Vec_INTP1 equ 0008h
+Vec_INTP2 equ 000ah
+Vec_INTP3 equ 000ch
+Vec_INTP4 equ 000eh
+Vec_INTP5 equ 0010h
+Vec_INTP6 equ 0012h
+Vec_INTCSI0 equ 0014h ; serielle Schnittstellen
+Vec_INTCSI1 equ 0016h
+Vec_INTSER equ 0018h
+Vec_INTSR equ 001ah
+Vec_INTCSI2 equ Vec_INTSR
+Vec_INTST equ 001ch
+Vec_INTTM3 equ 001eh ; Uhren-Timer
+Vec_INTTM00 equ 0020h ; Timer
+Vec_INTTM01 equ 0022h
+Vec_INTTM1 equ 0024h ; Vergleicher Timer 1
+Vec_INTTM2 equ 0026h ; Vergleicher Timer 2
+Vec_INTAD equ 0028h ; A/D-Wandler
+Vec_INTTM5 equ 002ah ; Vergleicher Timer 5
+Vec_INTTM6 equ 002ch ; Vergleicher Timer 6
+Vec_BRK equ 003eh ; BRK-Befehl
+
+;----------------------------------------------------------------------------
+; Speicheradressen
+
+BUFRAM equ 0fac0h ; Puffer-RAM
+BUFRAMEND equ 0fadfh
+
+IRAM equ 0fb00h ; internes RAM
+IRAMEND equ 0fedfh ; dahinter sind die Register gemappt!
+
+;----------------------------------------------------------------------------
+
+ endif ; von IFDEF...
+ restore ; wieder erlauben
+
+
+
diff --git a/include/reg96.inc b/include/reg96.inc
new file mode 100644
index 0000000..02b309b
--- /dev/null
+++ b/include/reg96.inc
@@ -0,0 +1,610 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REG96.INC *
+;* *
+;* Sinn : enthält Makro-, SFR- und Adreßdefinitionen für die *
+;* MCS-96-Prozessoren *
+;* OK, der Name fällt aus dem Rahmen, aber STDDEF96.INC war schon *
+;* belegt... *
+;* *
+;* letzte Änderungen : 20. 2.1994 *
+;* 28. 6.1994 80196 (KR) hinzugefügt *
+;* 9. 3.1997 80196N(T), 80296 hinzugefügt *
+;* *
+;****************************************************************************
+
+ ifndef reg96inc ; verhindert Mehrfacheinbindung
+
+reg96inc equ 1
+
+ if (MOMCPUNAME<>"8096")&&(MOMCPUNAME<>"80196")
+ fatal "Falscher Prozessortyp eingestellt: nur 8096, 80196, 80196N oder 80299 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "MCS-96-SFR-Definitionen (C) 1994 Alfred Arnold"
+ message "binde \{MOMCPU}-SFRs ein"
+ endif
+
+;----------------------------------------------------------------------------
+; CPU-Register:
+
+R0 equ 0 ; Nullregister
+ZERO_REG equ R0
+ONES_REG equ 2 ; nur Einsen
+SP equ 18h ; Stackpointer
+ if MOMCPU>=80196h
+WSR equ 14h ; RAM-Window in Registerbank
+ if MOMCPU>=80296h
+WSR1 equ 15h ; RAM-Window in untere Hälfte Registerbank
+ endif
+ endif
+
+ if MOMCPU>=80296h ; Signalprozessorregister
+ACC_00 equ 000ch ; Akkumulator
+ACC_02 equ 000eh
+ACC_04 equ 0006h
+ACC_STAT equ 000bh
+ICB0 equ 1fc3h ; Indexregister
+ICB1 equ 1fc7h
+ICX0 equ 0010h
+ICX1 equ 0016h
+IDX0 equ 1fc0h
+IDX1 equ 1fc4h
+RPT_CNT equ 0004h ; Zählregister
+ endif
+
+;----------------------------------------------------------------------------
+; SFRs:
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; A/D-Wandler
+ switch MOMCPUNAME
+
+ case "80296" ; Warnung unterdrücken
+
+
+ case "80196N"
+AD_RESULT equ 1faah ; Ergebnis Wandlung (wortweise lesbar)
+AD_COMMAND equ 1fach ; Steuerung AD-Wandler
+AD_TEST equ 1faeh ; Justage
+AD_TIME equ 1fafh ; Wandlungsgeschwindigkeit
+
+
+ case "80196"
+AD_Result equ 1faah ; Ergebnis Wandlung (wortweise lesbar)
+AD_Command equ 1fach ; Steuerung AD-Wandler
+AD_Test equ 1faeh ; Justage
+AD_Time equ 1fafh ; Wandlungsgeschwindigkeit
+
+
+ case "8096"
+AD_Command equ 2 ; A/D-Wandler Steuerregister
+AD_Result_Lo equ 2 ; Ergebnis A/D-Wandler
+AD_Result_Hi equ 3 ; NUR byteweise lesen!!
+
+
+ endcase
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; HSI/HSO/EPA
+
+ switch MOMCPUNAME
+
+
+ case "80296"
+EPA_MASK equ 1f9ch ; Interruptmasken
+EPA_PEND equ 1f9eh ; Interruptanzeigen
+__CNT set 0
+ rept 4
+EPA{"\{__CNT}"}_CON equ 1f60h+(__CNT*4) ; Steuerung Vergleicher/Fangeinheiten
+EPA{"\{__CNT}"}_TIME equ 1f62h+(__CNT*4) ; Zeitpunkt " "
+__CNT set __CNT+1
+ endm
+
+
+ case "80196N"
+COMP0_CON equ 1f88h ; Steuerung Vergleicher 0
+COMP0_TIME equ 1f8ah ; Zeitpunkt Vergleicher 0
+
+COMP1_CON equ 1f8ch ; dito
+COMP1_CON equ 1f8eh
+
+EPA_MASK equ 1fa0h ; Interruptmasken
+EPA_MASK1 equ 1fa4h
+EPA_PEND equ 1fa2h ; Interruptanzeigen
+EPA_PEND1 equ 1fa6h
+__CNT set 0
+ rept 10
+EPA{"\{__CNT}"}_CON equ 1f60h+(__CNT*4) ; Steuerung Vergleicher/Fangeinheiten
+EPA{"\{__CNT}"}_TIME equ 1f62h+(__CNT*4) ; Zeitpunkt " "
+__CNT set __CNT+1
+ endm
+EPAIPV equ 1fa8h ; Interrupt-Priorität
+
+
+ case "80196"
+EPA_Mask equ 1fa0h ; (w) EPA Interruptfreigabe 4..9, 0..1, overrun 0..9/0/1
+EPA_Mask1 equ 1fa4h
+EPA_Pend equ 1fa2h ; (w) EPA Interrupt aufgetreten 4..9, 0..1, overrun 0..9/0/1
+EPA_Pend1 equ 1fa6h
+EPAIpv equ 1fa8h ; Priorität EPA-Interrupt
+
+EPA_Control0 equ 1f60h ; Steuerung Capture/Compare Kanal 0..9
+EPA_Time0 equ 1f62h ; (w) gespeicherter Zeitpunkt Kanal 0..9
+EPA_Control1 equ 1f64h
+EPA_Time1 equ 1f66h
+EPA_Control2 equ 1f68h
+EPA_Time2 equ 1f6ah
+EPA_Control3 equ 1f6ch
+EPA_Time3 equ 1f6eh
+EPA_Control4 equ 1f70h
+EPA_Time4 equ 1f72h
+EPA_Control5 equ 1f74h
+EPA_Time5 equ 1f76h
+EPA_Control6 equ 1f78h
+EPA_Time6 equ 1f7ah
+EPA_Control7 equ 1f7ch
+EPA_Time7 equ 1f7eh
+EPA_Control8 equ 1f80h
+EPA_Time8 equ 1f82h
+EPA_Control9 equ 1f84h
+EPA_Time9 equ 1f86h
+Comp_Control0 equ 1f88h ; Steuerung Compare-Kanal 0..1
+Comp_Time0 equ 1f8ah ; Vergleichswert Compare-Kanal 0..1
+Comp_Control1 equ 1f8ch
+Comp_Time1 equ 1f8eh
+
+
+ case "8096"
+HSI_Time equ 4 ; HSI Triggerzeitpunkt (nur Wort)
+HSI_Mode equ 3 ; HSI Modusregister
+HSI_Status equ 6 ; HSI Statusregister
+
+HSO_Time equ 4 ; HSO Zeiteinstellung (nur Wort)
+HSO_Command equ 6 ; HSO Steuerregister
+
+
+ endcase
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; serielles
+
+ switch MOMCPUNAME
+
+
+ case "80296"
+SP_CON equ 1fbbh ; Steuerung SIO
+SP_BAUD equ 1fbch ; (w) Baudrate SIO
+SP_STATUS equ 1fb9h ; Status SIO
+SBUF_RX equ 1fb8h ; Empfangsdaten
+SBUF_TX equ 1fbah ; Sendedaten
+
+
+ case "80196N"
+SP_CON equ 1fbbh ; Steuerung SIO
+SP_BAUD equ 1fbch ; (w) Baudrate SIO
+SP_STATUS equ 1fb9h ; Status SIO
+SBUF_RX equ 1fb8h ; Empfangsdaten
+SBUF_TX equ 1fbah ; Sendedaten
+
+SSIO_BAUD equ 1fb4h ; Baudrate SSIO
+SSIO0_BUF equ 1fb0h ; Datenregister SSIO0
+SSIO1_BUF equ 1fb2h ; Datenregister SSIO1
+SSIO0_CON equ 1fb1h ; Modus SSIO0
+SSIO1_CON equ 1fb3h ; Modus SSIO1
+
+
+ case "80196"
+SSIO_StB0 equ 1fb0h ; Datenpuffer SSIO Kanal 0
+SSIO_StCr0 equ 1fb1h ; Steuerung Sender/Empfänger SSIO Kanal 0
+SSIO_StB1 equ 1fb2h ; Datenpuffer SSIO Kanal 1
+SSIO_StCr1 equ 1fb3h ; Steuerung Sender/Empfänger SSIO Kanal 1
+SSIO_Baud equ 1fb4h ; Baudrate SSIO
+SBuf_RX equ 1fb8h ; Empfangsdaten
+SP_Stat equ 1fb9h ; Zustand SIO
+SBuf_TX equ 1fbah ; Sendedaten
+SP_Con equ 1fbbh ; Steuerung SIO
+SP_Baud equ 1fbch ; (w) Baudrate SIO
+
+
+ case "8096"
+SBUF equ 7 ; UART Datenregister
+SPStat equ 11h ; UART Statusregister
+SPCon equ 11h ; UART Steuerregister
+Baud_Reg equ 0eh ; UART Datenrate
+
+
+ endcase
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; Interruptsteuerung
+
+ switch MOMCPUNAME
+
+
+ case "80296"
+INT_MASK equ 08h ; Interruptmasken
+INT_MASK1 equ 13h
+INT_PEND equ 09h ; Interruptanzeigen
+INT_PEND1 equ 12h
+EXTINT_CON equ 1fcch ; Flankenwahl externe Interrupts
+IN_PROG0 equ 1fc8h ; Interruptbearbeitung läuft
+IN_PROG1 equ 1fcah
+INT_CON0 equ 1fe8h ; Prioritätsfestlegung
+INT_CON1 equ 1feah
+INT_CON2 equ 1fech
+INT_CON3 equ 1feeh
+NMI_PEND equ 1fc9h ; NMI angefordert ?
+VECT_ADDR equ 1ff0h ; Vektorbasis
+
+ case "80196N"
+INT_MASK equ 08h ; Interruptmasken
+INT_MASK1 equ 13h
+INT_PEND equ 09h ; Interruptanzeigen
+INT_PEND1 equ 12h
+
+PTSSRV equ 06h ; (w) PTS-Interrupt bedient
+PTSSEL equ 04h ; (w) Quellen PTS freigeben
+
+
+ case "80196"
+Int_Mask_Lo equ 08h ; Interruptfreigabe
+Int_Mask_Hi equ 13h
+Int_Pend_Lo equ 09h ; wartende Interrupts
+Int_Pend_Hi equ 12h
+
+PTS_Srv equ 06h ; w PTS-Interrupt bedient
+PTS_Select equ 04h ; w Quellen PTS freigeben
+
+
+ case "8096"
+INT_Mask equ 8 ; Interruptfreigabe
+INT_Pending equ 9 ; Interrupts aufgetreten ?
+
+
+ endcase
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; Timer
+
+Watchdog equ 0ah ; Watchdog zurücksetzen
+
+ switch MOMCPUNAME
+
+
+ case "80296"
+CON_REG0 equ 1fb6h ; Steuerung PWM
+PWM0_CONTROL equ 1fb0h ; Einschaltdauer PWM0
+PWM1_CONTROL equ 1fb2h
+PWM2_CONTROL equ 1fb4h
+
+T1CONTROL equ 1f90h ; Steuerung Timer 1
+TIMER1 equ 1f92h ; (w) Daten Timer 1
+T2CONTROL equ 1f94h ; Steuerung Timer 2
+TIMER22 equ 1f96h ; (w) Daten Timer 2
+
+
+ case "80196N"
+T1CONTROL equ 1f98h ; Steuerung Timer 1
+TIMER1 equ 1f9ah ; (w) Daten Timer 1
+T2CONTROL equ 1f9ch ; Steuerung Timer 2
+TIMER22 equ 1f9eh ; (w) Daten Timer 2
+
+
+ case "80196"
+Timer1_Control equ 1f98h ; Steuerung Timer 1
+Timer1 equ 1f9ah ; (w) Daten Timer 1
+Timer2_Control equ 1f9ch ; Steuerung Timer 2
+Timer2 equ 1f9eh ; (w) Daten Timer 2
+
+
+ case "8096"
+Timer1 equ 0ah ; Timer 1 (nur Wort)
+Timer2 equ 0ch ; Timer 2 (nur Wort)
+
+PWM_Control equ 17h ; Einstellung Pulsweite PWM
+
+
+ endcase
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; Ports
+
+ switch MOMCPUNAME
+
+
+ case "80296"
+
+P1_DIR equ 1fd2h ; Richtungsregister Port 1
+P1_MODE equ 1fd0h ; Auswahl Port 1 Spezialfunktion/IO-Port
+P1_PIN equ 1fd6h ; Status Port 1 Pins
+P1_REG equ 1fd4h ; Port 1 Ausgabedaten
+
+P2_DIR equ 1fd3h ; Rest sinngemäß
+P2_MODE equ 1fd1h
+P2_PIN equ 1fd7h
+P2_REG equ 1fd5h
+
+P3_DIR equ 1fdah
+P3_MODE equ 1fd8h
+P3_PIN equ 1fdeh
+P3_REG equ 1fdch
+
+P4_DIR equ 1fdbh
+P4_MODE equ 1fd9h
+P4_PIN equ 1fdfh
+P4_REG equ 1fddh
+
+EP_DIR equ 1fe3h
+EP_MODE equ 1fe1h
+EP_PIN equ 1fe7h
+EP_REG equ 1fe5h
+
+
+ case "80196N"
+P0_PIN equ 1fdah ; Daten Port 0
+
+P1_DIR equ 1fd2h ; Richtungsregister Port 1
+P1_MODE equ 1fd0h ; Auswahl Port 1 Spezialfunktion/IO-Port
+P1_PIN equ 1fd6h ; Status Port 1 Pins
+P1_REG equ 1fd4h ; Port 1 Ausgabedaten
+
+P2_DIR equ 1fcbh ; Rest sinngemäß
+P2_MODE equ 1fc9h
+P2_PIN equ 1fcfh
+P2_REG equ 1fcdh
+
+P3_PIN equ 1ffeh
+P3_REG equ 1ffch
+
+P4_PIN equ 1fffh
+P4_REG equ 1ffdh
+
+P34_DRV equ 1ff4h ; Umschaltung Port 3/4 als open-drain oder push-pull
+
+P5_DIR equ 1ff3h
+P5_MODE equ 1ff1h
+P5_PIN equ 1ff7h
+P5_REG equ 1ff5h
+
+P6_DIR equ 1fd3h
+P6_MODE equ 1fd1h
+P6_PIN equ 1fd7h
+P6_REG equ 1fd5h
+
+EP_DIR equ 1fe3h
+EP_MODE equ 1fe1h
+EP_PIN equ 1fe7h
+EP_REG equ 1fe5h
+
+
+ case "80196"
+P0PIn equ 1fdah ; Daten Port 0
+
+P1SSel equ 1fd0h ; Spezialfunktionen auf Port 1 ?
+P1IO equ 1fd2h ; Port 1 Datenrichtungsregister
+P1Reg equ 1fd4h ; Port 1 Datenausgabe
+P1PIn equ 1fd6h ; Eingangszustand Port 1
+
+P2SSel equ 1fc9h ; Rest sinngemäß
+P2IO equ 1fcbh
+P2Reg equ 1fcdh
+P2PIn equ 1fcfh
+
+P3Reg equ 1ffch
+P3PIn equ 1ffeh
+
+P4Reg equ 1ffdh
+P4PIn equ 1fffh
+
+P5SSel equ 1ff1h
+P5IO equ 1ff3h
+P5Reg equ 1ff5h
+P5PIn equ 1ff7h
+
+P6SSel equ 1fd1h
+P6IO equ 1fd3h
+P6Reg equ 1fd5h
+P6PIn equ 1fd7h
+
+
+ case "8096"
+Port0 equ 0eh ; Port 0
+Port1 equ 0fh ; Port 1
+Port2 equ 10h ; Port 2
+Port3 equ 1ffeh ; Port 3 (falls kein ext. Speicher)
+Port4 equ 1fffh ; Port 4 (falls kein ext. Speicher)
+
+IOS0 equ 15h ; I/O-Statusregister 0
+IOS1 equ 16h ; I/O-Statusregister 1
+IOC0 equ 15h ; I/O-Statusregister 0
+IOC1 equ 16h ; I/O-Statusregister 1
+
+
+ endcase
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; Slave-Port
+
+ switch MOMCPUNAME
+
+
+ case "80296" ; Warnung unterdrücken
+
+
+ case "80196N"
+SLP_CMD equ 1ffah ; Kommandoregister
+SLP_CON equ 1ffbh
+SLP_STAT equ 1ff8h
+
+
+ case "80196" ; Warnung unterdrücken
+
+
+ case "8096"
+SlpStat equ 1ff8h ; Status Slave-Port
+SlpCmd equ 1ffah ; Kommandoregister Slave-Port
+SlpFunReg equ 1ffbh ; Slave-Port Steuerung
+
+
+ endcase
+
+;----------------------------------------------------------------------------
+; Vektoren/Sonderadressen
+
+ if MOMCPU>=80196h
+EPAIntX_Vec equ 2000h ; Kanal 4...9/0/1 EPA
+EPAInt3_Vec equ 2002h ; Kanal 3 EPA
+EPAInt2_Vec equ 2004h ; Kanal 2 EPA
+EPAInt1_Vec equ 2006h ; Kanal 1 EPA
+EPAInt0_Vec equ 2008h ; Kanal 0 EPA
+AD_Complete_Vec equ 200ah ; A/D-Wandlung abgeschlossen
+OBE_Slp_Vec equ 200ch ; Ausgabepuffer leer
+IBF_Slp_Vec equ 200eh ; Eingabepuffer voll
+Trap_Vec equ 2010h ; Software-Trap
+Ill_Opcode_Vec equ 2012h ; undefinierter Opcode
+CMD_Full_Vec equ 2030h ; Kommandopuffer voll
+SSIO0_Trans_Vec equ 2032h ; Transfer SSIO0 abgeschlossen
+SSIO1_Trans_Vec equ 2034h ; Transfer SSIO1 abgeschlossen
+SIO_TrInt_Vec equ 2036h ; SIO hat Zeichen versandt
+SIO_RcInt_Vec equ 2038h ; SIO hat Zeichen empfangen
+ExtInt_Vec equ 203ch ; externer Interrupt
+NMI_Vec equ 203eh ; nicht mask. Interrupt
+ elseif
+TOverInt_Vec equ 2000h ; Vektor Timerüberlauf
+ADInt_Vec equ 2002h ; Vektor A/D-Wandlung beendet
+HSIDataInt_Vec equ 2004h ; Vektor HSI-Daten verfügbar
+HSOInt_Vec equ 2006h ; Vektor HSO
+HSI0Int_Vec equ 2008h ; Vektor HSI.0
+TimeInt_Vec equ 200ah ; Vektor für Timer
+SerialInt_Vec equ 200ch ; Vektor serieller Interrupt
+ExtInt_Vec equ 200eh ; Vektor externer Interrupt
+SoftInt_Vec equ 2010h ; TRAP Interruptvektor
+Self_Jump equ 201ah ; Endlosschleife
+ endif
+
+;----------------------------------------------------------------------------
+; Speicherbereiche, Spezialregister
+
+ switch MOMCPUNAME
+
+
+ case "80296"
+IRAM equ 1ah ; Beginn internes RAM
+IRAMEND equ 1ffh ; Ende internes RAM
+CODERAM equ 0f800h ; Beginn Code-RAM
+CODERAMEND equ 0ffffh ; Ende Code-RAM
+EXTMEM1 equ 400h ; Beginn externer Speicher Bereich 1
+EXTMEM1END equ 1bffh ; Ende externer Speicher Bereich 1
+EXTMEM2 equ 02000h ; Beginn externer Speicher Bereich 2
+EXTMEM2END equ 0f7ffh ; Ende externer Speicher Bereich 2
+EXTMEM3 equ 0ff0400h ; Beginn externer Speicher Bereich 3
+EXTMEM3END equ 0fff7ffh ; Ende externer Speicher Bereich 3
+CCB0 equ 0ff2018h ; Chip-Konfiguration
+CCB1 equ 0ff201ah ; erw. Chip-Konfiguration
+Reset_Location equ 0ff2080h ; Startadresse nach Reset
+
+
+ case "80196N"
+IRAM equ 1ah ; Beginn internes RAM
+IRAMEND equ 3ffh ; Ende internes RAM
+IROM equ 0ff2000h ; Beginn internes Programm-ROM
+IROMEND equ 0ff9fffh ; Ende internes Programm-ROM
+EXTMEM1 equ 600h ; Beginn externer Speicher Bereich 1
+EXTMEM1END equ 1effh ; Ende externer Speicher Bereich 1
+EXTMEM2 equ 0a000h ; Beginn externer Speicher Bereich 2
+EXTMEM2END equ 0ffffh ; Ende externer Speicher Bereich 2
+EXTMEM3 equ 0ff0100h ; Beginn externer Speicher Bereich 3
+EXTMEM3END equ 0ff03ffh ; Ende externer Speicher Bereich 3
+EXTMEM4 equ 0ff0600h ; Beginn externer Speicher Bereich 4
+EXTMEM4END equ 0ff1fffh ; Ende externer Speicher Bereich 4
+EXTMEM5 equ 0ffa000h ; Beginn externer Speicher Bereich 5
+EXTMEM5END equ 0ffffffh ; Ende externer Speicher Bereich 5
+CCB0 equ 0ff2018h ; Chip-Konfiguration
+CCB1 equ 0ff201ah ; erw. Chip-Konfiguration
+CCB2 equ 0ff201ch
+Security_Key equ 0ff2020h ; Schlüssel
+Reset_Location equ 0ff2080h ; Startadresse nach Reset
+USFR equ 1ff6h ; ???
+IRAM_CON equ 1fe0h ; Konfiguration Code-RAM
+
+
+ case "80196"
+IRAM equ 1ah ; Beginn internes RAM
+IRAMEND equ 1ffh ; Ende internes RAM
+PDRAM equ IRAM ; Beginn Power-Down-RAM
+PDRAMEND equ 1ffh ; Ende Power-Down-RAM
+CODERAM equ 400h ; Beginn Code-RAM (KEIN Windowing!)
+CODERAMEND equ 4ffh ; Ende Code-RAM
+IROM equ 2000h ; Beginn internes Programm-ROM
+IROMEND equ 3fffh ; Ende internes Programm-ROM
+EXTMEM1 equ 500h ; Beginn externer Speicher Bereich 1
+EXTMEM1END equ 1effh ; Ende externer Speicher Bereich 1
+EXTMEM2 equ 4000h ; Beginn externer Speicher Bereich 2
+EXTMEM2END equ 0ffffh ; Ende externer Speicher Bereich 2
+CCB equ 2018h ; Chip-Konfiguration
+CCB1 equ 201ah ; erw. Chip-Konfiguration
+Security_Key equ 2020h ; Schlüssel
+Reset_Location equ 2080h ; Startadresse nach Reset
+USFR equ 1ff6h ; ???
+
+
+ case "8096"
+IRAM equ 1ah ; Beginn internes RAM
+IRAMEND equ 0ffh ; Ende internes RAM
+PDRAM equ 0f0h ; Beginn Power-Down-RAM
+PDRAMEND equ 0ffh ; Ende Power-Down-RAM
+IROM equ 2000h ; Beginn internes Programm-ROM
+IROMEND equ 3fffh ; Ende internes Programm-ROM
+EXTMEM1 equ 100h ; Beginn externer Speicher Bereich 1
+EXTMEM1END equ 1effh ; Ende externer Speicher Bereich 1
+EXTMEM2 equ 4000h ; Beginn externer Speicher Bereich 2
+EXTMEM2END equ 0ffffh ; Ende externer Speicher Bereich 2
+CCB equ 2018h ; Chip-Konfiguration
+Security_Key equ 2020h ; Schlüssel
+Reset_Location equ 2080h ; Startadresse nach Reset
+
+
+ endcase
+
+Security_Key_End equ Security_Key+15
+
+;--------------------------------------------------------------------------
+; lange Sprünge
+
+__DefLongJmp macro new,old
+new macro Adr,{NoExpand}
+ old Skip
+ ljmp Adr
+Skip:
+ endm
+ endm
+
+ __DefLongJmp bc,jnc
+ __DefLongJmp be,jne
+ __DefLongJmp bge,jlt
+ __DefLongJmp bgt,jle
+ __DefLongJmp bh,jnh
+ __DefLongJmp ble,jgt
+ __DefLongJmp blt,jge
+ __DefLongJmp bnc,jc
+ __DefLongJmp bne,je
+ __DefLongJmp bnh,jh
+ __DefLongJmp bnst,jst
+ __DefLongJmp bnv,jv
+ __DefLongJmp bnvt,jvt
+ __DefLongJmp bst,jnst
+ __DefLongJmp bv,jnv
+ __DefLongJmp bvt,jnvt
+
+;--------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/regavr.inc b/include/regavr.inc
new file mode 100644
index 0000000..2414557
--- /dev/null
+++ b/include/regavr.inc
@@ -0,0 +1,329 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REGAVR.INC *
+;* *
+;* Sinn : enthält SFR- und Bitdefinitionen für die AVR-Prozessoren *
+;* *
+;* letzte Änderungen : 6. 7.1996 *
+;* letzte Änderungen : 8. 6.1997 Anpassung an die endgültigen Versionen *
+;* *
+;****************************************************************************
+
+ ifndef regavrinc ; verhindert Mehrfacheinbindung
+
+regavrinc equ 1
+
+ if (MOMCPUNAME<>"AT90S1200")&&(MOMCPUNAME<>"AT90S2313")&&(MOMCPUNAME<>"AT90S4414")&&(MOMCPUNAME<>"AT90S8515")
+ fatal "Falscher Prozessortyp eingestellt: nur AT90S1200, AT90S2313, AT90S4414 oder AT90S8515 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "Atmel-AVR-SFR-Definitionen (C) 1996 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; Prozessorkern
+
+sreg port $3f ; Statusregister:
+c equ 0 ; Carry
+z equ 1 ; Ergebnis Null
+n equ 2 ; Ergebnis negativ
+v equ 3 ; Zweierkomplement-Überlauf
+s equ 4 ; Vorzeichen
+h equ 5 ; Halfcarry
+t equ 6 ; Bitspeicher
+i equ 7 ; globale Interruptsperre
+
+ if MOMCPU>=$902313
+spl equ $3d ; Stapelzeiger (MSB)
+ if MOMCPU>=$904414
+sph equ $3e ; (LSB)
+ endif
+ endif
+
+;----------------------------------------------------------------------------
+; Chip-Konfiguration
+
+mcucr port $35 ; CPU-Steuerung:
+isc00 equ 0 ; Flankenwahl INT0
+isc01 equ 1 ; Flanken/Pegeltriggerung INT0
+ if MOMCPU>=$902313
+isc10 equ 2 ; Flankenwahl INT1
+isc11 equ 3 ; Flanken/Pegeltriggerung INT1
+ endif
+sm equ 4 ; Idle/Powerdown-Modus wählen
+se equ 5 ; Sleep-Modus freigeben
+ if MOMCPU>=$904414
+srw equ 6 ; Wait-State-Wahl externes SRAM
+sre equ 7 ; Freigabe externes SRAM
+ endif
+
+;----------------------------------------------------------------------------
+; Interrupt-Steuerung
+
+gimsk port $3b ; generelle Interrupt-Maske:
+int0 equ 6 ; externer Interrupt 0
+ if MOMCPU>=$902313
+int1 equ 7 ; externer Interrupt 1
+ endif
+
+ if MOMCPU>=$902313
+gifr port $3a ; generelle Interrupt-Flags:
+intf0 equ 6 ; externer Interrupt 0
+intf1 equ 7 ; externer Interrupt 1
+ endif
+
+timsk port $39 ; Timer-Interrupt-Maske:
+toie0 equ 1 ; Überlauf Timer 0
+ if MOMCPU>=$902313
+ if MOMCPU>=$904414
+ocie1b equ 5 ; Vergleich B Timer 1
+ endif
+ocie1a equ 6 ; Vergleich Timer 1
+toie1 equ 7 ; Überlauf Timer 1
+ticie1 equ 3 ; Fang Timer 1
+ endif
+
+tifr port $38 ; Timer-Interrupt-Flags:
+tov0 equ 1 ; Überlauf Timer 0
+ if MOMCPU>=$902313
+ if MOMCPU>=$904414
+ocf1b equ 5 ; Vergleich B Timer 1
+ endif
+ocf1a equ 6 ; Vergleich A Timer 1
+tov1 equ 7 ; Überlauf Timer 1
+icf1 equ 3 ; Fang Timer 1
+ endif
+
+;----------------------------------------------------------------------------
+; parallele Ports
+
+ if MOMCPU>=$904414
+porta port $1b ; Datenregister Port A
+ddra port $1a ; Datenrichtungsregister Port A
+pina port $19 ; Leseregister Port A
+ endif
+
+portb port $18 ; Datenregister Port B
+ddrb port $17 ; Datenrichtungsregister Port B
+pinb port $16 ; Leseregister Port B
+
+ if MOMCPU>=$904414
+portc port $15 ; Datenregister Port C
+ddrc port $14 ; Datenrichtungsregister Port C
+pinc port $13 ; Leseregister Port C
+ endif
+
+portd port $12 ; Datenregister Port D
+ddrd port $11 ; Datenrichtungsregister Port D
+pind port $10 ; Leseregister Port D
+
+;----------------------------------------------------------------------------
+; Timer
+
+tccr0 port $33 ; Steuerregister Timer 0:
+cs00 equ 0 ; Vorteilereinstellung
+cs01 equ 1
+cs02 equ 2
+
+tcnt0 port $32 ; Zählregister Timer 0
+
+ if MOMCPU>=$902313
+tccr1a port $2f ; Steuerregister A Timer 1:
+pwm10 equ 0 ; Modus Pulsweitenmodulator
+pwm11 equ 1
+com1a0 equ 6 ; Vergleichsmodus A
+com1a1 equ 7
+ if MOMCPU>=$904414
+com1b0 equ 4 ; Vergleichsmodus B
+com1b1 equ 5
+ endif
+
+tccr1b port $2e ; Steuerregister B Timer 1:
+cs10 equ 0 ; Vorteilereinstellung
+cs11 equ 1
+cs12 equ 2
+ctc1 equ 3 ; nach Gleichheit zurücksetzen ?
+ices1 equ 6 ; Flankenwahl Fang
+icnc1 equ 7 ; Rauschfilter für Fangfunktion
+
+tcnt1l port $2c ; Zählregister Timer 1 (LSB)
+tcnt1h port $2d ; (MSB)
+
+ if MOMCPU>=$904414
+ocr1al port $2a ; Vergleichsregister A Timer 1 (LSB)
+ocr1ah port $2b ; (MSB)
+ocr1bl port $28 ; Vergleichsregister B Timer 1 (LSB)
+ocr1bh port $29 ; (MSB)
+ elseif
+ocr1l port $2a ; Vergleichsregister Timer 1 (LSB)
+ocr1h port $2b ; (MSB)
+ endif
+
+icr1l port $24 ; Fangwert Timer 1 (LSB)
+icr1h port $25 ; (MSB)
+ endif
+
+;----------------------------------------------------------------------------
+; Watchdog
+
+wdtcr port $21 ; Watchdog-Steuerregister:
+wdp0 equ 0 ; Vorteiler
+wdp1 equ 1
+wdp2 equ 2
+wde equ 3 ; Freigabe
+ if MomCPU>=$902313
+wdttoe equ 4 ; zur Sperre gebraucht
+ endif
+
+;----------------------------------------------------------------------------
+; serielle Ports
+
+ if MOMCPU>=$902312
+udr port $0c ; Datenregister UART
+
+usr port $0b ; Statusregister UART:
+or equ 3 ; Empfängerüberlauf
+fe equ 4 ; Framing-Fehler
+udre equ 5 ; Datenregister wieder frei
+txc equ 6 ; Sendung komplett
+rxc equ 7 ; Empfang komplett
+
+ucr port $0a ; Steuerregister UART:
+txb8 equ 0 ; Sendebit 8
+rxb8 equ 1 ; Empfangsbit 8
+chr9 equ 2 ; auf 9-Bit-Datenwerte umschalten
+txen equ 3 ; Sender freigeben
+rxen equ 4 ; Empfänger freigeben
+udrie equ 5 ; Interrupts bei freiem Datenregister freigeben
+txcie equ 6 ; Interrupts nach Versand freigeben
+rxcie equ 7 ; Interrupts nach Empfang freigeben
+
+ubrr port $09 ; Baudratengenerator
+ endif
+
+ if MOMCPU>=$904414
+spcr port $0d ; SPI Steuerregister:
+spr0 equ 0 ; Wahl Taktfrequenz
+spr1 equ 1
+cpha equ 2 ; Taktphase
+cpol equ 3 ; Taktpolarität
+mstr equ 4 ; Master/Slave-Wahl
+dord equ 5 ; Bitreihenfolge
+spe equ 6 ; SPI freigeben
+spie equ 7 ; Interruptfreigabe SPI
+
+spsr port $0e ; SPI Statusregister:
+wcol equ 6 ; Schreibkollision ?
+spif equ 7 ; SPI-Interrupt aufgetreten ?
+
+spdr port $0f ; SPI Datenregister
+ endif
+
+;----------------------------------------------------------------------------
+; Analogkomparator
+
+acsr port $08 ; Komparator-Steuer/Statusregister:
+acis0 equ 0 ; Interrupt-Modus
+acis1 equ 1
+ if MomCPU>=$902313
+acic equ 2 ; Komparator als Fangsignal für Timer 1 benutzen
+ endif
+acie equ 3 ; Interrupt freigeben
+aci equ 4 ; Interrupt aufgetreten ?
+aco equ 5 ; Komparatorausgang
+acd equ 7 ; Strom abschalten
+
+;----------------------------------------------------------------------------
+; EEPROM
+
+ if MomCPU>=$908515
+eearl port $1e ; Adreßregister
+eearh port $1f
+ elseif
+eear port $1e
+ endif
+
+eedr port $1d ; Datenregister
+
+eecr port $1c ; Steuerregister:
+eere equ 0 ; Lesefreigabe
+eewe equ 1 ; Schreibfreigabe
+ if MomCPU>=$902313
+eemwe equ 2
+ endif
+
+;----------------------------------------------------------------------------
+; Vektoren
+; Leider verschieben sich Vektoren bei den höheren Prozessoren.
+; Warum nur, Atmel, warum ?
+
+vec_reset label 0 ; Reset-Einsprung
+vec_int0 label 1 ; Einsprung ext. Interrupt 0
+ switch MOMCPUNAME
+ case "AT90S1200"
+vec_tm0ovf label 2 ; Einsprung Überlauf Timer 0
+vec_anacomp label 3 ; Einsprung Analog-Komparator
+ case "AT90S2313"
+vec_int1 label 2 ; Einsprung ext. Interrupt 2
+vec_tm1capt label 3 ; Einsprung Fang Timer 1
+vec_tm1comp label 4 ; Einsprung Vergleich Timer 1
+vec_tm1ovf label 5 ; Einsprung Überlauf Timer 1
+vec_tm0ovf label 6 ; Einsprung Überlauf Timer 0
+vec_uartrx label 7 ; Einsprung UART Empfang komplett
+vec_uartudre label 8 ; Einsprung UART Datenregister leer
+vec_uarttx label 9 ; Einsprung UART Sendung komplett
+vec_anacomp label 10 ; Einsprung Analog-Komparator
+ case "AT90S4414","AT90S8515"
+vec_int1 label 2 ; Einsprung ext. Interrupt 2
+vec_tm1capt label 3 ; Einsprung Fang Timer 1
+vec_tm1compa label 4 ; Einsprung Vergleich A Timer 1
+vec_tm1compb label 5 ; Einsprung Vergleich A Timer 1
+vec_tm1ovf label 6 ; Einsprung Überlauf Timer 1
+vec_tm0ovf label 7 ; Einsprung Überlauf Timer 0
+vec_spi label 8 ; Einsprung SPI-Interrupt
+vec_uartrx label 9 ; Einsprung UART Empfang komplett
+vec_uartudre label 10 ; Einsprung UART Datenregister leer
+vec_uarttx label 11 ; Einsprung UART Sendung komplett
+vec_anacomp label 12 ; Einsprung Analog-Komparator
+ endcase
+
+;----------------------------------------------------------------------------
+; Speicheradressen
+
+eestart equ 0 ; Startadresse internes EEPROM
+iram equ 96,data ; Startadresse internes SRAM
+ ; (hinter gemapptem I/O)
+irom label 0 ; Startadresse internes EPROM
+
+ switch MOMCPUNAME
+ case "AT90S1200"
+eeend equ 63 ; Endadresse EEPROM
+iramend equ 95,data ; Endadresse SRAM
+iromend label 1023 ; Endadresse EPROM
+ case "AT90S2313"
+eeend equ 127
+iramend equ $df,data
+iromend label 2047
+ case "AT90S4414"
+eeend equ 255
+iramend equ $15f,data
+iromend label 4095
+ case "AT90S8515"
+eeend equ 511
+iramend equ $25f,data
+iromend label 8191
+ endcase
+
+;----------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
+
+
diff --git a/include/regcop8.inc b/include/regcop8.inc
new file mode 100644
index 0000000..cbf8292
--- /dev/null
+++ b/include/regcop8.inc
@@ -0,0 +1,242 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REGCOP8.INC *
+;* *
+;* Sinn : enthält Registerdefinitionen für die COP8-Familie *
+;* *
+;* letzte Änderungen : 2. 9.1996 *
+;* 8. 2.1997 MOmPass=1... *
+;* *
+;****************************************************************************
+
+ ifndef regcop8inc ; verhindert Mehrfacheinbindung
+
+regcop8inc equ 1
+
+ if MOMPASS=1
+ switch MOMCPUNAME
+ case "COP87L84"
+ message "including COP87L84-registers"
+ elsecase
+ fatal "invalid processor type: only COP87L84 allowed!"
+ endcase
+ endif
+
+;----------------------------------------------------------------------------
+; Prozessorkern
+
+__REG set 0
+ rept 10
+R{"\{__REG}"} equ __REG+0xf0
+__REG set __REG+1,data
+ endm
+ rept 6
+R1{"\{__REG-10}"} equ __REG+0xf0
+__REG set __REG+1,data
+ endm
+
+psw sfr 0xef ; Flags
+gie equ 0 ; globale Interruptfreigabe
+exen equ 1 ; externe Interruptfreigabe
+busy equ 2 ; Microwire busy ?
+expnd equ 3 ; externer Interrupt angefordert ?
+t1ena equ 4 ; Timer 1 Interruptfreigabe
+t1pnda equ 5 ; Timer 1 Interrupt angefordert ?
+c equ 6 ; Carry
+hc equ 7 ; Halfcarry
+x sfr 0xfc ; X-Register
+sp sfr 0xfd ; Stackpointer
+b sfr 0xfe ; B-Register
+
+;----------------------------------------------------------------------------
+; Peripherie-Steuerregister
+
+cntrl sfr 0xee ; globale Steuerung
+sl0 equ 0 ; Taktteiler Microwire
+sl1 equ 1
+iedg equ 2 ; Flankenwahl externer Interrupt
+msel equ 3 ; G4/G5 für Microwire benutzen
+t1c0 equ 4 ; Timer 1 Interrupt/Start-Stop
+t1c1 equ 5 ; Moduswahl Timer 1
+t1c2 equ 6
+t1c3 equ 7
+
+icntrl sfr 0xe8 ; Fortsetzung...
+t1enb equ 0 ; Freigabe Fang-Interrupt Timer 1
+t1pndb equ 1 ; Fang-Interrupt Timer 1 aufgetreten ?
+uwen equ 2 ; Freigabe MicroWire-Interrupt
+uwpnd equ 3 ; MicroWire-Interrupt aufgetreten ?
+t0en equ 4 ; Freigabe Interrupt Timer 0
+t0pndb equ 5 ; Timer 0-Interrupt aufgetreten ?
+lpen equ 6 ; Freigabe Port L-Interrupt
+
+;----------------------------------------------------------------------------
+; Timer
+
+t1rblo sfr 0xe6 ; Autoload-Wert B Timer 1
+t1rbhi sfr 0xe7
+
+tmr1lo sfr 0xea ; Zählwert Timer 0
+tmr1hi sfr 0xeb
+
+t1ralo sfr 0xec ; Autoload-Wert A Timer 1
+t1rahi sfr 0xed
+
+;----------------------------------------------------------------------------
+; PWM
+
+pscal sfr 0xa0 ; Vorteiler PWM
+
+rlon sfr 0xa1 ; On-Anteil PWM
+
+pwmcon sfr 0xa2 ; Steuerregister PWM
+pwen0 equ 0 ; PWM0 auf I/O-Port geben
+pwen1 equ 1 ; PWM1 auf I/O-Port geben
+pwon equ 2 ; PWM starten/stoppen
+pwmd equ 3 ; PWM-Modus
+pwie equ 4 ; Interrupt-Freigabe PWM
+pwpnd equ 5 ; Interrupt PWM aufgetreten ?
+esel equ 6 ; Flankenwahl PWM
+
+;----------------------------------------------------------------------------
+; MicroWire-Interface
+
+wkedg sfr 0xc8
+wken sfr 0xc9
+wkpnd sfr 0xca
+
+sior sfr 0xe9 ; Schieberegister
+
+;----------------------------------------------------------------------------
+; CAN Interface
+
+txd1 sfr 0xb0 ; Sendedaten (Byte 1,3,5,7,...)
+txd2 sfr 0xb1 ; Sendedaten (Byte 2,4,6,8,...)
+
+tdlc sfr 0xb2 ; Sendelängen-/Identifier(L)-Register
+tdlc0 equ 0 ; Sendelänge
+tdlc1 equ 1
+tdlc2 equ 2
+tdlc3 equ 3
+tid0 equ 4 ; Sendeidentifikation (Bit 0..3)
+tid1 equ 5
+tid2 equ 6
+tid3 equ 7
+
+tid sfr 0xb3 ; Sendeidentifikationsregister
+tid4 equ 0 ; Sendeidentifikation (Bit 4..10)
+tid5 equ 1
+tid6 equ 2
+tid7 equ 3
+tid8 equ 4
+tid9 equ 5
+tid10 equ 6
+trtr equ 7 ; Senderahmen remote ?
+
+rxd1 sfr 0xb4 ; Empfangsdaten (Byte 1,3,5,7,...)
+rxd2 sfr 0xb5 ; Empfangsdaten (Byte 2,4,6,8,...)
+
+ridl sfr 0xb6 ; Empfangslängen/Identifier(L)-Register
+rdlc0 equ 0 ; Empfangslänge
+rdlc1 equ 1
+rdlc2 equ 2
+rdlc3 equ 3
+rid0 equ 4 ; Empfangsidentifikation (Bit 0..3)
+rid1 equ 5
+rid2 equ 6
+rid3 equ 7
+
+rid sfr 0xb7 ; Empfangsidentifikationsregister
+rid4 equ 0 ; Empfangsidentifikation (Bit 4..10)
+rid5 equ 1
+rid6 equ 2
+rid7 equ 3
+rid8 equ 4
+rid9 equ 5
+rid10 equ 6
+
+cscal sfr 0xb8 ; Vorteiler CAN-Takt
+
+ctim sfr 0xb9 ; CAN-Bus-Timing-Register
+ps0 equ 2 ; Phase Segment
+ps1 equ 3
+ps2 equ 4
+pps0 equ 5 ; Propagation Segment
+pps1 equ 6
+pps2 equ 7
+
+cbus sfr 0xba ; CAN-Bus-Timing-Register
+fmod equ 1 ; Fault Confinement Mode
+rxred0 equ 2 ; Referenzspannung an Rx0 anlegen
+rxref1 equ 3 ; Referenzspannung an Tx0 anlegen
+txen0 equ 4 ; TxD Ausgangstreiber freigeben
+txen1 equ 5
+riaf equ 6 ; Empfangsfilter freigeben
+
+tcntl sfr 0xbb ; CAN-Bus-Steuer/Statusregister
+txss equ 0 ; Sender starten/stoppen
+rie equ 1 ; Freigabe Empfangs-Interrupt
+tie equ 2 ; Freigabe Sende-Interrupt
+ceie equ 3 ; Freigabe CAN-Interrupt
+rerr equ 4 ; Empfangsfehler
+terr equ 5 ; Sendefehler
+ns0 equ 6 ; Knoten-Status
+ns1 equ 7
+
+rtstat sfr 0xbc ; CAN-Bus-Sender/Empfängerstatus
+rbf equ 0 ; Empfangspuffer voll ?
+rcv equ 1 ; Empfang läuft ?
+rfv equ 2 ; empfangener Rahmen gültig ?
+rorn equ 3 ; Empfängerüberlauf ?
+rold equ 4 ; Empfängerrahmenüberlauf ?
+rrtr equ 5 ; Remote-Bit in empfangenem Rahmen gesetzt ?
+txpnd equ 6 ; Sendung läuft ?
+tbe equ 7 ; Sendepuffer leer ?
+
+tec sfr 0xbd ; Sendefehlerzähler
+rec sfr 0xbe ; Empfangsfehlerzähler
+
+;----------------------------------------------------------------------------
+; Komparatoren
+
+cmpsl sfr 0xd3 ; Steuerregister Komparatoren
+cmp1en equ 1 ; Komparator 1 aktivieren
+cmp1rd equ 2 ; Ausgangswert Komparator 1
+cmp1oe equ 3 ; Ausgang Komparator 1 herausgeben
+cmp2en equ 4 ; Komparator 2 aktivieren
+cmp2rd equ 5 ; Ausgangswert Komparator 2
+cmp2oe equ 6 ; Ausgang Komparator 2 herausgeben
+cmp2sel equ 7 ; Ausgabe Komparator 2 auf L3/L5
+
+;----------------------------------------------------------------------------
+; Ports
+
+portld sfr 0xd0 ; Ausgaberegister Port L
+portlc sfr 0xd1 ; Konfigurationsregister Port L
+portlp sfr 0xd2 ; Leseregister Port L
+
+portgd sfr 0xd4 ; Ausgaberegister Port G
+portgc sfr 0xd5 ; Konfigurationsregister Port G
+portgp sfr 0xd6 ; Leseregister Port G
+
+portd sfr 0xdc ; Ausgaberegister Port D
+
+;----------------------------------------------------------------------------
+; Vektoradressen
+
+;----------------------------------------------------------------------------
+; Speicheradressen
+
+iram sfr 0x00 ; Bereich internes RAM
+iramend sfr 0x2f
+
+;----------------------------------------------------------------------------
+
+ endif
+
+ restore ; Listing wieder an
+
+
diff --git a/include/reghc12.inc b/include/reghc12.inc
new file mode 100644
index 0000000..1a35ad8
--- /dev/null
+++ b/include/reghc12.inc
@@ -0,0 +1,228 @@
+ save
+ listing off
+
+;*****************************************************************************
+; REGHC12.INC
+; Register Definitions for HC812A4 & HC912B32
+; Source: MC68HC812A4, MC68HC912B32 Technical Summary (Motorola 1996)
+; 27.01.1997
+; Oliver Thamm (othamm@aol.com)
+;*****************************************************************************
+
+ ifndef reghc12inc ; verhindert Mehrfacheinbindung
+
+reghc12inc equ 1
+
+ if (MOMCPUNAME<>"68HC12")
+ fatal "Falscher Prozessortyp eingestellt: nur 68HC12 erlaubt!"
+ endif
+
+ if MOMPASS=1
+ message "68HC812A4/68HC912B32-Registerdefinitionen"
+ message "(C) 1996,1997 Oliver Thamm"
+ endif
+
+;-----------------------------------------------------------------------------
+
+REGBASE equ $0000 ; Below: [A=HC812A4|B=HC912B32]
+
+PORTA equ REGBASE+$0000 ; [A|B] Port A Register
+PORTB equ REGBASE+$0001 ; [A|B] Port B Register
+DDRA equ REGBASE+$0002 ; [A|B] Port A Data Direction Register
+DDRB equ REGBASE+$0003 ; [A|B] Port B Data Direction Register
+PORTC equ REGBASE+$0004 ; [A|-] Port C Register
+PORTD equ REGBASE+$0005 ; [A|-] Port D Register
+DDRC equ REGBASE+$0006 ; [A|-] Port C Data Direction Register
+DDRD equ REGBASE+$0007 ; [A|-] Port D Data Direction Register
+PORTE equ REGBASE+$0008 ; [A|B] Port E Register
+DDRE equ REGBASE+$0009 ; [A|B] Port E Data Direction Register
+PEAR equ REGBASE+$000a ; [A|B] Port E Assignment Register
+MODE equ REGBASE+$000b ; [A|B] Mode Register
+PUCR equ REGBASE+$000c ; [A|B] Pull Up Control Register
+RDRIV equ REGBASE+$000d ; [A|B] Reduced Drive of I/O Lines
+
+INITRM equ REGBASE+$0010 ; [A|B] Initialization of Internal RAM Position Register
+INITRG equ REGBASE+$0011 ; [A|B] Initialization of Internal Register Position Register
+INITEE equ REGBASE+$0012 ; [A|B] Initialization of Internal EEPROM Position Register
+MISC equ REGBASE+$0013 ; [A|B] Miscellaneous Mapping Register
+RTICTL equ REGBASE+$0014 ; [A|B] Real-Time Interrupt Control Register
+RTIFLG equ REGBASE+$0015 ; [A|B] Real-Time Interrupt Flag Register
+COPCTL equ REGBASE+$0016 ; [A|B] COP Control Register
+COPRST equ REGBASE+$0017 ; [A|B] Arm/Reset COP Timer Register
+ITST0 equ REGBASE+$0018 ; [A|B] Reserved
+ITST1 equ REGBASE+$0019 ; [A|B] Reserved
+ITST2 equ REGBASE+$001a ; [A|B] Reserved
+ITST3 equ REGBASE+$001b ; [A|B] Reserved
+
+INTCR equ REGBASE+$001e ; [A|B] Interrupt Control Register
+HPRIO equ REGBASE+$001f ; [A|B] Highest Priority I Interrupt
+KWIED equ REGBASE+$0020 ; [A|-] Key Wakeup Port D Interrupt Enable Register
+BRKCT0 equ REGBASE+$0020 ; [-|B] Breakpoint Control Register 0
+KWIFD equ REGBASE+$0021 ; [A|-] Key Wakeup Port D Flag Register
+BRKCT1 equ REGBASE+$0021 ; [-|B] Breakpoint Control Register 1
+BRKAH equ REGBASE+$0022 ; [-|B] Breakpoint Address Register (High Byte)
+BRKAL equ REGBASE+$0023 ; [-|B] Breakpoint Address Register (Low Byte)
+PORTH equ REGBASE+$0024 ; [A|-] Port H Register
+BRKDH equ REGBASE+$0024 ; [-|B] Breakpoint Data Register (High Byte)
+DDRH equ REGBASE+$0025 ; [A|-] Port H Data Direction Register
+BRKDL equ REGBASE+$0025 ; [-|B] Breakpoint Data Register (Low Byte)
+KWIEH equ REGBASE+$0026 ; [A|-] Key Wakeup Port H Interrupt Enable Register
+KWIFH equ REGBASE+$0027 ; [A|-] Key Wakeup Port H Flag Register
+PORTJ equ REGBASE+$0028 ; [A|-] Port J Register
+DDRJ equ REGBASE+$0029 ; [A|-] Port J Data Direction Register
+KWIEJ equ REGBASE+$002a ; [A|-] Key Wakeup Port J Interrupt Enable Register
+KWIFJ equ REGBASE+$002b ; [A|-] Key Wakeup Port J Flag Register
+KPOLJ equ REGBASE+$002c ; [A|-] Key Wakeup Port J Polarity Register
+PUPSJ equ REGBASE+$002d ; [A|-] Key Wakeup Port J Pull-Up/Pulldown Select Register
+PULEJ equ REGBASE+$002e ; [A|-] Key Wakeup Port J Pull-Up/Pulldown Enable Register
+
+PORTF equ REGBASE+$0030 ; [A|-] Port F Register
+PORTG equ REGBASE+$0031 ; [A|-] Port G Register
+DDRF equ REGBASE+$0032 ; [A|-] Port F Data Direction Register
+DDRG equ REGBASE+$0033 ; [A|-] Port G Data Direction Register
+DPAGE equ REGBASE+$0034 ; [A|-] Data Page Register
+PPAGE equ REGBASE+$0035 ; [A|-] Program Page Register
+EPAGE equ REGBASE+$0036 ; [A|-] Extra Page Register
+WINDEF equ REGBASE+$0037 ; [A|-] Window Definition Register
+MXAR equ REGBASE+$0038 ; [A|-] Memory Expansion Assignment Register
+
+CSCTL0 equ REGBASE+$003c ; [A|-] Chip Select Control Register 0
+CSCTL1 equ REGBASE+$003d ; [A|-] Chip Select Control Register 1
+CSSTR0 equ REGBASE+$003e ; [A|-] Chip Select Stretch Register 0
+CSSTR1 equ REGBASE+$003f ; [A|-] Chip Select Stretch Register 1
+LDV equ REGBASE+$0040 ; [A|-] Loop Divider Registers (Word)
+PWCLK equ REGBASE+$0040 ; [-|B] PWM Clocks and Concatenate
+PWPOL equ REGBASE+$0041 ; [-|B] PWM Clock Select and Polarity
+RDV equ REGBASE+$0042 ; [A|-] Reference Divider Register (Word)
+PWEN equ REGBASE+$0042 ; [-|B] PWM Enable
+PWPRES equ REGBASE+$0043 ; [-|B] PWM Prescale Counter
+PWSCAL0 equ REGBASE+$0044 ; [-|B] PWM Scale Register 0
+PWSCNT0 equ REGBASE+$0045 ; [-|B] PWM Scale Counter 0 Value
+PWSCAL1 equ REGBASE+$0046 ; [-|B] PWM Scale Register 1
+CLKCTL equ REGBASE+$0047 ; [A|-] Clock Control Register
+PWSCNT1 equ REGBASE+$0047 ; [-|B] PWM Scale Counter 1 Value
+PWCNT0 equ REGBASE+$0048 ; [-|B] PWM Channel 0 Counter
+PWCNT1 equ REGBASE+$0049 ; [-|B] PWM Channel 1 Counter
+PWCNT2 equ REGBASE+$004a ; [-|B] PWM Channel 2 Counter
+PWCNT3 equ REGBASE+$004b ; [-|B] PWM Channel 3 Counter
+PWPER0 equ REGBASE+$004c ; [-|B] PWM Channel 0 Period Register
+PWPER1 equ REGBASE+$004d ; [-|B] PWM Channel 1 Period Register
+PWPER2 equ REGBASE+$004e ; [-|B] PWM Channel 2 Period Register
+PWPER3 equ REGBASE+$004f ; [-|B] PWM Channel 3 Period Register
+PWDTY0 equ REGBASE+$0050 ; [-|B] PWM Channel 0 Duty Register
+PWDTY1 equ REGBASE+$0051 ; [-|B] PWM Channel 1 Duty Register
+PWDTY2 equ REGBASE+$0052 ; [-|B] PWM Channel 2 Duty Register
+PWDTY3 equ REGBASE+$0053 ; [-|B] PWM Channel 3 Duty Register
+PWCTL equ REGBASE+$0054 ; [-|B] PWM Control Register
+PWTST equ REGBASE+$0055 ; [-|B] PWM Special Mode Register
+PORTP equ REGBASE+$0056 ; [-|B] Port P Data Register
+DDRP equ REGBASE+$0057 ; [-|B] Port P Data Direction Register
+
+ATDCTL0 equ REGBASE+$0060 ; [A|B] Reserved
+ATDCTL1 equ REGBASE+$0061 ; [A|B] Reserved
+ATDCTL2 equ REGBASE+$0062 ; [A|B] ATD Control Register 2
+ATDCTL3 equ REGBASE+$0063 ; [A|B] ATD Control Register 3
+ATDCTL4 equ REGBASE+$0064 ; [A|B] ATD Control Register 4
+ATDCTL5 equ REGBASE+$0065 ; [A|B] ATD Control Register 5
+ATDSTAT equ REGBASE+$0066 ; [A|B] ATD Status Register (Word)
+ATDTEST equ REGBASE+$0068 ; [A|B] ATD Test Register (Word)
+
+PORTAD equ REGBASE+$006f ; [A|B] Port AD Data Input Register
+
+ADR0H equ REGBASE+$0070 ; [A|B] A/D Converter Result Register 0
+
+ADR1H equ REGBASE+$0072 ; [A|B] A/D Converter Result Register 1
+
+ADR2H equ REGBASE+$0074 ; [A|B] A/D Converter Result Register 2
+
+ADR3H equ REGBASE+$0076 ; [A|B] A/D Converter Result Register 3
+
+ADR4H equ REGBASE+$0078 ; [A|B] A/D Converter Result Register 4
+
+ADR5H equ REGBASE+$007a ; [A|B] A/D Converter Result Register 5
+
+ADR6H equ REGBASE+$007c ; [A|B] A/D Converter Result Register 6
+
+ADR7H equ REGBASE+$007e ; [A|B] A/D Converter Result Register 7
+
+TIOS equ REGBASE+$0080 ; [A|B] Timer Input Capture/Output Compare Select
+CFORC equ REGBASE+$0081 ; [A|B] Timer Compare Force Register
+OC7M equ REGBASE+$0082 ; [A|B] Output Compare 7 Mask Register
+OC7D equ REGBASE+$0083 ; [A|B] Output Compare 7 Data Register
+TCNT equ REGBASE+$0084 ; [A|B] Timer Count Register (Word)
+TSCR equ REGBASE+$0086 ; [A|B] Timer System Control Register
+TQCR equ REGBASE+$0087 ; [A|B] Reserved
+TCTL1 equ REGBASE+$0088 ; [A|B] Timer Control Register 1
+TCTL2 equ REGBASE+$0089 ; [A|B] Timer Control Register 2
+TCTL3 equ REGBASE+$008a ; [A|B] Timer Control Register 3
+TCTL4 equ REGBASE+$008b ; [A|B] Timer Control Register 4
+TMSK1 equ REGBASE+$008c ; [A|B] Timer Interrupt Mask 1
+TMSK2 equ REGBASE+$008d ; [A|B] Timer Interrupt Mask 2
+TFLG1 equ REGBASE+$008e ; [A|B] Timer Interrupt Flag 1
+TFLG2 equ REGBASE+$008f ; [A|B] Timer Interrupt Flag 2
+TC0 equ REGBASE+$0090 ; [A|B] Timer Input Capture/Output Compare Register 0 (Word)
+TC1 equ REGBASE+$0092 ; [A|B] Timer Input Capture/Output Compare Register 1 (Word)
+TC2 equ REGBASE+$0094 ; [A|B] Timer Input Capture/Output Compare Register 2 (Word)
+TC3 equ REGBASE+$0096 ; [A|B] Timer Input Capture/Output Compare Register 3 (Word)
+TC4 equ REGBASE+$0098 ; [A|B] Timer Input Capture/Output Compare Register 4 (Word)
+TC5 equ REGBASE+$009a ; [A|B] Timer Input Capture/Output Compare Register 5 (Word)
+TC6 equ REGBASE+$009c ; [A|B] Timer Input Capture/Output Compare Register 6 (Word)
+TC7 equ REGBASE+$009e ; [A|B] Timer Input Capture/Output Compare Register 7 (Word)
+PACTL equ REGBASE+$00a0 ; [A|B] Pulse Accumulator Control Register
+PAFLG equ REGBASE+$00a1 ; [A|B] Pulse Accumulator Flag Register
+PACNT equ REGBASE+$00a2 ; [A|B] 16-bit Pulse Accumulator Count Register (Word)
+
+TIMTST equ REGBASE+$00ad ; [A|B] Timer Test Register
+PORTT equ REGBASE+$00ae ; [A|B] Port T Register
+DDRT equ REGBASE+$00af ; [A|B] Port T Data Direction Register
+
+SC0BDH equ REGBASE+$00c0 ; [A|B] SCI 0 Baud Rate Control Register High
+SC0BDL equ REGBASE+$00c1 ; [A|B] SCI 0 Baud Rate Control Register Low
+SC0CR1 equ REGBASE+$00c2 ; [A|B] SCI 0 Control Register 1
+SC0CR2 equ REGBASE+$00c3 ; [A|B] SCI 0 Control Register 2
+SC0SR1 equ REGBASE+$00c4 ; [A|B] SCI 0 Status Register 1
+SC0SR2 equ REGBASE+$00c5 ; [A|B] SCI 0 Status Register 2
+SC0DRH equ REGBASE+$00c6 ; [A|B] SCI 0 Data Register High
+SC0DRL equ REGBASE+$00c7 ; [A|B] SCI 0 Data Register Low
+SC1BDH equ REGBASE+$00c8 ; [A|-] SCI 1 Baud Rate Control Register High
+SC1BDL equ REGBASE+$00c9 ; [A|-] SCI 1 Baud Rate Control Register Low
+SC1CR1 equ REGBASE+$00ca ; [A|-] SCI 1 Control Register 1
+SC1CR2 equ REGBASE+$00cb ; [A|-] SCI 1 Control Register 2
+SC1SR1 equ REGBASE+$00cc ; [A|-] SCI 1 Status Register 1
+SC1SR2 equ REGBASE+$00cd ; [A|-] SCI 1 Status Register 2
+SC1DRH equ REGBASE+$00ce ; [A|-] SCI 1 Data Register High
+SC1DRL equ REGBASE+$00cf ; [A|-] SCI 1 Data Register Low
+SP0CR1 equ REGBASE+$00d0 ; [A|B] SPI Control Register 1
+SP0CR2 equ REGBASE+$00d1 ; [A|B] SPI Control Register 2
+SP0BR equ REGBASE+$00d2 ; [A|B] SPI Baud Rate Register
+SP0SR equ REGBASE+$00d3 ; [A|B] SPI Status Register
+
+SP0DR equ REGBASE+$00d5 ; [A|B] SPI Data Register
+PORTS equ REGBASE+$00d6 ; [A|B] Port S Register
+DDRS equ REGBASE+$00d7 ; [A|B] Port S Data Direction Register
+
+PURDS equ REGBASE+$00db ; [-|B] Pullup and Reduced Drive for Port S
+
+EEMCR equ REGBASE+$00f0 ; [A|B] EEPROM Module Configuration
+EEPROT equ REGBASE+$00f1 ; [A|B] EEPROM Block Protect
+EETST equ REGBASE+$00f2 ; [A|B] EEPROM Test
+EEPROG equ REGBASE+$00f3 ; [A|B] EEPROM Control
+FEELCK equ REGBASE+$00f4 ; [-|B] Flash EEPROM Lock Control Register
+FEEMCR equ REGBASE+$00f5 ; [-|B] Flash EEPROM Module Configuration Register
+FEETST equ REGBASE+$00f6 ; [-|B] Flash EEPROM Module Test Register
+FEECTL equ REGBASE+$00f7 ; [-|B] Flash EEPROM Control Register
+BCR1 equ REGBASE+$00f8 ; [-|B] BDLC Control Register 1
+BSVR equ REGBASE+$00f9 ; [-|B] BDLC State Vector Register
+BCR2 equ REGBASE+$00fa ; [-|B] BDLC Control Register 2
+BDR equ REGBASE+$00fb ; [-|B] BDLC Data Register
+BARD equ REGBASE+$00fc ; [-|B] BDLC Analog Roundtrip Delay Register
+DLCSCR equ REGBASE+$00fd ; [-|B] Port DLC Control Register
+PORTDLC equ REGBASE+$00fe ; [-|B] Port DLC Data Register
+DDRDLC equ REGBASE+$00ff ; [-|B] Port DLC Data Direction Register
+
+;-----------------------------------------------------------------------------
+
+ endif ; von IFDEF...
+ restore ; wieder erlauben
+
+
diff --git a/include/regm16c.inc b/include/regm16c.inc
new file mode 100644
index 0000000..1ac7b35
--- /dev/null
+++ b/include/regm16c.inc
@@ -0,0 +1,421 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REGM16C.INC *
+;* *
+;* Sinn : enthält Registerdefinitionen für den M16C, Modell M30600M8 *
+;* *
+;* letzte Änderungen : 30. 8.1996 *
+;* 8. 2.1997 if MomPass... *
+;* 7. 7.1999 added two more M16C family CPU entries *
+;* *
+;****************************************************************************
+
+ ifndef regm16cinc ; verhindert Mehrfacheinbindung
+
+regm16cinc equ 1
+
+ if MOMPASS=1
+ switch MOMCPUNAME
+ case "M16C"
+ fatal "please be more specific; do not use the generic processor type for this header file!"
+ case "M30600M8"
+ message "including M30600M8-registers"
+ case "M30610"
+ message "including M30610 registers"
+ case "M30620"
+ message "including M30620 registers"
+ elsecase
+ fatal "invalid processor type: only M30600M8, M30610, or M30620 allowed!"
+ endcase
+ endif
+
+;----------------------------------------------------------------------------
+; benötigte Makros
+
+__bitreg macro Name,Adr,Mask
+Name equ Adr
+ irp BIT,0,1,2,3,4,5,6,7
+ if Mask&(1<<BIT)
+Name{"BIT"} equ Adr<<3+BIT
+ endif
+ endm
+ endm
+
+;----------------------------------------------------------------------------
+; Prozessorsteuerung
+
+ __bitreg PM,0004h,0ffh ; CPU-Modusregister
+ __bitreg CM0,0006h,0ffh ; Systemtaktsteuerung 0
+ __bitreg CM1,0007h,02bh ; Systemtaktsteuerung 1
+PRCR equ 000ah ; Schutzregister
+PRC0 equ PRCR<<3+0 ; Schreibschutz CM0/CM1
+PRC1 equ PRCR<<3+1 ; Schreibschutz PM
+PRC2 equ PRCR<<3+2 ; Schreibschutz PD9
+
+;----------------------------------------------------------------------------
+; Ports
+
+P0 equ 03e0h ; Datenregister Port 0
+PD0 equ 03e2h ; Datenrichtungsregister Port 0
+
+P1 equ 03e1h ; Datenregister Port 1
+PD1 equ 03e3h ; Datenrichtungsregister Port 1
+
+P2 equ 03e4h ; Datenregister Port 2
+PD2 equ 03e6h ; Datenrichtungsregister Port 2
+
+P3 equ 03e5h ; Datenregister Port 3
+PD3 equ 03e7h ; Datenrichtungsregister Port 3
+
+P4 equ 03e8h ; Datenregister Port 4
+PD4 equ 03eah ; Datenrichtungsregister Port 4
+
+P5 equ 03e9h ; Datenregister Port 5
+PD5 equ 03ebh ; Datenrichtungsregister Port 5
+
+P6 equ 03ech ; Datenregister Port 6
+PD6 equ 03eeh ; Datenrichtungsregister Port 6
+
+P7 equ 03edh ; Datenregister Port 7
+PD7 equ 03efh ; Datenrichtungsregister Port 7
+
+P8 equ 03f0h ; Datenregister Port 8
+PD8 equ 03f2h ; Datenrichtungsregister Port 8
+
+P9 equ 03f1h ; Datenregister Port 9
+PD9 equ 03f3h ; Datenrichtungsregister Port 9
+
+P10 equ 03f4h ; Datenregister Port 10
+PD10 equ 03f6h ; Datenrichtungsregister Port 10
+
+PUR0 equ 03fch ; Pull-Up-Register
+PUR1 equ 03fdh
+PUR2 equ 03feh
+PUR3 equ 03ffh
+
+;----------------------------------------------------------------------------
+; Interruptsteuerung
+
+DM0IC equ 004bh ; DMA-Kanal 0
+DM1IC equ 004ch ; DMA-Kanal 1
+KUPIC equ 004dh ; Keyboard input
+ADIC equ 004eh ; A/D-Wandler
+S0TIC equ 0051h ; Senden UART0
+S0RIC equ 0052h ; Empfang UART0
+S1TIC equ 0053h ; Senden UART1
+S1RIC equ 0054h ; Empfang UART1
+TA0IC equ 0055h ; Timer A0
+TA1IC equ 0056h ; Timer A1
+TA2IC equ 0057h ; Timer A2
+TA3IC equ 0058h ; Timer A3
+TA4IC equ 0059h ; Timer A4
+TB0IC equ 005ah ; Timer B0
+TB1IC equ 005bh ; Timer B1
+TB2IC equ 005ch ; Timer B2
+INT0IC equ 005dh ; externer Imterrupt 0
+INT1IC equ 005eh ; externer Interrupt 1
+INT2IC equ 005fh ; externer Interrupt 2
+
+_ILVL0 equ 0 ; Prioritätsebene
+_ILVL1 equ 1
+_ILVL2 equ 2
+_IR equ 3 ; Interrupt aufgetreten ?
+_POL equ 4 ; Polaritätswahl (nur INTxIC)
+_LVS equ 5 ; Pegel/Flankentriggerung (nur INTxIC)
+
+;----------------------------------------------------------------------------
+; Chip-Selects
+
+CSR equ 0008h
+CS0 equ CSR<<3+0 ; Freigabe Chip-Selects
+CS1 equ CSR<<3+1
+CS2 equ CSR<<3+2
+CS3 equ CSR<<3+3
+CS0W equ CSR<<3+4 ; mit / ohne Wait-State ?
+CS1W equ CSR<<3+5
+CS2W equ CSR<<3+6
+CS3W equ CSR<<3+7
+
+;----------------------------------------------------------------------------
+; Adreßvergleicher
+
+RMAD0 equ 0010h ; Vergleichsadresse 0
+RMAD1 equ 0014h ; Vergleichsadresse 1
+ __bitreg AIER,0009h,03h ; Interrupt-Freigaben
+
+;----------------------------------------------------------------------------
+; DMA-Controller
+
+DM0SL equ 03b8h ; Request-Auswahl Kanal 0
+DM1SL equ 03bah ; Request-Auswahl Kanal 1
+_DSEL0 equ 0 ; Request-Grund
+_DSEL1 equ 1
+_DSEL2 equ 2
+_DSEL3 equ 3
+_DSR equ 7 ; Software-Trigger
+
+DM0CON equ 002ch ; Steuerregister Kanal 0
+DM1CON equ 003ch ; Steuerregister Kanal 1
+_DMBIT equ 0 ; Transfereinheit (1/2 Byte)
+_DMASL equ 1 ; Einzel/Blocktransfer
+_DMAS equ 2 ; Request-Anzeige
+_DMAE equ 3 ; Freigabe
+_DSD equ 4 ; feste/wandernde Quelladresse
+_DAD equ 5 ; feste/wandernde Zieladresse
+
+SAR0 equ 0020h ; Quelladresse Kanal 0
+DAR0 equ 0024h ; Zieladresse Kanal 0
+TCR0 equ 0028h ; Zähler Kanal 0
+SAR1 equ 0030h ; Quelladresse Kanal 1
+DAR1 equ 0034h ; Zieladresse Kanal 1
+TCR1 equ 0038h ; Zähler Kanal 1
+
+;----------------------------------------------------------------------------
+; Timer
+
+TA0MR equ 0396h ; Modusregister Timer A0
+TA1MR equ 0397h ; Modusregister Timer A1
+TA2MR equ 0398h ; Modusregister Timer A2
+TA3MR equ 0399h ; Modusregister Timer A3
+TA4MR equ 039ah ; Modusregister Timer A4
+TB0MR equ 039bh ; Modusregister Timer B0
+TB1MR equ 039ch ; Modusregister Timer B1
+TB2MR equ 039dh ; Modusregister Timer B2
+_TMOD0 equ 0 ; Moduswahl
+_TMOD1 equ 1
+_MR0 equ 2 ; Sub-Funktionsauswahl
+_MR1 equ 3
+_MR2 equ 4
+_MR3 equ 5
+_TCK0 equ 6 ; Zählquellenwahl
+_TCK1 equ 7
+
+TA0 equ 0386h ; Zählregister Timer A0
+TA1 equ 0388h ; Zählregister Timer A1
+TA2 equ 038ah ; Zählregister Timer A2
+TA3 equ 038ch ; Zählregister Timer A3
+TA4 equ 038eh ; Zählregister Timer A4
+TB0 equ 0390h ; Zählregister Timer B0
+TB1 equ 0392h ; Zählregister Timer B1
+TB2 equ 0394h ; Zählregister Timer B2
+
+TABSR equ 0380h ; Start/Stop-Register:
+TA0S equ TABSR<<3+0 ; Timer A0
+TA1S equ TABSR<<3+1 ; Timer A1
+TA2S equ TABSR<<3+2 ; Timer A2
+TA3S equ TABSR<<3+3 ; Timer A3
+TA4S equ TABSR<<3+4 ; Timer A4
+TB0S equ TABSR<<3+5 ; Timer B0
+TB1S equ TABSR<<3+6 ; Timer B1
+TB2S equ TABSR<<3+7 ; Timer B2
+
+CPSRF equ 0381h ; Vorteilerregister:
+CPSR equ CPSRF<<3+7 ; Vorteiler zurücksetzen
+
+ONSF equ 0382h ; Monoflop-Triggerbits
+TA0OS equ ONSF<<3+0 ; Timer A0
+TA1OS equ ONSF<<3+1 ; Timer A1
+TA2OS equ ONSF<<3+2 ; Timer A2
+TA3OS equ ONSF<<3+3 ; Timer A3
+TA4OS equ ONSF<<3+4 ; Timer A4
+TA0TGL equ ONSF<<3+6 ; Triggerwahl Timer A0
+TA0TGH equ ONSF<<3+7
+
+TRGSR equ 0383h ; Triggerwahlregister
+TA1TGL equ TRGSR<<3+0 ; Triggerwahl Timer A1
+TA1TGH equ TRGSR<<3+1
+TA2TGL equ TRGSR<<3+2 ; Triggerwahl Timer A2
+TA2TGH equ TRGSR<<3+3
+TA3TGL equ TRGSR<<3+4 ; Triggerwahl Timer A3
+TA3TGH equ TRGSR<<3+5
+TA4TGL equ TRGSR<<3+6 ; Triggerwahl Timer A4
+TA4TGH equ TRGSR<<3+7
+
+UDF equ 0384h ; Zählrichtungen(A) / Zweiphasenmodi(A2-4)
+TA0UD equ UDF<<3+0 ; Timer A0
+TA1UD equ UDF<<3+1 ; Timer A1
+TA2UD equ UDF<<3+2 ; Timer A2
+TA3UD equ UDF<<3+3 ; Timer A3
+TA4UD equ UDF<<3+4 ; Timer A4
+TA2P equ UDF<<3+5 ; Timer A2
+TA3P equ UDF<<3+6 ; Timer A3
+TA4P equ UDF<<3+7 ; Timer A4
+
+;----------------------------------------------------------------------------
+; Watchdog
+
+WDTS equ 000eh ; Startwert
+ __bitreg WDC,000fh,80h ; Vorteilerwahl / obere Zähler-Bits
+
+;----------------------------------------------------------------------------
+; serielle Ports:
+
+U0TB equ 03a2h ; Senderegister UART0
+U1TB equ 03aah ; Senderegister UART1
+
+U0RB equ 03a6h ; Empfangsregister UART0
+U1RB equ 03aeh ; Empfangsregister UART1
+_OER equ 4 ; Overrun-Fehler ?
+_FER equ 5 ; Framing-Fehler ?
+_PER equ 6 ; Paritäts-Fehler ?
+_SUM equ 7 ; Summenfehler ?
+
+U0BRG equ 03a1h ; Baudratengenerator UART0
+U1BRG equ 03a9h ; Baudratengenerator UART1
+
+U0MR equ 03a0h ; Modusregister UART0
+U1MR equ 03a8h ; Modusregister UART1
+_SMD0 equ 0 ; Modus
+_SMD1 equ 1
+_SMD2 equ 2
+_CKDIR equ 3 ; interner/externer Takt
+_STPS equ 4 ; Anzahl Stopbits
+_PRY equ 5 ; Paritätswahl
+_PRYE equ 6 ; Paritätsart
+_SLEP equ 7 ; Sleep-Modus
+
+U0C0 equ 03a4h ; Steuerregister 0 UART0
+U1C0 equ 03ach ; Steuerregister 1 UART0
+_CLK0 equ 0 ; Taktquelle Baudratengenerator
+_CLK1 equ 1
+_CRS equ 2 ; RTS/CTS-Auswahl
+_TXEPT equ 3 ; Senderegister voll ?
+_CRD equ 4 ; CTS/RTS-Auswahl
+_NCH equ 5 ; TXD als Open-Collector ?
+_CKPOL equ 6 ; Taktpolaritätswahl
+_UFORM equ 7 ; Bitreihenfolge
+
+U0C1 equ 03a5h ; Steuerregister 1 UART0
+U1C1 equ 03adh ; Steuerregister 1 UART1
+_TE equ 0 ; Senderfreigabe
+_TI equ 1 ; Sendepuffer leer ?
+_RE equ 2 ; Empfängerfreigabe
+_RI equ 3 ; Empfangspuffer voll ?
+
+UCON equ 03b0h ; Steuerregister 2 UART0+1
+U0IRS equ UCON<<3+0 ; Interruptgrund Sender UART0
+U1IRS equ UCON<<3+1 ; Interruptgrund Sender UART1
+U0RRM equ UCON<<3+2 ; kontinuierlicher Empfangsmodus UART0
+U1RRM equ UCON<<3+3 ; kontinuierlicher Empfangsmodus UART1
+CLKMD0 equ UCON<<3+4 ; Taktausgabe an CLK1/CLKS1
+CLKMD1 equ UCON<<3+5
+RCSP equ UCON<<3+6 ; RTS/CTS gemeinsam/einzeln
+
+;----------------------------------------------------------------------------
+; CRC-Generator
+
+CRCD equ 03bch ; Ergebnis CRC-Berechnung
+
+CRCIN equ 03beh ; Datumseingabe CRC-Berechnung
+
+;----------------------------------------------------------------------------
+; A/D-Wandler
+
+AD0 equ 03c0h ; Datenregister Kanal 0
+AD1 equ 03c2h ; Datenregister Kanal 1
+AD2 equ 03c4h ; Datenregister Kanal 2
+AD3 equ 03c6h ; Datenregister Kanal 3
+AD4 equ 03c8h ; Datenregister Kanal 4
+AD5 equ 03cah ; Datenregister Kanal 5
+AD6 equ 03cch ; Datenregister Kanal 6
+AD7 equ 03ceh ; Datenregister Kanal 7
+
+ADCON0 equ 03d6h ; A/D-Steuerregister 0
+CH0 equ ADCON0<<3+0 ; Kanalwahl
+CH1 equ ADCON0<<3+1
+CH2 equ ADCON0<<3+2
+MD0 equ ADCON0<<3+3 ; Modus
+MD1 equ ADCON0<<3+4
+TRG equ ADCON0<<3+5 ; Soft/Hardwaretrigger
+ADST equ ADCON0<<3+6 ; Konversion starten
+CKS0 equ ADCON0<<3+7 ; Frequenzwahl
+
+ADCON1 equ 03d7h ; A/D-Steuerregister 1
+SCAN0 equ ADCON1<<3+0 ; Sweep-Modus
+SCAN1 equ ADCON1<<3+1
+MD2 equ ADCON1<<3+2 ; Modus
+BITS equ ADCON1<<3+3 ; Breitenwahl (8/10 Bit)
+VCUT equ ADCON1<<3+5
+OPA0 equ ADCON1<<3+6
+OPA1 equ ADCON1<<3+7
+
+ADCON2 equ 03d4h
+SMP equ ADCON2<<3+0 ; A-D Conversion method bit
+
+;----------------------------------------------------------------------------
+; D/A-Wandler
+
+DA0 equ 03d8h ; Wert D/A-Wandler 0
+DA1 equ 03dah ; Wert D/A-Wandler 1
+
+DACON equ 03dch ; Steuerregister D/A-Wandler
+DA0E equ DACON<<3+0 ; D/A-Wandler 0 freigeben
+DA1E equ DACON<<3+1 ; D/A-Wandler 1 freigeben
+
+;----------------------------------------------------------------------------
+; feste Vektoren
+
+Vec_UndefInstr equ 0fffdch ; UND ausgeführt
+Vec_Overflow equ 0fffe0h ; INTO+Overflow ausgeführt
+Vec_BRK equ 0fffe4h ; BRK ausgeführt
+Vec_AddrMatch equ 0fffe8h ; Adressengleichheit aufgetreten
+Vec_SingleStep equ 0fffech ; Einzelschrittverarbeitung
+Vec_WDT equ 0ffff0h ; Watchdog hat zugeschlagen
+Vec_DBC equ 0ffff4h
+Vec_NMI equ 0ffff8h ; nichtmaskierbarer Interrupt
+Vec_Reset equ 0ffffch
+
+;----------------------------------------------------------------------------
+; Variable Vektoren; hier Offset zu INTB
+
+Vec_BRK2 equ 0 ; BRK ausgeführt (falls fester Vektor abgeschaltet)
+Vec_DMA0 equ 44
+Vec_DMA1 equ 48
+Vec_KeyInp equ 52
+Vec_AD equ 56
+Vec_UART0T equ 68
+Vec_UART0R equ 72
+Vec_UART1T equ 76
+Vec_UART1R equ 80
+Vec_TA0 equ 84
+Vec_TA1 equ 88
+Vec_TA2 equ 92
+Vec_TA3 equ 96
+Vec_TA4 equ 100
+Vec_TB0 equ 104
+Vec_TB1 equ 108
+Vec_TB2 equ 112
+Vec_INT0 equ 116
+Vec_INT1 equ 120
+Vec_INT2 equ 124
+
+;----------------------------------------------------------------------------
+; Speicherbereiche
+
+ switch MOMCPUNAME
+ case "M30600M8"
+IROM equ 0f0000h ; 64K ROM am Ende des Speicherraums
+IROMEND equ 0fffffh
+IRAM equ 000400h ; 10K RAM hinter SFRs
+IRAMEND equ 002c00h
+ case "M30610" ; 128k ROM
+IROM equ 0e0000h
+IROMEND equ 0fffffh
+IRAM equ 000400h
+IRAMEND equ 002c00h ; 10k RAM
+ case "M30620"
+IROM equ 0e0000h
+IROMEND equ 0fffffh
+IRAM equ 000400h
+IRAMEND equ 002c00h ; 10k RAM
+ endcase
+
+;----------------------------------------------------------------------------
+
+ endif
+
+ restore ; Listing wieder an
+
diff --git a/include/regmsp.inc b/include/regmsp.inc
new file mode 100644
index 0000000..d5a6f92
--- /dev/null
+++ b/include/regmsp.inc
@@ -0,0 +1,227 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REGMSP.INC *
+;* *
+;* Sinn : enthält Makro- und Registerdefinitionen für den MSP430 *
+;* *
+;* letzte Änderungen : 11. 9.1996 *
+;* *
+;****************************************************************************
+
+ ifndef regmspinc ; verhindert Mehrfacheinbindung
+
+regmspinc equ 1
+
+ if (MOMCPUNAME<>"MSP430")
+ fatal "Falscher Prozessortyp eingestellt: nur MSP430 erlaubt!"
+ endif
+
+ if MOMPASS=1
+ message "MSP430-Register+Befehlsdefinitionen (C) 1996 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; Arithmetik
+
+adc macro op
+ addc.attribute #0,op
+ endm
+
+dadc macro op
+ dadd.attribute #0,op
+ endm
+
+dec macro op
+ sub.attribute #1,op
+ endm
+
+decd macro op
+ sub.attribute #2,op
+ endm
+
+inc macro op
+ add.attribute #1,op
+ endm
+
+incd macro op
+ add.attribute #2,op
+ endm
+
+sbc macro op
+ subc.attribute #0,op
+ endm
+
+;----------------------------------------------------------------------------
+; Logik
+
+inv macro op
+ xor.attribute #-1,op
+ endm
+
+rla macro op
+ add.attribute op,op
+ endm
+
+rlc macro op
+ addc.attribute op,op
+ endm
+
+;----------------------------------------------------------------------------
+; Daten bewegen ;-)
+
+clr macro op
+ mov.attribute #0,op
+ endm
+
+clrc macro
+ bic #1,sr
+ endm
+
+clrn macro
+ bic #4,sr
+ endm
+
+clrz macro
+ bic #2,sr
+ endm
+
+pop macro op
+ mov @sp+,op
+ endm
+
+setc macro
+ bis #1,sr
+ endm
+
+setn macro
+ bis #4,sr
+ endm
+
+setz macro
+ bis #2,sr
+ endm
+
+tst macro op
+ cmp.attribute #0,op
+ endm
+
+;----------------------------------------------------------------------------
+; Sprungbefehle
+
+br macro op
+ mov op,pc
+ endm
+
+dint macro
+ bic #8,sr
+ endm
+
+eint macro
+ bis #8,sr
+ endm
+
+nop macro
+ .word 04303h ; den symbolischen Befehl würde AS zurückweisen
+ endm
+
+ret macro
+ mov @sp+,pc
+ endm
+
+;----------------------------------------------------------------------------
+; Taktgenerator
+
+SCFQCTL equ 052h ; Multiplikator Quarzfrequenz
+SCFI0 equ 050h ; Integrator
+SCFI1 equ 051h
+CBCTL equ 053h ; Puffersteuerung
+EPCTL equ 054h ; EPROM-Steuerung
+
+;----------------------------------------------------------------------------
+; Module
+
+IE1 equ 000h ; Interrupt-Freigaben
+IE2 equ 001h
+IFG1 equ 002h ; Interrupt-Anzeigen
+IFG2 equ 003h
+ME1 equ 004h ; Modul-Freigaben
+ME2 equ 005h
+
+;----------------------------------------------------------------------------
+; Timer
+
+BTCTL equ 040h ; Basis-Steuerregister Timer 1
+
+BTCNT1 equ 046h ; Zählregister
+BTCNT2 equ 047h
+
+TCCTL equ 042h
+
+TCPLD equ 043h ; Vorladewert
+
+TCDAT equ 044h ; Zählwert
+
+TPCTL equ 04bh ; Timer/Port Steuerregister
+
+TPCNT1 equ 04ch ; Zählregister
+TPCNT2 equ 04dh
+
+TPD equ 04eh ; Datenregister
+
+TPE equ 04fh ; Freigaberegister
+
+;----------------------------------------------------------------------------
+; Watchdog
+
+WDTCTL equ 0120h
+
+;----------------------------------------------------------------------------
+; PWM
+
+PWMCTL equ 058h ; Zählwert
+PWMDTB equ 059h ; Pulsweite (Puffer)
+PWMDTR equ 05ah ; Pulsweite
+PWMCNT equ 05bh ; Steuerung
+
+;----------------------------------------------------------------------------
+; Ports
+
+P0IN equ 010h ; Leseregister (Pinzustand)
+P0OUT equ 011h ; Schreibregister (Latches)
+P0DIR equ 012h ; Richtungsregister
+P0IFG equ 013h ; Interrupt-Flags
+P0IES equ 014h ; Interrupf-Flankenwahl
+P0IE equ 015h ; Interrupt-Freigaben
+
+;----------------------------------------------------------------------------
+; LCD-Interface
+
+LCDCTL equ 030h ; Steuerung
+LCD_Start equ 031h ; Startadresse
+LCD_Stop equ 03fh ; Endadresse
+__TMP set 1 ; Einzeldefinitionen
+ rept 9
+LCD{"\{__TMP}"} equ 030h+__TMP
+__TMP set __TMP+1
+ endm
+ rept 6
+LCD1{"\{__TMP-10}"} equ 030h+__TMP
+__TMP set __TMP+1
+ endm
+
+;----------------------------------------------------------------------------
+; A/D-Wandler
+
+AIN equ 0110h ; Eingaberegister
+AEN equ 0112h ; Eingabefreigaben
+ACTL equ 0114h ; Steuerung
+ADAT equ 0118h ; Daten
+
+;----------------------------------------------------------------------------
+
+ endif ; von IFDEF...
+ restore ; wieder erlauben
+
diff --git a/include/regst9.inc b/include/regst9.inc
new file mode 100644
index 0000000..c6b87d9
--- /dev/null
+++ b/include/regst9.inc
@@ -0,0 +1,624 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REGST9.INC *
+;* *
+;* Sinn : enthält SFR-, Makro- und Adreßdefinitionen für die ST9-Familie *
+;* *
+;* letzte Änderungen : 6. 2.1997 *
+;* *
+;****************************************************************************
+
+ ifndef regst9inc ; verhindert Mehrfacheinbindung
+
+regst9inc equ 1
+
+ if (MOMCPUNAME<>"ST9020")&&(MOMCPUNAME<>"ST9030")&&(MOMCPUNAME<>"ST9040")&&(MOMCPUNAME<>"ST9050")
+ fatal "Falscher Prozessortyp eingestellt: nur ST9020,ST9030,ST9040 oder ST9050 erlaubt!"
+ endif
+
+ if MOMPASS=1
+ message "ST9-SFR-Definitionen (C) 1997 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; Registerbänke
+
+__CNT set 0
+ rept 16
+BK{"\{__CNT}"}0 equ __CNT*2
+BK{"\{__CNT}"}1 equ __CNT*2+1
+__CNT set __CNT+1
+ endm
+
+BK_SYS equ BKE0 ; Group system definition
+BK_F equ BKF0 ; page register definition
+
+;----------------------------------------------------------------------------
+; Definition eines Bits:
+; dies nutzt die interne Definition von Bitsymbolen aus: rrrrbbbi
+
+__defbit macro NAME,REG,BITPOS
+NAME bit ((REG&15)<<4)+(BITPOS<<1)
+{"NAME"}m equ 1<<BITPOS
+ endm
+
+;----------------------------------------------------------------------------
+; Systemgruppe
+
+FCW reg RR230 ; flag and control word
+CICR reg R230 ; central interrupt control register
+ __defbit gcen,CICR,7 ; global counter enable
+ __defbit tlip,CICR,6 ; top level interrupt pending bit
+ __defbit tli,CICR,5 ; top level interrupt bit
+ __defbit ien,CICR,4 ; interrupt enable flag
+ __defbit iam,CICR,3 ; interrupt arbitration mode
+ __defbit cpl2,CICR,2 ; current priority level bit 2
+ __defbit cpl1,CICR,1 ; current priority level bit 1
+ __defbit cpl0,CICR,0 ; current priority level bit 0
+cplm equ cpl2m|cpl1m|cpl0m ; current priority level
+
+FLAGR reg R231 ; flags register
+ __defbit c,FLAGR,7 ; carry flag
+ __defbit z,FLAGR,6 ; zero flag
+ __defbit s,FLAGR,5 ; sign flag
+ __defbit v,FLAGR,4 ; overflow flag
+ __defbit d,FLAGR,3 ; decimal adjust flag
+ __defbit h,FLAGR,2 ; half carry flag
+ __defbit uf,FLAGR,1 ; user flag 1
+ __defbit dp,FLAGR,0 ; data/program memory flag
+
+RPP reg RR232 ; register pointer pair
+
+RP0R reg R232 ; register pointer #0
+ __defbit rp0s,RP0R,2 ; register pointer selector
+
+RP1R reg R233 ; register pointer #1
+ __defbit rp1s,RP1R,2 ; register pointer selector
+
+PPR reg R234 ; page pointer register
+
+MODER reg R235 ; mode register
+ __defbit ssp,MODER,7 ; system stack pointer flag (int/ext)
+ __defbit usp,MODER,6 ; user stack pointer flag (int/ext)
+ __defbit div2,MODER,5 ; external clock divided by 2
+ __defbit prs2,MODER,4 ; internal clock prescaling bit 2
+ __defbit prs1,MODER,3 ; internal clock prescaling bit 1
+ __defbit prs0,MODER,2 ; internal clock prescaling bit 0
+ __defbit brqen,MODER,1 ; bus request enable
+ __defbit himp,MODER,0 ; high impedance enable
+prsm equ prs2m|prs1m|prs0m ; internal clock prescaler
+
+USPR reg RR236 ; user stack pointer
+USPHR reg R236
+USPLR reg R237
+
+SSPR reg RR238 ; system stack pointer
+SSPHR reg R238
+SSPLR reg R239
+
+;----------------------------------------------------------------------------
+; EEPROM
+
+ if MOMCPUNAME="ST9040"
+
+EEP_PG equ 0 ; EEPROM register page
+
+EECR reg R241 ; EEPROM control register
+ __defbit verify,EECR,6 ; EEPROM verify mode
+ __defbit eestby,EECR,5 ; EEPROM stand-by
+ __defbit eeien,EECR,4 ; EEPROM interrupt enable
+ __defbit pllst,EECR,3 ; Parallel write start
+ __defbit pllen,EECR,2 ; Parallel write enable
+ __defbit eebusy,EECR,1 ; EEPROM busy
+ __defbit eewen,EECR,0 ; EEPROM write enable
+
+ endif
+
+;----------------------------------------------------------------------------
+; Interrupts
+
+EXINT_PG equ 0 ; EXTERNAL interrupt register page
+
+EITR reg R242 ; External interrupt trigger level register
+ __defbit tea0,EITR,0 ; Trigger Event A0 bit
+ __defbit tea1,EITR,1 ; Trigger Event A1 bit
+ __defbit teb0,EITR,2 ; Trigger Event B0 bit
+ __defbit teb1,EITR,3 ; Trigger Event B1 bit
+ __defbit tec0,EITR,4 ; Trigger Event C0 bit
+ __defbit tec1,EITR,5 ; Trigger Event C1 bit
+ __defbit ted0,EITR,6 ; Trigger Event D0 bit
+ __defbit ted1,EITR,7 ; Trigger Event D1 bit
+
+EIPR reg R243 ; External interrupt pending register
+ __defbit ipa0,EIPR,0 ; Interrupt Pending bit Channel A0
+ __defbit ipa1,EIPR,1 ; Interrupt Pending bit " A1
+ __defbit ipb0,EIPR,2 ; Interrupt Pending bit " B0
+ __defbit ipb1,EIPR,3 ; Interrupt Pending bit " B1
+ __defbit ipc0,EIPR,4 ; Interrupt Pending bit " C0
+ __defbit ipc1,EIPR,5 ; Interrupt Pending bit " C1
+ __defbit ipd0,EIPR,6 ; Interrupt Pending bit " D0
+ __defbit ipd1,EIPR,7 ; Interrupt Pending bit " D1
+
+EIMR reg R244 ; External interrupt mask register
+ __defbit ima0,EIMR,0 ; Int. A0 bit
+ __defbit ima1,EIMR,1 ; Int. A1 bit
+ __defbit imb0,EIMR,2 ; Int. B0 bit
+ __defbit imb1,EIMR,3 ; Int. B1 bit
+ __defbit imc0,EIMR,4 ; Int. C0 bit
+ __defbit imc1,EIMR,5 ; Int. C1 bit
+ __defbit imd0,EIMR,6 ; Int. D0 bit
+ __defbit imd1,EIMR,7 ; Int. D1 bit
+
+EIPLR reg R245 ; Ext. interrupt priority level register
+
+EIVR reg R246 ; External interrupt vector register
+ __defbit ewen,EIVR,0 ; External wait enable
+ __defbit ia0s,EIVR,1 ; Interrupt A0 selection
+ __defbit tlis,EIVR,2 ; Top level input selection
+ __defbit tltev,EIVR,3 ; Top level trigger event
+
+NICR reg R247 ; Nested interrupt control register
+
+ __defbit tlnm,NICR,7 ; Top level not maskable
+
+;----------------------------------------------------------------------------
+; Watchdog
+
+WDT_PG equ 0 ; Timer Watchdog page
+
+WDTR reg RR248 ; TWD timer constant register.
+WDTHR reg R248 ; TWD timer high constant register
+WDTLR reg R249 ; TWD timer low constant register
+
+WDTPR reg R250 ; TWD timer prescaler constant register
+
+WDTCR reg R251 ; TWD timer control register
+ __defbit WD_stsp8,WDTCR,7 ; TWD start stop.
+ __defbit WD_sc,WDTCR,6 ; TWD single continuous mode.
+ __defbit WD_inmd1,WDTCR,5 ; Input mode 1
+ __defbit WD_inmd2,WDTCR,4 ; Input mode 2
+ __defbit WD_inen,WDTCR,3 ; TWD input section enable/disable.
+ __defbit WD_outmd,WDTCR,2 ; TWD output mode.
+ __defbit WD_wrout,WDTCR,1 ; TWD output bit.
+ __defbit WD_outen,WDTCR,0 ; TWD output enable.
+inm_evc equ 0 ; TWD input mode event counter.
+inm_g equ 010h ; TWD input mode gated.
+inm_t equ 020h ; TWD input mode triggerable.
+inm_r equ 030h ; TWD input mode retriggerable.
+
+WCR reg R252 ; Wait control register
+ __defbit WD_wden,WCR,6 ; TWD timer enable.
+wdm2 equ 1 << 5 ; Data Memory Wait Cycle
+wdm1 equ 1 << 4
+wdm0 equ 1 << 3
+wpm2 equ 1 << 2 ; Program Memory Wait Cycle
+wpm1 equ 1 << 1
+wpm0 equ 1 << 0
+dmwc1 equ wdm0 ; 1 wait cycle on Data M.
+dmwc2 equ wdm1 ; 2 wait cycles on Data M.
+dmwc3 equ wdm1|wdm0 ; 3 wait cycles on Data M.
+dmwc4 equ wdm2 ; 4 wait cycles on Data M.
+dmwc5 equ wdm2|wdm0 ; 5 wait cycles on Data M.
+dmwc6 equ wdm2|wdm1 ; 6 wait cycles on Data M.
+dmwc7 equ wdm2|wdm1|wdm0 ; 7 wait cycles on Data M.
+pmwc1 equ wpm0 ; 1 wait cycle on Prog M.
+pmwc2 equ wpm1 ; 2 wait cycles on Prog M.
+pmwc3 equ wpm1|wpm0 ; 3 wait cycles on Prog M.
+pmwc4 equ wpm2 ; 4 wait cycles on Prog M.
+pmwc5 equ wpm2|wpm0 ; 5 wait cycles on Prog M.
+pmwc6 equ wpm2|wpm1 ; 6 wait cycles on Prog M.
+pmwc7 equ wpm2|wpm1|wpm0 ; 7 wait cycles on Prog M.
+
+;----------------------------------------------------------------------------
+; SPI
+
+SPI_PG equ 0 ; SPI register page
+SPIDR reg R253 ; SPI Data register
+
+SPICR reg R254 ; SPI Control register
+ __defbit SP_spen,SPICR,7 ; Serial Peripheral Enable.
+ __defbit SP_bms,SPICR,6 ; SBUS/I2C bus Mode Selector.
+ __defbit SP_arb,SPICR,5 ; Arbitration flag bit.
+ __defbit SP_busy,SPICR,4 ; SPI busy flag.
+ __defbit SP_cpol,SPICR,3 ; SPI transmission clock polarity
+ __defbit SP_cpha,SPICR,2 ; SPI transmission clock phase
+ __defbit SP_spr1,SPICR,1 ; SPI rate bit 1
+ __defbit SP_spr0,SPICR,0 ; SPI rate bit 0
+
+SP_8 equ 0 ; SPI clock divider 8 = 1500 kHz (12MHz)
+SP_16 equ 1 ; SPI clock divider 16 = 750 kHz (12MHz)
+SP_128 equ 2 ; SPI clock divider 128 = 93.75 kHz (12MHz)
+SP_256 equ 3 ; SPI clock divider 256 = 46.87 kHz (12MHz)
+RW_PG equ 0 ; R/W signal programming page
+
+;----------------------------------------------------------------------------
+; Read/Write Register
+
+ if MOMCPUNAME="ST9050"
+
+RWR reg R255 ; R/W signal programming register
+ __defbit RW_rw,RWR,0 ; R/W bit
+ __defbit RW_bs,RWR,1 ; Bank switch port timing
+
+ endif
+
+;----------------------------------------------------------------------------
+; Ports
+
+P0C_PG equ 2 ; Port 0 control registers page
+
+P0DR reg R224 ; Port 0 data register
+P0C0R reg R240 ; Port 0 control register 0
+P0C1R reg R241 ; Port 0 control register 1
+P0C2R reg R242 ; Port 0 control register 2
+
+P1C_PG equ 2 ; Port 1 control registers page
+P1DR reg R225 ; Port 1 data register
+P1C0R reg R244 ; Port 1 control register 0
+P1C1R reg R245 ; Port 1 control register 1
+P1C2R reg R246 ; Port 1 control register 2
+
+P2C_PG equ 2 ; Port 2 control registers page
+P2DR reg R226 ; Port 2 data register
+BS_DSR reg R226 ; Bank Switch data segment register
+P2C0R reg R248 ; Port 2 control register 0
+BS_DDSR reg R248 ; Bank Switch Data DMA segment register
+P2C1R reg R249 ; Port 2 control register 1
+BS_PDSR reg R249 ; Bank Switch Program DMA segment Register
+P2C2R reg R250 ; Port 2 control register 2
+
+P3C_PG equ 2 ; Port 3 control registers page
+P3DR reg R227 ; Port 3 data register
+BS_PSR reg R227 ; Bank Switch Program Segment Register
+P3C0R reg R252 ; Port 3 control register 0
+P3C1R reg R253 ; Port 3 control register 1
+P3C2R reg R254 ; Port 3 control register 2
+
+P4C_PG equ 3 ; Port 4 control registers page
+P4DR reg R228 ; Port 4 data register
+P4C0R reg R240 ; Port 4 control register 0
+P4C1R reg R241 ; Port 4 control register 1
+P4C2R reg R242 ; Port 4 control register 2
+
+P5C_PG equ 3 ; Port 5 control registers page
+P5DR reg R229 ; Port 5 data register
+P5C0R reg R244 ; Port 5 control register 0
+P5C1R reg R245 ; Port 5 control register 1
+P5C2R reg R246 ; Port 5 control register 2
+
+P6C_PG equ 3 ; Port 6 control registers page
+P6D_PG equ 3 ; Port 6 data register page
+P6DR reg R251 ; Port 6 data register
+P6C0R reg R248 ; Port 6 control register 0
+P6C1R reg R249 ; Port 6 control register 1
+P6C2R reg R250 ; Port 6 control register 2
+
+P7C_PG equ 3 ; Port 7 control registers page
+P7D_PG equ 3 ; Port 7 data register page
+P7DR reg R255 ; Port 7 data register
+P7C0R reg R252 ; Port 7 control register 0
+P7C1R reg R253 ; Port 7 control register 1
+P7C2R reg R254 ; Port 7 control register 2
+
+P8C_PG equ 43 ; Port 8 control registers page
+P8D_PG equ 43 ; Port 8 data register page
+P8DR reg R251 ; Port 8 data register
+P8C0R reg R248 ; Port 8 control register 0
+P8C1R reg R249 ; Port 8 control register 1
+P8C2R reg R250 ; Port 8 control register 2
+
+P9C_PG equ 43 ; Port 9 control registers page
+P9D_PG equ 43 ; Port 9 data register page
+P9DR reg R255 ; Port 9 data register
+P9C0R reg R252 ; Port 9 control register 0
+P9C1R reg R253 ; Port 9 control register 1
+P9C2R reg R254 ; Port 9 control register 2
+
+HDCTL2R reg R251 ; Port 2 handshake DMA control register
+HDCTL3R reg R255 ; Port 3 handshake DMA control register
+HDCTL4R reg R243 ; Port 4 handshake DMA control register
+HDCTL5R reg R247 ; Port 5 handshake DMA control register
+
+;Handshake DMA control register configuration.
+hsdis equ 0E0h ; Handshake disabled mask
+hso2 equ 0C0h ; Handshake output 2 lines mask
+hso1 equ 040h ; Handshake output 1 line mask
+hsi2 equ 0A0h ; Handshake input 2 lines mask
+hsi1 equ 020h ; Handshake input 1 line mask
+hsb equ 000h ; Handshake bidirectional mask
+den equ 000h ; DMA enable mask
+ddi equ 010h ; DMA disable mask
+ddw equ 000h ; Data direction output mask (write)
+ddr equ 008h ; Data direction input mask (read)
+dst equ 004h ; DMA strobe on chip event mask
+dcp0 equ 000h ; DMA channel capture0 mask
+dcm0 equ 002h ; DMA channel compare0 mask
+
+;----------------------------------------------------------------------------
+; Multi function timer
+
+T0D_PG equ 10 ; MFTimer 0 data registers page
+T0C_PG equ 9 ; MFTimer 0 control registers page
+T1D_PG equ 8 ; MFTimer 1 data registers page
+T1C_PG equ 9 ; MFTimer 1 control registers page
+T2D_PG equ 14 ; MFTimer 2 data registers page
+T2C_PG equ 13 ; MFTimer 2 control registers page
+T3D_PG equ 12 ; MFTimer 3 data registers page
+T3C_PG equ 13 ; MFTimer 3 control registers page
+
+T_REG0R reg RR240 ; MFTimer REG0 load and capture register.
+T_REG0HR reg R240 ; Register 0 high register
+T_REG0LR reg R241 ; Register 0 low register
+T_REG1R reg RR242 ; MFTimer REG1 load constant
+T_REG1HR reg R242 ; Register 1 high register
+T_REG1LR reg R243 ; Register 1 low register
+T_CMP0R reg RR244 ; MFTimer CMP0 store compare constant.
+T_CMP0HR reg R244 ; Compare 0 high register
+T_CMP0LR reg R245 ; Compare 0 low register
+T_CMP1R reg RR246 ; MFTimer CMP1 store compare constant.
+T_CMP1HR reg R246 ; Compare 1 high register
+T_CMP1LR reg R247 ; Compare 1 low register
+
+T_TCR reg R248 ; MFTimer Control Register.
+ __defbit T_cs,T_TCR,0 ; Counter status
+ __defbit T_of0,T_TCR,1 ; over/underflow on CAP on REG0
+ __defbit T_udcs,T_TCR,2 ; up/down count status
+ __defbit T_udc,T_TCR,3 ; up/down count
+ __defbit T_ccl,T_TCR,4 ; Counter clear
+ __defbit T_ccmp0,T_TCR,5 ; Clear on compare 0
+ __defbit T_ccp0,T_TCR,6 ; Clear on capture
+ __defbit T_cen,T_TCR,7 ; Counter enable
+
+T_TMR reg R249 ; MFTimer Mode Register.
+ __defbit T_co,T_TMR,0 ; Continuous/one shot bit
+ __defbit T_ren,T_TMR,1 ; retrigger enable bit
+ __defbit T_eck,T_TMR,2 ; Enable clocking mode bit
+ __defbit T_rm0,T_TMR,3 ; register 0 mode bit
+ __defbit T_rm1,T_TMR,4 ; register 1 mode bit
+ __defbit T_bm,T_TMR,5 ; bivalue mode bit
+ __defbit T_oe0,T_TMR,6 ; output 0 enable bit
+ __defbit T_oe1,T_TMR,7 ; output 1 enable bit
+
+T_ICR reg R250 ; MFTimer External Input Control Register.
+
+exb_f equ 01h ; External B falling edge sensitive mask
+exb_r equ 02h ; External B rising edge sensitive mask
+exb_rf equ 03h ; External B falling and rising edge mask
+exa_f equ 04h ; External A falling edge sensitive mask
+exa_r equ 08h ; External A rising edge sensitive mask
+exa_rf equ 0Ch ; External A falling and rising edge mask
+ab_ii equ 00h ; A I/O B I/O mask
+ab_it equ 10h ; A I/O B trigger mask
+ab_gi equ 20h ; A gate B I/O mask
+ab_gt equ 30h ; A gate B trigger mask
+ab_ie equ 40h ; A I/O B external clock mask
+ab_ti equ 50h ; A trigger B I/O mask
+ab_ge equ 60h ; A gate B external clock mask
+ab_tt equ 70h ; A trigger B trigger mask
+ab_cucd equ 80h ; A clock up B clock down mask
+ab_ue equ 90h ; A clock up/down B external clock mask
+ab_tutd equ 0A0h ; A trigger up B trigger down mask
+ab_ui equ 0B0h ; A up/down clock B I/O mask
+ab_aa equ 0C0h ; A autodiscr. B autodiscr. mask
+ab_te equ 0D0h ; A trigger B external clock mask
+ab_et equ 0E0h ; A external clock B trigger mask
+ab_tg equ 0F0h ; A trigger B gate mask
+
+T_PRSR reg R251 ; MFTimer prescaler register
+
+T_OACR reg R252 ; MFTimer Output A Control Register.
+
+cev equ 02h ; on chip event bit on COMPARE 0 mask
+
+T_OBCR reg R253 ; MFTimer Output B Control Register.
+
+op equ 01h ; output preset bit mask
+oev equ 02h ; on chip event bit on OVF/UDF mask
+ou_set equ 00h ; overflow underflow set mask
+ou_tog equ 04h ; overflow underflow toggle mask
+ou_res equ 08h ; overflow underflow reset mask
+ou_nop equ 0Ch ; overflow underflow nop mask
+c1_set equ 00h ; Compare 1 set mask
+c1_tog equ 10h ; Compare 1 toggle mask
+c1_res equ 20h ; Compare 1 reset mask
+c1_nop equ 30h ; Compare 1 nop mask
+c0_set equ 00h ; Compare 0 set mask
+c0_tog equ 40h ; Compare 0 toggle mask
+c0_res equ 80h ; Compare 0 reset mask
+c0_nop equ 0C0h ; Compare 0 nop mask
+
+T_FLAGR reg R254 ; MFTimer Flags Register.
+ __defbit T_ao,T_FLAGR,0 ; and/or on capture interrupt
+ __defbit T_ocm0,T_FLAGR,1 ; overrun compare 0
+ __defbit T_ocp0,T_FLAGR,2 ; overrun capture 0
+ __defbit T_ouf,T_FLAGR,3 ; overflow underflow flag
+ __defbit T_cm1,T_FLAGR,4 ; successful compare 1
+ __defbit T_cm0,T_FLAGR,5 ; successful compare 0
+ __defbit T_cp1,T_FLAGR,6 ; successful capture 1
+ __defbit T_cp0,T_FLAGR,7 ; successful capture 0
+
+T_IDMR equ R255 ; MFTimer Interrupt DMA Mask Register.
+ __defbit T_oui,T_IDMR,0 ; overflow underflow interrupt
+ __defbit T_cm1i,T_IDMR,1 ; Compare 1 interrupt
+ __defbit T_cm0i,T_IDMR,2 ; Compare 0 interrupt
+ __defbit T_cm0d,T_IDMR,3 ; Compare 0 DMA
+ __defbit T_cp1i,T_IDMR,4 ; Capture 1 interrupt
+ __defbit T_cp0i,T_IDMR,5 ; Capture 0 interrupt
+ __defbit T_cp0d,T_IDMR,6 ; Capture 0 DMA
+ __defbit T_gtien,T_IDMR,7 ; global timer interrupt enable
+
+T0_DCPR reg R240 ; MFTimer 0 DMA Counter Pointer Register.
+T1_DCPR reg R244 ; MFTimer 1 DMA Counter Pointer Register.
+T0_DAPR reg R241 ; MFTimer 0 DMA Address Pointer Register.
+T1_DAPR reg R245 ; MFTimer 1 DMA Address Pointer Register.
+T0_IVR reg R242 ; MFTimer 0 Interrupt Vector Register.
+T1_IVR reg R246 ; MFTimer 1 Interrupt Vector Register.
+T0_IDCR reg R243 ; MFTimer 0 Interrupt/DMA Control Register.
+T1_IDCR reg R247 ; MFTimer 1 Interrupt/DMA Control Register.
+T2_DCPR reg R240 ; MFTimer 2 DMA Counter Pointer Register.
+T3_DCPR reg R244 ; MFTimer 3 DMA Counter Pointer Register.
+T2_DAPR reg R241 ; MFTimer 2 DMA Address Pointer Register.
+T3_DAPR reg R245 ; MFTimer 3 DMA Address Pointer Register.
+T2_IVR reg R242 ; MFTimer 2 Interrupt Vector Register.
+T3_IVR reg R246 ; MFTimer 3 Interrupt Vector Register.
+T2_IDCR reg R243 ; MFTimer 2 Interrupt/DMA Control Register.
+T3_IDCR reg R247 ; MFTimer 3 Interrupt/DMA Control Register.
+
+plm equ 07h ; Priority level mask
+swen equ 08h ; Swap function enable mask
+dctd equ 10h ; DMA compare transaction destination mask
+dcts equ 20h ; DMA capture transaction source mask
+cme equ 40h ; Compare 0 end of block mask
+cpe equ 80h ; Capture 0 end of block mask
+
+T_IOCR reg R248 ; MFTimer I/O connection register
+
+sc0 equ 01h ; TxOUTA and TxINA connection bit (even)
+
+sc1 equ 02h ; TxOUTA and TxINA connection bit (odd)
+
+;----------------------------------------------------------------------------
+; A/D-Wandler
+
+ if MOMCPUNAME<>"ST9020"
+
+AD0_PG equ 63 ; A/D converter registers page
+AD1_PG equ 62 ; second A/D unit
+
+AD_D0R reg R240 ; Channel 0 data register
+AD_D1R reg R241 ; Channel 1 data register
+AD_D2R reg R242 ; Channel 2 data register
+AD_D3R reg R243 ; Channel 3 data register
+AD_D4R reg R244 ; Channel 4 data register
+AD_D5R reg R245 ; Channel 5 data register
+AD_D6R reg R246 ; Channel 6 data register
+AD_D7R reg R247 ; Channel 7 data register
+AD_LT6R reg R248 ; Channel 6 lower threshold register
+AD_LT7R reg R249 ; Channel 7 lower threshold register
+AD_UT6R reg R250 ; Channel 6 upper threshold register
+AD_UT7R reg R251 ; Channel 7 upper threshold register
+
+AD_CRR reg R252 ; Compare result register
+ __defbit AD_c6l,AD_CRR,4 ; Compare channel 6 lower bit
+ __defbit AD_c7l,AD_CRR,5 ; Compare channel 7 lower bit
+ __defbit AD_c6u,AD_CRR,6 ; Compare channel 6 upper bit
+ __defbit AD_c7u,AD_CRR,7 ; Compare channel 7 upper bit
+
+AD_CLR reg R253 ; Control logic register
+ __defbit AD_st,AD_CLR,0 ; start/stop bit
+ __defbit AD_cont,AD_CLR,1 ; Continuous mode
+ __defbit AD_pow,AD_CLR,2 ; power up/down control
+ __defbit AD_intg,AD_CLR,3 ; internal trigger
+ __defbit AD_extg,AD_CLR,4 ; External trigger
+
+sch equ 0E0h ; scan channel selection mask
+
+AD_ICR reg R254 ; interrupt control register
+ __defbit AD_awdi,AD_ICR,4 ; analog watch-dog interrupt
+ __defbit AD_eci,AD_ICR,5 ; End of count interrupt
+ __defbit AD_awd,AD_ICR,6 ; analog watch-dog pending flag
+ __defbit AD_ecv,AD_ICR,7 ; End of conversion pending flag
+
+AD_prl equ 07h ; priority level mask
+
+AD_IVR reg R255 ; interrupt vector register
+
+ endif
+
+;----------------------------------------------------------------------------
+; Serielle Schnittstelle
+
+SCI1_PG equ 24 ; SCI1 control registers page
+SCI2_PG equ 25 ; SCI2 control registers page
+SCI3_PG equ 26 ; SCI3 control registers page
+SCI4_PG equ 27 ; SCI4 control registers page
+
+S_RDCPR reg R240 ; receive DMA counter pointer register
+S_RDAPR reg R241 ; receive DMA address pointer register
+S_TDCPR reg R242 ; transmit DMA counter pointer register
+S_TDAPR reg R243 ; transmit DMA address pointer register
+S_IVR reg R244 ; interrupt vector register
+S_ACR reg R245 ; address compare register
+
+S_IMR reg R246 ; interrupt mask register
+ __defbit S_txdi,S_IMR,0 ; transmitter data interrupt
+ __defbit S_rxdi,S_IMR,1 ; receiver data interrupt
+ __defbit S_rxb,S_IMR,2 ; receiver break
+ __defbit S_rxa,S_IMR,3 ; receiver address
+ __defbit S_rxe,S_IMR,4 ; receiver error
+ __defbit S_txeob,S_IMR,5 ; transmit end of block
+ __defbit S_rxeob,S_IMR,6 ; receive end of block
+ __defbit S_hsn,S_IMR,7 ; Holding or shift register empty.
+
+S_ISR reg R247 ; interrupt status register
+ __defbit S_txsem,S_ISR,0 ; transmit shift register empty
+ __defbit S_txhem,S_ISR,1 ; transmit hold register empty
+ __defbit S_rxdp,S_ISR,2 ; received data pending bit
+ __defbit S_rxbp,S_ISR,3 ; received break pending bit
+ __defbit S_rxap,S_ISR,4 ; received address pending bit
+ __defbit S_pe,S_ISR,5 ; parity error pending bit
+ __defbit S_fe,S_ISR,6 ; framing error pending bit
+ __defbit S_oe,S_ISR,7 ; overrun error pending bit
+
+S_RXBR reg R248 ; receive buffer register
+S_TXBR reg R248 ; transmit buffer register
+
+S_IDPR reg R249 ; interrupt/DMA priority register
+ __defbit S_txd,S_IDPR,3 ; transmitter DMA
+ __defbit S_rxd,S_IDPR,4 ; receiver DMA
+ __defbit S_sa,S_IDPR,5 ; set address
+ __defbit S_sb,S_IDPR,6 ; set break
+ __defbit S_amen,S_IDPR,7 ; address mode enable
+S_pri equ 07h ; interrupt/DMA priority mask
+
+S_CHCR reg R250 ; Character configuration register
+
+wl5 equ 000h ; 5 bits data word mask
+wl6 equ 001h ; 6 bits data word mask
+wl7 equ 002h ; 7 bits data word mask
+wl8 equ 003h ; 8 bits data word mask
+sb10 equ 000h ; 1.0 stop bit mask
+sb15 equ 004h ; 1.5 stop bit mask
+sb20 equ 008h ; 2.0 stop bit mask
+sb25 equ 00Ch ; 2.5 stop bit mask
+ab equ 010h ; address bit insertion mask
+pen equ 020h ; parity enable mask
+ep equ 040h ; Even parity mask
+oddp equ 000h ; odd parity mask
+am equ 080h ; address mode mask
+
+S_CCR reg R251 ; Clock configuration register
+ __defbit S_stpen,S_CCR,0 ; stick parity enable
+ __defbit S_lben,S_CCR,1 ; loop back enable
+ __defbit S_aen,S_CCR,2 ; auto echo enable
+ __defbit S_cd,S_CCR,3 ; Clock divider
+ __defbit S_xbrg,S_CCR,4 ; External baud rate generator source
+ __defbit S_xrx,S_CCR,5 ; External receiver source
+ __defbit S_oclk,S_CCR,6 ; output clock selection
+ __defbit S_txclk,S_CCR,7 ; transmit clock selection
+
+S_BRGR reg RR252 ; baud rate generator register
+S_BRGHR reg R252 ; baud rate generator reg. high
+S_BRGLR reg R253 ; baud rate generator reg. low
+
+;----------------------------------------------------------------------------
+; Security Register:
+
+SEC_PG equ 59 ; Security register page
+
+SECR reg R255
+ __defbit tlck,SECR,0 ; test lock bit
+ __defbit wf1,SECR,1 ; write fuse 1 bit
+ __defbit hlck,SECR,2 ; hardware lock bit
+ __defbit wf2,SECR,3 ; write fuse 2 bit
+ __defbit f2tst,SECR,4 ; select fuse 2 bit
+ __defbit slck,SECR,7 ; software lock bit
+
+;----------------------------------------------------------------------------
+
+ endif
+
+ restore ; Listing wieder an
diff --git a/include/regz380.inc b/include/regz380.inc
new file mode 100644
index 0000000..83c428d
--- /dev/null
+++ b/include/regz380.inc
@@ -0,0 +1,68 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei REGZ380.INC *
+;* *
+;* Sinn : enthält Registerdefinitionen für den Z380 *
+;* Diese Register sind nur mit den Befehlen IN0,OUT0 und TSTIO *
+;* erreichbar!! *
+;* *
+;* letzte Änderungen : 12.11.1994 *
+;* 2. 1.1996 Register 0..16h *
+;* (Info von Leonhard Schneider) *
+;* *
+;****************************************************************************
+
+ ifndef regz380inc ; verhindert Mehrfacheinbindung
+
+reg380inc equ 1
+
+ if (MOMCPU<>896)
+ fatal "Falscher Prozessortyp eingestellt: nur Z380 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "Z380-Register-Definitionen (C) 1994 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+
+LMCS0 port 00h ; Lower Memory Chip Select Register
+LMCS1 port 01h
+UMCS0 port 02h ; Upper Memory Chip Select Register
+UMCS1 port 03h
+MMCS0 port 04h ; Midrange Memory Chip Select Register
+MMCS1 port 05h
+MMCS2 port 06h
+MMCS3 port 07h
+LMWR port 08h ; Lower Memory Waits Register
+UMWR port 09h ; Upper Memory Waits Register
+MMWR0 port 0ah ; Midrange Memory Waits Register
+MMWR1 port 0bh
+MMWR2 port 0ch
+MMWR3 port 0dh
+IOWR port 0eh ; I/O Waits Register
+RFWR port 0fh ; Refresh Waits Register
+MSMER port 10h ; Memory Select Master Enable Register
+IOCR0 port 11h ; I/O Bus Control Register
+IOCR1 port 12h
+RFSHR0 port 13h ; Refresh Register
+RFSHR1 port 14h
+RFSHR2 port 15h
+SMCR port 16h ; Standby Mode Control Register
+IER port 17h ; Interrupt-Freigaben
+AVBR port 18h ; Offset Interruptvektoren ?!
+TRPBK port 19h ; zeigt an, ob Trap oder Break ausgetreten
+
+CHIPVERSION port 0ffh ; Chipversion (00=Z380MPU)
+
+
+;----------------------------------------------------------------------------
+
+ endif ; von IFDEF...
+ restore ; wieder erlauben
+
+
diff --git a/include/stddef04.inc b/include/stddef04.inc
new file mode 100644
index 0000000..d4e2550
--- /dev/null
+++ b/include/stddef04.inc
@@ -0,0 +1,54 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.39 - Datei STDDEF04.INC *
+;* *
+;* Sinn : enthält SFR-Definitionen für den 6804-Prozessor *
+;* Falls Sie noch ein paar schöne Makros suchen, schauen Sie sich *
+;* einmal in STDDEF62.INC um ! *
+;* *
+;* letzte Änderungen : 28.11.1993 *
+;* *
+;****************************************************************************
+
+ ifndef stddef04inc ; verhindert Mehrfacheinbindung
+
+stddef04inc equ 1
+
+ if (MOMCPU<>26628)
+ fatal "Falscher Prozessortyp eingestellt: nur 6804 erlaubt!"
+ endif
+
+ if MOMPASS=1
+ message "6804-SFR-Definitionen (C) 1993 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; erstmal die Sachen, die es überall gibt :
+
+XP SFR $80 ; Registeradressen (die kennt AS aber
+YP SFR $81 ; auch schon intern, nur der Voll-
+RegA SFR $ff ; ständigkeit halber)
+
+PA SFR $00 ; Port A
+DDRA SFR $04
+PB SFR $01 ; Port B
+DDRB SFR $05
+PC SFR $02
+DDRC SFR $06
+
+TSCR SFR $09 ; Timer : Steuerung/Status
+TCR SFR $fe ; Daten
+TPR SFR $fd ; Vorteiler
+
+USERROM SFR $20 ; benutzerdefiniertes ROM (bis $5f)
+USERRAM SFR $82 ; freies RAM (bis $9f)
+
+;---------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef16.inc b/include/stddef16.inc
new file mode 100644
index 0000000..10b11d7
--- /dev/null
+++ b/include/stddef16.inc
@@ -0,0 +1,188 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.39 - Datei STDDEF16.INC *
+;* *
+;* Sinn : enthält SFR- und Makrodefinitionen für die PIC 16C5x-Familie *
+;* *
+;* letzte Änderungen : 13. 4.1993 *
+;* 5. 6.1993 SAVE & RESTORE *
+;* Prozessorsperre (Idee von Matthias) *
+;* 11. 9.1993 Meldung nur im 1.Pass *
+;* *
+;****************************************************************************
+
+ ifndef stddef16inc ; verhindert Mehrfacheinbindung
+
+stddef16inc equ 1
+
+ if (MOMCPU<93268)&&(MOMCPU>93271)
+ fatal "Falscher Prozessortyp eingestellt: nur 16C54..16C57 erlaubt"
+ endif
+
+ if MOMPASS=1
+ message "PIC16C5x-Definitionen (C) 1993 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; erstmal die Spezialregister :
+
+Indirect SFR 0 ; indirekte Adressierung
+PCLo SFR 2 ; PC Bits 0..7
+RTCC SFR 1 ; Zähler
+Status SFR 3 ; Status-Register
+FSR SFR 4 ; File-Select-Register
+Port_A SFR 5 ; Ports
+Port_B SFR 6
+Port_C SFR 7
+
+;----------------------------------------------------------------------------
+; Bits im Statusregister
+
+Flag_C EQU 0 ; Carry
+Flag_DC EQU 1 ; Digit-Carry
+Flag_Z EQU 2 ; Zero
+
+PA1 EQU 5 ; Bank-Select Bit 9
+PA2 EQU 6 ; " " " 10
+
+
+;----------------------------------------------------------------------------
+; Flags setzen/löschen:
+
+clrc macro ; Carry löschen
+ bcf Status,Flag_C
+ endm
+
+setc macro ; Carry setzen
+ bsf Status,Flag_C
+ endm
+
+clrdc macro ; Digit-Carry löschen
+ bcf Status,Flag_DC
+ endm
+
+setdc macro ; Digit_Carry setzen
+ bsf Status,Flag_DC
+ endm
+
+clrz macro ; Zero-Flag löschen
+ bcf Status,Flag_Z
+ endm
+
+setz macro ; Zero-Flag setzen
+ bsf Status,Flag_Z
+ endm
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; einfachere Skip-Befehle
+
+skpc macro ; Sprung, falls C=1
+ btfss Status,Flag_C
+ endm
+
+skpnc macro ; Sprung, falls C=0
+ btfsc Status,Flag_C
+ endm
+
+skpdc macro ; Sprung, falls DC=1
+ btfss Status,Flag_DC
+ endm
+
+skpndc macro ; Sprung, falls DC=0
+ btfsc Status,Flag_DC
+ endm
+
+skpz macro ; Sprung, falls Z=1
+ btfss Status,Flag_Z
+ endm
+
+skpnz macro ; Sprung, falls Z=0
+ btfsc Status,Flag_Z
+ endm
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; bedingte Sprünge:
+; VORSICHT: Mehrbyteanweisungen, nicht skip-bar!!!!
+
+b macro target ; unbedingter Sprung
+ goto target
+ endm
+
+bc macro target ; Sprung, falls C=1
+ btfsc Status,Flag_C
+ goto target
+ endm
+
+bnc macro target ; Sprung, falls C=0
+ btfss Status,Flag_C
+ goto target
+ endm
+
+bdc macro target ; Sprung, falls DC=1
+ btfsc Status,Flag_DC
+ goto target
+ endm
+
+bndc macro target ; Sprung, falls DC=0
+ btfss Status,Flag_DC
+ goto target
+ endm
+
+bz macro target ; Sprung, falls Z=1
+ btfss Status,Flag_Z
+ goto target
+ endm
+
+bnz macro target ; Sprung, falls Z=0
+ btfsc Status,Flag_Z
+ goto target
+ endm
+
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; Carry-Arithmetik
+; wieder VORSICHT!!!
+
+addcf macro reg,dest ; Carry zu Register addieren
+ btfsc Status,Flag_C
+ incf reg,dest
+ endm
+
+adddcf macro reg,dest ; Digit-Carry zu Register addieren
+ btfsc Status,Flag_DC
+ incf reg,dest
+ endm
+
+subcf macro reg,dest ; Carry von Register subtrahieren
+ btfsc Status,Flag_C
+ decf reg,dest
+ endm
+
+subdcf macro reg,dest ; Digit-Carry von Register subtrahieren
+ btfsc Status,Flag_DC
+ decf reg,dest
+ endm
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; vermischtes...
+
+movfw macro reg ; Transfer Register-->W
+ movf reg,0
+ endm
+
+negf macro reg,dest ; Zweierkomplement
+ comf reg,1
+ incf reg,dest
+ endm
+
+tstf macro reg ; Flags entspr. Register bilden
+ movf reg,1
+ endm
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef17.inc b/include/stddef17.inc
new file mode 100644
index 0000000..4cd71ea
--- /dev/null
+++ b/include/stddef17.inc
@@ -0,0 +1,116 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.39 - Datei STDDEF17.INC *
+;* *
+;* Sinn : enthält SFR-Definitionen für die PIC 17C4x-Familie *
+;* Die Makrodefinitionen kann man bei Bedarf aus STDDEF16.INC *
+;* kopieren *
+;* *
+;* letzte Änderungen : 24. 4.1993 *
+;* 5. 6.1993 SAVE & RESTORE *
+;* Prozessorsperre (Idee von Matthias) *
+;* 11. 9.1993 Meldung nur im 1.Pass *
+;* *
+;****************************************************************************
+
+ ifndef stddef17inc ; verhindert Mehrfacheinbindung
+
+stddef17inc equ 1
+
+ if (MOMCPU<>97346)
+ fatal "Falscher Prozessortyp eingestellt: nur 17C42 erlaubt"
+ endif
+
+ if MOMPASS=1
+ message "PIC17C4x-Definitionen (C) 1993 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; CPU-Register
+
+Indirect0 SFR 0 ; indirekte Adressierung 1
+FSR0 SFR 1
+Indirect1 SFR 8 ; indirekte Adressierung 2
+FSR1 SFR 9
+PCL SFR 2 ; Bit 0..7 Programmzähler
+PCLATH SFR 3 ; Hilfsregister PC Bit 8..15
+W SFR 10 ; Akkumulator
+TBLPTRL SFR 13 ; Hilfsregister, um Daten
+TBLPTRH SFR 14 ; aus Codebereich zu lesen
+ALUSTA SFR 4 ; Flags, FSR-Modi
+CPUSTA SFR 6 ; CPU-Status
+INTSTA SFR 7 ; Interrupt-Status
+
+;------------------------------------------------------------------------------
+; Zähler
+
+RTCSTA SFR 5 ; Steuerregister
+RTCCL SFR 11 ; Daten
+RTCCH SFR 12
+
+;------------------------------------------------------------------------------
+
+BSR SFR 15 ; Bankauswahl Rest
+
+;------------------------------------------------------------------------------
+; Interruptsteuerung
+
+PIR SFR $16 ; Interrupt-Anforderungen
+PIE SFR $17 ; Interrupt-Freigaben
+
+;------------------------------------------------------------------------------
+; Ports
+
+PORTA SFR $10 ; Datenregister
+PORTB SFR $12
+PORTC SFR $11
+PORTD SFR $13
+PORTE SFR $15
+
+DDRB SFR $11 ; Richtungsregister
+DDRC SFR $10
+DDRD SFR $12
+DDRE SFR $14
+
+;------------------------------------------------------------------------------
+; serieller Port
+
+RCSTA SFR $13 ; Empfängerstatus
+RCREG SFR $14 ; Empfängerdaten
+TXSTA SFR $15 ; Senderstatus
+TXREG SFR $16 ; Sendedaten
+SPBRG SFR $17 ; Teiler für SIO
+
+;------------------------------------------------------------------------------
+; Timer
+
+TMR1 SFR $10 ; Daten Timer 1
+TMR2 SFR $11 ; Daten Timer 2
+TMR3L SFR $12 ; Daten Timer 3
+TMR3H SFR $13
+
+PR1 SFR $14 ; Periode Timer 1
+PR2 SFR $15 ; Periode Timer 2
+PR3L SFR $16 ; Periode Timer 3
+PR3H SFR $17
+
+CA1L SFR $16 ; Fangwert 1
+CA1H SFR $17
+CA2L SFR $14 ; Fangwert 1
+CA2H SFR $15
+
+PW1DCL SFR $10 ; PWM 1 Daten
+PW1DCH SFR $12
+PW2DCL SFR $11 ; PWM 2 Daten
+PW2DCH SFR $13
+
+TCON1 SFR $16 ; Steuerregister 1
+TCON2 SFR $17 ; Steuerregister 2
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef18.inc b/include/stddef18.inc
new file mode 100644
index 0000000..672c76a
--- /dev/null
+++ b/include/stddef18.inc
@@ -0,0 +1,262 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF18.INC *
+;* *
+;* Sinn : enthält die SFR-Definitionen für die PIC 16C8x-Familie *
+;* Die Makrodefinitionen kann man bei Bedarf aus STDDEF16.INC *
+;* kopieren *
+;* *
+;* letzte Änderungen : 14.11.1993 *
+;* 27. 2.1993 PIC16C64-Register *
+;* IND0-->INDF umbenannt *
+;* *
+;****************************************************************************
+
+ ifndef stddef18inc ; verhindert Mehrfacheinbindung
+
+stddef18inc equ 1
+
+ if (MOMCPU<93316)&&(MOMCPU<>93284)
+ fatal "Falscher Prozessortyp eingestellt: nur 16C84 oder 16C64 erlaubt"
+ endif
+
+ if MOMPASS=1
+ message "PIC16C8x-Definitionen (C) 1993 Alfred Arnold"
+ message "binde \{MOMCPU}-Register ein"
+ endif
+
+;----------------------------------------------------------------------------
+; erstmal die Spezialregister :
+
+INDF SFR 0 ; indirekte Adressierung
+PCL SFR 2 ; PC Bits 0..7
+PCLATH SFR 10 ; obere Hälfte Programmzähler
+Status SFR 3 ; Status-Register
+FSR SFR 4 ; File-Select-Register
+OPTION SFR $81 ; Chipkonfiguration
+ if MOMCPU=$16C64
+PCON SFR $8e
+ endif
+
+;----------------------------------------------------------------------------
+; Ports
+
+PortA SFR 5 ; Datenregister Port A
+TrisA SFR $85 ; Datenrichtungsregister Port A
+PortB SFR 6 ; Datenregister Port C
+TrisB SFR $86 ; Datenrichtungsregister Port B
+ if MOMCPU=$16C64
+PortC SFR 7 ; Datenregister Port C
+TrisC SFR $87 ; Datenrichtungsregister Port C
+PortD SFR 8 ; Datenregister Port D
+TrisD SFR $88 ; Datenrichtungsregister Port D
+PortE SFR 9 ; Datenregister Port E
+TrisE SFR $89 ; Datenrichtungsregister Port E
+ endif
+
+;----------------------------------------------------------------------------
+; Timer
+
+ if MOMCPU=$16C64
+TMR0 SFR 1 ; Zähler 0
+TMR1L SFR 14 ; Zähler 1
+TMR1H SFR 15
+TMR2 SFR 17 ; Zähler 2
+CCPR1L SFR $15 ; Vergleichs/Pulsweitenregister
+CCPR1H SFR $16
+T1CON SFR 16 ; Steuerung Zähler 1
+T2CON SFR 18 ; Steuerung Zähler 2
+PR2 SFR $92 ; Periode Zähler 2
+CCP1CON SFR $17 ; Modus Vergleicher
+ elseif
+RTCC SFR 1 ; Zähler
+ endif
+
+;----------------------------------------------------------------------------
+; serielle Schnittstelle
+
+ if MOMCPU=$16C64
+SSPBuf SFR $13 ; serielles Datenregister
+SSPCon SFR $14 ; Konfiguration
+SSPAD0 SFR $93 ; I2C-Adreßregister
+SSPSTAT SFR $94 ; Schnittstellenstatus
+ endif
+
+;----------------------------------------------------------------------------
+; EEPROM
+
+ if MOMCPU=$16C84
+EEData SFR 8 ; EEPROM Datenregister
+EEAdr SFR 9 ; EEPROM Adreßregister
+EECON1 SFR $88 ; Konfiguration EEPROM
+EECON2 SFR $89
+ endif
+
+;----------------------------------------------------------------------------
+; Interrupts
+
+INTCON SFR 11 ; Interruptsteuerung
+ if MOMCPU=$16C64
+PIR SFR 12 ; Interrupts aufgetreten ?
+PIE SFR $8c ; Interruptfreigabe
+ endif
+
+;============================================================================
+; Bits im Statusregister
+
+Flag_C EQU 0 ; Carry
+Flag_DC EQU 1 ; Digit-Carry
+Flag_Z EQU 2 ; Zero
+Flag_PD EQU 3 ; Aufgewacht aus SLEEP-Befehl ?
+Flag_TO EQU 4 ; Durch Watchdog zurückgesetzt ?
+Flag_RP0 EQU 5 ; Registerbank Bit 8
+ if MOMCPU=$16C84
+Flag_RP1 EQU 6 ; Registerbank Bit 9
+Flag_IRP EQU 7 ; Registerbnak Bit 9 (indirekt)
+ endif
+
+;----------------------------------------------------------------------------
+; Bits in TrisE
+
+ if MOMCPU=$16C64
+TRISE0 EQU 0 ; Datenrichtung RE0
+TRISE1 EQU 1 ; Datenrichtung RE1
+TRISE2 EQU 2 ; Datenrichtung RE2
+PSPMODE EQU 4 ; Modus Port D&E
+IBOV EQU 5 ; Überlauf Eingabepuffer
+OBF EQU 6 ; Ausgabepuffer voll
+IBF EQU 7 ; Eingabepuffer voll
+ endif
+
+;----------------------------------------------------------------------------
+; Bits in T1CON
+
+ if MOMCPU=$16C64
+TMR1ON EQU 0 ; Timer 1 starten
+TMR1CS EQU 1 ; Timer 1 mit internem/externem Takt
+T1INSYNC EQU 2 ; Timer 1 extern synchronisieren
+T1OSCEN EQU 3 ; Oszillator Timer 1 freigeben
+T1CKPS0 EQU 4 ; Vorteilerwahl Timer 1
+T1CKPS1 EQU 5
+ endif
+
+; Bits in T2CON
+
+ if MOMCPU=$16C64
+T2CKPS0 EQU 0 ; Vorteilerwahl Timer 2
+T2CKPS1 EQU 1
+TMR2ON EQU 2 ; Timer 2 ein/ausschalten
+TOUTPS0 EQU 3 ; Nachteilerwahl Timer 2
+TOUTPS1 EQU 4
+TOUTPS2 EQU 5
+TOUTPS3 EQU 7
+ endif
+
+; Bits in CCP1CON
+
+ if MOMCPU=$16C64
+CCP1M0 EQU 0 ; Modus CCP1
+CCP1M1 EQU 1
+CCP1M2 EQU 2
+CCP1M3 EQU 3
+CCP1Y EQU 4 ; PWM Bits 0,1
+CCP1X EQU 5
+ endif
+
+;----------------------------------------------------------------------------
+; Bits in SSPSTAT
+
+ if MOMCPU=$16C64
+BF EQU 0 ; Puffer voll ?
+UA EQU 1 ; neue Adresse muß in SSPADD geschrieben werden
+RW EQU 2 ; I2C lesen/schreiben ?
+S EQU 3 ; Startbit gefunden ?
+P EQU 4 ; Stopbit gefunden
+DA EQU 5 ; I2C Datum/Adresse empfangen ?
+ endif
+
+; Bits in SSPCON
+
+ if MOMCPU=$16C64
+SSPM0 EQU 0 ; Schnittstellenmodus
+SSPM1 EQU 1
+SSPM2 EQU 2
+SSPM3 EQU 3
+CKP EQU 4 ; Taktpolarität
+SSPEN EQU 5 ; Portfreigabe
+SSPOV EQU 6 ; Empfägerüberlauf
+WCOL EQU 7 ; Senderkollision
+ endif
+
+;----------------------------------------------------------------------------
+; Bits in INTCON
+
+RBIF EQU 0 ; auf 1, falls Pegelwechsel an PB4..7
+INTF EQU 1 ; Interrupt aufgetreten
+RTIF EQU 2 ; RTCC-Interrupt
+RBIE EQU 3 ; Interrupts durch Bit 0 freigeben
+INTE EQU 4 ; Interrupts durch Bit 1 freigeben
+RTIE EQU 5 ; Interrupts durch Bit 2 freigeben
+ if MOMCPU=$16C84
+EEIE EQU 6 ; Interrupts vom EEPROM freigeben
+ elseif
+PEIE EQU 6 ; Peripherie-Interrupts freigeben
+ endif
+GIE EQU 7 ; globale Interruptsperre
+
+; Bits in PIE1
+
+ if MOMCPU=$16C64
+TMR1IE EQU 0 ; Interrupts Timer 1 freigeben
+TMR2IE EQU 1 ; Interrupts Timer 2 freigeben
+CCP1IE EQU 2 ; Interrupts CCP1 freigeben
+SSPIE EQU 3 ; Interrupts serielle Schnittstelle freigeben
+PSPIE EQU 7 ; Interrupts Parallelport freigeben
+ endif
+
+; Bits in PIR1
+
+ if MOMCPU=$16C64
+TMR1IF EQU 0 ; Interrupt Timer 1 aufgetreten
+TMR2IF EQU 1 ; Interrupt Timer 2 aufgetreten
+CCP1IF EQU 2 ; Interrupt CCP1 aufgetreten
+SSPIF EQU 3 ; Interrupt serielle Schnittstelle aufgetreten
+PSPIF EQU 7 ; Interrupt Parallelport aufgetreten
+ endif
+
+;----------------------------------------------------------------------------
+; Bits in OPTION
+
+PS0 EQU 0 ; Einstellung Vorteiler
+PS1 EQU 1
+PS2 EQU 2
+PSA EQU 3 ; Vorteile-Zuordnung
+RTE EQU 4 ; Triggerflanke RTCC
+RTS EQU 5 ; RTCC-Signalquelle
+INTEDG EQU 6 ; INT-Triggerflanke
+RBPU EQU 7 ; Pull-Ups an Port B freigeben
+
+;Bits in PCON
+
+ if MOMCPU=$16C64
+POR EQU 1 ; 0=Power-On-Reset aufgetreten
+ endif
+
+;----------------------------------------------------------------------------
+; Bits in EECON1
+
+ if MOMCPU=$16C84
+RD EQU 0 ; Lesezyklus starten
+WR EQU 1 ; Schreibzyklus starten
+WREN EQU 2 ; Schreibsperre
+WRERR EQU 3 ; Schreibvorgang abgebrochen
+EEIF EQU 4 ; signalisiert Schreibende
+ endif
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef2x.inc b/include/stddef2x.inc
new file mode 100644
index 0000000..5a774de
--- /dev/null
+++ b/include/stddef2x.inc
@@ -0,0 +1,53 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF2X.INC *
+;* *
+;* Sinn : enthält die globalen Register-Definitionen für die *
+;* TMS320C2x Prozessoren *
+;* *
+;* letzte Änderungen : 27.02.1994 *
+;* *
+;****************************************************************************
+
+ ifndef stddef2xinc ; verhindert Mehrfacheinbindung
+
+stddef2xinc equ 1
+
+ if (MOMCPUNAME<>"320C25") && (MOMCPUNAME<>"320C26") && (MOMCPUNAME<>"320C28")
+ fatal "Falscher Prozessortyp eingestellt: nur 320C25, 320C26 und 320C28 erlaubt!"
+ endif
+
+ if MOMPASS=1
+ message "TMS320C2x Register-Definitionen (C) 1994 Thomas Sailer"
+ endif
+
+;----------------------------------------------------------------------------
+ segment data
+ org 0
+
+DRR res 1
+DXR res 1
+TIM res 1
+PRD res 1
+IMR res 1
+GREG res 1
+
+ if (MOMCPUNAME="320C26")
+B2_D equ 60h
+B0_D equ 200h
+B1_D equ 400h
+B3_D equ 600h
+B0_P equ 0fa00h
+B1_P equ 0fc00h
+B3_P equ 0fe00h
+ endif
+
+;---------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef37.inc b/include/stddef37.inc
new file mode 100644
index 0000000..7498f82
--- /dev/null
+++ b/include/stddef37.inc
@@ -0,0 +1,527 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF37.INC *
+;* *
+;* Sinn : enthält SFR- und Bitdefinitionen für die TMS370-Prozessoren *
+;* *
+;* letzte Änderungen : 12. 5.1993 *
+;* *
+;****************************************************************************
+
+ ifndef stddef37inc ; verhindert Mehrfacheinbindung
+
+stddef37inc equ 1
+
+ if (MOMCPU<>57720848)&&(MOMCPU<>57720864)&&(MOMCPU<>57720880)&&(MOMCPU<>57720896)&&(MOMCPU<>57720912)
+ fatal "Falscher Prozessortyp eingestellt: nur 370C010, 370C020, 370C030, 370C040 oder 370C050 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "TMS370-Register-Definitionen (C) 1994 Alfred Arnold"
+ message "binde \{MOMCPU}-SFRs ein"
+ endif
+
+; Das mit diesen langen Namen ist ja wohl nicht ernst gemeint ???
+
+;----------------------------------------------------------------------------
+; Systemsteuerung
+
+sccr0 equ p010
+cold_start dbit 7,sccr0 ; Kaltstart ?
+osc_power dbit 6,sccr0 ; Stromaufnahme Oszillator reduzieren
+pf_auto_wait dbit 5,sccr0 ; Wartezyklen für externe Peripherie
+osc_flt_flag dbit 4,sccr0 ; Fehler in Oszillatorschaltung ?
+mc_pin_wpo dbit 3,sccr0 ; Spannung an MC hoch genug ?
+mc_pin_data dbit 2,sccr0 ; Zustand des MC-Anschlusses
+up_uc_mode dbit 0,sccr0 ; Mikroprozessor/Mikrokontroller-Modus
+
+sccr1 equ p011
+auto_wait_disable dbit 4,sccr1 ; Wartezyklen für externen Speicher
+memory_disable dbit 2,sccr1 ; int. ROM abschalten
+
+sccr2 equ p012
+halt_standby dbit 7,sccr2 ; Halt oder /Standby-Modus
+pwrdwn_idle dbit 6,sccr2 ; /Idle oder Halt/Standby-Modus
+bus_stest dbit 4,sccr2 ; Bus-Selbsttest ??
+cpu_stest dbit 3,sccr2 ; Prozessor-Selbsttest ??
+int1_nmi dbit 1,sccr2 ; Interrupt 1 maskierbar/nicht maskierbar
+privilege_disable dbit 0,sccr2 ; privilegierten Modus verlassen
+
+;----------------------------------------------------------------------------
+; digitaler IO
+
+aport1 equ p020
+aport2 equ p021
+adata equ p022 ; Port A Datenregister
+adir equ p023 ; Port A Datenrichtungsregister
+
+ if (MOMCPU=370C020h)||(MOMCPU>370C030h)
+bport1 equ p024
+bport2 equ p025
+bdata equ p026 ; Port B Datenregister
+bdir equ p027 ; Port B Datenrichtungsregister
+ endif
+
+ if (MOMCPU=370C020h)||(MOMCPU=370C050h)
+cport1 equ p028
+cport2 equ p029
+cdata equ p02a ; Port C Datenregister
+cdir equ p02b ; Port C Datenrichtungsregister
+ endif
+
+dport1 equ p02c
+dport2 equ p02d
+ddata equ p02e ; Port D Datenregister
+ddir equ p02f ; Port D Datenrichtungsregister
+
+;----------------------------------------------------------------------------
+; Interrupts
+
+int1 equ p017
+int1_enable dbit 0,int1 ; Freigabe externer Interrupt 1
+int1_priority dbit 1,int1 ; Priorität externer Interrupt 1
+int1_polarity dbit 2,int1 ; Polarität externer Interrupt 1
+int1_pin_data dbit 6,int1 ; Zustand Interrupt 1-Pin
+int1_flag dbit 7,int1 ; externer Interrupt 1 aufgetreten
+
+int2 equ p018
+int2_enable dbit 0,int2 ; Freigabe externer Interrupt 2
+int2_priority dbit 1,int2 ; Priorität externer Interrupt 2
+int2_polarity dbit 2,int2 ; Polarität externer Interrupt 2
+int2_data_out dbit 3,int2 ; Ausgabewert Interrupt 2-Pin
+int2_data_dir dbit 4,int2 ; Datenrichtung Interrupt 2-Pin
+int2_pin_data dbit 6,int2 ; Zustand Interrupt 2-Pin
+int2_flag dbit 7,int2 ; externer Interrupt 2 aufgetreten
+
+int3 equ p019
+int3_enable dbit 0,int3 ; Freigabe externer Interrupt 3
+int3_priority dbit 1,int3 ; Priorität externer Interrupt 3
+int3_polarity dbit 2,int3 ; Polarität externer Interrupt 3
+int3_data_out dbit 3,int3 ; Ausgabewert Interrupt 3-Pin
+int3_data_dir dbit 4,int3 ; Datenrichtung Interrupt 3-Pin
+int3_pin_data dbit 6,int3 ; Zustand Interrupt 3-Pin
+int3_flag dbit 7,int3 ; externer Interrupt 3 aufgetreten
+
+;----------------------------------------------------------------------------
+; (E)EPROM
+
+deectl equ p01a
+ee_busy dbit 7,deectl ; EEPROM nicht zugreifbar
+ap dbit 2,deectl ; Blockprogrammierung freigeben
+w1w0 dbit 1,deectl ; Einsen oder Nullen programmieren ?
+ee_exe dbit 0,deectl ; Vorgang ausführen
+
+epctl0 equ p01c
+ep0_busy dbit 7,epctl0 ; EPROM Teil 1 nicht zugreifbar
+ep0_vpps dbit 6,epctl0 ; Brennspannung freigeben
+ep0_w0 dbit 1,epctl0 ; Schreiben von Nullen freigeben
+ep0_exe dbit 0,epctl0 ; Schreibvorgang ausführen
+
+epctl1 equ p01e
+ep1_busy dbit 7,epctl1 ; EPROM Teil 2 nicht zugreifbar
+ep1_vpps dbit 6,epctl1 ; Brennspannung freigeben
+ep1_w0 dbit 1,epctl1 ; Schreiben von Nullen freigeben
+ep1_exe dbit 0,epctl1 ; Schreibvorgang ausführen
+
+;----------------------------------------------------------------------------
+; Timer 1
+
+t1ctl1 equ p049 ; steuern auch Watchdog
+t1ctl2 equ p04a
+
+ if MOMCPU<>370C030h
+t1cntrh equ p040 ; Zählerregister
+t1cntrl equ p041
+
+t1ch equ p042 ; Vergleichsregister
+t1cl equ p043
+
+t1cch equ p044 ; Vergleichs/Fangregister
+t1ccl equ p045
+
+t1_input_select0 dbit 0,t1ctl1 ; Taktquelle
+t1_input_select1 dbit 1,t1ctl1
+t1_input_select2 dbit 2,t1ctl1
+
+t1_sw_reset dbit 0,t1ctl2 ; Zähler zurücksetzen
+t1_ovrfl_int_flag dbit 3,t1ctl2 ; Overflow aufgetreten ?
+t1_ovrfl_int_ena dbit 4,t1ctl2 ; Overflow-Interrupts freigeben
+
+t1ctl3 equ p04b
+t1c1_int_ena dbit 0,t1ctl3 ; Interrupts Vergleichsregister freigeben
+t1c2_int_ena dbit 1,t1ctl3 ; Interrupts Vergleichs(/Fang)register freigeben
+t1edge_int_ena dbit 2,t1ctl3 ; Interrupts bei Flanke an T1IC/CR freigeben
+t1c1_int_flag dbit 5,t1ctl3 ; Interrupt durch Vergleichsregister ?
+t1c2_int_flag dbit 6,t1ctl3 ; Interrupt durch Vergleichs(/Fang)register ?
+t1edge_int_flag dbit 7,t1ctl3 ; Interrupt durch Flanke an T1IC/CR ?
+
+t1ctl4 equ p04c
+t1edge_det_ena dbit 0,t1ctl4 ; Flankendetektor an T1IC/CR freigeben
+t1cr_rst_ena dbit 1,t1ctl4 ; externen Reset freigeben
+t1edge_polarity dbit 2,t1ctl4 ; Flankenwahl T1IC/CR
+t1cr_out_ena dbit 3,t1ctl4 ; Umschaltung PWM durch T1IC/CR freigeben
+t1c1_rst_ena dbit 4,t1ctl4 ; Rücksetzen durch Vergleicher freigeben
+t1c2_out_ena dbit 5,t1ctl4 ; Umschaltung PWM durch Vergleichs(/Fang)register freigeben
+t1c1_out_ena dbit 6,t1ctl4 ; Umschaltung PWM durch Vergleichsregister freigeben
+t1_mode dbit 7,t1ctl4 ; Modus Timer 1
+
+t1pc1 equ p04d
+t1evt_data_dir dbit 0,t1pc1 ; Timer 1 Event-Pin Datenrichtung
+t1evt_function dbit 1,t1pc1 ; Timer 1 Event-Pin Funktionsumschaltung
+t1evt_data_out dbit 2,t1pc1 ; Timer 1 Event-Pin Datenausgang
+t1evt_data_in dbit 3,t1pc1 ; Timer 1 Event-Pin Dateneingang
+
+t1pc2 equ p04e
+t1iccr_data_dir dbit 0,t1pc2 ; T1IC/CR-Pin Datenrichtung
+t1iccr_function dbit 1,t1pc2 ; T1IC/CR-Pin Funktionsumschaltung
+t1iccr_data_out dbit 2,t1pc2 ; T1IC/CR-Pin Datenausgang
+t1iccr_data_in dbit 3,t1pc2 ; T1IC/CR-Pin Dateneingang
+t1pwm_data_dir dbit 4,t1pc2 ; T1PWM-Pin Datenrichtung
+t1pwm_function dbit 5,t1pc2 ; T1PWM-Pin Funktionsumschaltung
+t1pwm_data_out dbit 2,t1pc2 ; T1PWM-Pin Datenausgang
+t1pwm_data_in dbit 7,t1pc2 ; T1PWM-Pin Dateneingang
+
+t1pri equ p04f
+t1_priority dbit 6,t1pri ; Priorität Interrupts Timer 1
+t1_stest dbit 7,t1pri ; Selbsttest Timer 1
+ endif
+
+;----------------------------------------------------------------------------
+; Timer 2
+
+ if MOMCPU>370C030H
+t2cntrh equ p060 ; Zählerregister
+t2cntrl equ p061
+
+t2ch equ p062 ; Vergleichsregister
+t2cl equ p063
+
+t2cch equ p064 ; Vergleichs/Fangregister
+t2ccl equ p065
+
+t2ich equ p066 ; Fangregister
+t2icl equ p067
+
+t2ctl1 equ p06a
+t2_sw_reset dbit 0,t2ctl1 ; Zähler zurücksetzen
+t2_input_select0 dbit 1,t2ctl1 ; Taktquelle
+t2_input_select1 dbit 2,t2ctl1
+t2_ovrfl_int_flag dbit 3,t2ctl1 ; Overflow aufgetreten ?
+t2_ovrfl_int_ena dbit 4,t2ctl1 ; Overflow-Interrupts freigeben
+
+t2ctl2 equ p06b
+t2c1_int_ena dbit 0,t2ctl2 ; Interrupts Vergleichsregister freigeben
+t2c2_int_ena dbit 1,t2ctl2 ; Interrupts Vergleichs(/Fang)register freigeben
+t2edge1_int_ena dbit 2,t2ctl2 ; Interrupts bei Flanke an T2IC1/CR freigeben
+t2c1_int_flag dbit 5,t2ctl2 ; Interrupt durch Vergleichsregister ?
+t2c2_int_flag dbit 6,t2ctl2 ; Interrupt durch Vergleichs(/Fang)register ?
+t2edge1_int_flag dbit 7,t2ctl2 ; Interrupt durch Flanke an T2IC1/CR ?
+
+t2ctl3 equ p06c
+t2edge1_det_ena dbit 0,t2ctl3 ; Flankendetektor an T2IC1/CR freigeben
+t2edge1_rst_ena dbit 1,t2ctl3 ; externen Reset freigeben
+t2edge2_det_ena dbit 1,t2ctl3 ; Flankendetektor an T2IC2/CR freigeben
+t2edge1_polarity dbit 2,t2ctl3 ; Flankenwahl T2IC1/CR
+t2edge1_out_ena dbit 3,t2ctl3 ; Umschaltung PWM durch T2IC1/CR freigeben
+t2edge2_polarity dbit 3,t2ctl3 ; Flankenwahl T2IC2/CR
+t2c1_rst_ena dbit 4,t2ctl3 ; Rücksetzen durch Vergleicher freigeben
+t2c2_out_ena dbit 5,t2ctl3 ; Umschaltung PWM durch Vergleichs(/Fang)register freigeben
+t2c1_out_ena dbit 6,t2ctl3 ; Umschaltung PWM durch Vergleichsregister freigeben
+t2_mode dbit 7,t2ctl3 ; Modus Timer 2
+
+t2pc1 equ p06d
+t2evt_data_dir dbit 0,t2pc1 ; Timer 2 Event-Pin Datenrichtung
+t2evt_function dbit 1,t2pc1 ; Timer 2 Event-Pin Funktionsumschaltung
+t2evt_data_out dbit 2,t2pc1 ; Timer 2 Event-Pin Datenausgang
+t2evt_data_in dbit 3,t2pc1 ; Timer 2 Event-Pin Dateneingang
+
+t2pc2 equ p06e
+t2ic1cr_data_dir dbit 0,t1pc2 ; T2IC1/CR-Pin Datenrichtung
+t2ic1cr_function dbit 1,t1pc2 ; T2IC1/CR-Pin Funktionsumschaltung
+t2ic1cr_data_out dbit 2,t1pc2 ; T2IC1/CR-Pin Datenausgang
+t2ic1cr_data_in dbit 3,t1pc2 ; T2IC1/CR-Pin Dateneingang
+t2ic2cr_data_dir dbit 4,t1pc2 ; T2IC2/CR-Pin Datenrichtung
+t2ic2cr_function dbit 5,t1pc2 ; T2IC2/CR-Pin Funktionsumschaltung
+t2ic2cr_data_out dbit 6,t1pc2 ; T2IC2/CR-Pin Datenausgang
+t2ic2cr_data_in dbit 7,t1pc2 ; T2IC2/CR-Pin Dateneingang
+t2pwm_data_dir dbit 4,t1pc2 ; T2PWM-Pin Datenrichtung
+t2pwm_function dbit 5,t1pc2 ; T2PWM-Pin Funktionsumschaltung
+t2pwm_data_out dbit 6,t1pc2 ; T2PWM-Pin Datenausgang
+t2pwm_data_in dbit 7,t1pc2 ; T2PWM-Pin Dateneingang
+
+t2pri equ p06f
+t2_priority dbit 6,t2pri ; Priorität Interrupts Timer 2
+t2_stest dbit 7,t2pri ; Selbsttest Timer 2
+ endif
+
+;----------------------------------------------------------------------------
+; Watchdog
+
+ if MOMCPU<>370C030h
+wdcntrh equ p046 ; Zählregister
+wdcntrl equ p047
+
+wdrst equ p048 ; Rücksetz-Schlüsselregister
+
+wd_input_select0 dbit 4,t1ctl1 ; Taktquelle
+wd_input_select1 dbit 5,t1ctl1
+wd_input_select2 dbit 6,t1ctl1
+wd_ovrfl_tap_sel dbit 7,t1ctl1 ; 15- oder 16-bittig zählen
+wd_ovrfl_int_flag dbit 5,t1ctl2 ; Watchdog-Reset aufgetreten ?
+wd_ovrfl_int_ena dbit 6,t1ctl2 ; Watchdog-Interrupts freigeben
+wd_ovrfl_rst_ena dbit 7,t1ctl2 ; Watchdog-Resets freigeben
+ endif
+
+;----------------------------------------------------------------------------
+; SCI
+
+ if (MOMCPU=370C020h)||(MOMCPU>370C030h)
+sciccr equ p050
+sci_char0 dbit 0,sciccr ; Zeichenlänge
+sci_char1 dbit 1,sciccr
+sci_char2 dbit 2,sciccr
+address_idle_wup dbit 3,sciccr ; Multiprozessormodus
+async_iosync dbit 4,sciccr ; Betriebsart: synchron/asynchron
+parity_enable dbit 5,sciccr ; mit/ohne Parität
+even_odd_parity dbit 6,sciccr ; gerade/ungerade Parität
+stop_bits dbit 7,sciccr ; Anzahl Stopbits
+
+scictl equ p051
+rxena dbit 0,scictl ; Empfängerfreigabe
+txena dbit 1,scictl ; Senderfreigabe
+sleep dbit 2,scictl ; Sleep-Modus SCI
+txwake dbit 3,scictl ; Sender aufwecken
+clock dbit 4,scictl ; interner/externer Takt SCI
+sci_sw_reset dbit 5,scictl ; Software-Reset
+
+baud_msb equ p052 ; Baudratengenerator
+baud_lsb equ p053
+
+txctl equ p054
+sci_tx_int_ena dbit 0,txctl ; Interrupts durch Sender freigeben
+tx_empty dbit 6,txctl ; Sender komplett leer ?
+txrdy dbit 7,txctl ; neues Datum kann geschrieben werden
+
+rxctl equ p055
+sci_rx_int_ena dbit 0,rxctl ; Interrupts durch Empfänger freigeben
+rxwake dbit 1,rxctl ; Ist Empfänger aufgeweckt worden ?
+sci_pe dbit 2,rxctl ; Paritätsfehler ?
+sci_oe dbit 3,rxctl ; Überlauffehler ?
+sci_fe dbit 4,rxctl ; kein korrektes Stopbit ?
+brkdt dbit 5,rxctl ; Break aufgetreten ?
+rxrdy dbit 6,rxctl ; Zeichen empfangen ?
+rx_error dbit 7,rxctl ; Empfangsfehler aufgetreten ?
+
+rxbuf equ p057 ; Datenregister
+txbuf equ p059
+
+scipc1 equ p05d
+sciclk_data_dir dbit 0,scipc1 ; SCICLK-Pin Datenrichtung
+sciclk_function dbit 1,scipc1 ; SCICLK-Pin Funktionsumschaltung
+sciclk_data_out dbit 2,scipc1 ; SCICLK-Pin Datenausgang
+sciclk_data_in dbit 3,scipc1 ; SCICLK-Pin Dateneingang
+
+scipc2 equ p05e
+scirxd_data_dir dbit 0,scipc2 ; SCIRXD-Pin Datenrichtung
+scirxd_function dbit 1,scipc2 ; SCIRXD-Pin Funktionsumschaltung
+scirxd_data_out dbit 2,scipc2 ; SCIRXD-Pin Datenausgang
+scirxd_data_in dbit 3,scipc2 ; SCIRXD-Pin Dateneingang
+scitxd_data_dir dbit 4,scipc2 ; SCITXD-Pin Datenrichtung
+scitxd_function dbit 5,scipc2 ; SCITXD-Pin Funktionsumschaltung
+scitxd_data_out dbit 6,scipc2 ; SCITXD-Pin Datenausgang
+scitxd_data_in dbit 7,scipc2 ; SCITXD-Pin Dateneingang
+
+scipri equ p05f
+sci_espen dbit 4,scipri ; SCI emulator suspend ?!
+scirx_priority dbit 5,scipri ; SCI Empfangsinterrupt Priorität
+scitx_priority dbit 6,scipri ; SCI Sendeinterrupt Priorität
+sci_test dbit 7,scipri ; SCI Selbsttest
+ endif
+
+;----------------------------------------------------------------------------
+; SPI
+
+ if (MOMCPU<370C030h)||(MOMCPU=370C050h)
+spiccr equ p030
+spi_char0 dbit 0,spiccr ; Zeichenlänge
+spi_char1 dbit 1,spiccr
+spi_char2 dbit 2,spiccr
+spi_bit_rate0 dbit 3,spiccr ; Bitrate
+spi_bit_rate1 dbit 4,spiccr
+spi_bit_rate2 dbit 5,spiccr
+clock_polarity dbit 6,spiccr ; Polarität Taktsignal
+spi_sw_reset dbit 7,spiccr ; Software-Reset
+
+spictl equ p031
+spi_int_ena dbit 0,spictl ; Interrupt-Freigabe
+talk dbit 1,spictl ; Slave/Master-Senderfreigabe
+master_slave dbit 2,spictl ; Slave/Master-Umschaltung
+spi_int_flag dbit 6,spictl ; Interrupt aufgetreten ?
+receiver_overrun dbit 7,spictl ; EMpfängerüberlauf ?
+
+spibuf equ p037 ; Empfängerpuffer
+spidat equ p039 ; Senderegister
+
+spipc1 equ p03d
+spiclk_data_dir dbit 0,spipc1 ; SPICLK-Pin Datenrichtung
+spiclk_function dbit 1,spipc1 ; SPICLK-Pin Funktionsumschaltung
+spiclk_data_out dbit 2,spipc1 ; SPICLK-Pin Datenausgang
+spiclk_data_in dbit 3,spipc1 ; SPICLK-Pin Dateneingang
+
+spipc2 equ p03e
+spisomi_data_dir dbit 0,spipc2 ; SPISOMI-Pin Datenrichtung
+spisomi_function dbit 1,spipc2 ; SPISOMI-Pin Funktionsumschaltung
+spisomi_data_out dbit 2,spipc2 ; SPISOMI-Pin Datenausgang
+spisomi_data_in dbit 3,spipc2 ; SPISOMI-Pin Dateneingang
+spimosi_data_dir dbit 4,spipc2 ; SPIMOSI-Pin Datenrichtung
+spimosi_function dbit 5,spipc2 ; SPIMOSI-Pin Funktionsumschaltung
+spimosi_data_out dbit 6,spipc2 ; SPIMOSI-Pin Datenausgang
+spimosi_data_in dbit 7,spipc2 ; SPIMOSI-Pin Dateneingang
+
+spipri equ p03f
+spi_espen dbit 5,spipri ; Emulator unterdrücken ?!
+spi_priority dbit 6,spipri ; Interrupt-Priorität
+spi_stest dbit 7,spipri ; Selbsttest
+ endif
+
+;----------------------------------------------------------------------------
+; A/D-Wandler
+
+ if MOMCPU>370C030h
+adctl equ p070
+ad_input_select0 dbit 0,adctl ; Kanalauswahl
+ad_input_select1 dbit 1,adctl
+ad_input_select2 dbit 2,adctl
+ref_volt_select0 dbit 3,adctl ; Auswahl Referenzspannung
+ref_volt_select1 dbit 4,adctl
+ref_volt_select2 dbit 5,adctl
+sample_start dbit 6,adctl ; Sample-Phase beginnen (wird autom. gelöscht)
+convert_start dbit 7,adctl ; Wandlungs-Phase beginnen
+
+adstat equ p071
+ad_int_ena dbit 0,adstat ; Interrupt-Freigabe
+ad_int_flag dbit 1,adstat ; Interrupt aufgetreten ?
+ad_ready dbit 2,adstat ; AD-Wandler bereit ?
+
+addata equ p072 ; Wandlungsergebnis
+adin equ p07d ; digitale Eingangsdaten, wenn nicht analog genutzt
+adena equ p07e ; Analogeingänge freischalten
+
+adpri equ p07f
+ad_espen dbit 5,adpri ; Emulator unterdrücken ?!
+ad_priority dbit 6,adpri ; Interrupt-Priorität
+ad_stest dbit 7,adpri ; Selbsttest
+ endif
+
+;----------------------------------------------------------------------------
+; PACT
+
+ if MOMCPU=370C030h
+pact_scr equ p040
+pact_prescale_select0 dbit 0,pact_scr ; Vorteilerauswahl
+pact_prescale_select1 dbit 1,pact_scr
+pact_prescale_select2 dbit 2,pact_scr
+pact_prescale_select3 dbit 3,pact_scr
+fast_mode_select dbit 4,pact_scr ; Vorteiler durch 8 aus
+cmd_def_area_ena dbit 5,pact_scr ; Zugriff auf Dual-Port-RAM freigeben
+deftim_ovrfl_int_flag dbit 6,pact_scr ; Timerüberlauf aufgetreten ?
+deftim_ovrfl_int_ena dbit 7,pact_scr ; Interrupts bei Timerüberlauf freigeben
+
+cdstart equ p041
+cmd_def_area2 dbit 2,cdstart ; Startadresse Kommando/Definitionsbereich
+cmd_def_area3 dbit 3,cdstart
+cmd_def_area4 dbit 4,cdstart
+cmd_def_area5 dbit 5,cdstart
+cmd_def_area_int_ena dbit 7,cdstart ; Interrupts aus dem Bereich freigeben
+
+cdend equ p042
+cmd_def_area_end2 dbit 2,cdend ; Endadresse Kommando/Definitionsbereich
+cmd_def_area_end3 dbit 3,cdend
+cmd_def_area_end4 dbit 4,cdend
+cmd_def_area_end5 dbit 5,cdend
+cmd_def_area_end6 dbit 6,cdend
+
+bufptr equ p043
+buffer_pointer1 dbit 1,bufptr ; Adresse Pufferzeiger
+buffer_pointer2 dbit 2,bufptr
+buffer_pointer3 dbit 3,bufptr
+buffer_pointer4 dbit 4,bufptr
+buffer_pointer5 dbit 5,bufptr
+
+scictlp equ p045
+sci_sw_reset dbit 0,scictlp ; Software Reset
+sci_tx_int_ena dbit 2,scictlp ; Sendeinterrupts freigeben
+sci_rx_int_ena dbit 3,scictlp ; Empfängerinterrupts freigeben
+pact_fe dbit 4,scictlp ; Rahmenfehler ?
+pact_parity dbit 5,scictlp ; Paritätsfehler ?
+pact_txrdy dbit 6,scictlp ; Sender leer ?
+pact_rxrdy dbit 7,scictlp ; Empfangspuffer voll ?
+
+rxbufp equ p046 ; Mini-SCI Empfangspuffer
+txbufp equ p047 ; Mini-SCI Sendepuffer
+
+opstate equ p048 ; Status Ausgabepins
+cdflags equ p049 ; Interrupts durch Kommandos 0..7 aufgetreten ?
+
+cpctl1 equ p04a
+cp1_capt_falling_edge dbit 0,cpctl1 ; Fangen bei fallender Flanke an CP1
+cp1_capt_rising_edge dbit 1,cpctl1 ; Fangen bei steigender Flanke an CP1
+cp1_int_flag dbit 2,cpctl1 ; Flanke an CP1 aufgetreten ?
+cp1_int_ena dbit 3,cpctl1 ; Interrupts durch CP1 freigeben
+cp2_capt_falling_edge dbit 4,cpctl1 ; Fangen bei fallender Flanke an CP2
+cp2_capt_rising_edge dbit 5,cpctl1 ; Fangen bei steigender Flanke an CP2
+cp2_int_flag dbit 6,cpctl1 ; Flanke an CP2 aufgetreten ?
+cp2_int_ena dbit 7,cpctl1 ; Interrupts durch CP2 freigeben
+
+cpctl2 equ p04b
+cp3_capt_falling_edge dbit 0,cpctl2 ; Fangen bei fallender Flanke an CP3
+cp3_capt_rising_edge dbit 1,cpctl2 ; Fangen bei steigender Flanke an CP3
+cp3_int_flag dbit 2,cpctl2 ; Flanke an CP3 aufgetreten ?
+cp3_int_ena dbit 3,cpctl2 ; Interrupts durch CP3 freigeben
+cp4_capt_falling_edge dbit 4,cpctl2 ; Fangen bei fallender Flanke an CP4
+cp4_capt_rising_edge dbit 5,cpctl2 ; Fangen bei steigender Flanke an CP4
+cp4_int_flag dbit 6,cpctl2 ; Flanke an CP4 aufgetreten ?
+cp4_int_ena dbit 7,cpctl2 ; Interrupts durch CP4 freigeben
+
+cpctl3 equ p04c
+cp5_capt_falling_edge dbit 0,cpctl3 ; Fangen bei fallender Flanke an CP5
+cp5_capt_rising_edge dbit 1,cpctl3 ; Fangen bei steigender Flanke an CP5
+cp5_int_flag dbit 2,cpctl3 ; Flanke an CP5 aufgetreten ?
+cp5_int_ena dbit 3,cpctl3 ; Interrupts durch CP5 freigeben
+cp6_capt_falling_edge dbit 4,cpctl3 ; Fangen bei fallender Flanke an CP6
+cp6_capt_rising_edge dbit 5,cpctl3 ; Fangen bei steigender Flanke an CP6
+cp6_int_flag dbit 6,cpctl3 ; Flanke an CP6 aufgetreten ?
+cp6_int_ena dbit 7,cpctl3 ; Interrupts durch CP6 freigeben
+
+cppre equ p04d
+op_set_clr_select dbit 0,cppre ; Ausgabepins per Sofware löschen/setzen?
+event_counter_sw_reset dbit 1,cppre ; Ereigniszähler zurücksetzen
+cp6_event_only dbit 2,cppre ; CP6 nur für Ereigniszähler
+input_capt_prescale_select0 dbit 3,cppre; Vorteiler für CP3..CP6
+input_capt_prescale_select1 dbit 4,cppre
+input_capt_prescale_select2 dbit 5,cppre
+buffer_half_full_int_flag dbit 6,cppre ; Interrupts, daß Puffer halb/ganz voll ?
+buffer_half_full_int_ena dbit 7,cppre ; obige Interrupts freischalten
+
+wdrst equ p04e
+
+pactpri equ p04f
+wd_prescale_select0 dbit 0,pactpri ; Vorteiler Watchdog
+wd_prescale_select1 dbit 1,pactpri
+pact_mode_select dbit 2,pactpri ; PACT in Modus A oder B
+pact_group_3_priority dbit 3,pactpri ; Prioritäten der Interruptgruppen
+pact_group_2_priority dbit 4,pactpri
+pact_group_1_priority dbit 5,pactpri
+pact_stest dbit 7,pactpri ; Selbsttest
+ endif
+
+;----------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef3x.inc b/include/stddef3x.inc
new file mode 100644
index 0000000..d364bf6
--- /dev/null
+++ b/include/stddef3x.inc
@@ -0,0 +1,96 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF3X.INC *
+;* *
+;* Sinn : enthält Register- und Adreßdefinitionen für die TMS320C3x-CPUs *
+;* *
+;* letzte Änderungen : 27. 9.1994 *
+;* *
+;****************************************************************************
+
+ ifndef stddef3xinc ; verhindert Mehrfacheinbindung
+
+stddef3xinc equ 1
+
+ if (MOMCPU<>3279920)&&(MOMCPU<>3279921)
+ fatal "Falscher Prozessortyp eingestellt: nur 320C30/320C31 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "TMS320C3x-Definitionen (C) 1994 Alfred Arnold"
+ endif
+
+;------------------------------------------------------------------------------
+; Timer
+
+T0CTRL equ 808020h
+T0CNT equ 808024h
+T0PERIOD equ 808028h
+
+T1CTRL equ 808030h
+T1CNT equ 808034h
+T1PERIOD equ 808038h
+
+;------------------------------------------------------------------------------
+; serielle Ports
+
+S0CTRL equ 808040h
+S0TXPORTCTRL equ 808042h
+S0RXPORTCTRL equ 808043h
+S0TIMERCTRL equ 808044h
+S0TIMERCNT equ 808045h
+S0TIMERPERIOD equ 808046h
+S0TBUF equ 808048h
+S0RBUF equ 80804ch
+
+ if MOMCPU=320C30h
+S1CTRL equ 808050h
+S1TXPORTCTRL equ 808052h
+S1RXPORTCTRL equ 808053h
+S1TIMERCTRL equ 808054h
+S1TIMERCNT equ 808055h
+S1TIMERPERIOD equ 808056h
+S1TBUF equ 808058h
+S1RBUF equ 80805ch
+ endif
+
+;------------------------------------------------------------------------------
+; DMA
+
+DMACTRL equ 808000h
+DMASRCADR equ 808004h
+DMADESTADR equ 808006h
+DMACNT equ 808008h
+
+;------------------------------------------------------------------------------
+; Adressen Interrupt-Vektoren
+
+INTVEC_RESET equ 0
+INTVEC_INT0 equ 1
+INTVEC_INT1 equ 2
+INTVEC_INT2 equ 3
+INTVEC_INT3 equ 4
+INTVEC_XINT0 equ 5
+INTVEC_RINT0 equ 6
+ if MOMCPU=320C30h
+INTVEC_XINT1 equ 7
+INTVEC_RINT1 equ 8
+ endif
+INTVEC_TINT0 equ 9
+INTVEC_TINT1 equ 0ah
+INTVEC_DINT equ 0bh
+__TMPINTVEC set 0
+ rept 28
+INTVEC_TRAP{"\{__TMPINTVEC}"} equ __TMPINTVEC+20h
+__TMPINTVEC set __TMPINTVEC+1
+ endm
+
+ endif
+
+ restore ; Listing wieder erlauben
+
+
diff --git a/include/stddef47.inc b/include/stddef47.inc
new file mode 100644
index 0000000..44ac1ae
--- /dev/null
+++ b/include/stddef47.inc
@@ -0,0 +1,279 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF47.INC *
+;* *
+;* Sinn : enthält den "erweiterten Befehlssatz für die *
+;* TLCS-47(0(A*))-Reihe *
+;* *
+;* Author Alfred Arnold *
+;* *
+;* letzte Änderungen : 22.1.1994 *
+;* *
+;****************************************************************************
+
+ ifndef stddef47inc ; verhindert Mehrfacheinbindung
+
+stddef47inc equ 1
+
+ if (MOMCPU<>293888)&&(MOMCPU<>4656128)&&(MOMCPU<>74492928)
+ fatal "Falscher Prozessortyp eingestellt: nur 47C00, 470C00, oder 470AC00 erlaubt"
+ endif
+
+ if MOMPASS=1
+ message "TLCS-47-Makrodefinitionen"
+ message "(C) 1994 Alfred Arnold"
+ message "Zielprozessor: \{MOMCPU}"
+ endif
+
+;----------------------------------------------------------------------------
+; hier geht's los...
+
+; bedingte Sprünge
+
+
+bz macro adr ; Sprung, falls ZF=1
+ testp zf
+ b adr
+ endm
+
+
+bnz macro adr ; Sprung, falls ZF=0
+ testp zf
+ b s1
+ b adr
+s1:
+ endm
+
+
+bc macro adr ; Sprung, falls CF=1
+ testp cf
+ b adr
+ endm
+
+
+bnc macro adr ; Sprung, falls CF=0
+ test cf
+ b adr
+ endm
+
+
+be macro dest,src,adr ; Vergleich & Sprung, falls =
+ cmpr dest,src
+ testp zf
+ b adr
+ endm
+
+
+bne macro dest,src,adr ; Vergleich & Sprung, falls <>
+ cmpr dest,src
+ if UpString("DEST")<>"A"
+ testp zf
+ b s1
+ endif
+ b adr
+s1:
+ endm
+
+
+bge macro dest,src,adr ; Vergleich & Sprung, falls >=
+ cmpr dest,src
+ testp zf
+ b adr
+ test cf
+ b adr
+ endm
+
+
+bgt macro dest,src,adr ; Vergleich und Sprung, falls >
+ cmpr dest,src
+ test cf
+ b adr
+ endm
+
+
+ble macro dest,src,adr ; Vergleich und Sprung, falls <=
+ cmpr dest,src
+ testp cf
+ b adr
+ endm
+
+
+blt macro dest,src,adr ; Vergleich und Sprung, falls <
+ cmpr dest,src
+ testp zf
+ b s1
+ testp cf
+ b adr
+s1:
+ endm
+
+
+; Unterprogrammaufrufe
+
+
+callss macro vector ; per Vektor
+ if vector=0
+ calls 86h
+ elseif
+ calls (vector<<3)+6
+ endif
+ endm
+
+
+callz macro adr ; falls ZF=1
+ testp zf
+ b s1
+ b s2
+s1: call adr
+s2:
+ endm
+
+
+callnz macro adr ; falls ZF=0
+ testp zf
+ b s1
+ call adr
+s1:
+ endm
+
+
+callc macro adr ; falls CF=1
+ test cf
+ b s1
+ call adr
+s1:
+ endm
+
+
+callnc macro adr ; falls CF=0
+ testp cf
+ b s1
+ call adr
+s1:
+ endm
+
+
+; Unterprogrammrücksprünge
+
+
+retz macro ; falls ZF=1
+ testp zf
+ b s1
+ b s2
+s1: ret
+s2:
+ endm
+
+
+retnz macro ; falls ZF=0
+ testp zf
+ b s1
+ ret
+s1:
+ endm
+
+
+retc macro ; falls CF=1
+ test cf
+ b s1
+ ret
+s1:
+ endm
+
+
+retnc macro ; falls CF=0
+ testp cf
+ b s1
+ ret
+s1:
+ endm
+
+
+; Interruptrücksprünge
+
+
+retiz macro ; falls ZF=1
+ testp zf
+ b s1
+ b s2
+s1: reti
+s2:
+ endm
+
+
+retinz macro ; falls ZF=0
+ testp zf
+ b s1
+ reti
+s1:
+ endm
+
+
+retic macro ; falls CF=1
+ test cf
+ b s1
+ reti
+s1:
+ endm
+
+
+retinc macro ; falls CF=0
+ testp cf
+ b s1
+ reti
+s1:
+ endm
+
+
+; erweiterte Schiebebefehle
+
+
+shl macro op,cnt ; log. Linksshift
+ if UpString("OP")<>"A"
+ xch a,op
+ endif
+ rept cnt
+ test cf
+ rolc a
+ endm
+ if UpString("OP")<>"A"
+ xch a,op
+ endif
+ endm
+
+shr macro op,cnt ; log. Rechtsshift
+ if UpString("OP")<>"A"
+ xch a,op
+ endif
+ rept cnt
+ test cf
+ rorc a
+ endm
+ if UpString("OP")<>"A"
+ xch a,op
+ endif
+ endm
+
+
+; Interruptsperren
+
+
+ei macro
+ eiclr il,3fh
+ endm
+
+di macro
+ diclr il,3fh
+ endm
+
+;---------------------------------------------------------------------------
+; das war's...
+
+ endif
+
+ restore
+
+
diff --git a/include/stddef51.inc b/include/stddef51.inc
new file mode 100644
index 0000000..bcc53e0
--- /dev/null
+++ b/include/stddef51.inc
@@ -0,0 +1,374 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei STDDEF51.INC *
+;* *
+;* Sinn : enthält SFR- und Bitdefinitionen für die MCS-51-Prozessoren *
+;* *
+;* letzte Änderungen : 7. 1.1993 *
+;* 14. 1.1993 USING-Makro hinzugefügt *
+;* 26. 1.1993 REGUSAGE-Variable ergänzt *
+;* 21. 1.1993 Erzeugerhinweis *
+;* 5. 6.1993 IPC & IEC hinzugefügt *
+;* SAVE & RESTORE *
+;* Prozessorsperre (Idee von Matthias) *
+;* 11. 9.1993 Meldung nur im 1.Pass *
+;* 12. 5.1994 DS80C320-Register hinzugefügt *
+;* 25. 6.1995 87C750 hinzugefügt *
+;* 22. 3.1996 SFR's fur 80517 eingefügt *
+;* (von Gabriel Jager) *
+;* 14. 6.1996 80517-Korrekturen wg. Klammerung *
+;* 26. 3.1997 Abfrage auf MOMCPU *
+;* *
+;****************************************************************************
+
+ ifndef stddef51inc ; verhindert Mehrfacheinbindung
+
+stddef51inc equ 1
+
+ if (MOMCPUNAME<>"87C750")&&(MOMCPUNAME<>"8051")&&(MOMCPUNAME<>"8052")&&(MOMCPUNAME<>"80C320")&&(MOMCPUNAME<>"80515")&&(MOMCPUNAME<>"80517")
+ fatal "Falscher Prozessortyp eingestellt: nur 87C750, 8051, 8052, 80C320, 80515 oder 80517 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "MCS-51-SFR-Definitionen (C) 1993 Alfred Arnold/Gabriel Jager"
+ message "binde \{MOMCPU}-SFRs ein"
+ endif
+
+;----------------------------------------------------------------------------
+; erstmal die Sachen, die es (fast) überall gibt :
+
+P0 SFRB 80h ; I/O-Ports
+P1 SFRB 90h
+P2 SFRB 0a0h
+P3 SFRB 0b0h
+RD BIT P3.7 ; Port 3: Schreibleitung
+WR BIT P3.6 ; Leseleitung
+T1 BIT P3.5 ; Testleitung 1
+T0 BIT P3.4 ; Testleitung 0
+INT1 BIT P3.3 ; ext. Interrupt 1
+INT0 BIT P3.2 ; ext. Interrupt 0
+TXD BIT P3.1 ; ser. Ausgang
+RXD BIT P3.0 ; ser. Eingang
+ if MOMCPU=80C320H
+TXD1 BIT P1.3 ; zweiter ser. Ausgang
+RXD1 BIT P1.2 ; zweiter ser. Eingang
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+SP SFR 81h ; Stapelzeiger
+DPL SFR 82h ; Datenzeiger Bit 0..7
+DPH SFR 83h ; " Bit 8..15
+ if MOMCPU=80C320H
+DPL0 SFR DPL
+DPH0 SFR DPH
+DPL1 SFR 84h ; zweiter Datenzeiger 80C320
+DPH1 SFR DPL1+1
+DPS SFR 86h ; Bit 0=Umschaltung DPTR0<-->DPTR1
+ endif
+PSW SFRB 0d0h ; Statuswort
+CY BIT PSW.7
+AC BIT PSW.6
+F0 BIT PSW.5
+RS1 BIT PSW.4
+RS0 BIT PSW.3
+OV BIT PSW.2
+P BIT PSW.0
+ACC SFRB 0e0h ; Akkumulator
+B SFRB 0f0h ; Hilfsakku für MUL/DIV
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+SCON SFRB 98h ; ser. Schnittstelle: Steuerregister
+SM0 BIT SCON.7 ; Betriebsarten
+SM1 BIT SCON.6
+SM2 BIT SCON.5
+REN BIT SCON.4 ; Empfangssperre
+TB8 BIT SCON.3 ; 9. zu sendendes Bit
+RB8 BIT SCON.2 ; 9. empfangenes Bit
+TI BIT SCON.1 ; Senderinterruptflag
+RI BIT SCON.0 ; Empfängerinterruptflag
+SBUF SFR 99h ; " " Datenregister
+
+ if MOMCPU=80C320H ; Register zweite serielle Schnittstelle
+SCON0 SFR SCON
+SBUF0 SFR SBUF
+SCON1 SFR 0c0h ; Steuerregister
+SBUF1 SFR 0c1h ; Datenregister
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+PCON SFR 87h ; "Power-Management"
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+TCON SFRB 88h ; Timer 0/1 Steuerregister
+TF1 BIT TCON.7 ; Überlauf Timer 1
+TR1 BIT TCON.6 ; Timer 1 laufenlassen
+TF0 BIT TCON.5 ; Überlauf Timer 0
+TR0 BIT TCON.4 ; Timer 0 laufenlassen
+IE1 BIT TCON.3 ; Externer Interrupt 1 aufgetreten
+IT1 BIT TCON.2 ; Einstellung Triggerflanke externer Interrupt 1
+IE0 BIT TCON.1 ; Externer Interrupt 0 aufgetreten
+IT0 BIT TCON.0 ; Einstellung Triggerflanke externer Interrupt 0
+TMOD SFR 89h ; Timer 0/1 Betriebsartenregister
+TL0 SFR 8ah ; Daten Timer 0
+TL1 SFR 8bh
+TH0 SFR 8ch ; Daten Timer 1
+TH1 SFR 8dh
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; kein Timer 2 beim 8051
+
+ if MOMCPU<>8051h
+T2CON SFRB 0c8h ; Steuerregister Timer 2
+TL2 SFR 0cch ; Daten Timer 2
+TH2 SFR 0cdh
+ if MOMCPU=8052h
+RCAP2L SFR 0cah ; Capture-Register
+RCAP2H SFR 0cbh
+TF2 BIT T2CON.7 ; Overflow Timer 2
+EXF2 BIT T2CON.6 ; Reload aufgetreten
+RCLK BIT T2CON.5 ; Timer 2 liefert RxD-Takt
+TCLK BIT T2CON.4 ; Timer 2 liefert TxD-Takt
+EXEN2 BIT T2CON.3 ; externer Enable Timer 2
+TR2 BIT T2CON.2 ; Timer 2 starten
+CT2 BIT T2CON.1 ; Timer 2 als Zähler
+CPRL2 BIT T2CON.0 ; Capture erlauben
+ elseif
+CRCL SFR 0cah ; andere Namen beim 80515 !!
+CRCH SFR 0cbh
+T2PS BIT T2CON.7
+I3FR BIT T2CON.6
+I2FR BIT T2CON.5
+T2R1 BIT T2CON.4
+T2R0 BIT T2CON.3
+T2CM BIT T2CON.2
+T2I1 BIT T2CON.1
+T2I0 BIT T2CON.0
+ endif
+ endif
+
+ if MOMCPU=80C320H ; Taktauswahl beim 80C320
+CKCON SFR 8eh ; Bit 3,4,5 <--> Timer 0,1,2
+ endif ; Bit 6,7 <--> Watchdog-Timeout
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; 80C320-Watchdog
+
+ if MOMCPU=80C320h
+WDCON SFRB 0d8h
+RWT BIT WDCON.0 ; Watchdog zurücksetzen
+EWT BIT WDCON.1 ; Watchdog freigeben
+WTRF BIT WDCON.2 ; Watchdog-Reset aufgetreten
+WDIF BIT WDCON.3 ; Interrupt 512 Takte bis Reset aufgetreten
+PFI BIT WDCON.4 ; Power-Fail-Interrupt aufgetreten ?
+EPFI BIT WDCON.5 ; Power-Fail-Interrupt freigeben
+POR BIT WDCON.6
+WD_SMOD BIT WDCON.7
+TA SFR 0c7h ; nacheinander AA 55 schreiben, um Zugriff auf
+ endif ; Spezialregister zu bekommen
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+
+ if MOMCPU=80C320H
+SADDR0 SFR 0a9h ; Slave-Adresse für seriellen Port 0
+SADDR1 SFR 0aah ; Slave-Adresse für seriellen Port 1
+SADEN0 SFR 0b9h ; Bits in SADDR0 freigeben
+SADEN1 SFR 0bah ; Bits in SADDR1 freigeben
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; zusätzliche 80515/80517-Register
+
+ if (MOMCPU=80515h)||(MOMCPU=80517h)
+P4 SFRB 0e8h
+P5 SFRB 0f8h
+
+CCEN SFR 0c1h
+CCH3 SFR 0c7h
+CCL3 SFR 0c6h
+CCH2 SFR 0c5h
+CCL2 SFR 0c4h
+CCH1 SFR 0c3h
+CCL1 SFR 0c2h
+
+ADCON SFRB 0d8h ; andere Namen beim 80515/80517
+BD BIT ADCON.7
+CLK BIT ADCON.6
+BSY BIT ADCON.4
+ADM BIT ADCON.3
+MX2 BIT ADCON.2
+MX1 BIT ADCON.1
+MX0 BIT ADCON.0
+ADDAT SFR 0d9h
+DAPR SFR 0dah
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; zusätzliche 80517-Register
+
+ if MOMCPU=80517h
+
+DPSEL SFR 92h ;Datenpointer Select
+ADCON1 SFR 0dch ;Kontrolle 1 über A/D-Wandler
+CTCON SFR 0e1h ;Kontrolle über Compare-Timer
+IEN2 SFR 9ah
+ARCON SFR 0efh
+MD0 SFR 0e9h ;] Multiplikations-
+MD1 SFR 0eah ;] und
+MD2 SFR 0ebh ;] Divisionsregister
+MD3 SFR 0ech ;]
+MD4 SFR 0edh ;] 1 - 5
+MD5 SFR 0eeh ;]
+CC4EN SFR 0c9h
+CCH4 SFR 0cfh
+CCL4 SFR 0ceh
+CMEN SFR 0f6h
+CMH0 SFR 0d3h
+CMH1 SFR 0d5h
+CMH2 SFR 0d7h
+CMH3 SFR 0e3h
+CMH4 SFR 0e5h
+CMH5 SFR 0e7h
+CMH6 SFR 0f3h
+CMH7 SFR 0f5h
+CML0 SFR 0d2h
+CML1 SFR 0d4h
+CML2 SFR 0d6h
+CML3 SFR 0e2h
+CML4 SFR 0e4h
+CML5 SFR 0e6h
+CML6 SFR 0f8h
+CML7 SFR 0f4h
+CMSEL SFR 0f7h
+CTRELH SFR 0dfh
+CTRELL SFR 0deh
+P6 SFR 0fah ; ??? bitadressierbar
+P7 SFR 0dbh ; ??? bitadressierbar
+P8 SFR 0ddH ; ??? bitadressierbar
+ADCON0 SFR 0d8h ;Kontrolle 1 über A/D-Wandler
+S0BUF SFR 99h ;] Kontrolle
+S0CON SFR 98h ;] für
+S1BUF SFR 9ch ;] die
+S1CON SFR 9bh ;] serielle
+S1REL SFR 9dh ;] Schnittstelle
+WDTREL SFR 86h ;] 0 und 1
+
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; Interruptsteuerregister: nicht kompatibel zwischen 8051/52 und 80515/80517 !!!
+
+ if (MOMCPU=80515h)||(MOMCPU=80517h)
+IEN0 SFRB 0a8h
+EAL BIT IEN0.7
+WDT BIT IEN0.6
+ET2 BIT IEN0.5
+ES BIT IEN0.4
+ET1 BIT IEN0.3
+EX1 BIT IEN0.2
+ET0 BIT IEN0.1
+EX0 BIT IEN0.0
+IEN1 SFRB 0b8h
+EXEN2 BIT IEN1.7
+SWDT BIT IEN1.6
+EX6 BIT IEN1.5
+EX5 BIT IEN1.4
+EX4 BIT IEN1.3
+EX3 BIT IEN1.2
+EX2 BIT IEN1.1
+EADC BIT IEN1.0
+IP0 SFR 0a9h
+IP1 SFR 0b9h
+IRCON SFRB 0c0h
+EXF2 BIT IRCON.7
+TF2 BIT IRCON.6
+IEX6 BIT IRCON.5
+IEX5 BIT IRCON.4
+IEX4 BIT IRCON.3
+IEX3 BIT IRCON.2
+IEX2 BIT IRCON.1
+IADC BIT IRCON.0
+ elseif
+IE SFRB 0a8h ; Interruptfreigaben
+IEC SFRB IE
+EA BIT IE.7 ; generelle Interruptsperre
+ES BIT IE.4 ; Interrupts ser. Schnittstelle freigeben
+ET1 BIT IE.3 ; Interrupt Timer 1 freigeben
+EX1 BIT IE.2 ; externen Interrupt 1 freigeben
+ET0 BIT IE.1 ; Interrupt Timer 0 freigeben
+EX0 BIT IE.0 ; externen Interrupt 0 freigeben
+IP SFRB 0b8h ; Interruptprioritäten
+IPC SFRB IP
+PS BIT IP.4 ; Priorität serieller Interrupt
+PT1 BIT IP.3 ; Priorität Interrupt Timer 1
+PX1 BIT IP.2 ; Priorität externer Interrupt 1
+PT0 BIT IP.1 ; Priorität Interrupt Timer 0
+PX0 BIT IP.0 ; Priorität externer Interrupt 0
+ if MOMCPU=8052h
+ET2 BIT IE.5 ; Interrupt Timer 2 freigeben
+PT2 BIT IP.5 ; Priorität Interrupt Timer 2
+ endif
+ endif
+
+ if MOMCPU=80C320H ; erweiterte Interrupts 80C320
+EIE SFRB 0e8h
+EWDI BIT EIE.4 ; Watchdog-Interrupt freigeben
+EX5 BIT EIE.3 ; externe Interrupts 2..5 freigeben
+EX4 BIT EIE.2
+EX3 BIT EIE.1
+EX2 BIT EIE.0
+EIP SFRB 0f8h
+PWDI BIT EIP.4 ; Priorität Watchdog-Interrupt
+PX5 BIT EIP.3 ; Priorität externer Interrupts 2..5
+PX4 BIT EIP.2
+PX3 BIT EIP.1
+PX2 BIT EIP.0
+EXIF SFR 91h ; erweitertes Interrupt-Flag-Register
+ endif
+
+
+;---------------------------------------------------------------------------
+; Da man die Register beim 8051 nicht direkt pushen und poppen kann, muß man
+; dies über direkte Adressen tun. Da dazu die Kenntnis der gewählten Regis-
+; terbank erforderlich ist, steht hier das Makro USING zur Verfügung, wel-
+; ches in den Symbolen AR0..AR7 die momentanen Registeradressen ablegt.
+; USING erwartet als Parameter die gewählte Banknummer.
+
+Bank0 equ 0 ; nur der Schönheit halber...
+Bank1 equ 1
+Bank2 equ 2
+Bank3 equ 3
+
+using macro bank
+ if (bank<0)||(bank>3) ; nur 0..3 erlaubt
+ error "Falsche Banknummer: \{BANK}"
+ endif
+
+ ifdef RegUsage ; Buchführung über benutzte Bänke
+RegUsage set RegUsage|(2^bank)
+ elseif
+RegUsage set 2^bank
+ endif
+
+ar0 set bank*8 ; Symbole besetzen
+ar1 set ar0+1
+ar2 set ar0+2
+ar3 set ar0+3
+ar4 set ar0+4
+ar5 set ar0+5
+ar6 set ar0+6
+ar7 set ar0+7
+ endm
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef56k.inc b/include/stddef56k.inc
new file mode 100644
index 0000000..d47fab7
--- /dev/null
+++ b/include/stddef56k.inc
@@ -0,0 +1,69 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF56.INC *
+;* *
+;* Sinn : enthält SFR-Definitionen für den DSP56000-Prozessor *
+;* *
+;* letzte Änderungen : 30.12.1993 *
+;* *
+;****************************************************************************
+
+ ifndef stddef56inc ; verhindert Mehrfacheinbindung
+
+stddef56inc equ 1
+
+ if (MOMCPU<>352256)
+ fatal "Falscher Prozessortyp eingestellt: nur 56000 erlaubt!"
+ endif
+
+ if MOMPASS=1
+ message "DSP56000-SFR-Definitionen (C) 1993 Alfred Arnold"
+ endif
+
+;---------------------------------------------------------------------------
+
+pbc xsfr $ffe0 ; Port B Bussteuerregister
+pbddr xsfr $ffe2 ; Port B Datenrichtungsregister
+pbd xsfr $ffe4 ; Port B Datenregister
+
+pcc xsfr $ffe1 ; Port C Steuerregister
+pcddr xsfr $ffe3 ; Port C Datenrichtungsregister
+pcd xsfr $ffe5 ; Port C Datenregister
+
+hcr xsfr $ffe8 ; Host-Steuerregister
+hsr xsfr $ffe9 ; Host-Statusregister
+htx xsfr $ffeb ; Host-Senderegister
+hrx xsfr htx ; Host-Empfangsregister
+
+cra xsfr $ffec ; SSI Steuerregister A
+crb xsfr $ffed ; SSI Steuerregister B
+tsr xsfr $ffee ; SSI Status/Zeitschlitzregister
+
+tx xsfr $ffef ; SCI Senderegister
+rx xsfr tx ; SCI Empfangsregister
+scr xsfr $fff0 ; SCI Schnittstellensteuerregister
+ssr xsfr $fff1 ; SCI Schittstellenstatusregister
+sccr xsfr $fff2 ; SCI Steuerregister
+stxa xsfr $fff3 ; SCI Sendedatenadreßregister
+srx xsfr $fff4 ; SCI Empfangsregister Basisadresse
+stx xsfr srx ; SCI Senderegister Basisadresse
+srx_lo xsfr srx ; SCI Empfangsregister in Bit 0..7
+stx_lo xsfr stx ; SCI Senderegister in Bit 0..7
+srx_mid xsfr srx+1 ; SCI Empfangsregister in Bit 8..15
+stx_mid xsfr stx+1 ; SCI Senderegister in Bit 8..15
+srx_hi xsfr srx+2 ; SCI Empfangsregister in Bit 16..23
+stx_hi xsfr stx+2 ; SCI Senderegister in Bit 16..23
+
+bcr xsfr $fffe ; Bussteuerregister
+ipr xsfr $ffff ; Interrupt-Prioritätenregister
+
+;---------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
+
diff --git a/include/stddef5x.inc b/include/stddef5x.inc
new file mode 100644
index 0000000..5f4e227
--- /dev/null
+++ b/include/stddef5x.inc
@@ -0,0 +1,109 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF2X.INC *
+;* *
+;* Sinn : enthält die globalen Register-Definitionen für die *
+;* TMS320C5x Prozessoren *
+;* *
+;* letzte Änderungen : 03.11.1995 *
+;* *
+;****************************************************************************
+
+ ifndef stddef5xinc ; verhindert Mehrfacheinbindung
+
+stddef5xinc equ 1
+
+ if (MOMCPU<>3279952) && (MOMCPU<>3279953) && (MOMCPU<>3279955)
+ fatal "Falscher Prozessortyp eingestellt: nur 320C50, 320C51 und 320C53 erlaubt!"
+ endif
+
+ if MOMPASS=1
+ message "TMS320C5x Register-Definitionen (C) 1995 Thomas Sailer"
+ endif
+
+;----------------------------------------------------------------------------
+ segment data
+
+ org 4
+ ;Core Processor Memory Mapped Registers
+IMR res 1
+GREG res 1
+IFR res 1
+PMST res 1
+RPTC res 1
+BRCR res 1
+PASR res 1
+PAER res 1
+TREG0 res 1
+TREG1 res 1
+TREG2 res 1
+DBMR res 1
+AR0 res 1
+AR1 res 1
+AR2 res 1
+AR3 res 1
+AR4 res 1
+AR5 res 1
+AR6 res 1
+AR7 res 1
+INDX res 1
+ARCR res 1
+CBSR1 res 1
+CBER1 res 1
+CBSR2 res 1
+CBER2 res 1
+CBCR res 1
+BMAR res 1
+
+ org 32
+ ;Peripherial memory mapped registers
+DRR res 1
+DXR res 1
+SPC res 1
+
+ org 36
+TIM res 1
+PRD res 1
+TCR res 1
+
+ org 40
+PDWSR res 1
+IOWSR res 1
+CWSR res 1
+
+ org 48
+TRCV res 1
+TDXR res 1
+TSPC res 1
+TCSR res 1
+TRTA res 1
+TRAD res 1
+
+ org 80
+PA0 res 1
+PA1 res 1
+PA2 res 1
+PA3 res 1
+PA4 res 1
+PA5 res 1
+PA6 res 1
+PA7 res 1
+PA8 res 1
+PA9 res 1
+PA10 res 1
+PA11 res 1
+PA12 res 1
+PA13 res 1
+PA14 res 1
+PA15 res 1
+
+
+;---------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef60.inc b/include/stddef60.inc
new file mode 100644
index 0000000..22d1613
--- /dev/null
+++ b/include/stddef60.inc
@@ -0,0 +1,674 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF60.INC *
+;* *
+;* Sinn : enthält Makrodefinitionen für den PowerPC *
+;* *
+;* letzte Änderungen : 29. 5.1994 *
+;* 26.12.1994 PPC403-Erweiterungen *
+;* 28.12.1994 MPC505-Erweiterungen *
+;* 10. 3.1999 PPC403G[BC]-Erweiterungen *
+;* 28. 3.1999 Korrektur: MMU erst ab PPC403GC *
+;* *
+;****************************************************************************
+
+ ifndef stddef60inc ; verhindert Mehrfacheinbindung
+
+stddef60inc equ 1
+
+ if (MOMCPU<>1537)&&(MOMCPU<>24576)&&(MOMCPU<>1027)&&(MOMCPU<>1285)&&(MOMCPU<>16443)&&(MOMCPU<>16444)
+ fatal "Falscher Prozessortyp eingestellt: nur MPC601, MPC505, PPC403 oder RS6000 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "PowerPC-Makro-Definitionen (C) 1994 Alfred Arnold"
+ switch MOMCPU
+ case 0x6000
+ message "Zielsystem RS6000"
+ case 0x601
+ message "Zielsystem MPC601"
+ case 0x505
+ message "Zielsystem MPC505"
+ case 0x403,0x403c
+ message "Zielsystem PPC403Gx"
+ endcase
+ endif
+
+
+;============================================================================
+; Device-Control-Register
+
+__defdcr macro NAME,val,{NoExpand}
+NAME equ val
+mt{"NAME"} macro reg
+ mtdcr NAME,reg
+ endm
+mf{"NAME"} macro reg
+ mfdcr reg,NAME
+ endm
+ endm
+
+ if (MOMCPU=0x403)||(MOMCPU=0x403c)
+ __defdcr BEAR,0x90 ; Adresse Busfehler
+ __defdcr BESR,0x91 ; Syndrom Busfehler
+ __defdcr BR0,0x80 ; Bank-Register 0..7
+ __defdcr BR1,0x81
+ __defdcr BR2,0x82
+ __defdcr BR3,0x83
+ __defdcr BR4,0x84
+ __defdcr BR5,0x85
+ __defdcr BR6,0x86
+ __defdcr BR7,0x87
+ __defdcr DMACC0,0xc4 ; DMA Kettenzähler (?)
+ __defdcr DMACR0,0xc0 ; DMA Steuerregister Kanal 0..3
+ __defdcr DMACR1,0xc8
+ __defdcr DMACR2,0xd0
+ __defdcr DMACR3,0xd8
+ __defdcr DMACT0,0xc1 ; DMA Zählregister Kanal 0..3
+ __defdcr DMACT1,0xc9
+ __defdcr DMACT2,0xd1
+ __defdcr DMACT3,0xd9
+ __defdcr DMADA0,0xc2 ; DMA Zieladresse Kanal 0..3
+ __defdcr DMADA1,0xca
+ __defdcr DMADA2,0xd2
+ __defdcr DMADA3,0xda
+ __defdcr DMASA0,0xc3 ; DMA Quelladresse Kanal 0..3
+ __defdcr DMASA1,0xcb
+ __defdcr DMASA2,0xd3
+ __defdcr DMASA3,0xdb
+ __defdcr DMASR,0xe0 ; DMA Statusregister
+ __defdcr EXISR,0x40 ; Anzeige externer Interrupts
+ __defdcr EXIER,0x42 ; Freigabe externer Interrupts
+ __defdcr IOCR,0xa0 ; I/O-Konfiguration
+ endif
+
+;============================================================================
+; Special-Purpose-Register
+
+__defspr macro NAME,val,{NoExpand}
+NAME equ val
+mt{"NAME"} macro reg
+ mtspr NAME,reg
+ endm
+mf{"NAME"} macro reg
+ mfspr reg,NAME
+ endm
+ endm
+
+ __defspr XER,0x001 ; Integer Exception Register
+ __defspr LR,0x008 ; Rücksprungadresse
+ __defspr CTR,0x009 ; Zählregister
+ __defspr SRR0,0x01a ; Save/Restore-Register
+ __defspr SRR1,0x01b
+ __defspr SPRG0,0x110 ; Special Purpose-Register
+ __defspr SPRG1,0x111
+ __defspr SPRG2,0x112
+ __defspr SPRG3,0x113
+ switch MOMCPU
+ case 0x403,0x403c
+ __defspr DAC1,0x3f6 ; Datenadresse Vergleichsregister
+ __defspr DAC2,0x3f7
+ __defspr DBCR,0x3f2 ; Debug-Steuerregister
+ __defspr DBSR,0x3f0 ; Debug-Statusregister
+ __defspr DCCR,0x3fa ; Steuerung Daten-Cache
+ __defspr DEAR,0x3d5 ; Exception-Adresse Datenzugriff
+ __defspr ESR,0x3d4 ; Exception-Syndrom Datenzugriff
+ __defspr EVPR,0x3d6 ; Exception-Vektor-Präfix
+ __defspr IAC1,0x3f4 ; Codeadresse Vergleichsregister
+ __defspr IAC2,0x3f5
+ __defspr ICCR,0x3fb ; Steuerung Code-Cache
+ __defspr PBL1,0x3fc ; Untergrenzen
+ __defspr PBL2,0x3fe
+ __defspr PBU1,0x3fd ; Obergrenzen
+ __defspr PBU2,0x3ff
+ __defspr PIT,0x3db ; Timer
+ __defspr PVR,0x11f ; Prozessorversion
+ __defspr SRR2,0x3de ; Save/Restore-Register
+ __defspr SRR3,0x3df
+ __defspr TBHI,0x3dc ; Zeitbasis
+ __defspr TBLO,0x3dd
+ __defspr TCR,0x3da ; Timer Steuerregister
+ __defspr TSR,0x3d8 ; Timer Statusregister
+ __defspr SGR,0x3b9 ; ????
+ case 0x505
+ __defspr TBL,268 ; Zeitbasis
+ __defspr TBU,269
+ __defspr DSISR,18 ; zeigt Grund von Alignment-Exceptions an
+ __defspr DAR,19 ; Fehlerhafte Datenadresse nach Exception
+ __defspr DEC,22 ; zählt mit 1 MHz
+ __defspr EIE,80 ; Freigabe externer Interrupts
+ __defspr EID,81 ; Sperre externer Interrupts
+ __defspr NRE,82 ; Non-recoverable Exception
+ __defspr TBL_S,284 ; nochmal Zeitbasis ?!
+ __defspr TBU_S,285
+ __defspr PVR,287 ; Prozessorversion
+ __defspr ICCST,560 ; Steuerung & Status Instruktionscache
+ __defspr ICADR,561 ; Instruktionscache Adreßregister
+ __defspr ICDAT,562 ; Instruktionscache Datenregister
+ __defspr FPECR,1022 ; Gleitkommaexception
+ __defspr CMPA,144 ; Vergleicherwert A..D
+ __defspr CMPB,145
+ __defspr CMPC,146
+ __defspr CMPD,147
+ __defspr ECR,148 ; Grund der Debug-Exception
+ __defspr DER,149 ; Freigabe Debug-Features
+ __defspr COUNTA,150 ; Breakpoint Zähler
+ __defspr COUNTB,151
+ __defspr CMPE,152 ; Vergleicherwert E..G
+ __defspr CMPF,153
+ __defspr CMPG,154
+ __defspr CMPH,155
+ __defspr LCTRL1,156 ; Debug-Steuerung Vergleicher L-Bus
+ __defspr LCTRL2,157
+ __defspr ICTRL,158 ; Debug-Steuerung I-Bus
+ __defspr BAR,159 ; Breakpoint-Adresse
+ __defspr DPDR,630 ; Development-Port Daten
+ __defspr DPIR,631 ; " " Instruktionen
+ case 0x601
+ __defspr RTCU,0x004 ; Zähler
+ __defspr RTCL,0x005
+ __defspr DEC,0x006
+ __defspr DSISR,0x012
+ __defspr DAR,0x013
+ __defspr DEC2,0x016
+ __defspr SDR1,0x019
+ __defspr EAR,0x11a
+ __defspr BAT0U,0x210
+ __defspr BAT0L,0x211
+ __defspr BAT1U,0x212
+ __defspr BAT1L,0x213
+ __defspr BAT2U,0x214
+ __defspr BAT2L,0x215
+ __defspr BAT3U,0x216
+ __defspr BAT3L,0x217
+ __defspr HID0,0x3f0
+ __defspr HID1,0x3f1
+ __defspr HID2,0x3f2
+ __defspr HID5,0x3f5
+ __defspr HID15,0x3ff
+ case 0x6000
+ __defspr MQ,0x000 ; obere Hälfte Divident/Produkt
+ endcase
+ if MOMCPU=0x403c
+ __defspr pid, 0x3b1
+ endif
+
+;============================================================================
+; serieller Port PPC403:
+
+ if (MOMCPU=0x403)||(MOMCPU=0x403c)
+spls equ 0x40000000 ; Leitungsstatus
+sphs equ 0x40000002 ; Status Handshake-Leitungen
+brdh equ 0x40000004 ; Baudratenteiler
+brdl equ 0x40000005
+spctl equ 0x40000006 ; Steuerregister
+sprc equ 0x40000007 ; Kommandoregister Empfänger
+sptc equ 0x40000008 ; Kommandoregister Sender
+sprb equ 0x40000009 ; Sende/Empfangspuffer
+sptb equ sprb
+ endif
+
+;============================================================================
+; SIU MPC505:
+; erinnert irgendwie an die vom 6833x...
+
+ if MOMCPU=0x505
+siumcr equ 0x8007fc00 ; Basissteuerregister
+siutest1 equ 0x8007fc04
+memmap equ 0x8007fc20 ; Speicherlayout
+specaddr equ 0x8007fc24 ; erlauben Sperren spekulativer
+specmask equ 0x8007fc28 ; Ladevorgänge
+termstat equ 0x8007fc2c
+picsr equ 0x8007fc40 ; Steuerung periodische Interrupts
+pit equ 0x8007fc44 ; Zählwert periodischer Interrupt-Timer
+bmcr equ 0x8007fc48 ; Steuerung Bus-Monitor
+rsr equ 0x8007fc4c ; Reset-Status
+sccr equ 0x8007fc50 ; Steuerung Systemtakt
+sccsr equ 0x8007fc54 ; Status Systemtakt
+portbase equ 0x8007fc60
+ddrm equ portbase+0x00 ; Datenrichtungsregister Port M
+pmpar equ portbase+0x04 ; Pinzuordnung Port M
+portm equ portbase+0x08 ; Datenregister Port M
+papar equ portbase+0x24 ; Pinzuordnung Port A+B
+pbpar equ papar
+porta equ portbase+0x28 ; Datenregister Port A+B
+portb equ porta
+ddri equ portbase+0x38 ; Datenrichtungsregister Port I..L
+ddrj equ ddri
+ddrk equ ddri
+ddrl equ ddri
+pipar equ portbase+0x38 ; Pinzuordnung Port I..L
+pjpar equ pipar
+pkpar equ pipar
+plpar equ pipar
+porti equ portbase+0x40 ; Datenregister Port I..L
+portj equ porti
+portk equ porti
+portl equ porti
+csbase equ 0x8007fd00
+csbtbar equ csbase+0xf8 ; Basisadresse Boot-EPROM
+csbtsbbar equ csbase+0xf0
+csbar1 equ csbase+0xe0 ; Basisadressen /CS1../CS5
+csbar2 equ csbase+0xd8
+csbar3 equ csbase+0xd0
+csbar4 equ csbase+0xc8
+csbar5 equ csbase+0xc0
+csbtor equ csbase+0xfc ; Optionen Boot-EPROM
+csbtsbor equ csbase+0xf4
+csor0 equ csbase+0xec ; Optionen /CS1../CS11
+csor1 equ csbase+0xe4
+csor2 equ csbase+0xdc
+csor3 equ csbase+0xd4
+csor4 equ csbase+0xcc
+csor5 equ csbase+0xc4
+csor6 equ csbase+0xbc
+csor7 equ csbase+0xb4
+csor8 equ csbase+0xac
+csor9 equ csbase+0xa4
+csor10 equ csbase+0x9c
+csor11 equ csbase+0x94
+ endif
+
+;----------------------------------------------------------------------------
+; Peripheral Control Unit MPC505:
+
+ if MOMCPU=0x505
+pcubase equ 0x8007ef80
+pcumcr equ pcubase+0x00 ; Basiskonfiguration
+tstmsra equ pcubase+0x10
+tstmsrb equ tstmsra
+tstcntrab equ pcubase+0x14
+tstreps equ tstcntrab
+tstcreg1 equ pcubase+0x18
+tstcreg2 equ tstcreg1
+tstdreg equ pcubase+0x1c
+irqpend equ pcubase+0x20 ; auszuführende Interrupts
+irqand equ pcubase+0x24 ; freigegebene&auszuführende Interrupts
+irqenable equ pcubase+0x28 ; freigegebene Interrupts
+pitqil equ pcubase+0x2c ; Interruptebene PortQ/PIT
+swsr equ pcubase+0x40 ; Reload Watchdog auslösen
+swcr equ pcubase+0x44 ; Steuerung Watchdog
+swtc equ swcr
+swr equ pcubase+0x48
+pqedgdat equ pcubase+0x50 ; Flankenauswahl PortQ
+pqpar equ pcubase+0x54 ; Pinzuordnung PortQ
+ endif
+
+;----------------------------------------------------------------------------
+; SRAM-Modul MPC505:
+
+ if MOMCPU=0x505
+srammcr equ 0x8007f00 ; Basiskonfiguration SRAM
+ endif
+
+;============================================================================
+; SUBI geht sowohl mit 2 als auch 3 Argumenten
+
+subi macro dest,src,VAL
+ if "VAL"=""
+ addi dest,dest,-src
+ elseif
+ addi dest,src,-VAL
+ endif
+ endm
+
+;----------------------------------------------------------------------------
+; Vergleiche
+
+cmpw macro cr,REG1,REG2
+ if "REG2"=""
+ cmp 0,0,cr,REG1
+ elseif
+ cmp cr,0,REG1,REG2
+ endif
+ endm
+
+cmpwi macro cr,REG1,IMM
+ if "IMM"=""
+ cmpi 0,0,cr,IMM
+ elseif
+ cmpi cr,0,REG1,imm
+ endif
+ endm
+
+cmplw macro cr,REG1,REG2
+ if "REG2"=""
+ cmpl 0,0,cr,REG1
+ elseif
+ cmpl cr,0,REG1,REG2
+ endif
+ endm
+
+cmplwi macro cr,REG1,IMM
+ if "IMM"=""
+ cmpli 0,0,cr,IMM
+ elseif
+ cmpli cr,0,REG1,IMM
+ endif
+ endm
+
+;----------------------------------------------------------------------------
+; erweiterte Befehle Bedingungsregister
+
+crset macro bx
+ creqv bx,bx,bx
+ endm
+
+crnot macro bx,by
+ crnor bx,by,by
+ endm
+
+crmove macro bx,by
+ cror bx,by,by
+ endm
+
+;----------------------------------------------------------------------------
+; erweiterte Befehle Logik
+
+not macro dest,SRC
+ if "SRC"=""
+ nor dest,dest
+ elseif
+ nor dest,SRC,SRC
+ endif
+ endm
+
+not. macro dest,SRC
+ if "SRC"=""
+ nor. dest,dest
+ elseif
+ nor. dest,SRC,SRC
+ endif
+ endm
+
+mr macro dest,src
+ or dest,src,src
+ endm
+
+mr. macro dest,src
+ or. dest,src,src
+ endm
+
+nop macro
+ ori 0,0,0
+ endm
+
+;----------------------------------------------------------------------------
+; vereinfachte Einschiebebefehle
+
+inslwi macro ra,rs,n,b
+ rlwimi ra,rs,32-b,b,b+n-1
+ endm
+inslwi. macro ra,rs,n,b
+ rlwimi. ra,rs,32-b,b,b+n-1
+ endm
+
+insrwi macro ra,rs,n,b
+ rlwimi ra,rs,32-b-n,b,b+n-1
+ endm
+insrwi. macro ra,rs,n,b
+ rlwimi. ra,rs,32-b-n,b,b+n-1
+ endm
+
+__defins1 macro NAME,par1,par2,par3,{NoExpand}
+{"NAME"} macro ra,rs,n
+ rlwinm ra,rs,par1,par2,par3
+ endm
+{"NAME"}. macro ra,rs,n
+ rlwinm. ra,rs,par1,par2,par3
+ endm
+ endm
+
+__defins2 macro NAME,par1,par2,par3,{NoExpand}
+{"NAME"} macro ra,rs,b,n
+ rlwinm ra,rs,par1,par2,par3
+ endm
+{"NAME"}. macro ra,rs,b,n
+ rlwinm. ra,rs,par1,par2,par3
+ endm
+ endm
+
+ __defins1 clrlwi,0,n,31
+ __defins2 clrlslwi,n,b-n,31-n
+ __defins1 clrrwi,0,0,31-n
+ __defins2 extlwi,b,0,n-1
+ __defins2 extrwi,b+n,32-n,31
+ __defins1 rotlwi,n,0,31
+ __defins1 rotrwi,32-n,0,31
+ __defins1 slwi,n,0,31-n
+ __defins1 srwi,32-n,n,31
+
+rotlw macro ra,rs,rb
+ rlwnm ra,rs,rb,0,31
+ endm
+rotlw. macro ra,rs,rb
+ rlwnm. ra,rs,rb,0,31
+ endm
+
+;----------------------------------------------------------------------------
+; vereinfachte Sprünge
+
+__defjmp1 macro NAME,m1,m2,{NoExpand}
+{"NAME"} macro adr
+ bc m1,m2,adr
+ endm
+{"NAME"}a macro adr
+ bca m1,m2,adr
+ endm
+{"NAME"}l macro adr
+ bcl m1,m2,adr
+ endm
+{"NAME"}la macro adr
+ bcla m1,m2,adr
+ endm
+ endm
+
+ __defjmp1 bdnz,16,0
+ __defjmp1 bdz,18,0
+
+__defjmp2 macro NAME,m1,{NoExpand}
+{"NAME"} macro cr,adr
+ bc m1,cr,adr
+ endm
+{"NAME"}a macro cr,adr
+ bca m1,cr,adr
+ endm
+{"NAME"}l macro cr,adr
+ bcl m1,cr,adr
+ endm
+{"NAME"}la macro cr,adr
+ bcla m1,cr,adr
+ endm
+ endm
+
+ __defjmp2 bdnzf,0
+ __defjmp2 bdnzt,8
+ __defjmp2 bdzf,2
+ __defjmp2 bdzt,10
+ __defjmp2 bf,4
+ __defjmp2 bt,12
+
+__defjmp3 macro NAME,mask,ofs,{NoExpand}
+{"NAME"} macro cr,ADR
+ if "ADR"=""
+ bc mask,ofs,cr
+ elseif
+ bc mask,cr*4+ofs,adr
+ endif
+ endm
+{"NAME"}a macro cr,ADR
+ if "ADR"=""
+ bca mask,ofs,cr
+ elseif
+ bca mask,cr*4+ofs,adr
+ endif
+ endm
+{"NAME"}l macro cr,ADR
+ if "ADR"=""
+ bcl mask,ofs,cr
+ elseif
+ bcl mask,cr*4+ofs,adr
+ endif
+ endm
+{"NAME"}la macro cr,ADR
+ if "ADR"=""
+ bcla mask,ofs,cr
+ elseif
+ bcla mask,cr*4+ofs,adr
+ endif
+ endm
+{"NAME"}ctr macro CR
+ if "CR"=""
+ bcctr mask,ofs
+ elseif
+ bc mask,CR*4+ofs
+ endif
+ endm
+{"NAME"}ctrl macro CR
+ if "CR"=""
+ bcl mask,ofs
+ elseif
+ bcl mask,CR*4+ofs
+ endif
+ endm
+{"NAME"}lr macro CR
+ if "CR"=""
+ bclr mask,ofs
+ elseif
+ bclr mask,4*CR+ofs
+ endif
+ endm
+{"NAME"}lrl macro CR
+ if "CR"=""
+ bclrl mask,ofs
+ elseif
+ bclrl mask,4*CR+ofs
+ endif
+ endm
+ endm
+
+ __defjmp3 beq,12,2
+ __defjmp3 bge,4,0
+ __defjmp3 bgt,12,1
+ __defjmp3 ble,4,1
+ __defjmp3 blt,12,0
+ __defjmp3 bne,4,2
+ __defjmp3 bng,4,1
+ __defjmp3 bnl,4,0
+ __defjmp3 bns,4,3
+ __defjmp3 bnu,4,3
+ __defjmp3 bso,12,3
+ __defjmp3 bun,12,3
+
+bctr macro
+ bcctr 20,0
+ endm
+bctrl macro
+ bcctrl 20,0
+ endm
+
+__defjmp4 macro NAME,mask,{NoExpand}
+{"NAME"} macro cr
+ bcctr mask,cr
+ endm
+{"NAME"}l macro cr
+ bcctrl mask,cr
+ endm
+ endm
+
+ __defjmp4 bfctr,4
+ __defjmp4 btctr,12
+
+__defjmp6 macro NAME,mask,bit,{NoExpand}
+{"NAME"} macro
+ bclr mask,bit
+ endm
+{"NAME"}l macro
+ bclrl mask,bit
+ endm
+ endm
+
+ __defjmp6 blr,20,0
+ __defjmp6 bdnzlr,16,0
+ __defjmp6 bdzlr,18,0
+
+__defjmp7 macro NAME,mask,{NoExpand}
+{"NAME"} macro cr
+ bclr mask,cr
+ endm
+{"NAME"}l macro cr
+ bclrl mask,cr
+ endm
+ endm
+
+ __defjmp7 bdnzflr,0
+ __defjmp7 bdnztlr,8
+ __defjmp7 bdzflr,2
+ __defjmp7 bdztlr,10
+ __defjmp7 bflr,4
+ __defjmp7 btlr,12
+
+;-------------------------------------------------------------------------
+; Traps
+
+trap macro ra,rb
+ tw 31,ra,rb
+ endm
+
+__deftrap macro NAME,mask,{NoExpand}
+{"NAME"} macro ra,rb
+ tw mask,ra,rb
+ endm
+{"NAME"}i macro ra,im
+ twi mask,ra,im
+ endm
+ endm
+
+ __deftrap tweq,4
+ __deftrap twge,12
+ __deftrap twgt,8
+ __deftrap twle,20
+ __deftrap twlge,5
+ __deftrap twlgt,1
+ __deftrap twlle,6
+ __deftrap twllt,2
+ __deftrap twlng,6
+ __deftrap twlnl,5
+ __deftrap twlt,16
+ __deftrap twne,24
+ __deftrap twng,20
+ __deftrap twnl,12
+
+;-------------------------------------------------------------------------
+; MMU-Makros PPC403G[BC]
+
+ if (MOMCPU=0x403c)||(MOMCPU=0x403c)
+
+tlbrehi macro rt,ra
+ tlbre rt,ra,0
+ endm
+
+tlbrelo macro rt,ra
+ tlbre rt,ra,1
+ endm
+
+tlbwehi macro rt,ra
+ tlbwe rt,ra,0
+ endm
+
+tlbwelo macro rt,ra
+ tlbwe rt,ra,1
+ endm
+
+ endif
+
+;=========================================================================
+
+ endif
+
+ restore ; Listing wieder erlauben
+
diff --git a/include/stddef62.inc b/include/stddef62.inc
new file mode 100644
index 0000000..1bac205
--- /dev/null
+++ b/include/stddef62.inc
@@ -0,0 +1,147 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.39 - Datei STDDEF62.INC *
+;* *
+;* Sinn : enthält SFR- und Makrodefinitionen für die ST62xx-Prozessoren *
+;* *
+;* letzte Änderungen : 7. 8.1993 *
+;* 11. 9.1993 Meldung nur im 1.Pass *
+;* 21.11.1993 ROMWIN eingebaut *
+;* *
+;****************************************************************************
+
+ ifndef stddef62inc ; verhindert Mehrfacheinbindung
+
+stddef62inc equ 1
+
+ if (MOMCPU<>25104)&&(MOMCPU<>25109)&&(MOMCPU<>25120)&&(MOMCPU<>25125)
+ fatal "Falscher Prozessortyp eingestellt: nur ST6210, ST6215, ST6220 oder ST6225 erlaubt!"
+ endif
+
+ if MOMPASS=1
+ message "ST62xx-SFR-Definitionen (C) 1993 Alfred Arnold"
+ message "Zielprozessor: ST\{MOMCPU}"
+ endif
+
+;----------------------------------------------------------------------------
+; erstmal die Sachen, die es überall gibt :
+
+RegX SFR 80h ; Registeradressen (die kennt AS aber
+RegY SFR 81h ; auch schon intern, nur der Voll-
+RegV SFR 82h ; ständigkeit halber)
+RegW SFR 83h
+RegA SFR 0ffh
+
+RomBase SFR 40h ; Basisadresse ROM-Fenster (besser
+RDW SFR 0c9h ; aber das ASSUME-Feature nutzen)
+
+PA SFR 0c0h ; Port A
+DDRA SFR 0c4h
+OPTA SFR 0cch
+PB SFR 0c1h ; Port B
+DDRB SFR 0c5h
+OPTB SFR 0cdh
+
+IOPT SFR 0c8h ; Interrupt-Steuerung
+
+ADDATA SFR 0d0h ; A/D-Wandler
+ADCTRL SFR 0d1h
+
+TPSC SFR 0d2h ; Timer
+TDATA SFR 0d3h
+TSCR SFR 0d4h
+
+WDOG SFR 0d8h ; Watchdog
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; Port C nur mit den 28-Pinnern:
+
+ if (MOMCPU=6215H)||(MOMCPU=6225H)
+PC SFR 0c2h ; Port C
+DDRC SFR 0c6h
+OPTC SFR 0ceh
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; hiermit versuche ich, etwas die Leerstellen im Befehlssatz aufzufangen.
+; das ist nur ein Angebot an Ihre Bequemlichkeit, niemand zwingt Sie, diese
+; Makros zu benutzen, wenn Sie es im Einzelfall kürzer können!
+
+; Addition/Subtraktion mit Carry: erster Operand muß A (Akku) sein!
+
+adc macro dst,src
+ jrnc NoCarry
+ inc dst
+NoCarry: add dst,src ; Rest normal addieren
+ endm
+
+sbc macro dst,src
+ jrnc NoCarry
+ dec dst
+NoCarry: sub dst,src
+ endm
+
+; ODER-Verknüpfung:
+; arbeitet nach der Regel von De Morgan: A OR B = /((/A) AND (/B))
+; verwendet W-Register
+; dst muß A (Akku) sein!
+
+or macro dst,src
+ com dst
+ ld w,dst
+ ld dst,src
+ com dst
+ and dst,w
+ com dst
+ endm
+
+; EXOR-Verknüpfung:
+; arbeitet nach dem Prinzip der 4 NAND-Gatter, muß also selber nicht auf
+; das OR-Makro zugreifen
+; verwendet V- und W-Register
+; dst muß A (Akku) sein!
+
+xor macro dst,src
+ ld v,dst ; Op1 retten
+ and dst,src ; Hilfsergebnis A NAND B bilden
+ com dst
+ ld w,dst ; in W retten
+ ld dst,v ; Op1 nochmal holen
+ and dst,w ; 1. Teilergebnis A NAND W bilden
+ com dst
+ ld v,dst ; in V retten
+ ld dst,src ; 2. Teilergebnis B NAND W bilden
+ and dst,w
+ com dst
+ and dst,v
+ com dst
+ endif
+ endm
+
+; rechts mit Carry rotieren
+; ok, das ist brute force, aber mir ist nix besseres eingefallen...
+; dst muß Akku (A) sein
+
+rrc macro dst
+ rept 7
+ rlc dst
+ endm
+ endm
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; Für diejenigen, die auf einmal den ROMWIN-Befehl vermissen, hier eine
+; kleine Überbrückungshilfe:
+
+romwin macro adr
+ assume rombase:adr>>6
+ endm
+
+;---------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef75.inc b/include/stddef75.inc
new file mode 100644
index 0000000..85cb366
--- /dev/null
+++ b/include/stddef75.inc
@@ -0,0 +1,699 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF75.INC *
+;* *
+;* Sinn : enthält SFR-Definitionen für die µPD75K0-Familie *
+;* *
+;* letzte Änderungen : 2.12.1994 *
+;* *
+;****************************************************************************
+
+ ifndef stddef75inc ; verhindert Mehrfacheinbindung
+
+stddef75inc equ 1
+
+;----------------------------------------------------------------------------
+; Bequemlichkeit
+
+__message macro msg,{NoExpand}
+ if MOMPASS=1
+ message msg
+ endif
+ endm
+
+ __message "µPD75K0-Registerdefinitionen, (C) 1994 Alfred Arnold"
+
+;----------------------------------------------------------------------------
+; Die Prozessoren zu Gruppen zusammenfassen
+
+ switch MOMCPU
+ case 480258
+ __message "Binde µPD75402-Register ein"
+__family equ 400
+
+ case 479236,479238,479240
+ __message "Binde µPD750xx-Register ein"
+__family equ 000
+
+ case 479848
+ __message "Binde µPD75268-Register ein"
+__family equ 260
+
+ case 480004,480006,480008,480018,480022
+ __message "Binde µPD753xx-Register ein"
+__family equ 300
+
+ case 480040
+ __message "Binde µPD75328-Register ein"
+__family equ 320
+
+ case 479492,479494,479496,479506,479510
+ __message "Binde µPD751xx-Register ein"
+__family equ 100
+
+ case 479750,479752,479762,479766
+ __message "Binde µPD752xx-Register ein"
+__family equ 200
+
+ case 480530,480534
+ __message "Binde µPD755xx-Register ein"
+__family equ 500
+
+ elsecase
+ fatal "Fehler: Keine CPU aus der µPD75xxx-Familie definiert"
+ endcase
+
+;----------------------------------------------------------------------------
+; da alle Interrupt-Register gleich sind, dafür ein Makro bauen
+
+__defint macro NAME,base,{NoExpand}
+__tmpnam set "NAME"
+I{__tmpnam} sfr base
+IE{__tmpnam} bit base.1
+IRQ{__tmpnam} bit base.0
+ endm
+
+;----------------------------------------------------------------------------
+; gemeinsame Register:
+
+SP sfr 0f80h ; [8W] Stack-Pointer
+BTM sfr 0f85h ; [4W] Modus Basis-Timer
+BT sfr 0f86h ; [8R] Zählwert Basis-Timer
+IM0 sfr 0fb4h ; [4W] INT0 Modusregister
+ __defint BT,0fb8h ; [4] Freigabe/Anzeige Interrupt BT
+PORT0 sfr 0ff0h ; [4R] Datenregister Port 0
+PORT1 sfr 0ff1h ; [4R] Datenregister Port 1
+PORT2 sfr 0ff2h ; [4] Datenregister Port 2
+PORT3 sfr 0ff3h ; [4] Datenregister Port 3
+PORT5 sfr 0ff5h ; [4] Datenregister Port 5
+PORT6 sfr 0ff6h ; [4] Datenregister Port 6
+
+RESET label 0000h ; Resetvektor
+VIBT label 0002h ; Interruptvektoradresse INTBT
+ ; z.T. auch INT4
+VI0 label 0004h ; Interruptvektoradresse INT0
+ ; z.T. auch INT1
+
+;----------------------------------------------------------------------------
+
+ if __family=400
+IME bit 0fb2h.3 ; [8] Interruptsperre (mit EI/DI ansprechen)
+PCC sfr 0fb3h ; [4W] Steuerung Prozessortakt
+ __defint CSI,0fbdh ; [4] Freigabe/Anzeige Interrupt CSI
+ __defint 0,0fbeh ; [4] Freigabe/Anzeige Interrupt 0
+ __defint 2,0fbeh ; [4] Freigabe/Anzeige Interrupt 2
+CLOM sfr 0fd0h ; [4W] Taktausgabe Modusregister
+POGA sfr 0fdch ; [8W] Steuerung Pull-Ups Port A
+CSIM sfr 0fe0h ; [8W] Betriebsart serielle Schnittstelle
+CSIE bit CSIM+1.3
+COI bit CSIM+1.2
+WUP bit CSIM+1.1
+SBIC sfr 0fe2h ; [1] Steuerung SBI
+CMDD bit SBIC.3
+RELD bit SBIC.2
+CMDT bit SBIC.1
+RELT bit SBIC.0
+BSYE bit SBIC+1.3
+ACKD bit SBIC+1.2
+ACKE bit SBIC+1.1
+ACKT bit SBIC+1.0
+SIO sfr 0fe4h ; [8] Datenregister SIO
+SVA sfr 0fe6h ; [8W] Knotenadresse auf seriellem Bus
+PMGA sfr 0fe8h ; [8W] Betriebsart Ports
+PMGB sfr 0fech ; [8W] " "
+
+VICSI label 0008h ; Interruptvektoradresse INTCSI
+
+RAMEnd sfr 64 ; RAM-Größe
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ if __family=000
+WM sfr 0f98h ; [8] Modus Watchdog
+TM0 sfr 0fa0h ; [8] Modus Timer 0
+TOE0 bit 0fa2h.3 ; [1W] Freigabe Ausgabe Timer 0
+T0 sfr 0fa4h ; [8R] Zählwert Timer 0
+TMOD0 sfr 0fa6h ; [8W] Moduloregister Timer 0
+PSW sfr 0fb0h ; [4] Programmstatus
+IST0 bit PSW.2
+MBE bit PSW.1
+IME bit 0fb2h.3 ; [8] Interruptsperre (mit EI/DI ansprechen)
+PCC sfr 0fb3h ; [4W] Steuerung Prozessortakt
+IM1 sfr 0fb5h ; [4W] INT1 Modusregister
+IM2 sfr 0fb6h ; [4W] INT2 Modusregister
+SCC sfr 0fb7h ; [1W] Steuerung Systemtakt
+IE4 bit IBT.3 ; Freigabe/Anzeige Interrupt 4
+IRQ4 bit IBT.2
+ __defint W,0fbah ; [4] Freigabe/Anzeige Interrupt W
+ __defint T0,0fbch ; [4] Freigabe/Anzeige Interrupt T0
+ __defint CSI,0fbdh ; [4] Freigabe/Anzeige Interrupt CSI
+ __defint 0,0fbeh ; [4] Freigabe/Anzeige Interrupt 0
+IE1 bit I0.3 ; Freigabe/Anzeige Interrupt 1
+IRQ1 bit I0.2
+ __defint 2,0fbfh ; [4] Freigabe/Anzeige Interrupt 2
+BSB0 sfr 0fc0h ; [4] bitsequentielle Puffer
+BSB1 sfr 0fc1h
+BSB2 sfr 0fc2h
+BSB3 sfr 0fc3h
+CLOM sfr 0fd0h ; [4W] Taktausgabe Modusregister
+POGA sfr 0fdch ; [8W] Steuerung Pull-Ups Port A
+POGB sfr 0fdeh ; [8W] Steuerung Pull-Ups Port B
+CSIM sfr 0fe0h ; [8W] Betriebsart serielle Schnittstelle
+CSIE bit CSIM+1.3
+COI bit CSIM+1.2
+WUP bit CSIM+1.1
+SBIC sfr 0fe2h ; [1] Steuerung SBI
+CMDD bit SBIC.3
+RELD bit SBIC.2
+CMDT bit SBIC.1
+RELT bit SBIC.0
+BSYE bit SBIC+1.3
+ACKD bit SBIC+1.2
+ACKE bit SBIC+1.1
+ACKT bit SBIC+1.0
+SIO sfr 0fe4h ; [8] Datenregister SIO
+SVA sfr 0fe6h ; [8W] Knotenadresse auf seriellem Bus
+PMGA sfr 0fe8h ; [8W] Betriebsart Ports
+PM33 bit PMGA.3
+PM32 bit PMGA.2
+PM31 bit PMGA.1
+PM30 bit PMGA.0
+PM63 bit PMGA+1.3
+PM62 bit PMGA+1.2
+PM61 bit PMGA+1.1
+PM60 bit PMGA+1.0
+PMGB sfr 0fech ; [8W] " "
+PM2 bit PMGB.2
+PM4 bit PMGB+1.0
+PM5 bit PMGB+1.1
+PM7 bit PMGB+1.3
+PMGC sfr 0feeh ; [8W] " "
+PM8 bit PMGC.0
+PORT4 sfr 0ff4h ; [4] Datenregister Port 4
+KR0 sfr PORT6.0
+KR1 sfr PORT6.1
+KR2 sfr PORT6.2
+KR3 sfr PORT6.3
+PORT7 sfr 0ff7h ; [4] Datenregister Port 7
+KR4 sfr PORT7.0
+KR5 sfr PORT7.1
+KR6 sfr PORT7.2
+KR7 sfr PORT7.3
+PORT8 sfr 0ff8h ; [4] Datenregister Port 8
+
+VI1 label 0006h ; Interruptvektoradresse INT1
+VICSI label 0008h ; Interruptvektoradresse INTCSI
+VIT0 label 000ah ; Interruptvektoradresse INTT0
+
+RAMEnd sfr 512 ; RAM-Größe
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ if __family=260
+DSPM sfr 0f88h ; [4W] Modus Display
+DIMS sfr 0f89h ; [4W] Dimmereinstellung Display
+DIGS sfr 0f8ah ; [4] Stellenauswahl Display
+KSF bit DIGS.3
+WM sfr 0f98h ; [8] Modus Watchdog
+TM0 sfr 0fa0h ; [8] Modus Timer 0
+T0 sfr 0fa4h ; [8R] Zählwert Timer 0
+TMOD0 sfr 0fa6h ; [8W] Moduloregister Timer 0
+PSW sfr 0fb0h ; [4] Programmstatus
+IST0 bit PSW.2
+MBE bit PSW.1
+IME bit 0fb2h.3 ; [8] Interruptsperre (mit EI/DI ansprechen)
+PCC sfr 0fb3h ; [4W] Steuerung Prozessortakt
+IM1 sfr 0fb5h ; [4W] INT1 Modusregister
+SCC sfr 0fb7h ; [1W] Steuerung Systemtakt
+IE4 bit IBT.3 ; Freigabe/Anzeige Interrupt 4
+IRQ4 bit IBT.2
+ __defint W,0fbah ; [4] Freigabe/Anzeige Interrupt W
+IEKS bit 0fbbh.3 ; [1] Freigabe/Anzeige Tastatur
+IRQKS bit 0fbbh.2
+ __defint T0,0fbch ; [4] Freigabe/Anzeige Interrupt T0
+ __defint SIO,0fbdh ; [4] Freigabe/Anzeige Interrupt SIO
+ __defint 0,0fbeh ; [4] Freigabe/Anzeige Interrupt 0
+IE1 bit I0.3 ; Freigabe/Anzeige Interrupt 1
+IRQ1 bit I0.2
+ __defint 2,0fbfh ; [4] Freigabe/Anzeige Interrupt 2
+SIOM sfr 0fe0h ; [8W] Betriebsart serielle Schnittstelle
+SIO sfr 0fe4h ; [8] Datenregister SIO
+PMGA sfr 0fe8h ; [8W] Betriebsart Ports
+PM33 bit PMGA.3
+PM32 bit PMGA.2
+PM31 bit PMGA.1
+PM30 bit PMGA.0
+PM63 bit PMGA+1.3
+PM62 bit PMGA+1.2
+PM61 bit PMGA+1.1
+PM60 bit PMGA+1.0
+PMGB sfr 0fech ; [8W] " "
+PM2 bit PMGB.2
+PM4 bit PMGB+1.0
+PM5 bit PMGB+1.1
+PORT4 sfr 0ff4h ; [4] Datenregister Port 4
+SSTART sfr 01c0h ; Beginn Anzeigespeicher
+KS0 sfr 01fch ; [8] Tastaturregister
+KS1 sfr 01feh ; [4]
+PORTH sfr 01ffh ; [4] Datenregister Port H
+
+VI1 label 0006h ; Interruptvektoradresse INT1
+VISIO label 0008h ; Interruptvektoradresse INTSIO
+VIT0 label 000ah ; Interruptvektoradresse INTT0
+VIKS label 000eh ; Interruptvektoradresse INTKS
+
+RAMEnd sfr 512 ; RAM-Größe
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ if __family=300
+LCDM sfr 0f8ch ; [8W] Modus LC-Display
+LCDC sfr 0f8eh ; [4W] Steuerung LC-Display
+WM sfr 0f98h ; [8] Modus Watchdog
+TM0 sfr 0fa0h ; [8] Modus Timer 0
+TOE0 bit 0fa2h.3 ; [1W] Freigabe Ausgabe Timer 0
+T0 sfr 0fa4h ; [8R] Zählwert Timer 0
+TMOD0 sfr 0fa6h ; [8W] Moduloregister Timer 0
+PSW sfr 0fb0h ; [4] Programmstatus
+IST0 bit PSW.2
+MBE bit PSW.1
+IME bit 0fb2h.3 ; [8] Interruptsperre (mit EI/DI ansprechen)
+PCC sfr 0fb3h ; [4W] Steuerung Prozessortakt
+IM1 sfr 0fb5h ; [4W] INT1 Modusregister
+IM2 sfr 0fb6h ; [4W] INT2 Modusregister
+SCC sfr 0fb7h ; [1W] Steuerung Systemtakt
+IE4 bit IBT.3 ; Freigabe/Anzeige Interrupt 4
+IRQ4 bit IBT.2
+ __defint W,0fbah ; [4] Freigabe/Anzeige Interrupt W
+ __defint T0,0fbch ; [4] Freigabe/Anzeige Interrupt T0
+ __defint CSI,0fbdh ; [4] Freigabe/Anzeige Interrupt CSI
+ __defint 0,0fbeh ; [4] Freigabe/Anzeige Interrupt 0
+IE1 bit I0.3 ; Freigabe/Anzeige Interrupt 1
+IRQ1 bit I0.2
+ __defint 2,0fbfh ; [4] Freigabe/Anzeige Interrupt 2
+BSB0 sfr 0fc0h ; [4] bitsequentielle Puffer
+BSB1 sfr 0fc1h
+BSB2 sfr 0fc2h
+BSB3 sfr 0fc3h
+CLOM sfr 0fd0h ; [4W] Taktausgabe Modusregister
+POGA sfr 0fdch ; [8W] Steuerung Pull-Ups Port A
+CSIM sfr 0fe0h ; [8W] Betriebsart serielle Schnittstelle
+CSIE bit CSIM+1.3
+COI bit CSIM+1.2
+WUP bit CSIM+1.1
+SBIC sfr 0fe2h ; [1] Steuerung SBI
+CMDD bit SBIC.3
+RELD bit SBIC.2
+CMDT bit SBIC.1
+RELT bit SBIC.0
+BSYE bit SBIC+1.3
+ACKD bit SBIC+1.2
+ACKE bit SBIC+1.1
+ACKT bit SBIC+1.0
+SIO sfr 0fe4h ; [8] Datenregister SIO
+SVA sfr 0fe6h ; [8W] Knotenadresse auf seriellem Bus
+PMGA sfr 0fe8h ; [8W] Betriebsart Ports
+PM33 bit PMGA.3
+PM32 bit PMGA.2
+PM31 bit PMGA.1
+PM30 bit PMGA.0
+PM63 bit PMGA+1.3
+PM62 bit PMGA+1.2
+PM61 bit PMGA+1.1
+PM60 bit PMGA+1.0
+PMGB sfr 0fech ; [8W] " "
+PM2 bit PMGB.2
+PM4 bit PMGB+1.0
+PM5 bit PMGB+1.1
+PM7 bit PMGB+1.3
+PORT4 sfr 0ff4h ; [4] Datenregister Port 4
+KR0 sfr PORT6.0
+KR1 sfr PORT6.1
+KR2 sfr PORT6.2
+KR3 sfr PORT6.3
+PORT7 sfr 0ff7h ; [4] Datenregister Port 7
+KR4 sfr PORT7.0
+KR5 sfr PORT7.1
+KR6 sfr PORT7.2
+KR7 sfr PORT7.3
+
+VI1 label 0006h ; Interruptvektoradresse INT1
+VICSI label 0008h ; Interruptvektoradresse INTCSI
+VIT0 label 000ah ; Interruptvektoradresse INTT0
+
+RAMEnd sfr 512 ; RAM-Größe
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ if __family=320
+LCDM sfr 0f8ch ; [8W] Modus LC-Display
+LCDC sfr 0f8eh ; [4W] Steuerung LC-Display
+WM sfr 0f98h ; [8] Modus Watchdog
+TM0 sfr 0fa0h ; [8] Modus Timer 0
+TOE0 bit 0fa2h.3 ; [1W] Freigabe Ausgabe Timer 0
+T0 sfr 0fa4h ; [8R] Zählwert Timer 0
+TMOD0 sfr 0fa6h ; [8W] Moduloregister Timer 0
+PSW sfr 0fb0h ; [4] Programmstatus
+IST0 bit PSW.2
+MBE bit PSW.1
+IME bit 0fb2h.3 ; [8] Interruptsperre (mit EI/DI ansprechen)
+PCC sfr 0fb3h ; [4W] Steuerung Prozessortakt
+IM1 sfr 0fb5h ; [4W] INT1 Modusregister
+IM2 sfr 0fb6h ; [4W] INT2 Modusregister
+SCC sfr 0fb7h ; [1W] Steuerung Systemtakt
+IE4 bit IBT.3 ; Freigabe/Anzeige Interrupt 4
+IRQ4 bit IBT.2
+ __defint W,0fbah ; [4] Freigabe/Anzeige Interrupt W
+ __defint T0,0fbch ; [4] Freigabe/Anzeige Interrupt T0
+ __defint CSI,0fbdh ; [4] Freigabe/Anzeige Interrupt CSI
+ __defint 0,0fbeh ; [4] Freigabe/Anzeige Interrupt 0
+IE1 bit I0.3 ; Freigabe/Anzeige Interrupt 1
+IRQ1 bit I0.2
+ __defint 2,0fbfh ; [4] Freigabe/Anzeige Interrupt 2
+BSB0 sfr 0fc0h ; [4] bitsequentielle Puffer
+BSB1 sfr 0fc1h
+BSB2 sfr 0fc2h
+BSB3 sfr 0fc3h
+CLOM sfr 0fd0h ; [4W] Taktausgabe Modusregister
+ADM sfr 0fd8h ; [1] Steuerung A/D-Wandler
+SOC sfr ADM.3
+EOC sfr ADM.2
+SA sfr 0fdah
+POGA sfr 0fdch ; [8W] Steuerung Pull-Ups Port A
+POBG sfr 0fdeh ; [8W] Steuerung Pull-Ups Port B
+CSIM sfr 0fe0h ; [8W] Betriebsart serielle Schnittstelle
+CSIE bit CSIM+1.3
+COI bit CSIM+1.2
+WUP bit CSIM+1.1
+SBIC sfr 0fe2h ; [1] Steuerung SBI
+CMDD bit SBIC.3
+RELD bit SBIC.2
+CMDT bit SBIC.1
+RELT bit SBIC.0
+BSYE bit SBIC+1.3
+ACKD bit SBIC+1.2
+ACKE bit SBIC+1.1
+ACKT bit SBIC+1.0
+SIO sfr 0fe4h ; [8] Datenregister SIO
+SVA sfr 0fe6h ; [8W] Knotenadresse auf seriellem Bus
+PMGA sfr 0fe8h ; [8W] Betriebsart Ports
+PM33 bit PMGA.3
+PM32 bit PMGA.2
+PM31 bit PMGA.1
+PM30 bit PMGA.0
+PM63 bit PMGA+1.3
+PM62 bit PMGA+1.2
+PM61 bit PMGA+1.1
+PM60 bit PMGA+1.0
+PMGB sfr 0fech ; [8W] " "
+PM2 bit PMGB.2
+PM4 bit PMGB+1.0
+PM5 bit PMGB+1.1
+PM7 bit PMGB+1.3
+PMGC sfr 0feeh ; [8W] " "
+PORT4 sfr 0ff4h ; [4] Datenregister Port 4
+KR0 sfr PORT6.0
+KR1 sfr PORT6.1
+KR2 sfr PORT6.2
+KR3 sfr PORT6.3
+PORT7 sfr 0ff7h ; [4] Datenregister Port 7
+KR4 sfr PORT7.0
+KR5 sfr PORT7.1
+KR6 sfr PORT7.2
+KR7 sfr PORT7.3
+PORT8 sfr 0ff8h ; [4] Datenregister Port 8
+
+VI1 label 0006h ; Interruptvektoradresse INT1
+VICSI label 0008h ; Interruptvektoradresse INTCSI
+VIT0 label 000ah ; Interruptvektoradresse INTT0
+
+RAMEnd sfr 512 ; RAM-Größe
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ if __family=100
+TM0 sfr 0fa0h ; [8] Modus Timer 0
+TOE0 bit 0fa2h.3 ; [1W] Freigabe Ausgabe Timer 0
+TO0 bit 0fa2h.2 ; [1W] Ausgabe Timer 0
+TOF0 bit 0fa2h.1 ; [1W] Ausgabeflipflop Timer 0
+TI0 bit 0fa2h.0 ; [1W] Eingabe Timer 0
+T0 sfr 0fa4h ; [8R] Zählwert Timer 0
+TMOD0 sfr 0fa6h ; [8W] Moduloregister Timer 0
+TM1 sfr 0fa8h ; [8] Modus Timer 1
+TOE1 bit 0faah.3 ; [1W] Freigabe Ausgabe Timer 1
+TO1 bit 0faah.2 ; [1W] Ausgabe Timer 1
+TOF1 bit 0faah.1 ; [1W] Ausgabeflipflop Timer 1
+TI1 bit 0faah.0 ; [1W] Eingabe Timer 1
+T1 sfr 0fach ; [8R] Zählwert Timer 1
+TMOD1 sfr 0faeh ; [8W] Moduloregister Timer 1
+PSW sfr 0fb0h ; [4] Programmstatus
+IST1 bit PSW.3
+IST0 bit PSW.2
+MBE bit PSW.1
+RBE bit PSW.0
+IPS sfr 0fb2h ; [4W] Interruptprioritäten
+PCC sfr 0fb3h ; [4W] Steuerung Prozessortakt
+IM1 sfr 0fb5h ; [4W] INT1 Modusregister
+IE4 bit IBT.3 ; Freigabe/Anzeige Interrupt 4
+IRQ4 bit IBT.2
+ __defint T0,0fbch ; [4] Freigabe/Anzeige Interrupt T0
+IET1 bit IT0.3
+IRQT1 bit IT0.2
+ __defint SIO,0fbdh ; [4] Freigabe/Anzeige Interrupt SIO
+ __defint 0,0fbeh ; [4] Freigabe/Anzeige Interrupt 0
+IE1 bit I0.3 ; Freigabe/Anzeige Interrupt 1
+IRQ1 bit I0.2
+ __defint 2,0fbfh ; [4] Freigabe/Anzeige Interrupt 2
+IE3 bit I2.3 ; Freigabe/Anzeige Interrupt 3
+IRQ3 bit I2.2
+BSB0 sfr 0fc0h ; [4] bitsequentielle Puffer
+BSB1 sfr 0fc1h
+BSB2 sfr 0fc2h
+BSB3 sfr 0fc3h
+CLOM sfr 0fd0h ; [4W] Taktausgabe Modusregister
+PONF bit 0fd1h.0 ; [1] Power-on-Flag
+PTHM sfr 0fd6h ; [8] Schwellwerteinstellung
+SIOM sfr 0fe0h ; [8W] Betriebsart serielle Schnittstelle
+SIO sfr 0fe4h ; [8] Datenregister SIO
+PMGA sfr 0fe8h ; [8W] Betriebsart Ports
+PM33 bit PMGA.3
+PM32 bit PMGA.2
+PM31 bit PMGA.1
+PM30 bit PMGA.0
+PM63 bit PMGA+1.3
+PM62 bit PMGA+1.2
+PM61 bit PMGA+1.1
+PM60 bit PMGA+1.0
+PMGB sfr 0fech ; [8W] " "
+PM2 bit PMGB.2
+PM4 bit PMGB+1.0
+PM5 bit PMGB+1.1
+PM7 bit PMGB+1.3
+PMGC sfr 0feeh ; [8W] " "
+PM8 bit PMGC.0
+PM9 bit PMGC.1
+PM12 bit PMGC+1.0
+PM13 bit PMGC+1.1
+PM14 bit PMGC+1.2
+PORT4 sfr 0ff4h ; [4] Datenregister Port 4
+PORT7 sfr 0ff7h ; [4] Datenregister Port 7
+PORT8 sfr 0ff8h ; [4] Datenregister Port 8
+PORT9 sfr 0ff9h ; [4] Datenregister Port 9
+PORT12 sfr 0ffch ; [4] Datenregister Port 12
+PORT13 sfr 0ffdh ; [4] Datenregister Port 13
+PORT14 sfr 0ffeh ; [4] Datenregister Port 14
+
+VISIO label 0006h ; Interruptvektoradresse INTSIO
+VIT0 label 0008h ; Interruptvektoradresse INTT0
+VIT1 label 000ah ; Interruptvektoradresse INTT1
+
+ if MOMCPU<75108h ; RAM-Größe
+RAMEnd sfr 320
+ elseif
+RAMEnd sfr 512
+ endif
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ if __family=200
+DSPM sfr 0f88h ; [4W] Modus Display
+DIMS sfr 0f89h ; [4W] Dimmereinstellung Display
+DIGS sfr 0f8ah ; [4] Stellenauswahl Display
+KSF bit DIGS.3
+TPGM sfr 0f90h ; [8W] Modus Pulsgenerator
+MODL sfr 0f94h ; [8] Modulo-Wert Pulsgenerator
+MODH sfr 0f96h ; [8]
+WM sfr 0f98h ; [8] Modus Watchdog
+TM0 sfr 0fa0h ; [8] Modus Timer 0
+T0 sfr 0fa4h ; [8R] Zählwert Timer 0
+TMOD0 sfr 0fa6h ; [8W] Moduloregister Timer 0
+PSW sfr 0fb0h ; [4] Programmstatus
+IST1 bit PSW.3
+IST0 bit PSW.2
+MBE bit PSW.1
+RBE bit PSW.0
+IPS sfr 0fb2h ; [4W] Interruptprioritäten
+PCC sfr 0fb3h ; [4W] Steuerung Prozessortakt
+IM1 sfr 0fb5h ; [4W] INT1 Modusregister
+SCC sfr 0fb7h ; [1W] Steuerung Systemtakt
+IE4 bit IBT.3 ; Freigabe/Anzeige Interrupt 4
+IRQ4 bit IBT.2
+ __defint W,0fbah ; [4] Freigabe/Anzeige Interrupt W
+ __defint TPG,0fbbh ; [4] Freigabe/Anzeige Interrupt TPG
+IEKS bit ITPG.3 ; Freigabe/Anzeige Interrupt KS
+IRQKS bit ITPG.2
+ __defint T0,0fbch ; [4] Freigabe/Anzeige Interrupt T0
+ __defint SIO,0fbdh ; [4] Freigabe/Anzeige Interrupt SIO
+ __defint 0,0fbeh ; [4] Freigabe/Anzeige Interrupt 0
+IE1 bit I0.3 ; Freigabe/Anzeige Interrupt 1
+IRQ1 bit I0.2
+ __defint 2,0fbfh ; [4] Freigabe/Anzeige Interrupt 2
+PONF bit 0fd1h.0 ; [1] Power-on-Flag
+SIOM sfr 0fe0h ; [8W] Betriebsart serielle Schnittstelle
+SIO sfr 0fe4h ; [8] Datenregister SIO
+PMGA sfr 0fe8h ; [8W] Betriebsart Ports
+PM33 bit PMGA.3
+PM32 bit PMGA.2
+PM31 bit PMGA.1
+PM30 bit PMGA.0
+PM63 bit PMGA+1.3
+PM62 bit PMGA+1.2
+PM61 bit PMGA+1.1
+PM60 bit PMGA+1.0
+PMGB sfr 0fech ; [8W] " "
+PM2 bit PMGB.2
+PM4 bit PMGB+1.0
+PM5 bit PMGB+1.1
+PORT4 sfr 0ff4h ; [4] Datenregister Port 4
+SSTART sfr 01c0h ; Beginn Anzeigespeicher
+KS0 sfr 01fch ; [8] Tastaturregister
+KS1 sfr 01feh ; [4]
+PORTH sfr 01ffh ; [4] Datenregister Port H
+
+VI1 label 0006h ; Interruptvektoradresse INT1
+VISIO label 0008h ; Interruptvektoradresse INTSIO
+VIT0 label 000ah ; Interruptvektoradresse INTT0
+VITPG label 000ch ; Interruptvektoradresse INTTPG
+VIKS label 000eh ; Interruptvektoradresse INTKS
+
+ if MOMCPU<75108h ; RAM-Größe
+RAMEnd sfr 396
+ elseif MOMCPU<75212h
+RAMEnd sfr 497
+ elseif
+RAMEnd sfr 512
+ endif
+ endif
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ if __family=500
+TPGM sfr 0f90h ; [8W] Modus Pulsgenerator
+MODL sfr 0f94h ; [8] Modulo-Wert Pulsgenerator
+MODH sfr 0f96h ; [8]
+WM sfr 0f98h ; [8] Modus Watchdog
+TM0 sfr 0fa0h ; [8] Modus Timer 0
+TOE0 bit 0fa2h.3 ; [1W] Freigabe Ausgabe Timer 0
+T0 sfr 0fa4h ; [8R] Zählwert Timer 0
+TMOD0 sfr 0fa6h ; [8W] Moduloregister Timer 0
+PSW sfr 0fb0h ; [4] Programmstatus
+IST1 bit PSW.3
+IST0 bit PSW.2
+MBE bit PSW.1
+RBE bit PSW.0
+IPS sfr 0fb2h ; [4W] Interruptprioritäten
+PCC sfr 0fb3h ; [4W] Steuerung Prozessortakt
+IM1 sfr 0fb5h ; [4W] INT1 Modusregister
+IM2 sfr 0fb6h ; [4W] INT2 Modusregister
+SCC sfr 0fb7h ; [1W] Steuerung Systemtakt
+IE4 bit IBT.3 ; Freigabe/Anzeige Interrupt 4
+IRQ4 bit IBT.2
+EOT bit 0fb9h.0
+ __defint W,0fbah ; [4] Freigabe/Anzeige Interrupt W
+ __defint TPG,0fbbh ; [4] Freigabe/Anzeige Interrupt TPG
+ __defint T0,0fbch ; [4] Freigabe/Anzeige Interrupt T0
+ __defint CSIO,0fbdh ; [4] Freigabe/Anzeige Interrupt CSIO
+ __defint 0,0fbeh ; [4] Freigabe/Anzeige Interrupt 0
+IE1 bit I0.3 ; Freigabe/Anzeige Interrupt 1
+IRQ1 bit I0.2
+ __defint 2,0fbfh ; [4] Freigabe/Anzeige Interrupt 2
+BSB0 sfr 0fc0h ; [4] bitsequentielle Puffer
+BSB1 sfr 0fc1h
+BSB2 sfr 0fc2h
+BSB3 sfr 0fc3h
+CSIM1 sfr 0fc8h ; [8W] Betriebsart serielle Schnittstelle
+CSIE1 bit CSIM1+1.3
+SIO1 sfr 0fcch ; [8] Datenregister SIO
+CLOM sfr 0fd0h ; [4W] Taktausgabe Modusregister
+ADM sfr 0fd8h ; [1] Steuerung A/D-Wandler
+SOC sfr ADM.3
+EOC sfr ADM.2
+SA sfr 0fdah
+POGA sfr 0fdch ; [8W] Steuerung Pull-Ups Port A
+CSIM0 sfr 0fe0h ; [8W] Betriebsart serielle Schnittstelle
+CSIE bit CSIM+1.3
+COI bit CSIM+1.2
+WUP bit CSIM+1.1
+SBIC sfr 0fe2h ; [1] Steuerung SBI
+CMDD bit SBIC.3
+RELD bit SBIC.2
+CMDT bit SBIC.1
+RELT bit SBIC.0
+BSYE bit SBIC+1.3
+ACKD bit SBIC+1.2
+ACKE bit SBIC+1.1
+ACKT bit SBIC+1.0
+SIO0 sfr 0fe4h ; [8] Datenregister SIO
+SVA sfr 0fe6h ; [8W] Knotenadresse auf seriellem Bus
+PMGA sfr 0fe8h ; [8W] Betriebsart Ports
+PM33 bit PMGA.3
+PM32 bit PMGA.2
+PM31 bit PMGA.1
+PM30 bit PMGA.0
+PM63 bit PMGA+1.3
+PM62 bit PMGA+1.2
+PM61 bit PMGA+1.1
+PM60 bit PMGA+1.0
+PMGB sfr 0fech ; [8W] " "
+PM2 bit PMGB.2
+PM4 bit PMGB+1.0
+PM5 bit PMGB+1.1
+PM7 bit PMGB+1.3
+PMGC sfr 0feeh ; [8W] " "
+PM8 bit PMGC.0
+PM9 bit PMGC.1
+PM12 bit PMGC+1.0
+PM13 bit PMGC+1.1
+PM14 bit PMGC+1.2
+PORT4 sfr 0ff4h ; [4] Datenregister Port 4
+PORT7 sfr 0ff7h ; [4] Datenregister Port 7
+PORT8 sfr 0ff8h ; [4R] Datenregister Port 8
+PORT9 sfr 0ff9h ; [4] Datenregister Port 9
+PORT10 sfr 0ffah ; [4] Datenregister Port 10
+PORT11 sfr 0ffbh ; [4] Datenregister Port 11
+PORT12 sfr 0ffch ; [4] Datenregister Port 12
+PORT13 sfr 0ffdh ; [4] Datenregister Port 13
+PORT14 sfr 0ffeh ; [4] Datenregister Port 14
+PORT15 sfr 0fffh ; [4R] Datenregister Port 15
+
+VI1 label 0006h ; Interruptvektoradresse INT1
+VICSIO label 0008h ; Interruptvektoradresse INTCSIO
+VIT0 label 000ah ; Interruptvektoradresse INTT0
+VITPG label 000ch ; Interruptvektoradresse INTTPG
+
+RAMEnd sfr 512 ; RAM-Größe
+ endif
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/include/stddef87.inc b/include/stddef87.inc
new file mode 100644
index 0000000..4435c98
--- /dev/null
+++ b/include/stddef87.inc
@@ -0,0 +1,218 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.40 - Datei STDDEF87.INC *
+;* *
+;* Sinn : enthält Register- und Speicheradressen für TLCS-870-Prozessoren *
+;* Port- bzw. Registernamen nach Toshiba-Konvention *
+;* aus dem Handbuch zur Prozessorfamilie TLCS-870 *
+;* *
+;* Author Alfred Arnold *
+;* *
+;* letzte Änderungen : 9.1.1994 *
+;* *
+;****************************************************************************
+
+ ifndef stddef87inc ; verhindert Mehrfacheinbindung
+
+stddef87inc equ 1
+
+ if (MOMCPU<>556032)&&(MOMCPU<>556064)&&(MOMCPU<>556096)&&(MOMCPU<>556144)
+ fatal "Falscher Prozessortyp eingestellt: nur 87C00, 87C20, 87C40 oder 87C70 erlaubt"
+ endif
+
+ if MOMPASS=1
+ message "TLCS-870-Adreßdefinitionen"
+ message "(C) 1994 Alfred Arnold"
+ message "Zielprozessor: \{MOMCPU}"
+ endif
+
+;----------------------------------------------------------------------------
+; hier geht's los...
+
+; Ports
+
+P0 equ 00h
+P1 equ 01h
+P2 equ 02h
+P3 equ 03h
+P4 equ 04h
+P5 equ 05h
+P6 equ 06h
+ if MOMCPU<>87C20h
+P7 equ 07h
+ endif
+ if MOMCPU=87C70h
+P8 equ 08h
+P9 equ 09h
+ endif
+P0CR equ 0Ah
+P1CR equ 0BH
+ if MOMCPU=87C70h
+P4CR equ 0Ch
+ endif
+ if (MOMCPU=87C00h)||(MOMCPU=87C40h)
+P6CR equ 0Ch
+P7CR equ 0Dh
+ endif
+ if MOMCPU=87C20h
+P6CR equ 29h
+ endif
+
+; Tastaturinterface
+
+ if MOMCPU=87C70h
+KEYDR equ P4
+KEYSR equ 2Ah
+ endif
+
+; Vergleicher
+
+ if MOMCPU=87C70h
+CMPCR equ 0Eh
+CMPDR equ 0Fh
+ endif
+
+; Timer: hier geht es ziemlich durcheinander
+
+ if MOMCPU=87C70h
+TREG1 equ 10h
+TREG1L equ TREG1
+TREG1H equ TREG1+1
+ elseif
+TREG1A equ 10h
+TREG1AL equ TREG1A
+TREG1AH equ TREG1A+1
+TREG1B equ 12h
+ if MOMCPU<>87C20h
+TREG1BL equ TREG1B
+TREG1BH equ TREG1B+1
+ elseif
+TC1CR equ 13h
+ endif
+ endif
+ if MOMCPU=87C20h
+TREG5 equ 1Dh
+TC5CR equ 1Eh
+TREG6 equ 16h
+TC6CR equ 17h
+ elseif
+TC1CR equ 14h
+TC2CR equ 15h
+ if MOMCPU<>87C70h
+TREG2 equ 16h
+TREG2L equ TREG2
+TREG2H equ TREG2+1
+ endif
+ endif
+TREG3A equ 18h
+TREG3B equ 19h
+TC3CR equ 1Ah
+TREG4 equ 1Bh
+TC4CR equ 1Ch
+
+; Seriell: auch nicht viel übersichtlicher
+
+ if (MOMCPU=87C00h)||(MOMCPU=87C40h)
+SIO1SR equ 20h
+ if MOMCPU=87C40h
+SIO1CR1 equ 20h
+SIO1CR2 equ 21h
+SIO2CR1 equ 22h
+SIO2CR2 equ 23h
+SIO2SR equ 22h
+ elseif
+SIO2SR equ 21h
+SIO1CR equ 20h
+SIO2CR equ 21h
+SIOBCR equ 22h
+SIOWCR equ 23h
+ endif
+SIO1_BUFFER equ 0FF0h
+SIO2_BUFFER equ 0FF8h
+ elseif
+SIOSR equ 20h
+SIOCR1 equ 20h
+SIOCR2 equ 21h
+SIO_BUFFER equ 0FF0h
+ endif
+
+
+; High-Speed-seriell
+
+ if MOMCPU=87C70h
+HSOSR equ 24h
+HSOCR equ 24h
+HSO_BUFFER equ 0FF8H
+ endif
+
+; AD-Wandler
+
+ if MOMCPU=87C40h
+ADCCR equ 0Eh
+ADCDR equ 0Fh
+ endif
+
+; LCD
+
+ if MOMCPU=87C20h
+LCDCR equ 28h
+LCD_BUFFER equ 0F80h
+ endif
+
+; Fluoreszenz-Display
+
+ if MOMCPU=87C70h
+VFTCR1 equ 28h
+VFTSR equ 29h
+VFTCR2 equ 29h
+ endif
+
+; Watchdog
+
+WDTCR1 equ 34h
+WDTCR2 equ 35h
+
+; Systemsteuerung
+
+TBTCR equ 36h
+SYSCR1 equ 38h
+SYSCR2 equ 39h
+GPSW equ 3Fh
+GRBS equ 3Fh
+
+; Interrupt
+
+EINTCR equ 37h
+EIR equ 3Ah
+EIRL equ EIR
+EIRH equ EIR+1
+IL equ 3ch
+ILL equ EIR
+ILH equ EIR+1
+
+; feste Speicherbereiche
+
+IRAM equ 000C0H ; Internal RAM 256/512/512/512 Byte...
+ if MOMCPU=87C00h
+IRAMEND equ 0013FH
+ elseif
+IRAMEND equ 0023FH
+ endif
+IEAREA equ 0FFC0H ; Interrupt Entry Area...
+IEAREAEND equ 0FFFFH ; ...up to 007FH
+IROM equ 0E000H ; Internal (P)ROM 8K...
+IROMEND equ 0FFFFH ;
+EXTMEM equ IRAMEND+1 ; External Memory
+MEMEND equ IROM-1 ; ...up to ROM-Start
+
+;---------------------------------------------------------------------------
+; das war's...
+
+ endif
+
+ restore
+
+
diff --git a/include/stddef90.inc b/include/stddef90.inc
new file mode 100644
index 0000000..89eb17b
--- /dev/null
+++ b/include/stddef90.inc
@@ -0,0 +1,129 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.39 - Datei STDDEF90.INC *
+;* *
+;* Sinn : enthält Register- und Speicheradressen für TLCS-90-Prozessoren *
+;* Port- bzw. Registernamen nach Toshiba-Konvention *
+;* aus dem Handbuch zur Prozessorfamilie TLCS-90 *
+;* *
+;* Author Alfred Arnold *
+;* *
+;* letzte Änderungen : 1.11.1993 *
+;* *
+;****************************************************************************
+
+ ifndef stddef90inc ; verhindert Mehrfacheinbindung
+
+stddef90inc equ 1
+
+ if (MOMCPU<>9486657)
+ fatal "Falscher Prozessortyp eingestellt: nur 90C141 erlaubt"
+ endif
+
+ if MOMPASS=1
+ message "TLCS-90-Adreßdefinitionen"
+ message "(C) 1993 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; hier geht's los...
+
+;Ports
+
+P0 equ 0ffc0h
+P1 equ 0ffc1h
+P01CR equ 0ffc2h ; ==IRFL !!
+
+P2 equ 0ffc4h
+P2CR equ 0ffc5h
+
+P3 equ 0ffc6h
+P3CR equ 0ffc7h
+
+P4 equ 0ffc8h
+P4CR equ 0ffc9h
+
+P5 equ 0ffcah
+
+P6 equ 0ffcch
+P7 equ 0ffcdh
+P67CR equ 0ffceh
+
+P8 equ 0ffd0h
+P8CR equ 0ffd1h
+
+; Timer
+
+TMOD equ 0ffdah
+TCLK equ 0ffd8h
+TRUN equ 0ffdbh
+TFFCR equ 0ffd9h
+T4MOD equ 0ffe4h
+T4FFCR equ 0ffe5h
+TREG0 equ 0ffd4h
+TREG1 equ 0ffd5h
+TREG2 equ 0ffd6h
+TREG3 equ 0ffd7h
+TREG4L equ 0ffe0h
+TREG4H equ 0ffe1h
+TREG5L equ 0ffe2h
+TREG5H equ 0ffe3h
+CAP1L equ 0ffdch
+CAP1H equ 0ffddh
+CAP2L equ 0ffdeh
+CAL2H equ 0ffdfh
+
+; Pattern
+
+SMMOD equ 0ffcbh
+SMCR equ 0ffcfh
+
+; Seriell
+
+SCMOD equ 0ffe9h ; Betriebsart
+SCCR equ 0ffeah ; Steuerregister
+SCBUF equ 0ffebh ; Datenregister
+
+; Watchdog, Misc
+
+BX equ 0ffech ; Bank-Register IX
+BY equ 0ffedh ; IY
+
+WDMOD equ 0ffd2h ; Watchdog, Halt-Modus
+WDCR equ 0ffd3h ; Steuerregister
+
+; AD-Wandler
+
+ADMOD equ 0ffefh ; Betriebsart
+ADREG equ 0ffeeh ; Datenregister
+
+; Interrupt
+
+IRFL equ 0ffc2h ; Request Flip-Flops
+IRFH equ 0ffc3h
+INTEL equ 0ffe6h ; Freigabe Interrupts
+INTEH equ 0ffe7h
+DMAEH equ 0ffe8h ; Freigabe Micro-DMA
+
+; feste Speicherbereiche
+
+IRAM equ 0fec0H ; Internal RAM 256 Byte...
+IRAMEND equ 0ffbfH
+IEAREA equ 00000H ; Interrupt Entry Area...
+IEAREAEND equ 0007FH ; ...up to 007FH
+IROM equ 00000H ; Internal (P)ROM 8K...
+IROMEND equ 01FFFH ;
+EXTMEM equ IROMEND+1 ; External Memory
+MEMEND equ IRAM-1 ; ...up to FFFFH
+
+;---------------------------------------------------------------------------
+; das war's...
+
+ endif
+
+ restore
+
+
diff --git a/include/stddef96.inc b/include/stddef96.inc
new file mode 100644
index 0000000..e6330e0
--- /dev/null
+++ b/include/stddef96.inc
@@ -0,0 +1,170 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.39 - Datei STDDEF96.INC *
+;* *
+;* Sinn : enthält Register- und Speicheradressen für TLCS-900-Prozessoren *
+;* Port- bzw. Registernamen nach Toshiba-Konvention *
+;* aus dem Handbuch zur Prozessorfamilie TLCS-900 *
+;* *
+;* Original von Ernst Ahlers, Oktober 1993 *
+;* für AS angepaßt von Alfred Arnold *
+;* *
+;* letzte Änderungen : 30.10.1993 *
+;* *
+;****************************************************************************
+
+ ifndef stddef96inc ; verhindert Mehrfacheinbindung
+
+stddef96inc equ 1
+
+ if (MOMCPU<>9879873)&&(MOMCPU<>9683265)
+ fatal "Falscher Prozessortyp eingestellt: nur 96C141 oder 93C141 erlaubt"
+ endif
+
+ if MOMPASS=1
+ message "TLCS-900(L)-Adreßdefinitionen"
+ message "(C) 1993 Ernst Ahlers, Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; hier geht's los...
+
+P0 equ 0000H ; Port 0 Register
+P0CR equ 0002H ; Port 0 Control
+
+P1 equ 0001H ; Port 1 Register
+P1CR equ 0004H ; Port 1 Control
+P1FC equ 0005H ; Port 1 Function
+
+P2 equ 0006H ; Port 2 Register
+P2CR equ 0008H ; Port 2 Control
+P2FC equ 0009H ; Port 2 Function
+
+P3 equ 0007H ; Port 3 Register
+P3CR equ 000AH ; Port 3 Control
+P3FC equ 000BH ; Port 3 Function
+
+P4 equ 000CH ; Port 4 Register
+P4CR equ 000EH ; Port 4 Control
+P4FC equ 0010H ; Port 4 Function
+
+P5 equ 000DH ; Port 5 Register
+
+P6 equ 0012H ; Port 6 Register
+P6CR equ 0014H ; Port 6 Control
+P6FC equ 0016H ; Port 6 Function
+
+P7 equ 0013H ; Port 7 Register
+P7CR equ 0015H ; Port 7 Control
+P7FC equ 0017H ; Port 7 Function
+
+P8 equ 0018H ; Port 8 Register
+P8CR equ 001AH ; Port 8 Control
+P8FC equ 001CH ; Port 8 Function
+
+P9 equ 0019H ; Port 9 Register
+P9CR equ 001BH ; Port 9 Control
+P9FC equ 001DH ; Port 9 Function
+
+TRUN equ 0020H ; Timer Operation Control
+TREG0 equ 0022H ; Timer Register 0
+TREG1 equ 0023H ; Timer Register 1
+TMOD equ 0024H ; Timer Mode Control
+TFFCF equ 0025H ; Timer Flip-Flop Control
+TREG2 equ 0026H ; Timer Register 2
+TREG3 equ 0027H ; Timer Register 3
+P0MOD equ 0028H ; 8-Bit PWM 0 Mode Control
+P1MOD equ 0029H ; 8-Bit PWM 1 Mode Control
+PFFCR equ 002AH ; 8-Bit PWM Flip-Flop Control
+
+TREG4L equ 0030H ; Timer 4 Low Byte
+TREG4H equ 0031H ; Timer 4 High Byte
+TREG5L equ 0032H ; Timer 5 Low Byte
+TREG5H equ 0033H ; Timer 5 High Byte
+CAP1L equ 0034H ; Capture 1 Low Byte
+CAP1H equ 0035H ; Capture 1 High Byte
+CAP2L equ 0036H ; Capture 2 Low Byte
+CAP2H equ 0037H ; Capture 2 High Byte
+T4MOD equ 0038H ; 16-Bit Timer 4 Mode Control
+T4FFCR equ 0039H ; 16-Bit Timer 4 Flip-Flop Control
+T45CR equ 003AH ; 16-Bit Timer 4/5 Control
+
+TREG6L equ 0040H ; Timer 6 Low Byte
+TREG6H equ 0041H ; Timer 6 High Byte
+TREG7L equ 0042H ; Timer 7 Low Byte
+TREG7H equ 0043H ; Timer 7 High Byte
+CAP3L equ 0044H ; Capture 3 Low Byte
+CAP3H equ 0045H ; Capture 3 High Byte
+CAP4L equ 0046H ; Capture 4 Low Byte
+CAP4H equ 0047H ; Capture 4 High Byte
+T5MOD equ 0048H ; 16-Bit Timer 4 Mode Control
+T5FFCR equ 0049H ; 16-Bit Timer 4 Flip-Flop Control
+
+PG0REG equ 004CH ; Pattern Generator 0
+PG1REG equ 004DH ; Pattern Generator 1
+PG01CR equ 004EH ; Pattern Generator 0/1 Control
+
+SC0BUF equ 0050H ; Serial Channel 0 Buffer Data
+SC0CR equ 0051H ; Serial Channel 0 Control
+SC0MOD equ 0052H ; Serial Channel 0 Mode Control
+BR0CR equ 0053H ; Bit Rate Ser. Channel 0 Control
+SC1BUF equ 0054H ; Serial Channel 1 Buffer Data
+SC1CR equ 0055H ; Serial Channel 1 Control
+SC1MOD equ 0056H ; Serial Channel 1 Mode Control
+BR1CR equ 0057H ; Bit Rate Ser. Channel 1 Control
+
+ODE equ 0058H ; Port 9 Open Drain Enable
+WDMOD equ 005CH ; Watchdog Timer Mode
+WDCR equ 005DH ; Watchdog Timer Control
+
+ADMOD equ 005EH ; A/D Control
+ADREG0L equ 0060H ; A/D Result Channel 0 Bit 7..6 = AD1..0
+ADREG0H equ 0061H ; A/D Result Channel 0 Bit 7..0 = AD9..2
+ADREG1L equ 0062H ; A/D Result Channel 1 Bit 7..6 = AD1..0
+ADREG1H equ 0063H ; A/D Result Channel 1 Bit 7..0 = AD9..2
+ADREG2L equ 0064H ; A/D Result Channel 2 Bit 7..6 = AD1..0
+ADREG2H equ 0065H ; A/D Result Channel 2 Bit 7..0 = AD9..2
+ADREG3L equ 0066H ; A/D Result Channel 3 Bit 7..6 = AD1..0
+ADREG3H equ 0067H ; A/D Result Channel 3 Bit 7..0 = AD9..2
+
+B0CS equ 0068H ; Block 0 CS/WAIT Control
+B1CS equ 0069H ; Block 1 CS/WAIT Control
+B2CS equ 006AH ; Block 2 CS/WAIT Control
+
+INTE0AD equ 0070H ; Interrupt Enable/Level AD/Timer 0
+INTE45 equ 0071H ; Interrupt Enable/Level IRQ 5/4
+INTE67 equ 0072H ; Interrupt Enable/Level IRQ 7/6
+INTET10 equ 0073H ; Interrupt Enable/Level Timer 1/0
+INTEPW10 equ 0074H ; Interrupt Enable/Level Timer 3/2 (PWM 1/0)
+INTET54 equ 0075H ; Interrupt Enable/Level TREG 5/4
+INTET76 equ 0076H ; Interrupt Enable/Level TREG 7/6
+INTES0 equ 0077H ; Interrupt Enable/Level Serial Channel 0
+INTES1 equ 0078H ; Interrupt Enable/Level Serial Channel 1
+IIMC equ 007BH ; Interrupt Input Mode Control
+
+DMA0V equ 007CH ; fDMA 0 Start Vector
+DMA1V equ 007DH ; fDMA 1 Start Vector
+DMA2V equ 007EH ; fDMA 2 Start Vector
+DMA3V equ 007FH ; fDMA 3 Start Vector
+
+; feste Speicherbereiche
+
+IRAM equ 000080H ; Internal RAM 1K...
+IRAMEND equ 00047FH ; ...up to 00047FH
+IEAREA equ 008000H ; Interrupt Entry Area...
+IEAREAEND equ 0081FFH ; ...up to 0081FFH
+IROM equ 008200H ; Internal (P)ROM 31.5K...
+IROMEND equ 00FFFFH ; ...up to 00FFFFH
+EXTMEM equ 010000H ; External Memory
+MEMEND equ 0FFFFFFH ; ...up to FFFFFFH
+
+;---------------------------------------------------------------------------
+; das war's...
+
+ endif
+
+ restore
+
diff --git a/include/stddefxa.inc b/include/stddefxa.inc
new file mode 100644
index 0000000..e13dd10
--- /dev/null
+++ b/include/stddefxa.inc
@@ -0,0 +1,405 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.41 - Datei STDDEFXA.INC *
+;* *
+;* Sinn : enthält SFR- und Bitdefinitionen für die XA-Prozessoren *
+;* *
+;* letzte Änderungen : 29. 6.1996 *
+;* 18. 8.1998 bei P_51, F0_51 und F1_51 den Postfix *
+;* wieder entfernt, da diese sich mit kei- *
+;* nen XA-Bits namensmaessig "beissen" *
+;* *
+;****************************************************************************
+
+ ifndef stddefxainc ; verhindert Mehrfacheinbindung
+
+stddefxainc equ 1
+
+ if (MOMCPUNAME<>"XAG3")&&(MOMCPUNAME<>"XAG1")&&(MOMCPUNAME<>"XAG1")
+ fatal "Falscher Prozessortyp eingestellt: nur XAG1, XAG2 oder XAG3 erlaubt!"
+ endif
+
+
+ if MOMPASS=1
+ message "Philips-XA-SFR-Definitionen (C) 1996 Alfred Arnold"
+ endif
+
+;----------------------------------------------------------------------------
+; Prozessorkern
+
+cs port 443h ; Code-Segment
+ds port 441h ; Daten-Segment
+es port 442h ; Extra-Segment
+
+ssel port 403h ; Auswahl-Bits, ob [R0..R6] mit ES/DS arbeiten
+r0seg bit ssel.0
+r1seg bit ssel.1
+r2seg bit ssel.2
+r3seg bit ssel.3
+r4seg bit ssel.4
+r5seg bit ssel.5
+r6seg bit ssel.6
+eswen bit ssel.7 ; Schreibzugriffe über ES erlauben/sperren (Usermode)
+
+pswl port 400h ; Prozessorstatus(L):
+z bit pswl.0 ; Zero-Flag
+n bit pswl.1 ; Negativ-Flag
+v bit pswl.2 ; Overflow-Flag
+ac bit pswl.6 ; Hilfs-Carry (für DAA)
+c bit pswl.7 ; Carry
+
+pswh port 401h ; Prozessorstatus(H):
+im0 bit pswh.0 ; Interrupt-Maske Bit 0
+im1 bit pswh.1 ; Interrupt-Maske Bit 1
+im2 bit pswh.2 ; Interrupt-Maske Bit 2
+im3 bit pswh.3 ; Interrupt-Maske Bit 3
+rs0 bit pswh.4 ; Register-Bank-Auswahl Bit 0
+rs1 bit pswh.5 ; Register-Bank-Auswahl Bit 1
+tm bit pswh.6 ; CPU im Einzelschritt-Modus
+sm bit pswh.7 ; CPU im Supervisor-Mode
+
+psw51 port 402h ; emuliertes 8051-PSW:
+p bit psw51.0 ; Paritätsbit
+f1 bit psw51.1 ; User-Flag 1
+v_51 bit psw51.2 ; Overflow-Flag
+rs0_51 bit psw51.3 ; Register-Bank-Auswahl Bit 0
+rs1_51 bit psw51.4 ; Register-Bank-Auswahl Bit 1
+f0 bit psw51.5 ; User-Flag 0
+ac_51 bit psw51.6 ; Hilfs-Carry (für DAA)
+c_51 bit psw51.7 ; Carry
+
+pcon port 404h ; Steuerung Power-Modi
+idl bit pcon.0 ; Idle-Modus aktivieren
+pd bit pcon.1 ; Powerdown-Modus aktivieren
+
+;----------------------------------------------------------------------------
+; Chip-Konfiguration
+
+scr port 440h ; Systemkonfiguration
+;pz bit scr.0 ; Adreßräume auf 64K begrenzen
+;cm bit scr.1 ; 8051-kompatibles Registermapping
+;pt0 bit scr.2 ; Vorteiler-Einstellung
+;pt1 bit scr.3
+
+bcr port 46ah ; Bus-Konfiguration
+;bc0 bit bcr.0 ; Einstellung 12/16/20/24 Adreßleitungen
+;bc1 bit bcr.1
+;bc2 bit bcr.2 ; Einstellung 8/16 Datenleitungen
+;busd bit bcr.3 ; Bus komplett abschalten
+;waitd bit bcr.4 ; WAIT-Pin ignorieren
+
+btrl port 468h ; Einstellung Bus-Timing(L)
+;dra0 bit btrl.0 ; Gesamtlänge Lesezyklus
+;dra1 bit btrl.1
+;dr0 bit btrl.2 ; Länge Lesezyklus ohne ALE
+;dr1 bit btrl.3
+;dwa0 bit btrl.4 ; Gesamtlänge Schreibzyklus
+;dwa1 bit btrl.5
+;dw0 bit btrl.6 ; Länge Schreibzyklus ohne ALE
+;dw1 bit btrl.7
+
+btrh port 469h ; Einstellung Bus-Timing(L)
+;cra0 bit btrl.0 ; Gesamtlänge Codelesezyklus
+;cra1 bit btrl.1
+;cr0 bit btrl.2 ; Länge Codelesezyklus ohne ALE
+;cr1 bit btrl.3
+;alew bit btrl.5 ; Länge ALE-Puls
+;wm0 bit btrl.6 ; Länge WR-Puls
+;wm1 bit btrl.7
+
+;----------------------------------------------------------------------------
+; Interrupt-Steuerung
+
+iel port 426h ; Interruptfreigabe(L):
+ex0 bit iel.0 ; externer Interrupt 0
+et0 bit iel.1 ; Timer 0
+ex1 bit iel.2 ; externer Interrupt 1
+et1 bit iel.3 ; Timer 1
+et2 bit iel.4 ; Timer 2
+ea bit iel.7 ; global
+
+ieh port 427h ; Interruptfreigabe(H):
+eri0 bit ieh.0 ; Empfang UART0
+eti0 bit ieh.1 ; Versand UART0
+eri1 bit ieh.2 ; Empfang UART1
+eti1 bit ieh.3 ; Versand UART1
+
+ipa0 port 4a0h ; Interruptprioritäten(0):
+;px0 bit ipa0.0 ; externer Interrupt 0 (4 Bits)
+;pt0 bit ipa0.4 ; Timer 0 (4 Bits)
+
+ipa1 port 4a1h ; Interruptprioritäten(1):
+;px1 bit ipa1.0 ; externer Interrupt 1 (4 Bits)
+;pt1 bit ipa1.4 ; Timer 1 (4 Bits)
+
+ipa2 port 4a2h ; Interruptprioritäten(2):
+;pt2 bit ipa1.0 ; Timer 2 (4 Bits)
+
+ipa4 port 4a4h ; Interruptprioritäten(4):
+;pri0 bit ipa4.0 ; Empfang UART0 (4 Bits)
+;pti0 bit ipa4.4 ; Versand UART0 (4 Bits)
+
+ipa5 port 4a5h ; Interruptprioritäten(4):
+;pri1 bit ipa5.0 ; Empfang UART1 (4 Bits)
+;pti1 bit ipa5.4 ; Versand UART1 (4 Bits)
+
+swe port 403h ; Freigabe Software-Interrupts
+swe1 bit swe.0
+swe2 bit swe.1
+swe3 bit swe.2
+swe4 bit swe.3
+swe5 bit swe.4
+swe6 bit swe.5
+swe7 bit swe.6
+
+swr port 42ah ; Auslösung Software-Interrupts
+swr1 bit swr.0
+swr2 bit swr.1
+swr3 bit swr.2
+swr4 bit swr.3
+swr5 bit swr.4
+swr6 bit swr.5
+swr7 bit swr.6
+
+;----------------------------------------------------------------------------
+; Ports
+
+p0 port 430h ; Datenregister Port 0
+ad0 bit p0.0 ; Datenbit 0/Adreßbit 4
+ad1 bit p0.1 ; Datenbit 1/Adreßbit 5
+ad2 bit p0.2 ; Datenbit 2/Adreßbit 6
+ad3 bit p0.3 ; Datenbit 3/Adreßbit 7
+ad4 bit p0.4 ; Datenbit 4/Adreßbit 8
+ad5 bit p0.5 ; Datenbit 5/Adreßbit 9
+ad6 bit p0.6 ; Datenbit 6/Adreßbit 10
+ad7 bit p0.7 ; Datenbit 7/Adreßbit 11
+
+p1 port 431h ; Datenregister Port 1
+a0 bit p1.0 ; Adreßleitung 0 (8-Bit-Modus)
+wrh bit p1.0 ; Schreibimpuls D8-D15 (16-Bit-Modus)
+a1 bit p1.1 ; Adreßleitung 1
+a2 bit p1.2 ; Adreßleitung 2
+a3 bit p1.3 ; Adreßleitung 3
+rxd1 bit p1.4 ; Empfangsleitung UART1
+txd1 bit p1.5 ; Sendeleitung UART1
+t2 bit p1.6 ; Timer 2 Ein/Ausgang
+t2ex bit p1.7 ; Trigger Timer 2
+
+p2 port 432h ; Datenregister Port 2
+ad8 bit p2.0 ; Datenbit 8/Adreßbit 12
+ad9 bit p2.1 ; Datenbit 9/Adreßbit 13
+ad10 bit p2.2 ; Datenbit 10/Adreßbit 14
+ad11 bit p2.3 ; Datenbit 11/Adreßbit 15
+ad12 bit p2.4 ; Datenbit 12/Adreßbit 16
+ad13 bit p2.5 ; Datenbit 13/Adreßbit 17
+ad14 bit p2.6 ; Datenbit 14/Adreßbit 18
+ad15 bit p2.7 ; Datenbit 15/Adreßbit 19
+
+p3 port 433h ; Datenregister Port 3
+rxd0 bit p3.0 ; Empfangsleitung UART0
+txd0 bit p3.1 ; Sendeleitung UART0
+int0 bit p3.2 ; externer Interrupt 0
+int1 bit p3.3 ; externer Interrupt 1
+t0 bit p3.4 ; Timer 0 Ein/Ausgang
+t1 bit p3.5 ; Timer 1 Ein/Ausgang
+wr bit p3.6 ; Schreibimpuls D0-7
+rd bit p3.7 ; Leseimpuls D0-15
+
+p0cfga port 470h ; Konfigurationsbits A für Port 0
+p1cfga port 471h ; Konfigurationsbits A für Port 1
+p2cfga port 472h ; Konfigurationsbits A für Port 2
+p3cfga port 473h ; Konfigurationsbits A für Port 3
+
+p0cfgb port 4f0h ; Konfigurationsbits B für Port 0
+p1cfgb port 4f1h ; Konfigurationsbits B für Port 1
+p2cfgb port 4f2h ; Konfigurationsbits B für Port 2
+p3cfgb port 4f3h ; Konfigurationsbits B für Port 3
+
+;----------------------------------------------------------------------------
+; Timer
+
+tl0 port 450h ; Zählregister Timer 0
+th0 port 451h
+rtl0 port 454h ; Reload Timer 0
+rth0 port 455h
+
+tl1 port 452h ; Zählregister Timer 1
+th1 port 453h
+rtl1 port 456h ; Reload Timer 1
+rth1 port 457h
+
+tmod port 45ch ; Modusregister Timer 0/1
+;t0_m0 bit tmod.0 ; Betriebsart Timer 0
+;t0_m1 bit tmod.1
+;ct_t0 bit tmod.2 ; Timer 0 als Timer oder Zähler
+;t0_gate bit tmod.3 ; Freigabe Timer 0
+;t1_m0 bit tmod.4 ; Betriebsart Timer 1
+;t1_m1 bit tmod.5
+;ct_t1 bit tmod.6 ; Timer 1 als Timer oder Zähler
+;t1_gate bit tmod.7 ; Freigabe Timer 1
+
+tcon port 410h ; Timer-Steuerregister 0/1
+it0 bit tcon.0 ; Flanken/Zustandstriggerung Interrupt 0
+ie0 bit tcon.1 ; Flankendetektor Interrupt 0
+it1 bit tcon.2 ; Flanken/Zustandstriggerung Interrupt 1
+ie1 bit tcon.3 ; Flankendetektor Interrupt 1
+tr0 bit tcon.4 ; Timer 0 einschalten/stoppen
+tf0 bit tcon.5 ; Überlauf Timer 0 ?
+tr1 bit tcon.6 ; Timer 1 einschalten/stoppen
+tf1 bit tcon.7 ; Überlauf Timer 1 ?
+
+tstat port 411h ; Timer-Status 0/1
+t0oe bit tstat.0 ; Takt von Timer 0 an T0 ausgeben
+t1oe bit tstat.1 ; Takt von Timer 1 an T1 ausgeben
+
+tl2 port 458h ; Zählregister Timer 2
+th2 port 459h
+
+t2capl port 45ah ; Fangwert Timer 2
+t2caph port 45bh
+
+t2mod port 419h ; Modus Timer 2
+dcen bit t2mod.0 ; Zählrichtung Timer 2 auf/durch T2EX bestimmt
+t2oe bit t2mod.1 ; Takt von Timer 2 an T2 ausgeben
+tclk1 bit t2mod.4 ; UART1 benutzt Timer2 statt Timer 1 zum Senden
+rclk1 bit t2mod.5 ; UART1 benutzt Timer2 statt Timer 1 zum Empfangen
+
+t2con port 418h ; Timer-Steurregister 2
+cp_rl2 bit t2con.0 ; Timer 2 Fang/Neuladen ?
+ct_t2 bit t2con.1 ; Timer 2 als Timer oder Zähler
+tr2 bit t2con.2 ; Timer 2 einschalten/stoppen
+exen2 bit t2con.3 ; Capture/Reload über T2EX erlauben
+tclk0 bit t2con.4 ; UART0 benutzt Timer2 statt Timer 1 zum Senden
+rclk0 bit t2con.5 ; UART0 benutzt Timer2 statt Timer 1 zum Empfangen
+exf2 bit t2con.6 ; Capture/Reload aufgetreten ?
+tf2 bit t2con.7 ; Überlauf Timer 2 ?
+
+;----------------------------------------------------------------------------
+; Watchdog
+
+wdcon port 41fh ; Konfiguration Watchdog
+wdtof bit wdcon.1 ; Timeout aufgetreten ?
+wdrun bit wdcon.2 ; Watchdog einschalten
+pre0 bit wdcon.5 ; Vorteiler
+pre1 bit wdcon.6
+pre2 bit wdcon.7
+
+wdl port 45fh ; Reload-Wert
+
+wfeed1 port 45dh ; Rücksetzregister 1 (a5h)
+wfeed2 port 45eh ; Rücksetzregister 2 (5ah)
+
+;----------------------------------------------------------------------------
+; serielle Ports
+
+s0buf port 460h ; Datenregister UART0
+
+s0addr port 461h ; Slave-Adresse UART0
+s0aden port 462h ; Adreßmaske UART0
+
+s0stat port 421h ; Status UART0
+stint0 bit s0stat.0 ; Interruptfreigabe UART0
+oe0 bit s0stat.1 ; Empfängerüberlauf UART0
+br0 bit s0stat.2 ; Break auf UART0 empfangen?
+fe0 bit s0stat.3 ; kein gültiges Stopbit auf UART0 ?
+
+s0con port 420h ; Steuerung UART0
+ri_0 bit s0con.0 ; Zeichen auf UART0 empfangen ?
+ti_0 bit s0con.1 ; Zeichen auf UART0 verschickt ?
+rb8_0 bit s0con.2 ; auf UART0 empfangenes, 9. Bit
+tb8_0 bit s0con.3 ; auf UART0 verschicktes, 9. Bit
+ren_0 bit s0con.4 ; Empfänger UART0 freigeben
+sm2_0 bit s0con.5 ; Multiprozessormodus auf UART0 freigeben
+sm1_0 bit s0con.6 ; Moduseinstellung UART0
+sm0_0 bit s0con.7
+
+s1stat port 421h ; Status UART1
+stint1 bit s1stat.0 ; Interruptfreigabe UART1
+oe1 bit s1stat.1 ; Empfängerüberlauf UART1
+br1 bit s1stat.2 ; Break auf UART1 empfangen?
+fe1 bit s1stat.3 ; kein gültiges Stopbit auf UART1 ?
+
+s1con port 424h ; Steuerung UART1
+ri_1 bit s1con.0 ; Zeichen auf UART1 empfangen ?
+ti_1 bit s1con.1 ; Zeichen auf UART1 verschickt ?
+rb8_1 bit s1con.2 ; auf UART1 empfangenes, 9. Bit
+tb8_1 bit s1con.3 ; auf UART1 verschicktes, 9. Bit
+ren_1 bit s1con.4 ; Empfänger UART1 freigeben
+sm2_1 bit s1con.5 ; Multiprozessormodus auf UART1 freigeben
+sm1_1 bit s1con.6 ; Moduseinstellung UART1
+sm0_1 bit s1con.7
+
+s1buf port 464h ; Datenregister UART1
+
+s1addr port 465h ; Slave-Adresse UART1
+s1aden port 466h ; Adreßmaske UART1
+
+
+;----------------------------------------------------------------------------
+; Vektoren
+
+vec_reset label 0000h ; Resetadresse
+vec_bkpt label 0004h ; Breakpoint-Befehl
+vec_trace label 0008h ; Einzelschrittverfolgung
+vec_stkover label 000ch ; Stapelüberlauf
+vec_divzero label 0010h ; Division durch 0
+vec_reti label 0014h ; Privilegverletzung (RETI im User-Mode)
+vec_trap0 label 0040h ; TRAP 0
+vec_trap1 label 0044h ; TRAP 1
+vec_trap2 label 0048h ; TRAP 2
+vec_trap3 label 004ch ; TRAP 3
+vec_trap4 label 0050h ; TRAP 4
+vec_trap5 label 0054h ; TRAP 5
+vec_trap6 label 0058h ; TRAP 6
+vec_trap7 label 005ch ; TRAP 7
+vec_trap8 label 0060h ; TRAP 8
+vec_trap9 label 0064h ; TRAP 9
+vec_trap10 label 0068h ; TRAP 10
+vec_trap11 label 006ch ; TRAP 11
+vec_trap12 label 0070h ; TRAP 12
+vec_trap13 label 0074h ; TRAP 13
+vec_trap14 label 0078h ; TRAP 14
+vec_trap15 label 007ch ; TRAP 15
+
+vec_ie0 label 0080h ; externer Interrupt 0
+vec_tf0 label 0084h ; Interrupt durch Timer 0
+vec_ie1 label 0088h ; externer Interrupt 1
+vec_tf1 label 008ch ; Interrupt durch Timer 1
+vec_tf2 label 0090h ; Interrupt durch Timer 2
+vec_ri0 label 00a0h ; Empfang auf UART0
+vec_ti0 label 00a4h ; Sendung auf UART0
+vec_ri1 label 00a8h ; Empfang auf UART1
+vec_ti1 label 00ach ; Sendung auf UART1
+
+vec_swr1 label 0100h ; Software-Interrupt 1
+vec_swr2 label 0104h ; Software-Interrupt 2
+vec_swr3 label 0108h ; Software-Interrupt 3
+vec_swr4 label 010ch ; Software-Interrupt 4
+vec_swr5 label 0110h ; Software-Interrupt 5
+vec_swr6 label 0114h ; Software-Interrupt 6
+vec_swr7 label 0118h ; Software-Interrupt 7
+
+;----------------------------------------------------------------------------
+; Speicheradressen
+
+irom label 0 ; Beginn internes ROM
+ switch MOMCPUNAME ; Ende internes ROM
+ case "XAG3"
+iromend label 7fffh ; XA-G3: 32K ROM
+ case "XAG2"
+iromend label 3fffh ; XA-G2: 16K ROM
+ case "XAG1"
+iromend label 1fffh ; XA-G1: 8K ROM
+ endcase
+
+iram equ 0,data ; Beginn internes RAM
+iramend equ 1ffh,data ; Ende internes RAM: immer 512 Byte
+
+ endif
+
+ restore ; wieder erlauben
+
+
diff --git a/include/stddefz8.inc b/include/stddefz8.inc
new file mode 100644
index 0000000..c245058
--- /dev/null
+++ b/include/stddefz8.inc
@@ -0,0 +1,56 @@
+ save
+ listing off ; kein Listing über diesen File
+
+;****************************************************************************
+;* *
+;* AS 1.39 - Datei Z8.INC *
+;* *
+;* Sinn : enthält Registerkürzel für den Z8-Prozessor *
+;* *
+;* letzte Änderungen : 16.12.1993 Rüdiger Mersiovsky *
+;* 25.12.1993 Copyrightvermerk *
+;* *
+;****************************************************************************
+
+ ifndef stddefz8inc ; verhindert Mehrfacheinbindung
+
+stddefz8inc equ 1
+
+ if (MOMCPU<>34305)
+ fatal "Falscher Prozessortyp eingestellt: nur Z8601 erlaubt!"
+ endif
+
+ if MOMPASS=1
+ message "Z8-Kürzel-Definitionen"
+ message "(C) 1993 Rüdiger Mersiovsky"
+ endif
+
+;----------------------------------------------------------------------------
+
+P0 EQU 00H ; Port 0
+P1 EQU 01H ; Port 1
+P2 EQU 02H ; Port 2
+P3 EQU 03H ; Port 3
+SIO EQU 0F0H ; serielles Ein-Ausgaberegister
+FLAGS EQU 0FCH ; Flagregister
+SPH EQU 0FEH ; Stackpointer, Highteil
+SPL EQU 0FFH ; Stackpointer, Lowteil
+TMR EQU 0F1H ; Zähler/Zeitgeberbetriebsart
+T0 EQU 0F4H ; Zähler/Zeitgeberregister Kanal 0
+T1 EQU 0F2H ; Zähler/Zeitgeberregister Kanal 1
+PRE0 EQU 0F5H ; T0-Vorteilerregister
+PRE1 EQU 0F3H ; T1-Vorteilerregister
+P01M EQU 0F8H ; Tor 0, Tor 1 Betriebsart
+P2M EQU 0F6H ; Tor 2 Betriebsart
+P3M EQU 0F7H ; Tor 3 Betriebsart
+IMR EQU 0FBH ; Interrupt-Maskierungsregister
+IPR EQU 0F9H ; Interrupt-Prioritätsregister
+IRQ EQU 0FAH ; Interrupt-Anmelderegister
+RP EQU 0FDH ; Registerpointer
+
+;---------------------------------------------------------------------------
+
+ endif
+
+ restore ; wieder erlauben
+
diff --git a/install.bat b/install.bat
new file mode 100644
index 0000000..e08cdec
--- /dev/null
+++ b/install.bat
@@ -0,0 +1,24 @@
+@echo off
+md %1
+set binfiles=asl.exe plist.exe pbind.exe p2hex.exe p2bin.exe
+for %%i in (%binfiles%) do tdstrip %%i
+for %%i in (%binfiles%) do copy %%i %1
+ren %1\asl.exe as.exe
+set binfiles=
+copy *.msg %1
+
+md %2
+for %%i in (include\*.inc) do copy %%i %2
+for %%i in (%2\*.inc) do unumlaut %%i
+
+md %3
+for %%i in (*.1) do copy %%i %3
+
+md %4
+for %%i in (*.msg) do copy %%i %1
+
+md %5
+set docdirs=DE EN
+for %%i in (%docdirs%) do copy doc_%%i\as.doc %5\as_%%i.doc
+for %%i in (%docdirs%) do copy doc_%%i\as.tex %5\as_%%i.tex
+for %%i in (%docdirs%) do copy doc_%%i\as.htm %5\as_%%i.htm
diff --git a/install.cmd b/install.cmd
new file mode 100644
index 0000000..b5ddba2
--- /dev/null
+++ b/install.cmd
@@ -0,0 +1,24 @@
+md %1
+set binfiles=asl.exe plist.exe pbind.exe p2hex.exe p2bin.exe
+rem for %%i in (%binfiles%) do strip %%i
+for %%i in (%binfiles%) do copy %%i %1
+ren %1\asl.exe as2.exe
+set binfiles=
+copy *.msg %1
+
+md %2
+for %%i in (include\*.inc) do copy %%i %2
+for %%i in (%2\*.inc) do unumlaut %%i
+
+md %3
+for %%i in (*.1) do copy %%i %3
+
+md %4
+for %%i in (*.msg) do copy %%i %1
+
+md %5
+set docdirs=DE EN
+for %%i in (%docdirs%) do copy doc_%%i\as.doc %5\as_%%i.doc
+for %%i in (%docdirs%) do copy doc_%%i\as.tex %5\as_%%i.tex
+for %%i in (%docdirs%) do copy doc_%%i\as.html %5\as_%%i.html
+ \ No newline at end of file
diff --git a/install.sh b/install.sh
new file mode 100755
index 0000000..affd41e
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+# set -v
+
+echo "Installing files:"
+
+if [ "$1" != "" ]; then
+ mkdirhier $1
+ chmod 755 $1
+ for i in asl plist pbind p2hex p2bin; do
+ echo $1/$i
+ strip $i
+ cp $i $1
+ chmod 755 $1/$i
+ done
+fi
+
+if [ "$2" != "" ]; then
+ mkdirhier $2
+ chmod 755 $2
+ for i in include/*.inc; do
+ base=`basename $i`
+ echo $2/$base
+ cp $i $2
+ chmod 644 $2/$base
+ done
+fi
+
+if [ "$3" != "" ]; then
+ mkdirhier $3/man1
+ chmod 755 $3 $3/man1
+ for i in *.1; do
+ echo $3/man1/$i
+ cp $i $3/man1
+ chmod 644 $3/man1/$i
+ done
+fi
+
+if [ "$4" != "" ]; then
+ mkdirhier $4
+ chmod 755 $4
+ for i in *.msg; do
+ echo $4/$i
+ cp $i $4
+ chmod 644 $4/$i
+ done
+fi
+
+if [ "$5" != "" ]; then
+ mkdirhier $5
+ chmod 755 $5
+ for i in DE EN; do
+ echo $5/as-$i.doc
+ cp doc_$i/as.doc $5/as-$i.doc
+ echo $5/as-$i.tex
+ cp doc_$i/as.tex $5/as-$i.tex
+ if [ -f doc_$i/as.dvi ]; then
+ echo $5/as-$i.dvi
+ cp doc_$i/as.dvi $5/as-$i.dvi
+ fi
+ if [ -f doc_$i/as.ps ]; then
+ echo $5/as-$i.ps
+ cp doc_$i/as.ps $5/as-$i.ps
+ fi
+ chmod 644 $5/as-$i.*
+ done
+fi
diff --git a/ioerrs.c b/ioerrs.c
new file mode 100644
index 0000000..7efa5d7
--- /dev/null
+++ b/ioerrs.c
@@ -0,0 +1,193 @@
+/* ioerrs.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Abliefern der I/O-Fehlermeldungen */
+/* */
+/* Historie: 11.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <errno.h>
+#include "nlmessages.h"
+#include "ioerrs.rsc"
+#include "ioerrs.h"
+
+typedef struct
+ {
+ int Code;
+ int Msg;
+ } ErrorDef;
+
+static TMsgCat MsgCat;
+
+static ErrorDef ErrorDefs[]={
+#ifdef EPERM
+ {EPERM , Num_IoErr_EPERM},
+#endif
+#ifdef ENOENT
+ {ENOENT , Num_IoErr_ENOENT},
+#endif
+#ifdef ESRCH
+ {ESRCH , Num_IoErr_ESRCH},
+#endif
+#ifdef EINTR
+ {EINTR , Num_IoErr_EINTR},
+#endif
+#ifdef EIO
+ {EIO , Num_IoErr_EIO},
+#endif
+#ifdef ENXIO
+ {ENXIO , Num_IoErr_ENXIO},
+#endif
+#ifdef E2BIG
+ {E2BIG , Num_IoErr_E2BIG},
+#endif
+#ifdef ENOEXEC
+ {ENOEXEC , Num_IoErr_ENOEXEC},
+#endif
+#ifdef EBADF
+ {EBADF , Num_IoErr_EBADF},
+#endif
+#ifdef ECHILD
+ {ECHILD , Num_IoErr_ECHILD},
+#endif
+#ifdef EDEADLK
+ {EDEADLK , Num_IoErr_EDEADLK},
+#endif
+#ifdef ENOMEM
+ {ENOMEM , Num_IoErr_ENOMEM},
+#endif
+#ifdef EACCES
+ {EACCES , Num_IoErr_EACCES},
+#endif
+#ifdef EFAULT
+ {EFAULT , Num_IoErr_EFAULT},
+#endif
+#ifdef ENOTBLK
+ {ENOTBLK , Num_IoErr_ENOTBLK},
+#endif
+#ifdef EBUSY
+ {EBUSY , Num_IoErr_EBUSY},
+#endif
+#ifdef EEXIST
+ {EEXIST , Num_IoErr_EEXIST},
+#endif
+#ifdef EXDEV
+ {EXDEV , Num_IoErr_EXDEV},
+#endif
+#ifdef ENODEV
+ {ENODEV , Num_IoErr_ENODEV},
+#endif
+#ifdef ENOTDIR
+ {ENOTDIR , Num_IoErr_ENOTDIR},
+#endif
+#ifdef EISDIR
+ {EISDIR , Num_IoErr_EISDIR},
+#endif
+#ifdef EINVAL
+ {EINVAL , Num_IoErr_EINVAL},
+#endif
+#ifdef ENFILE
+ {ENFILE , Num_IoErr_ENFILE},
+#endif
+#ifdef EMFILE
+ {EMFILE , Num_IoErr_EMFILE},
+#endif
+#ifdef ENOTTY
+ {ENOTTY , Num_IoErr_ENOTTY},
+#endif
+#ifdef ETXTBSY
+ {ETXTBSY , Num_IoErr_ETXTBSY},
+#endif
+#ifdef EFBIG
+ {EFBIG , Num_IoErr_EFBIG},
+#endif
+#ifdef ENOSPC
+ {ENOSPC , Num_IoErr_ENOSPC},
+#endif
+#ifdef ESPIPE
+ {ESPIPE , Num_IoErr_ESPIPE},
+#endif
+#ifdef EROFS
+ {EROFS , Num_IoErr_EROFS},
+#endif
+#ifdef EMLINK
+ {EMLINK , Num_IoErr_EMLINK},
+#endif
+#ifdef EPIPE
+ {EPIPE , Num_IoErr_EPIPE},
+#endif
+#ifdef EDOM
+ {EDOM , Num_IoErr_EDOM},
+#endif
+#ifdef ERANGE
+ {ERANGE , Num_IoErr_ERANGE},
+#endif
+#ifdef ENAMETOOLONG
+ {ENAMETOOLONG, Num_IoErr_ENAMETOOLONG},
+#endif
+#ifdef ENOLCK
+ {ENOLCK , Num_IoErr_ENOLCK},
+#endif
+#ifdef ENOSYS
+ {ENOSYS , Num_IoErr_ENOSYS},
+#endif
+#ifdef ENOTEMPTY
+ {ENOTEMPTY , Num_IoErr_ENOTEMPTY},
+#endif
+#ifdef ELOOP
+ {ELOOP , Num_IoErr_ELOOP},
+#endif
+#ifdef EWOULDBLOCK
+ {EWOULDBLOCK , Num_IoErr_EWOULDBLOCK},
+#endif
+#ifdef ENOMSG
+ {ENOMSG , Num_IoErr_ENOMSG},
+#endif
+#ifdef EIDRM
+ {EIDRM , Num_IoErr_EIDRM},
+#endif
+#ifdef ECHRNG
+ {ECHRNG , Num_IoErr_ECHRNG},
+#endif
+#ifdef EL2NSYNC
+ {EL2NSYNC , Num_IoErr_EL2NSYNC},
+#endif
+#ifdef EL3HLT
+ {EL3HLT , Num_IoErr_EL3HLT},
+#endif
+#ifdef EL3RST
+ {EL3RST , Num_IoErr_EL3RST},
+#endif
+#ifdef ELNRNG
+ {ELNRNG , Num_IoErr_ELNRNG},
+#endif
+#ifdef EUNATCH
+ {EUNATCH , Num_IoErr_EUNATCH},
+#endif
+#ifdef ENOCSI
+ {ENOCSI , Num_IoErr_ENOCSI},
+#endif
+ {-1,-1}};
+
+ char *GetErrorMsg(int number)
+BEGIN
+ static String hs;
+ ErrorDef *z;
+
+ for (z=ErrorDefs; z->Msg!=-1; z++)
+ if (number==z->Code) break;
+
+ if (z->Msg!=-1) return catgetmessage(&MsgCat,z->Msg);
+ else
+ BEGIN
+ sprintf(hs,"%s%d",catgetmessage(&MsgCat,Num_IoErrUnknown),number); return hs;
+ END
+END
+
+ void ioerrs_init(char *ProgPath)
+BEGIN
+ opencatalog(&MsgCat,"ioerrs.msg",ProgPath,MsgId1,MsgId2);
+END
diff --git a/ioerrs.h b/ioerrs.h
new file mode 100644
index 0000000..c3238c3
--- /dev/null
+++ b/ioerrs.h
@@ -0,0 +1,13 @@
+/* ioerrs.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Abliefern der I/O-Fehlermeldungen */
+/* */
+/* Historie: 11.10.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern char *GetErrorMsg(int number);
+
+extern void ioerrs_init(char *ProgPath);
diff --git a/ioerrs.res b/ioerrs.res
new file mode 100644
index 0000000..b2a70b5
--- /dev/null
+++ b/ioerrs.res
@@ -0,0 +1,212 @@
+;* ioerrs.res
+;*****************************************************************************
+;* AS-Portierung *
+;* *
+;* Definition Fehlermeldungs-Strings *
+;* *
+;* Historie: 6. 9.1996 Grundsteinlegung *
+;* 19. 9.1996 ...EACCESS *
+;* *
+;*****************************************************************************
+
+Include header.res
+
+Message IoErr_EPERM
+ "kein Eigent&auml;mer"
+ "Not owner"
+
+Message IoErr_ENOENT
+ "Datei oder Verzeichnis nicht gefunden"
+ "No such file or directory"
+
+Message IoErr_ESRCH
+ "Proze&szlig; existiert nicht"
+ "No such process"
+
+Message IoErr_EINTR
+ "unterbrochener Systemaufruf"
+ "Interrupted system call"
+
+Message IoErr_EIO
+ "E/A-Fehler"
+ "I/O error"
+
+Message IoErr_ENXIO
+ "Ger&auml;t existiert nicht"
+ "No such device or address"
+
+Message IoErr_E2BIG
+ "Parameterliste zu lang"
+ "Exec format error"
+
+Message IoErr_ENOEXEC
+ "Programm-Dateiformatfehler"
+ "Bad file number"
+
+Message IoErr_EBADF
+ "ung&uuml;ltiger Dateihandle"
+ "No children"
+
+Message IoErr_ECHILD
+ "Tochterproze&szlig; existiert nicht"
+ "Operation would cause deadlock"
+
+Message IoErr_EDEADLK
+ "Operation w&uuml;rde Deadlock verursachen"
+ "Operation would cause deadlock"
+
+Message IoErr_ENOMEM
+ "Speicher&uuml;berlauf"
+ "Not enough core"
+
+Message IoErr_EACCES
+ "Zugriff verweigert"
+ "Permission denied"
+
+Message IoErr_EFAULT
+ "Adre&szlig;fehler"
+ "Bad address"
+
+Message IoErr_ENOTBLK
+ "Blockger&auml;t erforderlich"
+ "Block device required"
+
+Message IoErr_EBUSY
+ "Ger&auml;t blockiert"
+ "Device or resource busy"
+
+Message IoErr_EEXIST
+ "Datei existiert bereits"
+ "File exists"
+
+Message IoErr_EXDEV
+ "Link &uuml;ber verschiedene Ger&auml;te"
+ "Cross-device link"
+
+Message IoErr_ENODEV
+ "Ger&auml;t nicht vorhanden"
+ "No such device"
+
+Message IoErr_ENOTDIR
+ "kein Verzeichnis"
+ "Not a directory"
+
+Message IoErr_EISDIR
+ "Verzeichnis"
+ "Is a directory"
+
+Message IoErr_EINVAL
+ "ung&uuml;ltiges Argument"
+ "Invalid argument"
+
+Message IoErr_ENFILE
+ "Dateitabellen&uuml;berlauf"
+ "File table overflow"
+
+Message IoErr_EMFILE
+ "zu viele offene Dateien"
+ "Too many open files"
+
+Message IoErr_ENOTTY
+ "kein Fernschreiber"
+ "Not a typewriter"
+
+Message IoErr_ETXTBSY
+ "Code-Datei blockiert"
+ "Text file busy"
+
+Message IoErr_EFBIG
+ "Datei zu gro&szlig;"
+ "File too large"
+
+Message IoErr_ENOSPC
+ "Dateisystem voll"
+ "No space left on device"
+
+Message IoErr_ESPIPE
+ "Ung&uuml;ltige Positionierung"
+ "Illegal seek"
+
+Message IoErr_EROFS
+ "Dateisystem nur lesbar"
+ "Read-only file system"
+
+Message IoErr_EMLINK
+ "zu viele Links"
+ "Too many links"
+
+Message IoErr_EPIPE
+ "geplatzter Schlauch ;-)"
+ "Broken pipe"
+
+Message IoErr_EDOM
+ "Funktionsargument au&szlig;erhalb Definitionsbereich"
+ "Math argument out of domain of func"
+
+Message IoErr_ERANGE
+ "Funktionsergebnis au&szlig;erhalb Wertebereich"
+ "Math result not representable"
+
+Message IoErr_ENAMETOOLONG
+ "Dateiname zu lang"
+ "File name too long"
+
+Message IoErr_ENOLCK
+ "Datensatzverieglung nicht m&ouml;glich"
+ "No record locks available"
+
+Message IoErr_ENOSYS
+ "Funktion nicht implementiert"
+ "Function not implemented"
+
+Message IoErr_ENOTEMPTY
+ "Verzeichnis nicht leer"
+ "Directory not empty"
+
+Message IoErr_ELOOP
+ "zu viele symbolische Links"
+ "Too many symbolic links encountered"
+
+Message IoErr_EWOULDBLOCK
+ "Operation w&uuml;rde blockieren"
+ "Operation would block"
+
+Message IoErr_ENOMSG
+ "keine Nachricht gew&uuml;nschten Typs verf&uuml;gbar"
+ "No message of desired type"
+
+Message IoErr_EIDRM
+ "Kennung entfernt"
+ "Identifier removed"
+
+Message IoErr_ECHRNG
+ "Kanalnummer au&szlig;erhalb Bereich"
+ "Channel number out of range"
+
+Message IoErr_EL2NSYNC
+ "Ebene 2 nicht synchronisiert"
+ "Level 2 not synchronized"
+
+Message IoErr_EL3HLT
+ "Ebene 3 angehalten"
+ "Level 3 halted"
+
+Message IoErr_EL3RST
+ "Ebene 3 zur&uuml;ckgesetzt"
+ "Level 3 reset"
+
+Message IoErr_ELNRNG
+ "Link-Nummer au&szlig;erhalb Bereich"
+ "Link number out of range"
+
+Message IoErr_EUNATCH
+ "Protokolltreiber nicht angebunden"
+ "Protocol driver not attached"
+
+Message IoErr_ENOCSI
+ "keine CSI-Struktur verf&uuml;gbar"
+ "No CSI structure available"
+
+Message IoErrUnknown
+ "unbekannter Fehler Nr."
+ "unknown error no."
diff --git a/makedefs.files b/makedefs.files
new file mode 100644
index 0000000..3c79423
--- /dev/null
+++ b/makedefs.files
@@ -0,0 +1,35 @@
+BASEARCH1FILES = *.c *.h *.1 \
+ INSTALL README README.OS2 README.DOS README.LANGS README.KR TODO BENCHES Makefile Makefile.dos Makefile.os2 Makefile.def.tmpl \
+ install.sh install.bat install.cmd marks.asm \
+ *.res objdefs.* makedefs.* asl.def \
+ include/*.inc \
+ Makefile.def-samples
+BASEARCH2FILES = doc_DE doc_EN \
+ tests
+
+DISTARCHFILES = $(BASEARCH1FILES) $(BASEARCH2FILES) asl-$(VERSION).lsm changelog
+
+ARCH1FILES = $(BASEARCH1FILES)
+ARCH2FILES = $(BASEARCH2FILES) header.tmpl *.lsm changelog
+
+ARCHFILES = $(ARCH1FILES) $(ARCH2FILES)
+
+# set EXEXTENSION im Makefile.def if you need a specific extension for
+# the executables (e.g. .exe for OS/2)
+
+ASLTARGET = asl$(EXEXTENSION)
+PLISTTARGET = plist$(EXEXTENSION)
+PBINDTARGET = pbind$(EXEXTENSION)
+P2HEXTARGET = p2hex$(EXEXTENSION)
+P2BINTARGET = p2bin$(EXEXTENSION)
+RESCOMPTARGET = rescomp$(EXEXTENSION)
+TEX2DOCTARGET = tex2doc$(EXEXTENSION)
+TEX2HTMLTARGET = tex2html$(EXEXTENSION)
+UNUMLAUTTARGET = unumlaut$(EXEXTENSION)
+
+ALLTARGETS = ioerrs.msg cmdarg.msg tools.msg \
+ as.msg $(ASLTARGET) \
+ plist.msg $(PLISTTARGET) \
+ pbind.msg $(PBINDTARGET) \
+ p2hex.msg $(P2HEXTARGET) \
+ p2bin.msg $(P2BINTARGET)
diff --git a/makedefs.src b/makedefs.src
new file mode 100644
index 0000000..53e0b05
--- /dev/null
+++ b/makedefs.src
@@ -0,0 +1,53 @@
+CODE_SRCS = codepseudo.c codevars.c \
+ code68k.c \
+ code56k.c \
+ code601.c \
+ codemcore.c \
+ code68.c code6805.c code6809.c code6812.c code6816.c \
+ codeh8_3.c codeh8_5.c code7000.c \
+ code65.c code7700.c code4500.c codem16.c codem16c.c \
+ code4004.c code8008.c code48.c code51.c code96.c code85.c code86.c code960.c \
+ code8x30x.c codexa.c \
+ codeavr.c \
+ code29k.c \
+ code166.c \
+ codez80.c codez8.c \
+ code96c141.c code90c141.c code87c800.c code47c00.c code97c241.c \
+ code16c5x.c code16c8x.c code17c4x.c \
+ codest6.c codest7.c codest9.c code6804.c \
+ code3201x.c code3202x.c code3203x.c code3205x.c code3206x.c \
+ code9900.c codetms7.c code370.c codemsp.c \
+ code78c10.c code75k0.c code78k0.c code7720.c code77230.c \
+ codescmp.c codecop8.c codesc14xxx.c \
+ codeace.c \
+ code53c8xx.c \
+ codefmc8.c
+
+ST_SRCS = strutil.c stdhandl.c stringlists.c
+
+NLS_SRCS = nls.c nlmessages.c
+
+ASM_SRCS = as.c asmdef.c asmsub.c asmpars.c asmmac.c asmcode.c asmdebug.c asmif.c \
+ asmfnums.c asmrelocs.c asminclist.c asmitree.c asmallg.c
+
+AS_SRCS = version.c endian.c bpemu.c chunks.c cmdarg.c ioerrs.c headids.c
+
+PLIST_SRCS = plist.c version.c toolutils.c headids.c\
+ endian.c bpemu.c hex.c strutil.c cmdarg.c ioerrs.c
+
+PBIND_SRCS = pbind.c version.c toolutils.c\
+ endian.c bpemu.c strutil.c stdhandl.c cmdarg.c ioerrs.c
+
+P2HEX_SRCS = p2hex.c version.c toolutils.c headids.c\
+ endian.c bpemu.c hex.c strutil.c chunks.c cmdarg.c ioerrs.c
+
+P2BIN_SRCS = p2bin.c version.c toolutils.c\
+ endian.c bpemu.c hex.c strutil.c chunks.c cmdarg.c ioerrs.c
+
+RESCOMP_SRCS = rescomp.c endian.c strutil.c bpemu.c
+
+TEX2DOC_SRCS = tex2doc.c findhyphen.c asmitree.c strutil.c ushyph.c grhyph.c
+
+TEX2HTML_SRCS = tex2html.c asmitree.c strutil.c
+
+UNUMLAUT_SRCS = unumlaut.c
diff --git a/makedefs.str b/makedefs.str
new file mode 100644
index 0000000..b5d40d1
--- /dev/null
+++ b/makedefs.str
@@ -0,0 +1,41 @@
+ioerrs.$(OBJEXTENSION): ioerrs.rsc
+
+ioerrs.msg ioerrs.rsc: ioerrs.res header.res $(RESCOMPTARGET)
+ $(CURRDIR)$(RESCOMPTARGET) ioerrs.res ioerrs.msg ioerrs.rsc
+
+cmdarg.$(OBJEXTENSION): cmdarg.rsc
+
+cmdarg.msg cmdarg.rsc: cmdarg.res header.res $(RESCOMPTARGET)
+ $(CURRDIR)$(RESCOMPTARGET) cmdarg.res cmdarg.msg cmdarg.rsc
+
+toolutils.$(OBJEXTENSION): tools.rsc
+
+tools.msg tools.rsc: tools.res header.res $(RESCOMPTARGET)
+ $(CURRDIR)$(RESCOMPTARGET) tools.res tools.msg tools.rsc
+
+as.$(OBJEXTENSION) asminclist.$(OBJEXTENSION) asmmac.$(OBJEXTENSION) asmpars.$(OBJEXTENSION) asmsub.$(OBJEXTENSION): as.rsc
+
+as.msg as.rsc: as.res header.res $(RESCOMPTARGET)
+ $(CURRDIR)$(RESCOMPTARGET) as.res as.msg as.rsc
+
+plist.$(OBJEXTENSION): plist.rsc
+
+plist.msg plist.rsc: plist.res tools2.res header.res $(RESCOMPTARGET)
+ $(CURRDIR)$(RESCOMPTARGET) plist.res plist.msg plist.rsc
+
+pbind.$(OBJEXTENSION): pbind.rsc
+
+pbind.msg pbind.rsc: pbind.res tools2.res header.res $(RESCOMPTARGET)
+ $(CURRDIR)$(RESCOMPTARGET) pbind.res pbind.msg pbind.rsc
+
+p2hex.$(OBJEXTENSION): p2hex.rsc
+
+p2hex.msg p2hex.rsc: p2hex.res tools2.res header.res $(RESCOMPTARGET)
+ $(CURRDIR)$(RESCOMPTARGET) p2hex.res p2hex.msg p2hex.rsc
+
+p2bin.$(OBJEXTENSION): p2bin.rsc
+
+p2bin.msg p2bin.rsc: p2bin.res tools2.res header.res $(RESCOMPTARGET)
+ $(CURRDIR)$(RESCOMPTARGET) p2bin.res p2bin.msg p2bin.rsc
+
+tex2doc.$(OBJEXTENSION): ushyph.h grhyph.h
diff --git a/marks.asm b/marks.asm
new file mode 100644
index 0000000..b501f98
--- /dev/null
+++ b/marks.asm
@@ -0,0 +1,29 @@
+ConstBUF32 equ 65.12
+ConstFL900 equ 33.52
+ConstMIC51 equ 359.52
+
+
+ read "BUF32, Pass1 [sec]: ", buf32_1
+ read "FL900, Pass1 [sec]: ", fl900_1
+ read "MIC51, Pass1 [sec]: ", mic51_1
+ read "BUF32, Pass2 [sec]: ", buf32_2
+ read "FL900, Pass2 [sec]: ", fl900_2
+ read "MIC51, Pass2 [sec]: ", mic51_2
+ read "BUF32, Pass3 [sec]: ", buf32_3
+ read "FL900, Pass3 [sec]: ", fl900_3
+ read "MIC51, Pass3 [sec]: ", mic51_3
+
+buf32 equ (buf32_1+buf32_2+buf32_3)/3.0
+ message "--> BUF32= \{BUF32}"
+fl900 equ (fl900_1+fl900_2+fl900_3)/3.0
+ message "--> Fl900= \{FL900}"
+mic51 equ (mic51_1+mic51_2+mic51_3)/3.0
+ message "--> MIC51= \{MIC51}"
+
+marks equ ((ConstBUF32/buf32)+(ConstFL900/fl900)+(ConstMIC51/mic51))/3
+ message "--> Marks= \{MARKS}"
+
+ read "Clk [MHz]: ", ClkFreq
+rel equ marks/ClkFreq
+ message "Rel=\{REL}"
+
diff --git a/nlmessages.c b/nlmessages.c
new file mode 100644
index 0000000..4610a23
--- /dev/null
+++ b/nlmessages.c
@@ -0,0 +1,210 @@
+/* nlmessages.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Einlesen und Verwalten von Meldungs-Strings */
+/* */
+/* Historie: 13. 8.1997 Grundsteinlegung */
+/* 17. 8.1997 Verallgemeinerung auf mehrere Kataloge */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include "strutil.h"
+
+#include "endian.h"
+#include "bpemu.h"
+#include "nls.h"
+
+#include "nlmessages.h"
+
+/*****************************************************************************/
+
+static char *IdentString="AS Message Catalog - not readable\n\032\004";
+
+static char *EOpenMsg="cannot open msg file %s";
+static char *ERdMsg="cannot read from msg file";
+static char *EIndMsg="string table index error";
+
+static TMsgCat DefaultCatalog={Nil,Nil,0};
+
+/*****************************************************************************/
+
+ static void error(char *Msg)
+BEGIN
+ fprintf(stderr,"message catalog handling: %s - program terminated\n",Msg);
+ exit(255);
+END
+
+ char *catgetmessage(PMsgCat Catalog, int Num)
+BEGIN
+ static char umess[256];
+
+ if ((Num>=0) AND (Num<Catalog->MsgCount)) return Catalog->MsgBlock+Catalog->StrPosis[Num];
+ else
+ BEGIN
+ sprintf(umess,"Hey sie Sack, Message-Nummer %d gibbet nich!",Num);
+ return umess;
+ END
+END
+
+ char *getmessage(int Num)
+BEGIN
+ return catgetmessage(&DefaultCatalog,Num);
+END
+
+ FILE *myopen(char *name, LongInt MsgId1, LongInt MsgId2)
+BEGIN
+ FILE *tmpfile;
+ String line;
+ LongInt RId1,RId2;
+ Boolean EForm=False;
+
+ tmpfile=fopen(name,OPENRDMODE);
+ if (tmpfile==Nil) return Nil;
+ if (fread(line,1,strlen(IdentString),tmpfile)!=strlen(IdentString)) EForm=True;
+ if (memcmp(line,IdentString,strlen(IdentString))!=0) EForm=True;
+ if (NOT Read4(tmpfile,&RId1)) EForm=True;
+ if (RId1!=MsgId1) EForm=True;
+ if (NOT Read4(tmpfile,&RId2)) EForm=True;
+ if (RId2!=MsgId2) EForm=True;
+ if (EForm)
+ BEGIN
+ fclose(tmpfile);
+ fprintf(stderr,"message catalog handling: warning: %s has invalid format or is out of date\n",name);
+ return Nil;
+ END
+ else return tmpfile;
+END
+
+#define MSGPATHNAME "AS_MSGPATH"
+
+ void opencatalog(PMsgCat Catalog, char *File, char *Path, LongInt MsgId1, LongInt MsgId2)
+BEGIN
+ FILE *MsgFile;
+ char str[2048],*ptr;
+#if defined(DOS_NLS) || defined (OS2_NLS)
+ NLS_CountryInfo NLSInfo;
+#else
+ char *lcstring;
+#endif
+ LongInt DefPos= -1,MomPos,DefLength=0,MomLength,z,StrStart,CtryCnt,Ctrys[100];
+ Boolean fi,Gotcha;
+
+ /* get reference for finding out which language set to use */
+
+#if defined(DOS_NLS) || defined (OS2_NLS)
+ NLS_GetCountryInfo(&NLSInfo);
+#else
+ lcstring=getenv("LC_MESSAGES");
+ if (lcstring==Nil) lcstring=getenv("LC_ALL");
+ if (lcstring==Nil) lcstring=getenv("LANG");
+ if (lcstring==Nil) lcstring="";
+#endif
+
+ /* find first valid message file */
+
+ MsgFile=myopen(File,MsgId1,MsgId2);
+ if (MsgFile==Nil)
+ BEGIN
+ if (*Path!='\0')
+ BEGIN
+#ifdef _WIN32
+ for (ptr=Path; *ptr!='\0'; ptr++)
+ if (*ptr=='/') *ptr='\\';
+#endif
+ ptr=strrchr(Path,PATHSEP); if (ptr==Nil) ptr=Path+strlen(Path);
+ memcpy(str,Path,ptr-Path); str[ptr-Path]='\0';
+ strcat(str,SPATHSEP); strcat(str,File);
+ MsgFile=myopen(str,MsgId1,MsgId2);
+ END
+ if (MsgFile==Nil)
+ BEGIN
+ ptr=getenv(MSGPATHNAME);
+ if (ptr!=Nil)
+ BEGIN
+ sprintf(str,"%s/%s",ptr,File);
+ MsgFile=myopen(str,MsgId1,MsgId2);
+ END
+ else
+ BEGIN
+ ptr=getenv("PATH");
+ if (ptr==Nil) MsgFile=Nil;
+ else
+ BEGIN
+ strmaxcpy(str,ptr,255);
+ ptr=FSearch(File,str);
+ MsgFile=(*ptr!='\0') ? myopen(ptr,MsgId1,MsgId2) : Nil;
+ END
+ END
+ if (MsgFile==Nil)
+ BEGIN
+ sprintf(str,"%s/%s",LIBDIR,File);
+ MsgFile=myopen(str,MsgId1,MsgId2);
+ if (MsgFile==Nil)
+ BEGIN
+ sprintf(str,EOpenMsg,File); error(str);
+ END
+ END
+ END
+ END
+
+ Gotcha=False;
+ do
+ BEGIN
+ ptr=str;
+ do
+ BEGIN
+ if (fread(ptr,1,1,MsgFile)!=1) error(ERdMsg);
+ fi=(*ptr=='\0');
+ if (NOT fi) ptr++;
+ END
+ while (NOT fi);
+ if (*str!='\0')
+ BEGIN
+ if (NOT Read4(MsgFile,&MomLength)) error(ERdMsg);
+ if (NOT Read4(MsgFile,&CtryCnt)) error(ERdMsg);
+ for (z=0; z<CtryCnt; z++)
+ if (NOT Read4(MsgFile,Ctrys+z)) error(ERdMsg);
+ if (NOT Read4(MsgFile,&MomPos)) error(ERdMsg);
+ if (DefPos==-1) { DefPos=MomPos; DefLength=MomLength; }
+#if defined(DOS_NLS) || defined (OS2_NLS)
+ for (z=0; z<CtryCnt; z++)
+ if (Ctrys[z]==NLSInfo.Country) Gotcha=True;
+#else
+ Gotcha=(strncasecmp(lcstring,str,strlen(str))==0);
+#endif
+ END
+ END
+ while ((*str!='\0') AND (NOT Gotcha));
+ if (*str=='\0') { MomPos=DefPos; MomLength=DefLength; }
+
+ /* read pointer table */
+
+ fseek(MsgFile,MomPos,SEEK_SET);
+ if (NOT Read4(MsgFile,&StrStart)) error(ERdMsg);
+ Catalog->MsgCount=(StrStart-MomPos)>>2;
+ Catalog->StrPosis=(LongInt *) malloc(sizeof(LongInt)*Catalog->MsgCount);
+ Catalog->StrPosis[0]=0;
+ if (fread(Catalog->StrPosis+1,4,Catalog->MsgCount-1,MsgFile)!=Catalog->MsgCount-1) error(ERdMsg);
+ if (BigEndian) DSwap(Catalog->StrPosis+1,(Catalog->MsgCount-1)<<2);
+ for (z=1; z<Catalog->MsgCount; z++)
+ BEGIN
+ Catalog->StrPosis[z]-=StrStart;
+ if ((Catalog->StrPosis[z]<0) OR (Catalog->StrPosis[z]>=MomLength)) error(EIndMsg);
+ END
+
+ /* read string table */
+
+ fseek(MsgFile,StrStart,SEEK_SET);
+ Catalog->MsgBlock=(char *) malloc(MomLength);
+ if (fread(Catalog->MsgBlock,1,MomLength,MsgFile)!=MomLength) error(ERdMsg);
+
+ fclose(MsgFile);
+END
+
+ void nlmessages_init(char *File, char *ProgPath, LongInt MsgId1, LongInt MsgId2)
+BEGIN
+ opencatalog(&DefaultCatalog,File,ProgPath,MsgId1,MsgId2);
+END
diff --git a/nlmessages.h b/nlmessages.h
new file mode 100644
index 0000000..5bf8186
--- /dev/null
+++ b/nlmessages.h
@@ -0,0 +1,24 @@
+/* nlmessages.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Einlesen und Verwalten von Meldungs-Strings */
+/* */
+/* Historie: 13. 8.1997 Grundsteinlegung */
+/* 17. 8.1997 Verallgemeinerung auf mehrere Kataloge */
+/* */
+/*****************************************************************************/
+
+typedef struct
+ {
+ char *MsgBlock;
+ LongInt *StrPosis,MsgCount;
+ } TMsgCat,*PMsgCat;
+
+extern char *catgetmessage(PMsgCat Catalog, int Num);
+
+extern void opencatalog(PMsgCat Catalog, char *File, char *Path, LongInt MsgId1, LongInt MsgId2);
+
+extern char *getmessage(int Num);
+
+extern void nlmessages_init(char *File, char *Path, LongInt MsgId1, LongInt MsgId2);
diff --git a/nls.c b/nls.c
new file mode 100644
index 0000000..f377003
--- /dev/null
+++ b/nls.c
@@ -0,0 +1,644 @@
+/* nls.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Abhandlung landesspezifischer Unterschiede */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* 28. 7.1999 %T ist Abkuerzung fuer %H:%M:%S */
+/* */
+/*****************************************************************************/
+
+#undef DEBUG_NLS
+
+#include "stdinc.h"
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#ifdef LOCALE_NLS
+#include <locale.h>
+#include <langinfo.h>
+#endif
+
+#ifdef OS2_NLS
+#define INCL_DOSNLS
+#include <os2.h>
+#endif
+
+#ifdef DOS_NLS
+#include <dos.h>
+#endif
+
+#include "strutil.h"
+
+#include "nls.h"
+
+CharTable UpCaseTable; /* Umsetzungstabellen */
+CharTable LowCaseTable;
+
+static NLS_CountryInfo NLSInfo;
+static CharTable CollateTable;
+
+/*-------------------------------------------------------------------------------*/
+
+/* einen String anhand einer Tabelle uebersetzen: */
+
+ static void TranslateString(char *s, CharTable Table)
+BEGIN
+ for (; *s!='\0'; s++) *s=Table[((unsigned int) *s)&0xff];
+END
+
+/*-------------------------------------------------------------------------------*/
+/* Da es moeglich ist, die aktuelle Codeseite im Programmlauf zu wechseln,
+ ist die Initialisierung in einer getrennten Routine untergebracht. Nach
+ einem Wechsel stellt ein erneuter Aufruf wieder korrekte Verhaeltnisse
+ her. Wen das stoert, der schreibe einfach einen Aufruf in den Initiali-
+ sierungsteil der Unit hinein. */
+
+#ifdef DOS_NLS
+typedef struct
+ {
+ Byte TimeFmt;
+ Byte DateFmt;
+ char Currency[2];
+ char ThouSep[2];
+ char DecSep[2];
+ Byte Reserved[24];
+ } Dos2CountryInfo;
+typedef struct
+ {
+ Word DateFmt;
+ char Currency[5];
+ char ThouSep[2];
+ char DecSep[2];
+ char DateSep[2];
+ char TimeSep[2];
+ Byte CurrFmt;
+ Byte CurrDecimals;
+ Byte TimeFmt;
+ char *UpCasePtr;
+ char DataSep[2];
+ Byte Dummy[8];
+ } Dos3CountryInfo;
+typedef struct
+ {
+ Byte SubFuncNo;
+ char *Result;
+ } DosTableRec;
+
+ char *DosCopy(char *Src, int Len)
+BEGIN
+ char *res=malloc(sizeof(char)*(Len+1));
+ memcpy(res,Src,Len); res[Len]='\0';
+ return res;
+END
+
+ void StandardUpCases(void)
+BEGIN
+ char *s1,*s2;
+
+ s1=CH_ae; s2=CH_Ae; UpCaseTable[((unsigned int) *s1)&0xff]=*s2;
+ s1=CH_oe; s2=CH_Oe; UpCaseTable[((unsigned int) *s1)&0xff]=*s2;
+ s1=CH_ue; s2=CH_Ue; UpCaseTable[((unsigned int) *s1)&0xff]=*s2;
+END
+#endif
+
+ void NLS_Initialize(void)
+BEGIN
+ char *tmpstr,*run,*cpy;
+ Word FmtBuffer;
+ int z;
+#ifdef DEBUG_NLS
+ int z2;
+#endif
+ Boolean DidDate;
+
+#ifdef LOCALE_NLS
+ struct lconv *lc;
+#endif
+
+#ifdef OS2_NLS
+ COUNTRYCODE ccode;
+ COUNTRYINFO cinfo;
+ ULONG erglen;
+#endif
+
+#ifdef DOS_NLS
+ union REGS Regs;
+ struct SREGS SRegs;
+ void *info;
+ Dos2CountryInfo DOS2Info;
+ Dos3CountryInfo DOS3Info;
+ DosTableRec DOSTablePtr;
+#endif
+
+ /* get currency format, separators */
+
+#ifdef NO_NLS
+ NLSInfo.DecSep=".";
+ NLSInfo.DataSep=",";
+ NLSInfo.ThouSep=",";
+ NLSInfo.Currency="$";
+ NLSInfo.CurrDecimals=2;
+ NLSInfo.CurrFmt=CurrFormatPreNoBlank;
+#endif
+
+#ifdef LOCALE_NLS
+ lc=localeconv();
+
+ NLSInfo.DecSep=(lc->mon_decimal_point!=Nil)?lc->decimal_point:".";
+
+ NLSInfo.ThouSep=(lc->mon_thousands_sep!=Nil)?lc->mon_thousands_sep:",";
+
+ NLSInfo.DataSep=",";
+
+ NLSInfo.Currency=(lc->currency_symbol!=Nil)?lc->currency_symbol:"$";
+
+ NLSInfo.CurrDecimals=lc->int_frac_digits;
+ if (NLSInfo.CurrDecimals>4) NLSInfo.CurrDecimals=2;
+
+ if (lc->p_cs_precedes)
+ if (lc->p_sep_by_space) NLSInfo.CurrFmt=CurrFormatPreBlank;
+ else NLSInfo.CurrFmt=CurrFormatPreNoBlank;
+ else
+ if (lc->p_sep_by_space) NLSInfo.CurrFmt=CurrFormatPostBlank;
+ else NLSInfo.CurrFmt=CurrFormatPostNoBlank;
+#endif
+
+#ifdef OS2_NLS
+ ccode.country=0; ccode.codepage=0;
+ DosQueryCtryInfo(sizeof(cinfo),&ccode,&cinfo,&erglen);
+
+ NLSInfo.Country=cinfo.country;
+ NLSInfo.CodePage=cinfo.codepage;
+ NLSInfo.DecSep=strdup(cinfo.szDecimal);
+ NLSInfo.DataSep=strdup(cinfo.szDataSeparator);
+ NLSInfo.ThouSep=strdup(cinfo.szThousandsSeparator);
+ NLSInfo.Currency=strdup(cinfo.szCurrency);
+ NLSInfo.CurrDecimals=cinfo.cDecimalPlace;
+ NLSInfo.CurrFmt=(CurrFormat) cinfo.fsCurrencyFmt;
+#endif
+
+#ifdef DOS_NLS
+ if (_osmajor<3) NLSInfo.CodePage=437;
+ else if (_osminor<30) NLSInfo.CodePage=437;
+ else
+ BEGIN
+ Regs.x.ax=0x6601;
+ int86(0x21,&Regs,&Regs);
+ NLSInfo.CodePage=Regs.x.bx;
+ END
+
+ Regs.x.ax=0x3800;
+ if (_osmajor<3) info=&DOS2Info; else info=&DOS3Info;
+ SRegs.ds=FP_SEG(info); Regs.x.dx=FP_OFF(info);
+ int86x(0x21,&Regs,&Regs,&SRegs);
+ NLSInfo.Country=Regs.x.bx;
+ if (_osmajor>=3)
+ BEGIN
+ NLSInfo.DecSep=DosCopy(DOS3Info.DecSep,2);
+ NLSInfo.DataSep=DosCopy(DOS3Info.DataSep,2);
+ NLSInfo.ThouSep=DosCopy(DOS3Info.ThouSep,2);
+ NLSInfo.Currency=DosCopy(DOS3Info.Currency,5);
+ NLSInfo.CurrDecimals=DOS3Info.CurrDecimals;
+ NLSInfo.CurrFmt=(CurrFormat) DOS3Info.CurrFmt;
+ END
+ /* DOS 2 kennt noch nicht soviel, daher muessen wir selber etwas beisteuern */
+ else
+ BEGIN
+ NLSInfo.DecSep=DosCopy(DOS2Info.DecSep,2);
+ NLSInfo.DataSep=",";
+ NLSInfo.ThouSep=DosCopy(DOS2Info.ThouSep,2);
+ NLSInfo.Currency=DosCopy(DOS2Info.Currency,2);
+ NLSInfo.CurrDecimals=(NLSInfo.Country==39) ? 0 : 2;
+ switch (NLSInfo.Country)
+ BEGIN
+ case 1: case 39:
+ NLSInfo.CurrFmt=CurrFormatPreNoBlank; break;
+ case 3: case 33: case 34: case 358:
+ NLSInfo.CurrFmt=CurrFormatPostBlank; break;
+ default:
+ NLSInfo.CurrFmt=CurrFormatPreBlank;
+ END
+ END
+#endif
+
+ /* get date format */
+
+#ifdef NO_NLS
+ tmpstr="%m/%d/%y"; DidDate=False;
+#endif
+
+#ifdef LOCALE_NLS
+ tmpstr=nl_langinfo(D_FMT);
+ if ((tmpstr==Nil) OR (*tmpstr == '\0')) tmpstr="%m/%d/%y";
+ DidDate=False;
+#endif
+
+#ifdef OS2_NLS
+ NLSInfo.DateFmt=(DateFormat) cinfo.fsDateFmt;
+ NLSInfo.DateSep=strdup(cinfo.szDateSeparator);
+ DidDate=True;
+#endif
+
+#ifdef DOS_NLS
+ if (_osmajor>=3)
+ BEGIN
+ NLSInfo.DateFmt=(DateFormat) DOS3Info.DateFmt;
+ NLSInfo.DateSep=DosCopy(DOS3Info.DateSep,2);
+ END
+ else
+ BEGIN
+ NLSInfo.DateFmt=(DateFormat) DOS2Info.DateFmt;
+ switch (NLSInfo.Country)
+ BEGIN
+ case 3: case 47: case 351: case 32: case 33: case 39: case 34:
+ NLSInfo.DateSep="/"; break;
+ case 49: case 358: case 41:
+ NLSInfo.DateSep="."; break;
+ case 972:
+ NLSInfo.DateSep=" "; break;
+ default:
+ NLSInfo.DateSep="-";
+ END
+ END
+ DidDate=True;
+#endif
+
+ if (NOT DidDate)
+ BEGIN
+ NLSInfo.DateSep=Nil; FmtBuffer=0; run=tmpstr;
+ while (*run!='\0')
+ if (*run=='%')
+ BEGIN
+ FmtBuffer<<=4;
+ switch (toupper(*(++run)))
+ BEGIN
+ case 'D': FmtBuffer+=1; break;
+ case 'M': FmtBuffer+=2; break;
+ case 'Y': FmtBuffer+=3; break;
+ END
+ if (NLSInfo.DateSep==Nil)
+ BEGIN
+ run++; cpy=NLSInfo.DateSep=strdup(" ");
+ while ((*run!=' ') AND (*run!='%')) *(cpy++)=(*(run++));
+ *cpy='\0';
+ END
+ else run++;
+ END
+ else run++;
+ if (FmtBuffer==0x213) NLSInfo.DateFmt=DateFormatMTY;
+ else if (FmtBuffer==0x123) NLSInfo.DateFmt=DateFormatTMY;
+ else NLSInfo.DateFmt=DateFormatYMT;
+ END
+
+ /* get time format */
+
+#ifdef NO_NLS
+ tmpstr="%H:%M:%S"; DidDate=False;
+#endif
+
+#ifdef LOCALE_NLS
+ tmpstr=nl_langinfo(T_FMT);
+ if ((tmpstr==Nil) OR (*tmpstr == '\0')) tmpstr="%H:%M:%S";
+ DidDate=False;
+#endif
+
+#ifdef OS2_NLS
+ NLSInfo.TimeFmt=(TimeFormat) cinfo.fsTimeFmt;
+ NLSInfo.TimeSep=strdup(cinfo.szTimeSeparator);
+ DidDate=True;
+#endif
+
+#ifdef DOS_NLS
+ if (_osmajor>=3)
+ BEGIN
+ NLSInfo.TimeFmt=(TimeFormat) DOS3Info.TimeFmt;
+ NLSInfo.TimeSep=DosCopy(DOS3Info.TimeSep,2);
+ END
+ else
+ BEGIN
+ NLSInfo.TimeFmt=(TimeFormat) DOS2Info.TimeFmt;
+ switch (NLSInfo.Country)
+ BEGIN
+ case 41: case 46: case 47: case 358:
+ NLSInfo.TimeSep=".";
+ default:
+ NLSInfo.TimeSep=":";
+ END
+ END
+ DidDate=True;
+#endif
+
+ if (NOT DidDate)
+ BEGIN
+ NLSInfo.TimeSep=Nil; FmtBuffer=0; run=tmpstr;
+ while (*run!='\0')
+ if (*run=='%')
+ BEGIN
+ FmtBuffer<<=4;
+ switch (toupper(*(++run)))
+ BEGIN
+ case 'S': FmtBuffer+=1; break;
+ case 'M': FmtBuffer+=2; break;
+ case 'H': FmtBuffer+=3; break;
+ case 'T': fprintf(stderr, "\nwarning, detected non-ANSI time format specifier '%%T'");
+ run = "H:%M:%S"; break;
+ case 'R': fprintf(stderr, "\nwarning, detected non-ANSI time format specifier '%%R'");
+ run = "H:%M"; break;
+ END
+ if (NLSInfo.TimeSep==Nil)
+ BEGIN
+ run++; cpy=NLSInfo.TimeSep=strdup(" ");
+ while ((*run != '\0') AND (*run!=' ') AND (*run!='%'))
+ *(cpy++)=(*(run++));
+ *cpy='\0';
+ END
+ else run++;
+ END
+ else run++;
+ NLSInfo.TimeFmt=TimeFormatEurope;
+ END
+
+ /* get lower->upper case table */
+
+#if defined(NO_NLS) || defined(LOCALE_NLS)
+ for (z=0; z<256; z++) UpCaseTable[z]=toupper(z);
+#endif
+
+#ifdef OS2_NLS
+ for (z=0; z<256; z++) UpCaseTable[z]=(char) z;
+ for (z='a'; z<='z'; z++) UpCaseTable[z]-='a'-'A';
+ DosMapCase(sizeof(UpCaseTable),&ccode,UpCaseTable);
+#endif
+
+#ifdef DOS_NLS
+ for (z=0; z<256; z++) UpCaseTable[z]=(char) z;
+ for (z='a'; z<='z'; z++) UpCaseTable[z]-='a'-'A';
+#ifdef __DPMI16__
+ StandardUpCases();
+#else
+ if ((((Word)_osmajor)*100)+_osminor>=330)
+ BEGIN
+ Regs.x.ax=0x6502;
+ Regs.x.bx=NLSInfo.CodePage;
+ Regs.x.dx=NLSInfo.Country;
+ Regs.x.cx=sizeof(DOSTablePtr);
+ info=&DOSTablePtr; SRegs.es=FP_SEG(info); Regs.x.di=FP_OFF(info);
+ int86x(0x21,&Regs,&Regs,&SRegs);
+ if (Regs.x.cx==sizeof(DOSTablePtr))
+ BEGIN
+ DOSTablePtr.Result+=sizeof(Word);
+ memcpy(UpCaseTable+128,DOSTablePtr.Result,128);
+ END
+ else StandardUpCases();
+ END
+ else StandardUpCases();
+#endif
+#endif
+
+ /* get upper->lower case table */
+
+#if defined(NO_NLS) || defined(LOCALE_NLS)
+ for (z=0; z<256; z++) LowCaseTable[z]=tolower(z);
+#endif
+
+#if defined(OS2_NLS) || defined(DOS_NLS)
+ for (z=0; z<256; z++) LowCaseTable[z]=(char) z;
+ for (z=255; z>=0; z--)
+ if (UpCaseTable[z]!=(char) z)
+ LowCaseTable[((unsigned int) UpCaseTable[z])&0xff]=(char) z;
+#endif
+
+ /* get collation table */
+
+#if defined(NO_NLS) || defined(LOCALE_NLS)
+ for (z=0; z<256; z++) CollateTable[z]=z;
+ for (z='a'; z<='z'; z++) CollateTable[z]=toupper(z);
+#endif
+
+#ifdef OS2_NLS
+ for (z=0; z<256; z++) CollateTable[z]=(char) z;
+ DosQueryCollate(sizeof(CollateTable),&ccode,CollateTable,&erglen);
+#endif
+
+#ifdef DOS_NLS
+ for (z=0; z<256; z++) CollateTable[z]=(char) z;
+ for (z='a'; z<='z'; z++) CollateTable[z]=(char) (z-('a'-'A'));
+#ifndef __DPMI16__
+ if ((((Word)_osmajor)*100)+_osminor>=330)
+ BEGIN
+ Regs.x.ax=0x6506;
+ Regs.x.bx=NLSInfo.CodePage;
+ Regs.x.dx=NLSInfo.Country;
+ Regs.x.cx=sizeof(DOSTablePtr);
+ info=&DOSTablePtr; SRegs.es=FP_SEG(info); Regs.x.di=FP_OFF(info);
+ int86x(0x21,&Regs,&Regs,&SRegs);
+ if (Regs.x.cx==sizeof(DOSTablePtr))
+ BEGIN
+ DOSTablePtr.Result+=sizeof(Word);
+ memcpy(CollateTable,DOSTablePtr.Result,256);
+ END
+ END
+#endif
+#endif
+
+#ifdef DEBUG_NLS
+ printf("Country = %d\n",NLSInfo.Country);
+ printf("CodePage = %d\n",NLSInfo.CodePage);
+ printf("DateFmt = ");
+ switch(NLSInfo.DateFmt)
+ BEGIN
+ case DateFormatMTY: printf("MTY\n"); break;
+ case DateFormatTMY: printf("TMY\n"); break;
+ case DateFormatYMT: printf("YMT\n"); break;
+ default: printf("???\n");
+ END
+ printf("DateSep = %s\n",NLSInfo.DateSep);
+ printf("TimeFmt = ");
+ switch(NLSInfo.TimeFmt)
+ BEGIN
+ case TimeFormatUSA: printf("USA\n"); break;
+ case TimeFormatEurope: printf("Europe\n"); break;
+ case TimeFormatJapan: printf("Japan\n"); break;
+ default: printf("???\n");
+ END
+ printf("TimeSep = %s\n",NLSInfo.TimeSep);
+ printf("Currency = %s\n",NLSInfo.Currency);
+ printf("CurrFmt = ");
+ switch (NLSInfo.CurrFmt)
+ BEGIN
+ case CurrFormatPreNoBlank: printf("PreNoBlank\n"); break;
+ case CurrFormatPostNoBlank: printf("PostNoBlank\n"); break;
+ case CurrFormatPreBlank: printf("PreBlank\n"); break;
+ case CurrFormatPostBlank: printf("PostBlank\n"); break;
+ default: printf("???\n");
+ END
+ printf("CurrDecimals = %d\n",NLSInfo.CurrDecimals);
+ printf("ThouSep = %s\n",NLSInfo.ThouSep);
+ printf("DecSep = %s\n",NLSInfo.DecSep);
+ printf("DataSep = %s\n",NLSInfo.DataSep);
+
+ printf("\nUpcaseTable:\n");
+ for (z=0; z<4; z++)
+ BEGIN
+ for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(z*64+z2); putchar ('\n');
+ for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(UpCaseTable[z*64+z2]); putchar ('\n');
+ putchar('\n');
+ END
+
+ printf("\nLowcaseTable:\n");
+ for (z=0; z<4; z++)
+ BEGIN
+ for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(z*64+z2); putchar ('\n');
+ for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(LowCaseTable[z*64+z2]); putchar ('\n');
+ putchar('\n');
+ END
+
+ printf("\nCollateTable:\n");
+ for (z=0; z<4; z++)
+ BEGIN
+ for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(z*64+z2); putchar ('\n');
+ for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(CollateTable[z*64+z2]); putchar ('\n');
+ putchar('\n');
+ END
+
+ exit(0);
+#endif
+END
+
+ void NLS_GetCountryInfo(NLS_CountryInfo *Info)
+BEGIN
+ *Info=NLSInfo;
+END
+
+ void NLS_DateString(Word Year, Word Month, Word Day, char *Dest)
+BEGIN
+ switch (NLSInfo.DateFmt)
+ BEGIN
+ case DateFormatMTY:
+ sprintf(Dest,"%d%s%d%s%d",Month,NLSInfo.DateSep,Day,NLSInfo.DateSep,Year); break;
+ case DateFormatTMY:
+ sprintf(Dest,"%d%s%d%s%d",Day,NLSInfo.DateSep,Month,NLSInfo.DateSep,Year); break;
+ case DateFormatYMT:
+ sprintf(Dest,"%d%s%d%s%d",Year,NLSInfo.DateSep,Month,NLSInfo.DateSep,Day); break;
+ END
+END
+
+ void NLS_CurrDateString(char *Dest)
+BEGIN
+ time_t timep;
+ struct tm *trec;
+
+ time(&timep); trec=localtime(&timep);
+ NLS_DateString(trec->tm_year+1900,trec->tm_mon+1,trec->tm_mday,Dest);
+END
+
+ void NLS_TimeString(Word Hour, Word Minute, Word Second, Word Sec100, char *Dest)
+BEGIN
+ Word OriHour;
+ String ext;
+
+ OriHour=Hour;
+ if (NLSInfo.TimeFmt==TimeFormatUSA)
+ BEGIN
+ Hour%=12; if (Hour==0) Hour=12;
+ END
+ sprintf(Dest,"%d%s%02d%s%02d",Hour,NLSInfo.TimeSep,Minute,NLSInfo.TimeSep,Second);
+ if (Sec100<100)
+ BEGIN
+ sprintf(ext,"%s%02d",NLSInfo.DecSep,Sec100); strcat(Dest,ext);
+ END
+ if (NLSInfo.TimeFmt==TimeFormatUSA)
+ strcat(Dest,(OriHour>12)?"p":"a");
+END
+
+ void NLS_CurrTimeString(Boolean Use100, char *Dest)
+BEGIN
+ time_t timep;
+ struct tm *trec;
+
+ time(&timep); trec=localtime(&timep);
+ NLS_TimeString(trec->tm_hour,trec->tm_min,trec->tm_sec,Use100?0:100,Dest);
+END
+
+ void NLS_CurrencyString(double inp, char *erg)
+BEGIN
+ char s[1024],form[1024];
+ char *p,*z;
+
+ /* Schritt 1: mit passender Nachkommastellenzahl wandeln */
+
+ sprintf(form,"%%0.%df",NLSInfo.CurrDecimals);
+ sprintf(s,form,inp);
+
+ /* Schritt 2: vorne den Punkt suchen */
+
+ p=(NLSInfo.CurrDecimals==0) ? s+strlen(s) : strchr(s,'.');
+
+ /* Schritt 3: Tausenderstellen einfuegen */
+
+ z=p;
+ while (z-s>3)
+ BEGIN
+ strins(s,NLSInfo.ThouSep,z-s-3); z-=3; p+=strlen(NLSInfo.ThouSep);
+ END;
+
+ /* Schritt 4: Komma anpassen */
+
+ strcpy(p,p+1); strins(s,NLSInfo.DecSep,p-s);
+
+ /* Schritt 5: Einheit anbauen */
+
+ switch (NLSInfo.CurrFmt)
+ BEGIN
+ case CurrFormatPreNoBlank:
+ sprintf(erg,"%s%s",NLSInfo.Currency,s); break;
+ case CurrFormatPreBlank:
+ sprintf(erg,"%s %s",NLSInfo.Currency,s); break;
+ case CurrFormatPostNoBlank:
+ sprintf(erg,"%s%s",s,NLSInfo.Currency); break;
+ case CurrFormatPostBlank:
+ sprintf(erg,"%s%s",s,NLSInfo.Currency); break;
+ default:
+ strcpy(p,p+strlen(NLSInfo.DecSep)); strins(NLSInfo.Currency,s,p-s);
+ END
+END
+
+ char Upcase(char inp)
+BEGIN
+ return UpCaseTable[((unsigned int) inp)&0xff];
+END
+
+ void NLS_UpString(char *s)
+BEGIN
+ char *z;
+
+ for (z=s; *z!='\0'; z++) *z=UpCaseTable[((unsigned int)*z)&0xff];
+END
+
+ void NLS_LowString(char *s)
+BEGIN
+ char *z;
+
+ for (z=s; *z!='\0'; z++) *z=LowCaseTable[((unsigned int)*z)&0xff];
+END
+
+ int NLS_StrCmp(const char *s1, const char *s2)
+BEGIN
+ while (CollateTable[((unsigned int)*s1)&0xff]==CollateTable[((unsigned int)*s2)&0xff])
+ BEGIN
+ if ((NOT *s1) AND (NOT *s2)) return 0;
+ s1++; s2++;
+ END
+ return ((int) CollateTable[((unsigned int)*s1)&0xff]-CollateTable[((unsigned int)*s2)&0xff]);
+END
+
+ void nls_init(void)
+BEGIN
+#ifdef LOCALE_NLS
+ (void) setlocale(LC_TIME,"");
+ (void) setlocale(LC_MONETARY,"");
+#endif
+END
diff --git a/nls.h b/nls.h
new file mode 100644
index 0000000..52ab367
--- /dev/null
+++ b/nls.h
@@ -0,0 +1,60 @@
+/* nls.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Abhandlung landesspezifischer Unterschiede */
+/* */
+/* Historie: 16. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+typedef enum {TimeFormatUSA,TimeFormatEurope,TimeFormatJapan} TimeFormat;
+typedef enum {DateFormatMTY,DateFormatTMY,DateFormatYMT} DateFormat;
+typedef enum {CurrFormatPreNoBlank,CurrFormatPostNoBlank,
+ CurrFormatPreBlank ,CurrFormatPostBlank } CurrFormat;
+
+typedef struct
+ {
+ Word Country; /* = internationale Vorwahl */
+ Word CodePage; /* mom. gewaehlter Zeichensatz */
+ DateFormat DateFmt; /* Datumsreihenfolge */
+ char *DateSep; /* Trennzeichen zwischen Datumskomponenten */
+ TimeFormat TimeFmt; /* 12/24-Stundenanzeige */
+ char *TimeSep; /* Trennzeichen zwischen Zeitkomponenten */
+ char *Currency; /* Waehrungsname */
+ CurrFormat CurrFmt; /* Anzeigeformat Waehrung */
+ Byte CurrDecimals; /* Nachkommastellen Waehrungsbetraege */
+ char *ThouSep; /* Trennzeichen fuer Tausenderbloecke */
+ char *DecSep; /* Trennzeichen fuer Nachkommastellen */
+ char *DataSep; /* ??? */
+ } NLS_CountryInfo;
+
+typedef char CharTable[256];
+
+extern CharTable UpCaseTable,LowCaseTable;
+
+
+extern void NLS_Initialize(void);
+
+extern void NLS_GetCountryInfo(NLS_CountryInfo *Info);
+
+extern void NLS_DateString(Word Year, Word Month, Word Day, char *Dest);
+
+extern void NLS_CurrDateString(char *Dest);
+
+extern void NLS_TimeString(Word Hour, Word Minute, Word Second, Word Sec100, char *Dest);
+
+extern void NLS_CurrTimeString(Boolean Use100, char *Dest);
+
+extern void NLS_CurrencyString(double inp, char *erg);
+
+extern char Upcase(char inp);
+
+extern void NLS_UpString(char *s);
+
+extern void NLS_LowString(char *s);
+
+extern int NLS_StrCmp(const char *s1, const char *s2);
+
+
+extern void nls_init(void);
diff --git a/objdefs.dos b/objdefs.dos
new file mode 100644
index 0000000..35ff5b3
--- /dev/null
+++ b/objdefs.dos
@@ -0,0 +1,14 @@
+CODE_OBJECTS = $(CODE_SRCS:.c=.obj)
+ST_OBJECTS = $(ST_SRCS:.c=.obj)
+NLS_OBJECTS = $(NLS_SRCS:.c=.obj)
+ASM_OBJECTS = $(ASM_SRCS:.c=.obj)
+AS_OBJECTS = $(AS_SRCS:.c=.obj)
+PLIST_OBJECTS = $(PLIST_SRCS:.c=.obj)
+PBIND_OBJECTS = $(PBIND_SRCS:.c=.obj)
+P2HEX_OBJECTS = $(P2HEX_SRCS:.c=.obj)
+P2BIN_OBJECTS = $(P2BIN_SRCS:.c=.obj)
+RESCOMP_OBJECTS = $(RESCOMP_SRCS:.c=.obj)
+TEX2DOC_OBJECTS = $(TEX2DOC_SRCS:.c=.obj)
+TEX2HTML_OBJECTS = $(TEX2HTML_SRCS:.c=.obj)
+UNUMLAUT_OBJECTS = $(UNUMLAUT_SRCS:.c=.obj)
+OBJEXTENSION = obj
diff --git a/objdefs.unix b/objdefs.unix
new file mode 100644
index 0000000..648be2e
--- /dev/null
+++ b/objdefs.unix
@@ -0,0 +1,14 @@
+CODE_OBJECTS = $(CODE_SRCS:.c=.o)
+ST_OBJECTS = $(ST_SRCS:.c=.o)
+NLS_OBJECTS = $(NLS_SRCS:.c=.o)
+ASM_OBJECTS = $(ASM_SRCS:.c=.o)
+AS_OBJECTS = $(AS_SRCS:.c=.o)
+PLIST_OBJECTS = $(PLIST_SRCS:.c=.o)
+PBIND_OBJECTS = $(PBIND_SRCS:.c=.o)
+P2HEX_OBJECTS = $(P2HEX_SRCS:.c=.o)
+P2BIN_OBJECTS = $(P2BIN_SRCS:.c=.o)
+RESCOMP_OBJECTS = $(RESCOMP_SRCS:.c=.o)
+TEX2DOC_OBJECTS = $(TEX2DOC_SRCS:.c=.o)
+TEX2HTML_OBJECTS = $(TEX2HTML_SRCS:.c=.o)
+UNUMLAUT_OBJECTS = $(UNUMLAUT_SRCS:.c=.o)
+OBJEXTENSION = o
diff --git a/p2bin.1 b/p2bin.1
new file mode 100644
index 0000000..66248d4
--- /dev/null
+++ b/p2bin.1
@@ -0,0 +1,241 @@
+.TH p2bin 1
+
+.SH NAME
+.B p2bin \- convert code files into hex files
+
+.SH SYNTAX
+.B p2bin
+[ option(s) ] <name(s)> [ further options/names ]
+
+.SH DESCRIPTION
+
+P2BIN is a tool to convert the contents of one or several code files
+generated by AS into binary files. A binary file is a 1:1 memory image
+of the processor's memory and is especially suited for EPROM programmers
+and emulators.
+
+Arguments to P2BIN may be either command line parameters or file name
+specifications. Any argument that starts with the charactes +, - or
+/ is regarded as a comand line parameter (which may take an
+additional command line argument); any other argument is regarded as
+a file name. Generally, P2BIN needs at least two file names: An
+input code file and the name of the binary output file. If multiple
+file names are given, P2BIN will always take the last name as the
+output file's name. If an input file name does not have an
+extension, the extension '.p' is added automatically. Similarly, the
+extension '.bin' is added automatically to the target file's name.
+A special case occurs when only one file name is given: P2BIN will
+then take its name as the source (possibly extended with '.p'), and
+the same name as target (with '.bin' as additional or replaced
+extension).
+
+.SH COMMAND-LINE PARAMETERS
+
+If a command-line parameter starts with a slash(/) or minus sign(-),
+it turns an option on; if a command-line parameter starts with a plus
+sign(+), it turns a specific option off. Numeric arguments to
+parameters can be either written in decimal or hexadecimal notation.
+For hexadecimal notation, prefix the number with a dollar($) sign.
+In the following list, all options will be shown in the form that is
+needed to change the default behaviour, which might be a plus or
+minus sign, depening on wether the option is on or off by default.
+
+.B p2bin
+accepts the following command-line parameters:
+.TP
+.B -f <number>[,<further numbers>]
+
+Add <number> to the list of record header IDs that allow a record
+from a source file to be written to the target file. A certain
+header ID marks code for a certain target processor family; thus,
+this filter allows to distill code for a certain processor out of a
+source file that contains code for different processor families.
+Negation of this parameter removes certain header IDs from P2BIN's
+list. See the user manual of AS for a list of all possible header ID
+values. If P2BIN's list of header IDs is empty, no filtering will
+take place, i.e. all records from a source file will make it into the
+target file.
+.TP
+.B -l <number>
+
+Set the value that should be used to fill memory areas in the binary
+image that are unused by the input code file(s). The default for this
+is to fill unused areas with the value 255 (0xff), which is the best choice
+for EPROMs as erased EPROM cells carry this value and an intelligent
+EPROM burner can skip these cells, speeding up the programming process and
+reducing stress for the EPROM. However, there are specialized EPROMs that
+have zeros in their cells after erasure, and you might want to fill unused
+areas with a code that executes as a NOP or BREAK statement.
+.TP
+.B -m <all|even|odd|byte<0|1|2|3>|word<0|1>>
+
+Set the mask of bytes to be filtered out. If your target processor has
+a 16- or 32-bit data path, but your EPROMs are only 8- or 16-bits wide,
+the code has to be spread over the EPROMs in an alternating fashion.
+This option allows you to do the necesary splitting, however you have
+to run P2BIN two or four times with different masks. The possible arguments
+have the following meanings:
+
+.B all
+does not do any filtering, i.e. all bytes of your code will show up in the
+resulting image. This is the default.
+
+.B even
+or
+.B odd
+will take only those bytes whose addresses are in the form 2*n or 2*n+1. They
+are useful if you have a 16-bit data path and two 8-bit EPROMs.
+
+.B byte0, byte1, byte2
+or
+.B byte3
+will take only those bytes whose addresses are in the form 4*n ... 4*n+3.
+They are useful if you have a 32-bit data path and four 8-bit EPROMs.
+
+.B word0
+or
+.B word1
+will take only those bytes whose addresses are in the form 4*n+0 / 4*n+1
+or 4*n+2 / 4*n+3. They are useful if you have a 32-bit data path and two
+16-bit EPROMs.
+
+When using one of these filters, the resulting images will automatically
+become smaller by a factor of 2 or 4. Beware that this does not influence
+address specifications given with the
+.B -r
+command-line parameter! See also the examples section below for correct
+usage.
+.TP
+.B -r < <start>-<stop> >
+
+Set a certain address range to be filtered out of the input file(s).
+Code that lies outside this range does not appear in the output file.
+The default for the address filter is the 0-$7fff, which might create
+confusion in some cases. As a special option,
+.B <start>
+and
+.B <stop>
+may consist of just a single dollar sign (escape this
+in UNIX shells!) to signify the lowest resp. highest address that
+occurs in the input file(s). Using this option will implicitly
+enable a second pass over all input files to find the minimum and
+maximum values before conversion starts, reducing the speed of P2BIN
+slightly.
+.TP
+.B -e <address>
+
+Set an entry address or modify an existing one. P2BIN can optionally
+prepend the start address to the binary image to tell a program loader
+where to jump after the image has been loaded (see the '-S' option).
+Normally, this address is generated by AS if the program's END statement
+has a label as argument, but this options allows to change the entry point
+or add one if it was forgotten in the program itself.
+.TP
+.B -S [L|B]<n>
+
+Instruct P2BIN to prepend the program entry address to the image. 'n' is
+the length in bytes the address should have and has an allowed range from 1
+to 4. The number may be prefixed by a 'L' or 'B' letter that sets the
+endianess of the address. If no letter is used, little endian is assumed.
+.TP
+.B -s
+
+Tell P2BIN to include a checksum into the image. A checksum is a byte
+value entered into the image's last byte that is the two's complement of
+the sum of all previous bytes. Therefore, the sum of all bytes modulus
+256 will become zero. This option is useful if you want to check the
+ROM contents in your program as part of a power-on self-test, but keep
+in mind that you must not use the last byte for your own purposes any
+more!
+.TP
+.B -k
+
+Instruct P2BIN to erase the program source files after conversion.
+
+.SH PRESETTING PARAMETERS
+
+Parameters need not neccessarily be given in the command line itself. Before
+processing of command line parameters starts, P2BIN will look if the
+.B P2BINCMD
+environment variable is defined. If it exists, its contents will be
+treated as additional command line paramters whose syntax is absolutely
+equal to normal command line parameters. As exception is made if the
+variable's contents start with a '@' sign; in such a case, the string after
+the '@' sign is treated as the name of a file that contains the options.
+Such a file (also called a 'key file') has the advantage that it allows
+the options to be written in different lines, and it does not have a size
+limit. Some operating systems (like MS-DOS) do have a length limit on
+command lines and environment variable contents, so the key file may be
+your only option if you have a lot of lengthy parameters for P2BIN.
+
+.SH RETURN CODES
+
+.B p2bin
+may return with the following codes:
+.TP
+.B 0
+no errors.
+.TP
+.B 1
+incorrect command line parameters.
+.TP
+.B 2
+I/O-error.
+.TP
+.B 3
+An input file had an incorrect format.
+
+.SH EXAMPLES
+
+To convert a file
+.B file1.p
+fully into its binary representation, use
+.PP
+.B p2bin -r \e$-\e$ file1
+.PP
+If you have a processor with a 64 KByte address space and a 16-bit
+data path and you want to assure that the memory image always starts
+at address 0, regardless of address layout in the code file, use
+.PP
+.B p2bin -r 0-\e$ffff -m even file1
+.B evenfile
+
+.B p2bin -r 0-\e$ffff -m odd file1
+.B oddfile
+.PP
+to get images for two 27256 EPROMs.
+
+.SH NATIONAL LANGUAGE SUPPORT
+
+p2bin supports national languages in the same way as AS. See the manual
+page for asl(1) for maore information about this.
+
+.SH TIPS
+
+Calling P2BIN without any arguments will print a short help
+listing all command line parameters.
+
+.SH SEE ALSO
+
+asl(1), plist(1), pbind(1), p2hex(1)
+
+.SH HISTORY
+
+P2BIN originally appeared as an AS tool in 1992, written in
+Borland-Pascal, and was ported to C and UNIX in 1996.
+
+.SH BUGS
+
+Command line interpreters of some operating systems reserve some
+characters for their own use, so it might be necessary to give
+command line parameters with certain tricks (e.g., with the help
+of escape characters).
+
+P2BIN does not have so far an opportunity to filter records by
+target segment. Instead, records that contain data for any other
+segment than CODE are completely ignored.
+
+.SH AUTHOR(S)
+
+Alfred Arnold (a.arnold@kfa-juelich.de)
+
diff --git a/p2bin.c b/p2bin.c
new file mode 100644
index 0000000..58b9de0
--- /dev/null
+++ b/p2bin.c
@@ -0,0 +1,536 @@
+/* p2bin.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Umwandlung von AS-Codefiles in Binaerfiles */
+/* */
+/* Historie: 3. 6.1996 Grundsteinlegung */
+/* 30. 5.1999 0x statt $ erlaubt */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "version.h"
+#include "endian.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "hex.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "p2bin.rsc"
+#include "ioerrs.h"
+#include "chunks.h"
+#include "cmdarg.h"
+#include "toolutils.h"
+
+#define BinSuffix ".bin"
+
+
+typedef void (*ProcessProc)(
+#ifdef __PROTOS__
+char *FileName, LongWord Offset
+#endif
+);
+
+
+static CMDProcessed ParProcessed;
+
+static FILE *TargFile;
+static String SrcName,TargName;
+
+static LongWord StartAdr,StopAdr,EntryAdr,RealFileLen;
+static LongWord MaxGran,Dummy;
+static Boolean StartAuto,StopAuto,AutoErase,EntryAdrPresent;
+
+static Byte FillVal;
+static Boolean DoCheckSum;
+
+static Byte SizeDiv;
+static LongInt ANDMask,ANDEq;
+static ShortInt StartHeader;
+
+static ChunkList UsedList;
+
+
+#ifdef DEBUG
+#define ChkIO(s) ChkIO_L(s,__LINE__)
+
+ static void ChkIO_L(char *s, int line)
+BEGIN
+ if (errno!=0)
+ BEGIN
+ fprintf(stderr,"%s %d\n",s,line); exit(3);
+ END
+END
+#endif
+
+ static void ParamError(Boolean InEnv, char *Arg)
+BEGIN
+ printf("%s%s\n%s\n",getmessage((InEnv)?Num_ErrMsgInvEnvParam:Num_ErrMsgInvParam),Arg,getmessage(Num_ErrMsgProgTerm));
+ exit(1);
+END
+
+#define BufferSize 4096
+static Byte Buffer[BufferSize];
+
+ static void OpenTarget(void)
+BEGIN
+ LongWord Rest,Trans;
+
+ TargFile=fopen(TargName,OPENWRMODE);
+ if (TargFile==Nil) ChkIO(TargName);
+ RealFileLen=((StopAdr-StartAdr+1)*MaxGran)/SizeDiv;
+
+ if (StartHeader!=0)
+ BEGIN
+ memset(Buffer,0,abs(StartHeader));
+ if (fwrite(Buffer,1,abs(StartHeader),TargFile)!=abs(StartHeader)) ChkIO(TargName);
+ END
+
+ memset(Buffer,FillVal,BufferSize);
+
+ Rest=RealFileLen;
+ while (Rest!=0)
+ BEGIN
+ Trans=min(Rest,BufferSize);
+ if (fwrite(Buffer,1,Trans,TargFile)!=Trans) ChkIO(TargName);
+ Rest-=Trans;
+ END
+END
+
+ static void CloseTarget(void)
+BEGIN
+ LongWord Sum,Rest,Trans,Real,z,bpos;
+
+ if ((EntryAdrPresent) AND (StartHeader!=0))
+ BEGIN
+ rewind(TargFile);
+ bpos=((StartHeader>0) ? 0 : -1-StartHeader)<<3;
+ for (z=0; z<abs(StartHeader); z++)
+ BEGIN
+ Buffer[z]=(EntryAdr >> bpos) & 0xff;
+ bpos += (StartHeader>0) ? 8 : -8;
+ END
+ if (fwrite(Buffer,1,abs(StartHeader),TargFile)!=abs(StartHeader)) ChkIO(TargName);
+ END
+
+ if (fclose(TargFile)==EOF) ChkIO(TargName);
+
+ if (DoCheckSum)
+ BEGIN
+ TargFile=fopen(TargName,OPENUPMODE); if (TargFile==Nil) ChkIO(TargName);
+ if (fseek(TargFile,abs(StartHeader),SEEK_SET)==-1) ChkIO(TargName);
+ Rest=FileSize(TargFile)-1;
+ Sum=0;
+ while (Rest!=0)
+ BEGIN
+ Trans=min(Rest,BufferSize);
+ Rest-=Trans;
+ Real=fread(Buffer,1,Trans,TargFile);
+ if (Real!=Trans) ChkIO(TargName);
+ for (z=0; z<Trans; Sum+=Buffer[z++]);
+ END
+ errno=0; printf("%s%s\n",getmessage(Num_InfoMessChecksum),HexLong(Sum));
+ Buffer[0]=0x100-(Sum&0xff); fflush(TargFile);
+ if (fwrite(Buffer,1,1,TargFile)!=1) ChkIO(TargName); fflush(TargFile);
+ if (fclose(TargFile)==EOF) ChkIO(TargName);
+ END
+
+ if (Magic!=0) unlink(TargName);
+END
+
+ static void ProcessFile(char *FileName, LongWord Offset)
+BEGIN
+ FILE *SrcFile;
+ Word TestID;
+ Byte InpHeader,InpSegment;
+ LongWord InpStart,SumLen;
+ Word InpLen,TransLen,ResLen;
+ Boolean doit;
+ LongWord ErgStart,ErgStop,NextPos;
+ Word ErgLen=0;
+ LongInt z;
+ Byte Gran;
+
+ SrcFile=fopen(FileName,OPENRDMODE);
+ if (SrcFile==Nil) ChkIO(FileName);
+
+ if (NOT Read2(SrcFile,&TestID)) ChkIO(FileName);
+ if (TestID!=FileID) FormatError(FileName,getmessage(Num_FormatInvHeaderMsg));
+
+ errno=0; printf("%s==>>%s",FileName,TargName); ChkIO(OutName);
+
+ SumLen=0;
+
+ do
+ BEGIN
+ ReadRecordHeader(&InpHeader,&InpSegment,&Gran,FileName,SrcFile);
+ if (InpHeader==FileHeaderStartAdr)
+ BEGIN
+ if (NOT Read4(SrcFile,&ErgStart)) ChkIO(FileName);
+ if (NOT EntryAdrPresent)
+ BEGIN
+ EntryAdr=ErgStart; EntryAdrPresent=True;
+ END
+ END
+ else if (InpHeader!=FileHeaderEnd)
+ BEGIN
+ if (NOT Read4(SrcFile,&InpStart)) ChkIO(FileName);
+ if (NOT Read2(SrcFile,&InpLen)) ChkIO(FileName);
+
+ NextPos=ftell(SrcFile)+InpLen;
+ if (NextPos>=FileSize(SrcFile)-1)
+ FormatError(FileName,getmessage(Num_FormatInvRecordLenMsg));
+
+ doit=(FilterOK(InpHeader) AND (InpSegment==SegCode));
+
+ if (doit)
+ BEGIN
+ InpStart+=Offset;
+ ErgStart=max(StartAdr,InpStart);
+ ErgStop=min(StopAdr,InpStart+(InpLen/Gran)-1);
+ doit=(ErgStop>=ErgStart);
+ if (doit)
+ BEGIN
+ ErgLen=(ErgStop+1-ErgStart)*Gran;
+ if (AddChunk(&UsedList,ErgStart,ErgStop-ErgStart+1,True))
+ BEGIN
+ errno=0; printf(" %s\n",getmessage(Num_ErrMsgOverlap)); ChkIO(OutName);
+ END
+ END
+ END
+
+ if (doit)
+ BEGIN
+ /* an Anfang interessierender Daten */
+
+ if (fseek(SrcFile,(ErgStart-InpStart)*Gran,SEEK_CUR)==-1) ChkIO(FileName);
+
+ /* in Zieldatei an passende Stelle */
+
+ if (fseek(TargFile,(((ErgStart-StartAdr)*Gran)/SizeDiv)+abs(StartHeader),SEEK_SET)==-1) ChkIO(TargName);
+
+ /* umkopieren */
+
+ while (ErgLen>0)
+ BEGIN
+ TransLen=min(BufferSize,ErgLen);
+ if (fread(Buffer,1,TransLen,SrcFile)!=TransLen) ChkIO(FileName);
+ if (SizeDiv==1) ResLen=TransLen;
+ else
+ BEGIN
+ ResLen=0;
+ for (z=0; z<(LongInt)TransLen; z++)
+ if (((ErgStart*Gran+z)&ANDMask)==ANDEq)
+ Buffer[ResLen++]=Buffer[z];
+ END
+ if (fwrite(Buffer,1,ResLen,TargFile)!=ResLen) ChkIO(TargName);
+ ErgLen-=TransLen; ErgStart+=TransLen; SumLen+=ResLen;
+ END
+ END
+ if (fseek(SrcFile,NextPos,SEEK_SET)==-1) ChkIO(FileName);
+ END
+ END
+ while (InpHeader!=0);
+
+ errno=0; printf(" (%d Byte)\n",SumLen); ChkIO(OutName);
+
+ if (fclose(SrcFile)==EOF) ChkIO(FileName);
+END
+
+static ProcessProc CurrProcessor;
+static LongWord CurrOffset;
+
+ static void Callback(char *Name)
+BEGIN
+ CurrProcessor(Name,CurrOffset);
+END
+
+ static void ProcessGroup(char *GroupName_O, ProcessProc Processor)
+BEGIN
+ String Ext,GroupName;
+
+ CurrProcessor=Processor;
+ strmaxcpy(GroupName,GroupName_O,255); strmaxcpy(Ext,GroupName,255);
+ if (NOT RemoveOffset(GroupName,&CurrOffset)) ParamError(False,Ext);
+ AddSuffix(GroupName,getmessage(Num_Suffix));
+
+ if (NOT DirScan(GroupName,Callback))
+ fprintf(stderr,"%s%s%s\n",getmessage(Num_ErrMsgNullMaskA),GroupName,getmessage(Num_ErrMsgNullMaskB));
+END
+
+ static void MeasureFile(char *FileName, LongWord Offset)
+BEGIN
+ FILE *f;
+ Byte Header,Gran,Segment;
+ Word Length,TestID;
+ LongWord Adr,EndAdr,NextPos;
+
+ f=fopen(FileName,OPENRDMODE);
+ if (f==Nil) ChkIO(FileName);
+
+ if (NOT Read2(f,&TestID)) ChkIO(FileName);
+ if (TestID!=FileMagic) FormatError(FileName,getmessage(Num_FormatInvHeaderMsg));
+
+ do
+ BEGIN
+ ReadRecordHeader(&Header,&Segment,&Gran,FileName,f);
+
+ if (Header==FileHeaderStartAdr)
+ BEGIN
+ if (fseek(f,sizeof(LongWord),SEEK_CUR)==-1) ChkIO(FileName);
+ END
+ else if (Header!=FileHeaderEnd)
+ BEGIN
+ if (NOT Read4(f,&Adr)) ChkIO(FileName);
+ if (NOT Read2(f,&Length)) ChkIO(FileName);
+ NextPos=ftell(f)+Length;
+ if (NextPos>FileSize(f))
+ FormatError(FileName,getmessage(Num_FormatInvRecordLenMsg));
+
+ if (FilterOK(Header) AND (Segment==SegCode))
+ BEGIN
+ Adr+=Offset;
+ EndAdr=Adr+(Length/Gran)-1;
+ if (Gran>MaxGran) MaxGran=Gran;
+ if (StartAuto) if (StartAdr>Adr) StartAdr=Adr;
+ if (StopAuto) if (EndAdr>StopAdr) StopAdr=EndAdr;
+ END
+
+ fseek(f,NextPos,SEEK_SET);
+ END
+ END
+ while(Header!=0);
+
+ if (fclose(f)==EOF) ChkIO(FileName);
+END
+
+ static CMDResult CMD_AdrRange(Boolean Negate, char *Arg)
+BEGIN
+ char *p,Save;
+ Boolean err;
+
+ if (Negate)
+ BEGIN
+ StartAdr=0; StopAdr=0x7fff;
+ return CMDOK;
+ END
+ else
+ BEGIN
+ p=strchr(Arg,'-'); if (p==Nil) return CMDErr;
+
+ Save=(*p); *p='\0';
+ if ((StartAuto = AddressWildcard(Arg))) err = True;
+ else StartAdr = ConstLongInt(Arg, &err);
+ *p = Save;
+ if (NOT err) return CMDErr;
+
+ if ((StopAuto = AddressWildcard(p + 1))) err = True;
+ else StopAdr = ConstLongInt(p+1, &err);
+ if (NOT err) return CMDErr;
+
+ if ((NOT StartAuto) AND (NOT StopAuto) AND (StartAdr>StopAdr)) return CMDErr;
+
+ return CMDArg;
+ END
+END
+
+ static CMDResult CMD_ByteMode(Boolean Negate, char *Arg)
+BEGIN
+#define ByteModeCnt 9
+ static char *ByteModeStrings[ByteModeCnt]={"ALL","EVEN","ODD","BYTE0","BYTE1","BYTE2","BYTE3","WORD0","WORD1"};
+ static Byte ByteModeDivs[ByteModeCnt]={1,2,2,4,4,4,4,2,2};
+ static Byte ByteModeMasks[ByteModeCnt]={0,1,1,3,3,3,3,2,2};
+ static Byte ByteModeEqs[ByteModeCnt]={0,0,1,0,1,2,3,0,2};
+
+ int z;
+
+ if (*Arg=='\0')
+ BEGIN
+ SizeDiv=1; ANDEq=0; ANDMask=0;
+ return CMDOK;
+ END
+ else
+ BEGIN
+ for (z=0; z<strlen(Arg); z++) Arg[z]=toupper(Arg[z]);
+ ANDEq=0xff;
+ for (z=0; z<ByteModeCnt; z++)
+ if (strcmp(Arg,ByteModeStrings[z])==0)
+ BEGIN
+ SizeDiv=ByteModeDivs[z];
+ ANDMask=ByteModeMasks[z];
+ ANDEq =ByteModeEqs[z];
+ END
+ if (ANDEq==0xff) return CMDErr; else return CMDArg;
+ END
+END
+
+ static CMDResult CMD_StartHeader(Boolean Negate, char *Arg)
+BEGIN
+ Boolean err;
+ ShortInt Sgn;
+
+ if (Negate)
+ BEGIN
+ StartHeader=0; return CMDOK;
+ END
+ else
+ BEGIN
+ Sgn=1; if (*Arg=='\0') return CMDErr;
+ switch (toupper(*Arg))
+ BEGIN
+ case 'B': Sgn=(-1);
+ case 'L': Arg++;
+ END
+ StartHeader=ConstLongInt(Arg,&err);
+ if ((NOT err) OR (StartHeader>4)) return CMDErr;
+ StartHeader*=Sgn;
+ return CMDArg;
+ END
+END
+
+ static CMDResult CMD_EntryAdr(Boolean Negate, char *Arg)
+BEGIN
+ Boolean err;
+
+ if (Negate)
+ BEGIN
+ EntryAdrPresent=False; return CMDOK;
+ END
+ else
+ BEGIN
+ EntryAdr=ConstLongInt(Arg,&err);
+ return (err) ? CMDArg : CMDErr;
+ END
+END
+
+ static CMDResult CMD_FillVal(Boolean Negate, char *Arg)
+BEGIN
+ Boolean err;
+
+ FillVal=ConstLongInt(Arg,&err);
+ if (NOT err) return CMDErr; else return CMDArg;
+END
+
+ static CMDResult CMD_CheckSum(Boolean Negate, char *Arg)
+BEGIN
+ DoCheckSum=NOT Negate;
+ return CMDOK;
+END
+
+ static CMDResult CMD_AutoErase(Boolean Negate, char *Arg)
+BEGIN
+ AutoErase=NOT Negate;
+ return CMDOK;
+END
+
+#define P2BINParamCnt 8
+static CMDRec P2BINParams[P2BINParamCnt]=
+ {{"f", CMD_FilterList},
+ {"r", CMD_AdrRange},
+ {"s", CMD_CheckSum},
+ {"m", CMD_ByteMode},
+ {"l", CMD_FillVal},
+ {"e", CMD_EntryAdr},
+ {"S", CMD_StartHeader},
+ {"k", CMD_AutoErase}};
+
+ int main(int argc, char **argv)
+BEGIN
+ int z;
+ char *ph1,*ph2;
+ String Ver;
+
+ ParamStr=argv; ParamCount=argc-1;
+
+ nls_init(); NLS_Initialize();
+
+ endian_init();
+ strutil_init();
+ bpemu_init();
+ hex_init();
+ nlmessages_init("p2bin.msg",*argv,MsgId1,MsgId2); ioerrs_init(*argv);
+ chunks_init();
+ cmdarg_init(*argv);
+ toolutils_init(*argv);
+
+ sprintf(Ver,"P2BIN/C V%s",Version);
+ WrCopyRight(Ver);
+
+ InitChunk(&UsedList);
+
+ if (ParamCount==0)
+ BEGIN
+ errno=0; printf("%s%s%s\n",getmessage(Num_InfoMessHead1),GetEXEName(),getmessage(Num_InfoMessHead2)); ChkIO(OutName);
+ for (ph1=getmessage(Num_InfoMessHelp),ph2=strchr(ph1,'\n'); ph2!=Nil; ph1=ph2+1,ph2=strchr(ph1,'\n'))
+ BEGIN
+ *ph2='\0';
+ printf("%s\n",ph1);
+ *ph2='\n';
+ END
+ exit(1);
+ END
+
+ StartAdr=0; StopAdr=0x7fff; StartAuto=False; StopAuto=False;
+ FillVal=0xff; DoCheckSum=False; SizeDiv=1; ANDEq=0;
+ EntryAdr=(-1); EntryAdrPresent=False; AutoErase=False;
+ StartHeader=0;
+ ProcessCMD(P2BINParams,P2BINParamCnt,ParProcessed,"P2BINCMD",ParamError);
+
+ if (ProcessedEmpty(ParProcessed))
+ BEGIN
+ errno=0;
+ printf("%s\n",getmessage(Num_ErrMsgTargMissing));
+ ChkIO(OutName);
+ exit(1);
+ END
+
+ z=ParamCount;
+ while ((z>0) AND (NOT ParProcessed[z])) z--;
+ strmaxcpy(TargName,ParamStr[z],255);
+ if (NOT RemoveOffset(TargName,&Dummy)) ParamError(False,ParamStr[z]);
+ ParProcessed[z]=False;
+ if (ProcessedEmpty(ParProcessed))
+ BEGIN
+ strmaxcpy(SrcName,ParamStr[z],255); DelSuffix(TargName);
+ END
+ AddSuffix(TargName,BinSuffix);
+
+ MaxGran=1;
+ if ((StartAuto) OR (StopAuto))
+ BEGIN
+#ifdef __STDC__
+ if (StartAuto) StartAdr=0xffffffffu;
+#else
+ if (StartAuto) StartAdr=0xffffffff;
+#endif
+ if (StopAuto) StopAdr=0;
+ if (ProcessedEmpty(ParProcessed)) ProcessGroup(SrcName,MeasureFile);
+ else for (z=1; z<=ParamCount; z++)
+ if (ParProcessed[z]) ProcessGroup(ParamStr[z],MeasureFile);
+ if (StartAdr>StopAdr)
+ BEGIN
+ errno=0; printf("%s\n",getmessage(Num_ErrMsgAutoFailed)); ChkIO(OutName); exit(1);
+ END
+ END
+
+ OpenTarget();
+
+ if (ProcessedEmpty(ParProcessed)) ProcessGroup(SrcName,ProcessFile);
+ else for (z=1; z<=ParamCount; z++)
+ if (ParProcessed[z]) ProcessGroup(ParamStr[z],ProcessFile);
+
+ CloseTarget();
+
+ if (AutoErase)
+ BEGIN
+ if (ProcessedEmpty(ParProcessed)) ProcessGroup(SrcName,EraseFile);
+ else for (z=1; z<=ParamCount; z++)
+ if (ParProcessed[z]) ProcessGroup(ParamStr[z],EraseFile);
+ END
+
+ return 0;
+END
diff --git a/p2bin.res b/p2bin.res
new file mode 100644
index 0000000..99f535a
--- /dev/null
+++ b/p2bin.res
@@ -0,0 +1,46 @@
+;* p2bin.res
+;*****************************************************************************
+;* AS-Portierung *
+;* *
+;* Stringdefinitionen fuer P2BIN *
+;* *
+;* Historie: 3. 6.1996 Grundsteinlegung *
+;* *
+;*****************************************************************************
+
+Include header.res
+
+Include tools2.res
+
+;------------------------------------------------------------------------------
+; Ansagen
+
+Message InfoMessChecksum
+ "Pr&uuml;fsumme: "
+ "checksum: "
+
+Message InfoMessHead2
+ " <Quelldatei(en)> <Zieldatei> [Optionen]"
+ " <source file(s)> <target file> [options]"
+
+Message InfoMessHelp
+ "\n" \
+ "Optionen: -f <Headerliste> : auszufilternde Records\n" \
+ " -r <Start>-<Stop> : auszufilternder Adre&szlig;bereich\n" \
+ " ($ = erste bzw. letzte auftauchende Adresse)\n" \
+ " -l <8-Bit-Zahl> : Inhalt unbenutzter Speicherzellen festlegen\n" \
+ " -s : Pr&uuml;fsumme in Datei ablegen\n" \
+ " -m <Modus> : EPROM-Modus (odd,even,byte0..byte3)\n" \
+ " -e <Adresse> : Startadresse festlegen\n" \
+ " -S [L|B]<L&auml;nge> : Startadresse voranstellen\n" \
+ " -k : Quelldateien automatisch l&ouml;schen\n"
+ "\n" \
+ "options: -f <header list> : records to filter out\n" \
+ " -r <start>-<stop> : address range to filter out\n" \
+ " ($ = first resp. last occuring address)\n" \
+ " -l <8-bit-number> : set filler value for unused cells\n" \
+ " -s : put checksum into file\n" \
+ " -m <mode> : EPROM-mode (odd,even,byte0..byte3)\n" \
+ " -e <address> : set entry address\n" \
+ " -S [L|B]<length> : prepend entry address to image\n" \
+ " -k : automatically erase source files\n"
diff --git a/p2hex.1 b/p2hex.1
new file mode 100644
index 0000000..a5274a2
--- /dev/null
+++ b/p2hex.1
@@ -0,0 +1,288 @@
+.TH p2hex 1
+
+.SH NAME
+.B p2hex \- convert code files into hex files
+
+.SH SYNTAX
+.B p2hex
+[ option(s) ] <name(s)> [ further options/names ]
+
+.SH DESCRIPTION
+
+P2HEX is a tool to convert the contents of one or several code files
+generated by AS into HEX files. A HEX file is a common method of
+representing binary data in a way that is human-readable and
+transferrable over non-transparent data lines. Generally spoken,
+each byte of code or data is represented by two characters that show
+the byte in its hexadecimal notation. A HEX file also contains
+additional information like addresses and checksums that ease
+processing of the data. Unfortunately, there is no generally
+accepted standard format for HEX files. Instead, every processor
+manufacturer developed his own format and some of them have become
+"industry standards". P2HEX supports all formats that seem to have
+gained acceptance, with some variations that are commonplace.
+
+Arguments to P2HEX may be either command line parameters or file name
+specifications. Any argument that starts with the charactes +, - or
+/ is regarded as a comand line parameter (which may take an
+additional command line argument); any other argument is regarded as
+a file name. Generally, P2HEX needs at least two file names: An
+input code file and the name of the HEX output file. If multiple
+file names are given, P2HEX will always take the last name as the
+output file's name. If an input file name does not have an
+extension, the extension '.p' is added automatically. Similarly, the
+extension '.hex' is added automatically to the target file's name.
+A special case occurs when only one file name is given: P2HEX will
+then take its name as the source (possibly extended with '.p'), and
+the same name as target (with '.hex' as additional or replaced
+extension).
+
+By default, P2HEX will choose a HEX format that is the most common
+for the processor family a source file contains code for; this
+however means that if the source file(s) contain(s) code for different
+processor families, the HEX file might become an undesirable mixture
+of formats; use the
+.B -F
+command-line parameter to force a certain format then.
+
+.SH COMMAND-LINE PARAMETERS
+
+If a command-line parameter starts with a slash(/) or minus sign(-),
+it turns an option on; if a command-line parameter starts with a plus
+sign(+), it turns a specific option off. Numeric arguments to
+parameters can be either written in decimal or hexadecimal notation.
+For hexadecimal notation, prefix the number with a dollar($) sign.
+In the following list, all options will be shown in the form that is
+needed to change the default behaviour, which might be a plus or
+minus sign, depening on wether the option is on or off by default.
+
+.B p2hex
+accepts the following command-line parameters:
+.TP
+.B -a
+
+Tell P2HEX to use relative addressing in the output HEX file. By
+default, addresses the HEX file will be exactly the same absolute
+addresses as they were in the code file. This may create problems
+with some EPROM-burners if your code does not start at address 0. In
+relative mode, the address filter's start address (see the
+.B -r
+command line switch) is subtracted from all addresses specifications
+in the HEX file (with the exception of the entry address).
+Therefore, addresses in the HEX file again start at 0.
+.TP
+.B -d < <start address>-<stop address> >
+Tell P2HEX that items in the address range given by the argument
+should be regarded as data rather than code. This option only has a
+meaning for the TI-DSK format that can differenciate between code and
+data. It will probably disappear on the day when P2HEX can process
+all address spaces, making a manual distinction unnecessary.
+.TP
+.B -e <address>
+
+Set an entry address or modify an existing one. Some HEX file
+formats can carry a special record for an entry address that tells a
+program loader where to jump after a program has been loaded.
+Normally, this address is generated by AS if the program's END
+statement has a label as argument, but this options allows to change
+the entry point or add one if it was forgotten in the program itself.
+.TP
+.B -F <Default|Moto|Intel|Intel16|Intel32|MOS|Tek|DSK>
+
+Force a certain format for the output HEX file. By default, P2HEX
+will choose one depending on the target processor. Using
+.B Default
+as argument will also set this behaviour, which might be useful to
+revert to P2HEX's default behaviour if the default has been changed
+(see the discussion of the
+.B P2HEXCMD
+variable below for presetting parameters).
+
+.B Moto
+stands for the Motorola S-Record format, which allows addresses from
+16 to 32 bits in length and entry addresses. It bears its name due
+to the fact that every record starts with the letter S.
+
+.B Intel
+is the "standard" Intellec-MCS8-Format for a variety of Intel
+8-Bit-CPUs that almost became a standard, but was originally limited
+to 16-bit addresses. In later editions, the addressing capability
+was extended to 20 (
+.B Intel16
+) and 32 bits (
+.B Intel32
+).
+
+.B MOS
+is a simple format introduced by the manufacturer MOS for their line
+of 65xx CPUs. It is limited to 16-bit addresses, just like the
+.B Tek
+format that was defined by Tektronix.
+
+.B DSK
+is the format Texas Instruments uses for their line of 16-bit
+fixed-point signal processors. In contrast to all other formats, it
+is word-oriented and can distinguish between data and code segments.
+.TP
+.B -f <number>[,<further numbers>]
+
+Add <number> to the list of record header IDs that allow a record
+from a source file to be written to the target file. A certain
+header ID marks code for a certain target processor family; thus,
+this filter allows to distill code for a certain processor out of a
+source file that contains code for different processor families.
+Negation of this parameter removes certain header IDs from P2HEX's
+list. See the user manual of AS for a list of all possible header ID
+values. If P2HEX's list of header IDs is empty, no filtering will
+take place, i.e. all records from a source file will make it into the
+target file.
+.TP
+.B -i <0|1|2>
+
+Change the terminating line for an Intel-HEX file. Normally, an
+Intel-HEX file is terminated with the line
+.B :00000001FF ,
+but there are sources that also mention
+.B :00000001
+or
+.B :0000000000
+as the last line. The numeric argument of this parameter selects one
+of these opportunities, with the first one being the default. This
+parameter only has an effect if the target file's format is one of
+the Intel-HEX variants.
+.TP
+.B -l <length>
+
+Set the maximum number of bytes per record, and therefore the maximum
+length of a line in the target file. Possible values are between 2
+and 254 bytes, with 16 being the default.
+.TP
+.B -m <0..3>
+
+Set one of the four Intel-Hex variants defined by Microchip for the
+PIC family of microcontrollers. The Default is the INHX8(0) format,
+which contains all words in a Lobyte-Hibyte-ordering. INHX16M(1) does just
+the opposite, whereas INHX8L(2) and INHX8H(3) only store the lower
+resp. higher bytes of each word. This parameter only has an effect
+if the target file's format is one of the Intel-HEX variants.
+.TP
+.B -r < <start>-<stop> >
+
+Set a certain address range to be filtered out of the input file(s).
+Code that lies outside this range does not appear in the output file.
+The default for the address filter is the 0-$7fff, which might create
+confusion in some cases. As a special option,
+.B <start>
+and
+.B <stop>
+may consist of just a single dollar sign (escape this
+in UNIX shells!) to signify the lowest resp. highest address that
+occurs in the input file(s). Using this option will implicitly
+enable a second pass over all input files to find the minimum and
+maximum values before conversion starts, reducing the speed of P2HEX
+slightly.
+.TP
+.B -s
+
+In Motorola S-Record format, force P2HEX to write a termination record
+after each group of data records, which may be necessary in some cases
+(but creates problems most of the time...)
+.TP
+.B +5
+
+Disable output of Motorola S5-records, which contain the number of
+data records that were sent and therefore allow an additional level
+of checking. However, they are not understood by all programs and
+therefore might be a source of trouble.
+.TP
+.B -M <1|2|3>
+
+Force P2HEX to use a minimum length for the address fields of Motorola
+S-records. For example, a value of 2 will effectively disable S1 records,
+and a value of 3 will force usage of S3 records. The default is 1, which
+enables full automatic setting of the S record length.
+.TP
+.B -k
+
+Instruct P2HEX to erase the program source files after conversion.
+
+.SH PRESETTING PARAMETERS
+
+Parameters need not neccessarily be given in the command line itself. Before
+processing of command line parameters starts, P2HEX will look if the
+.B P2HEXCMD
+environment variable is defined. If it exists, its contents will be
+treated as additional command line paramters whose syntax is absolutely
+equal to normal command line parameters. As exception is made if the
+variable's contents start with a '@' sign; in such a case, the string after
+the '@' sign is treated as the name of a file that contains the options.
+Such a file (also called a 'key file') has the advantage that it allows
+the options to be written in different lines, and it does not have a size
+limit. Some operating systems (like MS-DOS) do have a length limit on
+command lines and environment variable contents, so the key file may be
+your only option if you have a lot of lengthy parameters for P2HEX.
+
+.SH RETURN CODES
+
+.B p2hex
+may return with the following codes:
+.TP
+.B 0
+no errors.
+.TP
+.B 1
+incorrect command line parameters.
+.TP
+.B 2
+I/O-error.
+.TP
+.B 3
+An input file had an incorrect format.
+
+.SH EXAMPLES
+
+To convert a file
+.B file1.p
+fully into its HEX representation on a Unix platform, use
+.PP
+.B p2hex -r \e$-\e$ file1
+.PP
+If you additionally want to force usage of the Motorola S-Record format, use
+.PP
+.B p2hex -r \e$-\e$ -F Moto file1
+.PP
+
+.SH NATIONAL LANGUAGE SUPPORT
+
+p2hex supports national languages in the same way as AS. See the manual
+page for asl(1) for maore information about this.
+
+.SH TIPS
+
+Calling P2HEX without any arguments will print a short help
+listing all command line parameters.
+
+.SH SEE ALSO
+
+asl(1), plist(1), pbind(1), p2bin(1)
+
+.SH HISTORY
+
+P2HEX originally appeared as an AS tool in 1992, written in
+Borland-Pascal, and was ported to C and UNIX in 1996.
+
+.SH BUGS
+
+Command line interpreters of some operating systems reserve some
+characters for their own use, so it might be necessary to give
+command line parameters with certain tricks (e.g., with the help
+of escape characters).
+
+P2HEX does not have so far an opportunity to filter records by
+target segment. Instead, records that contain data for any other
+segment than CODE are completely ignored.
+
+.SH AUTHOR(S)
+
+Alfred Arnold (a.arnold@kfa-juelich.de)
+
diff --git a/p2hex.c b/p2hex.c
new file mode 100644
index 0000000..9d8cd78
--- /dev/null
+++ b/p2hex.c
@@ -0,0 +1,987 @@
+/* p2hex.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Konvertierung von AS-P-Dateien nach Hex */
+/* */
+/* Historie: 1. 6.1996 Grundsteinlegung */
+/* 29. 8.1998 HeadIds verwendet fuer Default-Hex-Format */
+/* 30. 5.1999 0x statt $ erlaubt */
+/* 6. 7.1999 minimal S-Record-Adresslaenge setzbar */
+/* Fehlerabfrage in CMD_Linelen war falsch */
+/* 12.10.1999 Startadresse 16-Bit-Hex geaendert */
+/* 13.10.1999 Startadressen 20+32 Bit Intel korrigiert */
+/* 24.10.1999 Relokation von Adressen (Thomas Eschenbach) */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "version.h"
+#include "endian.h"
+#include "bpemu.h"
+#include "hex.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "p2hex.rsc"
+#include "ioerrs.h"
+#include "strutil.h"
+#include "chunks.h"
+#include "cmdarg.h"
+
+#include "toolutils.h"
+#include "headids.h"
+
+static char *HexSuffix=".hex";
+#define MaxLineLen 254
+
+typedef void (*ProcessProc)(
+#ifdef __PROTOS__
+char *FileName, LongWord Offset
+#endif
+);
+
+static CMDProcessed ParProcessed;
+static int z;
+static FILE *TargFile;
+static String SrcName, TargName;
+
+static LongWord StartAdr, StopAdr, LineLen;
+static LongWord StartData, StopData, EntryAdr;
+static LargeInt Relocate;
+static Boolean StartAuto, StopAuto, AutoErase, EntryAdrPresent;
+static Word Seg, Ofs;
+static LongWord Dummy;
+static Byte IntelMode;
+static Byte MultiMode; /* 0=8M, 1=16, 2=8L, 3=8H */
+static Byte MinMoto;
+static Boolean Rec5;
+static Boolean SepMoto;
+
+static Boolean RelAdr, MotoOccured, IntelOccured, MOSOccured, DSKOccured;
+static Byte MaxMoto, MaxIntel;
+
+static THexFormat DestFormat;
+
+static ChunkList UsedList;
+
+ static void ParamError(Boolean InEnv, char *Arg)
+BEGIN
+ printf("%s%s\n",getmessage(InEnv?Num_ErrMsgInvEnvParam:Num_ErrMsgInvParam),Arg);
+ printf("%s\n",getmessage(Num_ErrMsgProgTerm));
+ exit(1);
+END
+
+ static void OpenTarget(void)
+BEGIN
+ TargFile=fopen(TargName,"w");
+ if (TargFile==Nil) ChkIO(TargName);
+END
+
+ static void CloseTarget(void)
+BEGIN
+ errno=0; fclose(TargFile); ChkIO(TargName);
+ if (Magic!=0) unlink(TargName);
+END
+
+ static void ProcessFile(char *FileName, LongWord Offset)
+BEGIN
+ FILE *SrcFile;
+ Word TestID;
+ Byte InpHeader,InpSegment,InpGran,BSwap;
+ LongInt InpStart,SumLen;
+ int z2;
+ Word InpLen,TransLen;
+ Boolean doit,FirstBank=0;
+ Byte Buffer[MaxLineLen];
+ Word *WBuffer=(Word *) Buffer;
+ LongWord ErgStart,
+#ifdef __STDC__
+ ErgStop=0xffffffffu,
+#else
+ ErgStop=0xffffffff,
+#endif
+ NextPos,IntOffset=0,MaxAdr;
+ Word ErgLen=0,ChkSum=0,RecCnt,Gran,SwapBase,HSeg;
+
+ LongInt z;
+
+ Byte MotRecType=0;
+
+ THexFormat ActFormat;
+ PFamilyDescr FoundDscr;
+
+ SrcFile=fopen(FileName,OPENRDMODE);
+ if (SrcFile==Nil) ChkIO(FileName);
+
+ if (NOT Read2(SrcFile,&TestID)) ChkIO(FileName);
+ if (TestID!=FileMagic) FormatError(FileName,getmessage(Num_FormatInvHeaderMsg));
+
+ errno=0; printf("%s==>>%s",FileName,TargName); ChkIO(OutName);
+
+ SumLen=0;
+
+ do
+ BEGIN
+ ReadRecordHeader(&InpHeader,&InpSegment,&InpGran,FileName,SrcFile);
+ if (InpHeader==FileHeaderStartAdr)
+ BEGIN
+ if (NOT Read4(SrcFile,&ErgStart)) ChkIO(FileName);
+ if (NOT EntryAdrPresent)
+ BEGIN
+ EntryAdr=ErgStart; EntryAdrPresent=True;
+ END
+ END
+ else if (InpHeader!=FileHeaderEnd)
+ BEGIN
+ Gran=InpGran;
+
+ if ((ActFormat=DestFormat)==Default)
+ BEGIN
+ FoundDscr=FindFamilyById(InpHeader);
+ if (FoundDscr==Nil)
+ FormatError(FileName,getmessage(Num_FormatInvRecordHeaderMsg));
+ else ActFormat=FoundDscr->HexFormat;
+ END
+
+ switch (ActFormat)
+ BEGIN
+ case MotoS:
+ case IntHex32:
+#ifdef __STDC__
+ MaxAdr=0xffffffffu; break;
+#else
+ MaxAdr=0xffffffff; break;
+#endif
+ case IntHex16:
+ MaxAdr=0xffff0+0xffff; break;
+ case Atmel:
+ MaxAdr=0xffffff; break;
+ default:
+ MaxAdr=0xffff;
+ END
+
+ if (NOT Read4(SrcFile,&InpStart)) ChkIO(FileName);
+ if (NOT Read2(SrcFile,&InpLen)) ChkIO(FileName);
+
+ NextPos=ftell(SrcFile)+InpLen;
+ if (NextPos>=FileSize(SrcFile)-1)
+ FormatError(FileName,getmessage(Num_FormatInvRecordLenMsg));
+
+ doit=(FilterOK(InpHeader)) AND (InpSegment==SegCode);
+
+ if (doit)
+ BEGIN
+ InpStart+=Offset;
+ ErgStart=max(StartAdr,InpStart);
+ ErgStop=min(StopAdr,InpStart+(InpLen/Gran)-1);
+ doit=(ErgStop>=ErgStart);
+ if (doit)
+ BEGIN
+ ErgLen=(ErgStop+1-ErgStart)*Gran;
+ if (AddChunk(&UsedList,ErgStart,ErgStop-ErgStart+1,True))
+ BEGIN
+ errno=0; printf(" %s\n",getmessage(Num_ErrMsgOverlap)); ChkIO(OutName);
+ END
+ END
+ END
+
+ if (ErgStop>MaxAdr)
+ BEGIN
+ errno=0; printf(" %s\n",getmessage(Num_ErrMsgAdrOverflow)); ChkIO(OutName);
+ END
+
+ if (doit)
+ BEGIN
+ /* an Anfang interessierender Daten */
+
+ if (fseek(SrcFile,(ErgStart-InpStart)*Gran,SEEK_CUR)==-1) ChkIO(FileName);
+
+ /* Statistik, Anzahl Datenzeilen ausrechnen */
+
+ RecCnt=ErgLen/LineLen;
+ if ((ErgLen%LineLen)!=0) RecCnt++;
+
+ /* relative Angaben ? */
+
+ if (RelAdr) ErgStart -= StartAdr;
+
+ /* Auf Zieladressbereich verschieben */
+
+ ErgStart += Relocate;
+
+ /* Kopf einer Datenzeilengruppe */
+
+ switch (ActFormat)
+ BEGIN
+ case MotoS:
+ if ((NOT MotoOccured) OR (SepMoto))
+ BEGIN
+ errno=0; fprintf(TargFile,"S0030000FC\n"); ChkIO(TargName);
+ END
+ if ((ErgStop >> 24) != 0) MotRecType=2;
+ else if ((ErgStop>>16)!=0) MotRecType=1;
+ else MotRecType=0;
+ if (MotRecType < (MinMoto - 1)) MotRecType = (MinMoto - 1);
+ if (MaxMoto<MotRecType) MaxMoto=MotRecType;
+ if (Rec5)
+ BEGIN
+ ChkSum=Lo(RecCnt)+Hi(RecCnt)+3;
+ errno=0;
+ fprintf(TargFile,"S503%s%s\n",HexWord(RecCnt),HexByte(Lo(ChkSum^0xff)));
+ ChkIO(TargName);
+ END
+ MotoOccured=True;
+ break;
+ case MOSHex:
+ MOSOccured=True;
+ break;
+ case IntHex:
+ IntelOccured=True;
+ IntOffset=0;
+ break;
+ case IntHex16:
+ IntelOccured=True;
+#ifdef __STDC__
+ IntOffset=ErgStart&0xfffffff0u;
+#else
+ IntOffset=ErgStart&0xfffffff0;
+#endif
+ HSeg=IntOffset>>4; ChkSum=4+Lo(HSeg)+Hi(HSeg);
+ errno=0;
+ fprintf(TargFile,":02000002%s%s\n",HexWord(HSeg),HexByte(0x100-ChkSum));
+ if (MaxIntel<1) MaxIntel=1;
+ ChkIO(TargName);
+ break;
+ case IntHex32:
+ IntelOccured=True;
+#ifdef __STDC__
+ IntOffset=ErgStart&0xffff0000u;
+#else
+ IntOffset=ErgStart&0xffff0000;
+#endif
+ HSeg=IntOffset>>16; ChkSum=6+Lo(HSeg)+Hi(HSeg);
+ fprintf(TargFile,":02000004%s%s\n",HexWord(HSeg),HexByte(0x100-ChkSum));
+ if (MaxIntel<2) MaxIntel=2;
+ ChkIO(TargName);
+ FirstBank=False;
+ break;
+ case TekHex:
+ break;
+ case Atmel:
+ break;
+ case TiDSK:
+ if (NOT DSKOccured)
+ BEGIN
+ DSKOccured=True;
+ errno=0; fprintf(TargFile,"%s%s\n",getmessage(Num_DSKHeaderLine),TargName); ChkIO(TargName);
+ END
+ break;
+ default:
+ break;
+ END
+
+ /* Datenzeilen selber */
+
+ while (ErgLen>0)
+ BEGIN
+ /* evtl. Folgebank fuer Intel32 ausgeben */
+
+ if ((ActFormat==IntHex32) AND (FirstBank))
+ BEGIN
+ IntOffset+=0x10000;
+ HSeg=IntOffset>>16; ChkSum=6+Lo(HSeg)+Hi(HSeg);
+ errno=0;
+ fprintf(TargFile,":02000004%s%s\n",HexWord(HSeg),HexByte(0x100-ChkSum));
+ ChkIO(TargName);
+ FirstBank=False;
+ END
+
+ /* Recordlaenge ausrechnen, fuer Intel32 auf 64K-Grenze begrenzen
+ bei Atmel nur 2 Byte pro Zeile! */
+
+ TransLen=min(LineLen,ErgLen);
+ if ((ActFormat==IntHex32) AND ((ErgStart&0xffff)+(TransLen/Gran)>=0x10000))
+ BEGIN
+ TransLen=Gran*(0x10000-(ErgStart&0xffff));
+ FirstBank=True;
+ END
+ else if (ActFormat==Atmel) TransLen=min(2,TransLen);
+
+ /* Start der Datenzeile */
+
+ switch (ActFormat)
+ BEGIN
+ case MotoS:
+ errno=0;
+ fprintf(TargFile,"S%c%s",'1'+MotRecType,HexByte(TransLen+3+MotRecType));
+ ChkIO(TargName);
+ ChkSum=TransLen+3+MotRecType;
+ if (MotRecType>=2)
+ BEGIN
+ errno=0; fprintf(TargFile,"%s",HexByte((ErgStart>>24)&0xff)); ChkIO(TargName);
+ ChkSum+=((ErgStart>>24)&0xff);
+ END
+ if (MotRecType>=1)
+ BEGIN
+ errno=0; fprintf(TargFile,"%s",HexByte((ErgStart>>16)&0xff)); ChkIO(TargName);
+ ChkSum+=((ErgStart>>16)&0xff);
+ END
+ errno=0; fprintf(TargFile,"%s",HexWord(ErgStart&0xffff)); ChkIO(TargName);
+ ChkSum+=Hi(ErgStart)+Lo(ErgStart);
+ break;
+ case MOSHex:
+ errno=0; fprintf(TargFile,";%s%s",HexByte(TransLen),HexWord(ErgStart AND 0xffff)); ChkIO(TargName);
+ ChkSum+=TransLen+Lo(ErgStart)+Hi(ErgStart);
+ break;
+ case IntHex:
+ case IntHex16:
+ case IntHex32:
+ errno=0; fprintf(TargFile,":"); ChkIO(TargName); ChkSum=0;
+ if (MultiMode==0)
+ BEGIN
+ errno=0; fprintf(TargFile,"%s",HexByte(TransLen)); ChkIO(TargName);
+ errno=0; fprintf(TargFile,"%s",HexWord((ErgStart-IntOffset)*Gran)); ChkIO(TargName);
+ ChkSum+=TransLen;
+ ChkSum+=Lo((ErgStart-IntOffset)*Gran);
+ ChkSum+=Hi((ErgStart-IntOffset)*Gran);
+ END
+ else
+ BEGIN
+ errno=0; fprintf(TargFile,"%s",HexByte(TransLen/Gran)); ChkIO(TargName);
+ errno=0; fprintf(TargFile,"%s",HexWord(ErgStart-IntOffset)); ChkIO(TargName);
+ ChkSum+=TransLen/Gran;
+ ChkSum+=Lo(ErgStart-IntOffset);
+ ChkSum+=Hi(ErgStart-IntOffset);
+ END
+ errno=0; fprintf(TargFile,"00"); ChkIO(TargName);
+ break;
+ case TekHex:
+ errno=0;
+ fprintf(TargFile,"/%s%s%s",HexWord(ErgStart),HexByte(TransLen),
+ HexByte(Lo(ErgStart)+Hi(ErgStart)+TransLen));
+ ChkIO(TargName);
+ ChkSum=0;
+ break;
+ case TiDSK:
+ errno=0; fprintf(TargFile,"9%s",HexWord(/*Gran**/ErgStart));
+ ChkIO(TargName);
+ ChkSum=0;
+ break;
+ case Atmel:
+ errno=0; fprintf(TargFile,"%s%s:",HexByte(ErgStart >> 16),HexWord(ErgStart & 0xffff));
+ ChkIO(TargName);
+ default:
+ break;
+ END
+
+ /* Daten selber */
+
+ if (fread(Buffer,1,TransLen,SrcFile)!=TransLen) ChkIO(FileName);
+ if ((Gran!=1) AND (MultiMode==1))
+ for (z=0; z<(TransLen/Gran); z++)
+ BEGIN
+ SwapBase=z*Gran;
+ for (z2=0; z2<(Gran/2); z++)
+ BEGIN
+ BSwap=Buffer[SwapBase+z2];
+ Buffer[SwapBase+z2]=Buffer[SwapBase+Gran-1-z2];
+ Buffer[SwapBase+Gran-1-z2]=BSwap;
+ END
+ END
+ if (ActFormat==TiDSK)
+ BEGIN
+ if (BigEndian) WSwap(WBuffer,TransLen);
+ for (z=0; z<(TransLen/2); z++)
+ BEGIN
+ errno=0;
+ if ((ErgStart+z >= StartData) AND (ErgStart+z <= StopData))
+ fprintf(TargFile,"M%s",HexWord(WBuffer[z]));
+ else
+ fprintf(TargFile,"B%s",HexWord(WBuffer[z]));
+ ChkIO(TargName);
+ ChkSum+=WBuffer[z];
+ SumLen+=Gran;
+ END
+ END
+ else if (ActFormat==Atmel)
+ BEGIN
+ if (TransLen>=2)
+ BEGIN
+ fprintf(TargFile,"%s",HexWord(WBuffer[0])); SumLen+=2;
+ END
+ END
+ else
+ for (z=0; z<(LongInt)TransLen; z++)
+ if ((MultiMode<2) OR (z%Gran==MultiMode-2))
+ BEGIN
+ errno=0; fprintf(TargFile,"%s",HexByte(Buffer[z])); ChkIO(TargName);
+ ChkSum+=Buffer[z];
+ SumLen++;
+ END
+
+ /* Ende Datenzeile */
+
+ switch (ActFormat)
+ BEGIN
+ case MotoS:
+ errno=0;
+ fprintf(TargFile,"%s\n",HexByte(Lo(ChkSum^0xff)));
+ ChkIO(TargName);
+ break;
+ case MOSHex:
+ errno=0;
+ fprintf(TargFile,"%s\n",HexWord(ChkSum));
+ break;
+ case IntHex:
+ case IntHex16:
+ case IntHex32:
+ errno=0;
+ fprintf(TargFile,"%s\n",HexByte(Lo(1+(ChkSum^0xff))));
+ ChkIO(TargName);
+ break;
+ case TekHex:
+ errno=0;
+ fprintf(TargFile,"%s\n",HexByte(Lo(ChkSum)));
+ ChkIO(TargName);
+ break;
+ case TiDSK:
+ errno=0;
+ fprintf(TargFile,"7%sF\n",HexWord(ChkSum));
+ ChkIO(TargName);
+ break;
+ case Atmel:
+ errno=0;
+ fprintf(TargFile,"\n");
+ ChkIO(TargName);
+ break;
+ default:
+ break;
+ END
+
+ /* Zaehler rauf */
+
+ ErgLen-=TransLen;
+ ErgStart+=TransLen/Gran;
+ END
+
+ /* Ende der Datenzeilengruppe */
+
+ switch (ActFormat)
+ BEGIN
+ case MotoS:
+ if (SepMoto)
+ BEGIN
+ errno=0;
+ fprintf(TargFile,"S%c%s",'9'-MotRecType,HexByte(3+MotRecType));
+ ChkIO(TargName);
+ for (z=1; z<=2+MotRecType; z++)
+ BEGIN
+ errno=0; fprintf(TargFile,"%s",HexByte(0)); ChkIO(TargName);
+ END
+ errno=0;
+ fprintf(TargFile,"%s\n",HexByte(0xff-3-MotRecType));
+ ChkIO(TargName);
+ END
+ break;
+ case MOSHex:
+ break;
+ case IntHex:
+ case IntHex16:
+ case IntHex32:
+ break;
+ case TekHex:
+ break;
+ case TiDSK:
+ break;
+ case Atmel:
+ break;
+ default:
+ break;
+ END;
+ END
+ if (fseek(SrcFile,NextPos,SEEK_SET)==-1) ChkIO(FileName);
+ END
+ END
+ while (InpHeader!=0);
+
+ errno=0; printf(" (%d Byte)\n",SumLen); ChkIO(OutName);
+
+ errno=0; fclose(SrcFile); ChkIO(FileName);
+END
+
+static ProcessProc CurrProcessor;
+static LongWord CurrOffset;
+
+ static void Callback(char *Name)
+BEGIN
+ CurrProcessor(Name,CurrOffset);
+END
+
+ static void ProcessGroup(char *GroupName_O, ProcessProc Processor)
+BEGIN
+ String Ext,GroupName;
+
+ CurrProcessor=Processor;
+ strmaxcpy(GroupName,GroupName_O,255); strmaxcpy(Ext,GroupName,255);
+ if (NOT RemoveOffset(GroupName,&CurrOffset)) ParamError(False,Ext);
+ AddSuffix(GroupName,getmessage(Num_Suffix));
+
+ if (NOT DirScan(GroupName,Callback))
+ fprintf(stderr,"%s%s%s\n",getmessage(Num_ErrMsgNullMaskA),GroupName,getmessage(Num_ErrMsgNullMaskB));
+END
+
+ static void MeasureFile(char *FileName, LongWord Offset)
+BEGIN
+ FILE *f;
+ Byte Header,Segment,Gran;
+ Word Length,TestID;
+ LongWord Adr,EndAdr,NextPos;
+
+ f=fopen(FileName,OPENRDMODE); if (f==Nil) ChkIO(FileName);
+
+ if (NOT Read2(f,&TestID)) ChkIO(FileName);
+ if (TestID!=FileMagic) FormatError(FileName,getmessage(Num_FormatInvHeaderMsg));
+
+ do
+ BEGIN
+ ReadRecordHeader(&Header,&Segment,&Gran,FileName,f);
+
+ if (Header==FileHeaderStartAdr)
+ BEGIN
+ if (fseek(f,sizeof(LongWord),SEEK_CUR)==-1) ChkIO(FileName);
+ END
+ else if (Header!=FileHeaderEnd)
+ BEGIN
+ if (NOT Read4(f,&Adr)) ChkIO(FileName);
+ if (NOT Read2(f,&Length)) ChkIO(FileName);
+ NextPos=ftell(f)+Length;
+ if (NextPos>FileSize(f))
+ FormatError(FileName,getmessage(Num_FormatInvRecordLenMsg));
+
+ if (FilterOK(Header))
+ BEGIN
+ Adr+=Offset;
+ EndAdr=Adr+(Length/Gran)-1;
+ if (StartAuto) if (StartAdr>Adr) StartAdr=Adr;
+ if (StopAuto) if (EndAdr>StopAdr) StopAdr=EndAdr;
+ END
+
+ fseek(f,NextPos,SEEK_SET);
+ END
+ END
+ while(Header!=0);
+
+ fclose(f);
+END
+
+ static CMDResult CMD_AdrRange(Boolean Negate, char *Arg)
+BEGIN
+ char *p,Save;
+ Boolean err;
+
+ if (Negate)
+ BEGIN
+ StartAdr=0; StopAdr=0x7fff;
+ return CMDOK;
+ END
+ else
+ BEGIN
+ p=strchr(Arg,'-'); if (p==Nil) return CMDErr;
+
+ Save = (*p); *p = '\0';
+ if ((StartAuto = AddressWildcard(Arg))) err = True;
+ else StartAdr = ConstLongInt(Arg, &err);
+ *p = Save;
+ if (NOT err) return CMDErr;
+
+ if ((StopAuto = AddressWildcard(p + 1))) err = True;
+ else StopAdr = ConstLongInt(p + 1, &err);
+ if (NOT err) return CMDErr;
+
+ if ((NOT StartAuto) AND (NOT StopAuto) AND (StartAdr>StopAdr)) return CMDErr;
+
+ return CMDArg;
+ END
+END
+
+ static CMDResult CMD_RelAdr(Boolean Negate, char *Arg)
+BEGIN
+ RelAdr=(NOT Negate);
+ return CMDOK;
+END
+
+ static CMDResult CMD_AdrRelocate(Boolean Negate, char *Arg)
+BEGIN
+ Boolean err;
+
+ if (Negate)
+ BEGIN
+ Relocate = 0;
+ return CMDOK;
+ END
+ else
+ BEGIN
+ Relocate = ConstLongInt(Arg,&err);
+ if (NOT err) return CMDErr;
+
+ return CMDArg;
+ END
+END
+
+ static CMDResult CMD_Rec5(Boolean Negate, char *Arg)
+BEGIN
+ Rec5=(NOT Negate);
+ return CMDOK;
+END
+
+ static CMDResult CMD_SepMoto(Boolean Negate, char *Arg)
+BEGIN
+ SepMoto=(NOT Negate);
+ return CMDOK;
+END
+
+ static CMDResult CMD_IntelMode(Boolean Negate, char *Arg)
+BEGIN
+ int Mode;
+ Boolean err;
+
+ if (*Arg=='\0') return CMDErr;
+ else
+ BEGIN
+ Mode=ConstLongInt(Arg,&err);
+ if ((NOT err) OR (Mode<0) OR (Mode>2)) return CMDErr;
+ else
+ BEGIN
+ if (NOT Negate) IntelMode=Mode;
+ else if (IntelMode==Mode) IntelMode=0;
+ return CMDArg;
+ END
+ END
+END
+
+ static CMDResult CMD_MultiMode(Boolean Negate, char *Arg)
+BEGIN
+ int Mode;
+ Boolean err;
+
+ if (*Arg=='\0') return CMDErr;
+ else
+ BEGIN
+ Mode=ConstLongInt(Arg,&err);
+ if ((NOT err) OR (Mode<0) OR (Mode>3)) return CMDErr;
+ else
+ BEGIN
+ if (NOT Negate) MultiMode=Mode;
+ else if (MultiMode==Mode) MultiMode=0;
+ return CMDArg;
+ END
+ END
+END
+
+ static CMDResult CMD_DestFormat(Boolean Negate, char *Arg)
+BEGIN
+#define NameCnt 9
+
+ static char *Names[NameCnt]={"DEFAULT","MOTO","INTEL","INTEL16","INTEL32","MOS","TEK","DSK","ATMEL"};
+ static THexFormat Format[NameCnt]={Default,MotoS,IntHex,IntHex16,IntHex32,MOSHex,TekHex,TiDSK,Atmel};
+ int z;
+
+ for (z=0; z<strlen(Arg); z++) Arg[z]=toupper(Arg[z]);
+
+ z=0;
+ while ((z<NameCnt) AND (strcmp(Arg,Names[z])!=0)) z++;
+ if (z>=NameCnt) return CMDErr;
+
+ if (NOT Negate) DestFormat=Format[z];
+ else if (DestFormat==Format[z]) DestFormat=Default;
+
+ return CMDArg;
+END
+
+ static CMDResult CMD_DataAdrRange(Boolean Negate, char *Arg)
+BEGIN
+ char *p,Save;
+ Boolean err;
+
+ if (Negate)
+ BEGIN
+ StartData=0; StopData=0x1fff;
+ return CMDOK;
+ END
+ else
+ BEGIN
+ p=strchr(Arg,'-'); if (p==Nil) return CMDErr;
+
+ Save=(*p); *p='\0';
+ StartData=ConstLongInt(Arg,&err);
+ *p=Save;
+ if (NOT err) return CMDErr;
+
+ StopData=ConstLongInt(p+1,&err);
+ if (NOT err) return CMDErr;
+
+ if (StartData>StopData) return CMDErr;
+
+ return CMDArg;
+ END
+END
+
+ static CMDResult CMD_EntryAdr(Boolean Negate, char *Arg)
+BEGIN
+ Boolean err;
+
+ if (Negate)
+ BEGIN
+ EntryAdrPresent=False;
+ return CMDOK;
+ END
+ else
+ BEGIN
+ EntryAdr=ConstLongInt(Arg,&err);
+ if ((NOT err) OR (EntryAdr>0xffff)) return CMDErr;
+ return CMDArg;
+ END
+END
+
+ static CMDResult CMD_LineLen(Boolean Negate, char *Arg)
+BEGIN
+ Boolean err;
+
+ if (Negate)
+ if (*Arg!='\0') return CMDErr;
+ else
+ BEGIN
+ LineLen=16; return CMDOK;
+ END
+ else if (*Arg=='\0') return CMDErr;
+ else
+ BEGIN
+ LineLen=ConstLongInt(Arg,&err);
+ if ((NOT err) OR (LineLen<1) OR (LineLen>MaxLineLen)) return CMDErr;
+ else
+ BEGIN
+ LineLen+=(LineLen&1); return CMDArg;
+ END
+ END
+END
+
+ static CMDResult CMD_MinMoto(Boolean Negate, char *Arg)
+BEGIN
+ Boolean err;
+
+ if (Negate)
+ if (*Arg != '\0') return CMDErr;
+ else
+ BEGIN
+ MinMoto = 0; return CMDOK;
+ END
+ else if (*Arg == '\0') return CMDErr;
+ else
+ BEGIN
+ MinMoto = ConstLongInt(Arg,&err);
+ if ((NOT err) OR (MinMoto < 1) OR (MinMoto > 3)) return CMDErr;
+ else return CMDArg;
+ END
+END
+
+ static CMDResult CMD_AutoErase(Boolean Negate, char *Arg)
+BEGIN
+ AutoErase=NOT Negate;
+ return CMDOK;
+END
+
+#define P2HEXParamCnt 14
+static CMDRec P2HEXParams[P2HEXParamCnt]=
+ {{"f", CMD_FilterList},
+ {"r", CMD_AdrRange},
+ {"R", CMD_AdrRelocate},
+ {"a", CMD_RelAdr},
+ {"i", CMD_IntelMode},
+ {"m", CMD_MultiMode},
+ {"F", CMD_DestFormat},
+ {"5", CMD_Rec5},
+ {"s", CMD_SepMoto},
+ {"d", CMD_DataAdrRange},
+ {"e", CMD_EntryAdr},
+ {"l", CMD_LineLen},
+ {"k", CMD_AutoErase},
+ {"M", CMD_MinMoto}};
+
+static Word ChkSum;
+
+ int main(int argc, char **argv)
+BEGIN
+ char *ph1,*ph2;
+ String Ver;
+
+ ParamCount=argc-1; ParamStr=argv;
+
+ nls_init(); NLS_Initialize();
+
+ hex_init();
+ endian_init();
+ bpemu_init();
+ hex_init();
+ chunks_init();
+ cmdarg_init(*argv);
+ toolutils_init(*argv);
+ nlmessages_init("p2hex.msg",*argv,MsgId1,MsgId2); ioerrs_init(*argv);
+
+ sprintf(Ver,"P2HEX/C V%s",Version);
+ WrCopyRight(Ver);
+
+ InitChunk(&UsedList);
+
+ if (ParamCount==0)
+ BEGIN
+ errno=0; printf("%s%s%s\n",getmessage(Num_InfoMessHead1),GetEXEName(),getmessage(Num_InfoMessHead2)); ChkIO(OutName);
+ for (ph1=getmessage(Num_InfoMessHelp),ph2=strchr(ph1,'\n'); ph2!=Nil; ph1=ph2+1,ph2=strchr(ph1,'\n'))
+ BEGIN
+ *ph2='\0';
+ printf("%s\n",ph1);
+ *ph2='\n';
+ END
+ exit(1);
+ END
+
+ StartAdr = 0; StopAdr = 0x7fff;
+ StartAuto = False; StopAuto = False;
+ StartData = 0; StopData = 0x1fff;
+ EntryAdr = (-1); EntryAdrPresent = False; AutoErase = False;
+ RelAdr = False; Rec5 = True; LineLen = 16;
+ IntelMode = 0; MultiMode = 0; DestFormat = Default; MinMoto = 1;
+ *TargName = '\0';
+ Relocate = 0;
+ ProcessCMD(P2HEXParams, P2HEXParamCnt, ParProcessed, "P2HEXCMD", ParamError);
+
+ if (ProcessedEmpty(ParProcessed))
+ BEGIN
+ errno=0; printf("%s\n",getmessage(Num_ErrMsgTargMissing)); ChkIO(OutName);
+ exit(1);
+ END
+
+ z=ParamCount;
+ while ((z>0) AND (NOT ParProcessed[z])) z--;
+ strmaxcpy(TargName,ParamStr[z],255);
+ if (NOT RemoveOffset(TargName,&Dummy)) ParamError(False,ParamStr[z]);
+ ParProcessed[z]=False;
+ if (ProcessedEmpty(ParProcessed))
+ BEGIN
+ strmaxcpy(SrcName,ParamStr[z],255); DelSuffix(TargName);
+ END
+ AddSuffix(TargName,HexSuffix);
+
+ if ((StartAuto) OR (StopAuto))
+ BEGIN
+#ifdef __STDC__
+ if (StartAuto) StartAdr=0xffffffffu;
+#else
+ if (StartAuto) StartAdr=0xffffffff;
+#endif
+ if (StopAuto) StopAdr=0;
+ if (ProcessedEmpty(ParProcessed)) ProcessGroup(SrcName,MeasureFile);
+ else for (z=1; z<=ParamCount; z++)
+ if (ParProcessed[z]) ProcessGroup(ParamStr[z],MeasureFile);
+ if (StartAdr>StopAdr)
+ BEGIN
+ errno=0; printf("%s\n",getmessage(Num_ErrMsgAutoFailed)); ChkIO(OutName); exit(1);
+ END
+ END
+
+ OpenTarget();
+ MotoOccured=False; IntelOccured=False;
+ MOSOccured=False; DSKOccured=False;
+ MaxMoto=0; MaxIntel=0;
+
+ if (ProcessedEmpty(ParProcessed)) ProcessGroup(SrcName,ProcessFile);
+ else for (z=1; z<=ParamCount; z++)
+ if (ParProcessed[z]) ProcessGroup(ParamStr[z],ProcessFile);
+
+ if ((MotoOccured) AND (NOT SepMoto))
+ BEGIN
+ errno=0; fprintf(TargFile,"S%c%s",'9'-MaxMoto,HexByte(3+MaxMoto)); ChkIO(TargName);
+ ChkSum=3+MaxMoto;
+ if (NOT EntryAdrPresent) EntryAdr=0;
+ if (MaxMoto>=2)
+ BEGIN
+ errno=0; fprintf(TargFile,HexByte((EntryAdr>>24)&0xff)); ChkIO(TargName);
+ ChkSum+=(EntryAdr>>24)&0xff;
+ END
+ if (MaxMoto>=1)
+ BEGIN
+ errno=0; fprintf(TargFile,HexByte((EntryAdr>>16)&0xff)); ChkIO(TargName);
+ ChkSum+=(EntryAdr>>16)&0xff;
+ END
+ errno=0; fprintf(TargFile,"%s",HexWord(EntryAdr&0xffff)); ChkIO(TargName);
+ ChkSum+=(EntryAdr>>8)&0xff;
+ ChkSum+=EntryAdr&0xff;
+ errno=0; fprintf(TargFile,"%s\n",HexByte(0xff-(ChkSum&0xff))); ChkIO(TargName);
+ END
+
+ if (IntelOccured)
+ BEGIN
+ if (EntryAdrPresent)
+ BEGIN
+ if (MaxIntel == 2)
+ BEGIN
+ errno = 0; fprintf(TargFile, ":04000005"); ChkIO(TargName); ChkSum = 4 + 5;
+ errno = 0; fprintf(TargFile, "%s", HexLong(EntryAdr)); ChkIO(TargName);
+ ChkSum+=((EntryAdr >> 24)& 0xff) +
+ ((EntryAdr >> 16)& 0xff) +
+ ((EntryAdr >> 8) & 0xff) +
+ ( EntryAdr & 0xff);
+ END
+ else if (MaxIntel == 1)
+ BEGIN
+ Seg = (EntryAdr >> 4) & 0xffff;
+ Ofs = EntryAdr & 0x000f;
+ errno = 0; fprintf(TargFile, ":04%s03%s", HexWord(Ofs), HexWord(Seg));
+ ChkIO(TargName); ChkSum = 4 + 3 + Lo(Seg) + Hi(Seg) + Ofs;
+ END
+ else
+ BEGIN
+ errno = 0; fprintf(TargFile, ":00%s03", HexWord(EntryAdr & 0xffff));
+ ChkIO(TargName); ChkSum = 3 + Lo(EntryAdr) + Hi(EntryAdr);
+ END
+ errno = 0; fprintf(TargFile, "%s\n", HexByte(0x100 - ChkSum)); ChkIO(TargName);
+ END
+ errno=0;
+ switch (IntelMode)
+ BEGIN
+ case 0: fprintf(TargFile,":00000001FF\n"); break;
+ case 1: fprintf(TargFile,":00000001\n"); break;
+ case 2: fprintf(TargFile,":0000000000\n"); break;
+ END
+ ChkIO(TargName);
+ END
+
+ if (MOSOccured)
+ BEGIN
+ errno=0; fprintf(TargFile,";0000040004\n"); ChkIO(TargName);
+ END
+
+ if (DSKOccured)
+ BEGIN
+ if (EntryAdrPresent)
+ BEGIN
+ errno=0;
+ fprintf(TargFile,"1%s7%sF\n",HexWord(EntryAdr),HexWord(EntryAdr));
+ ChkIO(TargName);
+ END
+ errno=0; fprintf(TargFile,":\n"); ChkIO(TargName);
+ END
+
+ CloseTarget();
+
+ if (AutoErase)
+ BEGIN
+ if (ProcessedEmpty(ParProcessed)) ProcessGroup(SrcName,EraseFile);
+ else for (z=1; z<=ParamCount; z++)
+ if (ParProcessed[z]) ProcessGroup(ParamStr[z],EraseFile);
+ END
+
+ return 0;
+END
diff --git a/p2hex.res b/p2hex.res
new file mode 100644
index 0000000..be60312
--- /dev/null
+++ b/p2hex.res
@@ -0,0 +1,77 @@
+;* p2hex.res
+;*****************************************************************************
+;* AS-Portierung *
+;* *
+;* String-Definitionen fuer P2HEX *
+;* *
+;* Historie: 1. 6.1996 Grundsteinlegung *
+;* 26.10.1997 kill-Option *
+;* 6. 7.1999 Minimalparameter Motorola S-Records *
+;* 24.10.1999 Parameter Relokation *
+;* *
+;*****************************************************************************
+
+Include header.res
+
+Include tools2.res
+
+;------------------------------------------------------------------------------
+; Steuerstrings HEX-Files
+
+Message DSKHeaderLine
+ "K_DSKA_1.00_DSK_"
+ "K_DSKA_1.00_DSK_"
+
+;------------------------------------------------------------------------------
+; Fehlermeldungen
+
+Message ErrMsgAdrOverflow
+ "Warnung: Adre&szlig;&uuml;berlauf "
+ "warning: address overflow "
+
+;------------------------------------------------------------------------------
+; Ansagen
+
+Message InfoMessHead2
+ " <Quelldatei(en)> <Zieldatei> [Optionen]"
+ " <source file(s)> <target file> [options]"
+
+Message InfoMessHelp
+ "\n" \
+ "Optionen: -f <Headerliste> : auszufilternde Records\n" \
+ " -r <Start>-<Stop> : auszufilternder Adre&szlig;bereich\n" \
+ " -R <offset> : Adressen um Offset verschieben\n" \
+ " ($ = erste bzw. letzte auftauchende Adresse)\n" \
+ " -a : Adressen relativ zum Start ausgeben\n" \
+ " -l <L&auml;nge> : L&auml;nge Datenzeile/Bytes\n" \
+ " -i <0|1|2> : Terminierer f&uuml;r Intel-Hexfiles\n" \
+ " -m <0..3> : Multibyte-Modus\n" \
+ " -F <Default|Moto|\n" \
+ " Intel|MOS|Tek|\n" \
+ " Intel16|DSK|\n" \
+ " Intel32> : Zielformat\n" \
+ " +5 : S5-Records unterdr&uuml;cken\n" \
+ " -s : S-Record-Gruppen einzeln terminieren\n" \
+ " -M <1|2|3> : Minimallaenge Adressen S-Records\n" \
+ " -d <Start>-<Stop> : Datenbereich festlegen\n" \
+ " -e <Adresse> : Startadresse festlegen\n" \
+ " -k : Quelldateien autom. l&ouml;schen\n"
+ "\n" \
+ "options: -f <header list> : records to filter out\n" \
+ " -r <start>-<stop> : address range to filter out\n" \
+ " -R <offset> : relocate addresses by offset\n" \
+ " ($ = first resp. last occuring address)\n" \
+ " -a : addresses in hex file relativ to start\n" \
+ " -l <length> : set length of data line in bytes\n" \
+ " -i <0|1|2> : terminating line for intel hex\n" \
+ " -m <0..3> : multibyte mode\n" \
+ " -F <Default|Moto|\n" \
+ " Intel|MOS|Tek|\n" \
+ " Intel16|DSK|\n" \
+ " Intel32> : target format\n" \
+ " +5 : supress S5-records\n" \
+ " -s : separate terminators for S-record groups\n" \
+ " -M <1|2|3> : minimum length of S records addresses\n" \
+ " -d <start>-<stop> : set data range\n" \
+ " -e <address> : set entry address\n" \
+ " -k : automatically erase source files\n"
diff --git a/pascstyle.h b/pascstyle.h
new file mode 100644
index 0000000..82e8b91
--- /dev/null
+++ b/pascstyle.h
@@ -0,0 +1,17 @@
+#define BEGIN {
+#define END }
+
+#define AND &&
+#define OR ||
+#define NOT !
+
+#ifndef False
+#define False 0
+#define True 1
+#endif
+
+#define Nil NULL
+
+#define Ord(b) ((b)?1L:0L)
+
+#define MaxLongInt 2147483647
diff --git a/pbind.1 b/pbind.1
new file mode 100644
index 0000000..0515a2d
--- /dev/null
+++ b/pbind.1
@@ -0,0 +1,145 @@
+.TH pbind 1
+
+.SH NAME
+.B pbind \- recombine output files generated by AS
+
+.SH SYNTAX
+.B pbind
+[ option(s) ] <name(s)> [ further options/names ]
+
+.SH DESCRIPTION
+
+BIND is a tool to combine code files generated by the AS cross
+assembler to a single file or to extract records out of a code file.
+.B pbind
+is the Unix/C implementation of BIND. BIND is
+.B not
+a linker; AS does not generate linkable code!
+
+Arguments to BIND can be either file name specifications or
+command line parameters; any argument starting with a plus(+), minus(-)
+or slash(/) is recognized as a parameter; anything else is regarded as
+a file name. BIND always regards the last name as the target file's name
+specification; all other files are regarded as source files. A target
+name and no source will yield an empty target file, whereas no file name
+at all will result in an error message. File names that do not have an
+extension will be expanded with '.p', the standard extension for code
+files.
+
+The way BIND operates is to process source files in the order they are given
+in the command line, reading record by record, and to write records that fit
+into the given filtering criteria to the target file. After all source files
+have been processed, BIND will write a new creator entry to the target file.
+
+.SH COMMAND-LINE PARAMETERS
+
+If a command-line parameter starts with a slash(/) or minus sign(-), it
+turns an option on; if a command-line parameter starts with a plus sign(+),
+it turns a specific option off. Numeric arguments to parameters can be
+either written in decimal or hexadecimal notation. For hexadecimal notation,
+prefix the number with a dollar($) sign.
+
+.B pbind
+accepts the following command-line parameters:
+.TP
+.B -f <number>[,<further numbers>]
+Add <number> to the list of record header IDs that allow a record from a source
+file to be written to the target file. A certain header ID marks code for a certain
+target processor family; thus, this filter allows to distill code for a certain
+processor out of a source file that contains code for different processor families.
+Negation of this parameter removes certain header IDs from BIND's list. See
+the user manual of AS for a list of all possible header ID values. If BIND's list
+of header IDs is empty, no filtering will take place, i.e. all records from a source
+file will make it into the target file.
+
+.SH PRESETTING PARAMETERS
+
+Parameters need not neccessarily be given in the command line itself. Before
+processing of command line parameters starts, BIND will look if the
+.B BINDCMD
+environment variable is defined. If it exists, its contents will be
+treated as additional command line paramters whose syntax is absolutely
+equal to normal command line parameters. As exception is made if the
+variable's contents start with a '@' sign; in such a case, the string after
+the '@' sign is treated as the name of a file that contains the options.
+Such a file (also called a 'key file') has the advantage that it allows
+the options to be written in different lines, and it does not have a size
+limit. Some operating systems (like MS-DOS) do have a length limit on
+command lines and environment variable contents, so the key file may be
+your only option if you have a lot of lengthy parameters for BIND.
+
+.SH RETURN CODES
+
+.B pbind
+may return with the following codes:
+.TP
+.B 0
+no errors.
+.TP
+.B 1
+incorrect command line parameters.
+.TP
+.B 2
+I/O-error.
+.TP
+.B 3
+An input file had an incorrect format.
+
+.SH EXAMPLES
+
+To combine all records of
+.B src1.p
+and
+.B src2.p
+into a single file
+.B dest.p,
+use:
+.PP
+.B pbind src1 src2 dest
+.PP
+To extract all records with MCS-51-code from a file
+.B mixed.p,
+use
+.PP
+.B pbind -f \e$31 mixed only51,
+.PP
+and the record will be written to a file
+.B only51.p.
+Notice that the dollar sign in this example had to be protected with a backslash
+sign, as a UNIX shell uses the dollar character for expansion of variables. This
+would not have been necessary on an OS/2 or MS-DOS system (it would result in
+an error).
+
+.SH NATIONAL LANGUAGE SUPPORT
+
+pbind supports national languages in the same way as AS. See the manual
+page for asl(1) for maore information about this.
+
+.SH TIPS
+
+Calling BIND without any arguments will print a short help
+listing all command line parameters.
+
+.SH SEE ALSO
+
+asl(1), plist(1), p2hex(1), p2bin(1)
+
+.SH HISTORY
+
+BIND originally appeared as an AS tool in 1992, written in
+Borland-Pascal, and was ported to C and UNIX in 1997.
+
+.SH BUGS
+
+Command line interpreters of some operating systems reserve some
+characters for their own use, so it might be necessary to give
+command line parameters with certain tricks (e.g., with the help
+of escape characters).
+
+BIND does not have so far an opportunity to filter records by
+target segment.
+
+.SH AUTHOR(S)
+
+Alfred Arnold (a.arnold@kfa-juelich.de)
+
diff --git a/pbind.c b/pbind.c
new file mode 100644
index 0000000..9f0410f
--- /dev/null
+++ b/pbind.c
@@ -0,0 +1,182 @@
+/* bind.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Bearbeitung von AS-P-Dateien */
+/* */
+/* Historie: 1. 6.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "version.h"
+#include "endian.h"
+#include "stdhandl.h"
+#include "bpemu.h"
+#include "strutil.h"
+#include "cmdarg.h"
+#include "toolutils.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "pbind.rsc"
+#include "ioerrs.h"
+
+static char *Creator="BIND/C 1.41r6";
+
+
+static CMDProcessed ParProcessed;
+
+static FILE *TargFile;
+static String TargName;
+
+ static void OpenTarget(void)
+BEGIN
+ TargFile=fopen(TargName,OPENWRMODE);
+ if (TargFile==Nil) ChkIO(TargName);
+ if (NOT Write2(TargFile,&FileID)) ChkIO(TargName);
+END
+
+ static void CloseTarget(void)
+BEGIN
+ Byte EndHeader=FileHeaderEnd;
+
+ if (fwrite(&EndHeader,1,1,TargFile)!=1) ChkIO(TargName);
+ if (fwrite(Creator,1,strlen(Creator),TargFile)!=strlen(Creator)) ChkIO(TargName);
+ if (fclose(TargFile)==EOF) ChkIO(TargName);
+ if (Magic!=0) unlink(TargName);
+END
+
+ static void ProcessFile(char *FileName)
+BEGIN
+#define BufferSize 8192
+ FILE *SrcFile;
+ Word TestID;
+ Byte InpHeader,InpSegment,InpGran;
+ LongInt InpStart,SumLen;
+ Word InpLen,TransLen;
+ Boolean doit;
+ Byte Buffer[BufferSize];
+
+ SrcFile=fopen(FileName,OPENRDMODE);
+ if (SrcFile==Nil) ChkIO(FileName);
+
+ if (NOT Read2(SrcFile,&TestID)) ChkIO(FileName);
+ if (TestID!=FileMagic) FormatError(FileName,getmessage(Num_FormatInvHeaderMsg));
+
+ errno=0; printf("%s==>>%s",FileName,TargName); ChkIO(OutName);
+
+ SumLen=0;
+
+ do
+ BEGIN
+ ReadRecordHeader(&InpHeader,&InpSegment,&InpGran,FileName,SrcFile);
+ if (InpHeader==FileHeaderStartAdr)
+ BEGIN
+ if (NOT Read4(SrcFile,&InpStart)) ChkIO(FileName);
+ WriteRecordHeader(&InpHeader,&InpSegment,&InpGran,TargName,TargFile);
+ if (NOT Write4(TargFile,&InpStart)) ChkIO(TargName);
+ END
+ else if (InpHeader!=FileHeaderEnd)
+ BEGIN
+ if (NOT Read4(SrcFile,&InpStart)) ChkIO(FileName);
+ if (NOT Read2(SrcFile,&InpLen)) ChkIO(FileName);
+
+ if (ftell(SrcFile)+InpLen>=FileSize(SrcFile)-1)
+ FormatError(FileName,getmessage(Num_FormatInvRecordLenMsg));
+
+ doit=FilterOK(InpHeader);
+
+ if (doit)
+ BEGIN
+ SumLen+=InpLen;
+ WriteRecordHeader(&InpHeader,&InpSegment,&InpGran,TargName,TargFile);
+ if (NOT Write4(TargFile,&InpStart)) ChkIO(TargName);
+ if (NOT Write2(TargFile,&InpLen)) ChkIO(TargName);
+ while (InpLen>0)
+ BEGIN
+ TransLen=min(BufferSize,InpLen);
+ if (fread(Buffer,1,TransLen,SrcFile)!=TransLen) ChkIO(FileName);
+ if (fwrite(Buffer,1,TransLen,TargFile)!=TransLen) ChkIO(TargName);
+ InpLen-=TransLen;
+ END
+ END
+ else
+ BEGIN
+ if (fseek(SrcFile,InpLen,SEEK_CUR)==-1) ChkIO(FileName);
+ END
+ END
+ END
+ while (InpHeader!=FileHeaderEnd);
+
+ errno=0; printf(" (%d Byte",SumLen); ChkIO(OutName);
+
+ if (fclose(SrcFile)==EOF) ChkIO(FileName);
+END
+
+ static void ParamError(Boolean InEnv, char *Arg)
+BEGIN
+ printf("%s%s\n",getmessage(InEnv ? Num_ErrMsgInvEnvParam : Num_ErrMsgInvParam),Arg);
+ printf("%s\n",getmessage(Num_ErrMsgProgTerm));
+ exit(1);
+END
+
+#define BINDParamCnt 1
+static CMDRec BINDParams[BINDParamCnt]=
+ {{"f", CMD_FilterList}};
+
+ int main(int argc, char **argv)
+BEGIN
+ int z;
+ char *ph1,*ph2;
+ String Ver;
+
+ ParamCount=argc-1; ParamStr=argv;
+
+ NLS_Initialize();
+
+ sprintf(Ver,"BIND/C V%s",Version);
+ WrCopyRight(Ver);
+
+ stdhandl_init(); cmdarg_init(*argv); toolutils_init(*argv); nls_init();
+ nlmessages_init("pbind.msg",*argv,MsgId1,MsgId2); ioerrs_init(*argv);
+
+ if (ParamCount==0)
+ BEGIN
+ errno=0; printf("%s%s%s\n",getmessage(Num_InfoMessHead1),GetEXEName(),getmessage(Num_InfoMessHead2)); ChkIO(OutName);
+ for (ph1=getmessage(Num_InfoMessHelp),ph2=strchr(ph1,'\n'); ph2!=Nil; ph1=ph2+1,ph2=strchr(ph1,'\n'))
+ BEGIN
+ *ph2='\0';
+ printf("%s\n",ph1);
+ *ph2='\n';
+ END
+ exit(1);
+ END
+
+ ProcessCMD(BINDParams,BINDParamCnt,ParProcessed,"BINDCMD",ParamError);
+
+ z=ParamCount;
+ while ((z>0) AND (NOT ParProcessed[z])) z--;
+ if (z==0)
+ BEGIN
+ errno=0; printf("%s\n",getmessage(Num_ErrMsgTargetMissing));
+ ChkIO(OutName);
+ exit(1);
+ END
+ else
+ BEGIN
+ strmaxcpy(TargName,ParamStr[z],255); ParProcessed[z]=False;
+ AddSuffix(TargName,getmessage(Num_Suffix));
+ END
+
+ OpenTarget();
+
+ for (z=1; z<=ParamCount; z++)
+ if (ParProcessed[z]) DirScan(ParamStr[z],ProcessFile);
+
+ CloseTarget();
+
+ return 0;
+END
diff --git a/pbind.res b/pbind.res
new file mode 100644
index 0000000..f8c7975
--- /dev/null
+++ b/pbind.res
@@ -0,0 +1,34 @@
+;* pbind.res
+;****************************************************************************
+;* Makroassembler AS *
+;* *
+;* Headerdatei BIND.RSC - enthaelt Stringdefinitionen fuer BIND *
+;* *
+;* Historie : 28.1.1997 Grundsteinlegung *
+;* *
+;****************************************************************************
+
+Include header.res
+
+Include tools2.res
+
+;-----------------------------------------------------------------------------
+; Fehlermeldungen
+
+Message ErrMsgTargetMissing
+ "Zieldateiangabe fehlt!"
+ "target file specification is missing!"
+
+;-----------------------------------------------------------------------------
+; Ansagen
+
+Message InfoMessHead2
+ " <Quelldatei(en)> <Zieldatei> [Optionen]"
+ " <source file(s)> <target file> [options]"
+
+Message InfoMessHelp
+ "\n" \
+ "Optionen: -f <Headerliste> : auszufilternde Records"
+ "\n" \
+ "options: -f <header list> : records to filter out"
+
diff --git a/plist.1 b/plist.1
new file mode 100644
index 0000000..180de5f
--- /dev/null
+++ b/plist.1
@@ -0,0 +1,84 @@
+.TH plist 1
+
+.SH NAME
+.B plist \- list contents of output files generated by AS
+
+.SH SYNTAX
+.B plist
+[ file name ]
+
+.SH DESCRIPTION
+
+PLIST is a program to list the contents of code output files generated by
+AS, a cross assembler for a variety of microprocessors and -controllers.
+PLIST takes only one argument: the name of the file to list. If [ name ]
+does not have an extension, the default extension '.p' will be added
+automatically. The output consists of a single line for each record in
+the file, listing the target processor, target address space, number of
+code/data bytes, and start/stop address. Note that the difference between
+the start and stop address need not equal the number of bytes, since there
+are target processors whose memory is not bytewise-organized. The records
+that specify entry address and file creator have a different layout and
+therefore have a little bit different look in PLIST's output.
+
+PLIST does not accept multiple file arguments; processing of several files
+must be done with individual calls.
+
+.SH COMMAND-LINE PARAMETERS
+
+none.
+
+.SH NATIONAL LANGUAGE SUPPORT
+
+plist supports national languages in the same way as AS. See the manual
+page for asl(1) for maore information about this.
+
+.SH RETURN CODES
+
+.B plist
+may return with the following codes:
+.TP
+.B 0
+no errors.
+.TP
+.B 1
+incorrect command line parameters.
+.TP
+.B 2
+I/O-error.
+.TP
+.B 3
+An input file had an incorrect format.
+
+.SH EXAMPLES
+
+To list the contents of a code file
+.B file1.p,
+use:
+.PP
+.B plist file1
+.PP
+There aren't more meaningful examples, as PLIST does not have
+any command line parameters.
+
+.SH TIPS
+
+If PLIST is started without any argument, it will prompt for a file's name.
+
+.SH SEE ALSO
+
+asl(1), pbind(1), p2hex(1), p2bin(1)
+
+.SH HISTORY
+
+PLIST originally appeared as an AS tool in 1992, written in
+Borland-Pascal, and was ported to C and UNIX in 1996.
+
+.SH BUGS
+
+There are too few options.
+
+.SH AUTHOR(S)
+
+Alfred Arnold (a.arnold@kfa-juelich.de)
+
diff --git a/plist.c b/plist.c
new file mode 100644
index 0000000..5905e88
--- /dev/null
+++ b/plist.c
@@ -0,0 +1,169 @@
+/* plist.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Anzeige des Inhalts einer Code-Datei */
+/* */
+/* Historie: 31. 5.1996 Grundsteinlegung */
+/* 29. 8.1998 Tabellen auf HeadIds umgestellt */
+/* main-lokale Variablen dorthin verschoben */
+/* 11. 9.1998 ROMDATA-Segment hinzugenommen */
+/* 15. 8.1999 Einrueckung der Endadresse korrigiert */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "version.h"
+#include "endian.h"
+#include "hex.h"
+#include "bpemu.h"
+#include "cmdarg.h"
+#include "nls.h"
+#include "nlmessages.h"
+#include "plist.rsc"
+#include "ioerrs.h"
+#include "strutil.h"
+#include "toolutils.h"
+#include "headids.h"
+
+static char *SegNames[PCMax+1]={"NONE","CODE","DATA","IDATA","XDATA","YDATA",
+ "BITDATA","IO","REG","ROMDATA"};
+
+
+
+ int main(int argc, char **argv)
+BEGIN
+ FILE *ProgFile;
+ String ProgName;
+ Byte Header,Segment,Gran;
+ LongWord StartAdr,Sums[PCMax+1];
+ Word Len,ID,z;
+ int Ch;
+ Boolean HeadFnd;
+ char *ph1,*ph2;
+ String Ver;
+ PFamilyDescr FoundId;
+
+ ParamCount=argc-1; ParamStr=argv;
+
+ nls_init(); NLS_Initialize();
+
+ endian_init();
+ hex_init();
+ bpemu_init();
+ strutil_init();
+ nlmessages_init("plist.msg",*argv,MsgId1,MsgId2); ioerrs_init(*argv);
+ cmdarg_init(*argv);
+ toolutils_init(*argv);
+
+ sprintf(Ver,"PLIST/C V%s",Version);
+ WrCopyRight(Ver);
+
+ if (ParamCount==0)
+ BEGIN
+ errno=0;
+ printf("%s",getmessage(Num_MessFileRequest)); fgets(ProgName,255,stdin);
+ ChkIO(OutName);
+ END
+ else if (ParamCount==1 ) strmaxcpy(ProgName,ParamStr[1],255);
+ else
+ BEGIN
+ errno=0; printf("%s%s%s\n",getmessage(Num_InfoMessHead1),GetEXEName(),getmessage(Num_InfoMessHead2)); ChkIO(OutName);
+ for (ph1=getmessage(Num_InfoMessHelp),ph2=strchr(ph1,'\n'); ph2!=Nil; ph1=ph2+1,ph2=strchr(ph1,'\n'))
+ BEGIN
+ *ph2='\0';
+ printf("%s\n",ph1);
+ *ph2='\n';
+ END
+ exit(1);
+ END
+
+ AddSuffix(ProgName,getmessage(Num_Suffix));
+
+ if ((ProgFile=fopen(ProgName,OPENRDMODE))==Nil) ChkIO(ProgName);
+
+ if (NOT Read2(ProgFile,&ID)) ChkIO(ProgName);
+ if (ID!=FileMagic) FormatError(ProgName,getmessage(Num_FormatInvHeaderMsg));
+
+ errno=0; printf("\n"); ChkIO(OutName);
+ errno=0; printf("%s\n",getmessage(Num_MessHeaderLine1)); ChkIO(OutName);
+ errno=0; printf("%s\n",getmessage(Num_MessHeaderLine2)); ChkIO(OutName);
+
+ for (z=0; z<=PCMax; Sums[z++]=0);
+
+ do
+ BEGIN
+ ReadRecordHeader(&Header,&Segment,&Gran,ProgName,ProgFile);
+
+ HeadFnd=False;
+
+ if (Header==FileHeaderEnd)
+ BEGIN
+ errno=0; printf(getmessage(Num_MessGenerator)); ChkIO(OutName);
+ do
+ BEGIN
+ errno=0; Ch=fgetc(ProgFile); ChkIO(ProgName);
+ if (Ch!=EOF)
+ BEGIN
+ errno=0; putchar(Ch); ChkIO(OutName);
+ END
+ END
+ while (Ch!=EOF);
+ errno=0; printf("\n"); ChkIO(OutName); HeadFnd=True;
+ END
+
+ else if (Header==FileHeaderStartAdr)
+ BEGIN
+ if (NOT Read4(ProgFile,&StartAdr)) ChkIO(ProgName);
+ errno=0; printf("%s%s\n",getmessage(Num_MessEntryPoint),HexLong(StartAdr));
+ ChkIO(OutName);
+ END
+
+ else
+ BEGIN
+ errno=0;
+ if (Magic!=0) FoundId=Nil;
+ else FoundId=FindFamilyById(Header);
+ if (FoundId==Nil) printf("???=%02x ",Header);
+ else printf("%-13s ",FoundId->Name);
+ ChkIO(OutName);
+
+ errno=0; printf("%-5s ",SegNames[Segment]); ChkIO(OutName);
+
+ if (NOT Read4(ProgFile,&StartAdr)) ChkIO(ProgName);
+ errno=0; printf("%s ",HexLong(StartAdr)); ChkIO(OutName);
+
+ if (NOT Read2(ProgFile,&Len)) ChkIO(ProgName);
+ errno=0; printf("%s ",HexWord(Len)); ChkIO(OutName);
+
+ if (Len!=0) StartAdr+=(Len/Gran)-1;
+ else StartAdr--;
+ errno=0; printf("%s\n",HexLong(StartAdr)); ChkIO(OutName);
+
+ Sums[Segment]+=Len;
+
+ if (ftell(ProgFile)+Len>=FileSize(ProgFile))
+ FormatError(ProgName,getmessage(Num_FormatInvRecordLenMsg));
+ else if (fseek(ProgFile,Len,SEEK_CUR)!=0) ChkIO(ProgName);
+ END
+ END
+ while (Header!=0);
+
+ errno=0; printf("\n"); ChkIO(OutName);
+ errno=0; printf("%s",getmessage(Num_MessSum1)); ChkIO(OutName);
+ for (z=0; z<=PCMax; z++)
+ if ((z==SegCode) OR (Sums[z]!=0))
+ BEGIN
+ errno=0;
+ printf(LongIntFormat,Sums[z]);
+ printf("%s%s\n%s",getmessage((Sums[z]==1)?Num_MessSumSing:Num_MessSumPlur),
+ SegNames[z],Blanks(strlen(getmessage(Num_MessSum1))));
+ END
+ errno=0; printf("\n"); ChkIO(OutName);
+ errno=0; printf("\n"); ChkIO(OutName);
+
+ errno=0; fclose(ProgFile); ChkIO(ProgName);
+ return 0;
+END
diff --git a/plist.res b/plist.res
new file mode 100644
index 0000000..bc9b2bf
--- /dev/null
+++ b/plist.res
@@ -0,0 +1,57 @@
+;* plist.res
+;*****************************************************************************
+;* AS-Portierung *
+;* *
+;* Stringdefinitionen fuer PLIST *
+;* *
+;* Historie: 31. 5.1996 Grundsteinlegung *
+;* 3.12.1996 Erweiterung um Segment-Spalte *
+;* *
+;*****************************************************************************
+
+Include header.res
+
+Include tools2.res
+
+;-----------------------------------------------------------------------------
+; Ansagen
+
+Message MessFileRequest
+ "zu listende Programmdatei [.P] : "
+ "program file to list [.P] : "
+
+Message MessHeaderLine1
+ "Codetyp Segment Startadresse L&auml;nge (Byte) Endadresse"
+ "code type segment start address length (byte) end address"
+
+Message MessHeaderLine2
+ "------------------------------------------------------------"
+ "--------------------------------------------------------------"
+
+Message MessGenerator
+ "Erzeuger : "
+ "creator : "
+
+Message MessSum1
+ "insgesamt "
+ "altogether "
+
+Message MessSumSing
+ " Byte "
+ " byte "
+
+Message MessSumPlur
+ " Bytes "
+ " bytes "
+
+Message MessEntryPoint
+ "<Einsprung> "
+ "<entry point> "
+
+Message InfoMessHead2
+ " [Programmdateiname]"
+ " [name of program file]"
+
+Message InfoMessHelp
+ "\n"
+ "\n"
diff --git a/reltypes.c b/reltypes.c
new file mode 100644
index 0000000..08410c3
--- /dev/null
+++ b/reltypes.c
@@ -0,0 +1,9 @@
+1. Startadresse (tU64)
+2. Gesamtbits (tU8)
+3. Gesamtbytes (tU8)
+4. Bitverteilung auf die Bytes im Code:
+ - Startbit im Quellwert (tU8)
+ - Startbit im Byte (1. H. tU8)
+ - Anzahl Bits (2. H. tU8)
+
+Sonderwerte für n-Byte-Werte in Little/Big-Endian
diff --git a/rescomp.c b/rescomp.c
new file mode 100644
index 0000000..cedba36
--- /dev/null
+++ b/rescomp.c
@@ -0,0 +1,433 @@
+/* rescomp.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Compiler fuer Message-Dateien */
+/* */
+/* 17. 5.1998 Symbol gegen Mehrfachinklusion eingebaut */
+/* 5. 7.1998 zusaetzliche Sonderzeichen */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "endian.h"
+#include "strutil.h"
+#include "bpemu.h"
+
+/*****************************************************************************/
+
+typedef struct _TMsgList
+ {
+ struct _TMsgList *Next;
+ LongInt Position;
+ char *Contents;
+ } TMsgList,*PMsgList;
+
+typedef struct
+ {
+ PMsgList Messages,LastMessage;
+ char *CtryName;
+ LongInt *CtryCodes,CtryCodeCnt;
+ LongInt FilePos,HeadLength,TotLength;
+ } TMsgCat,*PMsgCat;
+
+typedef struct
+ {
+ char *AbbString,*Character;
+ } TransRec;
+
+/*****************************************************************************/
+
+#ifdef __TURBOC__
+unsigned _stklen=16384;
+#endif
+
+static char *IdentString="AS Message Catalog - not readable\n\032\004";
+
+static LongInt MsgCounter;
+static PMsgCat MsgCats;
+static LongInt CatCount,DefCat;
+static FILE *SrcFile,*MsgFile,*HFile;
+static char *IncSym;
+
+static TransRec TransRecs[]={
+ {"&auml;",CH_ae},
+ {"&euml;",CH_ee},
+ {"&iuml;",CH_ie},
+ {"&ouml;",CH_oe},
+ {"&uuml;",CH_ue},
+ {"&Auml;",CH_Ae},
+ {"&Euml;",CH_Ee},
+ {"&Iuml;",CH_Ie},
+ {"&Ouml;",CH_Oe},
+ {"&Uuml;",CH_Ue},
+ {"&szlig;",CH_sz},
+ {"&sup2;",CH_e2},
+ {"&micro;",CH_mu},
+ {"&agrave;",CH_agrave},
+ {"&Agrave;",CH_Agrave},
+ {"&egrave;",CH_egrave},
+ {"&Egrave;",CH_Egrave},
+ {"&igrave;",CH_igrave},
+ {"&Igrave;",CH_Igrave},
+ {"&ograve;",CH_ograve},
+ {"&Ograve;",CH_Ograve},
+ {"&ugrave;",CH_ugrave},
+ {"&Ugrave;",CH_Ugrave},
+ {"&aacute;",CH_aacute},
+ {"&Aacute;",CH_Aacute},
+ {"&eacute;",CH_eacute},
+ {"&Eacute;",CH_Eacute},
+ {"&iacute;",CH_iacute},
+ {"&Iacute;",CH_Iacute},
+ {"&oacute;",CH_oacute},
+ {"&Oacute;",CH_Oacute},
+ {"&uacute;",CH_uacute},
+ {"&Uacute;",CH_Uacute},
+ {"&acirc;",CH_acirc},
+ {"&Acirc;",CH_Acirc},
+ {"&ecirc;",CH_ecirc},
+ {"&Ecirc;",CH_Ecirc},
+ {"&icirc;",CH_icirc},
+ {"&Icirc;",CH_Icirc},
+ {"&ocirc;",CH_ocirc},
+ {"&Ocirc;",CH_Ocirc},
+ {"&ucirc;",CH_ucirc},
+ {"&Ucirc;",CH_Ucirc},
+ {"&ccedil;",CH_ccedil},
+ {"&Ccedil;",CH_Ccedil},
+ {"&ntilde;",CH_ntilde},
+ {"&Ntilde;",CH_Ntilde},
+ {"&aring;",CH_aring},
+ {"&Aring;",CH_Aring},
+ {"&aelig;",CH_aelig},
+ {"&Aelig;",CH_Aelig},
+ {"&iquest;",CH_iquest},
+ {"&iexcl;",CH_iexcl},
+ {"\\n","\n"},
+ {Nil,Nil}};
+
+/*****************************************************************************/
+
+typedef struct _TIncList
+ {
+ struct _TIncList *Next;
+ FILE *Contents;
+ } TIncList,*PIncList;
+
+PIncList IncList=Nil;
+
+ static void GetLine(char *Dest)
+BEGIN
+ PIncList OneFile;
+
+ ReadLn(SrcFile,Dest);
+ if (strncasecmp(Dest,"INCLUDE",7)==0)
+ BEGIN
+ OneFile=(PIncList) malloc(sizeof(TIncList));
+ OneFile->Next=IncList; OneFile->Contents=SrcFile;
+ IncList=OneFile;
+ strcpy(Dest,Dest+7); KillPrefBlanks(Dest); KillPrefBlanks(Dest);
+ SrcFile=fopen(Dest,"r");
+ if (SrcFile==Nil)
+ BEGIN
+ perror(Dest); exit(2);
+ END
+ GetLine(Dest);
+ END
+ if ((feof(SrcFile)) AND (IncList!=Nil))
+ BEGIN
+ fclose(SrcFile);
+ OneFile=IncList; IncList=OneFile->Next;
+ SrcFile=OneFile->Contents; free(OneFile);
+ END
+END
+
+/*****************************************************************************/
+
+ static void SynError(char *LinePart)
+BEGIN
+ fprintf(stderr,"syntax error : %s\n",LinePart); exit(10);
+END
+
+/*---------------------------------------------------------------------------*/
+
+ static void Process_LANGS(char *Line)
+BEGIN
+ char NLine[1024],*p,*p2,*p3,*end,z,Part[1024];
+ PMsgCat PCat;
+ int num;
+
+ strmaxcpy(NLine,Line,1024);
+ KillPrefBlanks(NLine); KillPostBlanks(NLine);
+
+ p=NLine; z=0;
+ while (*p!='\0')
+ BEGIN
+ for (; ((*p!='\0') AND (NOT isspace((unsigned int) *p))); p++);
+ for (; ((*p!='\0') AND (isspace((unsigned int) *p))); p++);
+ z++;
+ END
+
+ MsgCats=(PMsgCat) malloc(sizeof(TMsgCat)*(CatCount=z)); p=NLine;
+ for (z=0,PCat=MsgCats; z<CatCount; z++,PCat++)
+ BEGIN
+ PCat->Messages=Nil;
+ PCat->TotLength=0;
+ PCat->CtryCodeCnt=0;
+ for (p2=p; ((*p2!='\0') AND (NOT isspace((unsigned int) *p2))); p2++);
+ if (*p2=='\0') strcpy(Part,p);
+ else
+ BEGIN
+ *p2='\0'; strcpy(Part,p);
+ for (p=p2+1; ((*p!='\0') AND (isspace((unsigned int) *p2))); p++);
+ END
+ if (Part[strlen(Part)-1]!=')') SynError(Part); Part[strlen(Part)-1]='\0';
+ p2=strchr(Part,'(');
+ if (p2==Nil) SynError(Part); *p2='\0';
+ PCat->CtryName=strdup(Part); p2++;
+ do
+ BEGIN
+ for (p3=p2; ((*p3!='\0') AND (*p3!=',')); p3++);
+ switch (*p3)
+ BEGIN
+ case '\0':
+ num=strtol(p2,&end,10); p2=p3; break;
+ case ',':
+ *p3='\0'; num=strtol(p2,&end,10); p2=p3+1; break;
+ default:
+ num=0;
+ END
+ if (*end!='\0') SynError("numeric format");
+ PCat->CtryCodes=(PCat->CtryCodeCnt==0) ?
+ (LongInt *) malloc(sizeof(LongInt)) :
+ (LongInt *) realloc(PCat->CtryCodes,sizeof(LongInt)*(PCat->CtryCodeCnt+1));
+ PCat->CtryCodes[PCat->CtryCodeCnt++]=num;
+ END
+ while (*p2!='\0');
+ END
+END
+
+ static void Process_DEFAULT(char *Line)
+BEGIN
+ PMsgCat z;
+
+ if (CatCount==0) SynError("DEFAULT before LANGS");
+ KillPrefBlanks(Line); KillPostBlanks(Line);
+ for (z=MsgCats; z<MsgCats+CatCount; z++) if (strcasecmp(z->CtryName,Line)==0) break;
+ if (z>=MsgCats+CatCount) SynError("unknown country name in DEFAULT");
+ DefCat=z-MsgCats;
+END
+
+ static void Process_MESSAGE(char *Line)
+BEGIN
+ char Msg[4096];
+ String OneLine;
+ int l;
+ PMsgCat z;
+ TransRec *PRec;
+ char *pos;
+ PMsgList List;
+ Boolean Cont;
+
+ KillPrefBlanks(Line); KillPostBlanks(Line);
+ if (HFile!=Nil) fprintf(HFile,"#define Num_%s %d\n",Line,MsgCounter);
+ MsgCounter++;
+
+ for (z=MsgCats; z<MsgCats+CatCount; z++)
+ BEGIN
+ *Msg='\0';
+ do
+ BEGIN
+ GetLine(OneLine); KillPrefBlanks(OneLine); KillPostBlanks(OneLine);
+ l=strlen(OneLine);
+ if ((Cont=(OneLine[l-1]=='\\')))
+ BEGIN
+ OneLine[l-1]='\0'; KillPostBlanks(OneLine); l=strlen(OneLine);
+ END
+ if (*OneLine!='"') SynError(OneLine);
+ if (OneLine[l-1]!='"') SynError(OneLine); OneLine[l-1]='\0';
+ strmaxcat(Msg,OneLine+1,4095);
+ END
+ while (Cont);
+ for (PRec=TransRecs; PRec->AbbString!=Nil; PRec++)
+ while ((pos=strstr(Msg,PRec->AbbString))!=Nil)
+ BEGIN
+ strcpy(pos,pos+strlen(PRec->AbbString)-1);
+ *pos= *PRec->Character;
+ END
+ List=(PMsgList) malloc(sizeof(TMsgList));
+ List->Next=Nil;
+ List->Position=z->TotLength;
+ List->Contents=strdup(Msg);
+ if (z->Messages==Nil) z->Messages=List;
+ else z->LastMessage->Next=List;
+ z->LastMessage=List;
+ z->TotLength+=strlen(Msg)+1;
+ END
+END
+
+/*---------------------------------------------------------------------------*/
+
+ int main(int argc, char **argv)
+BEGIN
+ char Line[1024],Cmd[1024],*p,Save;
+ PMsgCat z;
+ TMsgCat TmpCat;
+ PMsgList List;
+ int c;
+ time_t stamp;
+ LongInt Id1,Id2;
+ LongInt RunPos,StrPos;
+
+ endian_init(); strutil_init();
+
+ if ((argc<3) OR (argc>4))
+ BEGIN
+ fprintf(stderr,"usage: %s <input resource file> <output msg file> [header file]\n",*argv);
+ exit(1);
+ END
+
+ SrcFile=fopen(argv[1],"r");
+ if (SrcFile==Nil)
+ BEGIN
+ perror(argv[1]); exit(2);
+ END
+
+ if (argc==4)
+ BEGIN
+ HFile=fopen(argv[3],"w");
+ if (HFile==Nil)
+ BEGIN
+ perror(argv[3]); exit(3);
+ END
+ IncSym=strdup(argv[3]);
+ for (p=IncSym; *p!='\0'; p++)
+ if (isalpha(((unsigned int) *p)&0xff)) *p=toupper(*p);
+ else *p='_';
+ END
+ else HFile=Nil;
+
+ stamp=GetFileTime(argv[1]); Id1=stamp&0x7fffffff;
+ Id2=0;
+ for (c=0; c<min(strlen(argv[1]),4); c++)
+ Id2=(Id2<<8)+((Byte) argv[1][c]);
+ if (HFile!=Nil)
+ BEGIN
+ fprintf(HFile,"#ifndef %s\n",IncSym);
+ fprintf(HFile,"#define %s\n",IncSym);
+ fprintf(HFile,"#define MsgId1 %ld\n",(long) Id1);
+ fprintf(HFile,"#define MsgId2 %ld\n",(long) Id2);
+ END
+
+ MsgCounter=CatCount=0; MsgCats=Nil; DefCat= -1;
+ while (NOT feof(SrcFile))
+ BEGIN
+ GetLine(Line); KillPrefBlanks(Line); KillPostBlanks(Line);
+ if ((*Line!=';') AND (*Line!='#') AND (*Line!='\0'))
+ BEGIN
+ for (p=Line; ((NOT isspace((unsigned int) *p)) AND (*p!='\0')); p++);
+ Save= *p; *p='\0'; strmaxcpy(Cmd,Line,1024); *p=Save; strcpy(Line,p);
+ if (strcasecmp(Cmd,"LANGS")==0) Process_LANGS(Line);
+ else if (strcasecmp(Cmd,"DEFAULT")==0) Process_DEFAULT(Line);
+ else if (strcasecmp(Cmd,"MESSAGE")==0) Process_MESSAGE(Line);
+ END
+ END
+
+ fclose(SrcFile);
+ if (HFile!=Nil)
+ BEGIN
+ fprintf(HFile,"#endif /* #ifndef %s */\n",IncSym);
+ fclose(HFile);
+ END
+
+ MsgFile=fopen(argv[2],OPENWRMODE);
+ if (MsgFile==Nil)
+ BEGIN
+ perror(argv[2]); exit(4);
+ END
+
+ /* Magic-String */
+
+ fwrite(IdentString,1,strlen(IdentString),MsgFile);
+ Write4(MsgFile,&Id1); Write4(MsgFile,&Id2);
+
+ /* Default nach vorne */
+
+ if (DefCat>0)
+ BEGIN
+ TmpCat=MsgCats[0]; MsgCats[0]=MsgCats[DefCat]; MsgCats[DefCat]=TmpCat;
+ END
+
+ /* Startadressen String-Kataloge berechnen */
+
+ RunPos=ftell(MsgFile)+1;
+ for (z=MsgCats; z<MsgCats+CatCount; z++)
+ RunPos+=(z->HeadLength=strlen(z->CtryName)+1+4+4+(4*z->CtryCodeCnt)+4);
+ for (z=MsgCats; z<MsgCats+CatCount; z++)
+ BEGIN
+ z->FilePos=RunPos; RunPos+=z->TotLength+(4*MsgCounter);
+ END
+
+ /* Country-Records schreiben */
+
+ for (z=MsgCats; z<MsgCats+CatCount; z++)
+ BEGIN
+ fwrite(z->CtryName,1,strlen(z->CtryName)+1,MsgFile);
+ Write4(MsgFile,&(z->TotLength));
+ Write4(MsgFile,&(z->CtryCodeCnt));
+ for (c=0; c<z->CtryCodeCnt; c++) Write4(MsgFile,z->CtryCodes+c);
+ Write4(MsgFile,&(z->FilePos));
+ END
+ Save='\0'; fwrite(&Save,1,1,MsgFile);
+
+ /* Stringtabellen schreiben */
+
+ for (z=MsgCats; z<MsgCats+CatCount; z++)
+ BEGIN
+ for (List=z->Messages; List!=Nil; List=List->Next)
+ BEGIN
+ StrPos=z->FilePos+(4*MsgCounter)+List->Position;
+ Write4(MsgFile,&StrPos);
+ END
+ for (List=z->Messages; List!=Nil; List=List->Next)
+ fwrite(List->Contents,1,strlen(List->Contents)+1,MsgFile);
+ END
+
+ /* faeaedisch... */
+
+ fclose(MsgFile);
+
+ return 0;
+END
+
+#ifdef CKMALLOC
+#undef malloc
+#undef realloc
+
+ void *ckmalloc(size_t s)
+BEGIN
+ void *tmp=malloc(s);
+ if (tmp==NULL)
+ BEGIN
+ fprintf(stderr,"allocation error(malloc): out of memory");
+ exit(255);
+ END
+ return tmp;
+END
+
+ void *ckrealloc(void *p, size_t s)
+BEGIN
+ void *tmp=realloc(p,s);
+ if (tmp==NULL)
+ BEGIN
+ fprintf(stderr,"allocation error(realloc): out of memory");
+ exit(255);
+ END
+ return tmp;
+END
+#endif
+
diff --git a/specchars.h b/specchars.h
new file mode 100644
index 0000000..60db3c6
--- /dev/null
+++ b/specchars.h
@@ -0,0 +1,13 @@
+static unsigned char specchars[][2]=
+ {{0204,0344}, /* adieresis */
+ {0224,0366}, /* odieresis */
+ {0201,0374}, /* udieresis */
+ {0216,0304}, /* Adieresis */
+ {0231,0326}, /* Odieresis */
+ {0232,0334}, /* Udieresis */
+ {0341,0337}, /* ssharp */
+ {0375,0262}, /* 2-exp */
+ {0346,0265}, /* mu */
+ {0205,0340}, /* a graph */
+ {0000,0000}};
+ \ No newline at end of file
diff --git a/stdhandl.c b/stdhandl.c
new file mode 100644
index 0000000..d47c7dd
--- /dev/null
+++ b/stdhandl.c
@@ -0,0 +1,110 @@
+/* stdhandl.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Bereitstellung von fuer AS benoetigten Handle-Funktionen */
+/* */
+/* Historie: 5. 4.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include <sys/stat.h>
+#include "stdhandl.h"
+
+#if defined ( __EMX__ ) || defined ( __IBMC__ )
+#include <os2.h>
+#endif
+
+#ifdef __TURBOC__
+#include <io.h>
+#endif
+
+#ifndef S_ISCHR
+#ifdef __IBMC__
+#define S_ISCHR(m) ((m) & S_IFCHR)
+#else
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+#endif
+#ifndef S_ISREG
+#ifdef __IBMC__
+#define S_ISREG(m) ((m) & S_IFREG)
+#else
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+#endif
+
+TRedirected Redirected;
+
+/* eine Textvariable auf einen der Standardkanaele umbiegen. Die Reduzierung
+ der Puffergroesse auf fast Null verhindert, dass durch Pufferung evtl. Ausgaben
+ durcheinandergehen. */
+
+ static void AssignHandle(FILE **T, Word Num)
+BEGIN
+#ifdef NODUP
+ switch (Num)
+ BEGIN
+ case 0: *T=stdin; break;
+ case 1: *T=stdout; break;
+ case 2: *T=stderr; break;
+ default: *T=Nil;
+ END
+#else
+ *T=fdopen(dup(Num),"w");
+#ifndef _WIN32t
+ setbuf(*T,Nil);
+#endif
+#endif
+END
+
+/* Eine Datei unter Beruecksichtigung der Standardkanaele oeffnen */
+
+ void RewriteStandard(FILE **T, String Path)
+BEGIN
+ if ((strlen(Path)==2) AND (Path[0]=='!') AND (Path[1]>='0') AND (Path[1]<='2'))
+ AssignHandle(T,Path[1]-'0');
+ else *T=fopen(Path,"w");
+END
+
+ void stdhandl_init(void)
+BEGIN
+#ifdef __EMX__
+ ULONG HandType,DevAttr;
+
+#else
+#ifdef __TURBOC__
+ int HandErg;
+
+#else
+ struct stat stdout_stat;
+
+#endif
+#endif
+
+ /* wohin zeigt die Standardausgabe ? */
+
+#ifdef __EMX__
+ DosQueryHType(1,&HandType,&DevAttr);
+ if ((HandType & 0xff)==FHT_DISKFILE) Redirected=RedirToFile;
+ else if ((DevAttr & 2)==0) Redirected=RedirToDevice;
+ else Redirected=NoRedir;
+
+#else
+#ifdef __TURBOC__
+ HandErg=ioctl(1,0x00);
+ if ((HandErg & 2)==2) Redirected=NoRedir;
+ else if ((HandErg & 0x8000)==0) Redirected=RedirToFile;
+ else Redirected=RedirToDevice;
+
+#else
+ fstat(fileno(stdout),&stdout_stat);
+ if (S_ISREG(stdout_stat.st_mode)) Redirected=RedirToFile;
+ else if (S_ISCHR(stdout_stat.st_mode)) Redirected=RedirToDevice;
+ else Redirected=NoRedir;
+
+#endif
+#endif
+END
diff --git a/stdhandl.h b/stdhandl.h
new file mode 100644
index 0000000..3906065
--- /dev/null
+++ b/stdhandl.h
@@ -0,0 +1,21 @@
+/* stdhandl.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Bereitstellung von fuer AS benoetigten Handle-Funktionen */
+/* */
+/* Historie: 5. 4.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+typedef enum {NoRedir,RedirToDevice,RedirToFile} TRedirected; /* Umleitung von Handles */
+
+#define NumStdIn 0
+#define NumStdOut 1
+#define NumStdErr 2
+
+extern TRedirected Redirected;
+
+extern void RewriteStandard(FILE **T, char *Path);
+
+extern void stdhandl_init(void);
diff --git a/stdinc.h b/stdinc.h
new file mode 100644
index 0000000..70d2fe3
--- /dev/null
+++ b/stdinc.h
@@ -0,0 +1,45 @@
+/* stdinc.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* globaler Einzug immer benoetigter includes */
+/* */
+/* Historie: 21. 5.1996 min/max */
+/* 11. 5.1997 DOS-Anpassungen */
+/* */
+/*****************************************************************************/
+
+#include <stdio.h>
+#ifndef __MUNIX__
+#include <stdlib.h>
+#endif
+#if !defined ( __MSDOS__ ) && !defined( __IBMC__ )
+#include <unistd.h>
+#endif
+#include <math.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifdef __MSDOS__
+#include <alloc.h>
+#else
+#include <memory.h>
+#ifndef __FreeBSD__
+#include <malloc.h>
+#endif
+#endif
+
+#include "pascstyle.h"
+#include "datatypes.h"
+#include "chardefs.h"
+
+#ifndef min
+#define min(a,b) ((a<b)?(a):(b))
+#endif
+#ifndef max
+#define max(a,b) ((a>b)?(a):(b))
+#endif
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932385E0
+#endif
+
diff --git a/stringlists.c b/stringlists.c
new file mode 100644
index 0000000..8b2092c
--- /dev/null
+++ b/stringlists.c
@@ -0,0 +1,151 @@
+/* stringlists.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Implementation von String-Listen */
+/* */
+/* Historie: 5. 4.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+#include "strutil.h"
+#include "stringlists.h"
+
+ void InitStringList(StringList *List)
+BEGIN
+ *List=Nil;
+END
+
+ void ClearStringEntry(StringRecPtr *Elem)
+BEGIN
+ free((*Elem)->Content); free(*Elem); *Elem=Nil;
+END
+
+ void ClearStringList(StringList *List)
+BEGIN
+ StringRecPtr Hilf;
+
+ while (*List!=Nil)
+ BEGIN
+ Hilf=(*List); *List=(*List)->Next;
+ ClearStringEntry(&Hilf);
+ END
+END
+
+ void AddStringListFirst(StringList *List, char *NewStr)
+BEGIN
+ StringRecPtr Neu;
+
+ Neu=(StringRecPtr) malloc(sizeof(StringRec));
+ Neu->Content=strdup(NewStr);
+ Neu->Next=(*List);
+ *List=Neu;
+END
+
+ void AddStringListLast(StringList *List, char *NewStr)
+BEGIN
+ StringRecPtr Neu,Lauf;
+
+ Neu=(StringRecPtr) malloc(sizeof(StringRec));
+ Neu->Content=strdup(NewStr); Neu->Next=Nil;
+ if (*List==Nil) *List=Neu;
+ else
+ BEGIN
+ Lauf=(*List); while (Lauf->Next!=Nil) Lauf=Lauf->Next;
+ Lauf->Next=Neu;
+ END
+END
+
+ void RemoveStringList(StringList *List, char *OldStr)
+BEGIN
+ StringRecPtr Lauf,Hilf;
+
+ if (*List==Nil) return;
+ if (strcmp((*List)->Content,OldStr)==0)
+ BEGIN
+ Hilf=(*List); *List=(*List)->Next; ClearStringEntry(&Hilf);
+ END
+ else
+ BEGIN
+ Lauf=(*List);
+ while ((Lauf->Next!=Nil) AND (strcmp(Lauf->Next->Content,OldStr)!=0)) Lauf=Lauf->Next;
+ if (Lauf->Next!=Nil)
+ BEGIN
+ Hilf=Lauf->Next; Lauf->Next=Hilf->Next; ClearStringEntry(&Hilf);
+ END
+ END
+END
+
+ char *GetStringListFirst(StringList List, StringRecPtr *Lauf)
+BEGIN
+ static char *Dummy="",*tmp;
+
+ *Lauf=List;
+ if (*Lauf==Nil) return Dummy;
+ else
+ BEGIN
+ tmp=(*Lauf)->Content;
+ *Lauf=(*Lauf)->Next;
+ return tmp;
+ END
+END
+
+ char *GetStringListNext(StringRecPtr *Lauf)
+BEGIN
+ static char *Dummy="",*tmp;
+
+ if (*Lauf==Nil) return Dummy;
+ else
+ BEGIN
+ tmp=(*Lauf)->Content;
+ *Lauf=(*Lauf)->Next;
+ return tmp;
+ END
+END
+
+ char *GetAndCutStringList(StringList *List)
+BEGIN
+ StringRecPtr Hilf;
+ static String Result;
+
+ if (*List==Nil) Result[0]='\0';
+ else
+ BEGIN
+ Hilf=(*List); *List=(*List)->Next;
+ strmaxcpy(Result,Hilf->Content,255);
+ free(Hilf->Content); free(Hilf);
+ END
+ return Result;
+END
+
+ Boolean StringListEmpty(StringList List)
+BEGIN
+ return (List==Nil);
+END
+
+ StringList DuplicateStringList(StringList Src)
+BEGIN
+ StringRecPtr Lauf;
+ StringList Dest;
+
+ InitStringList(&Dest);
+ if (Src!=Nil)
+ BEGIN
+ AddStringListLast(&Dest,GetStringListFirst(Src,&Lauf));
+ while (Lauf!=Nil)
+ AddStringListLast(&Dest,GetStringListNext(&Lauf));
+ END
+ return Dest;
+END
+
+ Boolean StringListPresent(StringList List, char *Search)
+BEGIN
+ while ((List!=Nil) AND (strcmp(List->Content,Search)!=0)) List=List->Next;
+ return (List!=Nil);
+END
+
+ void stringlists_init(void)
+BEGIN
+END
diff --git a/stringlists.h b/stringlists.h
new file mode 100644
index 0000000..eac7c14
--- /dev/null
+++ b/stringlists.h
@@ -0,0 +1,43 @@
+/* stringlists.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Verwaltung von String-Listen */
+/* */
+/* Historie: 4. 5.1996 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+typedef struct _StringRec
+ {
+ struct _StringRec *Next;
+ char *Content;
+ } StringRec,*StringRecPtr;
+typedef StringRecPtr StringList;
+
+extern void InitStringList(StringList *List);
+
+extern void ClearStringEntry(StringRecPtr *Elem);
+
+extern void ClearStringList(StringList *List);
+
+extern void AddStringListFirst(StringList *List, char *NewStr);
+
+extern void AddStringListLast(StringList *List, char *NewStr);
+
+extern void RemoveStringList(StringList *List, char *OldStr);
+
+extern char *GetStringListFirst(StringList List, StringRecPtr *Lauf);
+
+extern char *GetStringListNext(StringRecPtr *Lauf);
+
+extern char *GetAndCutStringList(StringList *List);
+
+extern Boolean StringListEmpty(StringList List);
+
+extern StringList DuplicateStringList(StringList Src);
+
+extern Boolean StringListPresent(StringList List, char *Search);
+
+
+extern void stringlists_init(void);
diff --git a/strutil.c b/strutil.c
new file mode 100644
index 0000000..2135723
--- /dev/null
+++ b/strutil.c
@@ -0,0 +1,461 @@
+/* strutil.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* haeufig benoetigte String-Funktionen */
+/* */
+/* Historie: 5. 5.1996 Grundsteinlegung */
+/* 13. 8.1997 KillBlanks-Funktionen aus asmsub.c heruebergenommen */
+/* 29. 8.1998 sprintf-Emulation */
+/* 17. 4.1999 strcasecmp gegen Nullzeiger geschuetzt */
+/* 30. 5.1999 ConstLongInt akzeptiert auf 0x fuer Hex-Zahlen */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <ctype.h>
+#include <string.h>
+
+#include "strutil.h"
+#undef strlen /* VORSICHT, Rekursion!!! */
+#ifdef BROKEN_SPRINTF
+#undef sprintf
+#endif
+
+Boolean HexLowerCase; /* Hex-Konstanten mit Kleinbuchstaben */
+
+/*--------------------------------------------------------------------------*/
+/* eine bestimmte Anzahl Leerzeichen liefern */
+
+ char *Blanks(int cnt)
+BEGIN
+ static char *BlkStr=" ";
+
+ if (cnt<0) cnt=0;
+
+ return BlkStr+(strlen(BlkStr)-cnt);
+END
+
+
+/****************************************************************************/
+/* eine Integerzahl in eine Hexstring umsetzen. Weitere vordere Stellen als */
+/* Nullen */
+
+#define BufferCnt 8
+
+ char *HexString(LargeWord i, int Stellen)
+BEGIN
+ static ShortString h[BufferCnt];
+ static int z = 0;
+ LargeWord digit;
+ char *ptr;
+
+ if (Stellen > sizeof(ShortString) - 1)
+ Stellen = sizeof(ShortString) - 1;
+
+ ptr = h[z] + sizeof(ShortString) - 1;
+ *ptr = '\0';
+ do
+ BEGIN
+ digit = i & 15;
+ if (digit < 10)
+ *(--ptr) = digit + '0';
+ else if (HexLowerCase)
+ *(--ptr) = digit - 10 + 'a';
+ else
+ *(--ptr) = digit - 10 + 'A';
+ i = i >> 4;
+ Stellen--;
+ END
+ while ((Stellen > 0) OR (i != 0));
+
+ z = (z + 1) % BufferCnt;
+
+ return ptr;
+END
+
+ char *SysString(LargeWord i, LargeWord System, int Stellen)
+BEGIN
+ static ShortString h[BufferCnt];
+ static int z = 0;
+ LargeWord digit;
+ char *ptr;
+
+ if (Stellen > sizeof(ShortString) - 1)
+ Stellen = sizeof(ShortString) - 1;
+
+ ptr = h[z] + sizeof(ShortString) - 1;
+ *ptr = '\0';
+ do
+ BEGIN
+ digit = i % System;
+ if (digit < 10)
+ *(--ptr) = digit + '0';
+ else if (HexLowerCase)
+ *(--ptr) = digit - 10 + 'a';
+ else
+ *(--ptr) = digit - 10 + 'A';
+ i /= System;
+ Stellen--;
+ END
+ while ((Stellen > 0) OR (i != 0));
+
+ z = (z + 1) % BufferCnt;
+
+ return ptr;
+END
+
+/*--------------------------------------------------------------------------*/
+/* dito, nur vorne Leerzeichen */
+
+ char *HexBlankString(LargeWord i, Byte Stellen)
+BEGIN
+ static String temp;
+
+ strmaxcpy(temp,HexString(i,0),255);
+ if (strlen(temp)<Stellen) strmaxprep(temp,Blanks(Stellen-strlen(temp)),255);
+ return temp;
+END
+
+/*---------------------------------------------------------------------------*/
+/* Da manche Systeme (SunOS) Probleme mit der Ausgabe extra langer Ints
+ haben, machen wir das jetzt zu Fuss :-( */
+
+ char *LargeString(LargeInt i)
+BEGIN
+ Boolean SignFlag=False;
+ static String s;
+ String tmp;
+ char *p,*p2;
+
+ if (i<0)
+ BEGIN
+ i=(-i); SignFlag=True;
+ END
+
+ p=tmp;
+ do
+ BEGIN
+ *(p++)='0'+(i%10);
+ i/=10;
+ END
+ while (i>0);
+
+ p2=s; if (SignFlag) *(p2++)='-';
+ while (p>tmp) *(p2++)=(*(--p));
+ *p2='\0'; return s;
+END
+
+
+/*---------------------------------------------------------------------------*/
+/* manche haben's nicht... */
+
+#if defined(NEEDS_STRDUP) || defined(CKMALLOC)
+#ifdef CKMALLOC
+ char *mystrdup(char *s)
+BEGIN
+#else
+ char *strdup(char *s)
+BEGIN
+#endif
+ char *ptr=(char *) malloc(strlen(s)+1);
+#ifdef CKMALLOC
+ if (ptr==Nil)
+ BEGIN
+ fprintf(stderr,"strdup: out of memory?\n"); exit(255);
+ END
+#endif
+ if (ptr!=0) strcpy(ptr,s);
+ return ptr;
+END
+#endif
+
+#ifdef NEEDS_CASECMP
+ int strcasecmp(const char *src1, const char *src2)
+BEGIN
+ if (src1 == NULL) src1 = "";
+ if (src2 == NULL) src2 = "";
+ while (toupper(*src1)==toupper(*src2))
+ BEGIN
+ if ((NOT *src1) AND (NOT *src2)) return 0;
+ src1++; src2++;
+ END
+ return ((int) toupper(*src1))-((int) toupper(*src2));
+END
+
+ int strncasecmp(const char *src1, const char *src2, int len)
+BEGIN
+ if (src1 == NULL) src1 = "";
+ if (src2 == NULL) src2 = "";
+ while (toupper(*src1)==toupper(*src2))
+ BEGIN
+ if (--len==0) return 0;
+ if ((NOT *src1) AND (NOT *src2)) return 0;
+ src1++; src2++;
+ END
+ return ((int) toupper(*src1))-((int) toupper(*src2));
+END
+#endif
+
+#ifdef NEEDS_STRSTR
+ char *strstr(char *haystack, char *needle)
+BEGIN
+ int lh=strlen(haystack), ln=strlen(needle);
+ int z;
+ char *p;
+
+ for (z=0; z<=lh-ln; z++)
+ if (strncmp(p=haystack+z,needle,ln)==0) return p;
+ return Nil;
+END
+#endif
+
+#ifdef BROKEN_SPRINTF
+#include <varargs.h>
+
+ int mysprintf(va_alist) va_dcl
+BEGIN
+ va_list pvar;
+ char *form,*dest,*run;
+
+ va_start(pvar);
+ dest=va_arg(pvar,char*);
+ form=va_arg(pvar,char*);
+ vsprintf(dest,form,pvar);
+
+ for (run=dest; *run!='\0'; run++);
+ return run-dest;
+END
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* wenn man mit unsigned arbeitet, gibt das boese Seiteneffekte bei direkter
+ Arithmetik mit strlen... */
+
+ signed int strslen(const char *s)
+BEGIN
+ return strlen(s);
+END
+
+/*---------------------------------------------------------------------------*/
+/* das originale strncpy plaettet alle ueberstehenden Zeichen mit Nullen */
+
+ void strmaxcpy(char *dest, const char *src, int Max)
+BEGIN
+ int cnt=strlen(src);
+
+ if (cnt>Max) cnt=Max;
+ memcpy(dest,src,cnt); dest[cnt]='\0';
+END
+
+/*---------------------------------------------------------------------------*/
+/* einfuegen, mit Begrenzung */
+
+ void strmaxcat(char *Dest, const char *Src, int MaxLen)
+BEGIN
+ int TLen=strlen(Src),DLen=strlen(Dest);
+
+ if (TLen>MaxLen-DLen) TLen=MaxLen-DLen;
+ if (TLen>0)
+ BEGIN
+ memcpy(Dest+DLen,Src,TLen);
+ Dest[DLen+TLen]='\0';
+ END
+END
+
+ void strprep(char *Dest, const char *Src)
+BEGIN
+ memmove(Dest+strlen(Src),Dest,strlen(Dest)+1);
+ memmove(Dest,Src,strlen(Src));
+END
+
+ void strmaxprep(char *Dest, const char *Src, int MaxLen)
+BEGIN
+ int RLen;
+
+ RLen=strlen(Src); if (RLen>MaxLen-strlen(Dest)) RLen=MaxLen-strlen(Dest);
+ memmove(Dest+RLen,Dest,strlen(Dest)+1);
+ memmove(Dest,Src,RLen);
+END
+
+ void strins(char *Dest, const char *Src, int Pos)
+BEGIN
+ memmove(Dest+Pos+strlen(Src),Dest+Pos,strlen(Dest)+1-Pos);
+ memmove(Dest+Pos,Src,strlen(Src));
+END
+
+ void strmaxins(char *Dest, const char *Src, int Pos, int MaxLen)
+BEGIN
+ int RLen;
+
+ RLen=strlen(Src); if (RLen>MaxLen-strlen(Dest)) RLen=MaxLen-strlen(Dest);
+ memmove(Dest+Pos+RLen,Dest+Pos,strlen(Dest)+1-Pos);
+ memmove(Dest+Pos,Src,RLen);
+END
+
+/*---------------------------------------------------------------------------*/
+/* Bis Zeilenende lesen */
+
+ void ReadLn(FILE *Datei, char *Zeile)
+BEGIN
+/* int Zeichen='\0';
+ char *Run=Zeile;
+
+ while ((Zeichen!='\n') AND (Zeichen!=EOF) AND (!feof(Datei)))
+ BEGIN
+ Zeichen=fgetc(Datei);
+ if (Zeichen!=26) *Run++=Zeichen;
+ END
+
+ if ((Run>Zeile) AND ((Zeichen==EOF) OR (Zeichen=='\n'))) Run--;
+ if ((Run>Zeile) AND (Run[-1]==13)) Run--;
+ *Run++='\0';*/
+
+ char *ptr;
+ int l;
+
+ *Zeile='\0'; ptr=fgets(Zeile,256,Datei);
+ if ((ptr==Nil) AND (ferror(Datei)!=0)) *Zeile='\0';
+ l=strlen(Zeile);
+ if ((l>0) AND (Zeile[l-1]=='\n')) Zeile[--l]='\0';
+ if ((l>0) AND (Zeile[l-1]=='\r')) Zeile[--l]='\0';
+ if ((l>0) AND (Zeile[l-1]==26)) Zeile[--l]='\0';
+END
+
+/*--------------------------------------------------------------------*/
+/* Zahlenkonstante umsetzen: $ hex, % binaer, @ oktal */
+/* inp: Eingabezeichenkette */
+/* erg: Zeiger auf Ergebnis-Longint */
+/* liefert TRUE, falls fehlerfrei, sonst FALSE */
+
+ LongInt ConstLongInt(const char *inp, Boolean *err)
+BEGIN
+ static char Prefixes[4]={'$','@','%','\0'}; /* die moeglichen Zahlensysteme */
+ static LongInt Bases[3]={16,8,2}; /* die dazugehoerigen Basen */
+ LongInt erg;
+ LongInt Base=10,z,val,vorz=1; /* Vermischtes */
+
+ /* eventuelles Vorzeichen abspalten */
+
+ if (*inp == '-')
+ BEGIN
+ vorz = (-1); inp++;
+ END
+
+ /* Sonderbehandlung 0x --> $ */
+
+ if ((strlen(inp) >= 2) && (*inp == '0') && (toupper(inp[1]) == 'X'))
+ BEGIN
+ inp += 2;
+ Base = 16;
+ END
+
+ /* Jetzt das Zahlensystem feststellen. Vorgabe ist dezimal, was
+ sich aber durch den Initialwert von Base jederzeit aendern
+ laesst. Der break-Befehl verhindert, dass mehrere Basenzeichen
+ hintereinander eingegeben werden koennen */
+
+ else
+ for (z = 0; z < 3; z++)
+ if (*inp == Prefixes[z])
+ BEGIN
+ Base = Bases[z]; inp++; break;
+ END
+
+ /* jetzt die Zahlenzeichen der Reihe nach durchverwursten */
+
+ erg=0; *err=False;
+ for(; *inp != '\0'; inp++)
+ BEGIN
+ /* Ziffern 0..9 ergeben selbiges */
+
+ if ((*inp>='0') AND (*inp<='9')) val=(*inp)-'0';
+
+ /* Grossbuchstaben fuer Hexziffern */
+
+ else if ((*inp>='A') AND (*inp<='F')) val=(*inp)-'A'+10;
+
+ /* Kleinbuchstaben nicht vergessen...! */
+
+ else if ((*inp>='a') AND (*inp<='f')) val=(*inp)-'a'+10;
+
+ /* alles andere ist Schrott */
+
+ else break;
+
+ /* entsprechend der Basis zulaessige Ziffer ? */
+
+ if (val>=Base) break;
+
+ /* Zahl linksschieben, zusammenfassen, naechster bitte */
+
+ erg=erg*Base+val;
+ END
+
+ /* bis zum Ende durchgelaufen ? */
+
+ if (*inp == '\0')
+ BEGIN
+ /* Vorzeichen beruecksichtigen */
+
+ erg*=vorz;
+ *err=True;
+ END
+
+ return erg;
+END
+
+/*--------------------------------------------------------------------------*/
+/* alle Leerzeichen aus einem String loeschen */
+
+ void KillBlanks(char *s)
+BEGIN
+ char *z,*dest;
+ Boolean InHyp=False,InQuot=False;
+
+ dest=s;
+ for (z=s; *z!='\0'; z++)
+ BEGIN
+ switch (*z)
+ BEGIN
+ case '\'': if (NOT InQuot) InHyp=NOT InHyp; break;
+ case '"': if (NOT InHyp) InQuot=NOT InQuot; break;
+ END
+ if ((NOT isspace((unsigned char)*z)) OR (InHyp) OR (InQuot)) *(dest++)=(*z);
+ END
+ *dest='\0';
+END
+
+/*--------------------------------------------------------------------------*/
+/* fuehrende Leerzeichen loeschen */
+
+ void KillPrefBlanks(char *s)
+BEGIN
+ char *z=s;
+
+ while ((*z!='\0') AND (isspace((unsigned char)*z))) z++;
+ if (z!=s) strcpy(s,z);
+END
+
+/*--------------------------------------------------------------------------*/
+/* anhaengende Leerzeichen loeschen */
+
+ void KillPostBlanks(char *s)
+BEGIN
+ char *z=s+strlen(s)-1;
+
+ while ((z>=s) AND (isspace((unsigned char)*z))) *(z--)='\0';
+END
+
+/*--------------------------------------------------------------------------*/
+
+ int strqcmp(const char *s1, const char *s2)
+BEGIN
+ int erg=(*s1)-(*s2);
+ return (erg!=0) ? erg : strcmp(s1,s2);
+END
+
+ void strutil_init(void)
+BEGIN
+ HexLowerCase=False;
+END
diff --git a/strutil.h b/strutil.h
new file mode 100644
index 0000000..c46b02e
--- /dev/null
+++ b/strutil.h
@@ -0,0 +1,70 @@
+/* strutil.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* haeufig benoetigte String-Funktionen */
+/* */
+/* Historie: 5. 5.1996 Grundsteinlegung */
+/* 13. 8.1997 KillBlanks-Funktionen aus asmsub.c heruebergenommen */
+/* 29. 8.1998 sprintf-Emulation */
+/* 29. 5.1999 SysString */
+/* */
+/*****************************************************************************/
+
+extern Boolean HexLowerCase;
+
+extern char *Blanks(int cnt);
+
+extern char *HexString(LargeWord i, int Stellen);
+
+extern char *SysString(LargeWord i, LargeWord System, int Stellen);
+
+extern char *HexBlankString(LargeWord i, Byte Stellen);
+
+extern char *LargeString(LargeInt i);
+
+#ifdef NEEDS_STRDUP
+extern char *strdup(char *s);
+#endif
+#ifdef CKMALLOC
+#define strdup(s) mystrdup(s)
+extern char *mystrdup(char *s);
+#endif
+
+#ifdef NEEDS_CASECMP
+extern int strcasecmp(const char *src1, const char *src2);
+extern int strncasecmp(const char *src1, const char *src2, int maxlen);
+#endif
+
+#ifdef NEEDS_STRSTR
+extern char *strstr(char *haystack, char *needle);
+#endif
+
+#ifdef BROKEN_SPRINTF
+#define sprintf mysprintf
+extern int mysprintf();
+#endif
+
+#undef strlen
+#define strlen(s) strslen(s)
+extern signed int strslen(const char *s);
+extern void strmaxcpy(char *dest, const char *src, int Max);
+extern void strmaxcat(char *Dest, const char *Src, int MaxLen);
+extern void strprep(char *Dest, const char *Src);
+extern void strmaxprep(char *Dest, const char *Src, int MaxLen);
+extern void strins(char *Dest, const char *Src, int Pos);
+extern void strmaxins(char *Dest, const char *Src, int Pos, int MaxLen);
+
+extern void ReadLn(FILE *Datei, char *Zeile);
+
+extern LongInt ConstLongInt(const char *inp, Boolean *err);
+
+extern void KillBlanks(char *s);
+
+extern void KillPrefBlanks(char *s);
+
+extern void KillPostBlanks(char *s);
+
+extern int strqcmp(const char *s1, const char *s2);
+
+extern void strutil_init(void);
diff --git a/sysdefs.h b/sysdefs.h
new file mode 100644
index 0000000..d145cd5
--- /dev/null
+++ b/sysdefs.h
@@ -0,0 +1,774 @@
+/*---------------------------------------------------------------------------*/
+/* unify 68K platforms */
+
+#ifdef __mc68020
+#ifndef __m68k
+#define __m68k
+#endif
+#endif
+
+#ifdef m68000
+#ifndef __m68k
+#define __m68k
+#endif
+#endif
+
+#ifdef __mc68000
+#ifndef __m68k
+#define __m68k
+#endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* ditto for i386 platforms */
+
+/* MSDOS only runs on x86s... */
+
+#ifdef __MSDOS__
+#define __i386
+#endif
+
+/* For IBMC... */
+
+#ifdef _M_I386
+#define __i386
+#endif
+
+#ifdef __i386__
+#ifndef __i386
+#define __i386
+#endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* If the compiler claims to be ANSI, we surely can use prototypes */
+
+#ifdef __STDC__
+#define __PROTOS__
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* just a hack to allow distinguishing SunOS from Solaris on Sparcs... */
+
+#ifdef sparc
+#ifndef __sparc
+#define __sparc
+#endif
+#endif
+
+#ifdef __sparc
+#ifndef __SVR4
+#define __sunos__
+#else
+#define __solaris__
+#endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* similar on Sun 3's... */
+
+#ifdef __m68k
+#ifndef __NetBSD__
+#ifndef __MUNIX__
+#define __sunos__
+#endif
+#endif
+#endif
+
+/*===========================================================================*/
+/* 68K platforms */
+
+#ifdef __m68k
+
+#define ARCHPRNAME "m68k"
+
+/*---------------------------------------------------------------------------*/
+/* SUN/3 with SunOS 4.x:
+
+ see my SunOS quarrels in the Sparc section... */
+
+#ifdef __sunos__
+#define ARCHSYSNAME "sun-sunos"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+#define NEEDS_CASECMP
+#define BROKEN_SPRINTF
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+#ifdef __GNUC__
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#else
+#define NOLONGLONG
+#endif
+#define memmove(s1,s2,len) bcopy(s2,s1,len)
+extern void bcopy();
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* SUN/3 with NetBSD 1.x:
+
+ quite a normal 32-Bit-UNIX system */
+
+#ifdef __NetBSD__
+#define ARCHSYSNAME "sun-netbsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* PCS/Cadmus:
+
+ quite a bare system, lots of work required... */
+
+#ifdef __MUNIX__
+#define ARCHSYSNAME "pcs-munix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+#define NEEDS_CASECMP
+#define NEEDS_STRSTR
+typedef char Integ8;
+typedef unsigned char Card8;
+typedef short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef int Integ32;
+typedef unsigned int Card32;
+#define NOLONGLONG
+#define memmove(s1,s2,len) bcopy(s2,s1,len)
+extern double strtod();
+extern char *getenv();
+#define NO_NLS
+#endif
+/*---------------------------------------------------------------------------*/
+/* Linux/68K:
+
+ quite a normal 32-Bit-UNIX system */
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define NO_NLS
+#endif
+
+#endif /* __m68k */
+
+/*===========================================================================*/
+/* SPARC platforms */
+
+#ifdef __sparc
+
+#define ARCHPRNAME "sparc"
+
+/*---------------------------------------------------------------------------*/
+/* SUN Sparc with SunOS 4.1.x:
+
+ don't try cc, use gcc, it's hopeless without an ANSI-compliant compiler...
+ SunOS does have NLS support, but it does not have D_FMT and T_FMT
+ I should change this ...
+ Though the manual pages claim that memmove and atexit exist, I could not
+ find them in any library :-( Fortunately, bcopy claims to be safe for
+ overlapping arrays, we just have to reverse source and destination pointers.
+ The sources themselves contain a switch to use on_exit instead of atexit
+ (it uses a different callback scheme, so we cannot just make a #define here...)
+ To get rid of most of the messages about missing prototypes, add
+ -D__USE_FIXED_PROTOTYPES__ to your compiler flags!
+ Apart from these few points, one could claim SunOS to be quite a normal
+ 32-bit-UNIX... */
+
+#ifdef __sunos__
+#define ARCHSYSNAME "sun-sunos"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+#ifdef __GNUC__
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#else
+#define NOLONGLONG
+#endif
+#define fpos_t long
+#ifdef __STDC__
+extern void bcopy();
+#endif
+#define memmove(s1,s2,len) bcopy(s2,s1,len)
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* SUN Sparc with Solaris 2.x:
+
+ quite a normal 32-Bit-UNIX system */
+
+#ifdef __solaris__
+#define ARCHSYSNAME "sun-solaris"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* __sparc */
+
+/*===========================================================================*/
+/* Mips platforms */
+
+#ifdef __mips
+
+#define ARCHPRNAME "mips"
+
+/*---------------------------------------------------------------------------*/
+/* R3000 with Ultrix 4.3:
+
+ nl_langinfo prototype is there, but no function in library ?!
+ use long long only if you have gcc, c89 doesn't like them !
+ cc isn't worth trying, believe me! */
+
+#ifdef __ultrix
+#define ARCHSYSNAME "dec-ultrix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+#define NEEDS_STRDUP
+#define BROKEN_SPRINTF
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+#ifdef __GNUC__
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#else
+#define NOLONGLONG
+#endif
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* R2000/3000 with NetBSD 1.2:
+
+ quite a normal 32-Bit-UNIX system */
+
+#ifdef __NetBSD__
+#define ARCHSYSNAME "dec-netbsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* R3000/4x00 with Irix 5.x:
+
+ quite a normal 32-Bit-UNIX system
+ seems also to work with 6.2... */
+
+#ifdef __sgi
+#define ARCHSYSNAME "sgi-irix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* __mips */
+
+/*===========================================================================*/
+/* HP-PA platforms */
+
+#ifdef __hppa
+
+#define ARCHPRNAME "parisc"
+
+/*---------------------------------------------------------------------------*/
+/* HP-PA 1.x with HP-UX: */
+
+#ifdef __hpux
+#define ARCHSYSNAME "hp-hpux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* __hppa */
+
+/*===========================================================================*/
+/* POWER platforms */
+
+#ifdef _POWER
+
+#define ARCHPRNAME "rs6000"
+
+/*---------------------------------------------------------------------------*/
+/* POWER with AIX 4.1: */
+
+#ifdef _AIX
+#define ARCHSYSNAME "ibm-aix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* _POWER */
+
+
+/*===========================================================================*/
+/* VAX platforms */
+
+#ifdef vax
+
+#define ARCHPRNAME "vax"
+
+/*---------------------------------------------------------------------------*/
+/* VAX with Ultrix: */
+
+#ifdef ultrix
+#define ARCHSYSNAME "dec-ultrix"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define VAXFLOAT
+#define NEEDS_STRDUP
+#define NEEDS_CASECMP
+#define BKOKEN_SPRINTF
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+#define NOLONGLONG
+#define NO_NLS
+#endif
+
+#endif
+
+/*===========================================================================*/
+/* DEC Alpha platforms */
+
+#ifdef __alpha
+
+#define ARCHPRNAME "alpha"
+
+/*---------------------------------------------------------------------------*/
+/* DEC Alpha with Digital UNIX and DEC C / GCC:
+
+ Alpha is a 64 bit machine, so we do not need to use extra longs
+ OSF has full NLS support */
+
+#ifdef __osf__
+#define ARCHSYSNAME "dec-osf"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long Integ64;
+typedef unsigned long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* DEC Alpha with Linux and GCC:
+
+ see OSF...
+ NLS still missing...well, my Linux/Alpha is stone-age and still
+ ECOFF-based... */
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long Integ64;
+typedef unsigned long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+#endif /* __alpha */
+
+/*===========================================================================*/
+/* Intel i386 platforms */
+
+#ifdef __i386
+
+#define ARCHPRNAME "i386"
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with Linux and GCC:
+
+ principally, a normal 32-bit *NIX */
+
+#ifdef __linux__
+#define ARCHSYSNAME "unknown-linux"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with FreeBSD and GCC:
+
+ principally, a normal 32-bit *NIX */
+
+#ifdef __FreeBSD__
+#define ARCHSYSNAME "unknown-freebsd"
+#define DEFSMADE
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with WIN32 and Cygnus GCC:
+
+ well, not really a UNIX... */
+
+#ifdef _WIN32
+#define ARCHSYSNAME "unknown-win32"
+#define DEFSMADE
+#define OPENRDMODE "rb"
+#define OPENWRMODE "wb"
+#define OPENUPMODE "rb+"
+#define IEEEFLOAT
+#define PATHSEP '\\'
+#define SPATHSEP "\\"
+#define DIRSEP ';'
+#define SDIRSEP ";"
+/*#define DRSEP ':'
+#define SDRSEP ":"*/
+#define NULLDEV "NUL"
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define NO_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with OS/2 and emx-GCC:
+
+ well, not really a UNIX... */
+
+#ifdef __EMX__
+#define ARCHSYSNAME "unknown-os2"
+#define DEFSMADE
+#define OPENRDMODE "rb"
+#define OPENWRMODE "wb"
+#define OPENUPMODE "rb+"
+#define IEEEFLOAT
+#define PATHSEP '\\'
+#define SPATHSEP "\\"
+#define DIRSEP ';'
+#define SDIRSEP ";"
+#define DRSEP ':'
+#define SDRSEP ":"
+#define NULLDEV "NUL"
+#define NEEDS_CASECMP
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+typedef signed long long Integ64;
+typedef unsigned long long Card64;
+#define HAS64
+#define OS2_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel i386 with OS/2 and IBMC:
+
+well, not really a UNIX... */
+
+#ifdef __IBMC__
+#define DEFSMADE
+#define NODUP
+#define OPENRDMODE "rb"
+#define OPENWRMODE "wb"
+#define OPENUPMODE "rb+"
+#define PATHSEP '\\'
+#define SPATHSEP "\\"
+#define DRSEP ':'
+#define SDRSEP ":"
+#define NULLDEV "NUL"
+#define NEEDS_CASECMP
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed int Integ32;
+typedef unsigned int Card32;
+#define NOLONGLONG
+#define OS2_NLS
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Intel x86 with MS-DOS and Borland-C:
+
+ well, not really a UNIX...
+ assure we get a usable memory model */
+
+#ifdef __MSDOS__
+#ifdef __TURBOC__
+#ifndef __LARGE__
+#error Wrong memory model - use large!
+#endif
+#undef ARCHPRNAME
+#ifdef __DPMI16__
+#define ARCHPRNAME "i286"
+#define ARCHSYSNAME "unknown-dpmi"
+#else
+#define ARCHPRNAME "i86"
+#define ARCHSYSNAME "unknown-msdos"
+#endif
+#define CKMALLOC
+#define DEFSMADE
+#define OPENRDMODE "rb"
+#define OPENWRMODE "wb"
+#define OPENUPMODE "rb+"
+#define IEEEFLOAT
+#define PATHSEP '\\'
+#define SPATHSEP "\\"
+#define DIRSEP ';'
+#define SDIRSEP ";"
+#define DRSEP ':'
+#define SDRSEP ":"
+#define NULLDEV "NUL"
+#define NEEDS_CASECMP
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ16;
+typedef unsigned short Card16;
+#define HAS16
+typedef signed long Integ32;
+typedef unsigned long Card32;
+#define NOLONGLONG
+#define DOS_NLS
+#define __PROTOS__
+#endif
+#endif
+
+#endif /* __i386 */
+
+/*===========================================================================*/
+/* Misc... */
+
+/*---------------------------------------------------------------------------*/
+/* Just for curiosity, it won't work without 16 bit int's... */
+
+#ifdef _CRAYMPP
+#define OPENRDMODE "r"
+#define OPENWRMODE "w"
+#define OPENUPMODE "r+"
+#define IEEEFLOAT
+typedef signed char Integ8;
+typedef unsigned char Card8;
+typedef signed short Integ32;
+typedef unsigned short Card32;
+typedef signed int Integ64;
+typedef unsigned int Card64;
+#define HAS64
+#define LOCALE_NLS
+#endif
+
+/*===========================================================================*/
+/* Post-Processing: check for definition, add defaults */
+
+
+#ifdef DEFSMADE
+#ifndef PATHSEP
+#define PATHSEP '/'
+#define SPATHSEP "/"
+#define DIRSEP ':'
+#define SDIRSEP ":"
+#endif
+#ifndef NULLDEV
+#define NULLDEV "/dev/null"
+#endif
+#else
+#error "your platform so far is not included in AS's header files!"
+#error "please edit sysdefs.h!"
+#endif
+
+#ifdef CKMALLOC
+#define malloc(s) ckmalloc(s)
+#define realloc(p,s) ckrealloc(p,s)
+
+extern void *ckmalloc(size_t s);
+
+extern void *ckrealloc(void *p, size_t s);
+#endif
diff --git a/tests/t_166/asflags b/tests/t_166/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_166/asflags
diff --git a/tests/t_166/t_166.asm b/tests/t_166/t_166.asm
new file mode 100644
index 0000000..d23a52b
--- /dev/null
+++ b/tests/t_166/t_166.asm
@@ -0,0 +1,232 @@
+ cpu 80c167
+ page 0
+ include reg166
+
+ diswdt
+ einit
+ idle
+ nop
+ pwrdn
+ ret
+ reti
+ rets
+ srst
+ srvwdt
+
+targ: jmpr targ
+ jmpr nz,targ
+ jmpr ult,targ
+ jmpr sgt,targ
+ jmpr nv,targ
+ jmpr net,targ
+ callr targ
+
+ jmpa targ
+ jmpa nz,targ
+ jmpa ult,targ
+ jmpa sgt,targ
+ jmpa nv,targ
+ jmpa net,targ
+ calla 1234h
+
+ jmps targ
+ jmps 1,2345h
+ calls targ
+
+ jmpi [r3]
+ jmpi z,[r12]
+ calli nc,[r4]
+
+ jmp 10000h
+ jmp 3ffffh
+ jmp 12345h
+ jmp 80h
+ jmp 2000h
+ jmp [r14]
+
+ call 10000h
+ call 3ffffh
+ call 12345h
+ call z,80h
+ call sle,2000h
+ call nn,[r14]
+
+ add 1234h,r10
+ addb 2345h,0fe00h
+ addc r7,1234h
+ addcb 0fe02h,2345h
+ sub r12,#4
+ subb r5,#200
+ subc 0fe04h,#4
+ subcb 0fe06h,#200
+ cmp r5,r3
+ cmpb rh0,rl0
+ and r1,[r2]
+ andb r5,[r1]
+ or r3,[r3+]
+ xorb r15,[r0+]
+
+ ashr r2,r4
+ rol r5,#4
+ ror r10,r1
+ shl r3,#12
+ shr r15,r0
+
+ band r2.5,r7.14
+ bmov r3.7,0fd08h.5
+ bmovn r7.10,0ff10h.12
+ bcmp r7.14,r2.5
+ bor 0fd08h.5,r3.7
+ bxor 0ff10h.12,r7.10
+ bset r5.2
+ bclr 0ff80h.13
+ bfldl r5,#0c3h,#3ch
+ bfldh 0fd02h,#0c3h,#3ch
+
+ cmpd1 r5,#10
+ cmpd2 r12,#200
+ cmpi1 r9,Targ
+ cmpi2 r14,#(5*4)-7
+
+ cpl r5
+ cplb rh1
+ neg r12
+ negb r10
+
+ div r3
+ divl r7
+ divu r10
+ divlu r0
+
+targ2: jb r5.2,targ2
+ jbc 0fd30h.12,targ2
+ jnb r7.14,targ2
+ jnbs 0ff58h.2,targ2
+
+ mov r2,r5
+ movb r0,rh5
+ mov r4,#2
+ movb r6,#10
+ mov r12,#1234
+ movb r0,#23h
+ mov r0,[r2]
+ movb rl4,[r10]
+ mov r3,[r4+]
+ movb r10,[r7+]
+ mov r1,[r1+300]
+ movb r10,[30+r4-40]
+ mov r12,Targ
+ movb rl2,targ2
+
+ mov 0fe00h,#10
+ movb 0fe02h,#100
+ mov 0fe04h,[r2]
+ movb 0fe06h,[r7]
+ mov 0fe08h,Targ
+ movb 0fe0ah,targ2
+ mov [r4],r3
+ movb [r7],rl5
+ mov [r10],[r2]
+ movb [r14],[r0]
+ mov [r13],[r6+]
+ movb [r14],[r2+]
+ mov [r11],targ2
+ movb [r15],Targ
+ mov [-r4],r2
+ movb [-r15],rh7
+ mov [r6+],[r13]
+ movb [r2+],[r14]
+ mov [r15+20],r4
+ movb [r0-7],rh1
+ mov targ2,[r7]
+ movb Targ,[r4]
+ mov Targ,0fe10h
+ movb targ2,0ff10h
+
+ movbs r10,rh1
+ movbs 0fe04h,targ2
+ movbs targ2,0fe04h
+ movbz r11,rl1
+ movbz 0fe08h,targ2
+ movbz targ2,0fe40h
+
+ mul r12,r15
+ mulu r0,r7
+ prior r2,r4
+
+ pcall r10,targ2
+ pcall 0fe02h,8000h
+
+ push r2
+ pop 0ff20h
+ retp r14
+
+ scxt 0fe20h,#1234h
+ scxt r5,targ2
+
+ trap #10
+ trap #127
+
+;-------------------------------
+; Pipeline-Tests
+
+ mov dpp0,#4
+ assume dpp0:4
+ mov r0,12345h ; DPP0 noch nicht ver„nert
+ mov r0,12345h ; ab hier wieder gut
+ mov dpp0,#0
+ assume dpp0:0
+
+ mov cp,0fc00h
+ mov r5,r3 ; gleich doppelt
+ movb r3,r1
+
+ mov sp,0fd00h ; SP noch in der Pipe
+ pop r4
+ ret
+
+;-------------------------------
+; Bit-Tests
+
+ bset 123h
+tbit bit 0ff80h.4
+
+;-------------------------------
+
+Str equ "PSW+5"
+tmp equ Val(Str)
+
+;-------------------------------
+; Adressierungs-Tests
+
+ atomic #2
+
+ extr #1
+ mov 0f000h,#1234h
+ mov 0fe00h,#1234h
+
+ebit bit 0f100h.4
+sbit bit 0ff00h.4
+
+ extr #1
+ bclr ebit
+ bclr sbit
+
+ extr #1
+ bset 0f1deh.12
+ bset 0ffdeh.12
+
+ extp r5,#1
+ mov r0,0abcdh
+ mov r0,0abcdh
+
+ extpr #4,#1
+ extp #4,#1
+ mov r0,12345h
+ mov r0,12345h
+
+ extsr #1,#1
+ exts #1,#1
+ mov r0,12345h
+ mov r0,12345h
+
diff --git a/tests/t_166/t_166.doc b/tests/t_166/t_166.doc
new file mode 100644
index 0000000..a21d1c6
--- /dev/null
+++ b/tests/t_166/t_166.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application 166 ----------------------------+
+| |
+| This is a (synthetic) test of the 80C166 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_166/t_166.ori b/tests/t_166/t_166.ori
new file mode 100644
index 0000000..0fbb6db
--- /dev/null
+++ b/tests/t_166/t_166.ori
Binary files differ
diff --git a/tests/t_16c5x/asflags b/tests/t_16c5x/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_16c5x/asflags
diff --git a/tests/t_16c5x/t_16c5x.asm b/tests/t_16c5x/t_16c5x.asm
new file mode 100755
index 0000000..805013f
--- /dev/null
+++ b/tests/t_16c5x/t_16c5x.asm
@@ -0,0 +1,45 @@
+ cpu 16c57
+ page 0
+ relaxed on
+
+ clrw
+ nop
+ option
+ sleep
+
+ andlw 12h
+ iorlw 12h
+ movlw 12h
+ retlw 12h
+ xorlw 12h
+
+ addwf 12h
+ andwf 12h,0
+ comf 12h,1
+ decf 12h,w
+ decfsz 12h,f
+ incf 12h
+ incfsz 12h,0
+ iorwf 12h,1
+ movf 12h,w
+ rlf 12h,f
+ rrf 12h
+ subwf 12h,0
+ swapf 12h,1
+ xorwf 12h,w
+
+ bcf 10h,3
+ bsf 17h,5
+ btfsc 12h,7
+ btfss 08h,1
+
+ clrf 12h
+ movwf 12h
+
+ tris 5
+ tris 6
+ tris 7
+
+ call 234h
+ goto 123h
+
diff --git a/tests/t_16c5x/t_16c5x.doc b/tests/t_16c5x/t_16c5x.doc
new file mode 100644
index 0000000..e75d915
--- /dev/null
+++ b/tests/t_16c5x/t_16c5x.doc
@@ -0,0 +1,5 @@
++----------------------- Test Application 16C5x ----------------------------+
+| |
+| This is a (synthetic) test of the PIC 16C5x code generator |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_16c5x/t_16c5x.ori b/tests/t_16c5x/t_16c5x.ori
new file mode 100755
index 0000000..03a128c
--- /dev/null
+++ b/tests/t_16c5x/t_16c5x.ori
Binary files differ
diff --git a/tests/t_16c84/asflags b/tests/t_16c84/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_16c84/asflags
diff --git a/tests/t_16c84/t_16c84.asm b/tests/t_16c84/t_16c84.asm
new file mode 100644
index 0000000..e5b2ed4
--- /dev/null
+++ b/tests/t_16c84/t_16c84.asm
@@ -0,0 +1,53 @@
+ cpu 16c84
+
+ clrw
+ nop
+ clrwdt
+ retfie
+ return
+ sleep
+ option
+
+ addlw 1
+ andlw 100
+ iorlw $55
+ movlw %10101010
+ retlw 0
+ sublw 300-400
+ xorlw 186
+
+ addwf 3,f
+ addwf 4,w
+ addwf 5
+ addwf 6,0
+ addwf 7,1
+ andwf 8
+ comf 9,f
+ comf 10,w
+ comf 11
+ comf 12,0
+ comf 13,1
+ decf 14
+ decfsz 15
+ incf 16
+ incfsz 17
+ iorwf 18
+ movf 19
+ rlf 20
+ rrf 21
+ subwf 22
+ swapf 23
+ xorwf 24
+
+ bcf 17,4
+ bsf 500,6
+ btfsc 23,3
+ btfss 20,0
+
+ clrf 20
+ movwf 33
+
+ tris 6
+
+ call $200
+ goto $300
diff --git a/tests/t_16c84/t_16c84.doc b/tests/t_16c84/t_16c84.doc
new file mode 100644
index 0000000..999b8bd
--- /dev/null
+++ b/tests/t_16c84/t_16c84.doc
@@ -0,0 +1,5 @@
++----------------------- Test Application 16C84 ----------------------------+
+| |
+| This is a (synthetic) test of the PIC 16C8x code generator |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_16c84/t_16c84.ori b/tests/t_16c84/t_16c84.ori
new file mode 100644
index 0000000..1c6741a
--- /dev/null
+++ b/tests/t_16c84/t_16c84.ori
Binary files differ
diff --git a/tests/t_17c42/asflags b/tests/t_17c42/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_17c42/asflags
diff --git a/tests/t_17c42/t_17c42.asm b/tests/t_17c42/t_17c42.asm
new file mode 100644
index 0000000..a74fb9c
--- /dev/null
+++ b/tests/t_17c42/t_17c42.asm
@@ -0,0 +1,66 @@
+ cpu 17c42
+ relaxed on
+
+ retfie
+ return
+ clrwdt
+ nop
+ sleep
+
+ movlb 12h
+ addlw 12h
+ andlw 12h
+ iorlw 12h
+ movlw 12h
+ sublw 12h
+ xorlw 12h
+ retlw 12h
+
+ addwf 12h,0
+ addwfc 12h,1
+ andwf 12h,w
+ clrf 12h,f
+ comf 12h
+ daw 12h,0
+ decf 12h,1
+ incf 12h,w
+ iorwf 12h,f
+ negw 12h
+ rlcf 12h,0
+ rlncf 12h,1
+ rrcf 12h,w
+ rrncf 12h,f
+ setf 12h
+ subwf 12h,0
+ subwfb 12h,1
+ swapf 12h,w
+ xorwf 12h,f
+ decfsz 12h
+ dcfsnz 12h,0
+ incfsz 12h,1
+ infsnz 12h,w
+
+ bcf 12h,1
+ bsf 12h,3
+ btfsc 12h,5
+ btfss 12h,7
+ btg 12h,1
+
+ movwf 12h
+ cpfseq 12h
+ cpfsgt 12h
+ tstfsz 12h
+
+ movfp 34h,12h
+ movpf 12h,34h
+
+ tablrd 1,1,12h
+ tablwt 1,1,12h
+
+ tlrd 1,12h
+ tlwt 1,12h
+
+ call 1234h
+ goto 1234h
+ lcall 0fedch
+
diff --git a/tests/t_17c42/t_17c42.doc b/tests/t_17c42/t_17c42.doc
new file mode 100644
index 0000000..22221cc
--- /dev/null
+++ b/tests/t_17c42/t_17c42.doc
@@ -0,0 +1,5 @@
++----------------------- Test Application 17C42 ----------------------------+
+| |
+| This is a (synthetic) test of the PIC 17C42 code generator |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_17c42/t_17c42.ori b/tests/t_17c42/t_17c42.ori
new file mode 100644
index 0000000..1db73f8
--- /dev/null
+++ b/tests/t_17c42/t_17c42.ori
Binary files differ
diff --git a/tests/t_251/asflags b/tests/t_251/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_251/asflags
diff --git a/tests/t_251/t_251.asm b/tests/t_251/t_251.asm
new file mode 100644
index 0000000..2002ac9
--- /dev/null
+++ b/tests/t_251/t_251.asm
@@ -0,0 +1,399 @@
+ cpu 80c251
+ include reg251
+
+ page 0
+
+ org 0ff0000h
+
+data equ 30h
+;acc equ 0eeh
+Bit1 bit 21h.7
+Bit2 bit s:90h.4
+Bit3 bit data.5
+Bit4 bit acc.3
+Bit5 bit Bit3
+
+ acall Targ
+ ajmp Targ
+
+ lcall Targ
+ lcall @wr4
+ ljmp Targ
+ ljmp @wr2
+
+ ecall Targ
+ ecall @dpx
+ ejmp Targ
+ ejmp @dr16
+
+ sjmp Targ
+ jc Targ
+ jnc Targ
+ jnz Targ
+ jz Targ
+ je Targ
+ jsle Targ
+ jle Targ
+ jne Targ
+ jsg Targ
+ jsge Targ
+ jsl Targ
+ jsle Targ
+
+ jmp @a+dptr
+ jmp @wr2
+ jmp @dr16
+ jmp Targ
+ jmp Targ+4000h
+ jmp 4000h
+ call @wr4
+ call @dpx
+ call Targ
+ call Targ+4000h
+
+ jb Bit1,Targ
+ jbc Bit2,Targ
+ jnb Bit4,Targ
+ jb Bit3,Targ
+ jnb s:91h.4,Targ
+ jbc 44h.5,Targ
+
+ djnz r5,Targ
+ djnz acc,Targ
+ djnz data,Targ
+
+ cjne a,data,Targ
+ cjne a,#'A',Targ
+ cjne r6,#50,Targ
+ cjne @r1,#40h,Targ
+
+Targ:
+
+ add a,#12h
+ add a,data
+ add a,1234h
+ add a,@r1
+ add a,@wr2
+ add a,@dr8
+ add a,r4
+ add a,a
+ add a,r13
+ add r3,r12
+ add wr8,wr12
+ add dr20,dpx
+ add r4,#23h
+ add r11,#23h
+ add wr4,#1234h
+ add dr4,#1234h
+ add r8,data
+ add r11,data
+ add wr8,data
+ add r8,1234h
+ add wr8,55ah
+ add r11,@r1
+ add r2,@wr6
+ add r6,@dr12
+
+ sub a,r7
+ sub wr4,wr10
+ sub dr12,dr28
+ sub r4,#10
+ sub wr6,#1000
+ sub dr16,#05aa5h
+ sub a,data
+ sub wr8,data
+ sub r12,1243h
+ sub wr10,1342h
+ sub r3,@wr14
+ sub a,@spx
+
+ cmp a,r7
+ cmp wr4,wr10
+ cmp dr12,dr28
+ cmp r4,#10
+ cmp wr6,#1000
+ cmp dr16,#05aa5h
+ cmp dr16,#-3
+ cmp a,data
+ cmp wr8,data
+ cmp r12,1243h
+ cmp wr10,1342h
+ cmp r3,@wr14
+ cmp a,@spx
+
+ addc a,r6
+ addc r11,@r0
+ addc a,data
+ addc a,#20h
+ subb a,r6
+ subb r11,@r0
+ subb a,data
+ subb a,#20h
+
+ anl c,Bit1
+ anl cy,Bit3
+ anl c,/Bit1
+ anl cy,/Bit3
+ orl c,Bit1
+ orl cy,Bit3
+ orl c,/Bit1
+ orl cy,/Bit3
+
+ anl data,a
+ anl data,r11
+ anl data,#10001111b
+ anl a,#20h
+ anl a,acc
+ anl a,90h
+ anl a,s:90h
+ anl a,@r1
+ anl a,@wr10
+ anl a,@dr12
+ anl a,r4
+ anl a,r10
+ anl a,a
+ anl r10,r4
+ anl wr10,wr6
+ anl r10,#55h
+ anl r11,#0aah
+ anl wr14,#1000100010001001b
+ anl r1,data
+ anl r11,data
+ anl wr4,data
+ anl r10,1234h
+ anl wr2,1234h
+ anl r11,@r1
+ anl r6,@wr14
+ anl r7,@dr16
+
+ orl data,a
+ orl data,r11
+ orl data,#10001111b
+ orl a,#20h
+ orl a,acc
+ orl a,90h
+ orl a,s:90h
+ orl a,@r1
+ orl a,@wr10
+ orl a,@dr12
+ orl a,r4
+ orl a,r10
+ orl a,a
+ orl r10,r4
+ orl wr10,wr6
+ orl r10,#55h
+ orl r11,#0aah
+ orl wr14,#1000100010001001b
+ orl r1,data
+ orl r11,data
+ orl wr4,data
+ orl r10,1234h
+ orl wr2,1234h
+ orl r11,@r1
+ orl r6,@wr14
+ orl r7,@dr16
+
+ xrl data,a
+ xrl data,r11
+ xrl data,#10001111b
+ xrl a,#20h
+ xrl a,acc
+ xrl a,90h
+ xrl a,s:90h
+ xrl a,@r1
+ xrl a,@wr10
+ xrl a,@dr12
+ xrl a,r4
+ xrl a,r10
+ xrl a,a
+ xrl r10,r4
+ xrl wr10,wr6
+ xrl r10,#55h
+ xrl r11,#0aah
+ xrl wr14,#1000100010001001b
+ xrl r1,data
+ xrl r11,data
+ xrl wr4,data
+ xrl r10,1234h
+ xrl wr2,1234h
+ xrl r11,@r1
+ xrl r6,@wr14
+ xrl r7,@dr16
+
+
+ clr a
+ clr c
+ clr Bit1
+ clr s:92h.6
+
+ cpl a
+ cpl c
+ cpl Bit1
+ cpl s:92h.6
+
+ setb c
+ setb Bit1
+ setb s:92h.6
+
+ dec a
+ dec data
+ dec @r1
+ dec r5,#1
+ dec r10
+ dec r11,#1
+ dec a,#2
+ dec r11,#4
+ dec wr2,#2
+ dec spx,#4
+
+ inc a
+ inc data
+ inc @r1
+ inc r5,#1
+ inc r10
+ inc r11,#1
+ inc a,#2
+ inc r11,#4
+ inc wr2,#2
+ inc spx,#4
+ inc dptr
+
+ mul ab
+ mul r5,r7
+ mul wr10,wr14
+
+ div ab
+ div r5,r7
+ div wr10,wr14
+
+ mov a,#10
+ mov acc,#20
+ mov @r1,#30
+ mov r4,#40
+ mov data,acc
+ mov s:90h,@r1
+ mov 70h,r6
+ mov @r1,data
+ mov r5,data
+ mov a,acc
+ mov a,@r1
+ mov a,r2
+ mov acc,a
+ mov @r1,a
+ mov r4,a
+ mov a,r12
+ mov r12,a
+ mov r11,r5
+ mov r5,r11
+ mov r10,r6
+ mov wr4,wr10
+ mov dr12,dpx
+ mov r11,#50
+ mov r7,#60
+ mov r14,#70
+ mov wr12,#8090
+ mov dr12,#8090
+ mov dr12,#-100
+ mov r11,data
+ mov r4,data
+ mov r15,data
+ mov wr10,acc
+ mov dr16,s:0a0h
+ mov a,1234h
+ mov r10,1234h
+ mov wr14,1234h
+ mov dr20,1243h
+ mov a,@wr10
+ mov r2,@wr10
+ mov a,@dr12
+ mov r4,@dr12
+ mov wr10,@wr12
+ mov wr10,@dr12
+ mov data,r11
+ mov data,r5
+ mov data,r8
+ mov data,wr2
+ mov data,spx
+ mov 1234h,a
+ mov 1234h,r5
+ mov 1234h,wr8
+ mov 1234h,dr16
+ mov @wr14,a
+ mov @wr14,r9
+ mov @dr12,a
+ mov @dr12,r8
+ mov @wr14,wr18
+ mov @dr8,wr18
+ mov a,@wr2+10
+ mov r4,@wr2-20
+ mov wr10,@wr2+30
+ mov a,@dpx-40
+ mov r8,@dpx+50
+ mov wr10,@dpx-60
+ mov @wr2+10,a
+ mov @wr2-20,r4
+ mov @wr2+30,wr10
+ mov @dpx-40,a
+ mov @dpx+50,r8
+ mov @dpx-60,wr10
+ mov dptr,#1234h
+
+ movc a,@a+dptr
+ movc a,@a+pc
+
+ movh dr12,#55aah
+
+ movs wr10,a
+ movz wr12,r12
+
+ movx a,@dptr
+ movx a,@r1
+ movx @dptr,a
+ movx @r0,r11
+
+ pop data
+ pop acc
+ pop a
+ pop r5
+ pop wr8
+ pop dr20
+ push data
+ push acc
+ push a
+ push r5
+ push wr8
+ push dr20
+ push #20
+ pushw #55aah
+
+ xch a,r5
+ xch a,data
+ xch a,@r1
+ xch r5,r11
+ xch data,a
+ xch @r1,a
+ xchd a,@r1
+ xchd @r1,r11
+
+ nop
+ ret
+ reti
+ eret
+ trap
+
+ da a
+ rl a
+ rlc a
+ rr a
+ rrc a
+ swap r11
+
+ sll a
+ sll r6
+ sll wr12
+ sra a
+ sra r6
+ sra wr12
+ srl a
+ srl r6
+ srl wr12
diff --git a/tests/t_251/t_251.doc b/tests/t_251/t_251.doc
new file mode 100644
index 0000000..e2b4505
--- /dev/null
+++ b/tests/t_251/t_251.doc
@@ -0,0 +1,5 @@
++----------------------- Test Application 251 ----------------------------+
+| |
+| This is a (synthetic) test of the MCS-251 code generator |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_251/t_251.ori b/tests/t_251/t_251.ori
new file mode 100644
index 0000000..ecd8c4c
--- /dev/null
+++ b/tests/t_251/t_251.ori
Binary files differ
diff --git a/tests/t_296/asflags b/tests/t_296/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_296/asflags
diff --git a/tests/t_296/t_296.asm b/tests/t_296/t_296.asm
new file mode 100644
index 0000000..27cdb60
--- /dev/null
+++ b/tests/t_296/t_296.asm
@@ -0,0 +1,132 @@
+ cpu 80296
+
+ax equ 40
+al equ ax
+ah equ al+1
+bx equ 42
+cx equ 44
+dx equ 46
+
+ reti
+
+ eld ax,[bx]
+ eld ax,0[bx]
+ eld ax,100[bx] ; nur 24-Bit-Displacement
+ eld ax,1000[bx]
+ eld ax,100000[bx]
+ eld ax,-100[bx]
+ eld ax,-1000[bx]
+ eld ax,-100000[bx]
+ eld ax,123456h
+
+ eldb al,[bx]
+ eldb al,0[bx]
+ eldb al,100[bx] ; nur 24-Bit-Displacement
+ eldb al,1000[bx]
+ eldb al,100000[bx]
+ eldb al,-100[bx]
+ eldb al,-1000[bx]
+ eldb al,-100000[bx]
+ eldb al,123456h
+
+ est ax,[bx]
+ est ax,0[bx]
+ est ax,100[bx] ; nur 24-Bit-Displacement
+ est ax,1000[bx]
+ est ax,100000[bx]
+ est ax,-100[bx]
+ est ax,-1000[bx]
+ est ax,-100000[bx]
+ est ax,123456h
+
+ estb al,[bx]
+ estb al,0[bx]
+ estb al,100[bx] ; nur 24-Bit-Displacement
+ estb al,1000[bx]
+ estb al,100000[bx]
+ estb al,-100[bx]
+ estb al,-1000[bx]
+ estb al,-100000[bx]
+ estb al,123456h
+
+ ecall $+123456h
+ ejmp $-10h
+ ebr [bx]
+
+ ebmovi cx,ax
+
+ mac #12h
+ mac ax,#12h
+
+ macr bx
+ macr ax,bx
+
+ macrz 10[bx]
+ macrz ax,10[bx]
+
+ macz -1000[bx]
+ macz ax,-1000[bx]
+
+ smac [cx]
+ smac ax,[cx]
+
+ smacr [cx]+
+ smacr ax,[cx]+
+
+ smacrz 1000h
+ smacrz ax,1000h
+
+ smacz 0ffc0h
+ smacz ax,0ffc0h
+
+ msac ax,#20
+
+ mvac cx,al
+
+ rpt ax
+ rptnst #10
+ rptnh [cx]
+ rptgt [cx]+
+ rptnc ax
+ rptnvt #10
+ rptnv [cx]
+ rptge [cx]+
+ rptne ax
+ rptst #10
+ rpth [cx]
+ rptle [cx]+
+ rptc ax
+ rptvt #10
+ rptv [cx]
+ rptlt [cx]+
+ rpte ax
+ rpti #10
+ rptinst [cx]
+ rptinh [cx]+
+ rptigt ax
+ rptinc #10
+ rptinvt [cx]
+ rptinv [cx]+
+ rptige ax
+ rptine #10
+ rptist [cx]
+ rptih [cx]+
+ rptile ax
+ rptic #10
+ rptivt [cx]
+ rptiv [cx]+
+ rptilt ax
+ rptie #10
+
+ assume wsr:3eh ; 1f80h...1fbfh --> 0c0h...0ffh
+ assume wsr1:9eh ; 0f780h...0f7bfh --> 40h..7fh
+
+ ld ax,3eh ; normal
+ ld ax,44h ; muß absolut werden
+ ld ax,92h ; wieder normal
+ ld ax,0d0h ; muß wieder absolut werden
+ ld ax,1000h ; muß absolut bleiben
+ ld ax,1f90h ; mit WSR
+ ld ax,2000h ; muß wieder absolut bleiben
+ ld ax,0f7a0h ; mit WSR1
+ ld ax,0fffeh ; muß wieder absolut bleiben
diff --git a/tests/t_296/t_296.doc b/tests/t_296/t_296.doc
new file mode 100644
index 0000000..da5b3ba
--- /dev/null
+++ b/tests/t_296/t_296.doc
@@ -0,0 +1,6 @@
++------------------------- Test Application 296 -----------------------------+
+| |
+| This is a (synthetic) test of the 80196Nx/80296's instruction set |
+| extensions |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_296/t_296.ori b/tests/t_296/t_296.ori
new file mode 100755
index 0000000..b4fe458
--- /dev/null
+++ b/tests/t_296/t_296.ori
Binary files differ
diff --git a/tests/t_29k/asflags b/tests/t_29k/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_29k/asflags
diff --git a/tests/t_29k/t_29k.asm b/tests/t_29k/t_29k.asm
new file mode 100644
index 0000000..303a6af
--- /dev/null
+++ b/tests/t_29k/t_29k.asm
@@ -0,0 +1,80 @@
+ cpu AM29240
+ emulated class,convert,sqrt
+ supmode on
+
+ page 0
+ relaxed on
+
+ include reg29k
+
+ add r128,r129,r130
+ add r129,r130,131
+ add r130,r131
+ add r131,132
+ ; andere Op's dito...
+
+ dadd r132,r133,r134
+ dadd r133,r134
+ ; andere Op's dito
+
+ aseq 134,r135,r136
+ aseq 135,r136,137
+
+ call r136,$+0x048d0
+ call r137,0x30000
+ call r138,r139
+ calli r139,r140
+ jmp $
+ jmpi r141
+ jmpf r142,$
+ jmpfi r143,r144
+ jmpfdec r144,$
+ jmpt r145,$
+ jmpti r146,r147
+
+ load 0,27,r160,r161
+ loadl 27,r161,r162
+ loadm 27,r162,163
+ loadset 13,r163,r164
+ store 13,r164,165
+ storel 13,r165,r166
+ storem 7,r166,167
+
+ class r147,r148,2
+ sqrt r147,r148,2
+ sqrt r149,2
+
+ clz r148,r149
+ clz r149,150
+
+ const r150,151
+ const r151,-152
+ const r152,0x153154
+ consth r153,500
+ constn r154,0xffff1234
+ constn r155,-5
+ constn r156,0123
+
+ convert r157,r158,1,2,2,1
+ exhws r158,r159
+
+ halt
+ iret
+
+ inv
+ iretinv 2
+
+ emulate 20,lr10,lr11
+
+ mfsr r148,lru
+ mtsr ipc,r148
+ mtsrim lru,0xa55a
+ mftlb r159,r160
+ mttlb r160,r161
+
+ add lr122,lr110,0
+ addc gr10,gr30
+
+ add gr20,gr40,gr60
+ assume rbp:0b0000000000000010
+ add gr20,gr40,gr60
diff --git a/tests/t_29k/t_29k.doc b/tests/t_29k/t_29k.doc
new file mode 100644
index 0000000..a0ccad8
--- /dev/null
+++ b/tests/t_29k/t_29k.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 29K -----------------------------+
+| |
+| This is a (synthetic) test of the AM29K instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_29k/t_29k.ori b/tests/t_29k/t_29k.ori
new file mode 100644
index 0000000..c878f69
--- /dev/null
+++ b/tests/t_29k/t_29k.ori
Binary files differ
diff --git a/tests/t_32/asflags b/tests/t_32/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_32/asflags
diff --git a/tests/t_32/t_32.asm b/tests/t_32/t_32.asm
new file mode 100644
index 0000000..d7738e5
--- /dev/null
+++ b/tests/t_32/t_32.asm
@@ -0,0 +1,39 @@
+ cpu 68340
+ supmode on
+ include reg683xx.inc
+ page 0
+
+ lpstop #$55aa
+
+ link a6,#10
+ link.l a6,#10
+
+ bgnd
+
+Test1 tbls.b (a4),d5
+Test2: tbls.w 30(a6),d1
+ Test3: tbls.l 20(a4,d5*1),d6
+ Test4: tblsn.b (a4),d5
+ tblsn.w 30(a6),d1
+ tblsn.l 20(a4,d5*1),d6
+ tblu.b (a4),d5
+ tblu.w 30(a6),d1
+ tblu.l 20(a4,d5*1),d6
+ tblun.b (a4),d5
+ tblun.w 30(a6),d1
+ tblun.l 20(a4,d5*1),d6
+
+ tbls.b d1:d2,d3
+ tbls.w d2:d3,d4
+ tbls.l d3:d4,d5
+ tblsn.b d1:d2,d3
+ tblsn.w d2:d3,d4
+ tblsn.l d3:d4,d5
+ tblu.b d1:d2,d3
+ tblu.w d2:d3,d4
+ tblu.l d3:d4,d5
+ tblun.b d1:d2,d3
+ tblun.w d2:d3,d4
+ tblun.l d3:d4,d5
+
+ move.l (d0.l),d0
diff --git a/tests/t_32/t_32.doc b/tests/t_32/t_32.doc
new file mode 100644
index 0000000..e069ffe
--- /dev/null
+++ b/tests/t_32/t_32.doc
@@ -0,0 +1,6 @@
++-------------------------- Test Application 32 -----------------------------+
+| |
+| This is a (synthetic) test of the CPU32's extensions to the 680x0 |
+| basic instruction set. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_32/t_32.ori b/tests/t_32/t_32.ori
new file mode 100644
index 0000000..1413840
--- /dev/null
+++ b/tests/t_32/t_32.ori
Binary files differ
diff --git a/tests/t_3201x/asflags b/tests/t_3201x/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_3201x/asflags
diff --git a/tests/t_3201x/t_3201x.asm b/tests/t_3201x/t_3201x.asm
new file mode 100644
index 0000000..f07148f
--- /dev/null
+++ b/tests/t_3201x/t_3201x.asm
@@ -0,0 +1,74 @@
+ cpu 32015
+
+ abs
+ apac
+ cala
+ dint
+ eint
+ nop
+ pac
+ pop
+ push
+ ret
+ rovm
+ sovm
+ spac
+ zac
+
+ b 345h
+ banz 345h
+ bgez 345h
+ bgz 345h
+ bioz 345h
+ blez 345h
+ blz 345h
+ bnz 345h
+ bv 345h
+ bz 345h
+ call 345h
+
+ addh *,ar1
+ adds *-,ar0
+ and *+,ar1
+ dmov *,1
+ ldp *-,0
+ lst *+,1
+ lt dat123
+ lta dat45
+ ltd 12h
+ mar *,ar1
+ mpy *-,ar0
+ or *+,ar1
+ sst *,1
+ subc *-,0
+ subh *+,1
+ subs dat123
+ tblr dat45
+ tblw 12h
+ xor *,ar1
+ zalh *-,ar0
+ zals *+,ar1
+
+ add *+,4,ar0
+ lac *+,ar0
+ sach 12h,4
+ sacl 12h
+ sub 12h,6
+
+ lack 12h
+ ldpk 1
+ mpyk 123h
+
+ in *,2,ar1
+ in 45h,4
+ out *,2,ar1
+ out 45h,4
+
+ larp ar1
+ larp 1
+
+ lar ar1,12h
+ sar 1,*,ar0
+
+ lark ar1,12h
+
diff --git a/tests/t_3201x/t_3201x.doc b/tests/t_3201x/t_3201x.doc
new file mode 100644
index 0000000..6fc74f1
--- /dev/null
+++ b/tests/t_3201x/t_3201x.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 3201x ---------------------------+
+| |
+| This is a (synthetic) test of the TMS3201x instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_3201x/t_3201x.ori b/tests/t_3201x/t_3201x.ori
new file mode 100644
index 0000000..4b0cfb6
--- /dev/null
+++ b/tests/t_3201x/t_3201x.ori
Binary files differ
diff --git a/tests/t_3203x/asflags b/tests/t_3203x/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_3203x/asflags
diff --git a/tests/t_3203x/t_3203x.asm b/tests/t_3203x/t_3203x.asm
new file mode 100644
index 0000000..d6b35ef
--- /dev/null
+++ b/tests/t_3203x/t_3203x.asm
@@ -0,0 +1,271 @@
+ cpu 320C30
+ relaxed on
+ page 0
+
+ org $123456
+
+targ: br targ
+ brd targ
+ call targ
+
+ bu r0
+ bud r0
+ bu targ
+ bud targ
+ blo ar1
+ blsd targ
+ bhi ir0
+ bhs targ
+ beqd ar4
+ bne targ
+ blt targ
+ ble r10
+ bgtd targ
+ bge r6
+ bzd targ
+ bnz ar5
+ bpd targ
+ bn targ
+ bnnd ar3
+ bnv targ
+ bv ar7
+ bnufd ir1
+ buf targ
+ bnc ar2
+ bcd iof
+ bnlv targ
+ blv targ
+ bnluf targ
+ bluf targ
+ bzuf targ
+ b targ
+
+ callne r4
+ callnluf targ
+
+ dbne ar1,r5
+ dbn ar5,targ
+ dbud ar2,ar7
+ dbzufd ar6,targ
+ db ar7,targ
+
+ retine
+ retsnc
+ retsu
+ rets
+
+ trapu 7
+ trapuf 2
+
+ swi
+ sigi
+ idle
+
+ rol r4
+ rolc ar2
+ ror sp
+ rorc r20
+
+ rptb targ
+
+ nop ar2
+ nop *+ar3(2)
+ nop *-ar4(200)
+ nop *++ar5(30)
+ nop *--ar6
+ nop *ar5++(20)
+ nop *ar1--(12h)
+ nop *ar7++($56)%
+ nop *ar0--(0x10)%
+ nop *+ar6(ir0)
+ nop *-ar4(ir0)
+ nop *++ar2(ir0)
+ nop *--ar2(ir0)
+ nop *ar2++(ir0)
+ nop *ar2--(ir0)
+ nop *ar2++(ir0)%
+ nop *ar2--(ir0)%
+ nop *+ar6(ir1)
+ nop *-ar4(ir1)
+ nop *++ar2(ir1)
+ nop *--ar2(ir1)
+ nop *ar2++(ir1)
+ nop *ar2--(ir1)
+ nop *ar2++(ir1)%
+ nop *ar2--(ir1)%
+ nop *ar4
+ nop *ar3(100-$64)
+ nop *ar1++(ir0)B
+ iack *ar5
+ rpts ar5
+
+ absf r4
+ absf ar2,r5
+ absf @$1300,r7
+ absf *ar4++,r3
+ absf 200,r5
+
+ absi r4
+ absi ar2,r5
+ absi @$1300,r7
+ absi *ar4++,r3
+ absi 200,r5
+ ;
+ addc ar2,r5
+ addc @$1300,r7
+ addc *ar4++,r3
+ addc 200,r5
+
+ addc3 *ar1++(1),*ar2,r5
+ addc3 *-ar3,r5,r2
+ addc3 r6,*ar4++,r3
+ addc3 r1,r2,r3
+
+ stf r4,@2000h
+ stf r6,*ar5
+
+ tstb3 r5,*ar3++
+
+ absf *ar4++,r6
+|| stf r6,*ar5++
+
+ sti r5,*ar3
+|| absi *ar4++%,r1
+
+ addf3 *ar4++,r5,r7
+|| stf r3,*ar5++
+
+ sti r3,*ar5++
+|| addi3 *ar4++,r5,r7
+
+ mpyi3 *ar4,*ar5,r1
+|| subi3 r6,r7,r3
+
+ subi3 *ar4,r6,r3
+|| mpyi3 *ar5,r7,r1
+
+ mpyi3 r7,*ar5,r1
+|| subi3 *ar4,r6,r3
+
+ mpyi3 *ar5,r7,r1
+|| subi3 r6,*ar4,r3
+
+ mpyi3 r7,*ar5,r1
+|| subi3 r6,*ar4,r3
+
+ mpyi3 r6,r7,r1
+|| subi3 *ar5,*ar4,r3
+
+ absf *++ar3(ir1) ,r4
+|| stf r4,*-ar7(1)
+
+ absi *-ar5(1),r5
+|| sti r1,*ar2--(ir1)
+
+ addf3 *+ar3(ir1),r2,r5
+|| stf r4,*ar2
+
+ addi3 *ar0--(ir0),r5,r0
+|| sti r3,*ar7
+
+ and3 *+ar1(ir0),r4,r7
+|| sti r3,*ar2
+
+ ash3 r1,*ar6++(ir1),r0
+|| sti r5,*ar2
+
+ fix *++ar4(1),r1
+|| sti r0,*ar2
+
+ float *+ar2(ir0),r6
+|| stf r7,*ar1
+
+ ldf *--ar1(ir0),r7
+|| ldf *ar7++(1),r3
+
+ ldf *ar2--(1),r1
+|| stf r3,*ar4++(ir1)
+
+ ldi *-ar1(1),r7
+|| ldi *ar7++(ir0),r1
+
+ ldi *-ar1(1),r2
+|| sti r7,*ar5++(ir0)
+
+ lsh3 r7,*ar2--(1),r2
+|| sti r0,*+ar0(1)
+
+ mpyf3 *ar5++(1),*--ar1(ir0),r0
+|| addf3 r5,r7,r3
+
+ mpyf3 *-ar2(1),r7,r0
+|| stf r3,*ar0--(ir0)
+
+ mpyf3 r5,*++ar7(ir1),r0
+|| subf3 r7,*ar3--(1),r2
+
+ mpyi3 r7,r4,r0
+|| addi3 *-ar3,*ar5--(1),r3
+
+ mpyi3 *++ar0(1),r5,r7
+|| sti r2,*-ar3(1)
+
+ mpyi3 r2,*++ar0(1),r0
+|| subi3 *ar5--(ir1),r4,r2
+
+ negf *ar4--(1),r7
+|| stf r2,*++ar5(1)
+
+ negi *-ar3,r2
+|| sti r2,*ar1++
+
+ not *+ar2,r3
+|| sti r7,*--ar4(ir1)
+
+ or3 *++ar2,r5,r2
+|| sti r6,*ar1--
+
+ stf r4,*ar3--
+|| stf r3,*++ar5
+
+ sti r0,*++ar2(ir0)
+|| sti r5,*ar0
+
+ subf3 r1,*-ar4(ir1),r0
+|| stf r7,*+ar5(ir0)
+
+ subi3 r7,*+ar2(ir0),r1
+|| sti r3,*++ar7
+
+ xor3 *ar1++,r3,r3
+|| sti r6,*-ar2(ir0)
+
+ xor3 *ar1++,r3,r3
+ ||sti r6,*-ar2(ir0)
+
+ ldfz r3,r5
+ ldfzuf 20h,r6
+ ldiz r4,r6
+ ldp @123456h,dp
+
+ pop r3
+ popf r4
+ push r6
+ pushf r2
+
+ ldfz 1.27578125e+01,r4
+
+ ldi *ar5,r6
+ ||ldi *ar5++,r6
+
+ addf3 *ar5++,*ar5++,r3
+
+ single 1.79750e+02
+ single -6.281250e+01
+ single -9.90337307e+27
+ single 9.90337307e+27
+ single -6.118750e+01, 1.79750e+02
+ extended 9.90337307e+27
+ bss 20h
+ word 20,55,'ABCD'
+ data 12345h,-1.2345e6,"Hello world"
diff --git a/tests/t_3203x/t_3203x.doc b/tests/t_3203x/t_3203x.doc
new file mode 100644
index 0000000..618d68b
--- /dev/null
+++ b/tests/t_3203x/t_3203x.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 3203x ---------------------------+
+| |
+| This is a (synthetic) test of the TMS320C3x instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_3203x/t_3203x.ori b/tests/t_3203x/t_3203x.ori
new file mode 100755
index 0000000..7874442
--- /dev/null
+++ b/tests/t_3203x/t_3203x.ori
Binary files differ
diff --git a/tests/t_3205x/asflags b/tests/t_3205x/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_3205x/asflags
diff --git a/tests/t_3205x/t_3205x.asm b/tests/t_3205x/t_3205x.asm
new file mode 100644
index 0000000..7ae84a6
--- /dev/null
+++ b/tests/t_3205x/t_3205x.asm
@@ -0,0 +1,499 @@
+;------------------------------------
+; C20x subset
+
+ cpu 320c203
+ page 0
+
+ abs
+
+ add #25
+ add #2255
+ add #25,0
+ add #25,1
+ add #2255,1
+ add 123
+ add 123,3
+ add 123,16
+ add *
+ add *,3
+ add *,16
+ add *,0,AR2
+ add *,3,AR2
+ add *,16,AR2
+
+ addc 123
+ addc *
+ addc *,ar2
+
+ adds 123
+ adds *
+ adds *,ar2
+
+ addt 123
+ addt *
+ addt *,ar2
+
+ adrk #30
+
+ and 123
+ and *
+ and *,ar2
+ and #255
+ and #255, 3
+ and #255,16
+
+ apac
+
+ b 1234h
+ b 1234h, *
+ b 1234h, *, ar2
+
+ bacc
+
+ banz 1234h
+ banz 1234h, *
+ banz 1234h, *, ar2
+
+ bcnd 1234h, eq, c
+
+ bit 123, 3
+ bit *, 3
+ bit *, 3, ar2
+
+ bitt 123
+ bitt *
+ bitt *,ar2
+
+ bldd #10, 123
+ bldd #10, *
+ bldd #10, *, ar2
+ bldd 123, #10
+ bldd *, #10
+ bldd *, #10, ar2
+
+ blpd #1234h, 123
+ blpd #1233h, *, ar2
+
+ cala
+
+ call 1234h
+ call 1234h, *
+ call 1234h, *, ar2
+
+ cc 1234h, eq, c
+
+ clrc c
+ clrc cnf
+ clrc intm
+ clrc ovm
+ clrc sxm
+ clrc tc
+ clrc xf
+
+ cmpl
+
+ cmpr 2
+
+ dmov 123
+ dmov *
+ dmov *,ar2
+
+ idle
+
+ in 123, 1234h
+ in *, 1234h
+ in *, 1234h, ar2
+
+ intr 4
+
+ lacc 123
+ lacc 123, 16
+ lacc *
+ lacc *, 16
+ lacc *, 0, ar2
+ lacc *, 16, ar2
+ lacc #2
+ lacc #2, 10
+
+ lacl 123
+ lacl *
+ lacl *, ar2
+ lacl #23
+
+ lact 123
+ lact *
+ lact *, ar2
+
+ lar ar2, 123
+ lar ar2, *
+ lar ar2, *, ar2
+ lar ar2, #10
+ lar ar2, #1000
+
+ ldp 123
+ ldp *
+ ldp *, ar2
+ ldp #40
+
+ lph 123
+ lph *
+ lph *, ar2
+
+ lst #0, 123
+ lst #0, *
+ lst #0, *, ar2
+
+ lst #1, 123
+ lst #1, *
+ lst #1, *, ar2
+
+ lt 123
+ lt *
+ lt *, ar2
+
+ lta 123
+ lta *
+ lta *, ar2
+
+ ltd 123
+ ltd *
+ ltd *, ar2
+
+ ltp 123
+ ltp *
+ ltp *, ar2
+
+ lts 123
+ lts *
+ lts *, ar2
+
+ mac 1234h, 123
+ mac 1234h, *
+ mac 1234h, *, ar2
+
+ macd 1234h, 123
+ macd 1234h, *
+ macd 1234h, *, ar2
+
+ mar 123
+ mar *
+ mar *, ar2
+
+ mpy 123
+ mpy *
+ mpy *, ar2
+ mpy #300
+ mpy #-300
+
+ mpya 123
+ mpya *
+ mpya *, ar2
+
+ mpys 123
+ mpys *
+ mpys *, ar2
+
+ mpyu 123
+ mpyu *
+ mpyu *, ar2
+
+ neg
+
+ nmi
+
+ nop
+
+ norm *
+ norm *, ar2
+
+ or 123
+ or *
+ or *,ar2
+ or #255
+ or #255, 3
+ or #255,16
+
+ out 123, 1234h
+ out *, 1234h
+ out *, 1234h, ar2
+
+ pac
+
+ pop
+
+ popd 123
+ popd *
+ popd *, ar2
+
+ pshd 123
+ pshd *
+ pshd *, ar2
+
+ push
+
+ ret
+
+ retc eq
+
+ rol
+
+ ror
+
+ rpt #30
+ rpt 123
+ rpt *
+ rpt *, ar2
+
+ sach 123
+ sach *, 0
+ sach *, 2
+ sach *, 0, ar2
+ sach *, 2, ar2
+
+ sacl 123
+ sacl *, 0
+ sacl *, 2
+ sacl *, 0, ar2
+ sacl *, 2, ar2
+
+ sar ar3, 123
+ sar ar3, *
+ sar ar3, *, ar2
+
+ sbrk #10
+
+ setc c
+ setc cnf
+ setc intm
+ setc ovm
+ setc sxm
+ setc tc
+ setc xf
+
+ sfl
+
+ sfr
+
+ spac
+
+ spl 123
+ spl *
+ spl *, ar2
+
+ sph 123
+ sph *
+ sph *, ar2
+
+ splk #1234, 123
+ splk #1234, *
+ splk #1234, *, ar2
+
+ spm 2
+
+ sqra 123
+ sqra *
+ sqra *, ar2
+
+ sqrs 123
+ sqrs *
+ sqrs *, ar2
+
+ sst #0, 123
+ sst #0, *
+ sst #0, *, ar2
+
+ sst #1, 123
+ sst #1, *
+ sst #1, *, ar2
+
+ sub #25
+ sub #2255
+ sub #25,0
+ sub #25,1
+ sub #2255,1
+ sub 123
+ sub 123,3
+ sub 123,16
+ sub *
+ sub *,3
+ sub *,16
+ sub *,0,AR2
+ sub *,3,AR2
+ sub *,16,AR2
+
+ subb 123
+ subb *
+ subb *, ar2
+
+ subc 123
+ subc *
+ subc *, ar2
+
+ subs 123
+ subs *
+ subs *, ar2
+
+ subt 123
+ subt *
+ subt *, ar2
+
+ tblr 123
+ tblr *
+ tblr *, ar2
+
+ tblw 123
+ tblw *
+ tblw *, ar2
+
+ trap
+
+ xor 123
+ xor *
+ xor *,ar2
+ xor #255
+ xor #255, 3
+ xor #255,16
+
+ zalr 123
+ zalr *
+ zalr *, ar2
+
+;------------------------------------
+; C5x additions
+
+ cpu 320c50
+
+ adcb
+
+ addb
+
+ andb
+
+ apl #10, 123
+ apl #10, *
+ apl #10, *, ar2
+ apl 123
+ apl *
+ apl *, ar2
+
+ bd 1234h
+ bd 1234h, *
+ bd 1234h, *, ar2
+
+ baccd
+
+ banzd 1234h
+ banzd 1234h, *
+ banzd 1234h, *, ar2
+
+ bcndd 1234h, eq, c
+
+ bldd bmar, 123
+ bldd bmar, *
+ bldd bmar, *, ar2
+ bldd 123, bmar
+ bldd *, bmar
+ bldd *, bmar, ar2
+
+ bldp 123
+ bldp *
+ bldp *, ar2
+
+ blpd bmar, 123
+ blpd bmar, *
+ blpd bmar, *, ar2
+
+ bsar 7
+
+ calad
+
+ calld 1234h
+ calld 1234h, *
+ calld 1234h, *, ar2
+
+ ccd 1234h, eq, c
+
+ cpl #10, 123
+ cpl #10, *
+ cpl #10, *, ar2
+ cpl 123
+ cpl *
+ cpl *, ar2
+
+ crgt
+
+ crlt
+
+ exar
+
+ idle2
+
+ lacb
+
+ lamm 123
+ lamm *
+ lamm *, ar2
+
+ lmmr 123, #1234
+ lmmr *, #1234
+ lmmr *, #1234, ar2
+
+ madd 123
+ madd *
+ madd *, ar2
+
+ mads 123
+ mads *
+ mads *, ar2
+
+ opl #10, 123
+ opl #10, *
+ opl #10, *, ar2
+ opl 123
+ opl *
+ opl *, ar2
+
+ orb
+
+ retd
+
+ retcd eq
+
+ rete
+
+ reti
+
+ rolb
+
+ rorb
+
+ rptb 123
+
+ rptz #10
+
+ sacb
+
+ samm 123
+ samm *
+ samm *, ar2
+
+ sath
+
+ satl
+
+ sbb
+
+ sbbb
+
+ sflb
+
+ sfrb
+
+; haven't found encoding of the C5x SHM instruction so far :-(
+; shm
+
+ smmr 123, #1234
+ smmr *, #1234
+ smmr *, #1234, ar2
+
+ xc 2, eq
diff --git a/tests/t_3205x/t_3205x.doc b/tests/t_3205x/t_3205x.doc
new file mode 100644
index 0000000..1f2b721
--- /dev/null
+++ b/tests/t_3205x/t_3205x.doc
@@ -0,0 +1,7 @@
++------------------------- Test Application 3205x ---------------------------+
+| |
+| This is a (synthetic) test of the TMS320C5x instruction set |
+| It includes moreover a clear separation between the C20x subset and |
+| the full C5x instruction set. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_3205x/t_3205x.ori b/tests/t_3205x/t_3205x.ori
new file mode 100644
index 0000000..e0089cb
--- /dev/null
+++ b/tests/t_3205x/t_3205x.ori
Binary files differ
diff --git a/tests/t_3206x/asflags b/tests/t_3206x/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_3206x/asflags
diff --git a/tests/t_3206x/t_3206x.asm b/tests/t_3206x/t_3206x.asm
new file mode 100644
index 0000000..5c5804d
--- /dev/null
+++ b/tests/t_3206x/t_3206x.asm
@@ -0,0 +1,241 @@
+ cpu 32060
+
+ page 0
+
+mv macro src,dest
+ add.ATTRIBUTE 0,src,dest
+ endm
+
+neg macro src,dest
+ sub.ATTRIBUTE 0,src,dest
+ endm
+
+not macro src,dest
+ xor.ATTRIBUTE -1,src,dest
+ endm
+
+ not a0,a1
+
+zero macro dest
+ xor.ATTRIBUTE dst,dst,dst
+ endm
+
+ mv a1,a3
+ mv.l2 a1,b3
+
+ nop
+|| nop
+|| nop
+ nop
+ nop
+
+ [b0] nop
+|| [!b0] nop
+
+ idle
+
+ nop
+ nop 7
+
+ abs a4,a7
+ abs.l1 a4,a7
+ abs b4,a7
+ abs.l1 b4,a7
+ abs.l1x b4,a7
+ abs b3:b2,b11:b10
+ abs a7:a6,b11:b10
+
+ add a1,a3,a7:a6
+ add a1,b3,a7:a6
+ add b1,a3,a7:a6
+ add a7,a5:a4,a13:a12
+ add b7,a5:a4,a13:a12
+ add a5:a4,a7,a13:a12
+ add a5:a4,b7,a13:a12
+ add b9:b8,-3,b15:b14
+ add -3,b9:b8,b15:b14
+
+ addab.d1 a4,a2,a4
+ addah.d1 a4,a2,a4
+ addaw.d2 b4,2,b4
+ subab.d1 a4,a2,a4
+ subah.d1 a4,a2,a4
+ subaw.d2 b4,2,b4
+
+ addk 15401,a1
+ addk.s1 15401,a1
+
+ add2 a1,b1,a2
+ sub2 b1,a0,b2
+
+ clr a1,4,19,a2
+ clr b1,b3,b2
+
+ cmpeq.l2 a1,b1,b2
+ cmpeq.l1 -9,a1,a2
+ cmpeq.l2 a1,b3:b2,b1
+ cmpgt.l1 a1,b2,a2
+ cmpgt.l1 a1,b1,a2
+ cmpgt.l1 8,a1,a2
+ cmpgt.l1 a1,b1,a2
+ cmpgtu.l1 a1,a2,a3
+ cmpgtu.l1 0ah,a1,a2
+ cmpgtu.l1 0eh,a3:a2,a4
+ cmplt.l1 a1,a2,a3
+ cmplt.l1 9,a1,a2
+ cmpltu.l1 a1,a2,a3
+ cmpltu.l1 14,a1,a2
+ cmpltu.l1 a1,a5:a4,a2
+
+ ext.s1 a1,10,19,a2
+ ext.s1 a1,a2,a3
+ extu.s1 a1,10,19,a2
+ extu.s1 a1,a2,a3
+
+ ldw.d1 *a10,a1
+ ldb.d1 *-a5[4],a7
+ ldh.d1 *++a4[a1],a8
+ ldw.d1 *a4++[1],a6
+ ldw.d1 *++a4(4),a6
+ ldb.d2 *+b14[36],b1
+
+ lmbd a1,a2,a3
+
+ mpy.m1 a1,a2,a3
+ mpyu.m1 a1,a2,a3
+ mpyus.m1 a1,a2,a3
+ mpy.m1 13,a1,a2
+ mpysu.m1 13,a1,a2
+ mpyh.m1 a1,a2,a3
+ mpyhu.m1 a1,a2,a3
+ mpyhsu.m1 a1,a2,a3
+ mpyhl.m1 a1,a2,a3
+ mpylh.m1 a1,a2,a3
+
+ mvc.s2 a1,amr
+ mvc istp,b4
+
+ mvk.s1 293,a1
+ mvk.s2 125h,b1
+ mvk.s1 0ff12h,a1
+ mvkh.s1 0a329123h,a1
+ mvklh 7a8h,a1
+
+ norm a1,a2
+ norm a1:a0,a2
+
+ sadd.l1 a1,a2,a3
+ sadd.l1 b2,a5:a4,a7:a6
+
+ sat.l1 a1:a0,a2
+ sat.l2 b1:b0,b5
+
+ set.s1 a0,7,21,a1
+ set.s2 b0,b1,b2
+
+ shl.s1 a0,4,a1
+ shl.s2 b0,b1,b2
+ shl.s2 b1:b0,b2,b3:b2
+
+ shr.s1 a0,8,a1
+ shr.s2 b0,b1,b2
+ shr.s2 b1:b0,b2,b3:b2
+
+ shru.s1 a0,8,a1
+
+ smpy.m1 a1,a2,a3
+ smpyhl.m1 a1,a2,a3
+ smpylh.m1 a1,a2,a3
+
+ sshl.s1 a0,2,a1
+ sshl.s1 a0,a1,a2
+
+ ssub.l2 b1,b2,b3
+ ssub.l1 a0,a1,a2
+
+ stb.d1 a1,*a10
+ sth.d1 a1,*+a10(4)
+ stw.d1 a1,*++a10[1]
+ sth.d1 a1,*a10--[a11]
+ stb.d2 b1,*+b14[40]
+
+ align 32
+ mvk.s1 2c80h,a0
+|| mvk.s2 0200h,b0
+ mvkh.s1 01880000h,a0
+|| mvkh.s2 00000000h,b0
+ mvc.s2 a0,pdata_o
+ stp.s2 b0
+ nop 4
+ mpy.m1 a1,a2,a3
+
+ sub.l1 a1,a2,a3
+ subu.l1 a1,a2,a5:a4
+ subc.l1 a0,a1,a0
+
+ align 32
+ ifdef error
+ add.s1 a0,a1,a2
+|| shr.s1 a3,15,a4
+ endif
+ add.l1 a0,a1,a2
+|| shr.s1 a3,15,a4
+
+ align 32
+ ifdef error
+ add.l1x a0,b1,a1
+|| mpy.m1x a4,b4,a5
+ endif
+ add.l1x a0,b1,a1
+|| mpy.m2x a4,b4,b2
+
+ align 32
+ ifdef error
+ ldw.d1 *a0,a1
+|| ldw.d1 *a2,b2
+ endif
+ ldw.d1 *a0,a1
+|| ldw.d2 *b0,b2
+
+ align 32
+ ifdef error
+ ldw.d1 *a4,a5
+|| stw.d2 a6,*b4
+ endif
+ ldw.d1 *a4,b4
+|| stw.d2 a6,*b4
+
+ align 32
+ ifdef error
+ add.l1 a5:a4,a1,a3:a2
+|| shl.s1 a8,a9,a7:a6
+ endif
+ add.l1 a5:a4,a1,a3:a2
+|| shl.s2 b8,b9,b7:b6
+
+ align 32
+ ifdef error
+ add.l1 a5:a4,a1,a3:a2
+|| stw.d1 a8,*a9
+ endif
+ add.l1 a4,a1,a3:a2
+|| stw.d1 a8,*a9
+
+ align 32
+ ifdef error
+ mpy.m1 a1,a1,a4
+|| add.l1 a1,a1,a5
+|| sub.d1 a1,a2,a3
+ endif
+ mpy.m1 a1,a1,a4
+|| [a1] add.l1 a0,a1,a5
+|| sub.d1 a1,a2,a3
+
+ align 32
+ ifdef error
+ add.l2 b5,b6,b7
+|| sub.s2 b8,b9,b7
+ endif
+[!b0] add.l2 b5,b6,b7
+|| [b0] sub.s2 b8,b9,b7
+
diff --git a/tests/t_3206x/t_3206x.doc b/tests/t_3206x/t_3206x.doc
new file mode 100644
index 0000000..ddfa640
--- /dev/null
+++ b/tests/t_3206x/t_3206x.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 3206x ---------------------------+
+| |
+| This is a (synthetic) test of the TMS320C6x instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_3206x/t_3206x.ori b/tests/t_3206x/t_3206x.ori
new file mode 100644
index 0000000..d8cf606
--- /dev/null
+++ b/tests/t_3206x/t_3206x.ori
Binary files differ
diff --git a/tests/t_370/asflags b/tests/t_370/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_370/asflags
diff --git a/tests/t_370/t_370.asm b/tests/t_370/t_370.asm
new file mode 100644
index 0000000..120f985
--- /dev/null
+++ b/tests/t_370/t_370.asm
@@ -0,0 +1,163 @@
+ page 0
+
+ cpu 370c010
+
+cat equ r16
+dog equ r011
+mouse equ p055
+rat equ p127
+
+ clrc
+ setc
+ dint
+ eint
+ eintl
+ einth
+ idle
+ ldsp
+ stsp
+ nop
+ rti
+ rts
+
+Targ: jmp Targ
+ jc Targ
+ jeq Targ
+ jg Targ
+ jge Targ
+ jhs Targ
+ jl Targ
+ jle Targ
+ jlo Targ
+ jn Targ
+ jnc Targ
+ jne Targ
+ jnv Targ
+ jnz Targ
+ jp Targ
+ jpz Targ
+ jv Targ
+ jz Targ
+
+ adc b,a
+ add dog,a
+ dac cat,b
+ dsb dog,cat
+ sbb #55h,a
+ sub #0aah,b
+ mpy #' ',dog
+
+ and a,p050
+ btjo b,a,Targ
+ btjz b,p10,Targ
+ or cat,a
+ xor dog,b
+ and r020,r10
+ btjo #55,a,Targ
+ btjz #66,b,Targ
+ or #77,r10
+ xor #88,rat
+
+ br Targ
+ br @dog
+ br Targ(b)
+ br 10(cat)
+ call Targ
+ call @dog
+ call Targ(b)
+ call 10(cat)
+ callr Targ
+ callr @dog
+ callr Targ(b)
+ callr 10(cat)
+ jmpl Targ
+ jmpl @dog
+ jmpl Targ(b)
+ jmpl 10(cat)
+
+ clr a
+ compl b
+ dec cat
+ inc a
+ inv b
+ pop dog
+ push a
+ pop st
+ push st
+ rl b
+ rlc r020
+ rr a
+ rrc b
+ swap dog
+ xchb a
+ djnz b,$
+
+ cmp 2000h,a
+ cmp @dog,a
+ cmp targ(b),a
+ cmp 10(cat),a
+ cmp -5(sp),a
+ cmp b,a
+ cmp dog,a
+ cmp cat,b
+ cmp cat,dog
+ cmp #55h,a
+ cmp #66h,b
+ cmp #77h,r0ff
+
+bit1 dbit 1,r12
+bit2 dbit 4,p033
+bit3 dbit 5,b
+
+ cmpbit bit1
+ cmpbit bit2
+ jbit0 bit1,$
+ jbit0 bit2,$
+ jbit1 bit1,$
+ jbit1 bit2,$
+ sbit0 bit1
+ sbit0 bit2
+ sbit1 bit1
+ sbit1 bit2
+
+ div r45,a
+ incw #56h,dog
+ ldst #12
+
+ mov a,b
+ mov a,cat
+ mov a,mouse
+ mov a,1234h
+ mov a,@r33
+ mov a,Targ(b)
+ mov a,15(r015)
+ mov a,-2(sp)
+ mov dog,a
+ mov cat,b
+ mov 1234h,a
+ mov @dog,a
+ mov Targ(b),a
+ mov -33(cat),a
+ mov 15(sp),a
+ mov b,a
+ mov b,dog
+ mov b,rat
+ mov cat,dog
+ mov dog,mouse
+ mov rat,a
+ mov p15,b
+ mov p15,r015
+ mov #11h,a
+ mov #-1,b
+ mov #0110110b,r10
+ mov #10h,rat
+
+ movw cat,dog
+ movw #12345,r010
+ movw #Targ(b),cat
+ movw #(cat),cat
+
+ trap 7
+
+ tst a
+ tst b
diff --git a/tests/t_370/t_370.doc b/tests/t_370/t_370.doc
new file mode 100644
index 0000000..da6bdb5
--- /dev/null
+++ b/tests/t_370/t_370.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application 370 ----------------------------+
+| |
+| This is a (synthetic) test of the TMS370 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_370/t_370.ori b/tests/t_370/t_370.ori
new file mode 100644
index 0000000..75db2ab
--- /dev/null
+++ b/tests/t_370/t_370.ori
Binary files differ
diff --git a/tests/t_4004/asflags b/tests/t_4004/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_4004/asflags
diff --git a/tests/t_4004/t_4004.asm b/tests/t_4004/t_4004.asm
new file mode 100644
index 0000000..fc6d55f
--- /dev/null
+++ b/tests/t_4004/t_4004.asm
@@ -0,0 +1,205 @@
+ cpu 4004
+
+ nop
+
+ jcn z, Next
+ jcn nz, Next
+ jcn c, Next
+ jcn nc, Next
+ jcn t, Next
+ jcn nt, Next
+ jcm z, Next
+ jcm nz, Next
+ jcm c, Next
+ jcm nc, Next
+ jcm t, Next
+ jcm nt, Next
+Next:
+ fim r0r1, 12h
+ fim r2r3, 23h
+ fim r4r5, 34h
+ fim r6r7, 45h
+ fim r8r9, 56h
+ fim rarb, 67h
+ fim rcrd, 78h
+ fim rerf, 89h
+
+ src r0r1
+ src r2r3
+ src r4r5
+ src r6r7
+ src r8r9
+ src rarb
+ src rcrd
+ src rerf
+
+ fin r0r1
+ fin r2r3
+ fin r4r5
+ fin r6r7
+ fin r8r9
+ fin rarb
+ fin rcrd
+ fin rerf
+
+ jin r0r1
+ jin r2r3
+ jin r4r5
+ jin r6r7
+ jin r8r9
+ jin rarb
+ jin rcrd
+ jin rerf
+
+ jun 123h
+ jms 456h
+
+ inc r0
+ inc r1
+ inc r2
+ inc r3
+ inc r4
+ inc r5
+ inc r6
+ inc r7
+ inc r8
+ inc r9
+ inc ra
+ inc rb
+ inc rc
+ inc rd
+ inc re
+ inc rf
+
+loop:
+ isz r0, loop
+ isz r1, loop
+ isz r2, loop
+ isz r3, loop
+ isz r4, loop
+ isz r5, loop
+ isz r6, loop
+ isz r7, loop
+ isz r8, loop
+ isz r9, loop
+ isz ra, loop
+ isz rb, loop
+ isz rc, loop
+ isz rd, loop
+ isz re, loop
+ isz rf, loop
+
+ add a, r0
+ add a, r1
+ add a, r2
+ add a, r3
+ add a, r4
+ add a, r5
+ add a, r6
+ add a, r7
+ add a, r8
+ add a, r9
+ add a, ra
+ add a, rb
+ add a, rc
+ add a, rd
+ add a, re
+ add a, rf
+
+ sub a, r0
+ sub a, r1
+ sub a, r2
+ sub a, r3
+ sub a, r4
+ sub a, r5
+ sub a, r6
+ sub a, r7
+ sub a, r8
+ sub a, r9
+ sub a, ra
+ sub a, rb
+ sub a, rc
+ sub a, rd
+ sub a, re
+ sub a, rf
+
+ ld a, r0
+ ld a, r1
+ ld a, r2
+ ld a, r3
+ ld a, r4
+ ld a, r5
+ ld a, r6
+ ld a, r7
+ ld a, r8
+ ld a, r9
+ ld a, ra
+ ld a, rb
+ ld a, rc
+ ld a, rd
+ ld a, re
+ ld a, rf
+
+ xch r0
+ xch r1
+ xch r2
+ xch r3
+ xch r4
+ xch r5
+ xch r6
+ xch r7
+ xch r8
+ xch r9
+ xch ra
+ xch rb
+ xch rc
+ xch rd
+ xch re
+ xch rf
+
+ bbl 1
+ bbl 3
+ bbl 0dh
+
+ ldm 1
+ ldm 3
+ ldm 0dh
+
+ wrm
+ wmp
+ wrr
+ wpm
+ wr0
+ wr1
+ wr2
+ wr3
+ sbm
+ rdm
+ rdr
+ adm
+ ad0
+ ad1
+ ad2
+ ad3
+ rd0
+ rd1
+ rd2
+ rd3
+
+ clb
+ clc
+ iac
+ cmc
+ cma
+ ral
+ rar
+ tcc
+ dac
+ tcs
+ stc
+ daa
+ kbp
+ dcl
+
+ data 1,2,3,4,5
+ data "This is a test"
diff --git a/tests/t_4004/t_4004.doc b/tests/t_4004/t_4004.doc
new file mode 100644
index 0000000..a5f66e1
--- /dev/null
+++ b/tests/t_4004/t_4004.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 4004 ----------------------------+
+| |
+| This is a (synthetic) test of the 4004 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_4004/t_4004.ori b/tests/t_4004/t_4004.ori
new file mode 100644
index 0000000..e508c0c
--- /dev/null
+++ b/tests/t_4004/t_4004.ori
Binary files differ
diff --git a/tests/t_403/asflags b/tests/t_403/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_403/asflags
diff --git a/tests/t_403/t_403.asm b/tests/t_403/t_403.asm
new file mode 100644
index 0000000..0ee143a
--- /dev/null
+++ b/tests/t_403/t_403.asm
@@ -0,0 +1,27 @@
+ cpu ppc403
+ page 0
+ include stddef60
+
+ org 0x1000
+
+
+ mtdcr 10,r5
+ mtbear r5
+ mfdcr r5,10
+ mfbesr r5
+ wrtee r10
+ wrteei 1
+
+ bdnzl 0x10
+ bdztla 7,0x10
+ beq 0x10
+ beq 2,0x10
+ beq cr2,0x10
+
+ cmpw r1,r2
+ clrlwi r1,r2,5
+
+ mtspr pit,r5
+
+ mcrf cr4,cr5
+ mcrf 4,5
diff --git a/tests/t_403/t_403.doc b/tests/t_403/t_403.doc
new file mode 100644
index 0000000..893ca08
--- /dev/null
+++ b/tests/t_403/t_403.doc
@@ -0,0 +1,6 @@
++------------------------- Test Application 403 -----------------------------+
+| |
+| This is a (synthetic) test of the PPC403's extensions to the PowerPC |
+| basic instruction set. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_403/t_403.ori b/tests/t_403/t_403.ori
new file mode 100644
index 0000000..8bae53a
--- /dev/null
+++ b/tests/t_403/t_403.ori
Binary files differ
diff --git a/tests/t_4500/asflags b/tests/t_4500/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_4500/asflags
diff --git a/tests/t_4500/t_4500.asm b/tests/t_4500/t_4500.asm
new file mode 100644
index 0000000..5e9f028
--- /dev/null
+++ b/tests/t_4500/t_4500.asm
@@ -0,0 +1,109 @@
+ cpu melps4500
+
+ a 10
+ am
+ amc
+ and
+ b $20
+ bl $20,$20
+ bl $1234
+ bla 7
+ bm $110
+ bml $20,$20
+ bml $1234
+ bmla 7
+ cld
+ cma
+ dey
+ di
+ ei
+ iap0
+ iap1
+ iap2
+ iap3
+ iap4
+ iny
+ la $c
+ lxy 2,3
+ lxy $ac
+ lz %10
+ nop
+ or
+ op0a
+ op1a
+ pof
+ pof2
+ rar
+ rb 2
+ rc
+ rc3
+ rc4
+ rd
+ rt
+ rti
+ rts
+ sb 1
+ sc
+ sc3
+ sc4
+ sd
+ sea 3
+ seam
+ snz0
+ snzp
+ snzt1
+ snzt2
+ snzt3
+ spcr
+ stcr
+ szb 3
+ szc
+ szd
+ t1r1
+ t3ab
+ tab
+ tab3
+ tabe
+ tabp 1
+ tad
+ tai1
+ tal1
+ tam 7
+ tamr
+ tasp
+ tav1
+ taw1
+ taw2
+ taw3
+ tax
+ tay
+ taz
+ tba
+ tc1a
+ tc2a
+ tda
+ teab
+ ti1a
+ tl1a
+ tl2a
+ tl3a
+ tlca
+ tma 12
+ tmra
+ tpta
+ tpaa
+ tr1a
+ tr1ab
+ tv1a
+ tw1a
+ tw2a
+ tw3a
+ tya
+ wrst
+ xam 2
+ xamd 12
+ xami 6
+
+ res 5
+ data 10,1000,-13,'A'
+ data "ABC"
diff --git a/tests/t_4500/t_4500.doc b/tests/t_4500/t_4500.doc
new file mode 100644
index 0000000..7cb1aec
--- /dev/null
+++ b/tests/t_4500/t_4500.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 4500 ----------------------------+
+| |
+| This is a (synthetic) test of the MELPS/45xx instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_4500/t_4500.ori b/tests/t_4500/t_4500.ori
new file mode 100644
index 0000000..727e60d
--- /dev/null
+++ b/tests/t_4500/t_4500.ori
Binary files differ
diff --git a/tests/t_47c00/asflags b/tests/t_47c00/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_47c00/asflags
diff --git a/tests/t_47c00/t_47c00.asm b/tests/t_47c00/t_47c00.asm
new file mode 100644
index 0000000..30ab5d9
--- /dev/null
+++ b/tests/t_47c00/t_47c00.asm
@@ -0,0 +1,255 @@
+ cpu 470ac00
+ include stddef47.inc
+
+ page 0
+
+
+ segment data
+
+nvar1 db ?
+nvar2 db ?
+ align 4
+bvar db 2 dup (?)
+
+
+ segment io
+
+port1 db ?
+port2 db ?
+port3 port 7
+
+ segment code
+
+targ: db ?
+
+ ret
+ nop
+ reti
+
+ inc @hl
+ dec @hl
+ inc a
+ dec a
+ inc l
+ dec l
+
+ and a,@hl
+ and @hl,#3
+ and a,#5
+ or a,@hl
+ or @hl,#3
+ or a,#5
+ xor a,@hl
+
+ ld a,@hl
+ ld a,123
+ ld hl,bvar
+ ld a,#4
+ ld h,#-3
+ ld l,#7
+ ld hl,#0a5h
+ ld dmb,#2
+ ld dmb,@hl
+
+ ldl a,@dc
+ ldh a,@dc+
+
+ st a,@hl
+ st a,@hl+
+ st a,@hl-
+ st a,123
+ st #3,@hl+
+ st #5,nvar1
+ st dmb,@hl
+
+ mov h,a
+ mov l,a
+ mov a,dmb
+ mov dmb,a
+ mov a,spw13
+ mov stk13,a
+
+ xch a,@hl
+ xch nvar2,a
+ xch hl,bvar
+ xch a,l
+ xch h,a
+ xch eir,a
+
+ in %port1,a
+ in %15h,a
+ in %port2,@hl
+ in %1ah,@hl
+
+ out a,%port1
+ out @hl,%port2
+ out #-3,%port2
+
+ outb @hl
+
+ cmpr a,@hl
+ cmpr a,nvar2
+ cmpr nvar2,#3
+ cmpr a,#4
+ cmpr h,#5
+ cmpr l,#6
+
+ add a,@hl
+ add @hl,#4
+ add nvar2,#5
+ add a,#6
+ add h,#7
+ add l,#7
+
+ addc a,@hl
+ subrc a,@hl
+
+ subr a,#7
+ subr @hl,#0ah
+
+ rolc a
+ rolc a,3
+ rorc a
+ rorc a,2
+
+ clr @l
+ set @l
+ test @l
+
+ test cf
+ testp cf
+
+ testp zf
+
+; clr gf
+; set gf
+; testp gf
+
+; clr dmb
+; set dmb
+; test dmb
+; testp dmb
+
+ clr dmb0
+ set dmb0
+ test dmb0
+ testp dmb0
+
+ clr dmb1
+ set dmb1
+ test dmb1
+ testp dmb1
+
+ clr stk13
+ set stk13
+
+ clr il,8h
+
+ test a,2
+
+ clr @hl,1
+ set @hl,3
+ test @hl,2
+
+ clr %5,1
+ set %6,3
+ test %7,2
+ testp %8,0
+
+ clr nvar2,1
+ set nvar2,3
+ test nvar2,2
+ testp nvar2,0
+
+ bss ($&3fc0h)+20h
+ bs 123h
+ bsl 0123h
+ bsl 1123h
+ bsl 2123h
+ bsl 3123h
+
+ calls 002eh
+
+ call 123h
+
+ eiclr il,3
+ diclr il,5
+
+ b ($&3fc0h)+20h
+ b 123h
+ b 0123h
+ b 1123h
+ b 2123h
+ b 3123h
+
+ bz targ
+ bnz targ
+ bc targ
+ bnc targ
+ be a,@hl,targ
+ be a,nvar2,targ
+ be a,#3,targ
+ be h,#4,targ
+ be l,#5,targ
+ be nvar1,#6,targ
+ bne a,@hl,targ
+ bne a,nvar2,targ
+ bne a,#3,targ
+ bne h,#4,targ
+ bne l,#5,targ
+ bne nvar1,#6,targ
+ bge a,@hl,targ
+ bge a,nvar2,targ
+ bge a,#3,targ
+ bge h,#4,targ
+ bge l,#5,targ
+ bge nvar1,#6,targ
+ bgt a,@hl,targ
+ bgt a,nvar2,targ
+ bgt a,#3,targ
+ bgt h,#4,targ
+ bgt l,#5,targ
+ bgt nvar1,#6,targ
+ ble a,@hl,targ
+ ble a,nvar2,targ
+ ble a,#3,targ
+ ble h,#4,targ
+ ble l,#5,targ
+ ble nvar1,#6,targ
+ blt a,@hl,targ
+ blt a,nvar2,targ
+ blt a,#3,targ
+ blt h,#4,targ
+ blt l,#5,targ
+ blt nvar1,#6,targ
+
+ callss 0
+ callss 5
+
+ callz targ
+ callnz targ
+ callc targ
+ callnc targ
+
+ retz
+ retnz
+ retc
+ retnc
+ retiz
+ retinz
+ retic
+ retinc
+
+ shl a,2
+ shl h,2
+ shl l,2
+ shl @hl,2
+ shl nvar1,2
+ shr a,2
+ shr h,2
+ shr l,2
+ shr @hl,2
+ shr nvar1,2
+
+ ei
+ di \ No newline at end of file
diff --git a/tests/t_47c00/t_47c00.doc b/tests/t_47c00/t_47c00.doc
new file mode 100644
index 0000000..23953b5
--- /dev/null
+++ b/tests/t_47c00/t_47c00.doc
@@ -0,0 +1,5 @@
++------------------------ Test Application 47C00 ----------------------------+
+| |
+| This is a (synthetic) test of the TLCS-47(0(A)) instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_47c00/t_47c00.ori b/tests/t_47c00/t_47c00.ori
new file mode 100644
index 0000000..122b6d9
--- /dev/null
+++ b/tests/t_47c00/t_47c00.ori
Binary files differ
diff --git a/tests/t_48/asflags b/tests/t_48/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_48/asflags
diff --git a/tests/t_48/t_48.asm b/tests/t_48/t_48.asm
new file mode 100644
index 0000000..fc50424
--- /dev/null
+++ b/tests/t_48/t_48.asm
@@ -0,0 +1,178 @@
+ cpu 8048
+
+ add a,r2
+ add a,@r1
+ add a,#21h
+
+ addc a,r3
+ addc a,@r1
+ addc a,#21h
+
+ anl a,r4
+ anl a,@r1
+ anl a,#21h
+ anl bus,#12h
+
+ anld p5,a
+
+ call 345h
+
+ clr a
+ clr c
+ clr f0
+ clr f1
+
+ cpl a
+ cpl c
+ cpl f0
+ cpl f1
+
+ da a
+
+ dec a
+ dec r1
+
+ dis i
+ dis tcnti
+
+ djnz r2,$
+
+ en i
+ en tcnti
+
+ ent0 clk
+
+ in a,p1
+ in a,p2
+
+ inc a
+ inc r7
+ inc @r1
+
+ ins a,bus
+
+ jb3 $
+
+ jc $
+
+ jf0 $
+ jf1 $
+
+ jmp 123h
+
+ jnc $
+
+ jni $
+
+ jnt0 $
+ jnt1 $
+
+ jnz $
+
+ jt0 $
+ jt1 $
+
+ jtf $
+
+ jz $
+
+ jmpp @a
+
+ mov a,r2
+ mov a,@r1
+ mov a,#21h
+ mov r3,a
+ mov @r1,a
+ mov r4,#21h
+ mov @r1,#21h
+ mov a,psw
+ mov psw,a
+ mov a,t
+ mov t,a
+
+ movd a,p5
+ movd p6,a
+
+ movx a,@r1
+ movx @r1,a
+
+ movp a,@a
+ movp3 a,@a
+
+ nop
+
+ orl a,r5
+ orl a,@r1
+ orl a,#21h
+ orl bus,#12h
+
+ orld p5,a
+
+ outl p1,a
+ outl p2,a
+ outl bus,a
+
+ ret
+
+ retr
+
+ rl a
+
+ rlc a
+
+ rr a
+
+ rrc a
+
+ sel mb0
+ sel mb1
+ sel rb0
+ sel rb1
+
+ strt cnt
+ strt t
+
+ stop tcnt
+
+ swap a
+
+ xch a,r5
+ xch a,@r1
+
+ xchd a,@r1
+
+ xrl a,r6
+ xrl a,@r1
+ xrl a,#21h
+
+
+ cpu 8041
+
+ en dma
+ en flags
+
+ in a,dbb
+
+ jnibf $
+
+ jobf $
+
+ mov sts,a
+
+ out dbb,a
+
+
+ cpu 80c39
+
+ idl
+
+
+ cpu 8022
+
+ in a,p0
+ outl p0,a
+
+ sel an0
+ sel an1
+ rad
+
diff --git a/tests/t_48/t_48.doc b/tests/t_48/t_48.doc
new file mode 100644
index 0000000..1ca6179
--- /dev/null
+++ b/tests/t_48/t_48.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application 48 -----------------------------+
+| |
+| This is a (synthetic) test of the MCS-48 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_48/t_48.ori b/tests/t_48/t_48.ori
new file mode 100644
index 0000000..15d3a3b
--- /dev/null
+++ b/tests/t_48/t_48.ori
Binary files differ
diff --git a/tests/t_56000/asflags b/tests/t_56000/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_56000/asflags
diff --git a/tests/t_56000/t_56000.asm b/tests/t_56000/t_56000.asm
new file mode 100644
index 0000000..acf594f
--- /dev/null
+++ b/tests/t_56000/t_56000.asm
@@ -0,0 +1,244 @@
+ page 0
+
+ cpu 56000
+
+ include stddef56k.inc
+
+ segment code
+ org $300
+
+ nop
+ enddo
+ illegal
+ reset
+ rti
+ rts
+ stop
+ swi
+ wait
+
+ jmp $214
+ jsr $889
+ jmp $3567
+ jsr $2340
+ jmp (r3)
+ jsr (r5)
+ jmp (r6)+
+ jsr (r1)+
+ jmp (r4)-
+ jsr (r2)-
+ jmp -(r5)
+ jsr -(r0)
+ jmp (r3+n3)
+ jsr (r7+n7)
+ jmp (r2)+n2
+ jsr (r6)+n6
+ jmp (r5)-n5
+ jsr (r3)-n3
+
+ jcc $123
+ jge $2345
+ jne (r7)
+ jpl (r6)-
+ jnn (r5)+
+ jec -(r4)
+ jlc (r3+n3)
+ jgt (r2)+n2
+ jcs (r1)-n1
+ jlt $123
+ jeq $2345
+ jmi (r0)
+ jnr (r1)-
+ jes (r2)+
+ jls -(r3)
+ jle (r4+n4)
+ jhs (r5)+n5
+ jlo (r6)-n6
+
+ jsnn $768
+ jsle (r0)
+
+
+ move (r3)+n3
+ move (r4)-n4
+ move (r2)-
+ move (r6)+
+
+ move n5,a2
+ move r4,b1
+ move a0,b2
+ move a,r4
+
+ move #$30,n5
+ move #$ff,r3
+
+ move x:#$123456,a0
+ move y:#$234567,y1
+ move #$345678,r5
+ move y:#$456789,n1
+
+ move x:$12,b2
+ move y:$34,n6
+ move x:$1234,a
+ move y:$2345,b2
+ move b2,x:$12
+ move n6,y:$34
+ move a,x:$1234
+ move b2,y:$2345
+
+ move x:(r3),a0
+ move y:(r4)+n4,x1
+ move a0,x:(r3)
+ move x1,y:(r4)+n4
+
+ move l:$12,ab
+ move $3456,y
+ move ab,l:$12
+ move y,$3456
+
+ move b,x:(r1)+ x0,b
+ move y0,b b,y:(r1)+
+
+ move x1,x:(r2)+ a,y:(r5)+n5
+ move x:(r2)+,x1 a,y:(r5)+n5
+ move x:(r2)+,x1 y:(r5)+n5,a
+
+ move x:(r5),x1 a,y1
+ move a,x:-(r1) b,y0
+ move b,x:$1234 a,y0
+ move #$234567,x0 b,y1
+
+ move b,x1 y:(r6)-n6,b
+
+ abs a #$123456,x0 a,y0
+ asl a (r3)-
+ asr b x:-(r3),r3
+ clr a #$7f,n0
+ lsl b #$7f,r0
+ lsr a a1,n4
+ neg b x1,x:(r3)+ y:(r6)-,a
+ not a ab,l:(r2)+
+ rnd a #$123456,x1 b,y1
+ rol a #$314,n2
+ ror b #$1234,r2
+ tst a #$345678,b
+ adc y,b a10,l:$4
+ sbc y,b a10,l:$4
+ add x0,a a,x1 a,y:(r1)+
+ cmp y0,b x0,x:(r6)+n6 y1,y:(r0)-
+ cmpm x1,a ba,l:-(r4)
+ sub x1,a x:(r2)+n2,r0
+ addl a,b #$0,r0
+ addr b,a x0,x:(r1)+n1 y0,y:(r4)-
+ subl a,b y:(r5+n5),r7
+ subr b,a n5,y:-(r5)
+ and x0,a (r5)-n5
+ eor y1,b (r2)+
+ or y1,b ba,l:$1234
+ mac x0,x0,a x:(r2)+n2,y1
+ macr x0,y0,b y:(r4)+n4,y0
+ mpy -x1,y1,a #$543210,y0
+ mpyr -y0,y0,b (r3)-n3
+
+ bchg #$7,x:$ffe2
+ bclr #$e,x:$ffe4
+ bset #$0,x:$ffe5
+ btst #$1,x:$ffee
+ bclr #$4,y:$ffe0
+ bclr #$5,x:$0020
+ bclr #$6,y:$0012
+ bclr #$7,x:$1234
+ bclr #$8,y:(r3)+
+ bclr #$9,r5
+ bclr #$a,m6
+ bclr #$b,omr
+
+ div x1,b
+
+ do x:(r3),$1234
+ do y:(r5+n5),$2345
+ do x:$12,$3456
+ do y:$23,$4567
+ do #$123,$5678
+ do n7,$6789
+
+ jclr #$5,x:$fff1,$1234
+ jsclr #$1,y:$ffe3,$1357
+ jset #12,x:$fff2,$4321
+ jsset #$17,y:$3f,$100
+ jclr #21,x:(r5),$6789
+ jclr #22,ssh,$5678
+
+ lua (r0)+n0,r1
+
+ movec m0,m2
+ movec m4,r2
+ movec n5,ssl
+ movec #0,omr
+ movec #123456,ssh
+ movec x:$12,m2
+ movec m2,x:$12
+ movec y:$23,m2
+ movec m2,y:$23
+ movec x:(r4),m5
+ movec m5,y:(r4)
+ movec y:(r4),m5
+ movec m5,x:(r4)
+
+ movem m4,$12
+ movem $12,m4
+ movem $123,m4
+ movem m4,$123
+
+ andi #2,ccr
+ ori #5,omr
+
+ norm r5,a
+ norm r2,b
+
+ rep r4
+ rep #$987
+ rep x:$12
+ rep y:$23
+ rep x:(r3)
+ rep y:$12
+
+ movep x:(r3),x:$ffe0
+ movep y:(r3),x:$ffe1
+ movep #$123456,x:$ffe2
+ movep x:$ffe3,x:(r3)
+ movep x:$ffe4,y:(r3)
+ movep x:(r3),y:$ffe5
+ movep y:(r3),y:$ffe6
+ movep #$123456,y:$ffe7
+ movep y:$ffe8,x:(r3)
+ movep y:$ffe9,y:(r3)
+ movep p:(r3),x:$ffea
+ movep x:$ffeb,p:(r3)
+ movep p:(r3),y:$ffec
+ movep y:$ffed,p:(r3)
+ movep a1,x:$ffef
+ movep x:$fff0,r3
+ movep n5,y:$fff1
+ movep y:$fff2,m1
+
+ tfr a,b a,x1 y:(r4+n4),y0
+ tfr y0,a
+
+ tgt x0,a r0,r1
+ tne y1,a
+
+ dc "Hallo"
+ dc '123'
+ dc $123456
+ dc "Dies ist ein Test, Leute" 0
+
+ segment xdata
+
+ org $123
+var1: ds 1
+
+ segment ydata
+
+ org $234
+var2: ds 1
diff --git a/tests/t_56000/t_56000.doc b/tests/t_56000/t_56000.doc
new file mode 100644
index 0000000..326f888
--- /dev/null
+++ b/tests/t_56000/t_56000.doc
@@ -0,0 +1,5 @@
++---------------------- Test Application 56000 ----------------------------+
+| |
+| This is a (synthetic) test of the DSP56K code generator |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_56000/t_56000.ori b/tests/t_56000/t_56000.ori
new file mode 100644
index 0000000..e661401
--- /dev/null
+++ b/tests/t_56000/t_56000.ori
Binary files differ
diff --git a/tests/t_56300/asflags b/tests/t_56300/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_56300/asflags
diff --git a/tests/t_56300/t_56300.asm b/tests/t_56300/t_56300.asm
new file mode 100644
index 0000000..d392a11
--- /dev/null
+++ b/tests/t_56300/t_56300.asm
@@ -0,0 +1,1462 @@
+ cpu 56300
+ page 0
+
+ org $8000
+
+ abs a ; >=56000
+ abs b
+
+ adc x,a ; >=56000
+ adc y,a
+ adc x,b
+ adc y,b
+
+ add x0,a ; >=56000
+ add x1,a
+ add y0,a
+ add y1,a
+ add x,a
+ add y,a
+ add b,a
+ add x0,b ; >=56000
+ add x1,b
+ add y0,b
+ add y1,b
+ add x,b
+ add y,b
+ add a,b
+
+ add #31,a ; >=56300
+ add #1234,a
+ add #31,b
+ add #1234,b
+
+ addl b,a ; >=56000
+ addl a,b
+
+ addr b,a
+ addr a,b
+
+ and x0,a ; >=56000
+ and x1,a
+ and y0,a
+ and y1,a
+ and x0,b
+ and x1,b
+ and y0,b
+ and y1,b
+
+ and #31,a ; >=56000
+ and #1234,a
+ and #31,b
+ and #1234,b
+
+ andi #$12,mr ; >=56000
+ andi #$12,ccr
+ andi #$12,com
+ andi #$12,eom
+
+ asl a ; >=56000
+ asl b
+ asl #$23,a,a ; >=56300
+ asl #$23,a,b
+ asl #$23,b,a
+ asl #$23,b,b
+ asl a1,a,a ; >=56300
+ asl b1,a,a
+ asl x0,a,a
+ asl y0,a,a
+ asl x1,a,a
+ asl y1,a,a
+ asl a1,a,b
+ asl b1,a,b
+ asl x0,a,b
+ asl y0,a,b
+ asl x1,a,b
+ asl y1,a,b
+ asl a1,b,a
+ asl b1,b,a
+ asl x0,b,a
+ asl y0,b,a
+ asl x1,b,a
+ asl y1,b,a
+ asl a1,b,b
+ asl b1,b,b
+ asl x0,b,b
+ asl y0,b,b
+ asl x1,b,b
+ asl y1,b,b
+
+ asr a ; >=56000
+ asr b
+ asr #$23,a,a ; >=56300
+ asr #$23,a,b
+ asr #$23,b,a
+ asr #$23,b,b
+ asr a1,a,a ; >=56300
+ asr b1,a,a
+ asr x0,a,a
+ asr y0,a,a
+ asr x1,a,a
+ asr y1,a,a
+ asr a1,a,b
+ asr b1,a,b
+ asr x0,a,b
+ asr y0,a,b
+ asr x1,a,b
+ asr y1,a,b
+ asr a1,b,a
+ asr b1,b,a
+ asr x0,b,a
+ asr y0,b,a
+ asr x1,b,a
+ asr y1,b,a
+ asr a1,b,b
+ asr b1,b,b
+ asr x0,b,b
+ asr y0,b,b
+ asr x1,b,b
+ asr y1,b,b
+
+ bcc *+$2000
+ bge *+$20
+ bne r3
+ bpl *-$2000
+ bnn *-$20
+ bec r4
+ blc >*+$20
+ bgt <*-$20
+ bcs *+$2000
+ blt *+$20
+ beq r5
+ bmi *-$2000
+ bnr *-$20
+ bes r6
+ bls >*+$20
+ ble <*-$20
+ bhs *+$2000
+ blo *+$20
+
+ bchg #2,x:(r1)-n1 ; >=56000
+ bchg #2,y:(r1)-n1
+ bchg #3,x:(r2)+n2
+ bchg #3,y:(r2)+n2
+ bchg #4,x:(r3)-
+ bchg #4,y:(r3)-
+ bchg #5,x:(r4)+
+ bchg #5,y:(r4)+
+ bchg #6,x:(r5)
+ bchg #6,y:(r5)
+ bchg #7,x:(r6+n6)
+ bchg #7,y:(r6+n6)
+ bchg #8,x:-(r7)
+ bchg #8,y:-(r7)
+ bchg #9,x:$1234
+ bchg #9,y:$1234
+ bchg #11,x:$20
+ bchg #11,y:$20
+ bchg #13,x:$ffffca
+ bchg #13,y:$ffffca
+ bchg #7,x:$ffff95 ; >=56300
+ bchg #7,y:$ffff95
+ bchg #10,r6 ; >=56000
+ bchg #10,b
+
+ bclr #2,x:(r1)-n1 ; >=56000
+ bclr #2,y:(r1)-n1
+ bclr #3,x:(r2)+n2
+ bclr #3,y:(r2)+n2
+ bclr #4,x:(r3)-
+ bclr #4,y:(r3)-
+ bclr #5,x:(r4)+
+ bclr #5,y:(r4)+
+ bclr #6,x:(r5)
+ bclr #6,y:(r5)
+ bclr #7,x:(r6+n6)
+ bclr #7,y:(r6+n6)
+ bclr #8,x:-(r7)
+ bclr #8,y:-(r7)
+ bclr #9,x:$1234
+ bclr #9,y:$1234
+ bclr #11,x:$20
+ bclr #11,y:$20
+ bclr #13,x:$ffffca
+ bclr #13,y:$ffffca
+ bclr #7,x:$ffff95 ; >=56300
+ bclr #7,y:$ffff95
+ bclr #10,r6 ; >=56000
+ bclr #10,b
+
+ bra *+$2000
+ bra *+$20
+ bra *-$2000
+ bra *-$20
+ bra >*+$20
+ bra >*-$20
+ bra r5
+
+ brclr #2,x:(r1)-n1,* ; >=56300
+ brclr #2,y:(r1)-n1,*
+ brclr #3,x:(r2)+n2,*
+ brclr #3,y:(r2)+n2,*
+ brclr #4,x:(r3)-,*
+ brclr #4,y:(r3)-,*
+ brclr #5,x:(r4)+,*
+ brclr #5,y:(r4)+,*
+ brclr #6,x:(r5),*
+ brclr #6,y:(r5),*
+ brclr #7,x:(r6+n6),*
+ brclr #7,y:(r6+n6),*
+ brclr #8,x:-(r7),*
+ brclr #8,y:-(r7),*
+ brclr #11,x:$20,*
+ brclr #11,y:$20,*
+ brclr #13,x:$ffffca,*
+ brclr #13,y:$ffffca,*
+ brclr #7,x:$ffff95,*
+ brclr #7,y:$ffff95,*
+ brclr #10,r6,*
+ brclr #10,b,*
+
+ brkcc
+ brkge
+ brkne
+ brkpl
+ brknn
+ brkec
+ brklc
+ brkgt
+ brkcs
+ brklt
+ brkeq
+ brkmi
+ brknr
+ brkes
+ brkls
+ brkle
+ brkhs
+ brklo
+
+ brset #2,x:(r1)-n1,* ; >=56300
+ brset #2,y:(r1)-n1,*
+ brset #3,x:(r2)+n2,*
+ brset #3,y:(r2)+n2,*
+ brset #4,x:(r3)-,*
+ brset #4,y:(r3)-,*
+ brset #5,x:(r4)+,*
+ brset #5,y:(r4)+,*
+ brset #6,x:(r5),*
+ brset #6,y:(r5),*
+ brset #7,x:(r6+n6),*
+ brset #7,y:(r6+n6),*
+ brset #8,x:-(r7),*
+ brset #8,y:-(r7),*
+ brset #11,x:$20,*
+ brset #11,y:$20,*
+ brset #13,x:$ffffca,*
+ brset #13,y:$ffffca,*
+ brset #7,x:$ffff95,*
+ brset #7,y:$ffff95,*
+ brset #10,r6,*
+ brset #10,b,*
+
+ bscc *+$2000
+ bsge *+$20
+ bsne r3
+ bspl *-$2000
+ bsnn *-$20
+ bsec r4
+ bslc >*+$20
+ bsgt <*-$20
+ bscs *+$2000
+ bslt *+$20
+ bseq r5
+ bsmi *-$2000
+ bsnr *-$20
+ bses r6
+ bsls >*+$20
+ bsle <*-$20
+ bshs *+$2000
+ bslo *+$20
+
+ bsclr #2,x:(r1)-n1,* ; >=56300
+ bsclr #2,y:(r1)-n1,*
+ bsclr #3,x:(r2)+n2,*
+ bsclr #3,y:(r2)+n2,*
+ bsclr #4,x:(r3)-,*
+ bsclr #4,y:(r3)-,*
+ bsclr #5,x:(r4)+,*
+ bsclr #5,y:(r4)+,*
+ bsclr #6,x:(r5),*
+ bsclr #6,y:(r5),*
+ bsclr #7,x:(r6+n6),*
+ bsclr #7,y:(r6+n6),*
+ bsclr #8,x:-(r7),*
+ bsclr #8,y:-(r7),*
+ bsclr #11,x:$20,*
+ bsclr #11,y:$20,*
+ bsclr #13,x:$ffffca,*
+ bsclr #13,y:$ffffca,*
+ bsclr #7,x:$ffff95,*
+ bsclr #7,y:$ffff95,*
+ bsclr #10,r6,*
+ bsclr #10,b,*
+
+ bset #2,x:(r1)-n1 ; >=56000
+ bset #2,y:(r1)-n1
+ bset #3,x:(r2)+n2
+ bset #3,y:(r2)+n2
+ bset #4,x:(r3)-
+ bset #4,y:(r3)-
+ bset #5,x:(r4)+
+ bset #5,y:(r4)+
+ bset #6,x:(r5)
+ bset #6,y:(r5)
+ bset #7,x:(r6+n6)
+ bset #7,y:(r6+n6)
+ bset #8,x:-(r7)
+ bset #8,y:-(r7)
+ bset #9,x:$1234
+ bset #9,y:$1234
+ bset #11,x:$20
+ bset #11,y:$20
+ bset #13,x:$ffffca
+ bset #13,y:$ffffca
+ bset #7,x:$ffff95 ; >=56300
+ bset #7,y:$ffff95
+ bset #10,r6 ; >=56000
+ bset #10,b
+
+ bsr *+$2000
+ bsr *+$20
+ bsr *-$2000
+ bsr *-$20
+ bsr >*+$20
+ bsr >*-$20
+ bsr r5
+
+ bsset #2,x:(r1)-n1,* ; >=56300
+ bsset #2,y:(r1)-n1,*
+ bsset #3,x:(r2)+n2,*
+ bsset #3,y:(r2)+n2,*
+ bsset #4,x:(r3)-,*
+ bsset #4,y:(r3)-,*
+ bsset #5,x:(r4)+,*
+ bsset #5,y:(r4)+,*
+ bsset #6,x:(r5),*
+ bsset #6,y:(r5),*
+ bsset #7,x:(r6+n6),*
+ bsset #7,y:(r6+n6),*
+ bsset #8,x:-(r7),*
+ bsset #8,y:-(r7),*
+ bsset #11,x:$20,*
+ bsset #11,y:$20,*
+ bsset #13,x:$ffffca,*
+ bsset #13,y:$ffffca,*
+ bsset #7,x:$ffff95,*
+ bsset #7,y:$ffff95,*
+ bsset #10,r6,*
+ bsset #10,b,*
+
+ btst #2,x:(r1)-n1 ; >=56000
+ btst #2,y:(r1)-n1
+ btst #3,x:(r2)+n2
+ btst #3,y:(r2)+n2
+ btst #4,x:(r3)-
+ btst #4,y:(r3)-
+ btst #5,x:(r4)+
+ btst #5,y:(r4)+
+ btst #6,x:(r5)
+ btst #6,y:(r5)
+ btst #7,x:(r6+n6)
+ btst #7,y:(r6+n6)
+ btst #8,x:-(r7)
+ btst #8,y:-(r7)
+ btst #9,x:$1234
+ btst #9,y:$1234
+ btst #11,x:$20
+ btst #11,y:$20
+ btst #13,x:$ffffca
+ btst #13,y:$ffffca
+ btst #7,x:$ffff95 ; >=56300
+ btst #7,y:$ffff95
+ btst #10,r6 ; >=56000
+ btst #10,b
+
+ clb a,a ; >=56300
+ clb a,b
+ clb b,a
+ clb b,b
+
+ clr a ; >=56000
+ clr b
+
+ cmp x0,a ; >=56000
+ cmp x1,a
+ cmp y0,a
+ cmp y1,a
+ cmp x,a
+ cmp y,a
+ cmp b,a
+ cmp x0,b ; >=56000
+ cmp x1,b
+ cmp y0,b
+ cmp y1,b
+ cmp x,b
+ cmp y,b
+ cmp a,b
+
+ cmp #31,a ; >=56300
+ cmp #1234,a
+ cmp #31,b
+ cmp #1234,b
+
+ cmpm x0,a ; >=56000
+ cmpm x1,a
+ cmpm y0,a
+ cmpm y1,a
+ cmpm b,a
+ cmpm x0,b
+ cmpm x1,b
+ cmpm y0,b
+ cmpm y1,b
+ cmpm a,b
+
+ cmpu x0,a ; >=56300
+ cmpu x1,a
+ cmpu y0,a
+ cmpu y1,a
+ cmpu b,a
+ cmpu x0,b
+ cmpu x1,b
+ cmpu y0,b
+ cmpu y1,b
+ cmpu a,b
+
+ debug ; >=56300
+ debugcc
+ debugge
+ debugne
+ debugpl
+ debugnn
+ debugec
+ debuglc
+ debuggt
+ debugcs
+ debuglt
+ debugeq
+ debugmi
+ debugnr
+ debuges
+ debugls
+ debugle
+ debughs
+ debuglo
+
+ dec a ; >=56002
+ dec b
+
+ div x0,a ; >=56000
+ div x1,a
+ div y0,a
+ div y1,a
+ div x0,b
+ div x1,b
+ div y0,b
+ div y1,b
+
+ dmacss +x0,x0,a ; >=56300
+ dmacss -y0,y0,a
+ dmacss +x1,x0,b
+ dmacss -y1,y0,b
+ dmacss +x1,x1,a
+ dmacss -y1,y1,a
+ dmacss +x0,x1,b
+ dmacss -y0,y1,b
+ dmacss +x0,y1,a
+ dmacss -y0,x0,a
+ dmacss +x1,y0,b
+ dmacss -y1,x1,b
+ dmacss +y1,x0,a
+ dmacss -x0,y0,a
+ dmacss +y0,x1,b
+ dmacss -x1,y1,b
+
+ dmacsu +x0,x0,a ; >=56300
+ dmacsu -y0,y0,a
+ dmacsu +x1,x0,b
+ dmacsu -y1,y0,b
+ dmacsu +x1,x1,a
+ dmacsu -y1,y1,a
+ dmacsu +x0,x1,b
+ dmacsu -y0,y1,b
+ dmacsu +x0,y1,a
+ dmacsu -y0,x0,a
+ dmacsu +x1,y0,b
+ dmacsu -y1,x1,b
+ dmacsu +y1,x0,a
+ dmacsu -x0,y0,a
+ dmacsu +y0,x1,b
+ dmacsu -x1,y1,b
+
+ dmacuu +x0,x0,a ; >=56300
+ dmacuu -y0,y0,a
+ dmacuu +x1,x0,b
+ dmacuu -y1,y0,b
+ dmacuu +x1,x1,a
+ dmacuu -y1,y1,a
+ dmacuu +x0,x1,b
+ dmacuu -y0,y1,b
+ dmacuu +x0,y1,a
+ dmacuu -y0,x0,a
+ dmacuu +x1,y0,b
+ dmacuu -y1,x1,b
+ dmacuu +y1,x0,a
+ dmacuu -x0,y0,a
+ dmacuu +y0,x1,b
+ dmacuu -x1,y1,b
+
+ do x:(r1)-n1,*+2 ; >=56000
+ do y:(r1)-n1,*+2
+ do x:(r2)+n2,*+2
+ do y:(r2)+n2,*+2
+ do x:(r3)-,*+2
+ do y:(r3)-,*+2
+ do x:(r4)+,*+2
+ do y:(r4)+,*+2
+ do x:(r5),*+2
+ do y:(r5),*+2
+ do x:(r6+n6),*+2
+ do y:(r6+n6),*+2
+ do x:-(r7),*+2
+ do y:-(r7),*+2
+ do x:$12,*+2
+ do y:$12,*+2
+ do #$78,*+2
+ do #$678,*+2
+ do r4,*+2
+ do forever,*+2 ; >=56300
+
+ dor x:(r1)-n1,*+3 ; >=56300
+ dor y:(r1)-n1,*+3
+ dor x:(r2)+n2,*+3
+ dor y:(r2)+n2,*+3
+ dor x:(r3)-,*+3
+ dor y:(r3)-,*+3
+ dor x:(r4)+,*+3
+ dor y:(r4)+,*+3
+ dor x:(r5),*+3
+ dor y:(r5),*+3
+ dor x:(r6+n6),*+3
+ dor y:(r6+n6),*+3
+ dor x:-(r7),*+3
+ dor y:-(r7),*+3
+ dor x:$12,*+3
+ dor y:$12,*+3
+ dor #$78,*+3
+ dor #$678,*+3
+ dor r4,*+3
+ dor forever,*+3
+
+ enddo ; >=56000
+
+ eor x0,a ; >=56000
+ eor y0,a
+ eor x1,a
+ eor y1,a
+ eor x0,b
+ eor y0,b
+ eor x1,b
+ eor y1,b
+
+ eor #$34,a ; >=56300
+ eor #$34,b
+ eor #$123456,a
+ eor #$123456,b
+
+ extract a1,a,a ; >=56300
+ extract b1,a,a
+ extract x0,a,a
+ extract x1,a,a
+ extract y0,a,a
+ extract y1,a,a
+ extract a1,b,a
+ extract a1,a,b
+ extract #$234567,a,a
+ extract #$234567,a,b
+ extract #$234567,b,a
+ extract #$234567,b,b
+
+ extractu a1,a,a ; >=56300
+ extractu b1,a,a
+ extractu x0,a,a
+ extractu x1,a,a
+ extractu y0,a,a
+ extractu y1,a,a
+ extractu a1,b,a
+ extractu a1,a,b
+ extractu #$234567,a,a
+ extractu #$234567,a,b
+ extractu #$234567,b,a
+ extractu #$234567,b,b
+
+ abs a ifcc ; >=56300
+ abs a ifge
+ abs a ifne
+ abs a ifpl
+ abs a ifnn
+ abs a ifec
+ abs a iflc
+ abs a ifgt
+ abs a ifcs
+ abs a iflt
+ abs a ifeq
+ abs a ifmi
+ abs a ifnr
+ abs a ifes
+ abs a ifls
+ abs a ifle
+ abs a ifhs
+ abs a iflo
+
+ abs a ifcc.u ; >=56300
+ abs a ifge.u
+ abs a ifne.u
+ abs a ifpl.u
+ abs a ifnn.u
+ abs a ifec.u
+ abs a iflc.u
+ abs a ifgt.u
+ abs a ifcs.u
+ abs a iflt.u
+ abs a ifeq.u
+ abs a ifmi.u
+ abs a ifnr.u
+ abs a ifes.u
+ abs a ifls.u
+ abs a ifle.u
+ abs a ifhs.u
+ abs a iflo.u
+
+ illegal ; >=56000
+
+ inc a ; >=56002
+ inc b
+
+ insert a1,a0,a ; >=56300
+ insert b1,a0,a
+ insert x0,a0,a
+ insert y0,a0,a
+ insert x1,a0,a
+ insert y1,a0,a
+ insert a1,b0,a
+ insert a1,x0,a
+ insert a1,y0,a
+ insert a1,x1,a
+ insert a1,y1,a
+ insert a1,a0,b
+ insert #345678,a0,a
+ insert #345678,b0,a
+ insert #345678,x0,a
+ insert #345678,y0,a
+ insert #345678,x1,a
+ insert #345678,y1,a
+ insert #345678,a0,b
+
+ jcc $123
+ jge $123456
+ jne (r1)-n1
+ jpl (r2)+n2
+ jnn (r3)-
+ jec (r4)+
+ jlc (r5)
+ jgt (r6+n6)
+ jcs -(r7)
+ jlt $123
+ jeq $123456
+ jmi (r1)-n1
+ jnr (r2)+n2
+ jes (r3)-
+ jls (r4)+
+ jle (r5)
+ jhs (r6+n6)
+ jlo -(r7)
+
+ jclr #2,x:(r1)-n1,* ; >=56000
+ jclr #2,y:(r1)-n1,*
+ jclr #3,x:(r2)+n2,*
+ jclr #3,y:(r2)+n2,*
+ jclr #4,x:(r3)-,*
+ jclr #4,y:(r3)-,*
+ jclr #5,x:(r4)+,*
+ jclr #5,y:(r4)+,*
+ jclr #6,x:(r5),*
+ jclr #6,y:(r5),*
+ jclr #7,x:(r6+n6),*
+ jclr #7,y:(r6+n6),*
+ jclr #8,x:-(r7),*
+ jclr #8,y:-(r7),*
+ jclr #11,x:$20,*
+ jclr #11,y:$20,*
+ jclr #13,x:$ffffca,*
+ jclr #13,y:$ffffca,*
+ jclr #7,x:$ffff95,* ; >=56300
+ jclr #7,y:$ffff95,*
+ jclr #10,r6,* ; >=56000
+ jclr #10,b,*
+
+ jmp $123 ; >=56000
+ jmp $123456
+ jmp (r1)-n1
+ jmp (r2)+n2
+ jmp (r3)-
+ jmp (r4)+
+ jmp (r5)
+ jmp (r6+n6)
+ jmp -(r7)
+
+ jscc $123 ; >=56000
+ jsge $123456
+ jsne (r1)-n1
+ jspl (r2)+n2
+ jsnn (r3)-
+ jsec (r4)+
+ jslc (r5)
+ jsgt (r6+n6)
+ jscs -(r7)
+ jslt $123
+ jseq $123456
+ jsmi (r1)-n1
+ jsnr (r2)+n2
+ jses (r3)-
+ jsls (r4)+
+ jsle (r5)
+ jshs (r6+n6)
+ jslo -(r7)
+
+ jsclr #2,x:(r1)-n1,* ; >=56000
+ jsclr #2,y:(r1)-n1,*
+ jsclr #3,x:(r2)+n2,*
+ jsclr #3,y:(r2)+n2,*
+ jsclr #4,x:(r3)-,*
+ jsclr #4,y:(r3)-,*
+ jsclr #5,x:(r4)+,*
+ jsclr #5,y:(r4)+,*
+ jsclr #6,x:(r5),*
+ jsclr #6,y:(r5),*
+ jsclr #7,x:(r6+n6),*
+ jsclr #7,y:(r6+n6),*
+ jsclr #8,x:-(r7),*
+ jsclr #8,y:-(r7),*
+ jsclr #11,x:$20,*
+ jsclr #11,y:$20,*
+ jsclr #13,x:$ffffca,*
+ jsclr #13,y:$ffffca,*
+ jsclr #7,x:$ffff95,* ; >=56300
+ jsclr #7,y:$ffff95,*
+ jsclr #10,r6,* ; >=56000
+ jsclr #10,b,*
+
+ jset #2,x:(r1)-n1,* ; >=56000
+ jset #2,y:(r1)-n1,*
+ jset #3,x:(r2)+n2,*
+ jset #3,y:(r2)+n2,*
+ jset #4,x:(r3)-,*
+ jset #4,y:(r3)-,*
+ jset #5,x:(r4)+,*
+ jset #5,y:(r4)+,*
+ jset #6,x:(r5),*
+ jset #6,y:(r5),*
+ jset #7,x:(r6+n6),*
+ jset #7,y:(r6+n6),*
+ jset #8,x:-(r7),*
+ jset #8,y:-(r7),*
+ jset #11,x:$20,*
+ jset #11,y:$20,*
+ jset #13,x:$ffffca,*
+ jset #13,y:$ffffca,*
+ jset #7,x:$ffff95,* ; >=56300
+ jset #7,y:$ffff95,*
+ jset #10,r6,* ; >=56000
+ jset #10,b,*
+
+ jsr $123 ; >=56000
+ jsr $123456
+ jsr (r1)-n1
+ jsr (r2)+n2
+ jsr (r3)-
+ jsr (r4)+
+ jsr (r5)
+ jsr (r6+n6)
+ jsr -(r7)
+
+ jsset #2,x:(r1)-n1,* ; >=56000
+ jsset #2,y:(r1)-n1,*
+ jsset #3,x:(r2)+n2,*
+ jsset #3,y:(r2)+n2,*
+ jsset #4,x:(r3)-,*
+ jsset #4,y:(r3)-,*
+ jsset #5,x:(r4)+,*
+ jsset #5,y:(r4)+,*
+ jsset #6,x:(r5),*
+ jsset #6,y:(r5),*
+ jsset #7,x:(r6+n6),*
+ jsset #7,y:(r6+n6),*
+ jsset #8,x:-(r7),*
+ jsset #8,y:-(r7),*
+ jsset #11,x:$20,*
+ jsset #11,y:$20,*
+ jsset #13,x:$ffffca,*
+ jsset #13,y:$ffffca,*
+ jsset #7,x:$ffff95,* ; >=56300
+ jsset #7,y:$ffff95,*
+ jsset #10,r6,* ; >=56000
+ jsset #10,b,*
+
+ lra r3,x0 ; >=56000
+ lra r3,x1
+ lra r3,y0
+ lra r3,y1
+ lra r3,a0
+ lra r3,b0
+ lra r3,a2
+ lra r3,b2
+ lra r3,a1
+ lra r3,b1
+ lra r3,a
+ lra r3,b
+ lra r3,r5
+ lra r3,n5
+
+ lra *+2,x0 ; >=56000
+ lra *+2,x1
+ lra *+2,y0
+ lra *+2,y1
+ lra *+2,a0
+ lra *+2,b0
+ lra *+2,a2
+ lra *+2,b2
+ lra *+2,a1
+ lra *+2,b1
+ lra *+2,a
+ lra *+2,b
+ lra *+2,r5
+ lra *+2,n5
+
+ lsl a ; >=56000
+ lsl b
+ lsl #$13,a ; >=56300
+ lsl #$13,b
+ lsl a1,a
+ lsl b1,a
+ lsl x0,a
+ lsl y0,a
+ lsl x1,a
+ lsl y1,a
+ lsl a1,b
+ lsl b1,b
+ lsl x0,b
+ lsl y0,b
+ lsl x1,b
+ lsl y1,b
+
+ lsr a ; >=56000
+ lsr b
+ lsr #$13,a ; >=56300
+ lsr #$13,b
+ lsr a1,a
+ lsr b1,a
+ lsr x0,a
+ lsr y0,a
+ lsr x1,a
+ lsr y1,a
+ lsr a1,b
+ lsr b1,b
+ lsr x0,b
+ lsr y0,b
+ lsr x1,b
+ lsr y1,b
+
+ lua (r1)-n1,x0 ; >=56000
+ lua (r2)+n2,x1
+ lua (r3)-,y0
+ lua (r4)+,y1
+ lua (r5)-n5,a0
+ lua (r6)+n6,b0
+ lua (r7)-,a2
+ lua (r1)+,b2
+ lua (r2)-n2,a1
+ lua (r3)+n3,b1
+ lua (r4)-,a
+ lua (r5)+,b
+ lua (r6)-n6,r4
+ lua (r7)+n7,n6
+ lua (r2+20),r5 ; >=56300
+ lua (r3-20),n7
+
+ mac +x0,x0,a ; >=56000
+ mac -y0,y0,a
+ mac +x1,x0,b
+ mac -y1,y0,b
+ mac +x0,y1,a
+ mac -y0,x0,a
+ mac +x1,y0,b
+ mac -y1,x1,b
+ mac +y1,#8,a ; >=56300
+ mac -x0,#32,a
+ mac +y0,#128,b
+ mac -x1,#(1<<22),b
+
+ maci +#$123456,x0,a ; >=56300
+ maci -#$234567,y0,a
+ maci +#$345678,x1,b
+ maci -#$456789,y1,b
+
+ macsu +x0,x0,a ; >=56300
+ macsu -y0,y0,a
+ macsu +x1,x0,b
+ macsu -y1,y0,b
+ macsu +x1,x1,a
+ macsu -y1,y1,a
+ macsu +x0,x1,b
+ macsu -y0,y1,b
+ macsu +x0,y1,a
+ macsu -y0,x0,a
+ macsu +x1,y0,b
+ macsu -y1,x1,b
+ macsu +y1,x0,a
+ macsu -x0,y0,a
+ macsu +y0,x1,b
+ macsu -x1,y1,b
+
+ macuu +x0,x0,a ; >=56300
+ macuu -y0,y0,a
+ macuu +x1,x0,b
+ macuu -y1,y0,b
+ macuu +x1,x1,a
+ macuu -y1,y1,a
+ macuu +x0,x1,b
+ macuu -y0,y1,b
+ macuu +x0,y1,a
+ macuu -y0,x0,a
+ macuu +x1,y0,b
+ macuu -y1,x1,b
+ macuu +y1,x0,a
+ macuu -x0,y0,a
+ macuu +y0,x1,b
+ macuu -x1,y1,b
+
+ macr +x0,x0,a ; >=56000
+ macr -y0,y0,a
+ macr +x1,x0,b
+ macr -y1,y0,b
+ macr +x0,y1,a
+ macr -y0,x0,a
+ macr +x1,y0,b
+ macr -y1,x1,b
+ macr +y1,#8,a ; >=56300
+ macr -x0,#32,a
+ macr +y0,#128,b
+ macr -x1,#(1<<22),b
+
+ macri +#$123456,x0,a ; >=56300
+ macri -#$234567,y0,a
+ macri +#$345678,x1,b
+ macri -#$456789,y1,b
+
+ max a,b ifne ; >=56300
+ maxm a,b
+
+ merge a1,a ; >=56300
+ merge b1,a
+ merge x0,a
+ merge y0,a
+ merge x1,a
+ merge y1,a
+ merge a1,b
+ merge b1,b
+ merge x0,b
+ merge y0,b
+ merge x1,b
+ merge y1,b
+
+ move ; >=56000
+
+ move #30,x0 ; >=56000
+ move #31,x1
+ move #32,y0
+ move #33,y1
+ move #34,a0
+ move #35,b0
+ move #36,a2
+ move #37,b2
+ move #38,a1
+ move #39,b1
+ move #40,a
+ move #41,b
+ move #42,r2
+ move #43,n4
+
+ move n4,x0 ; >=56000
+ move x0,x1
+ move x1,y0
+ move y0,y1
+ move y1,a0
+ move a0,b0
+ move b0,a2
+ move a2,b2
+ move b2,a1
+ move a1,b1
+ move b1,a
+ move a,b
+ move b,r2
+ move r2,n4
+
+ move (r1)-n1 ; >=56000
+ move (r2)+n2
+ move (r3)-
+ move (r4)+
+
+ move x:(r1)-n1,x0 ; >=56000
+ move x:(r2)+n2,x1
+ move x:(r3)-,y0
+ move x:(r4)+,y1
+ move x:(r5),a0
+ move x:(r6+n6),b0
+ move x:-(r7),a2
+ move x:$123456,b2
+ move x:#$123456,a1
+ move x:$12,b1
+ move a,x:(r1)-n1
+ move b,x:(r2)+n2
+ move r0,x:(r3)-
+ move r1,x:(r4)+
+ move r2,x:(r5)
+ move r3,x:(r6+n6)
+ move r4,x:-(r7)
+ move r5,x:$123456
+ move r6,x:$12
+ move n0,x:$12
+
+ move x:(r1+30),x0 ; >=56300
+ move x:(r2-30),x1
+ move x:(r3+300),y0
+ move x:(r4-300),y1
+ move x:(r5+30),n2
+ move x:(r6-30),n2
+ move x0,x:(r1+30) ; >=56300
+ move x1,x:(r2-30)
+ move y0,x:(r3+300)
+ move y1,x:(r4-300)
+ move n2,x:(r5+30)
+ move n2,x:(r6-30)
+
+ move x0,x:(r1)-n1 a,y0 ; >=56000
+ move x1,x:(r2)+n2 a,y1
+ move a,x:(r3)- b,y0
+ move b,x:(r4)+ b,y1
+ move x:(r5),x0 a,y0
+ move x:(r6+n6),x1 a,y1
+ move x:-(r7),a b,y0
+ move x:$123,b b,y1
+ move #$1234,a a,y0
+
+ move a,x:(r1)-n1 x0,a ; >=56000
+ move b,x:(r2)+n2 x0,b
+
+ move y:(r1)-n1,x0 ; >=56000
+ move y:(r2)+n2,x1
+ move y:(r3)-,y0
+ move y:(r4)+,y1
+ move y:(r5),a0
+ move y:(r6+n6),b0
+ move y:-(r7),a2
+ move y:$123456,b2
+ move y:#$123456,a1
+ move y:$12,b1
+ move a,y:(r1)-n1
+ move b,y:(r2)+n2
+ move r0,y:(r3)-
+ move r1,y:(r4)+
+ move r2,y:(r5)
+ move r3,y:(r6+n6)
+ move r4,y:-(r7)
+ move r5,y:$123456
+ move r6,y:$12
+ move n0,y:$12
+
+ move y:(r1+30),x0 ; >=56300
+ move y:(r2-30),x1
+ move y:(r3+300),y0
+ move y:(r4-300),y1
+ move y:(r5+30),n2
+ move y:(r6-30),n2
+ move x0,y:(r1+30) ; >=56300
+ move x1,y:(r2-30)
+ move y0,y:(r3+300)
+ move y1,y:(r4-300)
+ move n2,y:(r5+30)
+ move n2,y:(r6-30)
+
+ move a,x0 y0,y:(r1)-n1 ; >=56000
+ move a,x1 y1,y:(r2)+n2
+ move b,x0 a,y:(r3)-
+ move b,x1 b,y:(r4)+
+ move a,x0 y:(r5),y0
+ move a,x1 y:(r6+n6),y1
+ move b,x0 y:-(r7),a
+ move b,x1 y:$123,b
+ move a,x0 #$1234,a
+
+ move y0,a a,y:(r1)-n1 ; >=56000
+ move y0,b b,y:(r2)+n2
+
+ move l:(r1)-n1,a10 ; >=56000
+ move l:(r2)+n2,b10
+ move l:(r3)-,x
+ move l:(r4)+,y
+ move l:(r5),a
+ move l:(r6+n6),b
+ move l:-(r7),ab
+ move l:$123456,ba
+ move l:$12,ba
+
+ move a10,l:(r1)-n1 ; >=56000
+ move b10,l:(r2)+n2
+ move x,l:(r3)-
+ move y,l:(r4)+
+ move a,l:(r5)
+ move b,l:(r6+n6)
+ move ab,l:-(r7)
+ move ba,l:$123456
+ move ba,l:$12
+
+ move x:(r0)+n0,x0 y:(r4)+n4,y0 ; >=56000
+ move x:(r1)-,x1 y:(r5)-,y1
+ move x:(r2)+,a y:(r6)+,b
+ move x:(r3),b y:(r7),a
+ move x0,x:(r0)+n0 y0,y:(r4)+n4
+ move x1,x:(r1)- y1,y:(r5)-
+ move a,x:(r2)+ b,y:(r6)+
+ move b,x:(r3) a,y:(r7)
+
+ movec x:(r1)-n1,m0 ; >=56000
+ movec x:(r2)+n2,m1
+ movec x:(r3)-,m2
+ movec x:(r4)+,m3
+ movec x:(r5),m4
+ movec x:(r6+n6),m5
+ movec x:-(r7),m6
+ movec x:$123456,m7
+ movec x:$12,ep
+ movec r4,vba
+ movec #$123456,sc
+ movec #$12,sz
+ movec y:(r1)-n1,sr
+ movec y:(r2)+n2,omr
+ movec y:(r3)-,sp
+ movec y:(r4)+,ssh
+ movec y:(r5),ssl
+ movec y:(r6+n6),la
+ movec y:-(r7),lc
+
+ movec m0,x:(r1)-n1 ; >=56000
+ movec m1,x:(r2)+n2
+ movec m2,x:(r3)-
+ movec m3,x:(r4)+
+ movec m4,x:(r5)
+ movec m5,x:(r6+n6)
+ movec m6,x:-(r7)
+ movec m7,x:$123456
+ movec ep,x:$12
+ movec vba,r4
+ movec sr,y:(r1)-n1
+ movec omr,y:(r2)+n2
+ movec sp,y:(r3)-
+ movec ssh,y:(r4)+
+ movec ssl,y:(r5)
+ movec la,y:(r6+n6)
+ movec lc,y:-(r7)
+
+ movem r4,p:$123456 ; >=56000
+ movem p:$123456,r4
+ movem r4,p:$12
+ movem p:$12,r4
+
+ movep x:$ffffd2,x:$123456 ; >=56000
+ movep y:$ffffd2,x:$123456
+ movep x:$ffffd2,y:$123456
+ movep y:$ffffd2,y:$123456
+ movep x:$123456,x:$ffffd2
+ movep x:$123456,y:$ffffd2
+ movep y:$123456,x:$ffffd2
+ movep y:$123456,y:$ffffd2
+
+ movep x:$ffff92,x:$123456
+ movep x:$ffff92,y:$123456
+ movep x:$123456,x:$ffff92
+ movep y:$123456,x:$ffff92
+
+ movep y:$ffff92,x:$123456
+ movep y:$ffff92,y:$123456
+ movep x:$123456,y:$ffff92
+ movep y:$123456,y:$ffff92
+
+ movep x:$ffffd2,p:$123456
+ movep y:$ffffd2,p:$123456
+ movep p:$123456,x:$ffffd2
+ movep p:$123456,y:$ffffd2
+
+ movep x:$ffff92,p:$123456
+ movep y:$ffff92,p:$123456
+ movep p:$123456,x:$ffff92
+ movep p:$123456,y:$ffff92
+
+ movep x:$ffffd2,r4
+ movep y:$ffffd2,r4
+ movep r4,x:$ffffd2
+ movep r4,y:$ffffd2
+
+ movep x:$ffff92,r4
+ movep y:$ffff92,r4
+ movep r4,x:$ffff92
+ movep r4,y:$ffff92
+
+ mpy +x0,x0,a ; >=56000
+ mpy -y0,y0,a
+ mpy +x1,x0,b
+ mpy -y1,y0,b
+ mpy +x0,y1,a
+ mpy -y0,x0,a
+ mpy +x1,y0,b
+ mpy -y1,x1,b
+ mpy +y1,#8,a ; >=56300
+ mpy -x0,#32,a
+ mpy +y0,#128,b
+ mpy -x1,#(1<<22),b
+
+ mpysu +x0,x0,a ; >=56300
+ mpysu -y0,y0,a
+ mpysu +x1,x0,b
+ mpysu -y1,y0,b
+ mpysu +x1,x1,a
+ mpysu -y1,y1,a
+ mpysu +x0,x1,b
+ mpysu -y0,y1,b
+ mpysu +x0,y1,a
+ mpysu -y0,x0,a
+ mpysu +x1,y0,b
+ mpysu -y1,x1,b
+ mpysu +y1,x0,a
+ mpysu -x0,y0,a
+ mpysu +y0,x1,b
+ mpysu -x1,y1,b
+
+ mpyuu +x0,x0,a ; >=56300
+ mpyuu -y0,y0,a
+ mpyuu +x1,x0,b
+ mpyuu -y1,y0,b
+ mpyuu +x1,x1,a
+ mpyuu -y1,y1,a
+ mpyuu +x0,x1,b
+ mpyuu -y0,y1,b
+ mpyuu +x0,y1,a
+ mpyuu -y0,x0,a
+ mpyuu +x1,y0,b
+ mpyuu -y1,x1,b
+ mpyuu +y1,x0,a
+ mpyuu -x0,y0,a
+ mpyuu +y0,x1,b
+ mpyuu -x1,y1,b
+
+ mpyi +#$123456,x0,a ; >=56300
+ mpyi -#$234567,y0,a
+ mpyi +#$345678,x1,b
+ mpyi -#$456789,y1,b
+
+ mpyr +x0,x0,a ; >=56000
+ mpyr -y0,y0,a
+ mpyr +x1,x0,b
+ mpyr -y1,y0,b
+ mpyr +x0,y1,a
+ mpyr -y0,x0,a
+ mpyr +x1,y0,b
+ mpyr -y1,x1,b
+ mpyr +y1,#8,a ; >=56300
+ mpyr -x0,#32,a
+ mpyr +y0,#128,b
+ mpyr -x1,#(1<<22),b
+
+ mpyri +#$123456,x0,a ; >=56300
+ mpyri -#$234567,y0,a
+ mpyri +#$345678,x1,b
+ mpyri -#$456789,y1,b
+
+ neg a ; >=56000
+ neg b
+
+ nop
+
+ norm r2,a ; >=56000
+ norm r4,b
+
+ normf a1,a ; >=56300
+ normf b1,a
+ normf x0,a
+ normf y0,a
+ normf x1,a
+ normf y1,a
+ normf a1,b
+ normf b1,b
+ normf x0,b
+ normf y0,b
+ normf x1,b
+ normf y1,b
+
+ not a ; >=56000
+ not b
+
+ or x0,a ; >=56000
+ or x1,a
+ or y0,a
+ or y1,a
+ or x0,b
+ or x1,b
+ or y0,b
+ or y1,b
+
+ or #31,a ; >=56000
+ or #1234,a
+ or #31,b
+ or #1234,b
+
+ ori #$12,mr ; >=56000
+ ori #$12,ccr
+ ori #$12,com
+ ori #$12,eom
+
+ pflush ; >=56300
+ pflushun
+ pfree
+ plock $123456
+ plockr *
+ punlockr *
+
+ rep x:(r1)-n1 ; >=56000
+ rep x:(r2)+n2
+ rep x:(r3)-
+ rep x:(r4)+
+ rep x:(r5)
+ rep x:(r6+n6)
+ rep x:-(r7)
+ rep x:$12
+ rep y:(r1)-n1
+ rep y:(r2)+n2
+ rep y:(r3)-
+ rep y:(r4)+
+ rep y:(r5)
+ rep y:(r6+n6)
+ rep y:-(r7)
+ rep y:$12
+ rep r4
+ rep #$234
+
+ reset ; >=56000
+
+ rnd a ; >=56000
+ rnd b
+
+ rol a ; >=56000
+ rol b
+
+ ror a ; >=56000
+ ror b
+
+ rti ; >=56000
+ rts
+
+ sbc x,a ; >=56000
+ sbc y,a
+ sbc x,b
+ sbc y,b
+
+ stop ; >=56000
+
+ sub x0,a ; >=56000
+ sub x1,a
+ sub y0,a
+ sub y1,a
+ sub x,a
+ sub y,a
+ sub b,a
+ sub x0,b ; >=56000
+ sub x1,b
+ sub y0,b
+ sub y1,b
+ sub x,b
+ sub y,b
+ sub a,b
+
+ sub #31,a ; >=56300
+ sub #1234,a
+ sub #31,b
+ sub #1234,b
+
+ subl b,a ; >=56000
+ subl a,b
+
+ subr b,a ; >=56000
+ subr a,b
+
+ tne b,a ; >=56000
+ tne x0,a
+ tne y0,a
+ tne x1,a
+ tne y1,a
+ tne a,b
+ tne x0,b
+ tne y0,b
+ tne x1,b
+ tne y1,b
+
+ tne r2,r3 ; >=56000
+
+ tne y1,b r2,r3 ; >=56000
+
+ tfr b,a ; >=56000
+ tfr x0,a
+ tfr y0,a
+ tfr x1,a
+ tfr y1,a
+ tfr a,b
+ tfr x0,b
+ tfr y0,b
+ tfr x1,b
+ tfr y1,b
+
+ trap ; >=56300
+
+ trapcc ; >=56300
+ trapge
+ trapne
+ trappl
+ trapnn
+ trapec
+ traplc
+ trapgt
+ trapcs
+ traplt
+ trapeq
+ trapmi
+ trapnr
+ trapes
+ trapls
+ traple
+ traphs
+ traplo
+
+ tst a ; >=56000
+ tst b
+
+ wait
+
diff --git a/tests/t_56300/t_56300.doc b/tests/t_56300/t_56300.doc
new file mode 100644
index 0000000..9798c65
--- /dev/null
+++ b/tests/t_56300/t_56300.doc
@@ -0,0 +1,6 @@
++---------------------- Test Application 56300 ----------------------------+
+| |
+| This is a (synthetic but halfway complete) test of the DSP563xx's |
+| instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_56300/t_56300.ori b/tests/t_56300/t_56300.ori
new file mode 100644
index 0000000..2418ca4
--- /dev/null
+++ b/tests/t_56300/t_56300.ori
Binary files differ
diff --git a/tests/t_65/asflags b/tests/t_65/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_65/asflags
diff --git a/tests/t_65/t_65.asm b/tests/t_65/t_65.asm
new file mode 100755
index 0000000..0b9d3bc
--- /dev/null
+++ b/tests/t_65/t_65.asm
@@ -0,0 +1,283 @@
+ cpu melps740
+
+ adc #$12
+ adc $12
+ adc $12,x
+ adc $12,y
+ adc $1234
+ adc $1234,x
+ adc $1234,y
+ adc ($12,x)
+ adc ($12),y
+
+ and #$12
+ and $12
+ and $12,x
+ and $12,y
+ and $1234
+ and $1234,x
+ and $1234,y
+ and ($12,x)
+ and ($12),y
+
+ asl
+ asl a
+ asl $12
+ asl $12,x
+ asl $1234
+ asl $1234,x
+
+ bbc 3,a,*
+ bbc 4,$12,*
+
+ bbs 5,a,*
+ bbs 6,$12,*+1
+
+ bcc *+2
+ bcs *+3
+ beq *+4
+
+ bit $12
+ bit $1234
+
+ bmi *+5
+ bne *+6
+ bpl *+7
+ bra *+8
+
+ brk
+
+ bvc *+9
+ bvs *+10
+
+ clb 2,a
+ clb 3,$12
+
+ clc
+ cld
+ cli
+ clt
+ clv
+
+ cmp #$12
+ cmp $12
+ cmp $12,x
+ cmp $12,y
+ cmp $1234
+ cmp $1234,x
+ cmp $1234,y
+ cmp ($12,x)
+ cmp ($12),y
+
+ com $12
+
+ cpx #$12
+ cpx $12
+ cpx $1234
+
+ cpy #$12
+ cpy $12
+ cpy $1234
+
+ dec
+ dec a
+ dec $12
+ dec $12,x
+ dec $1234
+ dec $1234,x
+
+ dex
+ dey
+
+ div $12,x
+
+ eor #$12
+ eor $12
+ eor $12,x
+ eor $12,y
+ eor $1234
+ eor $1234,x
+ eor $1234,y
+ eor ($12,x)
+ eor ($12),y
+
+ fst
+
+ inc
+ inc a
+ inc $12
+ inc $12,x
+ inc $1234
+ inc $1234,x
+
+ inx
+ iny
+
+ jmp $1234
+ jmp ($1234)
+ jmp ($12)
+
+ assume sp:$12
+ jsr $1234
+ jsr \$1234
+ jsr ($12)
+
+ lda #$12
+ lda $12
+ lda $12,x
+ lda $12,y
+ lda $1234
+ lda $1234,x
+ lda $1234,y
+ lda ($12,x)
+ lda ($12),y
+
+ ldm #$12,$34
+
+ ldx #$12
+ ldx $12
+ ldx $12,y
+ ldx $1234
+ ldx $1234,y
+
+ ldy #$12
+ ldy $12
+ ldy $12,x
+ ldy $1234
+ ldy $1234,x
+
+ lsr
+ lsr a
+ lsr $12
+ lsr $12,x
+ lsr $1234
+ lsr $1234,x
+
+ mul $12,x
+
+ nop
+
+ ora #$12
+ ora $12
+ ora $12,x
+ ora $12,y
+ ora $1234
+ ora $1234,x
+ ora $1234,y
+ ora ($12,x)
+ ora ($12),y
+
+ pha
+ php
+ pla
+ plp
+
+ rol
+ rol a
+ rol $12
+ rol $12,x
+ rol $1234
+ rol $1234,x
+
+ ror
+ ror a
+ ror $12
+ ror $12,x
+ ror $1234
+ ror $1234,x
+
+ rrf $12
+
+ rti
+ rts
+
+ sbc #$12
+ sbc $12
+ sbc $12,x
+ sbc $12,y
+ sbc $1234
+ sbc $1234,x
+ sbc $1234,y
+ sbc ($12,x)
+ sbc ($12),y
+
+ seb 2,a
+ seb 3,$12
+
+ sec
+ sed
+ sei
+ set
+
+ slw
+
+ sta $12
+ sta $12,x
+ sta $12,y
+ sta $1234
+ sta $1234,x
+ sta $1234,y
+ sta ($12,x)
+ sta ($12),y
+
+ stp
+
+ stx $12
+ stx $12,y
+ stx $1234
+
+ sty $12
+ sty $12,x
+ sty $1234
+
+ tax
+ tay
+
+ tst $12
+
+ tsx
+ txa
+ txs
+ tya
+
+ wit
+
+ cpu 65c02
+
+ dec a
+ inc a
+ plx
+ ply
+ phx
+ phy
+
+ tsb $12
+ trb $12
+ tsb $1234
+ trb $1234
+
+ stz $12
+ stz $1234
+ stz $12,x
+ stz $1234,x
+
+ bit $12,x
+ bit $1234,x
+ bit #$12
+
+ lda ($12)
+ sta ($12)
+ adc ($12)
+ sbc ($12)
+ and ($12)
+ ora ($12)
+ eor ($12)
+ cmp ($12)
+
+ jmp ($12,x)
+
+ bbr2 $12,*
+ bbs4 $12,*
+
+ rmb3 $12
+ smb5 $12
diff --git a/tests/t_65/t_65.doc b/tests/t_65/t_65.doc
new file mode 100644
index 0000000..6d7cba0
--- /dev/null
+++ b/tests/t_65/t_65.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application 65 -----------------------------+
+| |
+| This is a (synthetic) test of the 65xx/MELPS-740 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_65/t_65.ori b/tests/t_65/t_65.ori
new file mode 100755
index 0000000..2ff599b
--- /dev/null
+++ b/tests/t_65/t_65.ori
Binary files differ
diff --git a/tests/t_6502u/asflags b/tests/t_6502u/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_6502u/asflags
diff --git a/tests/t_6502u/t_6502u.asm b/tests/t_6502u/t_6502u.asm
new file mode 100644
index 0000000..337b5d1
--- /dev/null
+++ b/tests/t_6502u/t_6502u.asm
@@ -0,0 +1,110 @@
+ cpu 6502undoc
+
+ nop
+ nop #$12
+ nop $12
+ nop $12,x
+ nop $1234
+ nop $1234,x
+
+ jam
+ crs
+ kil
+
+ slo $12
+ slo $12,x
+ slo $1234
+ slo $1234,x
+ slo $12,y
+ slo $1234,y
+ slo ($12,x)
+ slo ($12),y
+
+ anc #$12
+
+ rla $12
+ rla $12,x
+ rla $1234
+ rla $1234,x
+ rla $12,y
+ rla $1234,y
+ rla ($12,x)
+ rla ($12),y
+
+ sre $12
+ sre $12,x
+ sre $1234
+ sre $1234,x
+ sre $12,y
+ sre $1234,y
+ sre ($12,x)
+ sre ($12),y
+
+ asr #$12
+
+ rra $12
+ rra $12,x
+ rra $1234
+ rra $1234,x
+ rra $12,y
+ rra $1234,y
+ rra ($12,x)
+ rra ($12),y
+
+ arr #$12
+
+ sax $12
+ sax $12,y
+ sax $1234
+ sax ($12,x)
+
+ ane #$12
+
+ sha $12,x
+ sha $1234,x
+ sha $12,y
+ sha $1234,y
+
+ shs $12,y
+ shs $1234,y
+
+ shy $12,y
+ shy $1234,y
+
+ shx $12,x
+ shx $1234,x
+
+ lax $12
+ lax $12,y
+ lax $1234
+ lax $1234,y
+ lax ($12,x)
+ lax ($12),y
+
+ lxa #$12
+
+ lae $12,y
+ lae $1234,y
+
+ dcp $12
+ dcp $12,x
+ dcp $1234
+ dcp $1234,x
+ dcp $12,y
+ dcp $1234,y
+ dcp ($12,x)
+ dcp ($12),y
+
+ sbx #$12
+
+ isb $12
+ isb $12,x
+ isb $1234
+ isb $1234,x
+ isb $12,y
+ isb $1234,y
+ isb ($12,x)
+ isb ($12),y
+
+ end *
+
diff --git a/tests/t_6502u/t_6502u.doc b/tests/t_6502u/t_6502u.doc
new file mode 100644
index 0000000..62849cc
--- /dev/null
+++ b/tests/t_6502u/t_6502u.doc
@@ -0,0 +1,7 @@
++------------------------ Test Application 6502U ----------------------------+
+| |
+| Hacker's corner: This tests the 'undocumented' instructions of the 6502/ |
+| 6510 processor, i.e. the things the processor does when yuo use undocu- |
+| mented opcode bytes. I do not recommend that, but it's your program... |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_6502u/t_6502u.ori b/tests/t_6502u/t_6502u.ori
new file mode 100644
index 0000000..1e4282a
--- /dev/null
+++ b/tests/t_6502u/t_6502u.ori
Binary files differ
diff --git a/tests/t_6804/asflags b/tests/t_6804/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_6804/asflags
diff --git a/tests/t_6804/t_6804.asm b/tests/t_6804/t_6804.asm
new file mode 100644
index 0000000..78da533
--- /dev/null
+++ b/tests/t_6804/t_6804.asm
@@ -0,0 +1,72 @@
+ cpu 6804
+
+ include stddef04.inc
+
+ clra
+ clrx
+ clry
+ coma
+ rola
+ asla
+ inca
+ incx
+ incy
+ deca
+ decx
+ decy
+ tax
+ tay
+ txa
+ tya
+ rts
+ rti
+ nop
+
+targ: beq targ
+ bne targ
+ blo targ
+ bcs targ
+ bhs targ
+ bcc targ
+
+ jmp $123
+ jsr $456
+
+ add (x)
+ add (y)
+ add $30
+ add #$40
+ sub (x)
+ sub (y)
+ sub $50
+ sub #$60
+ cmp (x)
+ cmp (y)
+ cmp $70
+ cmp #$80
+ and (x)
+ and (y)
+ and $90
+ and #$a0
+
+ lda (x)
+ sta (y)
+ lda $82
+ sta $40
+ lda #55
+
+ ldxi #0
+ ldyi #-1
+
+ mvi $12,#$45
+
+ dec $82
+ inc $40
+ dec (y)
+ inc (x)
+
+ bset 1,$12
+ bclr 3,$34
+
+ brset 5,$56,targ
+ brclr 7,$78,targ
diff --git a/tests/t_6804/t_6804.doc b/tests/t_6804/t_6804.doc
new file mode 100644
index 0000000..3fc32a7
--- /dev/null
+++ b/tests/t_6804/t_6804.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 6804 ----------------------------+
+| |
+| This is a (synthetic) test of the 6804's instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_6804/t_6804.ori b/tests/t_6804/t_6804.ori
new file mode 100644
index 0000000..ecaff8c
--- /dev/null
+++ b/tests/t_6804/t_6804.ori
Binary files differ
diff --git a/tests/t_68040/asflags b/tests/t_68040/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_68040/asflags
diff --git a/tests/t_68040/t_68040.asm b/tests/t_68040/t_68040.asm
new file mode 100644
index 0000000..b356a56
--- /dev/null
+++ b/tests/t_68040/t_68040.asm
@@ -0,0 +1,29 @@
+ cpu 68040
+ supmode on
+ pmmu on
+
+ move16 (a1)+,(a3)+
+ move16 (a4)+,$1234
+ move16 $12345,(a5)+
+ move16 (a6),$12345
+ move16 $1234,(a7)
+
+ cinva dc
+ cinva ic
+ cinva dc/ic
+ cinvl dc/ic,(a1)
+ cinvp dc/ic,(a2)
+ cpusha dc
+ cpusha ic
+ cpusha ic/dc
+ cpushl dc/ic,(a3)
+ cpushp dc/ic,(a4)
+
+ pflushn (a2)
+ pflush (a3)
+ pflushan
+ pflusha
+
+ ptestw (a2)
+ ptestr (a4)
+
diff --git a/tests/t_68040/t_68040.doc b/tests/t_68040/t_68040.doc
new file mode 100644
index 0000000..29ec852
--- /dev/null
+++ b/tests/t_68040/t_68040.doc
@@ -0,0 +1,6 @@
++------------------------ Test Application 68040 ----------------------------+
+| |
+| This is a (synthetic) test of the 68040's extensions to the 680x0 |
+| instruction set. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_68040/t_68040.ori b/tests/t_68040/t_68040.ori
new file mode 100644
index 0000000..3b5f3ac
--- /dev/null
+++ b/tests/t_68040/t_68040.ori
Binary files differ
diff --git a/tests/t_6805/asflags b/tests/t_6805/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_6805/asflags
diff --git a/tests/t_6805/t_6805.asm b/tests/t_6805/t_6805.asm
new file mode 100755
index 0000000..cbd5697
--- /dev/null
+++ b/tests/t_6805/t_6805.asm
@@ -0,0 +1,244 @@
+ cpu 6805
+ page 0
+
+ brset0 $12,*
+ brset1 $12,*+1
+ brset2 $12,*+2
+ brset3 $12,*+3
+ brset4 $12,*+4
+ brset5 $12,*+5
+ brset6 $12,*+6
+ brset7 $12,*+7
+ brclr0 $12,*+8
+ brclr1 $12,*+9
+ brclr2 $12,*+10
+ brclr3 $12,*+11
+ brclr4 $12,*+12
+ brclr5 $12,*+13
+ brclr6 $12,*+14
+ brclr7 $12,*+15
+
+ bset0 $12
+ bset1 $12
+ bset2 $12
+ bset3 $12
+ bset4 $12
+ bset5 $12
+ bset6 $12
+ bset7 $12
+ bclr0 $12
+ bclr1 $12
+ bclr2 $12
+ bclr3 $12
+ bclr4 $12
+ bclr5 $12
+ bclr6 $12
+ bclr7 $12
+
+ bra *-1
+ brn *-2
+ bhi *-3
+ bls *-4
+ bcc *-5
+ bcs *-6
+ bne *-7
+ beq *-8
+ bhcc *-9
+ bhcs *-10
+ bpl *-11
+ bmi *-12
+ bmc *-13
+ bms *-14
+ bil *-15
+ bih *-16
+
+ neg $12
+ nega
+ negx
+ neg $12,x
+ neg x
+
+ com $12
+ coma
+ comx
+ com $12,x
+ com x
+
+ lsr $12
+ lsra
+ lsrx
+ lsr $12,x
+ lsr x
+
+ ror $12
+ rora
+ rorx
+ ror $12,x
+ ror x
+
+ asr $12
+ asra
+ asrx
+ asr $12,x
+ asr x
+
+ lsl $12
+ lsla
+ lslx
+ lsl $12,x
+ lsl x
+
+ rol $12
+ rola
+ rolx
+ rol $12,x
+ rol x
+
+ dec $12
+ deca
+ decx
+ dec $12,x
+ dec x
+
+ inc $12
+ inca
+ incx
+ inc $12,x
+ inc x
+
+ tst $12
+ tsta
+ tstx
+ tst $12,x
+ tst x
+
+ clr $12
+ clra
+ clrx
+ clr $12,x
+ clr x
+
+ mul
+ rti
+ rts
+ swi
+ tax
+ clc
+ sec
+ cli
+ sei
+ rsp
+ nop
+ stop
+ wait
+ txa
+
+ sub #$12
+ sub $12
+ sub $1234
+ sub $1234,x
+ sub $12,x
+ sub x
+
+ cmp #$12
+ cmp $12
+ cmp $1234
+ cmp $1234,x
+ cmp $12,x
+ cmp x
+
+ cpx #$12
+ cpx $12
+ cpx $1234
+ cpx $1234,x
+ cpx $12,x
+ cpx x
+
+ sbc #$12
+ sbc $12
+ sbc $1234
+ sbc $1234,x
+ sbc $12,x
+ sbc x
+
+ and #$12
+ and $12
+ and $1234
+ and $1234,x
+ and $12,x
+ and x
+
+ bit #$12
+ bit $12
+ bit $1234
+ bit $1234,x
+ bit $12,x
+ bit x
+
+ lda #$12
+ lda $12
+ lda $1234
+ lda $1234,x
+ lda $12,x
+ lda x
+
+ sta $12
+ sta $1234
+ sta $1234,x
+ sta $12,x
+ sta x
+
+ eor #$12
+ eor $12
+ eor $1234
+ eor $1234,x
+ eor $12,x
+ eor x
+
+ adc #$12
+ adc $12
+ adc $1234
+ adc $1234,x
+ adc $12,x
+ adc x
+
+ ora #$12
+ ora $12
+ ora $1234
+ ora $1234,x
+ ora $12,x
+ ora x
+
+ add #$12
+ add $12
+ add $1234
+ add $1234,x
+ add $12,x
+ add x
+
+ jmp $12
+ jmp $1234
+ jmp $1234,x
+ jmp $12,x
+ jmp x
+
+ bsr *
+ jsr $12
+ jsr $1234
+ jsr $1234,x
+ jsr $12,x
+ jsr x
+
+ ldx #$12
+ ldx $12
+ ldx $1234
+ ldx $1234,x
+ ldx $12,x
+ ldx x
+
+ stx $12
+ stx $1234
+ stx $1234,x
+ stx $12,x
+ stx x
+
diff --git a/tests/t_6805/t_6805.doc b/tests/t_6805/t_6805.doc
new file mode 100644
index 0000000..dd38f44
--- /dev/null
+++ b/tests/t_6805/t_6805.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 6805 ----------------------------+
+| |
+| This is a (synthetic) test of the 6805 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_6805/t_6805.ori b/tests/t_6805/t_6805.ori
new file mode 100755
index 0000000..b60907f
--- /dev/null
+++ b/tests/t_6805/t_6805.ori
Binary files differ
diff --git a/tests/t_6808/asflags b/tests/t_6808/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_6808/asflags
diff --git a/tests/t_6808/t_6808.asm b/tests/t_6808/t_6808.asm
new file mode 100644
index 0000000..0143d90
--- /dev/null
+++ b/tests/t_6808/t_6808.asm
@@ -0,0 +1,406 @@
+ cpu 68HC08
+ page 0
+
+ adc #$55
+ adc $20
+ adc <$20
+ adc >$20
+ adc $2030
+ adc >$2030
+ adc ,x
+ adc 0,x
+ adc <0,x
+ adc $40,x
+ adc <$40,x
+ adc >$40,x
+ adc $4050,x
+ adc >$4050,x
+ adc ,sp
+ adc 0,sp
+ adc <0,sp
+ adc $40,sp
+ adc <$40,sp
+ adc >$40,sp
+ adc $4050,sp
+ adc >$4050,sp
+
+ add #$55
+ add $20
+ add $2030
+ add ,x
+ add $40,x
+ add $4050,x
+ add $40,sp
+ add $4050,sp
+
+ aix #34
+
+ ais #-16
+
+ and #$55
+ and $20
+ and $2030
+ and ,x
+ and $40,x
+ and $4050,x
+ and $40,sp
+ and $4050,sp
+
+ asla
+ aslx
+ asl $20
+ asl ,x
+ asl $40,x
+ asl $40,sp
+
+ asra
+ asrx
+ asr $20
+ asr ,x
+ asr $40,x
+ asr $40,sp
+
+ bcc *
+
+ bclr 0,$20
+ bclr 1,$20
+ bclr 2,$20
+ bclr 3,$20
+ bclr 4,$20
+ bclr 5,$20
+ bclr 6,$20
+ bclr 7,$20
+
+ bcs *
+
+ beq *
+
+ bge *
+
+ bgt *
+
+ bhcc *
+
+ bhcs *
+
+ bhi *
+
+ bhs *
+
+ bih *
+
+ bil *
+
+ bit #$55
+ bit $20
+ bit $2030
+ bit ,x
+ bit $40,x
+ bit $4050,x
+ bit $40,sp
+ bit $4050,sp
+
+ ble *
+
+ blo *
+
+ bls *
+
+ blt *
+
+ bmc *
+
+ bmi *
+
+ bms *
+
+ bne *
+
+ bpl *
+
+ bra *
+
+ brclr 0,$20,*
+ brclr 1,$20,*
+ brclr 2,$20,*
+ brclr 3,$20,*
+ brclr 4,$20,*
+ brclr 5,$20,*
+ brclr 6,$20,*
+ brclr 7,$20,*
+
+ brn *
+
+ brset 0,$20,*
+ brset 1,$20,*
+ brset 2,$20,*
+ brset 3,$20,*
+ brset 4,$20,*
+ brset 5,$20,*
+ brset 6,$20,*
+ brset 7,$20,*
+
+ bset 0,$20
+ bset 1,$20
+ bset 2,$20
+ bset 3,$20
+ bset 4,$20
+ bset 5,$20
+ bset 6,$20
+ bset 7,$20
+
+ bsr *
+
+ cbeq $20,*
+ cbeq x+,*
+ cbeq $40,x+,*
+ cbeq $40,sp,*
+
+ cbeqa #$55,*
+ cbeqx #$66,*
+
+ clc
+
+ cli
+
+ clra
+ clrx
+ clrh
+ clr $20
+ clr ,x
+ clr $40,x
+ clr $40,sp
+
+ cmp #$55
+ cmp $20
+ cmp $2030
+ cmp ,x
+ cmp $40,x
+ cmp $4050,x
+ cmp $40,sp
+ cmp $4050,sp
+
+ coma
+ comx
+ com $20
+ com ,x
+ com $40,x
+ com $40,sp
+
+ cphx #$55aa
+ cphx $20
+
+ cpx #$55
+ cpx $20
+ cpx $2030
+ cpx ,x
+ cpx $40,x
+ cpx $4050,x
+ cpx $40,sp
+ cpx $4050,sp
+
+ daa
+
+ dbnza *
+ dbnzx *
+
+ dbnz $20,*
+ dbnz x,*
+ dbnz $40,x,*
+ dbnz $40,sp,*
+
+ deca
+ decx
+ dec $20
+ dec ,x
+ dec $40,x
+ dec $40,sp
+
+ div
+
+ eor #$55
+ eor $20
+ eor $2030
+ eor ,x
+ eor $40,x
+ eor $4050,x
+ eor $40,sp
+ eor $4050,sp
+
+ inca
+ incx
+ inc $20
+ inc ,x
+ inc $40,x
+ inc $40,sp
+
+ jmp $20
+ jmp $2030
+ jmp ,x
+ jmp $40,x
+ jmp $4050,x
+
+ jsr $20
+ jsr $2030
+ jsr ,x
+ jsr $40,x
+ jsr $4050,x
+
+ lda #$55
+ lda $20
+ lda $2030
+ lda ,x
+ lda $40,x
+ lda $4050,x
+ lda $40,sp
+ lda $4050,sp
+
+ ldhx #$55aa
+ ldhx $20
+
+ ldx #$55
+ ldx $20
+ ldx $2030
+ ldx ,x
+ ldx $40,x
+ ldx $4050,x
+ ldx $40,sp
+ ldx $4050,sp
+
+ lsla
+ lslx
+ lsl $20
+ lsl ,x
+ lsl $40,x
+ lsl $40,sp
+
+ lsra
+ lsrx
+ lsr $20
+ lsr ,x
+ lsr $40,x
+ lsr $40,sp
+
+ mov #$55,$20
+ mov $20,$40
+ mov x+,$20
+ mov $40,x+
+
+ mul
+
+ nega
+ negx
+ neg $20
+ neg ,x
+ neg $40,x
+ neg $40,sp
+
+ nop
+
+ nsa
+
+ ora #$55
+ ora $20
+ ora $2030
+ ora ,x
+ ora $40,x
+ ora $4050,x
+ ora $40,sp
+ ora $4050,sp
+
+ psha
+
+ pshh
+
+ pshx
+
+ pula
+
+ pulh
+
+ pulx
+
+ rola
+ rolx
+ rol $20
+ rol ,x
+ rol $40,x
+ rol $40,sp
+
+ rora
+ rorx
+ ror $20
+ ror ,x
+ ror $40,x
+ ror $40,sp
+
+ rsp
+
+ rti
+
+ rts
+
+ sbc #$55
+ sbc $20
+ sbc $2030
+ sbc ,x
+ sbc $40,x
+ sbc $4050,x
+ sbc $40,sp
+ sbc $4050,sp
+
+ sec
+
+ sei
+
+ sta $20
+ sta $2030
+ sta ,x
+ sta $40,x
+ sta $4050,x
+ sta $40,sp
+ sta $4050,sp
+
+ sthx $20
+
+ stop
+
+ stx $20
+ stx $2030
+ stx ,x
+ stx $40,x
+ stx $4050,x
+ stx $40,sp
+ stx $4050,sp
+
+ sub #$55
+ sub $20
+ sub $2030
+ sub ,x
+ sub $40,x
+ sub $4050,x
+ sub $40,sp
+ sub $4050,sp
+
+ swi
+
+ tap
+
+ tax
+
+ tpa
+
+ tsta
+ tstx
+ tst $20
+ tst ,x
+ tst $40,x
+ tst $40,sp
+
+ tsx
+
+ txa
+
+ txs
+
+ wait
diff --git a/tests/t_6808/t_6808.doc b/tests/t_6808/t_6808.doc
new file mode 100644
index 0000000..714175b
--- /dev/null
+++ b/tests/t_6808/t_6808.doc
@@ -0,0 +1,6 @@
++------------------------- Test Application 6808 ----------------------------+
+| |
+| This is a (synthetic) test of the 68HC08's extensions to the 6805 |
+| basic instruction set. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_6808/t_6808.ori b/tests/t_6808/t_6808.ori
new file mode 100644
index 0000000..ca94eea
--- /dev/null
+++ b/tests/t_6808/t_6808.ori
Binary files differ
diff --git a/tests/t_6812/asflags b/tests/t_6812/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_6812/asflags
diff --git a/tests/t_6812/t_6812.asm b/tests/t_6812/t_6812.asm
new file mode 100644
index 0000000..35c547e
--- /dev/null
+++ b/tests/t_6812/t_6812.asm
@@ -0,0 +1,644 @@
+ cpu 68hc12
+ page 0
+
+ aba
+
+ abx
+
+ aby
+
+ adca #45
+ adca $45
+ adca $1234
+ adca >$45
+ adca ,y
+ adca 5,x
+ adca -5,sp
+ adca *,pc
+ adca *+10,pc
+ adca *+17,pc
+ adca a,y
+ adca b,sp
+ adca d,pc
+ adca 55,y
+ adca -55,sp
+ adca <5,y
+ adca <-5,sp
+ adca *+18,pc
+ adca *+258,pc
+ adca 555,y
+ adca -555,sp
+ adca >55,y
+ adca >-55,sp
+ adca *+259,pc
+ adca [d,sp]
+ adca [d,x]
+ adca [-5,y]
+ adca [500,y]
+ adca 4,+y
+ adca 4,y+
+ adca 4,-y
+ adca 4,y-
+
+ adcb #55
+ adcb $55
+ adcb ,x
+ adcb $1234
+
+ adda #55
+ adda $55
+ adda ,x
+ adda $1234
+
+ addb #55
+ addb $55
+ addb ,x
+ addb $1234
+
+ addd #55
+ addd $55
+ addd ,x
+ addd $1234
+
+ anda #55
+ anda $55
+ anda ,x
+ anda $1234
+
+ andb #55
+ andb $55
+ andb ,x
+ andb $1234
+
+ andcc #$fe
+
+ asl $55
+ asl ,x
+ asl $1234
+
+ asla
+
+ aslb
+
+ asld
+
+ asr $55
+ asr ,x
+ asr $1234
+
+ asra
+
+ asrb
+
+ bcc *
+
+ bclr $20 #$40
+ bclr $20,#$40
+ bclr $1234 #$40
+ bclr $1234,#$40
+ bclr ,x $40
+ bclr $20,y,$40
+ bclr *,pc,$40
+
+ bcs *
+
+ beq *
+
+ bge *
+
+ bgnd
+
+ bgt *
+
+ bhi *
+
+ bhs *
+
+ bita #$55
+ bita $55
+ bita ,x
+ bita $1234
+
+ bitb #$55
+ bitb $55
+ bitb ,x
+ bitb $1234
+
+ ble *
+
+ blo *
+
+ bls *
+
+ blt *
+
+ bmi *
+
+ bne *
+
+ bpl *
+
+ bra *
+
+ brclr $20 #$40 *
+ brclr $2000,#$40,*
+ brclr ,x,#$40,*
+ brclr *,pc,#$40,*
+
+ brn *
+
+ brset $20 #$40 *
+ brset $2000,#$40,*
+ brset ,x,#$40,*
+ brset *,pc,#$40,*
+
+ bset $20 #$40
+ bset $20,#$40
+ bset $1234 #$40
+ bset $1234,#$40
+ bset ,x $40
+ bset $20,y,$40
+
+ bsr *
+
+ bvc *
+
+ bvs *
+
+ call $2000,5
+ call 5,y,6
+ call 200,y,7
+ call 20000,y,8
+ call [d,y]
+ call [20,y]
+
+ cba
+
+ clc
+ andcc #$fe
+
+ cli
+ andcc #$ef
+
+ clr $55
+ clr ,x
+ clr $1234
+
+ clra
+
+ clrb
+
+ clv
+ andcc #$fd
+
+ cmpa #55
+ cmpa $55
+ cmpa ,x
+ cmpa $1234
+
+ cmpb #55
+ cmpb $55
+ cmpb ,x
+ cmpb $1234
+
+ com $55
+ com ,x
+ com $1234
+
+ coma
+
+ comb
+
+ cpd #55
+ cpd $55
+ cpd ,x
+ cpd $1234
+
+ cps #55
+ cps $55
+ cps ,x
+ cps $1234
+
+ cpx #55
+ cpx $55
+ cpx ,x
+ cpx $1234
+
+ cpy #55
+ cpy $55
+ cpy ,x
+ cpy $1234
+
+ daa
+
+ dbeq x,*
+
+ dbne x,*
+
+ dec $55
+ dec ,x
+ dec $1234
+
+ deca
+
+ decb
+
+ des
+ leas -1,sp
+
+ dex
+
+ dey
+
+ ediv
+
+ edivs
+
+ emacs $1234
+
+ emaxd ,x
+
+ emaxm ,x
+
+ emind ,x
+
+ eminm ,x
+
+ emul
+
+ emuls
+
+ eora #55
+ eora $55
+ eora ,x
+ eora $1234
+
+ eorb #55
+ eorb $55
+ eorb ,x
+ eorb $1234
+
+ etbl 5,y
+
+ exg ccr,sp
+
+ fdiv
+
+ ibeq a,*
+
+ ibne a,*
+
+ idiv
+
+ idivs
+
+ inc $55
+ inc ,x
+ inc $1234
+
+ inca
+
+ incb
+
+ ins
+ leas 1,sp
+
+ inx
+
+ iny
+
+ jmp $2000
+ jmp $20
+ jmp [d,x]
+
+ jsr $2000
+ jsr $20
+ jsr [d,x]
+
+ lbcc *
+
+ lbcs *
+
+ lbeq *
+
+ lbge *
+
+ lbgt *
+
+ lbhi *
+
+ lbhs *
+
+ lble *
+
+ lblo *
+
+ lbls *
+
+ lblt *
+
+ lbmi *
+
+ lbne *
+
+ lbpl *
+
+ lbra *
+
+ lbrn *
+
+ lbvc *
+
+ lbvs *
+
+ ldaa #55
+ ldaa $55
+ ldaa ,x
+ ldaa $1234
+
+ ldab #55
+ ldab $55
+ ldab ,x
+ ldab $1234
+
+ ldd #55
+ ldd $55
+ ldd ,x
+ ldd $1234
+
+ lds #55
+ lds $55
+ lds ,x
+ lds $1234
+
+ ldx #55
+ ldx $55
+ ldx ,x
+ ldx $1234
+
+ ldy #55
+ ldy $55
+ ldy ,x
+ ldy $1234
+
+ leas 2000,sp
+
+ leax ,y
+
+ leay ,x
+
+ lsl $55
+ lsl ,x
+ lsl $1234
+
+ lsla
+
+ lslb
+
+ lsld
+
+ lsr $55
+ lsr ,x
+ lsr $1234
+
+ lsra
+
+ lsrb
+
+ lsrd
+
+ maxa ,x
+
+ maxm ,x
+
+ mem
+
+ mina ,x
+
+ minm ,x
+
+ movb #$55 $1234
+ movb #$55,$1234
+ movb #$55 2,y
+ movb #$55,2,y
+ movb #$55,next_a,pc
+next_a: movb $1234 $3456
+ movb $1234,$3456
+ movb $1234 2,y
+ movb $1234,2,y
+ movb $1234,next_b,pc
+next_b: movb 2,y $1234
+ movb 2,y,$1234
+ movb next_c,pc,$1234
+next_c: movb 2,y 2,y
+ movb 2,y,2,y
+ movb next_d,pc next_d,pc
+next_d:
+ movw #$55 $1234
+ movw #$55,$1234
+ movw #$55 2,y
+ movw #$55,2,y
+ movw #$55,next_e,pc
+next_e: movw $1234 $3456
+ movw $1234,$3456
+ movw $1234 2,y
+ movw $1234,2,y
+ movw $1234,next_f,pc
+next_f: movw 2,y $1234
+ movw 2,y,$1234
+ movw next_g,pc,$1234
+next_g: movw 2,y 2,y
+ movw 2,y,2,y
+ movw next_h,pc next_h,pc
+next_h:
+
+ mul
+
+ neg $55
+ neg ,x
+ neg $1234
+
+ nega
+
+ negb
+
+ nop
+
+ oraa #55
+ oraa $55
+ oraa ,x
+ oraa $1234
+
+ orab #55
+ orab $55
+ orab ,x
+ orab $1234
+
+ orcc #$10
+
+ psha
+
+ pshb
+
+ pshc
+
+ pshd
+
+ pshx
+
+ pshy
+
+ pula
+
+ pulb
+
+ pulc
+
+ puld
+
+ pulx
+
+ puly
+
+ rev
+
+ revw
+
+ rol $55
+ rol ,x
+ rol $1234
+
+ rola
+
+ rolb
+
+ ror $55
+ ror ,x
+ ror $1234
+
+ rora
+
+ rorb
+
+ rtc
+
+ rti
+
+ rts
+
+ sba
+
+ sbca #55
+ sbca $55
+ sbca ,x
+ sbca $1234
+
+ sbcb #55
+ sbcb $55
+ sbcb ,x
+ sbcb $1234
+
+ sec
+ orcc #$01
+
+ sei
+ orcc #$10
+
+ sev
+ orcc #$02
+
+ sex a,d
+
+ staa $55
+ staa ,x
+ staa $1234
+
+ stab $55
+ stab ,x
+ stab $1234
+
+ std $55
+ std ,x
+ std $1234
+
+ sts $55
+ sts ,x
+ sts $1234
+
+ stx $55
+ stx ,x
+ stx $1234
+
+ sty $55
+ sty ,x
+ sty $1234
+
+ stop
+
+ suba #55
+ suba $55
+ suba ,x
+ suba $1234
+
+ subb #55
+ subb $55
+ subb ,x
+ subb $1234
+
+ subd #55
+ subd $55
+ subd ,x
+ subd $1234
+
+ swi
+
+ tab
+
+ tap
+ tfr a,ccr
+
+ tba
+
+ tbeq d,*
+
+ tbl a,x
+
+ tbne d,*
+
+ tfr a,b
+ tfr x,y
+
+ tpa
+ tfr ccr,a
+
+ trap #$42
+
+ tst $55
+ tst ,x
+ tst $1234
+
+ tsta
+
+ tstb
+
+ tsx
+ tfr sp,x
+
+ tsy
+ tfr sp,y
+
+ txs
+ tfr x,sp
+
+ tys
+ tfr y,sp
+
+ wai
+
+ wav
+
+ xgdx
+ exg d,x
+
+ xgdy
+ exg d,y
diff --git a/tests/t_6812/t_6812.doc b/tests/t_6812/t_6812.doc
new file mode 100644
index 0000000..ed4a23a
--- /dev/null
+++ b/tests/t_6812/t_6812.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 6812 ----------------------------+
+| |
+| This is a (synthetic) test of the 68HC12 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_6812/t_6812.ori b/tests/t_6812/t_6812.ori
new file mode 100644
index 0000000..b57d4cd
--- /dev/null
+++ b/tests/t_6812/t_6812.ori
Binary files differ
diff --git a/tests/t_6816/asflags b/tests/t_6816/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_6816/asflags
diff --git a/tests/t_6816/t_6816.asm b/tests/t_6816/t_6816.asm
new file mode 100644
index 0000000..70299d2
--- /dev/null
+++ b/tests/t_6816/t_6816.asm
@@ -0,0 +1,1037 @@
+ cpu 68hc16
+ page 0
+ assume ek:0
+
+ aba ;$370b
+ abx ;$374f
+ aby ;$375f
+ abz ;$376f
+ ace ;$3722
+ aced ;$3723
+ ade ;$2778
+ adx ;$37cd
+ ady ;$37dd
+ adz ;$37ed
+ aex ;$374d
+ aey ;$375d
+ aez ;$376d
+ asla ;$3704
+ aslb ;$3714
+ asld ;$27f4
+ asle ;$2774
+ aslm ;$27b6
+ asra ;$370d
+ asrb ;$371d
+ asrd ;$27fd
+ asre ;$277d
+ asrm ;$27ba
+ bgnd ;$37a6
+ cba ;$371b
+ clra ;$3705
+ clrb ;$3715
+ clrd ;$27f5
+ clre ;$2775
+ clrm ;$27b7
+ coma ;$3700
+ comb ;$3710
+ comd ;$27f0
+ come ;$2770
+ daa ;$3721
+ deca ;$3701
+ decb ;$3711
+ ediv ;$3728
+ edivs ;$3729
+ emul ;$3725
+ emuls ;$3726
+ fdiv ;$372b
+ fmuls ;$3727
+ idiv ;$372a
+ inca ;$3703
+ incb ;$3713
+ lpstop ;$27f1
+ lsla ;$3704
+ lslb ;$3714
+ lsld ;$27f4
+ lsle ;$2774
+ lsra ;$370f
+ lsrb ;$371f
+ lsrd ;$27ff
+ lsre ;$277f
+ mul ;$3724
+ nega ;$3702
+ negb ;$3712
+ negd ;$27f2
+ nege ;$2772
+ nop ;$274c
+ psha ;$3708
+ pshb ;$3718
+ pshmac ;$27b8
+ pula ;$3709
+ pulb ;$3719
+ pulmac ;$27b9
+ rola ;$370c
+ rolb ;$371c
+ rold ;$27fc
+ role ;$277c
+ rora ;$370e
+ rorb ;$371e
+ rord ;$27fe
+ rore ;$277e
+ rti ;$2777
+ rts ;$27f7
+ sba ;$370a
+ sde ;$2779
+ swi ;$3720
+ sxt ;$27f8
+ tab ;$3717
+ tap ;$37fd
+ tba ;$3707
+ tbek ;$27fa
+ tbsk ;$379f
+ tbxk ;$379c
+ tbyk ;$379d
+ tbzk ;$379e
+ tde ;$277b
+ tdmsk ;$372f
+ tdp ;$372d
+ ted ;$27fb
+ tedm ;$27b1
+ tekb ;$27bb
+ tem ;$27b2
+ tmer ;$27b4
+ tmet ;$27b5
+ tmxed ;$27b3
+ tpa ;$37fc
+ tpd ;$372c
+ tskb ;$37af
+ tsta ;$3706
+ tstb ;$3716
+ tstd ;$27f6
+ tste ;$2776
+ tsx ;$274f
+ tsy ;$275f
+ tsz ;$276f
+ txkb ;$37ac
+ txs ;$374e
+ txy ;$275c
+ txz ;$276c
+ tykb ;$37ad
+ tys ;$375e
+ tyx ;$274d
+ tyz ;$276d
+ tzkb ;$37ae
+ tzs ;$376e
+ tzx ;$274e
+ tzy ;$275e
+ wai ;$27f3
+ xgab ;$371a
+ xgde ;$277a
+ xgdx ;$37cc
+ xgdy ;$37dc
+ xgdz ;$37ec
+ xgex ;$374c
+ xgey ;$375c
+ xgez ;$376c
+
+targ: bra targ
+ brn targ
+ bcc targ
+ bcs targ
+ bhs targ
+ blo targ
+ bmi targ
+ bne targ
+ bpl targ
+ bvc targ
+ bvs targ
+ bhi targ
+ bls targ
+ beq targ
+ bge targ
+ bgt targ
+ ble targ
+ blt targ
+ lbra targ
+ lbrn targ
+ lbcc targ
+ lbcs targ
+ lbhs targ
+ lblo targ
+ lbmi targ
+ lbne targ
+ lbpl targ
+ lbvc targ
+ lbvs targ
+ lbhi targ
+ lbls targ
+ lbeq targ
+ lbge targ
+ lbgt targ
+ lble targ
+ lblt targ
+ bsr targ
+ lbev targ
+ lbmv targ
+ lbsr targ
+
+ adca $55,x
+ adca $55,y
+ adca $55,z
+ adca #$aa
+ adca $5aa5,x
+ adca $5aa5,y
+ adca $5aa5,z
+ adca $1234
+ adca e,x
+ adca e,y
+ adca e,z
+
+ adcb $55,x
+ adcb $55,y
+ adcb $55,z
+ adcb #$aa
+ adcb $5aa5,x
+ adcb $5aa5,y
+ adcb $5aa5,z
+ adcb $1234
+ adcb e,x
+ adcb e,y
+ adcb e,z
+
+ adcd $55,x
+ adcd $55,y
+ adcd $55,z
+ adcd #$aa
+ adcd $5aa5,x
+ adcd $5aa5,y
+ adcd $5aa5,z
+ adcd $1234
+ adcd e,x
+ adcd e,y
+ adcd e,z
+
+ adce $55,x
+ adce $55,y
+ adce $55,z
+ adce #$aa
+ adce $5aa5,x
+ adce $5aa5,y
+ adce $5aa5,z
+ adce $1234
+
+ adda $55,x
+ adda $55,y
+ adda $55,z
+ adda #$aa
+ adda $5aa5,x
+ adda $5aa5,y
+ adda $5aa5,z
+ adda $1234
+ adda e,x
+ adda e,y
+ adda e,z
+
+ addb $55,x
+ addb $55,y
+ addb $55,z
+ addb #$aa
+ addb $5aa5,x
+ addb $5aa5,y
+ addb $5aa5,z
+ addb $1234
+ addb e,x
+ addb e,y
+ addb e,z
+
+ addd $55,x
+ addd $55,y
+ addd $55,z
+ addd #$55
+ addd #$aa
+ addd $5aa5,x
+ addd $5aa5,y
+ addd $5aa5,z
+ addd $1234
+ addd e,x
+ addd e,y
+ addd e,z
+
+ adde $55,x
+ adde $55,y
+ adde $55,z
+ adde #$55
+ adde #$aa
+ adde $5aa5,x
+ adde $5aa5,y
+ adde $5aa5,z
+ adde $1234
+
+ anda $55,x
+ anda $55,y
+ anda $55,z
+ anda #$aa
+ anda $5aa5,x
+ anda $5aa5,y
+ anda $5aa5,z
+ anda $1234
+ anda e,x
+ anda e,y
+ anda e,z
+
+ andb $55,x
+ andb $55,y
+ andb $55,z
+ andb #$aa
+ andb $5aa5,x
+ andb $5aa5,y
+ andb $5aa5,z
+ andb $1234
+ andb e,x
+ andb e,y
+ andb e,z
+
+ andd $55,x
+ andd $55,y
+ andd $55,z
+ andd #$aa
+ andd $5aa5,x
+ andd $5aa5,y
+ andd $5aa5,z
+ andd $1234
+ andd e,x
+ andd e,y
+ andd e,z
+
+ ande $55,x
+ ande $55,y
+ ande $55,z
+ ande #$aa
+ ande $5aa5,x
+ ande $5aa5,y
+ ande $5aa5,z
+ ande $1234
+
+ asl $55,x
+ asl $55,y
+ asl $55,z
+ asl $5aa5,x
+ asl $5aa5,y
+ asl $5aa5,z
+ asl $1234
+
+ aslw $5aa5,x
+ aslw $5aa5,y
+ aslw $5aa5,z
+ aslw $1234
+
+ asr $55,x
+ asr $55,y
+ asr $55,z
+ asr $5aa5,x
+ asr $5aa5,y
+ asr $5aa5,z
+ asr $1234
+
+ asrw $5aa5,x
+ asrw $5aa5,y
+ asrw $5aa5,z
+ asrw $1234
+
+ bita $55,x
+ bita $55,y
+ bita $55,z
+ bita #$aa
+ bita $5aa5,x
+ bita $5aa5,y
+ bita $5aa5,z
+ bita $1234
+ bita e,x
+ bita e,y
+ bita e,z
+
+ bitb $55,x
+ bitb $55,y
+ bitb $55,z
+ bitb #$aa
+ bitb $5aa5,x
+ bitb $5aa5,y
+ bitb $5aa5,z
+ bitb $1234
+ bitb e,x
+ bitb e,y
+ bitb e,z
+
+ clr $55,x
+ clr $55,y
+ clr $55,z
+ clr $5aa5,x
+ clr $5aa5,y
+ clr $5aa5,z
+ clr $1234
+
+ clrw $5aa5,x
+ clrw $5aa5,y
+ clrw $5aa5,z
+ clrw $1234
+
+ cmpa $55,x
+ cmpa $55,y
+ cmpa $55,z
+ cmpa #$aa
+ cmpa $5aa5,x
+ cmpa $5aa5,y
+ cmpa $5aa5,z
+ cmpa $1234
+ cmpa e,x
+ cmpa e,y
+ cmpa e,z
+
+ cmpb $55,x
+ cmpb $55,y
+ cmpb $55,z
+ cmpb #$aa
+ cmpb $5aa5,x
+ cmpb $5aa5,y
+ cmpb $5aa5,z
+ cmpb $1234
+ cmpb e,x
+ cmpb e,y
+ cmpb e,z
+
+ com $55,x
+ com $55,y
+ com $55,z
+ com $5aa5,x
+ com $5aa5,y
+ com $5aa5,z
+ com $1234
+
+ comw $5aa5,x
+ comw $5aa5,y
+ comw $5aa5,z
+ comw $1234
+
+ cpd $55,x
+ cpd $55,y
+ cpd $55,z
+ cpd #$aa
+ cpd $5aa5,x
+ cpd $5aa5,y
+ cpd $5aa5,z
+ cpd $1234
+ cpd e,x
+ cpd e,y
+ cpd e,z
+
+ cpe $55,x
+ cpe $55,y
+ cpe $55,z
+ cpe #$aa
+ cpe $5aa5,x
+ cpe $5aa5,y
+ cpe $5aa5,z
+ cpe $1234
+
+ dec $55,x
+ dec $55,y
+ dec $55,z
+ dec $5aa5,x
+ dec $5aa5,y
+ dec $5aa5,z
+ dec $1234
+
+ decw $5aa5,x
+ decw $5aa5,y
+ decw $5aa5,z
+ decw $1234
+
+ eora $55,x
+ eora $55,y
+ eora $55,z
+ eora #$aa
+ eora $5aa5,x
+ eora $5aa5,y
+ eora $5aa5,z
+ eora $1234
+ eora e,x
+ eora e,y
+ eora e,z
+
+ eorb $55,x
+ eorb $55,y
+ eorb $55,z
+ eorb #$aa
+ eorb $5aa5,x
+ eorb $5aa5,y
+ eorb $5aa5,z
+ eorb $1234
+ eorb e,x
+ eorb e,y
+ eorb e,z
+
+ eord $55,x
+ eord $55,y
+ eord $55,z
+ eord #$aa
+ eord $5aa5,x
+ eord $5aa5,y
+ eord $5aa5,z
+ eord $1234
+ eord e,x
+ eord e,y
+ eord e,z
+
+ eore $55,x
+ eore $55,y
+ eore $55,z
+ eore #$aa
+ eore $5aa5,x
+ eore $5aa5,y
+ eore $5aa5,z
+ eore $1234
+
+ inc $55,x
+ inc $55,y
+ inc $55,z
+ inc $5aa5,x
+ inc $5aa5,y
+ inc $5aa5,z
+ inc $1234
+
+ incw $5aa5,x
+ incw $5aa5,y
+ incw $5aa5,z
+ incw $1234
+
+ ldaa $55,x
+ ldaa $55,y
+ ldaa $55,z
+ ldaa #$aa
+ ldaa $5aa5,x
+ ldaa $5aa5,y
+ ldaa $5aa5,z
+ ldaa $1234
+ ldaa e,x
+ ldaa e,y
+ ldaa e,z
+
+ ldab $55,x
+ ldab $55,y
+ ldab $55,z
+ ldab #$aa
+ ldab $5aa5,x
+ ldab $5aa5,y
+ ldab $5aa5,z
+ ldab $1234
+ ldab e,x
+ ldab e,y
+ ldab e,z
+
+ ldd $55,x
+ ldd $55,y
+ ldd $55,z
+ ldd #$aa
+ ldd $5aa5,x
+ ldd $5aa5,y
+ ldd $5aa5,z
+ ldd $1234
+ ldd e,x
+ ldd e,y
+ ldd e,z
+
+ lde $55,x
+ lde $55,y
+ lde $55,z
+ lde #$aa
+ lde $5aa5,x
+ lde $5aa5,y
+ lde $5aa5,z
+ lde $1234
+
+ lsl $55,x
+ lsl $55,y
+ lsl $55,z
+ lsl $5aa5,x
+ lsl $5aa5,y
+ lsl $5aa5,z
+ lsl $1234
+
+ lslw $5aa5,x
+ lslw $5aa5,y
+ lslw $5aa5,z
+ lslw $1234
+
+ lsr $55,x
+ lsr $55,y
+ lsr $55,z
+ lsr $5aa5,x
+ lsr $5aa5,y
+ lsr $5aa5,z
+ lsr $1234
+
+ lsrw $5aa5,x
+ lsrw $5aa5,y
+ lsrw $5aa5,z
+ lsrw $1234
+
+ neg $55,x
+ neg $55,y
+ neg $55,z
+ neg $5aa5,x
+ neg $5aa5,y
+ neg $5aa5,z
+ neg $1234
+
+ negw $5aa5,x
+ negw $5aa5,y
+ negw $5aa5,z
+ negw $1234
+
+ oraa $55,x
+ oraa $55,y
+ oraa $55,z
+ oraa #$aa
+ oraa $5aa5,x
+ oraa $5aa5,y
+ oraa $5aa5,z
+ oraa $1234
+ oraa e,x
+ oraa e,y
+ oraa e,z
+
+ orab $55,x
+ orab $55,y
+ orab $55,z
+ orab #$aa
+ orab $5aa5,x
+ orab $5aa5,y
+ orab $5aa5,z
+ orab $1234
+ orab e,x
+ orab e,y
+ orab e,z
+
+ ord $55,x
+ ord $55,y
+ ord $55,z
+ ord #$aa
+ ord $5aa5,x
+ ord $5aa5,y
+ ord $5aa5,z
+ ord $1234
+ ord e,x
+ ord e,y
+ ord e,z
+
+ ore $55,x
+ ore $55,y
+ ore $55,z
+ ore #$aa
+ ore $5aa5,x
+ ore $5aa5,y
+ ore $5aa5,z
+ ore $1234
+
+ rol $55,x
+ rol $55,y
+ rol $55,z
+ rol $5aa5,x
+ rol $5aa5,y
+ rol $5aa5,z
+ rol $1234
+
+ rolw $5aa5,x
+ rolw $5aa5,y
+ rolw $5aa5,z
+ rolw $1234
+
+ ror $55,x
+ ror $55,y
+ ror $55,z
+ ror $5aa5,x
+ ror $5aa5,y
+ ror $5aa5,z
+ ror $1234
+
+ rorw $5aa5,x
+ rorw $5aa5,y
+ rorw $5aa5,z
+ rorw $1234
+
+ sbca $55,x
+ sbca $55,y
+ sbca $55,z
+ sbca #$aa
+ sbca $5aa5,x
+ sbca $5aa5,y
+ sbca $5aa5,z
+ sbca $1234
+ sbca e,x
+ sbca e,y
+ sbca e,z
+
+ sbcb $55,x
+ sbcb $55,y
+ sbcb $55,z
+ sbcb #$aa
+ sbcb $5aa5,x
+ sbcb $5aa5,y
+ sbcb $5aa5,z
+ sbcb $1234
+ sbcb e,x
+ sbcb e,y
+ sbcb e,z
+
+ sbcd $55,x
+ sbcd $55,y
+ sbcd $55,z
+ sbcd #$aa
+ sbcd $5aa5,x
+ sbcd $5aa5,y
+ sbcd $5aa5,z
+ sbcd $1234
+ sbcd e,x
+ sbcd e,y
+ sbcd e,z
+
+ sbce $55,x
+ sbce $55,y
+ sbce $55,z
+ sbce #$aa
+ sbce $5aa5,x
+ sbce $5aa5,y
+ sbce $5aa5,z
+ sbce $1234
+
+ staa $55,x
+ staa $55,y
+ staa $55,z
+ staa $5aa5,x
+ staa $5aa5,y
+ staa $5aa5,z
+ staa $1234
+ staa e,x
+ staa e,y
+ staa e,z
+
+ stab $55,x
+ stab $55,y
+ stab $55,z
+ stab $5aa5,x
+ stab $5aa5,y
+ stab $5aa5,z
+ stab $1234
+ stab e,x
+ stab e,y
+ stab e,z
+
+ std $55,x
+ std $55,y
+ std $55,z
+ std $5aa5,x
+ std $5aa5,y
+ std $5aa5,z
+ std $1234
+ std e,x
+ std e,y
+ std e,z
+
+ ste $55,x
+ ste $55,y
+ ste $55,z
+ ste $5aa5,x
+ ste $5aa5,y
+ ste $5aa5,z
+ ste $1234
+
+ suba $55,x
+ suba $55,y
+ suba $55,z
+ suba #$aa
+ suba $5aa5,x
+ suba $5aa5,y
+ suba $5aa5,z
+ suba $1234
+ suba e,x
+ suba e,y
+ suba e,z
+
+ subb $55,x
+ subb $55,y
+ subb $55,z
+ subb #$aa
+ subb $5aa5,x
+ subb $5aa5,y
+ subb $5aa5,z
+ subb $1234
+ subb e,x
+ subb e,y
+ subb e,z
+
+ subd $55,x
+ subd $55,y
+ subd $55,z
+ subd #$aa
+ subd $5aa5,x
+ subd $5aa5,y
+ subd $5aa5,z
+ subd $1234
+ subd e,x
+ subd e,y
+ subd e,z
+
+ sube $55,x
+ sube $55,y
+ sube $55,z
+ sube #$aa
+ sube $5aa5,x
+ sube $5aa5,y
+ sube $5aa5,z
+ sube $1234
+
+ tst $55,x
+ tst $55,y
+ tst $55,z
+ tst $5aa5,x
+ tst $5aa5,y
+ tst $5aa5,z
+ tst $1234
+
+ tstw $5aa5,x
+ tstw $5aa5,y
+ tstw $5aa5,z
+ tstw $1234
+
+ cps $55,x
+ cps $55,y
+ cps $55,z
+ cps #$aa
+ cps $5aa5,x
+ cps $5aa5,y
+ cps $5aa5,z
+ cps $1234
+
+ cpx $55,x
+ cpx $55,y
+ cpx $55,z
+ cpx #$aa
+ cpx $5aa5,x
+ cpx $5aa5,y
+ cpx $5aa5,z
+ cpx $1234
+
+ cpy $55,x
+ cpy $55,y
+ cpy $55,z
+ cpy #$aa
+ cpy $5aa5,x
+ cpy $5aa5,y
+ cpy $5aa5,z
+ cpy $1234
+
+ cpz $55,x
+ cpz $55,y
+ cpz $55,z
+ cpz #$aa
+ cpz $5aa5,x
+ cpz $5aa5,y
+ cpz $5aa5,z
+ cpz $1234
+
+ lds $55,x
+ lds $55,y
+ lds $55,z
+ lds #$aa
+ lds $5aa5,x
+ lds $5aa5,y
+ lds $5aa5,z
+ lds $1234
+
+ ldx $55,x
+ ldx $55,y
+ ldx $55,z
+ ldx #$aa
+ ldx $5aa5,x
+ ldx $5aa5,y
+ ldx $5aa5,z
+ ldx $1234
+
+ ldy $55,x
+ ldy $55,y
+ ldy $55,z
+ ldy #$aa
+ ldy $5aa5,x
+ ldy $5aa5,y
+ ldy $5aa5,z
+ ldy $1234
+
+ ldz $55,x
+ ldz $55,y
+ ldz $55,z
+ ldz #$aa
+ ldz $5aa5,x
+ ldz $5aa5,y
+ ldz $5aa5,z
+ ldz $1234
+
+ sts $55,x
+ sts $55,y
+ sts $55,z
+ sts $5aa5,x
+ sts $5aa5,y
+ sts $5aa5,z
+ sts $1234
+
+ stx $55,x
+ stx $55,y
+ stx $55,z
+ stx $5aa5,x
+ stx $5aa5,y
+ stx $5aa5,z
+ stx $1234
+
+ sty $55,x
+ sty $55,y
+ sty $55,z
+ sty $5aa5,x
+ sty $5aa5,y
+ sty $5aa5,z
+ sty $1234
+
+ stz $55,x
+ stz $55,y
+ stz $55,z
+ stz $5aa5,x
+ stz $5aa5,y
+ stz $5aa5,z
+ stz $1234
+
+ jmp $12345
+ jmp $23456,x
+ jmp $23456,y
+ jmp $23456,z
+
+ jsr $12345
+ jsr $23456,x
+ jsr $23456,y
+ jsr $23456,z
+
+ ais #-2
+ ais #1000
+
+ aix #-2
+ aix #1000
+
+ aiy #-2
+ aiy #1000
+
+ aiz #-2
+ aiz #1000
+
+ andp #$feff
+ orp #$0100
+
+ lded $a55a
+ ldhi $a55a
+ sted $5aa5
+
+ mac 3,5
+ rmac 5,3
+
+ pshm d,x,z,ccr
+ pulm e,y,k
+
+ bclr $55,x,#2
+ bclr $55,y,#2
+ bclr $55,z,#2
+ bclr $5aa5,x,#2
+ bclr $5aa5,y,#2
+ bclr $5aa5,z,#2
+ bclr $1234,#2
+
+ bset $55,x,#2
+ bset $55,y,#2
+ bset $55,z,#2
+ bset $5aa5,x,#2
+ bset $5aa5,y,#2
+ bset $5aa5,z,#2
+ bset $1234,#2
+
+ bclrw $55,x,#2
+ bclrw $55,y,#2
+ bclrw $55,z,#2
+ bclrw $5aa5,x,#2
+ bclrw $5aa5,y,#2
+ bclrw $5aa5,z,#2
+ bclrw $1234,#2
+
+ bsetw $55,x,#2
+ bsetw $55,y,#2
+ bsetw $55,z,#2
+ bsetw $5aa5,x,#2
+ bsetw $5aa5,y,#2
+ bsetw $5aa5,z,#2
+ bsetw $1234,#2
+
+ movb $1234,$5678
+ movb $1234,5,x
+ movb -5,x,$5678
+
+ movw $1234,$5678
+ movw $1234,5,x
+ movw -5,x,$5678
+
+ brclr $55,x,#2,*+$30
+ brclr $55,y,#2,*+$30
+ brclr $55,z,#2,*+$30
+ brclr $55,x,#2,*+$300
+ brclr $55,y,#2,*+$300
+ brclr $55,z,#2,*+$300
+ brclr $5aa5,x,#2,*+$300
+ brclr $5aa5,y,#2,*+$300
+ brclr $5aa5,z,#2,*+$300
+ brclr $1234,#2,*+$300
+
+ brset $55,x,#2,*+$30
+ brset $55,y,#2,*+$30
+ brset $55,z,#2,*+$30
+ brset $55,x,#2,*+$300
+ brset $55,y,#2,*+$300
+ brset $55,z,#2,*+$300
+ brset $5aa5,x,#2,*+$300
+ brset $5aa5,y,#2,*+$300
+ brset $5aa5,z,#2,*+$300
+ brset $1234,#2,*+$300
+
+ clc
+ andp #$feff
+ cli
+ andp #$ff1f
+ clv
+ andp #$fdff
+ des
+ ais #-1
+ dex
+ aix #-1
+ dey
+ aiy #-1
+ ins
+ ais #1
+ inx
+ aix #1
+ iny
+ aiy #1
+ pshx
+ pshm x
+ pshy
+ pshm y
+ pulx
+ pulm x
+ puly
+ pulm y
+ sec
+ orp #$0100
+ sei
+ orp #$00e0
+ sev
+ orp #$0200
diff --git a/tests/t_6816/t_6816.doc b/tests/t_6816/t_6816.doc
new file mode 100644
index 0000000..ad1fc09
--- /dev/null
+++ b/tests/t_6816/t_6816.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 6816 ----------------------------+
+| |
+| This is a (synthetic) test of the 68HC16 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_6816/t_6816.ori b/tests/t_6816/t_6816.ori
new file mode 100644
index 0000000..1642194
--- /dev/null
+++ b/tests/t_6816/t_6816.ori
Binary files differ
diff --git a/tests/t_7000/asflags b/tests/t_7000/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_7000/asflags
diff --git a/tests/t_7000/t_7000.asm b/tests/t_7000/t_7000.asm
new file mode 100644
index 0000000..ed60212
--- /dev/null
+++ b/tests/t_7000/t_7000.asm
@@ -0,0 +1,249 @@
+ cpu sh7600
+ page 0
+ supmode on
+
+ rts
+ rte
+ rtb
+ clrt
+ sett
+ clrmac
+ nop
+ sleep
+ div0u
+ brk
+
+ movt r4
+ cmp/pz r6
+ cmp/pl r12
+ rotl r5
+ rotr sp
+ rotcl r8
+ rotcr r2
+ shal r1
+ shar r13
+ shll r9
+ shlr r11
+ shll2 r4
+ shlr2 r10
+ shll8 r15
+ shlr8 r3
+ shll16 r5
+ shlr16 r7
+ stbr r5
+ ldbr sp
+ dt r6
+
+ tas @sp
+
+ xtrct r0,r1
+ addc r1,r2
+ addv r2,r3
+ cmp/hs r3,r4
+ cmp/ge r4,r5
+ cmp/hi r5,r6
+ cmp/gt r6,r7
+ cmp/str r7,r8
+ div1 r8,r9
+ div0s r9,r10
+ muls.w r10,r11
+ mulu.w r11,r12
+ neg r12,r13
+ negc r13,r14
+ sub r14,r15
+ subc r15,r0
+ subv r0,r1
+ not r1,r2
+ dmuls.l r2,r3
+ dmulu.l r3,r4
+ mul r4,r5
+
+ swap.b r5,r10
+ swap.w r6,r11
+ exts.b r7,r12
+ exts.w r8,r13
+ extu.b r9,r14
+ extu.w r10,r15
+
+ add r3,r5
+ add #-30,r4
+ cmp/eq r3,r5
+ cmp/eq #-30,r0
+ mac @r5+,@r7+
+ mac.l @r5+,@r7+
+
+ and r5,r9
+ and #30,r0
+ and.b #$55,@(r0,gbr)
+
+ or r7,sp
+ or #%10111011,r0
+ or #123,@(gbr,r0,3-5+2)
+
+ tst r4,r12
+ tst.l #20,r0
+ tst.b #33,@(r0,gbr)
+
+ xor r5,r3
+ xor.l #45,r0
+ xor #%10,@(gbr,r0)
+
+
+ bt targ
+targ: bf targ
+ bt/s targ
+ bf/s targ
+ bra targ
+ bsr targ
+ jmp @r5
+ jsr @r10
+
+ ldc r5,sr
+ ldc r10,gbr
+ ldc r7,vbr
+ ldc @r6+,sr
+ ldc @r9+,gbr
+ ldc @r13+,vbr
+ stc sr,r4
+ stc gbr,r3
+ stc vbr,r7
+ stc sr,@-r6
+ stc gbr,@-r4
+ stc vbr,@-r14
+ lds r5,mach
+ lds r10,macl
+ lds r7,pr
+ lds @r6+,mach
+ lds @r9+,macl
+ lds @r13+,pr
+ sts mach,r4
+ sts macl,r3
+ sts pr,r7
+ sts mach,@-r6
+ sts macl,@-r4
+ sts pr,@-r14
+
+ mova ldata,r0
+
+ mov.l r5,r13
+
+ mov.b r1,@-r2
+ mov.b @r2+,r1
+ mov.w r3,@-r4
+ mov.w @r4+,r3
+ mov.l r6,@-r5
+ mov.l @r5+,r6
+
+ mov.b r12,@r5
+ mov.b @r5,r12
+ mov.w r5,@r14
+ mov.w @r14,r5
+ mov.l r7,@r7
+ mov.l @r7,r7
+
+ mov.b r0,@(r6,3)
+ mov.b @(r6,1+2),r0
+ mov.w r0,@(10,r12)
+ mov.w @(10,r12),r0
+ mov.l r7,@(60,r3)
+ mov.l @(2*30,r3),r7
+
+ mov.b r4,@(r0,r5)
+ mov.b @(r5,r0),r4
+ mov.w r6,@(r0,r10)
+ mov.w @(r10,r0),r6
+ mov.l r7,@(r0,r6)
+ mov.l @(r6,r0),r7
+
+ mov.b r0,@(gbr,30)
+ mov.b @(30,gbr),r0
+ mov.w r0,@(gbr,60)
+ mov.w @(10,5*5*2,gbr),r0
+ mov.l r0,@(gbr,120)
+ mov.l @(120,gbr),r0
+
+ mov #120,r4
+ mov.w wdata,r3
+ mov.l ldata,r12
+
+ trapa #$21
+
+ mov #$1234,r3
+ mov #$8000,r3
+ mov #$11223344,r3
+ mov #$0000,r3
+ mov #$1122,r3
+ mov #$3344,r3
+
+ bra next
+ mov #$1234,r3
+ bra next
+ mov #$11223344,r3
+ nop
+next: nop
+ nop
+
+ section test
+ mov #$1234,r5
+ nop
+ ltorg
+ endsection
+
+ align 4
+ldata: dc.l $12345678
+wdata: dc.w $1234
+
+ ltorg
+
+ cpu sh7700
+
+ clrs
+ sets
+ ldtlb
+
+ ldc r4,ssr
+ ldc r4,spc
+ ldc r4,r0_bank
+ ldc r4,r1_bank
+ ldc r4,r2_bank
+ ldc r4,r3_bank
+ ldc r4,r4_bank
+ ldc r4,r5_bank
+ ldc r4,r6_bank
+ ldc r4,r7_bank
+ ldc.l @r4+,ssr
+ ldc.l @r4+,spc
+ ldc.l @r4+,r0_bank
+ ldc.l @r4+,r1_bank
+ ldc.l @r4+,r2_bank
+ ldc.l @r4+,r3_bank
+ ldc.l @r4+,r4_bank
+ ldc.l @r4+,r5_bank
+ ldc.l @r4+,r6_bank
+ ldc.l @r4+,r7_bank
+ stc ssr,r4
+ stc spc,r4
+ stc r0_bank,r4
+ stc r1_bank,r4
+ stc r2_bank,r4
+ stc r3_bank,r4
+ stc r4_bank,r4
+ stc r5_bank,r4
+ stc r6_bank,r4
+ stc r7_bank,r4
+ stc.l ssr,@-r4
+ stc.l spc,@-r4
+ stc.l r0_bank,@-r4
+ stc.l r1_bank,@-r4
+ stc.l r2_bank,@-r4
+ stc.l r3_bank,@-r4
+ stc.l r4_bank,@-r4
+ stc.l r5_bank,@-r4
+ stc.l r6_bank,@-r4
+ stc.l r7_bank,@-r4
+
+ pref @r5
+
+ shad r3,r7
+ shld r12,sp
+
diff --git a/tests/t_7000/t_7000.doc b/tests/t_7000/t_7000.doc
new file mode 100644
index 0000000..9be3f47
--- /dev/null
+++ b/tests/t_7000/t_7000.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 7000 ----------------------------+
+| |
+| This is a (synthetic) test of the SH7x00 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_7000/t_7000.ori b/tests/t_7000/t_7000.ori
new file mode 100644
index 0000000..560ff72
--- /dev/null
+++ b/tests/t_7000/t_7000.ori
Binary files differ
diff --git a/tests/t_75k0/asflags b/tests/t_75k0/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_75k0/asflags
diff --git a/tests/t_75k0/t_75k0.asm b/tests/t_75k0/t_75k0.asm
new file mode 100644
index 0000000..9925e87
--- /dev/null
+++ b/tests/t_75k0/t_75k0.asm
@@ -0,0 +1,191 @@
+ cpu 75104
+ page 0
+ include stddef75
+
+ ret
+ reti
+ rets
+ halt
+ stop
+ nop
+
+ br pc+5
+ br pc-5
+ br pc+200h
+ br pc+2000h
+ br $pc+5
+ brcb pc+5
+ br !pc+5
+ br $pc-5
+ brcb pc-5
+ br !pc-5
+ brcb pc+200h
+ br !pc+200h
+ br !pc+2000h
+ br pcde
+ br pcxa
+
+ call !200h
+ call !2000h
+ call 200h
+ call 2000h
+ callf 200h
+ callf !200h
+
+ adds a,#5
+ adds xa,#30
+ adds a,@hl
+ adds xa,hl
+ adds xa,de
+ adds xa,bc
+ adds xa,xa'
+ adds xa,hl'
+ adds xa,de`
+ adds xa,bc`
+ adds de,xa
+
+ addc a,@hl
+ addc xa,bc
+ addc de`,xa
+
+ subs a,@hl
+ subs xa,bc
+ subs de`,xa
+
+ subc a,@hl
+ subc xa,bc
+ subc de`,xa
+
+ and a,#13
+ and a,@hl
+ and xa,bc
+ and de`,xa
+
+ or a,#13
+ or a,@hl
+ or xa,bc
+ or de`,xa
+
+ xor a,#13
+ xor a,@hl
+ xor xa,bc
+ xor de`,xa
+
+ incs d
+ incs de
+ incs @hl
+ incs 20h
+
+ decs d
+ decs de'
+
+ ske b,#5
+ ske @hl,#6
+ ske a,@hl
+ ske @hl,a
+ ske xa,@hl
+ ske @hl,xa
+ ske a,c
+ ske c,a
+ ske xa,hl'
+ ske hl`,xa
+
+ mov a,#5
+ mov b,#5
+ mov de,#55h
+ mov a,@hl
+ mov a,@hl+
+ mov a,@hl-
+ mov a,@de
+ mov a,@dl
+ mov xa,@hl
+ mov @hl,a
+ mov @hl,xa
+ mov a,12h
+ mov xa,34h
+ mov 56h,a
+ mov 78h,xa
+ mov a,c
+ mov xa,bc'
+ mov d,a
+ mov hl`,xa
+
+ xch a,@hl+
+ xch @hl+,a
+ xch xa,@hl
+ xch @hl,xa
+ xch a,12h
+ xch 12h,a
+ xch xa,34h
+ xch 34h,xa
+ xch a,d
+ xch d,a
+ xch xa,de
+ xch de,xa
+
+ movt xa,@pcde
+ movt xa,@pcxa
+
+ mov1 cy,0fb2h.2
+ mov1 0ff4h.1,cy
+ mov1 cy,0fe4h.@l
+ mov1 @h+13.3,cy
+
+ set1 cy
+ set1 40h.2
+ set1 0ff2h.3
+
+ clr1 cy
+ clr1 40h.2
+ clr1 0ff2h.3
+
+ skt cy
+ skt 40h.2
+ skt 0ff2h.3
+
+ skf 40h.2
+ skf 0ff2h.3
+
+ not1 cy
+ sktclr 0ff2h.3
+
+ and1 cy,0ff2h.3
+ or1 cy,0ff2h.3
+ xor1 cy,0ff2h.3
+
+ rorc a
+ not a
+
+ push bs
+ pop bs
+ push hl
+ pop bc
+
+ in a,port3
+ in xa,port12
+ out port10,a
+ out port7,xa
+
+ ei
+ di
+ ei ieks
+ di iew
+
+ sel rb2
+ sel mb10
+
+ geti 15
+
+bit1 bit 0ff0h.@l
+bit2 bit 0fb0h.2
+bit3 bit 0ff0h.1
+bit4 bit 0430h.3
+bit5 bit @h+5+3.2
+
+ set1 bit1
+ clr1 bit4
+ sel mb4
+ set1 mbe
+ assume mbs:4,mbe:1
+ clr1 bit4
+
diff --git a/tests/t_75k0/t_75k0.doc b/tests/t_75k0/t_75k0.doc
new file mode 100644
index 0000000..68b87c8
--- /dev/null
+++ b/tests/t_75k0/t_75k0.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 75K0 ----------------------------+
+| |
+| This is a (synthetic) test of the 75K0 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_75k0/t_75k0.ori b/tests/t_75k0/t_75k0.ori
new file mode 100644
index 0000000..09c49c4
--- /dev/null
+++ b/tests/t_75k0/t_75k0.ori
Binary files differ
diff --git a/tests/t_7700/asflags b/tests/t_7700/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_7700/asflags
diff --git a/tests/t_7700/t_7700.asm b/tests/t_7700/t_7700.asm
new file mode 100644
index 0000000..f4537d9
--- /dev/null
+++ b/tests/t_7700/t_7700.asm
@@ -0,0 +1,356 @@
+ cpu melps7751
+ page 0
+
+
+ ldt #0
+ assume pg:0,dt:0,dpr:0
+
+accmode macro size
+ switch size
+ case 8
+ sep #$20
+ assume m:1
+ case 16
+ clp #$20
+ assume m:0
+ elsecase
+ fatal "accmode: ungltige OperandengrӇe: $\{SIZE}"
+ endcase
+ endm
+
+idxmode macro size
+ switch size
+ case 8
+ sep #$10
+ assume x:1
+ case 16
+ clp #$10
+ assume x:0
+ elsecase
+ fatal "idxmode: ungltige OperandengrӇe: $\{SIZE}"
+ endcase
+ endm
+
+ xab
+ wit
+ tyx
+ tyb
+ tya
+ txy
+ txs
+ txb
+ txa
+ tsx
+ tsb
+ tsa
+ tdb
+ tda
+ tby
+ tbx
+ tbs
+ tbd
+ tay
+ tax
+ tas
+ tad
+ stp
+ sem
+ sei
+ sec
+ rts
+ rtl
+ rti
+ ply
+ plx
+ plt
+ plp
+ pld
+ plb
+ pla
+ phy
+ phx
+ pht
+ php
+ phg
+ phd
+ phb
+ pha
+ nop
+ iny
+ inx
+ dey
+ dex
+ clv
+ clm
+ cli
+ clc
+
+ rla #7
+
+targ:
+ bcc targ
+ bcs targ
+ beq targ
+ bmi targ
+ bne targ
+ bpl targ
+ bvc targ
+ bvs targ
+ bra targ
+ per targ
+ org *+$100
+ bra targ
+ per targ
+
+ accmode 8
+ idxmode 8
+
+ adc #20
+ and a,#-1
+ cmp b,#-$a
+
+targ2:
+ bbc #$80,$20,targ2
+ bbs #$40,$2000,targ2
+ clb #$20,$20
+ seb #$10,$2000
+
+ cpx #$aa
+ cpy #$aa
+ ldx #$bb
+ ldy #$bb
+
+ ldm #$aa,$20
+ ldm #$aa,$2000
+ ldm #$aa,$20,x
+ ldm #$aa,$2000,x
+
+ accmode 16
+ idxmode 16
+
+ eor #%0000111111110000
+ lda a,#'AB'
+ ora b,#3000
+
+ sbc $20
+ sta a,$2000
+ adc b,$200000
+
+ and $30,x
+ cmp a,$3000,x
+ eor b,$300000,x
+
+ lda $40,y
+ ora a,$4000,y
+; sbc b,$400000,y
+
+ sta ($50)
+; adc a,($5000)
+; and b,($500000)
+
+ cmpl ($60)
+; eorl a,($6000)
+; ldal b,($600000)
+
+ ora ($70,x)
+; sbc ($7000,x)
+; sta ($700000,x)
+
+ adc ($80),y
+; and ($8000),y
+; cmp ($800000),y
+
+ eorl ($80),y
+; ldal ($8000),y
+; oral ($800000),y
+
+ sbc b,3,s
+ sta a,(5,s),y
+
+ asl
+ dec a
+ inc b
+ lsr $20
+ rol $2000
+ ror $20,x
+ asl $2000,x
+
+targ3:
+ bbs #$80,$20,targ3
+ bbc #$40,$2000,targ3
+ clb #$20,$20
+ seb #$10,$2000
+
+ cpx #$aa
+ cpy #$aa
+ ldx #$bb
+ ldy #$bb
+ cpx $20
+ cpy $20
+ ldx $20
+ ldy $20
+ stx $20
+ sty $20
+ cpx $2000
+ cpy $2000
+ ldx $2000
+ ldy $2000
+ stx $2000
+ sty $2000
+ ldx $30,y
+ ldy $30,x
+ stx $30,y
+ sty $30,x
+ ldx $3000,y
+ ldy $3000,x
+
+ mpy #55
+ accmode 8
+ mpy #55
+ accmode 16
+ mpy $12
+ mpy $12,x
+ mpy ($12)
+ mpy ($12,x)
+ mpy ($12),y
+ mpyl ($12)
+ mpyl ($12),y
+ mpy $1234
+ mpy $1234,x
+ mpy $1234,y
+ mpy $123456
+ mpy $123456,x
+ mpy $12,s
+ mpy ($12,s),y
+
+ div #55
+ accmode 8
+ div #55
+ accmode 16
+ div $12
+ div $12,x
+ div ($12)
+ div ($12,x)
+ div ($12),y
+ divl ($12)
+ divl ($12),y
+ div $1234
+ div $1234,x
+ div $1234,y
+ div $123456
+ div $123456,x
+ div $12,s
+ div ($12,s),y
+
+ jmp $20
+ jmp $2000
+ jmp $200000
+ jmp ($3000)
+ jmpl ($3000)
+ jmp ($4000,x)
+ jsr $20
+ jsr $2000
+ jsr $200000
+ jsr ($4000,x)
+
+ ldm #$aa,$20
+ ldm #$aa,$2000
+ ldm #$aa,$20,x
+ ldm #$aa,$2000,x
+
+ mvn $200000,$300000
+ mvp $200000,$300000
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ cpu 65816
+
+ cop
+ jml $2000
+ jsl $4000
+ brl *
+ rep #$55
+ tsb $33
+ trb $66
+ tsb $9999
+ trb $cccc
+ bit $00
+ bit $11,x
+ bit $2222
+ bit $3333,x
+ bit #$44
+ stz $55
+ stz $6666
+ stz $77,x
+ stz $8888,x
+ cld
+ sed
+ tcs
+ tsc
+ phk
+ tcd
+ tdc
+ phb
+ plb
+ wai
+ xba
+ xce
+
+;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ cpu melps7750
+
+ asr
+ asr a
+ asr b
+ asr $aa
+ asr $1234
+ asr $aa,x
+ asr $1234,x
+
+ extz
+ extz a
+ extz b
+ exts
+ exts a
+ exts b
+
+ mpys #55
+ accmode 8
+ mpys #55
+ accmode 16
+ mpys $12
+ mpys $12,x
+ mpys ($12)
+ mpys ($12,x)
+ mpys ($12),y
+ mpysl ($12)
+ mpysl ($12),y
+ mpys $1234
+ mpys $1234,x
+ mpys $1234,y
+ mpys $123456
+ mpys $123456,x
+ mpys $12,s
+ mpys ($12,s),y
+
+ divs #55
+ accmode 8
+ divs #55
+ accmode 16
+ divs $12
+ divs $12,x
+ divs ($12)
+ divs ($12,x)
+ divs ($12),y
+ divsl ($12)
+ divsl ($12),y
+ divs $1234
+ divs $1234,x
+ divs $1234,y
+ divs $123456
+ divs $123456,x
+ divs $12,s
+ divs ($12,s),y
+
+
diff --git a/tests/t_7700/t_7700.doc b/tests/t_7700/t_7700.doc
new file mode 100644
index 0000000..d7186e0
--- /dev/null
+++ b/tests/t_7700/t_7700.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 7700 ----------------------------+
+| |
+| This is a (synthetic) test of the MELPS/77xx instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_7700/t_7700.ori b/tests/t_7700/t_7700.ori
new file mode 100644
index 0000000..df9af4e
--- /dev/null
+++ b/tests/t_7700/t_7700.ori
Binary files differ
diff --git a/tests/t_7720/asflags b/tests/t_7720/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_7720/asflags
diff --git a/tests/t_7720/t_7720.asm b/tests/t_7720/t_7720.asm
new file mode 100644
index 0000000..d25c058
--- /dev/null
+++ b/tests/t_7720/t_7720.asm
@@ -0,0 +1,141 @@
+ cpu 7720
+
+ jmp lab
+ call lab
+ jnca lab
+ jncb lab
+ jcb lab
+ jnza lab
+ jza lab
+ jnzb lab
+ jzb lab
+ jnova0 lab
+ jova0 lab
+ jnovb0 lab
+ jovb0 lab
+ jnova1 lab
+ jova1 lab
+ jnovb1 lab
+ jovb1 lab
+ jnsa0 lab
+ jsa0 lab
+ jnsb0 lab
+ jsb0 lab
+ jnsa1 lab
+ jsa1 lab
+ jnsb1 lab
+ jsb1 lab
+ jdpl0 lab
+ jdplf lab
+ jnsiak lab
+ jsiak lab
+ jnsoak lab
+ jsoak lab
+ jnrqm lab
+ jrqm lab
+lab:
+
+ ldi @non,1234h
+ ldi @a,1234h
+ ldi @b,1234h
+ ldi @tr,1234h
+ ldi @dp,1234h
+ ldi @rp,1234h
+ ldi @dr,1234h
+ ldi @sr,1234h
+ ldi @sol,1234h
+ ldi @som,1234h
+ ldi @k,1234h
+ ldi @klr,1234h
+ ldi @klm,1234h
+ ldi @l,1234h
+ ldi @mem,1234h
+
+ op mov @a,non
+ op mov @a,a
+ op mov @a,b
+ op mov @a,tr
+ op mov @a,dp
+ op mov @a,rp
+ op mov @a,ro
+ op mov @a,sgn
+ op mov @a,dr
+ op mov @a,drnf
+ op mov @a,sr
+ op mov @a,sim
+ op mov @a,sil
+ op mov @a,k
+ op mov @a,l
+ op mov @a,mem
+
+ op mov @a,non
+ or acca,ram
+ op mov @a,non
+ or accb,ram
+ op mov @a,non
+ or acca,idb
+ op mov @a,non
+ or acca,m
+ op mov @a,non
+ or acca,n
+ op mov @a,non
+ and acca,ram
+ op mov @a,non
+ xor acca,ram
+ op mov @a,non
+ sub acca,ram
+ op mov @a,non
+ add acca,ram
+ op mov @a,non
+ sbb acca,ram
+ op mov @a,non
+ adc acca,ram
+ op mov @a,non
+ cmp acca,ram
+ op mov @a,non
+ inc accb
+ op mov @a,non
+ dec acca
+ op mov @a,non
+ shr1 accb
+ op mov @a,non
+ shl1 acca
+ op mov @a,non
+ shl2 accb
+ op mov @a,non
+ shl4 acca
+ op mov @a,non
+ xchg accb
+ op mov @a,non
+ nop
+
+ op mov @a,non
+ dpnop
+ op mov @a,non
+ dpinc
+ op mov @a,non
+ dpdec
+ op mov @a,non
+ dpclr
+
+ op mov @a,non
+ m0
+ op mov @a,non
+ m1
+ op mov @a,non
+ m2
+ op mov @a,non
+ m3
+ op mov @a,non
+ m4
+ op mov @a,non
+ m5
+ op mov @a,non
+ m6
+ op mov @a,non
+ m7
+
+ op mov @a,non
+ rpnop
+ op mov @a,non
+ rpdec
diff --git a/tests/t_7720/t_7720.doc b/tests/t_7720/t_7720.doc
new file mode 100644
index 0000000..cdf17c8
--- /dev/null
+++ b/tests/t_7720/t_7720.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application 7720 ---------------------------+
+| |
+| This is a (synthetic) test of the uPD7720 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_7720/t_7720.ori b/tests/t_7720/t_7720.ori
new file mode 100644
index 0000000..bb3ef05
--- /dev/null
+++ b/tests/t_7720/t_7720.ori
Binary files differ
diff --git a/tests/t_77230/asflags b/tests/t_77230/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_77230/asflags
diff --git a/tests/t_77230/t_77230.asm b/tests/t_77230/t_77230.asm
new file mode 100644
index 0000000..494b9c3
--- /dev/null
+++ b/tests/t_77230/t_77230.asm
@@ -0,0 +1,245 @@
+ cpu 77230
+ page 0
+
+ ; Test Case 1 (nur LDI) und DestReg-Kodierungen
+
+ ldi rp,123456h
+ ldi psw0,123456h
+ ldi psw1,123456h
+ ldi svr,123456h
+ ldi sr,123456h
+ ldi lc,123456h
+ ldi stk,123456h
+ ldi lkr0,123456h
+ ldi klr1,123456h
+ ldi tre,123456h
+ ldi tr,123456h
+ ldi ar,123456h
+ ldi so,123456h
+ ldi dr,123456h
+ ldi drs,123456h
+ ldi wr0,123456h
+ ldi wr1,123456h
+ ldi wr2,123456h
+ ldi wr3,123456h
+ ldi wr4,123456h
+ ldi wr5,123456h
+ ldi wr6,123456h
+ ldi wr7,123456h
+ ldi ram0,123456h
+ ldi ram1,123456h
+ ldi bp0,123456h
+ ldi bp1,123456h
+ ldi ix0,123456h
+ ldi ix1,123456h
+ ldi k,123456h
+ ldi l,123456h
+
+ ; Sprünge wahlweise mit oder ohne MOV, Test SrcReg-Kodierungen
+ jmp target
+ call target mov wr0,rp
+ ret
+ ret mov wr0,psw0
+ mov wr0,psw1 jnzrp target
+ jz0 target mov wr0,svr
+ mov wr0,sr jnz0 target
+ jz1 target mov wr0,lc
+ mov wr0,stx jnz1 target
+ jc0 target mov wr0,m
+ mov wr0,ml jnc0 target
+ jc1 target mov wr0,rom
+ mov wr0,tr jnc1 target
+ js0 target mov wr0,ar
+ mov wr0,si jns0 target
+ js1 target mov wr0,dr
+ mov wr0,drs jns1 target
+ jv0 target mov wr0,wr0
+ mov wr0,wr1 jnv0 target
+ jv1 target mov wr0,wr2
+ mov wr0,wr3 jnv1 target
+ jev0 target mov wr0,wr4
+ mov wr0,wr5 jev1 target
+ jnfsi target mov wr0,wr6
+ mov wr0,wr7 jneso target
+ jip0 target mov wr0,ram0
+ mov wr0,ram1 jip1 target
+ jnzix0 target mov wr0,bp0
+ mov wr0,bp1 jnzix1 target
+ jnzbp0 target mov wr0,ix0
+ mov wr0,ix1 jnzbp1 target
+ jrdy target mov wr0,k
+ mov wr0,l jrqm target
+target:
+
+ ; ALU
+
+ nop
+ inc wr1
+ dec wr2
+ abs wr3
+ not wr4
+ neg wr5
+ shlc wr6
+ shrc wr7
+ rol wr1
+ ror wr2
+ shlm wr3
+ shrm wr4
+ shram wr5
+ clr wr6
+ norm wr7
+ cvt wr1
+ add wr1,ib
+ sub wr1,m
+ addc wr1,ram0
+ subc wr1,ram1
+ cmp wr1,ib
+ and wr1,m
+ or wr1,ram0
+ xor wr1,ram1
+ addf wr1,ib
+ subf wr1,m
+
+ ; Mx-Felder
+
+ spcbp0 spcbi1
+ spcix0 spcix1
+ spcbi0 spcbp1
+
+ ; DPx-Felder
+
+ incbp0 clrix1
+ decbp0 decix1
+ clrbp0 incix1
+ stix0 stix1
+ incix0 clrbp1
+ decix0 decbp1
+ clrix0 incbp1
+
+ ; EA-Feld
+
+ incar
+ decar
+
+ ; FC-Feld
+
+ xchpsw
+
+ ; RP-Feld
+
+ incrp
+ decrp
+ incbrp
+
+ ; L-Feld
+
+ declc
+
+ ; BASE-Felder
+
+ mcnbp0 0 mcnbp1 7
+ mcnbp0 1 mcnbp1 6
+ mcnbp0 2 mcnbp1 5
+ mcnbp0 3 mcnbp1 4
+ mcnbp0 4 mcnbp1 3
+ mcnbp0 5 mcnbp1 2
+ mcnbp0 6 mcnbp1 1
+ mcnbp0 7 mcnbp1 0
+
+ ; RPC-Feld
+
+ bitrp 0
+ bitrp 1
+ bitrp 2
+ bitrp 3
+ bitrp 4
+ bitrp 5
+ bitrp 6
+ bitrp 7
+ bitrp 8
+ bitrp 9
+
+ ; Ports nur im Paket
+
+ clrp2 clrp3
+ setp2 clrp3
+ clrp2 setp3
+ setp2 setp3
+
+ ; Interrupts nur mit Ports
+
+ clrp2 clrp3 clrbm
+ clrp2 clrp3 setbm
+ clrp2 clrp3 di
+ clrp2 clrp3 ei
+ clrp2 clrp3 ei clrbm
+ clrp2 clrp3 ei setbm
+
+ ; RW-Feld
+
+ rd
+ wr
+
+ ; WT-Feld
+
+ wrbord
+ wrbl24
+ wrbl23
+ wrbel8
+ wrbl8e
+ wrbxch
+ wrbbrv
+
+ ; NF-Feld
+
+ trnorm
+ rdnorm
+ fltfix
+ fixma
+
+ ; WI-Feld
+
+ bwrl24
+ bwrord
+
+ ; FIS-Feld
+
+ spcpsw0
+ spcpsw1
+ clrpsw0
+ clrpsw1
+ clrpsw
+
+ ; FD-Feld
+
+ spie
+ iesp
+
+ ; SHV-Feld
+
+ setsvl 7
+ setsvr 17
+
+ ; RPS-Feld
+
+ spcra 123
+
+ ; NAL-Feld
+
+ jblk $+5
+
+ ; Datenablage
+
+ dw 12345678h
+ dw 32.0,-32.0
+ dw 1.0,-1.0
+; dw 3.6e-46 ; these do not work on machines that
+; dw 3.6e-45 ; do not support denormalized values,
+; dw 3.6e-44 ; so we better leave them out for portable
+; dw 3.6e-43 ; tests...
+; dw 3.6e-42
+; dw 3.6e-41
+; dw 3.6e-40
+; dw 3.6e-39
+ dw 3.6e-38
+
diff --git a/tests/t_77230/t_77230.doc b/tests/t_77230/t_77230.doc
new file mode 100644
index 0000000..a891a66
--- /dev/null
+++ b/tests/t_77230/t_77230.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 77230 ---------------------------+
+| |
+| This is a (synthetic) test of the uPD77230 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_77230/t_77230.ori b/tests/t_77230/t_77230.ori
new file mode 100644
index 0000000..d121bd3
--- /dev/null
+++ b/tests/t_77230/t_77230.ori
Binary files differ
diff --git a/tests/t_7725/asflags b/tests/t_7725/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_7725/asflags
diff --git a/tests/t_7725/t_7725.asm b/tests/t_7725/t_7725.asm
new file mode 100644
index 0000000..2611a7d
--- /dev/null
+++ b/tests/t_7725/t_7725.asm
@@ -0,0 +1,171 @@
+ cpu 7725
+
+ jmp lab
+ call lab
+ jnca lab
+ jncb lab
+ jcb lab
+ jnza lab
+ jza lab
+ jnzb lab
+ jzb lab
+ jnova0 lab
+ jova0 lab
+ jnovb0 lab
+ jovb0 lab
+ jnova1 lab
+ jova1 lab
+ jnovb1 lab
+ jovb1 lab
+ jnsa0 lab
+ jsa0 lab
+ jnsb0 lab
+ jsb0 lab
+ jnsa1 lab
+ jsa1 lab
+ jnsb1 lab
+ jsb1 lab
+ jdpl0 lab
+ jdplf lab
+ jnsiak lab
+ jsiak lab
+ jnsoak lab
+ jsoak lab
+ jnrqm lab
+ jrqm lab
+ jdpln0 lab
+ jdplnf lab
+lab:
+
+ ldi @non,1234h
+ ldi @a,1234h
+ ldi @b,1234h
+ ldi @tr,1234h
+ ldi @dp,1234h
+ ldi @rp,1234h
+ ldi @dr,1234h
+ ldi @sr,1234h
+ ldi @sol,1234h
+ ldi @som,1234h
+ ldi @k,1234h
+ ldi @klr,1234h
+ ldi @klm,1234h
+ ldi @l,1234h
+ ldi @mem,1234h
+ ldi @trb,1234h
+
+ op mov @a,non
+ op mov @a,a
+ op mov @a,b
+ op mov @a,tr
+ op mov @a,dp
+ op mov @a,rp
+ op mov @a,ro
+ op mov @a,sgn
+ op mov @a,dr
+ op mov @a,drnf
+ op mov @a,sr
+ op mov @a,sim
+ op mov @a,sil
+ op mov @a,k
+ op mov @a,l
+ op mov @a,mem
+
+ op mov @a,non
+ or acca,ram
+ op mov @a,non
+ or accb,ram
+ op mov @a,non
+ or acca,idb
+ op mov @a,non
+ or acca,m
+ op mov @a,non
+ or acca,n
+ op mov @a,non
+ and acca,ram
+ op mov @a,non
+ xor acca,ram
+ op mov @a,non
+ sub acca,ram
+ op mov @a,non
+ add acca,ram
+ op mov @a,non
+ sbb acca,ram
+ op mov @a,non
+ adc acca,ram
+ op mov @a,non
+ cmp acca,ram
+ op mov @a,non
+ inc accb
+ op mov @a,non
+ dec acca
+ op mov @a,non
+ shr1 accb
+ op mov @a,non
+ shl1 acca
+ op mov @a,non
+ shl2 accb
+ op mov @a,non
+ shl4 acca
+ op mov @a,non
+ xchg accb
+ op mov @a,non
+ nop
+
+ op mov @a,non
+ dpnop
+ op mov @a,non
+ dpinc
+ op mov @a,non
+ dpdec
+ op mov @a,non
+ dpclr
+
+ op mov @a,non
+ m0
+ op mov @a,non
+ m1
+ op mov @a,non
+ m2
+ op mov @a,non
+ m3
+ op mov @a,non
+ m4
+ op mov @a,non
+ m5
+ op mov @a,non
+ m6
+ op mov @a,non
+ m7
+ op mov @a,non
+ m8
+ op mov @a,non
+ m9
+ op mov @a,non
+ ma
+ op mov @a,non
+ mb
+ op mov @a,non
+ mc
+ op mov @a,non
+ md
+ op mov @a,non
+ me
+ op mov @a,non
+ mf
+
+ op mov @a,non
+ rpnop
+ op mov @a,non
+ rpdec
+
+ data 1,2,3
+ data "a"
+ data "ab"
+ data "abc"
+ data "abcd"
+ data "abcde"
+ data "abcdef"
+ data "abcdefg"
+ data "abcdefgh"
+
diff --git a/tests/t_7725/t_7725.doc b/tests/t_7725/t_7725.doc
new file mode 100644
index 0000000..c8d6a1a
--- /dev/null
+++ b/tests/t_7725/t_7725.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application 7725 ---------------------------+
+| |
+| This is a (synthetic) test of the uPD7725 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_7725/t_7725.ori b/tests/t_7725/t_7725.ori
new file mode 100644
index 0000000..667ba6d
--- /dev/null
+++ b/tests/t_7725/t_7725.ori
Binary files differ
diff --git a/tests/t_78c1x/asflags b/tests/t_78c1x/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_78c1x/asflags
diff --git a/tests/t_78c1x/t_78c1x.asm b/tests/t_78c1x/t_78c1x.asm
new file mode 100644
index 0000000..4b9b143
--- /dev/null
+++ b/tests/t_78c1x/t_78c1x.asm
@@ -0,0 +1,258 @@
+ cpu 78c10
+
+ block
+ calb
+ clc
+ daa
+ di
+ ei
+ exa
+ exh
+ exx
+ hlt
+ jb
+ jea
+ nega
+ nop
+ ret
+ reti
+ rets
+ rld
+ rrd
+ softi
+ stc
+ stop
+ table
+
+ aci a,0
+ aci h,10
+ aci pc,55h
+
+ adi a,40
+ adi b,33o
+ adi eom,6
+
+ adinc a,56
+ ani l,33h
+ eqi mkh,34
+ gti a,20
+ lti c,34
+ nei mkl,10
+ offi a,0ffh
+ oni d,0
+ ori anm,47
+ sbi a,41h
+ sui v,7
+ suinb smh,98
+
+ xri a,055h
+ xri v,1010b
+ xri pb,40h
+
+ adc a,v
+ adc v,a
+ addnc a,b
+ addnc b,a
+ sub a,c
+ sub c,a
+ sbb a,d
+ sbb d,a
+ subnb a,e
+ subnb e,a
+ ana a,h
+ ana h,a
+ ora a,l
+ ora l,a
+ xra a,v
+ xra v,a
+ gta a,b
+ gta b,a
+ lta a,c
+ lta c,a
+ nea a,d
+ nea d,a
+ eqa a,e
+ eqa e,a
+ ona a,h
+ ona h,a
+ offa a,l
+ offa l,a
+
+ assume v:0
+
+ adcw 10h
+ addncw 20h
+ addw 30h
+ subw 40h
+ sbbw 50h
+ subnbw 60h
+ anaw 70h
+ oraw 80h
+ xraw 90h
+ gtaw 0a0h
+ ltaw 0b0h
+ neaw 0c0h
+ eqaw 0d0h
+ onaw 0e0h
+ offaw 0f0h
+
+ adcx b
+ addncx d
+ addx h
+ subx d+
+ sbbx h+
+ subnbx d-
+ anax h-
+ orax b
+ xrax d
+ gtax h
+ ltax d+
+ neax h+
+ eqax d-
+ onax h-
+ offax b
+
+ dadc ea,b
+ daddnc ea,d
+ dadd ea,h
+ dsub ea,b
+ dsbb ea,d
+ dsubnb ea,h
+ dan ea,b
+ dor ea,d
+ dxr ea,h
+ dgt ea,b
+ dlt ea,d
+ dne ea,h
+ deq ea,b
+ don ea,d
+ doff ea,h
+
+ aniw 10h,'A'
+ eqiw 20h,'B'
+ gtiw 30h,'C'
+ ltiw 40h,'D'
+ neiw 50h,'E'
+ oniw 60h,'F'
+ offiw 70h,'G'
+ oriw 80h,'H'
+
+ call 1234h
+ jmp 5678h
+ lbcd 1234h
+ sbcd 5678h
+ lded 1234h
+ sded 5678h
+ lhld 1234h
+ shld 5678h
+ lspd 1234h
+ sspd 5678h
+
+ calf 0c08h
+ calt 150
+
+ bit 5,20h
+ bit 2,0ffh
+
+ dcr a
+ inr b
+ mul c
+ div a
+ sll b
+ slr c
+ sllc a
+ slrc b
+ rll c
+ rlr a
+
+ dcrw 20h
+ inrw 30h
+ ldaw 40h
+ staw 50h
+
+ inx ea
+ dcx ea
+ inx h
+ dcx b
+
+ dmov ea,b
+ dmov h,ea
+ dmov ea,ecpt
+ dmov etm0,ea
+
+ drll ea
+ dsll ea
+ drlr ea
+ dslr ea
+
+ eadd ea,b
+ esub ea,c
+
+back: nop
+ jr back
+ jre $-100
+ jr forw
+ jre $+100
+forw: nop
+
+ ldax b
+ ldax d
+ ldax h
+ ldax d+
+ ldax h+
+ ldax d-
+ ldax h-
+ ldax d+20
+ ldax d-30
+ ldax h+a
+ ldax h+b
+ ldax h+ea
+ ldax h+40
+ ldax h-50
+ stax b
+ stax d
+ stax h
+ stax d+
+ stax h+
+ stax d-
+ stax h-
+ stax d+20
+ stax d-30
+ stax h+a
+ stax h+b
+ stax h+ea
+ stax h+40
+ stax h-50
+
+ ldeax h++
+ steax d++
+ ldeax h+ea
+ steax h-5
+
+ lxi sp,2000h
+ lxi h,101010101010b
+ lxi ea,1001
+
+ mov a,eal
+ mov h,a
+ mov a,pa
+ mov pa,a
+ mov c,1000h
+ mov 1234h,d
+
+ mvi d,55h
+ mvi eom,0
+
+ mviw 20h,01101001b
+ mvix d,22o
+
+ push va
+ push b
+ pop h
+ pop ea
+
+ sk z
+ skn hc
+
+ skit fsr
+ skint an6
diff --git a/tests/t_78c1x/t_78c1x.doc b/tests/t_78c1x/t_78c1x.doc
new file mode 100644
index 0000000..61460db
--- /dev/null
+++ b/tests/t_78c1x/t_78c1x.doc
@@ -0,0 +1,5 @@
++------------------------ Test Application 78C1x ----------------------------+
+| |
+| This is a (synthetic) test of the uPD78C1x instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_78c1x/t_78c1x.ori b/tests/t_78c1x/t_78c1x.ori
new file mode 100644
index 0000000..e1c44ea
--- /dev/null
+++ b/tests/t_78c1x/t_78c1x.ori
Binary files differ
diff --git a/tests/t_78k0/asflags b/tests/t_78k0/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_78k0/asflags
diff --git a/tests/t_78k0/t_78k0.asm b/tests/t_78k0/t_78k0.asm
new file mode 100644
index 0000000..8dd0a33
--- /dev/null
+++ b/tests/t_78k0/t_78k0.asm
@@ -0,0 +1,291 @@
+ cpu 78070
+ page 0
+ relaxed on
+
+ include reg78k0.inc
+
+saddr equ 0fe80h
+sfr equ 0ff90h
+
+ brk
+ ret
+ retb
+ reti
+ nop
+ ei
+ di
+ halt
+ stop
+ adjba
+ adjbs
+
+ mov d,#20
+ mov saddr,#30
+ mov sfr,#40
+ mov a,c
+ mov e,a
+ mov a,saddr
+ mov saddr,a
+ mov a,sfr
+ mov sfr,a
+ mov a,!saddr
+ mov !saddr,r1
+ mov psw,#40h
+ mov a,psw
+ mov psw,a
+ mov a,[de]
+ mov [de],a
+ mov a,[hl]
+ mov [hl],a
+ mov a,[hl+10]
+ mov [hl+10],a
+ mov a,[hl+b]
+ mov [hl+b],a
+ mov a,[hl+c]
+ mov [hl+c],a
+
+ xch a,d
+ xch l,a
+ xch a,saddr
+ xch a,sfr
+ xch a,!saddr
+ xch a,[de]
+ xch a,[hl]
+ xch a,[hl+10]
+ xch a,[hl+b]
+ xch a,[hl+c]
+
+ movw de,#1000
+ movw saddr,#2000
+ movw sfr,#3000
+ movw ax,saddr
+ movw saddr,ax
+ movw ax,sfr
+ movw sfr,ax
+ movw ax,de
+ movw hl,ax
+ movw ax,!saddr
+ movw !saddr,ax
+
+ xchw ax,de
+ xchw hl,ax
+
+ add a,#10
+ add saddr,#20
+ add a,c
+ add h,a
+ add a,saddr
+ add a,!saddr
+ add a,[hl]
+ add a,[hl+10]
+ add a,[hl+b]
+ add a,[hl+c]
+
+ addc a,#10
+ addc saddr,#20
+ addc a,c
+ addc h,a
+ addc a,saddr
+ addc a,!saddr
+ addc a,[hl]
+ addc a,[hl+10]
+ addc a,[hl+b]
+ addc a,[hl+c]
+
+ sub a,#10
+ sub saddr,#20
+ sub a,c
+ sub h,a
+ sub a,saddr
+ sub a,!saddr
+ sub a,[hl]
+ sub a,[hl+10]
+ sub a,[hl+b]
+ sub a,[hl+c]
+
+ subc a,#10
+ subc saddr,#20
+ subc a,c
+ subc h,a
+ subc a,saddr
+ subc a,!saddr
+ subc a,[hl]
+ subc a,[hl+10]
+ subc a,[hl+b]
+ subc a,[hl+c]
+
+ and a,#10
+ and saddr,#20
+ and a,c
+ and h,a
+ and a,saddr
+ and a,!saddr
+ and a,[hl]
+ and a,[hl+10]
+ and a,[hl+b]
+ and a,[hl+c]
+
+ or a,#10
+ or saddr,#20
+ or a,c
+ or h,a
+ or a,saddr
+ or a,!saddr
+ or a,[hl]
+ or a,[hl+10]
+ or a,[hl+b]
+ or a,[hl+c]
+
+ xor a,#10
+ xor saddr,#20
+ xor a,c
+ xor h,a
+ xor a,saddr
+ xor a,!saddr
+ xor a,[hl]
+ xor a,[hl+10]
+ xor a,[hl+b]
+ xor a,[hl+c]
+
+ cmp a,#10
+ cmp saddr,#20
+ cmp a,c
+ cmp h,a
+ cmp a,saddr
+ cmp a,!saddr
+ cmp a,[hl]
+ cmp a,[hl+10]
+ cmp a,[hl+b]
+ cmp a,[hl+c]
+
+ addw ax,#1234h
+ subw rp0,#2345h
+ cmpw ax,#3456h
+
+ mulu x
+ divuw c
+
+ inc d
+ inc saddr
+ dec e
+ dec saddr
+
+ incw hl
+ decw de
+
+ ror a,1
+ rol a,1
+ rorc a,1
+ rolc a,1
+
+ ror4 [hl]
+ rol4 [hl]
+
+ mov1 cy,saddr.3
+ mov1 cy,sfr.4
+ mov1 cy,a.5
+ mov1 cy,psw.6
+ mov1 cy,[hl].7
+ mov1 saddr.3,cy
+ mov1 sfr.4,cy
+ mov1 a.5,cy
+ mov1 psw.6,cy
+ mov1 [hl].7,cy
+
+ and1 cy,saddr.3
+ and1 cy,sfr.4
+ and1 cy,a.5
+ and1 cy,psw.6
+ and1 cy,[hl].7
+
+ or1 cy,saddr.3
+ or1 cy,sfr.4
+ or1 cy,a.5
+ or1 cy,psw.6
+ or1 cy,[hl].7
+
+ xor1 cy,saddr.3
+ xor1 cy,sfr.4
+ xor1 cy,a.5
+ xor1 cy,psw.6
+ xor1 cy,[hl].7
+
+ set1 saddr.3
+ set1 sfr.4
+ set1 a.5
+ set1 psw.6
+ set1 [hl].7
+
+ clr1 saddr.3
+ clr1 sfr.4
+ clr1 a.5
+ clr1 psw.6
+ clr1 [hl].7
+
+ set1 cy
+ clr1 cy
+ not1 cy
+
+ call 1234h
+ callf 234h
+ callt [12h]
+
+ push psw
+ push de
+ pop psw
+ pop hl
+
+ movw sp,#1234h
+ movw sp,ax
+ movw ax,sp
+
+ br ax
+ br rp0
+ br 1234h
+ br pc
+ br $pc
+ br !pc
+
+ bc pc
+ bnc pc
+ bz pc
+ bnz pc
+
+ bt saddr.3,pc
+ bt sfr.4,pc
+ bt a.5,pc
+ bt psw.6,pc
+ bt [hl].7,pc
+
+ bf saddr.3,pc
+ bf sfr.4,pc
+ bf a.5,pc
+ bf psw.6,pc
+ bf [hl].7,pc
+
+ btclr saddr.3,pc
+ btclr sfr.4,pc
+ btclr a.5,pc
+ btclr psw.6,pc
+ btclr [hl].7,pc
+
+ dbnz b,pc
+ dbnz c,pc
+ dbnz saddr,pc
+
+ sel rb0
+ sel rb1
+ sel rb2
+ sel rb3
+
+ db 1,2,3
+ dw 1,2,3
+ dd 1,2,3
+ dd 1.0,2.0,3.0
+ dq 1.0,2.0,3.0
+ dt 1.0,2.0,3.0
+ db 10 dup (?)
+ db 0
+
+ end
+
diff --git a/tests/t_78k0/t_78k0.doc b/tests/t_78k0/t_78k0.doc
new file mode 100644
index 0000000..3d02b67
--- /dev/null
+++ b/tests/t_78k0/t_78k0.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 78K0 ----------------------------+
+| |
+| This is a (synthetic) test of the 78K0 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_78k0/t_78k0.ori b/tests/t_78k0/t_78k0.ori
new file mode 100644
index 0000000..5b6fc6a
--- /dev/null
+++ b/tests/t_78k0/t_78k0.ori
Binary files differ
diff --git a/tests/t_85/asflags b/tests/t_85/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_85/asflags
diff --git a/tests/t_85/t_85.asm b/tests/t_85/t_85.asm
new file mode 100644
index 0000000..3243692
--- /dev/null
+++ b/tests/t_85/t_85.asm
@@ -0,0 +1,134 @@
+ cpu 8085
+ page 0
+
+ mov d,h
+ mov m,a
+ mov c,m
+ mvi d,12h
+ mvi m,12h
+ lxi b,1234h
+ lxi d,1234h
+ lxi h,1234h
+ stax b
+ stax d
+ stax h
+ ldax b
+ ldax d
+ ldax d
+ ldax h
+ sta 1234h
+ lda 1234h
+ shld 1234h
+ lhld 1234h
+ xchg
+
+ push b
+ push d
+ push h
+ push psw
+ pop b
+ pop d
+ pop h
+ pop psw
+ xthl
+ sphl
+ lxi sp,1234h
+ inx sp
+ dcx sp
+
+ jmp 1234h
+ jc 1234h
+ jnc 1234h
+ jz 1234h
+ jnz 1234h
+ jp 1234h
+ jm 1234h
+ jpe 1234h
+ jpo 1234h
+ pchl
+
+ call 1234h
+ cc 1234h
+ cnc 1234h
+ cz 1234h
+ cnz 1234h
+ cp 1234h
+ cm 1234h
+ cpe 1234h
+ cpo 1234h
+
+ ret
+ rc
+ rnc
+ rz
+ rnz
+ rp
+ rm
+ rpe
+ rpo
+
+ rst 2
+
+ in 12h
+ out 12h
+
+ inr d
+ dcr h
+ inr m
+ dcr m
+ inx b
+ inx d
+ inx h
+ dcx b
+ dcx d
+ dcx h
+
+ add c
+ adc d
+ add m
+ adc m
+ adi 12h
+ aci 12h
+ dad b
+ dad d
+ dad h
+ dad sp
+
+ sub c
+ sbb d
+ sub m
+ sbb m
+ sui 12h
+ sbi 12h
+
+ ana c
+ xra c
+ ora c
+ cmp c
+ ana m
+ xra m
+ ora m
+ cmp m
+ ani 12h
+ xri 12h
+ ori 12h
+ cpi 12h
+
+ rlc
+ rrc
+ ral
+ rar
+
+ cma
+ stc
+ cmc
+ daa
+
+ ei
+ di
+ nop
+ hlt
+
+ rim
+ sim
+
diff --git a/tests/t_85/t_85.doc b/tests/t_85/t_85.doc
new file mode 100644
index 0000000..244e635
--- /dev/null
+++ b/tests/t_85/t_85.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application 85 -----------------------------+
+| |
+| This is a (synthetic) test of the 8080/8085 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_85/t_85.ori b/tests/t_85/t_85.ori
new file mode 100644
index 0000000..0bbef41
--- /dev/null
+++ b/tests/t_85/t_85.ori
Binary files differ
diff --git a/tests/t_87c800/asflags b/tests/t_87c800/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_87c800/asflags
diff --git a/tests/t_87c800/t_87c800.asm b/tests/t_87c800/t_87c800.asm
new file mode 100644
index 0000000..c8e1276
--- /dev/null
+++ b/tests/t_87c800/t_87c800.asm
@@ -0,0 +1,310 @@
+ cpu 87c70
+ include stddef87.inc
+ page 0
+
+ ei
+ di
+ swi
+ nop
+ ret
+ reti
+ retn
+
+targ: jrs t,targ
+ jrs f,targ
+
+ jr t,targ
+ jr f,targ
+ jr eq,targ
+ jr z,targ
+ jr ne,targ
+ jr nz,targ
+ jr cs,targ
+ jr lt,targ
+ jr cc,targ
+ jr ge,targ
+ jr le,targ
+ jr gt,targ
+ jr targ
+
+ daa a
+ daa b
+ das a
+ das c
+ shlc a
+ shlc d
+ shrc a
+ shrc e
+ rolc a
+ rolc h
+ rorc a
+ rorc l
+ swap a
+ swap b
+
+ add a,c
+ addc l,a
+ sub wa,de
+ subb a,(12h)
+ and a,(hl)
+ or a,(de)
+ xor a,(hl+)
+ cmp a,(-hl)
+ add a,(hl+10)
+ addc a,(hl-125)
+ sub a,(hl+c)
+ subb a,(c+hl)
+ and a,(pc+a)
+ or a,(a+pc)
+ cmp (12h),(hl)
+ add (de),(hl)
+ addc (hl+5),(hl)
+ sub (hl+c),(hl)
+ subb (pc+a),(hl)
+ and a,55h
+ or c,55h
+ xor hl,5678h
+ cmp (12h),55h
+ add (hl),55h
+ addc (hl+),55h
+ sub (-hl),55h
+ subb (hl-32),55h
+ and (hl+c),55h
+ or (pc+a),55h
+
+ mcmp (12h),55h
+ mcmp (de),55h
+ mcmp (hl+),55h
+ mcmp (-hl),55h
+ mcmp (hl+3),55h
+ mcmp (c+hl),55h
+ mcmp (pc+a),55h
+
+ inc c
+ inc bc
+ inc (12h)
+ inc (hl)
+ inc (de)
+ inc (hl+)
+ inc (-hl)
+ inc (hl+4)
+ inc (hl+c)
+ inc (a+pc)
+ dec e
+ dec hl
+ dec (12h)
+ dec (hl)
+ dec (de)
+ dec (hl+)
+ dec (-hl)
+ dec (hl-7)
+ dec (hl+c)
+ dec (pc+a)
+
+ mul w,a
+ mul c,b
+ mul d,e
+ mul l,h
+
+ div wa,c
+ div de,c
+ div hl,c
+
+ rold a,(12h)
+ rold a,(hl)
+ rold a,(hl+)
+ rold a,(-hl)
+ rold a,(hl+16)
+ rold a,(c+hl)
+ rord a,(12h)
+ rord a,(hl)
+ rord a,(hl+)
+ rord a,(-hl)
+ rord a,(hl-16)
+ rord a,(hl+c)
+
+ xch a,d
+ xch d,w
+ xch hl,de
+ xch bc,wa
+ xch b,(12h)
+ xch (12h),c
+ xch d,(hl)
+ xch (de),e
+ xch l,(hl+)
+ xch (hl+),h
+ xch a,(-hl)
+ xch (-hl),w
+ xch b,(hl+5)
+ xch (hl-3),c
+ xch d,(hl+c)
+ xch (c+hl),e
+ xch h,(pc+a)
+ xch (a+pc),l
+
+ clr b
+ clr de
+ clr (12h)
+ clr (hl)
+ clr (de)
+ clr (hl+)
+ clr (-hl)
+ clr (hl+5)
+
+ ldw hl,1234h
+ ldw (12h),1234h
+ ldw (hl),1234h
+
+ ld a,l
+ ld d,a
+ ld w,h
+ ld a,(12h)
+ ld c,(12h)
+ ld a,(hl)
+ ld d,(hl)
+ ld c,(de)
+ ld b,(-hl)
+ ld h,(hl+)
+ ld c,(hl-122)
+ ld w,(hl+c)
+ ld d,(a+pc)
+ ld h,20
+
+ ld hl,bc
+ ld de,(12h)
+ ld bc,(de)
+ ld wa,(hl+1)
+ ld hl,(hl+c)
+ ld de,(pc+a)
+ ld bc,1234
+
+ ld (12h),a
+ ld (12h),c
+ ld (12h),de
+ ld (12h),(23h)
+ ld (12h),(de)
+ ld (12h),(hl-42)
+ ld (12h),(hl+c)
+ ld (12h),(pc+a)
+ ld (12h),23h
+
+ ld (hl),a
+ ld (de),d
+ ld (hl+),c
+ ld (-hl),e
+ ld (hl+4),h
+ ld (hl),de
+ ld (hl+5),bc
+ ld (hl),(12h)
+ ld (hl),(de)
+ ld (hl),(hl+1)
+ ld (hl),(hl+c)
+ ld (hl),(pc+a)
+ ld (hl),23h
+ ld (de),23h
+ ld (hl+),23h
+ ld (-hl),23h
+ ld (hl-77),23h
+
+ ld sp,1234h
+ ld sp,de
+ ld hl,sp
+ ld rbs,7
+
+ jp 2000h
+ call 1234h
+ call 0ff54h
+ jp hl
+ call de
+ jp (hl)
+ jp (de)
+ jp (12h)
+ call (12h)
+ jp (hl+5)
+ call (hl-100)
+ jp (hl+c)
+ call (a+pc)
+ jp (c+hl)
+ call (pc+a)
+
+ callv 3
+
+ callp 76h
+ callp 0ff12h
+
+ push psw
+ push de
+ pop wa
+ pop psw
+
+ ld cf,a.5
+ ld cf,(12h).4
+ ld cf,(hl).3
+ ld cf,(hl+).2
+ ld cf,(-hl).1
+ ld cf,(hl+3).0
+ ld cf,(hl+c).7
+ ld cf,(pc+a).3
+ ld cf,(de).c
+
+ ld a.5,cf
+ ld (12h).4,cf
+ ld (hl).3,cf
+ ld (hl+).2,cf
+ ld (-hl).1,cf
+ ld (hl+3).0,cf
+ ld (hl+c).7,cf
+ ld (pc+a).3,cf
+ ld (de).c,cf
+
+ xor cf,d.3
+ xor cf,(12h).4
+ xor cf,(de).5
+ xor cf,(hl+).6
+ xor cf,(-hl).7
+ xor cf,(hl+3).0
+ xor cf,(hl+c).1
+ xor cf,(pc+a).2
+
+ clr cf
+ clr d.3
+ clr (12h).4
+ clr (de).5
+ clr (hl+).6
+ clr (-hl).7
+ clr (hl+3).0
+ clr (hl+c).1
+ clr (pc+a).2
+ clr (de).c
+
+ set cf
+ set d.3
+ set (12h).4
+ set (de).5
+ set (hl+).6
+ set (-hl).7
+ set (hl+3).0
+ set (hl+c).1
+ set (pc+a).2
+ set (de).c
+
+ cpl cf
+ cpl d.3
+ cpl (12h).4
+ cpl (de).5
+ cpl (hl+).6
+ cpl (-hl).7
+ cpl (hl+3).0
+ cpl (hl+c).1
+ cpl (pc+a).2
+ cpl (de).c
+
+ test d.3
+ test (12h).4
+ test (de).5
+ test (hl+).6
+ test (-hl).7
+ test (hl+3).0
+ test (hl+c).1
+ test (pc+a).2
+ test (de).c \ No newline at end of file
diff --git a/tests/t_87c800/t_87c800.doc b/tests/t_87c800/t_87c800.doc
new file mode 100644
index 0000000..3a5a505
--- /dev/null
+++ b/tests/t_87c800/t_87c800.doc
@@ -0,0 +1,5 @@
++------------------------ Test Application 87C800 ---------------------------+
+| |
+| This is a (synthetic) test of the TLCS-870 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_87c800/t_87c800.ori b/tests/t_87c800/t_87c800.ori
new file mode 100644
index 0000000..662b119
--- /dev/null
+++ b/tests/t_87c800/t_87c800.ori
Binary files differ
diff --git a/tests/t_8x30x/asflags b/tests/t_8x30x/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_8x30x/asflags
diff --git a/tests/t_8x30x/t_8x30x.asm b/tests/t_8x30x/t_8x30x.asm
new file mode 100644
index 0000000..9062243
--- /dev/null
+++ b/tests/t_8x30x/t_8x30x.asm
@@ -0,0 +1,57 @@
+ cpu 8x305
+
+leftobj liv $12,3,4
+left2obj liv $12,5,6
+rightobj riv $34,5,6
+right2obj riv $34,3,4
+
+ move r3,ivl ; Register-->Register: ohne Rotation
+ add r11(3),r5 ; mit Rotation
+ and liv1,r1 ; I/O -->Register: direkt, ohne L„nge
+ xor riv3,6,r4 ; direkt, mit L„nge
+ move leftobj,r5 ; symbolisch, ohne L„nge
+ add leftobj,4,r5 ; symbolisch, mit L„nge (redundant)
+ and r2,liv6 ; Register-->I/O direkt, ohne L„nge
+ xor r3,3,riv4 ; direkt, mit L„nge
+ move r11,rightobj ; symbolisch, ohne L„nge
+ add r11,6,rightobj ; symbolisch, mit L„nge (redundant)
+ and liv2,riv4 ; Register-->Register: direkt-->direkt, ohne L„nge
+ xor liv2,5,riv4 ; direkt-->direkt, mit L„nge
+ move riv1,leftobj ; direkt-->symbolisch, ohne L„nge
+ add riv1,4,leftobj ; direkt-->symbolisch, mit L„nge(redundant)
+ and rightobj,liv5 ; symbolisch-->direkt, ohne L„nge
+ xor rightobj,6,liv5 ; symbolisch-->direkt, mit L„nge(redundant)
+ move leftobj,right2obj ; symbolisch-->symbolisch, ohne L„ange
+ add leftobj,4,right2obj ; symbolisch-->symbolisch, mit L„nge(redundant)
+
+ xec $55(r5)
+ xec $12(liv3)
+ xec $12(liv3),6
+ xec $12(leftobj)
+ xec $12(leftobj),4
+
+ nzt r5,*
+ nzt liv3,*
+ nzt liv3,6,*
+ nzt leftobj,*
+ nzt leftobj,4,*
+
+ xmit $34,r5
+ xmit $12,liv3
+ xmit $12,liv3,6
+ xmit $12,leftobj
+ xmit $12,leftobj,4
+
+ sel leftobj
+ sel rightobj
+
+ nop
+
+ halt
+
+ xml 2
+ xmr $0f
+
+temp1 riv @200,7,8
+ sel temp1
+
diff --git a/tests/t_8x30x/t_8x30x.doc b/tests/t_8x30x/t_8x30x.doc
new file mode 100644
index 0000000..06e7536
--- /dev/null
+++ b/tests/t_8x30x/t_8x30x.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 8X30x ---------------------------+
+| |
+| This is a (synthetic) test of the 8X30x instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_8x30x/t_8x30x.ori b/tests/t_8x30x/t_8x30x.ori
new file mode 100644
index 0000000..0370a9e
--- /dev/null
+++ b/tests/t_8x30x/t_8x30x.ori
Binary files differ
diff --git a/tests/t_96/asflags b/tests/t_96/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_96/asflags
diff --git a/tests/t_96/t_96.asm b/tests/t_96/t_96.asm
new file mode 100644
index 0000000..a98eef5
--- /dev/null
+++ b/tests/t_96/t_96.asm
@@ -0,0 +1,217 @@
+ cpu 80196
+
+ include reg96
+
+ax equ 20h
+al equ ax
+ah equ ax+1
+eax equ ax
+bx equ 24h
+bl equ bx
+bh equ bx+1
+ebx equ bx
+cx equ 28h
+cl equ cx
+ch equ cx+1
+ecx equ cx
+dx equ 2ch
+dl equ dx
+dh equ dx+1
+edx equ dx
+
+ CLRC
+ CLRVT
+ DI
+ EI
+ NOP
+ POPF
+ PUSHF
+ RET
+ RSC
+ SETC
+ TRAP
+ PUSHA
+ POPA
+ EPTS
+ DPTS
+
+targ:
+ JC targ
+ JE targ
+ JGE targ
+ JGT targ
+ JH targ
+ JLE targ
+ JLT targ
+ JNC targ
+ JNE targ
+ JNH targ
+ JNST targ
+ JNV targ
+ JNVT targ
+ JST targ
+ JV targ
+ JVT targ
+
+ bmov eax,cx
+ bmovi eax,cx
+
+ add ax,bx
+ add ax,2000h
+ add ax,[bx]
+ add ax,[bx]+
+ add ax,2[bx]
+ add ax,-15[bx]
+ add ax,700[bx]
+ add ax,-300[bx]
+ add ax,#1234h
+
+ add ax,cx,bx
+ add ax,cx,2000h
+ add ax,cx,[bx]
+ add ax,cx,[bx]+
+ add ax,cx,2[bx]
+ add ax,cx,-15[bx]
+ add ax,cx,700[bx]
+ add ax,cx,-300[bx]
+ add ax,cx,#1234h
+
+ addb al,bl
+ addb al,2000h
+ addb al,[bx]
+ addb al,[bx]+
+ addb al,2[bx]
+ addb al,-15[bx]
+ addb al,700[bx]
+ addb al,-300[bx]
+ addb al,#12h
+
+ addb al,cl,bl
+ addb al,cl,2000h
+ addb al,cl,[bx]
+ addb al,cl,[bx]+
+ addb al,cl,2[bx]
+ addb al,cl,-15[bx]
+ addb al,cl,700[bx]
+ addb al,cl,-300[bx]
+ addb al,cl,#12h
+
+ and dx,300h
+ mulu eax,bx,cx
+ mulb ax,cl,ch
+ subb cl,#5
+
+ addc ax,bx
+ addcb al,[bx]
+ cmp ax,[bx]+
+ cmpb al,2[bx]
+ cmpl ecx,edx
+ div eax,-15[bx]
+ divb ax,200[bx]
+ divu eax,-300[bx]
+ divub ax,200
+ ld ax,#2345h
+ ldb al,#16
+ st ax,bx
+ stb al,[bx]
+ subc ax,[bx]+
+ subcb al,2[bx]
+ xor ax,-15[bx]
+ xorb al,200[bx]
+
+ push ax
+ push [bx]
+ push #1234h
+ pop 2000h
+ pop 10[cx]
+
+ xch ax,bx
+ xch ax,[bx]
+ xch ax,10[bx]
+ xch ax,-150[bx]
+ xch ax,[bx]+
+ xch ax,2000h
+ xchb bl,al
+ xchb [bx],al
+ xchb 10[bx],al
+ xchb -150[bx],al
+ xchb [bx]+,al
+ xchb 2000h,al
+
+ clr ax
+ clrb al
+ dec bx
+ decb bh
+ ext eax
+ extb ax
+ inc cx
+ incb cl
+ neg dx
+ negb dh
+ not ax
+ notb al
+
+ scall targ
+ lcall targ
+ call targ
+
+ sjmp targ
+ ljmp targ
+ br targ
+ br [dx]
+
+ djnz cl,$
+ djnzw cx,$
+
+ jbc dh,3,$
+ jbs al,1,$
+
+ tijmp bx,ax,#127
+
+ ldbse ax,#-1
+ ldbze cx,[bx]+
+
+ norml eax,cl
+
+ shl ax,#5
+ shl ax,cl
+ shlb al,#6
+ shlb al,cl
+ shll eax,#7
+ shll eax,cl
+ shr ax,#5
+ shr ax,cl
+ shrb al,#6
+ shrb al,cl
+ shrl eax,#7
+ shrl eax,cl
+ shra ax,#5
+ shra ax,cl
+ shrab al,#6
+ shrab al,cl
+ shral eax,#7
+ shral eax,cl
+
+ skip dl
+
+ idlpd #2
+
+
+ ldb al,100h ; lang
+ ldb al,0c0h ; kurz
+ ldb al,000h ; kurz
+ ldb al,140h ; lang
+ ldb al,[0c0h]
+ ldb al,[000h]
+
+ assume wsr:24h ; =100h..13fh auf 0c0h..0ffh
+
+ ldb al,100h ; jetzt kurz
+ ldb al,0c0h ; jetzt lang
+ ldb al,000h ; immmer noch kurz
+ ldb al,140h ; immer noch lang
+ ldb al,[100h]
+ ldb al,[000h]
+
+ bne 2000h
+ bc 2000h
diff --git a/tests/t_96/t_96.doc b/tests/t_96/t_96.doc
new file mode 100644
index 0000000..6e89bc7
--- /dev/null
+++ b/tests/t_96/t_96.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application 96 -----------------------------+
+| |
+| This is a (synthetic) test of the MCS-96 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_96/t_96.ori b/tests/t_96/t_96.ori
new file mode 100644
index 0000000..d8d17cd
--- /dev/null
+++ b/tests/t_96/t_96.ori
Binary files differ
diff --git a/tests/t_960/asflags b/tests/t_960/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_960/asflags
diff --git a/tests/t_960/t_960.asm b/tests/t_960/t_960.asm
new file mode 100644
index 0000000..df58c12
--- /dev/null
+++ b/tests/t_960/t_960.asm
@@ -0,0 +1,101 @@
+ cpu 80960
+ org 0
+
+ fpu on
+ supmode on
+
+start:
+ flushreg
+ fmark
+ mark
+ ret
+ syncf
+ faultno
+ faultg
+ faulte
+ faultge
+ faultl
+ faultne
+ faultle
+ faulto
+
+ addc r3,r4,r5 ; lokale Register
+ addc g3,g4,g5 ; globale Register
+ addc g3,g5 ; impl. src2=dest
+ addc 10,r4,g10 ; src1 immediate
+ addc g2,20,g4 ; src2 immediate
+
+ addr r3,r4,r5 ; Float: normale Register
+ addr fp2,r4,r5 ; Float-Register
+ addr r3,fp1,r5
+ addr r3,r4,fp3
+ addr 0,r4,r5 ; Float-Konstanten
+ addr r3,1,r5
+
+ addc sp,fp,rip ; Sonderregister
+
+ addi r3,r4,r5 ; nur noch mal zum Testen der Opcodes...
+ addo r3,r4,r5
+
+ calls g2 ; nur ein Operand:
+ calls 4
+
+ chkbit 7,r5 ; kein Ziel
+
+ classr fp1 ; ein Float-Operand
+ classrl g4
+
+ cosr fp1 ; dito mit Ziel
+ cosr g4,fp2
+
+ modpc r3,r4,r5 ; nur im Supervisor-Mode erlaubt
+
+ bbc r4,g5,$+32 ; COBR-Anweisungen
+ bbs 10,r10,$+32
+ cmpobge 10,r4,$+32
+ testne r5
+
+ b $-32 ; CTRL-Anweisungen
+ call $+32
+ bal $+64
+ ble $-64
+
+ bx (r5) ; MEMA ohne disp
+ bx 2345(r5) ; MEMA mit disp
+ bx 2345 ; MEMA ohne base
+ bx -30(r5) ; MEMB base+disp
+ bx 5000(r5) ; dito positiv
+ bx $(ip) ; PC-relativ
+ bx [r4] ; nur Index
+ bx [r4*1] ; Scaling
+ bx [r4*2]
+ bx [r4*4]
+ bx [r4*8]
+ bx [r4*16]
+ bx 0(r5)[r4] ; base+index
+ bx 12345678h ; nur disp
+ bx 450[r6*4] ; disp+index
+ bx 123(r5)[r6*4] ; volles Programm
+
+ st r7,123(r5)[r6*4]; mit 2 Ops
+ ld 123(r5)[r6*4],r7
+
+ db 1
+ align 4
+ db 1,2
+ align 4
+ db 1,2,3
+ align 4
+ db 1,2,3,4
+ dw 1
+ align 4
+ dw 1,2
+ dd 1
+ dd 1.0
+ dq 1.0
+ dt 1.0
+ dw 0
+
+ space 32
+
+ word 1,2,3,4,5
diff --git a/tests/t_960/t_960.doc b/tests/t_960/t_960.doc
new file mode 100644
index 0000000..177a972
--- /dev/null
+++ b/tests/t_960/t_960.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 960 -----------------------------+
+| |
+| This is a (very incomplete) test of the i960 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_960/t_960.ori b/tests/t_960/t_960.ori
new file mode 100644
index 0000000..26b7924
--- /dev/null
+++ b/tests/t_960/t_960.ori
Binary files differ
diff --git a/tests/t_97c241/asflags b/tests/t_97c241/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_97c241/asflags
diff --git a/tests/t_97c241/t_97c241.asm b/tests/t_97c241/t_97c241.asm
new file mode 100644
index 0000000..3c117fb
--- /dev/null
+++ b/tests/t_97c241/t_97c241.asm
@@ -0,0 +1,336 @@
+ page 0
+
+ cpu 97c241
+
+ unlk
+ szf
+ svf
+ ssf
+ scf
+ rzf
+ rvf
+ rsf
+ rets
+ reti
+ ret
+ rcf
+ nop
+ halt
+ ei
+ di
+ czf
+ cvf
+ csf
+ ccf
+
+Targ: jr Targ
+ calr Targ
+ jr $+1002h
+
+ jrc z,Targ
+ jrc ult,Targ
+ jrc ge,Targ
+
+ jrbc 5,1234h,$+108h
+ jrbs 1,345h,Targ
+
+ djnz rw5,Targ
+ djnz.d (123456h),$+100ah
+ djnzc rw6,nov,Targ
+ djnzc.d (rd2+123456h),eq,$+100ah
+
+ link 20h
+ link 3334h
+ retd -122
+ retd -1234
+
+ swi 7
+
+ cpl rb2
+ cpl rw12
+ cpl rd14
+
+ cpl.b rb5
+ cpl.w rw15
+ cpl.d rd4
+
+ cpl.b (123h)
+ cpl.w (123h)
+ cpl.d (123h)
+
+ cpl.b (123456h)
+ cpl.w (123456h)
+ cpl.d (123456h)
+
+ cpl.b (rw2)
+ cpl.w (rw5)
+ cpl.d (rw0)
+
+ cpl.b (rd10)
+ cpl.w (rd6 )
+ cpl.d (rd12)
+
+ cpl.b (rw4++)
+ cpl.w (rw6++)
+ cpl.d (rw9++)
+
+ cpl.b (--rw8)
+ cpl.w (--rw7)
+ cpl.d (--rw5)
+
+ cpl.b (rd2++)
+ cpl.w (rd10++)
+ cpl.d (rd14++)
+
+ cpl.b (--rd4)
+ cpl.w (--rd8)
+ cpl.d (--rd12)
+
+ cpl.b (rw3+123h)
+ cpl.w (rw7+123h)
+ cpl.d (rw1+123h)
+
+ cpl.b (rd2-123h)
+ cpl.w (rd8-123h)
+ cpl.d (rd4-123h)
+
+ cpl.b (rw4 +123456h)
+ cpl.w (rw7 +123456h)
+ cpl.d (rw14+123456h)
+
+ cpl.b (rd6 -123456h)
+ cpl.w (rd12-123456h)
+ cpl.d (rd10-123456h)
+
+ cpl.b (rw0+12h)
+ cpl.w (rw0+12h)
+ cpl.d (rw0+12h)
+
+ cpl.b (rd0-12h)
+ cpl.w (rd0-12h)
+ cpl.d (rd0-12h)
+
+ cpl.b (rw0+12345h)
+ cpl.w (rw0+12345h)
+ cpl.d (rw0+12345h)
+
+ cpl.b (rd0-12345h)
+ cpl.w (rd0-12345h)
+ cpl.d (rd0-12345h)
+
+ cpl.b (sp+12h)
+ cpl.w (sp+12h)
+ cpl.d (sp+12h)
+
+ cpl.b (sp+89h)
+ cpl.w (sp+89h)
+ cpl.d (sp+89h)
+
+ cpl.b (sp+12345h)
+ cpl.w (sp+12345h)
+ cpl.d (sp+12345h)
+
+ cpl.b (pc-89h)
+ cpl.w (pc-89h)
+ cpl.d (pc-89h)
+
+ cpl.b (pc-12345h)
+ cpl.w (pc-12345h)
+ cpl.d (pc-12345h)
+
+ cpl.b (rw2 *4)
+ cpl.w (rw5 *4)
+ cpl.d (rw10*4)
+
+ cpl.b (13h+rd10*8)
+ cpl.w (rd14*8+12h)
+ cpl.d (rd4 *8+12h)
+
+ cpl.b (rw7*2-12345h)
+ cpl.w (rw9*2-12345h)
+ cpl.d (rw1*2-12345h)
+
+ cpl.b (rd10*2+12345h)
+ cpl.w (rd4 *2+12345h)
+ cpl.d (rd6 *2+12345h)
+
+ cpl.b (rw4 + rw6 *8 + 12h)
+ cpl.w (rw5 + rd8 *4 + 12h)
+ cpl.d (rd4 + rw9 *2 + 12h)
+ cpl.b (rd10 + rd14 *1 + 12h)
+ cpl.w (sp + rw5 *2 + 12h)
+ cpl.d (sp + rd2 *4 + 12h)
+ cpl.b (pc + rw11 *8 + 12h)
+ cpl.w (pc + rd4 *4 + 12h)
+
+ cpl sp
+ cpl isp
+ cpl esp
+ cpl pbp
+ cpl cbp
+ cpl psw
+ cpl imc
+ cpl cc
+
+ call targ
+ call (rw2)
+ call.w 123456h
+ clr rb5
+ clr.w (rw3-4)
+ clr.d (--rd2)
+ exts rw1
+ exts.d (sp+20)
+ extz.w (pc-7)
+ extz.d rd12
+ jp Targ
+ jp.w (rd4++)
+ jp.d (--rw5)
+ mirr rb1
+ mirr.w (Targ)
+ mirr.d (sp+1234h)
+ neg.d rd8
+ pop.b (rd10++)
+ push.d 12345678h
+ pusha Targ
+ rvby.w (sp+rw4*4+0aah)
+ tjp.d (rd6)
+ tst.w rw13
+
+ lda rd6,(rd4+12345h)
+
+ add3 rw4,(rd4),(rw2)
+ sub3 rw4,(rd4),1000
+ add3 rw4,(rd4),100
+ sub3 rd2,rd10,(123456h)
+ add3 rd8,(rw2*4+12345h),10
+ sub3 rb5,rb3,rb15
+
+ mac rw4,rb3,rb1
+ macs rd14,(rw4-2),(rd2+4)
+
+ cpsz (rd6++),rb2,rw15
+ cpsn.w (--rd4),(--rd10),rw14
+ lds.d (rd8++),10,rw13
+ lds.w (--rd10),1000,rw12
+
+ rrm.b rb5,rw3,4
+ rlm.d (123456h),rw4,(123456h)
+
+ bfex rw7,rd10,2,12
+ bfexs.b rw9,(rd4),4,6
+ bfin.w (sp+5),rw3,10,3
+ bfex rw10,rd12,20,5
+ bfexs.d rw12,(rd4),30,2
+
+ abcd rb5,(rw2*4)
+ abcd rw4,(1234h)
+ abcd (1234h),rd4
+ adc.w (rd4+2),(rd2*8+5)
+ adc.b (Targ),4
+ cbcd.b (Targ),99h
+ cpc rb5,(rw4+rw4)
+ cpc rb5,(2)
+ max rb5,rb2
+ maxs rw5,(Targ)
+ min.d (Targ),(rw2)
+ mins.d (rd4+3),(rd6-3)
+ sbc.w (rd4),(rd2)
+ sbc.d (Targ),1
+ sbcd rw4,(Targ)
+ sbcd (rd2),rd0
+
+ andcf rw10,15
+ andcf.b (rd2),(rw4)
+ andcf.d (rw10),(Targ)
+ andcf.w (Targ),1
+ ldcf rw10,15
+ ldcf.b (rd2),(rw4)
+ ldcf.d (rw10),(Targ)
+ ldcf.w (Targ),1
+ orcf rw10,15
+ orcf.b (rd2),(rw4)
+ orcf.d (rw10),(Targ)
+ orcf.w (Targ),1
+ stcf rw10,15
+ stcf.b (rd2),(rw4)
+ stcf.d (rw10),(Targ)
+ stcf.w (Targ),1
+ tset rw10,15
+ tset.b (rd2),(rw4)
+ tset.d (rw10),(Targ)
+ tset.w (Targ),1
+ xorcf rw10,15
+ xorcf.b (rd2),(rw4)
+ xorcf.d (rw10),(Targ)
+ xorcf.w (Targ),1
+
+ bs0b rb10,rd12
+ bs0f (Targ),rw3
+ bs1b.w rb10,(Targ)
+ bs1f.b (Targ),(rw10+2)
+
+ chk.d:g (Targ),rd8
+ chk.d (Targ),rd8
+ chks.w (rd6),(rd4)
+ chks.w (rw2),(Targ)
+
+ mul rd2,rw1
+ muls.w (rw2),(Targ)
+ div.d (Targ),(rw2)
+ divs rw4,rb8
+
+ add rw11,2
+ add (rw4),rd8
+ add.w (rd4+2),(rd6+rd8*4+100)
+ add.b rb2,150
+ add.w rw2,150
+ add.d rd2,150
+ add.d (Targ),2
+ add.w:a rw14,(Targ) ; !!! automatische Wahl sonst S
+
+ ld rd10,2000
+ cp rd8,(Targ)
+ sub.w (rd4++),(rd6++)
+
+ and rw4,rw3
+ and.d rd10,rd12
+ or rd10,(rd8)
+ or.w (Targ),(rd4+rw2*4-5)
+ xor.d (Targ),12345678h
+ xor rd2,1000h
+ or rb2,rb7
+ and.w (Targ),rw4
+ xor.d (rw2),(Targ)
+
+ bres rb4,1
+ bset rw7,5
+ bchg rw12,10
+ btst rd4,8
+ bres rd12,20
+ bset.w (rd4),10
+ bchg.d (rw2),15
+ btst.b (Targ),rb1
+ bres rb1,(Targ)
+
+ ex rb1,rb7
+ ex rw5,(rd4)
+ ex.d (Targ),(rw1)
+ ex.b (rw1),(Targ)
+
+ rl rw4,1
+ rlc.w (rd6*2),1
+ rr rd0,5
+ rrc rw1,(rd4)
+ sla rw7,(Targ)
+ sll.d (Targ),3
+ sra.w (rd4),(rw4)
+ srl.b (rw4),(rd4)
+
+ add.w (rw4+0eah),rw7
+ add.w (sp+rw4*4+1234h),(sp+28h)
+ add.w:g (rw4+12345h),(10028h)
+ add.w (rw4+12345h),(10028h)
+ add.w:g (rw4+56h),3579h
+ add.w (rw4+56h),3579h
+ jrc nz,$-1234h
+
diff --git a/tests/t_97c241/t_97c241.doc b/tests/t_97c241/t_97c241.doc
new file mode 100644
index 0000000..08358f7
--- /dev/null
+++ b/tests/t_97c241/t_97c241.doc
@@ -0,0 +1,5 @@
++------------------------ Test Application 97C241 ---------------------------+
+| |
+| This is a (synthetic) test of the TLCS-9000 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_97c241/t_97c241.ori b/tests/t_97c241/t_97c241.ori
new file mode 100644
index 0000000..6b72195
--- /dev/null
+++ b/tests/t_97c241/t_97c241.ori
Binary files differ
diff --git a/tests/t_9900/asflags b/tests/t_9900/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_9900/asflags
diff --git a/tests/t_9900/t_9900.asm b/tests/t_9900/t_9900.asm
new file mode 100644
index 0000000..1c15261
--- /dev/null
+++ b/tests/t_9900/t_9900.asm
@@ -0,0 +1,222 @@
+ cpu tms9900
+ page 0
+ supmode on
+
+ a r5,r3
+
+ a wr5,wr3
+ ab wr6,*wr10
+ c wr7,*wr2+
+ cb wr8,@1234h
+ s wr9,@1234h(wr6)
+
+ sb *wr10,wr9
+ soc *wr11,*wr6
+ socb *wr12,*wr1+
+ szc *wr13,@1234h
+ szcb *wr14,@1234h(wr14)
+
+ mov *wr15+,wr10
+ movb *wr0+,*wr6
+ a *wr1+,*wr6+
+ ab *wr2+,@1234h
+ c *wr3+,@1234h(wr7)
+
+ cb *wr4+,wr5
+ s *wr5+,*wr13
+ sb *wr6+,*wr13+
+ soc *wr7+,@1234h
+ socb *wr8+,@1234h(wr12)
+
+ szc @1234h,wr10
+ szcb @1234h,*wr2
+ mov @1234h,*wr3+
+ movb @1234h,@2345h
+ a @1234h,@2345h(wr8)
+
+ ab @1234h(wr9),wr5
+ c @1234h(wr10),*wr1
+ cb @1234h(wr11),*wr14+
+ s @1234h(wr12),@2345h
+ sb @1234h(wr13),@2345h(wr5)
+
+
+ coc wr12,wr5
+ czc *wr4,wr10
+ xor *wr12+,wr7
+ mpy @1234h,wr4
+ div @200(wr4),wr6
+ xop @2345h,wr5
+
+ mpys wr5
+ divs *wr9+
+
+ b @1234h
+ bl *wr5
+ blwp *wr7+
+ clr wr4
+ seto @1234h(wr8)
+ inv wr7
+ neg *wr15
+ abs wr3
+ swpb wr9
+ inc *wr12+
+ inct *wr12+
+ dec *wr12+
+ dect *wr12+
+ x *wr6
+
+ ldcr wr5,10
+ stcr wr6,16
+
+ sbo 10
+ sbz -33
+ tb 34h
+
+ jeq lab
+ jgt lab
+ jh lab
+ jhe lab
+ jl lab
+ jle lab
+lab: jlt lab
+ jmp lab
+ jnc lab
+ jne lab
+ jno lab
+ joc lab
+ jop lab
+
+ sla wr1,1
+ sra wr5,wr0
+ src wr6,10
+ srl wr10,15
+
+ ai wr5,1234h
+ andi wr10,2345h
+ ci wr15,3456h
+ li wr5,4567h
+ ori wr10,5678h
+
+ lwpi 1234h
+ limi 2345h
+
+ stst wr2
+ lst wr4
+ stwp wr6
+ lwp wr8
+
+ rtwp
+ idle
+ rset
+ ckof
+ ckon
+ lrex
+
+ padding on
+
+ byte 1,2,3,4,5
+ byte "Hello World"
+ byte 1,2,3,4,5,6
+ byte "Hello World!"
+ word 1,2,3,4,5
+
+ padding off
+
+ byte 1,2,3,4,5
+ byte "Hello World"
+ byte 1,2,3,4,5,6
+ byte "Hello World!"
+ word 1,2,3,4,5
+
+
+table equ 1234h
+oldval equ 2345h
+newval equ 3456h
+new equ 4567h
+loc equ 5678h
+count equ 6789h
+list equ 789ah
+tran equ 89abh
+testbits equ 9abch
+testbit equ 0abcdh
+ones equ 0bcdeh
+temp equ 0cdefh
+change equ 0def0h
+bits equ 0ef01h
+testva equ 0f012h
+prt equ r3
+
+ a r5,@table
+ ab 3,*2+
+ ai 6,0ch
+ s @oldval,@newval
+ sb *6+,1
+ mpy @new,5
+ div @loc,2
+ inc @count
+ inct 5
+ dec @count
+ dect prt
+ abs @list(7)
+ neg 5
+ b *3
+ bl @tran
+ blwp @tran
+ rtwp
+ jmp $
+ jh $
+ jl $
+ jhe $
+ jle $
+ jgt $
+ jlt $
+ jeq $
+ jne $
+ joc $
+ jnc $
+ jno $
+ jop $
+ x @tran
+ c r5,@table
+ cb 3,*2+
+ ci 9,0f330h
+ coc @testbits,8
+ czc @testbit,8
+ rset
+ idle
+ ckof
+ ckon
+ lrex
+ sbo 20
+ sbz 30
+ tb 40
+ ldcr @1234h,7
+ stcr @1234h,7
+ li 7,5
+ limi 3
+ lwpi 12h
+ lmf r5,0
+ mov 7,7
+ mov @ones,9
+ movb @temp,3
+ swpb *0+
+ stst 7
+ stwp r5
+ andi 0,6d03h
+ ori 5,60d3h
+ xor @change,2
+ inv 11
+ clr *0bh
+ seto 3
+ soc 3,@new
+ socb 5,8
+ szc 5,7
+ SZCB @bits,@testva
+ sra 5,0
+ sla 10,5
+ srl 0,3
+ src 2,7
+ xop *4,wr4
+ lds @bits
+ ldd @bits
diff --git a/tests/t_9900/t_9900.doc b/tests/t_9900/t_9900.doc
new file mode 100644
index 0000000..b0dc9c4
--- /dev/null
+++ b/tests/t_9900/t_9900.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application 9900 ----------------------------+
+| |
+| This is a (synthetic) test of the TMS99xx instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_9900/t_9900.ori b/tests/t_9900/t_9900.ori
new file mode 100644
index 0000000..b50ef4a
--- /dev/null
+++ b/tests/t_9900/t_9900.ori
Binary files differ
diff --git a/tests/t_ace/asflags b/tests/t_ace/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_ace/asflags
diff --git a/tests/t_ace/t_ace.asm b/tests/t_ace/t_ace.asm
new file mode 100644
index 0000000..cf4389b
--- /dev/null
+++ b/tests/t_ace/t_ace.asm
@@ -0,0 +1,132 @@
+ cpu ace1202
+ page 0
+
+ adc a, #055h
+ adc a, 030h
+ adc a, [x]
+ adc a, [#33h, x]
+
+ add a, #055h
+ add a, 030h
+ add a, [x]
+ add a, [#33h, x]
+
+ and a, #055h
+ and a, 030h
+ and a, [x]
+ and a, [#33h, x]
+
+ clr a
+ clr x
+ clr 030h
+
+ dec a
+ dec x
+ dec 030h
+
+ ifbit 7, a
+ ifbit 7, 033h
+ ifbit 7, [x]
+
+ ifc
+
+ ifeq a, #033h
+ ifeq a, 033h
+ ifeq a, [x]
+ ifeq a, [#044h, x]
+ ifeq x, #00344h
+ ifeq 033h, #044h
+
+ ifgt a, #033h
+ ifgt a, 033h
+ ifgt a, [x]
+ ifgt a, [#044h, x]
+ ifgt x, #00344h
+
+ iflt x, #00344h
+
+ ifnc
+
+ ifne a, #055h
+ ifne a, 030h
+ ifne a, [x]
+ ifne a, [#33h, x]
+
+ inc a
+ inc x
+ inc 030h
+
+ intr
+
+ invc
+
+ jmp 070eh
+ jmp [#01h, x]
+
+ jp $-30
+ jp $-15
+ jp $-1
+ jp $
+ jp $+1
+ jp $+15
+ jp $+31
+ jp $+32
+
+ jsr 070eh
+ jsr [#01h, x]
+
+ ld a, #033h
+ ld a, 033h
+ ld a, [x]
+ ld a, [#044h, x]
+ ld x, #00344h
+ ld 033h, #044h
+ ld 033h, 034h
+
+ ldc 2, 033h
+
+ nop
+
+ or a, #055h
+ or a, 030h
+ or a, [x]
+ or a, [#33h, x]
+
+ rbit 2, 033h
+ rbit 2, [x]
+ rbit 2, a ; Makro
+
+ rc
+
+ ret
+
+ reti
+
+ rlc a
+ rlc 030h
+
+ rrc a
+ rrc 030h
+
+ sbit 2, 033h
+ sbit 2, [x]
+ sbit 2, a ; Makro
+
+ sc
+
+ st a, 033h
+ st a, [x]
+ st a, [#044h, x]
+
+ stc 2, 033h
+
+ subc a, #055h
+ subc a, 030h
+ subc a, [x]
+ subc a, [#33h, x]
+
+ xor a, #055h
+ xor a, 030h
+ xor a, [x]
+ xor a, [#33h, x]
+
diff --git a/tests/t_ace/t_ace.doc b/tests/t_ace/t_ace.doc
new file mode 100644
index 0000000..5f86dbf
--- /dev/null
+++ b/tests/t_ace/t_ace.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application ACE -----------------------------+
+| |
+| This is a (synthetic) test of the ACE code generator |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_ace/t_ace.ori b/tests/t_ace/t_ace.ori
new file mode 100644
index 0000000..6db9f2e
--- /dev/null
+++ b/tests/t_ace/t_ace.ori
Binary files differ
diff --git a/tests/t_avr/asflags b/tests/t_avr/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_avr/asflags
diff --git a/tests/t_avr/t_avr.asm b/tests/t_avr/t_avr.asm
new file mode 100644
index 0000000..e84e084
--- /dev/null
+++ b/tests/t_avr/t_avr.asm
@@ -0,0 +1,229 @@
+
+ cpu at90s8515
+ page 0
+ include regavr.inc
+
+ adc r3,r1
+
+ add r28,r28
+
+ and r2,r16
+
+ andi r19,$aa
+
+ adiw r26,14
+
+ asr r17
+
+ bclr 7
+
+ bld r0,4
+
+ brbc 1,*
+
+ brbs 6,*
+
+ brcc next ; 1 = 01
+
+ brcs next ; 0 = 00
+next:
+ breq next ; -1 = 7F
+
+ brge next ; -2 = 7E
+
+ brsh next ; -3 = 7D
+
+ brid next ; -4 = 7C
+
+ brie next ; -5 = 7B
+
+ brlo next ; -6 = 7A
+
+ brlt next ; -7 = 79
+
+ brmi next ; -8 = 78
+
+ brne next ; -9 = 77
+
+ brhc next ; -10 = 76
+
+ brhs next ; -11 = 75
+
+ brpl next ; -12 = 74
+
+ brtc next ; -13 = 73
+
+ brts next ; -14 = 72
+
+ brvc next ; -15 = 71
+
+ brvs next ; -16 = 70
+
+ bset 6
+
+ bst r1,2
+
+; call $123456
+
+ cbr r16,$f0
+
+ cbi $12,7
+
+ clc
+
+ cli
+
+ cln
+
+ clh
+
+ clr r18
+
+ cls
+
+ clt
+
+ clv
+
+ clz
+
+ com r4
+
+ cp r4,r19
+
+ cpc r3,r1
+
+ cpi r19,3
+
+ cpse r4,r0
+
+ dec r17
+
+ eor r0,r22
+
+ icall
+
+ ijmp
+
+ in r23,$34
+
+ inc r22
+
+; jmp $123456
+
+ ld r2,x
+ ld r0,x+
+ ld r3,-x
+
+ ld r1,y
+ ld r0,y+
+ ld r3,-y
+ ldd r4,y+$33
+
+ ld r1,z
+ ld r0,z+
+ ld r3,-z
+ ldd r4,z+$33
+
+ ldi r30,$f0
+
+ lds r2,$ff00
+
+ lpm
+
+ lsl r0
+
+ lsr r0
+
+ mov r16,r0
+
+; mul r6,r5
+
+ neg r11
+
+ nop
+
+ or r15,r16
+
+ ori r16,$f0
+
+ out $18,r16
+
+ pop r13
+
+ push r14
+
+ rcall *
+
+ ret
+
+ reti
+
+ rjmp *
+
+ rol r15
+
+ ror r15
+
+ sbc r3,r1
+
+ sbci r17,$4f
+
+ sbi $1c,3
+
+ sbic $1c,1
+
+ sbis $10,3
+
+ sbr r16,3
+
+ sbrc r0,7
+
+ sbrs r0,7
+
+ sec
+
+ sei
+
+ sen
+
+ seh
+
+ ser r17
+
+ ses
+
+ set
+
+ sev
+
+ sez
+
+ sleep
+
+ st x,r1
+ st x+,r0
+ st -x,r3
+
+ st y,r1
+ st y+,r0
+ st -y,r3
+ std y+2,r4
+
+ st z,r1
+ st z+,r0
+ st -z,r3
+ std z+2,r4
+
+ sts $ff00,r2
+
+ sub r13,r12
+
+ subi r22,$11
+
+ swap r1
+
+ tst r3
+
+ wdr
+
diff --git a/tests/t_avr/t_avr.doc b/tests/t_avr/t_avr.doc
new file mode 100644
index 0000000..71f3709
--- /dev/null
+++ b/tests/t_avr/t_avr.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application AVR ----------------------------+
+| |
+| This is a (synthetic) test of the Atmel AVR instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_avr/t_avr.ori b/tests/t_avr/t_avr.ori
new file mode 100644
index 0000000..9a74d6f
--- /dev/null
+++ b/tests/t_avr/t_avr.ori
Binary files differ
diff --git a/tests/t_bas52/asflags b/tests/t_bas52/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_bas52/asflags
diff --git a/tests/t_bas52/bas52.clk b/tests/t_bas52/bas52.clk
new file mode 100644
index 0000000..d019e11
--- /dev/null
+++ b/tests/t_bas52/bas52.clk
@@ -0,0 +1,18 @@
+ ;**************************************************************
+ ;
+ ; The statement action routine - CLOCK
+ ;
+ ;**************************************************************
+ ;
+SCLOCK: ACALL OTST ;GET CHARACTER AFTER CLOCK TOKEN
+ CLR ET0
+ CLR C_BIT
+ JNC SC_R ;EXIT IF A ZERO
+ ANL TMOD,#0F0H ;SET UP THE MODE
+ SETB C_BIT ;USER INTERRUPTS
+ ORL IE,#82H ;ENABLE ET0 AND EA
+ SETB TR0 ;TURN ON THE TIMER
+ ;
+SC_R: RET
+ ;
+
diff --git a/tests/t_bas52/bas52.fp b/tests/t_bas52/bas52.fp
new file mode 100644
index 0000000..c8a137c
--- /dev/null
+++ b/tests/t_bas52/bas52.fp
@@ -0,0 +1,1616 @@
+;************************************************************
+;
+; This is a complete BCD floating point package for the 8051 micro-
+; controller. It provides 8 digits of accuracy with exponents that
+; range from +127 to -127. The mantissa is in packed BCD, while the
+; exponent is expressed in pseudo-twos complement. A ZERO exponent
+; is used to express the number ZERO. An exponent value of 80H or
+; greater than means the exponent is positive, i.e. 80H = E 0,
+; 81H = E+1, 82H = E+2 and so on. If the exponent is 7FH or less,
+; the exponent is negative, 7FH = E-1, 7EH = E-2, and so on.
+; ALL NUMBERS ARE ASSUMED TO BE NORMALIZED and all results are
+; normalized after calculation. A normalized mantissa is >=.10 and
+; <=.99999999.
+;
+; The numbers in memory assumed to be stored as follows:
+;
+; EXPONENT OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE
+; SIGN OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-1
+; DIGIT 78 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-2
+; DIGIT 56 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-3
+; DIGIT 34 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-4
+; DIGIT 12 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-5
+;
+; EXPONENT OF ARGUMENT 1 = VALUE OF ARG_STACK
+; SIGN OF ARGUMENT 1 = VALUE OF ARG_STACK-1
+; DIGIT 78 OF ARGUMENT 1 = VALUE OF ARG_STACK-2
+; DIGIT 56 OF ARGUMENT 1 = VALUE OF ARG_STACK-3
+; DIGIT 34 OF ARGUMENT 1 = VALUE OF ARG_STACK-4
+; DIGIT 12 OF ARGUMENT 1 = VALUE OF ARG_STACK-5
+;
+; The operations are performed thusly:
+;
+; ARG_STACK+FP_NUMBER_SIZE = ARG_STACK+FP_NUMBER_SIZE # ARG_STACK
+;
+; Which is ARGUMENT 2 = ARGUMENT 2 # ARGUMENT 1
+;
+; Where # can be ADD, SUBTRACT, MULTIPLY OR DIVIDE.
+;
+; Note that the stack gets popped after an operation.
+;
+; The FP_COMP instruction POPS the ARG_STACK TWICE and returns status.
+;
+;**********************************************************************
+;
+
+ segment code
+ newpage
+ section float ; protect symbols
+;**********************************************************************
+;
+; STATUS ON RETURN - After performing an operation (+, -, *, /)
+; the accumulator contains the following status
+;
+; ACCUMULATOR - BIT 0 - FLOATING POINT UNDERFLOW OCCURED
+;
+; - BIT 1 - FLOATING POINT OVERFLOW OCCURED
+;
+; - BIT 2 - RESULT WAS ZER0
+;
+; - BIT 3 - DIVIDE BY ZERO ATTEMPTED
+;
+; - BIT 4 - NOT USED, 0 RETURNED
+;
+; - BIT 5 - NOT USED, 0 RETURNED
+;
+; - BIT 6 - NOT USED, 0 RETURNED
+;
+; - BIT 7 - NOT USED, 0 RETURNED
+;
+; NOTE: When underflow occures, a ZERO result is returned.
+; When overflow or divide by zero occures, a result of
+; .99999999 E+127 is returned and it is up to the user
+; to handle these conditions as needed in the program.
+;
+; NOTE: The Compare instruction returns F0 = 0 if ARG 1 = ARG 2
+; and returns a CARRY FLAG = 1 if ARG 1 is > ARG 2
+;
+;***********************************************************************
+;
+ newpage
+;***********************************************************************
+;
+; The following values MUST be provided by the user
+;
+;***********************************************************************
+;
+ARG_STACK EQU 9 ;ARGUMENT STACK POINTER
+ARG_STACK_PAGE EQU 1
+FORMAT EQU 23 ;LOCATION OF OUTPUT FORMAT BYTE
+OUTPUT EQU 1990H ;CALL LOCATION TO OUTPUT A CHARACTER
+CONVT EQU 58H ;LOCATION TO CONVERT NUMBERS
+INTGRC BIT 25 ;BIT SET IF INTGER ERROR
+ZSURP BIT 54 ;ZERO SUPRESSION FOR HEX PRINT
+;
+;***********************************************************************
+;
+; The following equates are used internally
+;
+;***********************************************************************
+;
+FP_NUMBER_SIZE EQU 6
+DIGIT EQU FP_NUMBER_SIZE-2
+R0B0 EQU 0
+R1B0 EQU 1
+UNDERFLOW EQU 0
+ACC_UNDERFLOW BIT ACC.0 ; ******AA added
+OVERFLOW EQU 1
+ACC_OVERFLOW BIT ACC.1 ; ******AA added
+ZERO EQU 2
+ACC_ZERO BIT ACC.2 ; ******AA added
+ZERO_DIVIDE EQU 3
+ACC_ZERO_DIVIDE BIT ACC.3 ; ******AA added
+;
+;***********************************************************************
+ newpage
+ ;**************************************************************
+ ;
+ ; The following internal locations are used by the math pack
+ ; ordering is important and the FP_DIGITS must be bit
+ ; addressable
+ ;
+ ;***************************************************************
+ ;
+FP_STATUS EQU 28H ;NOT USED
+FP_TEMP EQU FP_STATUS+1 ;NOT USED
+FP_CARRY SFRB FP_STATUS+2 ;USED FOR BITS ******AA EQU-->SFRB
+ADD_IN BIT 35 ;DCMPXZ IN BASIC BACKAGE
+XSIGN BIT FP_CARRY.0
+FOUND_RADIX BIT FP_CARRY.1
+FIRST_RADIX BIT FP_CARRY.2
+DONE_LOAD BIT FP_CARRY.3
+FP_DIG12 EQU FP_CARRY+1
+FP_DIG34 EQU FP_CARRY+2
+FP_DIG56 EQU FP_CARRY+3
+FP_DIG78 EQU FP_CARRY+4
+FP_SIGN SFRB FP_CARRY+5 ; ******AA EQU-->SFRB
+MSIGN BIT FP_SIGN.0
+FP_EXP EQU FP_CARRY+6
+FP_NIB1 EQU FP_DIG12
+FP_NIB2 EQU FP_NIB1+1
+FP_NIB3 EQU FP_NIB1+2
+FP_NIB4 EQU FP_NIB1+3
+FP_NIB5 EQU FP_NIB1+4
+FP_NIB6 EQU FP_NIB1+5
+FP_NIB7 EQU FP_NIB1+6
+FP_NIB8 EQU FP_NIB1+7
+FP_ACCX EQU FP_NIB1+8
+FP_ACCC EQU FP_NIB1+9
+FP_ACC1 EQU FP_NIB1+10
+FP_ACC2 EQU FP_NIB1+11
+FP_ACC3 EQU FP_NIB1+12
+FP_ACC4 EQU FP_NIB1+13
+FP_ACC5 EQU FP_NIB1+14
+FP_ACC6 EQU FP_NIB1+15
+FP_ACC7 EQU FP_NIB1+16
+FP_ACC8 EQU FP_NIB1+17
+FP_ACCS EQU FP_NIB1+18
+ ;
+ newpage
+ ORG 1993H
+ ;
+ ;**************************************************************
+ ;
+ ; The floating point entry points and jump table
+ ;
+ ;**************************************************************
+ ;
+ AJMP FLOATING_ADD
+ AJMP FLOATING_SUB
+ AJMP FLOATING_COMP
+ AJMP FLOATING_MUL
+ AJMP FLOATING_DIV
+ AJMP HEXSCAN
+ AJMP FLOATING_POINT_INPUT
+ AJMP FLOATING_POINT_OUTPUT
+ AJMP CONVERT_BINARY_TO_ASCII_STRING
+ AJMP CONVERT_ASCII_STRING_TO_BINARY
+ AJMP MULNUM10
+ AJMP HEXOUT
+ AJMP PUSHR2R0
+ ;
+ newpage
+ ;
+FLOATING_SUB:
+ ;
+ MOV P2,#ARG_STACK_PAGE
+ MOV R0,ARG_STACK
+ DEC R0 ;POINT TO SIGN
+ MOVX A,@R0 ;READ SIGN
+ CPL ACC.0
+ MOVX @R0,A
+ ;
+ ;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ ;
+FLOATING_ADD:
+ ;
+ ;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ ;
+ ;
+ ACALL MDES1 ;R7=TOS EXP, R6=TOS-1 EXP, R4=TOS SIGN
+ ;R3=TOS-1 SIGN, OPERATION IS R1 # R0
+ ;
+ MOV A,R7 ;GET TOS EXPONENT
+ JZ POP_AND_EXIT ;IF TOS=0 THEN POP AND EXIT
+ CJNE R6,#0,LOAD1 ;CLEAR CARRY EXIT IF ZERO
+ ;
+ ;**************************************************************
+ ;
+SWAP_AND_EXIT: ; Swap external args and return
+ ;
+ ;**************************************************************
+ ;
+ ACALL LOAD_POINTERS
+ MOV R7,#FP_NUMBER_SIZE
+ ;
+SE1: MOVX A,@R0 ;SWAP THE ARGUMENTS
+ MOVX @R1,A
+ DEC R0
+ DEC R1
+ DJNZ R7,SE1
+ ;
+POP_AND_EXIT:
+ ;
+ MOV A,ARG_STACK ;POP THE STACK
+ ADD A,#FP_NUMBER_SIZE
+ MOV ARG_STACK,A
+ CLR A
+ RET
+ ;
+ ;
+LOAD1: SUBB A,R6 ;A = ARG 1 EXP - ARG 2 EXP
+ MOV FP_EXP,R7 ;SAVE EXPONENT AND SIGN
+ MOV FP_SIGN,R4
+ JNC LOAD2 ;ARG1 EXPONENT IS LARGER OR SAME
+ MOV FP_EXP,R6
+ MOV FP_SIGN,R3
+ CPL A
+ INC A ;COMPENSATE FOR EXP DELTA
+ XCH A,R0 ;FORCE R0 TO POINT AT THE LARGEST
+ XCH A,R1 ;EXPONENT
+ XCH A,R0
+ ;
+LOAD2: MOV R7,A ;SAVE THE EXPONENT DELTA IN R7
+ CLR ADD_IN
+ CJNE R5,#0,$+5
+ SETB ADD_IN
+ ;
+ newpage
+ ; Load the R1 mantissa
+ ;
+ ACALL LOADR1_MANTISSA ;LOAD THE SMALLEST NUMBER
+ ;
+ ; Now align the number to the delta exponent
+ ; R4 points to the string of the last digits lost
+ ;
+ CJNE R7,#DIGIT+DIGIT+3,$+3
+ JC $+4
+ MOV R7,#DIGIT+DIGIT+2
+ ;
+ MOV FP_CARRY,#00 ;CLEAR THE CARRY
+ ACALL RIGHT ;SHIFT THE NUMBER
+ ;
+ ; Set up for addition and subtraction
+ ;
+ MOV R7,#DIGIT ;LOOP COUNT
+ MOV R1,#FP_DIG78
+ MOV A,#9EH
+ CLR C
+ SUBB A,R4
+ DA A
+ XCH A,R4
+ JNZ $+3
+ MOV R4,A
+ CJNE A,#50H,$+3 ;TEST FOR SUBTRACTION
+ JNB ADD_IN,SUBLP ;DO SUBTRACTION IF NO ADD_IN
+ CPL C ;FLIP CARRY FOR ADDITION
+ ACALL ADDLP ;DO ADDITION
+ ;
+ JNC ADD_R
+ INC FP_CARRY
+ MOV R7,#1
+ ACALL RIGHT
+ ACALL INC_FP_EXP ;SHIFT AND BUMP EXPONENT
+ ;
+ADD_R: AJMP STORE_ALIGN_TEST_AND_EXIT
+ ;
+ADDLP: MOVX A,@R0
+ ADDC A,@R1
+ DA A
+ MOV @R1,A
+ DEC R0
+ DEC R1
+ DJNZ R7,ADDLP ;LOOP UNTIL DONE
+ RET
+ ;
+ newpage
+ ;
+SUBLP: MOVX A,@R0 ;NOW DO SUBTRACTION
+ MOV R6,A
+ CLR A
+ ADDC A,#99H
+ SUBB A,@R1
+ ADD A,R6
+ DA A
+ MOV @R1,A
+ DEC R0
+ DEC R1
+ DJNZ R7,SUBLP
+ JC FSUB6
+ ;
+ newpage
+ ;
+ ; Need to complement the result and sign because the floating
+ ; point accumulator mantissa was larger than the external
+ ; memory and their signs were equal.
+ ;
+ CPL FP_SIGN.0
+ MOV R1,#FP_DIG78
+ MOV R7,#DIGIT ;LOOP COUNT
+ ;
+FSUB5: MOV A,#9AH
+ SUBB A,@R1
+ ADD A,#0
+ DA A
+ MOV @R1,A
+ DEC R1
+ CPL C
+ DJNZ R7,FSUB5 ;LOOP
+ ;
+ ; Now see how many zeros their are
+ ;
+FSUB6: MOV R0,#FP_DIG12
+ MOV R7,#0
+ ;
+FSUB7: MOV A,@R0
+ JNZ FSUB8
+ INC R7
+ INC R7
+ INC R0
+ CJNE R0,#FP_SIGN,FSUB7
+ AJMP ZERO_AND_EXIT
+ ;
+FSUB8: CJNE A,#10H,$+3
+ JNC FSUB9
+ INC R7
+ ;
+ ; Now R7 has the number of leading zeros in the FP ACC
+ ;
+FSUB9: MOV A,FP_EXP ;GET THE OLD EXPONENT
+ CLR C
+ SUBB A,R7 ;SUBTRACT FROM THE NUMBER OF ZEROS
+ JZ FSUB10
+ JC FSUB10
+ ;
+ MOV FP_EXP,A ;SAVE THE NEW EXPONENT
+ ;
+ ACALL LEFT1 ;SHIFT THE FP ACC
+ MOV FP_CARRY,#0
+ AJMP STORE_ALIGN_TEST_AND_EXIT
+ ;
+FSUB10: AJMP UNDERFLOW_AND_EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+FLOATING_COMP: ; Compare two floating point numbers
+ ; used for relational operations and is faster
+ ; than subtraction. ON RETURN, The carry is set
+ ; if ARG1 is > ARG2, else carry is not set
+ ; if ARG1 = ARG2, F0 gets set
+ ;
+ ;***************************************************************
+ ;
+ ACALL MDES1 ;SET UP THE REGISTERS
+ MOV A,ARG_STACK
+ ADD A,#FP_NUMBER_SIZE+FP_NUMBER_SIZE
+ MOV ARG_STACK,A ;POP THE STACK TWICE, CLEAR THE CARRY
+ MOV A,R6 ;CHECK OUT EXPONENTS
+ CLR F0
+ SUBB A,R7
+ JZ EXPONENTS_EQUAL
+ JC ARG1_EXP_IS_LARGER
+ ;
+ ; Now the ARG2 EXPONENT is > ARG1 EXPONENT
+ ;
+SIGNS_DIFFERENT:
+ ;
+ MOV A,R3 ;SEE IF SIGN OF ARG2 IS POSITIVE
+ SJMP $+3
+ ;
+ARG1_EXP_IS_LARGER:
+ ;
+ MOV A,R4 ;GET THE SIGN OF ARG1 EXPONENT
+ JZ $+3
+ CPL C
+ RET
+ ;
+EXPONENTS_EQUAL:
+ ;
+ ; First, test the sign, then the mantissa
+ ;
+ CJNE R5,#0,SIGNS_DIFFERENT
+ ;
+BOTH_PLUS:
+ ;
+ MOV R7,#DIGIT ;POINT AT MS DIGIT
+ DEC R0
+ DEC R0
+ DEC R0
+ DEC R1
+ DEC R1
+ DEC R1
+ ;
+ ; Now do the compare
+ ;
+CLOOP: MOVX A,@R0
+ MOV R6,A
+ MOVX A,@R1
+ SUBB A,R6
+ JNZ ARG1_EXP_IS_LARGER
+ INC R0
+ INC R1
+ DJNZ R7,CLOOP
+ ;
+ ; If here, the numbers are the same, the carry is cleared
+ ;
+ SETB F0
+ RET ;EXIT WITH EQUAL
+ ;
+ newpage
+;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
+;
+FLOATING_MUL: ; Floating point multiply
+;
+;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
+;
+ ACALL MUL_DIV_EXP_AND_SIGN
+ ;
+ ; check for zero exponents
+ ;
+ CJNE R6,#00,$+5 ;ARG 2 EXP ZERO?
+ AJMP ZERO_AND_EXIT
+ ;
+ ; calculate the exponent
+ ;
+FMUL1: MOV FP_SIGN,R5 ;SAVE THE SIGN, IN CASE OF FAILURE
+ ;
+ MOV A,R7
+ JZ FMUL1-2
+ ADD A,R6 ;ADD THE EXPONENTS
+ JB ACC.7,FMUL_OVER
+ JBC CY,FMUL2 ;SEE IF CARRY IS SET
+ ;
+ AJMP UNDERFLOW_AND_EXIT
+ ;
+FMUL_OVER:
+ ;
+ JNC FMUL2 ;OK IF SET
+ ;
+FOV: AJMP OVERFLOW_AND_EXIT
+ ;
+FMUL2: SUBB A,#129 ;SUBTRACT THE EXPONENT BIAS
+ MOV R6,A ;SAVE IT FOR LATER
+ ;
+ ; Unpack and load R0
+ ;
+ ACALL UNPACK_R0
+ ;
+ ; Now set up for loop multiply
+ ;
+ MOV R3,#DIGIT
+ MOV R4,R1B0
+ ;
+ newpage
+ ;
+ ; Now, do the multiply and accumulate the product
+ ;
+FMUL3: MOV R1B0,R4
+ MOVX A,@R1
+ MOV R2,A
+ ACALL MUL_NIBBLE
+ ;
+ MOV A,R2
+ SWAP A
+ ACALL MUL_NIBBLE
+ DEC R4
+ DJNZ R3,FMUL3
+ ;
+ ; Now, pack and restore the sign
+ ;
+ MOV FP_EXP,R6
+ MOV FP_SIGN,R5
+ AJMP PACK ;FINISH IT OFF
+ ;
+ newpage
+ ;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
+ ;
+FLOATING_DIV:
+ ;
+ ;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
+ ;
+ ACALL MDES1
+ ;
+ ; Check the exponents
+ ;
+ MOV FP_SIGN,R5 ;SAVE THE SIGN
+ CJNE R7,#0,DIV0 ;CLEARS THE CARRY
+ ACALL OVERFLOW_AND_EXIT
+ CLR A
+ SETB ACC_ZERO_DIVIDE
+ RET
+ ;
+DIV0: MOV A,R6 ;GET EXPONENT
+ JZ FMUL1-2 ;EXIT IF ZERO
+ SUBB A,R7 ;DELTA EXPONENT
+ JB ACC.7,D_UNDER
+ JNC DIV3
+ AJMP UNDERFLOW_AND_EXIT
+ ;
+D_UNDER:JNC FOV
+ ;
+DIV3: ADD A,#129 ;CORRECTLY BIAS THE EXPONENT
+ MOV FP_EXP,A ;SAVE THE EXPONENT
+ ACALL LOADR1_MANTISSA ;LOAD THE DIVIDED
+ ;
+ MOV R2,#FP_ACCC ;SAVE LOCATION
+ MOV R3,R0B0 ;SAVE POINTER IN R3
+ MOV FP_CARRY,#0 ;ZERO CARRY BYTE
+ ;
+DIV4: MOV R5,#0FFH ;LOOP COUNT
+ SETB C
+ ;
+DIV5: MOV R0B0,R3 ;RESTORE THE EXTERNAL POINTER
+ MOV R1,#FP_DIG78 ;SET UP INTERNAL POINTER
+ MOV R7,#DIGIT ;LOOP COUNT
+ JNC DIV7 ;EXIT IF NO CARRY
+ ;
+DIV6: MOVX A,@R0 ;DO ACCUMLATION
+ MOV R6,A
+ CLR A
+ ADDC A,#99H
+ SUBB A,R6
+ ADD A,@R1
+ DA A
+ MOV @R1,A
+ DEC R0
+ DEC R1
+ DJNZ R7,DIV6 ;LOOP
+ ;
+ INC R5 ;SUBTRACT COUNTER
+ JC DIV5 ;KEEP LOOPING IF CARRY
+ MOV A,@R1 ;GET CARRY
+ SUBB A,#1 ;CARRY IS CLEARED
+ MOV @R1,A ;SAVE CARRY DIGIT
+ CPL C
+ SJMP DIV5 ;LOOP
+ ;
+ ; Restore the result if carry was found
+ ;
+DIV7: ACALL ADDLP ;ADD NUMBER BACK
+ MOV @R1,#0 ;CLEAR CARRY
+ MOV R0B0,R2 ;GET SAVE COUNTER
+ MOV @R0,5 ;SAVE COUNT BYTE
+ ;
+ INC R2 ;ADJUST SAVE COUNTER
+ MOV R7,#1 ;BUMP DIVIDEND
+ ACALL LEFT
+ CJNE R2,#FP_ACC8+2,DIV4
+ ;
+ DJNZ FP_EXP,DIV8
+ AJMP UNDERFLOW_AND_EXIT
+ ;
+DIV8: MOV FP_CARRY,#0
+ ;
+ newpage
+ ;***************************************************************
+ ;
+PACK: ; Pack the mantissa
+ ;
+ ;***************************************************************
+ ;
+ ; First, set up the pointers
+ ;
+ MOV R0,#FP_ACCC
+ MOV A,@R0 ;GET FP_ACCC
+ MOV R6,A ;SAVE FOR ZERO COUNT
+ JZ PACK0 ;JUMP OVER IF ZERO
+ ACALL INC_FP_EXP ;BUMP THE EXPONENT
+ DEC R0
+ ;
+PACK0: INC R0 ;POINT AT FP_ACC1
+ ;
+PACK1: MOV A,#8 ;ADJUST NIBBLE POINTER
+ MOV R1,A
+ ADD A,R0
+ MOV R0,A
+ CJNE @R0,#5,$+3 ;SEE IF ADJUSTING NEEDED
+ JC PACK3+1
+ ;
+PACK2: SETB C
+ CLR A
+ DEC R0
+ ADDC A,@R0
+ DA A
+ XCHD A,@R0 ;SAVE THE VALUE
+ JNB ACC.4,PACK3
+ DJNZ R1,PACK2
+ ;
+ DEC R0
+ MOV @R0,#1
+ ACALL INC_FP_EXP
+ SJMP PACK4
+ ;
+PACK3: DEC R1
+ MOV A,R1
+ CLR C
+ XCH A,R0
+ SUBB A,R0
+ MOV R0,A
+ ;
+PACK4: MOV R1,#FP_DIG12
+ ;
+ ; Now, pack
+ ;
+PLOOP: MOV A,@R0
+ SWAP A ;FLIP THE DIGITS
+ INC R0
+ XCHD A,@R0
+ ORL 6,A ;ACCUMULATE THE OR'ED DIGITS
+ MOV @R1,A
+ INC R0
+ INC R1
+ CJNE R1,#FP_SIGN,PLOOP
+ MOV A,R6
+ JNZ STORE_ALIGN_TEST_AND_EXIT
+ MOV FP_EXP,#0 ;ZERO EXPONENT
+ ;
+ ;**************************************************************
+ ;
+STORE_ALIGN_TEST_AND_EXIT: ;Save the number align carry and exit
+ ;
+ ;**************************************************************
+ ;
+ ACALL LOAD_POINTERS
+ MOV ARG_STACK,R1 ;SET UP THE NEW STACK
+ MOV R0,#FP_EXP
+ ;
+ ; Now load the numbers
+ ;
+STORE2: MOV A,@R0
+ MOVX @R1,A ;SAVE THE NUMBER
+ DEC R0
+ DEC R1
+ CJNE R0,#FP_CARRY,STORE2
+ ;
+ CLR A ;NO ERRORS
+ ;
+PRET: RET ;EXIT
+ ;
+ newpage
+INC_FP_EXP:
+ ;
+ INC FP_EXP
+ MOV A,FP_EXP
+ JNZ PRET ;EXIT IF NOT ZERO
+ POP ACC ;WASTE THE CALLING STACK
+ POP ACC
+ AJMP OVERFLOW_AND_EXIT
+ ;
+;***********************************************************************
+;
+UNPACK_R0: ; Unpack BCD digits and load into nibble locations
+;
+;***********************************************************************
+ ;
+ PUSH R1B0
+ MOV R1,#FP_NIB8
+ ;
+ULOOP: MOVX A,@R0
+ ANL A,#0FH
+ MOV @R1,A ;SAVE THE NIBBLE
+ MOVX A,@R0
+ SWAP A
+ ANL A,#0FH
+ DEC R1
+ MOV @R1,A ;SAVE THE NIBBLE AGAIN
+ DEC R0
+ DEC R1
+ CJNE R1,#FP_NIB1-1,ULOOP
+ ;
+ POP R1B0
+ ;
+LOAD7: RET
+ ;
+ newpage
+ ;**************************************************************
+ ;
+OVERFLOW_AND_EXIT: ;LOAD 99999999 E+127, SET OV BIT, AND EXIT
+ ;
+ ;**************************************************************
+ ;
+ MOV R0,#FP_DIG78
+ MOV A,#99H
+ ;
+OVE1: MOV @R0,A
+ DEC R0
+ CJNE R0,#FP_CARRY,OVE1
+ ;
+ MOV FP_EXP,#0FFH
+ ACALL STORE_ALIGN_TEST_AND_EXIT
+ ;
+ SETB ACC_OVERFLOW ; ******AA
+ RET
+ ;
+ newpage
+ ;**************************************************************
+ ;
+UNDERFLOW_AND_EXIT: ;LOAD 0, SET UF BIT, AND EXIT
+ ;
+ ;**************************************************************
+ ;
+ ACALL ZERO_AND_EXIT
+ CLR A
+ SETB ACC_UNDERFLOW ; ******AA
+ RET
+ ;
+ ;**************************************************************
+ ;
+ZERO_AND_EXIT: ;LOAD 0, SET ZERO BIT, AND EXIT
+ ;
+ ;**************************************************************
+ ;
+ ACALL FP_CLEAR
+ ACALL STORE_ALIGN_TEST_AND_EXIT
+ SETB ACC_ZERO ; ******AA
+ RET ;EXIT
+ ;
+ ;**************************************************************
+ ;
+FP_CLEAR:
+ ;
+ ; Clear internal storage
+ ;
+ ;**************************************************************
+ ;
+ CLR A
+ MOV R0,#FP_ACC8+1
+ ;
+FPC1: MOV @R0,A
+ DEC R0
+ CJNE R0,#FP_TEMP,FPC1
+ RET
+ ;
+ newpage
+ ;**************************************************************
+ ;
+RIGHT: ; Shift ACCUMULATOR RIGHT the number of nibbles in R7
+ ; Save the shifted values in R4 if SAVE_ROUND is set
+ ;
+ ;**************************************************************
+ ;
+ MOV R4,#0 ;IN CASE OF NO SHIFT
+ ;
+RIGHT1: CLR C
+ MOV A,R7 ;GET THE DIGITS TO SHIFT
+ JZ RIGHT5-1 ;EXIT IF ZERO
+ SUBB A,#2 ;TWO TO DO?
+ JNC RIGHT5 ;SHIFT TWO NIBBLES
+ ;
+ ; Swap one nibble then exit
+ ;
+RIGHT3: PUSH R0B0 ;SAVE POINTER REGISTER
+ PUSH R1B0
+ ;
+ MOV R1,#FP_DIG78 ;LOAD THE POINTERS
+ MOV R0,#FP_DIG56
+ MOV A,R4 ;GET THE OVERFLOW REGISTER
+ XCHD A,@R1 ;GET DIGIT 8
+ SWAP A ;FLIP FOR LOAD
+ MOV R4,A
+ ;
+RIGHTL: MOV A,@R1 ;GET THE LOW ORDER BYTE
+ XCHD A,@R0 ;SWAP NIBBLES
+ SWAP A ;FLIP FOR STORE
+ MOV @R1,A ;SAVE THE DIGITS
+ DEC R0 ;BUMP THE POINTERS
+ DEC R1
+ CJNE R1,#FP_DIG12-1,RIGHTL ;LOOP
+ ;
+ MOV A,@R1 ;ACC = CH8
+ SWAP A ;ACC = 8CH
+ ANL A,#0FH ;ACC = 0CH
+ MOV @R1,A ;CARRY DONE
+ POP R1B0 ;EXIT
+ POP R0B0 ;RESTORE REGISTER
+ RET
+ ;
+RIGHT5: MOV R7,A ;SAVE THE NEW SHIFT NUMBER
+ CLR A
+ XCH A,FP_CARRY ;SWAP THE NIBBLES
+ XCH A,FP_DIG12
+ XCH A,FP_DIG34
+ XCH A,FP_DIG56
+ XCH A,FP_DIG78
+ MOV R4,A ;SAVE THE LAST DIGIT SHIFTED
+ SJMP RIGHT1+1
+ ;
+ newpage
+ ;***************************************************************
+ ;
+LEFT: ; Shift ACCUMULATOR LEFT the number of nibbles in R7
+ ;
+ ;***************************************************************
+ ;
+ MOV R4,#00H ;CLEAR FOR SOME ENTRYS
+ ;
+LEFT1: CLR C
+ MOV A,R7 ;GET SHIFT VALUE
+ JZ LEFT5-1 ;EXIT IF ZERO
+ SUBB A,#2 ;SEE HOW MANY BYTES TO SHIFT
+ JNC LEFT5
+ ;
+LEFT3: PUSH R0B0 ;SAVE POINTER
+ PUSH R1B0
+ MOV R0,#FP_CARRY
+ MOV R1,#FP_DIG12
+ ;
+ MOV A,@R0 ;ACC=CHCL
+ SWAP A ;ACC = CLCH
+ MOV @R0,A ;ACC = CLCH, @R0 = CLCH
+ ;
+LEFTL: MOV A,@R1 ;DIG 12
+ SWAP A ;DIG 21
+ XCHD A,@R0
+ MOV @R1,A ;SAVE IT
+ INC R0 ;BUMP POINTERS
+ INC R1
+ CJNE R0,#FP_DIG78,LEFTL
+ ;
+ MOV A,R4
+ SWAP A
+ XCHD A,@R0
+ ANL A,#0F0H
+ MOV R4,A
+ ;
+ POP R1B0
+ POP R0B0 ;RESTORE
+ RET ;DONE
+ ;
+LEFT5: MOV R7,A ;RESTORE COUNT
+ CLR A
+ XCH A,R4 ;GET THE RESTORATION BYTE
+ XCH A,FP_DIG78 ;DO THE SWAP
+ XCH A,FP_DIG56
+ XCH A,FP_DIG34
+ XCH A,FP_DIG12
+ XCH A,FP_CARRY
+ SJMP LEFT1+1
+ ;
+ newpage
+MUL_NIBBLE:
+ ;
+ ; Multiply the nibble in R7 by the FP_NIB locations
+ ; accumulate the product in FP_ACC
+ ;
+ ; Set up the pointers for multiplication
+ ;
+ ANL A,#0FH ;STRIP OFF MS NIBBLE
+ MOV R7,A
+ MOV R0,#FP_ACC8
+ MOV R1,#FP_NIB8
+ CLR A
+ MOV FP_ACCX,A
+ ;
+MNLOOP: DEC R0 ;BUMP POINTER TO PROPAGATE CARRY
+ ADD A,@R0 ;ATTEMPT TO FORCE CARRY
+ DA A ;BCD ADJUST
+ JNB ACC.4,MNL0 ;DON'T ADJUST IF NO NEED
+ DEC R0 ;PROPAGATE CARRY TO THE NEXT DIGIT
+ INC @R0 ;DO THE ADJUSTING
+ INC R0 ;RESTORE R0
+ ;
+MNL0: XCHD A,@R0 ;RESTORE INITIAL NUMBER
+ MOV B,R7 ;GET THE NUBBLE TO MULTIPLY
+ MOV A,@R1 ;GET THE OTHER NIBBLE
+ MUL AB ;DO THE MULTIPLY
+ MOV B,#10 ;NOW BCD ADJUST
+ DIV AB
+ XCH A,B ;GET THE REMAINDER
+ ADD A,@R0 ;PROPAGATE THE PARTIAL PRODUCTS
+ DA A ;BCD ADJUST
+ JNB ACC.4,MNL1 ;PROPAGATE PARTIAL PRODUCT CARRY
+ INC B
+ ;
+MNL1: INC R0
+ XCHD A,@R0 ;SAVE THE NEW PRODUCT
+ DEC R0
+ MOV A,B ;GET BACK THE QUOTIENT
+ DEC R1
+ CJNE R1,#FP_NIB1-1,MNLOOP
+ ;
+ ADD A,FP_ACCX ;GET THE OVERFLOW
+ DA A ;ADJUST
+ MOV @R0,A ;SAVE IT
+ RET ;EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+LOAD_POINTERS: ; Load the ARG_STACK into R0 and bump R1
+ ;
+ ;***************************************************************
+ ;
+ MOV P2,#ARG_STACK_PAGE
+ MOV R0,ARG_STACK
+ MOV A,#FP_NUMBER_SIZE
+ ADD A,R0
+ MOV R1,A
+ RET
+ ;
+ ;***************************************************************
+ ;
+MUL_DIV_EXP_AND_SIGN:
+ ;
+ ; Load the sign into R7, R6. R5 gets the sign for
+ ; multiply and divide.
+ ;
+ ;***************************************************************
+ ;
+ ACALL FP_CLEAR ;CLEAR INTERNAL MEMORY
+ ;
+MDES1: ACALL LOAD_POINTERS ;LOAD REGISTERS
+ MOVX A,@R0 ;ARG 1 EXP
+ MOV R7,A ;SAVED IN R7
+ MOVX A,@R1 ;ARG 2 EXP
+ MOV R6,A ;SAVED IN R6
+ DEC R0 ;BUMP POINTERS TO SIGN
+ DEC R1
+ MOVX A,@R0 ;GET THE SIGN
+ MOV R4,A ;SIGN OF ARG1
+ MOVX A,@R1 ;GET SIGN OF NEXT ARG
+ MOV R3,A ;SIGN OF ARG2
+ XRL A,R4 ;ACC GETS THE NEW SIGN
+ MOV R5,A ;R5 GETS THE NEW SIGN
+ ;
+ ; Bump the pointers to point at the LS digit
+ ;
+ DEC R0
+ DEC R1
+ ;
+ RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+LOADR1_MANTISSA:
+ ;
+ ; Load the mantissa of R0 into FP_Digits
+ ;
+ ;***************************************************************
+ ;
+ PUSH R0B0 ;SAVE REGISTER 1
+ MOV R0,#FP_DIG78 ;SET UP THE POINTER
+ ;
+LOADR1: MOVX A,@R1
+ MOV @R0,A
+ DEC R1
+ DEC R0
+ CJNE R0,#FP_CARRY,LOADR1
+ ;
+ POP R0B0
+ RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+HEXSCAN: ; Scan a string to determine if it is a hex number
+ ; set carry if hex, else carry = 0
+ ;
+ ;***************************************************************
+ ;
+ ACALL GET_DPTR_CHARACTER
+ PUSH DPH
+ PUSH DPL ;SAVE THE POINTER
+ ;
+HEXSC1: MOVX A,@DPTR ;GET THE CHARACTER
+ ACALL DIGIT_CHECK ;SEE IF A DIGIT
+ JC HS1 ;CONTINUE IF A DIGIT
+ ACALL HEX_CHECK ;SEE IF HEX
+ JC HS1
+ ;
+ CLR ACC.5 ;NO LOWER CASE
+ CJNE A,#'H',HEXDON
+ SETB C
+ SJMP HEXDO1 ;NUMBER IS VALID HEX, MAYBE
+ ;
+HEXDON: CLR C
+ ;
+HEXDO1: POP DPL ;RESTORE POINTER
+ POP DPH
+ RET
+ ;
+HS1: INC DPTR ;BUMP TO NEXT CHARACTER
+ SJMP HEXSC1 ;LOOP
+ ;
+HEX_CHECK: ;CHECK FOR A VALID ASCII HEX, SET CARRY IF FOUND
+ ;
+ CLR ACC.5 ;WASTE LOWER CASE
+ CJNE A,#'F'+1,$+3 ;SEE IF F OR LESS
+ JC HC1
+ RET
+ ;
+HC1: CJNE A,#'A',$+3 ;SEE IF A OR GREATER
+ CPL C
+ RET
+ ;
+ newpage
+ ;
+PUSHR2R0:
+ ;
+ MOV R3,#HI(CONVT) ;CONVERSION LOCATION
+ MOV R1,#LO(CONVT)
+ ACALL CONVERT_BINARY_TO_ASCII_STRING
+ MOV A,#0DH ;A CR TO TERMINATE
+ MOVX @R1,A ;SAVE THE CR
+ MOV DPTR,#CONVT
+ ;
+ ; Falls thru to FLOATING INPUT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+FLOATING_POINT_INPUT: ; Input a floating point number pointed to by
+ ; the DPTR
+ ;
+ ;***************************************************************
+ ;
+ ACALL FP_CLEAR ;CLEAR EVERYTHING
+ ACALL GET_DPTR_CHARACTER
+ ACALL PLUS_MINUS_TEST
+ MOV MSIGN,C ;SAVE THE MANTISSA SIGN
+ ;
+ ; Now, set up for input loop
+ ;
+ MOV R0,#FP_ACCC
+ MOV R6,#7FH ;BASE EXPONENT
+ SETB F0 ;SET INITIAL FLAG
+ ;
+INLOOP: ACALL GET_DIGIT_CHECK
+ JNC GTEST ;IF NOT A CHARACTER, WHAT IS IT?
+ ANL A,#0FH ;STRIP ASCII
+ ACALL STDIG ;STORE THE DIGITS
+ ;
+INLPIK: INC DPTR ;BUMP POINTER FOR LOOP
+ SJMP INLOOP ;LOOP FOR INPUT
+ ;
+GTEST: CJNE A,#'.',GT1 ;SEE IF A RADIX
+ JB FOUND_RADIX,INERR
+ SETB FOUND_RADIX
+ CJNE R0,#FP_ACCC,INLPIK
+ SETB FIRST_RADIX ;SET IF FIRST RADIX
+ SJMP INLPIK ;GET ADDITIONAL DIGITS
+ ;
+GT1: JB F0,INERR ;ERROR IF NOT CLEARED
+ CJNE A,#'e',$+5 ;CHECK FOR LOWER CASE
+ SJMP $+5
+ CJNE A,#'E',FINISH_UP
+ ACALL INC_AND_GET_DPTR_CHARACTER
+ ACALL PLUS_MINUS_TEST
+ MOV XSIGN,C ;SAVE SIGN STATUS
+ ACALL GET_DIGIT_CHECK
+ JNC INERR
+ ;
+ ANL A,#0FH ;STRIP ASCII BIAS OFF THE CHARACTER
+ MOV R5,A ;SAVE THE CHARACTER IN R5
+ ;
+GT2: INC DPTR
+ ACALL GET_DIGIT_CHECK
+ JNC FINISH1
+ ANL A,#0FH ;STRIP OFF BIAS
+ XCH A,R5 ;GET THE LAST DIGIT
+ MOV B,#10 ;MULTIPLY BY TEN
+ MUL AB
+ ADD A,R5 ;ADD TO ORIGINAL VALUE
+ MOV R5,A ;SAVE IN R5
+ JNC GT2 ;LOOP IF NO CARRY
+ MOV R5,#0FFH ;FORCE AN ERROR
+ ;
+FINISH1:MOV A,R5 ;GET THE SIGN
+ JNB XSIGN,POSNUM ;SEE IF EXPONENT IS POS OR NEG
+ CLR C
+ SUBB A,R6
+ CPL A
+ INC A
+ JC FINISH2
+ MOV A,#01H
+ RET
+ ;
+POSNUM: ADD A,R6 ;ADD TO EXPONENT
+ JNC FINISH2
+ ;
+POSNM1: MOV A,#02H
+ RET
+ ;
+FINISH2:XCH A,R6 ;SAVE THE EXPONENT
+ ;
+FINISH_UP:
+ ;
+ MOV FP_EXP,R6 ;SAVE EXPONENT
+ CJNE R0,#FP_ACCC,$+5
+ ACALL FP_CLEAR ;CLEAR THE MEMORY IF 0
+ MOV A,ARG_STACK ;GET THE ARG STACK
+ CLR C
+ SUBB A,#FP_NUMBER_SIZE+FP_NUMBER_SIZE
+ MOV ARG_STACK,A ;ADJUST FOR STORE
+ AJMP PACK
+ ;
+STDIG: CLR F0 ;CLEAR INITIAL DESIGNATOR
+ JNZ STDIG1 ;CONTINUE IF NOT ZERO
+ CJNE R0,#FP_ACCC,STDIG1
+ JNB FIRST_RADIX,RET_X
+ ;
+DECX: DJNZ R6,RET_X
+ ;
+INERR: MOV A,#0FFH
+ ;
+RET_X: RET
+ ;
+STDIG1: JB DONE_LOAD,FRTEST
+ CLR FIRST_RADIX
+ ;
+FRTEST: JB FIRST_RADIX,DECX
+ ;
+FDTEST: JB FOUND_RADIX,FDT1
+ INC R6
+ ;
+FDT1: JB DONE_LOAD,RET_X
+ CJNE R0,#FP_ACC8+1,FDT2
+ SETB DONE_LOAD
+ ;
+FDT2: MOV @R0,A ;SAVE THE STRIPPED ACCUMULATOR
+ INC R0 ;BUMP THE POINTER
+ RET ;EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; I/O utilities
+ ;
+ ;***************************************************************
+ ;
+INC_AND_GET_DPTR_CHARACTER:
+ ;
+ INC DPTR
+ ;
+GET_DPTR_CHARACTER:
+ ;
+ MOVX A,@DPTR ;GET THE CHARACTER
+ CJNE A,#' ',PMT1 ;SEE IF A SPACE
+ ;
+ ; Kill spaces
+ ;
+ SJMP INC_AND_GET_DPTR_CHARACTER
+ ;
+PLUS_MINUS_TEST:
+ ;
+ CJNE A,#0E3H,$+5 ;SEE IF A PLUS, PLUS TOKEN FROM BASIC
+ SJMP PMT3
+ CJNE A,#'+',$+5
+ SJMP PMT3
+ CJNE A,#0E5H,$+5 ;SEE IF MINUS, MINUS TOKEN FROM BASIC
+ SJMP PMT2
+ CJNE A,#'-',PMT1
+ ;
+PMT2: SETB C
+ ;
+PMT3: INC DPTR
+ ;
+PMT1: RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+FLOATING_POINT_OUTPUT: ; Output the number, format is in location 23
+ ;
+ ; IF FORMAT = 00 - FREE FLOATING
+ ; = FX - EXPONENTIAL (X IS THE NUMBER OF SIG DIGITS)
+ ; = NX - N = NUM BEFORE RADIX, X = NUM AFTER RADIX
+ ; N + X = 8 MAX
+ ;
+ ;***************************************************************
+ ;
+ ACALL MDES1 ;GET THE NUMBER TO OUTPUT, R0 IS POINTER
+ ACALL POP_AND_EXIT ;OUTPUT POPS THE STACK
+ MOV A,R7
+ MOV R6,A ;PUT THE EXPONENT IN R6
+ ACALL UNPACK_R0 ;UNPACK THE NUMBER
+ MOV R0,#FP_NIB1 ;POINT AT THE NUMBER
+ MOV A,FORMAT ;GET THE FORMAT
+ MOV R3,A ;SAVE IN CASE OF EXP FORMAT
+ JZ FREE ;FREE FLOATING?
+ CJNE A,#0F0H,$+3 ;SEE IF EXPONENTIAL
+ JNC EXPOUT
+ ;
+ ; If here, must be integer USING format
+ ;
+ MOV A,R6 ;GET THE EXPONENT
+ JNZ $+4
+ MOV R6,#80H
+ MOV A,R3 ;GET THE FORMAT
+ SWAP A ;SPLIT INTEGER AND FRACTION
+ ANL A,#0FH
+ MOV R2,A ;SAVE INTEGER
+ ACALL NUM_LT ;GET THE NUMBER OF INTEGERS
+ XCH A,R2 ;FLIP FOR SUBB
+ CLR C
+ SUBB A,R2
+ MOV R7,A
+ JNC $+8
+ MOV R5,#'?' ;OUTPUT A QUESTION MARK
+ ACALL SOUT1 ;NUMBER IS TOO LARGE FOR FORMAT
+ AJMP FREE
+ CJNE R2,#00,USING0 ;SEE IF ZERO
+ DEC R7
+ ACALL SS7
+ ACALL ZOUT ;OUTPUT A ZERO
+ SJMP USING1
+ ;
+USING0: ACALL SS7 ;OUTPUT SPACES, IF NEED TO
+ MOV A,R2 ;OUTPUT DIGITS
+ MOV R7,A
+ ACALL OUTR0
+ ;
+USING1: MOV A,R3
+ ANL A,#0FH ;GET THE NUMBER RIGHT OF DP
+ MOV R2,A ;SAVE IT
+ JZ PMT1 ;EXIT IF ZERO
+ ACALL ROUT ;OUTPUT DP
+ ACALL NUM_RT
+ CJNE A,2,USINGX ;COMPARE A TO R2
+ ;
+USINGY: MOV A,R2
+ AJMP Z7R7
+ ;
+USINGX: JNC USINGY
+ ;
+USING2: XCH A,R2
+ CLR C
+ SUBB A,R2
+ XCH A,R2
+ ACALL Z7R7 ;OUTPUT ZEROS IF NEED TO
+ MOV A,R2
+ MOV R7,A
+ AJMP OUTR0
+ ;
+ ; First, force exponential output, if need to
+ ;
+FREE: MOV A,R6 ;GET THE EXPONENT
+ JNZ FREE1 ;IF ZERO, PRINT IT
+ ACALL SOUT
+ AJMP ZOUT
+ ;
+FREE1: MOV R3,#0F0H ;IN CASE EXP NEEDED
+ MOV A,#80H-DIGIT-DIGIT-1
+ ADD A,R6
+ JC EXPOUT
+ SUBB A,#0F7H
+ JC EXPOUT
+ ;
+ ; Now, just print the number
+ ;
+ ACALL SINOUT ;PRINT THE SIGN OF THE NUMBER
+ ACALL NUM_LT ;GET THE NUMBER LEFT OF DP
+ CJNE A,#8,FREE4
+ AJMP OUTR0
+ ;
+FREE4: ACALL OUTR0
+ ACALL ZTEST ;TEST FOR TRAILING ZEROS
+ JZ U_RET ;DONE IF ALL TRAILING ZEROS
+ ACALL ROUT ;OUTPUT RADIX
+ ;
+FREE2: MOV R7,#1 ;OUTPUT ONE DIGIT
+ ACALL OUTR0
+ JNZ U_RET
+ ACALL ZTEST
+ JZ U_RET
+ SJMP FREE2 ;LOOP
+ ;
+EXPOUT: ACALL SINOUT ;PRINT THE SIGN
+ MOV R7,#1 ;OUTPUT ONE CHARACTER
+ ACALL OUTR0
+ ACALL ROUT ;OUTPUT RADIX
+ MOV A,R3 ;GET FORMAT
+ ANL A,#0FH ;STRIP INDICATOR
+ JZ EXPOTX
+ ;
+ MOV R7,A ;OUTPUT THE NUMBER OF DIGITS
+ DEC R7 ;ADJUST BECAUSE ONE CHAR ALREADY OUT
+ ACALL OUTR0
+ SJMP EXPOT4
+ ;
+EXPOTX: ACALL FREE2 ;OUTPUT UNTIL TRAILING ZEROS
+ ;
+EXPOT4: ACALL SOUT ;OUTPUT A SPACE
+ MOV R5,#'E'
+ ACALL SOUT1 ;OUTPUT AN E
+ MOV A,R6 ;GET THE EXPONENT
+ JZ XOUT0 ;EXIT IF ZERO
+ DEC A ;ADJUST FOR THE DIGIT ALREADY OUTPUT
+ CJNE A,#80H,XOUT2 ;SEE WHAT IT IS
+ ;
+XOUT0: ACALL SOUT
+ CLR A
+ SJMP XOUT4
+ ;
+XOUT2: JC XOUT3 ;NEGATIVE EXPONENT
+ MOV R5,#'+' ;OUTPUT A PLUS SIGN
+ ACALL SOUT1
+ SJMP XOUT4
+ ;
+XOUT3: ACALL MOUT
+ CPL A ;FLIP BITS
+ INC A ;BUMP
+ ;
+XOUT4: CLR ACC.7
+ MOV R0,A
+ MOV R2,#0
+ MOV R1,#LO(CONVT) ;CONVERSION LOCATION
+ MOV R3,#HI(CONVT)
+ ACALL CONVERT_BINARY_TO_ASCII_STRING
+ MOV R0,#LO(CONVT) ;NOW, OUTPUT EXPONENT
+ ;
+EXPOT5: MOVX A,@R0 ;GET THE CHARACTER
+ MOV R5,A ;OUTPUT IT
+ ACALL SOUT1
+ INC R0 ;BUMP THE POINTER
+ MOV A,R0 ;GET THE POINTER
+ CJNE A,R1B0,EXPOT5 ;LOOP
+ ;
+U_RET: RET ;EXIT
+ ;
+OUTR0: ; Output the characters pointed to by R0, also bias ascii
+ ;
+ MOV A,R7 ;GET THE COUNTER
+ JZ OUTR ;EXIT IF DONE
+ MOV A,@R0 ;GET THE NUMBER
+ ORL A,#30H ;ASCII BIAS
+ INC R0 ;BUMP POINTER AND COUNTER
+ DEC R7
+ MOV R5,A ;PUT CHARACTER IN OUTPUT REGISTER
+ ACALL SOUT1 ;OUTPUT THE CHARACTER
+ CLR A ;JUST FOR TEST
+ CJNE R0,#FP_NIB8+1,OUTR0
+ MOV A,#55H ;KNOW WHERE EXIT OCCURED
+ ;
+OUTR: RET
+ ;
+ZTEST: MOV R1,R0B0 ;GET POINTER REGISTER
+ ;
+ZT0: MOV A,@R1 ;GET THE VALUE
+ JNZ ZT1
+ INC R1 ;BUMP POINTER
+ CJNE R1,#FP_NIB8+1,ZT0
+ ;
+ZT1: RET
+ ;
+NUM_LT: MOV A,R6 ;GET EXPONENT
+ CLR C ;GET READY FOR SUBB
+ SUBB A,#80H ;SUB EXPONENT BIAS
+ JNC NL1 ;OK IF NO CARRY
+ CLR A ;NO DIGITS LEFT
+ ;
+NL1: MOV R7,A ;SAVE THE COUNT
+ RET
+ ;
+NUM_RT: CLR C ;SUBB AGAIN
+ MOV A,#80H ;EXPONENT BIAS
+ SUBB A,R6 ;GET THE BIASED EXPONENT
+ JNC NR1
+ CLR A
+ ;
+NR1: RET ;EXIT
+ ;
+SPACE7: MOV A,R7 ;GET THE NUMBER OF SPACES
+ JZ NR1 ;EXIT IF ZERO
+ ACALL SOUT ;OUTPUT A SPACE
+ DEC R7 ;BUMP COUNTER
+ SJMP SPACE7 ;LOOP
+ ;
+Z7R7: MOV R7,A
+ ;
+ZERO7: MOV A,R7 ;GET COUNTER
+ JZ NR1 ;EXIT IF ZERO
+ ACALL ZOUT ;OUTPUT A ZERO
+ DEC R7 ;BUMP COUNTER
+ SJMP ZERO7 ;LOOP
+ ;
+SS7: ACALL SPACE7
+ ;
+SINOUT: MOV A,R4 ;GET THE SIGN
+ JZ SOUT ;OUTPUT A SPACE IF ZERO
+ ;
+MOUT: MOV R5,#'-'
+ SJMP SOUT1 ;OUTPUT A MINUS IF NOT
+ ;
+ROUT: MOV R5,#'.' ;OUTPUT A RADIX
+ SJMP SOUT1
+ ;
+ZOUT: MOV R5,#'0' ;OUTPUT A ZERO
+ SJMP SOUT1
+ ;
+SOUT: MOV R5,#' ' ;OUTPUT A SPACE
+ ;
+SOUT1: AJMP OUTPUT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+CONVERT_ASCII_STRING_TO_BINARY:
+ ;
+ ;DPTR POINTS TO ASCII STRING
+ ;PUT THE BINARY NUMBER IN R2:R0, ERROR IF >64K
+ ;
+ ;***************************************************************
+ ;
+CASB: ACALL HEXSCAN ;SEE IF HEX NUMBER
+ MOV ADD_IN,C ;IF ADD_IN IS SET, THE NUMBER IS HEX
+ ACALL GET_DIGIT_CHECK
+ CPL C ;FLIP FOR EXIT
+ JC RCASB
+ MOV R3,#00H ;ZERO R3:R1 FOR LOOP
+ MOV R1,#00H
+ SJMP CASB5
+ ;
+CASB2: INC DPTR
+ MOV R0B0,R1 ;SAVE THE PRESENT CONVERTED VALUE
+ MOV R0B0+2,R3 ;IN R2:R0
+ ACALL GET_DIGIT_CHECK
+ JC CASB5
+ JNB ADD_IN,RCASB ;CONVERSION COMPLETE
+ ACALL HEX_CHECK ;SEE IF HEX NUMBER
+ JC CASB4 ;PROCEED IF GOOD
+ INC DPTR ;BUMP PAST H
+ SJMP RCASB
+ ;
+CASB4: ADD A,#9 ;ADJUST HEX ASCII BIAS
+ ;
+CASB5: MOV B,#10
+ JNB ADD_IN,CASB6
+ MOV B,#16 ;HEX MODE
+ ;
+CASB6: ACALL MULNUM ;ACCUMULATE THE DIGITS
+ JNC CASB2 ;LOOP IF NO CARRY
+ ;
+RCASB: CLR A ;RESET ACC
+ MOV ACC_OVERFLOW,C ;IF OVERFLOW, SAY SO ******AA
+ RET ;EXIT
+ ;
+ newpage
+ ;
+MULNUM10:MOV B,#10
+ ;
+ ;***************************************************************
+ ;
+MULNUM: ; Take the next digit in the acc (masked to 0FH)
+ ; accumulate in R3:R1
+ ;
+ ;***************************************************************
+ ;
+ PUSH ACC ;SAVE ACC
+ PUSH B ;SAVE MULTIPLIER
+ MOV A,R1 ;PUT LOW ORDER BITS IN ACC
+ MUL AB ;DO THE MULTIPLY
+ MOV R1,A ;PUT THE RESULT BACK
+ MOV A,R3 ;GET THE HIGH ORDER BYTE
+ MOV R3,B ;SAVE THE OVERFLOW
+ POP B ;GET THE MULTIPLIER
+ MUL AB ;DO IT
+ MOV C,OV ;SAVE OVERFLOW IN F0
+ MOV F0,C
+ ADD A,R3 ;ADD OVERFLOW TO HIGH RESULT
+ MOV R3,A ;PUT IT BACK
+ POP ACC ;GET THE ORIGINAL ACC BACK
+ ORL C,F0 ;OR CARRY AND OVERFLOW
+ JC MULX ;NO GOOD IF THE CARRY IS SET
+ ;
+MUL11: ANL A,#0FH ;MASK OFF HIGH ORDER BITS
+ ADD A,R1 ;NOW ADD THE ACC
+ MOV R1,A ;PUT IT BACK
+ CLR A ;PROPAGATE THE CARRY
+ ADDC A,R3
+ MOV R3,A ;PUT IT BACK
+ ;
+MULX: RET ;EXIT WITH OR WITHOUT CARRY
+ ;
+ ;***************************************************************
+ ;
+CONVERT_BINARY_TO_ASCII_STRING:
+ ;
+ ;R3:R1 contains the address of the string
+ ;R2:R0 contains the value to convert
+ ;DPTR, R7, R6, and ACC gets clobbered
+ ;
+ ;***************************************************************
+ ;
+ CLR A ;NO LEADING ZEROS
+ MOV DPTR,#10000 ;SUBTRACT 10000
+ ACALL RSUB ;DO THE SUBTRACTION
+ MOV DPTR,#1000 ;NOW 1000
+ ACALL RSUB
+ MOV DPTR,#100 ;NOW 100
+ ACALL RSUB
+ MOV DPTR,#10 ;NOW 10
+ ACALL RSUB
+ MOV DPTR,#1 ;NOW 1
+ ACALL RSUB
+ JZ RSUB2 ;JUMP OVER RET
+ ;
+RSUB_R: RET
+ ;
+RSUB: MOV R6,#-1 ;SET UP THE COUNTER
+ ;
+RSUB1: INC R6 ;BUMP THE COUNTER
+ XCH A,R2 ;DO A FAST COMPARE
+ CJNE A,DPH,$+3
+ XCH A,R2
+ JC FAST_DONE
+ XCH A,R0 ;GET LOW BYTE
+ SUBB A,DPL ;SUBTRACT, CARRY IS CLEARED
+ XCH A,R0 ;PUT IT BACK
+ XCH A,R2 ;GET THE HIGH BYTE
+ SUBB A,DPH ;ADD THE HIGH BYTE
+ XCH A,R2 ;PUT IT BACK
+ JNC RSUB1 ;LOOP UNTIL CARRY
+ ;
+ XCH A,R0
+ ADD A,DPL ;RESTORE R2:R0
+ XCH A,R0
+ XCH A,R2
+ ADDC A,DPH
+ XCH A,R2
+ ;
+FAST_DONE:
+ ;
+ ORL A,R6 ;OR THE COUNT VALUE
+ JZ RSUB_R ;RETURN IF ZERO
+ ;
+RSUB2: MOV A,#'0' ;GET THE ASCII BIAS
+ ADD A,R6 ;ADD THE COUNT
+ ;
+RSUB4: MOV P2,R3 ;SET UP P2
+ MOVX @R1,A ;PLACE THE VALUE IN MEMORY
+ INC R1
+ CJNE R1,#00H,RSUB3 ;SEE IF RAPPED AROUND
+ INC R3 ;BUMP HIGH BYTE
+ ;
+RSUB3: RET ;EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+HEXOUT: ; Output the hex number in R3:R1, supress leading zeros, if set
+ ;
+ ;***************************************************************
+ ;
+ ACALL SOUT ;OUTPUT A SPACE
+ MOV C,ZSURP ;GET ZERO SUPPRESSION BIT
+ MOV ADD_IN,C
+ MOV A,R3 ;GET HIGH NIBBLE AND PRINT IT
+ ACALL HOUTHI
+ MOV A,R3
+ ACALL HOUTLO
+ ;
+HEX2X: CLR ADD_IN ;DON'T SUPPRESS ZEROS
+ MOV A,R1 ;GET LOW NIBBLE AND PRINT IT
+ ACALL HOUTHI
+ MOV A,R1
+ ACALL HOUTLO
+ MOV R5,#'H' ;OUTPUT H TO INDICATE HEX MODE
+ ;
+SOUT_1: AJMP SOUT1
+ ;
+HOUT1: CLR ADD_IN ;PRINTED SOMETHING, SO CLEAR ADD_IN
+ ADD A,#90H ;CONVERT TO ASCII
+ DA A
+ ADDC A,#40H
+ DA A ;GOT IT HERE
+ MOV R5,A ;OUTPUT THE BYTE
+ SJMP SOUT_1
+ ;
+HOUTHI: SWAP A ;SWAP TO OUTPUT HIGH NIBBLE
+ ;
+HOUTLO: ANL A,#0FH ;STRIP
+ JNZ HOUT1 ;PRINT IF NOT ZERO
+ JNB ADD_IN,HOUT1 ;OUTPUT A ZERO IF NOT SUPRESSED
+ RET
+ ;
+ newpage
+ ORG 1FEBH ;FOR LINK COMPATABILITY
+ ;
+ ;
+GET_DIGIT_CHECK: ; Get a character, then check for digit
+ ;
+ ACALL GET_DPTR_CHARACTER
+ ;
+DIGIT_CHECK: ;CHECK FOR A VALID ASCII DIGIT, SET CARRY IF FOUND
+ ;
+ CJNE A,#'9'+1,$+3 ;SEE IF ASCII 9 OR LESS
+ JC DC1
+ RET
+ ;
+DC1: CJNE A,#'0',$+3 ;SEE IF ASCII 0 OR GREATER
+ CPL C
+ RET
+
+ endsection
diff --git a/tests/t_bas52/bas52.out b/tests/t_bas52/bas52.out
new file mode 100644
index 0000000..b6a0f80
--- /dev/null
+++ b/tests/t_bas52/bas52.out
@@ -0,0 +1,75 @@
+ ;***************************************************************
+ ;
+ ; TEROT - Output a character to the system console
+ ; update PHEAD position.
+ ;
+ ;***************************************************************
+ ;
+STEROT: MOV R5,#' ' ;OUTPUT A SPACE
+ ;
+TEROT: PUSH ACC ;SAVE THE ACCUMULATOR
+ PUSH DPH ;SAVE THE DPTR
+ PUSH DPL
+ JNB CNT_S,$+7 ;WAIT FOR A CONTROL Q
+ ACALL BCK ;GET SERIAL STATUS
+ SJMP $-5
+ MOV A,R5 ;PUT OUTPUT BYTE IN A
+ JNB BO,$+8 ;CHECK FOR MONITOR
+ LCALL 2040H ;DO THE MONITOR
+ AJMP TEROT1 ;CLEAN UP
+ JNB COUB,$+8 ;SEE IF USER WANTS OUTPUT
+ LCALL 4030H
+ AJMP TEROT1
+ JNB UPB,T_1 ;NO AT IF NO XBIT
+ JNB LPB,T_1 ;AT PRINT
+ LCALL 403CH ;CALL AT LOCATION
+ AJMP TEROT1 ;FINISH OFF OUTPUT
+ ;
+T_1: JNB COB,TXX ;SEE IF LIST SET
+ MOV DPTR,#SPV ;LOAD BAUD RATE
+ ACALL LD_T
+ CLR LP ;OUTPUT START BIT
+ ACALL TIMER_LOAD ;LOAD AND START THE TIMER
+ MOV A,R5 ;GET THE OUTPUT BYTE
+ SETB C ;SET CARRY FOR LAST OUTPUT
+ MOV R5,#9 ;LOAD TIMER COUNTDOWN
+ ;
+LTOUT1: RRC A ;ROTATE A
+ JNB TF1,$ ;WAIT TILL TIMER READY
+ MOV LP,C ;OUTPUT THE BIT
+ ACALL TIMER_LOAD ;DO THE NEXT BIT
+ DJNZ R5,LTOUT1 ;LOOP UNTIL DONE
+ JNB TF1,$ ;FIRST STOP BIT
+ ACALL TIMER_LOAD
+ JNB TF1,$ ;SECOND STOP BIT
+ MOV R5,A ;RESTORE R5
+ SJMP TEROT1 ;BACK TO TEROT
+ ;
+ newpage
+TXX: JNB TI,$ ;WAIT FOR TRANSMIT READY
+ CLR TI
+ MOV SBUF,R5 ;SEND OUT THE CHARACTER
+ ;
+TEROT1: CJNE R5,#CR,$+6 ;SEE IF A CR
+ MOV PHEAD,#00H ;IF A CR, RESET PHEAD AND
+ ;
+ CJNE R5,#LF,NLC ;SEE IF A LF
+ MOV A,NULLCT ;GET THE NULL COUNT
+ JZ NLC ;NO NULLS IF ZERO
+ ;
+TEROT2: MOV R5,#NULL ;PUT THE NULL IN THE OUTPUT REGISTER
+ ACALL TEROT ;OUTPUT THE NULL
+ DEC A ;DECREMENT NULL COUNT
+ JNZ TEROT2 ;LOOP UNTIL DONE
+ ;
+NLC: CJNE R5,#BS,$+5 ;DEC PHEAD IF A BACKSPACE
+ DEC PHEAD
+ CJNE R5,#20H,$+3 ;IS IT A PRINTABLE CHARACTER?
+ JC $+4 ;DON'T INCREMENT PHEAD IF NOT PRINTABLE
+ INC PHEAD ;BUMP PRINT HEAD
+ POP DPL ;RESTORE DPTR
+ POP DPH
+ POP ACC ;RESTORE ACC
+ RET ;EXIT
+ ;
+
diff --git a/tests/t_bas52/bas52.pgm b/tests/t_bas52/bas52.pgm
new file mode 100644
index 0000000..080d43f
--- /dev/null
+++ b/tests/t_bas52/bas52.pgm
@@ -0,0 +1,125 @@
+
+PG8: MOV R7,#00H ;PROGRAM ONE BYTE AT A TIME
+ MOV R6,#01H
+ MOV R2,#HI(ROMADR-1)
+ MOV R0,#LO(ROMADR-1);LOAD PROM ADDRESS
+ ACALL PG1+3
+ INC R6
+ DB 0E5H ;MOV A DIRECT OP CODE
+ DB 0CBH ;ADDRESS OF R2CAP HIGH
+ ACALL PG1+3
+ DB 0E5H ;MOV A, DIRECT OP CODE
+ DB 0CAH ;R2CAP LOW
+ MOV R6,#3
+ MOV R1,#LO(MEMTOP-1)
+ MOV R3,#HI(MEMTOP)
+ ACALL PG1+3 ;SAVE MEMTOP
+ SJMP PGR
+ ;
+CIPROG: MOV DPTR,#IPROGS ;LOAD IPROG LOCATION
+ SETB INTELB
+ SJMP $+7 ;GO DO PROG
+ ;
+CPROG: MOV DPTR,#PROGS ;LOAD PROG LOCATION
+ CLR INTELB
+ ;
+ ACALL LD_T ;LOAD THE TIMER
+ CLR PROMV ;TURN ON THE PROM VOLTAGE
+ LCALL DELTST ;SEE IF A CR ******AA CALL-->LCALL
+ JNZ PG8 ;SAVE TIMER IF SO
+ MOV R4,#0FEH
+ SETB INBIT
+ ACALL ROMFD ;GET THE ROM ADDRESS OF THE LAST LOCATION
+ LCALL TEMPD ;SAVE THE ADDRESS ******AA CALL-->LCALL
+ MOV A,R4 ;GET COUNT
+ CPL A
+ LCALL TWO_R2 ;PUT IT ON THE STACK ******AA CALL-->LCALL
+ CALL FP_BASE+14 ;OUTPUT IT
+ ACALL CCAL ;GET THE PROGRAM
+ ACALL CRLF ;DO CRLF
+ MOV R0,TEMP4 ;GET ADDRESS
+ MOV R2,TEMP5
+ MOV A,#55H ;LOAD SIGNIFIER
+ INC R6 ;LOAD LEN + 1
+ CJNE R6,#00,$+4
+ INC R7
+ ACALL PG2-2
+ ;
+ newpage
+PGR: SETB PROMV
+ AJMP C_K
+ ;
+PG1: MOV P2,R3 ;GET THE BYTE TO PROGRAM
+ MOVX A,@R1
+ LCALL INC3210 ;BUMP POINTERS
+ MOV R5,#1 ;SET UP INTELLIGENT COUMTER
+ ;
+PG2: MOV R4,A ;SAVE THE BYTE IN R4
+ ACALL PG7 ;PROGRAM THE BYTE
+ ACALL PG9
+ JB INTELB,PG4 ;SEE IF INTELLIGENT PROGRAMMING
+ ;
+PG3: XRL A,R4
+ JNZ PG6 ;ERROR IF NOT THE SAME
+ LCALL DEC76 ;BUMP THE COUNTERS ******AA CALL-->LCALL
+ JNZ PG1 ;LOOP IF NOT DONE
+ ANL PSW,#11100111B ;INSURE RB0
+ RET
+ ;
+PG4: XRL A,R4 ;SEE IF PROGRAMMED
+ JNZ PG5 ;JUMP IF NOT
+ MOV A,R4 ;GET THE DATA BACK
+ ACALL PG7 ;PROGRAM THE LOCATION
+ ACALL ZRO ;AGAIN
+ ACALL ZRO ;AND AGAIN
+ ACALL ZRO ;AND AGAIN
+ DJNZ R5,$-6 ;KEEP DOING IT
+ ACALL PG9 ;RESET PROG
+ SJMP PG3 ;FINISH THE LOOP
+ ;
+PG5: INC R5 ;BUMP THE COUNTER
+ MOV A,R4 ;GET THE BYTE
+ CJNE R5,#25,PG2 ;SEE IF TRIED 25 TIMES
+ ;
+PG6: SETB PROMV ;TURN OFF PROM VOLTAGE
+ MOV PSW,#0 ;INSURE RB0
+ JNB DIRF,PG4-1 ;EXIT IF IN RUN MODE
+ MOV DPTR,#E16X ;PROGRAMMING ERROR
+ ;
+ERRLK: LJMP ERROR ;PROCESS THE ERROR
+ ;
+ newpage
+PG7: MOV P0,R0 ;SET UP THE PORTS
+ MOV P2,R2 ;LATCH LOW ORDER ADDRESS
+ ACALL PG11 ;DELAY FOR 8748/9
+ CLR ALED
+ MOV P0,A ;PUT DATA ON THE PORT
+ ;
+ZRO: NOP ;SETTLEING TIME + FP ZERO
+ NOP
+ NOP
+ NOP
+ NOP
+ NOP
+ ACALL PG11 ;DELAY A WHILE
+ CLR PROMP ;START PROGRAMMING
+ ACALL TIMER_LOAD ;START THE TIMER
+ JNB TF1,$ ;WAIT FOR PART TO PROGRAM
+ RET ;EXIT
+ ;
+PG9: SETB PROMP
+ ACALL PG11 ;DELAY FOR A WHILE
+ JNB P3.2,$ ;LOOP FOR EEPROMS
+ MOV P0,#0FFH
+ CLR P3.7 ;LOWER READ
+ ACALL PG11
+ MOV A,P0 ;READ THE PORT
+ SETB P3.7
+ SETB ALED
+ RET
+ ;
+PG11: MOV TEMP5,#12 ;DELAY 30uS AT 12 MHZ
+ DJNZ TEMP5,$
+ RET
+ ;
+
diff --git a/tests/t_bas52/bas52.pwm b/tests/t_bas52/bas52.pwm
new file mode 100644
index 0000000..44ac409
--- /dev/null
+++ b/tests/t_bas52/bas52.pwm
@@ -0,0 +1,25 @@
+ ;**************************************************************
+ ;
+STONE: ; Toggle the I/O port
+ ;
+ ;**************************************************************
+ ;
+ CALL THREE ;GET THE NUMBERS
+ ACALL CBIAS ;BIAS R3:R1 FOR COUNT LOOP
+ ;
+STONE1: CLR T_BIT ;TOGGLE THE BIT
+ CLR TR1 ;STOP THE TIMER
+ MOV TH1,R3 ;LOAD THE TIMER
+ MOV TL1,R1
+ CLR TF1 ;CLEAR THE OVERFLOW FLAG
+ SETB TR1 ;TURN IT ON
+ ACALL DEC76
+ JNB TF1,$ ;WAIT
+ ACALL ALPAR
+ SETB T_BIT ;BACK TO A ONE
+ CALL TIMER_LOAD+2 ;LOAD THE HIGH VALUE
+ JNB TF1,$ ;WAIT
+ JNZ STONE1 ;LOOP
+ RET
+ ;
+
diff --git a/tests/t_bas52/bas52.rst b/tests/t_bas52/bas52.rst
new file mode 100644
index 0000000..2d2f13a
--- /dev/null
+++ b/tests/t_bas52/bas52.rst
@@ -0,0 +1,111 @@
+
+ ;**************************************************************
+ ;
+CRST: ; This performs system initialzation, it was moved here so the
+ ; new power on reset functions could be tested in an 8751.
+ ;
+ ;**************************************************************
+ ;
+ ; First, initialize SFR's
+ ;
+ MOV SCON,#5AH ;INITIALIZE SFR'S
+ MOV TMOD,#10H
+ MOV TCON,#54H
+ DB 75H ;MOV DIRECT, # OP CODE
+ DB 0C8H ;T2CON LOCATION
+ DB 34H ;CONFIGURATION BYTE
+ ;
+ MOV DPTR,#2001H ;READ CODE AT 2001H
+ CLR A
+ MOVC A,@A+DPTR
+ CJNE A,#0AAH,$+6 ;IF IT IS AN AAH, DO USER RESET
+ LCALL 2090H
+ ;
+ MOV R0,#IRAMTOP ;PUT THE TOP OF RAM IN R0
+ CLR A ;ZERO THE ACC
+ ;
+ MOV @R0,A ;CLEAR INTERNAL MEMORY
+ DJNZ R0,$-1 ;LOOP TIL DONE
+ ;
+ ; Now, test the external memory
+ ;
+ MOV SPSAV,#CMNDSP ;SET UP THE STACK
+ MOV SP,SPSAV
+ ;
+ MOV BOFAH,#HI(ROMADR)
+ MOV BOFAL,#LO(ROMADR+17)
+ MOV DPTR,#ROMADR ;GET THE BYTE AT 8000H
+ MOVX A,@DPTR
+ CLR C
+ SUBB A,#31H ;FOR BIAS
+ MOV MT1,A ;SAVE IN DIRECT MATH LOC
+ CLR ACC.2 ;SAVE FOR RESET
+ MOV R7,A ;SAVE IT IN R7
+ INC DPTR
+ ACALL L31DPI ;SAVE BAUD RATE
+ LCALL RCL
+ INC DPTR ;GET MEMTOP
+ ACALL L31DPI
+ MOV DPTR,#5FH ;READ THE EXTERNAL BYTE
+ MOVX A,@DPTR
+ MOV DPTR,#0 ;ESTABLISH BASE FOR CLEAR
+ CJNE A,#0A5H,CRS
+ MOV A,MT1
+ CLR ACC.0 ;CLEAR BIT ONE
+ XRL A,#4H
+ JZ CR2
+ ;
+CRS: CJNE R7,#2,$+5
+ SJMP $+5
+ CJNE R7,#3,$+7
+ ACALL CL_1
+ SJMP CR1
+ ;
+CR0: MOV R3,DPH ;SAVE THE DPTR
+ MOV R1,DPL
+ INC DPTR
+ MOV A,#5AH
+ MOVX @DPTR,A
+ MOVX A,@DPTR
+ CJNE A,#5AH,CR1
+ CLR A
+ MOVX @DPTR,A
+ CJNE R3,#0E0H,CR0
+ ;
+CR1: CJNE R3,#03H,$+3 ;NEED THIS MUCH RAM
+ JC CRST
+ MOV DPTR,#MEMTOP ;SAVE MEMTOP
+ ACALL S31DP2 ;SAVE MEMTOP AND SEED RCELL
+ ACALL CNEW ;CLEAR THE MEMORY AND SET UP POINTERS
+ ;
+CR2: ACALL RC1 ;SET UP STACKS IF NOT DONE
+ ;
+ LCALL AXTAL0 ;DO THE CRYSTAL
+ MOV A,MT1 ;GET THE RESET BYTE
+ CJNE A,#5,$+6
+ LCALL 4039H
+ JNC BG1 ;CHECK FOR 0,1,2,3, OR 4
+ JNB ACC.0,BG3 ;NO RUN IF WRONG TYPE
+ MOV DPTR,#ROMADR+16
+ MOVX A,@DPTR ;READ THE BYTE
+ CJNE A,#55H,BG3
+ LJMP CRUN
+ ;
+BG1: CLR A ;DO BAUD RATE
+ MOV R3,A
+ MOV R1,A
+ MOV R0,#4
+ JB RXD,$ ;LOOP UNTIL A CHARACTER IS RECEIVED
+ ;
+BG2: DJNZ R0,$ ;FOUR CLOCKS, IN LOOP
+ LCALL DEC3210+4 ;NINE CLOCKS ******AA CALL-->LCALL
+ MOV R0,#2 ;ONE CLOCK
+ JNB RXD,BG2 ;TWO CLOCKS, LOOP UNTIL DONE
+ JB RXD,$ ;WAIT FOR STOP CHARACTER TO END
+ JNB RXD,$
+ LCALL RCL ;LOAD THE TIMER ******AA CALL-->LCALL
+ ;
+BG3: MOV DPTR,#S_N ;GET THE MESSAGE
+ ACALL CRP ;PRINT IT
+ LJMP CRAM
+
diff --git a/tests/t_bas52/bas52.tl b/tests/t_bas52/bas52.tl
new file mode 100644
index 0000000..fdf95da
--- /dev/null
+++ b/tests/t_bas52/bas52.tl
@@ -0,0 +1,16 @@
+
+ ;**************************************************************
+ ;
+TIMER_LOAD:; Load the timer
+ ;
+ ;*************************************************************
+ ;
+ ACALL $-1 ;DELAY FOUR CLOCKS
+ CLR TR1 ;STOP IT WHILE IT'S LOADED
+ MOV TH1,T_HH
+ MOV TL1,T_LL
+ CLR TF1 ;CLEAR THE OVERFLOW FLAG
+ SETB TR1 ;START IT NOW
+ RET
+ ;
+
diff --git a/tests/t_bas52/look52.inc b/tests/t_bas52/look52.inc
new file mode 100644
index 0000000..b4d13f4
--- /dev/null
+++ b/tests/t_bas52/look52.inc
@@ -0,0 +1,779 @@
+ ;**************************************************************
+ ;
+ ; This is the equate table for 8052 basic.
+ ;
+ ;**************************************************************
+ ;
+ ; The register to direct equates for CJNE instructions.
+ ;
+R0B0 EQU 0
+R1B0 EQU 1
+R2B0 EQU 2
+R3B0 EQU 3
+R4B0 EQU 4
+R5B0 EQU 5
+R6B0 EQU 6
+R7B0 EQU 7
+ ;
+ ; Register bank 1 contains the text pointer
+ ; and the arg stack pointer.
+ ;
+TXAL EQU 8 ;R0 BANK 1 = TEXT POINTER LOW
+ASTKA EQU 9 ;R1 BANK 1 = ARG STACK
+TXAH EQU 10 ;R2 BANK 1 = TEXT POINTER HIGH
+ ;
+ ; Now five temporary locations that are used by basic.
+ ;
+TEMP1 EQU 11
+TEMP2 EQU 12
+TEMP3 EQU 13
+TEMP4 EQU 14
+TEMP5 EQU 15
+ ;
+ newpage
+ ; Register bank 2 contains the read text pointer
+ ; and the control stack pointer.
+ ;
+RTXAL EQU 16 ;R0 BANK 2 = READ TEXT POINTER LOW
+CSTKA EQU 17 ;R1 BANK 2 = CONTROL STACK POINTER
+RTXAH EQU 18 ;R2 BANK 2 = READ TEXT POINTER HIGH
+ ;
+ ; Now some internal system equates.
+ ;
+BOFAH EQU 19 ;START OF THE BASIC PROGRAM, HIGH BYTE
+BOFAL EQU 20 ;START OF THE BASIC PROGRAM, LOW BYTE
+NULLCT EQU 21 ;NULL COUNT
+PHEAD EQU 22 ;PRINT HEAD POSITION
+FORMAT EQU 23
+ ;
+ ; Register bank 3 is for the user and can be loaded
+ ; by basic
+ ;
+ ;
+ ;
+ ; Now everything else is used by basic.
+ ; First the bit locations, these use bytes 34, 35, 36, 37 and 38
+ ;
+ newpage
+OTS BIT 16 ;34.0-ON TIME INSTRUCTION EXECUTED
+INPROG BIT 17 ;34.1-INTERRUPT IN PROCESS
+INTBIT BIT 18 ;34.2-INTERRUPT SET BIT
+ON_ERR BIT 19 ;34.3-ON ERROR EXECUTED
+OTI BIT 20 ;34.4-ON TIME INTERRUPT IN PROGRESS
+LINEB BIT 21 ;34.5-LINE CHANGE OCCURED
+INTPEN BIT 22 ;34.6-INTERRUPT PENDING BIT
+CONB BIT 23 ;34.7-CAN CONTINUE IF SET
+GTRD BIT 24 ;35.0-READ GET LOCATION
+LPB BIT 25 ;35.1-PRINT TO LINE PRINTER PORT
+CKS_B BIT 26 ;35.2-FOR PWM INTERRUPT
+COB BIT 27 ;35.3-CONSOLE OUT BIT
+ ; 0 = SERIAL PORT
+ ; 1 = LINE PRINTER
+COUB BIT 28 ;35.4-USER CONSOLE OUT BIT
+ ; 0 = SERIAL PORT
+ ; 1 = USER DRIVER
+INBIT BIT 29 ;35.5-INITIALIZATION BIT
+CIUB BIT 30 ;35.6-USER CONSOLE IN BIT
+ ; 0 = SERIAL PORT
+ ; 1 = USER ROUTINE
+SPINT BIT 31 ;35.7-SERIAL PORT INTERRUPT
+STOPBIT BIT 32 ;36.0-PROGRAM STOP ENCOUNTERED
+U_IDL BIT 33 ;36.1-USER IDLE BREAK
+INP_B BIT 34 ;36.2-SET DURING INPUT INSTRUCTION
+;DCMPXZ BIT 35 ;36.3-DCMPX ZERO FLAG
+ARGF BIT 36 ;36.4-ARG STACK HAS A VALUE
+RETBIT BIT 37 ;36.5-RET FROM INTERRUPT EXECUTED
+I_T0 BIT 38 ;36.6-TRAP INTERRUPT ZERO TO MON
+UPB BIT 39 ;36.7-SET WHEN @ IS VALID
+JKBIT BIT 40 ;37.0-WB TRIGGER
+ENDBIT BIT 41 ;37.1-GET END OF PROGRAM
+UBIT BIT 42 ;37.2-FOR DIM STATEMENT
+ISAV BIT 43 ;37.3-SAVE INTERRUPT STATUS
+BO BIT 44 ;37.4-BUBBLE OUTPUT
+XBIT BIT 45 ;37.5-EXTERNAL PROGRAM PRESENT
+C_BIT BIT 46 ;37.6-SET WHEN CLOCK RUNNING
+DIRF BIT 47 ;37.7-DIRECT INPUT MODE
+NO_C BIT 48 ;38.0-NO CONTROL C
+DRQ BIT 49 ;38.1-DMA ENABLED
+BI BIT 50 ;38.2-BUBBLE INPUT
+INTELB BIT 51 ;38.3-INTELLIGENT PROM PROGRAMMING
+C0ORX1 BIT 52 ;38.4-PRINT FROM ROM OR RAM
+CNT_S BIT 53 ;38.5-CONTROL S ENCOUNTERED
+ZSURP BIT 54 ;38.6-ZERO SUPRESS
+HMODE BIT 55 ;38.7-HEX MODE PRINT
+LP BIT P1.7 ;SOFTWARE LINE PRINTER
+DACK BIT P1.6 ;DMA ACK
+PROMV BIT P1.5 ;TURN ON PROM VOLTAGE
+PROMP BIT P1.4 ;PROM PULSE
+ALED BIT P1.3 ;ALE DISABLE
+T_BIT BIT P1.2 ;I/O TOGGLE BIT
+ ;
+ newpage
+ ;
+ ; The next location is a bit addressable byte counter
+ ;
+BABC EQU 39
+ ;
+ ; Now floating point and the other temps
+ ;
+ ; FP Uses to locations 03CH
+ ;
+ ; Now the stack designators.
+ ;
+SPSAV EQU 3EH
+S_LEN EQU 3FH
+T_HH EQU 40H
+T_LL EQU 41H
+INTXAH EQU 42H
+INTXAL EQU 43H
+MT1 EQU 45H
+MT2 EQU 46H
+MILLIV EQU 47H ;TIMER LOCATIONS
+TVH EQU 48H
+TVL EQU 49H
+SAVE_T EQU 4AH
+SP_H EQU 4BH ;SERIAL PORT TIME OUT
+SP_L EQU 4CH
+CMNDSP EQU 4DH ;SYSTEM STACK POINTER
+IRAMTOP EQU 0FFH ;TOP OF RAM
+STACKTP EQU 0FEH ;ARG AND CONTROL STACK TOPS
+ ;
+ ; The character equates
+ ;
+CR EQU 0DH ;CARRIAGE RETURN
+LF EQU 0AH ;LINE FEED
+BELL EQU 07H ;BELL CHARACTER
+BS EQU 08H ;BACK SPACE
+CNTRLC EQU 03H ;CONTROL C
+CNTRLD EQU 04H ;CONTROL D
+NULL EQU 00H ;NULL
+ ;
+ newpage
+ ;
+ ; The internal system equates
+ ;
+LINLEN EQU 73 ;THE LENGTH OF AN INPUT LINE
+EOF EQU 01 ;END OF FILE CHARACTER
+ASTKAH EQU 01 ;ASTKA IS IN PAGE 1 OF RAM
+CSTKAH EQU 00 ;CSTKA IS IN PAGE 0 OF RAM
+FTYPE EQU 01 ;CONTROL STACK "FOR"
+GTYPE EQU 02 ;CONTROL STACK "GOSUB"
+DTYPE EQU 03 ;DO-WHILE/UNTIL TYPE
+ROMADR EQU 8000H ;LOCATION OF ROM
+ ;
+ ; The floating point equates
+ ;
+FPSIZ EQU 6 ;NO. OF BYTES IN A FLOATING NUM
+DIGIT EQU FPSIZ-2 ;THE MANTISSA OF A FLOATING NUM
+STESIZ EQU FPSIZ+3 ;SIZE OF SYMBOL ADJUSTED TABLE ELEMENT
+FP_BASE EQU 1993H ;BASE OF FLOATING POINT ROUTINES
+PSTART EQU 512 ;START OF A PROGRAM IN RAM
+FSIZE EQU FPSIZ+FPSIZ+2+2+1
+ ;
+ newpage
+ ;**************************************************************
+ ;
+USENT: ; User entry jump table
+ ;
+ ;**************************************************************
+ ;
+ DW CMND1 ;(00, 00H)COMMAND MODE JUMP
+ DW IFIX ;(01, 01H)CONVERT FP TO INT
+ DW PUSHAS ;(02, 02H)PUSH VALUE ONTO ARG STACK
+ DW POPAS ;(03, 03H)POP VALUE OFF ARG STACK
+ DW PG1 ;(04, 04H)PROGRAM A PROM
+ DW INLINE ;(05, 05H)INPUT A LINE
+ DW UPRNT ;(06, 06H)PRINT A LINR
+ DW CRLF ;(07, 07H)OUTPUT A CRLF
+ ;
+ ;**************************************************************
+ ;
+ ; This is the operation jump table for arithmetics
+ ;
+ ;**************************************************************
+ ;
+OPTAB: DW ALPAR ;(08, 08H)LEFT PAREN
+ DW AEXP ;(09, 09H)EXPONENTAION
+ DW AMUL ;(10, 0AH)FP MUL
+ DW AADD ;(11, 0BH)FLOATING POINT ADD
+ DW ADIV ;(12, 0CH)FLOATING POINT DIVIDE
+ DW ASUB ;(13, 0DH)FLOATING POINT SUBTRACTION
+ DW AXRL ;(14, 0EH)XOR
+ DW AANL ;(15, 0FH)AND
+ DW AORL ;(16, 10H)OR
+ DW ANEG ;(17, 11H)NEGATE
+ DW AEQ ;(18, 12H)EQUAL
+ DW AGE ;(19, 13H)GREATER THAN OR EQUAL
+ DW ALE ;(20, 14H)LESS THAN OR EQUAL
+ DW ANE ;(21, 15H)NOT EQUAL
+ DW ALT ;(22, 16H)LESS THAN
+ DW AGT ;(23, 17H)GREATER THAN
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; This is the jump table for unary operators
+ ;
+ ;***************************************************************
+ ;
+ DW AABS ;(24, 18H)ABSOLUTE VALUE
+ DW AINT ;(25, 19H)INTEGER OPERATOR
+ DW ASGN ;(26, 1AH)SIGN OPERATOR
+ DW ANOT ;(27, 1BH)ONE'S COMPLEMENT
+ DW ACOS ;(28, 1CH)COSINE
+ DW ATAN ;(29, 1DH)TANGENT
+ DW ASIN ;(30, 1EH)SINE
+ DW ASQR ;(31, 1FH)SQUARE ROOT
+ DW ACBYTE ;(32, 20H)READ CODE
+ DW AETOX ;(33, 21H)E TO THE X
+ DW AATAN ;(34, 22H)ARC TANGENT
+ DW ALN ;(35, 23H)NATURAL LOG
+ DW ADBYTE ;(36, 24H)READ DATA MEMORY
+ DW AXBYTE ;(37, 25H)READ EXTERNAL MEMORY
+ DW PIPI ;(38, 26H)PI
+ DW ARND ;(39, 27H)RANDOM NUMBER
+ DW AGET ;(40, 28H)GET INPUT CHARACTER
+ DW AFREE ;(41, 29H)COMPUTE #BYTES FREE
+ DW ALEN ;(42, 2AH) COMPUTE LEN OF PORGRAM
+ DW AXTAL ;(43, 2BH) CRYSTAL
+ DW PMTOP ;(44, 2CH)TOP OF MEMORY
+ DW ATIME ;(45, 2DH) TIME
+ DW A_IE ;(46, 2EH) IE
+ DW A_IP ;(47, 2FH) IP
+ DW ATIM0 ;(48, 30H) TIMER 0
+ DW ATIM1 ;(49, 31H) TIMER 1
+ DW ATIM2 ;(50, 32H) TIMER 2
+ DW AT2CON ;(51, 33H) T2CON
+ DW ATCON ;(52, 34H) TCON
+ DW ATMOD ;(53, 35H) ATMOD
+ DW ARCAP2 ;(54, 36H) RCAP2
+ DW AP1 ;(55, 37H) P1
+ DW APCON ;(56, 38H) PCON
+ DW EXPRB ;(57, 39H) EVALUATE AN EXPRESSION
+ DW AXTAL1 ;(58, 3AH) CALCULATE CRYSTAL
+ DW LINE ;(59, 3BH) EDIT A LINE
+ DW PP ;(60, 3CH) PROCESS A LINE
+ DW UPPL-3 ;(61, 3DH) UNPROCESS A LINE
+ DW VAR ;(62, 3EH) FIND A VARIABLE
+ DW GC ;(63, 3FH) GET A CHARACTER
+ DW GCI ;(64, 40H) GET CHARACTER AND INCREMENT
+ DW INCHAR ;(65, 41H) INPUT A CHARACTER
+ DW CRUN ;(66, 42H) RUN A PROGRAM
+ newpage
+OPBOL: DB 1 ;
+ ;
+ DB 15 ;LEFT PAREN
+ DB 14 ;EXPONENTIAN **
+ DB 10 ;MUL
+ DB 8 ;ADD
+ DB 10 ;DIVIDE
+ DB 8 ;SUB
+ DB 3 ;XOR
+ DB 5 ;AND
+ DB 4 ;OR
+ DB 12 ;NEGATE
+ DB 6 ;EQ
+ DB 6 ;GT
+ DB 6 ;LT
+ DB 6 ;NE
+ DB 6 ;LE
+ DB 6 ;GE
+ ;
+UOPBOL: DB 15 ;AABS
+ DB 15 ;AAINT
+ DB 15 ;ASGN
+ DB 15 ;ANOT
+ DB 15 ;ACOS
+ DB 15 ;ATAN
+ DB 15 ;ASIN
+ DB 15 ;ASQR
+ DB 15 ;ACBYTE
+ DB 15 ;E TO THE X
+ DB 15 ;AATAN
+ DB 15 ;NATURAL LOG
+ DB 15 ;DBYTE
+ DB 15 ;XBYTE
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The ASCII printed messages.
+ ;
+ ;***************************************************************
+ ;
+STP: DB "STOP",'"'
+ ;
+IAN: DB "TRY AGAIN",'"'
+ ;
+RDYS: DB "READY",'"'
+ ;
+INS: DB " - IN LINE ",'"'
+ ;
+ ;**************************************************************
+ ;
+ ; This is the command jump table
+ ;
+ ;**************************************************************
+ ;
+CMNDD: DW CRUN ;RUN
+ DW CLIST ;LIST
+ DW CNULL ;NULL
+ DW CNEW ;NEW
+ DW CCONT ;CONTINUE
+ DW CPROG ;PROGRAM A PROM
+ DW CXFER ;TRANSFER FROM ROM TO RAM
+ DW CRAM ;RAM MODE
+ DW CROM ;ROM MODE
+ DW CIPROG ;INTELLIGENT PROM PROGRAMMING
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; This is the statement jump table.
+ ;
+ ;**************************************************************
+ ;
+STATD: ;
+ DW SLET ;LET 80H
+ DW SCLR ;CLEAR 81H
+ DW SPUSH ;PUSH VAR 82H
+ DW SGOTO ;GO TO 83H
+ DW STONE ;TONE 84H
+ DW SPH0 ;PRINT MODE 0 85H
+ DW SUI ;USER INPUT 86H
+ DW SUO ;USER OUTPUT 87H
+ DW SPOP ;POP VAR 88H
+ DW SPRINT ;PRINT 89H
+ DW SCALL ;CALL 8AH
+ DW SDIMX ;DIMENSION 8BH
+ DW STRING ;STRING ALLO 8CH
+ DW SBAUD ;SET BAUD 8DH
+ DW SCLOCK ;CLOCK 8EH
+ DW SPH1 ;PRINT MODE 1 8FH
+ ;
+ ; No direct mode from here on
+ ;
+ DW SSTOP ;STOP 90H
+ DW SOT ;ON TIME 91H
+ DW SONEXT ;ON EXT INT 92H
+ DW SRETI ;RET FROM INT 93H
+ DW S_DO ;DO 94H
+ DW SRESTR ;RESTOR 95H
+ DW WCR ;REM 96H
+ DW SNEXT ;NEXT 97H
+ DW SONERR ;ON ERROR 98H
+ DW S_ON ;ON 99H
+ DW SINPUT ;INPUT 9AH
+ DW SREAD ;READ 9BH
+ DW FINDCR ;DATA 9CH
+ DW SRETRN ;RETURN 9DH
+ DW SIF ;IF 9EH
+ DW SGOSUB ;GOSUB 9FH
+ DW SFOR ;FOR A0H
+ DW SWHILE ;WHILE A1H
+ DW SUNTIL ;UNTIL A2H
+ DW CMND1 ;END A3H
+ DW I_DL ;IDLE A4H
+ DW ST_A ;STORE AT A5H
+ DW LD_A ;LOAD AT A6H
+ DW PGU ;PGM A7H
+ DW RROM ;RUN A ROM A9H
+ ;
+ newpage
+ ;**************************************************************
+ ;
+TOKTAB: ; This is the basic token table
+ ;
+ ;**************************************************************
+ ;
+ ; First the tokens for statements
+ ;
+ DB 80H ;LET TOKEN
+ DB "LET"
+ ;
+ DB 81H ;CLEAR TOKEN
+ DB "CLEAR"
+ ;
+ DB 82H ;PUSH TOKEN
+ DB "PUSH"
+ ;
+T_GOTO EQU 83H
+ ;
+ DB 83H ;GO TO TOKEN
+ DB "GOTO"
+ ;
+ DB 84H ;TOGGLE TOKEN
+ DB "PWM"
+ ;
+ DB 85H ;PRINT HEX MODE 0
+ DB "PH0."
+ ;
+ DB 86H ;USER IN TOKEN
+ DB "UI"
+ ;
+ DB 87H ;USER OUT TOKEN
+ DB "UO"
+ ;
+ DB 88H ;POP TOKEN
+ DB "POP"
+ ;
+ newpage
+ DB 89H ;PRINT TOKEN
+ DB "PRINT"
+ DB 89H
+ DB "P." ;P. ALSO MEANS PRINT
+ DB 89H ;? ALSO
+ DB '?'
+ ;
+ DB 8AH ;CALL TOKEN
+ DB "CALL"
+ ;
+ DB 8BH ;DIMENSION TOKEN
+ DB "DIM"
+ ;
+ DB 8CH ;STRING TOKEN
+ DB "STRING"
+ ;
+ DB 8DH ;SET BAUD RATE
+ DB "BAUD"
+ ;
+ DB 8EH ;CLOCK
+ DB "CLOCK"
+ ;
+ DB 8FH ;PRINT HEX MODE 1
+ DB "PH1."
+ ;
+T_STOP EQU 90H ;STOP TOKEN
+ DB T_STOP
+ DB "STOP"
+ ;
+T_DIR EQU T_STOP ;NO DIRECT FROM HERE ON
+ ;
+ DB T_STOP+1 ;ON TIMER INTERRUPT
+ DB "ONTIME"
+ ;
+ DB T_STOP+2 ;ON EXTERNAL INTERRUPT
+ DB "ONEX1"
+ ;
+ DB T_STOP+3 ;RETURN FROM INTERRUPT
+ DB "RETI"
+ ;
+ DB T_STOP+4 ;DO TOKEN
+ DB "DO"
+ ;
+ DB T_STOP+5 ;RESTORE TOKEN
+ DB "RESTORE"
+ ;
+ newpage
+T_REM EQU T_STOP+6 ;REMARK TOKEN
+ DB T_REM
+ DB "REM"
+ ;
+ DB T_REM+1 ;NEXT TOKEN
+ DB "NEXT"
+ ;
+ DB T_REM+2 ;ON ERROR TOKEN
+ DB "ONERR"
+ ;
+ DB T_REM+3 ;ON TOKEN
+ DB "ON"
+ ;
+ DB T_REM+4 ;INPUT
+ DB "INPUT"
+ ;
+ DB T_REM+5 ;READ
+ DB "READ"
+ ;
+T_DATA EQU T_REM+6 ;DATA
+ DB T_DATA
+ DB "DATA"
+ ;
+ DB T_DATA+1 ;RETURN
+ DB "RETURN"
+ ;
+ DB T_DATA+2 ;IF
+ DB "IF"
+ ;
+T_GOSB EQU T_DATA+3 ;GOSUB
+ DB T_GOSB
+ DB "GOSUB"
+ ;
+ DB T_GOSB+1 ;FOR
+ DB "FOR"
+ ;
+ DB T_GOSB+2 ;WHILE
+ DB "WHILE"
+ ;
+ DB T_GOSB+3 ;UNTIL
+ DB "UNTIL"
+ ;
+ DB T_GOSB+4 ;END
+ DB "END"
+ ;
+ newpage
+T_LAST EQU T_GOSB+5 ;LAST INITIAL TOKEN
+ ;
+T_TAB EQU T_LAST ;TAB TOKEN
+ DB T_TAB
+ DB "TAB"
+ ;
+T_THEN EQU T_LAST+1 ;THEN TOKEN
+ DB T_THEN
+ DB "THEN"
+ ;
+T_TO EQU T_LAST+2 ;TO TOKEN
+ DB T_TO
+ DB "TO"
+ ;
+T_STEP EQU T_LAST+3 ;STEP TOKEN
+ DB T_STEP
+ DB "STEP"
+ ;
+T_ELSE EQU T_LAST+4 ;ELSE TOKEN
+ DB T_ELSE
+ DB "ELSE"
+ ;
+T_SPC EQU T_LAST+5 ;SPACE TOKEN
+ DB T_SPC
+ DB "SPC"
+ ;
+T_CR EQU T_LAST+6
+ DB T_CR
+ DB "CR"
+ ;
+ DB T_CR+1
+ DB "IDLE"
+ ;
+ DB T_CR+2
+ DB "ST@"
+ ;
+ DB T_CR+3
+ DB "LD@"
+ ;
+ DB T_CR+4
+ DB "PGM"
+ ;
+ DB T_CR+5
+ DB "RROM"
+ ;
+ newpage
+ ; Operator tokens
+ ;
+T_LPAR EQU 0E0H ;LEFT PAREN
+ DB T_LPAR
+ DB '('
+ ;
+ DB T_LPAR+1 ;EXPONENTIAN
+ DB "**"
+ ;
+ DB T_LPAR+2 ;FP MULTIPLY
+ DB '*'
+ ;
+T_ADD EQU T_LPAR+3
+ DB T_LPAR+3 ;ADD TOKEN
+ DB '+'
+ ;
+ DB T_LPAR+4 ;DIVIDE TOKEN
+ DB '/'
+ ;
+T_SUB EQU T_LPAR+5 ;SUBTRACT TOKEN
+ DB T_SUB
+ DB '-'
+ ;
+ DB T_LPAR+6 ;LOGICAL EXCLUSIVE OR
+ DB ".XOR."
+ ;
+ DB T_LPAR+7 ;LOGICAL AND
+ DB ".AND."
+ ;
+ DB T_LPAR+8 ;LOGICAL OR
+ DB ".OR."
+ ;
+T_NEG EQU T_LPAR+9
+ ;
+T_EQU EQU T_LPAR+10 ;EQUAL
+ DB T_EQU
+ DB '='
+ ;
+ DB T_LPAR+11 ;GREATER THAN OR EQUAL
+ DB ">="
+ ;
+ DB T_LPAR+12 ;LESS THAN OR EQUAL
+ DB "<="
+ ;
+ DB T_LPAR+13 ;NOT EQUAL
+ DB "<>"
+ ;
+ DB T_LPAR+14 ;LESS THAN
+ DB '<'
+ ;
+ DB T_LPAR+15 ;GREATER THAN
+ DB '>'
+ ;
+ ;
+T_UOP EQU 0B0H ;UNARY OP BASE TOKEN
+ ;
+ DB T_UOP ;ABS TOKEN
+ DB "ABS"
+ ;
+ DB T_UOP+1 ;INTEGER TOKEN
+ DB "INT"
+ ;
+ DB T_UOP+2 ;SIGN TOKEN
+ DB "SGN"
+ ;
+ DB T_UOP+3 ;GET TOKEN
+ DB "NOT"
+ ;
+ DB T_UOP+4 ;COSINE TOKEN
+ DB "COS"
+ ;
+ DB T_UOP+5 ;TANGENT TOKEN
+ DB "TAN"
+ ;
+ DB T_UOP+6 ;SINE TOKEN
+ DB "SIN"
+ ;
+ DB T_UOP+7 ;SQUARE ROOT TOKEN
+ DB "SQR"
+ ;
+ DB T_UOP+8 ;CBYTE TOKEN
+ DB "CBY"
+ ;
+ DB T_UOP+9 ;EXP (E TO THE X) TOKEN
+ DB "EXP"
+ ;
+ DB T_UOP+10
+ DB "ATN"
+ ;
+ DB T_UOP+11
+ DB "LOG"
+ ;
+ DB T_UOP+12 ;DBYTE TOKEN
+ DB "DBY"
+ ;
+ DB T_UOP+13 ;XBYTE TOKEN
+ DB "XBY"
+ ;
+T_ULAST EQU T_UOP+14 ;LAST OPERATOR NEEDING PARENS
+ ;
+ DB T_ULAST
+ DB "PI"
+ ;
+ DB T_ULAST+1 ;RND TOKEN
+ DB "RND"
+ ;
+ DB T_ULAST+2 ;GET TOKEN
+ DB "GET"
+ ;
+ DB T_ULAST+3 ;FREE TOKEN
+ DB "FREE"
+ ;
+ DB T_ULAST+4 ;LEN TOKEN
+ DB "LEN"
+ ;
+T_XTAL EQU T_ULAST+5 ;CRYSTAL TOKEN
+ DB T_XTAL
+ DB "XTAL"
+ ;
+T_MTOP EQU T_ULAST+6 ;MTOP
+ DB T_MTOP
+ DB "MTOP"
+ ;
+T_IE EQU T_ULAST+8 ;IE REGISTER
+ DB T_IE
+ DB "IE"
+ ;
+T_IP EQU T_ULAST+9 ;IP REGISTER
+ DB T_IP
+ DB "IP"
+ ;
+TMR0 EQU T_ULAST+10 ;TIMER 0
+ DB TMR0
+ DB "TIMER0"
+ ;
+TMR1 EQU T_ULAST+11 ;TIMER 1
+ DB TMR1
+ DB "TIMER1"
+ ;
+TMR2 EQU T_ULAST+12 ;TIMER 2
+ DB TMR2
+ DB "TIMER2"
+ ;
+T_TIME EQU T_ULAST+7 ;TIME
+ DB T_TIME
+ DB "TIME"
+ ;
+TT2C EQU T_ULAST+13 ;T2CON
+ DB TT2C
+ DB "T2CON"
+ ;
+TTC EQU T_ULAST+14 ;TCON
+ DB TTC
+ DB "TCON"
+ ;
+TTM EQU T_ULAST+15 ;TMOD
+ DB TTM
+ DB "TMOD"
+ ;
+TRC2 EQU T_ULAST+16 ;RCAP2
+ DB TRC2
+ DB "RCAP2"
+ ;
+T_P1 EQU T_ULAST+17 ;P1
+ DB T_P1
+ DB "PORT1"
+ ;
+T_PC EQU T_ULAST+18 ;PCON
+ DB T_PC
+ DB "PCON"
+ ;
+T_ASC EQU T_ULAST+19 ;ASC TOKEN
+ DB T_ASC
+ DB "ASC("
+ ;
+T_USE EQU T_ULAST+20 ;USING TOKEN
+ DB T_USE
+ DB "USING("
+ DB T_USE
+ DB "U.("
+ ;
+T_CHR EQU T_ULAST+21 ;CHR TOKEN
+ DB T_CHR
+ DB "CHR("
+ ;
+ newpage
+T_CMND EQU 0F0H ;COMMAND BASE
+ ;
+ DB 0F0H ;RUN TOKEN
+ DB "RUN"
+ ;
+ DB 0F1H ;LIST TOKEN
+ DB "LIST"
+ ;
+ DB 0F2H ;NULL TOKEN
+ DB "NULL"
+ ;
+ DB 0F3H ;NEW TOKEN
+ DB "NEW"
+ ;
+ DB 0F4H ;CONTINUE TOKEN
+ DB "CONT"
+ ;
+ DB 0F5H ;PROGRAM TOKEN
+ DB "PROG"
+ ;
+ DB 0F6H ;TRANSFER TOKEN
+ DB "XFER"
+ ;
+ DB 0F7H ;RAM MODE
+ DB "RAM"
+ ;
+ DB 0F8H ;ROM MODE
+ DB "ROM"
+ ;
+ DB 0F9H ;INTELLIGENT PROM PROGRAMMING
+ DB "FPROG"
+ ;
+ DB 0FFH ;END OF TABLE
+ ;
diff --git a/tests/t_bas52/t_bas52.asm b/tests/t_bas52/t_bas52.asm
new file mode 100644
index 0000000..3fff5d8
--- /dev/null
+++ b/tests/t_bas52/t_bas52.asm
@@ -0,0 +1,4644 @@
+; December 18, 1986
+; MS-DOS compatible Source code for MCS BASIC-52 (tm)
+; Assembles with ASM51 Macro Assembler Version 2.2
+;
+; The following source code does not include the floating point math
+; routines. These are seperately compiled using FP52.SRC.
+;
+; Both the BASIC.SRC and FP52.SRC programs assemble into ABSOLUTE
+; object files, and do not need to be relocated or linked. The FP52
+; object code and the BASIC object code, when compiled without modification
+; of the source listings, create the same object code that is found on
+; the MCS BASIC-52 Version 1.1 microcontrollers.
+;
+; The original source code had 7 "include" files that have been incorporated
+; into this file for ease of assembly.
+; These 7 files are: LOOK52.SRC, BAS52.RST, BAS52.PGM, BAS52.TL, BAS52.OUT,
+; BAS52.PWM, and BAS52.CLK.
+;
+;
+; Intel Corporation, Embedded Controller Operations
+
+ cpu 8052
+
+ page 0
+ newpage
+
+ include stddef51.inc
+ include bitfuncs.inc
+ bigendian on
+
+ segment code
+
+ ;**************************************************************
+ ;
+ ; TRAP VECTORS TO MONITOR
+ ;
+ ; RESET TAG (0AAH) ---------2001H
+ ;
+ ; TAG LOCATION (5AH) ------ 2002H
+ ;
+ ; EXTERNAL INTERRUPT 0 ---- 2040H
+ ;
+ ; COMMAND MODE ENTRY ------ 2048H
+ ;
+ ; SERIAL PORT ------------- 2050H
+ ;
+ ; MONITOR (BUBBLE) OUTPUT - 2058H
+ ;
+ ; MONITOR (BUBBLE) INPUT -- 2060H
+ ;
+ ; MONITOR (BUBBLE) CSTS --- 2068H
+ ;
+ ; GET USER JUMP VECTOR ---- 2070H
+ ;
+ ; GET USER LOOKUP VECTOR -- 2078H
+ ;
+ ; PRINT AT VECTOR --------- 2080H
+ ;
+ ; INTERRUPT PWM ----------- 2088H
+ ;
+ ; EXTERNAL RESET ---------- 2090H
+ ;
+ ; USER OUTPUT-------------- 4030H
+ ;
+ ; USER INPUT -------------- 4033H
+ ;
+ ; USER CSTS --------------- 4036H
+ ;
+ ; USER RESET -------------- 4039H
+ ;
+ ; USER DEFINED PRINT @ --- 403CH
+ ;
+ ;***************************************************************
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; MCS - 51 - 8K BASIC VERSION 1.1
+ ;
+ ;***************************************************************
+ ;
+ AJMP CRST ;START THE PROGRAM
+ db 037h ; ******AA inserted
+ ;
+ ORG 3H
+ ;
+ ;***************************************************************
+ ;
+ ;EXTERNAL INTERRUPT 0
+ ;
+ ;***************************************************************
+ ;
+ JB DRQ,STQ ;SEE IF DMA IS SET
+ PUSH PSW ;SAVE THE STATUS
+ LJMP 4003H ;JUMP TO USER IF NOT SET
+ ;
+ ORG 0BH
+ ;
+ ;***************************************************************
+ ;
+ ;TIMER 0 OVERFLOW INTERRUPT
+ ;
+ ;***************************************************************
+ ;
+ PUSH PSW ;SAVE THE STATUS
+ JB C_BIT,STJ ;SEE IF USER WANTS INTERRUPT
+ LJMP 400BH ;EXIT IF USER WANTS INTERRUPTS
+ ;
+ ORG 13H
+ ;
+ ;***************************************************************
+ ;
+ ;EXTERNAL INTERRUPT 1
+ ;
+ ;***************************************************************
+ ;
+ JB INTBIT,STK
+ PUSH PSW
+ LJMP 4013H
+ ;
+ newpage
+ ;
+ ORG 1BH
+ ;
+ ;***************************************************************
+ ;
+ ;TIMER 1 OVERFLOW INTERRUPT
+ ;
+ ;***************************************************************
+ ;
+ PUSH PSW
+ LJMP CKS_I
+ ;
+STJ: LJMP I_DR ;DO THE INTERRUPT
+ ;
+ ;***************************************************************
+ ;
+ ;SERIAL PORT INTERRUPT
+ ;
+ ;***************************************************************
+ ;
+ ORG 23H
+ ;
+ PUSH PSW
+ JB SPINT,STU ;SEE IF MONITOR EANTS INTERRUPT
+ LJMP 4023H
+ ;
+ ORG 2BH
+ ;
+ ;**************************************************************
+ ;
+ ;TIMER 2 OVERFLOW INTERRUPT
+ ;
+ ;**************************************************************
+ ;
+ PUSH PSW
+ LJMP 402BH
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ;USER ENTRY
+ ;
+ ;**************************************************************
+ ;
+ ORG 30H
+ ;
+ LJMP IBLK ;LINK TO USER BLOCK
+ ;
+STQ: JB I_T0,STS ;SEE IF MONITOR WANTS IT
+ CLR DACK
+ JNB P3.2,$ ;WAIT FOR DMA TO END
+ SETB DACK
+ RETI
+ ;
+STS: LJMP 2040H ;GO TO THE MONITOR
+ ;
+STK: SETB INTPEN ;TELL BASIC AN INTERRUPT WAS RECEIVED
+ RETI
+ ;
+STU: LJMP 2050H ;SERIAL PORT INTERRUPT
+ ;
+ newpage
+
+ include look52.inc ; ******AA
+
+EIG: DB "EXTRA IGNORED",'"'
+ ;
+EXA: DB "A-STACK",'"'
+ ;
+EXC: DB "C-STACK",'"'
+ ;
+ newpage
+
+ include bas52.rst ; ******AA
+
+ newpage
+ ;***************************************************************
+ ;
+ ; CIPROG AND CPROG - Program a prom
+ ;
+ ;***************************************************************
+ ;
+ include bas52.pgm ; ******AA
+ newpage
+ ;**************************************************************
+ ;
+PGU: ;PROGRAM A PROM FOR THE USER
+ ;
+ ;**************************************************************
+ ;
+ CLR PROMV ;TURN ON THE VOLTAGE
+ MOV PSW,#00011000B ;SELECT RB3
+ ACALL PG1 ;DO IT
+ SETB PROMV ;TURN IT OFF
+ RET
+ ;
+ ;
+ ;*************************************************************
+ ;
+CCAL: ; Set up for prom moves
+ ; R3:R1 gets source
+ ; R7:R6 gets # of bytes
+ ;
+ ;*************************************************************
+ ;
+ ACALL GETEND ;GET THE LAST LOCATION
+ INC DPTR ;BUMP TO LOAD EOF
+ MOV R3,BOFAH
+ MOV R1,BOFAL ;RESTORE START
+ CLR C ;PREPARE FOR SUBB
+ MOV A,DPL ;SUB DPTR - BOFA > R7:R6
+ SUBB A,R1
+ MOV R6,A
+ MOV A,DPH
+ SUBB A,R3
+ MOV R7,A
+ RET
+ ;
+ ;
+ include bas52.tl ; ******AA
+ newpage
+ ;***************************************************************
+ ;
+CROM: ; The command action routine - ROM - Run out of rom
+ ;
+ ;***************************************************************
+ ;
+ CLR CONB ;CAN'T CONTINUE IF MODE CHANGE
+ ACALL RO1 ;DO IT
+ ;
+C_K: LJMP CL3 ;EXIT
+ ;
+RO1: LCALL DELTST ;SEE IF INTGER PRESENT ******AA CALL-->LCALL, INTGER-->DELTST
+ MOV R4,#R1B0 ;SAVE THE NUMBER ******AA ABS-->IMM, R0B0-->R0B1 ?!?
+ JNC $+6 ; ******AA $+4-->$+6 ???
+ ;MOV R4,#01H ;ONE IF NO INTEGER PRESENT ******AA repl. by next two
+ LCALL ONE ; ******AA
+ MOV R4,A ; ******AA
+ ACALL ROMFD ;FIND THE PROGRAM
+ CJNE R4,#0,RFX ;EXIT IF R4 <> 0
+ INC DPTR ;BUMP PAST TAG
+ MOV BOFAH,DPH ;SAVE THE ADDRESS
+ MOV BOFAL,DPL
+ RET
+ ;
+ROMFD: MOV DPTR,#ROMADR+16 ;START OF USER PROGRAM
+ ;
+RF1: MOVX A,@DPTR ;GET THE BYTE
+ CJNE A,#55H,RF3 ;SEE IF PROPER TAG
+ DJNZ R4,RF2 ;BUMP COUNTER
+ ;
+RFX: RET ;DPTR HAS THE START ADDRESS
+ ;
+RF2: INC DPTR ;BUMP PAST TAG
+ ACALL G5
+ INC DPTR ;BUMP TO NEXT PROGRAM
+ SJMP RF1 ;DO IT AGAIN
+ ;
+RF3: JBC INBIT,RFX ;EXIT IF SET
+ ;
+NOGO: MOV DPTR,#NOROM
+ AJMP ERRLK
+ ;
+ newpage
+ ;***************************************************************
+ ;
+L20DPI: ; load R2:R0 with the location the DPTR is pointing to
+ ;
+ ;***************************************************************
+ ;
+ MOVX A,@DPTR
+ MOV R2,A
+ INC DPTR
+ MOVX A,@DPTR
+ MOV R0,A
+ RET ;DON'T BUMP DPTR
+ ;
+ ;***************************************************************
+ ;
+X31DP: ; swap R3:R1 with DPTR
+ ;
+ ;***************************************************************
+ ;
+ XCH A,R3
+ XCH A,DPH
+ XCH A,R3
+ XCH A,R1
+ XCH A,DPL
+ XCH A,R1
+ RET
+ ;
+ ;***************************************************************
+ ;
+LD_T: ; Load the timer save location with the value the DPTR is
+ ; pointing to.
+ ;
+ ;****************************************************************
+ ;
+ MOVX A,@DPTR
+ MOV T_HH,A
+ INC DPTR
+ MOVX A,@DPTR
+ MOV T_LL,A
+ RET
+ ;
+ newpage
+ ;
+ ;***************************************************************
+ ;
+ ;GETLIN - FIND THE LOCATION OF THE LINE NUMBER IN R3:R1
+ ; IF ACC = 0 THE LINE WAS NOT FOUND I.E. R3:R1
+ ; WAS TOO BIG, ELSE ACC <> 0 AND THE DPTR POINTS
+ ; AT THE LINE THAT IS GREATER THAN OR EQUAL TO THE
+ ; VALUE IN R3:R1.
+ ;
+ ;***************************************************************
+ ;
+GETEND: SETB ENDBIT ;GET THE END OF THE PROGRAM
+ ;
+GETLIN: LCALL DP_B ;GET BEGINNING ADDRESS ******AA CALL-->LCALL
+ ;
+G1: LCALL B_C ; ******AA CALL-->LCALL
+ JZ G3 ;EXIT WITH A ZERO IN A IF AT END
+ INC DPTR ;POINT AT THE LINE NUMBER
+ JB ENDBIT,G2 ;SEE IF WE WANT TO FIND THE END
+ ACALL DCMPX ;SEE IF (DPTR) = R3:R1
+ ACALL DECDP ;POINT AT LINE COUNT
+ MOVX A,@DPTR ;PUT LINE LENGTH INTO ACC
+ JB UBIT,G3 ;EXIT IF EQUAL
+ JC G3 ;SEE IF LESS THAN OR ZERO
+ ;
+G2: ACALL ADDPTR ;ADD IT TO DPTR
+ SJMP G1 ;LOOP
+ ;
+G3: CLR ENDBIT ;RESET ENDBIT
+ RET ;EXIT
+ ;
+G4: MOV DPTR,#PSTART ;DO RAM
+ ;
+G5: SETB ENDBIT
+ SJMP G1 ;NOW DO TEST
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; LDPTRI - Load the DATA POINTER with the value it is pointing
+ ; to - DPH = (DPTR) , DPL = (DPTR+1)
+ ;
+ ; acc gets wasted
+ ;
+ ;***************************************************************
+ ;
+LDPTRI: MOVX A,@DPTR ;GET THE HIGH BYTE
+ PUSH ACC ;SAVE IT
+ INC DPTR ;BUMP THE POINTER
+ MOVX A,@DPTR ;GET THE LOW BYTE
+ MOV DPL,A ;PUT IT IN DPL
+ POP DPH ;GET THE HIGH BYTE
+ RET ;GO BACK
+ ;
+ ;***************************************************************
+ ;
+ ;L31DPI - LOAD R3 WITH (DPTR) AND R1 WITH (DPTR+1)
+ ;
+ ;ACC GETS CLOBBERED
+ ;
+ ;***************************************************************
+ ;
+L31DPI: MOVX A,@DPTR ;GET THE HIGH BYTE
+ MOV R3,A ;PUT IT IN THE REG
+ INC DPTR ;BUMP THE POINTER
+ MOVX A,@DPTR ;GET THE NEXT BYTE
+ MOV R1,A ;SAVE IT
+ RET
+ ;
+ ;***************************************************************
+ ;
+ ;DECDP - DECREMENT THE DATA POINTER - USED TO SAVE SPACE
+ ;
+ ;***************************************************************
+ ;
+DECDP2: ACALL DECDP
+ ;
+DECDP: XCH A,DPL ;GET DPL
+ JNZ $+4 ;BUMP IF ZERO
+ DEC DPH
+ DEC A ;DECREMENT IT
+ XCH A,DPL ;GET A BACK
+ RET ;EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ;DCMPX - DOUBLE COMPARE - COMPARE (DPTR) TO R3:R1
+ ;R3:R1 - (DPTR) = SET CARRY FLAG
+ ;
+ ;IF R3:R1 > (DPTR) THEN C = 0
+ ;IF R3:R1 < (DPTR) THEN C = 1
+ ;IF R3:R1 = (DPTR) THEN C = 0
+ ;
+ ;***************************************************************
+ ;
+DCMPX: CLR UBIT ;ASSUME NOT EQUAL
+ MOVX A,@DPTR ;GET THE BYTE
+ CJNE A,R3B0,D1 ;IF A IS GREATER THAN R3 THEN NO CARRY
+ ;WHICH IS R3<@DPTR = NO CARRY AND
+ ;R3>@DPTR CARRY IS SET
+ INC DPTR ;BUMP THE DATA POINTER
+ MOVX A,@DPTR ;GET THE BYTE
+ ACALL DECDP ;PUT DPTR BACK
+ CJNE A,R1B0,D1 ;DO THE COMPARE
+ CPL C ;FLIP CARRY
+ ;
+ CPL UBIT ;SET IT
+D1: CPL C ;GET THE CARRY RIGHT
+ RET ;EXIT
+ ;
+ ;***************************************************************
+ ;
+ ; ADDPTR - Add acc to the dptr
+ ;
+ ; acc gets wasted
+ ;
+ ;***************************************************************
+ ;
+ADDPTR: ADD A,DPL ;ADD THE ACC TO DPL
+ MOV DPL,A ;PUT IT IN DPL
+ JNC $+4 ;JUMP IF NO CARRY
+ INC DPH ;BUMP DPH
+ RET ;EXIT
+ ;
+ newpage
+ ;*************************************************************
+ ;
+LCLR: ; Set up the storage allocation
+ ;
+ ;*************************************************************
+ ;
+ ACALL ICLR ;CLEAR THE INTERRUPTS
+ ACALL G4 ;PUT END ADDRESS INTO DPTR
+ MOV A,#6 ;ADJUST MATRIX SPACE
+ ACALL ADDPTR ;ADD FOR PROPER BOUNDS
+ ACALL X31DP ;PUT MATRIX BOUNDS IN R3:R1
+ MOV DPTR,#MT_ALL ;SAVE R3:R1 IN MATRIX FREE SPACE
+ ACALL S31DP ;DPTR POINTS TO MEMTOP
+ ACALL L31DPI ;LOAD MEMTOP INTO R3:R1
+ MOV DPTR,#STR_AL ;GET MEMORY ALLOCATED FOR STRINGS
+ ACALL LDPTRI
+ LCALL DUBSUB ;R3:R1 = MEMTOP - STRING ALLOCATION ******AA CALL-->LCALL
+ MOV DPTR,#VARTOP ;SAVE R3:R1 IN VARTOP
+ ;
+ ; FALL THRU TO S31DP2
+ ;
+ ;***************************************************************
+ ;
+ ;S31DP - STORE R3 INTO (DPTR) AND R1 INTO (DPTR+1)
+ ;
+ ;ACC GETS CLOBBERED
+ ;
+ ;***************************************************************
+ ;
+S31DP2: ACALL S31DP ;DO IT TWICE
+ ;
+S31DP: MOV A,R3 ;GET R3 INTO ACC
+ MOVX @DPTR,A ;STORE IT
+ INC DPTR ;BUMP DPTR
+ MOV A,R1 ;GET R1
+ MOVX @DPTR,A ;STORE IT
+ INC DPTR ;BUMP IT AGAIN TO SAVE PROGRAM SPACE
+ RET ;GO BACK
+ ;
+ ;
+ ;***************************************************************
+ ;
+STRING: ; Allocate memory for strings
+ ;
+ ;***************************************************************
+ ;
+ LCALL TWO ;R3:R1 = NUMBER, R2:R0 = LEN
+ MOV DPTR,#STR_AL ;SAVE STRING ALLOCATION
+ ACALL S31DP
+ INC R6 ;BUMP
+ MOV S_LEN,R6 ;SAVE STRING LENGTH
+ AJMP RCLEAR ;CLEAR AND SET IT UP
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; F_VAR - Find the variable in symbol table
+ ; R7:R6 contain the variable name
+ ; If not found create a zero entry and set the carry
+ ; R2:R0 has the address of variable on return
+ ;
+ ;***************************************************************
+ ;
+F_VAR: MOV DPTR,#VARTOP ;PUT VARTOP IN DPTR
+ ACALL LDPTRI
+ ACALL DECDP2 ;ADJUST DPTR FOR LOOKUP
+ ;
+F_VAR0: MOVX A,@DPTR ;LOAD THE VARIABLE
+ JZ F_VAR2 ;TEST IF AT THE END OF THE TABLE
+ INC DPTR ;BUMP FOR NEXT BYTE
+ CJNE A,R7B0,F_VAR1 ;SEE IF MATCH
+ MOVX A,@DPTR ;LOAD THE NAME
+ CJNE A,R6B0,F_VAR1
+ ;
+ ; Found the variable now adjust and put in R2:R0
+ ;
+DLD: MOV A,DPL ;R2:R0 = DPTR-2
+ SUBB A,#2
+ MOV R0,A
+ MOV A,DPH
+ SUBB A,#0 ;CARRY IS CLEARED
+ MOV R2,A
+ RET
+ ;
+F_VAR1: MOV A,DPL ;SUBTRACT THE STACK SIZE+ADJUST
+ CLR C
+ SUBB A,#STESIZ
+ MOV DPL,A ;RESTORE DPL
+ JNC F_VAR0
+ DEC DPH
+ SJMP F_VAR0 ;CONTINUE COMPARE
+ ;
+ newpage
+ ;
+ ; Add the entry to the symbol table
+ ;
+F_VAR2: LCALL R76S ;SAVE R7 AND R6
+ CLR C
+ ACALL DLD ;BUMP THE POINTER TO GET ENTRY ADDRESS
+ ;
+ ; Adjust pointer and save storage allocation
+ ; and make sure we aren't wiping anything out
+ ; First calculate new storage allocation
+ ;
+ MOV A,R0
+ SUBB A,#STESIZ-3 ;NEED THIS MUCH RAM
+ MOV R1,A
+ MOV A,R2
+ SUBB A,#0
+ MOV R3,A
+ ;
+ ; Now save the new storage allocation
+ ;
+ MOV DPTR,#ST_ALL
+ CALL S31DP ;SAVE STORAGE ALLOCATION
+ ;
+ ; Now make sure we didn't blow it, by wiping out MT_ALL
+ ;
+ ACALL DCMPX ;COMPARE STORAGE ALLOCATION
+ JC CCLR3 ;ERROR IF CARRY
+ SETB C ;DID NOT FIND ENTRY
+ RET ;EXIT IF TEST IS OK
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; Command action routine - NEW
+ ;
+ ;***************************************************************
+ ;
+CNEW: MOV DPTR,#PSTART ;SAVE THE START OF PROGRAM
+ MOV A,#EOF ;END OF FILE
+ MOVX @DPTR,A ;PUT IT IN MEMORY
+ ;
+ ; falls thru
+ ;
+ ;*****************************************************************
+ ;
+ ; The statement action routine - CLEAR
+ ;
+ ;*****************************************************************
+ ;
+ CLR LINEB ;SET UP FOR RUN AND GOTO
+ ;
+RCLEAR: ACALL LCLR ;CLEAR THE INTERRUPTS, SET UP MATRICES
+ MOV DPTR,#MEMTOP ;PUT MEMTOP IN R3:R1
+ ACALL L31DPI
+ ACALL G4 ;DPTR GETS END ADDRESS
+ ACALL CL_1 ;CLEAR THE MEMORY
+ ;
+RC1: MOV DPTR,#STACKTP ;POINT AT CONTROL STACK TOP
+ CLR A ;CONTROL UNDERFLOW
+ ;
+RC2: MOVX @DPTR,A ;SAVE IN MEMORY
+ MOV CSTKA,#STACKTP
+ MOV ASTKA,#STACKTP
+ CLR CONB ;CAN'T CONTINUE
+ RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; Loop until the memory is cleared
+ ;
+ ;***************************************************************
+ ;
+CL_1: INC DPTR ;BUMP MEMORY POINTER
+ CLR A ;CLEAR THE MEMORY
+ MOVX @DPTR,A ;CLEAR THE RAM
+ MOVX A,@DPTR ;READ IT
+ JNZ CCLR3 ;MAKE SURE IT IS CLEARED
+ MOV A,R3 ;GET POINTER FOR COMPARE
+ CJNE A,DPH,CL_1 ;SEE TO LOOP
+ MOV A,R1 ;NOW TEST LOW BYTE
+ CJNE A,DPL,CL_1
+ ;
+CL_2: RET
+ ;
+CCLR3: LJMP TB ;ALLOCATED MEMORY DOESN'T EXSIST ******AA JMP-->LJMP
+ ;
+ ;**************************************************************
+ ;
+SCLR: ;Entry point for clear return
+ ;
+ ;**************************************************************
+ ;
+ LCALL DELTST ;TEST FOR A CR ******AA CALL-->LCALL
+ JNC RCLEAR
+ LCALL GCI1 ;BUMP THE TEST POINTER ******AA CALL-->LCALL
+ CJNE A,#'I',RC1 ;SEE IF I, ELSE RESET THE STACK
+ ;
+ ;**************************************************************
+ ;
+ICLR: ; Clear interrupts and system garbage
+ ;
+ ;**************************************************************
+ ;
+ JNB INTBIT,$+5 ;SEE IF BASIC HAS INTERRUPTS
+ CLR EX1 ;IF SO, CLEAR INTERRUPTS
+ ANL 34,#00100000B ;SET INTERRUPTS + CONTINUE
+ RETI
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ;OUTPUT ROUTINES
+ ;
+ ;***************************************************************
+ ;
+CRLF2: ACALL CRLF ;DO TWO CRLF'S
+ ;
+CRLF: MOV R5,#CR ;LOAD THE CR
+ ACALL TEROT ;CALL TERMINAL OUT
+ MOV R5,#LF ;LOAD THE LF
+ AJMP TEROT ;OUTPUT IT AND RETURN
+ ;
+ ;PRINT THE MESSAGE ADDRESSED IN ROM OR RAM BY THE DPTR
+ ;ENDS WITH THE CHARACTER IN R4
+ ;DPTR HAS THE ADDRESS OF THE TERMINATOR
+ ;
+CRP: ACALL CRLF ;DO A CR THEN PRINT ROM
+ ;
+ROM_P: CLR A ;CLEAR A FOR LOOKUP
+ MOVC A,@A+DPTR ;GET THE CHARACTER
+ CLR ACC.7 ;CLEAR MS BIT
+ CJNE A,#'"',$+4 ;EXIT IF TERMINATOR
+ RET
+ SETB C0ORX1
+ ;
+PN1: MOV R5,A ;OUTPUT THE CHARACTER
+ ACALL TEROT
+ INC DPTR ;BUMP THE POINTER
+ SJMP PN0
+ ;
+UPRNT: ACALL X31DP
+ ;
+PRNTCR: MOV R4,#CR ;OUTPUT UNTIL A CR
+ ;
+PN0: JBC C0ORX1,ROM_P
+ MOVX A,@DPTR ;GET THE RAM BYTE
+ JZ $+5
+ CJNE A,R4B0,$+4 ;SEE IF THE SAME AS TERMINATOR
+ RET ;EXIT IF THE SAME
+ CJNE A,#CR,PN1 ;NEVER PRINT A CR IN THIS ROUTINE
+ LJMP E1XX ;BAD SYNTAX
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; INLINE - Input a line to IBUF, exit when a CR is received
+ ;
+ ;***************************************************************
+ ;
+INL2: CJNE A,#CNTRLD,INL2B ;SEE IF A CONTROL D
+ ;
+INL0: ACALL CRLF ;DO A CR
+ ;
+INLINE: MOV P2,#HI(IBUF) ;IBUF IS IN THE ZERO PAGE
+ MOV R0,#LO(IBUF) ;POINT AT THE INPUT BUFFER
+ ;
+INL1: ACALL INCHAR ;GET A CHARACTER
+ MOV R5,A ;SAVE IN R5 FOR OUTPUT
+ CJNE A,#7FH,INL2 ;SEE IF A DELETE CHARACTER
+ CJNE R0,#LO(IBUF),INL6
+ MOV R5,#BELL ;OUTPUT A BELL
+ ;
+INLX: ACALL TEROT ;OUTPUT CHARACTER
+ SJMP INL1 ;DO IT AGAIN
+ ;
+INL2B: MOVX @R0,A ;SAVE THE CHARACTER
+ CJNE A,#CR,$+5 ;IS IT A CR
+ AJMP CRLF ;OUTPUT A CRLF AND EXIT
+ CJNE A,#20H,$+3
+ JC INLX ;ONLY ECHO CONTROL CHARACTERS
+ INC R0 ;BUMP THE POINTER
+ CJNE R0,#IBUF+79,INLX
+ DEC R0 ;FORCE 79
+ SJMP INLX-2 ;OUTPUT A BELL
+ ;
+INL6: DEC R0 ;DEC THE RAM POINTER
+ MOV R5,#BS ;OUTPUT A BACK SPACE
+ ACALL TEROT
+ ACALL STEROT ;OUTPUT A SPACE
+ MOV R5,#BS ;ANOTHER BACK SPACE
+ SJMP INLX ;OUTPUT IT
+ ;
+PTIME: DB 128-2 ; PROM PROGRAMMER TIMER
+ DB 00H
+ DB 00H
+ DB 50H
+ DB 67H
+ DB 41H
+ ;
+ newpage
+ include bas52.out ; ******AA
+ ;
+BCK: ACALL CSTS ;CHECK STATUS
+ JNC CI_RET+1 ;EXIT IF NO CHARACTER
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ;INPUTS A CHARACTER FROM THE SYSTEM CONSOLE.
+ ;
+ ;***************************************************************
+ ;
+INCHAR: JNB BI,$+8 ;CHECK FOR MONITOR (BUBBLE)
+ LCALL 2060H
+ SJMP INCH1
+ JNB CIUB,$+8 ;CHECK FOR USER
+ LCALL 4033H
+ SJMP INCH1
+ JNB RI,$ ;WAIT FOR RECEIVER READY.
+ MOV A,SBUF
+ CLR RI ;RESET READY
+ CLR ACC.7 ;NO BIT 7
+ ;
+INCH1: CJNE A,#13H,$+5
+ SETB CNT_S
+ CJNE A,#11H,$+5
+ CLR CNT_S
+ CJNE A,#CNTRLC,$+7
+ JNB NO_C,C_EX ;TRAP NO CONTROL C
+ RET
+ ;
+ CLR JKBIT
+ CJNE A,#17H,CI_RET ;CONTROL W
+ SETB JKBIT
+ ;
+CI_RET: SETB C ;CARRY SET IF A CHARACTER
+ RET ;EXIT
+ ;
+ ;*************************************************************
+ ;
+ ;RROM - The Statement Action Routine RROM
+ ;
+ ;*************************************************************
+ ;
+RROM: SETB INBIT ;SO NO ERRORS
+ ACALL RO1 ;FIND THE LINE NUMBER
+ JBC INBIT,CRUN
+ RET ;EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+CSTS: ; RETURNS CARRY = 1 IF THERE IS A CHARACTER WAITING FROM
+ ; THE SYSTEM CONSOLE. IF NO CHARACTER THE READY CHARACTER
+ ; WILL BE CLEARED
+ ;
+ ;***************************************************************
+ ;
+ JNB BI,$+6 ;BUBBLE STATUS
+ LJMP 2068H
+ JNB CIUB,$+6 ;SEE IF EXTERNAL CONSOLE
+ LJMP 4036H
+ MOV C,RI
+ RET
+ ;
+ MOV DPTR,#WB ;EGO MESSAGE
+ ACALL ROM_P
+ ;
+C_EX: CLR CNT_S ;NO OUTPUT STOP
+ LCALL SPRINT+4 ;ASSURE CONSOLE
+ ACALL CRLF
+ JBC JKBIT,C_EX-5
+ ;
+ JNB DIRF,SSTOP0
+ AJMP C_K ;CLEAR COB AND EXIT
+ ;
+T_CMP: MOV A,TVH ;COMPARE TIMER TO SP_H AND SP_L
+ MOV R1,TVL
+ CJNE A,TVH,T_CMP
+ XCH A,R1
+ SUBB A,SP_L
+ MOV A,R1
+ SUBB A,SP_H
+ RET
+ ;
+ ;*************************************************************
+ ;
+BR0: ; Trap the timer interrupt
+ ;
+ ;*************************************************************
+ ;
+ CALL T_CMP ;COMPARE TIMER
+ JC BCHR+6 ;EXIT IF TEST FAILS
+ SETB OTI ;DOING THE TIMER INTERRUPT
+ CLR OTS ;CLEAR TIMER BIT
+ MOV C,INPROG ;SAVE IN PROGRESS
+ MOV ISAV,C
+ MOV DPTR,#TIV
+ SJMP BR2
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The command action routine - RUN
+ ;
+ ;***************************************************************
+ ;
+CRUN: LCALL RCLEAR-2 ;CLEAR THE STORAGE ARRAYS
+ ACALL SRESTR+2 ;GET THE STARTING ADDRESS
+ ACALL B_C
+ JZ CMNDLK ;IF NULL GO TO COMMAND MODE
+ ;
+ ACALL T_DP
+ ACALL B_TXA ;BUMP TO STARTING LINE
+ ;
+CILOOP: ACALL SP0 ;DO A CR AND A LF
+ CLR DIRF ;NOT IN DIRECT MODE
+ ;
+ ;INTERPERTER DRIVER
+ ;
+ILOOP: MOV SP,SPSAV ;RESTORE THE STACK EACH TIME
+ JB DIRF,$+9 ;NO INTERRUPTS IF IN DIRECT MODE
+ MOV INTXAH,TXAH ;SAVE THE TEXT POINTER
+ MOV INTXAL,TXAL
+ LCALL BCK ;GET CONSOLE STATUS
+ JB DIRF,I_L ;DIRECT MODE
+ ANL C,/GTRD ;SEE IF CHARACTER READY
+ JNC BCHR ;NO CHARACTER = NO CARRY
+ ;
+ ; DO TRAP OPERATION
+ ;
+ MOV DPTR,#GTB ;SAVE TRAP CHARACTER
+ MOVX @DPTR,A
+ SETB GTRD ;SAYS READ A BYTE
+ ;
+BCHR: JB OTI,I_L ;EXIT IF TIMER INTERRUPT IN PROGRESS
+ JB OTS,BR0 ;TEST TIMER VALUE IF SET
+ JNB INTPEN,I_L ;SEE IF INTERRUPT PENDING
+ JB INPROG,I_L ;DON'T DO IT AGAIN IF IN PROGRESS
+ MOV DPTR,#INTLOC ;POINT AT INTERRUPT LOCATION
+ ;
+BR2: MOV R4,#GTYPE ;SETUP FOR A FORCED GOSUB
+ ACALL SGS1 ;PUT TXA ON STACK
+ SETB INPROG ;INTERRUPT IN PROGRESS
+ ;
+ERL4: CALL L20DPI
+ AJMP D_L1 ;GET THE LINE NUMBER
+ ;
+I_L: ACALL ISTAT ;LOOP
+ ACALL CLN_UP ;FINISH IT OFF
+ JNC ILOOP ;LOOP ON THE DRIVER
+ JNB DIRF,CMNDLK ;CMND1 IF IN RUN MODE
+ LJMP CMNDR ;DON'T PRINT READY
+ ;
+CMNDLK: LJMP CMND1 ;DONE ******AA JMP-->LJMP
+ newpage
+ ;**************************************************************
+ ;
+ ; The Statement Action Routine - STOP
+ ;
+ ;**************************************************************
+ ;
+SSTOP: ACALL CLN_UP ;FINISH OFF THIS LINE
+ MOV INTXAH,TXAH ;SAVE TEXT POINTER FOR CONT
+ MOV INTXAL,TXAL
+ ;
+SSTOP0: SETB CONB ;CONTINUE WILL WORK
+ MOV DPTR,#STP ;PRINT THE STOP MESSAGE
+ SETB STOPBIT ;SET FOR ERROR ROUTINE
+ LJMP ERRS ;JUMP TO ERROR ROUTINE ******AA JMP-->LJMP
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; ITRAP - Trap special function register operators
+ ;
+ ;**************************************************************
+ ;
+ITRAP: CJNE A,#TMR0,$+8 ;TIMER 0
+ MOV TH0,R3
+ MOV TL0,R1
+ RET
+ ;
+ CJNE A,#TMR1,$+8 ;TIMER 1
+ MOV TH1,R3
+ MOV TL1,R1
+ RET
+ ;
+ CJNE A,#TMR2,$+8 ;TIMER 2
+ DB 8BH ;MOV R3 DIRECT OP CODE
+ DB 0CDH ;T2H LOCATION
+ DB 89H ;MOV R1 DIRECT OP CODE
+ DB 0CCH ;T2L LOCATION
+ RET
+ ;
+ CJNE A,#TRC2,$+8 ;RCAP2 TOKEN
+RCL: DB 8BH ;MOV R3 DIRECT OP CODE
+ DB 0CBH ;RCAP2H LOCATION
+ DB 89H ;MOV R1 DIRECT OP CODE
+ DB 0CAH ;RCAP2L LOCATION
+ RET
+ ;
+ ACALL R3CK ;MAKE SURE THAT R3 IS ZERO
+ CJNE A,#TT2C,$+6
+ DB 89H ;MOV R1 DIRECT OP CODE
+ DB 0C8H ;T2CON LOCATION
+ RET
+ ;
+ CJNE A,#T_IE,$+6 ;IE TOKEN
+ MOV IE,R1
+ RET
+ ;
+ CJNE A,#T_IP,$+6 ;IP TOKEN
+ MOV IP,R1
+ RET
+ ;
+ CJNE A,#TTC,$+6 ;TCON TOKEN
+ MOV TCON,R1
+ RET
+ ;
+ CJNE A,#TTM,$+6 ;TMOD TOKEN
+ MOV TMOD,R1
+ RET
+ ;
+ CJNE A,#T_P1,T_T2 ;P1 TOKEN
+ MOV P1,R1
+ RET
+ ;
+ ;***************************************************************
+ ;
+ ; T_TRAP - Trap special operators
+ ;
+ ;***************************************************************
+ ;
+T_T: MOV TEMP5,A ;SAVE THE TOKEN
+ ACALL GCI1 ;BUMP POINTER
+ ACALL SLET2 ;EVALUATE AFTER =
+ MOV A,TEMP5 ;GET THE TOKEN BACK
+ CJNE A,#T_XTAL,$+6
+ LJMP AXTAL1 ;SET UP CRYSTAL
+ ;
+ ACALL IFIXL ;R3:R1 HAS THE TOS
+ MOV A,TEMP5 ;GET THE TOKEN AGAIN
+ CJNE A,#T_MTOP,T_T1 ;SEE IF MTOP TOKEN
+ MOV DPTR,#MEMTOP
+ CALL S31DP
+ JMP RCLEAR ;CLEAR THE MEMORY
+ ;
+T_T1: CJNE A,#T_TIME,ITRAP ;SEE IF A TIME TOKEN
+ MOV C,EA ;SAVE INTERRUPTS
+ CLR EA ;NO TIMER 0 INTERRUPTS DURING LOAD
+ MOV TVH,R3 ;SAVE THE TIME
+ MOV TVL,R1
+ MOV EA,C ;RESTORE INTERRUPTS
+ RET ;EXIT
+ ;
+T_T2: CJNE A,#T_PC,INTERX ;PCON TOKEN
+ DB 89H ;MOV DIRECT, R1 OP CODE
+ DB 87H ;ADDRESS OF PCON
+ RET ;EXIT
+ ;
+T_TRAP: CJNE A,#T_ASC,T_T ;SEE IF ASC TOKEN
+ ACALL IGC ;EAT IT AND GET THE NEXT CHARACTER
+ CJNE A,#'$',INTERX ;ERROR IF NOT A STRING
+ ACALL CSY ;CALCULATE ADDRESS
+ ACALL X3120
+ LCALL TWO_EY ; ******AA CALL-->LCALL
+ ACALL SPEOP+4 ;EVALUATE AFTER EQUALS
+ AJMP ISTAX1 ;SAVE THE CHARACTER
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ;INTERPERT THE STATEMENT POINTED TO BY TXAL AND TXAH
+ ;
+ ;**************************************************************
+ ;
+ISTAT: ACALL GC ;GET THR FIRST CHARACTER
+ JNB XBIT,IAT ;TRAP TO EXTERNAL RUN PACKAGE
+ CJNE A,#20H,$+3
+ JNC IAT
+ LCALL 2070H ;LET THE USER SET UP THE DPTR
+ ACALL GCI1
+ ANL A,#0FH ;STRIP OFF BIAS
+ SJMP ISTA1
+ ;
+IAT: CJNE A,#T_XTAL,$+3
+ JNC T_TRAP
+ JNB ACC.7,SLET ;IMPLIED LET IF BIT 7 NOT SET
+ CJNE A,#T_UOP+12,ISTAX ;DBYTE TOKEN
+ ACALL SPEOP ;EVALUATE SPECIAL OPERATOR
+ ACALL R3CK ;CHECK LOCATION
+ MOV @R1,A ;SAVE IT
+ RET
+ ;
+ISTAX: CJNE A,#T_UOP+13,ISTAY ;XBYTE TOKEN
+ ACALL SPEOP
+ ;
+ISTAX1: MOV P2,R3
+ MOVX @R1,A
+ RET
+ ;
+ISTAY: CJNE A,#T_CR+1,$+3 ;TRAP NEW OPERATORS
+ JC I_S
+ CJNE A,#0B0H,$+3 ;SEE IF TOO BIG
+ JNC INTERX
+ ADD A,#0F9H ;BIAS FOR LOOKUP TABLE
+ SJMP ISTA0 ;DO THE OPERATION
+ ;
+I_S: CJNE A,#T_LAST,$+3 ;MAKE SURE AN INITIAL RESERVED WORD
+ JC $+5 ;ERROR IF NOT
+ ;
+INTERX: LJMP E1XX ;SYNTAX ERROR
+ ;
+ JNB DIRF,ISTA0 ;EXECUTE ALL STATEMENTS IF IN RUN MODE
+ CJNE A,#T_DIR,$+3 ;SEE IF ON TOKEN
+ JC ISTA0 ;OK IF DIRECT
+ CJNE A,#T_GOSB+1,$+5 ;SEE IF FOR
+ SJMP ISTA0 ;FOR IS OK
+ CJNE A,#T_REM+1,$+5 ;NEXT IS OK
+ SJMP ISTA0
+ CJNE A,#T_STOP+6,INTERX ;SO IS REM
+ ;
+ newpage
+ISTA0: ACALL GCI1 ;ADVANCE THE TEXT POINTER
+ MOV DPTR,#STATD ;POINT DPTR TO LOOKUP TABLE
+ CJNE A,#T_GOTO-3,$+5 ;SEE IF LET TOKEN
+ SJMP ISTAT ;WASTE LET TOKEN
+ ANL A,#3FH ;STRIP OFF THE GARBAGE
+ ;
+ISTA1: RL A ;ROTATE FOR OFFSET
+ ADD A,DPL ;BUMP
+ MOV DPL,A ;SAVE IT
+ CLR A
+ MOVC A,@A+DPTR ;GET HIGH BYTE
+ PUSH ACC ;SAVE IT
+ INC DPTR
+ CLR A
+ MOVC A,@A+DPTR ;GET LOW BYTE
+ POP DPH
+ MOV DPL,A
+ ;
+AC1: CLR A
+ JMP @A+DPTR ;GO DO IT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routine - LET
+ ;
+ ;***************************************************************
+ ;
+SLET: ACALL S_C ;CHECK FOR POSSIBLE STRING
+ JC SLET0 ;NO STRING
+ CLR LINEB ;USED STRINGS
+ ;
+ CALL X31DP ;PUT ADDRESS IN DPTR
+ MOV R7,#T_EQU ;WASTE =
+ ACALL EATC
+ ACALL GC ;GET THE NEXT CHARACTER
+ CJNE A,#'"',S_3 ;CHECK FOR A "
+ MOV R7,S_LEN ;GET THE STRING LENGTH
+ ;
+S_0: ACALL GCI1 ;BUMP PAST "
+ ACALL DELTST ;CHECK FOR DELIMITER
+ JZ INTERX ;EXIT IF CARRIAGE RETURN
+ MOVX @DPTR,A ;SAVE THE CHARACTER
+ CJNE A,#'"',S_1 ;SEE IF DONE
+ ;
+S_E: MOV A,#CR ;PUT A CR IN A
+ MOVX @DPTR,A ;SAVE CR
+ AJMP GCI1
+ ;
+S_3: PUSH DPH
+ PUSH DPL ;SAVE DESTINATION
+ ACALL S_C ;CALCULATE SOURCE
+ JC INTERX ;ERROR IF CARRY
+ POP R0B0 ;GET DESTINATION BACK
+ POP R2B0
+ ;
+SSOOP: MOV R7,S_LEN ;SET UP COUNTER
+ ;
+S_4: LCALL TBYTE ;TRANSFER THE BYTE ******AA CALL-->LCALL
+ CJNE A,#CR,$+4 ;EXIT IF A CR
+ RET
+ DJNZ R7,S_5 ;BUMP COUNTER
+ MOV A,#CR ;SAVE A CR
+ MOVX @R0,A
+ AJMP EIGP ;PRINT EXTRA IGNORED
+ ;
+ newpage
+ ;
+S_5: CALL INC3210 ;BUMP POINTERS
+ SJMP S_4 ;LOOP
+ ;
+S_1: DJNZ R7,$+8 ;SEE IF DONE
+ ACALL S_E
+ ACALL EIGP ;PRINT EXTRA IGNORED
+ AJMP FINDCR ;GO FIND THE END
+ INC DPTR ;BUMP THE STORE POINTER
+ SJMP S_0 ;CONTINUE TO LOOP
+ ;
+E3XX: MOV DPTR,#E3X ;BAD ARG ERROR
+ AJMP EK
+ ;
+SLET0: ACALL SLET1
+ AJMP POPAS ;COPY EXPRESSION TO VARIABLE
+ ;
+SLET1: ACALL VAR_ER ;CHECK FOR A"VARIABLE"
+ ;
+SLET2: PUSH R2B0 ;SAVE THE VARIABLE ADDRESS
+ PUSH R0B0
+ MOV R7,#T_EQU ;GET EQUAL TOKEN
+ ACALL WE
+ POP R1B0 ;POP VARIABLE TO R3:R1
+ POP R3B0
+ RET ;EXIT
+ ;
+R3CK: CJNE R3,#00H,E3XX ;CHECK TO SEE IF R3 IS ZERO
+ RET
+ ;
+SPEOP: ACALL GCI1 ;BUMP TXA
+ ACALL P_E ;EVALUATE PAREN
+ ACALL SLET2 ;EVALUATE AFTER =
+ CALL TWOL ;R7:R6 GETS VALUE, R3:R1 GETS LOCATION
+ MOV A,R6 ;SAVE THE VALUE
+ ;
+ CJNE R7,#00H,E3XX ;R2 MUST BE = 0
+ RET
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; ST_CAL - Calculate string Address
+ ;
+ ;**************************************************************
+ ;
+IST_CAL:;
+ ;
+ ACALL I_PI ;BUMP TEXT, THEN EVALUATE
+ ACALL R3CK ;ERROR IF R3 <> 0
+ INC R1 ;BUMP FOR OFFSET
+ MOV A,R1 ;ERROR IF R1 = 255
+ JZ E3XX
+ MOV DPTR,#VARTOP ;GET TOP OF VARIABLE STORAGE
+ MOV B,S_LEN ;MULTIPLY FOR LOCATION
+ ACALL VARD ;CALCULATE THE LOCATION
+ MOV DPTR,#MEMTOP ;SEE IF BLEW IT
+ CALL FUL1
+ MOV DPL,S_LEN ;GET STRING LENGTH, DPH = 00H
+ DEC DPH ;DPH = 0
+ ;
+DUBSUB: CLR C
+ MOV A,R1
+ SUBB A,DPL
+ MOV R1,A
+ MOV A,R3
+ SUBB A,DPH
+ MOV R3,A
+ ORL A,R1
+ RET
+ ;
+ ;***************************************************************
+ ;
+ ;VARD - Calculate the offset base
+ ;
+ ;***************************************************************
+ ;
+VARB: MOV B,#FPSIZ ;SET UP FOR OPERATION
+ ;
+VARD: CALL LDPTRI ;LOAD DPTR
+ MOV A,R1 ;MULTIPLY BASE
+ MUL AB
+ ADD A,DPL
+ MOV R1,A
+ MOV A,B
+ ADDC A,DPH
+ MOV R3,A
+ RET
+ ;
+ newpage
+ ;*************************************************************
+ ;
+CSY: ; Calculate a biased string address and put in R3:R1
+ ;
+ ;*************************************************************
+ ;
+ ACALL IST_CAL ;CALCULATE IT
+ PUSH R3B0 ;SAVE IT
+ PUSH R1B0
+ MOV R7,#',' ;WASTE THE COMMA
+ ACALL EATC
+ ACALL ONE ;GET THE NEXT EXPRESSION
+ MOV A,R1 ;CHECK FOR BOUNDS
+ CJNE A,S_LEN,$+3
+ JNC E3XX ;MUST HAVE A CARRY
+ DEC R1 ;BIAS THE POINTER
+ POP ACC ;GET VALUE LOW
+ ADD A,R1 ;ADD IT TO BASE
+ MOV R1,A ;SAVE IT
+ POP R3B0 ;GET HIGH ADDRESS
+ JNC $+3 ;PROPAGATE THE CARRY
+ INC R3
+ AJMP ERPAR ;WASTE THE RIGHT PAREN
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routine FOR
+ ;
+ ;***************************************************************
+ ;
+SFOR: ACALL SLET1 ;SET UP CONTROL VARIABLE
+ PUSH R3B0 ;SAVE THE CONTROL VARIABLE LOCATION
+ PUSH R1B0
+ ACALL POPAS ;POP ARG STACK AND COPY CONTROL VAR
+ MOV R7,#T_TO ;GET TO TOKEN
+ ACALL WE
+ ACALL GC ;GET NEXT CHARACTER
+ CJNE A,#T_STEP,SF2
+ ACALL GCI1 ;EAT THE TOKEN
+ ACALL EXPRB ;EVALUATE EXPRESSION
+ SJMP $+5 ;JUMP OVER
+ ;
+SF2: LCALL PUSH_ONE ;PUT ONE ON THE STACK
+ ;
+ MOV A,#-FSIZE ;ALLOCATE FSIZE BYTES ON THE CONTROL STACK
+ ACALL PUSHCS ;GET CS IN R0
+ ACALL CSC ;CHECK CONTROL STACK
+ MOV R3,#CSTKAH ;IN CONTROL STACK
+ MOV R1,R0B0 ;STACK ADDRESS
+ ACALL POPAS ;PUT STEP ON STACK
+ ACALL POPAS ;PUT LIMIT ON STACK
+ ACALL DP_T ;DPTR GETS TEXT
+ MOV R0,R1B0 ;GET THE POINTER
+ ACALL T_X_S ;SAVE THE TEXT
+ POP TXAL ;GET CONTROL VARIABLE
+ POP TXAH
+ MOV R4,#FTYPE ;AND THE TYPE
+ ACALL T_X_S ;SAVE IT
+ ;
+SF3: ACALL T_DP ;GET THE TEXT POINTER
+ AJMP ILOOP ;CONTINUE TO PROCESS
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; The statement action routines - PUSH and POP
+ ;
+ ;**************************************************************
+ ;
+SPUSH: ACALL EXPRB ;PUT EXPRESSION ON STACK
+ ACALL C_TST ;SEE IF MORE TO DO
+ JNC SPUSH ;IF A COMMA PUSH ANOTHER
+ RET
+ ;
+ ;
+SPOP: ACALL VAR_ER ;GET VARIABLE
+ ACALL XPOP ;FLIP THE REGISTERS FOR POPAS
+ ACALL C_TST ;SEE IF MORE TO DO
+ JNC SPOP
+ ;
+ RET
+ ;
+ ;***************************************************************
+ ;
+ ; The statement action routine - IF
+ ;
+ ;***************************************************************
+ ;
+SIF: ACALL RTST ;EVALUATE THE EXPRESSION
+ MOV R1,A ;SAVE THE RESULT
+ ACALL GC ;GET THE CHARACTER AFTER EXPR
+ CJNE A,#T_THEN,$+5 ;SEE IF THEN TOKEN
+ ACALL GCI1 ;WASTE THEN TOKEN
+ CJNE R1,#0,T_F1 ;CHECK R_OP RESULT
+ ;
+E_FIND: MOV R7,#T_ELSE ;FIND ELSE TOKEN
+ ACALL FINDC
+ JZ SIF-1 ;EXIT IF A CR
+ ACALL GCI1 ;BUMP PAST TOKEN
+ CJNE A,#T_ELSE,E_FIND;WASTE IF NO ELSE
+ ;
+T_F1: ACALL INTGER ;SEE IF NUMBER
+ JNC D_L1 ;EXECUTE LINE NUMBER
+ AJMP ISTAT ;EXECUTE STATEMENT IN NOT
+ ;
+B_C: MOVX A,@DPTR
+ DEC A
+ JB ACC.7,FL3-5
+ RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routine - GOTO
+ ;
+ ;***************************************************************
+ ;
+SGOTO: ACALL RLINE ;R2:R0 AND DPTR GET INTGER
+ ;
+SGT1: ACALL T_DP ;TEXT POINTER GETS DPTR
+ ;
+ JBC RETBIT,SGT2 ;SEE IF RETI EXECUTED
+ ;
+ JNB LINEB,$+6 ;SEE IF A LINE WAS EDITED
+ LCALL RCLEAR-2 ;CLEAR THE MEMORY IF SET
+ AJMP ILOOP-2 ;CLEAR DIRF AND LOOP
+ ;
+SGT2: JBC OTI,$+8 ;SEE IF TIMER INTERRUPT
+ ANL 34,#10111101B ;CLEAR INTERRUPTS
+ AJMP ILOOP ;EXECUTE
+ MOV C,ISAV
+ MOV INPROG,C
+ AJMP ILOOP ;RESTORE INTERRUPTS AND RET
+ ;
+ ;
+ ;*************************************************************
+ ;
+RTST: ; Test for ZERO
+ ;
+ ;*************************************************************
+ ;
+ ACALL EXPRB ;EVALUATE EXPRESSION
+ CALL INC_ASTKA ;BUMP ARG STACK
+ JZ $+4 ;EXIT WITH ZERO OR 0FFH
+ MOV A,#0FFH
+ RET
+ ;
+ newpage
+ ;
+ ;**************************************************************
+ ;
+ ; GLN - get the line number in R2:R0, return in DPTR
+ ;
+ ;**************************************************************
+ ;
+GLN: ACALL DP_B ;GET THE BEGINNING ADDRESS
+ ;
+FL1: MOVX A,@DPTR ;GET THE LENGTH
+ MOV R7,A ;SAVE THE LENGTH
+ DJNZ R7,FL3 ;SEE IF END OF FILE
+ ;
+ MOV DPTR,#E10X ;NO LINE NUMBER
+ AJMP EK ;HANDLE THE ERROR
+ ;
+FL3: JB ACC.7,$-5 ;CHECK FOR BIT 7
+ INC DPTR ;POINT AT HIGH BYTE
+ MOVX A,@DPTR ;GET HIGH BYTE
+ CJNE A,R2B0,FL2 ;SEE IF MATCH
+ INC DPTR ;BUMP TO LOW BYTE
+ DEC R7 ;ADJUST AGAIN
+ MOVX A,@DPTR ;GET THE LOW BYTE
+ CJNE A,R0B0,FL2 ;SEE IF LOW BYTE MATCH
+ INC DPTR ;POINT AT FIRST CHARACTER
+ RET ;FOUND IT
+ ;
+FL2: MOV A,R7 ;GET THE LENGTH COUNTER
+ CALL ADDPTR ;ADD A TO DATA POINTER
+ SJMP FL1 ;LOOP
+ ;
+ ;
+ ;*************************************************************
+ ;
+ ;RLINE - Read in ASCII string, get line, and clean it up
+ ;
+ ;*************************************************************
+ ;
+RLINE: ACALL INTERR ;GET THE INTEGER
+ ;
+RL1: ACALL GLN
+ AJMP CLN_UP
+ ;
+ ;
+D_L1: ACALL GLN ;GET THE LINE
+ AJMP SGT1 ;EXECUTE THE LINE
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routines WHILE and UNTIL
+ ;
+ ;***************************************************************
+ ;
+SWHILE: ACALL RTST ;EVALUATE RELATIONAL EXPRESSION
+ CPL A
+ SJMP S_WU
+ ;
+SUNTIL: ACALL RTST ;EVALUATE RELATIONAL EXPRESSION
+ ;
+S_WU: MOV R4,#DTYPE ;DO EXPECTED
+ MOV R5,A ;SAVE R_OP RESULT
+ SJMP SR0 ;GO PROCESS
+ ;
+ ;
+ ;***************************************************************
+ ;
+CNULL: ; The Command Action Routine - NULL
+ ;
+ ;***************************************************************
+ ;
+ ACALL INTERR ;GET AN INTEGER FOLLOWING NULL
+ MOV NULLCT,R0 ;SAVE THE NULLCOUNT
+ AJMP CMNDLK ;JUMP TO COMMAND MODE
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routine - RETI
+ ;
+ ;***************************************************************
+ ;
+SRETI: SETB RETBIT ;SAYS THAT RETI HAS BEEN EXECUTED
+ ;
+ ;***************************************************************
+ ;
+ ; The statement action routine - RETURN
+ ;
+ ;***************************************************************
+ ;
+SRETRN: MOV R4,#GTYPE ;MAKE SURE OF GOSUB
+ MOV R5,#55H ;TYPE RETURN TYPE
+ ;
+SR0: ACALL CSETUP ;SET UP CONTROL STACK
+ MOVX A,@R0 ;GET RETURN TEXT ADDRESS
+ MOV DPH,A
+ INC R0
+ MOVX A,@R0
+ MOV DPL,A
+ INC R0 ;POP CONTROL STACK
+ MOVX A,@DPTR ;SEE IF GOSUB WAS THE LAST STATEMENT
+ CJNE A,#EOF,$+5
+ AJMP CMNDLK
+ MOV A,R5 ;GET TYPE
+ JZ SGT1 ;EXIT IF ZERO
+ MOV CSTKA,R0 ;POP THE STACK
+ CPL A ;OPTION TEST, 00H, 55H, 0FFH, NOW 55H
+ JNZ SGT1 ;MUST BE GOSUB
+ RET ;NORMAL FALL THRU EXIT FOR NO MATCH
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routine - GOSUB
+ ;
+ ;***************************************************************
+ ;
+SGOSUB: ACALL RLINE ;NEW TXA IN DPTR
+ ;
+SGS0: MOV R4,#GTYPE
+ ACALL SGS1 ;SET EVERYTHING UP
+ AJMP SF3 ;EXIT
+ ;
+SGS1: MOV A,#-3 ;ALLOCATE 3 BYTES ON CONTROL STACK
+ ACALL PUSHCS
+ ;
+T_X_S: MOV P2,#CSTKAH ;SET UP PORT FOR CONTROL STACK
+ MOV A,TXAL ;GET RETURN ADDRESS AND SAVE IT
+ MOVX @R0,A
+ DEC R0
+ MOV A,TXAH
+ MOVX @R0,A
+ DEC R0
+ MOV A,R4 ;GET TYPE
+ MOVX @R0,A ;SAVE TYPE
+ RET ;EXIT
+ ;
+ ;
+CS1: MOV A,#3 ;POP 3 BYTES
+ ACALL PUSHCS
+ ;
+CSETUP: MOV R0,CSTKA ;GET CONTROL STACK
+ MOV P2,#CSTKAH
+ MOVX A,@R0 ;GET BYTE
+ CJNE A,R4B0,$+5 ;SEE IF TYPE MATCH
+ INC R0
+ RET
+ JZ E4XX ;EXIT IF STACK UNDERFLOW
+ CJNE A,#FTYPE,CS1 ;SEE IF FOR TYPE
+ ACALL PUSHCS-2 ;WASTE THE FOR TYPE
+ SJMP CSETUP ;LOOP
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routine - NEXT
+ ;
+ ;***************************************************************
+ ;
+SNEXT: MOV R4,#FTYPE ;FOR TYPE
+ ACALL CSETUP ;SETUP CONTROL STACK
+ MOV TEMP5,R0 ;SAVE CONTROL VARIABLE ADDRESS
+ MOV R1,#TEMP1 ;SAVE VAR + RETURN IN TEMP1-4
+ ;
+XXI: MOVX A,@R0 ;LOOP UNTIL DONE
+ MOV @R1,A
+ INC R1
+ INC R0
+ CJNE R1,#TEMP5,XXI
+ ;
+ ACALL VAR ;SEE IF THE USER HAS A VARIABLE
+ JNC $+6
+ MOV R2,TEMP1
+ MOV R0,TEMP2
+ MOV A,R2 ;SEE IF VAR'S AGREE
+ CJNE A,TEMP1,E4XX
+ MOV A,R0
+ CJNE A,TEMP2,E4XX
+ ACALL PUSHAS ;PUT CONTROL VARIABLE ON STACK
+ MOV A,#FPSIZ+FPSIZ+2;COMPUTE ADDRESS TO STEP VALUE SIGN
+ ADD A,TEMP5 ;ADD IT TO BASE OF STACK
+ MOV R0,A ;SAVE IN R0
+ MOV R2,#CSTKAH ;SET UP TO PUSH STEP VALUE
+ MOV P2,R2 ;SET UP PORT
+ MOVX A,@R0 ;GET SIGN
+ INC R0 ;BACK TO EXPONENT
+ PUSH ACC ;SAVE SIGN OF STEP
+ ACALL PUSHAS ;PUT STEP VALUE ON STACK
+ PUSH R0B0 ;SAVE LIMIT VALUE LOCATION
+ CALL AADD ;ADD STEP VALUE TO VARIABLE
+ CALL CSTAKA ;COPY STACK
+ MOV R3,TEMP1 ;GET CONTROL VARIABLE
+ MOV R1,TEMP2
+ ACALL POPAS ;SAVE THE RESULT
+ MOV R2,#CSTKAH ;RESTORE LIMIT LOCATION
+ POP R0B0
+ ACALL PUSHAS ;PUT LIMIT ON STACK
+ CALL FP_BASE+4 ;DO THE COMPARE
+ POP ACC ;GET LIMIT SIGN BACK
+ JZ $+3 ;IF SIGN NEGATIVE, TEST "BACKWARDS"
+ CPL C
+ ORL C,F0 ;SEE IF EQUAL
+ JC N4 ;STILL SMALLER THAN LIMIT?
+ MOV A,#FSIZE ;REMOVE CONTROL STACK ENTRY
+ ;
+ ; Fall thru to PUSHCS
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; PUSHCS - push frame onto control stack
+ ; acc has - number of bytes, also test for overflow
+ ;
+ ;***************************************************************
+ ;
+PUSHCS: ADD A,CSTKA ;BUMP CONTROL STACK
+ CJNE A,#CONVT+17,$+3 ;SEE IF OVERFLOWED
+ JC E4XX ;EXIT IF STACK OVERFLOW
+ XCH A,CSTKA ;STORE NEW CONTROL STACK VALUE, GET OLD
+ DEC A ;BUMP OLD VALUE
+ MOV R0,A ;PUT OLD-1 IN R0
+ ;
+ RET ;EXIT
+ ;
+CSC: ACALL CLN_UP ;FINISH OFF THE LINE
+ JNC CSC-1 ;EXIT IF NO TERMINATOR
+ ;
+E4XX: MOV DPTR,#EXC ;CONTROL STACK ERROR
+ AJMP EK ;STACK ERROR
+ ;
+N4: MOV TXAH,TEMP3 ;GET TEXT POINTER
+ MOV TXAL,TEMP4
+ AJMP ILOOP ;EXIT
+ ;
+ ;***************************************************************
+ ;
+ ; The statement action routine - RESTORE
+ ;
+ ;***************************************************************
+ ;
+SRESTR: ACALL X_TR ;SWAP POINTERS
+ ACALL DP_B ;GET THE STARTING ADDRESS
+ ACALL T_DP ;PUT STARTING ADDRESS IN TEXT POINTER
+ ACALL B_TXA ;BUMP TXA
+ ;
+ ; Fall thru
+ ;
+X_TR: ;swap txa and rtxa
+ ;
+ XCH A,TXAH
+ XCH A,RTXAH
+ XCH A,TXAH
+ XCH A,TXAL
+ XCH A,RTXAL
+ XCH A,TXAL
+ RET ;EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routine - READ
+ ;
+ ;***************************************************************
+ ;
+SREAD: ACALL X_TR ;SWAP POINTERS
+ ;
+SRD0: ACALL C_TST ;CHECK FOR COMMA
+ JC SRD4 ;SEE WHAT IT IS
+ ;
+SRD: ACALL EXPRB ;EVALUATE THE EXPRESSION
+ ACALL GC ;GET THE CHARACTER AFTER EXPRESSION
+ CJNE A,#',',SRD1 ;SEE IF MORE DATA
+ SJMP SRD2 ;BYBASS CLEAN UP IF A COMMA
+ ;
+SRD1: ACALL CLN_UP ;FINISH OFF THE LINE, IF AT END
+ ;
+SRD2: ACALL X_TR ;RESTORE POINTERS
+ ACALL VAR_ER ;GET VARIABLE ADDRESS
+ ACALL XPOP ;FLIP THE REGISTERS FOR POPAS
+ ACALL C_TST ;SEE IF A COMMA
+ JNC SREAD ;READ AGAIN IF A COMMA
+ RET ;EXIT IF NOT
+ ;
+SRD4: CJNE A,#T_DATA,SRD5 ;SEE IF DATA
+ ACALL GCI1 ;BUMP POINTER
+ SJMP SRD
+ ;
+SRD5: CJNE A,#EOF,SRD6 ;SEE IF YOU BLEW IT
+ ACALL X_TR ;GET THE TEXT POINTER BACK
+ MOV DPTR,#E14X ;READ ERROR
+ ;
+EK: LJMP ERROR
+ ;
+SRD6: ACALL FINDCR ;WASTE THIS LINE
+ ACALL CLN_UP ;CLEAN IT UP
+ JC SRD5+3 ;ERROR IF AT END
+ SJMP SRD0
+ ;
+NUMC: ACALL GC ;GET A CHARACTER
+ CJNE A,#'#',NUMC1 ;SEE IF A #
+ SETB COB ;VALID LINE PRINT
+ AJMP IGC ;BUMP THE TEXT POINTER
+ ;
+NUMC1: CJNE A,#'@',SRD4-1 ;EXIT IF NO GOOD
+ SETB LPB
+ AJMP IGC
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routine - PRINT
+ ;
+ ;***************************************************************
+ ;
+SPH0: SETB ZSURP ;NO ZEROS
+ ;
+SPH1: SETB HMODE ;HEX MODE
+ ;
+SPRINT: ACALL NUMC ;TEST FOR A LINE PRINT
+ ACALL $+9 ;PROCEED
+ ANL 35,#11110101B ;CLEAR COB AND LPB
+ ANL 38,#00111111B ;NO HEX MODE
+ ;
+ RET
+ ;
+ ACALL DELTST ;CHECK FOR A DELIMITER
+ JC SP1
+ ;
+SP0: JMP CRLF ;EXIT WITH A CR IF SO
+ ;
+SP2: ACALL C_TST ;CHECK FOR A COMMA
+ JC SP0 ;EXIT IF NO COMMA
+ ;
+SP1: ACALL CPS ;SEE IF A STRING TO PRINT
+ JNC SP2 ;IF A STRING, CHECK FOR A COMMA
+ ;
+SP4: CJNE A,#T_TAB,SP6
+ ACALL I_PI ;ALWAYS CLEARS CARRY
+ SUBB A,PHEAD ;TAKE DELTA BETWEEN TAB AND PHEAD
+ JC SP2 ;EXIT IF PHEAD > TAB
+ SJMP SP7 ;OUTPUT SPACES
+ ;
+SP6: CJNE A,#T_SPC,SM
+ ACALL I_PI ;SET UP PAREN VALUE
+ ;
+SP7: JZ SP2
+ LCALL STEROT ;OUTPUT A SPACE
+ DEC A ;DECREMENT COUNTER
+ SJMP SP7 ;LOOP
+ ;
+ newpage
+SM: CJNE A,#T_CHR,SP8
+ ACALL IGC
+ CJNE A,#'$',$+9
+ ACALL CNX ;PUT THE CHARACTER ON THE STACK
+ ACALL IFIXL ;PUT THE CHARACTER IN R1
+ SJMP $+6
+ ACALL ONE ;EVALUATE THE EXPRESSION, PUT IN R3:R1
+ ACALL ERPAR
+ MOV R5,R1B0 ;BYTE TO OUTPUT
+ SJMP SQ
+ ;
+SP8: CJNE A,#T_CR,SX
+ ACALL GCI1 ;EAT THE TOKEN
+ MOV R5,#CR
+ ;
+SQ: CALL TEROT
+ SJMP SP2 ;OUTPUT A CR AND DO IT AGAIN
+ ;
+SX: CJNE A,#T_USE,SP9 ;USING TOKEN
+ ACALL IGC ;GE THE CHARACTER AFTER THE USING TOKEN
+ CJNE A,#'F',U4 ;SEE IF FLOATING
+ MOV FORMAT,#0F0H ;SET FLOATING
+ ACALL IGC ;BUMP THE POINTER AND GET THE CHARACTER
+ ACALL GCI1 ;BUMP IT AGAIN
+ ANL A,#0FH ;STRIP OFF ASCII BIAS
+ JZ U3 ;EXIT IF ZERO
+ CJNE A,#3,$+3 ;SEE IF AT LEAST A THREE
+ JNC U3 ;FORCE A THREE IF NOT A THREE
+ MOV A,#3
+ ;
+U3: ORL FORMAT,A ;PUT DIGIT IN FORMAT
+ SJMP U8 ;CLEAN UP END
+ ;
+U4: CJNE A,#'0',U5
+ MOV FORMAT,#0 ;FREE FORMAT
+ ACALL GCI1 ;BUMP THE POINTER
+ SJMP U8
+ ;
+U5: CJNE A,#'#',U8 ;SEE IF INTGER FORMAT
+ ACALL U6
+ MOV FORMAT,R7 ;SAVE THE FORMAT
+ CJNE A,#'.',U8A ;SEE IF TERMINATOR WAS RADIX
+ ACALL IGC ;BUMP PAST .
+ ACALL U6 ;LOOP AGAIN
+ MOV A,R7 ;GET COUNT
+ ADD A,FORMAT ;SEE IF TOO BIG
+ ADD A,#0F7H
+ JNC U5A
+ ;
+ newpage
+SE0: AJMP INTERX ;ERROR, BAD SYNTAX
+ ;
+U5A: MOV A,R7 ;GET THE COUNT BACK
+ SWAP A ;ADJUST
+ ORL FORMAT,A ;GET THE COUNT
+ ;
+U8A: MOV A,FORMAT
+ ;
+U8B: SWAP A ;GET THE FORMAT RIGHT
+ MOV FORMAT,A
+ ;
+U8: ACALL ERPAR
+ AJMP SP2 ;DONE
+ ;
+U6: MOV R7,#0 ;SET COUNTER
+ ;
+U7: CJNE A,#'#',SP9A ;EXIT IF NOT A #
+ INC R7 ;BUMP COUNTER
+ ACALL IGC ;GET THE NEXT CHARACTER
+ SJMP U7 ;LOOP
+ ;
+SP9: ACALL DELTST+2 ;CHECK FOR DELIMITER
+ JNC SP9A ;EXIT IF A DELIMITER
+ ;
+ CJNE A,#T_ELSE,SS
+ ;
+SP9A: RET ;EXIT IF ELSE TOKEN
+ ;
+ ;**************************************************************
+ ;
+ ; P_E - Evaluate an expression in parens ( )
+ ;
+ ;**************************************************************
+ ;
+P_E: MOV R7,#T_LPAR
+ ACALL WE
+ ;
+ERPAR: MOV R7,#')' ;EAT A RIGHT PAREN
+ ;
+EATC: ACALL GCI ;GET THE CHARACTER
+ CJNE A,R7B0,SE0 ;ERROR IF NOT THE SAME
+ RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+S_ON: ; ON Statement
+ ;
+ ;***************************************************************
+ ;
+ ACALL ONE ;GET THE EXPRESSION
+ ACALL GCI ;GET THE NEXT CHARACTER
+ CJNE A,#T_GOTO,C0
+ ACALL C1 ;EAT THE COMMAS
+ AJMP SF3 ;DO GOTO
+ ;
+C0: CJNE A,#T_GOSB,SE0
+ ACALL C1
+ AJMP SGS0 ;DO GOSUB
+ ;
+C1: CJNE R1,#0,C2
+ ACALL INTERR ;GET THE LINE NUMBER
+ ACALL FINDCR
+ AJMP RL1 ;FINISH UP THIS LINE
+ ;
+C2: MOV R7,#','
+ ACALL FINDC
+ CJNE A,#',',SE0 ;ERROR IF NOT A COMMA
+ DEC R1
+ ACALL GCI1 ;BUMP PAST COMMA
+ SJMP C1
+ ;
+ newpage
+ ;
+SS: ACALL S_C ;SEE IF A STRING
+ JC SA ;NO STRING IF CARRY IS SET
+ LCALL UPRNT ;PUT POINTER IN DPTR
+ AJMP SP2 ;SEE IF MORE
+ ;
+SA: ACALL EXPRB ;MUST BE AN EXPRESSION
+ MOV A,#72
+ CJNE A,PHEAD,$+3 ;CHECK PHEAD POSITION
+ JNC $+4
+ ACALL SP0 ;FORCE A CRLF
+ JNB HMODE,S13 ;HEX MODE?
+ CALL FCMP ;SEE IF TOS IS < 0FFFH
+ JC S13 ;EXIT IF GREATER
+ CALL AABS ;GET THE SIGN
+ JNZ OOPS ;WASTE IF NEGATIVE
+ ACALL IFIXL
+ CALL FP_BASE+22 ;PRINT HEXMODE
+ AJMP SP2
+OOPS: CALL ANEG ;MAKE IT NEGATIVE
+ ;
+S13: CALL FP_BASE+14 ;DO FP OUTPUT
+ MOV A,#1 ;OUTPUT A SPACE
+ AJMP SP7
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; ANU - Get variable name from text - set carry if not found
+ ; if succeeds returns variable in R7:R6
+ ; R6 = 0 if no digit in name
+ ;
+ ;***************************************************************
+ ;
+ANU: ACALL IGC ;INCREMENT AND GET CHARACTER
+ LCALL 1FEDH ;CHECK FOR DIGIT
+ JC $+14 ;EXIT IF VALID DIGIT
+ CJNE A,#'_',$+4 ;SEE IF A _
+ RET
+ ;
+AL: CJNE A,#'A',$+3 ;IS IT AN ASCII A?
+ JC $+6 ;EXIT IF CARRY IS SET
+ CJNE A,#'Z'+1,$+3 ;IS IT LESS THAN AN ASCII Z
+ CPL C ;FLIP CARRY
+ RET
+ ;
+ JNB F0,VAR2
+ ;
+SD0: MOV DPTR,#E6X
+ AJMP EK
+ ;
+SDIMX: SETB F0 ;SAYS DOING A DIMENSION
+ SJMP VAR1
+ ;
+VAR: CLR F0 ;SAYS DOING A VARIABLE
+ ;
+VAR1: ACALL GC ;GET THE CHARACTER
+ ACALL AL ;CHECK FOR ALPHA
+ JNC $+6 ;ERROR IF IN DIM
+ JB F0,SD0
+ RET
+ MOV R7,A ;SAVE ALPHA CHARACTER
+ CLR A ;ZERO IN CASE OF FAILURE
+ MOV R5,A ;SAVE IT
+ ;
+VY: MOV R6,A
+ ACALL ANU ;CHECK FOR ALPHA OR NUMBER
+ JC VX ;EXIT IF NO ALPHA OR NUM
+ ;
+ XCH A,R7
+ ADD A,R5 ;NUMBER OF CHARACTERS IN ALPHABET
+ XCH A,R7 ;PUT IT BACK
+ MOV R5,#26 ;FOR THE SECOND TIME AROUND
+ SJMP VY
+ ;
+VX: CLR LINEB ;TELL EDITOR A VARIABLE IS DECLARED
+ CJNE A,#T_LPAR,V4 ;SEE IF A LEFT PAREN
+ ;
+ ORL R6B0,#80H ;SET BIT 7 TO SIGINIFY MATRIX
+ CALL F_VAR ;FIND THE VARIABLE
+ PUSH R2B0 ;SAVE THE LOCATION
+ PUSH R0B0
+ JNC SD0-3 ;DEFAULT IF NOT IN TABLE
+ JB F0,SDI ;NO DEFAULT FOR DIMENSION
+ MOV R1,#10
+ MOV R3,#0
+ ACALL D_CHK
+ ;
+VAR2: ACALL PAREN_INT ;EVALUATE INTEGER IN PARENS
+ CJNE R3,#0,SD0 ;ERROR IF R3<>0
+ POP DPL ;GET VAR FOR LOOKUP
+ POP DPH
+ MOVX A,@DPTR ;GET DIMENSION
+ DEC A ;BUMP OFFSET
+ SUBB A,R1 ;A MUST BE > R1
+ JC SD0
+ LCALL DECDP2 ;BUMP POINTER TWICE
+ ACALL VARB ;CALCULATE THE BASE
+ ;
+X3120: XCH A,R1 ;SWAP R2:R0, R3:R1
+ XCH A,R0
+ XCH A,R1
+ XCH A,R3
+ XCH A,R2
+ XCH A,R3
+ RET
+ ;
+V4: JB F0,SD0 ;ERROR IF NO LPAR FOR DIM
+ LCALL F_VAR ;GET SCALAR VARIABLE
+ CLR C
+ RET
+ ;
+ newpage
+ ;
+SDI: ACALL PAREN_INT ;EVALUATE PAREN EXPRESSION
+ CJNE R3,#0,SD0 ;ERROR IF NOT ZERO
+ POP R0B0 ;SET UP R2:R0
+ POP R2B0
+ ACALL D_CHK ;DO DIM
+ ACALL C_TST ;CHECK FOR COMMA
+ JNC SDIMX ;LOOP IF COMMA
+ RET ;RETURN IF NO COMMA
+ ;
+D_CHK: INC R1 ;BUMP FOR TABLE LOOKUP
+ MOV A,R1
+ JZ SD0 ;ERROR IF 0FFFFH
+ MOV R4,A ;SAVE FOR LATER
+ MOV DPTR,#MT_ALL ;GET MATRIX ALLOCATION
+ ACALL VARB ;DO THE CALCULATION
+ MOV R7,DPH ;SAVE MATRIX ALLOCATION
+ MOV R6,DPL
+ MOV DPTR,#ST_ALL ;SEE IF TOO MUCH MEMORY TAKEN
+ CALL FUL1 ;ST_ALL SHOULD BE > R3:R1
+ MOV DPTR,#MT_ALL ;SAVE THE NEW MATRIX POINTER
+ CALL S31DP
+ MOV DPL,R0 ;GET VARIABLE ADDRESS
+ MOV DPH,R2
+ MOV A,R4 ;DIMENSION SIZE
+ MOVX @DPTR,A ;SAVE IT
+ CALL DECDP2 ;SAVE TARGET ADDRESS
+ ;
+R76S: MOV A,R7
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,R6 ;ELEMENT SIZE
+ MOVX @DPTR,A
+ RET ;R2:R0 STILL HAS SYMBOL TABLE ADDRESS
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The statement action routine - INPUT
+ ;
+ ;***************************************************************
+ ;
+SINPUT: ACALL CPS ;PRINT STRING IF THERE
+ ;
+ ACALL C_TST ;CHECK FOR A COMMA
+ JNC IN2A ;NO CRLF
+ ACALL SP0 ;DO A CRLF
+ ;
+IN2: MOV R5,#'?' ;OUTPUT A ?
+ CALL TEROT
+ ;
+IN2A: SETB INP_B ;DOING INPUT
+ CALL INLINE ;INPUT THE LINE
+ CLR INP_B
+ MOV TEMP5,#HI(IBUF)
+ MOV TEMP4,#LO(IBUF)
+ ;
+IN3: ACALL S_C ;SEE IF A STRING
+ JC IN3A ;IF CARRY IS SET, NO STRING
+ ACALL X3120 ;FLIP THE ADDRESSES
+ MOV R3,TEMP5
+ MOV R1,TEMP4
+ ACALL SSOOP
+ ACALL C_TST ;SEE IF MORE TO DO
+ JNC IN2
+ RET
+ ;
+IN3A: CALL DTEMP ;GET THE USER LOCATION
+ CALL GET_NUM ;GET THE USER SUPPLIED NUMBER
+ JNZ IN5 ;ERROR IF NOT ZERO
+ CALL TEMPD ;SAVE THE DATA POINTER
+ ACALL VAR_ER ;GET THE VARIABLE
+ ACALL XPOP ;SAVE THE VARIABLE
+ CALL DTEMP ;GET DPTR BACK FROM VAR_ER
+ ACALL C_TST ;SEE IF MORE TO DO
+ JC IN6 ;EXIT IF NO COMMA
+ MOVX A,@DPTR ;GET INPUT TERMINATOR
+ CJNE A,#',',IN5 ;IF NOT A COMMA DO A CR AND TRY AGAIN
+ INC DPTR ;BUMP PAST COMMA AND READ NEXT VALUE
+ CALL TEMPD
+ SJMP IN3
+ ;
+ newpage
+ ;
+IN5: MOV DPTR,#IAN ;PRINT INPUT A NUMBER
+ CALL CRP ;DO A CR, THEN, PRINT FROM ROM
+ LJMP CC1 ;TRY IT AGAIN
+ ;
+IN6: MOVX A,@DPTR
+ CJNE A,#CR,EIGP
+ RET
+ ;
+EIGP: MOV DPTR,#EIG
+ CALL CRP ;PRINT THE MESSAGE AND EXIT
+ AJMP SP0 ;EXIT WITH A CRLF
+ ;
+ ;***************************************************************
+ ;
+SOT: ; On timer interrupt
+ ;
+ ;***************************************************************
+ ;
+ ACALL TWO ;GET THE NUMBERS
+ MOV SP_H,R3
+ MOV SP_L,R1
+ MOV DPTR,#TIV ;SAVE THE NUMBER
+ SETB OTS
+ AJMP R76S ;EXIT
+ ;
+ ;
+ ;***************************************************************
+ ;
+SCALL: ; Call a user rountine
+ ;
+ ;***************************************************************
+ ;
+ ACALL INTERR ;CONVERT INTEGER
+ CJNE R2,#0,S_C_1 ;SEE IF TRAP
+ MOV A,R0
+ JB ACC.7,S_C_1
+ ADD A,R0
+ MOV DPTR,#4100H
+ MOV DPL,A
+ ;
+S_C_1: ACALL AC1 ;JUMP TO USER PROGRAM
+ ANL PSW,#11100111B ;BACK TO BANK 0
+ RET ;EXIT
+ ;
+ newpage
+ ;**************************************************************
+ ;
+THREE: ; Save value for timer function
+ ;
+ ;**************************************************************
+ ;
+ ACALL ONE ;GET THE FIRST INTEGER
+ CALL CBIAS ;BIAS FOR TIMER LOAD
+ MOV T_HH,R3
+ MOV T_LL,R1
+ MOV R7,#',' ;WASTE A COMMA
+ ACALL EATC ;FALL THRU TO TWO
+ ;
+ ;**************************************************************
+ ;
+TWO: ; Get two values seperated by a comma off the stack
+ ;
+ ;**************************************************************
+ ;
+ ACALL EXPRB
+ MOV R7,#',' ;WASTE THE COMMA
+ ACALL WE
+ JMP TWOL ;EXIT
+ ;
+ ;*************************************************************
+ ;
+ONE: ; Evaluate an expression and get an integer
+ ;
+ ;*************************************************************
+ ;
+ ACALL EXPRB ;EVALUATE EXPERSSION
+ ;
+IFIXL: CALL IFIX ;INTEGERS IN R3:R1
+ MOV A,R1
+ RET
+ ;
+ ;
+ ;*************************************************************
+ ;
+I_PI: ; Increment text pointer then get an integer
+ ;
+ ;*************************************************************
+ ;
+ ACALL GCI1 ;BUMP TEXT, THEN GET INTEGER
+ ;
+PAREN_INT:; Get an integer in parens ( )
+ ;
+ ACALL P_E
+ SJMP IFIXL
+ ;
+ newpage
+ ;
+DP_B: MOV DPH,BOFAH
+ MOV DPL,BOFAL
+ RET
+ ;
+DP_T: MOV DPH,TXAH
+ MOV DPL,TXAL
+ RET
+ ;
+CPS: ACALL GC ;GET THE CHARACTER
+ CJNE A,#'"',NOPASS ;EXIT IF NO STRING
+ ACALL DP_T ;GET TEXT POINTER
+ INC DPTR ;BUMP PAST "
+ MOV R4,#'"'
+ CALL PN0 ;DO THE PRINT
+ INC DPTR ;GO PAST QUOTE
+ CLR C ;PASSED TEST
+ ;
+T_DP: MOV TXAH,DPH ;TEXT POINTER GETS DPTR
+ MOV TXAL,DPL
+ RET
+ ;
+ ;*************************************************************
+ ;
+S_C: ; Check for a string
+ ;
+ ;*************************************************************
+ ;
+ ACALL GC ;GET THE CHARACTER
+ CJNE A,#'$',NOPASS ;SET CARRY IF NOT A STRING
+ AJMP IST_CAL ;CLEAR CARRY, CALCULATE OFFSET
+ ;
+ ;
+ ;
+ ;**************************************************************
+ ;
+C_TST: ACALL GC ;GET A CHARACTER
+ CJNE A,#',',NOPASS ;SEE IF A COMMA
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ;GC AND GCI - GET A CHARACTER FROM TEXT (NO BLANKS)
+ ; PUT CHARACTER IN THE ACC
+ ;
+ ;***************************************************************
+ ;
+IGC: ACALL GCI1 ;BUMP POINTER, THEN GET CHARACTER
+ ;
+GC: SETB RS0 ;USE BANK 1
+ MOV P2,R2 ;SET UP PORT 2
+ MOVX A,@R0 ;GET EXTERNAL BYTE
+ CLR RS0 ;BACK TO BANK 0
+ RET ;EXIT
+ ;
+GCI: ACALL GC
+ ;
+ ; This routine bumps txa by one and always clears the carry
+ ;
+GCI1: SETB RS0 ;BANK 1
+ INC R0 ;BUMP TXA
+ CJNE R0,#0,$+4
+ INC R2
+ CLR RS0
+ RET ;EXIT
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; Check delimiters
+ ;
+ ;**************************************************************
+ ;
+DELTST: ACALL GC ;GET A CHARACTER
+ CJNE A,#CR,DT1 ;SEE IF A CR
+ CLR A
+ RET
+ ;
+DT1: CJNE A,#':',NOPASS ;SET CARRY IF NO MATCH
+ ;
+L_RET: RET
+ ;
+ ;
+ ;***************************************************************
+ ;
+ ; FINDC - Find the character in R7, update TXA
+ ;
+ ;***************************************************************
+ ;
+FINDCR: MOV R7,#CR ;KILL A STATEMENT LINE
+ ;
+FINDC: ACALL DELTST
+ JNC L_RET
+ ;
+ CJNE A,R7B0,FNDCL2 ;MATCH?
+ RET
+ ;
+FNDCL2: ACALL GCI1
+ SJMP FINDC ;LOOP
+ ;
+ ACALL GCI1
+ ;
+WCR: ACALL DELTST ;WASTE UNTIL A "REAL" CR
+ JNZ WCR-2
+ RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; VAR_ER - Check for a variable, exit if error
+ ;
+ ;***************************************************************
+ ;
+VAR_ER: ACALL VAR
+ SJMP INTERR+2
+ ;
+ ;
+ ;***************************************************************
+ ;
+ ; S_D0 - The Statement Action Routine DO
+ ;
+ ;***************************************************************
+ ;
+S_DO: ACALL CSC ;FINISH UP THE LINE
+ MOV R4,#DTYPE ;TYPE FOR STACK
+ ACALL SGS1 ;SAVE ON STACK
+ AJMP ILOOP ;EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; CLN_UP - Clean up the end of a statement, see if at end of
+ ; file, eat character and line count after CR
+ ;
+ ;***************************************************************
+ ;
+C_2: CJNE A,#':',C_1 ;SEE IF A TERMINATOR
+ AJMP GCI1 ;BUMP POINTER AND EXIT, IF SO
+ ;
+C_1: CJNE A,#T_ELSE,EP5
+ ACALL WCR ;WASTE UNTIL A CR
+ ;
+CLN_UP: ACALL GC ;GET THE CHARACTER
+ CJNE A,#CR,C_2 ;SEE IF A CR
+ ACALL IGC ;GET THE NEXT CHARACTER
+ CJNE A,#EOF,B_TXA ;SEE IF TERMINATOR
+ ;
+NOPASS: SETB C
+ RET
+ ;
+B_TXA: XCH A,TXAL ;BUMP TXA BY THREE
+ ADD A,#3
+ XCH A,TXAL
+ JBC CY,$+4
+ RET
+ INC TXAH
+ RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; Get an INTEGER from the text
+ ; sets CARRY if not found
+ ; returns the INTGER value in DPTR and R2:R0
+ ; returns the terminator in ACC
+ ;
+ ;***************************************************************
+ ;
+INTERR: ACALL INTGER ;GET THE INTEGER
+ JC EP5 ;ERROR IF NOT FOUND
+ RET ;EXIT IF FOUND
+ ;
+INTGER: ACALL DP_T
+ CALL FP_BASE+18 ;CONVERT THE INTEGER
+ ACALL T_DP
+ MOV DPH,R2 ;PUT THE RETURNED VALUE IN THE DPTR
+ MOV DPL,R0
+ ;
+ITRET: RET ;EXIT
+ ;
+ ;
+WE: ACALL EATC ;WASTE THE CHARACTER
+ ;
+ ; Fall thru to evaluate the expression
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; EXPRB - Evaluate an expression
+ ;
+ ;***************************************************************
+ ;
+EXPRB: MOV R2,#LO(OPBOL) ;BASE PRECEDENCE
+ ;
+EP1: PUSH R2B0 ;SAVE OPERATOR PRECEDENCE
+ CLR ARGF ;RESET STACK DESIGNATOR
+ ;
+EP2: MOV A,SP ;GET THE STACK POINTER
+ ADD A,#12 ;NEED AT LEAST 12 BYTES
+ JNC $+5
+ LJMP ERROR-3
+ MOV A,ASTKA ;GET THE ARG STACK
+ SUBB A,#LO(TM_TOP+12);NEED 12 BYTES ALSO
+ JNC $+5
+ LJMP E4YY
+ JB ARGF,EP4 ;MUST BE AN OPERATOR, IF SET
+ ACALL VAR ;IS THE VALUE A VARIABLE?
+ JNC EP3 ;PUT VARIABLE ON STACK
+ ;
+ ACALL CONST ;IS THE VALUE A NUMERIC CONSTANT?
+ JNC EP4 ;IF SO, CONTINUE, IF NOT, SEE WHAT
+ CALL GC ;GET THE CHARACTER
+ CJNE A,#T_LPAR,EP4 ;SEE IF A LEFT PAREN
+ MOV A,#(LO(OPBOL+1))
+ SJMP XLPAR ;PROCESS THE LEFT PAREN
+ ;
+EP3: ACALL PUSHAS ;SAVE VAR ON STACK
+ ;
+EP4: ACALL GC ;GET THE OPERATOR
+ ;
+ CJNE A,#T_LPAR,$+3 ;IS IT AN OPERATOR
+ JNC XOP ;PROCESS OPERATOR
+ CJNE A,#T_UOP,$+3 ;IS IT A UNARY OPERATOR
+ JNC XBILT ;PROCESS UNARY (BUILT IN) OPERATOR
+ POP R2B0 ;GET BACK PREVIOUS OPERATOR PRECEDENCE
+ JB ARGF,ITRET ;OK IF ARG FLAG IS SET
+ ;
+EP5: CLR C ;NO RECOVERY
+ LJMP E1XX+2
+ ;
+ ; Process the operator
+ ;
+XOP: ANL A,#1FH ;STRIP OFF THE TOKE BITS
+ JB ARGF,XOP1 ;IF ARG FLAG IS SET, PROCESS
+ CJNE A,#T_SUB-T_LPAR,XOP3
+ MOV A,#T_NEG-T_LPAR
+ ;
+ newpage
+XOP1: ADD A,#LO(OPBOL+1) ;BIAS THE TABLE
+ MOV R2,A
+ MOV DPTR,#00H
+ MOVC A,@A+DPTR ;GET THE CURRENT PRECEDENCE
+ MOV R4,A
+ POP ACC ;GET THE PREVIOUS PRECEDENCE
+ MOV R5,A ;SAVE THE PREVIOUS PRECEDENCE
+ MOVC A,@A+DPTR ;GET IT
+ CJNE A,R4B0,$+7 ;SEE WHICH HAS HIGHER PRECEDENCE
+ CJNE A,#12,ITRET ;SEE IF ANEG
+ SETB C
+ JNC ITRET ;PROCESS NON-INCREASING PRECEDENCE
+ ;
+ ; Save increasing precedence
+ ;
+ PUSH R5B0 ;SAVE OLD PRECEDENCE ADDRESS
+ PUSH R2B0 ;SAVE NEW PRECEDENCE ADDRESS
+ ACALL GCI1 ;EAT THE OPERATOR
+ ACALL EP1 ;EVALUATE REMAINING EXPRESSION
+ POP ACC
+ ;
+ ; R2 has the action address, now setup and perform operation
+ ;
+XOP2: MOV DPTR,#OPTAB
+ ADD A,#LO(~OPBOL)
+ CALL ISTA1 ;SET UP TO RETURN TO EP2
+ AJMP EP2 ;JUMP TO EVALUATE EXPRESSION
+ ;
+ ; Built-in operator processing
+ ;
+XBILT: ACALL GCI1 ;EAT THE TOKEN
+ ADD A,#LO(50H+LO(UOPBOL))
+ JB ARGF,EP5 ;XBILT MUST COME AFTER AN OPERATOR
+ CJNE A,#STP,$+3
+ JNC XOP2
+ ;
+XLPAR: PUSH ACC ;PUT ADDRESS ON THE STACK
+ ACALL P_E
+ SJMP XOP2-2 ;PERFORM OPERATION
+ ;
+XOP3: CJNE A,#T_ADD-T_LPAR,EP5
+ ACALL GCI1
+ AJMP EP2 ;WASTE + SIGN
+ ;
+ newpage
+XPOP: ACALL X3120 ;FLIP ARGS THEN POP
+ ;
+ ;***************************************************************
+ ;
+ ; POPAS - Pop arg stack and copy variable to R3:R1
+ ;
+ ;***************************************************************
+ ;
+POPAS: LCALL INC_ASTKA
+ JMP VARCOP ;COPY THE VARIABLE
+ ;
+AXTAL: MOV R2,#HI(CXTAL)
+ MOV R0,#LO(CXTAL)
+ ;
+ ; fall thru
+ ;
+ ;***************************************************************
+ ;
+PUSHAS: ; Push the Value addressed by R2:R0 onto the arg stack
+ ;
+ ;***************************************************************
+ ;
+ CALL DEC_ASTKA
+ SETB ARGF ;SAYS THAT SOMTHING IS ON THE STACK
+ LJMP VARCOP
+ ;
+ ;
+ ;***************************************************************
+ ;
+ST_A: ; Store at expression
+ ;
+ ;***************************************************************
+ ;
+ ACALL ONE ;GET THE EXPRESSION
+ SJMP POPAS ;SAVE IT
+ ;
+ ;
+ ;***************************************************************
+ ;
+LD_A: ; Load at expression
+ ;
+ ;***************************************************************
+ ;
+ ACALL ONE ;GET THE EXPRESSION
+ ACALL X3120 ;FLIP ARGS
+ SJMP PUSHAS
+ ;
+ newpage
+ ;***************************************************************
+ ;
+CONST: ; Get a constant fron the text
+ ;
+ ;***************************************************************
+ ;
+ CALL GC ;FIRST SEE IF LITERAL
+ CJNE A,#T_ASC,C0C ;SEE IF ASCII TOKEN
+ CALL IGC ;GET THE CHARACTER AFTER TOKEN
+ CJNE A,#'$',CN0 ;SEE IF A STRING
+ ;
+CNX: CALL CSY ;CALCULATE IT
+ LJMP AXBYTE+2 ;SAVE IT ON THE STACK ******AA JMP-->LJMP
+ ;
+CN0: LCALL TWO_R2 ;PUT IT ON THE STACK ******AA CALL-->LCALL
+ CALL GCI1 ;BUMP THE POINTER
+ LJMP ERPAR ;WASTE THE RIGHT PAREN ******AA JMP-->LJMP
+ ;
+ ;
+C0C: CALL DP_T ;GET THE TEXT POINTER
+ CALL GET_NUM ;GET THE NUMBER
+ CJNE A,#0FFH,C1C ;SEE IF NO NUMBER
+ SETB C
+C2C: RET
+ ;
+C1C: JNZ FPTST
+ CLR C
+ SETB ARGF
+ ;
+C3C: JMP T_DP
+ ;
+FPTST: ANL A,#00001011B ;CHECK FOR ERROR
+ JZ C2C ;EXIT IF ZERO
+ ;
+ ; Handle the error condition
+ ;
+ MOV DPTR,#E2X ;DIVIDE BY ZERO
+ JNB ACC.0,$+6 ;UNDERFLOW
+ MOV DPTR,#E7X
+ JNB ACC.1,$+6 ;OVERFLOW
+ MOV DPTR,#E11X
+ ;
+FPTS: JMP ERROR
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The Command action routine - LIST
+ ;
+ ;***************************************************************
+ ;
+CLIST: CALL NUMC ;SEE IF TO LINE PORT
+ ACALL FSTK ;PUT 0FFFFH ON THE STACK
+ CALL INTGER ;SEE IF USER SUPPLIES LN
+ CLR A ;LN = 0 TO START
+ MOV R3,A
+ MOV R1,A
+ JC CL1 ;START FROM ZERO
+ ;
+ CALL TEMPD ;SAVE THE START ADDTESS
+ CALL GCI ;GET THE CHARACTER AFTER LIST
+ CJNE A,#T_SUB,$+10 ;CHECK FOR TERMINATION ADDRESS '-'
+ ACALL INC_ASTKA ;WASTE 0FFFFH
+ LCALL INTERR ;GET TERMINATION ADDRESS
+ ACALL TWO_EY ;PUT TERMINATION ON THE ARG STACK
+ MOV R3,TEMP5 ;GET THE START ADDTESS
+ MOV R1,TEMP4
+ ;
+CL1: CALL GETLIN ;GET THE LINE NO IN R3:R1
+ JZ CL3 ;RET IF AT END
+ ;
+CL2: ACALL C3C ;SAVE THE ADDRESS
+ INC DPTR ;POINT TO LINE NUMBER
+ ACALL PMTOP+3 ;PUT LINE NUMBER ON THE STACK
+ ACALL CMPLK ;COMPARE LN TO END ADDRESS
+ JC CL3 ;EXIT IF GREATER
+ CALL BCK ;CHECK FOR A CONTROL C
+ ACALL DEC_ASTKA ;SAVE THE COMPARE ADDRESS
+ CALL DP_T ;RESTORE ADDRESS
+ ACALL UPPL ;UN-PROCESS THE LINE
+ ACALL C3C ;SAVE THE CR ADDRESS
+ ACALL CL6 ;PRINT IT
+ INC DPTR ;BUMP POINTER TO NEXT LINE
+ MOVX A,@DPTR ;GET LIN LENGTH
+ DJNZ ACC,CL2 ;LOOP
+ ACALL INC_ASTKA ;WASTE THE COMPARE BYTE
+ ;
+CL3: AJMP CMND1 ;BACK TO COMMAND PROCESSOR
+ ;
+CL6: MOV DPTR,#IBUF ;PRINT IBUF
+ CALL PRNTCR ;PRINT IT
+ CALL DP_T
+ ;
+CL7: JMP CRLF
+ ;
+ LCALL X31DP
+ newpage
+ ;***************************************************************
+ ;
+ ;UPPL - UN PREPROCESS A LINE ADDRESSED BY DPTR INTO IBUF
+ ; RETURN SOURCE ADDRESS OF CR IN DPTR ON RETURN
+ ;
+ ;***************************************************************
+ ;
+UPPL: MOV R3,#HI(IBUF) ;POINT R3 AT HIGH IBUF
+ MOV R1,#LO(IBUF) ;POINT R1 AT IBUF
+ INC DPTR ;SKIP OVER LINE LENGTH
+ ACALL C3C ;SAVE THE DPTR (DP_T)
+ CALL L20DPI ;PUT LINE NUMBER IN R2:R0
+ CALL FP_BASE+16 ;CONVERT R2:R0 TO INTEGER
+ CALL DP_T
+ INC DPTR ;BUMP DPTR PAST THE LINE NUMBER
+ ;
+UPP0: CJNE R1,#LO(IBUF+6),$+3
+ JC UPP1A-4 ;PUT SPACES IN TEXT
+ INC DPTR ;BUMP PAST LN HIGH
+ MOVX A,@DPTR ;GET USER TEXT
+ MOV R6,A ;SAVE A IN R6 FOR TOKE COMPARE
+ JB ACC.7,UPP1 ;IF TOKEN, PROCESS
+ CJNE A,#20H,$+3 ;TRAP THE USER TOKENS
+ JNC $+5
+ CJNE A,#CR,UPP1 ;DO IT IF NOT A CR
+ CJNE A,#'"',UPP9 ;SEE IF STRING
+ ACALL UPP7 ;SAVE IT
+ ACALL UPP8 ;GET THE NEXT CHARACTER AND SAVE IT
+ CJNE A,#'"',$-2 ;LOOP ON QUOTES
+ SJMP UPP0
+ ;
+UPP9: CJNE A,#':',UPP1A ;PUT A SPACE IN DELIMITER
+ ACALL UPP7A
+ MOV A,R6
+ ACALL UPP7
+ ACALL UPP7A
+ SJMP UPP0
+ ;
+UPP1A: ACALL UPP8+2 ;SAVE THE CHARACTER, UPDATE POINTER
+ SJMP UPP0 ;EXIT IF A CR, ELSE LOOP
+ ;
+UPP1: ACALL C3C ;SAVE THE TEXT POINTER
+ MOV C,XBIT
+ MOV F0,C ;SAVE XBIT IN F0
+ MOV DPTR,#TOKTAB ;POINT AT TOKEN TABLE
+ JNB F0,UPP2
+ LCALL 2078H ;SET UP DPTR FOR LOOKUP
+ ;
+UPP2: CLR A ;ZERO A FOR LOOKUP
+ MOVC A,@A+DPTR ;GET TOKEN
+ INC DPTR ;ADVANCE THE TOKEN POINTER
+ CJNE A,#0FFH,UP_2 ;SEE IF DONE
+ JBC F0,UPP2-9 ;NOW DO NORMAL TABLE
+ AJMP CMND1 ;EXIT IF NOT FOUND
+ ;
+UP_2: CJNE A,R6B0,UPP2 ;LOOP UNTIL THE SAME
+ ;
+UP_3: CJNE A,#T_UOP,$+3
+ JNC UPP3
+ ACALL UPP7A ;PRINT THE SPACE IF OK
+ ;
+UPP3: CLR A ;DO LOOKUP
+ MOVC A,@A+DPTR
+ JB ACC.7,UPP4 ;EXIT IF DONE, ELSE SAVE
+ JZ UPP4 ;DONE IF ZERO
+ ACALL UPP7 ;SAVE THE CHARACTER
+ INC DPTR
+ SJMP UPP3 ;LOOP
+ ;
+UPP4: CALL DP_T ;GET IT BACK
+ MOV A,R6 ;SEE IF A REM TOKEN
+ XRL A,#T_REM
+ JNZ $+6
+ ACALL UPP8
+ SJMP $-2
+ JNC UPP0 ;START OVER AGAIN IF NO TOKEN
+ ACALL UPP7A ;PRINT THE SPACE IF OK
+ SJMP UPP0 ;DONE
+ ;
+UPP7A: MOV A,#' ' ;OUTPUT A SPACE
+ ;
+UPP7: AJMP PPL9+1 ;SAVE A
+ ;
+UPP8: INC DPTR
+ MOVX A,@DPTR
+ CJNE A,#CR,UPP7
+ AJMP PPL7+1
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; This table contains all of the floating point constants
+ ;
+ ; The constants in ROM are stored "backwards" from the way
+ ; basic normally treats floating point numbers. Instead of
+ ; loading from the exponent and decrementing the pointer,
+ ; ROM constants pointers load from the most significant
+ ; digits and increment the pointers. This is done to 1) make
+ ; arg stack loading faster and 2) compensate for the fact that
+ ; no decrement data pointer instruction exsist.
+ ;
+ ; The numbers are stored as follows:
+ ;
+ ; BYTE X+5 = MOST SIGNIFICANT DIGITS IN BCD
+ ; BYTE X+4 = NEXT MOST SIGNIFICANT DIGITS IN BCD
+ ; BYTE X+3 = NEXT LEAST SIGNIFICANT DIGITS IN BCD
+ ; BYTE X+2 = LEAST SIGNIFICANT DIGITS IN BCD
+ ; BYTE X+1 = SIGN OF THE ABOVE MANTISSA 0 = +, 1 = -
+ ; BYTE X = EXPONENT IN TWO'S COMPLEMENT BINARY
+ ; ZERO EXPONENT = THE NUMBER ZERO
+ ;
+ ;**************************************************************
+ ;
+ATTAB: DB 128-2 ; ARCTAN LOOKUP
+ DB 00H
+ DB 57H
+ DB 22H
+ DB 66H
+ DB 28H
+ ;
+ DB 128-1
+ DB 01H
+ DB 37H
+ DB 57H
+ DB 16H
+ DB 16H
+ ;
+ DB 128-1
+ DB 00H
+ DB 14H
+ DB 96H
+ DB 90H
+ DB 42H
+ ;
+ DB 128-1
+ DB 01H
+ DB 40H
+ DB 96H
+ DB 28H
+ DB 75H
+ ;
+ DB 128
+ DB 00H
+ DB 64H
+ DB 62H
+ DB 65H
+ DB 10H
+ ;
+ DB 128
+ DB 01H
+ DB 99H
+ DB 88H
+ DB 20H
+ DB 14H
+ ;
+ DB 128
+ DB 00H
+ DB 51H
+ DB 35H
+ DB 99H
+ DB 19H
+ ;
+ DB 128
+ DB 01H
+ DB 45H
+ DB 31H
+ DB 33H
+ DB 33H
+ ;
+ DB 129
+ DB 00H
+ DB 00H
+ DB 00H
+ DB 00H
+ DB 10H
+ ;
+ DB 0FFH ;END OF TABLE
+ ;
+NTWO: DB 129
+ DB 0
+ DB 0
+ DB 0
+ DB 0
+ DB 20H
+ ;
+TTIME: DB 128-4 ; CLOCK CALCULATION
+ DB 00H
+ DB 00H
+ DB 00H
+ DB 04H
+ DB 13H
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; COSINE - Add pi/2 to stack, then fall thru to SIN
+ ;
+ ;***************************************************************
+ ;
+ACOS: ACALL POTWO ;PUT PI/2 ON THE STACK
+ ACALL AADD ;TOS = TOS+PI/2
+ ;
+ ;***************************************************************
+ ;
+ ; SINE - use taylor series to calculate sin function
+ ;
+ ;***************************************************************
+ ;
+ASIN: ACALL PIPI ;PUT PI ON THE STACK
+ ACALL RV ;REDUCE THE VALUE
+ MOV A,MT2 ;CALCULATE THE SIGN
+ ANL A,#01H ;SAVE LSB
+ XRL MT1,A ;SAVE SIGN IN MT1
+ ACALL CSTAKA ;NOW CONVERT TO ONE QUADRANT
+ ACALL POTWO
+ ACALL CMPLK ;DO COMPARE
+ JC $+6
+ ACALL PIPI
+ ACALL ASUB
+ ACALL AABS
+ MOV DPTR,#SINTAB ;SET UP LOOKUP TABLE
+ ACALL POLYC ;CALCULATE THE POLY
+ ACALL STRIP
+ AJMP SIN0
+ ;
+ ; Put PI/2 on the stack
+ ;
+POTWO: ACALL PIPI ;PUT PI ON THE STACK, NOW DIVIDE
+ ;
+DBTWO: MOV DPTR,#NTWO
+ ACALL PUSHC
+ ;MOV A,#2 ;BY TWO
+ ;ACALL TWO_R2
+ AJMP ADIV
+ ;
+ newpage
+ ;*************************************************************
+ ;
+POLYC: ; Expand a power series to calculate a polynomial
+ ;
+ ;*************************************************************
+ ;
+ ACALL CSTAKA2 ;COPY THE STACK
+ ACALL AMUL ;SQUARE THE STACK
+ ACALL POP_T1 ;SAVE X*X
+ ACALL PUSHC ;PUT CONSTANT ON STACK
+ ;
+POLY1: ACALL PUSH_T1 ;PUT COMPUTED VALUE ON STACK
+ ACALL AMUL ;MULTIPLY CONSTANT AND COMPUTED VALUE
+ ACALL PUSHC ;PUT NEXT CONSTANT ON STACK
+ ACALL AADD ;ADD IT TO THE OLD VALUE
+ CLR A ;CHECK TO SEE IF DONE
+ MOVC A,@A+DPTR
+ CJNE A,#0FFH,POLY1 ;LOOP UNTIL DONE
+ ;
+AMUL: LCALL FP_BASE+6
+ AJMP FPTST
+ ;
+ ;*************************************************************
+ ;
+RV: ; Reduce a value for Trig and A**X functions
+ ;
+ ; value = (value/x - INT(value/x)) * x
+ ;
+ ;*************************************************************
+ ;
+ ACALL C_T2 ;COPY TOS TO T2
+ ACALL ADIV ;TOS = TOS/TEMP2
+ ACALL AABS ;MAKE THE TOS A POSITIVE NUMBER
+ MOV MT1,A ;SAVE THE SIGN
+ ACALL CSTAKA2 ;COPY THE STACK TWICE
+ ACALL IFIX ;PUT THE NUMBER IN R3:R1
+ PUSH R3B0 ;SAVE R3
+ MOV MT2,R1 ;SAVE THE LS BYTE IN MT2
+ ACALL AINT ;MAKE THE TOS AN INTEGER
+ ACALL ASUB ;TOS = TOS/T2 - INT(TOS/T2)
+ ACALL P_T2 ;TOS = T2
+ ACALL AMUL ;TOS = T2*(TOS/T2 - INT(TOS/T2)
+ POP R3B0 ;RESTORE R3
+ RET ;EXIT
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; TAN
+ ;
+ ;**************************************************************
+ ;
+ATAN: ACALL CSTAKA ;DUPLACATE STACK
+ ACALL ASIN ;TOS = SIN(X)
+ ACALL SWAP_ASTKA ;TOS = X
+ ACALL ACOS ;TOS = COS(X)
+ AJMP ADIV ;TOS = SIN(X)/COS(X)
+ ;
+STRIP: ACALL SETREG ;SETUP R0
+ MOV R3,#1 ;LOOP COUNT
+ AJMP AI2-1 ;WASTE THE LSB
+ ;
+ ;************************************************************
+ ;
+ ; ARC TAN
+ ;
+ ;************************************************************
+ ;
+AATAN: ACALL AABS
+ MOV MT1,A ;SAVE THE SIGN
+ ACALL SETREG ;GET THE EXPONENT
+ ADD A,#7FH ;BIAS THE EXPONENT
+ MOV UBIT,C ;SAVE CARRY STATUS
+ JNC $+4 ;SEE IF > 1
+ ACALL RECIP ;IF > 1, TAKE RECIP
+ MOV DPTR,#ATTAB ;SET UP TO CALCULATE THE POLY
+ ACALL POLYC ;CALCULATE THE POLY
+ JNB UBIT,SIN0 ;JUMP IF NOT SET
+ ACALL ANEG ;MAKE X POLY NEGATIVE
+ ACALL POTWO ;SUBTRACT PI/2
+ ACALL AADD
+ ;
+SIN0: MOV A,MT1 ;GET THE SIGN
+ JZ SRT
+ AJMP ANEG
+ ;
+ newpage
+ ;*************************************************************
+ ;
+ ; FCOMP - COMPARE 0FFFFH TO TOS
+ ;
+ ;*************************************************************
+ ;
+FCMP: ACALL CSTAKA ;COPY THE STACK
+ ACALL FSTK ;MAKE THE TOS = 0FFFFH
+ ACALL SWAP_ASTKA ;NOW COMPARE IS 0FFFFH - X
+ ;
+CMPLK: JMP FP_BASE+4 ;DO THE COMPARE
+ ;
+ ;*************************************************************
+ ;
+DEC_ASTKA: ;Push ARG STACK and check for underflow
+ ;
+ ;*************************************************************
+ ;
+ MOV A,#-FPSIZ
+ ADD A,ASTKA
+ CJNE A,#LO(TM_TOP+6),$+3
+ JC E4YY
+ MOV ASTKA,A
+ MOV R1,A
+ MOV R3,#ASTKAH
+ ;
+SRT: RET
+ ;
+E4YY: MOV DPTR,#EXA
+ AJMP FPTS ;ARG STACK ERROR
+ ;
+ ;
+AXTAL3: ACALL PUSHC ;PUSH CONSTANT, THEN MULTIPLY
+ ACALL AMUL
+ ;
+ ; Fall thru to IFIX
+ ;
+ newpage
+ ;***************************************************************
+ ;
+IFIX: ; Convert a floating point number to an integer, put in R3:R1
+ ;
+ ;***************************************************************
+ ;
+ CLR A ;RESET THE START
+ MOV R3,A
+ MOV R1,A
+ MOV R0,ASTKA ;GET THE ARG STACK
+ MOV P2,#ASTKAH
+ MOVX A,@R0 ;READ EXPONENT
+ CLR C
+ SUBB A,#81H ;BASE EXPONENT
+ MOV R4,A ;SAVE IT
+ DEC R0 ;POINT AT SIGN
+ MOVX A,@R0 ;GET THE SIGN
+ JNZ SQ_ERR ;ERROR IF NEGATIVE
+ JC INC_ASTKA ;EXIT IF EXPONENT IS < 81H
+ INC R4 ;ADJUST LOOP COUNTER
+ MOV A,R0 ;BUMP THE POINTER REGISTER
+ SUBB A,#FPSIZ-1
+ MOV R0,A
+ ;
+I2: INC R0 ;POINT AT DIGIT
+ MOVX A,@R0 ;GET DIGIT
+ SWAP A ;FLIP
+ CALL FP_BASE+20 ;ACCUMULATE
+ JC SQ_ERR
+ DJNZ R4,$+4
+ SJMP INC_ASTKA
+ MOVX A,@R0 ;GET DIGIT
+ CALL FP_BASE+20
+ JC SQ_ERR
+ DJNZ R4,I2
+ ;
+ newpage
+ ;************************************************************
+ ;
+INC_ASTKA: ; Pop the ARG STACK and check for overflow
+ ;
+ ;************************************************************
+ ;
+ MOV A,#FPSIZ ;NUMBER TO POP
+ SJMP SETREG+1
+ ;
+SETREG: CLR A ;DON'T POP ANYTHING
+ MOV R0,ASTKA
+ MOV R2,#ASTKAH
+ MOV P2,R2
+ ADD A,R0
+ JC E4YY
+ MOV ASTKA,A
+ MOVX A,@R0
+A_D: RET
+ ;
+ ;************************************************************
+ ;
+ ; EBIAS - Bias a number for E to the X calculations
+ ;
+ ;************************************************************
+ ;
+EBIAS: ACALL PUSH_ONE
+ ACALL RV
+ CJNE R3,#00H,SQ_ERR ;ERROR IF R3 <> 0
+ ACALL C_T2 ;TEMP 2 GETS FRACTIONS
+ ACALL INC_ASTKA
+ ACALL POP_T1
+ ACALL PUSH_ONE
+ ;
+AELP: MOV A,MT2
+ JNZ AEL1
+ ;
+ MOV A,MT1
+ JZ A_D
+ MOV DPTR,#FPT2-1
+ MOVX @DPTR,A ;MAKE THE FRACTIONS NEGATIVE
+ ;
+RECIP: ACALL PUSH_ONE
+ ACALL SWAP_ASTKA
+ AJMP ADIV
+ ;
+AEL1: DEC MT2
+ ACALL PUSH_T1
+ ACALL AMUL
+ SJMP AELP
+ ;
+SQ_ERR: LJMP E3XX ;LINK TO BAD ARG
+ ;
+ newpage
+ ;************************************************************
+ ;
+ ; SQUARE ROOT
+ ;
+ ;************************************************************
+ ;
+ASQR: ACALL AABS ;GET THE SIGN
+ JNZ SQ_ERR ;ERROR IF NEGATIVE
+ ACALL C_T2 ;COPY VARIABLE TO T2
+ ACALL POP_T1 ;SAVE IT IN T1
+ MOV R0,#LO(FPT1)
+ MOVX A,@R0 ;GET EXPONENT
+ JZ ALN-2 ;EXIT IF ZERO
+ ADD A,#128 ;BIAS THE EXPONENT
+ JNC SQR1 ;SEE IF < 80H
+ RR A
+ ANL A,#127
+ SJMP SQR2
+ ;
+SQR1: CPL A ;FLIP BITS
+ INC A
+ RR A
+ ANL A,#127 ;STRIP MSB
+ CPL A
+ INC A
+ ;
+SQR2: ADD A,#128 ;BIAS EXPONENT
+ MOVX @R0,A ;SAVE IT
+ ;
+ ; NEWGUESS = ( X/OLDGUESS + OLDGUESS) / 2
+ ;
+SQR4: ACALL P_T2 ;TOS = X
+ ACALL PUSH_T1 ;PUT NUMBER ON STACK
+ ACALL ADIV ;TOS = X/GUESS
+ ACALL PUSH_T1 ;PUT ON AGAIN
+ ACALL AADD ;TOS = X/GUESS + GUESS
+ ACALL DBTWO ;TOS = ( X/GUESS + GUESS ) / 2
+ ACALL TEMP_COMP ;SEE IF DONE
+ JNB F0,SQR4
+ ;
+ AJMP PUSH_T1 ;PUT THE ANSWER ON THE STACK
+ ;
+ newpage
+ ;*************************************************************
+ ;
+ ; NATURAL LOG
+ ;
+ ;*************************************************************
+ ;
+ALN: ACALL AABS ;MAKE SURE THAT NUM IS POSITIVE
+ JNZ SQ_ERR ;ERROR IF NOT
+ MOV MT2,A ;CLEAR FOR LOOP
+ INC R0 ;POINT AT EXPONENT
+ MOVX A,@R0 ;READ THE EXPONENT
+ JZ SQ_ERR ;ERROR IF EXPONENT IS ZERO
+ CJNE A,#81H,$+3 ;SEE IF NUM >= 1
+ MOV UBIT,C ;SAVE CARRY STATUS
+ JC $+4 ;TAKE RECIP IF >= 1
+ ACALL RECIP
+ ;
+ ; Loop to reduce
+ ;
+ALNL: ACALL CSTAKA ;COPY THE STACK FOR COMPARE
+ ACALL PUSH_ONE ;COMPARE NUM TO ONE
+ ACALL CMPLK
+ JNC ALNO ;EXIT IF DONE
+ ACALL SETREG ;GET THE EXPONENT
+ ADD A,#85H ;SEE HOW BIG IT IS
+ JNC ALN11 ;BUMP BY EXP(11) IF TOO SMALL
+ ACALL PLNEXP ;PUT EXP(1) ON STACK
+ MOV A,#1 ;BUMP COUNT
+ ;
+ALNE: ADD A,MT2
+ JC SQ_ERR
+ MOV MT2,A
+ ACALL AMUL ;BIAS THE NUMBER
+ SJMP ALNL
+ ;
+ALN11: MOV DPTR,#EXP11 ;PUT EXP(11) ON STACK
+ ACALL PUSHC
+ MOV A,#11
+ SJMP ALNE
+ ;
+ newpage
+ALNO: ACALL C_T2 ;PUT NUM IN TEMP 2
+ ACALL PUSH_ONE ;TOS = 1
+ ACALL ASUB ;TOS = X - 1
+ ACALL P_T2 ;TOS = X
+ ACALL PUSH_ONE ;TOS = 1
+ ACALL AADD ;TOS = X + 1
+ ACALL ADIV ;TOS = (X-1)/(X+1)
+ MOV DPTR,#LNTAB ;LOG TABLE
+ ACALL POLYC
+ INC DPTR ;POINT AT LN(10)
+ ACALL PUSHC
+ ACALL AMUL
+ MOV A,MT2 ;GET THE COUNT
+ ACALL TWO_R2 ;PUT IT ON THE STACK
+ ACALL ASUB ;INT - POLY
+ ACALL STRIP
+ JNB UBIT,AABS
+ ;
+LN_D: RET
+ ;
+ ;*************************************************************
+ ;
+TEMP_COMP: ; Compare FPTEMP1 to TOS, FPTEMP1 gets TOS
+ ;
+ ;*************************************************************
+ ;
+ ACALL PUSH_T1 ;SAVE THE TEMP
+ ACALL SWAP_ASTKA ;TRADE WITH THE NEXT NUMBER
+ ACALL CSTAKA ;COPY THE STACK
+ ACALL POP_T1 ;SAVE THE NEW NUMBER
+ JMP FP_BASE+4 ;DO THE COMPARE
+ ;
+ newpage
+AETOX: ACALL PLNEXP ;EXP(1) ON TOS
+ ACALL SWAP_ASTKA ;X ON TOS
+ ;
+AEXP: ;EXPONENTIATION
+ ;
+ ACALL EBIAS ;T1=BASE,T2=FRACTIONS,TOS=INT MULTIPLIED
+ MOV DPTR,#FPT2 ;POINT AT FRACTIONS
+ MOVX A,@DPTR ;READ THE EXP OF THE FRACTIONS
+ JZ LN_D ;EXIT IF ZERO
+ ACALL P_T2 ;TOS = FRACTIONS
+ ACALL PUSH_T1 ;TOS = BASE
+ ACALL SETREG ;SEE IF BASE IS ZERO
+ JZ $+4
+ ACALL ALN ;TOS = LN(BASE)
+ ACALL AMUL ;TOS = FRACTIONS * LN(BASE)
+ ACALL PLNEXP ;TOS = EXP(1)
+ ACALL SWAP_ASTKA ;TOS = FRACTIONS * LN(BASE)
+ ACALL EBIAS ;T2 = FRACTIONS, TOS = INT MULTIPLIED
+ MOV MT2,#00H ;NOW CALCULATE E**X
+ ACALL PUSH_ONE
+ ACALL CSTAKA
+ ACALL POP_T1 ;T1 = 1
+ ;
+AEXL: ACALL P_T2 ;TOS = FRACTIONS
+ ACALL AMUL ;TOS = FRACTIONS * ACCUMLATION
+ INC MT2 ;DO THE DEMONIATOR
+ MOV A,MT2
+ ACALL TWO_R2
+ ACALL ADIV
+ ACALL CSTAKA ;SAVE THE ITERATION
+ ACALL PUSH_T1 ;NOW ACCUMLATE
+ ACALL AADD ;ADD ACCUMLATION
+ ACALL TEMP_COMP
+ JNB F0,AEXL ;LOOP UNTIL DONE
+ ;
+ ACALL INC_ASTKA
+ ACALL PUSH_T1
+ ACALL AMUL ;LAST INT MULTIPLIED
+ ;
+MU1: AJMP AMUL ;FIRST INT MULTIPLIED
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; integer operator - INT
+ ;
+ ;***************************************************************
+ ;
+AINT: ACALL SETREG ;SET UP THE REGISTERS, CLEAR CARRY
+ SUBB A,#129 ;SUBTRACT EXPONENT BIAS
+ JNC AI1 ;JUMP IF ACC > 81H
+ ;
+ ; Force the number to be a zero
+ ;
+ ACALL INC_ASTKA ;BUMP THE STACK
+ ;
+P_Z: MOV DPTR,#ZRO ;PUT ZERO ON THE STACK
+ AJMP PUSHC
+ ;
+AI1: SUBB A,#7
+ JNC AI3
+ CPL A
+ INC A
+ MOV R3,A
+ DEC R0 ;POINT AT SIGN
+ ;
+AI2: DEC R0 ;NOW AT LSB'S
+ MOVX A,@R0 ;READ BYTE
+ ANL A,#0F0H ;STRIP NIBBLE
+ MOVX @R0,A ;WRITE BYTE
+ DJNZ R3,$+3
+ RET
+ CLR A
+ MOVX @R0,A ;CLEAR THE LOCATION
+ DJNZ R3,AI2
+ ;
+AI3: RET ;EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+AABS: ; Absolute value - Make sign of number positive
+ ; return sign in ACC
+ ;
+ ;***************************************************************
+ ;
+ ACALL ANEG ;CHECK TO SEE IF + OR -
+ JNZ ALPAR ;EXIT IF NON ZERO, BECAUSE THE NUM IS
+ MOVX @R0,A ;MAKE A POSITIVE SIGN
+ RET
+ ;
+ ;***************************************************************
+ ;
+ASGN: ; Returns the sign of the number 1 = +, -1 = -
+ ;
+ ;***************************************************************
+ ;
+ ACALL INC_ASTKA ;POP STACK, GET EXPONENT
+ JZ P_Z ;EXIT IF ZERO
+ DEC R0 ;BUMP TO SIGN
+ MOVX A,@R0 ;GET THE SIGN
+ MOV R7,A ;SAVE THE SIGN
+ ACALL PUSH_ONE ;PUT A ONE ON THE STACK
+ MOV A,R7 ;GET THE SIGN
+ JZ ALPAR ;EXIT IF ZERO
+ ;
+ ; Fall thru to ANEG
+ ;
+ ;***************************************************************
+ ;
+ANEG: ; Flip the sign of the number on the tos
+ ;
+ ;***************************************************************
+ ;
+ ACALL SETREG
+ DEC R0 ;POINT AT THE SIGN OF THE NUMBER
+ JZ ALPAR ;EXIT IF ZERO
+ MOVX A,@R0
+ XRL A,#01H ;FLIP THE SIGN
+ MOVX @R0,A
+ XRL A,#01H ;RESTORE THE SIGN
+ ;
+ALPAR: RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ACBYTE: ; Read the ROM
+ ;
+ ;***************************************************************
+ ;
+ ACALL IFIX ;GET EXPRESSION
+ CALL X31DP ;PUT R3:R1 INTO THE DP
+ CLR A
+ MOVC A,@A+DPTR
+ AJMP TWO_R2
+ ;
+ ;***************************************************************
+ ;
+ADBYTE: ; Read internal memory
+ ;
+ ;***************************************************************
+ ;
+ ACALL IFIX ;GET THE EXPRESSION
+ CALL R3CK ;MAKE SURE R3 = 0
+ MOV A,@R1
+ AJMP TWO_R2
+ ;
+ ;***************************************************************
+ ;
+AXBYTE: ; Read external memory
+ ;
+ ;***************************************************************
+ ;
+ ACALL IFIX ;GET THE EXPRESSION
+ MOV P2,R3
+ MOVX A,@R1
+ AJMP TWO_R2
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The relational operators - EQUAL (=)
+ ; GREATER THAN (>)
+ ; LESS THAN (<)
+ ; GREATER THAN OR EQUAL (>=)
+ ; LESS THAN OR EQUAL (<=)
+ ; NOT EQUAL (<>)
+ ;
+ ;***************************************************************
+ ;
+AGT: ACALL CMPLK
+ ORL C,F0 ;SEE IF EITHER IS A ONE
+ JC P_Z
+ ;
+FSTK: MOV DPTR,#FS
+ AJMP PUSHC
+ ;
+FS: DB 85H
+ DB 00H
+ DB 00H
+ DB 50H
+ DB 53H
+ DB 65H
+ ;
+ALT: ACALL CMPLK
+ CPL C
+ SJMP AGT+4
+ ;
+AEQ: ACALL CMPLK
+ MOV C,F0
+ SJMP ALT+2
+ ;
+ANE: ACALL CMPLK
+ CPL F0
+ SJMP AEQ+2
+ ;
+AGE: ACALL CMPLK
+ SJMP AGT+4
+ ;
+ALE: ACALL CMPLK
+ ORL C,F0
+ SJMP ALT+2
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ARND: ; Generate a random number
+ ;
+ ;***************************************************************
+ ;
+ MOV DPTR,#RCELL ;GET THE BINARY SEED
+ CALL L31DPI
+ MOV A,R1
+ CLR C
+ RRC A
+ MOV R0,A
+ MOV A,#6
+ RRC A
+ ADD A,R1
+ XCH A,R0
+ ADDC A,R3
+ MOV R2,A
+ DEC DPL ;SAVE THE NEW SEED
+ ACALL S20DP
+ ACALL TWO_EY
+ ACALL FSTK
+ ;
+ADIV: LCALL FP_BASE+8
+ AJMP FPTST
+ ;
+ newpage
+ ;***************************************************************
+ ;
+SONERR: ; ON ERROR Statement
+ ;
+ ;***************************************************************
+ ;
+ LCALL INTERR ;GET THE LINE NUMBER
+ SETB ON_ERR
+ MOV DPTR,#ERRNUM ;POINT AT THR ERROR LOCATION
+ SJMP S20DP
+ ;
+ ;
+ ;**************************************************************
+ ;
+SONEXT: ; ON EXT1 Statement
+ ;
+ ;**************************************************************
+ ;
+ LCALL INTERR
+ SETB INTBIT
+ ORL IE,#10000100B ;ENABLE INTERRUPTS
+ MOV DPTR,#INTLOC
+ ;
+S20DP: MOV A,R2 ;SAVE R2:R0 @DPTR
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,R0
+ MOVX @DPTR,A
+ RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; CASTAK - Copy and push another top of arg stack
+ ;
+ ;***************************************************************
+ ;
+CSTAKA2:ACALL CSTAKA ;COPY STACK TWICE
+ ;
+CSTAKA: ACALL SETREG ;SET UP R2:R0
+ SJMP PUSH_T1+4
+ ;
+PLNEXP: MOV DPTR,#EXP1
+ ;
+ ;***************************************************************
+ ;
+ ; PUSHC - Push constant on to the arg stack
+ ;
+ ;***************************************************************
+ ;
+PUSHC: ACALL DEC_ASTKA
+ MOV P2,R3
+ MOV R3,#FPSIZ ;LOOP COUNTER
+ ;
+PCL: CLR A ;SET UP A
+ MOVC A,@A+DPTR ;LOAD IT
+ MOVX @R1,A ;SAVE IT
+ INC DPTR ;BUMP POINTERS
+ DEC R1
+ DJNZ R3,PCL ;LOOP
+ ;
+ SETB ARGF
+ RET ;EXIT
+ ;
+PUSH_ONE:;
+ ;
+ MOV DPTR,#FPONE
+ AJMP PUSHC
+ ;
+ newpage
+ ;
+POP_T1:
+ ;
+ MOV R3,#HI(FPT1)
+ MOV R1,#LO(FPT1)
+ JMP POPAS
+ ;
+PUSH_T1:
+ ;
+ MOV R0,#LO(FPT1)
+ MOV R2,#HI(FPT1)
+ LJMP PUSHAS
+ ;
+P_T2: MOV R0,#LO(FPT2)
+ SJMP $-7 ;JUMP TO PUSHAS
+ ;
+ ;****************************************************************
+ ;
+SWAP_ASTKA: ; SWAP TOS<>TOS-1
+ ;
+ ;****************************************************************
+ ;
+ ACALL SETREG ;SET UP R2:R0 AND P2
+ MOV A,#FPSIZ ;PUT TOS+1 IN R1
+ MOV R2,A
+ ADD A,R0
+ MOV R1,A
+ ;
+S_L: MOVX A,@R0
+ MOV R3,A
+ MOVX A,@R1
+ MOVX @R0,A
+ MOV A,R3
+ MOVX @R1,A
+ DEC R1
+ DEC R0
+ DJNZ R2,S_L
+ RET
+ ;
+ newpage
+ ;
+C_T2: ACALL SETREG ;SET UP R2:R0
+ MOV R3,#HI(FPT2)
+ MOV R1,#LO(FPT2) ;TEMP VALUE
+ ;
+ ; Fall thru
+ ;
+ ;***************************************************************
+ ;
+ ; VARCOP - Copy a variable from R2:R0 to R3:R1
+ ;
+ ;***************************************************************
+ ;
+VARCOP: MOV R4,#FPSIZ ;LOAD THE LOOP COUNTER
+ ;
+V_C: MOV P2,R2 ;SET UP THE PORTS
+ MOVX A,@R0 ;READ THE VALUE
+ MOV P2,R3 ;PORT TIME AGAIN
+ MOVX @R1,A ;SAVE IT
+ ACALL DEC3210 ;BUMP POINTERS
+ DJNZ R4,V_C ;LOOP
+ RET ;EXIT
+ ;
+PIPI: MOV DPTR,#PIE
+ AJMP PUSHC
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The logical operators ANL, ORL, XRL, NOT
+ ;
+ ;***************************************************************
+ ;
+AANL: ACALL TWOL ;GET THE EXPRESSIONS
+ MOV A,R3 ;DO THE AND
+ ANL A,R7
+ MOV R2,A
+ MOV A,R1
+ ANL A,R6
+ SJMP TWO_EX
+ ;
+AORL: ACALL TWOL ;SAME THING FOR OR
+ MOV A,R3
+ ORL A,R7
+ MOV R2,A
+ MOV A,R1
+ ORL A,R6
+ SJMP TWO_EX
+ ;
+ANOT: ACALL FSTK ;PUT 0FFFFH ON THE STACK
+ ;
+AXRL: ACALL TWOL
+ MOV A,R3
+ XRL A,R7
+ MOV R2,A
+ MOV A,R1
+ XRL A,R6
+ SJMP TWO_EX
+ ;
+TWOL: ACALL IFIX
+ MOV R7,R3B0
+ MOV R6,R1B0
+ AJMP IFIX
+ ;
+ newpage
+ ;*************************************************************
+ ;
+AGET: ; READ THE BREAK BYTE AND PUT IT ON THE ARG STACK
+ ;
+ ;*************************************************************
+ ;
+ MOV DPTR,#GTB ;GET THE BREAK BYTE
+ MOVX A,@DPTR
+ JBC GTRD,TWO_R2
+ CLR A
+ ;
+TWO_R2: MOV R2,#00H ;ACC GOES TO STACK
+ ;
+ ;
+TWO_EX: MOV R0,A ;R2:ACC GOES TO STACK
+ ;
+ ;
+TWO_EY: SETB ARGF ;R2:R0 GETS PUT ON THE STACK
+ JMP FP_BASE+24 ;DO IT
+ ;
+ newpage
+ ;*************************************************************
+ ;
+ ; Put directs onto the stack
+ ;
+ ;**************************************************************
+ ;
+A_IE: MOV A,IE ;IE
+ SJMP TWO_R2
+ ;
+A_IP: MOV A,IP ;IP
+ SJMP TWO_R2
+ ;
+ATIM0: MOV R2,TH0 ;TIMER 0
+ MOV R0,TL0
+ SJMP TWO_EY
+ ;
+ATIM1: MOV R2,TH1 ;TIMER 1
+ MOV R0,TL1
+ SJMP TWO_EY
+ ;
+ATIM2: DB 0AAH ;MOV R2 DIRECT OP CODE
+ DB 0CDH ;T2 HIGH
+ DB 0A8H ;MOV R0 DIRECT OP CODE
+ DB 0CCH ;T2 LOW
+ SJMP TWO_EY ;TIMER 2
+ ;
+AT2CON: DB 0E5H ;MOV A,DIRECT OPCODE
+ DB 0C8H ;T2CON LOCATION
+ SJMP TWO_R2
+ ;
+ATCON: MOV A,TCON ;TCON
+ SJMP TWO_R2
+ ;
+ATMOD: MOV A,TMOD ;TMOD
+ SJMP TWO_R2
+ ;
+ARCAP2: DB 0AAH ;MOV R2, DIRECT OP CODE
+ DB 0CBH ;RCAP2H LOCATION
+ DB 0A8H ;MOV R0, DIRECT OP CODE
+ DB 0CAH ;R2CAPL LOCATION
+ SJMP TWO_EY
+ ;
+AP1: MOV A,P1 ;GET P1
+ SJMP TWO_R2 ;PUT IT ON THE STACK
+ ;
+APCON: DB 0E5H ;MOV A, DIRECT OP CODE
+ DB 87H ;ADDRESS OF PCON
+ SJMP TWO_R2 ;PUT PCON ON THE STACK
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ;THIS IS THE LINE EDITOR
+ ;
+ ;TAKE THE PROCESSED LINE IN IBUF AND INSERT IT INTO THE
+ ;BASIC TEXT FILE.
+ ;
+ ;***************************************************************
+ ;
+ LJMP NOGO ;CAN'T EDIT A ROM
+ ;
+LINE: MOV A,BOFAH
+ CJNE A,#HI(PSTART),LINE-3
+ CALL G4 ;GET END ADDRESS FOR EDITING
+ MOV R4,DPL
+ MOV R5,DPH
+ MOV R3,TEMP5 ;GET HIGH ORDER IBLN
+ MOV R1,TEMP4 ;LOW ORDER IBLN
+ ;
+ CALL GETLIN ;FIND THE LINE
+ JNZ INSR ;INSERT IF NOT ZERO, ELSE APPEND
+ ;
+ ;APPEND THE LINE AT THE END
+ ;
+ MOV A,TEMP3 ;PUT IBCNT IN THE ACC
+ CJNE A,#4H,$+4 ;SEE IF NO ENTRY
+ RET ;RET IF NO ENTRY
+ ;
+ ACALL FULL ;SEE IF ENOUGH SPACE LEFT
+ MOV R2,R5B0 ;PUT END ADDRESS A INTO TRANSFER
+ MOV R0,R4B0 ;REGISTERS
+ ACALL IMOV ;DO THE BLOCK MOVE
+ ;
+UE: MOV A,#EOF ;SAVE EOF CHARACTER
+ AJMP TBR
+ ;
+ ;INSERT A LINE INTO THE FILE
+ ;
+INSR: MOV R7,A ;SAVE IT IN R7
+ CALL TEMPD ;SAVE INSERATION ADDRESS
+ MOV A,TEMP3 ;PUT THE COUNT LENGTH IN THE ACC
+ JC LTX ;JUMP IF NEW LINE # NOT = OLD LINE #
+ CJNE A,#04H,$+4 ;SEE IF NULL
+ CLR A
+ ;
+ SUBB A,R7 ;SUBTRACT LINE COUNT FROM ACC
+ JZ LIN1 ;LINE LENGTHS EQUAL
+ JC GTX ;SMALLER LINE
+ ;
+ newpage
+ ;
+ ;EXPAND FOR A NEW LINE OR A LARGER LINE
+ ;
+LTX: MOV R7,A ;SAVE A IN R7
+ MOV A,TEMP3 ;GET THE COUNT IN THE ACC
+ CJNE A,#04H,$+4 ;DO NO INSERTATION IF NULL LINE
+ RET ;EXIT IF IT IS
+ ;
+ MOV A,R7 ;GET THE COUNT BACK - DELTA IN A
+ ACALL FULL ;SEE IF ENOUGH MEMORY NEW EOFA IN R3:R1
+ CALL DTEMP ;GET INSERATION ADDRESS
+ ACALL NMOV ;R7:R6 GETS (EOFA)-DPTR
+ CALL X3120
+ MOV R1,R4B0 ;EOFA LOW
+ MOV R3,R5B0 ;EOFA HIGH
+ INC R6 ;INCREMENT BYTE COUNT
+ CJNE R6,#00,$+4 ;NEED TO BUMP HIGH BYTE?
+ INC R7
+ ;
+ ACALL RMOV ;GO DO THE INSERTION
+ SJMP LIN1 ;INSERT THE CURRENT LINE
+ ;
+GTX: CPL A ;FLIP ACC
+ INC A ;TWOS COMPLEMENT
+ CALL ADDPTR ;DO THE ADDITION
+ ACALL NMOV ;R7:R6 GETS (EOFA)-DPTR
+ MOV R1,DPL ;SET UP THE REGISTERS
+ MOV R3,DPH
+ MOV R2,TEMP5 ;PUT INSERTATION ADDRESS IN THE RIGHT REG
+ MOV R0,TEMP4
+ JZ $+4 ;IF ACC WAS ZERO FROM NMOV, JUMP
+ ACALL LMOV ;IF NO ZERO DO A LMOV
+ ;
+ ACALL UE ;SAVE NEW END ADDRESS
+ ;
+LIN1: MOV R2,TEMP5 ;GET THE INSERTATION ADDRESS
+ MOV R0,TEMP4
+ MOV A,TEMP3 ;PUT THE COUNT LENGTH IN ACC
+ CJNE A,#04H,IMOV ;SEE IF NULL
+ RET ;EXIT IF NULL
+ newpage
+ ;***************************************************************
+ ;
+ ;INSERT A LINE AT ADDRESS R2:R0
+ ;
+ ;***************************************************************
+ ;
+IMOV: CLR A ;TO SET UP
+ MOV R1,#LO(IBCNT) ;INITIALIZE THE REGISTERS
+ MOV R3,A
+ MOV R6,TEMP3 ;PUT THE BYTE COUNT IN R6 FOR LMOV
+ MOV R7,A ;PUT A 0 IN R7 FOR LMOV
+ ;
+ ;***************************************************************
+ ;
+ ;COPY A BLOCK FROM THE BEGINNING
+ ;
+ ;R2:R0 IS THE DESTINATION ADDRESS
+ ;R3:R1 IS THE SOURCE ADDRESS
+ ;R7:R6 IS THE COUNT REGISTER
+ ;
+ ;***************************************************************
+ ;
+LMOV: ACALL TBYTE ;TRANSFER THE BYTE
+ ACALL INC3210 ;BUMP THE POINTER
+ ACALL DEC76 ;BUMP R7:R6
+ JNZ LMOV ;LOOP
+ RET ;GO BACK TO CALLING ROUTINE
+ ;
+INC3210:INC R0
+ CJNE R0,#00H,$+4
+ INC R2
+ ;
+ INC R1
+ CJNE R1,#00H,$+4
+ INC R3
+ RET
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ;COPY A BLOCK STARTING AT THE END
+ ;
+ ;R2:R0 IS THE DESTINATION ADDRESS
+ ;R3:R1 IS THE SOURCE ADDRESS
+ ;R6:R7 IS THE COUNT REGISTER
+ ;
+ ;***************************************************************
+ ;
+RMOV: ACALL TBYTE ;TRANSFER THE BYTE
+ ACALL DEC3210 ;DEC THE LOCATIONS
+ ACALL DEC76 ;BUMP THE COUNTER
+ JNZ RMOV ;LOOP
+ ;
+DEC_R: NOP ;CREATE EQUAL TIMING
+ RET ;EXIT
+ ;
+DEC3210:DEC R0 ;BUMP THE POINTER
+ CJNE R0,#0FFH,$+4 ;SEE IF OVERFLOWED
+ DEC R2 ;BUMP THE HIGH BYTE
+ DEC R1 ;BUMP THE POINTER
+ CJNE R1,#0FFH,DEC_R ;SEE IF OVERFLOWED
+ DEC R3 ;CHANGE THE HIGH BYTE
+ RET ;EXIT
+ ;
+ ;***************************************************************
+ ;
+ ;TBYTE - TRANSFER A BYTE
+ ;
+ ;***************************************************************
+ ;
+TBYTE: MOV P2,R3 ;OUTPUT SOURCE REGISTER TO PORT
+ MOVX A,@R1 ;PUT BYTE IN ACC
+ ;
+TBR: MOV P2,R2 ;OUTPUT DESTINATION TO PORT
+ MOVX @R0,A ;SAVE THE BYTE
+ RET ;EXIT
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ;NMOV - R7:R6 = END ADDRESS - DPTR
+ ;
+ ;ACC GETS CLOBBERED
+ ;
+ ;***************************************************************
+ ;
+NMOV: MOV A,R4 ;THE LOW BYTE OF EOFA
+ CLR C ;CLEAR THE CARRY FOR SUBB
+ SUBB A,DPL ;SUBTRACT DATA POINTER LOW
+ MOV R6,A ;PUT RESULT IN R6
+ MOV A,R5 ;HIGH BYTE OF EOFA
+ SUBB A,DPH ;SUBTRACT DATA POINTER HIGH
+ MOV R7,A ;PUT RESULT IN R7
+ ORL A,R6 ;SEE IF ZERO
+ RET ;EXIT
+ ;
+ ;***************************************************************
+ ;
+ ;CHECK FOR A FILE OVERFLOW
+ ;LEAVES THE NEW END ADDRESS IN R3:R1
+ ;A HAS THE INCREASE IN SIZE
+ ;
+ ;***************************************************************
+ ;
+FULL: ADD A,R4 ;ADD A TO END ADDRESS
+ MOV R1,A ;SAVE IT
+ CLR A
+ ADDC A,R5 ;ADD THE CARRY
+ MOV R3,A
+ MOV DPTR,#VARTOP ;POINT AT VARTOP
+ ;
+FUL1: CALL DCMPX ;COMPARE THE TWO
+ JC FULL-1 ;OUT OF ROOM
+ ;
+TB: MOV DPTR,#E5X ;OUT OF MEMORY
+ AJMP FPTS
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; PP - Preprocesses the line in IBUF back into IBUF
+ ; sets F0 if no line number
+ ; leaves the correct length of processed line in IBCNT
+ ; puts the line number in IBLN
+ ; wastes the text address TXAL and TXAH
+ ;
+ ;***************************************************************
+ ;
+PP: ACALL T_BUF ;TXA GETS IBUF
+ CALL INTGER ;SEE IF A NUMBER PRESENT
+ CALL TEMPD ;SAVE THE INTEGER IN TEMP5:TEMP4
+ MOV F0,C ;SAVE INTEGER IF PRESENT
+ MOV DPTR,#IBLN ;SAVE THE LINE NUMBER, EVEN IF NONE
+ ACALL S20DP
+ MOV R0,TXAL ;TEXT POINTER
+ MOV R1,#LO(IBUF) ;STORE POINTER
+ ;
+ ; Now process the line back into IBUF
+ ;
+PPL: CLR ARGF ;FIRST PASS DESIGNATOR
+ MOV DPTR,#TOKTAB ;POINT DPTR AT LOOK UP TABLE
+ ;
+PPL1: MOV R5B0,R0 ;SAVE THE READ POINTER
+ CLR A ;ZERO A FOR LOOKUP
+ MOVC A,@A+DPTR ;GET THE TOKEN
+ MOV R7,A ;SAVE TOKEN IN CASE OF MATCH
+ ;
+PPL2: MOVX A,@R0 ;GET THE USER CHARACTER
+ MOV R3,A ;SAVE FOR REM
+ CJNE A,#'a',$+3
+ JC PPX ;CONVERT LOWER TO UPPER CASE
+ CJNE A,#('z'+1),$+3
+ JNC PPX
+ CLR ACC.5
+ ;
+PPX: MOV R2,A
+ MOVX @R0,A ;SAVE UPPER CASE
+ INC DPTR ;BUMP THE LOOKUP POINTER
+ CLR A
+ MOVC A,@A+DPTR
+ CJNE A,R2B0,PPL3 ;LEAVE IF NOT THE SAME
+ INC R0 ;BUMP THE USER POINTER
+ SJMP PPL2 ;CONTINUE TO LOOP
+ ;
+PPL3: JB ACC.7,PPL6 ;JUMP IF FOUND MATCH
+ JZ PPL6 ;USER MATCH
+ ;
+ ;
+ ; Scan to the next TOKTAB entry
+ ;
+PPL4: INC DPTR ;ADVANCE THE POINTER
+ CLR A ;ZERO A FOR LOOKUP
+ MOVC A,@A+DPTR ;LOAD A WITH TABLE
+ JB ACC.7,$+6 ;KEEP SCANNING IF NOT A RESERVED WORD
+ JNZ PPL4
+ INC DPTR
+ ;
+ ; See if at the end of TOKTAB
+ ;
+ MOV R0,R5B0 ;RESTORE THE POINTER
+ CJNE A,#0FFH,PPL1 ;SEE IF END OF TABLE
+ ;
+ ; Character not in TOKTAB, so see what it is
+ ;
+ CJNE R2,#' ',PPLX ;SEE IF A SPACE
+ INC R0 ;BUMP USER POINTER
+ SJMP PPL ;TRY AGAIN
+ ;
+PPLX: JNB XBIT,PPLY ;EXTERNAL TRAP
+ JB ARGF,PPLY
+ SETB ARGF ;SAYS THAT THE USER HAS TABLE
+ LCALL 2078H ;SET UP POINTER
+ AJMP PPL1
+ ;
+PPLY: ACALL PPL7 ;SAVE CHARACTER, EXIT IF A CR
+ CJNE A,#'"',PPL ;SEE IF QUOTED STRING, START AGAIN IF NOT
+ ;
+ ; Just copy a quoted string
+ ;
+ ACALL PPL7 ;SAVE THE CHARACTER, TEST FOR CR
+ CJNE A,#'"',$-2 ;IS THERE AN ENDQUOTE, IF NOT LOOP
+ SJMP PPL ;DO IT AGAIN IF ENDQUOTE
+ ;
+PPL6: MOV A,R7 ;GET THE TOKEN
+ ACALL PPL9+1 ;SAVE THE TOKEN
+ CJNE A,#T_REM,PPL ;SEE IF A REM TOKEN
+ MOV A,R3
+ ACALL PPL7+1 ;WASTE THE REM STATEMENT
+ ACALL PPL7 ;LOOP UNTIL A CR
+ SJMP $-2
+ ;
+PPL7: MOVX A,@R0 ;GET THE CHARACTER
+ CJNE A,#CR,PPL9 ;FINISH IF A CR
+ POP R0B0 ;WASTE THE CALLING STACK
+ POP R0B0
+ MOVX @R1,A ;SAVE CR IN MEMORY
+ INC R1 ;SAVE A TERMINATOR
+ MOV A,#EOF
+ MOVX @R1,A
+ MOV A,R1 ;SUBTRACT FOR LENGTH
+ SUBB A,#4
+ MOV TEMP3,A ;SAVE LENGTH
+ MOV R1,#LO(IBCNT) ;POINT AT BUFFER COUNT
+ ;
+PPL9: INC R0
+ MOVX @R1,A ;SAVE THE CHARACTER
+ INC R1 ;BUMP THE POINTERS
+ RET ;EXIT TO CALLING ROUTINE
+ ;
+ ;
+ ;***************************************************************
+ ;
+ ;DEC76 - DECREMENT THE REGISTER PAIR R7:R6
+ ;
+ ;ACC = ZERO IF R7:R6 = ZERO ; ELSE ACC DOES NOT
+ ;
+ ;***************************************************************
+ ;
+DEC76: DEC R6 ;BUMP R6
+ CJNE R6,#0FFH,$+4 ;SEE IF RAPPED AROUND
+ DEC R7
+ MOV A,R7 ;SEE IF ZERO
+ ORL A,R6
+ RET ;EXIT
+ ;
+ ;***************************************************************
+ ;
+ ; MTOP - Get or Put the top of assigned memory
+ ;
+ ;***************************************************************
+ ;
+PMTOP: MOV DPTR,#MEMTOP
+ CALL L20DPI
+ AJMP TWO_EY ;PUT R2:R0 ON THE STACK
+ ;
+ newpage
+ ;*************************************************************
+ ;
+ ; AXTAL - Crystal value calculations
+ ;
+ ;*************************************************************
+ ;
+AXTAL0: MOV DPTR,#XTALV ;CRYSTAL VALUE
+ ACALL PUSHC
+ ;
+AXTAL1: ACALL CSTAKA2 ;COPY CRYSTAL VALUE TWICE
+ ACALL CSTAKA
+ MOV DPTR,#PTIME ;PROM TIMER
+ ACALL AXTAL2
+ MOV DPTR,#PROGS
+ ACALL S31L
+ MOV DPTR,#IPTIME ;IPROM TIMER
+ ACALL AXTAL2
+ MOV DPTR,#IPROGS
+ ACALL S31L
+ MOV DPTR,#TTIME ;CLOCK CALCULATION
+ ACALL AXTAL3
+ MOV A,R1
+ CPL A
+ INC A
+ MOV SAVE_T,A
+ MOV R3,#HI(CXTAL)
+ MOV R1,#LO(CXTAL)
+ JMP POPAS
+ ;
+AXTAL2: ACALL AXTAL3
+ ;
+CBIAS: ;Bias the crystal calculations
+ ;
+ MOV A,R1 ;GET THE LOW COUNT
+ CPL A ;FLIP IT FOR TIMER LOAD
+ ADD A,#15 ;BIAS FOR CALL AND LOAD TIMES
+ MOV R1,A ;RESTORE IT
+ MOV A,R3 ;GET THE HIGH COUNT
+ CPL A ;FLIP IT
+ ADDC A,#00H ;ADD THE CARRY
+ MOV R3,A ;RESTORE IT
+ RET
+ ;
+ newpage
+ include bas52.pwm ; ******AA
+ newpage
+ ;LNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLN
+ ;
+LNTAB: ; Natural log lookup table
+ ;
+ ;LNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLN
+ ;
+ DB 80H
+ DB 00H
+ DB 71H
+ DB 37H
+ DB 13H
+ DB 19H
+ ;
+ DB 7FH
+ DB 00H
+ DB 76H
+ DB 64H
+ DB 37H
+ DB 94H
+ ;
+ DB 80H
+ DB 00H
+ DB 07H
+ DB 22H
+ DB 75H
+ DB 17H
+ ;
+ DB 80H
+ DB 00H
+ DB 52H
+ DB 35H
+ DB 93H
+ DB 28H
+ ;
+ DB 80H
+ DB 00H
+ DB 71H
+ DB 91H
+ DB 85H
+ DB 86H
+ ;
+ DB 0FFH
+ ;
+ DB 81H
+ DB 00H
+ DB 51H
+ DB 58H
+ DB 02H
+ DB 23H
+ ;
+ newpage
+ ;SINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSIN
+ ;
+SINTAB: ; Sin lookup table
+ ;
+ ;SINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSIN
+ ;
+ DB 128-9
+ DB 00H
+ DB 44H
+ DB 90H
+ DB 05H
+ DB 16H
+ ;
+ DB 128-7
+ DB 01H
+ DB 08H
+ DB 21H
+ DB 05H
+ DB 25H
+ ;
+ DB 128-5
+ DB 00H
+ DB 19H
+ DB 73H
+ DB 55H
+ DB 27H
+ ;
+ newpage
+ ;
+ DB 128-3
+ DB 01H
+ DB 70H
+ DB 12H
+ DB 84H
+ DB 19H
+ ;
+ DB 128-2
+ DB 00H
+ DB 33H
+ DB 33H
+ DB 33H
+ DB 83H
+ ;
+ DB 128
+ DB 01H
+ DB 67H
+ DB 66H
+ DB 66H
+ DB 16H
+ ;
+FPONE: DB 128+1
+ DB 00H
+ DB 00H
+ DB 00H
+ DB 00H
+ DB 10H
+ ;
+ DB 0FFH ;END OF TABLE
+ ;
+ newpage
+ ;
+SBAUD: CALL AXTAL ;PUT CRYSTAL ON THE STACK
+ CALL EXPRB ;PUT THE NUMBER AFTER BAUD ON STACK
+ MOV A,#12
+ ACALL TWO_R2 ;TOS = 12
+ ACALL AMUL ;TOS = 12*BAUD
+ ACALL ADIV ;TOS = XTAL/(12*BAUD)
+ ACALL IFIX
+ ACALL CBIAS
+ MOV DPTR,#SPV
+ ;
+S31L: JMP S31DP
+ ;
+AFREE: CALL PMTOP ;PUT MTOP ON STACK
+ CALL G4 ;GET END ADDRESS
+ MOV R0,DPL
+ MOV R2,DPH
+ ACALL TWO_EY
+ ;
+ASUB: LCALL FP_BASE+2 ;DO FP SUB
+ AJMP FPTST
+ ;
+ALEN: CALL CCAL ;CALCULATE THE LEN OF THE SELECTED PROGRAM
+ MOV R2,R7B0 ;SAVE THE HIGH BYTE
+ MOV A,R6 ;SAVE THE LOW BYTE
+ AJMP TWO_EX ;PUT IT ON THE STACK
+ ;
+ATIME: MOV C,EA ;SAVE INTERRUTS
+ CLR EA
+ PUSH MILLIV ;SAVE MILLI VALUE
+ MOV R2,TVH ;GET THE TIMER
+ MOV A,TVL
+ MOV EA,C ;SAVE INTERRUPTS
+ ACALL TWO_EX ;PUT TIMER ON THE STACK
+ POP ACC ;GET MILLI
+ ACALL TWO_R2 ;PUT MILLI ON STACK
+ MOV A,#200
+ ACALL TWO_R2 ;DIVIDE MILLI BY 200
+ ACALL ADIV
+ ;
+AADD: LCALL FP_BASE ;DO FP ADDITION
+ AJMP FPTST ;CHECK FOR ERRORS
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; Here are some error messages that were moved
+ ;
+ ;**************************************************************
+ ;
+ ;
+E1X: DB "BAD SYNTAX",'"'
+E2X: DB 128+10
+ DB "DIVIDE BY ZERO",'"'
+ ;
+E6X: DB "ARRAY SIZE",'"'
+ ;
+ newpage
+ ;**************************************************************
+ ;
+T_BUF: ; TXA gets IBUF
+ ;
+ ;**************************************************************
+ ;
+ MOV TXAH,#HI(IBUF)
+ MOV TXAL,#LO(IBUF)
+ RET
+ ;
+ ;
+ ;***************************************************************
+ ;
+CXFER: ; Transfer a program from rom to ram
+ ;
+ ;***************************************************************
+ ;
+ CALL CCAL ;GET EVERYTHING SET UP
+ MOV R2,#HI(PSTART)
+ MOV R0,#LO(PSTART)
+ ACALL LMOV ;DO THE TRANSFER
+ CALL RCLEAR ;CLEAR THE MEMORY
+ ;
+ ; Fall thru to CRAM
+ ;
+ ;***************************************************************
+ ;
+CRAM: ; The command action routine - RAM - Run out of ram
+ ;
+ ;***************************************************************
+ ;
+ CLR CONB ;CAN'T CONTINUE IF MODE CHANGE
+ MOV BOFAH,#HI(PSTART)
+ MOV BOFAL,#LO(PSTART)
+ ;
+ ; Fall thru to Command Processor
+ ;
+ newpage
+ ;***************************************************************
+ ;
+CMND1: ; The entry point for the command processor
+ ;
+ ;***************************************************************
+ ;
+ LCALL SPRINT+4 ;WASTE AT AND HEX
+ CLR XBIT ;TO RESET IF NEEDED
+ CLR A
+ MOV DPTR,#2002H ;CHECK FOR EXTERNAL TRAP PACKAGE
+ MOVC A,@A+DPTR
+ CJNE A,#5AH,$+6
+ LCALL 2048H ;IF PRESENT JUMP TO LOCATION 200BH
+ MOV DPTR,#RDYS ;PRINT THE READY MESSAGE
+ CALL CRP ;DO A CR, THEN, PRINT FROM THE ROM
+ ;
+CMNDR: SETB DIRF ;SET THE DIRECT INPUT BIT
+ MOV SP,SPSAV ;LOAD THE STACK
+ ACALL CL7 ;DO A CRLF
+ ;
+CMNX: CLR GTRD ;CLEAR BREAK
+ MOV DPTR,#5EH ;DO RUN TRAP
+ MOVX A,@DPTR
+ XRL A,#52
+ JNZ $+5
+ LJMP CRUN
+ MOV R5,#'>' ;OUTPUT A PROMPT
+ LCALL TEROT
+ CALL INLINE ;INPUT A LINE INTO IBUF
+ CALL PP ;PRE-PROCESS THE LINE
+ JB F0,CMND3 ;NO LINE NUMBER
+ CALL LINE ;PROCESS THE LINE
+ LCALL LCLR
+ JB LINEB,CMNX ;DON'T CLEAR MEMORY IF NO NEED
+ SETB LINEB
+ LCALL RCLEAR ;CLEAR THE MEMORY
+ SJMP CMNX ;LOOP BACK
+ ;
+CMND3: CALL T_BUF ;SET UP THE TEXT POINTER
+ CALL DELTST ;GET THE CHARACTER
+ JZ CMNDR ;IF CR, EXIT
+ MOV DPTR,#CMNDD ;POINT AT THE COMMAND LOOKUP
+ CJNE A,#T_CMND,$+3 ;PROCESS STATEMENT IF NOT A COMMAND
+ JC CMND5
+ CALL GCI1 ;BUMP TXA
+ ANL A,#0FH ;STRIP MSB'S FOR LOOKUP
+ LCALL ISTA1 ;PROCESS COMMAND
+ SJMP CMNDR
+ ;
+CMND5: LJMP ILOOP ;CHECK FOR A POSSIBLE BREAK
+ ;
+ ;
+ ;
+ ;CONSTANTS
+ ;
+XTALV: DB 128+8 ; DEFAULT CRYSTAL VALUE
+ DB 00H
+ DB 00H
+ DB 92H
+ DB 05H
+ DB 11H
+ ;
+EXP11: DB 85H
+ DB 00H
+ DB 42H
+ DB 41H
+ DB 87H
+ DB 59H
+ ;
+EXP1: DB 128+1 ; EXP(1)
+ DB 00H
+ DB 18H
+ DB 28H
+ DB 18H
+ DB 27H
+ ;
+IPTIME: DB 128-4 ;FPROG TIMING
+ DB 00H
+ DB 00H
+ DB 00H
+ DB 75H
+ DB 83H
+ ;
+PIE: DB 128+1 ;PI
+ DB 00H
+ DB 26H
+ DB 59H
+ DB 41H
+ DB 31H ; 3.1415926
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The error messages, some have been moved
+ ;
+ ;***************************************************************
+ ;
+E7X: DB 128+30
+ DB "ARITH. UNDERFLOW",'"'
+ ;
+E5X: DB "MEMORY ALLOCATION",'"'
+ ;
+E3X: DB 128+40
+ DB "BAD ARGUMENT",'"'
+ ;
+EXI: DB "I-STACK",'"'
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ ; The command action routine - CONTINUE
+ ;
+ ;***************************************************************
+ ;
+CCONT: MOV DPTR,#E15X
+ JNB CONB,ERROR ;ERROR IF CONTINUE IS NOT SET
+ ;
+CC1: ;used for input statement entry
+ ;
+ MOV TXAH,INTXAH ;RESTORE TXA
+ MOV TXAL,INTXAL
+ JMP CILOOP ;EXECUTE
+ ;
+DTEMP: MOV DPH,TEMP5 ;RESTORE DPTR
+ MOV DPL,TEMP4
+ RET
+ ;
+TEMPD: MOV TEMP5,DPH
+ MOV TEMP4,DPL
+ RET
+ ;
+ newpage
+ ;**************************************************************
+ ;
+I_DL: ; IDLE
+ ;
+ ;**************************************************************
+ ;
+ JB DIRF,E1XX ;SYNTAX ERROR IN DIRECT INPUT
+ CLR DACK ;ACK IDLE
+ ;
+U_ID1: DB 01000011B ;ORL DIRECT OP CODE
+ DB 87H ;PCON ADDRESS
+ DB 01H ;SET IDLE BIT
+ JB INTPEN,I_RET ;EXIT IF EXTERNAL INTERRUPT
+ JBC U_IDL,I_RET ;EXIT IF USER WANTS TO
+ JNB OTS,U_ID1 ;LOOP IF TIMER NOT ENABLED
+ LCALL T_CMP ;CHECK THE TIMER
+ JC U_ID1 ;LOOP IF TIME NOT BIG ENOUGH
+ ;
+I_RET: SETB DACK ;RESTORE EXECUTION
+ RET ;EXIT IF IT IS
+ ;
+ ;
+ ;
+ER0: INC DPTR ;BUMP TO TEXT
+ JB DIRF,ERROR0 ;CAN'T GET OUT OF DIRECT MODE
+ JNB ON_ERR,ERROR0 ;IF ON ERROR ISN'T SET, GO BACK
+ MOV DPTR,#ERRLOC ;SAVE THE ERROR CODE
+ CALL RC2 ;SAVE ERROR AND SET UP THE STACKS
+ INC DPTR ;POINT AT ERRNUM
+ JMP ERL4 ;LOAD ERR NUM AND EXIT
+ ;
+ newpage
+ ;
+ ; Syntax error
+ ;
+E1XX: MOV C,DIRF ;SEE IF IN DIRECT MODE
+ MOV DPTR,#E1X ;ERROR MESSAGE
+ SJMP ERROR+1 ;TRAP ON SET DIRF
+ ;
+ MOV DPTR,#EXI ;STACK ERROR
+ ;
+ ; Falls through
+ ;
+ ;***************************************************************
+ ;
+ ;ERROR PROCESSOR - PRINT OUT THE ERROR TYPE, CHECK TO SEE IF IN
+ ; RUN OR COMMAND MODE, FIND AND PRINT OUT THE
+ ; LINE NUMBER IF IN RUN MODE
+ ;
+ ;***************************************************************
+ ;
+ERROR: CLR C ;RESET STACK
+ MOV SP,SPSAV ;RESET THE STACK
+ LCALL SPRINT+4 ;CLEAR LINE AND AT MODE
+ CLR A ;SET UP TO GET ERROR CODE
+ MOVC A,@A+DPTR
+ JBC ACC.7,ER0 ;PROCESS ERROR
+ ;
+ERROR0: ACALL TEMPD ;SAVE THE DATA POINTER
+ JC $+5 ;NO RESET IF CARRY IS SET
+ LCALL RC1 ;RESET THE STACKS
+ CALL CRLF2 ;DO TWO CARRIAGE RET - LINE FEED
+ MOV DPTR,#ERS ;OUTPUT ERROR MESSAGE
+ CALL ROM_P
+ CALL DTEMP ;GET THE ERROR MESSAGE BACK
+ ;
+ERRS: CALL ROM_P ;PRINT ERROR TYPE
+ JNB DIRF,ER1 ;DO NOT PRINT IN LINE IF DIRF=1
+ ;
+SERR1: CLR STOPBIT ;PRINT STOP THEN EXIT, FOR LIST
+ JMP CMND1
+ ;
+ER1: MOV DPTR,#INS ;OUTPUT IN LINE
+ CALL ROM_P
+ ;
+ ;NOW, FIND THE LINE NUMBER
+ ;
+ ;
+ newpage
+ ;
+ ;
+ CALL DP_B ;GET THE FIRST ADDRESS OF THE PROGRAM
+ CLR A ;FOR INITIALIZATION
+ ;
+ER2: ACALL TEMPD ;SAVE THE DPTR
+ CALL ADDPTR ;ADD ACC TO DPTR
+ ACALL ER4 ;R3:R1 = TXA-DPTR
+ JC ER3 ;EXIT IF DPTR>TXA
+ JZ ER3 ;EXIT IF DPTR=TXA
+ MOVX A,@DPTR ;GET LENGTH
+ CJNE A,#EOF,ER2 ;SEE IF AT THE END
+ ;
+ER3: ACALL DTEMP ;PUT THE LINE IN THE DPTR
+ ACALL ER4 ;R3:R1 = TXA - BEGINNING OF LINE
+ MOV A,R1 ;GET LENGTH
+ ADD A,#10 ;ADD 10 TO LENGTH, DPTR STILL HAS ADR
+ MOV MT1,A ;SAVE THE COUNT
+ INC DPTR ;POINT AT LINE NUMBER HIGH BYTE
+ CALL PMTOP+3 ;LOAD R2:R0, PUT IT ON THE STACK
+ ACALL FP_BASE+14 ;OUTPUT IT
+ JB STOPBIT,SERR1 ;EXIT IF STOP BIT SET
+ CALL CRLF2 ;DO SOME CRLF'S
+ CALL DTEMP
+ CALL UPPL ;UNPROCESS THE LINE
+ CALL CL6 ;PRINT IT
+ MOV R5,#'-' ;OUTPUT DASHES, THEN AN X
+ ACALL T_L ;PRINT AN X IF ERROR CHARACTER FOUND
+ DJNZ MT1,$-4 ;LOOP UNTIL DONE
+ MOV R5,#'X'
+ ACALL T_L
+ AJMP SERR1
+ ;
+ER4: MOV R3,TXAH ;GET TEXT POINTER AND PERFORM SUBTRACTION
+ MOV R1,TXAL
+ JMP DUBSUB
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; Interrupt driven timer
+ ;
+ ;**************************************************************
+ ;
+I_DR: MOV TH0,SAVE_T ;LOAD THE TIMER
+ XCH A,MILLIV ;SAVE A, GET MILLI COUNTER
+ INC A ;BUMP COUNTER
+ CJNE A,#200,TR ;CHECK OUT TIMER VALUE
+ CLR A ;FORCE ACC TO BE ZERO
+ INC TVL ;INCREMENT LOW TIMER
+ CJNE A,TVL,TR ;CHECK LOW VALUE
+ INC TVH ;BUMP TIMER HIGH
+ ;
+TR: XCH A,MILLIV
+ POP PSW
+ RETI
+ ;
+ newpage
+ include bas52.clk
+ ;***************************************************************
+ ;
+SUI: ; Statement USER IN action routine
+ ;
+ ;***************************************************************
+ ;
+ ACALL OTST
+ MOV CIUB,C ;SET OR CLEAR CIUB
+ RET
+ ;
+ ;***************************************************************
+ ;
+SUO: ; Statement USER OUT action routine
+ ;
+ ;***************************************************************
+ ;
+ ACALL OTST
+ MOV COUB,C
+ RET
+ ;
+OTST: ; Check for a one
+ ;
+ LCALL GCI ;GET THE CHARACTER, CLEARS CARRY
+ SUBB A,#'1' ;SEE IF A ONE
+ CPL C ;SETS CARRY IF ONE, CLEARS IT IF ZERO
+ RET
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; IBLK - EXECUTE USER SUPPLIED TOKEN
+ ;
+ ;**************************************************************
+ ;
+IBLK: JB PSW.4,IBLK-1 ;EXIT IF REGISTER BANK <> 0
+ JB PSW.3,IBLK-1
+ JBC ACC.7,$+9 ;SEE IF BIT SEVEN IS SET
+ MOV DPTR,#USENT ;USER ENTRY LOCATION
+ LJMP ISTA1
+ ;
+ JB ACC.0,199FH ;FLOATING POINT INPUT
+ JZ T_L ;DO OUTPUT ON 80H
+ MOV DPTR,#FP_BASE-2
+ JMP @A+DPTR
+ ;
+ ;
+ ;**************************************************************
+ ;
+ ; GET_NUM - GET A NUMBER, EITHER HEX OR FLOAT
+ ;
+ ;**************************************************************
+ ;
+GET_NUM:ACALL FP_BASE+10 ;SCAN FOR HEX
+ JNC FP_BASE+12 ;DO FP INPUT
+ ;
+ ACALL FP_BASE+18 ;ASCII STRING TO R2:R0
+ JNZ H_RET
+ PUSH DPH ;SAVE THE DATA_POINTER
+ PUSH DPL
+ ACALL FP_BASE+24 ;PUT R2:R0 ON THE STACK
+ POP DPL ;RESTORE THE DATA_POINTER
+ POP DPH
+ CLR A ;NO ERRORS
+ RET ;EXIT
+ ;
+ newpage
+ ;**************************************************************
+ ;
+ ; WB - THE EGO MESSAGE
+ ;
+ ;**************************************************************
+ ;
+WB: DB 'W'+80H,'R'+80H
+ DB 'I'+80H,'T'+80H,'T','E'+80H,'N'+80H
+ DB ' ','B'+80H,'Y'+80H,' '
+ DB 'J'+80H,'O'+80H,'H'+80H,'N'+80H,' '+80H
+ DB 'K','A'+80H,'T'+80H,'A'+80H,'U'+80H
+ DB 'S','K'+80H,'Y'+80H
+ DB ", I",'N'+80H,'T'+80H,'E'+80H,'L'+80H
+ DB ' '+80H,'C'+80H,'O'+80H,'R'+80H,'P'+80H
+ DB ". 1",'9'+80H,"85"
+H_RET: RET
+ ;
+ newpage
+ ORG 1990H
+ ;
+T_L: LJMP TEROT
+ ;
+ ORG 1F78H
+ ;
+CKS_I: JB CKS_B,CS_I
+ LJMP 401BH
+ ;
+CS_I: LJMP 2088H
+ ;
+E14X: DB "NO DATA",'"'
+ ;
+E11X: DB 128+20
+ DB "ARITH. OVERFLOW",'"'
+ ;
+E16X: DB "PROGRAMMING",'"'
+ ;
+E15X: DB "CAN"
+ DB 27H
+ DB "T CONTINUE",'"'
+ ;
+E10X: DB "INVALID LINE NUMBER",'"'
+ ;
+NOROM: DB "PROM MODE",'"'
+ ;
+S_N: DB "*MCS-51(tm) BASIC V1.1*",'"'
+ ;
+ ORG 1FF8H
+ ;
+ERS: DB "ERROR: ",'"'
+ ;
+ newpage
+ ;***************************************************************
+ ;
+ segment xdata ;External Ram
+ ;
+ ;***************************************************************
+ ;
+ DS 4
+IBCNT: DS 1 ;LENGTH OF A LINE
+IBLN: DS 2 ;THE LINE NUMBER
+IBUF: DS LINLEN ;THE INPUT BUFFER
+CONVT: DS 15 ;CONVERSION LOCATION FOR FPIN
+ ;
+ ORG 100H
+ ;
+GTB: DS 1 ;GET LOCATION
+ERRLOC: DS 1 ;ERROR TYPE
+ERRNUM: DS 2 ;WHERE TO GO ON AN ERROR
+VARTOP: DS 2 ;TOP OF VARIABLE STORAGE
+ST_ALL: DS 2 ;STORAGE ALLOCATION
+MT_ALL: DS 2 ;MATRIX ALLOCATION
+MEMTOP: DS 2 ;TOP OF MEMORY
+RCELL: DS 2 ;RANDOM NUMBER CELL
+ DS FPSIZ-1
+CXTAL: DS 1 ;CRYSTAL
+ DS FPSIZ-1
+FPT1: DS 1 ;FLOATINP POINT TEMP 1
+ DS FPSIZ-1
+FPT2: DS 1 ;FLOATING POINT TEMP 2
+INTLOC: DS 2 ;LOCATION TO GO TO ON INTERRUPT
+STR_AL: DS 2 ;STRING ALLOCATION
+SPV: DS 2 ;SERIAL PORT BAUD RATE
+TIV: DS 2 ;TIMER INTERRUPT NUM AND LOC
+PROGS: DS 2 ;PROGRAM A PROM TIME OUT
+IPROGS: DS 2 ;INTELLIGENT PROM PROGRAMMER TIMEOUT
+TM_TOP: DS 1
+
+ include bas52.fp
+
+ END
diff --git a/tests/t_bas52/t_bas52.doc b/tests/t_bas52/t_bas52.doc
new file mode 100644
index 0000000..05efe9d
--- /dev/null
+++ b/tests/t_bas52/t_bas52.doc
@@ -0,0 +1,11 @@
++---------------------- Test Application BAS52 ----------------------------+
+| |
+| This is the source of the BASIC interpreter for Intel's 8052AH-Basic |
+| (version 1.1). In contrast to other test programs, the reference binary |
+| was extracted from a real 8052AH and not generated with the BP version |
+| of AS. Since the source of this interpreter is now freeware, it should |
+| be okay to include this program. Of course, I had to modify the code a |
+| bit to adapt it to AS... The source and ROM dump was provided by |
+| squest@cris.com. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_bas52/t_bas52.inc b/tests/t_bas52/t_bas52.inc
new file mode 100644
index 0000000..6bf1b5c
--- /dev/null
+++ b/tests/t_bas52/t_bas52.inc
@@ -0,0 +1,2 @@
+; tests/t_bas52/t_bas52.asm-Includefile für Assembler-Programm
+; Ende Includefile für Assembler-Programm
diff --git a/tests/t_bas52/t_bas52.ori b/tests/t_bas52/t_bas52.ori
new file mode 100644
index 0000000..f86786d
--- /dev/null
+++ b/tests/t_bas52/t_bas52.ori
Binary files differ
diff --git a/tests/t_buf32/asflags b/tests/t_buf32/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_buf32/asflags
diff --git a/tests/t_buf32/t_buf32.asm b/tests/t_buf32/t_buf32.asm
new file mode 100644
index 0000000..83e1d42
--- /dev/null
+++ b/tests/t_buf32/t_buf32.asm
@@ -0,0 +1,4883 @@
+;* BUFFALO
+;* "Bit User's Fast Friendly Aid to Logical Operation"
+;*
+;* Rev 2.0 - 4/23/85 - added disassembler.
+;* - variables now PTRn and TMPn.
+;* Rev 2.1 - 4/29/85 - added byte erase to chgbyt routine.
+;* Rev 2.2 - 5/16/85 - added hooks for evb board - acia
+;* drivers, init and host routines.
+;* 7/8/85 - fixed dump wraparound problem.
+;* 7/10/85 - added evm board commands.
+;* - added fill instruction.
+;* 7/18/85 - added jump to EEPROM.
+;* Rev 2.3 - 8/22/85 - call targco to disconnect sci from host
+;* in reset routine for evb board.
+;* 10/3/85 - modified load for download through terminal.
+;* Rev 2.4 - 7/1/86 - Changed DFLOP address to fix conflicts with
+;* EEPROM. (was at A000)
+;* Rev 2.5 - 9/8/86 - Modified to provide additional protection from
+;* program run-away on power down. Also fixed bugs
+;* in MM and MOVE. Changed to 1 stop bit from 2.
+;* Rev 2.6 - 9/25/86 - Modified boot routine for variable length download
+;* for use with 'HC11E8.
+;* Rev 3.0 1/15/87 - EEPROM programming routines consolidated into WRITE.
+;* Fill, Assem, and breakpoints will now do EEPROM.
+;* - Added compare a to $0D to WSKIP routine.
+;* 2/11/87 - Set up load to detect receiver error.
+;* Rev 3.2 7/7/87 - Add disassembly to trace.
+;* - Add entries to jump table.
+;* 9/20/87 - Rewrote trace to use XIRQ, added STOPAT Command
+;* 11/24/87- Write block protect reg for 'E9 version
+;* - Modified variable length download for use
+;* with 'E9 bootloader (XBOOT command)
+;*
+;*
+;****************************************************
+;* Although the information contained herein, *
+;* as well as any information provided relative *
+;* thereto, has been carefully reviewed and is *
+;* believed accurate, Motorola assumes no *
+;* liability arising out of its application or *
+;* use, neither does it convey any license under *
+;* its patent rights nor the rights of others. *
+;****************************************************
+
+ CPU 6811
+
+;***************
+;* EQUATES *
+;***************
+RAMBS EQU $0000 ; start of ram
+REGBS EQU $1000 ; start of registers
+ROMBS EQU $E000 ; start of rom
+STREE EQU $B600 ; start of eeprom
+ENDEE EQU $B7FF ; end of eeprom
+PORTE EQU REGBS+$0A ; port e
+CFORC EQU REGBS+$0B ; force output compare
+TCNT EQU REGBS+$0E ; timer count
+TOC5 EQU REGBS+$1E ; oc5 reg
+TCTL1 EQU REGBS+$20 ; timer control 1
+TMSK1 EQU REGBS+$22 ; timer mask 1
+TFLG1 EQU REGBS+$23 ; timer flag 1
+TMSK2 EQU REGBS+$24 ; timer mask 2
+BAUD EQU REGBS+$2B ; sci baud reg
+SCCR1 EQU REGBS+$2C ; sci control1 reg
+SCCR2 EQU REGBS+$2D ; sci control2 reg
+SCSR EQU REGBS+$2E ; sci status reg
+SCDAT EQU REGBS+$2F ; sci data reg
+BPROT EQU REGBS+$35 ; block protect reg
+OPTION EQU REGBS+$39 ; option reg
+COPRST EQU REGBS+$3A ; cop reset reg
+PPROG EQU REGBS+$3B ; ee prog reg
+HPRIO EQU REGBS+$3C ; hprio reg
+CONFIG EQU REGBS+$3F ; config register
+DFLOP EQU $4000 ; evb d flip flop
+DUART EQU $D000 ; duart address
+PORTA EQU DUART
+PORTB EQU DUART+8
+ACIA EQU $9800 ; acia address
+PROMPT EQU '>'
+BUFFLNG EQU 35
+CTLA EQU $01 ; exit host or assembler
+CTLB EQU $02 ; send break to host
+CTLW EQU $17 ; wait
+CTLX EQU $18 ; abort
+DEL EQU $7F ; abort
+EOT EQU $04 ; end of text/table
+SWI EQU $3F
+
+;***************
+;* RAM *
+;***************
+ ORG $33
+;*** Buffalo ram space ***
+ RMB 20 ; user stack area
+USTACK RMB 30 ; monitor stack area
+STACK RMB 1
+REGS RMB 9 ; user's pc,y,x,a,b,c
+SP RMB 2 ; user's sp
+INBUFF RMB BUFFLNG ; input buffer
+ENDBUFF EQU *
+COMBUFF RMB 8 ; command buffer
+SHFTREG RMB 2 ; input shift register
+BRKTABL RMB 8 ; breakpoint table
+AUTOLF RMB 1 ; auto lf flag for i/o
+IODEV RMB 1 ; 0=sci, 1=acia, 2=duartA, 3=duartB
+EXTDEV RMB 1 ; 0=none, 1=acia, 2=duart,
+HOSTDEV RMB 1 ; 0=sci, 1=acia, 3=duartB
+COUNT RMB 1 ; # characters read
+CHRCNT RMB 1 ; # characters output on current line
+PTRMEM RMB 2 ; current memory location
+
+;*** Buffalo variables - used by: ***
+PTR0 RMB 2 ; main,readbuff,incbuff,AS
+PTR1 RMB 2 ; main,BR,DU,MO,AS,EX
+PTR2 RMB 2 ; EX,DU,MO,AS
+PTR3 RMB 2 ; EX,HO,MO,AS
+PTR4 RMB 2 ; EX,AS
+PTR5 RMB 2 ; EX,AS,BOOT
+PTR6 RMB 2 ; EX,AS,BOOT
+PTR7 RMB 2 ; EX,AS
+PTR8 RMB 2 ; AS
+TMP1 RMB 1 ; main,hexbin,buffarg,termarg
+TMP2 RMB 1 ; GO,HO,AS,LOAD
+TMP3 RMB 1 ; AS,LOAD
+TMP4 RMB 1 ; TR,HO,ME,AS,LOAD
+;*** Vector jump table ***
+JSCI RMB 3
+JSPI RMB 3
+JPAIE RMB 3
+JPAO RMB 3
+JTOF RMB 3
+JTOC5 RMB 3
+JTOC4 RMB 3
+JTOC3 RMB 3
+JTOC2 RMB 3
+JTOC1 RMB 3
+JTIC3 RMB 3
+JTIC2 RMB 3
+JTIC1 RMB 3
+JRTI RMB 3
+JIRQ RMB 3
+JXIRQ RMB 3
+JSWI RMB 3
+JILLOP RMB 3
+JCOP RMB 3
+JCLM RMB 3
+
+;*****************
+;*
+;* ROM starts here *
+;*
+;*****************
+
+ ORG ROMBS
+
+;*****************
+;** BUFFALO - This is where Buffalo starts
+;** out of reset. All initialization is done
+;** here including determination of where the
+;** user terminal is (SCI,ACIA, or DUART).
+;*****************
+
+BUFFALO LDX #PORTE
+ BRCLR 0,X,#01,BUFISIT ; if bit 0 of port e is 1
+ JMP $B600 ; then jump to the start of EEPROM
+BUFISIT LDAA #$93
+ STAA OPTION ; adpu, dly, irqe, cop
+ LDAA #$00
+ STAA TMSK2 ; timer pre = %1 for trace
+ LDAA #$00
+ STAA BPROT ; clear 'E9 eeprom block protect
+ LDS #STACK ; monitor stack pointer
+ JSR VECINIT
+ LDX #USTACK
+ STX SP ; default user stack
+ LDAA TCTL1
+ ORAA #$03
+ STAA TCTL1 ; force oc5 pin high for trace
+ LDAA #$D0
+ STAA REGS+8 ; default user ccr
+ LDD #$3F0D ; initial command is ?
+ STD INBUFF
+ JSR BPCLR ; clear breakpoints
+ CLR AUTOLF
+ INC AUTOLF ; auto cr/lf = on
+
+;* Determine type of external comm device - none, or acia *
+
+ CLR EXTDEV ; default is none
+ LDAA HPRIO
+ ANDA #$20
+ BEQ BUFF2 ; jump if single chip mode
+ LDAA #$03 ; see if external acia exists
+ STAA ACIA ; master reset
+ LDAA ACIA
+ ANDA #$7F ; mask irq bit from status register
+ BNE BUFF1 ; jump if status reg not 0
+ LDAA #$12
+ STAA ACIA ; turn on acia
+ LDAA ACIA
+ ANDA #$02
+ BEQ BUFF1 ; jump if tdre not set
+ LDAA #$01
+ STAA EXTDEV ; external device is acia
+ BRA BUFF2
+
+BUFF1 EQU * ; see if duart exists
+ LDAA DUART+$0C ; read IRQ vector register
+ CMPA #$0F ; should be out of reset
+ BNE BUFF2
+ LDAA #$AA
+ STAA DUART+$0C ; write irq vector register
+ LDAA DUART+$0C ; read irq vector register
+ CMPA #$AA
+ BNE BUFF2
+ LDAA #$02
+ STAA EXTDEV ; external device is duart A
+
+;* Find terminal port - SCI or external. *
+
+BUFF2 CLR IODEV
+ JSR TARGCO ; disconnect sci for evb board
+ JSR SIGNON ; initialize sci
+ LDAA EXTDEV
+ BEQ BUFF3 ; jump if no external device
+ STAA IODEV
+ JSR SIGNON ; initialize external device
+BUFF3 CLR IODEV
+ JSR INPUT ; get input from sci port
+ CMPA #$0D
+ BEQ BUFF4 ; jump if cr - sci is terminal port
+ LDAA EXTDEV
+ BEQ BUFF3 ; jump if no external device
+ STAA IODEV
+ JSR INPUT ; get input from external device
+ CMPA #$0D
+ BEQ BUFF4 ; jump if cr - terminal found ext
+ BRA BUFF3
+
+SIGNON JSR INIT ; initialize device
+ LDX #MSG1 ; buffalo message
+ JSR OUTSTRG
+ RTS
+
+;* Determine where host port should be. *
+
+BUFF4 CLR HOSTDEV ; default - host = sci port
+ LDAA IODEV
+ CMPA #$01
+ BEQ BUFF5 ; default host if term = acia
+ LDAA #$03
+ STAA HOSTDEV ; else host is duart port b
+BUFF5 EQU *
+
+;*****************
+;** MAIN - This module reads the user's input into
+;** a buffer called INBUFF. The first field (assumed
+;** to be the command field) is then parsed into a
+;** second buffer called COMBUFF. The command table
+;** is then searched for the contents of COMBUFF and
+;** if found, the address of the corresponding task
+;** routine is fetched from the command table. The
+;** task is then called as a subroutine so that
+;** control returns back to here upon completion of
+;** the task. Buffalo expects the following format
+;** for commands:
+;** <cmd>[<wsp><arg><wsp><arg>...]<cr>
+;** [] implies contents optional.
+;** <wsp> means whitespace character (space,comma,tab).
+;** <cmd> = command string of 1-8 characters.
+;** <arg> = Argument particular to the command.
+;** <cr> = Carriage return signifying end of input string.
+;*****************
+;* Prompt user
+;*do
+;* a=input();
+;* if(a==(cntlx or del)) continue;
+;* elseif(a==backspace)
+;* b--;
+;* if(b<0) b=0;
+;* else
+;* if(a==cr && buffer empty)
+;* repeat last command;
+;* else put a into buffer;
+;* check if buffer full;
+;*while(a != (cr or /)
+
+MAIN LDS #STACK ; initialize sp every time
+ CLR AUTOLF
+ INC AUTOLF ; auto cr/lf = on
+ JSR OUTCRLF
+ LDAA #PROMPT ; prompt user
+ JSR OUTPUT
+ CLRB
+MAIN1 JSR INCHAR ; read terminal
+ LDX #INBUFF
+ ABX ; pointer into buffer
+ CMPA #CTLX
+ BEQ MAIN ; jump if cntl X
+ CMPA #DEL
+ BEQ MAIN ; jump if del
+ CMPA #$08
+ BNE MAIN2 ; jump if not bckspc
+ DECB
+ BLT MAIN ; jump if buffer empty
+ BRA MAIN1
+MAIN2 CMPA #$D
+ BNE MAIN3 ; jump if not cr
+ TSTB
+ BEQ COMM0 ; jump if buffer empty
+ STAA ,X ; put a in buffer
+ BRA COMM0
+MAIN3 STAA ,X ; put a in buffer
+ INCB
+ CMPB #BUFFLNG
+ BLE MAIN4 ; jump if not long
+ LDX #MSG3 ; "long"
+ JSR OUTSTRG
+ BRA MAIN
+MAIN4 CMPA #'/'
+ BNE MAIN1 ; jump if not "/"
+;* *******************
+
+;*****************
+;* Parse out and evaluate the command field.
+;*****************
+;*Initialize
+
+COMM0 EQU *
+ CLR TMP1 ; Enable "/" command
+ CLR SHFTREG
+ CLR SHFTREG+1
+ CLRB
+ LDX #INBUFF ; ptrbuff[] = inbuff[]
+ STX PTR0
+ JSR WSKIP ; find first char
+
+;*while((a=readbuff) != (cr or wspace))
+;* upcase(a);
+;* buffptr[b] = a
+;* b++
+;* if (b > 8) error(too long);
+;* if(a == "/")
+;* if(enabled) mslash();
+;* else error(command?);
+;* else hexbin(a);
+
+COMM1 EQU *
+ JSR READBUFF ; read from buffer
+ LDX #COMBUFF
+ ABX
+ JSR UPCASE ; convert to upper case
+ STAA ,X ; put in command buffer
+ CMPA #$0D
+ BEQ SRCH ; jump if cr
+ JSR WCHEK
+ BEQ SRCH ; jump if wspac
+ JSR INCBUFF ; move buffer pointer
+ INCB
+ CMPB #$8
+ BLE COMM2
+ LDX #MSG3 ; "long"
+ JSR OUTSTRG
+ JMP MAIN
+
+COMM2 EQU *
+ CMPA #'/'
+ BNE COMM4 ; jump if not "/"
+ TST TMP1
+ BNE COMM3 ; jump if not enabled
+ DECB
+ STAB COUNT
+ LDX #MSLASH
+ JMP EXEC ; execute "/"
+COMM3 LDX #MSG8 ; "command?"
+ JSR OUTSTRG
+ JMP MAIN
+COMM4 EQU *
+ JSR HEXBIN
+ BRA COMM1
+
+;*****************
+;* Search tables for command. At this point,
+;* COMBUFF holds the command field to be executed,
+;* and B = # of characters in the command field.
+;* The command table holds the whole command name
+;* but only the first n characters of the command
+;* must match what is in COMBUFF where n is the
+;* number of characters entered by the user.
+;*****************
+;*count = b;
+;*ptr1 = comtabl;
+;*while(ptr1[0] != end of table)
+;* ptr1 = next entry
+;* for(b=1; b=count; b++)
+;* if(ptr1[b] == combuff[b]) continue;
+;* else error(not found);
+;* execute task;
+;* return();
+;*return(command not found);
+
+SRCH STAB COUNT ; size of command entered
+ LDX #COMTABL ; pointer to table
+ STX PTR1 ; pointer to next entry
+SRCH1 LDX PTR1
+ LDY #COMBUFF ; pointer to command buffer
+ LDAB 0,X
+ CMPB #$FF
+ BNE SRCH2
+ LDX #MSG2 ; "command not found"
+ JSR OUTSTRG
+ JMP MAIN
+SRCH2 PSHX ; compute next table entry
+ ADDB #$3
+ ABX
+ STX PTR1
+ PULX
+ CLRB
+SRCHLP INCB ; match characters loop
+ LDAA 1,X ; read table
+ CMPA 0,Y ; compare to combuff
+ BNE SRCH1 ; try next entry
+ INX ; move pointers
+ INY
+ CMPB COUNT
+ BLT SRCHLP ; loop countu1 times
+ LDX PTR1
+ DEX
+ DEX
+ LDX 0,X ; jump address from table
+EXEC JSR 0,X ; call task as subroutine
+ JMP MAIN
+;*
+;*****************
+;* UTILITY SUBROUTINES - These routines
+;* are called by any of the task routines.
+;*****************
+;*****************
+;* UPCASE(a) - If the contents of A is alpha,
+;* returns a converted to uppercase.
+;*****************
+UPCASE CMPA #'a'
+ BLT UPCASE1 ; jump if < a
+ CMPA #'z'
+ BGT UPCASE1 ; jump if > z
+ SUBA #$20 ; convert
+UPCASE1 RTS
+
+;*****************
+;* BPCLR() - Clear all entries in the
+;* table of breakpoints.
+;*****************
+BPCLR LDX #BRKTABL
+ LDAB #8
+BPCLR1 CLR 0,X
+ INX
+ DECB
+ BGT BPCLR1 ; loop 8 times
+ RTS
+
+;*****************
+;* RPRNT1(x) - Prints name and contents of a single
+;* user register. On entry X points to name of register
+;* in reglist. On exit, a=register name.
+;*****************
+REGLIST FCC "PYXABCS" ; names
+ FCB 0,2,4,6,7,8,9 ; offset
+ FCB 1,1,1,0,0,0,1 ; size
+RPRNT1 LDAA 0,X
+ PSHA
+ PSHX
+ JSR OUTPUT ; name
+ LDAA #'-'
+ JSR OUTPUT ; dash
+ LDAB 7,X ; contents offset
+ LDAA 14,X ; bytesize
+ LDX #REGS ; address
+ ABX
+ TSTA
+ BEQ RPRN2 ; jump if 1 byte
+ JSR OUT1BYT ; 2 bytes
+RPRN2 JSR OUT1BSP
+ PULX
+ PULA
+ RTS
+
+;*****************
+;* RPRINT() - Print the name and contents
+;* of all the user registers.
+;*****************
+RPRINT PSHX
+ LDX #REGLIST
+RPRI1 JSR RPRNT1 ; print name
+ INX
+ CMPA #'S' ; s is last register
+ BNE RPRI1 ; jump if not done
+ PULX
+ RTS
+
+;*****************
+;* HEXBIN(a) - Convert the ASCII character in a
+;* to binary and shift into shftreg. Returns value
+;* in tmp1 incremented if a is not hex.
+;*****************
+HEXBIN PSHA
+ PSHB
+ PSHX
+ JSR UPCASE ; convert to upper case
+ CMPA #'0'
+ BLT HEXNOT ; jump if a < $30
+ CMPA #'9'
+ BLE HEXNMB ; jump if 0-9
+ CMPA #'A'
+ BLT HEXNOT ; jump if $39> a <$41
+ CMPA #'F'
+ BGT HEXNOT ; jump if a > $46
+ ADDA #$9 ; convert $A-$F
+HEXNMB ANDA #$0F ; convert to binary
+ LDX #SHFTREG
+ LDAB #4
+HEXSHFT ASL 1,X ; 2 byte shift through
+ ROL 0,X ; carry bit
+ DECB
+ BGT HEXSHFT ; shift 4 times
+ ORAA 1,X
+ STAA 1,X
+ BRA HEXRTS
+HEXNOT INC TMP1 ; indicate not hex
+HEXRTS PULX
+ PULB
+ PULA
+ RTS
+
+;*****************
+;* BUFFARG() - Build a hex argument from the
+;* contents of the input buffer. Characters are
+;* converted to binary and shifted into shftreg
+;* until a non-hex character is found. On exit
+;* shftreg holds the last four digits read, count
+;* holds the number of digits read, ptrbuff points
+;* to the first non-hex character read, and A holds
+;* that first non-hex character.
+;*****************
+;*Initialize
+;*while((a=readbuff()) not hex)
+;* hexbin(a);
+;*return();
+
+BUFFARG CLR TMP1 ; not hex indicator
+ CLR COUNT ; # or digits
+ CLR SHFTREG
+ CLR SHFTREG+1
+ JSR WSKIP
+BUFFLP JSR READBUFF ; read char
+ JSR HEXBIN
+ TST TMP1
+ BNE BUFFRTS ; jump if not hex
+ INC COUNT
+ JSR INCBUFF ; move buffer pointer
+ BRA BUFFLP
+BUFFRTS RTS
+
+;*****************
+;* TERMARG() - Build a hex argument from the
+;* terminal. Characters are converted to binary
+;* and shifted into shftreg until a non-hex character
+;* is found. On exit shftreg holds the last four
+;* digits read, count holds the number of digits
+;* read, and A holds the first non-hex character.
+;*****************
+;*initialize
+;*while((a=inchar()) == hex)
+;* if(a = cntlx or del)
+;* abort;
+;* else
+;* hexbin(a); countu1++;
+;*return();
+
+TERMARG CLR COUNT
+ CLR SHFTREG
+ CLR SHFTREG+1
+TERM0 JSR INCHAR
+ CMPA #CTLX
+ BEQ TERM1 ; jump if controlx
+ CMPA #DEL
+ BNE TERM2 ; jump if not delete
+TERM1 JMP MAIN ; abort
+TERM2 CLR TMP1 ; hex indicator
+ JSR HEXBIN
+ TST TMP1
+ BNE TERM3 ; jump if not hex
+ INC COUNT
+ BRA TERM0
+TERM3 RTS
+
+;*****************
+;* CHGBYT() - If shftreg is not empty, put
+;* contents of shftreg at address in X. If X
+;* is an address in EEPROM then program it.
+;*****************
+;*if(count != 0)
+;* (x) = a;
+CHGBYT TST COUNT
+ BEQ CHGBYT4 ; quit if shftreg empty
+ LDAA SHFTREG+1 ; get data into a
+ JSR WRITE
+CHGBYT4 RTS
+
+
+;*****************
+;* WRITE() - This routine is used to write the
+;*contents of A to the address of X. If the
+;*address is in EEPROM, it will be programmed
+;*and if it is already programmed, it will be
+;*byte erased first.
+;******************
+;*if(X is eeprom)then
+;* if(not erased) then erase;
+;* program (x) = A;
+;*write (x) = A;
+;*if((x) != A) error(rom);
+WRITE EQU *
+ CPX #CONFIG
+ BEQ WRITE1 ; jump if config
+ CPX #STREE ; start of EE
+ BLO WRITE2 ; jump if not EE
+ CPX #ENDEE ; end of EE
+ BHI WRITE2 ; jump if not EE
+WRITEE PSHB
+ LDAB 0,X
+ CMPB #$FF
+ PULB
+ BEQ WRITE1 ; jump if erased
+ JSR EEBYTE ; byte erase
+WRITE1 JSR EEWRIT ; byte program
+WRITE2 STAA 0,X ; write for non EE
+ CMPA 0,X
+ BEQ WRITE3 ; jump if write ok
+ PSHX
+ LDX #MSG6 ; "rom"
+ JSR OUTSTRG
+ PULX
+WRITE3 RTS
+
+
+;*****************
+;* EEWRIT(), EEBYTE(), EEBULK() -
+;* These routines are used to program and eeprom
+;*locations. eewrite programs the address in X with
+;*the value in A, eebyte does a byte address at X,
+;*and eebulk does a bulk of eeprom. Whether eebulk
+;*erases the config or not depends on the address it
+;*receives in X.
+;****************
+EEWRIT EQU * ; program one byte at x
+ PSHB
+ LDAB #$02
+ STAB PPROG
+ STAA 0,X
+ LDAB #$03
+ BRA EEPROG
+;***
+EEBYTE EQU * ; byte erase address x
+ PSHB
+ LDAB #$16
+ STAB PPROG
+ LDAB #$FF
+ STAB 0,X
+ LDAB #$17
+ BRA EEPROG
+;***
+EEBULK EQU * ; bulk erase eeprom
+ PSHB
+ LDAB #$06
+ STAB PPROG
+ LDAB #$FF
+ STAB 0,X ; erase config or not
+ LDAB #$07 ; depends on X addr
+EEPROG BNE ACL1
+ CLRB ; fail safe
+ACL1 STAB PPROG
+ PULB
+;***
+DLY10MS EQU * ; delay 10ms at E = 2MHz
+ PSHX
+ LDX #$0D06
+DLYLP DEX
+ BNE DLYLP
+ PULX
+ CLR PPROG
+ RTS
+
+
+;*****************
+;* READBUFF() - Read the character in INBUFF
+;* pointed at by ptrbuff into A. Returns ptrbuff
+;* unchanged.
+;*****************
+READBUFF PSHX
+ LDX PTR0
+ LDAA 0,X
+ PULX
+ RTS
+
+;*****************
+;* INCBUFF(), DECBUFF() - Increment or decrement
+;* ptrbuff.
+;*****************
+INCBUFF PSHX
+ LDX PTR0
+ INX
+ BRA INCDEC
+DECBUFF PSHX
+ LDX PTR0
+ DEX
+INCDEC STX PTR0
+ PULX
+ RTS
+
+;*****************
+;* WSKIP() - Read from the INBUFF until a
+;* non whitespace (space, comma, tab) character
+;* is found. Returns ptrbuff pointing to the
+;* first non-whitespace character and a holds
+;* that character. WSKIP also compares a to
+;* $0D (CR) and cond codes indicating the
+;* results of that compare.
+;*****************
+WSKIP JSR READBUFF ; read character
+ JSR WCHEK
+ BNE WSKIP1 ; jump if not wspc
+ JSR INCBUFF ; move pointer
+ BRA WSKIP ; loop
+WSKIP1 CMPA #$0D
+ RTS
+
+;*****************
+;* WCHEK(a) - Returns z=1 if a holds a
+;* whitespace character, else z=0.
+;*****************
+WCHEK CMPA #$2C ; comma
+ BEQ WCHEK1
+ CMPA #$20 ; space
+ BEQ WCHEK1
+ CMPA #$09 ; tab
+WCHEK1 RTS
+
+;*****************
+;* DCHEK(a) - Returns Z=1 if a = whitespace
+;* or carriage return. Else returns z=0.
+;*****************
+DCHEK JSR WCHEK
+ BEQ DCHEK1 ; jump if whitespace
+ CMPA #$0D
+DCHEK1 RTS
+
+;*****************
+;* CHKABRT() - Checks for a control x or delete
+;* from the terminal. If found, the stack is
+;* reset and the control is transferred to main.
+;* Note that this is an abnormal termination.
+;* If the input from the terminal is a control W
+;* then this routine keeps waiting until any other
+;* character is read.
+;*****************
+;*a=input();
+;*if(a=cntl w) wait until any other key;
+;*if(a = cntl x or del) abort;
+
+CHKABRT JSR INPUT
+ BEQ CHK4 ; jump if no input
+ CMPA #CTLW
+ BNE CHK2 ; jump in not cntlw
+CHKABRT1 JSR INPUT
+ BEQ CHKABRT1 ; jump if no input
+CHK2 CMPA #DEL
+ BEQ CHK3 ; jump if delete
+ CMPA #CTLX
+ BEQ CHK3 ; jump if control x
+ CMPA #CTLA
+ BNE CHK4 ; jump not control a
+CHK3 JMP MAIN ; abort
+CHK4 RTS ; return
+
+;***********************
+;* HOSTCO - connect sci to host for evb board.
+;* TARGCO - connect sci to target for evb board.
+;***********************
+HOSTCO PSHA
+ LDAA #$01
+ STAA DFLOP ; send 1 to d-flop
+ PULA
+ RTS
+
+TARGCO PSHA
+ LDAA #$00
+ STAA DFLOP ; send 0 to d-flop
+ PULA
+ RTS
+
+;*
+;**********
+;*
+;* VECINIT - This routine checks for
+;* vectors in the RAM table. All
+;* uninitialized vectors are programmed
+;* to JMP STOPIT
+;*
+;**********
+;*
+VECINIT LDX #JSCI ; Point to First RAM Vector
+ LDY #STOPIT ; Pointer to STOPIT routine
+ LDD #$7E03 ; A=JMP opcode; B=offset
+VECLOOP CMPA 0,X
+ BEQ VECNEXT ; If vector already in
+ STAA 0,X ; install JMP
+ STY 1,X ; to STOPIT routine
+VECNEXT ABX ; Add 3 to point at next vector
+ CPX #JCLM+3 ; Done?
+ BNE VECLOOP ; If not, continue loop
+ RTS
+;*
+STOPIT LDAA #$50 ; Stop-enable; IRQ, XIRQ-Off
+ TAP
+ STOP ; You are lost! Shut down
+ JMP STOPIT ; In case continue by XIRQ
+
+;**********
+;*
+;* I/O MODULE
+;* Communications with the outside world.
+;* 3 I/O routines (INIT, INPUT, and OUTPUT) call
+;* drivers specified by IODEV (0=SCI, 1=ACIA,
+;* 2=DUARTA, 3=DUARTB).
+;*
+;**********
+;* INIT() - Initialize device specified by iodev.
+;*********
+;*
+INIT EQU *
+ PSHA ; save registers
+ PSHX
+ LDAA IODEV
+ CMPA #$00
+ BNE INIT1 ; jump not sci
+ JSR ONSCI ; initialize sci
+ BRA INIT4
+INIT1 CMPA #$01
+ BNE INIT2 ; jump not acia
+ JSR ONACIA ; initialize acia
+ BRA INIT4
+INIT2 LDX #PORTA
+ CMPA #$02
+ BEQ INIT3 ; jump duart a
+ LDX #PORTB
+INIT3 JSR ONUART ; initialize duart
+INIT4 PULX ; restore registers
+ PULA
+ RTS
+
+;**********
+;* INPUT() - Read device. Returns a=char or 0.
+;* This routine also disarms the cop.
+;**********
+INPUT EQU *
+ PSHX
+ LDAA #$55 ; reset cop
+ STAA COPRST
+ LDAA #$AA
+ STAA COPRST
+ LDAA IODEV
+ BNE INPUT1 ; jump not sci
+ JSR INSCI ; read sci
+ BRA INPUT4
+INPUT1 CMPA #$01
+ BNE INPUT2 ; jump not acia
+ JSR INACIA ; read acia
+ BRA INPUT4
+INPUT2 LDX #PORTA
+ CMPA #$02
+ BEQ INPUT3 ; jump if duart a
+ LDX #PORTB
+INPUT3 JSR INUART ; read uart
+INPUT4 PULX
+ RTS
+
+;**********
+;* OUTPUT() - Output character in A.
+;* chrcnt indicates the current column on the
+;*output display. It is incremented every time
+;*a character is outputted, and cleared whenever
+;*the subroutine outcrlf is called.
+;**********
+
+OUTPUT EQU *
+ PSHA ; save registers
+ PSHB
+ PSHX
+ LDAB IODEV
+ BNE OUTPUT1 ; jump not sci
+ JSR OUTSCI ; write sci
+ BRA OUTPUT4
+OUTPUT1 CMPB #$01
+ BNE OUTPUT2 ; jump not acia
+ JSR OUTACIA ; write acia
+ BRA OUTPUT4
+OUTPUT2 LDX #PORTA
+ CMPB #$02
+ BEQ OUTPUT3 ; jump if duart a
+ LDX #PORTB
+OUTPUT3 JSR OUTUART ; write uart
+OUTPUT4 PULX
+ PULB
+ PULA
+ INC CHRCNT ; increment column count
+ RTS
+
+;**********
+;* ONUART(port) - Initialize a duart port.
+;* Sets duart to internal clock, divide by 16,
+;* 8 data + 1 stop bits.
+;**********
+
+ONUART LDAA #$22
+ STAA 2,X ; reset receiver
+ LDAA #$38
+ STAA 2,X ; reset transmitter
+ LDAA #$40
+ STAA 2,X ; reset error status
+ LDAA #$10
+ STAA 2,X ; reset pointer
+ LDAA #$00
+ STAA DUART+4 ; clock source
+ LDAA #$00
+ STAA DUART+5 ; interrupt mask
+ LDAA #$13
+ STAA 0,X ; 8 data, no parity
+ LDAA #$07
+ STAA 0,X ; 1 stop bits
+ LDAA #$BB ; baud rate (9600)
+ STAA 1,X ; tx and rcv baud rate
+ LDAA #$05
+ STAA 2,X ; enable tx and rcv
+ RTS
+
+;**********
+;* INUART(port) - Check duart for any input.
+;**********
+INUART LDAA 1,X ; read status
+ ANDA #$01 ; check rxrdy
+ BEQ INUART1 ; jump if no data
+ LDAA 3,X ; read data
+ ANDA #$7F ; mask parity
+INUART1 RTS
+
+;**********
+;* OUTUART(port) - Output the character in a.
+;* if autolf=1, transmits cr or lf as crlf.
+;**********
+OUTUART TST AUTOLF
+ BEQ OUTUART2 ; jump if no autolf
+ BSR OUTUART2
+ CMPA #$0D
+ BNE OUTUART1
+ LDAA #$0A ; if cr, output lf
+ BRA OUTUART2
+OUTUART1 CMPA #$0A
+ BNE OUTUART3
+ LDAA #$0D ; if lf, output cr
+OUTUART2 LDAB 1,X ; check status
+ ANDB #$4
+ BEQ OUTUART2 ; loop until tdre=1
+ ANDA #$7F ; mask parity
+ STAA 3,X ; send character
+OUTUART3 RTS
+
+;**********
+;* ONSCI() - Initialize the SCI for 9600
+;* baud at 8 MHz Extal.
+;**********
+ONSCI LDAA #$30
+ STAA BAUD ; baud register
+ LDAA #$00
+ STAA SCCR1
+ LDAA #$0C
+ STAA SCCR2 ; enable
+ RTS
+
+;**********
+;* INSCI() - Read from SCI. Return a=char or 0.
+;**********
+INSCI LDAA SCSR ; read status reg
+ ANDA #$20 ; check rdrf
+ BEQ INSCI1 ; jump if no data
+ LDAA SCDAT ; read data
+ ANDA #$7F ; mask parity
+INSCI1 RTS
+
+;**********
+;* OUTSCI() - Output A to sci. IF autolf = 1,
+;* cr and lf sent as crlf.
+;**********
+OUTSCI TST AUTOLF
+ BEQ OUTSCI2 ; jump if autolf=0
+ BSR OUTSCI2
+ CMPA #$0D
+ BNE OUTSCI1
+ LDAA #$0A ; if cr, send lf
+ BRA OUTSCI2
+OUTSCI1 CMPA #$0A
+ BNE OUTSCI3
+ LDAA #$0D ; if lf, send cr
+OUTSCI2 LDAB SCSR ; read status
+ BITB #$80
+ BEQ OUTSCI2 ; loop until tdre=1
+ ANDA #$7F ; mask parity
+ STAA SCDAT ; send character
+OUTSCI3 RTS
+
+;**********
+;* ONACIA - Initialize the ACIA for
+;* 8 data bits, 1 stop bit, divide by 64 clock.
+;**********
+ONACIA LDX #ACIA
+ LDAA #$03
+ STAA 0,X ; master reset
+ LDAA #$16
+ STAA 0,X ; setup
+ RTS
+
+;**********
+;* INACIA - Read from the ACIA, Return a=char or 0.
+;* Tmp3 is used to flag overrun or framing error.
+;**********
+INACIA LDX #ACIA
+ LDAA 0,X ; read status register
+ PSHA
+ ANDA #$30 ; check ov, fe
+ PULA
+ BEQ INACIA1 ; jump - no error
+ LDAA #$01
+ STAA TMP3 ; flag receiver error
+ BRA INACIA2 ; read data to clear status
+INACIA1 ANDA #$01 ; check rdrf
+ BEQ INACIA3 ; jump if no data
+INACIA2 LDAA 1,X ; read data
+ ANDA #$7F ; mask parity
+INACIA3 RTS
+
+;**********
+;* OUTACIA - Output A to acia. IF autolf = 1,
+;* cr or lf sent as crlf.
+;**********
+OUTACIA BSR OUTACIA3 ; output char
+ TST AUTOLF
+ BEQ OUTACIA2 ; jump no autolf
+ CMPA #$0D
+ BNE OUTACIA1
+ LDAA #$0A
+ BSR OUTACIA3 ; if cr, output lf
+ BRA OUTACIA2
+OUTACIA1 CMPA #$0A
+ BNE OUTACIA2
+ LDAA #$0D
+ BSR OUTACIA3 ; if lf, output cr
+OUTACIA2 RTS
+
+OUTACIA3 LDX #ACIA
+ LDAB 0,X
+ BITB #$2
+ BEQ OUTACIA3 ; loop until tdre
+ ANDA #$7F ; mask parity
+ STAA 1,X ; output
+ RTS
+;*
+;* Space for modifying OUTACIA routine
+;*
+ FDB $FFFF,$FFFF,$FFFF,$FFFF
+;*******************************
+;*** I/O UTILITY SUBROUTINES ***
+;***These subroutines perform the neccesary
+;* data I/O operations.
+;* OUTLHLF-Convert left 4 bits of A from binary
+;* to ASCII and output.
+;* OUTRHLF-Convert right 4 bits of A from binary
+;* to ASCII and output.
+;* OUT1BYT-Convert byte addresed by X from binary
+;* to ASCII and output.
+;* OUT1BSP-Convert byte addressed by X from binary
+;* to ASCII and output followed by a space.
+;* OUT2BSP-Convert 2 bytes addressed by X from binary
+;* to ASCII and output followed by a space.
+;* OUTSPAC-Output a space.
+;*
+;* OUTCRLF-Output a line feed and carriage return.
+;*
+;* OUTSTRG-Output the string of ASCII bytes addressed
+;* by X until $04.
+;* OUTA-Output the ASCII character in A.
+;*
+;* TABTO-Output spaces until column 20 is reached.
+;*
+;* INCHAR-Input to A and echo one character. Loops
+;* until character read.
+;* *******************
+;
+;**********
+;* OUTRHLF(), OUTLHLF(), OUTA()
+;*Convert A from binary to ASCII and output.
+;*Contents of A are destroyed..
+;**********
+OUTLHLF LSRA ; shift data to right
+ LSRA
+ LSRA
+ LSRA
+OUTRHLF ANDA #$0F ; mask top half
+ ADDA #$30 ; convert to ascii
+ CMPA #$39
+ BLE OUTA ; jump if 0-9
+ ADDA #$07 ; convert to hex A-F
+OUTA JSR OUTPUT ; output character
+ RTS
+
+;**********
+;* OUT1BYT(x) - Convert the byte at X to two
+;* ASCII characters and output. Return X pointing
+;* to next byte.
+;**********
+OUT1BYT PSHA
+ LDAA 0,X ; get data in a
+ PSHA ; save copy
+ BSR OUTLHLF ; output left half
+ PULA ; retrieve copy
+ BSR OUTRHLF ; output right half
+ PULA
+ INX
+ RTS
+
+;**********
+;* OUT1BSP(x), OUT2BSP(x) - Output 1 or 2 bytes
+;* at x followed by a space. Returns x pointing to
+;* next byte.
+;**********
+OUT2BSP JSR OUT1BYT ; do first byte
+OUT1BSP JSR OUT1BYT ; do next byte
+OUTSPAC LDAA #$20 ; output a space
+ JSR OUTPUT
+ RTS
+
+;**********
+;* OUTCRLF() - Output a Carriage return and
+;* a line feed. Returns a = cr.
+;**********
+OUTCRLF LDAA #$0D ; cr
+ JSR OUTPUT ; output a
+ LDAA #$00
+ JSR OUTPUT ; output padding
+ LDAA #$0D
+ CLR CHRCNT ; zero the column counter
+ RTS
+
+;**********
+;* OUTSTRG(x) - Output string of ASCII bytes
+;* starting at x until end of text ($04). Can
+;* be paused by control w (any char restarts).
+;**********
+OUTSTRG JSR OUTCRLF
+OUTSTRG0 PSHA
+OUTSTRG1 LDAA 0,X ; read char into a
+ CMPA #EOT
+ BEQ OUTSTRG3 ; jump if eot
+ JSR OUTPUT ; output character
+ INX
+ JSR INPUT
+ BEQ OUTSTRG1 ; jump if no input
+ CMPA #CTLW
+ BNE OUTSTRG1 ; jump if not cntlw
+OUTSTRG2 JSR INPUT
+ BEQ OUTSTRG2 ; jump if any input
+ BRA OUTSTRG1
+OUTSTRG3 PULA
+ RTS
+
+
+;*********
+;* TABTO() - move cursor over to column 20.
+;*while(chrcnt < 16) outspac.
+TABTO EQU *
+ PSHA
+TABTOLP JSR OUTSPAC
+ LDAA CHRCNT
+ CMPA #20
+ BLE TABTOLP
+ PULA
+ RTS
+
+;**********
+;* INCHAR() - Reads input until character sent.
+;* Echoes char and returns with a = char.
+INCHAR JSR INPUT
+ TSTA
+ BEQ INCHAR ; jump if no input
+ JSR OUTPUT ; echo
+ RTS
+
+;*********************
+;*** COMMAND TABLE ***
+COMTABL EQU *
+ FCB 5
+ FCC "ASSEM"
+ FDB ASSEM
+ FCB 5
+ FCC "BREAK"
+ FDB BREAK
+ FCB 4
+ FCC "BULK"
+ FDB BULK
+ FCB 7
+ FCC "BULKALL"
+ FDB BULKALL
+ FCB 4
+ FCC "CALL"
+ FDB CALL
+ FCB 4
+ FCC "DUMP"
+ FDB DUMP
+ FCB 4
+ FCC "FILL"
+ FDB FILL
+ FCB 2
+ FCC "GO"
+ FDB GO
+ FCB 4
+ FCC "HELP"
+ FDB HELP
+ FCB 4
+ FCC "HOST"
+ FDB HOST
+ FCB 4
+ FCC "LOAD"
+ FDB LOAD
+ FCB 6 ; LENGTH OF COMMAND
+ FCC "MEMORY" ; ASCII COMMAND
+ FDB MEMORY ; COMMAND ADDRESS
+ FCB 4
+ FCC "MOVE"
+ FDB MOVE
+ FCB 7
+ FCC "PROCEED"
+ FDB PROCEED
+ FCB 8
+ FCC "REGISTER"
+ FDB REGISTER
+ FCB 6
+ FCC "STOPAT"
+ FDB STOPAT
+ FCB 5
+ FCC "TRACE"
+ FDB TRACE
+ FCB 6
+ FCC "VERIFY"
+ FDB VERIFY
+ FCB 1
+ FCC "?" ; initial command
+ FDB HELP
+ FCB 5
+ FCC "XBOOT"
+ FDB BOOT
+;*
+;*** Command names for evm compatability ***
+;*
+ FCB 3
+ FCC "ASM"
+ FDB ASSEM
+ FCB 2
+ FCC "BF"
+ FDB FILL
+ FCB 4
+ FCC "COPY"
+ FDB MOVE
+ FCB 5
+ FCC "ERASE"
+ FDB BULK
+ FCB 2
+ FCC "MD"
+ FDB DUMP
+ FCB 2
+ FCC "MM"
+ FDB MEMORY
+ FCB 2
+ FCC "RD"
+ FDB REGISTER
+ FCB 2
+ FCC "RM"
+ FDB REGISTER
+ FCB 4
+ FCC "READ"
+ FDB MOVE
+ FCB 2
+ FCC "TM"
+ FDB HOST
+ FCB 4
+ FCC "TEST"
+ FDB EVBTEST
+ FCB $FF
+
+;*******************
+;*** TEXT TABLES ***
+
+MSG1 FCC "BUFFALO 3.2 (int) - Bit User Fast Friendly Aid to Logical Operation"
+ FCB EOT
+MSG2 FCC "What?"
+ FCB EOT
+MSG3 FCC "Too Long"
+ FCB EOT
+MSG4 FCC "Full"
+ FCB EOT
+MSG5 FCC "Op- "
+ FCB EOT
+MSG6 FCC "rom-"
+ FCB EOT
+MSG8 FCC "Command?"
+ FCB EOT
+MSG9 FCC "Bad argument"
+ FCB EOT
+MSG10 FCC "No host port available"
+ FCB EOT
+MSG11 FCC "done"
+ FCB EOT
+MSG12 FCC "checksum error"
+ FCB EOT
+MSG13 FCC "error addr "
+ FCB EOT
+MSG14 FCC "receiver error"
+ FCB EOT
+
+;**********
+;* break [-][<addr>] . . .
+;* Modifies the breakpoint table. More than
+;* one argument can be entered on the command
+;* line but the table will hold only 4 entries.
+;* 4 types of arguments are implied above:
+;* break Prints table contents.
+;* break <addr> Inserts <addr>.
+;* break -<addr> Deletes <addr>.
+;* break - Clears all entries.
+;**********
+;* while 1
+;* a = wskip();
+;* switch(a)
+;* case(cr):
+;* bprint(); return;
+
+BREAK JSR WSKIP
+ BNE BRKDEL ; jump if not cr
+ JSR BPRINT ; print table
+ RTS
+
+;* case("-"):
+;* incbuff(); readbuff();
+;* if(dchek(a)) /* look for wspac or cr */
+;* bpclr();
+;* breaksw;
+;* a = buffarg();
+;* if( !dchek(a) ) return(bad argument);
+;* b = bpsrch();
+;* if(b >= 0)
+;* brktabl[b] = 0;
+;* breaksw;
+
+BRKDEL CMPA #'-'
+ BNE BRKDEF ; jump if not -
+ JSR INCBUFF
+ JSR READBUFF
+ JSR DCHEK
+ BNE BRKDEL1 ; jump if not delimeter
+ JSR BPCLR ; clear table
+ JMP BREAK ; do next argument
+BRKDEL1 JSR BUFFARG ; get address to delete
+ JSR DCHEK
+ BEQ BRKDEL2 ; jump if delimeter
+ LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+BRKDEL2 JSR BPSRCH ; look for addr in table
+ TSTB
+ BMI BRKDEL3 ; jump if not found
+ LDX #BRKTABL
+ ABX
+ CLR 0,X ; clear entry
+ CLR 1,X
+BRKDEL3 JMP BREAK ; do next argument
+
+;* default:
+;* a = buffarg();
+;* if( !dchek(a) ) return(bad argument);
+;* b = bpsrch();
+;* if(b < 0) /* not already in table */
+;* x = shftreg;
+;* shftreg = 0;
+;* a = x[0]; x[0] = $3F
+;* b = x[0]; x[0] = a;
+;* if(b != $3F) return(rom);
+;* b = bpsrch(); /* look for hole */
+;* if(b >= 0) return(table full);
+;* brktabl[b] = x;
+;* breaksw;
+
+BRKDEF JSR BUFFARG ; get argument
+ JSR DCHEK
+ BEQ BRKDEF1 ; jump if delimiter
+ LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+BRKDEF1 JSR BPSRCH ; look for entry in table
+ TSTB
+ BGE BREAK ; jump if already in table
+
+ LDX SHFTREG ; x = new entry addr
+ LDAA 0,X ; save original contents
+ PSHA
+ LDAA #SWI
+ JSR WRITE ; write to entry addr
+ LDAB 0,X ; read back
+ PULA
+ JSR WRITE ; restore original
+ CMPB #SWI
+ BEQ BRKDEF2 ; jump if writes ok
+ STX PTR1 ; save address
+ LDX #PTR1
+ JSR OUT2BSP ; print address
+ JSR BPRINT
+ RTS
+BRKDEF2 CLR SHFTREG
+ CLR SHFTREG+1
+ PSHX
+ JSR BPSRCH ; look for 0 entry
+ PULX
+ TSTB
+ BPL BRKDEF3 ; jump if table not full
+ LDX #MSG4 ; "full"
+ JSR OUTSTRG
+ JSR BPRINT
+ RTS
+BRKDEF3 LDY #BRKTABL
+ ABY
+ STX 0,Y ; put new entry in
+ JMP BREAK ; do next argument
+
+;**********
+;* bprint() - print the contents of the table.
+;**********
+BPRINT JSR OUTCRLF
+ LDX #BRKTABL
+ LDAB #4
+BPRINT1 JSR OUT2BSP
+ DECB
+ BGT BPRINT1 ; loop 4 times
+ RTS
+
+;**********
+;* bpsrch() - search table for address in
+;* shftreg. Returns b = index to entry or
+;* b = -1 if not found.
+;**********
+;*for(b=0; b=6; b=+2)
+;* x[] = brktabl + b;
+;* if(x[0] = shftreg)
+;* return(b);
+;*return(-1);
+
+BPSRCH CLRB
+BPSRCH1 LDX #BRKTABL
+ ABX
+ LDX 0,X ; get table entry
+ CPX SHFTREG
+ BNE BPSRCH2 ; jump if no match
+ RTS
+BPSRCH2 INCB
+ INCB
+ CMPB #$6
+ BLE BPSRCH1 ; loop 4 times
+ LDAB #$FF
+ RTS
+
+
+;**********
+;* bulk - Bulk erase the eeprom not config.
+;* bulkall - Bulk erase eeprom and config.
+;*********
+BULK EQU *
+ LDX #$B600
+ BRA BULK1
+BULKALL LDX #CONFIG
+BULK1 LDAA #$FF
+ JSR EEBULK
+ RTS
+
+
+
+;**********
+;* dump [<addr1> [<addr2>]] - Dump memory
+;* in 16 byte lines from <addr1> to <addr2>.
+;* Default starting address is "current
+;* location" and default number of lines is 8.
+;**********
+;*ptr1 = ptrmem; /* default start address */
+;*ptr2 = ptr1 + $80; /* default end address */
+;*a = wskip();
+;*if(a != cr)
+;* a = buffarg();
+;* if(countu1 = 0) return(bad argument);
+;* if( !dchek(a) ) return(bad argument);
+;* ptr1 = shftreg;
+;* ptr2 = ptr1 + $80; /* default end address */
+;* a = wskip();
+;* if(a != cr)
+;* a = buffarg();
+;* if(countu1 = 0) return(bad argument);
+;* a = wskip();
+;* if(a != cr) return(bad argument);
+;* ptr2 = shftreg;
+
+DUMP LDX PTRMEM ; current location
+ STX PTR1 ; default start
+ LDAB #$80
+ ABX
+ STX PTR2 ; default end
+ JSR WSKIP
+ BEQ DUMP1 ; jump - no arguments
+ JSR BUFFARG ; read argument
+ TST COUNT
+ BEQ DUMPERR ; jump if no argument
+ JSR DCHEK
+ BNE DUMPERR ; jump if delimiter
+ LDX SHFTREG
+ STX PTR1
+ LDAB #$80
+ ABX
+ STX PTR2 ; default end address
+ JSR WSKIP
+ BEQ DUMP1 ; jump - 1 argument
+ JSR BUFFARG ; read argument
+ TST COUNT
+ BEQ DUMPERR ; jump if no argument
+ JSR WSKIP
+ BNE DUMPERR ; jump if not cr
+ LDX SHFTREG
+ STX PTR2
+ BRA DUMP1 ; jump - 2 arguments
+DUMPERR LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+
+;*ptrmem = ptr1;
+;*ptr1 = ptr1 & $fff0;
+
+DUMP1 LDD PTR1
+ STD PTRMEM ; new current location
+ ANDB #$F0
+ STD PTR1 ; start dump at 16 byte boundary
+
+;*** dump loop starts here ***
+;*do:
+;* output address of first byte;
+
+DUMPLP JSR OUTCRLF
+ LDX #PTR1
+ JSR OUT2BSP ; first address
+
+;* x = ptr1;
+;* for(b=0; b=16; b++)
+;* output contents;
+
+ LDX PTR1 ; base address
+ CLRB ; loop counter
+DUMPDAT JSR OUT1BSP ; hex value loop
+ INCB
+ CMPB #$10
+ BLT DUMPDAT ; loop 16 times
+
+;* x = ptr1;
+;* for(b=0; b=16; b++)
+;* a = x[b];
+;* if($7A < a < $20) a = $20;
+;* output ascii contents;
+
+ CLRB ; loop counter
+DUMPASC LDX PTR1 ; base address
+ ABX
+ LDAA ,X ; ascii value loop
+ CMPA #$20
+ BLO DUMP3 ; jump if non printable
+ CMPA #$7A
+ BLS DUMP4 ; jump if printable
+DUMP3 LDAA #$20 ; space for non printables
+DUMP4 JSR OUTPUT ; output ascii value
+ INCB
+ CMPB #$10
+ BLT DUMPASC ; loop 16 times
+
+;* chkabrt();
+;* ptr1 = ptr1 + $10;
+;*while(ptr1 <= ptr2);
+;*return;
+
+ JSR CHKABRT ; check abort or wait
+ LDD PTR1
+ ADDD #$10 ; point to next 16 byte bound
+ STD PTR1 ; update ptr1
+ CPD PTR2
+ BHI DUMP5 ; quit if ptr1 > ptr2
+ CPD #$00 ; check wraparound at $ffff
+ BNE DUMPLP ; jump - no wraparound
+ LDD PTR2
+ CPD #$FFF0
+ BLO DUMPLP ; upper bound not at top
+DUMP5 RTS ; quit
+
+
+
+;**********
+;* fill <addr1> <addr2> [<data>] - Block fill
+;*memory from addr1 to addr2 with data. Data
+;*defaults to $FF.
+;**********
+;*get addr1 and addr2
+FILL EQU *
+ JSR WSKIP
+ JSR BUFFARG
+ TST COUNT
+ BEQ FILLERR ; jump if no argument
+ JSR WCHEK
+ BNE FILLERR ; jump if bad argument
+ LDX SHFTREG
+ STX PTR1 ; address1
+ JSR WSKIP
+ JSR BUFFARG
+ TST COUNT
+ BEQ FILLERR ; jump if no argument
+ JSR DCHEK
+ BNE FILLERR ; jump if bad argument
+ LDX SHFTREG
+ STX PTR2 ; address2
+
+;*Get data if it exists
+ LDAA #$FF
+ STAA TMP2 ; default data
+ JSR WSKIP
+ BEQ FILL1 ; jump if default data
+ JSR BUFFARG
+ TST COUNT
+ BEQ FILLERR ; jump if no argument
+ JSR WSKIP
+ BNE FILLERR ; jump if bad argument
+ LDAA SHFTREG+1
+ STAA TMP2
+
+;*while(ptr1 <= ptr2)
+;* *ptr1 = data
+;* if(*ptr1 != data) abort
+
+FILL1 EQU *
+ JSR CHKABRT ; check for abort
+ LDX PTR1 ; starting address
+ LDAA TMP2 ; data
+ JSR WRITE ; write the data to x
+ CMPA 0,X
+ BNE FILLBAD ; jump if no write
+ CPX PTR2
+ BEQ FILL2 ; quit yet?
+ INX
+ STX PTR1
+ BRA FILL1 ; loop
+FILL2 RTS
+
+FILLERR LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+
+FILLBAD EQU *
+ LDX #PTR1 ; output bad address
+ JSR OUT2BSP
+ RTS
+
+
+
+;**********
+;* call [<addr>] - Execute a jsr to <addr> or user
+;*pc value. Return to monitor via rts or breakpoint.
+;**********
+;*a = wskip();
+;*if(a != cr)
+;* a = buffarg();
+;* a = wskip();
+;* if(a != cr) return(bad argument)
+;* pc = shftreg;
+CALL JSR WSKIP
+ BEQ CALL3 ; jump if no arg
+ JSR BUFFARG
+ JSR WSKIP
+ BEQ CALL2 ; jump if cr
+ LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+CALL2 LDX SHFTREG
+ STX REGS ; pc = <addr>
+
+;*put return address on user stack
+;*setbps();
+;*restack(); /* restack and go*/
+CALL3 LDX SP
+ DEX ; user stack pointer
+ LDD #RETURN ; return address
+ STD 0,X
+ DEX
+ STX SP ; new user stack pointer
+ JSR SETBPS
+ CLR TMP2 ; 1=go, 0=call
+ JMP RESTACK ; go to user code
+
+;**********
+;* return() - Return here from rts after
+;*call command.
+;**********
+RETURN PSHA ; save a register
+ TPA
+ STAA REGS+8 ; cc register
+ PULA
+ STD REGS+6 ; a and b registers
+ STX REGS+4 ; x register
+ STY REGS+2 ; y register
+ STS SP ; user stack pointer
+ LDS PTR2 ; monitor stack pointer
+ JSR REMBPS ; remove breakpoints
+ JSR OUTCRLF
+ JSR RPRINT ; print user registers
+ RTS
+
+
+;**********
+;* proceed - Same as go except it ignores
+;*a breakpoint at the first opcode. Calls
+;*runone for the first instruction only.
+;**********
+PROCEED EQU *
+ JSR RUNONE ; run one instruction
+ JSR CHKABRT ; check for abort
+ CLR TMP2 ; flag for breakpoints
+ INC TMP2 ; 1=go 0=call
+ JSR SETBPS
+ JMP RESTACK ; go execute
+
+;**********
+;* go [<addr>] - Execute starting at <addr> or
+;*user's pc value. Executes an rti to user code.
+;*Returns to monitor via an swi through swiin.
+;**********
+;*a = wskip();
+;*if(a != cr)
+;* a = buffarg();
+;* a = wskip();
+;* if(a != cr) return(bad argument)
+;* pc = shftreg;
+;*setbps();
+;*restack(); /* restack and go*/
+GO JSR WSKIP
+ BEQ GO2 ; jump if no arg
+ JSR BUFFARG
+ JSR WSKIP
+ BEQ GO1 ; jump if cr
+ LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+GO1 LDX SHFTREG
+ STX REGS ; pc = <addr>
+GO2 CLR TMP2
+ INC TMP2 ; 1=go, 0=call
+ JSR SETBPS
+ JMP RESTACK ; go to user code
+
+;*****
+;** SWIIN - Breakpoints from go or call commands enter here.
+;*Remove breakpoints, save user registers, return
+SWIIN EQU * ; swi entry point
+ TSX ; user sp -> x
+ LDS PTR2 ; restore monitor sp
+ JSR SAVSTACK ; save user regs
+ JSR REMBPS ; remove breakpoints from code
+ LDX REGS
+ DEX
+ STX REGS ; save user pc value
+
+;*if(call command) remove call return addr from user stack;
+ TST TMP2 ; 1=go, 0=call
+ BNE GO3 ; jump if go command
+ LDX SP ; remove return address
+ INX ; user stack pointer
+ INX
+ STX SP
+GO3 JSR OUTCRLF ; print register values
+ JSR RPRINT
+ RTS ; done
+
+;**********
+;* setbps - Replace user code with swi's at
+;*breakpoint addresses.
+;**********
+;*for(b=0; b=6; b =+ 2)
+;* x = brktabl[b];
+;* if(x != 0)
+;* optabl[b] = x[0];
+;* x[0] = $3F;
+;*Put monitor SWI vector into jump table
+
+SETBPS CLRB
+SETBPS1 LDX #BRKTABL
+ LDY #PTR4
+ ABX
+ ABY
+ LDX 0,X ; breakpoint table entry
+ BEQ SETBPS2 ; jump if 0
+ LDAA 0,X ; save user opcode
+ STAA 0,Y
+ LDAA #SWI
+ JSR WRITE ; insert swi into code
+SETBPS2 ADDB #$2
+ CMPB #$6
+ BLE SETBPS1 ; loop 4 times
+ LDX JSWI+1
+ STX PTR3 ; save user swi vector
+ LDAA #$7E ; jmp opcode
+ STAA JSWI
+ LDX #SWIIN
+ STX JSWI+1 ; monitor swi vector
+ RTS
+
+;**********
+;* rembps - Remove breakpoints from user code.
+;**********
+;*for(b=0; b=6; b =+ 2)
+;* x = brktabl[b];
+;* if(x != 0)
+;* x[0] = optabl[b];
+;*Replace user's SWI vector
+REMBPS CLRB
+REMBPS1 LDX #BRKTABL
+ LDY #PTR4
+ ABX
+ ABY
+ LDX 0,X ; breakpoint table entry
+ BEQ REMBPS2 ; jump if 0
+ LDAA 0,Y
+ JSR WRITE ; restore user opcode
+REMBPS2 ADDB #$2
+ CMPB #$6
+ BLE REMBPS1 ; loop 4 times
+ LDX PTR3 ; restore user swi vector
+ STX JSWI+1
+ RTS
+
+
+;**********
+;* trace <n> - Trace n instructions starting
+;*at user's pc value. n is a hex number less than
+;*$FF (defaults to 1).
+;**********
+;*a = wskip();
+;*if(a != cr)
+;* a = buffarg(); a = wskip();
+;* if(a != cr) return(bad argument);
+;* countt1 = n
+TRACE CLR TMP4
+ INC TMP4 ; default count=1
+ CLR CHRCNT ; set up for display
+ JSR WSKIP
+ BEQ TRACE2 ; jump if cr
+ JSR BUFFARG
+ JSR WSKIP
+ BEQ TRACE1 ; jump if cr
+ LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+TRACE1 LDAA SHFTREG+1 ; n
+ STAA TMP4
+
+;*Disassemble the line about to be traced
+TRACE2 EQU *
+ LDAB TMP4
+ PSHB
+ LDX REGS
+ STX PTR1 ; pc value for disass
+ JSR DISASSM
+ PULB
+ STAB TMP4
+
+;*run one instruction
+;*rprint();
+;*while(count > 0) continue trace;
+ JSR RUNONE
+ JSR CHKABRT ; check for abort
+ JSR TABTO ; print registers for
+ JSR RPRINT ; result of trace
+ DEC TMP4
+ BEQ TRACDON ; quit if count=0
+TRACE3 JSR OUTCRLF
+ BRA TRACE2
+TRACDON RTS
+
+
+;**********
+;* stopat <addr> - Trace instructions until <addr>
+;*is reached.
+;**********
+;*if((a=wskip) != cr)
+;* a = buffarg(); a = wskip();
+;* if(a != cr) return(bad argument);
+;*else return(bad argument);
+STOPAT EQU *
+ JSR WSKIP
+ BEQ STOPGO ; jump if cr - no argument
+ JSR BUFFARG
+ JSR WSKIP
+ BEQ STOPAT1 ; jump if cr
+ LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+STOPAT1 TST COUNT
+ BEQ STOPGO ; jump if no argument
+ LDX SHFTREG
+ STX PTRMEM ; update "current location"
+
+;*while(!(ptrmem <= userpc < ptrmem+10)) runone();
+;*rprint();
+STOPGO LDD REGS ; userpc
+ CPD PTRMEM
+ BLO STOPNEXT ; if(userpc < ptrmem) runone
+ LDD PTRMEM
+ ADDD #10
+ CPD REGS
+ BHI STOPDON ; quit if ptrmem+10 > userpc
+STOPNEXT JSR RUNONE
+ JSR CHKABRT ; check for abort
+ BRA STOPGO
+STOPDON JSR OUTCRLF
+ JSR RPRINT ; result of trace
+ RTS ; done
+
+
+;*************************
+;* runone - This routine is used by the trace and
+;* execute commands to run one only one user instruction.
+;* Control is passed to the user code via an RTI. OC5
+;* is then used to trigger an XIRQ as soon as the first user
+;* opcode is fetched. Control then returns to the monitor
+;* through XIRQIN.
+;* Externally, the OC5 pin must be wired to the XIRQ pin.
+;************************
+;* Disable oc5 interrupts
+;* Put monitor XIRQ vector into jump table
+;* Unmask x bit in user ccr
+;* Setup OC5 to go low when first user instruction executed
+RUNONE EQU *
+ LDAA #$7E ; put "jmp xirqin" in jump table
+ STAA JTOC5
+ LDX #XIRQIN
+ STX JXIRQ+1
+ LDAA REGS+8 ; x bit will be cleared when
+ ANDA #$BF ; rti is executed below
+ STAA REGS+8
+ LDAB #87 ; cycles to end of rti
+ LDX TCNT
+ ABX ; 3~ \
+ STX TOC5 ; oc5 match register 5~ \
+ LDAA TCTL1 ; 4~ \
+ ANDA #$FE ; set up oc5 low on match 2~ \
+ STAA TCTL1 ; enable oc5 interrupt 4~ / 86~
+
+;** RESTACK - Restore user stack and RTI to user code.
+;* This code is the pathway to execution of user code.
+;*(Force extended addressing to maintain cycle count)
+;*Restore user stack and rti to user code
+RESTACK EQU * ; 68~
+ STS >PTR2 ; save monitor sp
+ LDS >SP ; user stack pointer
+ LDX >REGS
+ PSHX ; pc
+ LDX >REGS+2
+ PSHX ; y
+ LDX >REGS+4
+ PSHX ; x
+ LDD >REGS+6
+ PSHA ; a
+ PSHB ; b
+ LDAA >REGS+8
+ PSHA ; ccr
+ RTI
+
+;** Return here from run one line of user code.
+XIRQIN EQU *
+ TSX ; user sp -> x
+ LDS PTR2 ; restore monitor sp
+
+;** SAVSTACK - Save user's registers.
+;* On entry - x points to top of user stack.
+SAVSTACK EQU *
+ LDAA 0,X
+ STAA REGS+8 ; user ccr
+ LDD 1,X
+ STAA REGS+7 ; b
+ STAB REGS+6 ; a
+ LDD 3,X
+ STD REGS+4 ; x
+ LDD 5,X
+ STD REGS+2 ; y
+ LDD 7,X
+ STD REGS ; pc
+ LDAB #8
+ ABX
+ STX SP ; user stack pointer
+ LDAA TCTL1 ; force oc5 pin high which
+ ORAA #$03 ; is tied to xirq line
+ STAA TCTL1
+ LDAA #$08
+ STAA CFORC
+ RTS
+
+
+;**********
+;* help - List buffalo commands to terminal.
+;**********
+HELP EQU *
+ LDX #HELPMSG1
+ JSR OUTSTRG ; print help screen
+ RTS
+
+HELPMSG1 EQU *
+ FCC "ASM [<addr>] Line assembler/disassembler."
+ FCB $0D
+ FCC " / Do same address. ^ Do previous address."
+ FCB $0D
+ FCC " CTRL-J Do next address. RETURN Do next opcode."
+ FCB $0D
+ FCC " CTRL-A Quit."
+ FCB $0D
+ FCC "BF <addr1> <addr2> [<data>] Block fill."
+ FCB $0D
+ FCC "BR [-][<addr>] Set up breakpoint table."
+ FCB $0D
+ FCC "BULK Erase the EEPROM. BULKALL Erase EEPROM and CONFIG."
+ FCB $0D
+ FCC "CALL [<addr>] Call user subroutine. G [<addr>] Execute user code."
+ FCB $0D
+ FCC "LOAD, VERIFY [T] <host download command> Load or verify S-records."
+ FCB $0D
+ FCC "MD [<addr1> [<addr2>]] Memory dump."
+ FCB $0D
+ FCC "MM [<addr>] Memory modify."
+ FCB $0D
+ FCC " / Open same address. CTRL-H or ^ Open previous address."
+ FCB $0D
+ FCC " CTRL-J Open next address. SPACE Open next address."
+ FCB $0D
+ FCC " RETURN Quit. <addr>O Compute offset to <addr>."
+ FCB $0D
+ FCC "MOVE <s1> <s2> [<d>] Block move."
+ FCB $0D
+ FCC "P Proceed/continue execution."
+ FCB $0D
+ FCC "RM [P, Y, X, A, B, C, or S] Register modify."
+ FCB $0D
+ FCC "T [<n>] Trace n instructions."
+ FCB $0D
+ FCC "TM Transparent mode (CTRL-A = exit, CTRL-B = send break)."
+ FCB $0D
+ FCC "CTRL-H Backspace. CTRL-W Wait for any key."
+ FCB $0D
+ FCC "CTRL-X or DELETE Abort/cancel command."
+ FCB $0D
+ FCC "RETURN Repeat last command."
+ FCB 4
+
+;**********
+;* HOST() - Establishes transparent link between
+;* terminal and host. Port used for host is
+;* determined in the reset initialization routine
+;* and stored in HOSTDEV.
+;* To exit type control A.
+;* To send break to host type control B.
+;*if(no external device) return;
+;*initialize host port;
+;*While( !(control A))
+;* input(terminal); output(host);
+;* input(host); output(terminal);
+
+HOST LDAA EXTDEV
+ BNE HOST0 ; jump if host port avail.
+ LDX #MSG10 ; "no host port avail"
+ JSR OUTSTRG
+ RTS
+HOST0 CLR AUTOLF ; turn off autolf
+ JSR HOSTCO ; connect sci (evb board)
+ JSR HOSTINIT ; initialize host port
+HOST1 JSR INPUT ; read terminal
+ TSTA
+ BEQ HOST3 ; jump if no char
+ CMPA #CTLA
+ BEQ HOSTEND ; jump if control a
+ CMPA #CTLB
+ BNE HOST2 ; jump if not control b
+ JSR TXBREAK ; send break to host
+ BRA HOST3
+HOST2 JSR HOSTOUT ; echo to host
+HOST3 JSR HOSTIN ; read host
+ TSTA
+ BEQ HOST1 ; jump if no char
+ JSR OUTPUT ; echo to terminal
+ BRA HOST1
+HOSTEND INC AUTOLF ; turn on autolf
+ JSR TARGCO ; disconnect sci (evb board)
+ RTS ; return
+
+;**********
+;* txbreak() - transmit break to host port.
+;* The duration of the transmitted break is
+;* approximately 200,000 E-clock cycles, or
+;* 100ms at 2.0 MHz.
+;***********
+TXBREAK EQU *
+ LDAA HOSTDEV
+ CMPA #$03
+ BEQ TXBDU ; jump if duartb is host
+
+TXBSCI LDX #SCCR2 ; sci is host
+ BSET 0,X,#01 ; set send break bit
+ BSR TXBWAIT
+ BCLR 0,X,#01 ; clear send break bit
+ BRA TXB1
+
+TXBDU LDX #PORTB ; duart host port
+ LDAA #$60 ; start break cmd
+ STAA 2,X ; port b command register
+ BSR TXBWAIT
+ LDAA #$70 ; stop break cmd
+ STAA 2,X ; port b command register
+
+TXB1 LDAA #$0D
+ JSR HOSTOUT ; send carriage return
+ LDAA #$0A
+ JSR HOSTOUT ; send linefeed
+ RTS
+
+TXBWAIT LDY #$6F9B ; loop count = 28571
+TXBWAIT1 DEY ; 7 cycle loop
+ BNE TXBWAIT1
+ RTS
+
+
+;**********
+;* hostinit(), hostin(), hostout() - host i/o
+;*routines. Restores original terminal device.
+;**********
+HOSTINIT LDAB IODEV ; save terminal
+ PSHB
+ LDAB HOSTDEV
+ STAB IODEV ; point to host
+ JSR INIT ; initialize host
+ BRA TERMRES ; restore terminal
+HOSTIN LDAB IODEV ; save terminal
+ PSHB
+ LDAB HOSTDEV
+ STAB IODEV ; point to host
+ JSR INPUT ; read host
+ BRA TERMRES ; restore terminal
+HOSTOUT LDAB IODEV ; save terminal
+ PSHB
+ LDAB HOSTDEV
+ STAB IODEV ; point to host
+ JSR OUTPUT ; write to host
+TERMRES PULB ; restore terminal device
+ STAB IODEV
+ RTS
+
+
+;**********
+;* load(ptrbuff[]) - Load s1/s9 records from
+;*host to memory. Ptrbuff[] points to string in
+;*input buffer which is a command to output s1/s9
+;*records from the host ("cat filename" for unix).
+;* Returns error and address if it can't write
+;*to a particular location.
+;**********
+;* verify(ptrbuff[]) - Verify memory from load
+;*command. Ptrbuff[] is same as for load.
+;* tmp3 is used as an error indication, 0=no errors,
+;* 1=receiver, 2=rom error, 3=checksum error.
+;**********
+VERIFY CLR TMP2
+ INC TMP2 ; TMP2=1=verify
+ BRA LOAD1
+LOAD CLR TMP2 ; 0=load
+
+;*a=wskip();
+;*if(a = cr) goto transparent mode;
+;*if(t option) hostdev = iodev;
+LOAD1 CLR TMP3 ; clear error flag
+ JSR WSKIP
+ BNE LOAD2
+ JMP HOST ; go to host if no args
+LOAD2 JSR UPCASE
+ CMPA #'T' ; look for t option
+ BNE LOAD3 ; jump not t option
+ JSR INCBUFF
+ JSR READBUFF ; get next character
+ JSR DECBUFF
+ CMPA #$0D
+ BNE LOAD3 ; jump if not t option
+ CLR AUTOLF
+ LDAA IODEV
+ STAA HOSTDEV ; set host port = terminal
+ BRA LOAD10 ; go wait for s1 records
+
+;*else while(not cr)
+;* read character from input buffer;
+;* send character to host;
+LOAD3 CLR AUTOLF
+ JSR HOSTCO ; connect sci (evb board)
+ JSR HOSTINIT ; initialize host port
+LOAD4 JSR READBUFF ; get next char
+ JSR INCBUFF
+ PSHA ; save char
+ JSR HOSTOUT ; output to host
+ JSR OUTPUT ; echo to terminal
+ PULA
+ CMPA #$0D
+ BNE LOAD4 ; jump if not cr
+
+;*repeat: /* look for s records */
+;* if(hostdev != iodev) check abort;
+;* a = hostin();
+;* if(a = 'S')
+;* a = hostin;
+;* if(a = '1')
+;* checksum = 0;
+;* get byte count in b;
+;* get base address in x;
+;* while(byte count > 0)
+;* byte();
+;* x++; b--;
+;* if(tmp3=0) /* no error */
+;* if(load) x[0] = shftreg+1;
+;* if(x[0] != shftreg+1)
+;* tmp3 = 2; /* rom error */
+;* ptr3 = x; /* save address */
+;* if(tmp3 = 0) do checksum;
+;* if(checksum err) tmp3 = 3; /* checksum error */
+LOAD10 EQU *
+ LDAA HOSTDEV
+ CMPA IODEV
+ BEQ LOAD11 ; jump if hostdev=iodev
+ JSR CHKABRT ; check for abort
+LOAD11 JSR HOSTIN ; read host
+ TSTA
+ BEQ LOAD10 ; jump if no input
+ CMPA #'S'
+ BNE LOAD10 ; jump if not S
+LOAD12 JSR HOSTIN ; read host
+ TSTA
+ BEQ LOAD12 ; jump if no input
+ CMPA #'9'
+ BEQ LOAD90 ; jump if S9 record
+ CMPA #'1'
+ BNE LOAD10 ; jump if not S1
+ CLR TMP4 ; clear checksum
+ JSR BYTE
+ LDAB SHFTREG+1
+ SUBB #$2 ; b = byte count
+ JSR BYTE
+ JSR BYTE
+ LDX SHFTREG ; x = base address
+ DEX
+LOAD20 JSR BYTE ; get next byte
+ INX
+ DECB ; check byte count
+ BEQ LOAD30 ; if b=0, go do checksum
+ TST TMP3
+ BNE LOAD10 ; jump if error flagged
+ TST TMP2
+ BNE LOAD21 ; jump if verify
+ LDAA SHFTREG+1
+ JSR WRITE ; load only
+LOAD21 CMPA 0,X ; verify ram location
+ BEQ LOAD20 ; jump if ram ok
+ LDAA #$02
+ STAA TMP3 ; indicate rom error
+ STX PTR3 ; save error address
+ BRA LOAD20 ; finish download
+
+;* calculate checksum
+LOAD30 TST TMP3
+ BNE LOAD10 ; jump if error already
+ LDAA TMP4
+ INCA ; do checksum
+ BEQ LOAD10 ; jump if s1 record okay
+ LDAA #$03
+ STAA TMP3 ; indicate checksum error
+ BRA LOAD10
+
+;* if(a = '9')
+;* read rest of record;
+;* if(tmp3=2) return("[ptr3]");
+;* if(tmp3=1) return("rcv error");
+;* if(tmp3=3) return("checksum err");
+;* else return("done");
+LOAD90 JSR BYTE
+ LDAB SHFTREG+1 ; b = byte count
+LOAD91 JSR BYTE
+ DECB
+ BNE LOAD91 ; loop until end of record
+ INC AUTOLF ; turn on autolf
+ JSR TARGCO ; disconnect sci (evb)
+ LDX #MSG11 ; "done" default msg
+ LDAA TMP3
+ CMPA #$02
+ BNE LOAD92 ; jump not rom error
+ LDX #PTR3
+ JSR OUT2BSP ; address of rom error
+ BRA LOAD95
+LOAD92 CMPA #$01
+ BNE LOAD93 ; jump not rcv error
+ LDX #MSG14 ; "rcv error"
+ BRA LOAD94
+LOAD93 CMPA #$03
+ BNE LOAD94 ; jump not checksum error
+ LDX #MSG12 ; "checksum error"
+LOAD94 JSR OUTSTRG
+LOAD95 RTS
+
+
+;**********
+;* byte() - Read 2 ascii bytes from host and
+;*convert to one hex byte. Returns byte
+;*shifted into shftreg and added to tmp4.
+;**********
+BYTE PSHB
+ PSHX
+BYTE0 JSR HOSTIN ; read host (1st byte)
+ TSTA
+ BEQ BYTE0 ; loop until input
+ JSR HEXBIN
+BYTE1 JSR HOSTIN ; read host (2nd byte)
+ TSTA
+ BEQ BYTE1 ; loop until input
+ JSR HEXBIN
+ LDAA SHFTREG+1
+ ADDA TMP4
+ STAA TMP4 ; add to checksum
+ PULX
+ PULB
+ RTS
+
+
+;*******************************************
+;* MEMORY [<addr>]
+;* [<addr>]/
+;* Opens memory and allows user to modify the
+;*contents at <addr> or the last opened location.
+;* Subcommands:
+;* [<data>]<cr> - Close current location and exit.
+;* [<data>]<lf> - Close current and open next.
+;* [<data>]<^> - Close current and open previous.
+;* [<data>]<sp> - Close current and open next.
+;* [<data>]/ - Reopen current location.
+;* The contents of the current location is only
+;* changed if valid data is entered before each
+;* subcommand.
+;* [<addr>]O - Compute relative offset from current
+;* location to <addr>. The current location must
+;* be the address of the offset byte.
+;**********
+;*a = wskip();
+;*if(a != cr)
+;* a = buffarg();
+;* if(a != cr) return(bad argument);
+;* if(countu1 != 0) ptrmem[] = shftreg;
+
+MEMORY JSR WSKIP
+ BEQ MEM1 ; jump if cr
+ JSR BUFFARG
+ JSR WSKIP
+ BEQ MSLASH ; jump if cr
+ LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+MSLASH TST COUNT
+ BEQ MEM1 ; jump if no argument
+ LDX SHFTREG
+ STX PTRMEM ; update "current location"
+
+;**********
+;* Subcommands
+;**********
+;*outcrlf();
+;*out2bsp(ptrmem[]);
+;*out1bsp(ptrmem[0]);
+
+MEM1 JSR OUTCRLF
+MEM2 LDX #PTRMEM
+ JSR OUT2BSP ; output address
+MEM3 LDX PTRMEM
+ JSR OUT1BSP ; output contents
+ CLR SHFTREG
+ CLR SHFTREG+1
+;*while 1
+;*a = termarg();
+;* switch(a)
+;* case(space):
+;* chgbyt();
+;* ptrmem[]++;
+;* case(linefeed):
+;* chgbyt();
+;* ptrmem[]++;
+;* case(up arrow):
+;* case(backspace):
+;* chgbyt();
+;* ptrmem[]--;
+;* case("/"):
+;* chgbyt();
+;* outcrlf();
+;* case(O):
+;* d = ptrmem[0] - (shftreg);
+;* if($80 < d < $ff81)
+;* print(out of range);
+;* countt1 = d-1;
+;* out1bsp(countt1);
+;* case(carriage return):
+;* chgbyt();
+;* return;
+;* default: return(command?)
+
+MEM4 JSR TERMARG
+ JSR UPCASE
+ LDX PTRMEM
+ CMPA #$20
+ BEQ MEMSP ; jump if space
+ CMPA #$0A
+ BEQ MEMLF ; jump if linefeed
+ CMPA #$5E
+ BEQ MEMUA ; jump if up arrow
+ CMPA #$08
+ BEQ MEMBS ; jump if backspace
+ CMPA #'/'
+ BEQ MEMSL ; jump if /
+ CMPA #'O'
+ BEQ MEMOFF ; jump if O
+ CMPA #$0D
+ BEQ MEMCR ; jump if carriage ret
+ LDX #MSG8 ; "command?"
+ JSR OUTSTRG
+ JMP MEM1
+MEMSP JSR CHGBYT
+ INX
+ STX PTRMEM
+ JMP MEM3 ; output contents
+MEMLF JSR CHGBYT
+ INX
+ STX PTRMEM
+ JMP MEM2 ; output addr, contents
+MEMUA EQU *
+MEMBS JSR CHGBYT
+ DEX
+ STX PTRMEM
+ JMP MEM1 ; output cr, addr, contents
+MEMSL JSR CHGBYT
+ JMP MEM1 ; output cr, addr, contents
+MEMOFF LDD SHFTREG ; destination addr
+ SUBD PTRMEM
+ CMPA #$0
+ BNE MEMOFF1 ; jump if not 0
+ CMPB #$80
+ BLS MEMOFF3 ; jump if in range
+ BRA MEMOFF2 ; out of range
+MEMOFF1 CMPA #$FF
+ BNE MEMOFF2 ; out of range
+ CMPB #$81
+ BHS MEMOFF3 ; in range
+MEMOFF2 LDX #MSG3 ; "Too long"
+ JSR OUTSTRG
+ JMP MEM1 ; output cr, addr, contents
+MEMOFF3 SUBD #$1 ; b now has offset
+ STAB TMP4
+ JSR OUTSPAC
+ LDX #TMP4
+ JSR OUT1BSP ; output offset
+ JMP MEM1 ; output cr, addr, contents
+MEMCR JSR CHGBYT
+ RTS ; exit task
+
+
+;**********
+;* move <src1> <src2> [<dest>] - move
+;*block at <src1> to <src2> to <dest>.
+;* Moves block 1 byte up if no <dest>.
+;**********
+;*a = buffarg();
+;*if(countu1 = 0) return(bad argument);
+;*if( !wchek(a) ) return(bad argument);
+;*ptr1 = shftreg; /* src1 */
+
+MOVE EQU *
+ JSR BUFFARG
+ TST COUNT
+ BEQ MOVERR ; jump if no arg
+ JSR WCHEK
+ BNE MOVERR ; jump if no delim
+ LDX SHFTREG ; src1
+ STX PTR1
+
+;*a = buffarg();
+;*if(countu1 = 0) return(bad argument);
+;*if( !dchek(a) ) return(bad argument);
+;*ptr2 = shftreg; /* src2 */
+
+ JSR BUFFARG
+ TST COUNT
+ BEQ MOVERR ; jump if no arg
+ JSR DCHEK
+ BNE MOVERR ; jump if no delim
+ LDX SHFTREG ; src2
+ STX PTR2
+
+;*a = buffarg();
+;*a = wskip();
+;*if(a != cr) return(bad argument);
+;*if(countu1 != 0) tmp2 = shftreg; /* dest */
+;*else tmp2 = ptr1 + 1;
+
+ JSR BUFFARG
+ JSR WSKIP
+ BNE MOVERR ; jump if not cr
+ TST COUNT
+ BEQ MOVE1 ; jump if no arg
+ LDX SHFTREG ; dest
+ BRA MOVE2
+MOVERR LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+
+MOVE1 LDX PTR1
+ INX ; default dest
+MOVE2 STX PTR3
+
+;*if(src1 < dest <= src2)
+;* dest = dest+(src2-src1);
+;* for(x = src2; x = src1; x--)
+;* dest[0]-- = x[0]--;
+ LDX PTR3 ; dest
+ CPX PTR1 ; src1
+ BLS MOVE3 ; jump if dest =< src1
+ CPX PTR2 ; src2
+ BHI MOVE3 ; jump if dest > src2
+ LDD PTR2
+ SUBD PTR1
+ ADDD PTR3
+ STD PTR3 ; dest = dest+(src2-src1)
+ LDX PTR2
+MOVELP1 JSR CHKABRT ; check for abort
+ LDAA ,X ; char at src2
+ PSHX
+ LDX PTR3
+ JSR WRITE ; write a to x
+ CMPA 0,X
+ BNE MOVEBAD ; jump if no write
+ DEX
+ STX PTR3
+ PULX
+ CPX PTR1
+ BEQ MOVRTS
+ DEX
+ BRA MOVELP1 ; Loop SRC2 - SRC1 times
+;*
+;* else
+;* for(x=src1; x=src2; x++)
+;* dest[0]++ = x[0]++;
+
+
+MOVE3 LDX PTR1 ; srce1
+MOVELP2 JSR CHKABRT ; check for abort
+ LDAA ,X
+ PSHX
+ LDX PTR3 ; dest
+ JSR WRITE ; write a to x
+ CMPA 0,X
+ BNE MOVEBAD ; jump if no write
+ INX
+ STX PTR3
+ PULX
+ CPX PTR2
+ BEQ MOVRTS
+ INX
+ BRA MOVELP2 ; Loop SRC2-SRC1 times
+MOVRTS RTS
+
+MOVEBAD LDX #PTR3
+ JSR OUT2BSP ; output bad address
+ RTS
+
+;**********
+;* register [<name>] - prints the user regs
+;*and opens them for modification. <name> is
+;*the first register opened (default = P).
+;* Subcommands:
+;* [<nn>]<space> Opens the next register.
+;* [<nn>]<cr> Return.
+;* The register value is only changed if
+;* <nn> is entered before the subcommand.
+;**********
+;*x[] = reglist
+;*a = wskip(); a = upcase(a);
+;*if(a != cr)
+;* while( a != x[0] )
+;* if( x[0] = "s") return(bad argument);
+;* x[]++;
+;* incbuff(); a = wskip();
+;* if(a != cr) return(bad argument);
+
+REGISTER LDX #REGLIST
+ JSR WSKIP ; a = first char of arg
+ JSR UPCASE ; convert to upper case
+ CMPA #$D
+ BEQ REG4 ; jump if no argument
+REG1 CMPA 0,X
+ BEQ REG3
+ LDAB 0,X
+ INX
+ CMPB #'S'
+ BNE REG1 ; jump if not "s"
+REG2 LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+REG3 PSHX
+ JSR INCBUFF
+ JSR WSKIP ; next char after arg
+ PULX
+ BNE REG2 ; jump if not cr
+
+;*rprint();
+;* while(x[0] != "s")
+;* rprnt1(x);
+;* a = termarg(); /* read from terminal */
+;* if( ! dchek(a) ) return(bad argument);
+;* if(countu1 != 0)
+;* if(x[14] = 1)
+;* regs[x[7]++ = shftreg;
+;* regs[x[7]] = shftreg+1;
+;* if(a = cr) break;
+;*return;
+
+REG4 JSR RPRINT ; print all registers
+REG5 JSR OUTCRLF
+ JSR RPRNT1 ; print reg name
+ CLR SHFTREG
+ CLR SHFTREG+1
+ JSR TERMARG ; read subcommand
+ JSR DCHEK
+ BEQ REG6 ; jump if delimeter
+ LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+REG6 PSHA
+ PSHX
+ TST COUNT
+ BEQ REG8 ; jump if no input
+ LDAB 7,X ; get reg offset
+ LDAA 14,X ; byte size
+ LDX #REGS ; user registers
+ ABX
+ TSTA
+ BEQ REG7 ; jump if 1 byte reg
+ LDAA SHFTREG
+ STAA 0,X ; put in top byte
+ INX
+REG7 LDAA SHFTREG+1
+ STAA 0,X ; put in bottom byte
+REG8 PULX
+ PULA
+ LDAB 0,X ; CHECK FOR REGISTER S
+ CMPB #'S'
+ BEQ REG9 ; jump if "s"
+ INX ; point to next register
+ CMPA #$D
+ BNE REG5 ; jump if not cr
+REG9 RTS
+
+PAGE1 EQU $00 ; values for page opcodes
+PAGE2 EQU $18
+PAGE3 EQU $1A
+PAGE4 EQU $CD
+IMMED EQU $0 ; addressing modes
+INDX EQU $1
+INDY EQU $2
+LIMMED EQU $3 ; (long immediate)
+OTHER EQU $4
+
+;*** Rename variables for assem/disassem ***
+AMODE EQU TMP2 ; addressing mode
+YFLAG EQU TMP3
+PNORM EQU TMP4 ; page for normal opcode
+OLDPC EQU PTR8
+PC EQU PTR1 ; program counter
+PX EQU PTR2 ; page for x indexed
+PY EQU PTR2+1 ; page for y indexed
+BASEOP EQU PTR3 ; base opcode
+CLASS EQU PTR3+1 ; class
+DISPC EQU PTR4 ; pc for disassembler
+BRADDR EQU PTR5 ; relative branch offset
+MNEPTR EQU PTR6 ; pointer to table for dis
+ASSCOMM EQU PTR7 ; subcommand for assembler
+
+;*** Error messages for assembler ***
+MSGDIR FDB MSGA1 ; message table index
+ FDB MSGA2
+ FDB MSGA3
+ FDB MSGA4
+ FDB MSGA5
+ FDB MSGA6
+ FDB MSGA7
+ FDB MSGA8
+ FDB MSGA9
+MSGA1 FCC "Immediate mode illegal"
+ FCB EOT
+MSGA2 FCC "Error in mnemonic table"
+ FCB EOT
+MSGA3 FCC "Illegal bit op"
+ FCB EOT
+MSGA4 FCC "Bad argument"
+ FCB EOT
+MSGA5 FCC "Mnemonic not found"
+ FCB EOT
+MSGA6 FCC "Unknown addressing mode"
+ FCB EOT
+MSGA7 FCC "Indexed addressing assumed"
+ FCB EOT
+MSGA8 FCC "Syntax error"
+ FCB EOT
+MSGA9 FCC "Branch out of range"
+ FCB EOT
+
+;****************
+;* assem(addr) -68HC11 line assembler/disassembler.
+;* This routine will disassemble the opcode at
+;*<addr> and then allow the user to enter a line for
+;*assembly. Rules for assembly are as follows:
+;* -A '#' sign indicates immediate addressing.
+;* -A ',' (comma) indicates indexed addressing
+;* and the next character must be X or Y.
+;* -All arguments are assumed to be hex and the
+;* '$' sign shouldn't be used.
+;* -Arguments should be separated by 1 or more
+;* spaces or tabs.
+;* -Any input after the required number of
+;* arguments is ignored.
+;* -Upper or lower case makes no difference.
+;*
+;* To signify end of input line, the following
+;*commands are available and have the indicated action:
+;* <cr> -Carriage return finds the next opcode for
+;* assembly. If there was no assembly input,
+;* the next opcode disassembled is retrieved
+;* from the disassembler.
+;* <lf> -Linefeed works the same as carriage return
+;* except if there was no assembly input, the
+;* <addr> is incremented and the next <addr> is
+;* disassembled.
+;* '^' -Up arrow decrements <addr> and the previous
+;* address is then disassembled.
+;* '/' -Slash redisassembles the current address.
+;*
+;* To exit the assembler use CONTROL A. Of course
+;*control X and DEL will also allow you to abort.
+;**********
+;*oldpc = rambase;
+;*a = wskip();
+;*if (a != cr)
+;* buffarg()
+;* a = wskip();
+;* if ( a != cr ) return(error);
+;* oldpc = a;
+
+ASSEM EQU *
+ LDX #RAMBS
+ STX OLDPC
+ JSR WSKIP
+ BEQ ASSLOOP ; jump if no argument
+ JSR BUFFARG
+ JSR WSKIP
+ BEQ ASSEM1 ; jump if argument ok
+ LDX #MSGA4 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+ASSEM1 LDX SHFTREG
+ STX OLDPC
+
+;*repeat
+;* pc = oldpc;
+;* out2bsp(pc);
+;* disassem();
+;* a=readln();
+;* asscomm = a; /* save command */
+;* if(a == ('^' or '/')) outcrlf;
+;* if(a == 0) return(error);
+
+ASSLOOP LDX OLDPC
+ STX PC
+ JSR OUTCRLF
+ LDX #PC
+ JSR OUT2BSP ; output the address
+ JSR DISASSM ; disassemble opcode
+ JSR TABTO
+ LDAA #PROMPT ; prompt user
+ JSR OUTA ; output prompt character
+ JSR READLN ; read input for assembly
+ STAA ASSCOMM
+ CMPA #'^'
+ BEQ ASSLP0 ; jump if up arrow
+ CMPA #'/'
+ BEQ ASSLP0 ; jump if slash
+ CMPA #$00
+ BNE ASSLP1 ; jump if none of above
+ RTS ; return if bad input
+ASSLP0 JSR OUTCRLF
+ASSLP1 EQU *
+ JSR OUTSPAC
+ JSR OUTSPAC
+ JSR OUTSPAC
+ JSR OUTSPAC
+ JSR OUTSPAC
+
+;* b = parse(input); /* get mnemonic */
+;* if(b > 5) print("not found"); asscomm='/';
+;* elseif(b >= 1)
+;* msrch();
+;* if(class==$FF)
+;* print("not found"); asscomm='/';
+;* else
+;* a = doop(opcode,class);
+;* if(a == 0) dispc=0;
+;* else process error; asscomm='/';
+
+ JSR PARSE
+ CMPB #$5
+ BLE ASSLP2 ; jump if mnemonic <= 5 chars
+ LDX #MSGA5 ; "mnemonic not found"
+ JSR OUTSTRG
+ BRA ASSLP5
+ASSLP2 EQU *
+ CMPB #$0
+ BEQ ASSLP10 ; jump if no input
+ JSR MSRCH
+ LDAA CLASS
+ CMPA #$FF
+ BNE ASSLP3
+ LDX #MSGA5 ; "mnemonic not found"
+ JSR OUTSTRG
+ BRA ASSLP5
+ASSLP3 JSR DOOP
+ CMPA #$00
+ BNE ASSLP4 ; jump if doop error
+ LDX #$00
+ STX DISPC ; indicate good assembly
+ BRA ASSLP10
+ASSLP4 DECA ; a = error message index
+ TAB
+ LDX #MSGDIR
+ ABX
+ ABX
+ LDX 0,X
+ JSR OUTSTRG ; output error message
+ASSLP5 CLR ASSCOMM ; error command
+
+;* /* compute next address - asscomm holds subcommand
+;* and dispc indicates if valid assembly occured. */
+;* if(asscomm=='^') oldpc -= 1;
+;* if(asscomm==(lf or cr)
+;* if(dispc==0) oldpc=pc;
+;* else
+;* if(asscomm==lf) dispc=oldpc+1;
+;* oldpc=dispc;
+;*until(eot)
+
+
+ASSLP10 EQU *
+ LDAA ASSCOMM
+ CMPA #'^'
+ BNE ASSLP11 ; jump if not up arrow
+ LDX OLDPC
+ DEX
+ STX OLDPC ; back up
+ BRA ASSLP15
+ASSLP11 CMPA #$0A
+ BEQ ASSLP12 ; jump if linefeed
+ CMPA #$0D
+ BNE ASSLP15 ; jump if not cr
+ASSLP12 LDX DISPC
+ BNE ASSLP13 ; jump if dispc != 0
+ LDX PC
+ STX OLDPC
+ BRA ASSLP15
+ASSLP13 CMPA #$0A
+ BNE ASSLP14 ; jump if not linefeed
+ LDX OLDPC
+ INX
+ STX DISPC
+ASSLP14 LDX DISPC
+ STX OLDPC
+ASSLP15 JMP ASSLOOP
+
+;****************
+;* readln() --- Read input from terminal into buffer
+;* until a command character is read (cr,lf,/,^).
+;* If more chars are typed than the buffer will hold,
+;* the extra characters are overwritten on the end.
+;* On exit: b=number of chars read, a=0 if quit,
+;* else a=next command.
+;****************
+;*for(b==0;b<=bufflng;b++) inbuff[b] = cr;
+
+READLN CLRB
+ LDAA #$0D ; carriage ret
+RLN0 LDX #INBUFF
+ ABX
+ STAA 0,X ; initialize input buffer
+ INCB
+ CMPB #BUFFLNG
+ BLT RLN0
+;*b=0;
+;*repeat
+;* if(a == (ctla, cntlc, cntld, cntlx, del))
+;* return(a=0);
+;* if(a == backspace)
+;* if(b > 0) b--;
+;* else b=0;
+;* else inbuff[b] = upcase(a);
+;* if(b < bufflng) b++;
+;*until (a == (cr,lf,^,/))
+;*return(a);
+
+ CLRB
+RLN1 JSR INCHAR
+ CMPA #DEL ; Delete
+ BEQ RLNQUIT
+ CMPA #CTLX ; Control X
+ BEQ RLNQUIT
+ CMPA #CTLA ; Control A
+ BEQ RLNQUIT
+ CMPA #$03 ; Control C
+ BEQ RLNQUIT
+ CMPA #$04 ; Control D
+ BEQ RLNQUIT
+ CMPA #$08 ; backspace
+ BNE RLN2
+ DECB
+ BGT RLN1
+ BRA READLN ; start over
+RLN2 LDX #INBUFF
+ ABX
+ JSR UPCASE
+ STAA 0,X ; put char in buffer
+ CMPB #BUFFLNG ; max buffer length
+ BGE RLN3 ; jump if buffer full
+ INCB ; move buffer pointer
+RLN3 JSR ASSCHEK ; check for subcommand
+ BNE RLN1
+ RTS
+RLNQUIT CLRA ; quit
+ RTS ; return
+
+
+;**********
+;* parse() -parse out the mnemonic from INBUFF
+;* to COMBUFF. on exit: b=number of chars parsed.
+;**********
+;*combuff[3] = <space>; initialize 4th character to space.
+;*ptrbuff[] = inbuff[];
+;*a=wskip();
+;*for (b = 0; b = 5; b++)
+;* a=readbuff(); incbuff();
+;* if (a = (cr,lf,^,/,wspace)) return(b);
+;* combuff[b] = upcase(a);
+;*return(b);
+
+PARSE LDAA #$20
+ STAA COMBUFF+3
+ LDX #INBUFF ; initialize buffer ptr
+ STX PTR0
+ JSR WSKIP ; find first character
+ CLRB
+PARSLP JSR READBUFF ; read character
+ JSR INCBUFF
+ JSR WCHEK
+ BEQ PARSRT ; jump if whitespace
+ JSR ASSCHEK
+ BEQ PARSRT ; jump if end of line
+ JSR UPCASE ; convert to upper case
+ LDX #COMBUFF
+ ABX
+ STAA 0,X ; store in combuff
+ INCB
+ CMPB #$5
+ BLE PARSLP ; loop 6 times
+PARSRT RTS
+
+
+;****************
+;* asschek() -perform compares for
+;* cr, lf, ^, /
+;****************
+ASSCHEK CMPA #$0A ; linefeed
+ BEQ ASSCHK1
+ CMPA #$0D ; carriage ret
+ BEQ ASSCHK1
+ CMPA #'^' ; up arrow
+ BEQ ASSCHK1
+ CMPA #'/' ; slash
+ASSCHK1 RTS
+
+
+;*********
+;* msrch() --- Search MNETABL for mnemonic in COMBUFF.
+;*stores base opcode at baseop and class at class.
+;* Class = FF if not found.
+;**********
+;*while ( != EOF )
+;* if (COMBUFF[0-3] = MNETABL[0-3])
+;* return(MNETABL[4],MNETABL[5]);
+;* else *MNETABL =+ 6
+
+MSRCH LDX #MNETABL ; pointer to mnemonic table
+ LDY #COMBUFF ; pointer to string
+ BRA MSRCH1
+MSNEXT EQU *
+ LDAB #6
+ ABX ; point to next table entry
+MSRCH1 LDAA 0,X ; read table
+ CMPA #EOT
+ BNE MSRCH2 ; jump if not end of table
+ LDAA #$FF
+ STAA CLASS ; FF = not in table
+ RTS
+MSRCH2 CMPA 0,Y ; op[0] = tabl[0] ?
+ BNE MSNEXT
+ LDAA 1,X
+ CMPA 1,Y ; op[1] = tabl[1] ?
+ BNE MSNEXT
+ LDAA 2,X
+ CMPA 2,Y ; op[2] = tabl[2] ?
+ BNE MSNEXT
+ LDAA 3,X
+ CMPA 3,Y ; op[2] = tabl[2] ?
+ BNE MSNEXT
+ LDD 4,X ; opcode, class
+ STAA BASEOP
+ STAB CLASS
+ RTS
+
+;**********
+;** doop(baseop,class) --- process mnemonic.
+;** on exit: a=error code corresponding to error
+;** messages.
+;**********
+;*amode = OTHER; /* addressing mode */
+;*yflag = 0; /* ynoimm, nlimm, and cpd flag */
+;*x[] = ptrbuff[]
+
+DOOP EQU *
+ LDAA #OTHER
+ STAA AMODE ; mode
+ CLR YFLAG
+ LDX PTR0
+
+;*while (*x != end of buffer)
+;* if (x[0]++ == ',')
+;* if (x[0] == 'y') amode = INDY;
+;* else amod = INDX;
+;* break;
+;*a = wskip()
+;*if( a == '#' ) amode = IMMED;
+
+DOPLP1 CPX #ENDBUFF ; (end of buffer)
+ BEQ DOOP1 ; jump if end of buffer
+ LDD 0,X ; read 2 chars from buffer
+ INX ; move pointer
+ CMPA #','
+ BNE DOPLP1
+ CMPB #'Y' ; look for ",y"
+ BNE DOPLP2
+ LDAA #INDY
+ STAA AMODE
+ BRA DOOP1
+DOPLP2 CMPB #'X' ; look for ",x"
+ BNE DOOP1 ; jump if not x
+ LDAA #INDX
+ STAA AMODE
+ BRA DOOP1
+DOOP1 JSR WSKIP
+ CMPA #'#' ; look for immediate mode
+ BNE DOOP2
+ JSR INCBUFF ; point at argument
+ LDAA #IMMED
+ STAA AMODE
+DOOP2 EQU *
+
+;*switch(class)
+ LDAB CLASS
+ CMPB #P2INH
+ BNE DOSW1
+ JMP DOP2I
+DOSW1 CMPB #INH
+ BNE DOSW2
+ JMP DOINH
+DOSW2 CMPB #REL
+ BNE DOSW3
+ JMP DOREL
+DOSW3 CMPB #LIMM
+ BNE DOSW4
+ JMP DOLIM
+DOSW4 CMPB #NIMM
+ BNE DOSW5
+ JMP DONOI
+DOSW5 CMPB #GEN
+ BNE DOSW6
+ JMP DOGENE
+DOSW6 CMPB #GRP2
+ BNE DOSW7
+ JMP DOGRP
+DOSW7 CMPB #CPD
+ BNE DOSW8
+ JMP DOCPD
+DOSW8 CMPB #XNIMM
+ BNE DOSW9
+ JMP DOXNOI
+DOSW9 CMPB #XLIMM
+ BNE DOSW10
+ JMP DOXLI
+DOSW10 CMPB #YNIMM
+ BNE DOSW11
+ JMP DOYNOI
+DOSW11 CMPB #YLIMM
+ BNE DOSW12
+ JMP DOYLI
+DOSW12 CMPB #BTB
+ BNE DOSW13
+ JMP DOBTB
+DOSW13 CMPB #SETCLR
+ BNE DODEF
+ JMP DOSET
+
+;* default: return("error in mnemonic table");
+
+DODEF LDAA #$2
+ RTS
+
+;* case P2INH: emit(PAGE2)
+
+DOP2I LDAA #PAGE2
+ JSR EMIT
+
+;* case INH: emit(baseop);
+;* return(0);
+
+DOINH LDAA BASEOP
+ JSR EMIT
+ CLRA
+ RTS
+
+;* case REL: a = assarg();
+;* if(a=4) return(a);
+;* d = address - pc + 2;
+;* if ($7f >= d >= $ff82)
+;* return (out of range);
+;* emit(opcode);
+;* emit(offset);
+;* return(0);
+
+DOREL JSR ASSARG
+ CMPA #$04
+ BNE DOREL1 ; jump if arg ok
+ RTS
+DOREL1 LDD SHFTREG ; get branch address
+ LDX PC ; get program counter
+ INX
+ INX ; point to end of opcode
+ STX BRADDR
+ SUBD BRADDR ; calculate offset
+ STD BRADDR ; save result
+ CPD #$7F ; in range ?
+ BLS DOREL2 ; jump if in range
+ CPD #$FF80
+ BHS DOREL2 ; jump if in range
+ LDAA #$09 ; 'Out of range'
+ RTS
+DOREL2 LDAA BASEOP
+ JSR EMIT ; emit opcode
+ LDAA BRADDR+1
+ JSR EMIT ; emit offset
+ CLRA ; normal return
+ RTS
+
+;* case LIMM: if (amode == IMMED) amode = LIMMED;
+
+DOLIM LDAA AMODE
+ CMPA #IMMED
+ BNE DONOI
+ LDAA #LIMMED
+ STAA AMODE
+
+;* case NIMM: if (amode == IMMED)
+;* return("Immediate mode illegal");
+
+DONOI LDAA AMODE
+ CMPA #IMMED
+ BNE DOGENE ; jump if not immediate
+ LDAA #$1 ; "immediate mode illegal"
+ RTS
+
+;* case GEN: dogen(baseop,amode,PAGE1,PAGE1,PAGE2);
+;* return;
+
+DOGENE LDAA #PAGE1
+ STAA PNORM
+ STAA PX
+ LDAA #PAGE2
+ STAA PY
+ JSR DOGEN
+ RTS
+
+;* case GRP2: if (amode == INDY)
+;* emit(PAGE2);
+;* amode = INDX;
+;* if( amode == INDX )
+;* doindx(baseop);
+;* else a = assarg();
+;* if(a=4) return(a);
+;* emit(opcode+0x10);
+;* emit(extended address);
+;* return;
+
+DOGRP LDAA AMODE
+ CMPA #INDY
+ BNE DOGRP1
+ LDAA #PAGE2
+ JSR EMIT
+ LDAA #INDX
+ STAA AMODE
+DOGRP1 EQU *
+ LDAA AMODE
+ CMPA #INDX
+ BNE DOGRP2
+ JSR DOINDEX
+ RTS
+DOGRP2 EQU *
+ LDAA BASEOP
+ ADDA #$10
+ JSR EMIT
+ JSR ASSARG
+ CMPA #$04
+ BEQ DOGRPRT ; jump if bad arg
+ LDD SHFTREG ; extended address
+ JSR EMIT
+ TBA
+ JSR EMIT
+ CLRA
+DOGRPRT RTS
+
+;* case CPD: if (amode == IMMED)
+;* amode = LIMMED; /* cpd */
+;* if( amode == INDY ) yflag = 1;
+;* dogen(baseop,amode,PAGE3,PAGE3,PAGE4);
+;* return;
+
+DOCPD LDAA AMODE
+ CMPA #IMMED
+ BNE DOCPD1
+ LDAA #LIMMED
+ STAA AMODE
+DOCPD1 LDAA AMODE
+ CMPA #INDY
+ BNE DOCPD2
+ INC YFLAG
+DOCPD2 LDAA #PAGE3
+ STAA PNORM
+ STAA PX
+ LDAA #PAGE4
+ STAA PY
+ JSR DOGEN
+ RTS
+
+;* case XNIMM: if (amode == IMMED) /* stx */
+;* return("Immediate mode illegal");
+
+DOXNOI LDAA AMODE
+ CMPA #IMMED
+ BNE DOXLI
+ LDAA #$1 ; "immediate mode illegal"
+ RTS
+
+;* case XLIMM: if (amode == IMMED) /* cpx, ldx */
+;* amode = LIMMED;
+;* dogen(baseop,amode,PAGE1,PAGE1,PAGE4);
+;* return;
+
+DOXLI LDAA AMODE
+ CMPA #IMMED
+ BNE DOXLI1
+ LDAA #LIMMED
+ STAA AMODE
+DOXLI1 LDAA #PAGE1
+ STAA PNORM
+ STAA PX
+ LDAA #PAGE4
+ STAA PY
+ JSR DOGEN
+ RTS
+
+;* case YNIMM: if (amode == IMMED) /* sty */
+;* return("Immediate mode illegal");
+
+DOYNOI LDAA AMODE
+ CMPA #IMMED
+ BNE DOYLI
+ LDAA #$1 ; "immediate mode illegal"
+ RTS
+
+;* case YLIMM: if (amode == INDY) yflag = 1;/* cpy, ldy */
+;* if(amode == IMMED) amode = LIMMED;
+;* dogen(opcode,amode,PAGE2,PAGE3,PAGE2);
+;* return;
+
+DOYLI LDAA AMODE
+ CMPA #INDY
+ BNE DOYLI1
+ INC YFLAG
+DOYLI1 CMPA #IMMED
+ BNE DOYLI2
+ LDAA #LIMMED
+ STAA AMODE
+DOYLI2 LDAA #PAGE2
+ STAA PNORM
+ STAA PY
+ LDAA #PAGE3
+ STAA PX
+ JSR DOGEN
+ RTS
+
+;* case BTB: /* bset, bclr */
+;* case SETCLR: a = bitop(baseop,amode,class);
+;* if(a=0) return(a = 3);
+;* if( amode == INDY )
+;* emit(PAGE2);
+;* amode = INDX;
+
+DOBTB EQU *
+DOSET JSR BITOP
+ CMPA #$00
+ BNE DOSET1
+ LDAA #$3 ; "illegal bit op"
+ RTS
+DOSET1 LDAA AMODE
+ CMPA #INDY
+ BNE DOSET2
+ LDAA #PAGE2
+ JSR EMIT
+ LDAA #INDX
+ STAA AMODE
+DOSET2 EQU *
+
+;* emit(baseop);
+;* a = assarg();
+;* if(a = 4) return(a);
+;* emit(index offset);
+;* if( amode == INDX )
+;* Buffptr += 2; /* skip ,x or ,y */
+
+ LDAA BASEOP
+ JSR EMIT
+ JSR ASSARG
+ CMPA #$04
+ BNE DOSET22 ; jump if arg ok
+ RTS
+DOSET22 LDAA SHFTREG+1 ; index offset
+ JSR EMIT
+ LDAA AMODE
+ CMPA #INDX
+ BNE DOSET3
+ JSR INCBUFF
+ JSR INCBUFF
+DOSET3 EQU *
+
+;* a = assarg();
+;* if(a = 4) return(a);
+;* emit(mask); /* mask */
+;* if( class == SETCLR )
+;* return;
+
+ JSR ASSARG
+ CMPA #$04
+ BNE DOSET33 ; jump if arg ok
+ RTS
+DOSET33 LDAA SHFTREG+1 ; mask
+ JSR EMIT
+ LDAA CLASS
+ CMPA #SETCLR
+ BNE DOSET4
+ CLRA
+ RTS
+DOSET4 EQU *
+
+;* a = assarg();
+;* if(a = 4) return(a);
+;* d = (pc+1) - shftreg;
+;* if ($7f >= d >= $ff82)
+;* return (out of range);
+;* emit(branch offset);
+;* return(0);
+
+ JSR ASSARG
+ CMPA #$04
+ BNE DOSET5 ; jump if arg ok
+ RTS
+DOSET5 LDX PC ; program counter
+ INX ; point to next inst
+ STX BRADDR ; save pc value
+ LDD SHFTREG ; get branch address
+ SUBD BRADDR ; calculate offset
+ CPD #$7F
+ BLS DOSET6 ; jump if in range
+ CPD #$FF80
+ BHS DOSET6 ; jump if in range
+ CLRA
+ JSR EMIT
+ LDAA #$09 ; 'out of range'
+ RTS
+DOSET6 TBA ; offset
+ JSR EMIT
+ CLRA
+ RTS
+
+
+;**********
+;** bitop(baseop,amode,class) --- adjust opcode on bit
+;** manipulation instructions. Returns opcode in a
+;** or a = 0 if error
+;**********
+;*if( amode == INDX || amode == INDY ) return(op);
+;*if( class == SETCLR ) return(op-8);
+;*else if(class==BTB) return(op-12);
+;*else fatal("bitop");
+
+BITOP EQU *
+ LDAA AMODE
+ LDAB CLASS
+ CMPA #INDX
+ BNE BITOP1
+ RTS
+BITOP1 CMPA #INDY
+ BNE BITOP2 ; jump not indexed
+ RTS
+BITOP2 CMPB #SETCLR
+ BNE BITOP3 ; jump not bset,bclr
+ LDAA BASEOP ; get opcode
+ SUBA #8
+ STAA BASEOP
+ RTS
+BITOP3 CMPB #BTB
+ BNE BITOP4 ; jump not bit branch
+ LDAA BASEOP ; get opcode
+ SUBA #12
+ STAA BASEOP
+ RTS
+BITOP4 CLRA ; 0 = fatal bitop
+ RTS
+
+;**********
+;** dogen(baseop,mode,pnorm,px,py) - process
+;** general addressing modes. Returns a = error #.
+;**********
+;*pnorm = page for normal addressing modes: IMM,DIR,EXT
+;*px = page for INDX addressing
+;*py = page for INDY addressing
+;*switch(amode)
+DOGEN LDAA AMODE
+ CMPA #LIMMED
+ BEQ DOGLIM
+ CMPA #IMMED
+ BEQ DOGIMM
+ CMPA #INDY
+ BEQ DOGINDY
+ CMPA #INDX
+ BEQ DOGINDX
+ CMPA #OTHER
+ BEQ DOGOTH
+
+;*default: error("Unknown Addressing Mode");
+
+DOGDEF LDAA #$06 ; unknown addre...
+ RTS
+
+;*case LIMMED: epage(pnorm);
+;* emit(baseop);
+;* a = assarg();
+;* if(a = 4) return(a);
+;* emit(2 bytes);
+;* return(0);
+
+DOGLIM LDAA PNORM
+ JSR EPAGE
+DOGLIM1 LDAA BASEOP
+ JSR EMIT
+ JSR ASSARG ; get next argument
+ CMPA #$04
+ BNE DOGLIM2 ; jump if arg ok
+ RTS
+DOGLIM2 LDD SHFTREG
+ JSR EMIT
+ TBA
+ JSR EMIT
+ CLRA
+ RTS
+
+;*case IMMED: epage(pnorm);
+;* emit(baseop);
+;* a = assarg();
+;* if(a = 4) return(a);
+;* emit(lobyte);
+;* return(0);
+
+DOGIMM LDAA PNORM
+ JSR EPAGE
+ LDAA BASEOP
+ JSR EMIT
+ JSR ASSARG
+ CMPA #$04
+ BNE DOGIMM1 ; jump if arg ok
+ RTS
+DOGIMM1 LDAA SHFTREG+1
+ JSR EMIT
+ CLRA
+ RTS
+
+;*case INDY: epage(py);
+;* a=doindex(op+0x20);
+;* return(a);
+
+DOGINDY LDAA PY
+ JSR EPAGE
+ LDAA BASEOP
+ ADDA #$20
+ STAA BASEOP
+ JSR DOINDEX
+ RTS
+
+;*case INDX: epage(px);
+;* a=doindex(op+0x20);
+;* return(a);
+
+DOGINDX LDAA PX
+ JSR EPAGE
+ LDAA BASEOP
+ ADDA #$20
+ STAA BASEOP
+ JSR DOINDEX
+ RTS
+
+;*case OTHER: a = assarg();
+;* if(a = 4) return(a);
+;* epage(pnorm);
+;* if(countu1 <= 2 digits) /* direct */
+;* emit(op+0x10);
+;* emit(lobyte(Result));
+;* return(0);
+;* else emit(op+0x30); /* extended */
+;* eword(Result);
+;* return(0)
+
+DOGOTH JSR ASSARG
+ CMPA #$04
+ BNE DOGOTH0 ; jump if arg ok
+ RTS
+DOGOTH0 LDAA PNORM
+ JSR EPAGE
+ LDAA COUNT
+ CMPA #$2
+ BGT DOGOTH1
+ LDAA BASEOP
+ ADDA #$10 ; direct mode opcode
+ JSR EMIT
+ LDAA SHFTREG+1
+ JSR EMIT
+ CLRA
+ RTS
+DOGOTH1 LDAA BASEOP
+ ADDA #$30 ; extended mode opcode
+ JSR EMIT
+ LDD SHFTREG
+ JSR EMIT
+ TBA
+ JSR EMIT
+ CLRA
+ RTS
+
+;**********
+;** doindex(op) --- handle all wierd stuff for
+;** indexed addressing. Returns a = error number.
+;**********
+;*emit(baseop);
+;*a=assarg();
+;*if(a = 4) return(a);
+;*if( a != ',' ) return("Syntax");
+;*buffptr++
+;*a=readbuff()
+;*if( a != 'x' && != 'y') warn("Ind Addr Assumed");
+;*emit(lobyte);
+;*return(0);
+
+DOINDEX LDAA BASEOP
+ JSR EMIT
+ JSR ASSARG
+ CMPA #$04
+ BNE DOINDX0 ; jump if arg ok
+ RTS
+DOINDX0 CMPA #','
+ BEQ DOINDX1
+ LDAA #$08 ; "syntax error"
+ RTS
+DOINDX1 JSR INCBUFF
+ JSR READBUFF
+ CMPA #'Y'
+ BEQ DOINDX2
+ CMPA #'X'
+ BEQ DOINDX2
+ LDX MSGA7 ; "index addr assumed"
+ JSR OUTSTRG
+DOINDX2 LDAA SHFTREG+1
+ JSR EMIT
+ CLRA
+ RTS
+
+;**********
+;** assarg(); - get argument. Returns a = 4 if bad
+;** argument, else a = first non hex char.
+;**********
+;*a = buffarg()
+;*if(asschk(aa) && countu1 != 0) return(a);
+;*return(bad argument);
+
+ASSARG JSR BUFFARG
+ JSR ASSCHEK ; check for command
+ BEQ ASSARG1 ; jump if ok
+ JSR WCHEK ; check for whitespace
+ BNE ASSARG2 ; jump if not ok
+ASSARG1 TST COUNT
+ BEQ ASSARG2 ; jump if no argument
+ RTS
+ASSARG2 LDAA #$04 ; bad argument
+ RTS
+
+;**********
+;** epage(a) --- emit page prebyte
+;**********
+;*if( a != PAGE1 ) emit(a);
+
+EPAGE CMPA #PAGE1
+ BEQ EPAGRT ; jump if page 1
+ JSR EMIT
+EPAGRT RTS
+
+;**********
+;* emit(a) --- emit contents of a
+;**********
+EMIT LDX PC
+ JSR WRITE ; write a to x
+ JSR OUT1BSP
+ STX PC
+ RTS
+
+;*Mnemonic table for hc11 line assembler
+NULL EQU $0 ; nothing
+INH EQU $1 ; inherent
+P2INH EQU $2 ; page 2 inherent
+GEN EQU $3 ; general addressing
+GRP2 EQU $4 ; group 2
+REL EQU $5 ; relative
+IMM EQU $6 ; immediate
+NIMM EQU $7 ; general except for immediate
+LIMM EQU $8 ; 2 byte immediate
+XLIMM EQU $9 ; longimm for x
+XNIMM EQU $10 ; no immediate for x
+YLIMM EQU $11 ; longimm for y
+YNIMM EQU $12 ; no immediate for y
+BTB EQU $13 ; bit test and branch
+SETCLR EQU $14 ; bit set or clear
+CPD EQU $15 ; compare d
+BTBD EQU $16 ; bit test and branch direct
+SETCLRD EQU $17 ; bit set or clear direct
+
+;**********
+;* mnetabl - includes all '11 mnemonics, base opcodes,
+;* and type of instruction. The assembler search routine
+;*depends on 4 characters for each mnemonic so that 3 char
+;*mnemonics are extended with a space and 5 char mnemonics
+;*are truncated.
+;**********
+
+MNETABL EQU *
+ FCC "ABA " ; Mnemonic
+ FCB $1B ; Base opcode
+ FCB INH ; Class
+ FCC "ABX "
+ FCB $3A
+ FCB INH
+ FCC "ABY "
+ FCB $3A
+ FCB P2INH
+ FCC "ADCA"
+ FCB $89
+ FCB GEN
+ FCC "ADCB"
+ FCB $C9
+ FCB GEN
+ FCC "ADDA"
+ FCB $8B
+ FCB GEN
+ FCC "ADDB"
+ FCB $CB
+ FCB GEN
+ FCC "ADDD"
+ FCB $C3
+ FCB LIMM
+ FCC "ANDA"
+ FCB $84
+ FCB GEN
+ FCC "ANDB"
+ FCB $C4
+ FCB GEN
+ FCC "ASL "
+ FCB $68
+ FCB GRP2
+ FCC "ASLA"
+ FCB $48
+ FCB INH
+ FCC "ASLB"
+ FCB $58
+ FCB INH
+ FCC "ASLD"
+ FCB $05
+ FCB INH
+ FCC "ASR "
+ FCB $67
+ FCB GRP2
+ FCC "ASRA"
+ FCB $47
+ FCB INH
+ FCC "ASRB"
+ FCB $57
+ FCB INH
+ FCC "BCC "
+ FCB $24
+ FCB REL
+ FCC "BCLR"
+ FCB $1D
+ FCB SETCLR
+ FCC "BCS "
+ FCB $25
+ FCB REL
+ FCC "BEQ "
+ FCB $27
+ FCB REL
+ FCC "BGE "
+ FCB $2C
+ FCB REL
+ FCC "BGT "
+ FCB $2E
+ FCB REL
+ FCC "BHI "
+ FCB $22
+ FCB REL
+ FCC "BHS "
+ FCB $24
+ FCB REL
+ FCC "BITA"
+ FCB $85
+ FCB GEN
+ FCC "BITB"
+ FCB $C5
+ FCB GEN
+ FCC "BLE "
+ FCB $2F
+ FCB REL
+ FCC "BLO "
+ FCB $25
+ FCB REL
+ FCC "BLS "
+ FCB $23
+ FCB REL
+ FCC "BLT "
+ FCB $2D
+ FCB REL
+ FCC "BMI "
+ FCB $2B
+ FCB REL
+ FCC "BNE "
+ FCB $26
+ FCB REL
+ FCC "BPL "
+ FCB $2A
+ FCB REL
+ FCC "BRA "
+ FCB $20
+ FCB REL
+ FCC "BRCL" ; (BRCLR)
+ FCB $1F
+ FCB BTB
+ FCC "BRN "
+ FCB $21
+ FCB REL
+ FCC "BRSE" ; (BRSET)
+ FCB $1E
+ FCB BTB
+ FCC "BSET"
+ FCB $1C
+ FCB SETCLR
+ FCC "BSR "
+ FCB $8D
+ FCB REL
+ FCC "BVC "
+ FCB $28
+ FCB REL
+ FCC "BVS "
+ FCB $29
+ FCB REL
+ FCC "CBA "
+ FCB $11
+ FCB INH
+ FCC "CLC "
+ FCB $0C
+ FCB INH
+ FCC "CLI "
+ FCB $0E
+ FCB INH
+ FCC "CLR "
+ FCB $6F
+ FCB GRP2
+ FCC "CLRA"
+ FCB $4F
+ FCB INH
+ FCC "CLRB"
+ FCB $5F
+ FCB INH
+ FCC "CLV "
+ FCB $0A
+ FCB INH
+ FCC "CMPA"
+ FCB $81
+ FCB GEN
+ FCC "CMPB"
+ FCB $C1
+ FCB GEN
+ FCC "COM "
+ FCB $63
+ FCB GRP2
+ FCC "COMA"
+ FCB $43
+ FCB INH
+ FCC "COMB"
+ FCB $53
+ FCB INH
+ FCC "CPD "
+ FCB $83
+ FCB CPD
+ FCC "CPX "
+ FCB $8C
+ FCB XLIMM
+ FCC "CPY "
+ FCB $8C
+ FCB YLIMM
+ FCC "DAA "
+ FCB $19
+ FCB INH
+ FCC "DEC "
+ FCB $6A
+ FCB GRP2
+ FCC "DECA"
+ FCB $4A
+ FCB INH
+ FCC "DECB"
+ FCB $5A
+ FCB INH
+ FCC "DES "
+ FCB $34
+ FCB INH
+ FCC "DEX "
+ FCB $09
+ FCB INH
+ FCC "DEY "
+ FCB $09
+ FCB P2INH
+ FCC "EORA"
+ FCB $88
+ FCB GEN
+ FCC "EORB"
+ FCB $C8
+ FCB GEN
+ FCC "FDIV"
+ FCB $03
+ FCB INH
+ FCC "IDIV"
+ FCB $02
+ FCB INH
+ FCC "INC "
+ FCB $6C
+ FCB GRP2
+ FCC "INCA"
+ FCB $4C
+ FCB INH
+ FCC "INCB"
+ FCB $5C
+ FCB INH
+ FCC "INS "
+ FCB $31
+ FCB INH
+ FCC "INX "
+ FCB $08
+ FCB INH
+ FCC "INY "
+ FCB $08
+ FCB P2INH
+ FCC "JMP "
+ FCB $6E
+ FCB GRP2
+ FCC "JSR "
+ FCB $8D
+ FCB NIMM
+ FCC "LDAA"
+ FCB $86
+ FCB GEN
+ FCC "LDAB"
+ FCB $C6
+ FCB GEN
+ FCC "LDD "
+ FCB $CC
+ FCB LIMM
+ FCC "LDS "
+ FCB $8E
+ FCB LIMM
+ FCC "LDX "
+ FCB $CE
+ FCB XLIMM
+ FCC "LDY "
+ FCB $CE
+ FCB YLIMM
+ FCC "LSL "
+ FCB $68
+ FCB GRP2
+ FCC "LSLA"
+ FCB $48
+ FCB INH
+ FCC "LSLB"
+ FCB $58
+ FCB INH
+ FCC "LSLD"
+ FCB $05
+ FCB INH
+ FCC "LSR "
+ FCB $64
+ FCB GRP2
+ FCC "LSRA"
+ FCB $44
+ FCB INH
+ FCC "LSRB"
+ FCB $54
+ FCB INH
+ FCC "LSRD"
+ FCB $04
+ FCB INH
+ FCC "MUL "
+ FCB $3D
+ FCB INH
+ FCC "NEG "
+ FCB $60
+ FCB GRP2
+ FCC "NEGA"
+ FCB $40
+ FCB INH
+ FCC "NEGB"
+ FCB $50
+ FCB INH
+ FCC "NOP "
+ FCB $01
+ FCB INH
+ FCC "ORAA"
+ FCB $8A
+ FCB GEN
+ FCC "ORAB"
+ FCB $CA
+ FCB GEN
+ FCC "PSHA"
+ FCB $36
+ FCB INH
+ FCC "PSHB"
+ FCB $37
+ FCB INH
+ FCC "PSHX"
+ FCB $3C
+ FCB INH
+ FCC "PSHY"
+ FCB $3C
+ FCB P2INH
+ FCC "PULA"
+ FCB $32
+ FCB INH
+ FCC "PULB"
+ FCB $33
+ FCB INH
+ FCC "PULX"
+ FCB $38
+ FCB INH
+ FCC "PULY"
+ FCB $38
+ FCB P2INH
+ FCC "ROL "
+ FCB $69
+ FCB GRP2
+ FCC "ROLA"
+ FCB $49
+ FCB INH
+ FCC "ROLB"
+ FCB $59
+ FCB INH
+ FCC "ROR "
+ FCB $66
+ FCB GRP2
+ FCC "RORA"
+ FCB $46
+ FCB INH
+ FCC "RORB"
+ FCB $56
+ FCB INH
+ FCC "RTI "
+ FCB $3B
+ FCB INH
+ FCC "RTS "
+ FCB $39
+ FCB INH
+ FCC "SBA "
+ FCB $10
+ FCB INH
+ FCC "SBCA"
+ FCB $82
+ FCB GEN
+ FCC "SBCB"
+ FCB $C2
+ FCB GEN
+ FCC "SEC "
+ FCB $0D
+ FCB INH
+ FCC "SEI "
+ FCB $0F
+ FCB INH
+ FCC "SEV "
+ FCB $0B
+ FCB INH
+ FCC "STAA"
+ FCB $87
+ FCB NIMM
+ FCC "STAB"
+ FCB $C7
+ FCB NIMM
+ FCC "STD "
+ FCB $CD
+ FCB NIMM
+ FCC "STOP"
+ FCB $CF
+ FCB INH
+ FCC "STS "
+ FCB $8F
+ FCB NIMM
+ FCC "STX "
+ FCB $CF
+ FCB XNIMM
+ FCC "STY "
+ FCB $CF
+ FCB YNIMM
+ FCC "SUBA"
+ FCB $80
+ FCB GEN
+ FCC "SUBB"
+ FCB $C0
+ FCB GEN
+ FCC "SUBD"
+ FCB $83
+ FCB LIMM
+ FCC "SWI "
+ FCB $3F
+ FCB INH
+ FCC "TAB "
+ FCB $16
+ FCB INH
+ FCC "TAP "
+ FCB $06
+ FCB INH
+ FCC "TBA "
+ FCB $17
+ FCB INH
+ FCC "TPA "
+ FCB $07
+ FCB INH
+ FCC "TEST"
+ FCB $00
+ FCB INH
+ FCC "TST "
+ FCB $6D
+ FCB GRP2
+ FCC "TSTA"
+ FCB $4D
+ FCB INH
+ FCC "TSTB"
+ FCB $5D
+ FCB INH
+ FCC "TSX "
+ FCB $30
+ FCB INH
+ FCC "TSY "
+ FCB $30
+ FCB P2INH
+ FCC "TXS "
+ FCB $35
+ FCB INH
+ FCC "TYS "
+ FCB $35
+ FCB P2INH
+ FCC "WAI "
+ FCB $3E
+ FCB INH
+ FCC "XGDX"
+ FCB $8F
+ FCB INH
+ FCC "XGDY"
+ FCB $8F
+ FCB P2INH
+ FCC "BRSE" ; bit direct modes for
+ FCB $12 ; disassembler.
+ FCB BTBD
+ FCC "BRCL"
+ FCB $13
+ FCB BTBD
+ FCC "BSET"
+ FCB $14
+ FCB SETCLRD
+ FCC "BCLR"
+ FCB $15
+ FCB SETCLRD
+ FCB EOT ; End of table
+
+;**********************************************
+PG1 EQU $0
+PG2 EQU $1
+PG3 EQU $2
+PG4 EQU $3
+
+;******************
+;*disassem() - disassemble the opcode.
+;******************
+;*(check for page prebyte)
+;*baseop=pc[0];
+;*pnorm=PG1;
+;*if(baseop==$18) pnorm=PG2;
+;*if(baseop==$1A) pnorm=PG3;
+;*if(baseop==$CD) pnorm=PG4;
+;*if(pnorm != PG1) dispc=pc+1;
+;*else dispc=pc; (dispc points to next byte)
+
+DISASSM EQU *
+ LDX PC ; address
+ LDAA 0,X ; opcode
+ LDAB #PG1
+ CMPA #$18
+ BEQ DISP2 ; jump if page2
+ CMPA #$1A
+ BEQ DISP3 ; jump if page3
+ CMPA #$CD
+ BNE DISP1 ; jump if not page4
+DISP4 INCB ; set up page value
+DISP3 INCB
+DISP2 INCB
+ INX
+DISP1 STX DISPC ; point to opcode
+ STAB PNORM ; save page
+
+;*If(opcode == ($00-$5F or $8D or $8F or $CF))
+;* if(pnorm == (PG3 or PG4))
+;* disillop(); return();
+;* b=disrch(opcode,NULL);
+;* if(b==0) disillop(); return();
+
+ LDAA 0,X ; get current opcode
+ STAA BASEOP
+ INX
+ STX DISPC ; point to next byte
+ CMPA #$5F
+ BLS DIS1 ; jump if in range
+ CMPA #$8D
+ BEQ DIS1 ; jump if bsr
+ CMPA #$8F
+ BEQ DIS1 ; jump if xgdx
+ CMPA #$CF
+ BEQ DIS1 ; jump if stop
+ JMP DISGRP ; try next part of map
+DIS1 LDAB PNORM
+ CMPB #PG3
+ BLO DIS2 ; jump if page 1 or 2
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+DIS2 LDAB BASEOP ; opcode
+ CLRB ; class=null
+ JSR DISRCH
+ TSTB
+ BNE DISPEC ; jump if opcode found
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+
+;* if(opcode==$8D) dissrch(opcode,REL);
+;* if(opcode==($8F or $CF)) disrch(opcode,INH);
+
+DISPEC LDAA BASEOP
+ CMPA #$8D
+ BNE DISPEC1
+ LDAB #REL
+ BRA DISPEC3 ; look for BSR opcode
+DISPEC1 CMPA #$8F
+ BEQ DISPEC2 ; jump if XGDX opcode
+ CMPA #$CF
+ BNE DISINH ; jump not STOP opcode
+DISPEC2 LDAB #INH
+DISPEC3 JSR DISRCH ; find other entry in table
+
+;* if(class==INH) /* INH */
+;* if(pnorm==PG2)
+;* b=disrch(baseop,P2INH);
+;* if(b==0) disillop(); return();
+;* prntmne();
+;* return();
+
+DISINH EQU *
+ LDAB CLASS
+ CMPB #INH
+ BNE DISREL ; jump if not inherent
+ LDAB PNORM
+ CMPB #PG1
+ BEQ DISINH1 ; jump if page1
+ LDAA BASEOP ; get opcode
+ LDAB #P2INH ; class=p2inh
+ JSR DISRCH
+ TSTB
+ BNE DISINH1 ; jump if found
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+DISINH1 JSR PRNTMNE
+ RTS
+
+;* elseif(class=REL) /* REL */
+;* if(pnorm != PG1)
+;* disillop(); return();
+;* prntmne();
+;* disrelad();
+;* return();
+
+DISREL EQU *
+ LDAB CLASS
+ CMPB #REL
+ BNE DISBTD
+ TST PNORM
+ BEQ DISREL1 ; jump if page1
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+DISREL1 JSR PRNTMNE ; output mnemonic
+ JSR DISRELAD ; compute relative address
+ RTS
+
+;* else /* SETCLR,SETCLRD,BTB,BTBD */
+;* if(class == (SETCLRD or BTBD))
+;* if(pnorm != PG1)
+;* disillop(); return(); /* illop */
+;* prntmne(); /* direct */
+;* disdir(); /* output $byte */
+;* else (class == (SETCLR or BTB))
+;* prntmne(); /* indexed */
+;* disindx();
+;* outspac();
+;* disdir();
+;* outspac();
+;* if(class == (BTB or BTBD))
+;* disrelad();
+;* return();
+
+DISBTD EQU *
+ LDAB CLASS
+ CMPB #SETCLRD
+ BEQ DISBTD1
+ CMPB #BTBD
+ BNE DISBIT ; jump not direct bitop
+DISBTD1 TST PNORM
+ BEQ DISBTD2 ; jump if page 1
+ JSR DISILLOP
+ RTS
+DISBTD2 JSR PRNTMNE
+ JSR DISDIR ; operand(direct)
+ BRA DISBIT1
+DISBIT EQU *
+ JSR PRNTMNE
+ JSR DISINDX ; operand(indexed)
+DISBIT1 JSR OUTSPAC
+ JSR DISDIR ; mask
+ LDAB CLASS
+ CMPB #BTB
+ BEQ DISBIT2 ; jump if btb
+ CMPB #BTBD
+ BNE DISBIT3 ; jump if not bit branch
+DISBIT2 JSR DISRELAD ; relative address
+DISBIT3 RTS
+
+
+;*Elseif($60 <= opcode <= $7F) /* GRP2 */
+;* if(pnorm == (PG3 or PG4))
+;* disillop(); return();
+;* if((pnorm==PG2) and (opcode != $6x))
+;* disillop(); return();
+;* b=disrch(baseop & $6F,NULL);
+;* if(b==0) disillop(); return();
+;* prntmne();
+;* if(opcode == $6x)
+;* disindx();
+;* else
+;* disext();
+;* return();
+
+DISGRP EQU *
+ CMPA #$7F ; a=opcode
+ BHI DISNEXT ; try next part of map
+ LDAB PNORM
+ CMPB #PG3
+ BLO DISGRP2 ; jump if page 1 or 2
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+DISGRP2 ANDA #$6F ; mask bit 4
+ CLRB ; class=null
+ JSR DISRCH
+ TSTB
+ BNE DISGRP3 ; jump if found
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+DISGRP3 JSR PRNTMNE
+ LDAA BASEOP ; get opcode
+ ANDA #$F0
+ CMPA #$60
+ BNE DISGRP4 ; jump if not 6x
+ JSR DISINDX ; operand(indexed)
+ RTS
+DISGRP4 JSR DISEXT ; operand(extended)
+ RTS
+
+;*Else ($80 <= opcode <= $FF)
+;* if(opcode == ($87 or $C7))
+;* disillop(); return();
+;* b=disrch(opcode&$CF,NULL);
+;* if(b==0) disillop(); return();
+
+DISNEXT EQU *
+ CMPA #$87 ; a=opcode
+ BEQ DISNEX1
+ CMPA #$C7
+ BNE DISNEX2
+DISNEX1 JSR DISILLOP ; "illegal opcode"
+ RTS
+DISNEX2 ANDA #$CF
+ CLRB ; class=null
+ JSR DISRCH
+ TSTB
+ BNE DISNEW ; jump if mne found
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+
+;* if(opcode&$CF==$8D) disrch(baseop,NIMM; (jsr)
+;* if(opcode&$CF==$8F) disrch(baseop,NIMM; (sts)
+;* if(opcode&$CF==$CF) disrch(baseop,XNIMM; (stx)
+;* if(opcode&$CF==$83) disrch(baseop,LIMM); (subd)
+
+DISNEW LDAA BASEOP
+ ANDA #$CF
+ CMPA #$8D
+ BNE DISNEW1 ; jump not jsr
+ LDAB #NIMM
+ BRA DISNEW4
+DISNEW1 CMPA #$8F
+ BNE DISNEW2 ; jump not sts
+ LDAB #NIMM
+ BRA DISNEW4
+DISNEW2 CMPA #$CF
+ BNE DISNEW3 ; jump not stx
+ LDAB #XNIMM
+ BRA DISNEW4
+DISNEW3 CMPA #$83
+ BNE DISGEN ; jump not subd
+ LDAB #LIMM
+DISNEW4 JSR DISRCH
+ TSTB
+ BNE DISGEN ; jump if found
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+
+;* if(class == (GEN or NIMM or LIMM )) /* GEN,NIMM,LIMM,CPD */
+;* if(opcode&$CF==$83)
+;* if(pnorm==(PG3 or PG4)) disrch(opcode#$CF,CPD)
+;* class=LIMM;
+;* if((pnorm == (PG2 or PG4) and (opcode != ($Ax or $Ex)))
+;* disillop(); return();
+;* disgenrl();
+;* return();
+
+DISGEN LDAB CLASS ; get class
+ CMPB #GEN
+ BEQ DISGEN1
+ CMPB #NIMM
+ BEQ DISGEN1
+ CMPB #LIMM
+ BNE DISXLN ; jump if other class
+DISGEN1 LDAA BASEOP
+ ANDA #$CF
+ CMPA #$83
+ BNE DISGEN3 ; jump if not #$83
+ LDAB PNORM
+ CMPB #PG3
+ BLO DISGEN3 ; jump not pg3 or 4
+ LDAB #CPD
+ JSR DISRCH ; look for cpd mne
+ LDAB #LIMM
+ STAB CLASS ; set class to limm
+DISGEN3 LDAB PNORM
+ CMPB #PG2
+ BEQ DISGEN4 ; jump if page 2
+ CMPB #PG4
+ BNE DISGEN5 ; jump not page 2 or 4
+DISGEN4 LDAA BASEOP
+ ANDA #$B0 ; mask bits 6,3-0
+ CMPA #$A0
+ BEQ DISGEN5 ; jump if $Ax or $Ex
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+DISGEN5 JSR DISGENRL ; process general class
+ RTS
+
+;* else /* XLIMM,XNIMM,YLIMM,YNIMM */
+;* if(pnorm==(PG2 or PG3))
+;* if(class==XLIMM) disrch(opcode&$CF,YLIMM);
+;* else disrch(opcode&$CF,YNIMM);
+;* if((pnorm == (PG3 or PG4))
+;* if(opcode != ($Ax or $Ex))
+;* disillop(); return();
+;* class=LIMM;
+;* disgen();
+;* return();
+
+DISXLN LDAB PNORM
+ CMPB #PG2
+ BEQ DISXLN1 ; jump if page2
+ CMPB #PG3
+ BNE DISXLN4 ; jump not page3
+DISXLN1 LDAA BASEOP
+ ANDA #$CF
+ LDAB CLASS
+ CMPB #XLIMM
+ BNE DISXLN2
+ LDAB #YLIMM
+ BRA DISXLN3 ; look for ylimm
+DISXLN2 LDAB #YNIMM ; look for ynimm
+DISXLN3 JSR DISRCH
+DISXLN4 LDAB PNORM
+ CMPB #PG3
+ BLO DISXLN5 ; jump if page 1 or 2
+ LDAA BASEOP ; get opcode
+ ANDA #$B0 ; mask bits 6,3-0
+ CMPA #$A0
+ BEQ DISXLN5 ; jump opcode = $Ax or $Ex
+ JSR DISILLOP ; "illegal opcode"
+ RTS
+DISXLN5 LDAB #LIMM
+ STAB CLASS
+ JSR DISGENRL ; process general class
+ RTS
+
+
+;******************
+;*disrch(a=opcode,b=class)
+;*return b=0 if not found
+;* else mneptr=points to mnemonic
+;* class=class of opcode
+;******************
+;*x=#MNETABL
+;*while(x[0] != eot)
+;* if((opcode==x[4]) && ((class=NULL) || (class=x[5])))
+;* mneptr=x;
+;* class=x[5];
+;* return(1);
+;* x += 6;
+;*return(0); /* not found */
+
+DISRCH EQU *
+ LDX #MNETABL ; point to top of table
+DISRCH1 CMPA 4,X ; test opcode
+ BNE DISRCH3 ; jump not this entry
+ TSTB
+ BEQ DISRCH2 ; jump if class=null
+ CMPB 5,X ; test class
+ BNE DISRCH3 ; jump not this entry
+DISRCH2 LDAB 5,X
+ STAB CLASS
+ STX MNEPTR ; return ptr to mnemonic
+ INCB
+ RTS ; return found
+DISRCH3 PSHB ; save class
+ LDAB #6
+ ABX
+ LDAB 0,X
+ CMPB #EOT ; test end of table
+ PULB
+ BNE DISRCH1
+ CLRB
+ RTS ; return not found
+
+;******************
+;*prntmne() - output the mnemonic pointed
+;*at by mneptr.
+;******************
+;*outa(mneptr[0-3]);
+;*outspac;
+;*return();
+
+PRNTMNE EQU *
+ LDX MNEPTR
+ LDAA 0,X
+ JSR OUTA ; output char1
+ LDAA 1,X
+ JSR OUTA ; output char2
+ LDAA 2,X
+ JSR OUTA ; output char3
+ LDAA 3,X
+ JSR OUTA ; output char4
+ JSR OUTSPAC
+ RTS
+
+;******************
+;*disindx() - process indexed mode
+;******************
+;*disdir();
+;*outa(',');
+;*if(pnorm == (PG2 or PG4)) outa('Y');
+;*else outa('X');
+;*return();
+
+DISINDX EQU *
+ JSR DISDIR ; output $byte
+ LDAA #','
+ JSR OUTA ; output ,
+ LDAB PNORM
+ CMPB #PG2
+ BEQ DISIND1 ; jump if page2
+ CMPB #PG4
+ BNE DISIND2 ; jump if not page4
+DISIND1 LDAA #'Y'
+ BRA DISIND3
+DISIND2 LDAA #'X'
+DISIND3 JSR OUTA ; output x or y
+ RTS
+
+;******************
+;*disrelad() - compute and output relative address.
+;******************
+;* braddr = dispc[0] + (dispc++);( 2's comp arith)
+;*outa('$');
+;*out2bsp(braddr);
+;*return();
+
+DISRELAD EQU *
+ LDX DISPC
+ LDAB 0,X ; get relative offset
+ INX
+ STX DISPC
+ TSTB
+ BMI DISRLD1 ; jump if negative
+ ABX
+ BRA DISRLD2
+DISRLD1 DEX
+ INCB
+ BNE DISRLD1 ; subtract
+DISRLD2 STX BRADDR ; save address
+ JSR OUTSPAC
+ LDAA #'$'
+ JSR OUTA
+ LDX #BRADDR
+ JSR OUT2BSP ; output address
+ RTS
+
+
+;******************
+;*disgenrl() - output data for the general cases which
+;*includes immediate, direct, indexed, and extended modes.
+;******************
+;*prntmne();
+;*if(baseop == ($8x or $Cx)) /* immediate */
+;* outa('#');
+;* disdir();
+;* if(class == LIMM)
+;* out1byt(dispc++);
+;*elseif(baseop == ($9x or $Dx)) /* direct */
+;* disdir();
+;*elseif(baseop == ($Ax or $Ex)) /* indexed */
+;* disindx();
+;*else (baseop == ($Bx or $Fx)) /* extended */
+;* disext();
+;*return();
+
+DISGENRL EQU *
+ JSR PRNTMNE ; print mnemonic
+ LDAA BASEOP ; get opcode
+ ANDA #$B0 ; mask bits 6,3-0
+ CMPA #$80
+ BNE DISGRL2 ; jump if not immed
+ LDAA #'#' ; do immediate
+ JSR OUTA
+ JSR DISDIR
+ LDAB CLASS
+ CMPB #LIMM
+ BEQ DISGRL1 ; jump class = limm
+ RTS
+DISGRL1 LDX DISPC
+ JSR OUT1BYT
+ STX DISPC
+ RTS
+DISGRL2 CMPA #$90
+ BNE DISGRL3 ; jump not direct
+ JSR DISDIR ; do direct
+ RTS
+DISGRL3 CMPA #$A0
+ BNE DISGRL4 ; jump not indexed
+ JSR DISINDX ; do extended
+ RTS
+DISGRL4 JSR DISEXT ; do extended
+ RTS
+
+;*****************
+;*disdir() - output "$ next byte"
+;*****************
+DISDIR EQU *
+ LDAA #'$'
+ JSR OUTA
+ LDX DISPC
+ JSR OUT1BYT
+ STX DISPC
+ RTS
+
+;*****************
+;*disext() - output "$ next 2 bytes"
+;*****************
+DISEXT EQU *
+ LDAA #'$'
+ JSR OUTA
+ LDX DISPC
+ JSR OUT2BSP
+ STX DISPC
+ RTS
+
+
+;*****************
+;*disillop() - output "illegal opcode"
+;*****************
+DISMSG1 FCC "ILLOP"
+ FCB EOT
+DISILLOP EQU *
+ PSHX
+ LDX #DISMSG1
+ JSR OUTSTRG0 ; no cr
+ PULX
+ RTS
+
+;* Equates
+JPORTD EQU $08
+JDDRD EQU $09
+JBAUD EQU $2B
+JSCCR1 EQU $2C
+JSCCR2 EQU $2D
+JSCSR EQU $2E
+JSCDAT EQU $2F
+;*
+
+;************
+;* xboot [<addr1> [<addr2>]] - Use SCI to talk to an 'hc11 in
+;* boot mode. Downloads bytes from addr1 thru addr2.
+;* Default addr1 = $C000 and addr2 = $C0ff.
+;*
+;* IMPORTANT:
+;* if talking to an 'A8 or 'A2: use either default addresses or ONLY
+;* addr1 - this sends 256 bytes
+;* if talking to an 'E9: include BOTH addr1 and addr2 for variable
+;* length
+;************
+
+;*Get arguments
+;*If no args, default $C000
+BOOT JSR WSKIP
+ BNE BOT1 ; jump if arguments
+ LDX #$C0FF ; addr2 default
+ STX PTR5
+ LDY #$C000 ; addr1 default
+ BRA BOT2 ; go - use default address
+
+;*Else get arguments
+BOT1 JSR BUFFARG
+ TST COUNT
+ BEQ BOTERR ; jump if no address
+ LDY SHFTREG ; start address (addr1)
+ JSR WSKIP
+ BNE BOT1A ; go get addr2
+ STY PTR5 ; default addr2...
+ LDD PTR5 ; ...by taking addr1...
+ ADDD #$FF ; ...and adding 255 to it...
+ STD PTR5 ; ...for a total download of 256
+ BRA BOT2 ; continue
+;*
+BOT1A JSR BUFFARG
+ TST COUNT
+ BEQ BOTERR ; jump if no address
+ LDX SHFTREG ; end address (addr2)
+ STX PTR5
+ JSR WSKIP
+ BNE BOTERR ; go use addr1 and addr2
+ BRA BOT2
+
+;*
+BOTERR LDX #MSG9 ; "bad argument"
+ JSR OUTSTRG
+ RTS
+
+;*Boot routine
+BOT2 LDAB #$FF ; control character ($ff -> download)
+ JSR BTSUB ; set up SCI and send control char
+;* initializes X as register pointer
+;*Download block
+BLOP LDAA 0,Y
+ STAA JSCDAT,X ; write to transmitter
+ BRCLR JSCSR,X,#80,* ; wait for TDRE
+ CPY PTR5 ; if last...
+ BEQ BTDONE ; ...quit
+ INY ; else...
+ BRA BLOP ; ...send next
+BTDONE RTS
+
+;************************************************
+;*Subroutine
+;* btsub - sets up SCI and outputs control character
+;* On entry, B = control character
+;* On exit, X = $1000
+;* A = $0C
+;***************************
+
+BTSUB EQU *
+ LDX #$1000 ; to use indexed addressing
+ LDAA #$02
+ STAA JPORTD,X ; drive transmitter line
+ STAA JDDRD,X ; high
+ CLR JSCCR2,X ; turn off XMTR and RCVR
+ LDAA #$22 ; BAUD = /16
+ STAA JBAUD,X
+ LDAA #$0C ; TURN ON XMTR & RCVR
+ STAA JSCCR2,X
+ STAB JSCDAT,X
+ BRCLR JSCSR,X,#80,* ; wait for TDRE
+ RTS
+
+;******************
+;*
+;* EVBTEST - This routine makes it a little easier
+;* on us to test this board.
+;*
+;******************
+
+EVBTEST LDAA #$FF
+ STAA $1000 ; Write ones to port A
+ CLR AUTOLF ; Turn off auto lf
+ JSR HOSTCO ; Connect host
+ JSR HOSTINIT ; Initialize host
+ LDAA #$7f
+ JSR HOSTOUT ; Send Delete to Altos
+ LDAA #$0d
+ JSR HOSTOUT ; Send <CR>
+ INC AUTOLF ; Turn on Auto LF
+ LDX #INBUFF+5 ; Point at Load message
+ STX PTR0 ; Set pointer for load command
+ LDY #MSGEVB ; Point at cat line
+LOOP LDAA 0,Y ; Loop to xfer command line
+ CMPA #04 ; Into buffalo line buffer
+ BEQ DONE ; Quit on $04
+ STAA 0,X
+ INX ; next character
+ INY
+ BRA LOOP
+DONE CLR TMP2 ; Set load vs. verify
+ JSR LOAD3 ; Jmp into middle of load
+ LDS #STACK ; Reset Stack
+ JMP $C0B3 ; Jump to Downloaded code
+
+MSGEVB FCC "cat evbtest.out"
+ FCB $0D
+ FCB $04
+
+
+
+;*** Jump table ***
+ ORG ROMBS+$1F7C
+.WARMST JMP MAIN
+.BPCLR JMP BPCLR
+.RPRINT JMP RPRINT
+.HEXBIN JMP HEXBIN
+.BUFFAR JMP BUFFARG
+.TERMAR JMP TERMARG
+.CHGBYT JMP CHGBYT
+.READBU JMP READBUFF
+.INCBUF JMP INCBUFF
+.DECBUF JMP DECBUFF
+.WSKIP JMP WSKIP
+.CHKABR JMP CHKABRT
+
+ ORG ROMBS+$1FA0
+.UPCASE JMP UPCASE
+.WCHEK JMP WCHEK
+.DCHEK JMP DCHEK
+.INIT JMP INIT
+.INPUT JMP INPUT
+.OUTPUT JMP OUTPUT
+.OUTLHL JMP OUTLHLF
+.OUTRHL JMP OUTRHLF
+.OUTA JMP OUTA
+.OUT1BY JMP OUT1BYT
+.OUT1BS JMP OUT1BSP
+.OUT2BS JMP OUT2BSP
+.OUTCRL JMP OUTCRLF
+.OUTSTR JMP OUTSTRG
+.OUTST0 JMP OUTSTRG0
+.INCHAR JMP INCHAR
+.VECINT JMP VECINIT
+
+ ORG ROMBS+$1FD6
+;*** Vectors ***
+VSCI FDB JSCI
+VSPI FDB JSPI
+VPAIE FDB JPAIE
+VPAO FDB JPAO
+VTOF FDB JTOF
+VTOC5 FDB JTOC5
+VTOC4 FDB JTOC4
+VTOC3 FDB JTOC3
+VTOC2 FDB JTOC2
+VTOC1 FDB JTOC1
+VTIC3 FDB JTIC3
+VTIC2 FDB JTIC2
+VTIC1 FDB JTIC1
+VRTI FDB JRTI
+VIRQ FDB JIRQ
+VXIRQ FDB JXIRQ
+VSWI FDB JSWI
+VILLOP FDB JILLOP
+VCOP FDB JCOP
+VCLM FDB JCLM
+VRST FDB BUFFALO
+ END
diff --git a/tests/t_buf32/t_buf32.doc b/tests/t_buf32/t_buf32.doc
new file mode 100644
index 0000000..67e8f37
--- /dev/null
+++ b/tests/t_buf32/t_buf32.doc
@@ -0,0 +1,5 @@
++------------------------ Test Application BUF32 ----------------------------+
+| |
+| This is a version of Motorola's 68HC11-Monitor Buffalo-32 adapted for AS. |
+| |
++-----------------------------------------------------------------------------+
diff --git a/tests/t_buf32/t_buf32.inc b/tests/t_buf32/t_buf32.inc
new file mode 100644
index 0000000..98ae373
--- /dev/null
+++ b/tests/t_buf32/t_buf32.inc
@@ -0,0 +1,2 @@
+; tests/t_buf32/t_buf32.asm-Includefile für Assembler-Programm
+; Ende Includefile für Assembler-Programm
diff --git a/tests/t_buf32/t_buf32.ori b/tests/t_buf32/t_buf32.ori
new file mode 100644
index 0000000..774e9c9
--- /dev/null
+++ b/tests/t_buf32/t_buf32.ori
Binary files differ
diff --git a/tests/t_cop8/asflags b/tests/t_cop8/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_cop8/asflags
diff --git a/tests/t_cop8/t_cop8.asm b/tests/t_cop8/t_cop8.asm
new file mode 100644
index 0000000..68573d1
--- /dev/null
+++ b/tests/t_cop8/t_cop8.asm
@@ -0,0 +1,128 @@
+ cpu cop87l84
+
+ macexp off
+
+ include regcop8.inc
+
+ nop
+ ret
+ reti
+ retsk
+ sc
+ rc
+ ifc
+ ifnc
+ vis
+ jid
+ intr
+ laid
+ rpnd
+
+ clr a
+ inc a
+ dec a
+ dcor a
+ rrc a
+ rlc a
+ swap a
+ pop a
+ push a
+
+ adc a,[b]
+ adc a,0x12
+ adc a,#0x12
+
+ subc a,[b]
+ subc a,0x12
+ subc a,#0x12
+
+ add a,[b]
+ add a,0x12
+ add a,#0x12
+
+ ifgt a,[b]
+ ifgt a,0x12
+ ifgt a,#0x12
+
+ and a,[b]
+ and a,0x12
+ and a,#0x12
+
+ xor a,[b]
+ xor a,0x12
+ xor a,#0x12
+
+ or a,[b]
+ or a,0x12
+ or a,#0x12
+
+ ld a,[b]
+ ld a,0x12
+ ld a,#0x12
+ ld a,[x]
+ ld r4,#0x12
+ ld b,#12
+ ld b,#0x12
+ ld a,[b+]
+ ld a,[x+]
+ ld a,[b-]
+ ld a,[x-]
+ ld [b],#0x12
+ ld [b+],#0x12
+ ld [b-],#0x12
+ ld 0x12,#0x12
+
+ x a,[b]
+ x [x],a
+ x a,[b+]
+ x [x+],a
+ x a,[b-]
+ x [x-],a
+ x a,0x12
+
+ andsz a,#0x12
+
+ ifeq a,[b]
+ ifeq a,0x12
+ ifeq a,#0x12
+ ifeq 0x12,#0x12
+
+ ifne a,[b]
+ ifne a,0x12
+ ifne a,#0x12
+
+ ifbit 3,[b]
+ ifbit 5,0x12
+ sbit 3,[b]
+ sbit 5,0x12
+ rbit 3,[b]
+ rbit 5,0x12
+
+ ifbne #7
+ ifbne #0xc
+
+ jmp 0x123
+ jsr 0x987
+
+ jmpl 0x1234
+ jsrl 0x3456
+
+ jp .+6
+ jp .-20
+ jp .+1
+
+ drsz r12
+ drsz r8
+
+reg sfr 10
+
+ addr 1,2,3,4,5
+ addrw 1,2,3,4,5
+ byte 1,2,3,4,5
+ word 1,2,3,4,5
+ dsb 20
+ dsw 20
+ fb 10,20
+ fw 10,20
+
+
diff --git a/tests/t_cop8/t_cop8.doc b/tests/t_cop8/t_cop8.doc
new file mode 100644
index 0000000..94aacd5
--- /dev/null
+++ b/tests/t_cop8/t_cop8.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application COP8 ----------------------------+
+| |
+| This is a (synthetic) test of the COP8 code generator |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_cop8/t_cop8.ori b/tests/t_cop8/t_cop8.ori
new file mode 100644
index 0000000..15e176e
--- /dev/null
+++ b/tests/t_cop8/t_cop8.ori
Binary files differ
diff --git a/tests/t_f2mc8l/asflags b/tests/t_f2mc8l/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_f2mc8l/asflags
diff --git a/tests/t_f2mc8l/t_f2mc8l.asm b/tests/t_f2mc8l/t_f2mc8l.asm
new file mode 100644
index 0000000..25540b7
--- /dev/null
+++ b/tests/t_f2mc8l/t_f2mc8l.asm
@@ -0,0 +1,242 @@
+ cpu mb89190
+ page 0
+
+;----------------------------------------------------------------------------
+; Transfer
+
+ mov 23h,a
+ mov @ix+34h,a
+ mov 1234h,a
+ mov @ep,a
+ mov r0,a
+ mov r1,a
+ mov r2,a
+ mov r3,a
+ mov r4,a
+ mov r5,a
+ mov r6,a
+ mov r7,a
+ mov a,#12h
+ mov a,23h
+ mov a,@ix+34h
+ mov a,1234h
+ mov a,@a
+ mov a,@ep
+ mov a,r0
+ mov a,r1
+ mov a,r2
+ mov a,r3
+ mov a,r4
+ mov a,r5
+ mov a,r6
+ mov a,r7
+ mov 23h,#12h
+ mov @ix+34h,#12h
+ mov @ep,#12h
+ mov r0,#12h
+ mov r1,#12h
+ mov r2,#12h
+ mov r3,#12h
+ mov r4,#12h
+ mov r5,#12h
+ mov r6,#12h
+ mov r7,#12h
+ movw 12h,a
+ movw @ix+34h,a
+ movw 1234h,a
+ movw @ep,a
+ movw ep,a
+ movw a,#2345h
+ movw a,12h
+ movw a,@ix+34h
+ movw a,1234h
+ movw a,@a
+ movw a,@ep
+ movw a,ep
+ movw ep,#2345h
+ movw ix,a
+ movw a,ix
+ movw sp,a
+ movw a,sp
+ mov @a,t
+ movw @a,t
+ movw ix,#2345h
+ movw a,ps
+ movw ps,a
+ movw sp,#2345h
+ swap
+ setb 12h:6
+ clrb 12h:5
+ xch a,t
+ xchw a,t
+ xchw a,ep
+ xchw a,ix
+ xchw a,sp
+ movw a,pc
+
+
+;----------------------------------------------------------------------------
+; Arithmetik
+
+ addc a,r0
+ addc a,r1
+ addc a,r2
+ addc a,r3
+ addc a,r4
+ addc a,r5
+ addc a,r6
+ addc a,r7
+ addc a,#12h
+ addc a,23h
+ addc a,@ix+34h
+ addc a,@ep
+ addcw a
+ addc a
+ subc a,r0
+ subc a,r1
+ subc a,r2
+ subc a,r3
+ subc a,r4
+ subc a,r5
+ subc a,r6
+ subc a,r7
+ subc a,#12h
+ subc a,23h
+ subc a,@ix+34h
+ subc a,@ep
+ subcw a
+ subc a
+ inc r0
+ inc r1
+ inc r2
+ inc r3
+ inc r4
+ inc r5
+ inc r6
+ inc r7
+ incw ep
+ incw ix
+ incw a
+ dec r0
+ dec r1
+ dec r2
+ dec r3
+ dec r4
+ dec r5
+ dec r6
+ dec r7
+ decw ep
+ decw ix
+ decw a
+ mulu a
+ divu a
+ andw a
+ orw a
+ xorw a
+ cmp a
+ rorc a
+ rolc a
+ cmp a,#12h
+ cmp a,23h
+ cmp a,@ix+34h
+ cmp a,@ep
+ cmp a,r0
+ cmp a,r1
+ cmp a,r2
+ cmp a,r3
+ cmp a,r4
+ cmp a,r5
+ cmp a,r6
+ cmp a,r7
+ daa
+ das
+ xor a
+ xor a,#12h
+ xor a,23h
+ xor a,@ix+34h
+ xor a,@ep
+ xor a,r0
+ xor a,r1
+ xor a,r2
+ xor a,r3
+ xor a,r4
+ xor a,r5
+ xor a,r6
+ xor a,r7
+ and a
+ and a,#12h
+ and a,23h
+ and a,@ix+34h
+ and a,@ep
+ and a,r0
+ and a,r1
+ and a,r2
+ and a,r3
+ and a,r4
+ and a,r5
+ and a,r6
+ and a,r7
+ or a
+ or a,#12h
+ or a,23h
+ or a,@ix+34h
+ or a,@ep
+ or a,r0
+ or a,r1
+ or a,r2
+ or a,r3
+ or a,r4
+ or a,r5
+ or a,r6
+ or a,r7
+ cmp 23h,#12h
+ cmp @ep,#12h
+ cmp @ix+34h,#12h
+ cmp r0,#12h
+ cmp r1,#12h
+ cmp r2,#12h
+ cmp r3,#12h
+ cmp r4,#12h
+ cmp r5,#12h
+ cmp r6,#12h
+ cmp r7,#12h
+ incw sp
+ decw sp
+
+;----------------------------------------------------------------------------
+; Spruenge
+
+ bz $
+ beq $
+ bnz $
+ bne $
+ bc $
+ blo $
+ bnc $
+ bhs $
+ bn $
+ bp $
+ blt $
+ bge $
+ bbc 23h:5,$
+ bbs 23h:4,$
+ jmp @a
+ jmp 2345h
+ callv #4
+ call 2345h
+ xchw a,pc
+ ret
+ reti
+
+;----------------------------------------------------------------------------
+; Sonstiges
+
+ pushw a
+ popw a
+ pushw ix
+ popw ix
+ nop
+ clrc
+ setc
+ clri
+ seti
diff --git a/tests/t_f2mc8l/t_f2mc8l.doc b/tests/t_f2mc8l/t_f2mc8l.doc
new file mode 100644
index 0000000..8bb3785
--- /dev/null
+++ b/tests/t_f2mc8l/t_f2mc8l.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application F2MC8L --------------------------+
+| |
+| This is a (synthetic) test of the F2MC8L's instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_f2mc8l/t_f2mc8l.ori b/tests/t_f2mc8l/t_f2mc8l.ori
new file mode 100644
index 0000000..3f1f4ae
--- /dev/null
+++ b/tests/t_f2mc8l/t_f2mc8l.ori
Binary files differ
diff --git a/tests/t_fl90/asflags b/tests/t_fl90/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_fl90/asflags
diff --git a/tests/t_fl90/cpu_time.inc b/tests/t_fl90/cpu_time.inc
new file mode 100644
index 0000000..bb23594
--- /dev/null
+++ b/tests/t_fl90/cpu_time.inc
@@ -0,0 +1,170 @@
+; CPU_TIME.INC
+;******************************************************************************
+;* Zeitmessmodul fr TLCS 90 *
+;* *
+;* Originale fr den TLCS 900 von Oli(ver Sellke) *
+;* Implementierung TLCS 90 von Alfred Arnold, Dezember 1993 *
+;* *
+;* Routine Funktion Eingabe Ausgabe Stack L„nge *
+;* *
+;* InitTimer Timer initialisieren ---- ---- 0 Byte 6 Byte *
+;* StartTimer Timer starten ---- ---- 0 Byte 7 Byte *
+;* StopTime Timer stoppen & Ausgabe ---- ---- 6 Byte 117 Byte *) *
+;* *
+;* *) bei hoher Aufl”sung *
+;* *
+;* - Die Routinen benutzen Timer 4, dieser darf nicht von der Anwendung *
+;* benutzt werden!! *
+;* - Die Aufl”sung kann ber das Symbol BigTime umgeschaltet werden: *
+;* *
+;* BigTime Aufl”sung Maximalzeit *
+;* definiert 0,8 us 52,428 ms *
+;* undefiniert 12,8 us 838,848 ms *
+;* *
+;* - Die Datei MON.INC wird fr die Einsprnge des TDBTMP90-Monitors ben”tigt.*
+;* - MACROS.INC muá vorher eingebunden werden *
+;* *
+;******************************************************************************
+
+ section CPU_Time
+
+;------------------------------------------------------------------------------
+; Monitoreinsprungadressen laden
+
+ include "mon.inc"
+
+;------------------------------------------------------------------------------
+; Timer vorinitialisieren
+
+ proc InitTimer
+ ifdef BigTime
+ ld (T4MOD),00100010b ; nur Software-Capture, Phi16
+ elseif
+ ld (T4MOD),00100001b ; nur Software-Capture, Phi1
+ endif
+ set 5,(TRUN) ; Vorteiler starten
+ res 4,(TRUN) ; Timer steht noch
+ ret
+ endp
+
+;------------------------------------------------------------------------------
+; Timer starten
+
+ proc StartTimer
+ set 2,(T4MOD) ; Timer l”schen
+ res 2,(T4MOD)
+ set 4,(TRUN) ; Timer starten
+ ret
+ endp
+
+;------------------------------------------------------------------------------
+; Timer stoppen & Wert auf Konsole ausgeben
+
+ subproc Div24
+
+ ld b,16 ; A-HL : B = HL und A
+DivLoop: sll l ; Divident hochschieben
+ rl h
+ rla
+ srl h ; fr nachher
+ rr l
+ sub a,c ; paát Divisor hinein ?
+ jr nc,DivOK
+ add a,c ; nein, zurcknehmen
+ scf ; ins Ergebnis 0 einschieben
+DivOK: ccf ; neues Ergebnisbit
+ rl l ; Ergebnis in HL einschieben
+ rl h
+ djnz DivLoop
+ ret
+
+ endp
+
+
+ proc StopTimer
+
+ push af ; Register retten
+ push hl
+ push de
+ push bc
+
+ res 5,(T4MOD) ; Wert im CAP1 latchen
+ res 4,(TRUN) ; Timer wieder anhalten
+ ld hl,(CAP1L) ; Wert auslesen
+
+ ifdef BigTime
+ ld a,h ; groáe Periode: x128...
+ ld h,l
+ ld l,0
+ srla
+ rr h
+ rr l
+ ld c,100 ; ...Teilen durch 100
+ elseif
+ ld a,0 ; kleine Periode: x8...
+ rept 3
+ sll l
+ rl h
+ rla
+ endm
+ ld c,10 ; ...Teilen durch 10
+ endif
+ call Div24 ; Division durchfhren
+ ifdef BigTime ; Kommatrennung fr groáe Periode
+ ld a,0
+ call Div24
+ ld d,a ; Rest merken
+ endif
+ ld e,0 ; Zeichenz„hler nullen
+ ld c,10 ; Teilerfaktor konstant
+InLoop: ld a,0 ; Erweiterung auf 24 Bit
+ call Div24 ; einmal teilen
+ push af ; Zeichen auf LIFO merken
+ inc e ; ein Zeichen mehr
+ or hl,hl ; noch etwas brig ?
+ jr nz,InLoop
+ ld a,5 ; Leerzeichen fr Ausrichtung
+ sub a,e ; Zahl berechnen
+ jr z,OutErg ; Nullschleife abfangen
+ ld b,a ; ansonsten passende Zahl Leerzeichen
+BlankLoop: call BLAUS ; voranstellen
+ djnz BlankLoop
+OutErg: ld b,e ; jetzt die Zeichen ausgeben
+OutLoop: pop af
+ add a,'0'
+ call CONOUT
+ djnz OutLoop
+ ifdef BigTime ; bei groáer Aufl”sung Nachkommastellen
+ ld a,'.'
+ call CONOUT
+ ld l,d ; Zehner/Einerzerlegung
+ ld h,0
+ div hl,c
+ add hl,'00'
+ ld a,l
+ call CONOUT
+ ld a,h
+ call CONOUT
+ call BLAUS
+ ld a,'m'
+ elseif
+ ld a,' '
+ call CONOUT
+ ld a,'u'
+ endif
+ call CONOUT ; Ausgabe Einheit
+ ld a,'s'
+ call CONOUT
+
+ pop bc ; Register zurck
+ pop de
+ pop hl
+ pop af
+
+ ret
+ endp
+
+;------------------------------------------------------------------------------
+; gemeinsames Ende
+
+ endsection
diff --git a/tests/t_fl90/float.inc b/tests/t_fl90/float.inc
new file mode 100644
index 0000000..7355130
--- /dev/null
+++ b/tests/t_fl90/float.inc
@@ -0,0 +1,1601 @@
+; FLOAT.INC
+;******************************************************************************
+;* Gleitkommabibliothek fr TLCS 90 *
+;* *
+;* Originale fr den Z80 aus mc 12/88,1/89 *
+;* Portierung auf TLCS 90 von Alfred Arnold, Dezember 1993 *
+;* *
+;* Routine Funktion Eingabe Ausgabe Stack L„nge Zeit/10MHz *
+;* *
+;* fadd Addition 2*Stack BC-DE 14 Byte 347 Byte 248 us *
+;* fsub Subtraktion 2*Stack BC-DE 14 Byte 12 Byte 255 us *
+;* fmul Multiplikation 2*Stack BC-DE 20 Byte 356 Byte 936 us *
+;* fdiv Division 2*Stack BC-DE 22 Byte 303 Byte 1081 us *
+;* fmul2 Mult. mit 2er-Potenz Stack,A BC-DE 10 Byte 162 Byte 28 us *
+;* fsqrt Quadratwurzel Stack BC-DE 22 Byte 621 Byte 1900 us *
+;* fitof Int-->Float Stack BC-DE 10 Byte 84 Byte 160 us *) *
+;* fftoi Float-->Int Stack BC-DE 10 Byte 104 Byte 170 us *) *
+;* fftoa Float-->ASCII 3*Stack ----- 40 Byte 451 Byte *) *
+;* fatof ASCII-->Float Stack C,BC-DE 42 Byte 396 Byte *) *
+;* *
+;* *) Die Ausfhrungszeiten streuen je nach Operand sehr stark und k”nnen *
+;* bei den ASCII-Funktionen bei vielen Millisekunden liegen. *
+;* *
+;* - Parametereingabe ber den Stack bedeutet, daá die Parameter mittels *
+;* PUSH vor dem Aufruf auf den Stack gelegt werden mssen. Diese Werte *
+;* werden von den Unterroutinen am Ende automatisch vom Stack entfernt. *
+;* Der zur šbergabe ben”tigte Platz ist bei den Angaben zur Stackbelastung *
+;* eingerechnet! *
+;* - Wollen Sie einzelne Routinen entfernen, so beachten Sie, daá fsub Teile *
+;* aus fadd, fdiv Teile aus fmul sowie fftoi Teile aus fitof verwendet ! *
+;* - Gleitkommaformat ist IEEE Single (32 Bit) *
+;* - Integerwerte bei fmul2, fitof und fftoi sind vorzeichenbehaftet *
+;* - Da die Routinen lokale Labels verwenden, ist mindestens AS 1.39 erfor- *
+;* derlich *
+;* - MACROS.INC muá vorher eingebunden werden *
+;******************************************************************************
+
+ section float
+
+;------------------------------------------------------------------------------
+; modulglobale Konstanten
+
+MaxExpo equ 255
+Bias equ 127
+
+OpSize equ 4 ; GrӇe eines Operanden
+
+fIX_alt equ 0 ; Top of Stack liegt IX
+FAdr equ 2 ; Rcksprungadresse
+Op2 equ 4 ; Adresse Operand 2
+Op1 equ Op2+OpSize ; Adresse Operand 1
+
+Ld10: dd ld(10)
+One: dd 1.0
+Ten: dd 10.0
+Tenth: dd 3dcccccdh ; =0.1, aber die Rundung auf manchen
+ ; Systemen variiert (damit Test nicht
+ ; scheitert)
+Half: dd 0.5
+
+cpsh macro reg,op,{NoExpand}
+ ld reg,(op+2)
+ push reg
+ ld reg,(op)
+ push reg
+ endm
+
+;------------------------------------------------------------------------------
+; Addition
+
+ proc fadd
+ link ix,0 ; Eintritt
+
+ push af ; Register retten
+ push hl
+
+ public AddSub:Parent ; Einsprung fr fsub
+
+AddSub: ld a,(ix+Op1+3) ; Vorzeichen Operand 1 laden
+ ld e,a ; Ergebnisvorzeichen in E, Bit 7
+ xor a,(ix+Op2+3) ; mit Vorzeichen von Op2 verknpfen
+ ld d,a ; Subtraktionsflag in D, Bit 7
+ res 7,(ix+Op1+3) ; Vorzeichen in Mantisse 1 l”schen
+ res 7,(ix+Op2+3) ; Vorzeichen in Mantisse 2 l”schen
+
+; Die Operanden sind jetzt in der Form 0eee eeee efff ... ffff
+
+ ld hl,(ix+Op1) ; Differenz Op1-Op2 bilden
+ sub hl,(ix+Op2)
+ ld hl,(ix+Op1+2)
+ sbc hl,(ix+Op2+2)
+ jr nc,Ad_1 ; Sprung falls Op1>Op2
+ ld bc,(ix+Op1) ; ansonsten Operanden vertauschen
+ ex bc,(ix+Op2)
+ ld (ix+Op1),bc
+ ld bc,(ix+Op1+2)
+ ex bc,(ix+Op2+2)
+ ld (ix+Op1+2),bc
+ ld a,e ; Ergebnisvorzeichen neu berechnen
+ xor a,d
+ ld e,a
+
+Ad_1: ld a,(ix+Op1+2) ; Exponent der grӇeren Zahl laden
+ ld c,(ix+Op1+3)
+ slaa
+ rl c
+ jr z,Den1
+ set 7,(ix+Op1+2) ; implizite Eins erzeugen
+Den1: ld a,(ix+Op2+2) ; dito Zahl 2
+ ld b,(ix+Op2+3)
+ slaa
+ rl b
+ jr z,Den2
+ set 7,(ix+Op2+2)
+
+Den2: push bc ; jetzt die Register fr den
+ push de ; Blocktransferbefehl retten
+ ld bc,2*OpSize-1 ; beide Operanden verschieben
+ ld hl,ix ; HL zeigt auf letztes Byte
+ add hl,Op2+2*OpSize-1
+ ld de,hl ; HL nach DE kopieren
+ dec hl ; HL zeigt auf vorletztes Byte
+ lddr ; Verschiebung beider Mantissen
+ pop de ; um 8 Bit nach links
+ pop bc
+
+ xor a,a
+ ld (ix+Op1),a ; Form: ffff ... ffff 0000 0000
+ ld (ix+Op2),a
+ ld a,c ; Differenz der Exponenten berechnen
+ sub a,b
+ ld b,a ; Differenz nach B fr LOOP-Befehl
+ jr z,N_Anp ; falls Null, keine Anpassung
+ cp a,25 ; mehr als 24? (Abfrage mit Carry
+ jp c,Anp ; erfordert Vergleich mit 25)
+ ld b,0 ; !!!!
+ jp Round
+
+Anp: srl (ix+Op2+3) ; Anpassung der zweiten Mantisse
+ rr (ix+Op2+2) ; durch Verschiebung nach rechts
+ rr (ix+Op2+1)
+ rr (ix+Op2)
+ djnz Anp ; bis B=0
+
+N_Anp: bit 7,d ; Addition oder Subtraktion ?
+ jr nz,Subtract ; ggfs. zur Subtraktion springen
+ ld hl,(ix+Op1) ; jetzt werden die beiden Mantissen
+ add hl,(ix+Op2) ; zueinander addiert
+ ld (ix+Op1),hl
+ ld hl,(ix+Op1+2)
+ adc hl,(ix+Op2+2)
+ ld (ix+Op1+2),hl
+ jr nc,Round ; kein šberlauf-->zum Runden
+ rr (ix+Op1+3) ; šberlauf einschieben
+ rr (ix+Op1+2)
+ rr (ix+Op1+1)
+ rr (ix+Op1)
+ inc bc ; Exponent erh”hen (B ist 0 durch
+ jr Round ; Schleife), zum Runden
+
+Subtract: ld hl,(ix+Op1) ; beide Mantissen werden voneinander
+ sub hl,(ix+Op2) ; subtrahiert
+ ld (ix+Op1),hl
+ ld hl,(ix+Op1+2)
+ sbc hl,(ix+Op2+2)
+ ld (ix+Op1+2),hl
+ jr m,Round ; bei fhrender Eins zum Runden
+ jr nz,Norm ; ungleich 0 ? Dann zum Normalisieren
+ cp hl,(ix+Op1) ; Rest der Mantisse auch Null ?
+ jr eq,Zero ; alles Null --> Ergebnis ist Null
+
+Norm: ld a,b ; Exponent noch nicht Null ?
+ or a,c
+ jr z,Round
+ dec bc ; Exponent erniedrigen
+ sla (ix+Op1) ; Mantisse normalisieren, bis
+ rl (ix+Op1+1) ; fhrende Eins auftaucht
+ rl (ix+Op1+2)
+ rl (ix+Op1+3)
+ jr p,Norm ; noch keine Eins-->weitermachen
+
+Round: add (ix+Op1),80h ; jetzt Runden auf Bit hinter Mantisse
+ jr nc,NoOver ; kein šbertrag ?
+ inc (ix+Op1+1) ; doch, n„chstes Mantissenbyte
+ jr nz,NoOver ; behandeln, jetzt auf Null prfen,
+ inc (ix+Op1+2) ; da der INC-Befehl kein Carry liefert
+ jr nz,NoOver
+ inc (ix+Op1+3)
+ jr nz,NoOver
+ scf ; fhrende Eins erzeugen
+ rr (ix+Op1+3) ; bei šberlauf Mantisse durch
+ rr (ix+Op1+2) ; Rechtsschieben wieder normalisieren
+ rr (ix+Op1+1) ; (nur fr 24 Bit notwendig)
+ inc bc ; und Exponent korrigieren
+
+NoOver: xor a,a ; A = 0
+ cp a,(ix+Op1+3) ; Mantisse auf Null prfen
+ jr nz,NoZero
+ cp a,(ix+Op1+2)
+ jr nz,NoZero
+ cp a,(ix+Op1+1) ; alle Mantissenbytes Null ?
+ jr nz,NoZero ; dann ist auch das Ergebnis Null
+
+Zero: ld b,a ; Null-Ergebnis aufbauen
+ ld c,a
+ ld de,bc
+ jr Exit ; dann Routine verlassen
+
+NoZero: cp a,b ; A ist Null
+ ld a,MaxExpo ; Exponent oberes Byte ungleich Null ?
+ jr nz,Over ; dann ist šberlauf eingetreten
+ cp a,c ; oder genau MaxExpo erreicht ?
+ jr nz,NoUe
+Over: ld c,a ; Exponent auf MaxExpo setzen
+ xor a,a ; und Mantisse auf Null
+ ld (ix+Op1+3),a
+ ld (ix+Op1+2),a
+ ld (ix+Op1+1),a
+ jr DeNorm
+
+NoUe: xor a,a ; A = 0
+ cp a,c ; Exponent Null (Zahl denormalisiert ?
+ jr z,DeNorm ; ja -->
+ sla (ix+Op1+1) ; fhrendes Bit wird nicht gespeichert
+ rl (ix+Op1+2) ; daher Mantisse um 1 Bit nach links
+ rl (ix+Op1+3)
+
+DeNorm: ld b,c ; Ergebnis aufbauen: Exponent in B
+ ld c,(ix+Op1+3) ; Mantisse oberstes Byte
+ ld d,(ix+Op1+2)
+ sla e ; Vorzeichen aus E in Carry schieben
+ ld e,(ix+Op1+1)
+ rr b ; Vorzeichen in Ergebnis einschieben
+ rr c
+ rr d
+ rr e
+
+Exit: pop hl ; Register restaurieren
+ pop af
+
+ unlk ix ; Austritt
+ retd 2*OpSize ; Parameter abr„umen
+ endp
+
+;------------------------------------------------------------------------------
+; Subtraktion
+
+ proc fsub
+
+ link ix,0 ; Eintritt
+
+ push af ; Register retten
+ push hl
+
+ xor (ix+Op2+3),80h ; Vorzeichen Operand 2 kippen
+
+ jrl AddSub ; weiter wie Addition
+
+ endp
+
+;------------------------------------------------------------------------------
+; Multiplikation
+
+ proc fmul
+
+ DefLocal temp,6 ; Platz Tempor„rvariable
+
+ link ix,LocalSize ; Platz auf Stack reservieren
+
+ push af ; Register retten
+ push hl
+
+ ld a,(ix+Op1+3) ; Ergebnisvorzeichen bestimmen
+ xor a,(ix+Op2+3)
+ ld c,a ; in C merken
+
+ ld d,0 ; Exponent 1 laden
+ ld e,(ix+Op1+3)
+ ld a,(ix+Op1+2)
+ slaa ; Exponent unterstes Bit in Carry
+ rl e ; und in E einschieben
+ srla ; ergibt Bit 7=0
+ ld (ix+Op1+3),a ; impl. Null vorbesetzen+um 8 Bit schieben
+ cp e,0
+ jr z,Den1 ; falls Null, dann denormalisiert
+ set 7,(ix+Op1+3) ; ansonsten impl. Eins erzeugen
+ dec de ; Bias kompensieren
+Den1: ld hl,(ix+Op1) ; jetzt restliche Bytes verschieben
+ ld (ix+Op1+1),hl
+ xor hl,hl ; unterste Mantissenbits l”schen
+ ld (ix+Op1),h ; Form: ffff ... ffff 0000 0000
+
+ ld (ix+temp+4),hl ; lokale Variable mit Null vorbesetzen
+ ld (ix+temp+2),hl
+ ld (ix+temp),hl
+
+ ld l,(ix+Op2+3) ; Exponent 2 in HL aufbauen
+ ld a,(ix+Op2+2)
+ res 7,(ix+Op2+2) ; gleiches Verfahren wie Op1
+ slaa
+ rl l
+ jr z,Den2
+ set 7,(ix+Op2+2)
+ dec hl
+Den2:
+ add hl,de ; Exponenten aufaddieren
+ sub hl,Bias-3 ; Bias-3 subtrahieren
+ jp p,NoZero ; positiv-->kein Unterlauf
+ ld a,l ; Exponent <-24 ?
+ cp a,-24
+ jr nc,NoZero
+ jp MulZero ; ja, dann ist Ergebnis Null
+
+NoZero: ld b,24 ; Schleifenz„hler Multiplikation
+ ld de,0 ; Hilfsregister Multiplikand
+ push hl ; HL zum Addieren benutzen
+Multiply: srl (ix+Op1+3) ; Multiplikand nach rechts schieben
+ rr (ix+Op1+2)
+ rr (ix+Op1+1)
+ rr (ix+Op1)
+ rr d ; DE als Verl„ngerung von Operand 1
+ rr e
+ sla (ix+Op2) ; Multiplikator nach links schieben
+ rl (ix+Op2+1)
+ rl (ix+Op2+2) ; falls fhrendes Bit 0, nicht addieren
+ jr nc,NoAdd
+ ld hl,(ix+temp) ; sonst aufaddieren
+ add hl,de
+ ld (ix+temp),hl
+ ld hl,(ix+temp+2)
+ adc hl,(ix+Op1)
+ ld (ix+temp+2),hl
+ ld hl,(ix+temp+4)
+ adc hl,(ix+Op1+2)
+ ld (ix+temp+4),hl
+NoAdd: djnz Multiply ; Schleife durchlaufen
+ pop hl
+ ld a,(ix+temp+5)
+ or a,a ; Flags setzen
+ jp m,MulRound ; bei fhrender Eins zum Runden
+ jr nz,Normalize ; ansonsten normalisieren
+ cp a,(ix+temp+4)
+ jr nz,Normalize
+ cp a,(ix+temp+3)
+ jr nz,Normalize
+ cp a,(ix+temp+2)
+ jr Normalize
+ jp MulZero ; komplett Null-->Ergebnis Null
+
+Normalize: bit 7,h ; Exponent negativ ?
+ jp nz,Underrun ; ggf. Unterlauf behandlen
+
+Norm1: cp hl,0 ; Exponent=0 ?
+ jr z,MulRound
+ dec hl ; Exponent erniedrigen,
+ sla (ix+temp) ; Mantisse verschieben...
+ rl (ix+temp+1)
+ rl (ix+temp+2)
+ rl (ix+temp+3)
+ rl (ix+temp+4)
+ rl (ix+temp+5)
+ jp p,Norm1 ; ...bis fhrende Eins auftaucht
+
+ public MulRound:Parent ; Einsprung fr Division
+MulRound: ld a,(ix+temp+2) ; jetzt Runden auf Bit hinter Mantisse
+ add a,80h
+ jr nc,NoOver ; kein šbertrag
+ inc (ix+temp+3) ; doch, n„chstes Mantissenbyte
+ jr nz,NoOver ; behandeln, jetzt auf Null prfen
+ inc (ix+temp+4) ; da INC kein Carry liefert
+ jr nz,NoOver
+ inc (ix+temp+5)
+ jr nz,NoOver
+ scf ; Eins erzeugen
+ rr (ix+temp+5) ; bei šberlauf Mantisse durch
+ rr (ix+temp+4) ; Rechtsschieben wieder normalisieren
+ rr (ix+temp+3)
+ inc hl ; und Exponent korrigieren
+
+NoOver: cp hl,MaxExpo ; Exponent prfen
+ jr ult,NoUeber ; kein šberlauf
+
+ public MulOver:Parent ; Einsprung fr fdiv
+MulOver: ld hl,MaxExpo ; šberlauf: Exponent=MaxExpo
+ ld (ix+temp+5),h
+ ld (ix+temp+4),h
+ ld (ix+temp+3),h
+ jr DeNorm
+
+NoUeber: xor a,a ; A=0
+ cp a,l ; Exponent ist Null ?
+ jr z,DeNorm ; ja, Ergebnis ist denormalisiert
+ sla (ix+temp+3) ; nein, fhrende=implizite Eins
+ rl (ix+temp+4) ; rausschieben
+ rl (ix+temp+5)
+
+DeNorm: sla c ; Vorzeichen in Carry schieben
+ ld b,l ; Exponent einsetzen
+ ld c,(ix+temp+5)
+ ld d,(ix+temp+4)
+ ld e,(ix+temp+3)
+ rr b ; und Vorzeichen einschieben
+ rr c
+ rr d
+ rr e ; Form: seee eeee efff ffff ... ffff
+
+Result: pop hl ; Register zurck
+ pop af
+
+ unlk ix ; Stackrahmen abbauen
+ retd 2*OpSize ; Operanden abr„umen
+
+ public MulZero:Parent ; Einsprung fr fdiv
+MulZero: xor a,a ; Ergebnis ist Null
+ ld b,a
+ ld c,a
+ ld d,a
+ ld e,a
+ jr Result
+
+Underrun: ld a,l ; Exponent in A
+ neg a ; negieren fr Schleifenz„hler
+ cp a,24 ; totaler Unterlauf ?
+ jr nc,MulZero ; ja, dann ist Ergebnis Null
+ ld b,a ; Mantisse denormalisieren
+Shr: srl (ix+temp+5) ; bis Exponent Null ist
+ rr (ix+temp+4)
+ rr (ix+temp+3)
+ djnz Shr
+ ld l,b ; Exponent in Register L=B=0
+ jp Denorm ; denormalisiertes Ergebnis erzeugen
+
+ endp
+
+;------------------------------------------------------------------------------
+; Division
+
+ proc fdiv
+
+ DefLocal temp,6 ; Platz Tempor„rvariable
+
+ link ix,LocalSize ; 6 Byte Platz auf Stack reservieren
+
+ push af ; Register retten
+ push hl
+
+ ld a,(ix+Op1+3) ; Ergebnisvorzeichen bestimmen
+ xor a,(ix+Op2+3)
+ ld c,a ; Vorzeichen in C Bit 7 merken
+ push bc ; Vorzeichen retten
+
+ ld h,0 ; Exponent 1 laden
+ ld l,(ix+Op1+3)
+ ld a,(ix+Op1+2)
+ res 7,(ix+Op1+2) ; impl. Null vorbesetzen
+ slaa ; Exponent unterstes Bit in Carry
+ rl l ; und in L einschieben
+ jr z,Den1 ; falls Null, dann Op1 denormalisiert
+ set 7,(ix+Op1+2) ; implizite Eins erzeugen
+ dec hl ; Bias kompensieren
+Den1:
+ ld d,0 ; Exponent 2 in DE aufbauen
+ ld e,(ix+Op2+3)
+ ld a,(ix+Op2+2)
+ ld (ix+Op2+3),a ; Verfahren wie oben
+ res 7,(ix+Op2+3)
+ slaa
+ rl e
+ jr z,Den2
+ set 7,(ix+Op2+3)
+ dec de
+Den2:
+ ld bc,(ix+Op2) ; jetzt restliche Bytes kopieren
+ ld (ix+Op2+1),bc
+ xor a,a ; A=0
+ ld (ix+Op2),a ; Form: ffff ... ffff 0000 0000
+ srl (ix+Op2+3)
+ rr (ix+Op2+2)
+ rr (ix+Op2+1)
+ rr (ix+Op2) ; Form: 0fff ... ffff f000 0000
+ jr nz,NoZero1 ; Mantisse 2 auf Null prfen
+ cp a,(ix+Op2+1)
+ jr nz,NoZero1
+ cp a,(ix+Op2+2)
+ jr nz,NoZero1
+ cp a,(ix+Op2+3)
+ jr nz,NoZero1
+ jp MulOver
+
+NoZero1: xor a,a ; Carry-Flag l”schen
+ sbc hl,de ; Exponenten subtrahieren
+ add hl,Bias ; Bias addieren
+ jr p,NoZero ; Exponent negativ ?
+ cp l,-24 ; Exponent kleiner als -24 ?
+ jr nc,NoZero
+ jp MulZero ; ja, dann ist das Ergebnis Null
+NoZero:
+ add hl,25 ; Exponent um 25 erh”hen; jetzt ist er sicher gr”áer als Null
+ xor a,a ; A=0
+ ld bc,(ix+Op1+1) ; Divident in Register kopieren
+ ld d,(ix+Op1)
+ ld e,a ; die untersten Bits sind Null
+ cp a,d ; ist Divident Null ?
+ jr nz,NoZero2
+ cp a,c
+ jr nz,NoZero2
+ cp a,b
+ jr nz,NoZero2
+ pop bc ; Stack bereinigen (Vorzeichen laden)
+ jp MulZero ; und Null als Ergebnis ausgeben
+NoZero2:
+ ld (ix+temp+5),a ; Ergebnis vorbesetzen
+ ld (ix+temp+4),a
+ ld (ix+temp+3),a
+ ld (ix+temp+2),a
+
+NormLoop: bit 6,(ix+Op2+3) ; ist der Divisor normalisiert ?
+ jr nz,Norm ; ja-->
+ inc hl ; nein, Exponent erh”hen
+ sla (ix+Op2) ; Divisor verschieben bis in
+ rl (ix+Op2+1) ; Form 01ff ...
+ rl (ix+Op2+2)
+ rl (ix+Op2+3)
+ jr NormLoop
+Norm: srl b
+ rr c
+ rr d
+ rr e ; Form: 0fff ... ffff f000 0000
+
+ push iy ; Exponent nach IY
+ ld iy,hl
+Loop: ld (ix+Op1+2),bc ; Divident zwischenspeichern
+ ; die Speicherpl„tze von Op1
+ ld (ix+Op1),de ; stehen zur Verfgung, da wir Op1
+ ; in die Register BC-DE kopiert haben
+ ld hl,de ; jetzt Divisor abziehen
+ sub hl,(ix+Op2)
+ ld de,hl
+ ld hl,bc
+ sbc hl,(ix+Op2+2)
+ ld bc,hl
+ jr nc,IsOne ; kein Carry: Divisor paát
+ ld de,(ix+Op1) ; ansonsten zurckkopieren
+ ld bc,(ix+Op1+2) ; Carry bleibt erhalten!
+IsOne: ccf ; Carry-Flag umdrehen
+ rl (ix+temp+2) ; Ergebnis aufbauen
+ rl (ix+temp+3)
+ rl (ix+temp+4)
+ rl (ix+temp+5)
+ sla e ; Divident verschieben
+ rl d
+ rl c
+ rl b
+
+ add iy,-1 ; Exponent erniedrigen
+ jr z,DeNorm ; falls Null, dann denormalisiert
+ bit 0,(ix+temp+5) ; fhrende Eins in Ergebnis-Mantisse ?
+ jr z,Loop ; nein, weiter rechnen
+
+DeNorm: ld hl,iy ; Exponent zurck
+ ld b,(ix+temp+5) ; h”chstes Bit merken
+ ld a,(ix+temp+4)
+ ld (ix+temp+5),a ; Mantisse in Form
+ ld iy,(ix+temp+2) ; ffff ... ffff 0000 0000
+ ld (ix+temp+3),iy
+ pop iy ; IY erst jetzt freigeben
+ rr b ; h”chstes Bit einschieben
+ rr (ix+temp+5)
+ rr (ix+temp+4)
+ rr (ix+temp+3)
+ rr (ix+temp+2)
+
+ pop bc ; Vorzeichen wieder laden
+ xor a,a ; A=0
+ cp a,(ix+temp+5) ; Mantisse ist Null ?
+ jr nz,NoZero3
+ cp a,(ix+temp+4)
+ jr nz,NoZero3
+ cp a,(ix+temp+3)
+ jr nz,NoZero3
+ cp a,(ix+temp+2)
+ jp z,MulZero
+NoZero3:
+ jp MulRound
+
+ endp
+
+;------------------------------------------------------------------------------
+; Wandlung Integer-->Gleitkomma
+
+ proc fitof
+
+ link ix,0 ; Stackrahmen aufbauen
+ push af ; Register retten
+ push hl
+
+ ld bc,(ix+Op2+2) ; Operanden hereinholen
+ ld de,(ix+Op2) ; Reihenfolge: BCDE
+
+ ld hl,bc ; Operand = 0 ?
+ or hl,de
+ jr z,ItofResult ; dann Ergebnis Null
+
+ bit 7,b ; Zahl positiv ?
+ jr z,Positive
+ ld hl,bc ; dann Zahl negieren
+ xor hl,-1
+ ld bc,hl
+ ld hl,de
+ xor hl,-1
+ inc hl
+ or hl,hl
+ ld de,hl
+ jr nz,Positive
+ inc bc
+
+Positive: ld l,Bias+32 ; Exponent vorbesetzen
+Shift: dec l
+ sla e ; Mantisse verschieben, bis fhrende
+ rl d ; Eins auftaucht
+ rl c
+ rl b
+ jr nc,Shift
+ ld e,d ; Exponent einsetzen
+ ld d,c
+ ld c,b
+ ld b,l
+ sla (ix+Op2+3) ; Vorzeichen in Carry
+ rr b ; ins Ergebnis einschieben
+ rr c
+ rr d
+ rr e
+
+ public ItofResult:Parent
+ItofResult: pop hl ; Register zurck
+ pop af
+ unlk ix ; abbauen
+ retd 4 ; Ende
+
+ endp
+
+;------------------------------------------------------------------------------
+; Wandlung Gleitkomma-->Integer
+
+ proc fftoi
+
+ link ix,0 ; Stackrahmen aufbauen
+
+ push af ; Register retten
+ push hl
+
+ ld d,(ix+Op2) ; Operand in Register laden
+ ld bc,(ix+Op2+1) ; Reihenfolge: EBCD
+ ld e,(ix+Op2+3) ; erspart sp„ter Vertauschungen
+
+ ld h,e ; Vorzeichen in H, Bit 7
+ ld a,e ; Exponent in A aufbauen
+ sla b ; LSB aus B holen
+ rla
+ scf ; impl. Eins einschieben
+ rr b
+ sub a,Bias
+ ld l,a ; Exponent nach L kopieren
+ jp m,Zero ; falls keiner Null, Ergebnis Null
+ ld a,30
+ cp a,l ; grӇer 30 ?
+ jr c,Over ; dann šberlauf
+ ld e,0 ; Zahl jetzt in BCDE in der Form
+ inc a ; 1fff ... ffff 0000 0000
+
+Shift: srl b ; jetzt Mantisse verschieben
+ rr c
+ rr d
+ rr e
+ inc l
+ cp a,l ; bis Exponent stimmt
+ jr nz,Shift
+ bit 7,h ; Zahl negativ ?
+ jr z,ItofResult ; nein, fertig
+
+ ld hl,de ; Zahl negieren
+ xor hl,-1
+ ld de,hl
+ ld hl,bc
+ xor hl,-1
+ ld bc,hl
+ inc de
+ jr nz,ItofResult
+ inc bc
+ jr nz,ItofResult
+
+Zero: ld bc,0
+ ld de,bc
+ jp ItofResult ; Ergebnis Null
+
+Over: bit 7,h ; Ergebnis positiv ?
+ jr z,OpPos
+ ld b,80h ; MININT laden
+ xor a,a ; A=0
+ ld c,a
+ ld d,a
+ ld e,a
+ jp ItofResult
+OpPos: ld b,7fh ; MAXINT laden
+ ld a,0ffh
+ ld c,a
+ ld d,a
+ ld e,a
+ jp ItofResult
+
+ endp
+
+;------------------------------------------------------------------------------
+; Multiplikation mit Zweierpotenz (in A)
+
+ proc fmul2
+
+ link ix,0 ; Stackrahmen aufbauen
+
+ push af ; Register retten
+ push hl
+
+ ld de,(ix+Op2) ; Operand 1 in Register laden
+ ld bc,(ix+Op2+2)
+
+ ld h,a ; Operand 2 nach H kopieren
+ ld l,b ; Vorzeichen nach L, Bit 7
+ xor a,a ; A=0
+ cp a,b ; Operand 1 = Null ?
+ jr nz,NoZero
+ cp a,c
+ jr nz,NoZero
+ cp a,d
+ jr nz,NoZero
+ cp a,e
+ jr z,Zero
+
+NoZero: sla e ; Operand 1 verschieben
+ rl d
+ rl c
+ rl b ; Form: eeee eeee ffff ... fff0
+ jr z,Den ; Falls Exponent Null -->denormal
+
+ add a,h ; A=0+H
+ jr m,Div ; Falls Op2<0-->Division
+ add a,b ; A=Summe der Exponenten
+ ld b,a ; zurck nach B
+ jr c,Over ; bei šberlauf-->
+ cp a,MaxExpo ; oder genau MaxExpo
+ jr z,Over
+
+Result: sla l ; Vorzeichen in Carry schieben
+ rr b
+ rr c
+ rr d
+ rr e ; Ergebnis zusammensetzen
+
+Zero: pop hl ; Register zurck
+ pop af
+
+ unlk ix ; Stackrahmen abbauen
+ retd 4 ; Ende
+
+Over: ld b,MaxExpo ; šberlauf: Exponent=MaxExpo
+ xor a,a ; Mantisse=0
+ ld c,a
+ ld d,a
+ ld e,a
+ jr Result
+
+Div: add a,b ; A = Summe der Exponenten
+ ld b,a ; zurck nach B
+ jr z,Div2
+ jr p,Result ; falls >0, Ergebnis abliefern
+Div2: scf ; implizite Eins real machen
+ rr c
+ rr d
+ rr e ; Form: eeee eeee 1fff ... ffff
+
+Denorm: xor a,a ; A = 0
+ cp a,b ; Exponent Null ?
+ jr z,Result ; ja, ergebnis abliefern
+ srl c
+ rr d
+ rr e ; Mantisse denormalisieren
+ jr nz,NoZero2
+ cp a,d
+ jr nz,NoZero2
+ cp a,c
+ jr nz,NoZero2
+ ld b,a ; totaler Unterlauf, Ergebnis = Null
+ jr Zero
+
+NoZero2: inc b ; Exponent erh”hen
+ jr Denorm ; weiter denormalisieren
+
+DDD: add a,b ; Summe der Exponenten bilden
+ ld b,a ; zurck nach B
+ jr Denorm
+
+Den: add a,h ; A=0+H
+ jr m,DDD ; bei Division verzweigen
+NoOver: sla e ; Multiplikation: Eine
+ rl d ; denormalisierte Mantisse
+ rl c ; wird wieder normalisiert
+ jr c,Stop ; bis fhrende Eins rausfliegt
+ dec h ; oder Operand 2 = Null
+ jr nz,NoOver
+ jr Result
+
+Stop: ld a,h ; Summe der Exponenten bilden
+ add a,b
+ ld b,a ; zurck nach B
+ jr Result
+
+ endp
+
+;------------------------------------------------------------------------------
+; Quadratwurzel ziehen
+
+ proc fsqrt
+
+Op equ 4 ; Lage Parameter
+ DefLocal XRoot,4 ; Iterationsvariablen
+ DefLocal m2,4
+ DefLocal xx2,4
+
+ link ix,LocalSize ; Stackrahmen aufbauen
+
+ push af ; Register retten
+ push hl
+ push iy
+
+ bit 7,(ix+Op+3) ; negatives Argument ?
+ jp nz,DomainError ; dann Fehler
+
+ ld hl,(ix+Op+2) ; Exponent isolieren
+ and hl,07f80h
+ jp z,Zero ; keine Behandlung denormaler Zahlen
+
+ ld (ix+Op+3),0 ; Mantisse isolieren
+ and (ix+Op+2),7fh
+ sub hl,7fh*80h ; Bias vom Exponenten entfernen
+ ld bc,hl
+ bit 7,c ; Exponent ungerade ?
+ res 7,c
+ jr z,EvenExp
+ ld hl,(ix+Op) ; ja: Mantisse verdoppeln
+ add hl,hl
+ ld (ix+Op),hl
+ ld hl,(ix+Op+2)
+ adc hl,hl
+ add hl,100h-80h ; impl. Eins dazu
+ ld (ix+Op+2),hl
+EvenExp:
+ sra b ; Exponent/2 mit Vorzeichen
+ rr c
+ ld hl,7fh*80h ; Bias wieder dazu
+ add hl,bc
+ ld iy,hl ; Exponent in IY aufheben
+ ld de,(ix+Op+1) ; x ausrichten (um 7 nach links)
+ ld a,(ix+Op+3) ; oberstes Byte merken
+ ld (ix+Op+2),de ; da wir hier eins zuviel schieben
+ ld d,(ix+Op)
+ ld e,0
+ ld (ix+Op),de
+ srla ; dieses Bit einschieben
+ rr (ix+Op+3)
+ rr (ix+Op+2)
+ rr (ix+Op+1)
+ rr (ix+Op)
+ ld de,0 ; vorbelegen
+ ld (ix+XRoot),de
+ ld (ix+m2),de
+ ld d,40h
+ ld (ix+XRoot+2),de
+ ld d,10h
+ ld (ix+m2+2),de
+Loop10: ld de,(ix+Op) ; xx2 = x
+ ld (ix+xx2),de
+ ld de,(ix+Op+2)
+ ld (ix+xx2+2),de
+Loop11: ld hl,(ix+xx2) ; xx2 -= xroot
+ sub hl,(ix+XRoot)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+XRoot+2)
+ ld (ix+xx2+2),hl
+ srl (ix+XRoot+3) ; xroot /= 2
+ rr (ix+XRoot+2)
+ rr (ix+XRoot+1)
+ rr (ix+XRoot)
+ ld hl,(ix+xx2) ; xx2 -= m2
+ sub hl,(ix+m2)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+m2+2)
+ ld (ix+xx2+2),hl
+ jr m,DontSet1
+ ld hl,(ix+xx2) ; x = xx2
+ ld (ix+Op),hl
+ ld hl,(ix+xx2+2)
+ ld (ix+Op+2),hl
+ ld hl,(ix+XRoot) ; xroot += m2
+ or hl,(ix+m2)
+ ld (ix+XRoot),hl
+ ld hl,(ix+XRoot+2)
+ or hl,(ix+m2+2)
+ ld (ix+XRoot+2),hl
+ ld hl,(ix+m2) ; m2 /= 4
+ ld de,(ix+m2+2)
+ rept 2
+ srl d
+ rr e
+ rr h
+ rr l
+ endm
+ ld (ix+m2),hl
+ ld (ix+m2+2),de
+ or hl,de
+ jr nz,Loop11
+ jr IsSame
+DontSet1: ld hl,(ix+m2) ; m2 /= 4
+ ld de,(ix+m2+2)
+ rept 2
+ srl d
+ rr e
+ rr h
+ rr l
+ endm
+ ld (ix+m2),hl
+ ld (ix+m2+2),de
+ or hl,de
+ jp nz,Loop10 ; 15* abarbeiten
+ ; Bit 22..8
+ ld hl,(ix+Op) ; 17. Iteration separat
+ ld (ix+xx2),hl
+ ld hl,(ix+Op+2)
+ ld (ix+xx2+2),hl
+IsSame: ld hl,(ix+xx2)
+ sub hl,(ix+XRoot)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+XRoot+2)
+ ld (ix+xx2+2),hl
+ ld de,(ix+XRoot+2) ; mitsamt Carry...
+ ld hl,(ix+XRoot)
+ srl d
+ rr e
+ rr h
+ rr l
+ jr nc,NoC1
+ set 7,d
+NoC1: ld (ix+XRoot+2),hl ; auf neues Alignment umstellen
+ ld (ix+XRoot),de
+ decw (ix+xx2) ; Carry von 0-$4000: xx2 -= m2
+ jr nz,NoC2
+ decw (ix+xx2+2)
+NoC2: bit 7,(ix+xx2+3)
+ jr nz,DontSet7
+ or (ix+xx2+3),0c0h ; 0-$4000: x2 -= m2, Teil 2
+ ld hl,(ix+xx2)
+ ld (ix+Op),hl
+ ld hl,(ix+xx2+2)
+ ld (ix+Op+2),hl
+ or (ix+XRoot+1),40h; xroot += m2
+DontSet7: ld hl,(ix+Op) ; x auf neues Alignment umstellen
+ ld de,(ix+Op+2)
+ ld (ix+Op),de
+ ld (ix+Op+2),hl
+ ld hl,1000h ; m2 - obere H„lfte schon 0
+ ld (ix+m2),hl
+Loop20: ld hl,(ix+Op) ; xx2 = x
+ ld (ix+xx2),hl
+ ld hl,(ix+Op+2)
+ ld (ix+xx2+2),hl
+Loop21: ld hl,(ix+xx2) ; xx2 -= xroot
+ sub hl,(ix+XRoot)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+XRoot+2)
+ ld (ix+xx2+2),hl
+ srl (ix+XRoot+3) ; XRoot = XRoot/2
+ rr (ix+XRoot+2)
+ rr (ix+XRoot+1)
+ rr (ix+XRoot)
+ ld hl,(ix+xx2) ; x2 -= m2
+ sub hl,(ix+m2)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+m2+2)
+ ld (ix+xx2+2),hl
+ jr m,DontSet2
+ ld hl,(ix+xx2) ; x = xx2
+ ld (ix+Op),hl
+ ld hl,(ix+xx2+2)
+ ld (ix+Op+2),hl
+ ld hl,(ix+XRoot) ; xroot += m2
+ or hl,(ix+m2)
+ ld (ix+XRoot),hl
+ ld hl,(ix+XRoot+2)
+ or hl,(ix+m2+2)
+ ld (ix+XRoot+2),hl
+ ld hl,(ix+m2) ; m2 /= 4
+ ld de,(ix+m2+2)
+ rept 2
+ srl d
+ rr e
+ rr h
+ rr l
+ endm
+ ld (ix+m2),hl
+ ld (ix+m2+2),de
+ or hl,de
+ jr nz,Loop21
+ jr Finish
+DontSet2: ld hl,(ix+m2) ; m2 /= 4
+ ld de,(ix+m2+2)
+ rept 2
+ srl d
+ rr e
+ rr h
+ rr l
+ endm
+ ld (ix+m2),hl
+ ld (ix+m2+2),de
+ or hl,de
+ jp nz,Loop20 ; 7* abarbeiten
+
+Finish: ld hl,(ix+Op) ; Aufrunden notwendig ?
+ sub hl,(ix+XRoot)
+ ld (ix+Op),hl
+ ld hl,(ix+Op+2)
+ sub hl,(ix+XRoot+2)
+ ld (ix+Op+2),hl
+ jr ule,NoInc
+ incw (ix+XRoot) ; wenn ja, durchfhren
+ jr nz,NoInc
+ incw (ix+XRoot)
+NoInc: res 7,(ix+XRoot+2) ; impl. Eins l”schen
+ ld hl,(ix+XRoot+2) ; Exponent einbauen
+ or hl,iy
+ ld bc,hl ; Ergebnis in BC-DE
+ ld de,(ix+XRoot)
+ jr End
+
+DomainError: ld bc,0ffc0h ; - NAN zuckgeben
+ ld de,0
+ jr End
+
+Zero: ld bc,0 ; Ergebnis 0
+ ld de,bc
+
+End: pop iy ; Register zurck
+ pop hl
+ pop af
+
+ unlk ix ; Stackrahmen abbauen
+ retd 4 ; Ende
+
+ endp
+
+;------------------------------------------------------------------------------
+; Zehnerpotenz bilden
+
+ subproc fPot10
+
+ push ix ; Register retten
+ push iy
+ push hl
+
+ ld bc,(One+2) ; Ausgangspunkt frs Multiplizieren
+ ld de,(One)
+ ld ix,(Ten+2) ; zu benutzende Potenz
+ ld iy,(Ten)
+ or hl,hl ; negative Potenz?
+ jr p,IsPos
+ ld ix,(Tenth+2) ; dann eben mit Zehntel
+ ld iy,(Tenth)
+ xor hl,-1 ; Zweierkomplement
+ inc hl
+IsPos:
+ or hl,hl ; weiter multiplizieren ?
+ jr z,End ; nein, Ende
+ bit 0,l ; Restpotenz ungerade ?
+ jr z,IsEven
+ push bc ; ja: einzeln multiplizieren
+ push de
+ push ix
+ push iy
+ call fmul
+IsEven: srl h
+ rr l
+ push bc ; n„chste Potenz berechnen
+ push de
+ push ix ; durch quadrieren
+ push iy
+ push ix
+ push iy
+ call fmul
+ ld ix,bc
+ ld iy,de
+ pop de
+ pop bc
+ jr IsPos ; weitersuchen
+End:
+ pop hl ; Register zurck
+ pop iy
+ pop ix
+
+ ret ; Ende
+
+ endp
+
+;------------------------------------------------------------------------------
+
+ subproc fOutDec
+
+Op equ 6 ; Adresse Operand
+Format equ 4 ; Formatdeskriptor
+ DefLocal Temp,4 ; 64-Bit-Erweiterung Divident
+
+ link ix,LocalSize
+
+ push af ; Register retten
+ push bc
+ push de
+ push hl
+
+ bit 7,(ix+Op+3) ; negativ ?
+ jr z,IsPos
+ ld (iy),'-' ; ja: vermerken...
+ inc iy
+ ld hl,(ix+Op) ; ...und Zweierkomplement
+ xor hl,-1
+ ld (ix+Op),hl
+ ld hl,(ix+Op+2)
+ xor hl,-1
+ ld (ix+Op+2),hl
+ incw (ix+Op)
+ jr nz,GoOn
+ incw (ix+Op+2)
+ jr GoOn
+IsPos: bit 7,(ix+Format+1) ; Pluszeichen ausgeben ?
+ jr nz,GoOn
+ ld (iy),'+'
+ inc iy
+GoOn: res 7,(ix+Format+1) ; Plusflag l”schen
+ ld de,0 ; Nullflag & Z„hler l”schen
+
+InLoop: ld hl,0 ; Division vorbereiten
+ ld (ix+Temp),hl ; dazu auf 64 Bit erweitern
+ ld (ix+Temp+2),hl
+ ld b,32 ; 32-Bit-Division
+DivLoop: sll (ix+Op) ; eins weiterschieben
+ rl (ix+Op+1)
+ rl (ix+Op+2)
+ rl (ix+Op+3)
+ rl (ix+Temp)
+ rl (ix+Temp+1)
+ rl (ix+Temp+2)
+ rl (ix+Temp+3)
+ srl (ix+Op) ; fr nachher
+ ld hl,(ix+Temp) ; probeweise abziehen
+ sub hl,10
+ ld (ix+Temp),hl
+ ld hl,(ix+Temp+2)
+ sbc hl,0
+ ld (ix+Temp+2),hl
+ jr nc,DivOK ; paát es ?
+ ld hl,(ix+Temp) ; nein, zurcknehmen
+ add hl,10
+ ld (ix+Temp),hl
+ ld hl,(ix+Temp+2)
+ adc hl,0
+ ld (ix+Temp+2),hl
+ scf ; ins Ergebnis 0 einschieben
+DivOK: ccf ; neues Ergebnisbit
+ rl (ix+Op) ; von unten einschieben
+ djnz DivLoop
+
+ ld a,(ix+Temp) ; ASCII-Offset addieren
+ add a,'0'
+ bit 0,d ; schon im Nullbereich ?
+ jr z,NormVal
+ ld a,(ix+Format) ; ja, dann gewnschtes Leerzeichen
+NormVal: push af ; auf LIFO legen
+ inc e ; ein Zeichen mehr
+ ld a,(ix+Op) ; Quotient Null ?
+ or a,(ix+Op+1)
+ or a,(ix+Op+2)
+ or a,(ix+Op+3)
+ ld d,0 ; Annahme: nicht Null
+ jr nz,InLoop ; falls <>0, auf jeden Fall weiter
+ ld d,0ffh ; Flag auf True setzen
+ ld a,e ; ansonsten nur weiter, falls minimale
+ cp a,(ix+Format+1) ; Zahl noch nicht erreicht
+ jr ult,InLoop
+
+ ld b,e ; jetzt Zeichen ausgeben
+OutLoop: pop af
+ ld (iy),a
+ inc iy
+ djnz OutLoop
+
+ pop hl ; Register zurck
+ pop de
+ pop bc
+ pop af
+
+ unlk ix
+ retd 6
+
+ endp
+
+;------------------------------------------------------------------------------
+; Wandlung Float-->ASCII
+
+ proc fftoa
+
+Op equ 8 ; Lage Eingabe auf Stack
+Format equ 6 ; Lage Formatdeskriptor auf Stack
+Buffer equ 4 ; Pufferadresse
+ DefLocal Copy,4 ; Tempor„rkopie der Zahl
+ DefLocal ExpSave,2 ; berechneter Exponent
+
+ link ix,LocalSize ; Platz fr Exponenten/Kopie der Zahl
+
+ push af ; Register retten
+ push de
+ push iy
+ push hl
+
+ ld iy,(ix+Buffer) ; Pufferadresse holen
+
+ ld hl,(ix+Op) ; Zahl kopieren
+ ld (ix+Copy),hl
+ ld hl,(ix+Op+2)
+ res 7,h ; dabei Vorzeichen l”schen
+ ld (ix+Copy+2),hl
+
+ ld a,'+' ; Annahme positiv
+ sll (ix+Op) ; Vorzeichen herausschieben
+ rl (ix+Op+1) ; und in Carry bringen
+ rl (ix+Op+2)
+ rl (ix+Op+3)
+ jr c,IsNeg ; Minuszeichen immer erforderlich
+ bit 0,(ix+Format+1) ; Pluszeichen dagegen optional
+ jr nz,NoMantSgn
+ jr WrMantSgn
+IsNeg: ld a,'-' ; negative Zahl
+WrMantSgn: ld (iy),a ; Vorzeichen ablegen
+ inc iy
+NoMantSgn:
+ ld l,(ix+Op+3) ; Exponent herausholen...
+ ld h,0 ; ...auf 16 Bit erweitern...
+ ld bc,(ix+Op+1) ; ...und in Quelle l”schen
+ ld (ix+Op+2),bc
+ ld b,(ix+Op)
+ ld c,0
+ ld (ix+Op),bc
+
+ cp hl,MaxExpo ; Sonderwerte ?
+ jp z,SpecialVals ; ja-->
+
+ or hl,hl ; Zahl denormal ?
+ jr nz,IsNormal ; nein, normal weiter
+ ld a,(ix+Op+3) ; falls Mantisse Null,
+ or a,(ix+Op+2) ; nicht normalisieren
+ or a,(ix+Op+1)
+ jr z,IsNull
+Normalize: sll (ix+Op+1) ; ansonsten schieben, bis fhrende
+ rl (ix+Op+2) ; Eins da
+ rl (ix+Op+3)
+ jr c,IsNormal
+ dec hl
+ jr Normalize
+IsNormal: sub hl,Bias ; Bias abziehen
+IsNull:
+ ld b,h ; Zweierexponenten in Float wandeln
+ ld c,h
+ push bc
+ push hl
+ call fitof
+ push bc ; in Dezimalexponenten wandeln
+ push de
+ cpsh bc,Ld10
+ call fdiv
+ bit 7,b ; Zahl negativ ?
+ jr z,NoCorr
+ push bc ; dann noch eins abziehen wegen
+ push de ; unterer Gauáklammer
+ cpsh bc,One
+ call fsub
+NoCorr: push bc ; den Ausflug in Float beenden
+ push de
+ call fftoi
+ ld (ix+ExpSave),de ; Exponenten retten
+
+ ld bc,(ix+Copy+2) ; Originalzahl
+ push bc
+ ld bc,(ix+Copy)
+ push bc
+ ld hl,de ; durch die Zehnerpotenz
+ call fPot10 ; des Exponenten
+ push bc
+ push de
+ call fdiv ; teilen
+Again: ld (ix+Copy),de ; Ergebnis zwischen 1...9,999 retten
+ ld (ix+Copy+2),bc
+ push bc ; Vorkommastelle berechnen
+ push de
+ call fftoi
+ cp e,10 ; doch etwas drber ?
+ jr ult,NoRoundErr
+ ld bc,(ix+Copy+2) ; dann nocheinmal zehnteln
+ push bc
+ ld bc,(ix+Copy)
+ push bc
+ cpsh bc,Tenth
+ call fmul
+ incw (ix+ExpSave)
+ jr Again
+NoRoundErr: add e,'0' ; Vorkommastelle nach ASCII
+ ld (iy),e ; ablegen
+ inc iy
+ sub e,'0' ; wieder rckg„ngig machen
+ cp (ix+Format),0 ; gar keine Nachkommastellen ?
+ jr eq,NoComma
+ ld (iy),'.' ; Dezimalpunkt ausgeben
+ inc iy
+ push bc ; Vorkomma nach Float wandeln
+ push de
+ call fitof
+ push bc
+ push de
+ cpsh bc,ix+Copy ; von alter Zahl abziehen
+ call fsub
+ xor b,80h ; war verkehrtherum
+ push bc ; zum Skalieren auf Stack
+ push de
+ ld l,(ix+Format) ; passende Skalierungskonstante ausrechnen
+ ld h,0
+ call fPot10
+ push bc
+ push de
+ call fmul ; hochskalieren
+ push bc ; Rundung
+ push de
+ cpsh bc,Half
+ call fadd
+ push bc ; Stellen nach Integer
+ push de
+ call fftoi
+ push bc ; entspr. ausgeben
+ push de
+ ld b,(ix+Format) ; Format fr fOutDec aufbauen
+ set 7,b ; kein Pluszeichen
+ ld c,'0' ; Fllzeichen Nullen
+ push bc
+ call fOutDec
+ bit 5,(ix+Format+1) ; Nullen am Ende abr„umen ?
+ jr nz,CleanZeros
+NoComma:
+ ld a,(ix+Format+1) ; falls Minimalstellenzahl Exponent=0
+ and a,00011100b ; und Exponent=0, vergessen
+ or a,(ix+ExpSave)
+ or a,(ix+ExpSave+1)
+ jr z,End
+
+ ld (iy),'E' ; Exponenten ausgeben
+ inc iy
+ ld hl,(ix+ExpSave)
+ ld b,h
+ ld c,h
+ push bc
+ push hl
+ ld c,'0' ; evtl. vornullen
+ ld b,(ix+Format+1)
+ rrc b ; Bit 1-->Bit 7
+ rrc b
+ and b,87h
+ push bc
+ call fOutDec
+
+End: ld (iy),0 ; NUL-Zeichen als Terminierer
+ ld de,iy ; Endezeiger nach DE
+ pop hl ; Register zurck
+ pop iy
+ ex de,hl ; zur Subtraktion tauschen
+ sub hl,de ; = Zahl geschriebener Zeichen
+ ex de,hl ; HL wieder original
+ ld bc,de ; Ergebnis nach BC
+ pop de
+ pop af
+
+ unlk ix ; Stackrahmen abbauen
+ retd 8 ; Ende
+
+SpecialVals: ld a,(ix+Op+3) ; Mantisse Null ?
+ or a,(ix+Op+2)
+ or a,(ix+Op+1)
+ jr nz,IsNAN
+ ld (iy),'I' ; ja: Unendlichkeit
+ ld (iy+1),'N'
+ ld (iy+2),'F'
+ add iy,3
+ jr End
+IsNAN: ld (iy),'N' ; nein: NAN
+ ld (iy+1),'A'
+ ld (iy+2),'N'
+ add iy,3
+ jr End
+
+CleanZeros: cp (iy-1),'0' ; Null am Ende ?
+ jr nz,CleanNoZero ; nein, Ende
+ dec iy ; ja: Z„hler runter, so daá ber-
+ jr CleanZeros ; schrieben wird und neuer Versuch
+CleanNoZero: cp (iy-1),'.' ; evtl. Komma entfernbar ?
+ jr nz,Ready ; nein-->
+ dec iy ; ja: noch ein Zeichen weniger
+Ready: jrl NoComma
+
+ endp
+
+;------------------------------------------------------------------------------
+; Wandlung ASCII-->Float
+
+ proc fatof
+
+SrcAddr equ 4 ; Lage Parameter auf Stack
+ DefLocal Flags,2 ; Steuerflags
+ DefLocal Exp,2 ; Speicher Exponent
+ DefLocal Mant,4 ; Speicher fr Mantissenzwischenwert
+ DefLocal Factor,4 ; Speicher fr Zehnerpotenz
+
+ link ix,LocalSize ; Stackrahmen aufbauen
+
+ push af ; Register retten
+ push hl
+ push iy
+
+ ld iy,(ix+SrcAddr) ; Zeigeradresse laden
+ ld (ix+Flags),01h ; Phase 1 (Mantisse), noch kein Vorzeichen
+ ld (ix+Flags+1),0
+ ld bc,(Ten) ; in der Mantisse mit 10 hochmultiplizieren
+ ld (ix+Factor),bc
+ ld bc,(Ten+2)
+ ld (ix+Factor+2),bc
+ ld bc,0 ; Exponent mit 0 vorbelegen
+ ld (ix+Exp),bc
+ ld (ix+Mant),bc ; Mantisse auch
+ ld (ix+Mant+2),bc
+
+ReadLoop: ld a,(iy) ; ein neues Zeichen holen
+ inc iy
+
+ cp a,0 ; Endezeichen ?
+ jp eq,Combine ; ja, zusammenbauen
+
+ cp a,' ' ; Leerzeichen ignorieren
+ jr eq,ReadLoop
+
+ cp a,'+' ; Pluszeichen gnadenhalber zulassen
+ jr ne,NoPlus ; ist aber nur ein Dummy
+ bit 0,(ix+Flags+1) ; schon ein Vorzeichen dagewesen ?
+ jp nz,Error ; dann Fehler
+ set 0,(ix+Flags+1) ; ansonsten einfach setzen
+ jr ReadLoop
+NoPlus:
+ cp a,'-' ; Minuszeichen bewirkt schon eher etwas
+ jr ne,NoMinus
+ bit 0,(ix+Flags+1) ; darf auch nur einmal auftreten
+ jp nz,Error
+ set 0,(ix+Flags+1)
+ cp (ix+Flags),1 ; je nach Phase anderes Flag setzen
+ jr ne,MinPhase3
+ set 1,(ix+Flags+1) ; bei Mantisse Bit 1...
+ jr ReadLoop
+MinPhase3: set 2,(ix+Flags+1) ; ...bei Exponent Bit 2
+ jr ReadLoop
+NoMinus:
+ cp a,'.' ; Umschaltung Phase 2 (Nachkomma) ?
+ jr ne,NoPoint
+ cp (ix+Flags),1 ; bish. Phase muá Eins sein
+ jp ne,Error
+ ld (ix+Flags),2 ; neue Phase eintragen
+ set 0,(ix+Flags+1) ; Nachkomma darf kein Vorzeichen haben
+ ld bc,(Tenth) ; im Nachkomma durch 10 teilen
+ ld (ix+Factor),bc
+ ld bc,(Tenth+2)
+ ld (ix+Factor+2),bc
+ jr ReadLoop
+NoPoint:
+ cp a,'e' ; kleines & groáes E zulassen
+ jr eq,IsE
+ cp a,'E'
+ jr ne,NoE
+IsE: cp (ix+Flags),3 ; vorh. Phase muá 1 oder 2 sein
+ jp eq,Error
+ ld (ix+Flags),3 ; vermerken
+ res 0,(ix+Flags+1) ; Vorzeichen wieder zulassen
+ jr ReadLoop
+NoE:
+ sub a,'0' ; jetzt nur noch 0..9 zugelassen
+ jp c,Error
+ cp a,9
+ jp ugt,Error
+ set 0,(ix+Flags+1) ; nach Ziffern keine Vorzeichen mehr zulassen
+
+ cp (ix+Flags),1 ; Phase 1 (Mantisse) :
+ jr ne,NoPhase1
+ cpsh bc,ix+Mant ; bish. Mantisse * 10
+ cpsh bc,ix+Factor
+ call fmul
+ push bc ; Ziffer dazuaddieren
+ push de
+ ld e,a
+ ld d,0
+ ld bc,0
+ push bc
+ push de
+ call fitof
+ push bc
+ push de
+ call fadd
+ ld (ix+Mant),de ; Mantisse zurcklegen
+ ld (ix+Mant+2),bc
+ jrl ReadLoop
+NoPhase1:
+ cp (ix+Flags),2 ; Phase 2 (Nachkomma) :
+ jr nz,NoPhase2
+ ld e,a ; Stelle nach Float
+ ld d,0
+ ld bc,0
+ push bc
+ push de
+ call fitof
+ push bc ; mit Zehnerpotenz skalieren
+ push de
+ cpsh bc,ix+Factor
+ call fmul
+ push bc ; zur Mantisse addieren
+ push de
+ cpsh bc,ix+Mant
+ call fadd
+ ld (ix+Mant),de ; Mantisse zurcklegen
+ ld (ix+Mant+2),bc
+ cpsh bc,ix+Factor ; Faktor * 1/10
+ cpsh bc,Tenth
+ call fmul
+ ld (ix+Factor),de
+ ld (ix+Factor+2),bc
+ jrl ReadLoop
+NoPhase2:
+ ld hl,(ix+Exp)
+ mul hl,10 ; Exponent heraufmultiplizieren
+ add a,l
+ ld l,a
+ ld a,0
+ adc h,0
+ cp hl,45 ; Minimum ist 1E-45
+ jr ugt,Error
+ ld (ix+Exp),hl
+ jrl ReadLoop
+
+Combine: ld hl,(ix+Exp)
+ bit 2,(ix+Flags+1) ; Exponent negativ ?
+ jr z,ExpPos
+ xor hl,-1
+ inc hl
+ExpPos: call fPot10 ; Zehnerpotenz des Exponenten bilden
+ push bc
+ push de
+ cpsh bc,ix+Mant ; mit Mantisse kombinieren
+ call fmul
+ bit 1,(ix+Flags+1) ; Mantisse negativ ?
+ jr z,ManPos
+ set 7,b
+ManPos: rcf ; Ende ohne Fehler
+
+End: pop iy ; Register zurck
+ pop hl
+ pop af
+
+ unlk ix ; Rahmen abbauen
+ retd 2 ; Ende
+
+Error: ld hl,iy ; rel. Zeichenposition ermitteln
+ sub hl,(ix+SrcAddr)
+ ld bc,hl
+ scf ; Ende mit Fehler
+ jr End
+
+ endp
+
+;------------------------------------------------------------------------------
+; gemeinsames Ende
+
+ endsection
+
diff --git a/tests/t_fl90/macros.inc b/tests/t_fl90/macros.inc
new file mode 100644
index 0000000..d949ddc
--- /dev/null
+++ b/tests/t_fl90/macros.inc
@@ -0,0 +1,57 @@
+; MACROS.INC
+;******************************************************************************
+;* überall gebrauchte Makros *
+;* *
+;* Alfred Arnold, Oktober 1993 *
+;******************************************************************************
+
+proc macro name,{NoExpand} ; Prozedureintritt
+ section name
+ forward LocalSize ; lokal reservierter Speicher auf Stack
+LocalSize eval 0
+ public name
+name label $
+ endm
+
+subproc macro name,{NoExpand} ; Prozedureintritt für private Routine
+ section name
+ forward LocalSize ; lokal reservierter Speicher auf Stack
+LocalSize eval 0
+ public name:Parent
+name label $
+ endm
+
+endp macro name,{NoExpand} ; Prozeduraustritt
+LocalSize eval 0-LocalSize ; damit man's im Listing lesen kann
+ endsection name
+ endm
+
+link macro reg,count,{NoExpand} ; Stack-Rahmen einrichten
+ push reg ; alten Basepointer retten
+ ld reg,sp ; neuen aufbauen
+ if count<>0
+ add sp,count ; Platz auf Stack reservieren
+ endif
+ endm
+
+unlk macro reg,{NoExpand} ; Stack-Rahmen abbauen
+ ld sp,reg ; Speicherreservierung zurücknehmen
+ pop reg ; alten Basepointer zurück
+ endm
+
+retd macro dist,{NoExpand} ; Return and Deallocate
+ if dist<>0
+ push hl ; Arbeitsregister retten
+ ld hl,(sp+2) ; Rücksprungadresse umkopieren
+ ld (sp+2+dist),hl
+ ld hl,(sp) ; Arbeitsregister zurück
+ add sp,2+dist ; Stack aufräumen
+ endif
+ ret
+ endm
+
+DefLocal macro Name,Size,{NoExpand} ; eine lokale Variable definieren
+LocalSize eval LocalSize-Size ; zählt lok. reservierten Speicher
+Name equ LocalSize ; liegt an neuem unteren Ende des Stackrahmens
+ endm
+
diff --git a/tests/t_fl90/mon.inc b/tests/t_fl90/mon.inc
new file mode 100644
index 0000000..46e08d3
--- /dev/null
+++ b/tests/t_fl90/mon.inc
@@ -0,0 +1,11 @@
+MRET EQU 0080H ; RETURN TO MONITOR
+CONIN EQU 0083H ; CONSOLE INPUT
+COSTAT EQU 0086H ; CONSOLE STATUS
+CONOUT EQU 0089H ; CONSOLE OUTPUT
+TXTAUS EQU 008CH ; TEXT-OUTPUT
+PSTR EQU 008FH ; STRING OUTPUT
+A_ASC EQU 0092H ; CONVERT CONTENT OF A TO ASCII
+HL_ASC EQU 0095H ; CONVERT CONTENT OF HL TO ASCII
+BLAUS EQU 0098H ; BLANK OUTPUT
+GETZEIL EQU 009BH ; READ LINE
+
diff --git a/tests/t_fl90/t_fl90.asm b/tests/t_fl90/t_fl90.asm
new file mode 100644
index 0000000..3e53195
--- /dev/null
+++ b/tests/t_fl90/t_fl90.asm
@@ -0,0 +1,179 @@
+; FTEST.ASM
+;******************************************************************************
+;* Testet Gleitkommabibliothek für TLCS90 *
+;* *
+;* Hardware: TDB-TMP90 *
+;* Software: AS 1.39p5 oder höher *
+;* Includes MACROS.INC, FLOAT.INC, CPU_TIME.INC *
+;* *
+;* Übersetzen mit AS ftest oder beiliegendem Makefile *
+;* *
+;******************************************************************************
+
+ cpu 90c141
+
+ org 8500h ; Startadresse User-RAM
+
+;------------------------------------------------------------------------------
+
+CR equ 13
+LF equ 10
+Format_Tab equ 0000100000000110b ; fftoa-Format für tab. Ausgabe
+Format_Min equ 0010001100000101b ; fftoa-Format für minimale Länge
+; ^<+>^^<--+--->
+; | | || |
+; | | || +------ Maximalzahl Nachkommastellen
+; | | |+---------- Mantissenpluszeichen unterdrücken
+; | | +----------- Exponentenpluszeichen unterdrücken
+; | +------------- Minimalstellenzahl Exponent
+; +--------------- anhängende Nullen in Mantisse löschen
+Format equ Format_Tab ; gewähltes fftoa-Format
+
+;------------------------------------------------------------------------------
+; Vorgaben
+
+ include stddef90.inc ; Registeradressen
+ include macros.inc ; für Unterroutinen benötigte Makros
+ include mon.inc ; Einsprungadressen TDBTMP90-Monitor
+
+ section MainProg
+
+;------------------------------------------------------------------------------
+; Makros zur Schreiberleichterung
+
+pushop macro adr,{NoExpand} ; einen Operanden auf den Stack legen
+ ld hl,(adr+2)
+ push hl
+ ld hl,(adr)
+ push hl
+ endm
+
+storeop macro {NoExpand} ; Ergebnis in Array ablegen
+ ld (iy),de
+ ld (iy+2),bc
+ add iy,4
+ endm
+
+OneOp macro Msg,Operation,Op1,Op2,{Expand} ; Aufruf, Ausgabe und
+ call PSTR ; Zeitmessung
+ db Msg,0
+ call StartTimer
+ if "OP1"<>""
+ pushop Op1
+ endif
+ if "OP2"<>""
+ pushop Op2
+ endif
+ call Operation
+ storeop
+ call StopTimer
+ if (("OPERATION"<>"FNOP") && ("OPERATION"<>"FFTOI"))
+ call PSTR
+ db ", Ergebnis ",0
+ push bc
+ push de
+ ld hl,Format
+ push hl
+ ld hl,CharBuffer
+ push hl
+ call fftoa
+ call TXTAUS
+ endif
+ call PSTR
+ db CR,LF,0
+ endm
+
+;------------------------------------------------------------------------------
+; Hauptroutine
+
+ proc Main
+
+ ld sp,Stack ; Stack reservieren
+ ld iy,Erg ; Zeiger auf Ergebnisfeld
+ call InitTimer ; Zeitmessung vorinitialisieren
+
+ OneOp "Ladeoverhead : ",fnop,Eins,Eins
+ OneOp "Addition 2+Pi : ",fadd,Zwei,Pi
+ OneOp "Addition 100000+2 : ",fadd,Thou,Zwei
+ OneOp "Addition 0+1 : ",fadd,Null,Eins
+ OneOp "Subtraktion Pi-2 : ",fsub,Pi,Zwei
+ OneOp "Subtraktion 100000-1 : ",fsub,Thou,Eins
+ OneOp "Multiplikation 2*Pi : ",fmul,Zwei,Pi
+ OneOp "Division 1/Pi : ",fdiv,Eins,Pi
+ OneOp "Wurzel aus 2 : ",fsqrt,Zwei,
+ OneOp "Wurzel aus 10000 : ",fsqrt,Thou,
+ OneOp "Wurzel aus -1 : ",fsqrt,MinEins,
+ OneOp "Wandlung 1-->Float : ",fitof,IntEins,
+ OneOp "Wandlung 1E5-->Float : ",fitof,IntThou,
+ OneOp "Wandlung 1-->Int : ",fftoi,Eins,
+ OneOp "Wandlung 1E5-->Int : ",fftoi,Thou,
+ ld a,10
+ OneOp "Pi*2^10 : ",fmul2,Pi,
+ ld a,-10
+ OneOp "Pi*2^(-10) : ",fmul2,Pi,
+
+ call PSTR
+ db "Eingabe: ",0
+ ld hl,InpBuffer
+ call TXTAUS
+ ld hl,InpBuffer
+ push hl
+ call fatof
+ storeop
+ call PSTR
+ db ", Ergebnis: ",0
+ push bc
+ push de
+ ld hl,Format
+ push hl
+ ld hl,CharBuffer
+ push hl
+ call fftoa
+ call TXTAUS
+ call PSTR
+ db 13,10,0
+
+ jp MRET
+
+ endp
+
+ proc fnop ; Dummyroutine fr Overheadmessung
+
+ link ix,0
+ unlk ix
+
+ retd 8
+
+ endp
+
+CharBuffer: db 30 dup (?) ; Puffer fr fftoa
+InpBuffer: db "-123.456E-7",0 ; Puffer fr fatof
+
+ align 4
+Eins: dd 1.0 ; ben”tigte Konstanten
+MinEins: dd -1.0
+Zwei: dd 2.0
+Pi: dd 40490fdbh ; um Vergleichsfehler durch Rundung zu
+ ; vermeiden
+Zehn: dd 10.0
+Null: dd 0.0
+Thou: dd 100000.0
+IntEins: dd 1
+IntThou: dd 100000
+Erg: dd 40 dup (?) ; Ergebnisfeld
+
+ align 2 ; Platz fr Stack
+ db 300 dup (?)
+Stack:
+ endsection
+
+;------------------------------------------------------------------------------
+; ben”tigte Module
+
+ include cpu_time.inc ; Zeitmessung
+ include float.inc ; Gleitkommabibliothek
+
+;------------------------------------------------------------------------------
+
+ end Main
+
diff --git a/tests/t_fl90/t_fl90.doc b/tests/t_fl90/t_fl90.doc
new file mode 100644
index 0000000..668986f
--- /dev/null
+++ b/tests/t_fl90/t_fl90.doc
@@ -0,0 +1,6 @@
++------------------------ Test Application FL90 -----------------------------+
+| |
+| This is an IEEE single precision floating point library for the Toshiba |
+| TLCS-90 microcontroller, embedded into a small test program. |
+| |
++-----------------------------------------------------------------------------+
diff --git a/tests/t_fl90/t_fl90.ori b/tests/t_fl90/t_fl90.ori
new file mode 100644
index 0000000..4aff532
--- /dev/null
+++ b/tests/t_fl90/t_fl90.ori
Binary files differ
diff --git a/tests/t_fl900/asflags b/tests/t_fl900/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_fl900/asflags
diff --git a/tests/t_fl900/conout.inc b/tests/t_fl900/conout.inc
new file mode 100644
index 0000000..6483884
--- /dev/null
+++ b/tests/t_fl900/conout.inc
@@ -0,0 +1,154 @@
+; CONOUT.INC
+;******************************************************************************
+;* Konsolenausgabe fr Micro-ICE TLCS900 *
+;* *
+;* Routinen CONOUT, PSTR, A_ASC von Oliver Sellke *
+;* Routine WriteDec von Alfred Arnold, Oktober 1993 *
+;* 20.11.1993 StrTerm C-konform auf 00h ge„ndert *
+;* TXTAUS hinzugefgt *
+;* *
+;* Routine Funktion Eingabe Stack *
+;* *
+;* CONOUT Zeichen ausgeben A 1..3 Byte *
+;* TXTAUS String ausgeben (XHL) *
+;* PSTR String ausgeben hinter CALL+StrTerm als Ende 6 Byte *
+;* A_ASC Byte hex ausgeben A 2 Byte *
+;* WriteDec Wort dez ausgeben WA 6 Byte *
+;* *
+;* - Da die Routinen lokale Labels verwenden, ist mindestens AS 1.39 erfor- *
+;* derlich *
+;* - Der Prozessor muá sich im Maximum-Modus befinden *
+;* - Symbol SIODelay setzen, falls langsames Terminal vorhanden *
+;* - MACROS.INC muá vorher eingebunden werden *
+;******************************************************************************
+
+;------------------------------------------------------------------------------
+; gemeinsamer Anfang, Definitionen
+
+ section ConOut
+
+ public StrTerm
+StrTerm equ 0
+
+SC0BUF EQU 050H
+INTES0 EQU 077H
+
+;******************************************************************************
+; (7 bit ASCII) Ausgabe ber SIO-Kanal 0
+
+ proc CONOUT
+ PUSH A ;sichern
+ RES 7,A ;MSB ausblenden (nur ASCII!)
+CONOUT1: BIT 7,(INTES0) ;ist der Buffer frei?
+ JR Z,CONOUT1 ;Wenn nicht, dann weiter prfen
+ LD (INTES0),0Dh ;Flag rcksetzen
+ LD (SC0BUF),A ;Zeichen in Transmit-Buffer
+ ifdef SIODelay
+ PUSH HL ;sichern
+ LD HL,80H ;Verz”gerungszeit laden
+WAIT: DEC 1,HL ;Z„hler - 1
+ CP HL,0 ;Ist Z„hler = 0?
+ JR NZ,WAIT ;Wenn nicht, dann weiter DEC
+ POP HL ;restaurieren
+ endif
+ POP A ;restaurieren
+ RET ;Zurck zum Aufruf
+ endp
+
+;******************************************************************************
+; ASCIIZ-String ab (XHL) ausgeben:
+
+ proc TXTAUS
+ push xhl ; Register retten
+ push a
+Schl: ld a,(xhl+) ; ein Zeichen holen
+ cp a,StrTerm ; Endemarkierung ?
+ jr eq,Ende
+ call CONOUT ; nein, ausgeben
+ jr Schl ; Go on...
+Ende: pop a ; Register zurck
+ pop xhl
+ ret
+ endp
+
+;******************************************************************************
+; String der dem Aufruf folgt bis zur Endemarkierung ausgeben
+; Siehe auch TXTAUS:
+
+ proc PSTR
+ PUSH XHL ;sichern
+ LD XHL,(XSP+4) ;Datenadresse lesen
+ PUSH F ;sichern
+ PUSH A ;dito
+PSTR1: LD A,(XHL) ;Zeichen holen
+ INC 1,C ;Zeichenz„hler + 1
+ INC 1,XHL ;Zeichenzeiger + 1
+ CP A,StrTerm ;Endemarkierung erwischt?
+ JR Z,PSTR2 ;Wenn ja, dann Ende
+ AND A,A ;Null-Zeichen erwischt?
+ JR Z,PSTR1 ;Wenn ja, dann nicht ausgeben
+ CALL CONOUT ;Zeichen ausgeben
+ AND A,A ;War das 8. Bit gesetzt?
+ JR P,PSTR1 ;Wenn nicht, dann n„chstes Zeichen
+PSTR2: POP A ;restaurieren
+ POP F ;dito
+ LD (XSP+4),XHL ;Rcksprungadresse restaurieren
+ POP XHL ;Rcksprungadresse abspeichern
+ RET ;Zurck zum Aufruf
+ endp
+
+;******************************************************************************
+; "A" als ASCII Text ausgeben
+
+ proc A_ASC
+ PUSH F ;Sichern
+ PUSH A ;dito
+ RR 4,A ;high nibble an die richtige
+ CALL A_ASC00 ;Stelle und ausgeben
+ POP A ;restaurieren bzw.
+ POP F ;low nibble laden
+A_ASC00: AND A,00FH ;low nibble maskieren
+ CP A,00AH ;eine Zahl ?
+ JR C,A_ASC01 ;ja
+ ADD A,007H ;Offset A-F
+A_ASC01: ADD A,'0' ;Offset ASCII
+ JP CONOUT ;Ausgabe und Ende UP
+ endp
+
+;******************************************************************************
+; Zahl in WA dezimal ausgeben
+; C = minimale Stellenzahl
+; B = Fllzeichen (z.B. ' ', '0')
+
+ proc WriteDec
+ push xwa ; Register retten
+ push de
+
+ sub de,de ; E z„hlt echte Stellenzahl, D=1 falls Null
+InLoop: extz xwa ; fr Division vorbereiten
+ div xwa,10 ; letzte Stelle ausmaskieren
+ add qa,'0' ; ASCII-Offset
+ cp d,1 ; schon im Nullbereich ?
+ jr ne,NormVal
+ ld qa,b ; ja, dann gewnschtes Leerzeichen
+NormVal: push qa ; ein Zeichen mehr
+ inc e
+ or wa,wa ; schon Null ?
+ scc z,d
+ jr nz,InLoop ; wenn nicht Null, auf jeden Fall weiter
+ cp e,c ; noch nicht genug Zeichen ?
+ jr ult,InLoop ; dann auch weiter
+
+OutLoop: pop a ; umgekehrt ausgeben
+ call ConOut
+ djnz e,OutLoop
+
+ pop de
+ pop xwa
+ ret
+ endp
+
+;******************************************************************************
+; Modulende
+
+ endsection
diff --git a/tests/t_fl900/cpu_time.inc b/tests/t_fl900/cpu_time.inc
new file mode 100644
index 0000000..1240be2
--- /dev/null
+++ b/tests/t_fl900/cpu_time.inc
@@ -0,0 +1,240 @@
+; CPU_TIME.INC
+;*************************************************************************
+;* *
+;* Author...: Oli(ver Sellke) D-65199 Wiesbaden *
+;* auf AS umgestellt von Alfred Arnold, Oktober 1993 *
+;* die Low-Level-Ausgaberoutinen sind nach CONOUT.INC verlagert *
+;* Date.....: 14 Okt 1993 Version..: 1.0 *
+;* Target...: TLCS900-Family (TOSHIBA) Compiler.: AS V1.39p1 *
+;* Project..: General Purpose / e.g. TMP96C141F / Watt Ihr Volt *
+;* *
+;* Function.: Mit dieser Routine kann man die Ausfhrungszeit die *
+;* ein Programm(teil) ben”tigt ermitteln. *
+;* Die Zeit wird mit Timer4 und CAP1 davon gemessen, d.h. *
+;* dieser darf innerhalb des gemessenen Programm(teil)s *
+;* nicht (!) benutzt werden. *
+;* !!! Alle Zeiten beziehen sich auf einen 14,7456MHz Quarz!! *
+;* Zur Ausgabe des Messwertes werden Monitor-Routinen benutzt,*
+;* deshalb kann es auch nur unter Anwendung von diesem zur *
+;* Ausfhrung gebracht werden. *
+;* Wenn ein Programm(teil) getestet wird, dessen Ausfhrungs- *
+;* zeit unbekannt ist, sollte man die 8,681æs Aufl”sung w„hlen*
+;* um einen Overrun des Counters zu verhindern. Wenn der Wert *
+;* entsprechend klein ist ( <0FFF ), kann man die 0,543æs Auf-*
+;* l”sung w„hlen um genauere Werte zu bekommen. *
+;* Auáerdem ist die Ermittlung der 16 gr”áten und 16 kleinsten*
+;* Werte die bei mehreren Durchl„ufen erzielt wurden m”glich! *
+;* Man kann so einige 1000 Durchl„ufe fahren mit immer unter- *
+;* schiedlichen Randbedingungen auf die der zu testende Pro- *
+;* teil entsprechend reagiert und auch Zeit ben”tigt. *
+;* So hat man sicher die minimale und maximale Laufzeit. *
+;* *
+;* Bei allgemeiner Verwendung: *
+;* Max.Meáwert=0FFFFH = 35.585æs bei 0,543æs Aufl”sung *
+;* Max.Meáwert=0FFFFH = 568.909æs bei 8,681æs Aufl”sung *
+;* *
+;* Hardware.: getested auf Micro-ICE TLCS900 mit 14,7456MHz Quarz !!!! *
+;* *
+;* Routine Funktion Ausgabe Stack *
+;* *
+;* CPU_TI_INI Initialisierung ------ 6 Byte *
+;* CPU_TIME Uhr starten ------ 0 Byte *
+;* CPU_STOP Uhr stoppen Zeit+Statistik 8 Byte *
+;* *
+;* - Der Prozessor muá sich im Maximum-Modus befinden *
+;* - Symbol BigTime definieren fr gr”áere Aufl”sung *
+;* - Da die Routinen lokale Labels verwenden, ist mindestens AS 1.39 *
+;* erforderlich *
+;* - MACROS.INC muá vorher, CONOUT.INC irgendwo eingebunden werden *
+;*************************************************************************
+
+;-------------------------------------------------------------------------
+; gemeinsamer Anfang, Definitionen
+
+ section Timer
+
+TRUN EQU 020H
+CAP1L EQU 034H
+CAP1H EQU 035H
+T4MOD EQU 038H
+
+CR EQU 0DH
+LF EQU 0AH
+
+ ifdef BigTime
+Overhead equ 1 ; Eigenverbrauch Start/Stop
+ elseif
+Overhead equ 9
+ endif
+
+CPU_TI_FAA db 40h dup (?) ; FeldAnfangsAdresse, ab hier wer-
+ ; den 40H (64) RAM-Zellen ben”tigt
+ ; gleich 2 * 16 Worte
+CPU_TI_CR dd ? ; CPU_TIME-Control-Register,
+ ; wird noch nicht ben”tigt!!!
+
+;*************************************************************************
+;Dieser Aufruf geh”rt in den Initialisierungsbereich des zu testenden
+;Programmabschnittes!!
+
+ proc CPU_TI_INI
+
+;Hier werden die Feldwerte initialisiert..
+
+ PUSH XDE ;Wird gleich benutzt
+ PUSH BC ;Wird gleich benutzt
+ LD B,10H ;16 W”rter fr Max.Werte werden gebraucht
+ LD XDE,CPU_TI_FAA ;FeldAnfangsAdresse laden
+CPU_TI_INI1: LDW (XDE),00000H ;Feldzelle fr Max.Werte initalisieren
+ INC 2,XDE ;n„chste Max.Wert-Feldzelle
+ ;adressieren
+ DJNZ CPU_TI_INI1 ;Alle Max.Werte initialisiert?
+ LD B,10H ;16 W”rter fr Min.Werte werden gebraucht
+CPU_TI_INI2: LDW (XDE),0FFFFH ;Feldzelle fr Min.Werte initalisieren
+ INC 2,XDE ;n„chste Max.Wert-Feldzelle
+ ;adressieren
+ DJNZ CPU_TI_INI2 ;Alle Min.Werte initialisiert?
+ POP BC ;Und wieder restaurieren
+ POP XDE ;hier auch...
+ RET ;Zurck zum Aufruf!
+ endp
+
+;*************************************************************************
+; Uhr starten
+
+ proc CPU_TIME
+
+ ;Timer4 CPU-Time-Messung vorbereiten
+ RES 4,(TRUN) ;Timer4 stop and clear !
+ ifdef BigTime
+ LD (T4MOD),00100011B ;Bit 0+1:Source-Clock: 8,681æs
+ elseif
+ LD (T4MOD),00100001B ;Bit 0+1:Source-Clock: 0,543æs
+ endif
+ ;Bit 2 :clear from TREG5 disabled
+ ;Bit 3+4:INT-Capture disabled
+ ;Bit 5 :No Sw. capture now
+ SET 4,(TRUN) ;Timer4 start and count !
+ RET
+ endp
+
+;*************************************************************************
+
+ proc CPU_STOP
+
+ RES 5,(T4MOD) ;Capture1 grabs count
+ CALL CPU_TI_SOUT ;Einzelausgabe des gemessenen Wertes
+ CALL CPU_TI_SOR ;gemessenen Wert ins Feld sortieren
+ RET ;Zurck zum Aufruf!
+ endp
+
+;*************************************************************************
+;Hier wird der gerade gemessene Wert ausgegeben. Diese Ausgabe ist
+;ausreichend um Laufzeitwerte von statischen Programmabschnitten
+;zu ermitteln (keine Verzweigungen im Programmabschnitt).
+
+CPU_TI_SOUT: PUSH A ; needed little later
+ PUSH F ; needed little later
+ push bc ; needed little later
+ ld wa,(cap1l) ; gemesser Wert
+ call WriteTime
+ pop bc ; back to the roots ...
+ POP F
+ POP A
+ RET ; Zurck zum Aufruf!
+
+;*************************************************************************
+;Hier werden die ermittelten Werte sortiert abgelegt!
+;Jeweils am Feldanfang steht der grӇte und der kleinste Wert.
+;Falls ein Wert einem anderen im Feld entspricht (gleicher Messwert)
+;wird dieser nicht nochmal eingetragen!!!!
+;!!Achtung diese Routine ben”tigt max. 145æs (14,7456MHz Quarz)
+; im worst case!! Aber nur wenn Daten und Code 16Bit breit sind
+; und keine Waitstates zugeschaltet sind (Micro-ICE TLCS900 default RAM)!
+
+CPU_TI_SOR: PUSH HL ;Wird gleich benutzt
+ PUSH BC ;Wird gleich benutzt
+ PUSH XDE ;Wird gleich benutzt
+ ;Max.Werte sortiert ablegen!!!
+ LD B,10H ;16 W”rter enth„lt Max.Wert-Feld
+ LD HL,(CAP1L) ;gemessenen Wert aus Capture-Reg. holen
+ LD XDE,CPU_TI_FAA ;erste Max.Wert-Feldzelle adressieren
+CPU_TI_SOR1: CP HL,(XDE) ;Wert mit Feldinhalt vergleichen
+ JR ULT,CPU_TI_SOR2 ;Ist Wert kleiner als Feldinhalt?
+ JR Z,CPU_TI_SOR3 ;Ist Wert gleich Feldinhalt? Abbrechen!
+ EX (XDE),HL ;Nein-->Wert mit Feldinhalt tauschen!
+CPU_TI_SOR2: INC 2,XDE ;n„chste Feldzelle adressieren
+ DJNZ B,CPU_TI_SOR1 ;Alle 16 Max.Werte kontrolliert?
+ ;Min.Werte sortiert ablegen!!!
+CPU_TI_SOR3: LD B,10H ;16 W”rter enth„lt Min.Wert-Feld
+ LD HL,(CAP1L) ;gemessenen Wert aus Capture-Reg. holen
+ LD XDE,CPU_TI_FAA+20H ;erste Min.Wert-Feldzelle adressieren
+CPU_TI_SOR4: CP HL,(XDE) ;Wert mit Feldinhalt vergleichen
+ JR UGT,CPU_TI_SOR5 ;Ist Wert grӇer als Feldinhalt?
+ JR Z,CPU_TI_SOR6 ;Ist Wert gleich Feldinhalt? Abbrechen!
+ EX (XDE),HL ;Nein-->Wert mit Feldinhalt tauschen!
+CPU_TI_SOR5: INC 2,XDE ;n„chste Feldzelle adressieren
+ DJNZ B,CPU_TI_SOR4 ;Alle 16 Min.Werte kontrolliert?
+CPU_TI_SOR6: POP XDE ;Und wieder restaurieren
+ POP BC ;wieder restaurieren
+ POP HL ;hier auch...
+ RET ;Zurck zum Aufruf!
+
+;*************************************************************************
+;Hier werden die im Feld abgelegten Werte ausgeben.
+
+CPU_TI_MOUT: ;Muá noch geschrieben werden!
+ RET ;Zurck zum Aufruf!
+
+;*************************************************************************
+; eine Zeitdifferenz in WA umrechnen und ausgeben
+; wegen der Aufl”sung der Timer ist die letzte Stelle hinter dem Komma
+; bei hoher Aufl”sung mit Vorsicht zu genieáen
+
+WriteTime: push xwa ; Register retten
+ push bc
+ sub wa,Overhead ; Zeit korrigieren
+ ifdef BigTime ; Fall 1: niedrige Aufl”sung
+ mul xwa,8681 ; -->Nanos in XWA
+ add xwa,5000 ; !!Rundung!!
+ div xwa,10000 ; Nanos , einzelne Mikros wegschmeiáen
+ extz xwa
+ div xwa,100 ; Millisekunden in WA
+ ld bc,2003h ; ausgeben
+ call WriteDec
+ ld a,'.'
+ call CONOUT
+ ld wa,qwa ; auf 10 us genau ausgeben
+ ld bc,3002h
+ call WriteDec
+ call PSTR
+ db " Milli",StrTerm
+ elseif ; Fall 2: hohe Aufl”sung
+ mul xwa,543 ; -->Nanosekunden in XWA
+ div xwa,1000 ; -->Nanos in QWA, Mikros in WA
+ ld bc,2005h ; Mikros 5-stellig mit Blanks
+ call WriteDec
+ ld a,'.'
+ call CONOUT
+ ld wa,qwa ; Nanos einstellig
+ add wa,50 ; Rundung
+ extz xwa
+ div xwa,100 ; Ergebnis 0..9
+ cp wa,10
+ jr ne,NoErr
+ ld wa,9
+NoErr: ld bc,3001h ; einstellig ausgeben
+ call WriteDec
+ call PSTR
+ db " Mikro",StrTerm
+ endif
+ call PSTR
+ db "sekunden",StrTerm ; gemeinsamer Rest
+ pop bc ; Register zurck
+ pop xwa
+ ret
+
+;*************************************************************************
+; gemeinsames Ende
+
+ endsection
diff --git a/tests/t_fl900/float.inc b/tests/t_fl900/float.inc
new file mode 100644
index 0000000..dd4796c
--- /dev/null
+++ b/tests/t_fl900/float.inc
@@ -0,0 +1,973 @@
+; FLOAT.INC
+;******************************************************************************
+;* Gleitkommabibliothek fr TLCS 900 *
+;* *
+;* Originale fr den 68000 aus mc, bis auf die Quadratwurzel aus c't *
+;* Portierung auf TLCS 900 von Alfred Arnold, Oktober 1993 *
+;* *
+;* Routine Funktion Eingabe Ausgabe Stack L„nge Zeit/14MHz *
+;* *
+;* fadd Addition XWA+XHL XWA 12 Byte 194 Byte 60 us *
+;* fsub Subtraktion XWA-XHL XWA 12 Byte 7 Byte 65 us *
+;* fmul Multiplikation XWA*XHL XWA 20 Byte 218 Byte 70 us *
+;* fdiv Division XWA/XHL XWA 20 Byte 147 Byte 300 us *
+;* fmul2 Mult. mit 2er-Potenz XWA*(2^BC) XWA 6 Byte 99 Byte 20 us *
+;* fitof Int-->Float XWA XWA 4 Byte 41 Byte 90 us *
+;* fftoi Float-->Int XWA XWA 2 Byte 72 Byte 20 us *
+;* fsqrt Quadratwurzel XWA XWA 16 Byte 192 Byte 220 us *
+;* fftoa Float-->ASCII XWA (XHL),BC ~38 Byte 228 Byte ~4500 us *
+;* fatof ASCII-->Float (XHL),BC XWA,[BC] ~40 Byte 260 Byte ~2300 us *
+;* *
+;* - Wollen Sie einzelne Routinen entfernen, so beachten Sie, daá fsub Teile *
+;* aus fadd und fdiv Teile aus fmul verwendet ! *
+;* - Gleitkommaformat ist IEEE Single (32 Bit) *
+;* - Integerwerte bei fmul2, fitof und fftoi sind vorzeichenbehaftet *
+;* - Der Prozessor muá sich im Maximum-Modus befinden *
+;* - Da die Routinen lokale Labels verwenden, ist mindestens AS 1.39 erfor- *
+;* derlich *
+;* - Die Ausfhrungszeiten k”nnen je nach Operand streuen, insbesondere bei *
+;* den Konvertierungsfunktionen *
+;* - MACROS.INC muá vorher eingebunden werden *
+;******************************************************************************
+
+;------------------------------------------------------------------------------
+; gemeinsamer Anfang, Makros
+
+shifta macro op,dest ; Schieben, falls evtl. A>=16
+ push a ; A wird zerschossen
+ bit 4,a ; Akku im Bereich 16..31 ?
+ jr z,smaller
+ op 16,dest ; dann einmal groá schieben
+smaller: push f ; Carry erhalten
+ and a,15 ; obere Bits pl„tten
+ jr z,fertig
+ pop f ; evtl. Rest verarbeiten
+ op a,dest
+ jr ende ; Carry schon gut
+fertig: pop f
+ende: pop a ; A zurck
+ endm
+
+ section FloatLib
+
+;------------------------------------------------------------------------------
+; Konstanten
+
+Ld10: dd ld(10) ; Konversionskonstanten
+One: dd 1.0
+Half: dd 0.5
+Ten: dd 10.0
+Tenth: dd 3dcccccdh ; =0.1, aber die Rundung auf manchen
+ ; Systemen variiert (damit Test nicht
+ ; scheitert)
+
+Bias equ 127
+MaxExpo equ 255
+Comma equ '.'
+
+;------------------------------------------------------------------------------
+; Addition: XWA=XWA+XHL
+
+ proc fadd
+
+ push xbc ; andere Register retten
+ push xde
+ push xhl
+
+ ld xde,xwa ; Operand 1 nach XDE verschieben
+ rlc 1,xde ; Vorzeichen der Operanden nach Bit 0
+ rlc 1,xhl
+ ld xbc,xde ; Differenz bilden
+ sub xbc,xhl
+ jr nc,NoSwap ; evtl. vertauschen, so daá
+ ld xwa,xhl ; grӇere in XDE
+ ld xhl,xde
+ ld xde,xwa
+NoSwap: ld qa,e ; Vorzeichen 1 ausmaskieren
+ and qa,1 ; (=Ergebnis Vorzeichen)
+ bit 0,c ; gleiches Vorzeichen ?
+ jr z,NoSub
+ set 1,qa ; dann Subtraktion vormerken
+
+NoSub: sub xbc,xbc ; XBC initialisieren
+ rlc 8,xde ; Exponent 1 rausholen
+ ld c,e
+ or e,e ; falls <>0, implizite 1 einbauen
+ scc nz,e
+ rrc 1,xde
+ ld e,0 ; Bit 0..7 wieder pl„tten
+
+ rlc 8,xhl ; dito Exponent 2 extrahieren
+ ld qc,l
+ or l,l
+ scc nz,l
+ rrc 1,xhl
+ ld l,0
+
+; Zwischenstand:
+; - Mantissen linksbndig inkl. impliziter Eins in XDE und XHL
+; - Exponent 1 in BC, Exponent 2 in QBC
+; - Ergebnisvorzeichen in QA, Bit 0
+; - Subtraktionsflag in QA, Bit 1
+
+ ld wa,bc ; Exponentendifferenz berechnen
+ sub wa,qbc
+ cp wa,24 ; >24, d.h. Zahl 2 vernachl„ssigbar gegen Zahl 1
+ jr gt,Round ; ja, Ergebnis ist grӇere Zahl
+ shifta srl,xhl ; ansonsten Mantisse 2 entspr. anpassen
+
+Add: bit 1,qa ; subtrahieren ?
+ jr nz,Subtract ; ja-->
+ add xde,xhl ; nein, Mantissen addieren
+ jr nc,Round ; kein šberlauf, runden
+ rr 1,xde ; ansonsten šberlauf einschieben...
+ inc bc ; ...und Exponent korrigieren
+ jr Round ; normal weiter runden
+
+Subtract: sub xde,xhl ; Mantissen subtrahieren
+ jr z,Zero ; falls Null, Gesamtergebnis 0
+ jr m,Round ; fhrende 1 noch da: zum Runden
+Normalize: or bc,bc ; Exponent bereits Null ?
+ jr z,Round ; dann denormales Ergebnis
+ dec bc ; ansonsten Mantisse eins rauf, Exponent
+ sll 1,xde ; eins runter
+ jr p,Normalize ; solange, bis Eins auftaucht
+
+Round: add xde,80h ; Rundung auf Bit hinter Mantisse
+ jr nc,NoOver
+ rr 1,xde ; Bei šberlauf korrigieren
+ inc bc
+NoOver: ld e,0 ; Mantissenrest pl„tten
+ or xde,xde ; insgesamt 0 ?
+ jr z,Zero ; dann Ergebnis 0
+ cp bc,MaxExpo ; Exponentenberlauf ?
+ jr lt,NoEOver
+ ld bc,MaxExpo ; ja: Unendlich: Exponent=Maximum
+ sub xde,xde ; Mantisse=0
+ jr Denormal
+
+NoEOver: or bc,bc ; Exponent 0 ?
+ jr z,Denormal ; ja, denormal
+ sll 1,xde ; fhrende Eins nicht speichern
+Denormal: ld e,c ; Exponenten einbauen
+ rrc 8,xde ; nach oben schieben
+ rr 1,qa ; Vorzeichen einbauen
+ rr 1,xde
+
+Zero: ld xwa,xde ; Ergebnis in Akku
+
+ pop xhl ; Register zurck
+ pop xde
+ pop xbc
+
+ ret
+
+ endp
+
+;------------------------------------------------------------------------------
+; Subtraktion: XWA=XWA-XHL
+
+ proc fsub
+
+ xor qh,80h ; Vorzeichen 2 drehen
+ jp fadd ; ansonsten wie Addition
+
+ endp
+
+;------------------------------------------------------------------------------
+; Multiplikation: XWA=XWA*XHL
+
+ proc fmul
+
+ public MulRound:Parent,MulZero:Parent,MulResult:Parent
+ public DivError:Parent
+
+ push xbc ; Register retten
+ push xde
+ push xhl
+ push xix
+ push xiy
+
+ ld xiy,xwa ; Op1 kopieren
+ xor xiy,xhl ; Ergebnisvorzeichen bestimmen
+
+ ex wa,qwa ; Registerh„lften Op1 vertauschen
+ ld xde,xwa ; Op1 ab sofort in XDE
+ and de,7fh ; Exponent und Vz. behandeln
+ and wa,7f80h ; Exponent maskieren
+ jr z,Denorm1 ; gleich Null-->Op1 denormal
+ set 7,de ; ansonsten implizite Eins einbauen
+ sub wa,80h ; Bias kompensieren
+Denorm1:
+ ex hl,qhl ; Op2 genauso behandeln
+ ld xbc,xhl
+ and hl,7fh
+ and bc,7f80h
+ jr z,Denorm2
+ set 7,hl
+ sub bc,80h
+Denorm2:
+ add bc,wa ; Exponenten addieren
+ srl 7,bc ; richtig positionieren
+ sub bc,Bias-3 ; Bias-3 abziehen
+ cp bc,-24 ; totaler Unterlauf ?
+ jr lt,MulZero ; dann Ergebnis 0
+
+ ld wa,de ; beide oberen H„lften multiplizieren
+ mul xwa,hl
+ ex wa,qwa ; Ergebnis in oberer H„lfte lagern
+ ld wa,de ; obere H„lfte Op1 retten
+ ex de,qde ; untere H„lfte Op1 holen
+ ld ix,hl ; untere H„lfte Op1 * obere Op2
+ mul xix,de
+ ex hl,qhl ; untere Op1 * untere Op2
+ mul xde,hl
+ ex de,qde ; obere Op1 * untere Op2
+ mul xhl,wa
+
+ ld wa,de ; Teile aufaddieren
+ add xwa,xix
+ add xwa,xhl
+ jr z,MulResult ; Mantisse Null, Ergebnis Null
+ jr m,MulRound
+
+ or bc,bc ; Exponent negativ ?
+ jr m,Unterlauf ; ggfs. Unterlauf behandeln
+
+Nor: or bc,bc ; Exponent Null ?
+ jr z,MulRound ; ja-->zum Runden
+ rl 1,xde ; nein, Mantisse eins nachschieben
+ rl 1,xwa
+ dec bc ; und Exponent runter
+ or xwa,xwa ; fhrende Eins da ?
+ jr p,Nor ; nein, weiterschieben
+
+MulRound: add xwa,80h ; Rundung
+ jr nc,NoROver ; dabei šberlauf ?
+ rr 1,xwa ; ja: Mantisse & Exponent korrigieren
+ inc bc
+NoROver: cp bc,MaxExpo ; Exponentenberlauf ?
+ jr lt,NoEOver
+DivError: ld bc,MaxExpo ; dann unendlich einstellen
+ sub xwa,xwa
+ jr Denormal
+
+NoEOver: or bc,bc ; Exponent 0 ?
+ jr z,Denormal
+ sll 1,xwa ; fhrende 1 l”schen
+
+Denormal: ld a,c ; Exponent einbauen
+ rrc 8,xwa ; hochschieben
+ rl 1,xiy ; Vorzeichen einbauen
+ rr 1,xwa
+
+MulResult: pop xiy
+ pop xix
+ pop xhl
+ pop xde
+ pop xbc
+
+ ret
+
+MulZero: sub xwa,xwa ; Null erzeugen
+ jr MulResult
+
+Unterlauf: cp bc,-24 ; totaler Unterlauf ?
+ jr le,MulZero ; dann Null
+ neg bc ; sonst umbauen
+ ld xde,xwa ; dazu Akku freimachen
+ sub wa,wa ; Endexponent
+ ex wa,bc ; ist 0
+ shifta srl,xde ; Mantisse herunterschieben
+ ld xwa,xde ; Ergebnis zurck nach XWA
+ jr MulRound ; zurck mit Exponent 0
+
+ endp
+
+;------------------------------------------------------------------------------
+; Division: XWA=XWA/XHL
+
+ proc fdiv
+
+ push xbc ; Register retten (muá gleich zu fmul sein)
+ push xde
+ push xhl
+ push xix
+ push xiy
+
+ ld xiy,xwa ; Op1 kopieren
+ xor xiy,xhl ; Ergebnisvorzeichen bestimmen
+
+ ex wa,qwa ; Vorbehandlung wie bei fmul
+ ld xde,xwa
+ and de,7fh
+ and wa,7f80h
+ jr z,Denorm1
+ set 7,de
+ sub wa,80h
+Denorm1:
+ ex hl,qhl
+ ld xbc,xhl
+ and hl,7fh
+ and bc,7f80h
+ jr z,Denorm2
+ set 7,hl
+ sub bc,80h
+Denorm2:
+ sub wa,bc ; Exponentendifferenz bilden
+ ld bc,wa ; muá in BC liegen
+ sra 7,bc ; richtig positionieren
+ add bc,Bias ; Bias addieren
+ cp bc,-24 ; totaler Unterlauf ?
+ jr lt,MulZero ; ja, Ergebnis Null
+
+ ex hl,qhl ; Format 0fff ... ffff 0000 0000
+ or xhl,xhl ; Ergebnis unendlich ?
+ jrl z,DivError
+ sll 7,xhl
+ ex de,qde ; dito Divident
+ or xde,xde ; falls Null, Ergebnis Null
+ jrl z,MulZero
+ sll 7,xde
+
+NormLoop: bit 14,qhl ; Divisor normalisiert ?
+ jr nz,Normal
+ inc bc ; nein, Exponent RAUF (ist Ergebnisexponent)
+ sll 1,xhl
+ jr NormLoop
+
+Normal: sub xwa,xwa ; Ergebnisquotient vorbesetzen
+ add bc,25 ; Exponent nicht grӇer als 0
+
+Loop: ld xix,xde ; Divident zwischenspeichern
+ sub xde,xhl ; probeweise abziehen
+ ccf ; Carry drehen
+ jr c,IsOne ; ungedrehter Carry=1: Divisor paát
+ ld xde,xix ; ansonsten zurckkopieren
+IsOne: rl 1,xwa ; Ergebnisbit einschieben
+ sll 1,xde ; Divident verschieben
+ dec bc ; Exponent runter
+ or bc,bc
+ jr z,Denorm ; falls Null, denormalisieren
+ bit 8,qwa ; fhrende Eins da ?
+ jr z,Loop ; nein, weiterrechnen
+
+Denorm: sll 7,xwa ; Mantisse positionieren
+ jrl z,MulResult ; Ergebnis 0 ?
+ jrl MulRound ; ansonsten zum Runden
+
+ endp
+
+;-----------------------------------------------------------------------------
+; Multiplikation mit Zweierpotenz: XWA=XWA*2^BC
+
+ proc fmul2
+
+ push bc ; Register retten
+ push xde
+
+ ld xde,xwa ; Vorzeichen merken
+ sll 1,xwa ; Vorzeichen rausschieben
+ jr z,Zero ; falls Null, Ergebnis Null
+ rlc 8,xwa ; Exponent nach unten...
+ sub de,de ; und in DE packen
+ add e,a
+ jr z,Denorm ; falls denormalisiert..
+ or bc,bc ; Multiplikation oder Division ?
+ jr m,Divide ; (neg. Exponent=Division)
+
+ add de,bc ; Exponent addieren
+ cp de,MaxExpo ; šberlauf ?
+ jr ge,Over ; ja, Ergebnis unendlich
+Result: ld a,e ; Ergebnisexponent einbauen
+ rrc 8,xwa ; Exponent nach oben
+ rl 1,xde ; Vorzeichen einschieben
+ rr 1,xwa
+
+Zero: pop xde ; Register zurck
+ pop bc
+ ret
+
+Over: ld de,MaxExpo ; Ergebnis unendlich
+ sub xwa,xwa
+ jr Result
+
+Divide: add de,bc ; Exponentensumme bilden
+ jr gt,Result ; >0, keine Sonderbehandlung
+ scf ; ansonsten 1 explizit fr
+ rr 1,xwa ; denormale Zahl machen
+DDenorm: or de,de ; Exponent=0 ?
+ jr z,Result ; ja, Ergebnis einfach denormal
+ srl 1,xwa ; ansonsten weiter denormalisieren
+ jr z,Zero ; dabei totaler Unterlauf->Null
+ inc de ; Exponent korrigieren
+ jr DDenorm
+DDDenorm: add de,bc ; Exponentensumme bilden
+ jr DDenorm
+
+Denorm: or bc,bc ; Multiplikation oder Division ?
+ jr m,DDDenorm
+ sub a,a ; alten Exponenten l”schen
+Norm: sll 1,xwa ; normalisieren...
+ jr c,Stop ; bis fhrende Eins da
+ dec bc ; oder 2. Exponent 0
+ or bc,bc
+ jr nz,Norm
+ jr Result ; Multiplikator kompl. fr Normalisierung draufgegangen
+Stop: add de,bc ; Rest addieren
+ jr Result ; alles andere schon o.k.
+
+ endp
+
+;------------------------------------------------------------------------------
+; LongInt-->Float : XWA-->XWA
+
+ proc fitof
+
+ push xbc ; Register retten
+
+ or xwa,xwa ; Null ?
+ jr z,Result ; dann Ergebnis Null
+ scc m,qc ; Vorzeichen nach QC, Bit 0
+ jr p,Positive
+ cpl wa ; falls negativ,drehen
+ cpl qwa
+ inc xwa
+Positive: ld bc,Bias+32 ; Exponent vorbesetzen
+Shift: dec bc ; Mantisse verschieben
+ sll 1,xwa
+ jr nc,Shift
+ ld a,c ; Exponent einbauen
+ rrc 8,xwa ; Exponent nach oben
+ rr 1,qc ; Vorzeichen einbauen
+ rr 1,xwa
+
+Result: pop xbc ; Register zurck
+ ret
+
+ endp
+
+;------------------------------------------------------------------------------
+; Float-->LongInt : XWA-->XWA
+
+ proc fftoi
+
+ push bc ; Register retten
+
+ rl 1,xwa ; Vorzeichen in Carry
+ scc c,b ; in B merken
+
+ rlc 8,xwa ; Exponent nach unten
+ ld c,a ; in C legen
+ sub c,Bias ; Bias abziehen
+
+ jr m,Zero ; neg. Exponent -> Zahl<0 -> Ergebnis 0
+ cp c,31 ; šberlauf ?
+ jr ge,Over
+
+ scf ; fhrende Eins einschieben
+ rr 1,xwa
+ sub a,a ; Exponent l”schen
+
+Shift: srl 1,xwa ; jetzt schieben, bis Ergebnis stimmt
+ inc c
+ cp c,31
+ jr ne,Shift
+
+ srl 1,b ; negieren ?
+ jr nc,Positive
+ cpl wa ; ggfs. negieren
+ cpl qwa
+ inc xwa
+
+Positive: pop bc ; Register zurck
+ ret
+
+Zero: sub xwa,xwa ; Ergebnis 0
+ jr Positive
+
+Over: ld xwa,7fffffffh ; šberlauf: Maxint zurckgeben
+ srl 1,b ; negativ ?
+ jr nc,Positive
+ cpl wa ; ja, neg. Maximum zurckgeben
+ cpl qwa
+ jr Positive
+
+ endp
+
+;------------------------------------------------------------------------------
+; Quadratwurzel: XWA=SQRT(XWA)
+
+ proc fsqrt
+
+ push xbc ; Register retten
+ push xde
+ push xhl
+ push xix
+
+ ld xix,xwa ; Argument retten
+ or xix,xix ; Zahl negativ ?
+ jrl m,DomainError ; dann geht es nicht
+
+ ex ix,qix ; MSW holen
+ and xix,7f80h ; Exponent isolieren
+ jrl z,Zero ; keine Behandlung denormaler Zahlen
+
+ and xwa,7fffffh ; Mantisse isolieren
+ sub ix,7fh*80h ; Bias vom Exponenten entfernen
+ bit 7,ix ; Exponent ungerade ?
+ res 7,ix
+ jr z,EvenExp
+ add xwa,xwa ; ja: Mantisse verdoppeln
+ add xwa,1000000h-800000h ; impl. Eins dazu
+EvenExp: ; erste Iteration ohne impl. Eins
+ sra 1,ix ; Exponent/2 mit Vorzeichen
+ add ix,7fh*80h ; Bias wieder dazu
+ ex ix,qix ; neuen Exponenten in QIX aufheben
+ sll 7,xwa ; x ausrichten
+ ld xde,40000000h ; xroot nach erster Iteration
+ ld xhl,10000000h ; m2=2 << (MaxBit-1)
+Loop10: ld xbc,xwa ; xx2 = x
+Loop11: sub xbc,xde ; xx2 -= xroot
+ srl 1,xde ; xroot = xroot/2
+ sub xbc,xhl ; x2 -= m2
+ jr m,DontSet1
+ ld xwa,xbc ; x = xx2
+ or xde,xhl ; xroot += m2
+ srl 2,xhl ; m2 = m2/4
+ jr nz,Loop11
+ jr WABCSame
+DontSet1: srl 2,xhl ; m2 = m2/4
+ jr nz,Loop10 ; 15* abarbeiten
+ ; Bit 22..8
+ ld xbc,xwa ; 17. Iteration separat
+WABCSame: sub xbc,xde
+ rrc 1,xde ; mitsamt Carry...
+ ex de,qde ; auf neues Alignment umstellen
+ sub xbc,1 ; Carry von 0-$4000: x2 -= m2
+ jr m,DontSet7
+ or xbc,-40000000h ; 0-$4000: x2 -= m2, Teil 2
+ ld xwa,xbc
+ or de,4000h ; xroot += m2
+DontSet7: ex wa,qwa ; x auf neues Alignment umstellen
+ ld hl,1000h ; m2 - obere H„lfte schon 0
+Loop20: ld xbc,xwa ; xx2 = x
+Loop21: sub xbc,xde ; xx2 -= xroot
+ srl 1,xde ; xroot = xroot/2
+ sub xbc,xhl ; x2 -= m2
+ jr m,DontSet2
+ ld xwa,xbc ; x = xx2
+ or xde,xhl ; xroot += m2
+ srl 2,xhl ; m2 = m2/4
+ jr nz,Loop21
+ jr Finish
+DontSet2: srl 2,xhl ; m2 = m2/4
+ jr nz,Loop20 ; 7* abarbeiten
+
+Finish: sub xwa,xde ; Aufrunden notwendig ?
+ jr ule,NoInc
+ inc xde ; wenn ja, durchfhren
+NoInc: res 7,qde ; impl. Eins l”schen
+ or xde,xix
+ ld xwa,xde ; Ergebnis in XWA
+ jr End
+
+DomainError: ld xwa,0ffc00000h ; -NAN zurckgeben
+ jr End
+
+Zero: sub xwa,xwa ; Ergebnis 0
+
+End: pop xix ; Register zurck
+ pop xhl
+ pop xde
+ pop xbc
+ ret
+
+ endp
+
+;------------------------------------------------------------------------------
+; Unterroutine Zehnerpotenz bilden: XWA=10.0^BC
+
+ section fPot10 ; nicht mit proc, da private Funktion
+ public fPot10:Parent
+fPot10:
+
+ push xbc ; Register retten
+ push xhl
+
+ ld xwa,(One) ; Ausgangspunkt frs Multiplizieren
+ ld xhl,(Ten) ; zu benutzende Potenz
+ or bc,bc ; negative Potenz ?
+ jr p,IsPos
+ ld xhl,(Tenth) ; dann eben Zehntel multiplizieren
+ neg bc ; fr Schleife immer positiv
+IsPos:
+ or bc,bc ; Noch weiter multiplizieren ?
+ jr z,End
+ bit 0,bc ; Restpotenz ungerade ?
+ jr z,IsEven
+ call fmul ; ja: einzeln multiplizieren
+IsEven: srl 1,bc ; n„chste Stelle
+ push xwa ; neue Potenz berechnen
+ ld xwa,xhl
+ call fmul ; durch quadrieren
+ ld xhl,xwa
+ pop xwa
+ jr IsPos ; weiter nach Einsen suchen
+
+End: pop xhl ; Register zurck
+ pop xbc
+ ret
+
+ endsection
+
+;------------------------------------------------------------------------------
+; Unterroutine Zahl dezimal wandeln
+
+ section fOutDec
+ public fOutDec:Parent
+fOutDec:
+
+ push xwa ; Register retten
+ push xbc
+ push de
+ push xhl
+
+ bit 15,qwa ; negativ ?
+ jr z,IsPos
+ ld (xix+),'-' ; ja: vermerken...
+ cpl wa ; ...und Zweierkomplement
+ cpl qwa
+ inc xwa
+ jr GoOn
+IsPos: bit 7,c ; Pluszeichen ausgeben ?
+ jr nz,GoOn
+ ld (xix+),'+'
+GoOn: res 7,c ; Plusflag l”schen
+ ld qbc,0 ; Nullflag und Z„hler l”schen
+
+InLoop: ld xhl,0 ; Division vorbereiten
+ ld e,32 ; 32 Bit-Division
+DivLoop: sll 1,xwa ; eins weiterschieben
+ rl 1,xhl
+ srl 1,xwa ; fr nachher
+ sub xhl,10 ; paát Divisor hinein ?
+ jr nc,DivOK
+ add xhl,10 ; nein, zurcknehmen...
+ scf ; im Ergebnis 0 einschieben
+DivOK: ccf ; neues Ergebnisbit
+ rl 1,xwa ; Ergebnis in XWA einschieben...
+ djnz e,DivLoop
+
+ add l,'0' ; ASCII-Offset addieren
+ bit 1,qb ; schon im Nullbereich ?
+ jr z,NormVal
+ ld l,b ; ja, dann gewnschtes Leerzeichen
+NormVal: push l ; auf LIFO legen
+ inc qc ; ein Zeichen mehr
+ or xwa,xwa ; Quotient Null ?
+ scc z,qb
+ jr nz,InLoop ; wenn nicht Null, auf jeden Fall weiter
+ cp c,qc ; ansonsten nur, falls min. Stellenzahl
+ jr ugt,InLoop ; noch nicht erreicht
+
+OutLoop: pop a ; jetzt Zeichen umgekehrt ablegen
+ ld (xix+),a
+ djnz qc,OutLoop
+
+ pop xhl ; Register zurck
+ pop de
+ pop xbc
+ pop xwa
+
+ ret
+
+ endsection
+
+;------------------------------------------------------------------------------
+; Gleitkomma nach ASCII wandeln:
+; In: Zahl in XWA
+; Zeiger auf Speicher in XHL
+; max. Anzahl Nachkommastellen in C
+; B/Bit 0 setzen, falls Mantissen-Pluszeichen unerwnscht
+; B/Bit 1 setzen, falls Exponenten-Pluszeichen unerwnscht
+; B/Bit 2..4 = Stellenzahl Exponent
+; B/Bit 5 setzen, falls Nullen am Ende der Mantisse unerwnscht
+; Out: Zahl abgelegter Zeichen (exkl. NUL am Ende) in BC
+; (XHL) = gebildeter String
+
+ proc fftoa
+
+ push xix ; Register retten
+ push xhl
+ push de
+ push xbc
+ push xwa
+
+ ld xix,xhl ; Zeiger auf Speicher kopieren
+ ld de,bc ; Parameter sichern
+
+ ld xhl,xwa ; Zahl auf die Zerlegebank bringen
+ res 15,qwa ; Vorzeichen hier nicht mehr gebraucht
+
+ ld c,'+' ; Annahme positiv
+ sll 1,xhl ; Vorzeichen in Carry bringen
+ jr c,IsNeg ; Minuszeichen immer erforderlich...
+ bit 0,d ; ...Pluszeichen optional
+ jr nz,NoMantSgn
+ jr WrMantSgn
+IsNeg: ld c,'-' ; ja
+WrMantSgn: ld (xix+),c ; Mantissenvorzeichen ablegen
+NoMantSgn:
+ ld c,qh ; Exponenten herausholen...
+ extz bc ; ...auf 16 Bit erweitern...
+ sll 8,xhl ; ...und in Quelle l”schen
+
+ cp bc,MaxExpo ; Sonderwert (INF/NAN) ?
+ jrl z,SpecialVals ; ja-->
+
+ or bc,bc ; Zahl denormal ?
+ jr nz,IsNormal ; nein, normal weiter
+ or xhl,xhl ; bei kompl. Null auch berspringen
+ jr z,IsNull
+Normalize: sll 1,xhl ; ja: solange z„hlen, bis 1 erscheint
+ jr c,IsNormal
+ dec bc
+ jr Normalize
+IsNormal: sub bc,Bias ; Bias abziehen
+IsNull:
+ push xwa ; fr folgendes Zahl retten
+ ld wa,bc ; Zweierexponenten in Float wandeln
+ exts xwa
+ call fitof
+ ld xhl,(Ld10) ; in Dezimalexponenten wandeln
+ call fdiv
+ or xwa,xwa ; Zahl negativ ?
+ jr p,NoCorr
+ ld xhl,(One) ; dann nocheinmal korrigieren wg.
+ call fsub ; unterer Gauáklammer
+NoCorr: call fftoi ; Den Ausflug in Float beenden
+ ld qbc,wa ; den Zehnerexponenten retten
+ ld bc,wa
+ call fPot10 ; von diesem Exponenten Zehnerpotenz
+ ld xhl,xwa ; bilden
+ pop xwa ; alte Zahl zurck
+ call fdiv ; Teilen: Ergebnis ist Zahl zwischen
+Again: ld xhl,xwa ; 1.0 und 9.9999..., diese retten
+ call fftoi ; Vorkommastelle berechnen
+ cp a,10 ; doch etwas drber ?
+ jr ult,NoRoundErr
+ ld xwa,xhl ; ja, dann noch einmal zehnteln
+ ld xhl,(Tenth)
+ call fmul
+ inc qbc
+ jr Again
+NoRoundErr: add a,'0' ; diese nach ASCII wandeln...
+ ld (xix+),a ; ...und ablegen
+ sub a,'0' ; wieder rckg„ngig machen
+ cp e,0 ; gar keine Nachkommastellen ?
+ jr eq,NoComma
+ ld (xix+),Comma ; Dezimalpunkt ausgeben
+ call fitof ; in ganze Gleitkommazahl wandeln
+ call fsub ; Differenz bilden
+ chg 15,qwa ; war verkehrtherum...
+ ld xhl,xwa ; nach XHL verschieben, weil XWA gebraucht
+ ld c,e ; Zehnerpotenz fr Skalierung ausrechnen
+ extz bc ; auf 16 Bit aufblasen
+ call fPot10 ; Skalierungswert berechnen
+ call fmul ; hochmultiplizieren
+ ld xhl,(Half) ; Rundung
+ call fadd
+ call fftoi ; diese herausziehen
+ ld b,'0' ; n-stellig mit Vornullen ausgeben
+ ld c,e
+ set 7,c ; kein Pluszeichen!
+ call fOutDec
+ bit 5,d ; Nullen am Ende abr„umen ?
+ jr nz,CleanZeros
+NoComma:
+ ld a,d ; falls Minimalstellenzahl Exponent=0
+ and a,00011100b ; und Exponent=0, vergessen
+ or a,qb
+ or a,qc
+ jr z,End
+
+ ld (xix+),'E' ; Exponenten ausgeben
+ ld wa,qbc
+ exts xwa
+ ld b,'0' ; evtl. vornullen...
+ ld c,d ; Bit 1-->Bit 7
+ rrc 2,c
+ and c,87h ; Bits ausmaskieren
+ call fOutDec
+
+End: pop xwa ; Register zurck
+ pop xbc
+ pop de
+ pop xhl
+ ld (xix),0 ; NUL-Zeichen im String nicht vergessen
+ sub xix,xhl ; Stringl„nge berechnen
+ ld bc,ix
+ pop xix
+
+ ret
+
+SpecialVals: or xde,xde ; Ist die Mantisse Null ?
+ jr nz,IsNAN
+ ldw (xix+),'NI' ; ja: INF einschreiben
+ ld (xix+),'F'
+ jr End
+IsNAN: ldw (xix+),'AN' ; nein: NAN einschreiben
+ ld (xix+),'N'
+ jr End
+
+CleanZeros: cp (xix-1),'0' ; steht da eine Null am Ende ?
+ jr nz,CleanNoZero ; nein, Ende
+ dec xix ; ja: Z„hler runter, so daá ber-
+ jr CleanZeros ; schrieben wird und neuer Versuch
+CleanNoZero: cp (xix-1),Comma ; evtl. Komma entfernbar ?
+ jr nz,NoComma ; nein-->
+ dec xix ; ja: noch ein Zeichen weniger
+ jr NoComma
+
+ endp
+
+;------------------------------------------------------------------------------
+; ASCII nach Gleitkomma wandeln:
+; In: Zeiger auf String (ASCIIZ) in XHL
+; Out: XWA = Ergebnis bzw. fehlerhafte Stelle
+; CY = 0, falls fehlerfrei
+
+ proc fatof
+
+ push xbc ; Register retten
+ push xde
+ push xhl
+ push xix
+
+ ld xix,xhl ; Zeiger nach XIX
+ ld qbc,01 ; Phase 1 (Mantisse), noch kein Vorzeichen
+ ld xde,(Ten) ; in der Mantisse mit 10 hochmultiplizieren
+ ld xhl,0 ; Mantisse vorbelegen
+ ld bc,0 ; Exponent vorbelegen
+
+ReadLoop: ld a,(xix+) ; ein neues Zeichen holen
+ extz wa ; auf 32 Bit aufblasen
+ extz xwa
+
+ cp a,0 ; Endezeichen ?
+ jrl eq,Combine ; ja, alles zusammen
+
+ cp a,' ' ; Leerzeichen ignorieren
+ jr eq,ReadLoop
+
+ cp a,'+' ; Pluszeichen gnadenhalber zugelassen
+ jr ne,NoPlus ; ist aber nur ein Dummy
+ bit 0,qb ; schon ein Vorzeichen dagewesen ?
+ jrl nz,Error ; dann Fehler
+ set 0,qb ; ansonsten einfach setzen
+ jr ReadLoop
+NoPlus:
+ cp a,'-' ; Minuszeichen bewirkt schon eher etwas
+ jr ne,NoMinus
+ bit 0,qb ; darf auch nur einmal auftreten
+ jrl nz,Error
+ set 0,qb
+ cp qc,1 ; je nach Phase anderes Flag setzen
+ jr ne,MinPhase3
+ set 1,qb ; bei Mantisse Bit 1...
+ jr ReadLoop
+MinPhase3: set 2,qb ; bei Exponent Bit 2
+ jr ReadLoop
+NoMinus:
+ cp a,'.' ; Umschaltung zu Phase 2 (Nachkomma) ?
+ jr ne,NoPoint
+ cp qc,1 ; bish. Phase muá eins sein
+ jrl ne,Error
+ ld qc,2 ; neue Phase eintragen
+ set 0,qb ; Nachkomma darf kein Vorzeichen haben
+ ld xde,(Tenth) ; im Nachkomma durch 10 teilen
+ jr ReadLoop
+NoPoint:
+ cp a,'e' ; kleines und groáes E zulassen
+ jr eq,IsE
+ cp a,'E'
+ jr ne,NoE
+IsE: cp qc,3 ; vorherige Phase muá 1 oder 2 sein
+ jr eq,Error
+ ld qc,3 ; vermerken
+ res 0,qb ; Vorzeichen wieder zugelassen
+ jr ReadLoop
+NoE:
+ sub a,'0' ; jetzt nur noch 0..9 zugelassen
+ jr c,Error
+ cp a,9
+ jr ugt,Error
+ set 0,qb ; nach Ziffern kein Vorzeichen mehr zulassen
+
+ cp qc,1 ; Phase 1 (Mantisse) :
+ jr ne,NoPhase1
+ push xwa ; Zeichen retten
+ ld xwa,xde ; bish. Mantisse * 10
+ call fmul
+ ld xhl,xwa
+ pop xwa ; Zahl nach Float wandeln
+ call fitof
+ call fadd ; dazuaddieren
+ ld xhl,xwa ; Mantisse zurcklegen
+ jrl ReadLoop
+NoPhase1:
+ cp qc,2 ; Phase 2 (Nachkomma) :
+ jr ne,NoPhase2
+ call fitof ; Stelle nach Float wandeln
+ push xhl ; Mantisse retten
+ ld xhl,xde ; Stelle mit Zehnerpotenz skalieren
+ call fmul
+ pop xhl ; zur Mantisse addieren
+ call fadd
+ push xwa ; Zwischenergebnis retten
+ ld xwa,xde ; n„chste Skalierungspotenz ausrechnen
+ ld xhl,(Tenth)
+ call fmul
+ ld xde,xwa ; alles wieder zurck
+ pop xhl
+ jrl ReadLoop
+NoPhase2:
+ mul bc,10 ; Exponent heraufmultiplizieren
+ add bc,wa
+ cp bc,45 ; Minimum ist 1e-45
+ jr ugt,Error
+ jrl ReadLoop
+
+Combine: bit 2,qb ; Exponent negativ ?
+ jr z,ExpPos
+ neg bc
+ExpPos: call fPot10 ; Zehnerpotenz des Exponenten bilden
+ call fmul ; mit Mantisse kombinieren
+ bit 1,qb ; Mantisse negativ ?
+ jr z,ManPos
+ set 15,qwa
+ManPos: rcf ; Ende ohne Fehler
+
+ pop xix ; Register zurck
+ pop xhl
+ pop xde
+ pop xbc
+ ret
+
+Error: ld xwa,xix ; Endzeiger laden
+ pop xix
+ pop xhl
+ sub xwa,xhl ; rel. Position des fehlerhaften Zeichens berechnen
+ pop xde
+ pop xbc
+ scf ; Ende mit Fehler
+ ret
+
+ endp
+
+;------------------------------------------------------------------------------
+; gemeinsames Ende
+
+ endsection
+
diff --git a/tests/t_fl900/macros.inc b/tests/t_fl900/macros.inc
new file mode 100644
index 0000000..951a117
--- /dev/null
+++ b/tests/t_fl900/macros.inc
@@ -0,0 +1,16 @@
+; MACROS.INC
+;******************************************************************************
+;* šberall gebrauchte Makros *
+;* *
+;* Alfred Arnold, Oktober 1993 *
+;******************************************************************************
+
+proc macro name ; Prozedureintritt
+ section name
+ public name
+name label $
+ endm
+
+endp macro name ; Prozeduraustritt
+ endsection name
+ endm
diff --git a/tests/t_fl900/t_fl900.asm b/tests/t_fl900/t_fl900.asm
new file mode 100644
index 0000000..72510c2
--- /dev/null
+++ b/tests/t_fl900/t_fl900.asm
@@ -0,0 +1,166 @@
+; FTEST.ASM
+;******************************************************************************
+;* Testet Gleitkommabibliothek fr TLCS900 *
+;* *
+;* Hardware: Micro-ICE TLCS900 *
+;* Software: AS 1.39p1 oder h”her *
+;* Includes MACROS.INC, FLOAT.INC, CONOUT.INC, CPU_TIME.INC *
+;* *
+;* šbersetzen mit AS ftest oder beiliegendem Makefile *
+;* *
+;******************************************************************************
+
+ cpu 96c141
+
+ org 1000h ; Startadresse User-RAM
+
+;------------------------------------------------------------------------------
+
+CR equ 13
+LF equ 10
+Format_Tab equ 0000100000000110b ; fftoa-Format fr tab. Ausgabe
+Format_Min equ 0010001100000101b ; fftoa-Format fr minimale L„nge
+; ³<Â>³³<ÄÄÂÄÄÄ>
+; ³ ³ ³³ ³
+; ³ ³ ³³ ÀÄÄÄÄÄÄ Maximalzahl Nachkommastellen
+; ³ ³ ³ÀÄÄÄÄÄÄÄÄÄÄ Mantissenpluszeichen unterdrcken
+; ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄ Exponentenpluszeichen unterdrcken
+; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄ Minimalstellenzahl Exponent
+; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ anh„ngende Nullen Mantisse l”schen
+Format equ Format_Tab ; gew„hltes fftoa-Format
+
+ supmode on ; Vorgaben
+ maxmode on
+ macexp off
+ page 0 ; keine FFs
+ include macros.inc
+
+;------------------------------------------------------------------------------
+; Hauptroutine, Test
+
+; kleine Schreiberleichterung:
+
+bench macro op,arg1,arg2,arg3,msg
+ call PSTR ; Kennmeldung ausgeben
+ db msg,StrTerm
+ call CPU_TIME ; Uhr starten
+ ld xwa,arg1 ; Operanden holen
+ if "ARG2"<>"" ; 2. Operanden evtl. weglassen
+ ld xhl,arg2
+ endif
+ if "ARG3"<>"" ; dito 3. Operanden
+ ld bc,arg3
+ endif
+ call op ; Probanden laufen lassen
+ ld (xiz),xwa ; Ergebnis weglegen...
+ call CPU_STOP ; Uhr anhalten, Zeit ausgeben
+ if ("OP"<>"FNOP")&&("OP"<>"FFTOI")
+ call PSTR ; etwas Platz
+ db ", Ergebnis: ",StrTerm
+ ld xwa,(xiz+) ; Wert ausgeben
+ lda xhl,(Buffer)
+ ld bc,Format
+ call fftoa
+ call TXTAUS
+ endif
+ call PSTR
+ db CR,LF,StrTerm
+ endm
+
+ proc Main
+
+ max ; ohne das macht das keinen Spaá !
+ lda xsp,(Stack) ; etwas brauchen wir schon...
+ lda xiz,(Ergs) ; Zeiger auf Ergebnisfeld
+ call CPU_TI_INI ; Timer initialisieren
+
+ ; Overhead messen
+ bench fnop,(FConst1),(FConst1),,"Overhead : "
+
+ ; Addition zweier fast gleicher Zahlen
+ bench fadd,(FConst1),(FConst2),,"Laufzeit 1+2 : "
+
+ ; Addition zweier unterschiedl. groáer Zahlen
+ bench fadd,(FConst1),(FConst100000),,"Laufzeit 1+100000 : "
+
+ ; Subtraktion zweier fast gleicher Zahlen
+ bench fsub,(FConst1),(FConst2),,"Laufzeit 1-2 : "
+
+ ; Subtraktion zweier unterschiedl. groáer Zahlen
+ bench fsub,(FConst1),(FConst100000),,"Laufzeit 1-100000 : "
+
+ ; Multiplikation
+ bench fmul,(FConst2),(FConstPi),,"Laufzeit 2*Pi : "
+
+ ; Division
+ bench fdiv,(FConst2),(FConstPi),,"Laufzeit 2/Pi : "
+
+ ; Multiplikation mit 2er-Potenz
+ bench fmul2,(FConstPi),,10,"Laufzeit Pi*2^(10) : "
+
+ ; Division durch 2er-Potenz
+ bench fmul2,(FConstPi),,-10,"Laufzeit Pi*2^(-10) : "
+
+ ; kleine Zahl nach Float wandeln
+ bench fitof,1,,,"Laufzeit 1-->Float : "
+
+ ; groáe Zahl nach Float wandeln
+ bench fitof,100000,,,"Laufzeit 1E5-->Float: "
+
+ ; kleine Zahl nach Int wandeln
+ bench fftoi,(FConst1),,,"Laufzeit 1-->Int : "
+
+ ; groáe Zahl nach Int wandeln
+ bench fftoi,(FConst100000),,,"Laufzeit 1E5-->Int : "
+
+ ; Wurzel
+ bench fsqrt,(FConst2),,,"Laufzeit SQRT(2) : "
+
+ call PSTR
+ db "Eingabe: ",StrTerm
+ lda xhl,(InpBuffer)
+ call TXTAUS
+ call fatof
+ call PSTR
+ db ", Ergebnis: ",StrTerm
+ lda xhl,(Buffer)
+ ld bc,Format
+ call fftoa
+ call TXTAUS
+ call PSTR
+ db 13,10,StrTerm
+
+ swi 7 ; zum Monitor zurck
+
+ endp
+
+fnop: ld xwa,0 ; Dummy
+ ret
+
+ include "float.inc"
+ include "conout.inc"
+ include "cpu_time.inc"
+
+;------------------------------------------------------------------------------
+; Gleitkommakonstanten
+
+ align 4 ; fr schnelleren Zugriff
+
+FConst1 dd 1.0
+FConst2 dd 2.0
+FConst100000 dd 100000.0
+FConstM1 dd -1.0
+FConstM2 dd -2.0
+FConstPi dd 40490fdbh ; um Vergleichsfehler durch Rundung zu
+ ; vermeiden
+Ergs dd 30 dup (?) ; Platz fr Ergebnisse
+
+Buffer: db 20 dup (?)
+InpBuffer: db "12.3456E-12",0
+
+;------------------------------------------------------------------------------
+; Stack
+
+ db 200 dup (?)
+Stack:
+
diff --git a/tests/t_fl900/t_fl900.doc b/tests/t_fl900/t_fl900.doc
new file mode 100644
index 0000000..4e7cf63
--- /dev/null
+++ b/tests/t_fl900/t_fl900.doc
@@ -0,0 +1,6 @@
++------------------------ Test Application FL900 ----------------------------+
+| |
+| This is an IEEE single precision floating point library for the Toshiba |
+| TLCS-900 microcontroller, embedded into a small test program. |
+| |
++-----------------------------------------------------------------------------+
diff --git a/tests/t_fl900/t_fl900.inc b/tests/t_fl900/t_fl900.inc
new file mode 100644
index 0000000..4a02c1e
--- /dev/null
+++ b/tests/t_fl900/t_fl900.inc
@@ -0,0 +1,2 @@
+; t_fl900.asm-Includefile für Assembler-Programm
+; Ende Includefile für Assembler-Programm
diff --git a/tests/t_fl900/t_fl900.ori b/tests/t_fl900/t_fl900.ori
new file mode 100755
index 0000000..74929d8
--- /dev/null
+++ b/tests/t_fl900/t_fl900.ori
Binary files differ
diff --git a/tests/t_full09/asflags b/tests/t_full09/asflags
new file mode 100644
index 0000000..27cc2fa
--- /dev/null
+++ b/tests/t_full09/asflags
@@ -0,0 +1 @@
+-D __6309__
diff --git a/tests/t_full09/t_full09.asm b/tests/t_full09/t_full09.asm
new file mode 100644
index 0000000..4b39d38
--- /dev/null
+++ b/tests/t_full09/t_full09.asm
@@ -0,0 +1,1604 @@
+ cpu 6309
+
+list macro
+ listing on
+ endm
+
+nolist macro
+ listing off
+ endm
+
+db macro op
+ byt (op)
+ endm
+
+fcb macro op
+ byt (op)
+ endm
+
+fcc macro op
+ byt (op)
+ endm
+
+dw macro op
+ adr (op)
+ endm
+
+fdb macro op
+ adr (op)
+ endm
+
+fcw macro op
+ adr (op)
+ endm
+
+ds macro op
+ dfs (op)
+ endm
+
+rmb macro op
+ rept op
+ db 0
+ endm
+ endm
+
+dd macro op
+ adr (op)>>16,(op)&$ffff
+ endm
+
+fcd macro op
+ adr (op)>>16,(op)&$ffff
+ endm
+
+direct macro num
+ if num=-1
+ assume dpr:nothing
+ elseif num>255
+ assume dpr:num>>8
+ elseif
+ assume dpr:num
+ endif
+ endm
+
+page macro
+ newpage
+ endm
+
+opt macro
+ endm
+
+noopt macro
+ endm
+
+nop macro cnt
+ if "CNT"=""
+__cnt set 1
+ elseif
+__cnt set cnt
+ endif
+ rept __cnt
+ !nop
+ endm
+ endm
+
+momseg set 0
+segsave_code set 0
+segsave_data set 0
+segsave_bss set 0
+
+saveseg macro
+ switch momseg
+ case 0
+segsave_code set *
+ case 1
+segsave_data set *
+ case 2
+segsave_bss set *
+ endcase
+ endm
+
+data macro
+ saveseg
+ org segsave_data
+momseg set 1
+ endm
+
+code macro
+ saveseg
+ org segsave_code
+momseg set 0
+ endm
+
+bss macro
+ saveseg
+ org segsave_bss
+momseg set 2
+ endm
+
+;--------------------------------------------------------------------------
+
+; <:t17,25,41,45:>
+; +=====================================================================+
+; | |
+; | TESTCASE.A09 |
+; | |
+; | Test case for 6809/6309 assembler. |
+; | |
+; | Copyright 1993, Frank A. Vorstenbosch |
+; | |
+; +=====================================================================+
+;
+; File created 13-oct-93
+
+ title "Test case for 6809/6309 assembler"
+
+ list
+
+; +---------------------------------------------------------------------+
+; | |
+; | Options. |
+; | |
+; +---------------------------------------------------------------------+
+
+; -dERRORS check error handling
+; -n disable optimizations
+
+
+; +---------------------------------------------------------------------+
+; | |
+; | Assembler pseudo instructions. |
+; | |
+; +---------------------------------------------------------------------+
+
+; ----- expressions -----------------------------------------------------
+
+ data
+ org 4
+ bss
+ org 1634
+
+TEST equ 2+*/2
+ ifdef ERRORS
+TEST equ TEST+1
+ endif
+
+Constant8 equ -43
+Constant16 equ 16383
+Constant32 equ 96285725
+Address equ $bb5a
+
+ANOTHER set 3|24&8
+ANOTHER set (3|24)&8
+ANOTHER set 4*(3>5)
+ANOTHER set 4*~~(3<5)
+ANOTHER set 15<<4
+ANOTHER set ANOTHER+1
+ANOTHER set ANOTHER+1 ; shorthand for SET
+
+CHAR equ "a"
+DOUBLECHAR equ "xy"
+QUADCHAR equ "quad"
+
+ ifdef ERRORS
+TRIPLE equ "abc"
+TOOMUCH equ "abcde"
+ endif
+
+ data
+AddressFour dw TEST
+ dw **5
+
+ org $800
+
+ direct $8
+ direct $0800
+
+ ds 14
+DirectByte db 123
+ align 32
+DirectWord dw 12345
+ align 48
+DirectLong dd 123456789
+ align 79
+DirectCode rts
+
+ dw 1234#12
+ dw %1010100101
+ dw (1+2)#8
+ dw 1010101#%1010101
+
+ bss
+Unin_1 db 0
+Unin_2 dw 4256
+Unin_3 dd 34568957
+
+ code
+ org $200
+
+ page
+
+ ifdef ERRORS
+1
+ equ 123
+ psscht
+ !
+ endif
+
+; ----- range checking on immediate values ------------------------------
+
+ lda #10
+ lda #100
+ ifdef ERRORS
+ lda #1000
+ lda #10000
+ lda #100000
+ lda #1000000
+ lda #10000000
+ lda #100000000
+ lda #1000000000
+ endif
+
+ ldx #10
+ ldx #100
+ ldx #1000
+ ldx #10000
+ ifdef ERRORS
+ ldx #100000
+ ldx #1000000
+ ldx #10000000
+ ldx #100000000
+ ldx #1000000000
+ endif
+
+ ifdef __6309__
+ ldq #10
+ ldq #100
+ ldq #1000
+ ldq #10000
+ ldq #100000
+ ldq #1000000
+ ldq #10000000
+ ldq #100000000
+ ldq #1000000000
+ endif
+
+ page 10 ; keep 10 lines togethre
+
+; ----- align -----------------------------------------------------------
+
+ align 16
+ align 32
+
+
+; ----- code, data, org -------------------------------------------------
+
+ code
+ org $1300
+ data
+ org $1180
+
+ code
+ lda #1
+
+ data
+Table db 1,2,3
+
+ code
+ ldx #Table
+
+
+; ----- db, fcb, fcc ----------------------------------------------------
+
+Message1 db 7,"Error",13,10,0
+
+Message2 fcb 7
+ fcc "Error"
+ fcb 13,10,0
+
+
+; ----- ds, rmb ---------------------------------------------------------
+
+ ds 10
+ rmb 10
+
+
+; ----- dw, fcw, fdb ----------------------------------------------------
+
+ dw 23457
+ fcw 13462
+ fdb 6235
+
+
+; ----- if ... else ... endif -------------------------------------------
+
+ if 5=6
+ db 0
+ if 0
+ db 1
+ else
+ db 2
+ endif
+ db 3
+ else
+ db 4
+ if 1
+ db 5
+ else
+ db 6
+ endif
+ db 7
+ endif
+
+
+; ----- list, nolist ----------------------------------------------------
+
+ nolist
+ ; comment not listed
+ db 10
+
+ list
+ ; comment is listed
+ db 10
+
+
+; ----- opt, noopt ------------------------------------------------------
+
+ noopt
+
+ opt
+
+
+; ----- nop -------------------------------------------------------------
+
+ nop
+ nop 3
+
+
+; ----- struct ----------------------------------------------------------
+
+; struct ListNode
+; dw LN_Next
+; dw LN_Previous
+; db LN_Type
+; end struct
+
+
+; ----- number bases ----------------------------------------------------
+
+ dd 1
+ dd 10
+ dd 100
+ dd 1000
+
+ dd $1
+ dd $10
+ dd $100
+ dd $1000
+
+ dd %1
+ dd %10
+ dd %100
+ dd %1000
+
+ dd @1
+ dd @10
+ dd @100
+ dd @1000
+
+ dd 2#1
+ dd 2#10
+ dd 2#100
+ dd 2#1000
+
+ dd 3#1
+ dd 3#10
+ dd 3#100
+ dd 3#1000
+ dd 3#12
+
+ dd 4#1
+ dd 4#10
+ dd 4#100
+ dd 4#1000
+ dd 4#123
+
+ dd 5#1
+ dd 5#10
+ dd 5#100
+ dd 5#1000
+ dd 5#1234
+
+ dd 6#1
+ dd 6#10
+ dd 6#100
+ dd 6#1000
+ dd 6#2345
+
+ dd 7#1
+ dd 7#10
+ dd 7#100
+ dd 7#1000
+ dd 7#3456
+
+ dd 8#1
+ dd 8#10
+ dd 8#100
+ dd 8#1000
+ dd 8#4567
+
+ dd 9#1
+ dd 9#10
+ dd 9#100
+ dd 9#1000
+ dd 9#5678
+
+ dd 10#1
+ dd 10#10
+ dd 10#100
+ dd 10#1000
+ dd 10#6789
+
+ dd 11#1
+ dd 11#10
+ dd 11#100
+ dd 11#1000
+; dd 11#789a
+
+ dd 12#1
+ dd 12#10
+ dd 12#100
+ dd 12#1000
+; dd 12#89ab
+
+ dd 13#1
+ dd 13#10
+ dd 13#100
+ dd 13#1000
+; dd 13#9abc
+
+ dd 14#1
+ dd 14#10
+ dd 14#100
+ dd 14#1000
+; dd 14#abcd
+
+ dd 15#1
+ dd 15#10
+ dd 15#100
+ dd 15#1000
+; dd 15#bcde
+
+ dd 16#1
+ dd 16#10
+ dd 16#100
+ dd 16#1000
+; dd 16#cdef
+
+ dd 17#1
+ dd 17#10
+ dd 17#100
+ dd 17#1000
+; dd 17#defg
+
+ dd 18#1
+ dd 18#10
+ dd 18#100
+ dd 18#1000
+; dd 18#efgh
+
+ dd 19#1
+ dd 19#10
+ dd 19#100
+ dd 19#1000
+; dd 19#fghi
+
+ dd 20#1
+ dd 20#10
+ dd 20#100
+ dd 20#1000
+; dd 20#ghij
+
+ dd 21#1
+ dd 21#10
+ dd 21#100
+ dd 21#1000
+; dd 21#hijk
+
+ dd 22#1
+ dd 22#10
+ dd 22#100
+ dd 22#1000
+; dd 22#ijkl
+
+ dd 23#1
+ dd 23#10
+ dd 23#100
+ dd 23#1000
+; dd 23#jklm
+
+ dd 24#1
+ dd 24#10
+ dd 24#100
+ dd 24#1000
+; dd 24#klmn
+
+ dd 25#1
+ dd 25#10
+ dd 25#100
+ dd 25#1000
+; dd 25#lmno
+
+ dd 26#1
+ dd 26#10
+ dd 26#100
+ dd 26#1000
+; dd 26#mnop
+
+ dd 27#1
+ dd 27#10
+ dd 27#100
+ dd 27#1000
+; dd 27#nopq
+
+ dd 28#1
+ dd 28#10
+ dd 28#100
+ dd 28#1000
+; dd 28#opqr
+
+ dd 29#1
+ dd 29#10
+ dd 29#100
+ dd 29#1000
+; dd 29#pqrs
+
+ dd 30#1
+ dd 30#10
+ dd 30#100
+ dd 30#1000
+; dd 30#qrst
+
+ dd 31#1
+ dd 31#10
+ dd 31#100
+ dd 31#1000
+; dd 31#rstu
+
+ dd 32#1
+ dd 32#10
+ dd 32#100
+ dd 32#1000
+; dd 32#stuv
+
+ dd 33#1
+ dd 33#10
+ dd 33#100
+ dd 33#1000
+; dd 33#tuvw
+
+ dd 34#1
+ dd 34#10
+ dd 34#100
+ dd 34#1000
+; dd 34#uvwx
+
+ dd 35#1
+ dd 35#10
+ dd 35#100
+ dd 35#1000
+; dd 35#vwxy
+
+ dd 36#1
+ dd 36#10
+ dd 36#100
+ dd 36#1000
+; dd 36#wxyz
+
+ ifdef ERRORS
+ dd 37#1
+ dd 37#10
+ dd 37#100
+ dd 37#1000
+
+ dd 1#1
+ dd 1#10
+ dd 1#100
+ dd 1#1000
+
+ dd 0#1
+ dd 0#10
+ dd 0#100
+ dd 0#1000
+ endif
+
+
+; ----- garbage in inactive if-clause -----------------------------------
+
+ if 0
+ !"#$%&'()*+,-./
+0123456789:;<=>?
+@ABCDEFGHIJKLMNO
+PQRSTUVWXYZ[\]^_
+`abcdefghijklmno
+pqrstuvwxyz{|}~
+€‚ƒ„…†‡ˆ‰Š‹ŒŽ
+‘’“”•–—˜™š›œžŸ
+ ¡¢£¤¥¦§¨©ª«¬­®¯
+°±²|´µ¶·¸¹|+¼½¾¿
+ÀÁÂÃ-ÅÆÇÈ+ÊËÌ=ÎÏ
+ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß
+àáâãäåæçèéêëìíîï
+ðñòóôõö÷øùúûüýþ
+ endif
+
+
+; +=====================================================================+
+; | |
+; | Instructions. |
+; | |
+; È=====================================================================¼
+
+; Ú---------------------------------------------------------------------¿
+; | |
+; | Register to register operations. |
+; | |
+; À---------------------------------------------------------------------Ù
+
+Start tfr a,a ; NOP
+ tfr a,b
+ tfr a,cc
+ tfr a,ccr
+ tfr a,dp
+ tfr a,dpr
+
+ tfr b,a
+ tfr b,b ; NOP
+ tfr b,cc
+ tfr b,ccr
+ tfr b,dp
+ tfr b,dpr
+
+ tfr d,d ; NOP
+ tfr d,x
+ tfr d,y
+ tfr d,u
+ tfr d,s
+ tfr d,sp
+
+ tfr x,d
+ tfr x,x ; NOP
+ tfr x,y
+ tfr x,u
+ tfr x,s
+ tfr x,sp
+
+ tfr y,d
+ tfr y,x
+ tfr y,y ; NOP
+ tfr y,u
+ tfr y,s
+ tfr y,sp
+
+ tfr u,d
+ tfr u,x
+ tfr u,y
+ tfr u,u ; NOP
+ tfr u,s
+ tfr u,sp
+
+ tfr s,d
+ tfr s,x
+ tfr s,y
+ tfr s,u
+ tfr s,s ; NOP
+ tfr s,sp ; NOP
+
+ tfr sp,d
+ tfr sp,x
+ tfr sp,y
+ tfr sp,u
+ tfr sp,s ; NOP
+ tfr sp,sp ; NOP
+
+ tfr pc,d
+ tfr pc,x
+ tfr pc,y
+ tfr pc,u
+ tfr pc,s
+ tfr pc,sp
+
+ ifdef __6309__
+ tfr a,e
+ tfr a,f
+ tfr b,e
+ tfr b,f
+
+ tfr e,a
+ tfr e,b
+ tfr e,cc
+ tfr e,ccr
+ tfr e,dp
+ tfr e,dpr
+ tfr e,e ; NOP
+ tfr e,f
+
+ tfr f,a
+ tfr f,b
+ tfr f,cc
+ tfr f,ccr
+ tfr f,dp
+ tfr f,dpr
+ tfr f,e
+ tfr f,f ; NOP
+
+ tfr d,v
+ tfr d,w
+
+ tfr v,d
+ tfr v,v ; NOP
+ tfr v,w
+ tfr v,x
+ tfr v,y
+ tfr v,u
+ tfr v,s
+ tfr v,sp
+
+ tfr w,d
+ tfr w,v
+ tfr w,w ; NOP
+ tfr w,x
+ tfr w,y
+ tfr w,u
+ tfr w,s
+ tfr w,sp
+
+ tfr x,v
+ tfr x,w
+ tfr y,v
+ tfr y,w
+ tfr u,v
+ tfr u,w
+ tfr s,v
+ tfr s,w
+ tfr pc,v
+ tfr pc,w
+
+ tfr z,a
+ tfr z,b
+ tfr z,cc
+ tfr z,ccr
+ tfr z,dp
+ tfr z,dpr
+ tfr z,e
+ tfr z,f
+ tfr z,d
+ tfr z,v
+ tfr z,w
+ tfr z,x
+ tfr z,y
+ tfr z,u
+ tfr z,s
+ tfr z,sp
+
+ tfr a,z
+ tfr b,z
+ tfr cc,z
+ tfr ccr,z
+ tfr dp,z
+ tfr dpr,z
+ tfr e,z
+ tfr f,z
+ tfr d,z
+ tfr v,z
+ tfr w,z
+ tfr x,z
+ tfr y,z
+ tfr u,z
+ tfr s,z
+ tfr sp,z
+ tfr pc,z
+ endif
+
+ ifdef ERRORS
+ tfm a,b
+ tfr a,d
+ tfr a,v
+ tfr a,w
+ tfr a,x
+ tfr a,y
+ tfr a,u
+ tfr a,s
+ tfr a,sp
+
+ tfr b,d
+ tfr b,v
+ tfr b,w
+ tfr b,x
+ tfr b,y
+ tfr b,u
+ tfr b,s
+ tfr b,sp
+ endif
+
+
+; +---------------------------------------------------------------------+
+; | |
+; | Addressing modes. |
+; | |
+; +---------------------------------------------------------------------+
+
+ lda #0
+ lda DirectByte
+ lda >DirectByte
+ lda AddressFour
+ ifdef ERRORS
+ lda <AddressFour
+ endif
+ lda 12+5*17/3
+ lda ,x
+ noopt
+ lda 0,x
+ opt
+ lda 0,x
+ lda <0,x
+ lda <<0,x
+ noopt
+ lda <<0,x
+ opt
+ lda >0,x
+ lda 1,x
+ lda <1,x
+ lda <<1,x
+ lda >1,x
+ lda 15,x
+ lda -16,x
+ lda 16,x
+ lda -17,x
+ lda 127,x
+ lda -128,x
+ lda 128,x
+ lda -129,x
+ lda FORWARD5,x
+ lda <FORWARD5,x
+ lda <<FORWARD5,x
+ lda FORWARD99,x
+ lda <FORWARD99,x
+ ifdef ERRORS
+ lda <<FORWARD99,x
+ endif
+ lda a,x
+ lda b,x
+ lda d,x
+ lda ,x+
+ lda ,x++
+ lda ,-x
+ lda ,--x
+ lda NearData,pc
+ lda <NearData,pc
+ lda AddressFour,pc
+ lda [,x]
+ lda [0,x]
+ lda [1,x]
+ lda [15,x]
+ lda [-16,x]
+ lda [17,x]
+ lda [-17,x]
+ lda [127,x]
+ lda [-128,x]
+ lda [128,x]
+ lda [-129,x]
+ lda [a,x]
+ lda [b,x]
+NearData lda [d,x]
+ lda [,x++]
+ lda [,--x]
+ lda [NearData,pc]
+ lda [>NearData,pc]
+ lda [AddressFour,pc]
+ ifdef ERRORS
+ lda [<AddressFour,pc]
+ endif
+
+FORWARD5 equ 5
+FORWARD99 equ 99
+
+ ifdef __6309__
+ lda e,x
+ lda f,x
+ lda w,x
+ lda ,w
+ lda 0,w
+ lda 1,w
+ lda ,w++
+ lda ,--w
+ lda [e,x]
+ lda [f,x]
+ lda [w,x]
+ lda [,w]
+ lda [0,w]
+ lda [1000,w]
+ lda [,w++]
+ lda [,--w]
+ endif
+
+
+; +---------------------------------------------------------------------+
+; | |
+; | Instructions in numerical order. |
+; | |
+; +---------------------------------------------------------------------+
+
+ neg DirectByte ; $00,2
+ ifdef __6309__
+ oim #123,DirectByte ; $01,3
+ aim #123,DirectByte ; $02,3
+ endif
+ com DirectByte ; $03,2
+ lsr DirectByte ; $04,2
+ ifdef __6309__
+ eim #123,DirectByte ; $05,3
+ endif
+ ror DirectByte ; $06,2
+ asr DirectByte ; $07,2
+ asl DirectByte ; $08,2
+ lsl DirectByte ; alternate
+ rol DirectByte ; $09,2
+ dec DirectByte ; $0A,2
+ ifdef __6309__
+ tim #1,DirectByte ; $0B,3
+ endif
+ inc DirectByte ; $0C,2
+ tst DirectByte ; $0D,2
+ jmp DirectByte ; $0E,2
+ clr DirectByte ; $0F,2
+
+; -----------------------------------------------------------------------
+
+ nop ; $12,1
+ nop 4 ; repeat count specified
+ sync ; $13,1
+ ifdef __6309__
+ sexw ; $14,1
+ endif
+ noopt
+ lbra AddressFour ; $16,3
+ lbsr AddressFour ; $17,3
+ opt
+ daa ; $19,1
+ orcc #1 ; $1A,2
+ orcc c ; alternate, specifying flags
+ andcc #~6 ; $1C,2
+ andcc z,v ; alternate
+ sex ; $1D,1
+ exg a,b ; $1E,2
+ tfr a,b ; $1F,2
+ ifdef __6309__
+ clrs ; using TFR to clear registers
+ clrv
+ clrx
+ clry
+ endif
+
+; -----------------------------------------------------------------------
+
+BranchTarget bra BranchTarget ; $20,2
+ brn BranchTarget ; $21,2
+ bhi BranchTarget ; $22,2
+ bls BranchTarget ; $23,2
+ bhs BranchTarget ; $24,2
+ bcc BranchTarget ; alternate
+ blo BranchTarget ; $25,2
+ bcs BranchTarget ; alternate
+ bne BranchTarget ; $26,2
+ beq BranchTarget ; $27,2
+ bvc BranchTarget ; $28,2
+ bvs BranchTarget ; $29,2
+ bpl BranchTarget ; $2A,2
+ bmi BranchTarget ; $2B,2
+ bge BranchTarget ; $2C,2
+ blt BranchTarget ; $2D,2
+ bgt BranchTarget ; $2E,2
+ ble BranchTarget ; $2F,2
+
+; -----------------------------------------------------------------------
+
+ leax a,x ; 30,2+
+ leay b,y ; 31,2+
+ leas d,s ; 32,2+
+ leau 1,u ; 33,2+
+ pshs a,b ; $34,2
+ pshs all ; alternate
+ pshs #123 ; alternate
+ puls x ; $35,2
+ puls all ; alternate
+ puls #$ff ; alternate
+ pshu ccr ; $36,2
+ pulu dpr ; $37,2
+ rts ; $39,1
+ abx ; $3A,1
+ rti ; $3B,1
+ cwai #127 ; $3C,2
+ cwai e ; alternate
+ mul ; $3D,1
+ swi ; $3F,1
+
+; -----------------------------------------------------------------------
+
+ nega ; $40,1
+ coma ; $43,1
+ lsra ; $44,1
+ rora ; $46,1
+ asra ; $47,1
+ asla ; $48,1
+ lsla ; alternate
+ rola ; $49,1
+ deca ; $4A,1
+ inca ; $4C,1
+ tsta ; $4D,1
+ clra ; $4F,1
+
+; -----------------------------------------------------------------------
+
+ negb ; $50,1
+ comb ; $53,1
+ lsrb ; $54,1
+ rorb ; $56,1
+ asrb ; $57,1
+ aslb ; $58,1
+ lslb ; alternate
+ rolb ; $59,1
+ decb ; $5A,1
+ incb ; $5C,1
+ tstb ; $5D,1
+ clrb ; $5F,1
+
+; -----------------------------------------------------------------------
+
+ neg ,x ; $60,2+
+ ifdef __6309__
+ oim #4,,x ; $61,3+
+ aim #8,,x ; $62,3+
+ endif
+ com ,x ; $63,2+
+ lsr ,x ; $64,2+
+ ifdef __6309__
+ eim #9,,x ; $65,3+
+ endif
+ ror ,x ; $66,2+
+ asr ,x ; $67,2+
+ asl ,x ; $68,2+
+ lsl ,x ; alternate
+ rol ,x ; $69,2+
+ dec ,x ; $6A,2+
+ ifdef __6309__
+ tim #123,,x ; $6B,3+
+ endif
+ inc ,x ; $6C,2+
+ tst ,x ; $6D,2+
+ jmp ,x ; $6E,2+
+ clr ,x ; $6F,2+
+
+; -----------------------------------------------------------------------
+
+ neg AddressFour ; $70,3
+ ifdef __6309__
+ oim #99,AddressFour ; $71,4
+ aim #99,AddressFour ; $72,4
+ endif
+ com AddressFour ; $73,3
+ lsr AddressFour ; $74,3
+ ifdef __6309__
+ eim #-1,AddressFour ; $75,4
+ endif
+ ror AddressFour ; $76,3
+ asr AddressFour ; $77,3
+ asl AddressFour ; $78,3
+ lsl AddressFour ; alternate
+ rol AddressFour ; $79,3
+ dec AddressFour ; $7A,3
+ ifdef __6309__
+ tim #-128,AddressFour ; $7B,4
+ endif
+ inc AddressFour ; $7C,3
+ tst AddressFour ; $7D,3
+ jmp AddressFour ; $7E,3
+ clr AddressFour ; $7F,3
+
+; -----------------------------------------------------------------------
+
+CallAddress suba #123 ; $80,2
+ cmpa #123 ; $81,2
+ sbca #123 ; $82,2
+ subd #12345 ; $83,3
+ anda #123 ; $84,2
+ bita #123 ; $85,2
+ lda #123 ; $86,2
+ eora #123 ; $88,2
+ adca #123 ; $89,2
+ ora #123 ; $8A,2
+ adda #123 ; $8B,2
+ cmpx #12345 ; $8C,3
+ bsr CallAddress ; $8D,2
+ ldx #12345 ; $8E,3
+
+; -----------------------------------------------------------------------
+
+ suba DirectByte ; $90,2
+ cmpa DirectByte ; $91,2
+ sbca DirectByte ; $92,2
+ subd DirectWord ; $93,3
+ anda DirectByte ; $94,2
+ bita DirectByte ; $95,2
+ lda DirectByte ; $96,2
+ sta DirectByte ; $97,2
+ eora DirectByte ; $98,2
+ adca DirectByte ; $99,2
+ ora DirectByte ; $9A,2
+ adda DirectByte ; $9B,2
+ cmpx DirectWord ; $9C,2
+ jsr DirectCode ; $9D,2
+ ldx DirectWord ; $9E,2
+ stx DirectWord ; $9F,2
+
+; -----------------------------------------------------------------------
+
+ suba [3,s] ; $A0,2+
+ cmpa [3,s] ; $A1,2+
+ sbca [3,s] ; $A2,2+
+ subd [3,s] ; $A3,2+
+ anda [3,s] ; $A4,2+
+ bita [3,s] ; $A5,2+
+ lda [3,s] ; $A6,2+
+ sta [3,s] ; $A7,2+
+ eora [3,s] ; $A8,2+
+ adca [3,s] ; $A9,2+
+ ora [3,s] ; $AA,2+
+ adda [3,s] ; $AB,2+
+ cmpx [3,s] ; $AC,2+
+ jsr [3,s] ; $AD,2+
+ ldx [3,s] ; $AE,2+
+ stx [3,s] ; $AF,2+
+
+; -----------------------------------------------------------------------
+
+ suba $ff00 ; $B0,3
+ cmpa $ff00 ; $B1,3
+ sbca $ff00 ; $B2,3
+ subd $ff00 ; $B3,3
+ anda $ff00 ; $B4,3
+ bita $ff00 ; $B5,3
+ lda $ff00 ; $B6,3
+ sta $ff00 ; $B7,3
+ eora $ff00 ; $B8,3
+ adca $ff00 ; $B9,3
+ ora $ff00 ; $BA,3
+ adda $ff00 ; $BB,3
+ cmpx $ff00 ; $BC,3
+ jsr $ff00 ; $BD,3
+ ldx $ff00 ; $BE,3
+ stx $ff00 ; $BF,3
+
+; -----------------------------------------------------------------------
+
+ subb #123 ; $C0,2
+ cmpb #123 ; $C1,2
+ sbcb #123 ; $C2,2
+ addd #12345 ; $C3,3
+ andb #123 ; $C4,2
+ bitb #123 ; $C5,2
+ ldb #123 ; $C6,2
+ eorb #123 ; $C8,2
+ adcb #123 ; $C9,2
+ orb #123 ; $CA,2
+ addb #123 ; $CB,2
+ ldd #12345 ; $CC,3
+ ifdef __6309__
+ ldq #123456789 ; $CD,5
+ endif
+ ldu #12345 ; $CE,3
+
+; -----------------------------------------------------------------------
+
+ subb DirectByte ; $D0,2
+ cmpb DirectByte ; $D1,2
+ sbcb DirectByte ; $D2,2
+ addd DirectWord ; $D3,3
+ andb DirectByte ; $D4,2
+ bitb DirectByte ; $D5,2
+ ldb DirectByte ; $D6,2
+ stb DirectByte ; $D7,2
+ eorb DirectByte ; $D8,2
+ adcb DirectByte ; $D9,2
+ orb DirectByte ; $DA,2
+ addb DirectByte ; $DB,2
+ ldd DirectWord ; $DC,2
+ std DirectWord ; $DD,2
+ ldu DirectWord ; $DE,2
+ stu DirectWord ; $DF,2
+
+; -----------------------------------------------------------------------
+
+; note effect of quasi-forward reference in the next line
+LocalData subb LocalData,pc ; $E0,2+
+AnotherLocal cmpb <AnotherLocal,pc ; $E1,2+
+ sbcb LocalData,pc ; $E2,2+
+ addd LocalData,pc ; $E3,2+
+ andb LocalData,pc ; $E4,2+
+ bitb LocalData,pc ; $E5,2+
+ ldb LocalData,pc ; $E6,2+
+ stb LocalData,pc ; $E7,2+
+ eorb LocalData,pc ; $E8,2+
+ adcb LocalData,pc ; $E9,2+
+ orb LocalData,pc ; $EA,2+
+ addb LocalData,pc ; $EB,2+
+ ldd LocalData,pc ; $EC,2+
+ std LocalData,pc ; $ED,2+
+ ldu LocalData,pc ; $EE,2+
+ stu LocalData,pc ; $EF,2+
+
+; -----------------------------------------------------------------------
+
+ subb LocalData ; $F0,3
+ cmpb LocalData ; $F1,3
+ sbcb LocalData ; $F2,3
+ addd LocalData ; $F3,3
+ andb LocalData ; $F4,3
+ bitb LocalData ; $F5,3
+ ldb LocalData ; $F6,3
+ stb LocalData ; $F7,3
+ eorb LocalData ; $F8,3
+ adcb LocalData ; $F9,3
+ orb LocalData ; $FA,3
+ addb LocalData ; $FB,3
+ ldd LocalData ; $FC,3
+ std LocalData ; $FD,3
+ ldu LocalData ; $FE,3
+ stu LocalData ; $FF,3
+
+; +---------------------------------------------------------------------+
+; | |
+; | Instructions with prefix byte $10. |
+; | |
+; +---------------------------------------------------------------------+
+
+ lbrn BranchTarget ; $1021,4
+ lbhi BranchTarget ; $1022,4
+ lbls BranchTarget ; $1023,4
+ lbhs BranchTarget ; $1024,4
+ lbcc BranchTarget ; alternate
+ lblo BranchTarget ; $1025,4
+ lbcs BranchTarget ; alternate
+ lbne BranchTarget ; $1026,4
+ lbeq BranchTarget ; $1027,4
+ lbvc BranchTarget ; $1028,4
+ lbvs BranchTarget ; $1029,4
+ lbpl BranchTarget ; $102A,4
+ lbmi BranchTarget ; $102B,4
+ lbge BranchTarget ; $102C,4
+ lblt BranchTarget ; $102D,4
+ lbgt BranchTarget ; $102E,4
+ lble BranchTarget ; $102F,4
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ addr a,b ; $1030,3
+ add a,b ; alternate
+ adcr w,d ; $1031,3
+ adc w,d ; alternate
+ subr d,x ; $1032,3
+ sub d,x ; alternate
+ sbcr b,a ; $1033,3
+ sbc b,a ; alternate
+ andr a,ccr ; $1034,3
+ and a,ccr ; alternate
+ orr b,dpr ; $1035,3
+ or b,dpr ; alternate
+ eorr w,d ; $1036,3
+ eor w,d ; alternate
+ cmpr d,u ; $1037,3
+ cmp d,u ; alternate
+ pshsw ; $1038,2
+ pshs w ; alternate
+ pulsw ; $1039,2
+ puls w ; alternate
+ pshuw ; $103A,2
+ pshu w ; alternate
+ puluw ; $103B,2
+ pulu w ; alternate
+ endif
+ swi2 ; $103F,2
+ swi 2 ; alternate
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ negd ; $1040,2
+ comd ; $1043,2
+ lsrd ; $1044,2
+ rord ; $1046,2
+ asrd ; $1047,2
+ asld ; $1048,2
+ rold ; $1049,2
+ decd ; $104A,2
+ incd ; $104C,2
+ tstd ; $104D,2
+ clrd ; $104F,2
+
+; -----------------------------------------------------------------------
+
+ comw ; $1053,2
+ lsrw ; $1054,2
+ rorw ; $1056,2
+ rolw ; $1059,2
+ decw ; $105A,2
+ incw ; $105C,2
+ tstw ; $105D,2
+ clrw ; $105F,2
+
+; -----------------------------------------------------------------------
+
+ subw #12345 ; $1080,4
+ cmpw #12345 ; $1081,4
+ sbcd #12345 ; $1082,4
+ endif
+ cmpd #12345 ; $1083,4
+ ifdef __6309__
+ andd #12345 ; $1084,4
+ bitd #12345 ; $1085,4
+ ldw #12345 ; $1086,4
+ eord #12345 ; $1088,4
+ adcd #12345 ; $1089,4
+ ord #12345 ; $108A,4
+ addw #12345 ; $108B,4
+ endif
+ cmpy #12345 ; $108C,4
+ ldy #12345 ; $108E,4
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ subw DirectWord ; $1090,3
+ cmpw DirectWord ; $1091,3
+ sbcd DirectWord ; $1092,3
+ endif
+ cmpd DirectWord ; $1093,3
+ ifdef __6309__
+ andd DirectWord ; $1094,3
+ bitd DirectWord ; $1095,3
+ ldw DirectWord ; $1096,3
+ stw DirectWord ; $1097,3
+ eord DirectWord ; $1098,3
+ adcd DirectWord ; $1099,3
+ ord DirectWord ; $109A,3
+ addw DirectWord ; $109B,3
+ endif
+ cmpy DirectWord ; $109C,3
+ ldy DirectWord ; $109E,3
+ sty DirectWord ; $109F,3
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ subw ,w++ ; $10A0,3+
+ cmpw ,w++ ; $10A1,3+
+ sbcd ,w++ ; $10A2,3+
+ endif
+ cmpd ,--x ; $10A3,3+
+ ifdef __6309__
+ andd ,w++ ; $10A4,3+
+ bitd ,w++ ; $10A5,3+
+ ldw ,w++ ; $10A6,3+
+ stw ,w++ ; $10A7,3+
+ eord ,w++ ; $10A8,3+
+ adcd ,w++ ; $10A9,3+
+ ord ,w++ ; $10AA,3+
+ addw ,w++ ; $10AB,3+
+ endif
+ cmpy ,--x ; $10AC,3+
+ ldy ,--x ; $10AE,3+
+ sty ,--x ; $10AF,3+
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ subw $7000 ; $10B0,4
+ cmpw $7000 ; $10B1,4
+ sbcd $7000 ; $10B2,4
+ endif
+ cmpd $7000 ; $10B3,4
+ ifdef __6309__
+ andd $7000 ; $10B4,4
+ bitd $7000 ; $10B5,4
+ ldw $7000 ; $10B6,4
+ stw $7000 ; $10B7,4
+ eord $7000 ; $10B8,4
+ adcd $7000 ; $10B9,4
+ ord $7000 ; $10BA,4
+ addw $7000 ; $10BB,4
+ endif
+ cmpy $7000 ; $10BC,4
+ ldy $7000 ; $10BE,4
+ sty $7000 ; $10BF,4
+
+; -----------------------------------------------------------------------
+
+ lds #12345 ; $10CE,4
+
+ ifdef __6309__
+ ldq DirectLong ; $10DC,3
+ stq DirectLong ; $10DD,3
+ endif
+ lds DirectWord ; $10DE,3
+ sts DirectWord ; $10DF,3
+
+ ifdef __6309__
+ ldq ,x ; $10EC,3+
+ stq ,x ; $10ED,3+
+ endif
+ lds ,x ; $10EE,3+
+ sts ,x ; $10EF,3+
+
+ ifdef __6309__
+ ldq AddressFour ; $10FC,4
+ stq AddressFour ; $10FD,4
+ endif
+ lds AddressFour ; $10FE,4
+ sts AddressFour ; $10FF,4
+
+; +---------------------------------------------------------------------+
+; | |
+; | Instructions with prefix byte $11. |
+; | |
+; +---------------------------------------------------------------------+
+
+ ifdef __6309__
+ band a.7,DirectByte.0 ; $1130,4
+ biand b.6,DirectByte.1 ; $1131,4
+ bor cc.5,DirectByte.2 ; $1132,4
+ bior a.4,DirectByte.3 ; $1133,4
+ beor b.3,DirectByte.4 ; $1134,4
+ bieor cc.2,DirectByte.5 ; $1135,4
+ ldbt ccr.1,DirectByte.6 ; $1136,4
+ stbt ccr.0,DirectByte.7 ; $1137,4
+
+ tfr x+,y+ ; $1138,3
+ tfm x+,y+ ; alternate
+ tfr u-,x- ; $1139,3
+ tfm u-,x- ; alternate
+ tfr s+,x ; $113A,3
+ tfm s+,x ; alternate
+ tfr x,y+ ; $113B,3
+ tfm x,y+ ; alternate
+ bitmd #128 ; $113C,3
+ ldmd #1 ; $113D,3
+ endif
+ swi3 ; $113F,2
+ swi 3 ; alternate
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ come ; $1143,2
+ dece ; $114A,2
+ ince ; $114C,2
+ tste ; $114D,2
+ clre ; $114F,2
+
+ comf ; $1153,2
+ decf ; $115A,2
+ incf ; $115C,2
+ tstf ; $115D,2
+ clrf ; $115F,2
+ endif
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ sube #123 ; $1180,3
+ cmpe #123 ; $1181,3
+ endif
+ cmpu #12345 ; $1183,4
+ ifdef __6309__
+ lde #123 ; $1186,3
+ adde #123 ; $118B,3
+ endif
+ cmps #12345 ; $118C,4
+ ifdef __6309__
+ divd #123 ; $118D,3
+ divq #12345 ; $118E,4
+ muld #12345 ; $118F,4
+ endif
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ sube DirectByte ; $1190,3
+ cmpe DirectByte ; $1191,3
+ endif
+ cmpu DirectWord ; $1193,3
+ ifdef __6309__
+ lde DirectByte ; $1196,3
+ ste DirectByte ; $1197,3
+ adde DirectByte ; $119B,3
+ endif
+ cmps DirectWord ; $119C,3
+ ifdef __6309__
+ divd DirectWord ; $119D,3
+ divq DirectWord ; $119E,3
+ muld DirectWord ; $119F,3
+ endif
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ sube ,s+ ; $11A0,3+
+ cmpe ,s+ ; $11A1,3+
+ endif
+ cmpu ,s++ ; $11A3,3+
+ ifdef __6309__
+ lde ,s+ ; $11A6,3+
+ ste ,s+ ; $11A7,3+
+ adde ,s+ ; $11AB,3+
+ endif
+ cmps ,s++ ; $11AC,3+
+ ifdef __6309__
+ divd ,s+ ; $11AD,3+
+ divq ,s++ ; $11AE,3+
+ muld ,s++ ; $11AF,3+
+ endif
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ sube $9000 ; $11B0,4
+ cmpe $9000 ; $11B1,4
+ endif
+ cmpu $9000 ; $11B3,4
+ ifdef __6309__
+ lde $9000 ; $11B6,4
+ ste $9000 ; $11B7,4
+ adde $9000 ; $11BB,4
+ endif
+ cmps $9000 ; $11BC,4
+ ifdef __6309__
+ divd $9000 ; $11BD,4
+ divq $9000 ; $11BE,4
+ muld $9000 ; $11BF,4
+ endif
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ subf #123 ; $11C0,3
+ cmpf #123 ; $11C1,3
+ ldf #123 ; $11C6,3
+ addf #123 ; $11CB,3
+ endif
+
+; -----------------------------------------------------------------------
+
+ ifdef __6309__
+ subf DirectByte ; $11D0,3
+ cmpf DirectByte ; $11D1,3
+ ldf DirectByte ; $11D6,3
+ stf DirectByte ; $11D7,3
+ addf DirectByte ; $11DB,3
+
+ subf ,s+ ; $11E0,3+
+ cmpf ,s+ ; $11E1,3+
+ ldf ,s+ ; $11E6,3+
+ stf ,s+ ; $11E7,3+
+ addf ,s+ ; $11EB,3+
+
+ subf $9000 ; $11F0,4
+ cmpf $9000 ; $11F1,4
+ ldf $9000 ; $11F6,4
+ stf $9000 ; $11F7,4
+ addf $9000 ; $11FB,4
+ endif
+
+
+ end Start
+; ----- EOF -------------------------------------------------------------
+
diff --git a/tests/t_full09/t_full09.doc b/tests/t_full09/t_full09.doc
new file mode 100644
index 0000000..1121b25
--- /dev/null
+++ b/tests/t_full09/t_full09.doc
@@ -0,0 +1,6 @@
++----------------------- Test Application FULL09 ----------------------------+
+| |
+| This is a bit more thorough (synthetic) test of the 6809/6309 in- |
+| tion set, borrowed from another 6809 assembler ;-) |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_full09/t_full09.ori b/tests/t_full09/t_full09.ori
new file mode 100644
index 0000000..564da0d
--- /dev/null
+++ b/tests/t_full09/t_full09.ori
Binary files differ
diff --git a/tests/t_h8_3/asflags b/tests/t_h8_3/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_h8_3/asflags
diff --git a/tests/t_h8_3/t_h8_3.asm b/tests/t_h8_3/t_h8_3.asm
new file mode 100644
index 0000000..47c8743
--- /dev/null
+++ b/tests/t_h8_3/t_h8_3.asm
@@ -0,0 +1,353 @@
+ cpu hd6413309
+ maxmode on
+ page 0
+ relaxed on
+
+ dc.w 1234
+ dc.w $4d2
+ dc.w @2322
+ dc.w %10011010010
+ dc.w 4d2h
+ dc.w 2322o
+ dc.w 10011010010b
+ dc.w 0x4d2
+ dc.w 02322
+
+ nop
+ sleep
+ rts
+ rte
+
+ eepmov
+ eepmov.b
+ eepmov.w
+
+ dec r2h
+ dec #1,r5l
+ dec r4
+ dec #1,e6
+ dec #2,e1
+ dec er1
+ dec #1,er4
+ dec #2,er7
+ inc r2h
+ inc #1,r5l
+ inc r4
+ inc #1,e6
+ inc #2,e1
+ inc er1
+ inc #1,er4
+ inc #2,er7
+
+targ: bsr targ
+ bsr.s targ
+ bsr.l targ
+ bra targ
+ bra.s targ
+ bra.l targ
+ bt targ
+ bt.s targ
+ bt.l targ
+ brn targ
+ brn.s targ
+ brn.l targ
+ bf targ
+ bf.s targ
+ bf.l targ
+ bhi targ
+ bhi.s targ
+ bhi.l targ
+ bls targ
+ bls.s targ
+ bls.l targ
+ bcc targ
+ bcc.s targ
+ bcc.l targ
+ bhs targ
+ bhs.s targ
+ bhs.l targ
+ bcs targ
+ bcs.s targ
+ bcs.l targ
+ blo targ
+ blo.s targ
+ blo.l targ
+ bne targ
+ bne.s targ
+ bne.l targ
+ beq targ
+ beq.l targ
+ bvc targ
+ bvc.l targ
+ bvs targ
+ bvs.l targ
+ bpl targ
+ bpl.l targ
+ bmi targ
+ bmi.l targ
+ bge targ
+ bge.l targ
+ blt targ
+ blt.l targ
+ bgt targ
+ bgt.l targ
+ ble targ
+ ble.l targ
+
+ rotl r4h
+ rotl r2
+ rotl er1
+ rotr r2l
+ rotr r1
+ rotr er5
+ rotxl r2h
+ rotxl e4
+ rotxl er2
+ rotxr r6h
+ rotxr e0
+ rotxr er7
+ shal r3l
+ shal r6
+ shal er0
+ shar r5l
+ shar r2
+ shar er6
+ shll r2h
+ shll e4
+ shll er5
+ shlr r1l
+ shlr r7
+ shlr er4
+
+ not r7h
+ not r6
+ not er2
+ neg r2l
+ neg e2
+ neg er5
+
+ exts r5
+ extu e3
+ exts er4
+ extu er6
+
+ and r5h,r3l
+ and #10,r2h
+ and r7,e1
+ and #%1101,r1
+ and er2,er6
+ and #$12345678,er3
+ andc #$20,ccr
+ or r6h,r4l
+ or #20,r3h
+ or r0,e2
+ or #%11101,r2
+ or er2,er7
+ or #$12345678,er4
+ orc #$30,ccr
+ xor r4h,r2l
+ xor #$08,r1h
+ xor r6,e0
+ xor #%101101,r0
+ xor er1,er5
+ xor #$12345678,er2
+ xorc #$30,ccr
+
+ daa r1l
+ das r5h
+
+ addx #10,r5l
+ addx r1h,r1l
+ subx #$55,r7h
+ subx r3h,r0l
+
+ adds #1,er0
+ adds #2,er4
+ adds #4,er5
+ subs #1,er6
+ subs #2,er3
+ subs #4,er1
+
+ divxs r4h,e2
+ divxs r4,er5
+ divxu r1l,r3
+ divxu e6,er7
+ mulxs r0l,e6
+ mulxs r5,er2
+ mulxu r7h,r5
+ mulxu e3,er4
+
+ add r1h,r2l
+ add #$34,r6h
+ add r2,e3
+ add #%10101010101010,e5
+ add er3,er1
+ add #1000000,er4
+ sub r1l,r2h
+ sub r6,e1
+ sub #%10101010101010,r2
+ sub er1,er5
+ sub #1000000,er6
+ cmp r1h,r2l
+ cmp #$34,r6h
+ cmp r2,e3
+ cmp #%10101010101010,e5
+ cmp er3,er1
+ cmp #1000000,er4
+
+
+ pop r5
+ push e2
+ pop er1
+ push er6
+
+ mov r2l,r5h
+ mov r1,e2
+ mov er5,er2
+
+ mov.b @er4,r6h
+ mov.b r6h,@er4
+ mov.w @er1,e7
+ mov.w e7,@er1
+ mov.l @er5,er2
+ mov.l er2,@er5
+
+ mov.b @er2+,r5l
+ mov.b r5l,@-er2
+ mov.w @er5+,r4
+ mov.w r4,@-er5
+ mov.l @er6+,er1
+ mov.l er1,@-er6
+
+ mov.b @(-100,er2),r4l
+ mov.b r4l,@(-100,er2)
+ mov.w @(200,er4),e3
+ mov.w e3,@(200,er4)
+ mov.l @(-300,sp),er5
+ mov.l er5,@(-300,sp)
+
+ mov.b @(-100000,er4),r3h
+ mov.b r3h,@(-100000,er4)
+ mov.w @(200000,er2),r6
+ mov.w r6,@(200000,er2)
+ mov.l @(-300000,er5),er1
+ mov.l er1,@(-300000,er5)
+
+ mov.b $ffff20,r1h
+ mov.b r1h,$ffff20
+ mov.w $ffffa4,e6
+ mov.w e6,$ffffa4
+ mov.l $ffffc0,er3
+ mov.l er3,$ffffc0
+
+ mov.b $1234,r3h
+ mov.b r3h,$1234
+ mov.w $2345,e5
+ mov.w e5,$2345
+ mov.l $3456,er4
+ mov.l er4,$3456
+
+ mov.b $123456,r3l
+ mov.b r3l,$123456
+ mov.w $234567,r5
+ mov.w r5,$234567
+ mov.l $345678,er7
+ mov.l er7,$345678
+
+ mov.b #$12,r4l
+ mov.w #$1234,e2
+ mov.l #$12345678,er3
+
+ movfpe @1234,r4l
+ movtpe r4l,@1234
+
+ band #4,r2l
+ band #2,@er3
+ band #6,$ffff4e
+ biand #4,r2l
+ biand #2,@er3
+ biand #6,$ffff4e
+ bild #4,r2l
+ bild #2,@er3
+ bild #6,$ffff4e
+ bior #4,r2l
+ bior #2,@er3
+ bior #6,$ffff4e
+ bist #4,r2l
+ bist #2,@er3
+ bist #6,$ffff4e
+ bixor #4,r2l
+ bixor #2,@er3
+ bixor #6,$ffff4e
+ bld #4,r2l
+ bld #2,@er3
+ bld #6,$ffff4e
+ bor #4,r2l
+ bor #2,@er3
+ bor #6,$ffff4e
+ bst #4,r2l
+ bst #2,@er3
+ bst #6,$ffff4e
+ bxor #4,r2l
+ bxor #2,@er3
+ bxor #6,$ffff4e
+
+ bclr #3,r5h
+ bclr #7,@er6
+ bclr #2,$ffff1a
+ bclr r5l,r6h
+ bclr r1h,@er4
+ bclr r7h,$ffff24
+ bnot #3,r5h
+ bnot #7,@er6
+ bnot #2,$ffff1a
+ bnot r5l,r6h
+ bnot r1h,@er4
+ bnot r7h,$ffff24
+ bset #3,r5h
+ bset #7,@er6
+ bset #2,$ffff1a
+ bset r5l,r6h
+ bset r1h,@er4
+ bset r7h,$ffff24
+ btst #3,r5h
+ btst #7,@er6
+ btst #2,$ffff1a
+ btst r5l,r6h
+ btst r1h,@er4
+ btst r7h,$ffff24
+
+ jmp @er2
+ jmp $123456
+ jmp @@$35
+ jsr @er2
+ jsr $123456
+ jsr @@$35
+
+ ldc #23,ccr
+ ldc r5h,ccr
+ stc ccr,r5h
+ ldc @er6,ccr
+ stc ccr,@er6
+ ldc @er3+,ccr
+ stc ccr,@-er3
+ ldc @(100,er1),ccr
+ stc ccr,@(100,er1)
+ ldc @(100000,er5),ccr
+ stc ccr,@(100000,er5)
+ ldc $1234,ccr
+ stc ccr,$1234
+ ldc $123456,ccr
+ stc ccr,$123456
+
+ dc 20
+
+ dc.b 5,"Hallo"
+ dc.w 1,2,3,4
+ dc.l 1,2,3,4
+; dc.q 1,2,3,4 ; omit for the sake of non-64-bit-platforms...
+ dc.s 1,2,3,4
+ dc.d 1,2,3,4
+ dc.x 1,2,3,4
+ dc.p 1,2,3,4
+
diff --git a/tests/t_h8_3/t_h8_3.doc b/tests/t_h8_3/t_h8_3.doc
new file mode 100644
index 0000000..d4ee7a9
--- /dev/null
+++ b/tests/t_h8_3/t_h8_3.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application H8_3 ----------------------------+
+| |
+| This is a (synthetic) test of the H8/300(H) instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_h8_3/t_h8_3.ori b/tests/t_h8_3/t_h8_3.ori
new file mode 100644
index 0000000..e2e4cbd
--- /dev/null
+++ b/tests/t_h8_3/t_h8_3.ori
Binary files differ
diff --git a/tests/t_h8_5/asflags b/tests/t_h8_5/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_h8_5/asflags
diff --git a/tests/t_h8_5/t_h8_5.asm b/tests/t_h8_5/t_h8_5.asm
new file mode 100644
index 0000000..8987d73
--- /dev/null
+++ b/tests/t_h8_5/t_h8_5.asm
@@ -0,0 +1,229 @@
+ cpu hd6475348
+ page 0
+ maxmode on
+ padding off
+
+ assume br:0,dp:0
+
+ add.b r5,sp
+ add.w r2,r4
+ add.b @r4,r2
+ add.w @r4,r2
+ add.b @(20,r4),r2
+ add.w @(20:8,r4),r2
+ add.b @(20:16,r4),r2
+ add.w @(2000,r4),r2
+ add.b @(2000:16,r4),r2
+ add.w @-r4,r2
+ add.b @r4+,r2
+ add.w @20,r2
+ add.b @20:16,r2
+ add.w @2000,r2
+ add.b #5,r2
+ add.w #100,r2
+ add.b:g #1,r2
+ add.w:g #-1,r2
+ add.b #1,r2
+ add.w #-1,r2
+
+ adds.w #$10,r3
+
+ addx.b @($20,r4),r0
+
+ and.b @$f8:8,r1
+
+ andc.b #$fe,ccr
+
+ bra *+20
+ bra *+2000
+ bt *+20
+ bt *+2000
+ brn *+20
+ brn *+2000
+ bf *+20
+ bf *+2000
+ bhi *+20
+ bhi *+2000
+ bls *+20
+ bls *+2000
+ bcc *+20
+ bcc *+2000
+ bhs *+20
+ bhs *+2000
+ bcs *+20
+ bcs *+2000
+ blo *+20
+ blo *+2000
+ bne *+20
+ bne *+2000
+ beq *+20
+ beq *+2000
+ bvc *+20
+ bvc *+2000
+ bvs *+20
+ bvs *+2000
+ bpl *+20
+ bpl *+2000
+ bmi *+20
+ bmi *+2000
+ bge *+20
+ bge *+2000
+ blt *+20
+ blt *+2000
+ bgt *+20
+ bgt *+2000
+ ble *+20
+ ble *+2000
+
+ bclr.b #7,@$ff00
+
+ bnot.w r0,r1
+
+ bset.b #0,@r1+
+
+ bsr *+20
+ bsr *+2000
+
+ btst.b r0,@$f0:8
+
+ clr.w @($1000,r5)
+
+ cmp:g.b #$aa,@-r3
+ cmp.b #$aa,@-r3
+ cmp:e.b #$00,r0
+ cmp.b #$00,r0
+ cmp:i.w #$ffff,r1
+ cmp.w #$ffff,r1
+
+ dadd r0,r1
+
+ divxu.w @r3,r0
+
+ dsub r2,r3
+
+ exts r0
+
+ extu r1
+
+ jmp @(#$10,r4)
+
+ jsr @($fff,r3)
+
+ ldc.b #$01,dp
+
+ ldm @sp+,(r0,r2-r4)
+
+ link fp,#-4
+
+ mov:g.w r0,@r1
+ mov.w r0,@r1
+ mov:e.b #$55,r0
+ mov.b #$55,r0
+ mov:f.b @(4,r6),r0
+ mov.b @(4,r6),r0
+ mov:f.b r0,@(4,r6)
+ mov.b r0,@(4,r6)
+ mov:i.w #$ff00,r5
+ mov.w #$ff00,r5
+ mov:l.b @$a0,r0
+ mov.b @$a0,r0
+ mov:s.w r0,@$a0:8
+ mov.w r0,@$a0:8
+
+ movfpe @$f000,r0
+
+ movtpe r0,@r1
+
+ mulxu.b r0,r1
+
+ neg.w r0
+
+ nop
+
+ not.b @($10,r2)
+
+ or.b @$f0:8,r1
+
+ orc.w #$0700,sr
+
+ pjmp @r4
+
+ pjsr @$010000
+
+ prtd #8
+
+ prts
+
+ rotl.w r0
+
+ rotr.b @r1
+
+ rotxl.w @($02,r1)
+
+ rotxr.b @$fa:8
+
+ rtd #400
+
+ rte
+
+ rts
+
+ scb/eq r4,*-20
+
+ shal.b @r2+
+
+ shar.w @$ff00
+
+ shll.b r1
+
+ shlr.w @-r1
+
+ sleep
+
+ stc.b br,@-sp
+
+ stm (r0-r3),@-sp
+
+ sub.w @r1,r0
+
+ subs.w #2,r2
+
+ subx.w @r2+,r0
+
+ swap r0
+
+ tas @$f000
+
+ trapa #4
+
+ trap/vs
+
+ tst @($1000,r1)
+
+ unlk fp
+
+ xch r0,r1
+
+ xor.b @$a0:8,r0
+
+ xorc.b #$01,ccr
+
+ bra *+126
+ bra *+127
+ bra *+128
+ bra *+129
+ bra *+130
+ bra *+131
+ bra *+132
+ bra *+133
+ bra *+134
+ bra *-123
+ bra *-124
+ bra *-125
+ bra *-126
+ bra *-127
+ bra *-128
+ bra *-129
+ bra *-130
+ bra *-131
+
diff --git a/tests/t_h8_5/t_h8_5.doc b/tests/t_h8_5/t_h8_5.doc
new file mode 100644
index 0000000..75c6b34
--- /dev/null
+++ b/tests/t_h8_5/t_h8_5.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application H8_5 ----------------------------+
+| |
+| This is a (synthetic) test of the H8/500 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_h8_5/t_h8_5.ori b/tests/t_h8_5/t_h8_5.ori
new file mode 100644
index 0000000..492cd40
--- /dev/null
+++ b/tests/t_h8_5/t_h8_5.ori
Binary files differ
diff --git a/tests/t_m16c/asflags b/tests/t_m16c/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_m16c/asflags
diff --git a/tests/t_m16c/t_m16c.asm b/tests/t_m16c/t_m16c.asm
new file mode 100644
index 0000000..6fe5136
--- /dev/null
+++ b/tests/t_m16c/t_m16c.asm
@@ -0,0 +1,4051 @@
+;
+;; A comprehensive mnemonic exerciser, thanks to a company in Sweden who
+;; shall go nameless... all mnemonics and addressing modes are represented.
+;;
+;; =RMS=
+;;
+;
+ cpu M30620
+
+ ORG 0
+
+ ABS.B [A0]
+ ABS.B 12H[A0]
+ ABS.B 12H[FB]
+ ABS.B 12H[SB]
+ ABS.B 2345H
+ ABS.B 2345H[A0]
+ ABS.B 2345H[SB]
+ ABS.B R0L
+ ABS.W [A0]
+ ABS.W 12H[A0]
+ ABS.W 12H[FB]
+ ABS.W 12H[SB]
+ ABS.W 2345H
+ ABS.W 2345H[A0]
+ ABS.W 2345H[SB]
+ ABS.W A0
+ ABS.W R0
+ ADC.B #7,[A0]
+ ADC.B #7,12H[A0]
+ ADC.B #7,12H[FB]
+ ADC.B #7,12H[SB]
+ ADC.B #7,2345H
+ ADC.B #7,2345H[A0]
+ ADC.B #7,2345H[SB]
+ ADC.B #7,A0
+ ADC.B #7,R0L
+ ADC.B [A0],[A0]
+ ADC.B [A0],12H[A0]
+ ADC.B [A0],12H[FB]
+ ADC.B [A0],12H[SB]
+ ADC.B [A0],2345H
+ ADC.B [A0],2345H[A0]
+ ADC.B [A0],2345H[SB]
+ ADC.B [A0],A0
+ ADC.B [A0],R0L
+ ADC.B 12H[A0],[A0]
+ ADC.B 12H[A0],12H[A0]
+ ADC.B 12H[A0],12H[FB]
+ ADC.B 12H[A0],12H[SB]
+ ADC.B 12H[A0],2345H
+ ADC.B 12H[A0],2345H[A0]
+ ADC.B 12H[A0],2345H[SB]
+ ADC.B 12H[A0],A0
+ ADC.B 12H[A0],R0L
+ ADC.B 12H[FB],[A0]
+ ADC.B 12H[FB],12H[A0]
+ ADC.B 12H[FB],12H[FB]
+ ADC.B 12H[FB],12H[SB]
+ ADC.B 12H[FB],2345H
+ ADC.B 12H[FB],2345H[A0]
+ ADC.B 12H[FB],2345H[SB]
+ ADC.B 12H[FB],A0
+ ADC.B 12H[FB],R0L
+ ADC.B 12H[SB],[A0]
+ ADC.B 12H[SB],12H[A0]
+ ADC.B 12H[SB],12H[FB]
+ ADC.B 12H[SB],12H[SB]
+ ADC.B 12H[SB],2345H
+ ADC.B 12H[SB],2345H[A0]
+ ADC.B 12H[SB],2345H[SB]
+ ADC.B 12H[SB],A0
+ ADC.B 12H[SB],R0L
+ ADC.B 2345H,[A0]
+ ADC.B 2345H,12H[A0]
+ ADC.B 2345H,12H[FB]
+ ADC.B 2345H,12H[SB]
+ ADC.B 2345H,2345H
+ ADC.B 2345H,2345H[A0]
+ ADC.B 2345H,2345H[SB]
+ ADC.B 2345H,A0
+ ADC.B 2345H,R0L
+ ADC.B 2345H[A0],[A0]
+ ADC.B 2345H[A0],12H[A0]
+ ADC.B 2345H[A0],12H[FB]
+ ADC.B 2345H[A0],12H[SB]
+ ADC.B 2345H[A0],2345H
+ ADC.B 2345H[A0],2345H[A0]
+ ADC.B 2345H[A0],2345H[SB]
+ ADC.B 2345H[A0],A0
+ ADC.B 2345H[A0],R0L
+ ADC.B 2345H[SB],[A0]
+ ADC.B 2345H[SB],12H[A0]
+ ADC.B 2345H[SB],12H[FB]
+ ADC.B 2345H[SB],12H[SB]
+ ADC.B 2345H[SB],2345H
+ ADC.B 2345H[SB],2345H[A0]
+ ADC.B 2345H[SB],2345H[SB]
+ ADC.B 2345H[SB],A0
+ ADC.B 2345H[SB],R0L
+ ADC.B A0,[A0]
+ ADC.B A0,12H[A0]
+ ADC.B A0,12H[FB]
+ ADC.B A0,12H[SB]
+ ADC.B A0,2345H
+ ADC.B A0,2345H[A0]
+ ADC.B A0,2345H[SB]
+ ADC.B A0,R0L
+ ADC.B R0L,[A0]
+ ADC.B R0L,12H[A0]
+ ADC.B R0L,12H[FB]
+ ADC.B R0L,12H[SB]
+ ADC.B R0L,2345H
+ ADC.B R0L,2345H[A0]
+ ADC.B R0L,2345H[SB]
+ ADC.B R0L,A0
+ ADC.B R0L,R0L
+ ADC.W #2345H,[A0]
+ ADC.W #2345H,12H[A0]
+ ADC.W #2345H,12H[FB]
+ ADC.W #2345H,12H[SB]
+ ADC.W #2345H,2345H
+ ADC.W #2345H,2345H[A0]
+ ADC.W #2345H,2345H[SB]
+ ADC.W #2345H,A0
+ ADC.W #2345H,R0
+ ADC.W #7,[A0]
+ ADC.W #7,12H[A0]
+ ADC.W #7,12H[FB]
+ ADC.W #7,12H[SB]
+ ADC.W #7,2345H
+ ADC.W #7,2345H[A0]
+ ADC.W #7,2345H[SB]
+ ADC.W #7,A0
+ ADC.W #7,R0
+ ADC.W [A0],[A0]
+ ADC.W [A0],12H[A0]
+ ADC.W [A0],12H[FB]
+ ADC.W [A0],12H[SB]
+ ADC.W [A0],2345H
+ ADC.W [A0],2345H[A0]
+ ADC.W [A0],2345H[SB]
+ ADC.W [A0],A0
+ ADC.W [A0],R0
+ ADC.W 12H[A0],[A0]
+ ADC.W 12H[A0],12H[A0]
+ ADC.W 12H[A0],12H[FB]
+ ADC.W 12H[A0],12H[SB]
+ ADC.W 12H[A0],2345H
+ ADC.W 12H[A0],2345H[A0]
+ ADC.W 12H[A0],2345H[SB]
+ ADC.W 12H[A0],A0
+ ADC.W 12H[A0],R0
+ ADC.W 12H[FB],[A0]
+ ADC.W 12H[FB],12H[A0]
+ ADC.W 12H[FB],12H[FB]
+ ADC.W 12H[FB],12H[SB]
+ ADC.W 12H[FB],2345H
+ ADC.W 12H[FB],2345H[A0]
+ ADC.W 12H[FB],2345H[SB]
+ ADC.W 12H[FB],A0
+ ADC.W 12H[FB],R0
+ ADC.W 12H[SB],[A0]
+ ADC.W 12H[SB],12H[A0]
+ ADC.W 12H[SB],12H[FB]
+ ADC.W 12H[SB],12H[SB]
+ ADC.W 12H[SB],2345H
+ ADC.W 12H[SB],2345H[A0]
+ ADC.W 12H[SB],2345H[SB]
+ ADC.W 12H[SB],A0
+ ADC.W 12H[SB],R0
+ ADC.W 2345H,[A0]
+ ADC.W 2345H,12H[A0]
+ ADC.W 2345H,12H[FB]
+ ADC.W 2345H,12H[SB]
+ ADC.W 2345H,2345H
+ ADC.W 2345H,2345H[A0]
+ ADC.W 2345H,2345H[SB]
+ ADC.W 2345H,A0
+ ADC.W 2345H,R0
+ ADC.W 2345H[A0],[A0]
+ ADC.W 2345H[A0],12H[A0]
+ ADC.W 2345H[A0],12H[FB]
+ ADC.W 2345H[A0],12H[SB]
+ ADC.W 2345H[A0],2345H
+ ADC.W 2345H[A0],2345H[A0]
+ ADC.W 2345H[A0],2345H[SB]
+ ADC.W 2345H[A0],A0
+ ADC.W 2345H[A0],R0
+ ADC.W 2345H[SB],[A0]
+ ADC.W 2345H[SB],12H[A0]
+ ADC.W 2345H[SB],12H[FB]
+ ADC.W 2345H[SB],12H[SB]
+ ADC.W 2345H[SB],2345H
+ ADC.W 2345H[SB],2345H[A0]
+ ADC.W 2345H[SB],2345H[SB]
+ ADC.W 2345H[SB],A0
+ ADC.W 2345H[SB],R0
+ ADC.W A0,[A0]
+ ADC.W A0,12H[A0]
+ ADC.W A0,12H[FB]
+ ADC.W A0,12H[SB]
+ ADC.W A0,2345H
+ ADC.W A0,2345H[A0]
+ ADC.W A0,2345H[SB]
+ ADC.W A0,A0
+ ADC.W A0,R0
+ ADC.W R0,[A0]
+ ADC.W R0,12H[A0]
+ ADC.W R0,12H[FB]
+ ADC.W R0,12H[SB]
+ ADC.W R0,2345H
+ ADC.W R0,2345H[A0]
+ ADC.W R0,2345H[SB]
+ ADC.W R0,A0
+ ADC.W R0,R0
+ ADCF.B [A0]
+ ADCF.B 12H[A0]
+ ADCF.B 12H[FB]
+ ADCF.B 12H[SB]
+ ADCF.B 2345H
+ ADCF.B 2345H[A0]
+ ADCF.B 2345H[SB]
+ ADCF.B R0L
+ ADCF.W [A0]
+ ADCF.W 12H[A0]
+ ADCF.W 12H[FB]
+ ADCF.W 12H[SB]
+ ADCF.W 2345H
+ ADCF.W 2345H[A0]
+ ADCF.W 2345H[SB]
+ ADCF.W A0
+ ADCF.W R0
+ ADD.B:G #7,[A0]
+ ADD.B:G #7,12H[A0]
+ ADD.B:G #7,12H[FB]
+ ADD.B:G #7,12H[SB]
+ ADD.B:G #7,2345H
+ ADD.B:G #7,2345H[A0]
+ ADD.B:G #7,2345H[SB]
+ ADD.B:G #7,A0
+ ADD.B:G #7,R0L
+ ADD.B:G #7,SP
+ ADD.B:G [A0],[A0]
+ ADD.B:G [A0],12H[A0]
+ ADD.B:G [A0],12H[FB]
+ ADD.B:G [A0],12H[SB]
+ ADD.B:G [A0],2345H
+ ADD.B:G [A0],2345H[A0]
+ ADD.B:G [A0],2345H[SB]
+ ADD.B:G [A0],A0
+ ADD.B:G [A0],R0L
+ ADD.B:G 12H[A0],[A0]
+ ADD.B:G 12H[A0],12H[A0]
+ ADD.B:G 12H[A0],12H[FB]
+ ADD.B:G 12H[A0],12H[SB]
+ ADD.B:G 12H[A0],2345H
+ ADD.B:G 12H[A0],2345H[A0]
+ ADD.B:G 12H[A0],2345H[SB]
+ ADD.B:G 12H[A0],A0
+ ADD.B:G 12H[A0],R0L
+ ADD.B:G 12H[FB],[A0]
+ ADD.B:G 12H[FB],12H[A0]
+ ADD.B:G 12H[FB],12H[FB]
+ ADD.B:G 12H[FB],12H[SB]
+ ADD.B:G 12H[FB],2345H
+ ADD.B:G 12H[FB],2345H[A0]
+ ADD.B:G 12H[FB],2345H[SB]
+ ADD.B:G 12H[FB],A0
+ ADD.B:G 12H[FB],R0L
+ ADD.B:G 12H[SB],[A0]
+ ADD.B:G 12H[SB],12H[A0]
+ ADD.B:G 12H[SB],12H[FB]
+ ADD.B:G 12H[SB],12H[SB]
+ ADD.B:G 12H[SB],2345H
+ ADD.B:G 12H[SB],2345H[A0]
+ ADD.B:G 12H[SB],2345H[SB]
+ ADD.B:G 12H[SB],A0
+ ADD.B:G 12H[SB],R0L
+ ADD.B:G 2345H,[A0]
+ ADD.B:G 2345H,12H[A0]
+ ADD.B:G 2345H,12H[FB]
+ ADD.B:G 2345H,12H[SB]
+ ADD.B:G 2345H,2345H
+ ADD.B:G 2345H,2345H[A0]
+ ADD.B:G 2345H,2345H[SB]
+ ADD.B:G 2345H,A0
+ ADD.B:G 2345H,R0L
+ ADD.B:G 2345H[A0],[A0]
+ ADD.B:G 2345H[A0],12H[A0]
+ ADD.B:G 2345H[A0],12H[FB]
+ ADD.B:G 2345H[A0],12H[SB]
+ ADD.B:G 2345H[A0],2345H
+ ADD.B:G 2345H[A0],2345H[A0]
+ ADD.B:G 2345H[A0],2345H[SB]
+ ADD.B:G 2345H[A0],A0
+ ADD.B:G 2345H[A0],R0L
+ ADD.B:G 2345H[SB],[A0]
+ ADD.B:G 2345H[SB],12H[A0]
+ ADD.B:G 2345H[SB],12H[FB]
+ ADD.B:G 2345H[SB],12H[SB]
+ ADD.B:G 2345H[SB],2345H
+ ADD.B:G 2345H[SB],2345H[A0]
+ ADD.B:G 2345H[SB],2345H[SB]
+ ADD.B:G 2345H[SB],A0
+ ADD.B:G 2345H[SB],R0L
+ ADD.B:G A0,[A0]
+ ADD.B:G A0,12H[A0]
+ ADD.B:G A0,12H[FB]
+ ADD.B:G A0,12H[SB]
+ ADD.B:G A0,2345H
+ ADD.B:G A0,2345H[A0]
+ ADD.B:G A0,2345H[SB]
+ ADD.B:G A0,R0L
+ ADD.B:G R0L,[A0]
+ ADD.B:G R0L,12H[A0]
+ ADD.B:G R0L,12H[FB]
+ ADD.B:G R0L,12H[SB]
+ ADD.B:G R0L,2345H
+ ADD.B:G R0L,2345H[A0]
+ ADD.B:G R0L,2345H[SB]
+ ADD.B:G R0L,A0
+ ADD.B:G R0L,R0L
+ ADD.B:Q #7,[A0]
+ ADD.B:Q #7,12H[A0]
+ ADD.B:Q #7,12H[FB]
+ ADD.B:Q #7,12H[SB]
+ ADD.B:Q #7,2345H
+ ADD.B:Q #7,2345H[A0]
+ ADD.B:Q #7,2345H[SB]
+ ADD.B:Q #7,A0
+ ADD.B:Q #7,R0L
+ ADD.B:Q #7,SP
+ ADD.B:S #7,12H[FB]
+ ADD.B:S #7,12H[SB]
+ ADD.B:S #7,2345H
+ ADD.B:S #7,R0L
+ ADD.B:S 12H[FB],R0L
+ ADD.B:S 12H[SB],R0L
+ ADD.B:S 2345H,R0L
+ ADD.W:G #2345H,[A0]
+ ADD.W:G #2345H,12H[A0]
+ ADD.W:G #2345H,12H[FB]
+ ADD.W:G #2345H,12H[SB]
+ ADD.W:G #2345H,2345H
+ ADD.W:G #2345H,2345H[A0]
+ ADD.W:G #2345H,2345H[SB]
+ ADD.W:G #2345H,A0
+ ADD.W:G #2345H,R0
+ ADD.W:G #2345H,SP
+ ADD.W:G #7,[A0]
+ ADD.W:G #7,12H[A0]
+ ADD.W:G #7,12H[FB]
+ ADD.W:G #7,12H[SB]
+ ADD.W:G #7,2345H
+ ADD.W:G #7,2345H[A0]
+ ADD.W:G #7,2345H[SB]
+ ADD.W:G #7,A0
+ ADD.W:G #7,R0
+ ADD.W:G #7,SP
+ ADD.W:G [A0],[A0]
+ ADD.W:G [A0],12H[A0]
+ ADD.W:G [A0],12H[FB]
+ ADD.W:G [A0],12H[SB]
+ ADD.W:G [A0],2345H
+ ADD.W:G [A0],2345H[A0]
+ ADD.W:G [A0],2345H[SB]
+ ADD.W:G [A0],A0
+ ADD.W:G [A0],R0
+ ADD.W:G 12H[A0],[A0]
+ ADD.W:G 12H[A0],12H[A0]
+ ADD.W:G 12H[A0],12H[FB]
+ ADD.W:G 12H[A0],12H[SB]
+ ADD.W:G 12H[A0],2345H
+ ADD.W:G 12H[A0],2345H[A0]
+ ADD.W:G 12H[A0],2345H[SB]
+ ADD.W:G 12H[A0],A0
+ ADD.W:G 12H[A0],R0
+ ADD.W:G 12H[FB],[A0]
+ ADD.W:G 12H[FB],12H[A0]
+ ADD.W:G 12H[FB],12H[FB]
+ ADD.W:G 12H[FB],12H[SB]
+ ADD.W:G 12H[FB],2345H
+ ADD.W:G 12H[FB],2345H[A0]
+ ADD.W:G 12H[FB],2345H[SB]
+ ADD.W:G 12H[FB],A0
+ ADD.W:G 12H[FB],R0
+ ADD.W:G 12H[SB],[A0]
+ ADD.W:G 12H[SB],12H[A0]
+ ADD.W:G 12H[SB],12H[FB]
+ ADD.W:G 12H[SB],12H[SB]
+ ADD.W:G 12H[SB],2345H
+ ADD.W:G 12H[SB],2345H[A0]
+ ADD.W:G 12H[SB],2345H[SB]
+ ADD.W:G 12H[SB],A0
+ ADD.W:G 12H[SB],R0
+ ADD.W:G 2345H,[A0]
+ ADD.W:G 2345H,12H[A0]
+ ADD.W:G 2345H,12H[FB]
+ ADD.W:G 2345H,12H[SB]
+ ADD.W:G 2345H,2345H
+ ADD.W:G 2345H,2345H[A0]
+ ADD.W:G 2345H,2345H[SB]
+ ADD.W:G 2345H,A0
+ ADD.W:G 2345H,R0
+ ADD.W:G 2345H[A0],[A0]
+ ADD.W:G 2345H[A0],12H[A0]
+ ADD.W:G 2345H[A0],12H[FB]
+ ADD.W:G 2345H[A0],12H[SB]
+ ADD.W:G 2345H[A0],2345H
+ ADD.W:G 2345H[A0],2345H[A0]
+ ADD.W:G 2345H[A0],2345H[SB]
+ ADD.W:G 2345H[A0],A0
+ ADD.W:G 2345H[A0],R0
+ ADD.W:G 2345H[SB],[A0]
+ ADD.W:G 2345H[SB],12H[A0]
+ ADD.W:G 2345H[SB],12H[FB]
+ ADD.W:G 2345H[SB],12H[SB]
+ ADD.W:G 2345H[SB],2345H
+ ADD.W:G 2345H[SB],2345H[A0]
+ ADD.W:G 2345H[SB],2345H[SB]
+ ADD.W:G 2345H[SB],A0
+ ADD.W:G 2345H[SB],R0
+ ADD.W:G A0,[A0]
+ ADD.W:G A0,12H[A0]
+ ADD.W:G A0,12H[FB]
+ ADD.W:G A0,12H[SB]
+ ADD.W:G A0,2345H
+ ADD.W:G A0,2345H[A0]
+ ADD.W:G A0,2345H[SB]
+ ADD.W:G A0,A0
+ ADD.W:G A0,R0
+ ADD.W:G R0,[A0]
+ ADD.W:G R0,12H[A0]
+ ADD.W:G R0,12H[FB]
+ ADD.W:G R0,12H[SB]
+ ADD.W:G R0,2345H
+ ADD.W:G R0,2345H[A0]
+ ADD.W:G R0,2345H[SB]
+ ADD.W:G R0,A0
+ ADD.W:G R0,R0
+ ADD.W:Q #7,[A0]
+ ADD.W:Q #7,12H[A0]
+ ADD.W:Q #7,12H[FB]
+ ADD.W:Q #7,12H[SB]
+ ADD.W:Q #7,2345H
+ ADD.W:Q #7,2345H[A0]
+ ADD.W:Q #7,2345H[SB]
+ ADD.W:Q #7,A0
+ ADD.W:Q #7,R0
+ ADD.W:Q #7,SP
+ AND.B:G #7,[A0]
+ AND.B:G #7,12H[A0]
+ AND.B:G #7,12H[FB]
+ AND.B:G #7,12H[SB]
+ AND.B:G #7,2345H
+ AND.B:G #7,2345H[A0]
+ AND.B:G #7,2345H[SB]
+ AND.B:G #7,A0
+ AND.B:G #7,R0L
+ AND.B:G [A0],[A0]
+ AND.B:G [A0],12H[A0]
+ AND.B:G [A0],12H[FB]
+ AND.B:G [A0],12H[SB]
+ AND.B:G [A0],2345H
+ AND.B:G [A0],2345H[A0]
+ AND.B:G [A0],2345H[SB]
+ AND.B:G [A0],A0
+ AND.B:G [A0],R0L
+ AND.B:G 12H[A0],[A0]
+ AND.B:G 12H[A0],12H[A0]
+ AND.B:G 12H[A0],12H[FB]
+ AND.B:G 12H[A0],12H[SB]
+ AND.B:G 12H[A0],2345H
+ AND.B:G 12H[A0],2345H[A0]
+ AND.B:G 12H[A0],2345H[SB]
+ AND.B:G 12H[A0],A0
+ AND.B:G 12H[A0],R0L
+ AND.B:G 12H[FB],[A0]
+ AND.B:G 12H[FB],12H[A0]
+ AND.B:G 12H[FB],12H[FB]
+ AND.B:G 12H[FB],12H[SB]
+ AND.B:G 12H[FB],2345H
+ AND.B:G 12H[FB],2345H[A0]
+ AND.B:G 12H[FB],2345H[SB]
+ AND.B:G 12H[FB],A0
+ AND.B:G 12H[FB],R0L
+ AND.B:G 12H[SB],[A0]
+ AND.B:G 12H[SB],12H[A0]
+ AND.B:G 12H[SB],12H[FB]
+ AND.B:G 12H[SB],12H[SB]
+ AND.B:G 12H[SB],2345H
+ AND.B:G 12H[SB],2345H[A0]
+ AND.B:G 12H[SB],2345H[SB]
+ AND.B:G 12H[SB],A0
+ AND.B:G 12H[SB],R0L
+ AND.B:G 2345H,[A0]
+ AND.B:G 2345H,12H[A0]
+ AND.B:G 2345H,12H[FB]
+ AND.B:G 2345H,12H[SB]
+ AND.B:G 2345H,2345H
+ AND.B:G 2345H,2345H[A0]
+ AND.B:G 2345H,2345H[SB]
+ AND.B:G 2345H,A0
+ AND.B:G 2345H,R0L
+ AND.B:G 2345H[A0],[A0]
+ AND.B:G 2345H[A0],12H[A0]
+ AND.B:G 2345H[A0],12H[FB]
+ AND.B:G 2345H[A0],12H[SB]
+ AND.B:G 2345H[A0],2345H
+ AND.B:G 2345H[A0],2345H[A0]
+ AND.B:G 2345H[A0],2345H[SB]
+ AND.B:G 2345H[A0],A0
+ AND.B:G 2345H[A0],R0L
+ AND.B:G 2345H[SB],[A0]
+ AND.B:G 2345H[SB],12H[A0]
+ AND.B:G 2345H[SB],12H[FB]
+ AND.B:G 2345H[SB],12H[SB]
+ AND.B:G 2345H[SB],2345H
+ AND.B:G 2345H[SB],2345H[A0]
+ AND.B:G 2345H[SB],2345H[SB]
+ AND.B:G 2345H[SB],A0
+ AND.B:G 2345H[SB],R0L
+ AND.B:G A0,[A0]
+ AND.B:G A0,12H[A0]
+ AND.B:G A0,12H[FB]
+ AND.B:G A0,12H[SB]
+ AND.B:G A0,2345H
+ AND.B:G A0,2345H[A0]
+ AND.B:G A0,2345H[SB]
+ AND.B:G A0,R0L
+ AND.B:G R0L,[A0]
+ AND.B:G R0L,12H[A0]
+ AND.B:G R0L,12H[FB]
+ AND.B:G R0L,12H[SB]
+ AND.B:G R0L,2345H
+ AND.B:G R0L,2345H[A0]
+ AND.B:G R0L,2345H[SB]
+ AND.B:G R0L,A0
+ AND.B:S #7,12H[FB]
+ AND.B:S #7,12H[SB]
+ AND.B:S #7,2345H
+ AND.B:S #7,R0L
+ AND.B:S 12H[FB],R0L
+ AND.B:S 12H[SB],R0L
+ AND.B:S 2345H,R0L
+ AND.W:G #2345H,[A0]
+ AND.W:G #2345H,12H[A0]
+ AND.W:G #2345H,12H[FB]
+ AND.W:G #2345H,12H[SB]
+ AND.W:G #2345H,2345H
+ AND.W:G #2345H,2345H[A0]
+ AND.W:G #2345H,2345H[SB]
+ AND.W:G #2345H,A0
+ AND.W:G #2345H,R0
+ AND.W:G #7,[A0]
+ AND.W:G #7,12H[A0]
+ AND.W:G #7,12H[FB]
+ AND.W:G #7,12H[SB]
+ AND.W:G #7,2345H
+ AND.W:G #7,2345H[A0]
+ AND.W:G #7,2345H[SB]
+ AND.W:G #7,A0
+ AND.W:G #7,R0
+ AND.W:G [A0],[A0]
+ AND.W:G [A0],12H[A0]
+ AND.W:G [A0],12H[FB]
+ AND.W:G [A0],12H[SB]
+ AND.W:G [A0],2345H
+ AND.W:G [A0],2345H[A0]
+ AND.W:G [A0],2345H[SB]
+ AND.W:G [A0],A0
+ AND.W:G [A0],R0
+ AND.W:G 12H[A0],[A0]
+ AND.W:G 12H[A0],12H[A0]
+ AND.W:G 12H[A0],12H[FB]
+ AND.W:G 12H[A0],12H[SB]
+ AND.W:G 12H[A0],2345H
+ AND.W:G 12H[A0],2345H[A0]
+ AND.W:G 12H[A0],2345H[SB]
+ AND.W:G 12H[A0],A0
+ AND.W:G 12H[A0],R0
+ AND.W:G 12H[FB],[A0]
+ AND.W:G 12H[FB],12H[A0]
+ AND.W:G 12H[FB],12H[FB]
+ AND.W:G 12H[FB],12H[SB]
+ AND.W:G 12H[FB],2345H
+ AND.W:G 12H[FB],2345H[A0]
+ AND.W:G 12H[FB],2345H[SB]
+ AND.W:G 12H[FB],A0
+ AND.W:G 12H[FB],R0
+ AND.W:G 12H[SB],[A0]
+ AND.W:G 12H[SB],12H[A0]
+ AND.W:G 12H[SB],12H[FB]
+ AND.W:G 12H[SB],12H[SB]
+ AND.W:G 12H[SB],2345H
+ AND.W:G 12H[SB],2345H[A0]
+ AND.W:G 12H[SB],2345H[SB]
+ AND.W:G 12H[SB],A0
+ AND.W:G 12H[SB],R0
+ AND.W:G 2345H,[A0]
+ AND.W:G 2345H,12H[A0]
+ AND.W:G 2345H,12H[FB]
+ AND.W:G 2345H,12H[SB]
+ AND.W:G 2345H,2345H
+ AND.W:G 2345H,2345H[A0]
+ AND.W:G 2345H,2345H[SB]
+ AND.W:G 2345H,A0
+ AND.W:G 2345H,R0
+ AND.W:G 2345H[A0],[A0]
+ AND.W:G 2345H[A0],12H[A0]
+ AND.W:G 2345H[A0],12H[FB]
+ AND.W:G 2345H[A0],12H[SB]
+ AND.W:G 2345H[A0],2345H
+ AND.W:G 2345H[A0],2345H[A0]
+ AND.W:G 2345H[A0],2345H[SB]
+ AND.W:G 2345H[A0],A0
+ AND.W:G 2345H[A0],R0
+ AND.W:G 2345H[SB],[A0]
+ AND.W:G 2345H[SB],12H[A0]
+ AND.W:G 2345H[SB],12H[FB]
+ AND.W:G 2345H[SB],12H[SB]
+ AND.W:G 2345H[SB],2345H
+ AND.W:G 2345H[SB],2345H[A0]
+ AND.W:G 2345H[SB],2345H[SB]
+ AND.W:G 2345H[SB],A0
+ AND.W:G 2345H[SB],R0
+ AND.W:G A0,[A0]
+ AND.W:G A0,12H[A0]
+ AND.W:G A0,12H[FB]
+ AND.W:G A0,12H[SB]
+ AND.W:G A0,2345H
+ AND.W:G A0,2345H[A0]
+ AND.W:G A0,2345H[SB]
+ AND.W:G A0,A0
+ AND.W:G A0,R0
+ AND.W:G R0,[A0]
+ AND.W:G R0,12H[A0]
+ AND.W:G R0,12H[FB]
+ AND.W:G R0,12H[SB]
+ AND.W:G R0,2345H
+ AND.W:G R0,2345H[A0]
+ AND.W:G R0,2345H[SB]
+ AND.W:G R0,A0
+ AND.W:G R0,R0
+ BAND [A0]
+ BAND 0FFFH
+ BAND 0FFFH,0FFFH
+ BAND 0FFFH,0FFFH[SB]
+ BAND 0FFFH,12H[SB]
+ BAND 0FFFH,15
+ BAND 12H[A0]
+ BAND 15
+ BAND 15,0FFFH
+ BAND 15,0FFFH[SB]
+ BAND 15,12H[SB]
+ BAND 15,15
+ BAND 15,1H[FB]
+ BAND 15,A0
+ BAND 15,R0
+ BAND 2345H[A0]
+ BCLR:G [A0]
+ BCLR:G 0FFFH
+ BCLR:G 0FFFH,0FFFH
+ BCLR:G 0FFFH,0FFFH[SB]
+ BCLR:G 0FFFH,12H[SB]
+ BCLR:G 0FFFH,15
+ BCLR:G 12H[A0]
+ BCLR:G 15
+ BCLR:G 15,0FFFH
+ BCLR:G 15,0FFFH[SB]
+ BCLR:G 15,12H[SB]
+ BCLR:G 15,15
+ BCLR:G 15,1H[FB]
+ BCLR:G 15,A0
+ BCLR:G 15,R0
+ BCLR:G 2345H[A0]
+ BCLR:S 15,12H[SB]
+ BMEQ [A0]
+ BMEQ 0FFFH
+ BMEQ 0FFFH,0FFFH
+ BMEQ 0FFFH,0FFFH[SB]
+ BMEQ 0FFFH,12H[SB]
+ BMEQ 0FFFH,15
+ BMEQ 12H[A0]
+ BMEQ 15
+ BMEQ 15,0FFFH
+ BMEQ 15,0FFFH[SB]
+ BMEQ 15,12H[SB]
+ BMEQ 15,15
+ BMEQ 15,1H[FB]
+ BMEQ 15,A0
+ BMEQ 15,R0
+ BMEQ 2345H[A0]
+ BMEQ C
+ BMGE [A0]
+ BMGE 0FFFH
+ BMGE 0FFFH,0FFFH
+ BMGE 0FFFH,0FFFH[SB]
+ BMGE 0FFFH,12H[SB]
+ BMGE 0FFFH,15
+ BMGE 12H[A0]
+ BMGE 15
+ BMGE 15,0FFFH
+ BMGE 15,0FFFH[SB]
+ BMGE 15,12H[SB]
+ BMGE 15,15
+ BMGE 15,1H[FB]
+ BMGE 15,A0
+ BMGE 15,R0
+ BMGE 2345H[A0]
+ BMGE C
+ BMGEU [A0]
+ BMGEU 0FFFH
+ BMGEU 0FFFH,0FFFH
+ BMGEU 0FFFH,0FFFH[SB]
+ BMGEU 0FFFH,12H[SB]
+ BMGEU 0FFFH,15
+ BMGEU 12H[A0]
+ BMGEU 15
+ BMGEU 15,0FFFH
+ BMGEU 15,0FFFH[SB]
+ BMGEU 15,12H[SB]
+ BMGEU 15,15
+ BMGEU 15,1H[FB]
+ BMGEU 15,A0
+ BMGEU 15,R0
+ BMGEU 2345H[A0]
+ BMGEU C
+ BMGT [A0]
+ BMGT 0FFFH
+ BMGT 0FFFH,0FFFH
+ BMGT 0FFFH,0FFFH[SB]
+ BMGT 0FFFH,12H[SB]
+ BMGT 0FFFH,15
+ BMGT 12H[A0]
+ BMGT 15
+ BMGT 15,0FFFH
+ BMGT 15,0FFFH[SB]
+ BMGT 15,12H[SB]
+ BMGT 15,15
+ BMGT 15,1H[FB]
+ BMGT 15,A0
+ BMGT 15,R0
+ BMGT 2345H[A0]
+ BMGT C
+ BMGTU [A0]
+ BMGTU 0FFFH
+ BMGTU 0FFFH,0FFFH
+ BMGTU 0FFFH,0FFFH[SB]
+ BMGTU 0FFFH,12H[SB]
+ BMGTU 0FFFH,15
+ BMGTU 12H[A0]
+ BMGTU 15
+ BMGTU 15,0FFFH
+ BMGTU 15,0FFFH[SB]
+ BMGTU 15,12H[SB]
+ BMGTU 15,15
+ BMGTU 15,1H[FB]
+ BMGTU 15,A0
+ BMGTU 15,R0
+ BMGTU 2345H[A0]
+ BMGTU C
+ BMLE [A0]
+ BMLE 0FFFH
+ BMLE 0FFFH,0FFFH
+ BMLE 0FFFH,0FFFH[SB]
+ BMLE 0FFFH,12H[SB]
+ BMLE 0FFFH,15
+ BMLE 12H[A0]
+ BMLE 15
+ BMLE 15,0FFFH
+ BMLE 15,0FFFH[SB]
+ BMLE 15,12H[SB]
+ BMLE 15,15
+ BMLE 15,1H[FB]
+ BMLE 15,A0
+ BMLE 15,R0
+ BMLE 2345H[A0]
+ BMLE C
+ BMLEU [A0]
+ BMLEU 0FFFH
+ BMLEU 0FFFH,0FFFH
+ BMLEU 0FFFH,0FFFH[SB]
+ BMLEU 0FFFH,12H[SB]
+ BMLEU 0FFFH,15
+ BMLEU 12H[A0]
+ BMLEU 15
+ BMLEU 15,0FFFH
+ BMLEU 15,0FFFH[SB]
+ BMLEU 15,12H[SB]
+ BMLEU 15,15
+ BMLEU 15,1H[FB]
+ BMLEU 15,A0
+ BMLEU 15,R0
+ BMLEU 2345H[A0]
+ BMLEU C
+ BMLT [A0]
+ BMLT 0FFFH
+ BMLT 0FFFH,0FFFH
+ BMLT 0FFFH,0FFFH[SB]
+ BMLT 0FFFH,12H[SB]
+ BMLT 0FFFH,15
+ BMLT 12H[A0]
+ BMLT 15
+ BMLT 15,0FFFH
+ BMLT 15,0FFFH[SB]
+ BMLT 15,12H[SB]
+ BMLT 15,15
+ BMLT 15,1H[FB]
+ BMLT 15,A0
+ BMLT 15,R0
+ BMLT 2345H[A0]
+ BMLT C
+ BMLTU [A0]
+ BMLTU 0FFFH
+ BMLTU 0FFFH,0FFFH
+ BMLTU 0FFFH,0FFFH[SB]
+ BMLTU 0FFFH,12H[SB]
+ BMLTU 0FFFH,15
+ BMLTU 12H[A0]
+ BMLTU 15
+ BMLTU 15,0FFFH
+ BMLTU 15,0FFFH[SB]
+ BMLTU 15,12H[SB]
+ BMLTU 15,15
+ BMLTU 15,1H[FB]
+ BMLTU 15,A0
+ BMLTU 15,R0
+ BMLTU 2345H[A0]
+ BMLTU C
+ BMN [A0]
+ BMN 0FFFH
+ BMN 0FFFH,0FFFH
+ BMN 0FFFH,0FFFH[SB]
+ BMN 0FFFH,12H[SB]
+ BMN 0FFFH,15
+ BMN 12H[A0]
+ BMN 15
+ BMN 15,0FFFH
+ BMN 15,0FFFH[SB]
+ BMN 15,12H[SB]
+ BMN 15,15
+ BMN 15,1H[FB]
+ BMN 15,A0
+ BMN 15,R0
+ BMN 2345H[A0]
+ BMN C
+ BMNC [A0]
+ BMNC 0FFFH
+ BMNC 0FFFH,0FFFH
+ BMNC 0FFFH,0FFFH[SB]
+ BMNC 0FFFH,12H[SB]
+ BMNC 0FFFH,15
+ BMNC 12H[A0]
+ BMNC 15
+ BMNC 15,0FFFH
+ BMNC 15,0FFFH[SB]
+ BMNC 15,12H[SB]
+ BMNC 15,15
+ BMNC 15,1H[FB]
+ BMNC 15,A0
+ BMNC 15,R0
+ BMNC 2345H[A0]
+ BMNC C
+ BMNE [A0]
+ BMNE 0FFFH
+ BMNE 0FFFH,0FFFH
+ BMNE 0FFFH,0FFFH[SB]
+ BMNE 0FFFH,12H[SB]
+ BMNE 0FFFH,15
+ BMNE 12H[A0]
+ BMNE 15
+ BMNE 15,0FFFH
+ BMNE 15,0FFFH[SB]
+ BMNE 15,12H[SB]
+ BMNE 15,15
+ BMNE 15,1H[FB]
+ BMNE 15,A0
+ BMNE 15,R0
+ BMNE 2345H[A0]
+ BMNE C
+ BMNO [A0]
+ BMNO 0FFFH
+ BMNO 0FFFH,0FFFH
+ BMNO 0FFFH,0FFFH[SB]
+ BMNO 0FFFH,12H[SB]
+ BMNO 0FFFH,15
+ BMNO 12H[A0]
+ BMNO 15
+ BMNO 15,0FFFH
+ BMNO 15,0FFFH[SB]
+ BMNO 15,12H[SB]
+ BMNO 15,15
+ BMNO 15,1H[FB]
+ BMNO 15,A0
+ BMNO 15,R0
+ BMNO 2345H[A0]
+ BMNO C
+ BMNZ [A0]
+ BMNZ 0FFFH
+ BMNZ 0FFFH,0FFFH
+ BMNZ 0FFFH,0FFFH[SB]
+ BMNZ 0FFFH,12H[SB]
+ BMNZ 0FFFH,15
+ BMNZ 12H[A0]
+ BMNZ 15
+ BMNZ 15,0FFFH
+ BMNZ 15,0FFFH[SB]
+ BMNZ 15,12H[SB]
+ BMNZ 15,15
+ BMNZ 15,1H[FB]
+ BMNZ 15,A0
+ BMNZ 15,R0
+ BMNZ 2345H[A0]
+ BMNZ C
+ BMO [A0]
+ BMO 0FFFH
+ BMO 0FFFH,0FFFH
+ BMO 0FFFH,0FFFH[SB]
+ BMO 0FFFH,12H[SB]
+ BMO 0FFFH,15
+ BMO 12H[A0]
+ BMO 15
+ BMO 15,0FFFH
+ BMO 15,0FFFH[SB]
+ BMO 15,12H[SB]
+ BMO 15,15
+ BMO 15,1H[FB]
+ BMO 15,A0
+ BMO 15,R0
+ BMO 2345H[A0]
+ BMO C
+ BMPZ [A0]
+ BMPZ 0FFFH
+ BMPZ 0FFFH,0FFFH
+ BMPZ 0FFFH,0FFFH[SB]
+ BMPZ 0FFFH,12H[SB]
+ BMPZ 0FFFH,15
+ BMPZ 12H[A0]
+ BMPZ 15
+ BMPZ 15,0FFFH
+ BMPZ 15,0FFFH[SB]
+ BMPZ 15,12H[SB]
+ BMPZ 15,15
+ BMPZ 15,1H[FB]
+ BMPZ 15,A0
+ BMPZ 15,R0
+ BMPZ 2345H[A0]
+ BMPZ C
+ BMZ [A0]
+ BMZ 0FFFH
+ BMZ 0FFFH,0FFFH
+ BMZ 0FFFH,0FFFH[SB]
+ BMZ 0FFFH,12H[SB]
+ BMZ 0FFFH,15
+ BMZ 12H[A0]
+ BMZ 15
+ BMZ 15,0FFFH
+ BMZ 15,0FFFH[SB]
+ BMZ 15,12H[SB]
+ BMZ 15,15
+ BMZ 15,1H[FB]
+ BMZ 15,A0
+ BMZ 15,R0
+ BMZ 2345H[A0]
+ BMZ C
+ BNAND [A0]
+ BNAND 0FFFH
+ BNAND 0FFFH,0FFFH
+ BNAND 0FFFH,0FFFH[SB]
+ BNAND 0FFFH,12H[SB]
+ BNAND 0FFFH,15
+ BNAND 12H[A0]
+ BNAND 15
+ BNAND 15,0FFFH
+ BNAND 15,0FFFH[SB]
+ BNAND 15,12H[SB]
+ BNAND 15,15
+ BNAND 15,1H[FB]
+ BNAND 15,A0
+ BNAND 15,R0
+ BNAND 2345H[A0]
+ BNOR [A0]
+ BNOR 0FFFH
+ BNOR 0FFFH,0FFFH
+ BNOR 0FFFH,0FFFH[SB]
+ BNOR 0FFFH,12H[SB]
+ BNOR 0FFFH,15
+ BNOR 12H[A0]
+ BNOR 15
+ BNOR 15,0FFFH
+ BNOR 15,0FFFH[SB]
+ BNOR 15,12H[SB]
+ BNOR 15,15
+ BNOR 15,1H[FB]
+ BNOR 15,A0
+ BNOR 15,R0
+ BNOR 2345H[A0]
+ BNOT:G [A0]
+ BNOT:G 0FFFH
+ BNOT:G 0FFFH,0FFFH
+ BNOT:G 0FFFH,0FFFH[SB]
+ BNOT:G 0FFFH,12H[SB]
+ BNOT:G 0FFFH,15
+ BNOT:G 12H[A0]
+ BNOT:G 15
+ BNOT:G 15,0FFFH
+ BNOT:G 15,0FFFH[SB]
+ BNOT:G 15,12H[SB]
+ BNOT:G 15,15
+ BNOT:G 15,1H[FB]
+ BNOT:G 15,A0
+ BNOT:G 15,R0
+ BNOT:G 2345H[A0]
+ BNOT:S 15,12H[SB]
+ BNTST [A0]
+ BNTST 0FFFH
+ BNTST 0FFFH,0FFFH
+ BNTST 0FFFH,0FFFH[SB]
+ BNTST 0FFFH,12H[SB]
+ BNTST 0FFFH,15
+ BNTST 12H[A0]
+ BNTST 15
+ BNTST 15,0FFFH
+ BNTST 15,0FFFH[SB]
+ BNTST 15,12H[SB]
+ BNTST 15,15
+ BNTST 15,1H[FB]
+ BNTST 15,A0
+ BNTST 15,R0
+ BNTST 2345H[A0]
+ BNXOR [A0]
+ BNXOR 0FFFH
+ BNXOR 0FFFH,0FFFH
+ BNXOR 0FFFH,0FFFH[SB]
+ BNXOR 0FFFH,12H[SB]
+ BNXOR 0FFFH,15
+ BNXOR 12H[A0]
+ BNXOR 15
+ BNXOR 15,0FFFH
+ BNXOR 15,0FFFH[SB]
+ BNXOR 15,12H[SB]
+ BNXOR 15,15
+ BNXOR 15,1H[FB]
+ BNXOR 15,A0
+ BNXOR 15,R0
+ BNXOR 2345H[A0]
+ BOR [A0]
+ BOR 0FFFH
+ BOR 0FFFH,0FFFH
+ BOR 0FFFH,0FFFH[SB]
+ BOR 0FFFH,12H[SB]
+ BOR 0FFFH,15
+ BOR 12H[A0]
+ BOR 15
+ BOR 15,0FFFH
+ BOR 15,0FFFH[SB]
+ BOR 15,12H[SB]
+ BOR 15,15
+ BOR 15,1H[FB]
+ BOR 15,A0
+ BOR 15,R0
+ BOR 2345H[A0]
+ BRK
+ BSET:G [A0]
+ BSET:G 0FFFH
+ BSET:G 0FFFH,0FFFH
+ BSET:G 0FFFH,0FFFH[SB]
+ BSET:G 0FFFH,12H[SB]
+ BSET:G 0FFFH,15
+ BSET:G 12H[A0]
+ BSET:G 15
+ BSET:G 15,0FFFH
+ BSET:G 15,0FFFH[SB]
+ BSET:G 15,12H[SB]
+ BSET:G 15,15
+ BSET:G 15,1H[FB]
+ BSET:G 15,A0
+ BSET:G 15,R0
+ BSET:G 2345H[A0]
+ BSET:S 15,12H[SB]
+ BTST:G [A0]
+ BTST:G 0FFFH
+ BTST:G 0FFFH,0FFFH
+ BTST:G 0FFFH,0FFFH[SB]
+ BTST:G 0FFFH,12H[SB]
+ BTST:G 0FFFH,15
+ BTST:G 12H[A0]
+ BTST:G 15
+ BTST:G 15,0FFFH
+ BTST:G 15,0FFFH[SB]
+ BTST:G 15,12H[SB]
+ BTST:G 15,15
+ BTST:G 15,1H[FB]
+ BTST:G 15,A0
+ BTST:G 15,R0
+ BTST:G 2345H[A0]
+ BTST:S 15,12H[SB]
+ BTSTC [A0]
+ BTSTC 0FFFH
+ BTSTC 0FFFH,0FFFH
+ BTSTC 0FFFH,0FFFH[SB]
+ BTSTC 0FFFH,12H[SB]
+ BTSTC 0FFFH,15
+ BTSTC 12H[A0]
+ BTSTC 15
+ BTSTC 15,0FFFH
+ BTSTC 15,0FFFH[SB]
+ BTSTC 15,12H[SB]
+ BTSTC 15,15
+ BTSTC 15,1H[FB]
+ BTSTC 15,A0
+ BTSTC 15,R0
+ BTSTC 2345H[A0]
+ BTSTS [A0]
+ BTSTS 0FFFH
+ BTSTS 0FFFH,0FFFH
+ BTSTS 0FFFH,0FFFH[SB]
+ BTSTS 0FFFH,12H[SB]
+ BTSTS 0FFFH,15
+ BTSTS 12H[A0]
+ BTSTS 15
+ BTSTS 15,0FFFH
+ BTSTS 15,0FFFH[SB]
+ BTSTS 15,12H[SB]
+ BTSTS 15,15
+ BTSTS 15,1H[FB]
+ BTSTS 15,A0
+ BTSTS 15,R0
+ BTSTS 2345H[A0]
+ BXOR [A0]
+ BXOR 0FFFH
+ BXOR 0FFFH,0FFFH
+ BXOR 0FFFH,0FFFH[SB]
+ BXOR 0FFFH,12H[SB]
+ BXOR 0FFFH,15
+ BXOR 12H[A0]
+ BXOR 15
+ BXOR 15,0FFFH
+ BXOR 15,0FFFH[SB]
+ BXOR 15,12H[SB]
+ BXOR 15,15
+ BXOR 15,1H[FB]
+ BXOR 15,A0
+ BXOR 15,R0
+ BXOR 2345H[A0]
+ CMP.B:G #7,[A0]
+ CMP.B:G #7,12H[A0]
+ CMP.B:G #7,12H[FB]
+ CMP.B:G #7,12H[SB]
+ CMP.B:G #7,2345H
+ CMP.B:G #7,2345H[A0]
+ CMP.B:G #7,2345H[SB]
+ CMP.B:G #7,A0
+ CMP.B:G #7,R0H
+ CMP.B:G #7,R0L
+ CMP.B:G [A0],[A0]
+ CMP.B:G [A0],12H[A0]
+ CMP.B:G [A0],12H[FB]
+ CMP.B:G [A0],12H[SB]
+ CMP.B:G [A0],2345H
+ CMP.B:G [A0],2345H[A0]
+ CMP.B:G [A0],2345H[SB]
+ CMP.B:G [A0],A0
+ CMP.B:G [A0],R0H
+ CMP.B:G [A0],R0L
+ CMP.B:G 12H[A0],[A0]
+ CMP.B:G 12H[A0],12H[A0]
+ CMP.B:G 12H[A0],12H[FB]
+ CMP.B:G 12H[A0],12H[SB]
+ CMP.B:G 12H[A0],2345H
+ CMP.B:G 12H[A0],2345H[A0]
+ CMP.B:G 12H[A0],2345H[SB]
+ CMP.B:G 12H[A0],A0
+ CMP.B:G 12H[A0],R0H
+ CMP.B:G 12H[A0],R0L
+ CMP.B:G 12H[FB],[A0]
+ CMP.B:G 12H[FB],12H[A0]
+ CMP.B:G 12H[FB],12H[FB]
+ CMP.B:G 12H[FB],12H[SB]
+ CMP.B:G 12H[FB],2345H
+ CMP.B:G 12H[FB],2345H[A0]
+ CMP.B:G 12H[FB],2345H[SB]
+ CMP.B:G 12H[FB],A0
+ CMP.B:G 12H[FB],R0H
+ CMP.B:G 12H[FB],R0L
+ CMP.B:G 12H[SB],[A0]
+ CMP.B:G 12H[SB],12H[A0]
+ CMP.B:G 12H[SB],12H[FB]
+ CMP.B:G 12H[SB],12H[SB]
+ CMP.B:G 12H[SB],2345H
+ CMP.B:G 12H[SB],2345H[A0]
+ CMP.B:G 12H[SB],2345H[SB]
+ CMP.B:G 12H[SB],A0
+ CMP.B:G 12H[SB],R0H
+ CMP.B:G 12H[SB],R0L
+ CMP.B:G 2345H,[A0]
+ CMP.B:G 2345H,12H[A0]
+ CMP.B:G 2345H,12H[FB]
+ CMP.B:G 2345H,12H[SB]
+ CMP.B:G 2345H,2345H
+ CMP.B:G 2345H,2345H[A0]
+ CMP.B:G 2345H,2345H[SB]
+ CMP.B:G 2345H,A0
+ CMP.B:G 2345H,R0H
+ CMP.B:G 2345H,R0L
+ CMP.B:G 2345H[A0],[A0]
+ CMP.B:G 2345H[A0],12H[A0]
+ CMP.B:G 2345H[A0],12H[FB]
+ CMP.B:G 2345H[A0],12H[SB]
+ CMP.B:G 2345H[A0],2345H
+ CMP.B:G 2345H[A0],2345H[A0]
+ CMP.B:G 2345H[A0],2345H[SB]
+ CMP.B:G 2345H[A0],A0
+ CMP.B:G 2345H[A0],R0H
+ CMP.B:G 2345H[A0],R0L
+ CMP.B:G 2345H[SB],[A0]
+ CMP.B:G 2345H[SB],12H[A0]
+ CMP.B:G 2345H[SB],12H[FB]
+ CMP.B:G 2345H[SB],12H[SB]
+ CMP.B:G 2345H[SB],2345H
+ CMP.B:G 2345H[SB],2345H[A0]
+ CMP.B:G 2345H[SB],2345H[SB]
+ CMP.B:G 2345H[SB],A0
+ CMP.B:G 2345H[SB],R0H
+ CMP.B:G 2345H[SB],R0L
+ CMP.B:G A0,[A0]
+ CMP.B:G A0,12H[A0]
+ CMP.B:G A0,12H[FB]
+ CMP.B:G A0,12H[SB]
+ CMP.B:G A0,2345H
+ CMP.B:G A0,2345H[A0]
+ CMP.B:G A0,2345H[SB]
+ CMP.B:G A0,R0H
+ CMP.B:G A0,R0L
+ CMP.B:G R0H,[A0]
+ CMP.B:G R0H,12H[A0]
+ CMP.B:G R0H,12H[FB]
+ CMP.B:G R0H,12H[SB]
+ CMP.B:G R0H,2345H
+ CMP.B:G R0H,2345H[A0]
+ CMP.B:G R0H,2345H[SB]
+ CMP.B:G R0H,A0
+ CMP.B:G R0H,R0H
+ CMP.B:G R0H,R0L
+ CMP.B:G R0L,[A0]
+ CMP.B:G R0L,12H[A0]
+ CMP.B:G R0L,12H[FB]
+ CMP.B:G R0L,12H[SB]
+ CMP.B:G R0L,2345H
+ CMP.B:G R0L,2345H[A0]
+ CMP.B:G R0L,2345H[SB]
+ CMP.B:G R0L,A0
+ CMP.B:G R0L,R0H
+ CMP.B:G R0L,R0L
+ CMP.B:Q #7,[A0]
+ CMP.B:Q #7,12H[A0]
+ CMP.B:Q #7,12H[FB]
+ CMP.B:Q #7,12H[SB]
+ CMP.B:Q #7,2345H
+ CMP.B:Q #7,2345H[A0]
+ CMP.B:Q #7,2345H[SB]
+ CMP.B:Q #7,A0
+ CMP.B:Q #7,R0H
+ CMP.B:Q #7,R0L
+ CMP.B:S #7,12H[FB]
+ CMP.B:S #7,12H[SB]
+ CMP.B:S #7,2345H
+ CMP.B:S #7,R0H
+ CMP.B:S #7,R0L
+ CMP.B:S 12H[FB],R0H
+ CMP.B:S 12H[FB],R0L
+ CMP.B:S 12H[SB],R0H
+ CMP.B:S 12H[SB],R0L
+ CMP.B:S 2345H,R0H
+ CMP.B:S 2345H,R0L
+ CMP.B:S R0H,R0L
+ CMP.B:S R0L,R0H
+ CMP.W:G #2345H,[A0]
+ CMP.W:G #2345H,12H[A0]
+ CMP.W:G #2345H,12H[FB]
+ CMP.W:G #2345H,12H[SB]
+ CMP.W:G #2345H,2345H
+ CMP.W:G #2345H,2345H[A0]
+ CMP.W:G #2345H,2345H[SB]
+ CMP.W:G #2345H,A0
+ CMP.W:G #2345H,R0
+ CMP.W:G #2345H,R1
+ CMP.W:G #7,[A0]
+ CMP.W:G #7,12H[A0]
+ CMP.W:G #7,12H[FB]
+ CMP.W:G #7,12H[SB]
+ CMP.W:G #7,2345H
+ CMP.W:G #7,2345H[A0]
+ CMP.W:G #7,2345H[SB]
+ CMP.W:G #7,A0
+ CMP.W:G #7,R0
+ CMP.W:G #7,R1
+ CMP.W:G [A0],[A0]
+ CMP.W:G [A0],12H[A0]
+ CMP.W:G [A0],12H[FB]
+ CMP.W:G [A0],12H[SB]
+ CMP.W:G [A0],2345H
+ CMP.W:G [A0],2345H[A0]
+ CMP.W:G [A0],2345H[SB]
+ CMP.W:G [A0],A0
+ CMP.W:G [A0],R0
+ CMP.W:G [A0],R1
+ CMP.W:G 12H[A0],[A0]
+ CMP.W:G 12H[A0],12H[A0]
+ CMP.W:G 12H[A0],12H[FB]
+ CMP.W:G 12H[A0],12H[SB]
+ CMP.W:G 12H[A0],2345H
+ CMP.W:G 12H[A0],2345H[A0]
+ CMP.W:G 12H[A0],2345H[SB]
+ CMP.W:G 12H[A0],A0
+ CMP.W:G 12H[A0],R0
+ CMP.W:G 12H[A0],R1
+ CMP.W:G 12H[FB],[A0]
+ CMP.W:G 12H[FB],12H[A0]
+ CMP.W:G 12H[FB],12H[FB]
+ CMP.W:G 12H[FB],12H[SB]
+ CMP.W:G 12H[FB],2345H
+ CMP.W:G 12H[FB],2345H[A0]
+ CMP.W:G 12H[FB],2345H[SB]
+ CMP.W:G 12H[FB],A0
+ CMP.W:G 12H[FB],R0
+ CMP.W:G 12H[FB],R1
+ CMP.W:G 12H[SB],[A0]
+ CMP.W:G 12H[SB],12H[A0]
+ CMP.W:G 12H[SB],12H[FB]
+ CMP.W:G 12H[SB],12H[SB]
+ CMP.W:G 12H[SB],2345H
+ CMP.W:G 12H[SB],2345H[A0]
+ CMP.W:G 12H[SB],2345H[SB]
+ CMP.W:G 12H[SB],A0
+ CMP.W:G 12H[SB],R0
+ CMP.W:G 12H[SB],R1
+ CMP.W:G 2345H,[A0]
+ CMP.W:G 2345H,12H[A0]
+ CMP.W:G 2345H,12H[FB]
+ CMP.W:G 2345H,12H[SB]
+ CMP.W:G 2345H,2345H
+ CMP.W:G 2345H,2345H[A0]
+ CMP.W:G 2345H,2345H[SB]
+ CMP.W:G 2345H,A0
+ CMP.W:G 2345H,R0
+ CMP.W:G 2345H,R1
+ CMP.W:G 2345H[A0],[A0]
+ CMP.W:G 2345H[A0],12H[A0]
+ CMP.W:G 2345H[A0],12H[FB]
+ CMP.W:G 2345H[A0],12H[SB]
+ CMP.W:G 2345H[A0],2345H
+ CMP.W:G 2345H[A0],2345H[A0]
+ CMP.W:G 2345H[A0],2345H[SB]
+ CMP.W:G 2345H[A0],A0
+ CMP.W:G 2345H[A0],R0
+ CMP.W:G 2345H[A0],R1
+ CMP.W:G 2345H[SB],[A0]
+ CMP.W:G 2345H[SB],12H[A0]
+ CMP.W:G 2345H[SB],12H[FB]
+ CMP.W:G 2345H[SB],12H[SB]
+ CMP.W:G 2345H[SB],2345H
+ CMP.W:G 2345H[SB],2345H[A0]
+ CMP.W:G 2345H[SB],2345H[SB]
+ CMP.W:G 2345H[SB],A0
+ CMP.W:G 2345H[SB],R0
+ CMP.W:G 2345H[SB],R1
+ CMP.W:G A0,[A0]
+ CMP.W:G A0,12H[A0]
+ CMP.W:G A0,12H[FB]
+ CMP.W:G A0,12H[SB]
+ CMP.W:G A0,2345H
+ CMP.W:G A0,2345H[A0]
+ CMP.W:G A0,2345H[SB]
+ CMP.W:G A0,A0
+ CMP.W:G A0,R0
+ CMP.W:G A0,R1
+ CMP.W:G R0,[A0]
+ CMP.W:G R0,12H[A0]
+ CMP.W:G R0,12H[FB]
+ CMP.W:G R0,12H[SB]
+ CMP.W:G R0,2345H
+ CMP.W:G R0,2345H[A0]
+ CMP.W:G R0,2345H[SB]
+ CMP.W:G R0,A0
+ CMP.W:G R0,R0
+ CMP.W:G R0,R1
+ CMP.W:G R1,[A0]
+ CMP.W:G R1,12H[A0]
+ CMP.W:G R1,12H[FB]
+ CMP.W:G R1,12H[SB]
+ CMP.W:G R1,2345H
+ CMP.W:G R1,2345H[A0]
+ CMP.W:G R1,2345H[SB]
+ CMP.W:G R1,A0
+ CMP.W:G R1,R0
+ CMP.W:G R1,R1
+ CMP.W:Q #7,[A0]
+ CMP.W:Q #7,12H[A0]
+ CMP.W:Q #7,12H[FB]
+ CMP.W:Q #7,12H[SB]
+ CMP.W:Q #7,2345H
+ CMP.W:Q #7,2345H[A0]
+ CMP.W:Q #7,2345H[SB]
+ CMP.W:Q #7,A0
+ CMP.W:Q #7,R0
+ CMP.W:Q #7,R1
+ DADC.B #7,R0L
+ DADC.B R0H,R0L
+ DADC.W #2345H,R0
+ DADC.W #7,R0
+ DADC.W R1,R0
+ DADD.B #7,R0L
+ DADD.B R0H,R0L
+ DADD.W #2345H,R0
+ DADD.W #7,R0
+ DADD.W R1,R0
+ DEC.B 12H[FB]
+ DEC.B 12H[SB]
+ DEC.B 2345H
+ DEC.B R0H
+ DEC.B R0L
+ DEC.W A0
+ DIV.B #7
+ DIV.B [A0]
+ DIV.B 12H[A0]
+ DIV.B 12H[FB]
+ DIV.B 12H[SB]
+ DIV.B 2345H
+ DIV.B 2345H[A0]
+ DIV.B 2345H[SB]
+ DIV.B A0
+ DIV.B R0H
+ DIV.B R0L
+ DIV.W #2345H
+ DIV.W #7
+ DIV.W [A0]
+ DIV.W 12H[A0]
+ DIV.W 12H[FB]
+ DIV.W 12H[SB]
+ DIV.W 2345H
+ DIV.W 2345H[A0]
+ DIV.W 2345H[SB]
+ DIV.W A0
+ DIV.W R0
+ DIV.W R1
+ DIVU.B #7
+ DIVU.B [A0]
+ DIVU.B 12H[A0]
+ DIVU.B 12H[FB]
+ DIVU.B 12H[SB]
+ DIVU.B 2345H
+ DIVU.B 2345H[A0]
+ DIVU.B 2345H[SB]
+ DIVU.B A0
+ DIVU.B R0H
+ DIVU.B R0L
+ DIVU.W #2345H
+ DIVU.W #7
+ DIVU.W [A0]
+ DIVU.W 12H[A0]
+ DIVU.W 12H[FB]
+ DIVU.W 12H[SB]
+ DIVU.W 2345H
+ DIVU.W 2345H[A0]
+ DIVU.W 2345H[SB]
+ DIVU.W A0
+ DIVU.W R0
+ DIVU.W R1
+ DIVX.B #7
+ DIVX.B [A0]
+ DIVX.B 12H[A0]
+ DIVX.B 12H[FB]
+ DIVX.B 12H[SB]
+ DIVX.B 2345H
+ DIVX.B 2345H[A0]
+ DIVX.B 2345H[SB]
+ DIVX.B A0
+ DIVX.B R0H
+ DIVX.B R0L
+ DIVX.W #2345H
+ DIVX.W #7
+ DIVX.W [A0]
+ DIVX.W 12H[A0]
+ DIVX.W 12H[FB]
+ DIVX.W 12H[SB]
+ DIVX.W 2345H
+ DIVX.W 2345H[A0]
+ DIVX.W 2345H[SB]
+ DIVX.W A0
+ DIVX.W R0
+ DIVX.W R1
+ DSBB.B #7,R0L
+ DSBB.B R0H,R0L
+ DSBB.W #2345H,R0
+ DSBB.W #7,R0
+ DSBB.W R1,R0
+ DSUB.B #7,R0L
+ DSUB.B R0H,R0L
+ DSUB.W #2345H,R0
+ DSUB.W #7,R0
+ DSUB.W R1,R0
+ ENTER #7
+ EXITD
+ EXTS.B [A0]
+ EXTS.B 12H[A0]
+ EXTS.B 12H[FB]
+ EXTS.B 12H[SB]
+ EXTS.B 2345H
+ EXTS.B 2345H[A0]
+ EXTS.B 2345H[SB]
+ EXTS.B R0L
+ FCLR C
+ FCLR D
+ FCLR I
+ FCLR O
+ FCLR S
+ FSET C
+ FSET D
+ FSET I
+ FSET O
+ FSET S
+ INC.B 12H[FB]
+ INC.B 12H[SB]
+ INC.B 2345H
+ INC.B R0H
+ INC.B R0L
+ INC.W A0
+ INT #7
+ INTO
+ JEQ $+5
+ JGE $+5
+ JGEU $+5
+ JGT $+5
+ JGTU $+5
+ JLE $+5
+ JLEU $+5
+ JLT $+5
+ JLTU $+5
+ jmp.a 12345H
+ jmp.a 2345H
+ jmp.b $+5
+ jmp.S $+5
+ jmp.w $+5
+ JMPI.A [A0]
+ JMPI.A 12H[A0]
+ JMPI.A 12H[FB]
+ JMPI.A 12H[SB]
+ JMPI.A 2345H
+ JMPI.A 2345H[A0]
+ JMPI.A 2345H[SB]
+ JMPI.A A1A0
+ JMPI.A R2R0
+ JMPI.W [A0]
+ JMPI.W 12H[A0]
+ JMPI.W 12H[FB]
+ JMPI.W 12H[SB]
+ JMPI.W $+5
+ JMPI.W 2345H[A0]
+ JMPI.W 2345H[SB]
+ JMPI.W A0
+ JMPI.W R0
+ JMPS #18
+ JN $+5
+ JNC $+5
+ JNE $+5
+ JNO $+5
+ JNZ $+5
+ JO $+5
+ JPZ $+5
+ jsr.a 12345H
+ jsr.a 2345H
+ jsr.w $+5
+ JSRI.A [A0]
+ JSRI.A 12H[A0]
+ JSRI.A 12H[FB]
+ JSRI.A 12H[SB]
+ JSRI.A 2345H
+ JSRI.A 2345H[A0]
+ JSRI.A 2345H[SB]
+ JSRI.A A1A0
+ JSRI.A R2R0
+ JSRI.W [A0]
+ JSRI.W 12H[A0]
+ JSRI.W 12H[FB]
+ JSRI.W 12H[SB]
+ JSRI.W $+5
+ JSRI.W 2345H[A0]
+ JSRI.W 2345H[SB]
+ JSRI.W A0
+ JSRI.W R0
+ JSRS #18
+ JZ $+5
+ LDC #2345H,FB
+ LDC #2345H,FLG
+ LDC #2345H,INTBH
+ LDC #2345H,INTBL
+ LDC #2345H,ISP
+ LDC #2345H,SB
+ LDC #2345H,SP
+ LDC #7,FB
+ LDC #7,FLG
+ LDC #7,INTBH
+ LDC #7,INTBL
+ LDC #7,ISP
+ LDC #7,SB
+ LDC #7,SP
+ LDC [A0],FB
+ LDC [A0],FLG
+ LDC [A0],INTBH
+ LDC [A0],INTBL
+ LDC [A0],ISP
+ LDC [A0],SB
+ LDC [A0],SP
+ LDC 12H[A0],FB
+ LDC 12H[A0],FLG
+ LDC 12H[A0],INTBH
+ LDC 12H[A0],INTBL
+ LDC 12H[A0],ISP
+ LDC 12H[A0],SB
+ LDC 12H[A0],SP
+ LDC 12H[FB],FB
+ LDC 12H[FB],FLG
+ LDC 12H[FB],INTBH
+ LDC 12H[FB],INTBL
+ LDC 12H[FB],ISP
+ LDC 12H[FB],SB
+ LDC 12H[FB],SP
+ LDC 12H[SB],FB
+ LDC 12H[SB],FLG
+ LDC 12H[SB],INTBH
+ LDC 12H[SB],INTBL
+ LDC 12H[SB],ISP
+ LDC 12H[SB],SB
+ LDC 12H[SB],SP
+ LDC 2345H,FB
+ LDC 2345H,FLG
+ LDC 2345H,INTBH
+ LDC 2345H,INTBL
+ LDC 2345H,ISP
+ LDC 2345H,SB
+ LDC 2345H,SP
+ LDC 2345H[A0],FB
+ LDC 2345H[A0],FLG
+ LDC 2345H[A0],INTBH
+ LDC 2345H[A0],INTBL
+ LDC 2345H[A0],ISP
+ LDC 2345H[A0],SB
+ LDC 2345H[A0],SP
+ LDC 2345H[SB],FB
+ LDC 2345H[SB],FLG
+ LDC 2345H[SB],INTBH
+ LDC 2345H[SB],INTBL
+ LDC 2345H[SB],ISP
+ LDC 2345H[SB],SB
+ LDC 2345H[SB],SP
+ LDC A0,FB
+ LDC A0,FLG
+ LDC A0,INTBH
+ LDC A0,INTBL
+ LDC A0,ISP
+ LDC A0,SB
+ LDC A0,SP
+ LDC R0,FB
+ LDC R0,FLG
+ LDC R0,INTBH
+ LDC R0,INTBL
+ LDC R0,ISP
+ LDC R0,SB
+ LDC R0,SP
+ LDCTX 2345H,12345H
+ LDCTX 2345H,2345H
+ LDE.B [A1A0],[A0]
+ LDE.B [A1A0],12H[A0]
+ LDE.B [A1A0],12H[FB]
+ LDE.B [A1A0],12H[SB]
+ LDE.B [A1A0],2345H
+ LDE.B [A1A0],2345H[A0]
+ LDE.B [A1A0],2345H[SB]
+ LDE.B [A1A0],A0
+ LDE.B [A1A0],R0L
+ LDE.B 12345H,[A0]
+ LDE.B 12345H,12H[A0]
+ LDE.B 12345H,12H[FB]
+ LDE.B 12345H,12H[SB]
+ LDE.B 12345H,2345H
+ LDE.B 12345H,2345H[A0]
+ LDE.B 12345H,2345H[SB]
+ LDE.B 12345H,A0
+ LDE.B 12345H,R0L
+ LDE.B 12345H[A0],[A0]
+ LDE.B 12345H[A0],12H[A0]
+ LDE.B 12345H[A0],12H[FB]
+ LDE.B 12345H[A0],12H[SB]
+ LDE.B 12345H[A0],2345H
+ LDE.B 12345H[A0],2345H[A0]
+ LDE.B 12345H[A0],2345H[SB]
+ LDE.B 12345H[A0],A0
+ LDE.B 12345H[A0],R0L
+ LDE.B 12H[A0],[A0]
+ LDE.B 12H[A0],12H[A0]
+ LDE.B 12H[A0],12H[FB]
+ LDE.B 12H[A0],12H[SB]
+ LDE.B 12H[A0],2345H
+ LDE.B 12H[A0],2345H[A0]
+ LDE.B 12H[A0],2345H[SB]
+ LDE.B 12H[A0],A0
+ LDE.B 12H[A0],R0L
+ LDE.B 2345H,[A0]
+ LDE.B 2345H,12H[A0]
+ LDE.B 2345H,12H[FB]
+ LDE.B 2345H,12H[SB]
+ LDE.B 2345H,2345H
+ LDE.B 2345H,2345H[A0]
+ LDE.B 2345H,2345H[SB]
+ LDE.B 2345H,A0
+ LDE.B 2345H,R0L
+ LDE.B 2345H[A0],[A0]
+ LDE.B 2345H[A0],12H[A0]
+ LDE.B 2345H[A0],12H[FB]
+ LDE.B 2345H[A0],12H[SB]
+ LDE.B 2345H[A0],2345H
+ LDE.B 2345H[A0],2345H[A0]
+ LDE.B 2345H[A0],2345H[SB]
+ LDE.B 2345H[A0],A0
+ LDE.B 2345H[A0],R0L
+ LDE.W [A1A0],[A0]
+ LDE.W [A1A0],12H[A0]
+ LDE.W [A1A0],12H[FB]
+ LDE.W [A1A0],12H[SB]
+ LDE.W [A1A0],2345H
+ LDE.W [A1A0],2345H[A0]
+ LDE.W [A1A0],2345H[SB]
+ LDE.W [A1A0],A0
+ LDE.W [A1A0],R0
+ LDE.W 12345H,[A0]
+ LDE.W 12345H,12H[A0]
+ LDE.W 12345H,12H[FB]
+ LDE.W 12345H,12H[SB]
+ LDE.W 12345H,2345H
+ LDE.W 12345H,2345H[A0]
+ LDE.W 12345H,2345H[SB]
+ LDE.W 12345H,A0
+ LDE.W 12345H,R0
+ LDE.W 12345H[A0],[A0]
+ LDE.W 12345H[A0],12H[A0]
+ LDE.W 12345H[A0],12H[FB]
+ LDE.W 12345H[A0],12H[SB]
+ LDE.W 12345H[A0],2345H
+ LDE.W 12345H[A0],2345H[A0]
+ LDE.W 12345H[A0],2345H[SB]
+ LDE.W 12345H[A0],A0
+ LDE.W 12345H[A0],R0
+ LDE.W 12H[A0],[A0]
+ LDE.W 12H[A0],12H[A0]
+ LDE.W 12H[A0],12H[FB]
+ LDE.W 12H[A0],12H[SB]
+ LDE.W 12H[A0],2345H
+ LDE.W 12H[A0],2345H[A0]
+ LDE.W 12H[A0],2345H[SB]
+ LDE.W 12H[A0],A0
+ LDE.W 12H[A0],R0
+ LDE.W 2345H,[A0]
+ LDE.W 2345H,12H[A0]
+ LDE.W 2345H,12H[FB]
+ LDE.W 2345H,12H[SB]
+ LDE.W 2345H,2345H
+ LDE.W 2345H,2345H[A0]
+ LDE.W 2345H,2345H[SB]
+ LDE.W 2345H,A0
+ LDE.W 2345H,R0
+ LDE.W 2345H[A0],[A0]
+ LDE.W 2345H[A0],12H[A0]
+ LDE.W 2345H[A0],12H[FB]
+ LDE.W 2345H[A0],12H[SB]
+ LDE.W 2345H[A0],2345H
+ LDE.W 2345H[A0],2345H[A0]
+ LDE.W 2345H[A0],2345H[SB]
+ LDE.W 2345H[A0],A0
+ LDE.W 2345H[A0],R0
+ LDINTB #2345H
+ LDINTB #7
+ LDIPL #7
+ MOV.B:G #0,[A0]
+ MOV.B:G #0,12H[A0]
+ MOV.B:G #0,12H[FB]
+ MOV.B:G #0,12H[SB]
+ MOV.B:G #0,2345H
+ MOV.B:G #0,2345H[A0]
+ MOV.B:G #0,2345H[SB]
+ MOV.B:G #0,A0
+ MOV.B:G #0,R0L
+ MOV.B:G #7,[A0]
+ MOV.B:G #7,12H[A0]
+ MOV.B:G #7,12H[FB]
+ MOV.B:G #7,12H[SB]
+ MOV.B:G #7,2345H
+ MOV.B:G #7,2345H[A0]
+ MOV.B:G #7,2345H[SB]
+ MOV.B:G #7,A0
+ MOV.B:G #7,R0L
+ MOV.B:G [A0],[A0]
+ MOV.B:G [A0],12H[A0]
+ MOV.B:G [A0],12H[FB]
+ MOV.B:G [A0],12H[SB]
+ MOV.B:G [A0],12H[SP]
+ MOV.B:G [A0],2345H
+ MOV.B:G [A0],2345H[A0]
+ MOV.B:G [A0],2345H[SB]
+ MOV.B:G [A0],A0
+ MOV.B:G [A0],R0L
+ MOV.B:G 12H[A0],[A0]
+ MOV.B:G 12H[A0],12H[A0]
+ MOV.B:G 12H[A0],12H[FB]
+ MOV.B:G 12H[A0],12H[SB]
+ MOV.B:G 12H[A0],12H[SP]
+ MOV.B:G 12H[A0],2345H
+ MOV.B:G 12H[A0],2345H[A0]
+ MOV.B:G 12H[A0],2345H[SB]
+ MOV.B:G 12H[A0],A0
+ MOV.B:G 12H[A0],R0L
+ MOV.B:G 12H[FB],[A0]
+ MOV.B:G 12H[FB],12H[A0]
+ MOV.B:G 12H[FB],12H[FB]
+ MOV.B:G 12H[FB],12H[SB]
+ MOV.B:G 12H[FB],12H[SP]
+ MOV.B:G 12H[FB],2345H
+ MOV.B:G 12H[FB],2345H[A0]
+ MOV.B:G 12H[FB],2345H[SB]
+ MOV.B:G 12H[FB],A0
+ MOV.B:G 12H[FB],R0L
+ MOV.B:G 12H[SB],[A0]
+ MOV.B:G 12H[SB],12H[A0]
+ MOV.B:G 12H[SB],12H[FB]
+ MOV.B:G 12H[SB],12H[SB]
+ MOV.B:G 12H[SB],12H[SP]
+ MOV.B:G 12H[SB],2345H
+ MOV.B:G 12H[SB],2345H[A0]
+ MOV.B:G 12H[SB],2345H[SB]
+ MOV.B:G 12H[SB],A0
+ MOV.B:G 12H[SB],R0L
+ MOV.B:G 12H[SP],[A0]
+ MOV.B:G 12H[SP],12H[A0]
+ MOV.B:G 12H[SP],12H[FB]
+ MOV.B:G 12H[SP],12H[SB]
+ MOV.B:G 12H[SP],2345H
+ MOV.B:G 12H[SP],2345H[A0]
+ MOV.B:G 12H[SP],2345H[SB]
+ MOV.B:G 12H[SP],A0
+ MOV.B:G 12H[SP],R0L
+ MOV.B:G 2345H,[A0]
+ MOV.B:G 2345H,12H[A0]
+ MOV.B:G 2345H,12H[FB]
+ MOV.B:G 2345H,12H[SB]
+ MOV.B:G 2345H,12H[SP]
+ MOV.B:G 2345H,2345H
+ MOV.B:G 2345H,2345H[A0]
+ MOV.B:G 2345H,2345H[SB]
+ MOV.B:G 2345H,A0
+ MOV.B:G 2345H,R0L
+ MOV.B:G 2345H[A0],[A0]
+ MOV.B:G 2345H[A0],12H[A0]
+ MOV.B:G 2345H[A0],12H[FB]
+ MOV.B:G 2345H[A0],12H[SB]
+ MOV.B:G 2345H[A0],12H[SP]
+ MOV.B:G 2345H[A0],2345H
+ MOV.B:G 2345H[A0],2345H[A0]
+ MOV.B:G 2345H[A0],2345H[SB]
+ MOV.B:G 2345H[A0],A0
+ MOV.B:G 2345H[A0],R0L
+ MOV.B:G 2345H[SB],[A0]
+ MOV.B:G 2345H[SB],12H[A0]
+ MOV.B:G 2345H[SB],12H[FB]
+ MOV.B:G 2345H[SB],12H[SB]
+ MOV.B:G 2345H[SB],12H[SP]
+ MOV.B:G 2345H[SB],2345H
+ MOV.B:G 2345H[SB],2345H[A0]
+ MOV.B:G 2345H[SB],2345H[SB]
+ MOV.B:G 2345H[SB],A0
+ MOV.B:G 2345H[SB],R0L
+ MOV.B:G A0,[A0]
+ MOV.B:G A0,12H[A0]
+ MOV.B:G A0,12H[FB]
+ MOV.B:G A0,12H[SB]
+ MOV.B:G A0,12H[SP]
+ MOV.B:G A0,2345H
+ MOV.B:G A0,2345H[A0]
+ MOV.B:G A0,2345H[SB]
+ MOV.B:G A0,R0L
+ MOV.B:G R0L,[A0]
+ MOV.B:G R0L,12H[A0]
+ MOV.B:G R0L,12H[FB]
+ MOV.B:G R0L,12H[SB]
+ MOV.B:G R0L,12H[SP]
+ MOV.B:G R0L,2345H
+ MOV.B:G R0L,2345H[A0]
+ MOV.B:G R0L,2345H[SB]
+ MOV.B:G R0L,A0
+ MOV.B:G R0L,R0L
+ MOV.B:Q #0,[A0]
+ MOV.B:Q #0,12H[A0]
+ MOV.B:Q #0,12H[FB]
+ MOV.B:Q #0,12H[SB]
+ MOV.B:Q #0,2345H
+ MOV.B:Q #0,2345H[A0]
+ MOV.B:Q #0,2345H[SB]
+ MOV.B:Q #0,A0
+ MOV.B:Q #0,R0L
+ MOV.B:Q #7,[A0]
+ MOV.B:Q #7,12H[A0]
+ MOV.B:Q #7,12H[FB]
+ MOV.B:Q #7,12H[SB]
+ MOV.B:Q #7,2345H
+ MOV.B:Q #7,2345H[A0]
+ MOV.B:Q #7,2345H[SB]
+ MOV.B:Q #7,A0
+ MOV.B:Q #7,R0L
+ MOV.B:S #0,12H[FB]
+ MOV.B:S #0,12H[SB]
+ MOV.B:S #0,2345H
+ MOV.B:S #0,A0
+ MOV.B:S #0,R0L
+ MOV.B:S #7,12H[FB]
+ MOV.B:S #7,12H[SB]
+ MOV.B:S #7,2345H
+ MOV.B:S #7,A0
+ MOV.B:S #7,R0L
+ MOV.B:S 12H[FB],A0
+ MOV.B:S 12H[FB],R0L
+ MOV.B:S 12H[SB],A0
+ MOV.B:S 12H[SB],R0L
+ MOV.B:S 2345H,A0
+ MOV.B:S 2345H,R0L
+ MOV.B:S R0L,12H[FB]
+ MOV.B:S R0L,12H[SB]
+ MOV.B:S R0L,2345H
+ MOV.B:Z #0,12H[FB]
+ MOV.B:Z #0,12H[SB]
+ MOV.B:Z #0,2345H
+ MOV.B:Z #0,R0L
+ MOV.W:G #0,[A0]
+ MOV.W:G #0,12H[A0]
+ MOV.W:G #0,12H[FB]
+ MOV.W:G #0,12H[SB]
+ MOV.W:G #0,2345H
+ MOV.W:G #0,2345H[A0]
+ MOV.W:G #0,2345H[SB]
+ MOV.W:G #0,A0
+ MOV.W:G #0,R0
+ MOV.W:G #2345H,[A0]
+ MOV.W:G #2345H,12H[A0]
+ MOV.W:G #2345H,12H[FB]
+ MOV.W:G #2345H,12H[SB]
+ MOV.W:G #2345H,2345H
+ MOV.W:G #2345H,2345H[A0]
+ MOV.W:G #2345H,2345H[SB]
+ MOV.W:G #2345H,A0
+ MOV.W:G #2345H,R0
+ MOV.W:G #7,[A0]
+ MOV.W:G #7,12H[A0]
+ MOV.W:G #7,12H[FB]
+ MOV.W:G #7,12H[SB]
+ MOV.W:G #7,2345H
+ MOV.W:G #7,2345H[A0]
+ MOV.W:G #7,2345H[SB]
+ MOV.W:G #7,A0
+ MOV.W:G #7,R0
+ MOV.W:G [A0],[A0]
+ MOV.W:G [A0],12H[A0]
+ MOV.W:G [A0],12H[FB]
+ MOV.W:G [A0],12H[SB]
+ MOV.W:G [A0],12H[SP]
+ MOV.W:G [A0],2345H
+ MOV.W:G [A0],2345H[A0]
+ MOV.W:G [A0],2345H[SB]
+ MOV.W:G [A0],A0
+ MOV.W:G [A0],R0
+ MOV.W:G 12H[A0],[A0]
+ MOV.W:G 12H[A0],12H[A0]
+ MOV.W:G 12H[A0],12H[FB]
+ MOV.W:G 12H[A0],12H[SB]
+ MOV.W:G 12H[A0],12H[SP]
+ MOV.W:G 12H[A0],2345H
+ MOV.W:G 12H[A0],2345H[A0]
+ MOV.W:G 12H[A0],2345H[SB]
+ MOV.W:G 12H[A0],A0
+ MOV.W:G 12H[A0],R0
+ MOV.W:G 12H[FB],[A0]
+ MOV.W:G 12H[FB],12H[A0]
+ MOV.W:G 12H[FB],12H[FB]
+ MOV.W:G 12H[FB],12H[SB]
+ MOV.W:G 12H[FB],12H[SP]
+ MOV.W:G 12H[FB],2345H
+ MOV.W:G 12H[FB],2345H[A0]
+ MOV.W:G 12H[FB],2345H[SB]
+ MOV.W:G 12H[FB],A0
+ MOV.W:G 12H[FB],R0
+ MOV.W:G 12H[SB],[A0]
+ MOV.W:G 12H[SB],12H[A0]
+ MOV.W:G 12H[SB],12H[FB]
+ MOV.W:G 12H[SB],12H[SB]
+ MOV.W:G 12H[SB],12H[SP]
+ MOV.W:G 12H[SB],2345H
+ MOV.W:G 12H[SB],2345H[A0]
+ MOV.W:G 12H[SB],2345H[SB]
+ MOV.W:G 12H[SB],A0
+ MOV.W:G 12H[SB],R0
+ MOV.W:G 12H[SP],[A0]
+ MOV.W:G 12H[SP],12H[A0]
+ MOV.W:G 12H[SP],12H[FB]
+ MOV.W:G 12H[SP],12H[SB]
+ MOV.W:G 12H[SP],2345H
+ MOV.W:G 12H[SP],2345H[A0]
+ MOV.W:G 12H[SP],2345H[SB]
+ MOV.W:G 12H[SP],A0
+ MOV.W:G 12H[SP],R0
+ MOV.W:G 2345H,[A0]
+ MOV.W:G 2345H,12H[A0]
+ MOV.W:G 2345H,12H[FB]
+ MOV.W:G 2345H,12H[SB]
+ MOV.W:G 2345H,12H[SP]
+ MOV.W:G 2345H,2345H
+ MOV.W:G 2345H,2345H[A0]
+ MOV.W:G 2345H,2345H[SB]
+ MOV.W:G 2345H,A0
+ MOV.W:G 2345H,R0
+ MOV.W:G 2345H[A0],[A0]
+ MOV.W:G 2345H[A0],12H[A0]
+ MOV.W:G 2345H[A0],12H[FB]
+ MOV.W:G 2345H[A0],12H[SB]
+ MOV.W:G 2345H[A0],12H[SP]
+ MOV.W:G 2345H[A0],2345H
+ MOV.W:G 2345H[A0],2345H[A0]
+ MOV.W:G 2345H[A0],2345H[SB]
+ MOV.W:G 2345H[A0],A0
+ MOV.W:G 2345H[A0],R0
+ MOV.W:G 2345H[SB],[A0]
+ MOV.W:G 2345H[SB],12H[A0]
+ MOV.W:G 2345H[SB],12H[FB]
+ MOV.W:G 2345H[SB],12H[SB]
+ MOV.W:G 2345H[SB],12H[SP]
+ MOV.W:G 2345H[SB],2345H
+ MOV.W:G 2345H[SB],2345H[A0]
+ MOV.W:G 2345H[SB],2345H[SB]
+ MOV.W:G 2345H[SB],A0
+ MOV.W:G 2345H[SB],R0
+ MOV.W:G A0,[A0]
+ MOV.W:G A0,12H[A0]
+ MOV.W:G A0,12H[FB]
+ MOV.W:G A0,12H[SB]
+ MOV.W:G A0,12H[SP]
+ MOV.W:G A0,2345H
+ MOV.W:G A0,2345H[A0]
+ MOV.W:G A0,2345H[SB]
+ MOV.W:G A0,A0
+ MOV.W:G A0,R0
+ MOV.W:G R0,[A0]
+ MOV.W:G R0,12H[A0]
+ MOV.W:G R0,12H[FB]
+ MOV.W:G R0,12H[SB]
+ MOV.W:G R0,12H[SP]
+ MOV.W:G R0,2345H
+ MOV.W:G R0,2345H[A0]
+ MOV.W:G R0,2345H[SB]
+ MOV.W:G R0,A0
+ MOV.W:G R0,R0
+ MOV.W:Q #0,[A0]
+ MOV.W:Q #0,12H[A0]
+ MOV.W:Q #0,12H[FB]
+ MOV.W:Q #0,12H[SB]
+ MOV.W:Q #0,2345H
+ MOV.W:Q #0,2345H[A0]
+ MOV.W:Q #0,2345H[SB]
+ MOV.W:Q #0,A0
+ MOV.W:Q #0,R0
+ MOV.W:Q #7,[A0]
+ MOV.W:Q #7,12H[A0]
+ MOV.W:Q #7,12H[FB]
+ MOV.W:Q #7,12H[SB]
+ MOV.W:Q #7,2345H
+ MOV.W:Q #7,2345H[A0]
+ MOV.W:Q #7,2345H[SB]
+ MOV.W:Q #7,A0
+ MOV.W:Q #7,R0
+ MOV.W:S #0,A0
+ MOV.W:S #2345H,A0
+ MOV.W:S #7,A0
+ MOVA 12H[A0],A0
+ MOVA 12H[A0],R0
+ MOVA 12H[FB],A0
+ MOVA 12H[FB],R0
+ MOVA 12H[SB],A0
+ MOVA 12H[SB],R0
+ MOVA 2345H,A0
+ MOVA 2345H,R0
+ MOVA 2345H[A0],A0
+ MOVA 2345H[A0],R0
+ MOVA 2345H[SB],A0
+ MOVA 2345H[SB],R0
+ MOVHH [A0],R0L
+ MOVHH 12H[A0],R0L
+ MOVHH 12H[FB],R0L
+ MOVHH 12H[SB],R0L
+ MOVHH 2345H,R0L
+ MOVHH 2345H[A0],R0L
+ MOVHH 2345H[SB],R0L
+ MOVHH R0L,[A0]
+ MOVHH R0L,12H[A0]
+ MOVHH R0L,12H[FB]
+ MOVHH R0L,12H[SB]
+ MOVHH R0L,2345H
+ MOVHH R0L,2345H[A0]
+ MOVHH R0L,2345H[SB]
+ MOVHH R0L,R0L
+ MOVHL [A0],R0L
+ MOVHL 12H[A0],R0L
+ MOVHL 12H[FB],R0L
+ MOVHL 12H[SB],R0L
+ MOVHL 2345H,R0L
+ MOVHL 2345H[A0],R0L
+ MOVHL 2345H[SB],R0L
+ MOVHL R0L,[A0]
+ MOVHL R0L,12H[A0]
+ MOVHL R0L,12H[FB]
+ MOVHL R0L,12H[SB]
+ MOVHL R0L,2345H
+ MOVHL R0L,2345H[A0]
+ MOVHL R0L,2345H[SB]
+ MOVHL R0L,R0L
+ MOVLH [A0],R0L
+ MOVLH 12H[A0],R0L
+ MOVLH 12H[FB],R0L
+ MOVLH 12H[SB],R0L
+ MOVLH 2345H,R0L
+ MOVLH 2345H[A0],R0L
+ MOVLH 2345H[SB],R0L
+ MOVLH R0L,[A0]
+ MOVLH R0L,12H[A0]
+ MOVLH R0L,12H[FB]
+ MOVLH R0L,12H[SB]
+ MOVLH R0L,2345H
+ MOVLH R0L,2345H[A0]
+ MOVLH R0L,2345H[SB]
+ MOVLH R0L,R0L
+ MOVLL [A0],R0L
+ MOVLL 12H[A0],R0L
+ MOVLL 12H[FB],R0L
+ MOVLL 12H[SB],R0L
+ MOVLL 2345H,R0L
+ MOVLL 2345H[A0],R0L
+ MOVLL 2345H[SB],R0L
+ MOVLL R0L,[A0]
+ MOVLL R0L,12H[A0]
+ MOVLL R0L,12H[FB]
+ MOVLL R0L,12H[SB]
+ MOVLL R0L,2345H
+ MOVLL R0L,2345H[A0]
+ MOVLL R0L,2345H[SB]
+ MOVLL R0L,R0L
+ MUL.B #0,[A0]
+ MUL.B #0,12H[A0]
+ MUL.B #0,12H[FB]
+ MUL.B #0,12H[SB]
+ MUL.B #0,2345H
+ MUL.B #0,2345H[A0]
+ MUL.B #0,2345H[SB]
+ MUL.B #0,A0
+ MUL.B #0,R0L
+ MUL.B #7,[A0]
+ MUL.B #7,12H[A0]
+ MUL.B #7,12H[FB]
+ MUL.B #7,12H[SB]
+ MUL.B #7,2345H
+ MUL.B #7,2345H[A0]
+ MUL.B #7,2345H[SB]
+ MUL.B #7,A0
+ MUL.B #7,R0L
+ MUL.B [A0],[A0]
+ MUL.B [A0],12H[A0]
+ MUL.B [A0],12H[FB]
+ MUL.B [A0],12H[SB]
+ MUL.B [A0],2345H
+ MUL.B [A0],2345H[A0]
+ MUL.B [A0],2345H[SB]
+ MUL.B [A0],A0
+ MUL.B [A0],R0L
+ MUL.B 12H[A0],[A0]
+ MUL.B 12H[A0],12H[A0]
+ MUL.B 12H[A0],12H[FB]
+ MUL.B 12H[A0],12H[SB]
+ MUL.B 12H[A0],2345H
+ MUL.B 12H[A0],2345H[A0]
+ MUL.B 12H[A0],2345H[SB]
+ MUL.B 12H[A0],A0
+ MUL.B 12H[A0],R0L
+ MUL.B 12H[FB],[A0]
+ MUL.B 12H[FB],12H[A0]
+ MUL.B 12H[FB],12H[FB]
+ MUL.B 12H[FB],12H[SB]
+ MUL.B 12H[FB],2345H
+ MUL.B 12H[FB],2345H[A0]
+ MUL.B 12H[FB],2345H[SB]
+ MUL.B 12H[FB],A0
+ MUL.B 12H[FB],R0L
+ MUL.B 12H[SB],[A0]
+ MUL.B 12H[SB],12H[A0]
+ MUL.B 12H[SB],12H[FB]
+ MUL.B 12H[SB],12H[SB]
+ MUL.B 12H[SB],2345H
+ MUL.B 12H[SB],2345H[A0]
+ MUL.B 12H[SB],2345H[SB]
+ MUL.B 12H[SB],A0
+ MUL.B 12H[SB],R0L
+ MUL.B 2345H,[A0]
+ MUL.B 2345H,12H[A0]
+ MUL.B 2345H,12H[FB]
+ MUL.B 2345H,12H[SB]
+ MUL.B 2345H,2345H
+ MUL.B 2345H,2345H[A0]
+ MUL.B 2345H,2345H[SB]
+ MUL.B 2345H,A0
+ MUL.B 2345H,R0L
+ MUL.B 2345H[A0],[A0]
+ MUL.B 2345H[A0],12H[A0]
+ MUL.B 2345H[A0],12H[FB]
+ MUL.B 2345H[A0],12H[SB]
+ MUL.B 2345H[A0],2345H
+ MUL.B 2345H[A0],2345H[A0]
+ MUL.B 2345H[A0],2345H[SB]
+ MUL.B 2345H[A0],A0
+ MUL.B 2345H[A0],R0L
+ MUL.B 2345H[SB],[A0]
+ MUL.B 2345H[SB],12H[A0]
+ MUL.B 2345H[SB],12H[FB]
+ MUL.B 2345H[SB],12H[SB]
+ MUL.B 2345H[SB],2345H
+ MUL.B 2345H[SB],2345H[A0]
+ MUL.B 2345H[SB],2345H[SB]
+ MUL.B 2345H[SB],A0
+ MUL.B 2345H[SB],R0L
+ MUL.B A0,[A0]
+ MUL.B A0,12H[A0]
+ MUL.B A0,12H[FB]
+ MUL.B A0,12H[SB]
+ MUL.B A0,2345H
+ MUL.B A0,2345H[A0]
+ MUL.B A0,2345H[SB]
+ MUL.B A0,R0L
+ MUL.B R0L,[A0]
+ MUL.B R0L,12H[A0]
+ MUL.B R0L,12H[FB]
+ MUL.B R0L,12H[SB]
+ MUL.B R0L,2345H
+ MUL.B R0L,2345H[A0]
+ MUL.B R0L,2345H[SB]
+ MUL.B R0L,A0
+ MUL.B R0L,R0L
+ MUL.W #0,[A0]
+ MUL.W #0,12H[A0]
+ MUL.W #0,12H[FB]
+ MUL.W #0,12H[SB]
+ MUL.W #0,2345H
+ MUL.W #0,2345H[A0]
+ MUL.W #0,2345H[SB]
+ MUL.W #0,A0
+ MUL.W #0,R0
+ MUL.W #2345H,[A0]
+ MUL.W #2345H,12H[A0]
+ MUL.W #2345H,12H[FB]
+ MUL.W #2345H,12H[SB]
+ MUL.W #2345H,2345H
+ MUL.W #2345H,2345H[A0]
+ MUL.W #2345H,2345H[SB]
+ MUL.W #2345H,A0
+ MUL.W #2345H,R0
+ MUL.W #7,[A0]
+ MUL.W #7,12H[A0]
+ MUL.W #7,12H[FB]
+ MUL.W #7,12H[SB]
+ MUL.W #7,2345H
+ MUL.W #7,2345H[A0]
+ MUL.W #7,2345H[SB]
+ MUL.W #7,A0
+ MUL.W #7,R0
+ MUL.W [A0],[A0]
+ MUL.W [A0],12H[A0]
+ MUL.W [A0],12H[FB]
+ MUL.W [A0],12H[SB]
+ MUL.W [A0],2345H
+ MUL.W [A0],2345H[A0]
+ MUL.W [A0],2345H[SB]
+ MUL.W [A0],A0
+ MUL.W [A0],R0
+ MUL.W 12H[A0],[A0]
+ MUL.W 12H[A0],12H[A0]
+ MUL.W 12H[A0],12H[FB]
+ MUL.W 12H[A0],12H[SB]
+ MUL.W 12H[A0],2345H
+ MUL.W 12H[A0],2345H[A0]
+ MUL.W 12H[A0],2345H[SB]
+ MUL.W 12H[A0],A0
+ MUL.W 12H[A0],R0
+ MUL.W 12H[FB],[A0]
+ MUL.W 12H[FB],12H[A0]
+ MUL.W 12H[FB],12H[FB]
+ MUL.W 12H[FB],12H[SB]
+ MUL.W 12H[FB],2345H
+ MUL.W 12H[FB],2345H[A0]
+ MUL.W 12H[FB],2345H[SB]
+ MUL.W 12H[FB],A0
+ MUL.W 12H[FB],R0
+ MUL.W 12H[SB],[A0]
+ MUL.W 12H[SB],12H[A0]
+ MUL.W 12H[SB],12H[FB]
+ MUL.W 12H[SB],12H[SB]
+ MUL.W 12H[SB],2345H
+ MUL.W 12H[SB],2345H[A0]
+ MUL.W 12H[SB],2345H[SB]
+ MUL.W 12H[SB],A0
+ MUL.W 12H[SB],R0
+ MUL.W 2345H,[A0]
+ MUL.W 2345H,12H[A0]
+ MUL.W 2345H,12H[FB]
+ MUL.W 2345H,12H[SB]
+ MUL.W 2345H,2345H
+ MUL.W 2345H,2345H[A0]
+ MUL.W 2345H,2345H[SB]
+ MUL.W 2345H,A0
+ MUL.W 2345H,R0
+ MUL.W 2345H[A0],[A0]
+ MUL.W 2345H[A0],12H[A0]
+ MUL.W 2345H[A0],12H[FB]
+ MUL.W 2345H[A0],12H[SB]
+ MUL.W 2345H[A0],2345H
+ MUL.W 2345H[A0],2345H[A0]
+ MUL.W 2345H[A0],2345H[SB]
+ MUL.W 2345H[A0],A0
+ MUL.W 2345H[A0],R0
+ MUL.W 2345H[SB],[A0]
+ MUL.W 2345H[SB],12H[A0]
+ MUL.W 2345H[SB],12H[FB]
+ MUL.W 2345H[SB],12H[SB]
+ MUL.W 2345H[SB],2345H
+ MUL.W 2345H[SB],2345H[A0]
+ MUL.W 2345H[SB],2345H[SB]
+ MUL.W 2345H[SB],A0
+ MUL.W 2345H[SB],R0
+ MUL.W A0,[A0]
+ MUL.W A0,12H[A0]
+ MUL.W A0,12H[FB]
+ MUL.W A0,12H[SB]
+ MUL.W A0,2345H
+ MUL.W A0,2345H[A0]
+ MUL.W A0,2345H[SB]
+ MUL.W A0,A0
+ MUL.W A0,R0
+ MUL.W R0,[A0]
+ MUL.W R0,12H[A0]
+ MUL.W R0,12H[FB]
+ MUL.W R0,12H[SB]
+ MUL.W R0,2345H
+ MUL.W R0,2345H[A0]
+ MUL.W R0,2345H[SB]
+ MUL.W R0,A0
+ MUL.W R0,R0
+ MULU.B #0,[A0]
+ MULU.B #0,12H[A0]
+ MULU.B #0,12H[FB]
+ MULU.B #0,12H[SB]
+ MULU.B #0,2345H
+ MULU.B #0,2345H[A0]
+ MULU.B #0,2345H[SB]
+ MULU.B #0,A0
+ MULU.B #0,R0L
+ MULU.B #7,[A0]
+ MULU.B #7,12H[A0]
+ MULU.B #7,12H[FB]
+ MULU.B #7,12H[SB]
+ MULU.B #7,2345H
+ MULU.B #7,2345H[A0]
+ MULU.B #7,2345H[SB]
+ MULU.B #7,A0
+ MULU.B #7,R0L
+ MULU.B [A0],[A0]
+ MULU.B [A0],12H[A0]
+ MULU.B [A0],12H[FB]
+ MULU.B [A0],12H[SB]
+ MULU.B [A0],2345H
+ MULU.B [A0],2345H[A0]
+ MULU.B [A0],2345H[SB]
+ MULU.B [A0],A0
+ MULU.B [A0],R0L
+ MULU.B 12H[A0],[A0]
+ MULU.B 12H[A0],12H[A0]
+ MULU.B 12H[A0],12H[FB]
+ MULU.B 12H[A0],12H[SB]
+ MULU.B 12H[A0],2345H
+ MULU.B 12H[A0],2345H[A0]
+ MULU.B 12H[A0],2345H[SB]
+ MULU.B 12H[A0],A0
+ MULU.B 12H[A0],R0L
+ MULU.B 12H[FB],[A0]
+ MULU.B 12H[FB],12H[A0]
+ MULU.B 12H[FB],12H[FB]
+ MULU.B 12H[FB],12H[SB]
+ MULU.B 12H[FB],2345H
+ MULU.B 12H[FB],2345H[A0]
+ MULU.B 12H[FB],2345H[SB]
+ MULU.B 12H[FB],A0
+ MULU.B 12H[FB],R0L
+ MULU.B 12H[SB],[A0]
+ MULU.B 12H[SB],12H[A0]
+ MULU.B 12H[SB],12H[FB]
+ MULU.B 12H[SB],12H[SB]
+ MULU.B 12H[SB],2345H
+ MULU.B 12H[SB],2345H[A0]
+ MULU.B 12H[SB],2345H[SB]
+ MULU.B 12H[SB],A0
+ MULU.B 12H[SB],R0L
+ MULU.B 2345H,[A0]
+ MULU.B 2345H,12H[A0]
+ MULU.B 2345H,12H[FB]
+ MULU.B 2345H,12H[SB]
+ MULU.B 2345H,2345H
+ MULU.B 2345H,2345H[A0]
+ MULU.B 2345H,2345H[SB]
+ MULU.B 2345H,A0
+ MULU.B 2345H,R0L
+ MULU.B 2345H[A0],[A0]
+ MULU.B 2345H[A0],12H[A0]
+ MULU.B 2345H[A0],12H[FB]
+ MULU.B 2345H[A0],12H[SB]
+ MULU.B 2345H[A0],2345H
+ MULU.B 2345H[A0],2345H[A0]
+ MULU.B 2345H[A0],2345H[SB]
+ MULU.B 2345H[A0],A0
+ MULU.B 2345H[A0],R0L
+ MULU.B 2345H[SB],[A0]
+ MULU.B 2345H[SB],12H[A0]
+ MULU.B 2345H[SB],12H[FB]
+ MULU.B 2345H[SB],12H[SB]
+ MULU.B 2345H[SB],2345H
+ MULU.B 2345H[SB],2345H[A0]
+ MULU.B 2345H[SB],2345H[SB]
+ MULU.B 2345H[SB],A0
+ MULU.B 2345H[SB],R0L
+ MULU.B A0,[A0]
+ MULU.B A0,12H[A0]
+ MULU.B A0,12H[FB]
+ MULU.B A0,12H[SB]
+ MULU.B A0,2345H
+ MULU.B A0,2345H[A0]
+ MULU.B A0,2345H[SB]
+ MULU.B A0,R0L
+ MULU.B R0L,[A0]
+ MULU.B R0L,12H[A0]
+ MULU.B R0L,12H[FB]
+ MULU.B R0L,12H[SB]
+ MULU.B R0L,2345H
+ MULU.B R0L,2345H[A0]
+ MULU.B R0L,2345H[SB]
+ MULU.B R0L,A0
+ MULU.B R0L,R0L
+ MULU.W #0,[A0]
+ MULU.W #0,12H[A0]
+ MULU.W #0,12H[FB]
+ MULU.W #0,12H[SB]
+ MULU.W #0,2345H
+ MULU.W #0,2345H[A0]
+ MULU.W #0,2345H[SB]
+ MULU.W #0,A0
+ MULU.W #0,R0
+ MULU.W #2345H,[A0]
+ MULU.W #2345H,12H[A0]
+ MULU.W #2345H,12H[FB]
+ MULU.W #2345H,12H[SB]
+ MULU.W #2345H,2345H
+ MULU.W #2345H,2345H[A0]
+ MULU.W #2345H,2345H[SB]
+ MULU.W #2345H,A0
+ MULU.W #2345H,R0
+ MULU.W #7,[A0]
+ MULU.W #7,12H[A0]
+ MULU.W #7,12H[FB]
+ MULU.W #7,12H[SB]
+ MULU.W #7,2345H
+ MULU.W #7,2345H[A0]
+ MULU.W #7,2345H[SB]
+ MULU.W #7,A0
+ MULU.W #7,R0
+ MULU.W [A0],[A0]
+ MULU.W [A0],12H[A0]
+ MULU.W [A0],12H[FB]
+ MULU.W [A0],12H[SB]
+ MULU.W [A0],2345H
+ MULU.W [A0],2345H[A0]
+ MULU.W [A0],2345H[SB]
+ MULU.W [A0],A0
+ MULU.W [A0],R0
+ MULU.W 12H[A0],[A0]
+ MULU.W 12H[A0],12H[A0]
+ MULU.W 12H[A0],12H[FB]
+ MULU.W 12H[A0],12H[SB]
+ MULU.W 12H[A0],2345H
+ MULU.W 12H[A0],2345H[A0]
+ MULU.W 12H[A0],2345H[SB]
+ MULU.W 12H[A0],A0
+ MULU.W 12H[A0],R0
+ MULU.W 12H[FB],[A0]
+ MULU.W 12H[FB],12H[A0]
+ MULU.W 12H[FB],12H[FB]
+ MULU.W 12H[FB],12H[SB]
+ MULU.W 12H[FB],2345H
+ MULU.W 12H[FB],2345H[A0]
+ MULU.W 12H[FB],2345H[SB]
+ MULU.W 12H[FB],A0
+ MULU.W 12H[FB],R0
+ MULU.W 12H[SB],[A0]
+ MULU.W 12H[SB],12H[A0]
+ MULU.W 12H[SB],12H[FB]
+ MULU.W 12H[SB],12H[SB]
+ MULU.W 12H[SB],2345H
+ MULU.W 12H[SB],2345H[A0]
+ MULU.W 12H[SB],2345H[SB]
+ MULU.W 12H[SB],A0
+ MULU.W 12H[SB],R0
+ MULU.W 2345H,[A0]
+ MULU.W 2345H,12H[A0]
+ MULU.W 2345H,12H[FB]
+ MULU.W 2345H,12H[SB]
+ MULU.W 2345H,2345H
+ MULU.W 2345H,2345H[A0]
+ MULU.W 2345H,2345H[SB]
+ MULU.W 2345H,A0
+ MULU.W 2345H,R0
+ MULU.W 2345H[A0],[A0]
+ MULU.W 2345H[A0],12H[A0]
+ MULU.W 2345H[A0],12H[FB]
+ MULU.W 2345H[A0],12H[SB]
+ MULU.W 2345H[A0],2345H
+ MULU.W 2345H[A0],2345H[A0]
+ MULU.W 2345H[A0],2345H[SB]
+ MULU.W 2345H[A0],A0
+ MULU.W 2345H[A0],R0
+ MULU.W 2345H[SB],[A0]
+ MULU.W 2345H[SB],12H[A0]
+ MULU.W 2345H[SB],12H[FB]
+ MULU.W 2345H[SB],12H[SB]
+ MULU.W 2345H[SB],2345H
+ MULU.W 2345H[SB],2345H[A0]
+ MULU.W 2345H[SB],2345H[SB]
+ MULU.W 2345H[SB],A0
+ MULU.W 2345H[SB],R0
+ MULU.W A0,[A0]
+ MULU.W A0,12H[A0]
+ MULU.W A0,12H[FB]
+ MULU.W A0,12H[SB]
+ MULU.W A0,2345H
+ MULU.W A0,2345H[A0]
+ MULU.W A0,2345H[SB]
+ MULU.W A0,A0
+ MULU.W A0,R0
+ MULU.W R0,[A0]
+ MULU.W R0,12H[A0]
+ MULU.W R0,12H[FB]
+ MULU.W R0,12H[SB]
+ MULU.W R0,2345H
+ MULU.W R0,2345H[A0]
+ MULU.W R0,2345H[SB]
+ MULU.W R0,A0
+ MULU.W R0,R0
+ NEG.B [A0]
+ NEG.B 12H[A0]
+ NEG.B 12H[FB]
+ NEG.B 12H[SB]
+ NEG.B 2345H
+ NEG.B 2345H[A0]
+ NEG.B 2345H[SB]
+ NEG.B R0L
+ NEG.W [A0]
+ NEG.W 12H[A0]
+ NEG.W 12H[FB]
+ NEG.W 12H[SB]
+ NEG.W 2345H
+ NEG.W 2345H[A0]
+ NEG.W 2345H[SB]
+ NEG.W A0
+ NEG.W R0
+ NOP
+ NOT.B:G [A0]
+ NOT.B:G 12H[A0]
+ NOT.B:G 12H[FB]
+ NOT.B:G 12H[SB]
+ NOT.B:G 2345H
+ NOT.B:G 2345H[A0]
+ NOT.B:G 2345H[SB]
+ NOT.B:G R0L
+ NOT.B:S 12H[FB]
+ NOT.B:S 12H[SB]
+ NOT.B:S 2345H
+ NOT.B:S R0L
+ NOT.W:G [A0]
+ NOT.W:G 12H[A0]
+ NOT.W:G 12H[FB]
+ NOT.W:G 12H[SB]
+ NOT.W:G 2345H
+ NOT.W:G 2345H[A0]
+ NOT.W:G 2345H[SB]
+ NOT.W:G A0
+ NOT.W:G R0
+ OR.B:G #7,[A0]
+ OR.B:G #7,12H[A0]
+ OR.B:G #7,12H[FB]
+ OR.B:G #7,12H[SB]
+ OR.B:G #7,2345H
+ OR.B:G #7,2345H[A0]
+ OR.B:G #7,2345H[SB]
+ OR.B:G #7,A0
+ OR.B:G #7,R0L
+ OR.B:G [A0],[A0]
+ OR.B:G [A0],12H[A0]
+ OR.B:G [A0],12H[FB]
+ OR.B:G [A0],12H[SB]
+ OR.B:G [A0],2345H
+ OR.B:G [A0],2345H[A0]
+ OR.B:G [A0],2345H[SB]
+ OR.B:G [A0],A0
+ OR.B:G [A0],R0L
+ OR.B:G 12H[A0],[A0]
+ OR.B:G 12H[A0],12H[A0]
+ OR.B:G 12H[A0],12H[FB]
+ OR.B:G 12H[A0],12H[SB]
+ OR.B:G 12H[A0],2345H
+ OR.B:G 12H[A0],2345H[A0]
+ OR.B:G 12H[A0],2345H[SB]
+ OR.B:G 12H[A0],A0
+ OR.B:G 12H[A0],R0L
+ OR.B:G 12H[FB],[A0]
+ OR.B:G 12H[FB],12H[A0]
+ OR.B:G 12H[FB],12H[FB]
+ OR.B:G 12H[FB],12H[SB]
+ OR.B:G 12H[FB],2345H
+ OR.B:G 12H[FB],2345H[A0]
+ OR.B:G 12H[FB],2345H[SB]
+ OR.B:G 12H[FB],A0
+ OR.B:G 12H[FB],R0L
+ OR.B:G 12H[SB],[A0]
+ OR.B:G 12H[SB],12H[A0]
+ OR.B:G 12H[SB],12H[FB]
+ OR.B:G 12H[SB],12H[SB]
+ OR.B:G 12H[SB],2345H
+ OR.B:G 12H[SB],2345H[A0]
+ OR.B:G 12H[SB],2345H[SB]
+ OR.B:G 12H[SB],A0
+ OR.B:G 12H[SB],R0L
+ OR.B:G 2345H,[A0]
+ OR.B:G 2345H,12H[A0]
+ OR.B:G 2345H,12H[FB]
+ OR.B:G 2345H,12H[SB]
+ OR.B:G 2345H,2345H
+ OR.B:G 2345H,2345H[A0]
+ OR.B:G 2345H,2345H[SB]
+ OR.B:G 2345H,A0
+ OR.B:G 2345H,R0L
+ OR.B:G 2345H[A0],[A0]
+ OR.B:G 2345H[A0],12H[A0]
+ OR.B:G 2345H[A0],12H[FB]
+ OR.B:G 2345H[A0],12H[SB]
+ OR.B:G 2345H[A0],2345H
+ OR.B:G 2345H[A0],2345H[A0]
+ OR.B:G 2345H[A0],2345H[SB]
+ OR.B:G 2345H[A0],A0
+ OR.B:G 2345H[A0],R0L
+ OR.B:G 2345H[SB],[A0]
+ OR.B:G 2345H[SB],12H[A0]
+ OR.B:G 2345H[SB],12H[FB]
+ OR.B:G 2345H[SB],12H[SB]
+ OR.B:G 2345H[SB],2345H
+ OR.B:G 2345H[SB],2345H[A0]
+ OR.B:G 2345H[SB],2345H[SB]
+ OR.B:G 2345H[SB],A0
+ OR.B:G 2345H[SB],R0L
+ OR.B:G A0,[A0]
+ OR.B:G A0,12H[A0]
+ OR.B:G A0,12H[FB]
+ OR.B:G A0,12H[SB]
+ OR.B:G A0,2345H
+ OR.B:G A0,2345H[A0]
+ OR.B:G A0,2345H[SB]
+ OR.B:G A0,R0L
+ OR.B:G R0L,[A0]
+ OR.B:G R0L,12H[A0]
+ OR.B:G R0L,12H[FB]
+ OR.B:G R0L,12H[SB]
+ OR.B:G R0L,2345H
+ OR.B:G R0L,2345H[A0]
+ OR.B:G R0L,2345H[SB]
+ OR.B:G R0L,A0
+ OR.B:G R0L,R0L
+ OR.B:S #7,12H[FB]
+ OR.B:S #7,12H[SB]
+ OR.B:S #7,2345H
+ OR.B:S #7,R0L
+ OR.B:S 12H[FB],R0L
+ OR.B:S 12H[SB],R0L
+ OR.B:S 2345H,R0L
+ OR.W:G #2345H,[A0]
+ OR.W:G #2345H,12H[A0]
+ OR.W:G #2345H,12H[FB]
+ OR.W:G #2345H,12H[SB]
+ OR.W:G #2345H,2345H
+ OR.W:G #2345H,2345H[A0]
+ OR.W:G #2345H,2345H[SB]
+ OR.W:G #2345H,A0
+ OR.W:G #2345H,R0
+ OR.W:G #7,[A0]
+ OR.W:G #7,12H[A0]
+ OR.W:G #7,12H[FB]
+ OR.W:G #7,12H[SB]
+ OR.W:G #7,2345H
+ OR.W:G #7,2345H[A0]
+ OR.W:G #7,2345H[SB]
+ OR.W:G #7,A0
+ OR.W:G #7,R0
+ OR.W:G [A0],[A0]
+ OR.W:G [A0],12H[A0]
+ OR.W:G [A0],12H[FB]
+ OR.W:G [A0],12H[SB]
+ OR.W:G [A0],2345H
+ OR.W:G [A0],2345H[A0]
+ OR.W:G [A0],2345H[SB]
+ OR.W:G [A0],A0
+ OR.W:G [A0],R0
+ OR.W:G 12H[A0],[A0]
+ OR.W:G 12H[A0],12H[A0]
+ OR.W:G 12H[A0],12H[FB]
+ OR.W:G 12H[A0],12H[SB]
+ OR.W:G 12H[A0],2345H
+ OR.W:G 12H[A0],2345H[A0]
+ OR.W:G 12H[A0],2345H[SB]
+ OR.W:G 12H[A0],A0
+ OR.W:G 12H[A0],R0
+ OR.W:G 12H[FB],[A0]
+ OR.W:G 12H[FB],12H[A0]
+ OR.W:G 12H[FB],12H[FB]
+ OR.W:G 12H[FB],12H[SB]
+ OR.W:G 12H[FB],2345H
+ OR.W:G 12H[FB],2345H[A0]
+ OR.W:G 12H[FB],2345H[SB]
+ OR.W:G 12H[FB],A0
+ OR.W:G 12H[FB],R0
+ OR.W:G 12H[SB],[A0]
+ OR.W:G 12H[SB],12H[A0]
+ OR.W:G 12H[SB],12H[FB]
+ OR.W:G 12H[SB],12H[SB]
+ OR.W:G 12H[SB],2345H
+ OR.W:G 12H[SB],2345H[A0]
+ OR.W:G 12H[SB],2345H[SB]
+ OR.W:G 12H[SB],A0
+ OR.W:G 12H[SB],R0
+ OR.W:G 2345H,[A0]
+ OR.W:G 2345H,12H[A0]
+ OR.W:G 2345H,12H[FB]
+ OR.W:G 2345H,12H[SB]
+ OR.W:G 2345H,2345H
+ OR.W:G 2345H,2345H[A0]
+ OR.W:G 2345H,2345H[SB]
+ OR.W:G 2345H,A0
+ OR.W:G 2345H,R0
+ OR.W:G 2345H[A0],[A0]
+ OR.W:G 2345H[A0],12H[A0]
+ OR.W:G 2345H[A0],12H[FB]
+ OR.W:G 2345H[A0],12H[SB]
+ OR.W:G 2345H[A0],2345H
+ OR.W:G 2345H[A0],2345H[A0]
+ OR.W:G 2345H[A0],2345H[SB]
+ OR.W:G 2345H[A0],A0
+ OR.W:G 2345H[A0],R0
+ OR.W:G 2345H[SB],[A0]
+ OR.W:G 2345H[SB],12H[A0]
+ OR.W:G 2345H[SB],12H[FB]
+ OR.W:G 2345H[SB],12H[SB]
+ OR.W:G 2345H[SB],2345H
+ OR.W:G 2345H[SB],2345H[A0]
+ OR.W:G 2345H[SB],2345H[SB]
+ OR.W:G 2345H[SB],A0
+ OR.W:G 2345H[SB],R0
+ OR.W:G A0,[A0]
+ OR.W:G A0,12H[A0]
+ OR.W:G A0,12H[FB]
+ OR.W:G A0,12H[SB]
+ OR.W:G A0,2345H
+ OR.W:G A0,2345H[A0]
+ OR.W:G A0,2345H[SB]
+ OR.W:G A0,A0
+ OR.W:G A0,R0
+ OR.W:G R0,[A0]
+ OR.W:G R0,12H[A0]
+ OR.W:G R0,12H[FB]
+ OR.W:G R0,12H[SB]
+ OR.W:G R0,2345H
+ OR.W:G R0,2345H[A0]
+ OR.W:G R0,2345H[SB]
+ OR.W:G R0,A0
+ OR.W:G R0,R0
+ POP.B:G [A0]
+ POP.B:G 12H[A0]
+ POP.B:G 12H[FB]
+ POP.B:G 12H[SB]
+ POP.B:G 2345H
+ POP.B:G 2345H[A0]
+ POP.B:G 2345H[SB]
+ POP.B:G R0L
+ POP.B:S R0L
+ POP.W:G [A0]
+ POP.W:G 12H[A0]
+ POP.W:G 12H[FB]
+ POP.W:G 12H[SB]
+ POP.W:G 2345H
+ POP.W:G 2345H[A0]
+ POP.W:G 2345H[SB]
+ POP.W:G A0
+ POP.W:G R0
+ POP.W:S A0
+ POPC FB
+ POPC FLG
+ POPC INTBH
+ POPC INTBL
+ POPC ISP
+ POPC SB
+ POPC SP
+ POPM A0
+ POPM A0,FB
+ POPM A0,R0
+ POPM A0,SB
+ POPM FB
+ POPM FB,A0
+ POPM FB,R0
+ POPM FB,SB
+ POPM R0
+ POPM R0,A0
+ POPM R0,FB
+ POPM R0,SB
+ POPM SB
+ POPM SB,A0
+ POPM SB,FB
+ POPM SB,R0
+ PUSH.B:G #7
+ PUSH.B:G [A0]
+ PUSH.B:G 12H[A0]
+ PUSH.B:G 12H[FB]
+ PUSH.B:G 12H[SB]
+ PUSH.B:G 2345H
+ PUSH.B:G 2345H[A0]
+ PUSH.B:G 2345H[SB]
+ PUSH.B:G R0L
+ PUSH.B:S R0L
+ PUSH.W:G #2345H
+ PUSH.W:G #7
+ PUSH.W:G [A0]
+ PUSH.W:G 12H[A0]
+ PUSH.W:G 12H[FB]
+ PUSH.W:G 12H[SB]
+ PUSH.W:G 2345H
+ PUSH.W:G 2345H[A0]
+ PUSH.W:G 2345H[SB]
+ PUSH.W:G A0
+ PUSH.W:G R0
+ PUSH.W:S A0
+ PUSHA 12H[A0]
+ PUSHA 12H[FB]
+ PUSHA 12H[SB]
+ PUSHA 2345H
+ PUSHA 2345H[A0]
+ PUSHA 2345H[SB]
+ PUSHC FB
+ PUSHC FLG
+ PUSHC INTBH
+ PUSHC INTBL
+ PUSHC ISP
+ PUSHC SB
+ PUSHC SP
+ PUSHM A0
+ PUSHM A0,FB
+ PUSHM A0,R0
+ PUSHM A0,SB
+ PUSHM FB
+ PUSHM FB,A0
+ PUSHM FB,R0
+ PUSHM FB,SB
+ PUSHM R0
+ PUSHM R0,A0
+ PUSHM R0,FB
+ PUSHM R0,SB
+ PUSHM SB
+ PUSHM SB,A0
+ PUSHM SB,FB
+ PUSHM SB,R0
+ REIT
+ RMPA.B
+ RMPA.W
+ ROLC.B [A0]
+ ROLC.B 12H[A0]
+ ROLC.B 12H[FB]
+ ROLC.B 12H[SB]
+ ROLC.B 2345H
+ ROLC.B 2345H[A0]
+ ROLC.B 2345H[SB]
+ ROLC.B r0l
+ ROLC.B R1H
+ ROLC.W [A0]
+ ROLC.W 12H[A0]
+ ROLC.W 12H[FB]
+ ROLC.W 12H[SB]
+ ROLC.W 2345H
+ ROLC.W 2345H[A0]
+ ROLC.W 2345H[SB]
+ ROLC.W A0
+ ROLC.W R0
+ RORC.B [A0]
+ RORC.B 12H[A0]
+ RORC.B 12H[FB]
+ RORC.B 12H[SB]
+ RORC.B 2345H
+ RORC.B 2345H[A0]
+ RORC.B 2345H[SB]
+ RORC.B r0l
+ RORC.B R1H
+ RORC.W [A0]
+ RORC.W 12H[A0]
+ RORC.W 12H[FB]
+ RORC.W 12H[SB]
+ RORC.W 2345H
+ RORC.W 2345H[A0]
+ RORC.W 2345H[SB]
+ RORC.W A0
+ RORC.W R0
+ ROT.B #7,[A0]
+ ROT.B #7,12H[A0]
+ ROT.B #7,12H[FB]
+ ROT.B #7,12H[SB]
+ ROT.B #7,2345H
+ ROT.B #7,2345H[A0]
+ ROT.B #7,2345H[SB]
+ ROT.B #7,r0l
+ ROT.B #7,R1H
+ ROT.B R1H,[A0]
+ ROT.B R1H,12H[A0]
+ ROT.B R1H,12H[FB]
+ ROT.B R1H,12H[SB]
+ ROT.B R1H,2345H
+ ROT.B R1H,2345H[A0]
+ ROT.B R1H,2345H[SB]
+ ROT.B R1H,r0l
+ ROT.W #7,[A0]
+ ROT.W #7,12H[A0]
+ ROT.W #7,12H[FB]
+ ROT.W #7,12H[SB]
+ ROT.W #7,2345H
+ ROT.W #7,2345H[A0]
+ ROT.W #7,2345H[SB]
+ ROT.W #7,A0
+ ROT.W #7,R0
+ ROT.W R1H,[A0]
+ ROT.W R1H,12H[A0]
+ ROT.W R1H,12H[FB]
+ ROT.W R1H,12H[SB]
+ ROT.W R1H,2345H
+ ROT.W R1H,2345H[A0]
+ ROT.W R1H,2345H[SB]
+ ROT.W R1H,A0
+ ROT.W R1H,R0
+ RTS
+ SBB.B #7,[A0]
+ SBB.B #7,12H[A0]
+ SBB.B #7,12H[FB]
+ SBB.B #7,12H[SB]
+ SBB.B #7,2345H
+ SBB.B #7,2345H[A0]
+ SBB.B #7,2345H[SB]
+ SBB.B #7,A0
+ SBB.B #7,R0L
+ SBB.B #7,R1H
+ SBB.B [A0],[A0]
+ SBB.B [A0],12H[A0]
+ SBB.B [A0],12H[FB]
+ SBB.B [A0],12H[SB]
+ SBB.B [A0],2345H
+ SBB.B [A0],2345H[A0]
+ SBB.B [A0],2345H[SB]
+ SBB.B [A0],A0
+ SBB.B [A0],R0L
+ SBB.B [A0],R1H
+ SBB.B 12H[A0],[A0]
+ SBB.B 12H[A0],12H[A0]
+ SBB.B 12H[A0],12H[FB]
+ SBB.B 12H[A0],12H[SB]
+ SBB.B 12H[A0],2345H
+ SBB.B 12H[A0],2345H[A0]
+ SBB.B 12H[A0],2345H[SB]
+ SBB.B 12H[A0],A0
+ SBB.B 12H[A0],R0L
+ SBB.B 12H[A0],R1H
+ SBB.B 12H[FB],[A0]
+ SBB.B 12H[FB],12H[A0]
+ SBB.B 12H[FB],12H[FB]
+ SBB.B 12H[FB],12H[SB]
+ SBB.B 12H[FB],2345H
+ SBB.B 12H[FB],2345H[A0]
+ SBB.B 12H[FB],2345H[SB]
+ SBB.B 12H[FB],A0
+ SBB.B 12H[FB],R0L
+ SBB.B 12H[FB],R1H
+ SBB.B 12H[SB],[A0]
+ SBB.B 12H[SB],12H[A0]
+ SBB.B 12H[SB],12H[FB]
+ SBB.B 12H[SB],12H[SB]
+ SBB.B 12H[SB],2345H
+ SBB.B 12H[SB],2345H[A0]
+ SBB.B 12H[SB],2345H[SB]
+ SBB.B 12H[SB],A0
+ SBB.B 12H[SB],R0L
+ SBB.B 12H[SB],R1H
+ SBB.B 2345H,[A0]
+ SBB.B 2345H,12H[A0]
+ SBB.B 2345H,12H[FB]
+ SBB.B 2345H,12H[SB]
+ SBB.B 2345H,2345H
+ SBB.B 2345H,2345H[A0]
+ SBB.B 2345H,2345H[SB]
+ SBB.B 2345H,A0
+ SBB.B 2345H,R0L
+ SBB.B 2345H,R1H
+ SBB.B 2345H[A0],[A0]
+ SBB.B 2345H[A0],12H[A0]
+ SBB.B 2345H[A0],12H[FB]
+ SBB.B 2345H[A0],12H[SB]
+ SBB.B 2345H[A0],2345H
+ SBB.B 2345H[A0],2345H[A0]
+ SBB.B 2345H[A0],2345H[SB]
+ SBB.B 2345H[A0],A0
+ SBB.B 2345H[A0],R0L
+ SBB.B 2345H[A0],R1H
+ SBB.B 2345H[SB],[A0]
+ SBB.B 2345H[SB],12H[A0]
+ SBB.B 2345H[SB],12H[FB]
+ SBB.B 2345H[SB],12H[SB]
+ SBB.B 2345H[SB],2345H
+ SBB.B 2345H[SB],2345H[A0]
+ SBB.B 2345H[SB],2345H[SB]
+ SBB.B 2345H[SB],A0
+ SBB.B 2345H[SB],R0L
+ SBB.B 2345H[SB],R1H
+ SBB.B A0,[A0]
+ SBB.B A0,12H[A0]
+ SBB.B A0,12H[FB]
+ SBB.B A0,12H[SB]
+ SBB.B A0,2345H
+ SBB.B A0,2345H[A0]
+ SBB.B A0,2345H[SB]
+ SBB.B A0,R0L
+ SBB.B A0,R1H
+ SBB.B R0L,[A0]
+ SBB.B R0L,12H[A0]
+ SBB.B R0L,12H[FB]
+ SBB.B R0L,12H[SB]
+ SBB.B R0L,2345H
+ SBB.B R0L,2345H[A0]
+ SBB.B R0L,2345H[SB]
+ SBB.B R0L,A0
+ SBB.B R0L,R0L
+ SBB.B R0L,R1H
+ SBB.B R1H,[A0]
+ SBB.B R1H,12H[A0]
+ SBB.B R1H,12H[FB]
+ SBB.B R1H,12H[SB]
+ SBB.B R1H,2345H
+ SBB.B R1H,2345H[A0]
+ SBB.B R1H,2345H[SB]
+ SBB.B R1H,A0
+ SBB.B R1H,R0L
+ SBB.B R1H,R1H
+ SBB.W #2345H,[A0]
+ SBB.W #2345H,12H[A0]
+ SBB.W #2345H,12H[FB]
+ SBB.W #2345H,12H[SB]
+ SBB.W #2345H,2345H
+ SBB.W #2345H,2345H[A0]
+ SBB.W #2345H,2345H[SB]
+ SBB.W #2345H,A0
+ SBB.W #2345H,R0
+ SBB.W #7,[A0]
+ SBB.W #7,12H[A0]
+ SBB.W #7,12H[FB]
+ SBB.W #7,12H[SB]
+ SBB.W #7,2345H
+ SBB.W #7,2345H[A0]
+ SBB.W #7,2345H[SB]
+ SBB.W #7,A0
+ SBB.W #7,R0
+ SBB.W [A0],[A0]
+ SBB.W [A0],12H[A0]
+ SBB.W [A0],12H[FB]
+ SBB.W [A0],12H[SB]
+ SBB.W [A0],2345H
+ SBB.W [A0],2345H[A0]
+ SBB.W [A0],2345H[SB]
+ SBB.W [A0],A0
+ SBB.W [A0],R0
+ SBB.W 12H[A0],[A0]
+ SBB.W 12H[A0],12H[A0]
+ SBB.W 12H[A0],12H[FB]
+ SBB.W 12H[A0],12H[SB]
+ SBB.W 12H[A0],2345H
+ SBB.W 12H[A0],2345H[A0]
+ SBB.W 12H[A0],2345H[SB]
+ SBB.W 12H[A0],A0
+ SBB.W 12H[A0],R0
+ SBB.W 12H[FB],[A0]
+ SBB.W 12H[FB],12H[A0]
+ SBB.W 12H[FB],12H[FB]
+ SBB.W 12H[FB],12H[SB]
+ SBB.W 12H[FB],2345H
+ SBB.W 12H[FB],2345H[A0]
+ SBB.W 12H[FB],2345H[SB]
+ SBB.W 12H[FB],A0
+ SBB.W 12H[FB],R0
+ SBB.W 12H[SB],[A0]
+ SBB.W 12H[SB],12H[A0]
+ SBB.W 12H[SB],12H[FB]
+ SBB.W 12H[SB],12H[SB]
+ SBB.W 12H[SB],2345H
+ SBB.W 12H[SB],2345H[A0]
+ SBB.W 12H[SB],2345H[SB]
+ SBB.W 12H[SB],A0
+ SBB.W 12H[SB],R0
+ SBB.W 2345H,[A0]
+ SBB.W 2345H,12H[A0]
+ SBB.W 2345H,12H[FB]
+ SBB.W 2345H,12H[SB]
+ SBB.W 2345H,2345H
+ SBB.W 2345H,2345H[A0]
+ SBB.W 2345H,2345H[SB]
+ SBB.W 2345H,A0
+ SBB.W 2345H,R0
+ SBB.W 2345H[A0],[A0]
+ SBB.W 2345H[A0],12H[A0]
+ SBB.W 2345H[A0],12H[FB]
+ SBB.W 2345H[A0],12H[SB]
+ SBB.W 2345H[A0],2345H
+ SBB.W 2345H[A0],2345H[A0]
+ SBB.W 2345H[A0],2345H[SB]
+ SBB.W 2345H[A0],A0
+ SBB.W 2345H[A0],R0
+ SBB.W 2345H[SB],[A0]
+ SBB.W 2345H[SB],12H[A0]
+ SBB.W 2345H[SB],12H[FB]
+ SBB.W 2345H[SB],12H[SB]
+ SBB.W 2345H[SB],2345H
+ SBB.W 2345H[SB],2345H[A0]
+ SBB.W 2345H[SB],2345H[SB]
+ SBB.W 2345H[SB],A0
+ SBB.W 2345H[SB],R0
+ SBB.W A0,[A0]
+ SBB.W A0,12H[A0]
+ SBB.W A0,12H[FB]
+ SBB.W A0,12H[SB]
+ SBB.W A0,2345H
+ SBB.W A0,2345H[A0]
+ SBB.W A0,2345H[SB]
+ SBB.W A0,A0
+ SBB.W A0,R0
+ SBB.W R0,[A0]
+ SBB.W R0,12H[A0]
+ SBB.W R0,12H[FB]
+ SBB.W R0,12H[SB]
+ SBB.W R0,2345H
+ SBB.W R0,2345H[A0]
+ SBB.W R0,2345H[SB]
+ SBB.W R0,A0
+ SBB.W R0,R0
+ SHA.B #7,[A0]
+ SHA.B #7,12H[A0]
+ SHA.B #7,12H[FB]
+ SHA.B #7,12H[SB]
+ SHA.B #7,2345H
+ SHA.B #7,2345H[A0]
+ SHA.B #7,2345H[SB]
+ SHA.B #7,R0L
+ SHA.B #7,R1H
+ SHA.B R1H,[A0]
+ SHA.B R1H,12H[A0]
+ SHA.B R1H,12H[FB]
+ SHA.B R1H,12H[SB]
+ SHA.B R1H,2345H
+ SHA.B R1H,2345H[A0]
+ SHA.B R1H,2345H[SB]
+ SHA.B R1H,R0L
+ SHA.L #7,R2R0
+ SHA.L R1H,R2R0
+ SHA.W #7,[A0]
+ SHA.W #7,12H[A0]
+ SHA.W #7,12H[FB]
+ SHA.W #7,12H[SB]
+ SHA.W #7,2345H
+ SHA.W #7,2345H[A0]
+ SHA.W #7,2345H[SB]
+ SHA.W #7,A0
+ SHA.W #7,R0
+ SHA.W R1H,[A0]
+ SHA.W R1H,12H[A0]
+ SHA.W R1H,12H[FB]
+ SHA.W R1H,12H[SB]
+ SHA.W R1H,2345H
+ SHA.W R1H,2345H[A0]
+ SHA.W R1H,2345H[SB]
+ SHA.W R1H,A0
+ SHA.W R1H,R0
+ SHL.B #7,[A0]
+ SHL.B #7,12H[A0]
+ SHL.B #7,12H[FB]
+ SHL.B #7,12H[SB]
+ SHL.B #7,2345H
+ SHL.B #7,2345H[A0]
+ SHL.B #7,2345H[SB]
+ SHL.B #7,R0L
+ SHL.B #7,R1H
+ SHL.B R1H,[A0]
+ SHL.B R1H,12H[A0]
+ SHL.B R1H,12H[FB]
+ SHL.B R1H,12H[SB]
+ SHL.B R1H,2345H
+ SHL.B R1H,2345H[A0]
+ SHL.B R1H,2345H[SB]
+ SHL.B R1H,R0L
+ SHL.L #7,R2R0
+ SHL.L R1H,R2R0
+ SHL.W #7,[A0]
+ SHL.W #7,12H[A0]
+ SHL.W #7,12H[FB]
+ SHL.W #7,12H[SB]
+ SHL.W #7,2345H
+ SHL.W #7,2345H[A0]
+ SHL.W #7,2345H[SB]
+ SHL.W #7,A0
+ SHL.W #7,R0
+ SHL.W R1H,[A0]
+ SHL.W R1H,12H[A0]
+ SHL.W R1H,12H[FB]
+ SHL.W R1H,12H[SB]
+ SHL.W R1H,2345H
+ SHL.W R1H,2345H[A0]
+ SHL.W R1H,2345H[SB]
+ SHL.W R1H,A0
+ SHL.W R1H,R0
+ SMOVB.B
+ SMOVB.w
+ SMOVF.B
+ SMOVF.w
+ SSTR.B
+ SSTR.w
+ STC FB,[A0]
+ STC FB,12H[A0]
+ STC FB,12H[FB]
+ STC FB,12H[SB]
+ STC FB,2345H
+ STC FB,2345H[A0]
+ STC FB,2345H[SB]
+ STC FB,A0
+ STC FB,R0
+ STC FLG,[A0]
+ STC FLG,12H[A0]
+ STC FLG,12H[FB]
+ STC FLG,12H[SB]
+ STC FLG,2345H
+ STC FLG,2345H[A0]
+ STC FLG,2345H[SB]
+ STC FLG,A0
+ STC FLG,R0
+ STC INTBH,[A0]
+ STC INTBH,12H[A0]
+ STC INTBH,12H[FB]
+ STC INTBH,12H[SB]
+ STC INTBH,2345H
+ STC INTBH,2345H[A0]
+ STC INTBH,2345H[SB]
+ STC INTBH,A0
+ STC INTBH,R0
+ STC INTBL,[A0]
+ STC INTBL,12H[A0]
+ STC INTBL,12H[FB]
+ STC INTBL,12H[SB]
+ STC INTBL,2345H
+ STC INTBL,2345H[A0]
+ STC INTBL,2345H[SB]
+ STC INTBL,A0
+ STC INTBL,R0
+ STC ISP,[A0]
+ STC ISP,12H[A0]
+ STC ISP,12H[FB]
+ STC ISP,12H[SB]
+ STC ISP,2345H
+ STC ISP,2345H[A0]
+ STC ISP,2345H[SB]
+ STC ISP,A0
+ STC ISP,R0
+ STC PC,[A0]
+ STC PC,12H[A0]
+ STC PC,12H[FB]
+ STC PC,12H[SB]
+ STC PC,2345H
+ STC PC,2345H[A0]
+ STC PC,2345H[SB]
+ STC PC,A1A0
+ STC PC,R2R0
+ STC SB,[A0]
+ STC SB,12H[A0]
+ STC SB,12H[FB]
+ STC SB,12H[SB]
+ STC SB,2345H
+ STC SB,2345H[A0]
+ STC SB,2345H[SB]
+ STC SB,A0
+ STC SB,R0
+ STC SP,[A0]
+ STC SP,12H[A0]
+ STC SP,12H[FB]
+ STC SP,12H[SB]
+ STC SP,2345H
+ STC SP,2345H[A0]
+ STC SP,2345H[SB]
+ STC SP,A0
+ STC SP,R0
+ STCTX 2345H,12345H
+ STCTX 2345H,2345H
+ STE.B [A0],[A1A0]
+ STE.B [A0],12345H
+ STE.B [A0],12345H[A0]
+ STE.B [A0],12H[A0]
+ STE.B [A0],2345H
+ STE.B [A0],2345H[A0]
+ STE.B 12H[A0],[A1A0]
+ STE.B 12H[A0],12345H
+ STE.B 12H[A0],12345H[A0]
+ STE.B 12H[A0],12H[A0]
+ STE.B 12H[A0],2345H
+ STE.B 12H[A0],2345H[A0]
+ STE.B 12H[FB],[A1A0]
+ STE.B 12H[FB],12345H
+ STE.B 12H[FB],12345H[A0]
+ STE.B 12H[FB],12H[A0]
+ STE.B 12H[FB],2345H
+ STE.B 12H[FB],2345H[A0]
+ STE.B 12H[SB],[A1A0]
+ STE.B 12H[SB],12345H
+ STE.B 12H[SB],12345H[A0]
+ STE.B 12H[SB],12H[A0]
+ STE.B 12H[SB],2345H
+ STE.B 12H[SB],2345H[A0]
+ STE.B 2345H,[A1A0]
+ STE.B 2345H,12345H
+ STE.B 2345H,12345H[A0]
+ STE.B 2345H,12H[A0]
+ STE.B 2345H,2345H
+ STE.B 2345H,2345H[A0]
+ STE.B 2345H[A0],[A1A0]
+ STE.B 2345H[A0],12345H
+ STE.B 2345H[A0],12345H[A0]
+ STE.B 2345H[A0],12H[A0]
+ STE.B 2345H[A0],2345H
+ STE.B 2345H[A0],2345H[A0]
+ STE.B 2345H[SB],[A1A0]
+ STE.B 2345H[SB],12345H
+ STE.B 2345H[SB],12345H[A0]
+ STE.B 2345H[SB],12H[A0]
+ STE.B 2345H[SB],2345H
+ STE.B 2345H[SB],2345H[A0]
+ STE.B A0,[A1A0]
+ STE.B A0,12345H
+ STE.B A0,12345H[A0]
+ STE.B A0,12H[A0]
+ STE.B A0,2345H
+ STE.B A0,2345H[A0]
+ STE.B R0L,[A1A0]
+ STE.B R0L,12345H
+ STE.B R0L,12345H[A0]
+ STE.B R0L,12H[A0]
+ STE.B R0L,2345H
+ STE.B R0L,2345H[A0]
+ STE.B R1H,[A1A0]
+ STE.B R1H,12345H
+ STE.B R1H,12345H[A0]
+ STE.B R1H,12H[A0]
+ STE.B R1H,2345H
+ STE.B R1H,2345H[A0]
+ STE.W [A0],[A1A0]
+ STE.W [A0],12345H
+ STE.W [A0],12345H[A0]
+ STE.W [A0],12H[A0]
+ STE.W [A0],2345H
+ STE.W [A0],2345H[A0]
+ STE.W 12H[A0],[A1A0]
+ STE.W 12H[A0],12345H
+ STE.W 12H[A0],12345H[A0]
+ STE.W 12H[A0],12H[A0]
+ STE.W 12H[A0],2345H
+ STE.W 12H[A0],2345H[A0]
+ STE.W 12H[FB],[A1A0]
+ STE.W 12H[FB],12345H
+ STE.W 12H[FB],12345H[A0]
+ STE.W 12H[FB],12H[A0]
+ STE.W 12H[FB],2345H
+ STE.W 12H[FB],2345H[A0]
+ STE.W 12H[SB],[A1A0]
+ STE.W 12H[SB],12345H
+ STE.W 12H[SB],12345H[A0]
+ STE.W 12H[SB],12H[A0]
+ STE.W 12H[SB],2345H
+ STE.W 12H[SB],2345H[A0]
+ STE.W 2345H,[A1A0]
+ STE.W 2345H,12345H
+ STE.W 2345H,12345H[A0]
+ STE.W 2345H,12H[A0]
+ STE.W 2345H,2345H
+ STE.W 2345H,2345H[A0]
+ STE.W 2345H[A0],[A1A0]
+ STE.W 2345H[A0],12345H
+ STE.W 2345H[A0],12345H[A0]
+ STE.W 2345H[A0],12H[A0]
+ STE.W 2345H[A0],2345H
+ STE.W 2345H[A0],2345H[A0]
+ STE.W 2345H[SB],[A1A0]
+ STE.W 2345H[SB],12345H
+ STE.W 2345H[SB],12345H[A0]
+ STE.W 2345H[SB],12H[A0]
+ STE.W 2345H[SB],2345H
+ STE.W 2345H[SB],2345H[A0]
+ STE.W A0,[A1A0]
+ STE.W A0,12345H
+ STE.W A0,12345H[A0]
+ STE.W A0,12H[A0]
+ STE.W A0,2345H
+ STE.W A0,2345H[A0]
+ STE.W R0,[A1A0]
+ STE.W R0,12345H
+ STE.W R0,12345H[A0]
+ STE.W R0,12H[A0]
+ STE.W R0,2345H
+ STE.W R0,2345H[A0]
+ STNZ #7,12H[FB]
+ STNZ #7,12H[SB]
+ STNZ #7,2345H
+ STNZ #7,R0H
+ STZ #7,12H[FB]
+ STZ #7,12H[SB]
+ STZ #7,2345H
+ STZ #7,R0H
+ SUB.B:G #7,[A0]
+ SUB.B:G #7,12H[A0]
+ SUB.B:G #7,12H[FB]
+ SUB.B:G #7,12H[SB]
+ SUB.B:G #7,2345H
+ SUB.B:G #7,2345H[A0]
+ SUB.B:G #7,2345H[SB]
+ SUB.B:G #7,A0
+ SUB.B:G #7,R0H
+ SUB.B:G [A0],[A0]
+ SUB.B:G [A0],12H[A0]
+ SUB.B:G [A0],12H[FB]
+ SUB.B:G [A0],12H[SB]
+ SUB.B:G [A0],2345H
+ SUB.B:G [A0],2345H[A0]
+ SUB.B:G [A0],2345H[SB]
+ SUB.B:G [A0],A0
+ SUB.B:G [A0],R0H
+ SUB.B:G 12H[A0],[A0]
+ SUB.B:G 12H[A0],12H[A0]
+ SUB.B:G 12H[A0],12H[FB]
+ SUB.B:G 12H[A0],12H[SB]
+ SUB.B:G 12H[A0],2345H
+ SUB.B:G 12H[A0],2345H[A0]
+ SUB.B:G 12H[A0],2345H[SB]
+ SUB.B:G 12H[A0],A0
+ SUB.B:G 12H[A0],R0H
+ SUB.B:G 12H[FB],[A0]
+ SUB.B:G 12H[FB],12H[A0]
+ SUB.B:G 12H[FB],12H[FB]
+ SUB.B:G 12H[FB],12H[SB]
+ SUB.B:G 12H[FB],2345H
+ SUB.B:G 12H[FB],2345H[A0]
+ SUB.B:G 12H[FB],2345H[SB]
+ SUB.B:G 12H[FB],A0
+ SUB.B:G 12H[FB],R0H
+ SUB.B:G 12H[SB],[A0]
+ SUB.B:G 12H[SB],12H[A0]
+ SUB.B:G 12H[SB],12H[FB]
+ SUB.B:G 12H[SB],12H[SB]
+ SUB.B:G 12H[SB],2345H
+ SUB.B:G 12H[SB],2345H[A0]
+ SUB.B:G 12H[SB],2345H[SB]
+ SUB.B:G 12H[SB],A0
+ SUB.B:G 12H[SB],R0H
+ SUB.B:G 2345H,[A0]
+ SUB.B:G 2345H,12H[A0]
+ SUB.B:G 2345H,12H[FB]
+ SUB.B:G 2345H,12H[SB]
+ SUB.B:G 2345H,2345H
+ SUB.B:G 2345H,2345H[A0]
+ SUB.B:G 2345H,2345H[SB]
+ SUB.B:G 2345H,A0
+ SUB.B:G 2345H,R0H
+ SUB.B:G 2345H[A0],[A0]
+ SUB.B:G 2345H[A0],12H[A0]
+ SUB.B:G 2345H[A0],12H[FB]
+ SUB.B:G 2345H[A0],12H[SB]
+ SUB.B:G 2345H[A0],2345H
+ SUB.B:G 2345H[A0],2345H[A0]
+ SUB.B:G 2345H[A0],2345H[SB]
+ SUB.B:G 2345H[A0],A0
+ SUB.B:G 2345H[A0],R0H
+ SUB.B:G 2345H[SB],[A0]
+ SUB.B:G 2345H[SB],12H[A0]
+ SUB.B:G 2345H[SB],12H[FB]
+ SUB.B:G 2345H[SB],12H[SB]
+ SUB.B:G 2345H[SB],2345H
+ SUB.B:G 2345H[SB],2345H[A0]
+ SUB.B:G 2345H[SB],2345H[SB]
+ SUB.B:G 2345H[SB],A0
+ SUB.B:G 2345H[SB],R0H
+ SUB.B:G A0,[A0]
+ SUB.B:G A0,12H[A0]
+ SUB.B:G A0,12H[FB]
+ SUB.B:G A0,12H[SB]
+ SUB.B:G A0,2345H
+ SUB.B:G A0,2345H[A0]
+ SUB.B:G A0,2345H[SB]
+ SUB.B:G A0,R0H
+ SUB.B:G R0H,[A0]
+ SUB.B:G R0H,12H[A0]
+ SUB.B:G R0H,12H[FB]
+ SUB.B:G R0H,12H[SB]
+ SUB.B:G R0H,2345H
+ SUB.B:G R0H,2345H[A0]
+ SUB.B:G R0H,2345H[SB]
+ SUB.B:G R0H,A0
+ SUB.B:G R0H,R0H
+ SUB.B:S #7,12H[FB]
+ SUB.B:S #7,12H[SB]
+ SUB.B:S #7,2345H
+ SUB.B:S #7,R0H
+ SUB.B:S 12H[FB],R0H
+ SUB.B:S 12H[SB],R0H
+ SUB.B:S 2345H,R0H
+ SUB.W:G #2345H,[A0]
+ SUB.W:G #2345H,12H[A0]
+ SUB.W:G #2345H,12H[FB]
+ SUB.W:G #2345H,12H[SB]
+ SUB.W:G #2345H,2345H
+ SUB.W:G #2345H,2345H[A0]
+ SUB.W:G #2345H,2345H[SB]
+ SUB.W:G #2345H,A0
+ SUB.W:G #2345H,R0
+ SUB.W:G #7,[A0]
+ SUB.W:G #7,12H[A0]
+ SUB.W:G #7,12H[FB]
+ SUB.W:G #7,12H[SB]
+ SUB.W:G #7,2345H
+ SUB.W:G #7,2345H[A0]
+ SUB.W:G #7,2345H[SB]
+ SUB.W:G #7,A0
+ SUB.W:G #7,R0
+ SUB.W:G [A0],[A0]
+ SUB.W:G [A0],12H[A0]
+ SUB.W:G [A0],12H[FB]
+ SUB.W:G [A0],12H[SB]
+ SUB.W:G [A0],2345H
+ SUB.W:G [A0],2345H[A0]
+ SUB.W:G [A0],2345H[SB]
+ SUB.W:G [A0],A0
+ SUB.W:G [A0],R0
+ SUB.W:G 12H[A0],[A0]
+ SUB.W:G 12H[A0],12H[A0]
+ SUB.W:G 12H[A0],12H[FB]
+ SUB.W:G 12H[A0],12H[SB]
+ SUB.W:G 12H[A0],2345H
+ SUB.W:G 12H[A0],2345H[A0]
+ SUB.W:G 12H[A0],2345H[SB]
+ SUB.W:G 12H[A0],A0
+ SUB.W:G 12H[A0],R0
+ SUB.W:G 12H[FB],[A0]
+ SUB.W:G 12H[FB],12H[A0]
+ SUB.W:G 12H[FB],12H[FB]
+ SUB.W:G 12H[FB],12H[SB]
+ SUB.W:G 12H[FB],2345H
+ SUB.W:G 12H[FB],2345H[A0]
+ SUB.W:G 12H[FB],2345H[SB]
+ SUB.W:G 12H[FB],A0
+ SUB.W:G 12H[FB],R0
+ SUB.W:G 12H[SB],[A0]
+ SUB.W:G 12H[SB],12H[A0]
+ SUB.W:G 12H[SB],12H[FB]
+ SUB.W:G 12H[SB],12H[SB]
+ SUB.W:G 12H[SB],2345H
+ SUB.W:G 12H[SB],2345H[A0]
+ SUB.W:G 12H[SB],2345H[SB]
+ SUB.W:G 12H[SB],A0
+ SUB.W:G 12H[SB],R0
+ SUB.W:G 2345H,[A0]
+ SUB.W:G 2345H,12H[A0]
+ SUB.W:G 2345H,12H[FB]
+ SUB.W:G 2345H,12H[SB]
+ SUB.W:G 2345H,2345H
+ SUB.W:G 2345H,2345H[A0]
+ SUB.W:G 2345H,2345H[SB]
+ SUB.W:G 2345H,A0
+ SUB.W:G 2345H,R0
+ SUB.W:G 2345H[A0],[A0]
+ SUB.W:G 2345H[A0],12H[A0]
+ SUB.W:G 2345H[A0],12H[FB]
+ SUB.W:G 2345H[A0],12H[SB]
+ SUB.W:G 2345H[A0],2345H
+ SUB.W:G 2345H[A0],2345H[A0]
+ SUB.W:G 2345H[A0],2345H[SB]
+ SUB.W:G 2345H[A0],A0
+ SUB.W:G 2345H[A0],R0
+ SUB.W:G 2345H[SB],[A0]
+ SUB.W:G 2345H[SB],12H[A0]
+ SUB.W:G 2345H[SB],12H[FB]
+ SUB.W:G 2345H[SB],12H[SB]
+ SUB.W:G 2345H[SB],2345H
+ SUB.W:G 2345H[SB],2345H[A0]
+ SUB.W:G 2345H[SB],2345H[SB]
+ SUB.W:G 2345H[SB],A0
+ SUB.W:G 2345H[SB],R0
+ SUB.W:G A0,[A0]
+ SUB.W:G A0,12H[A0]
+ SUB.W:G A0,12H[FB]
+ SUB.W:G A0,12H[SB]
+ SUB.W:G A0,2345H
+ SUB.W:G A0,2345H[A0]
+ SUB.W:G A0,2345H[SB]
+ SUB.W:G A0,A0
+ SUB.W:G A0,R0
+ SUB.W:G R0,[A0]
+ SUB.W:G R0,12H[A0]
+ SUB.W:G R0,12H[FB]
+ SUB.W:G R0,12H[SB]
+ SUB.W:G R0,2345H
+ SUB.W:G R0,2345H[A0]
+ SUB.W:G R0,2345H[SB]
+ SUB.W:G R0,A0
+ SUB.W:G R0,R0
+ TST.B #7,[A0]
+ TST.B #7,12H[A0]
+ TST.B #7,12H[FB]
+ TST.B #7,12H[SB]
+ TST.B #7,2345H
+ TST.B #7,2345H[A0]
+ TST.B #7,2345H[SB]
+ TST.B #7,A0
+ TST.B #7,R0H
+ TST.B [A0],[A0]
+ TST.B [A0],12H[A0]
+ TST.B [A0],12H[FB]
+ TST.B [A0],12H[SB]
+ TST.B [A0],2345H
+ TST.B [A0],2345H[A0]
+ TST.B [A0],2345H[SB]
+ TST.B [A0],A0
+ TST.B [A0],R0H
+ TST.B 12H[A0],[A0]
+ TST.B 12H[A0],12H[A0]
+ TST.B 12H[A0],12H[FB]
+ TST.B 12H[A0],12H[SB]
+ TST.B 12H[A0],2345H
+ TST.B 12H[A0],2345H[A0]
+ TST.B 12H[A0],2345H[SB]
+ TST.B 12H[A0],A0
+ TST.B 12H[A0],R0H
+ TST.B 12H[FB],[A0]
+ TST.B 12H[FB],12H[A0]
+ TST.B 12H[FB],12H[FB]
+ TST.B 12H[FB],12H[SB]
+ TST.B 12H[FB],2345H
+ TST.B 12H[FB],2345H[A0]
+ TST.B 12H[FB],2345H[SB]
+ TST.B 12H[FB],A0
+ TST.B 12H[FB],R0H
+ TST.B 12H[SB],[A0]
+ TST.B 12H[SB],12H[A0]
+ TST.B 12H[SB],12H[FB]
+ TST.B 12H[SB],12H[SB]
+ TST.B 12H[SB],2345H
+ TST.B 12H[SB],2345H[A0]
+ TST.B 12H[SB],2345H[SB]
+ TST.B 12H[SB],A0
+ TST.B 12H[SB],R0H
+ TST.B 2345H,[A0]
+ TST.B 2345H,12H[A0]
+ TST.B 2345H,12H[FB]
+ TST.B 2345H,12H[SB]
+ TST.B 2345H,2345H
+ TST.B 2345H,2345H[A0]
+ TST.B 2345H,2345H[SB]
+ TST.B 2345H,A0
+ TST.B 2345H,R0H
+ TST.B 2345H[A0],[A0]
+ TST.B 2345H[A0],12H[A0]
+ TST.B 2345H[A0],12H[FB]
+ TST.B 2345H[A0],12H[SB]
+ TST.B 2345H[A0],2345H
+ TST.B 2345H[A0],2345H[A0]
+ TST.B 2345H[A0],2345H[SB]
+ TST.B 2345H[A0],A0
+ TST.B 2345H[A0],R0H
+ TST.B 2345H[SB],[A0]
+ TST.B 2345H[SB],12H[A0]
+ TST.B 2345H[SB],12H[FB]
+ TST.B 2345H[SB],12H[SB]
+ TST.B 2345H[SB],2345H
+ TST.B 2345H[SB],2345H[A0]
+ TST.B 2345H[SB],2345H[SB]
+ TST.B 2345H[SB],A0
+ TST.B 2345H[SB],R0H
+ TST.B A0,[A0]
+ TST.B A0,12H[A0]
+ TST.B A0,12H[FB]
+ TST.B A0,12H[SB]
+ TST.B A0,2345H
+ TST.B A0,2345H[A0]
+ TST.B A0,2345H[SB]
+ TST.B A0,R0H
+ TST.B R0H,[A0]
+ TST.B R0H,12H[A0]
+ TST.B R0H,12H[FB]
+ TST.B R0H,12H[SB]
+ TST.B R0H,2345H
+ TST.B R0H,2345H[A0]
+ TST.B R0H,2345H[SB]
+ TST.B R0H,A0
+ TST.B R0H,R0H
+ TST.W #2345H,[A0]
+ TST.W #2345H,12H[A0]
+ TST.W #2345H,12H[FB]
+ TST.W #2345H,12H[SB]
+ TST.W #2345H,2345H
+ TST.W #2345H,2345H[A0]
+ TST.W #2345H,2345H[SB]
+ TST.W #2345H,A0
+ TST.W #2345H,R0
+ TST.W #7,[A0]
+ TST.W #7,12H[A0]
+ TST.W #7,12H[FB]
+ TST.W #7,12H[SB]
+ TST.W #7,2345H
+ TST.W #7,2345H[A0]
+ TST.W #7,2345H[SB]
+ TST.W #7,A0
+ TST.W #7,R0
+ TST.W [A0],[A0]
+ TST.W [A0],12H[A0]
+ TST.W [A0],12H[FB]
+ TST.W [A0],12H[SB]
+ TST.W [A0],2345H
+ TST.W [A0],2345H[A0]
+ TST.W [A0],2345H[SB]
+ TST.W [A0],A0
+ TST.W [A0],R0
+ TST.W 12H[A0],[A0]
+ TST.W 12H[A0],12H[A0]
+ TST.W 12H[A0],12H[FB]
+ TST.W 12H[A0],12H[SB]
+ TST.W 12H[A0],2345H
+ TST.W 12H[A0],2345H[A0]
+ TST.W 12H[A0],2345H[SB]
+ TST.W 12H[A0],A0
+ TST.W 12H[A0],R0
+ TST.W 12H[FB],[A0]
+ TST.W 12H[FB],12H[A0]
+ TST.W 12H[FB],12H[FB]
+ TST.W 12H[FB],12H[SB]
+ TST.W 12H[FB],2345H
+ TST.W 12H[FB],2345H[A0]
+ TST.W 12H[FB],2345H[SB]
+ TST.W 12H[FB],A0
+ TST.W 12H[FB],R0
+ TST.W 12H[SB],[A0]
+ TST.W 12H[SB],12H[A0]
+ TST.W 12H[SB],12H[FB]
+ TST.W 12H[SB],12H[SB]
+ TST.W 12H[SB],2345H
+ TST.W 12H[SB],2345H[A0]
+ TST.W 12H[SB],2345H[SB]
+ TST.W 12H[SB],A0
+ TST.W 12H[SB],R0
+ TST.W 2345H,[A0]
+ TST.W 2345H,12H[A0]
+ TST.W 2345H,12H[FB]
+ TST.W 2345H,12H[SB]
+ TST.W 2345H,2345H
+ TST.W 2345H,2345H[A0]
+ TST.W 2345H,2345H[SB]
+ TST.W 2345H,A0
+ TST.W 2345H,R0
+ TST.W 2345H[A0],[A0]
+ TST.W 2345H[A0],12H[A0]
+ TST.W 2345H[A0],12H[FB]
+ TST.W 2345H[A0],12H[SB]
+ TST.W 2345H[A0],2345H
+ TST.W 2345H[A0],2345H[A0]
+ TST.W 2345H[A0],2345H[SB]
+ TST.W 2345H[A0],A0
+ TST.W 2345H[A0],R0
+ TST.W 2345H[SB],[A0]
+ TST.W 2345H[SB],12H[A0]
+ TST.W 2345H[SB],12H[FB]
+ TST.W 2345H[SB],12H[SB]
+ TST.W 2345H[SB],2345H
+ TST.W 2345H[SB],2345H[A0]
+ TST.W 2345H[SB],2345H[SB]
+ TST.W 2345H[SB],A0
+ TST.W 2345H[SB],R0
+ TST.W A0,[A0]
+ TST.W A0,12H[A0]
+ TST.W A0,12H[FB]
+ TST.W A0,12H[SB]
+ TST.W A0,2345H
+ TST.W A0,2345H[A0]
+ TST.W A0,2345H[SB]
+ TST.W A0,A0
+ TST.W A0,R0
+ TST.W R0,[A0]
+ TST.W R0,12H[A0]
+ TST.W R0,12H[FB]
+ TST.W R0,12H[SB]
+ TST.W R0,2345H
+ TST.W R0,2345H[A0]
+ TST.W R0,2345H[SB]
+ TST.W R0,A0
+ TST.W R0,R0
+ UND
+ WAIT
+ XCHG.B R0H,[A0]
+ XCHG.B R0H,12H[A0]
+ XCHG.B R0H,12H[FB]
+ XCHG.B R0H,12H[SB]
+ XCHG.B R0H,2345H
+ XCHG.B R0H,2345H[A0]
+ XCHG.B R0H,2345H[SB]
+ XCHG.B R0H,A0
+ XCHG.B R0H,R0H
+ XCHG.W R0,[A0]
+ XCHG.W R0,12H[A0]
+ XCHG.W R0,12H[FB]
+ XCHG.W R0,12H[SB]
+ XCHG.W R0,2345H
+ XCHG.W R0,2345H[A0]
+ XCHG.W R0,2345H[SB]
+ XCHG.W R0,A0
+ XCHG.W R0,R0
+ XOR.B #7,[A0]
+ XOR.B #7,12H[A0]
+ XOR.B #7,12H[FB]
+ XOR.B #7,12H[SB]
+ XOR.B #7,2345H
+ XOR.B #7,2345H[A0]
+ XOR.B #7,2345H[SB]
+ XOR.B #7,A0
+ XOR.B #7,R0H
+ XOR.B [A0],[A0]
+ XOR.B [A0],12H[A0]
+ XOR.B [A0],12H[FB]
+ XOR.B [A0],12H[SB]
+ XOR.B [A0],2345H
+ XOR.B [A0],2345H[A0]
+ XOR.B [A0],2345H[SB]
+ XOR.B [A0],A0
+ XOR.B [A0],R0H
+ XOR.B 12H[A0],[A0]
+ XOR.B 12H[A0],12H[A0]
+ XOR.B 12H[A0],12H[FB]
+ XOR.B 12H[A0],12H[SB]
+ XOR.B 12H[A0],2345H
+ XOR.B 12H[A0],2345H[A0]
+ XOR.B 12H[A0],2345H[SB]
+ XOR.B 12H[A0],A0
+ XOR.B 12H[A0],R0H
+ XOR.B 12H[FB],[A0]
+ XOR.B 12H[FB],12H[A0]
+ XOR.B 12H[FB],12H[FB]
+ XOR.B 12H[FB],12H[SB]
+ XOR.B 12H[FB],2345H
+ XOR.B 12H[FB],2345H[A0]
+ XOR.B 12H[FB],2345H[SB]
+ XOR.B 12H[FB],A0
+ XOR.B 12H[FB],R0H
+ XOR.B 12H[SB],[A0]
+ XOR.B 12H[SB],12H[A0]
+ XOR.B 12H[SB],12H[FB]
+ XOR.B 12H[SB],12H[SB]
+ XOR.B 12H[SB],2345H
+ XOR.B 12H[SB],2345H[A0]
+ XOR.B 12H[SB],2345H[SB]
+ XOR.B 12H[SB],A0
+ XOR.B 12H[SB],R0H
+ XOR.B 2345H,[A0]
+ XOR.B 2345H,12H[A0]
+ XOR.B 2345H,12H[FB]
+ XOR.B 2345H,12H[SB]
+ XOR.B 2345H,2345H
+ XOR.B 2345H,2345H[A0]
+ XOR.B 2345H,2345H[SB]
+ XOR.B 2345H,A0
+ XOR.B 2345H,R0H
+ XOR.B 2345H[A0],[A0]
+ XOR.B 2345H[A0],12H[A0]
+ XOR.B 2345H[A0],12H[FB]
+ XOR.B 2345H[A0],12H[SB]
+ XOR.B 2345H[A0],2345H
+ XOR.B 2345H[A0],2345H[A0]
+ XOR.B 2345H[A0],2345H[SB]
+ XOR.B 2345H[A0],A0
+ XOR.B 2345H[A0],R0H
+ XOR.B 2345H[SB],[A0]
+ XOR.B 2345H[SB],12H[A0]
+ XOR.B 2345H[SB],12H[FB]
+ XOR.B 2345H[SB],12H[SB]
+ XOR.B 2345H[SB],2345H
+ XOR.B 2345H[SB],2345H[A0]
+ XOR.B 2345H[SB],2345H[SB]
+ XOR.B 2345H[SB],A0
+ XOR.B 2345H[SB],R0H
+ XOR.B A0,[A0]
+ XOR.B A0,12H[A0]
+ XOR.B A0,12H[FB]
+ XOR.B A0,12H[SB]
+ XOR.B A0,2345H
+ XOR.B A0,2345H[A0]
+ XOR.B A0,2345H[SB]
+ XOR.B A0,R0H
+ XOR.B R0H,[A0]
+ XOR.B R0H,12H[A0]
+ XOR.B R0H,12H[FB]
+ XOR.B R0H,12H[SB]
+ XOR.B R0H,2345H
+ XOR.B R0H,2345H[A0]
+ XOR.B R0H,2345H[SB]
+ XOR.B R0H,A0
+ XOR.B R0H,R0H
+ XOR.W #2345H,[A0]
+ XOR.W #2345H,12H[A0]
+ XOR.W #2345H,12H[FB]
+ XOR.W #2345H,12H[SB]
+ XOR.W #2345H,2345H
+ XOR.W #2345H,2345H[A0]
+ XOR.W #2345H,2345H[SB]
+ XOR.W #2345H,A0
+ XOR.W #2345H,R0
+ XOR.W #7,[A0]
+ XOR.W #7,12H[A0]
+ XOR.W #7,12H[FB]
+ XOR.W #7,12H[SB]
+ XOR.W #7,2345H
+ XOR.W #7,2345H[A0]
+ XOR.W #7,2345H[SB]
+ XOR.W #7,A0
+ XOR.W #7,R0
+ XOR.W [A0],[A0]
+ XOR.W [A0],12H[A0]
+ XOR.W [A0],12H[FB]
+ XOR.W [A0],12H[SB]
+ XOR.W [A0],2345H
+ XOR.W [A0],2345H[A0]
+ XOR.W [A0],2345H[SB]
+ XOR.W [A0],A0
+ XOR.W [A0],R0
+ XOR.W 12H[A0],[A0]
+ XOR.W 12H[A0],12H[A0]
+ XOR.W 12H[A0],12H[FB]
+ XOR.W 12H[A0],12H[SB]
+ XOR.W 12H[A0],2345H
+ XOR.W 12H[A0],2345H[A0]
+ XOR.W 12H[A0],2345H[SB]
+ XOR.W 12H[A0],A0
+ XOR.W 12H[A0],R0
+ XOR.W 12H[FB],[A0]
+ XOR.W 12H[FB],12H[A0]
+ XOR.W 12H[FB],12H[FB]
+ XOR.W 12H[FB],12H[SB]
+ XOR.W 12H[FB],2345H
+ XOR.W 12H[FB],2345H[A0]
+ XOR.W 12H[FB],2345H[SB]
+ XOR.W 12H[FB],A0
+ XOR.W 12H[FB],R0
+ XOR.W 12H[SB],[A0]
+ XOR.W 12H[SB],12H[A0]
+ XOR.W 12H[SB],12H[FB]
+ XOR.W 12H[SB],12H[SB]
+ XOR.W 12H[SB],2345H
+ XOR.W 12H[SB],2345H[A0]
+ XOR.W 12H[SB],2345H[SB]
+ XOR.W 12H[SB],A0
+ XOR.W 12H[SB],R0
+ XOR.W 2345H,[A0]
+ XOR.W 2345H,12H[A0]
+ XOR.W 2345H,12H[FB]
+ XOR.W 2345H,12H[SB]
+ XOR.W 2345H,2345H
+ XOR.W 2345H,2345H[A0]
+ XOR.W 2345H,2345H[SB]
+ XOR.W 2345H,A0
+ XOR.W 2345H,R0
+ XOR.W 2345H[A0],[A0]
+ XOR.W 2345H[A0],12H[A0]
+ XOR.W 2345H[A0],12H[FB]
+ XOR.W 2345H[A0],12H[SB]
+ XOR.W 2345H[A0],2345H
+ XOR.W 2345H[A0],2345H[A0]
+ XOR.W 2345H[A0],2345H[SB]
+ XOR.W 2345H[A0],A0
+ XOR.W 2345H[A0],R0
+ XOR.W 2345H[SB],[A0]
+ XOR.W 2345H[SB],12H[A0]
+ XOR.W 2345H[SB],12H[FB]
+ XOR.W 2345H[SB],12H[SB]
+ XOR.W 2345H[SB],2345H
+ XOR.W 2345H[SB],2345H[A0]
+ XOR.W 2345H[SB],2345H[SB]
+ XOR.W 2345H[SB],A0
+ XOR.W 2345H[SB],R0
+ XOR.W A0,[A0]
+ XOR.W A0,12H[A0]
+ XOR.W A0,12H[FB]
+ XOR.W A0,12H[SB]
+ XOR.W A0,2345H
+ XOR.W A0,2345H[A0]
+ XOR.W A0,2345H[SB]
+ XOR.W A0,A0
+ XOR.W A0,R0
+ XOR.W R0,[A0]
+ XOR.W R0,12H[A0]
+ XOR.W R0,12H[FB]
+ XOR.W R0,12H[SB]
+ XOR.W R0,2345H
+ XOR.W R0,2345H[A0]
+ XOR.W R0,2345H[SB]
+ XOR.W R0,A0
+ XOR.W R0,R0
+ END
diff --git a/tests/t_m16c/t_m16c.doc b/tests/t_m16c/t_m16c.doc
new file mode 100644
index 0000000..c80281e
--- /dev/null
+++ b/tests/t_m16c/t_m16c.doc
@@ -0,0 +1,6 @@
++------------------------- Test Application M16C ----------------------------+
+| |
+| This is a (synthetic) test of the M16C instruction set |
+| All instructions and addressing modes are exercised. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_m16c/t_m16c.ori b/tests/t_m16c/t_m16c.ori
new file mode 100644
index 0000000..6a366db
--- /dev/null
+++ b/tests/t_m16c/t_m16c.ori
Binary files differ
diff --git a/tests/t_mcore/asflags b/tests/t_mcore/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_mcore/asflags
diff --git a/tests/t_mcore/t_mcore.asm b/tests/t_mcore/t_mcore.asm
new file mode 100644
index 0000000..3e69815
--- /dev/null
+++ b/tests/t_mcore/t_mcore.asm
@@ -0,0 +1,140 @@
+ cpu mcore
+ page 0
+ supmode on
+
+ bkpt
+ doze
+ rfi
+ rte
+ stop
+ sync
+ wait
+
+ abs r0
+ asrc r1
+ brev r2
+ clrf r3
+ clrt r4
+ decf r5
+ decgt r6
+ declt r7
+ decne r8
+ dect r9
+ divs r10
+ divu r11
+ ff1 r12
+ incf r13
+ inct r14
+ jmp r15
+ jsr r0
+ lslc r1
+ lsrc r2
+ mvc r3
+ mvcv r4
+ not r5
+ sextb r6
+ sexth r7
+ tstnbz r8
+ xsr r9
+ xtrb0 r10
+ xtrb1 r11
+ xtrb2 r12
+ xtrb3 r13
+ zextb r14
+ zexth r15
+
+ addc r1,r2
+ addu r2,r3
+ and r3,r4
+ andn r4,r5
+ asr r5,r6
+ bgenr r6,r7
+ cmphs r7,r8
+ cmplt r8,r9
+ cmpne r9,r10
+ ixh r10,r11
+ ixw r11,r12
+ lsl r12,r13
+ lsr r13,r14
+ mov r14,r15
+ movf r1,r2
+ movt r2,r3
+ mult r3,r4
+ or r4,r5
+ rsub r5,r6
+ subc r6,r7
+ subu r7,r8
+ tst r8,r9
+ xor r9,r10
+
+ addi r2,1
+ andi r3,2
+ asri r4,3
+ bclri r5,4
+ bseti r6,5
+ btsti r7,6
+ cmplti r8,7
+ cmpnei r9,8
+ lsli r10,9
+ lsri r11,10
+ rotli r12,11
+ rsubi r13,12
+ subi r14,13
+
+ bgeni r4,0
+ bgeni r4,6
+ bgeni r4,7
+ bgeni r4,12
+ bgeni r4,31
+ bmaski r7,32
+ bmaski r7,1
+ bmaski r7,4
+ bmaski r7,7
+ bmaski r7,8
+ bmaski r7,22
+
+ bf *-$20
+ br *
+ bsr next
+ bt *+$200
+next:
+
+ align 4
+ jmpi [*+4]
+ jsri [*+2]
+
+ ldb r4,(0,r3)
+ ldh r4,(r3)
+ ldw r4,(r3,12)
+ ld r4,(10,r3,2)
+ ld.b r4,(3,r3)
+ ld.h r4,(r3,6)
+ ld.w r4,(24,r3)
+ stb r4,(0,r3)
+ sth r4,(r3)
+ stw r4,(r3,12)
+ st r4,(10,r3,2)
+ st.b r4,(3,r3)
+ st.h r4,(r3,6)
+ st.w r4,(24,r3)
+
+ ldm r2-r15,(r0)
+ stm r4-r15,(r0)
+ ldq r4-r7,(r3)
+ stq r4-r7,(r12)
+
+ loopt r4,*
+
+ align 4
+ lrm r4,[*+4]
+ lrm r4,[*+2]
+
+ mfcr r12,cr5
+ mfcr r12,fpc
+ mtcr r2,cr26
+
+ptrreg reg r10
+ movi r10,123
+ movi ptrreg,123
+
+ trap #2
diff --git a/tests/t_mcore/t_mcore.doc b/tests/t_mcore/t_mcore.doc
new file mode 100644
index 0000000..b3e90a1
--- /dev/null
+++ b/tests/t_mcore/t_mcore.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application MCORE ---------------------------+
+| |
+| This is a (synthetic) test of the M*CORE instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_mcore/t_mcore.ori b/tests/t_mcore/t_mcore.ori
new file mode 100644
index 0000000..819d8b7
--- /dev/null
+++ b/tests/t_mcore/t_mcore.ori
Binary files differ
diff --git a/tests/t_mic51/DEBUG.ASM b/tests/t_mic51/DEBUG.ASM
new file mode 100644
index 0000000..7aff702
--- /dev/null
+++ b/tests/t_mic51/DEBUG.ASM
@@ -0,0 +1,532 @@
+
+; Aufgabe Nr.: Speichermodul fuer uP- Praktikum II
+; Autor: Joerg Vollandt
+; erstellt am : 30.06.1994
+; letzte Aenderung am : 01.07.1994
+; Bemerkung : Wird in das gegebene File "MAIN.ASM" includet.
+;
+; Dateiname : debug.asm
+;
+
+;---------------------------------------------------------------------
+ SEGMENT CODE
+;---------------------------------------------------------------------
+; Funktion : Dump ext. RAM.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+N_BYTES EQU 12
+
+
+DUMP: PUSH PSW
+ PUSH ACC
+ PUSH B
+ PUSH_DPTR
+DUMP_ADR: LCALL LCD_CLEAR
+ LCD 0h,"Start="
+ LCALL IN_DPTR
+DUMP_LINE: LCALL LCD_CLEAR ; 1. Zeile
+ LCALL DPTR_LCD
+ MOV A,#':'
+ LCALL LCD_WRITE_CHAR
+ MOV B,#N_BYTES
+DUMP_BYTE: MOVX A,@DPTR
+ LCALL A_LCD
+ INC DPTR
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ DJNZ B,DUMP_BYTE
+
+ MOV A,#40h ; 2. Zeile
+ LCALL LCD_SET_DD_RAM_ADDRESS
+ LCALL DPTR_LCD
+ MOV A,#':'
+ LCALL LCD_WRITE_CHAR
+ MOV B,#(N_BYTES-1)
+DUMP_BYTE2: MOVX A,@DPTR
+ LCALL A_LCD
+ INC DPTR
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ DJNZ B,DUMP_BYTE2
+ MOVX A,@DPTR
+ LCALL A_LCD
+ INC DPTR
+
+ LCALL CHAR_ACC
+ LCALL UPCASE
+ IFMAKE 'D',LJMP DUMP_ADR
+ IFMAKE 'X',SUBB_DPTR N_BYTES
+ IFMAKE 'E',SUBB_DPTR (3*N_BYTES)
+ IFMAKE 'Q',LJMP DUMP_ENDE
+
+ LJMP DUMP_LINE
+DUMP_ENDE:
+ POP_DPTR
+ POP B
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Ausgabe der Start- und Endadr. des definierten ext. Speichers.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+ADRESSEN:
+ PUSH ACC
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"Startadr.="
+ MOV DPTR,#MEM_ANF
+ LCALL DPTR_LCD
+ LCD 0Eh,";Endadr.="
+ MOV DPTR,#MEM_ENDE
+ LCALL DPTR_LCD
+ LCD 1bh,";Groesse="
+ MOV DPTR,#(MEM_ENDE-MEM_ANF)
+ LCALL DPTR_LCD
+ LCD 40h,"NEXT_FREE="
+ GET_16 NEXT_FREE
+ LCALL DPTR_LCD
+ LCD 4Eh,";RD_P="
+ GET_16 RD_POINTER
+ LCALL DPTR_LCD
+ LCALL CHECK_SUM
+ LCD 5bh,";CHECK="
+ MOV DPL,CHECKSUMME
+ MOV DPH,CHECKSUMME+1
+ LCALL DPTR_LCD
+ LCALL WAIT_KEY
+ POP_DPTR
+ POP ACC
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Ausgabe der Variablen fuer die Synchronisation
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+DEBUG_SYNC:
+ PUSH ACC
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"R_Sync-C.="
+ MOV a,R_Sync_Counter
+ LCALL A_LCD
+ jb runningbit,DESYNC1
+ LCD 0ch,"not "
+DESYNC1: LCD 10h,"running"
+ jb Sync_Waiting,DESYNC2
+ LCD 18h,"not "
+DESYNC2: LCD 1ch,"Sync.waiting"
+ LCD 0h,"T_Sync-C.="
+ MOV a,T_Sync_Counter
+ LCALL A_LCD
+ jb Ready_Waiting,DESYNC3
+ LCD 4ch,"not "
+DESYNC3: LCD 50h,"Ready waiting"
+ POP_DPTR
+ POP ACC
+ LCALL WAIT_KEY
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher fuellen.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+FUELLEN:
+ PUSH PSW
+ PUSH ACC
+ PUSH B
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"Fuellwert ="
+ LCALL IN_ACC
+ MOV B,A
+ MOV DPTR,#MEM_ANF
+FUELLEN1: MOV A,B
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,DPH
+ CJNE A,#(MEM_ENDE/256),FUELLEN1
+ MOV A,DPL
+ CJNE A,#(MEM_ENDE#256),FUELLEN1
+ LCD 40h,"Speicher gefuellt."
+ LCALL WAIT_KEY
+ POP_DPTR
+ POP B
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Schreiben in Speicher
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+SCHREIBEN:
+ PUSH PSW
+ PUSH ACC
+ PUSH B
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"Schreibadr.="
+ LCALL IN_DPTR
+ LCD 12h,"Schreibwert="
+ LCALL IN_ACC
+ LCALL ACC_WR_MEM
+ LCD 40h,"Wert geschrieben."
+ LCALL WAIT_KEY
+ POP_DPTR
+ POP B
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Lesen aus Speicher
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+LESEN:
+ PUSH PSW
+ PUSH ACC
+ PUSH B
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"Leseadr.="
+ LCALL IN_DPTR
+ LCALL ACC_RD_MEM
+ LCD 40h,"Wert ="
+ LCALL A_LCD
+ LCALL WAIT_KEY
+ POP_DPTR
+ POP B
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher auf PC schreiben
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+WR_PC:
+ LCALL LCD_CLEAR
+ LCD 0h,"Speicher auf PC"
+ LCALL WR_MEM_PC
+ LCD 40h,"o.k."
+ LCALL WAIT_KEY
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher initialisieren
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+SPEICHER_INIT:
+ LCALL LCD_CLEAR
+ LCD 0h,"Speicher initialisieren"
+ LCALL INIT_MEM
+ LCD 40h,"o.k."
+ LCALL WAIT_KEY
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher zum lesen zuruecksetzen
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+RESET:
+ LCALL LCD_CLEAR
+ LCD 0h,"Speicher reset"
+ LCALL RESET_MEM
+ LCD 40h,"o.k."
+ LCALL WAIT_KEY
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Element aus Speicher lesen.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+GET:
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"Element lesen von:"
+ GET_16 RD_POINTER
+ LCALL DPTR_LCD
+ LCALL GET_ELEMENT_MEM
+ JC GET_ERROR
+ LCD 40h,"o.k. ACC="
+ LCALL A_LCD
+ LCALL WAIT_KEY
+ POP_DPTR
+ RET
+
+GET_ERROR:
+ LCD 40h,"Fehler."
+ LCALL WAIT_KEY
+ POP_DPTR
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Element in den Speicher schreiben
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+PUT:
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"Element schreiben ab:"
+ GET_16 NEXT_FREE
+ LCALL DPTR_LCD
+ LCD 20h,"ACC="
+ LCALL IN_ACC
+
+ LCALL PUT_ELEMENT_MEM
+ JC PUT_ERROR
+ LCD 40h,"o.k."
+ LCALL WAIT_KEY
+ POP_DPTR
+ RET
+
+PUT_ERROR:
+ LCD 40h,"Fehler."
+ LCALL WAIT_KEY
+ POP_DPTR
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher von PC lesen
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+RD_PC:
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"Speicher von PC"
+ CLR READY
+ LCALL RD_MEM_PC
+RD_PC_LOOP:
+ JNB MSG,$
+ LCALL MEM_SCHEDULER
+ JNB READY,RD_PC_LOOP
+ JB CRC,RD_PC_ERROR
+ LCD 10h,"o.k."
+ LCALL WAIT_KEY
+ POP_DPTR
+ RET
+
+RD_PC_ERROR:
+ LCD 10h,"CRC- Fehler beim laden."
+ LCALL WAIT_KEY
+ POP_DPTR
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Zeiger setzen
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+SET_NEXT_FREE:
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"next_free="
+ lcall IN_DPTR
+ SET_16 NEXT_FREE
+ LCALL WAIT_KEY
+ POP_DPTR
+ RET
+
+SET_RD_POINTER:
+ PUSH_DPTR
+ LCALL LCD_CLEAR
+ LCD 0h,"RD_POINTER="
+ lcall IN_DPTR
+ SET_16 RD_POINTER
+ LCALL WAIT_KEY
+ POP_DPTR
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Msg_Handler_Test
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+; ****************************************************************************
+; R0 Empf„nger (logische Adresse)
+; R1 Message
+; R2 - R7 Parameter
+; ****************************************************************************
+
+Msg_Handler_Test:
+ PUSH ACC
+ PUSH AR0
+ PUSH AR1
+ LCALL LCD_CLEAR
+ LCD 0h,"Msg_Handler_Test"
+ LCD 16h,"R0="
+ LCALL IN_ACC
+ MOV R0,A
+ LCD 20h,"R1="
+ LCALL IN_ACC
+ MOV R1,A
+ LCALL Dispatch_Msg
+ POP AR1
+ POP AR0
+ POP ACC
+ ret
+
+;---------------------------------------------------------------------
+; Funktion : Testbit toggeln
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+T_TEST:
+ LCALL LCD_CLEAR
+ LCD 0h,"TEST"
+ LCALL WAIT_KEY
+ CPL TESTBIT
+ ret
+
+;---------------------------------------------------------------------
+; Funktion : Test RUN- Manager
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+TEST_RUN:
+ LCD 0h,"TEST RUN_ Manager"
+ LCALL WAIT_KEY
+ LCALL START_RUNNING
+ LCALL LCD_CLEAR
+ ret
+
+;---------------------------------------------------------------------
+; Funktion : Debuger fuer das Speichermodul
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+DEBUG_MEM:
+ mov a,#1
+ lcall lcd_curser_onoff
+
+DEBUG_START:
+ LCALL LCD_CLEAR
+ LCD 0,"DEBUG SPEICHERMODUL "
+DEBUG_LOOP:
+ JNB KB_CHAR_READY,DEBUG3
+ LJMP DEBUG1
+DEBUG3:
+ LJMP DEBUG_LOOP
+
+DEBUG1: CLR KB_CHAR_READY
+ MOV A,KB_CHAR_BUFFER
+ LCALL LCD_WRITE_CHAR
+ LCALL UPCASE
+ IFCALL 'A',ADRESSEN
+ IFCALL 'B',LOAD_ROB
+ IFCALL 'C',LOAD_FRAES
+ IFCALL 'D',DUMP
+ IFCALL 'E',Msg_Handler_Test
+ IFCALL 'F',FUELLEN
+ IFCALL 'G',GET
+ IFCALL 'H',SAVE_ROB
+ IFCALL 'I',SAVE_FRAES
+ IFCALL 'J',SPEICHER_INIT
+ IFCALL 'K',T_TEST
+ IFCALL 'L',LESEN
+ IFCALL 'M',STORE_ROB
+ IFCALL 'O',RESET
+ IFCALL 'P',PUT
+ IFMAKE 'Q',LJMP DEBUG_ENDE
+ IFCALL 'R',RD_PC
+ IFCALL 'S',SCHREIBEN
+ IFCALL 'T',TEST_RUN
+ IFCALL 'U',SET_RD_POINTER
+ IFCALL 'W',WR_PC
+ IFCALL 'X',DEBUG_SYNC
+ IFCALL 'Y',STORE_SYNC
+ IFCALL 'Z',SET_NEXT_FREE
+
+ ljmp DEBUG_START
+
+DEBUG_ENDE:
+
+ LCALL LCD_CLEAR
+ ret
+
+;=====================================================================
+; END
+;---------------------------------------------------------------------
+
+
diff --git a/tests/t_mic51/MAKRO1.ASM b/tests/t_mic51/MAKRO1.ASM
new file mode 100644
index 0000000..4d93adc
--- /dev/null
+++ b/tests/t_mic51/MAKRO1.ASM
@@ -0,0 +1,542 @@
+
+; Aufgabe Nr.: Speichermodul fuer uP- Praktikum II
+; Autor: Joerg Vollandt
+; erstellt am : 21.05.1994
+; letzte Aenderung am : 01.08.1994
+; Bemerkung : Makros
+;
+; Dateiname : makro1.asm
+;
+
+;---------------------------------------------------------------------
+; Funktion : Direkter Bitmove- Befehl
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : PSW
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+MOVB MACRO ZIEL,QUELLE
+
+ MOV C,QUELLE
+ MOV ZIEL,C
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : String auf LCD ausgaben.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+LCD MACRO POS,STRG
+
+ PUSH ACC
+ PUSH DPH
+ PUSH DPL
+ MOV A,#POS
+ LCALL LCD_SET_DD_RAM_ADDRESS
+ MOV DPTR,#STR_ADR
+ LCALL LCD_WRITE_STRING
+ LJMP WEITER
+
+STR_ADR DB STRG,0
+
+WEITER: POP DPL
+ POP DPH
+ POP ACC
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : A, B, PSW, DPTR, R0 - R7 auf Stack retten
+; Aufrufparameter : PUSH_ALL
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf : 2
+; Zeitbedarf :
+;
+
+PUSH_ALL MACRO
+
+ PUSH ACC
+ PUSH B
+ PUSH PSW
+ PUSH_DPTR
+ PUSH AR0
+ PUSH AR1
+ PUSH AR2
+ PUSH AR3
+ PUSH AR4
+ PUSH AR5
+ PUSH AR6
+ PUSH AR7
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : A, B, PSW, DPTR, R0 - R7 von Stack holen
+; Aufrufparameter : POP_ALL
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf : 2
+; Zeitbedarf :
+;
+
+POP_ALL MACRO
+
+ POP AR7
+ POP AR6
+ POP AR5
+ POP AR4
+ POP AR3
+ POP AR2
+ POP AR1
+ POP AR0
+ POP_DPTR
+ POP PSW
+ POP B
+ POP ACC
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : DPTR pushen und popen.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+PUSH_DPTR MACRO
+
+ PUSH DPL
+ PUSH DPH
+
+ ENDM
+
+POP_DPTR MACRO
+
+ POP DPH
+ POP DPL
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : DPTR decreminieren.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+ ifdef joerg
+DEC_DPTR MACRO
+
+ INC DPL
+ DJNZ DPL,DEC_DPTR1
+ DEC DPH
+DEC_DPTR1:
+ DEC DPL
+
+ ENDM
+
+ endif
+
+;---------------------------------------------------------------------
+; Funktion : Addieren und subtraieren mit DPTR.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+ADD_DPTR MACRO WERT
+
+ PUSH PSW
+ PUSH ACC
+ MOV A,#(WERT#256)
+ ADD A,DPL
+ MOV DPL,A
+ MOV A,#(WERT/256)
+ ADDC A,DPH
+ MOV DPH,A
+ POP ACC
+ POP PSW
+
+ ENDM
+
+
+SUBB_DPTR MACRO WERT
+
+ PUSH PSW
+ PUSH ACC
+ MOV A,DPL
+ CLR C
+ SUBB A,#(WERT#256)
+ MOV DPL,A
+ MOV A,DPH
+ SUBB A,#(WERT/256)
+ MOV DPH,A
+ POP ACC
+ POP PSW
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : Rechnen mit 16- Bit- Werten im ext. RAM (L,H).
+; Aufrufparameter : DPTR = Wert
+; Ruechgabeparameter : DPTR = Wert
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+SET_16 MACRO NAME
+
+ PUSH ACC
+ PUSH_DPTR
+ PUSH DPH
+ PUSH DPL
+ MOV DPTR,#NAME
+ POP ACC
+ MOVX @DPTR,A
+ INC DPTR
+ POP ACC
+ MOVX @DPTR,A
+ POP_DPTR
+ POP ACC
+
+ ENDM
+
+GET_16 MACRO NAME
+
+ PUSH ACC
+ MOV DPTR,#NAME
+ MOVX A,@DPTR
+ PUSH ACC
+ INC DPTR
+ MOVX A,@DPTR
+ MOV DPH,A
+ POP DPL
+ POP ACC
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : Scheduler.
+; Aufrufparameter : ACC = Zeichen
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+IFCALL MACRO CONST,ROUTINE
+
+ CJNE A,#CONST,IFCALL1
+ LCALL ROUTINE
+IFCALL1:
+
+ ENDM
+
+IFMAKE MACRO CONST,CODE
+
+ CJNE A,#CONST,IFMAKE1
+ CODE
+IFMAKE1:
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : Warten bis Netzwerk freiund Message senden.
+; Aufrufparameter : ACC = Zeichen
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+SEND_NET MACRO
+
+ push acc
+SEND_NET1: LCALL READ_STATUS
+ JB ACC.1,SEND_NET1
+ pop acc
+ LCALL SEND_MESSAGE
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : Message senden.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+post_Message1 macro Modul,Msg
+
+; if MY_SLAVE_ADR = uC_Modul
+; call ADR_Msg ; interne Message
+; elseif
+ PUSH ACC
+WAIT_NET: LCALL READ_STATUS
+ JB ACC.1,WAIT_NET
+ PUSH DPL
+ PUSH DPH
+ MOV DPTR,#ModulNetAdr_Tab
+ MOV A,#Modul
+ MOVC A,@A+DPTR
+ POP DPH
+ POP DPL
+ MOV R0,#Modul
+ MOV R1,#Msg
+ LCALL SEND_MESSAGE ; Message ins Netz
+ POP ACC
+
+; endif
+ endm
+
+;---------------------------------------------------------------------
+; Funktion : Message senden, alle Parameter im Mkroaufruf, B automatisch.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : R0- R7
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+post_Message2 macro Modul,Msg,PARA1,PARA2,PARA3,PARA4,PARA5,PARA6
+
+Parameteranzahl SET 2 ; min. Modulnr. und Msg.-Nr.
+
+ PUSH ACC
+ PUSH B
+
+ IF "PARA1"<>""
+ MOV R2,PARA1
+Parameteranzahl SET Parameteranzahl+1
+ ENDIF
+ IF "PARA2"<>""
+ MOV R3,PARA2
+Parameteranzahl SET Parameteranzahl+1
+ ENDIF
+ IF "PARA3"<>""
+ MOV R4,PARA3
+Parameteranzahl SET Parameteranzahl+1
+ ENDIF
+ IF "PARA4"<>""
+ MOV R5,PARA4
+Parameteranzahl SET Parameteranzahl+1
+ ENDIF
+ IF "PARA5"<>""
+ MOV R6,PARA5
+Parameteranzahl SET Parameteranzahl+1
+ ENDIF
+ IF "PARA6"<>""
+ MOV R7,PARA6
+Parameteranzahl SET Parameteranzahl+1
+ ENDIF
+
+ PUSH DPL
+ PUSH DPH
+ MOV DPTR,#ModulNetAdr_Tab
+ MOV A,Modul
+ MOVC A,@A+DPTR
+ POP DPH
+ POP DPL
+ MOV R0,Modul
+ MOV R1,Msg
+ MOV B,#Parameteranzahl
+ PUSH ACC
+WAIT_NET: LCALL READ_STATUS
+ JB ACC.1,WAIT_NET
+ POP ACC
+ LCALL SEND_MESSAGE ; Message ins Netz
+
+ POP B
+ POP ACC
+
+ endm
+
+;---------------------------------------------------------------------
+; Funktion : Message ausgeben
+; Aufrufparameter : wie definiert
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+TEST_MESSAGE_HEX MACRO POS
+
+ PUSH ACC
+ MOV A,#POS
+ LCALL LCD_SET_DD_RAM_ADDRESS
+ POP ACC
+ PUSH ACC
+ LCALL A_LCD
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ MOV A,B
+ LCALL A_LCD
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ MOV A,R0
+ LCALL A_LCD
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ MOV A,R1
+ LCALL A_LCD
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ MOV A,R2
+ LCALL A_LCD
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ MOV A,R3
+ LCALL A_LCD
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ MOV A,R4
+ LCALL A_LCD
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ MOV A,R5
+ LCALL A_LCD
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ MOV A,R6
+ LCALL A_LCD
+ MOV A,#' '
+ LCALL LCD_WRITE_CHAR
+ MOV A,R7
+ LCALL A_LCD
+ POP ACC
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : Fehlerbehandlung
+; Aufrufparameter : Fehlernr.
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+ERROR MACRO NR
+
+
+ ENDM
+
+;---------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+;---------------------------------------------------------------------
+TEST_MESSAGE MACRO POS,SCHALTER
+
+ IF SCHALTER<=TEST_LEVEL
+ PUSH ACC
+ MOV A,#POS
+ LCALL LCD_SET_DD_RAM_ADDRESS
+ MOV A,R0
+ LCALL LCD_WRITE_CHAR
+ MOV A,R1
+ LCALL LCD_WRITE_CHAR
+ MOV A,R2
+ LCALL LCD_WRITE_CHAR
+ MOV A,R3
+ LCALL LCD_WRITE_CHAR
+ MOV A,R4
+ LCALL LCD_WRITE_CHAR
+ MOV A,R5
+ LCALL LCD_WRITE_CHAR
+ MOV A,R6
+ LCALL LCD_WRITE_CHAR
+ MOV A,R7
+ LCALL LCD_WRITE_CHAR
+ POP ACC
+ ENDIF
+ ENDM
+;---------------------------------------------------------------------
+MAKE_MESSAGE MACRO ADR,STRG
+
+ IF 0=0
+ MOV A,#0
+ MOV DPTR,#STR_ADR
+ MOVC A,@A+DPTR
+ MOV R0,A
+ MOV A,#0
+ INC DPTR
+ MOVC A,@A+DPTR
+ MOV R1,A
+ MOV A,#0
+ INC DPTR
+ MOVC A,@A+DPTR
+ MOV R2,A
+ MOV A,#0
+ INC DPTR
+ MOVC A,@A+DPTR
+ MOV R3,A
+ MOV A,#0
+ INC DPTR
+ MOVC A,@A+DPTR
+ MOV R4,A
+ MOV A,#0
+ INC DPTR
+ MOVC A,@A+DPTR
+ MOV R5,A
+ MOV A,#0
+ INC DPTR
+ MOVC A,@A+DPTR
+ MOV R6,A
+ MOV A,#0
+ INC DPTR
+ MOVC A,@A+DPTR
+ MOV R7,A
+ MOV A,#ADR
+ MOV B,#8
+ LJMP WEITER
+
+STR_ADR DB STRG
+
+WEITER: NOP
+ ENDIF
+ ENDM
+
+;---------------------------------------------------------------------
+MAKE_MESSAGE_HEX MACRO ADR,L,A0,A1,A2,A3,A4,A5,A6,A7
+
+ IF 0=0
+ MOV R0,#A0
+ MOV R1,#A1
+ MOV R2,#A2
+ MOV R3,#A3
+ MOV R4,#A4
+ MOV R5,#A5
+ MOV R6,#A6
+ MOV R7,#A7
+ MOV A,#ADR
+ MOV B,#L
+ ENDIF
+ ENDM
+
+;---------------------------------------------------------------------
+
diff --git a/tests/t_mic51/MEM1.ASM b/tests/t_mic51/MEM1.ASM
new file mode 100644
index 0000000..05fb409
--- /dev/null
+++ b/tests/t_mic51/MEM1.ASM
@@ -0,0 +1,727 @@
+
+; Aufgabe Nr.: Speichermodul fuer uP- Praktikum II
+; Autor: Joerg Vollandt
+; erstellt am : 21.05.1994
+; letzte Aenderung am : 02.08.1994
+; Bemerkung : Routinen fuer die Speicherverwaltung
+;
+; Dateiname : mem1.asm
+;
+
+;=====================================================================
+; Definitionen der Funktionen des Seichermoduls
+
+;INIT_MEM Initialisieren des Speichermoduls
+;DEINIT_MEM Deinitialisieren des Speichermoduls
+;CLEAR_MEM Speicher loeschen
+;RESET_MEM Speicher zum lesen zuruecksetzen
+;PUT_ELEMENT_MEM Element anf naechste freie Position schreiben
+;GET_ELEMENT_MEM Element von akt. Position lesen
+;WR_MEM_PC Speicher auf dem PC speichern.
+;RD_MEM_PC Speicher vom PC laden.
+
+;------------------------------------------------------------------------------
+
+;Messagedefinitionen
+
+;1.Dateityp (Bit 0 und Bit 1)
+Msg_PC_To_Net equ 00b ;direkte Eingabe von Hex-Messages fr das Netz
+Msg_Frs_Datei equ 01b ;Fr„stischdatei
+Msg_Rob_Teach_Datei equ 10b ;Roboter-Teach-In-Datei
+Msg_Frs_Teach_Datei equ 11b ;Fr„stisch-Teach-In-Datei
+
+;2.Aktion (Bit 2 und Bit 3)
+Msg_PC_Get equ 0000b ;Rekordanfrage an PC
+Msg_PC_Put equ 0100b ;Rekordspeichern Slave=>PC, Rekordausgabe PC=>Slave
+Msg_PC_Reset equ 1000b ;PC Datei ”ffnen zum Lesen
+Msg_PC_Rewrite equ 1100b ;PC Datei ”ffnen zum Schreiben
+
+;3.Slaveadresse Slave=>PC ; Msg_From_PC PC=>Slave
+Msg_From_PC equ 00000000b ;Antwort auf Anfrage
+
+EOF_Record equ 0ffffh ;
+PC_Slave_Adr equ 0eh ;
+
+;------------------------------------------------------------------------------
+; Speicherdefinitionen
+
+
+ SEGMENT DATA
+
+CHECKSUMME DW ?
+
+
+ SEGMENT XDATA
+
+POINTER DW ? ; fuer Test
+NEXT_FREE DW ?
+RD_POINTER DW ?
+BLOCKNR DW ?
+
+MEM_ANF DB 1000 DUP (?) ; Speichergroesse in Bytes
+MEM_ENDE
+
+;---------------------------------------------------------------------
+ SEGMENT CODE
+;---------------------------------------------------------------------
+; Funktion : Initialisieren des Speichermoduls
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+INIT_MEM:
+ PUSH PSW
+ PUSH_DPTR
+ MOV DPTR,#MEM_ANF
+ SET_16 NEXT_FREE
+ SET_16 RD_POINTER
+ MOV CHECKSUMME,#0
+ MOV CHECKSUMME+1,#0
+ CLR READY
+ CLR CRC
+
+ POP_DPTR
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Deinitialisieren des Speichermoduls
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+DEINIT_MEM:
+
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher loeschen
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+CLEAR_MEM:
+ PUSH PSW
+ PUSH_DPTR
+ MOV DPTR,#MEM_ANF
+ SET_16 NEXT_FREE
+ SET_16 RD_POINTER
+ MOV CHECKSUMME,#0
+ MOV CHECKSUMME+1,#0
+ CLR READY
+ CLR CRC
+
+ POP_DPTR
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher zum lesen zuruecksetzen
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+RESET_MEM:
+ PUSH_DPTR
+ MOV DPTR,#MEM_ANF
+ SET_16 RD_POINTER
+
+ POP_DPTR
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher von MEM_ANF bis NEXT_FREE auf dem PC speichern.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+WR_MEM_PC:
+ PUSH_ALL
+ ; MOV A,#MSG_PC_REWRITE+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_REWRITE
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr ; Datei oeffnen
+ MOV B,#8
+ SEND_NET
+
+ ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_PUT
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr ; Header zusammenstellen
+ MOV B,#8
+ MOV DPTR,#0
+ SET_16 BLOCKNR ; Blocknr.=0 setzen
+ MOV R1,DPL ; Blocknr.
+ MOV R2,DPH
+ GET_16 NEXT_FREE
+ SUBB_DPTR MEM_ANF
+ MOV R3,DPL ; Anzahl Bytes
+ MOV R4,DPH
+ LCALL CHECK_SUM
+ MOV R5,CHECKSUMME ; Pruefsumme
+ MOV R6,CHECKSUMME+1
+ SEND_NET ; Header senden
+
+ MOV DPTR,#MEM_ANF
+ SET_16 POINTER ; Zeiger auf MEM_ANF setzen
+
+WR_MEM_MSG:
+ LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
+ JNC WR_MEM_MSG1
+ LJMP WR_MEM_CLOSE ; keine Bytes mehr -> close datei
+WR_MEM_MSG1:
+ LCALL ACC_RD_MEM ; Byte aus MEM lesen
+ MOV R3,A ; Message aufbauen
+ LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
+ JNC WR_MEM_MSG2
+ LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben
+WR_MEM_MSG2:
+ LCALL ACC_RD_MEM ; Byte aus MEM lesen
+ MOV R4,A ; Message aufbauen
+ LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
+ JNC WR_MEM_MSG3
+ LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben
+WR_MEM_MSG3:
+ LCALL ACC_RD_MEM ; Byte aus MEM lesen
+ MOV R5,A ; Message aufbauen
+ LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
+ JNC WR_MEM_MSG4
+ LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben
+WR_MEM_MSG4:
+ LCALL ACC_RD_MEM ; Byte aus MEM lesen
+ MOV R6,A ; Message aufbauen
+ LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
+ JNC WR_MEM_MSG5
+ LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben
+WR_MEM_MSG5:
+ LCALL ACC_RD_MEM ; Byte aus MEM lesen
+ MOV R7,A ; Message aufbauen
+ PUSH_DPTR
+ GET_16 BLOCKNR
+ INC DPTR
+ SET_16 BLOCKNR ; Blocknr.=+1 setzen
+ MOV R1,DPL ; Blocknr.
+ MOV R2,DPH
+ POP_DPTR
+ ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_PUT
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr
+ MOV B,#8
+ SEND_NET ; Message senden
+ LJMP WR_MEM_MSG ; naechste Message
+
+WR_MEM_REST:
+ PUSH_DPTR ; nicht volle MSG schreiben
+ GET_16 BLOCKNR
+ INC DPTR
+ SET_16 BLOCKNR ; Blocknr.=+1 setzen
+ MOV R1,DPL ; Blocknr.
+ MOV R2,DPH
+ POP_DPTR
+ ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_PUT
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr
+ MOV B,#8
+ SEND_NET ; Message senden
+
+WR_MEM_CLOSE:
+ ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_PUT
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr ; Datei schlieáen
+ MOV B,#8
+ MOV R1,#(EOF_RECORD#256)
+ MOV R2,#(EOF_RECORD/256)
+ SEND_NET
+ POP_ALL
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher vom PC laden.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+RD_MEM_PC:
+ PUSH_ALL
+ ; MOV A,#MSG_PC_RESET+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_RESET
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr ; Datei oeffnen
+ MOV B,#8
+ SEND_NET
+ ; MOV A,#MSG_PC_GET+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_GET
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr ; Header laden
+ MOV B,#8
+ MOV DPTR,#0
+ SET_16 BLOCKNR ; Blocknr.=0 setzen
+ MOV R1,DPL ; Blocknr.
+ MOV R2,DPH
+ SEND_NET ; Header anfordern
+ POP_ALL
+ RET
+
+
+GET_FROM_PC:
+ PUSH_ALL
+ CJNE R1,#0,GET_NO_HEADER1 ; wenn Blocknr.=0, dann
+ CJNE R2,#0,GET_NO_HEADER1 ; Header
+ LJMP GET_HEADER
+GET_NO_HEADER1:
+ LJMP GET_NO_HEADER
+GET_HEADER:
+ CJNE R3,#0,GET_NOT_EMPTY_JMP ; testen ob 0 Bytes in Datei
+ CJNE R4,#0,GET_NOT_EMPTY_JMP
+ LJMP GET_EMPTY
+GET_NOT_EMPTY_JMP:
+ LJMP GET_NOT_EMPTY
+
+GET_EMPTY: ; Datei leer
+ LCALL INIT_MEM ; Speicherreset
+ ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_PUT
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr ; und Datei schlieáen
+ MOV B,#8
+ MOV R1,#(EOF_RECORD#256)
+ MOV R2,#(EOF_RECORD/256)
+ SEND_NET
+ POP_ALL
+ SETB READY
+ LCD 40H,"Teachin- Datei leer. "
+ RET
+
+GET_NOT_EMPTY: ; Datei nicht leer
+ MOV DPL,R3 ; Groesse nach DPTR
+ MOV DPH,R4
+ ADD_DPTR MEM_ANF
+ SET_16 NEXT_FREE ; neues Speicherende setzen
+ MOV CHECKSUMME,R5 ; neue Checksumme laden
+ MOV CHECKSUMME+1,R6
+ PUSH_DPTR
+ GET_16 BLOCKNR
+ INC DPTR
+ SET_16 BLOCKNR ; Blocknr.=+1 setzen
+ MOV R1,DPL ; Blocknr.
+ MOV R2,DPH
+ POP_DPTR
+ ; MOV A,#MSG_PC_GET+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_GET
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr
+ MOV B,#8
+ SEND_NET ; 1. Block anfordern
+
+ MOV DPTR,#MEM_ANF
+ SET_16 POINTER ; Zeiger auf MEM_ANF setzen
+
+ POP_ALL
+ RET
+
+GET_NO_HEADER:
+ GET_16 POINTER ; Schreibzeiger laden
+ MOV A,R3
+ LCALL ACC_WR_MEM ; in den Speicher schreiben
+ LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
+ JNC GET_MORE2
+ LJMP GET_CLOSE ; wenn nicht Datei schliessen
+GET_MORE2:
+ MOV A,R4
+ LCALL ACC_WR_MEM ; in den Speicher schreiben
+ LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
+ JNC GET_MORE3
+ LJMP GET_CLOSE ; wenn nicht Datei schliessen
+GET_MORE3:
+ MOV A,R5
+ LCALL ACC_WR_MEM ; in den Speicher schreiben
+ LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
+ JNC GET_MORE4
+ LJMP GET_CLOSE ; wenn nicht Datei schliessen
+GET_MORE4:
+ MOV A,R6
+ LCALL ACC_WR_MEM ; in den Speicher schreiben
+ LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
+ JNC GET_MORE5
+ LJMP GET_CLOSE ; wenn nicht Datei schliessen
+GET_MORE5:
+ MOV A,R7
+ LCALL ACC_WR_MEM ; in den Speicher schreiben
+ LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
+ JNC GET_MORE6
+ LJMP GET_CLOSE ; wenn nicht Datei schliessen
+GET_MORE6:
+ SET_16 POINTER
+ GET_16 BLOCKNR
+ INC DPTR
+ SET_16 BLOCKNR ; Blocknr.=+1 setzen
+ MOV R1,DPL ; Blocknr.
+ MOV R2,DPH
+ ; MOV A,#MSG_PC_GET+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_GET
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr
+ MOV B,#8
+ SEND_NET ; naechsten Block anfordern
+ POP_ALL
+ RET
+
+
+GET_CLOSE:
+ ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_PUT
+ MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
+ SETB ACC.1
+ MOV R0,A
+ MOV A,#PC_Slave_Adr ; und Datei schlieáen
+ MOV B,#8
+ MOV R1,#(EOF_RECORD#256)
+ MOV R2,#(EOF_RECORD/256)
+ SEND_NET
+ MOV R0,CHECKSUMME
+ MOV A,CHECKSUMME+1
+ LCALL CHECK_SUM
+ CJNE A,CHECKSUMME+1,GET_CRC_ERROR
+ MOV A,R0
+ CJNE A,CHECKSUMME,GET_CRC_ERROR
+ POP_ALL
+ CLR CRC
+ SETB READY
+ LCD 40H,"Teachin- Datei fehlerfrei geladen. "
+ RET
+
+GET_CRC_ERROR:
+ POP_ALL
+ SETB CRC
+ SETB READY
+ LCD 40H,"FEHLER bei Laden der Teachin- Datei. "
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Testen ob DPTR zum LESEN auf belegten Speicher zeigt.
+; C=0 ==> MEM_ANF <= DPTR < NEXT_FREE
+; C=1 ==> sonst
+; Aufrufparameter : DPTR = Pointer
+; Ruechgabeparameter : -
+; Veraenderte Register : PSW
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+CHECK_RD_POINTER:
+ PUSH PSW
+ PUSH ACC
+ MOV A,#((MEM_ANF-1)/256)
+ CJNE A,DPH,CH_RD1 ; Test ob Pointer >= MEM_ANF
+CH_RD1: JC CH_RD_OK1
+ CJNE A,DPH,CH_RD_ERROR ;
+ MOV A,#((MEM_ANF-1)#256)
+ CJNE A,DPL,CH_RD2
+CH_RD2: JC CH_RD_OK1
+ LJMP CH_RD_ERROR ;
+CH_RD_OK1:
+ PUSH_DPTR
+ MOV DPTR,#(NEXT_FREE+1)
+ MOVX A,@DPTR
+ POP_DPTR
+ CJNE A,DPH,CH_RD3 ; Test ob Pointer < NEXT_FREE
+CH_RD3: JC CH_RD_ERROR
+ CJNE A,DPH,CH_RD_OK2 ;
+ PUSH_DPTR
+ MOV DPTR,#NEXT_FREE
+ MOVX A,@DPTR
+ POP_DPTR
+ CJNE A,DPL,CH_RD4
+CH_RD4: JC CH_RD_ERROR
+ CJNE A,DPL,CH_RD_OK2
+ LJMP CH_RD_ERROR ;
+
+CH_RD_OK2:
+ POP ACC
+ POP PSW
+ CLR C ; o.k.
+ RET
+
+CH_RD_ERROR:
+ POP ACC
+ POP PSW
+ SETB C ; Fehler
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Testen ob DPTR zum SCHREIBEN auf belegten Speicher zeigt.
+; C=0 ==> MEM_ANF <= DPTR <= NEXT_FREE
+; C=1 ==> sonst
+; Aufrufparameter : DPTR = Pointer
+; Ruechgabeparameter : -
+; Veraenderte Register : PSW
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+CHECK_WR_POINTER:
+ PUSH PSW
+ PUSH ACC
+ MOV A,#((MEM_ANF-1)/256)
+ CJNE A,DPH,CH_WR1 ; Test ob Pointer >= MEM_ANF
+CH_WR1: JC CH_WR_OK1
+ CJNE A,DPH,CH_WR_ERROR ;
+ MOV A,#((MEM_ANF-1)#256)
+ CJNE A,DPL,CH_WR2
+CH_WR2: JC CH_WR_OK1
+ LJMP CH_WR_ERROR ;
+CH_WR_OK1:
+ PUSH_DPTR
+ MOV DPTR,#(NEXT_FREE+1)
+ MOVX A,@DPTR
+ POP_DPTR
+ CJNE A,DPH,CH_WR3 ; Test ob Pointer <= NEXT_FREE
+CH_WR3: JC CH_WR_ERROR
+ CJNE A,DPH,CH_WR_OK2 ;
+ PUSH_DPTR
+ MOV DPTR,#NEXT_FREE
+ MOVX A,@DPTR
+ POP_DPTR
+ CJNE A,DPL,CH_WR4
+CH_WR4: JNC CH_WR_OK2
+ LJMP CH_WR_ERROR ;
+
+CH_WR_OK2:
+ POP ACC
+ POP PSW
+ CLR C ; o.k.
+ RET
+
+CH_WR_ERROR:
+ POP ACC
+ POP PSW
+ SETB C ; Fehler
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Testen ob DPTR < MEM_ENDE.
+; C=0 ==> DPTR < MEM_ENDE
+; C=1 ==> sonst
+; Aufrufparameter : DPTR = Pointer
+; Ruechgabeparameter : -
+; Veraenderte Register : PSW
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+CHECK_EOM_POINTER:
+ PUSH PSW
+ PUSH ACC
+ MOV A,#(MEM_ENDE/256)
+ CJNE A,DPH,CH_EOM3 ; Test ob Pointer < MEM_ENDE
+CH_EOM3: JC CH_EOM_ERROR
+ CJNE A,DPH,CH_EOM_OK2 ;
+ MOV A,#(MEM_ENDE#256)
+ CJNE A,DPL,CH_EOM4
+CH_EOM4: JC CH_EOM_ERROR
+ CJNE A,DPL,CH_EOM_OK2
+ LJMP CH_EOM_ERROR ;
+
+CH_EOM_OK2:
+ POP ACC
+ POP PSW
+ CLR C ; o.k.
+ RET
+
+CH_EOM_ERROR:
+ POP ACC
+ POP PSW
+ SETB C ; Fehler
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : ACC in den Speicher schreiben, DPTR increminieren.
+; Aufrufparameter : ACC = Wert, DPTR = Pointer
+; Ruechgabeparameter : -
+; Veraenderte Register : DPTR
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+ACC_WR_MEM:
+ MOVX @DPTR,A
+ INC DPTR
+ RET
+
+
+;---------------------------------------------------------------------
+; Funktion : ACC aus dem Speicher lesen, DPTR increminieren.
+; Aufrufparameter : DPTR = Pointer
+; Ruechgabeparameter : ACC = Wert
+; Veraenderte Register : ACC, DPTR
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+ACC_RD_MEM:
+ MOVX A,@DPTR
+ INC DPTR
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Pruefsumme ueber den Speicher bilden.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+CHECK_SUM:
+ PUSH PSW
+ PUSH ACC
+ PUSH_DPTR
+ MOV CHECKSUMME,#0
+ MOV CHECKSUMME+1,#0
+ MOV DPTR,#MEM_ANF ; Pointer auf MEM_ANF setzen
+CHECK_SUM1:
+ LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
+ JC CHECK_SUM_ENDE
+ LCALL ACC_RD_MEM ; Byte aus MEM lesen
+ ADD A,CHECKSUMME
+ MOV CHECKSUMME,A
+ MOV A,#0
+ ADDC A,CHECKSUMME+1
+ MOV CHECKSUMME+1,A
+ LJMP CHECK_SUM1
+
+CHECK_SUM_ENDE:
+ POP_DPTR
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Element in den Speicher auf die naechste frei Position schreiben.
+; Aufrufparameter : ACC = Wert
+; Ruechgabeparameter : C=0 ==> o.k., C=1 ==> Speicherueberlauf
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+PUT_ELEMENT_MEM:
+ PUSH PSW
+ GET_16 NEXT_FREE
+ LCALL CHECK_EOM_POINTER ; testen ob DPTR < MEM_ENDE
+ JC GET_ELEMENT_ERROR ; wenn nicht Fehler
+ LCALL CHECK_WR_POINTER ; testen ob MEM_ANF <= DPTR <= NEXT_FREE
+ JC PUT_ELEMENT_ERROR ; wenn nicht Fehler
+ LCALL ACC_WR_MEM ; Byte aus MEM lesen
+ SET_16 NEXT_FREE
+
+PUT_EL_OK1:
+ POP PSW
+ CLR C
+ RET
+
+PUT_ELEMENT_ERROR:
+ POP PSW
+ SETB C
+ RET
+
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Element von der akt. Position aus dem Speicher lesen.
+; Aufrufparameter : -
+; Ruechgabeparameter : ACC = Wert
+; C=0 ==> o.k., C=1 ==> Schreib- gleich Lesezeiger
+; oder Lesezeiger ausserhalb des gueltigen Bereiches
+; Veraenderte Register : ACC, PSW
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+GET_ELEMENT_MEM:
+ PUSH PSW
+ GET_16 RD_POINTER
+ LCALL CHECK_EOM_POINTER ; testen ob DPTR < MEM_ENDE
+ JC GET_ELEMENT_ERROR ; wenn nicht Fehler
+ LCALL CHECK_RD_POINTER ; testen ob MEM_ANF <= DPTR < NEXT_FREE
+ JC GET_ELEMENT_ERROR ; wenn nicht Fehler
+ LCALL ACC_RD_MEM ; Byte aus MEM lesen
+ SET_16 RD_POINTER
+
+GET_EL_OK1:
+ POP PSW
+ CLR C
+ RET
+
+GET_ELEMENT_ERROR:
+ POP PSW
+ SETB C
+ RET
+
+;=====================================================================
+; END
+;---------------------------------------------------------------------
+
diff --git a/tests/t_mic51/RUN1.ASM b/tests/t_mic51/RUN1.ASM
new file mode 100644
index 0000000..690e68b
--- /dev/null
+++ b/tests/t_mic51/RUN1.ASM
@@ -0,0 +1,773 @@
+;
+; Aufgabe Nr.: Speichermodul fuer uP- Praktikum II
+; Autor: Joerg Vollandt
+; erstellt am : 01.07.1994
+; letzte Aenderung am : 02.08.1994
+; Bemerkung :
+;
+; Dateiname : run1.asm
+;
+
+;---------------------------------------------------------------------
+Definitionen
+
+ENDE_MARKE EQU 0FFH
+SYNC_MARKE EQU 0FEH
+READY_MARKE EQU 0FDH
+DRILL_MARKE EQU 0FCH
+
+PenUp EQU 000H
+PenDown EQU 0FFH
+d_z EQU 200 ; Schritte fuer Auf-/Ab
+Queue_Const EQU 10 ; je Befehle ein GibReady an Frs
+
+;---------------------------------------------------------------------
+ SEGMENT CODE
+;---------------------------------------------------------------------
+; Funktion : Initialisierung
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+INIT_RUN:
+ CLR RUNNINGBIT
+ CLR Sync_Waiting
+ CLR Ready_Waiting
+ CLR Drilling
+ CLR Drill_down
+ CLR FrsWarning
+ CLR PAUSE
+ CLR SingleStep
+ CLR Break
+ MOV R_Sync_Counter,#0
+ MOV Queue_Counter,#Queue_Const
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Runmodul liesst ein Fkt.-Byte oder eine komplette Msg.
+; aus dem Speicher und schickt diese ins Netz.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+RUN_MODUL:
+ PUSH_ALL
+ JNB Break,RUN1
+ LJMP RUN_ENDE
+RUN1: LCALL GET_ELEMENT_MEM ; Anzahl Bytes
+ JNC RUN4 ; Speicher leer
+ LJMP RUN_LEER
+RUN4: CJNE A,#ENDE_MARKE,RUN5 ; Ende -MARKE im Speicher
+ GET_16 RD_POINTER
+ DEC_DPTR
+ SET_16 RD_POINTER
+ LJMP RUN_ENDE ; erkannt
+RUN5: CJNE A,#SYNC_MARKE,RUN6 ; Sync -MARKE im Speicher
+ LJMP RUN_SYNC ; erkannt
+RUN6: CJNE A,#READY_MARKE,RUN7 ; Ready -MARKE im Speicher
+ LJMP RUN_READY ; erkannt
+RUN7: CJNE A,#DRILL_MARKE,RUN8 ; Drill -MARKE im Speicher
+ LJMP RUN_DRILL ; erkannt
+RUN8:
+ LCD 40h,"Ablauf der Teachin- Datei. "
+ PUSH ACC
+ MOV B,A
+ USING 1 ; Msg.
+ MOV R0,#AR0 ; aus Speicher nach Bank 1
+ USING 0
+RUN_Next_Byte:
+ LCALL GET_ELEMENT_MEM ; Bytes aus Speicher
+ MOV @R0,A ; holen
+ INC R0
+ DJNZ B,RUN_Next_Byte
+
+ POP B
+ PUSH PSW
+ CLR RS1 ; Bank 1
+ SETB RS0
+ MOV DPTR,#ModulNetAdr_Tab
+ MOV A,R0
+ MOVC A,@A+DPTR
+ SEND_NET ; Msg senden
+ POP PSW ; alte Bank
+ POP_ALL
+ JNB SingleStep,RUN_Next_Ende
+ PUSH_ALL
+ LJMP RUN_READY
+RUN_Next_Ende:
+ RET ; fertig !
+
+
+RUN_READY:
+ LCD 40h,"Warten bis Geraet fertig. "
+ JNB P3.5,RUN_READY_FRS
+ post_message2 #Frs,#GibReady,#MemFrs,#GetFrsReady,#0 ; Ready-Anforderung
+ LJMP RUN_READY_WEITER ; schicken
+RUN_READY_FRS:
+ post_message2 #Rob,#RobGibReady,#MemRob,#GetRobReady
+RUN_READY_WEITER:
+ SETB Ready_Waiting
+ POP_ALL
+ RET
+
+
+RUN_SYNC:
+ LCD 40h,"Warten auf Synchronisationspunkt Nr.: "
+ LCALL GET_ELEMENT_MEM ; Sync_Counter aus Speicher
+ LCALL A_LCD
+ JB P3.5,RUN_SYNC_FRS
+ post_message2 #MemFrs,#GetFrsSync,A ; Sync.-Meldung an Partner
+ LJMP RUN_SYNC0 ; schicken
+RUN_SYNC_FRS:
+ post_message2 #MemRob,#GetRobSync,A
+RUN_SYNC0:
+ MOV B,A
+ MOV A,R_Sync_Counter
+ CJNE A,B,RUN_SYNC1
+RUN_SYNC1: JNC RUN_SYNC_ENDE
+ SETB Sync_Waiting
+RUN_SYNC_ENDE:
+ POP_ALL
+ RET
+
+
+RUN_DRILL:
+ JNB P3.5,RUN_DRILL_ROB
+ LJMP RUN_DRILL_FRS
+RUN_DRILL_ROB:
+ LCD 40h,"Roboter kann nicht fraesen! Abbruch. "
+ CLR RUNNINGBIT
+ POP_ALL
+ LCALL INIT_TEACH
+ LCALL RESET_TEACH
+ RET
+
+RUN_DRILL_FRS:
+ LCD 40h,"Fraesdatei wird abgearbeitet. "
+ SETB Drilling
+ LCALL GET_ELEMENT_MEM ; Fraestiefe aus Speicher
+ MOV Frs_Ref_Tiefe,A
+ LCALL GET_ELEMENT_MEM
+ MOV Frs_Ref_Tiefe+1,A
+ post_message2 #Frs,#FrsVelocityDraw,#fast ; schnelle Bewegung
+ post_message2 #Frs,#GoPieceRefPos ; Werkstueckreferenz
+ post_message2 #Frs,#MoveRZ,#(d_z/256),#(d_z#256) ; Pen up
+ post_message2 #Frs,#DRILL,#on ; Motor an
+ clr DRILL_DOWN
+ SETB DRILL_DOWN
+
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_RESET+Msg_Frs_Datei
+ MOV R0,A
+ MOV A,#PC_Slave_Adr ; Datei oeffnen
+ MOV B,#8
+ SEND_NET
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_GET+Msg_Frs_Datei
+ MOV R0,A
+ MOV A,#PC_Slave_Adr ;
+ MOV B,#8
+ MOV DPTR,#0
+ SET_16 BLOCKNR ; Blocknr.=0 setzen
+ MOV R1,DPL ; Blocknr.
+ MOV R2,DPH
+ SEND_NET ; 0. Block laden
+ POP_ALL
+ RET
+
+
+RUN_LEER:
+ LCD 40h,"Speicherinhalt defeckt. "
+ CLR RUNNINGBIT
+ POP_ALL
+ LCALL INIT_TEACH
+ LCALL RESET_TEACH
+ RET
+
+
+RUN_ENDE:
+ LCD 40h,"Ablauf beendet. "
+ GET_16 NEXT_FREE
+ DEC_DPTR
+ SET_16 NEXT_FREE ; Ende- MARKE entfernen
+ CLR RUNNINGBIT ; Ablaufbeenden
+ MOV A,R_Sync_Counter
+ MOV T_Sync_Counter,A
+ GET_16 RD_POINTER
+ SET_16 NEXT_FREE
+ POP_ALL
+ CLR Break
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Start des Runmoduls. Schreibt die Endemarke in den Speicher,
+; setzt den Speicher zurueck und setzt das Bit RUNNINBIT.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+START_RUNNING:
+ JB READY,START_R
+ LJMP START_NICHT_BEREIT
+START_R: PUSH ACC
+ MOV A,#ENDE_MARKE
+ LCALL PUT_ELEMENT_MEM
+ POP ACC
+ LCALL RESET_MEM
+ SETB RUNNINGBIT
+ CLR Sync_Waiting
+ CLR Ready_Waiting
+ MOV R_Sync_Counter,#0
+ RET
+
+START_NICHT_BEREIT:
+ LCD 40H,"Modul nicht bereit fuer Ablauf. "
+ RET
+
+ ;---------------------------------------------------------------------
+; Funktion : Piece-Ref-Position der Fraese speichern. 1. Teil: Position
+; anforndern.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+STORE_PIECE_REF:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JNB READY,STORE_P_REF_ENDE ; Fertig und Fraese?
+ JNB P3.5,STORE_P_REF_ENDE
+
+; MOV B,#4 ; Msg. an Frs um Pos.
+; MOV R2,#MemFrs ; Empfaenger angeben
+; MOV R3,#FrsPieceRef ; Msg.-Nr. Empfaenger angeben
+; post_message1 Frs,GibFrsPos1 ; zu erfragen
+ post_message2 #Frs,#GibFrsPos1,#MemFrs,#FrsPieceRef
+
+STORE_P_REF_ENDE:
+ CLR READY ; Teach- In nicht bereit
+ POP AR0
+ POP ACC
+ POP PSW
+ RET
+
+ ;---------------------------------------------------------------------
+; Funktion : Piece-Ref-Position der Fraese speichern. 2. Teil: Position
+; in x,y,z speichern, Ref_Flag setzen.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+PIECE_REF_FROM_FRS:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JNB READY,P_REF_FRS_DO ; NICHT Fertig und Roboter ?
+ JB P3.5,P_REF_FRS_DO
+ LJMP P_REF_FRS_ENDE
+P_REF_FRS_DO:
+ MOV Frs_Ref_x,R2 ; Position speichern
+ MOV Frs_Ref_x+1,R3 ; Position speichern
+ MOV Frs_Ref_y,R4 ; Position speichern
+ MOV Frs_Ref_y+1,R5 ; Position speichern
+ MOV Frs_Ref_z,R6 ; Position speichern
+ MOV Frs_Ref_z+1,R7 ; Position speichern
+
+P_REF_FRS_ENDE:
+ POP AR0
+ POP ACC
+ POP PSW
+ SETB READY ; Teach- In wieder bereit
+ SETB Ref_Flag
+ RET
+
+ ;---------------------------------------------------------------------
+; Funktion : Fraestiefe der Fraese speichern. 1. Teil: Position
+; anforndern.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+STORE_TIEFE:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JNB READY,STORE_TIEFE_ENDE ; Fertig und Fraese?
+ JNB P3.5,STORE_TIEFE_ENDE
+
+; MOV B,#4 ; Msg. an Frs um Pos.
+; MOV R2,#MemFrs ; Empfaenger angeben
+; MOV R3,#FrsTiefe ; Msg.-Nr. Empfaenger angeben
+; post_message1 Frs,GibFrsPos1 ; zu erfragen
+ post_message2 #Frs,#GibFrsPos1,#MemFrs,#FrsTiefe
+
+STORE_TIEFE_ENDE:
+ CLR READY ; Teach- In nicht bereit
+ POP AR0
+ POP ACC
+ POP PSW
+ RET
+
+ ;---------------------------------------------------------------------
+; Funktion : Fraestiefe der Fraese speichern. 2. Teil: Tiefe berechnen
+; und in Frs_Ref_Tiefe speichern, Tiefe_Flag setzen.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+TIEFE_FROM_FRS:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JNB READY,TIEFE_FRS_DO ; NICHT Fertig und Roboter ?
+ JB P3.5,TIEFE_FRS_DO
+ LJMP TIEFE_FRS_ENDE
+TIEFE_FRS_DO:
+; MOV A,AR7 ; Fraestiefe berechnen
+; CLR C ; und speichern
+; SUBB A,Frs_Ref_Tiefe+1
+ MOV Frs_Ref_Tiefe+1,AR7
+; 7
+; MOV A,AR6
+; SUBB A,Frs_Ref_Tiefe
+ MOV Frs_Ref_Tiefe,AR6
+TIEFE_FRS_ENDE:
+ POP AR0
+ POP ACC
+ POP PSW
+ SETB READY ; Teach- In wieder bereit
+ SETB Tiefe_Flag
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Flags abfragen, nur wenn Ref_Flag und Tiefe_Flag low weiter.
+; SetPieceRef Msg. in Speicher ablegen, Drill Marke ablegen,
+; Tiefe ablegen.
+; Aufrrameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+STORE_DRILL:
+ PUSH PSW
+ PUSH ACC
+ JNB Ref_Flag,STORE_DRILL_ERROR ; PieceRefPos und Tiefe
+ JNB Tiefe_Flag,STORE_DRILL_ERROR ; definiert
+ LJMP STORE_DRILL_OK
+
+STORE_DRILL_ERROR:
+ LCD 40h,"Fehler: RefPos/ Tiefe nicht definiert. "
+ POP ACC
+ POP PSW
+ RET
+
+STORE_DRILL_OK:
+ MOV A,#8 ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.-Laenge)
+ ERROR 0
+ MOV A,#Frs ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Modulnr.)
+ ERROR 0
+ MOV A,#SetPieceRef ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.- Nr.)
+ ERROR 0
+ MOV A,Frs_Ref_x ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 High)
+ ERROR 0
+ MOV A,Frs_Ref_x+1 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 Low)
+ ERROR 0
+ MOV A,Frs_Ref_y ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 2 High)
+ ERROR 0
+ MOV A,Frs_Ref_y+1 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 2 Low)
+ ERROR 0
+ MOV A,Frs_Ref_z ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 High)
+ ERROR 0
+ MOV A,Frs_Ref_z+1 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 Low)
+ ERROR 0
+
+ MOV A,#DRILL_MARKE
+ LCALL PUT_ELEMENT_MEM
+
+ MOV A,Frs_Ref_Tiefe ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 High)
+ ERROR 0
+ MOV A,Frs_Ref_Tiefe+1 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 Low)
+ ERROR 0
+
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speichert die Ready-MARKE im Speicher
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+STORE_READY:
+ PUSH ACC
+ MOV A,#READY_MARKE
+ LCALL PUT_ELEMENT_MEM
+ POP ACC
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speichert das Sync.-MARKE und den Sync.-Counter im Speicher
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+STORE_SYNC:
+ PUSH ACC
+ MOV A,#SYNC_MARKE
+ LCALL PUT_ELEMENT_MEM
+ INC T_Sync_Counter ; Sync_Counter +1
+ MOV A,T_Sync_Counter
+ LCALL PUT_ELEMENT_MEM
+ LCD 29,"Sync.-Nr."
+ LCALL A_LCD
+ POP ACC
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Ready-Msg. erhalten und bearbeiten.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+GET_READY_MSG:
+ LCD 40H," "
+ CLR Ready_Waiting
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Sync.-Msg. erhalten und bearbeiten. Bricht Running ab
+; wenn von Partner Sync.-Nr. 0 kommt. Wenn eigenes Modul
+; noch nicht getstartet wird Sync.-Msg. mit #0 an Partner
+; geschickt.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+GET_SYNC_MSG:
+ JNB RunningBit,G_S_1
+ LJMP G_S_2
+G_S_1: PUSH B
+ MOV B,#3 ; Msg.
+ MOV R2,#0 ; mit #0
+ JB P3.5,G_S_FRS
+ post_message1 MemFrs,GetFrsSync ; Sync.-Meldung an Partner
+ POP B
+ RET ; schicken
+G_S_FRS: post_message1 MemRob,GetRobSync
+ POP B
+ RET
+
+G_S_2: PUSH PSW
+ PUSH ACC
+ INC R_Sync_Counter
+ MOV A,R2 ; Sync_Counter aus Msg. holen
+ CJNE A,#0,G_S_KEIN_ABBRUCH ; Abbruch bei #0
+ LJMP G_S_ABBRUCH
+G_S_KEIN_ABBRUCH:
+ CJNE A,R_Sync_Counter,G_S_ERROR ; Fehler wenn ungleich
+ CLR Sync_Waiting
+ POP ACC
+ POP PSW
+ RET
+
+G_S_ABBRUCH:
+ LCD 40h,"Partner nicht bereit. Abbruch. "
+ CLR RUNNINGBIT
+ POP ACC
+ POP PSW
+ LCALL INIT_TEACH
+ LCALL RESET_TEACH
+ RET
+
+G_S_ERROR:
+ LCD 40h,"Synchronisationsfehler. "
+ CLR RUNNINGBIT
+ POP ACC
+ POP PSW
+ LCALL INIT_TEACH
+ LCALL RESET_TEACH
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Testen ob Queue- Warnung von Frs gekommen ist. Wenn ja,
+; GibReady an die Fraese schicken und warten bis kommt.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+queue_test macro
+
+Q_T_Main_Loop:
+ LCALL MAIN_EVENT_LOOP
+ JB PAUSE,Q_T_Main_Loop ; Pause aktiv
+ JB READY_WAITING,Q_T_Main_Loop ; warten auf Ready von Frs
+ LCALL READ_STATUS
+ JB ACC.1,Q_T_Main_Loop
+
+ endm
+
+;---------------------------------------------------------------------
+; Funktion : Daten aus der Fraesdatei vom PC empfangen, konvertieren
+; und an die Fraese schicken.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+
+GET_WORKFR_FROM_PC:
+ PUSH_ALL
+ JB RUNNINGBIT,GET_WORKFR_FROM_PC_START
+ LJMP GET_WORKFR_FROM_PC_ABBRUCH
+GET_WORKFR_FROM_PC_START:
+ MOV A,R1 ; testen ob Dateiende
+ CJNE A,#0ffh,GET_WORKFR_FROM_PC_NEXT
+ MOV A,R2
+ CJNE A,#0ffh,GET_WORKFR_FROM_PC_NEXT
+ LJMP GET_WORKFR_FROM_PC_ENDE
+
+GET_WORKFR_FROM_PC_NEXT: ; naechste Msg. von PC
+ PUSH_ALL ; konvertieren und an Frs
+ queue_test
+ MOV A,AR7 ; schicken
+ CJNE A,#PenDown,G_W_PenUp ; Auf- oder Abbewegung?
+ ljmp G_W_PenDown
+G_W_PenUp:
+ jb drill_down,G_W_Make_Up
+ ljmp G_W_Pen_Ready ; ist schon oben
+G_W_Make_Up:
+ post_message2 #Frs,#MoveZ,Frs_Ref_z,Frs_Ref_z+1 ; Pen aus Werkstueck ziehen
+ queue_test
+ post_message2 #Frs,#FrsVelocityDraw,#fast ; schnelle Bewegung
+ queue_test
+ post_message2 #Frs,#MoveRZ,#(d_z/256),#(d_z#256) ; Pen up
+ clr DRILL_DOWN
+ queue_test
+ LJMP G_W_Pen_Ready ; fertig
+
+G_W_PenDown:
+ jnb drill_down,G_W_Make_Down
+ ljmp G_W_Pen_Ready ; ist schon unten
+G_W_Make_Down:
+ post_message2 #Frs,#MoveRZ,#(((-d_z) & 0ffffh) / 256),#(((-d_z) & 0ffffh) # 256) ; Ab
+ queue_test
+ post_message2 #Frs,#FrsVelocityDraw,#slow ; langsame Bewegung
+ queue_test
+ post_message2 #Frs,#MoveZ,Frs_Ref_Tiefe,Frs_Ref_Tiefe+1 ; Pen aus Werkstueck ziehen
+ queue_test
+ SETB DRILL_DOWN
+G_W_Pen_Ready: ; Pen fertig !
+
+ POP_ALL
+ post_message2 #Frs,#MovePR,AR4,AR3,AR6,AR5,#0,#0 ; rel. Bewegung
+ queue_test
+
+; DJNZ Queue_Counter,G_W_Send_no_Ready
+; MOV Queue_Counter,#Queue_Const
+; PUSH_ALL
+; post_message2 #Frs,#GibReady,#MemFrs,#GetFrsReady,#0
+; POP_ALL
+
+G_W_Send_no_Ready:
+
+ GET_16 BLOCKNR
+ INC DPTR
+ SET_16 BLOCKNR ; Blocknr.=+1 setzen
+ MOV R1,DPL ; Blocknr.
+ MOV R2,DPH
+ MOV A,MY_SLAVE_ADR
+ SWAP A ; *16
+ ADD A,#MSG_PC_GET+Msg_Frs_Datei
+ MOV R0,A
+ MOV A,#PC_Slave_Adr
+ MOV B,#8
+ SEND_NET ; naechsten Block anfordern
+ POP_ALL
+ RET
+
+GET_WORKFR_FROM_PC_ENDE:
+ post_message2 #Frs,#DRILL,#off ;
+ CLR Drilling
+
+ POP_ALL
+ LCD 40h,"Fraesdatei fertig. "
+ RET
+
+GET_WORKFR_FROM_PC_ABBRUCH:
+ CLR Drilling
+ POP_ALL
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Warnung von Frs erhalten und verarbeiten.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+Get_Warning_From_Frs:
+ LCD 40h,"Warnung Fraese: "
+ PUSH ACC
+ PUSH PSW
+ PUSH B
+ PUSH_DPTR
+
+ MOV A,AR2
+ IFMAKE QUEUE_WARNING,SETB FrsWarning ; Queue Fraese laeuf ueber
+
+ MOV DPTR,#ParamStr_Tab ; Tabellenbasis laden
+GWFF_NEXT:
+ MOV A,#0
+ MOVC A,@A+DPTR ; Wert laden
+ PUSH ACC ; retten
+ MOV A,#1
+ MOVC A,@A+DPTR ; Stringlaenge laden
+ MOV B,A
+ POP ACC ; Wert mit empfangenem
+ CJNE A,AR2,GWFF_LOOP ; vergleichen
+ LJMP GWFF_AUSGABE
+GWFF_LOOP:
+ MOV A,B ; Stringlaende auf Tabellen-
+ ADD A,DPL ; zeiger addieren
+ MOV DPL,A
+ MOV A,#0
+ ADDC A,DPH
+ MOV DPH,A
+ LJMP GWFF_NEXT
+
+GWFF_AUSGABE:
+ MOV A,#50h ; LCD- Position
+ LCALL LCD_SET_DD_RAM_ADDRESS
+ INC DPTR
+ INC DPTR
+ LCALL LCD_WRITE_STRING ; Meldung ausgeben
+ MOV A,#0h ; LCD- Position
+ LCALL LCD_SET_DD_RAM_ADDRESS
+
+ POP_DPTR
+ POP B
+ POP PSW
+ POP ACC
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Fehler von Frs erhalten und verarbeiten.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+Get_Error_From_Frs:
+ LCD 40h,"Fehler Fraese: "
+ PUSH ACC
+ PUSH PSW
+ PUSH B
+ PUSH_DPTR
+ MOV DPTR,#ParamStr_Tab ; Tabellenbasis laden
+GEFF_NEXT:
+ MOV A,#0
+ MOVC A,@A+DPTR ; Wert laden
+ PUSH ACC
+ MOV A,#1
+ MOVC A,@A+DPTR ; Stringlaenge laden
+ MOV B,A
+ POP ACC ; Wert mit empfangenem
+ CJNE A,AR2,GEFF_LOOP ; vergleichen
+ LJMP GEFF_AUSGABE
+GEFF_LOOP:
+ MOV A,B ; Stringlaende auf Tabellen-
+ ADD A,DPL ; zeiger addieren
+ MOV DPL,A
+ MOV A,#0
+ ADDC A,DPH
+ MOV DPH,A
+ LJMP GEFF_NEXT
+
+GEFF_AUSGABE:
+ MOV A,#4Fh ; LCD- Position
+ LCALL LCD_SET_DD_RAM_ADDRESS
+ INC DPTR
+ INC DPTR
+ LCALL LCD_WRITE_STRING ; Meldung ausgeben
+ MOV A,#0h ; LCD- Position
+ LCALL LCD_SET_DD_RAM_ADDRESS
+
+ POP_DPTR
+ POP B
+ POP PSW
+ POP ACC
+ RET
+
+;---------------------------------------------------------------------
+; Funktion :
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+;=====================================================================
+; END
+;---------------------------------------------------------------------
+
+
+
diff --git a/tests/t_mic51/TAST1.ASM b/tests/t_mic51/TAST1.ASM
new file mode 100644
index 0000000..0a34ecb
--- /dev/null
+++ b/tests/t_mic51/TAST1.ASM
@@ -0,0 +1,250 @@
+
+; Aufgabe Nr.: Speichermodul fuer uP- Praktikum II
+; Autor: Joerg Vollandt
+; erstellt am : 21.05.1994
+; letzte Aenderung am :
+; Bemerkung : Routinen fuer ASCII- Tastatur
+;
+; Dateiname : tast1.asm
+;
+
+;---------------------------------------------------------------------
+; Definitionen
+
+ SEGMENT DATA
+
+ZEICHEN DB ?
+
+ SEGMENT BITDATA
+
+STROB DB ?
+
+;---------------------------------------------------------------------
+ SEGMENT CODE
+;=====================================================================
+; Funktion : Tastaturinterrupt initialisieren
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+INIT_TASTATUR:
+ Init_Vektor INT0_VEKTOR,TASTATUR_INT
+ SETB IT0
+ CLR IE0
+ SETB EX0
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Interruptroutine fuer Tastatur, setzt bei Tastaturstrob
+; das Bit STROB und schreibt das Zeichen von der Tastatur
+; nach ZEICHEN.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+TASTATUR_INT:
+ MOV ZEICHEN,P1
+ SETB STROB
+ RETI
+
+;---------------------------------------------------------------------
+; Funktion : Klein- in Grossbuchstaben umwandeln.
+; Aufrufparameter : ACC = Zeichen
+; Ruechgabeparameter : ACC = Zeichen
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+ ifdef joerg
+
+UPCASE: PUSH PSW
+ CJNE A,#'a',UPCASE1
+UPCASE1: JC UPCASE2
+ CJNE A,#07bh,UPCASE3
+UPCASE3: JNC UPCASE2
+ CLR C
+ SUBB A,#32
+UPCASE2: POP PSW
+ RET
+
+ endif
+
+;---------------------------------------------------------------------
+; Funktion : Warten bis Tastendruck und Zeichen verwerfen.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+WAIT_KEY:
+ ifdef joerg
+
+ JNB STROB,$
+ CLR STROB
+ RET
+
+ elseif
+
+ JNB KB_CHAR_READY,$
+ CLR KB_CHAR_READY
+ RET
+
+ endif
+;---------------------------------------------------------------------
+; Funktion : Warten bis Tastendruck und Zeichen nach ACC von der
+; Tastatur einlesen.
+; Aufrufparameter : -
+; Ruechgabeparameter : ACC = Zeichen
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+CHAR_ACC:
+ ifdef joerg
+
+ JNB STROB,$
+ CLR STROB
+ MOV A,ZEICHEN
+ RET
+
+ elseif
+
+ JNB KB_CHAR_READY,$
+ CLR KB_CHAR_READY
+ MOV A,KB_CHAR_BUFFER
+ RET
+
+ endif
+
+;---------------------------------------------------------------------
+; Funktion : ACC in hex von der Tastatur einlesen.
+; Aufrufparameter : -
+; Ruechgabeparameter : ACC = Wert
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+IN_ACC:
+ PUSH PSW
+ PUSH B
+ LCALL CHAR_ACC
+ LCALL LCD_WRITE_CHAR
+ LCALL UPCASE
+ CJNE A,#'A',IN_ACC1
+IN_ACC1: JC IN_ACC2
+ CJNE A,#'G',IN_ACC3
+IN_ACC3: JNC IN_ACC2
+ CLR C
+ SUBB A,#7
+IN_ACC2: CLR C
+ SUBB A,#30h
+ SWAP A
+ MOV B,A
+ LCALL CHAR_ACC
+ LCALL LCD_WRITE_CHAR
+ LCALL UPCASE
+ CJNE A,#'A',IN_ACC11
+IN_ACC11: JC IN_ACC12
+ CJNE A,#'G',IN_ACC13
+IN_ACC13: JNC IN_ACC12
+ CLR C
+ SUBB A,#7
+IN_ACC12: CLR C
+ SUBB A,#30h
+ ORL A,B
+ POP B
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : DPTR in hex von der Tastatur einlesen.
+; Aufrufparameter : -
+; Ruechgabeparameter : DPTR = Wert
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+IN_DPTR:
+ PUSH ACC
+ LCALL IN_ACC
+ MOV DPH,A
+ LCALL IN_ACC
+ MOV DPL,A
+ POP ACC
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : ACC in hex auf LCD ausgeben.
+; Aufrufparameter : ACC = Wert
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+A_LCD: PUSH ACC
+ PUSH ACC
+ SWAP A
+ ANL A,#00001111B
+ ADD A,#'0'
+ CJNE A,#':',A_LCD1
+A_LCD1: JC A_LCD2
+ ADD A,#7
+A_LCD2: LCALL LCD_WRITE_CHAR
+ POP ACC
+ ANL A,#00001111B
+ ADD A,#'0'
+ CJNE A,#':',A_LCD3
+A_LCD3: JC A_LCD4
+ ADD A,#7
+A_LCD4: LCALL LCD_WRITE_CHAR
+ POP ACC
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : DPTR in hex auf LCD ausgeben.
+; Aufrufparameter : DPTR = Wert
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+DPTR_LCD:
+ PUSH ACC
+ MOV A,DPH
+ LCALL A_LCD
+ MOV A,DPL
+ LCALL A_LCD
+ POP ACC
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Setzt LCD- Status neu
+; Aufrufparameter : A = Status
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+LCD_SET_STATUS:
+
+ RET
+
+;=====================================================================
+; END
+;---------------------------------------------------------------------
+
diff --git a/tests/t_mic51/TEACH1.ASM b/tests/t_mic51/TEACH1.ASM
new file mode 100644
index 0000000..3618062
--- /dev/null
+++ b/tests/t_mic51/TEACH1.ASM
@@ -0,0 +1,504 @@
+
+; Aufgabe Nr.: Teach- In Einheit fuer uP- Praktikum II
+; Autor: Joerg Vollandt
+; erstellt am : 31.05.1994
+; letzte Aenderung am : 14.07.1994
+; Bemerkung :
+;
+; Dateiname : teach1.asm
+;
+
+;=====================================================================
+; Definitionen der Funktionen der Teach- In Einheit
+
+;INIT_TEACH Initialisieren der Teach- In Einheit
+;DEINIT_TEACH Deinitialisieren der Teach- In Einheit
+;CLEAR_TEACH Speicher loeschen
+;RESET_TEACH Speicher zum lesen zuruecksetzen
+;STORE_ROB Position Roboter speichern
+;STORE_FRAES Position Fraese speichern
+;SYNC
+;LOAD_ROB Roboter Teach- In Datei von PC laden
+;LOAD_FRAES Fraese- Teach- In Datei von PC laden
+;LOAD Beide Teach- In Dateien von PC laden
+;SAVE_ROB Roboter Teach- In Datei auf PC speichern
+;SAVE_FRAES Fraese- Teach- In Datei auf PC speichern
+
+;------------------------------------------------------------------------------
+ SEGMENT CODE
+;---------------------------------------------------------------------
+; Funktion : Initialisieren der Error- und Warningeinspruenge fuer die
+; Fraese.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+INIT_FRS:
+ JB P3.5,INIT_FRAES_START
+ LJMP INIT_FRAES_ENDE
+INIT_FRAES_START:
+ PUSH_ALL
+; MOV B,#5 ; Msg. Frs
+; MOV AR2,#MemFrs ; meine Adr.
+; MOV AR3,#GetFrsError ; Fehlereinsprung
+; MOV AR4,#GetFrsWarning ; Warnungeinsprung
+; post_message1 Frs,SetMasterAdress ; Ready-Anfordrung
+ post_message2 #Frs,#SetMasterAdress,#MemFrs,#GetFrsError,#GetFrsWarning
+ POP_ALL
+INIT_FRAES_ENDE:
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Initialisieren der Teach- In Einheit
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+INIT_TEACH:
+ CLR READY
+ CLR CRC
+ LCALL INIT_MEM
+ MOV T_Sync_Counter,#0
+ MOV Frs_Ref_x,#0
+ MOV Frs_Ref_x+1,#0
+ MOV Frs_Ref_y,#0
+ MOV Frs_Ref_y+1,#0
+ MOV Frs_Ref_z,#0
+ MOV Frs_Ref_z+1,#0
+ MOV Frs_Ref_Tiefe,#0
+ MOV Frs_Ref_Tiefe+1,#0
+ CLR Ref_Flag
+ CLR Tiefe_Flag
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Deinitialisieren der Teach- In Einheit
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+DEINIT_TEACH:
+ CLR READY
+ CLR CRC
+ LCALL DEINIT_MEM
+
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Speicher der Teach- In Einheit loeschen
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+CLEAR_TEACH:
+
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Teach- In Einheit zuruecksetzen
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+RESET_TEACH:
+ LCALL RESET_MEM
+ SETB READY
+
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Roboter Teach- In Datei von PC laden
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+LOAD_ROB:
+ JB P3.5,LOAD_ROB_ENDE
+ CLR READY
+ LCD 40H,"Roboter- Teachin- Datei wird geladen. "
+ LCALL RD_MEM_PC
+LOAD_ROB_ENDE:
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Fraese- Teach- In Datei von PC laden
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+LOAD_FRAES:
+ JNB P3.5,LOAD_FRAES_ENDE
+ CLR READY
+ LCD 40H,"Fraese- Teachin- Datei wird geladen. "
+ LCALL RD_MEM_PC
+LOAD_FRAES_ENDE:
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Roboter Teach- In Datei auf PC speichern
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+SAVE_ROB:
+ JB READY,SAVE_ROB_START
+ JNB P3.5,SAVE_ROB_START
+ LJMP SAVE_ROB_ENDE
+SAVE_ROB_START:
+ LCD 40H,"Roboter- Teachin- Datei wird gespeichert"
+ LCALL WR_MEM_PC
+ JNC SAVE_ROB_OK
+ LCD 40H,"FEHLER bei Speichern. "
+ RET
+
+SAVE_ROB_OK:
+ LCD 40H,"Datei gespeichert. "
+ RET
+
+SAVE_ROB_ENDE:
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Fraese- Teach- In Datei auf PC speichern
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+SAVE_FRAES:
+ JB READY,SAVE_FRAES_START
+ JB P3.5,SAVE_FRAES_START
+ LJMP SAVE_FRAES_ENDE
+SAVE_FRAES_START:
+ LCALL WR_MEM_PC
+ JNC SAVE_FRAES_OK
+ LCD 40H,"FEHLER bei Speichern. "
+ RET
+
+SAVE_FRAES_OK:
+ LCD 40H,"Datei gespeichert. "
+ RET
+
+SAVE_FRAES_ENDE:
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Position des Roboters speichern. 1. Teil: Msg- Header
+; in MEM speichern und ersten Teil der Position vom Roboter
+; anfordern.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+STORE_ROB:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JNB READY,STORE_ROB_ENDE ; Fertig und Roboter ?
+ JB P3.5,STORE_ROB_ENDE
+
+ MOV B,#4 ; Msg. an Roboter um Pos.
+ MOV R2,#MemRob ; Empfaenger angeben
+ MOV R3,#RobPos1 ; Msg.-Nr. Empfaenger angeben
+ post_message1 Rob,GibPos1 ; zu erfragen
+
+STORE_ROB_ENDE:
+ CLR READY ; Teach- In nicht bereit
+ POP AR0
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Position des Roboters speichern. 2. Teil: 1. Teil Position
+; in MEM speichern und zweiten Teil der Position vom Roboter
+; anfordern.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+FIRST_FROM_ROB:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JB READY,FIRST_ROB_ENDE ; NICHT Fertig und Roboter ?
+ JB P3.5,FIRST_ROB_ENDE
+ MOV A,#8 ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.-Laenge)
+ ERROR 0
+ MOV A,#Rob ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Modulnr.)
+ ERROR 0
+ MOV A,#MoveAPos1 ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.- Nr.)
+ ERROR 0
+ MOV A,R2 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 High)
+ ERROR 0
+ MOV A,R3 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 Low)
+ ERROR 0
+ MOV A,R4 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 2 High)
+ ERROR 0
+ MOV A,R5 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 2 Low)
+ ERROR 0
+ MOV A,R6 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 High)
+ ERROR 0
+ MOV A,R7 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 Low)
+ ERROR 0
+
+ MOV B,#4 ; Msg. an Roboter um Pos.
+ MOV R2,#MemRob ; Empfaenger angeben
+ MOV R3,#RobPos2 ; Msg.-Nr. Empfaenger angeben
+ post_message1 Rob,GibPos2 ; zu erfragen
+
+FIRST_ROB_ENDE:
+ POP AR0
+ POP ACC
+ POP PSW
+
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Position des Roboters speichern. 3. Teil: 2. Teil Position
+; in MEM speichern.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+SECOND_FROM_ROB:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JB READY,SECOND_ROB_ENDE ; NICHT Fertig und Roboter ?
+ JB P3.5,SECOND_ROB_ENDE
+ MOV A,#8 ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.-Laenge)
+ ERROR 0
+ MOV A,#Rob ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Modulnr.)
+ ERROR 0
+ MOV A,#MoveAPos2 ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.- Nr.)
+ ERROR 0
+ MOV A,R2 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 High)
+ ERROR 0
+ MOV A,R3 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 Low)
+ ERROR 0
+ MOV A,R4 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 2 High)
+ ERROR 0
+ MOV A,R5 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 2 Low)
+ ERROR 0
+ MOV A,R6 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 High)
+ ERROR 0
+ MOV A,R7 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 Low)
+ ERROR 0
+
+SECOND_ROB_ENDE:
+ POP AR0
+ POP ACC
+ POP PSW
+ SETB READY ; Teach- In wieder bereit
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Position der Fraese speichern. 1. Teil: Msg- Header
+; in MEM speichern und ersten Teil der Position von Fraese
+; anfordern.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+STORE_FRAES:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JNB READY,STORE_FRS_ENDE ; Fertig und Fraese?
+ JNB P3.5,STORE_FRS_ENDE
+
+ MOV B,#4 ; Msg. an Roboter um Pos.
+ MOV R2,#MemFrs ; Empfaenger angeben
+ MOV R3,#FrsPos1 ; Msg.-Nr. Empfaenger angeben
+ post_message1 Frs,GibFrsPos1 ; zu erfragen
+
+STORE_FRS_ENDE:
+ CLR READY ; Teach- In nicht bereit
+ POP AR0
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Position der Fraese speichern. 2. Teil: 1. Teil Position
+; in MEM speichern und zweiten Teil der Position von Fraese
+; anfordern.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+FIRST_FROM_FRS:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JB READY,FIRST_FRS_ENDE ; NICHT Fertig und Roboter ?
+ JNB P3.5,FIRST_FRS_ENDE
+ MOV A,#8 ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.-Laenge)
+ ERROR 0
+ MOV A,#Frs ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Modulnr.)
+ ERROR 0
+ MOV A,#MoveAPos ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.- Nr.)
+ ERROR 0
+ MOV A,R2 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 High)
+ ERROR 0
+ MOV A,R3 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 Low)
+ ERROR 0
+ MOV A,R4 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 2 High)
+ ERROR 0
+ MOV A,R5 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 2 Low)
+ ERROR 0
+ MOV A,R6 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 High)
+ ERROR 0
+ MOV A,R7 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 3 Low)
+ ERROR 0
+
+ MOV B,#4 ; Msg. an Roboter um Pos.
+ MOV R2,#MemFrs ; Empfaenger angeben
+ MOV R3,#FrsPos2 ; Msg.-Nr. Empfaenger angeben
+ post_message1 Frs,GibFrsPos2 ; zu erfragen
+
+FIRST_FRS_ENDE:
+ POP AR0
+ POP ACC
+ POP PSW
+
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Position der Fraese speichern. 3. Teil: 2. Teil Position
+; in MEM speichern.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+SECOND_FROM_FRS:
+ PUSH PSW
+ PUSH ACC
+ PUSH AR0
+ JB READY,SECOND_FRS_ENDE ; NICHT Fertig und Roboter ?
+ JNB P3.5,SECOND_FRS_ENDE
+
+ MOV A,#4 ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.-Laenge)
+ ERROR 0
+ MOV A,#Frs ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Modulnr.)
+ ERROR 0
+ MOV A,#MoveV ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.- Nr.)
+ ERROR 0
+ MOV A,R2 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 High)
+ ERROR 0
+ MOV A,R3 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 1 Low)
+ ERROR 0
+
+ MOV A,#3 ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.-Laenge)
+ ERROR 0
+ MOV A,#Frs ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Modulnr.)
+ ERROR 0
+ MOV A,#Drill ; Msg- Header speichern
+ LCALL PUT_ELEMENT_MEM ; (Msg.- Nr.)
+ ERROR 0
+ MOV A,R4 ; Position speichern
+ LCALL PUT_ELEMENT_MEM ; (Parameter 2 High)
+ ERROR 0
+
+SECOND_FRS_ENDE:
+ POP AR0
+ POP ACC
+ POP PSW
+ SETB READY ; Teach- In wieder bereit
+ RET
+
+;---------------------------------------------------------------------
+; Funktion :
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+
+ RET
+
+;=====================================================================
+; END
+;---------------------------------------------------------------------
+
diff --git a/tests/t_mic51/asflags b/tests/t_mic51/asflags
new file mode 100644
index 0000000..d0334c2
--- /dev/null
+++ b/tests/t_mic51/asflags
@@ -0,0 +1 @@
+-c -A \ No newline at end of file
diff --git a/tests/t_mic51/defKey.inc b/tests/t_mic51/defKey.inc
new file mode 100644
index 0000000..aac5ab1
--- /dev/null
+++ b/tests/t_mic51/defKey.inc
@@ -0,0 +1,83 @@
+; *****************************************************************************
+; Definition des Tastenfeldes der Teach-In Einheit
+; Format:
+; DefKey {On,Off}, {P4,P5}, <Teach-In Modul>, <String>
+;
+; Es muss genau 8 Elemente pro Kategorie eingetragen werden
+; Wenn leerer String, wird keine Message durch das Netz gesendet
+
+
+ DefKey On, P4, TeachRob, "Rob MoveCHL" ; Hand links
+ DefKey On, P4, TeachRob, "Rob MoveCHR" ; Hand rechts
+ DefKey On, P4, TeachRob, "Rob MoveCHO" ; Hand oeffnen
+ DefKey On, P4, TeachRob, "Rob MoveCHC" ; Hand schliessen
+ DefKey On, P4, TeachRob, "MemRob StoreRobPos" ; STORE
+ DefKey On, P4, TeachRob, "MemRob StoreRobReady" ; AUX1
+ DefKey On, P4, TeachRob, "MemRob StoreRobSync" ; AUX2
+ DefKey On, P4, TeachRob, "Rob RobVelocity Fast" ; FAST
+
+ DefKey Off, P4, TeachRob, "Rob StopCHT"
+ DefKey Off, P4, TeachRob, "Rob StopCHT"
+ DefKey Off, P4, TeachRob, "Rob StopCH"
+ DefKey Off, P4, TeachRob, "Rob StopCH"
+ DefKey Off, P4, TeachRob, ""
+ DefKey Off, P4, TeachRob, ""
+ DefKey Off, P4, TeachRob, ""
+ DefKey Off, P4, TeachRob, "Rob RobVelocity Slow"
+
+ DefKey On, P5, TeachRob, "Rob MoveCBL" ; Rumpf links
+ DefKey On, P5, TeachRob, "Rob MoveCBR" ; Rumpf rechts
+ DefKey On, P5, TeachRob, "Rob MoveCSU" ; Oberarm heben
+ DefKey On, P5, TeachRob, "Rob MoveCSD" ; Oberarm senken
+ DefKey On, P5, TeachRob, "Rob MoveCEU" ; Unterarm heben
+ DefKey On, P5, TeachRob, "Rob MoveCED" ; Unterarm senken
+ DefKey On, P5, TeachRob, "Rob MoveCHU" ; Hand heben
+ DefKey On, P5, TeachRob, "Rob MoveCHD" ; Hand senken
+
+ DefKey Off, P5, TeachRob, "Rob StopCB"
+ DefKey Off, P5, TeachRob, "Rob StopCB"
+ DefKey Off, P5, TeachRob, "Rob StopCS"
+ DefKey Off, P5, TeachRob, "Rob StopCS"
+ DefKey Off, P5, TeachRob, "Rob StopCE"
+ DefKey Off, P5, TeachRob, "Rob StopCE"
+ DefKey Off, P5, TeachRob, "Rob StopCHP"
+ DefKey Off, P5, TeachRob, "Rob StopCHP"
+
+ DefKey On, P4, TeachFrs, "Frs Drill on" ; Fraesmotor ein
+ DefKey On, P4, TeachFrs, "Frs Drill off" ; Fraesmotor aus
+ DefKey On, P4, TeachFrs, "MemFrs StoreFrsPos" ; STORE
+ DefKey On, P4, TeachFrs, "Frs FrsVelocity fast" ; FAST
+ DefKey On, P4, TeachFrs, "MemFrs StoreFrsReady" ; AUX1
+ DefKey On, P4, TeachFrs, "MemFrs StoreFrsSync" ; AUX2
+ DefKey On, P4, TeachFrs, "MemFrs StoreFrsDrill" ; AUX3
+ DefKey On, P4, TeachFrs, "" ; AUX4
+
+ DefKey Off, P4, TeachFrs, ""
+ DefKey Off, P4, TeachFrs, ""
+ DefKey Off, P4, TeachFrs, ""
+ DefKey Off, P4, TeachFrs, "Frs FrsVelocity slow"
+ DefKey Off, P4, TeachFrs, ""
+ DefKey Off, P4, TeachFrs, ""
+ DefKey Off, P4, TeachFrs, ""
+ DefKey Off, P4, TeachFrs, ""
+
+ DefKey On, P5, TeachFrs, "Frs MoveCX +" ; X+
+ DefKey On, P5, TeachFrs, "Frs MoveCX -" ; X-
+ DefKey On, P5, TeachFrs, "Frs MoveCY +" ; Y+
+ DefKey On, P5, TeachFrs, "Frs MoveCY -" ; Y-
+ DefKey On, P5, TeachFrs, "Frs MoveCZ +" ; Z+
+ DefKey On, P5, TeachFrs, "Frs MoveCZ -" ; Z-
+ DefKey On, P5, TeachFrs, "Frs MoveCV +" ; Schraubstock auf
+ DefKey On, P5, TeachFrs, "Frs MoveCV -" ; Schraubstock zu
+
+ DefKey Off, P5, TeachFrs, "Frs StopCX +"
+ DefKey Off, P5, TeachFrs, "Frs StopCX -"
+ DefKey Off, P5, TeachFrs, "Frs StopCY +"
+ DefKey Off, P5, TeachFrs, "Frs StopCY -"
+ DefKey Off, P5, TeachFrs, "Frs StopCZ +"
+ DefKey Off, P5, TeachFrs, "Frs StopCZ -"
+ DefKey Off, P5, TeachFrs, "Frs StopCV +"
+ DefKey Off, P5, TeachFrs, "Frs StopCV -"
+
+;
+; *****************************************************************************
diff --git a/tests/t_mic51/defModul.inc b/tests/t_mic51/defModul.inc
new file mode 100644
index 0000000..98682ca
--- /dev/null
+++ b/tests/t_mic51/defModul.inc
@@ -0,0 +1,18 @@
+; ****************************************************************************
+; Definition der Modulnamen
+; Format:
+; defModul <Modulname>, <Netzwerkadressse>
+;
+; Dem <Modulname> wird eine eindeutige Zahl zugeordnet.
+;
+ defModul Rob, uC_Rob
+ defModul Frs, uC_Frs
+ defModul TeachRob, uC_Teach_Rob
+ defModul TeachFrs, uC_Teach_Frs
+ defModul TeachKey, uC_Teach_Key
+ defModul MemRob, uC_Teach_Rob
+ defModul MemFrs, uC_Teach_Frs
+ defModul PC_SIO, uC_PC_SIO
+
+;
+; ****************************************************************************
diff --git a/tests/t_mic51/defMsg.inc b/tests/t_mic51/defMsg.inc
new file mode 100644
index 0000000..420c19e
--- /dev/null
+++ b/tests/t_mic51/defMsg.inc
@@ -0,0 +1,141 @@
+; ****************************************************************************
+; Definition der Parameter - Pattern
+;
+;NoParamSingle
+;ParamSingle1
+;ParamSingle2
+;ParamSingle3
+;ParamSingle4
+;ParamSingle5
+;ParamSingle6
+
+;
+; ****************************************************************************
+; Definition der Messages
+; Format:
+; DefMsg <Modul>, <MsgName>, <Anzahl Parameter>, <Parameter - Pattern>
+;
+ DefMsg Rob, MoveAB , 1, NoParamSingle
+ DefMsg Rob, MoveAS , 1, NoParamSingle
+ DefMsg Rob, MoveAE , 1, NoParamSingle
+ DefMsg Rob, MoveARW , 1, NoParamSingle
+ DefMsg Rob, MoveALW , 1, NoParamSingle
+ DefMsg Rob, MoveAH , 1, NoParamSingle
+ DefMsg Rob, MoveAPos1 , 3, NoParamSingle
+ DefMsg Rob, MoveAPos2 , 3, NoParamSingle
+ DefMsg Rob, MoveRB , 1, NoParamSingle
+ DefMsg Rob, MoveRS , 1, NoParamSingle
+ DefMsg Rob, MoveRE , 1, NoParamSingle
+ DefMsg Rob, MoveRRW , 1, NoParamSingle
+ DefMsg Rob, MoveRLW , 1, NoParamSingle
+ DefMsg Rob, MoveRH , 1, NoParamSingle
+ DefMsg Rob, MoveRPos1 , 3, NoParamSingle
+ DefMsg Rob, MoveRPos2 , 3, NoParamSingle
+ DefMsg Rob, MoveCBL , 0, NoParamSingle
+ DefMsg Rob, MoveCBR , 0, NoParamSingle
+ DefMsg Rob, StopCB , 0, NoParamSingle
+ DefMsg Rob, MoveCSU , 0, NoParamSingle
+ DefMsg Rob, MoveCSD , 0, NoParamSingle
+ DefMsg Rob, StopCS , 0, NoParamSingle
+ DefMsg Rob, MoveCEU , 0, NoParamSingle
+ DefMsg Rob, MoveCED , 0, NoParamSingle
+ DefMsg Rob, StopCE , 0, NoParamSingle
+ DefMsg Rob, MoveCHU , 0, NoParamSingle
+ DefMsg Rob, MoveCHD , 0, NoParamSingle
+ DefMsg Rob, StopCHP , 0, NoParamSingle
+ DefMsg Rob, MoveCHL , 0, NoParamSingle
+ DefMsg Rob, MoveCHR , 0, NoParamSingle
+ DefMsg Rob, StopCHT , 0, NoParamSingle
+ DefMsg Rob, MoveCHO , 0, NoParamSingle
+ DefMsg Rob, MoveCHC , 0, NoParamSingle
+ DefMsg Rob, StopCH , 0, NoParamSingle
+ DefMsg Rob, RobVelocity , 1, ParamSingle1
+ DefMsg Rob, RobGoHome , 0, NoParamSingle
+ DefMsg Rob, SetHome , 0, NoParamSingle
+ DefMsg Rob, GibPos1 , 2, ParamSingle1+ParamSingle2
+ DefMsg Rob, GibPos2 , 2, ParamSingle1+ParamSingle2
+ DefMsg Rob, RobGibReady , 2, ParamSingle1+ParamSingle2
+ DefMsg Rob, RobInit , 0, NoParamSingle
+ DefMsg Rob, RobDeInit , 0, NoParamSingle
+
+ DefMsg Frs, Init , 0, NoParamSingle
+ DefMsg Frs, DeInit , 0, NoParamSingle
+ DefMsg Frs, MoveCX , 1, ParamSingle1
+ DefMsg Frs, MoveCY , 1, ParamSingle1
+ DefMsg Frs, MoveCZ , 1, ParamSingle1
+ DefMsg Frs, MoveCV , 1, ParamSingle1
+ DefMsg Frs, StopCX , 1, ParamSingle1
+ DefMsg Frs, StopCY , 1, ParamSingle1
+ DefMsg Frs, StopCZ , 1, ParamSingle1
+ DefMsg Frs, StopCV , 1, ParamSingle1
+ DefMsg Frs, FrsVelocity , 1, ParamSingle1
+ DefMsg Frs, FrsVelocityDraw , 1, ParamSingle1
+ DefMsg Frs, FrsGoHome , 0, NoParamSingle
+ DefMsg Frs, RefFahrt , 0, NoParamSingle
+ DefMsg Frs, SetDrillRef , 0, NoParamSingle
+ DefMsg Frs, SetPieceRef , 3, NoParamSingle
+ DefMsg Frs, MoveX , 1, NoParamSingle
+ DefMsg Frs, MoveY , 1, NoParamSingle
+ DefMsg Frs, MoveZ , 1, NoParamSingle
+ DefMsg Frs, MoveAPos , 3, NoParamSingle
+ DefMsg Frs, MoveRX , 1, NoParamSingle
+ DefMsg Frs, MoveRY , 1, NoParamSingle
+ DefMsg Frs, MoveRZ , 1, NoParamSingle
+ DefMsg Frs, MoveRV , 1, NoParamSingle
+ DefMsg Frs, MoveRPos , 3, NoParamSingle
+ DefMsg Frs, MoveVOpen , 0, NoParamSingle
+ DefMsg Frs, MoveVClose , 0, NoParamSingle
+ DefMsg Frs, MoveV , 1, NoParamSingle
+ DefMsg Frs, GoPieceRefPos , 0, NoParamSingle
+ DefMsg Frs, MovePR , 3, NoParamSingle
+ DefMsg Frs, Drill , 1, ParamSingle1
+ DefMsg Frs, SetMasterAdress , 3, ParamSingle1+ParamSingle2+ParamSingle3
+ DefMsg Frs, GibFrsPos1 , 2, ParamSingle1+ParamSingle2
+ DefMsg Frs, GibFrsPos2 , 2, ParamSingle1+ParamSingle2
+ DefMsg Frs, GibPosP , 2, ParamSingle1+ParamSingle2
+ DefMsg Frs, GibStatus , 2, ParamSingle1+ParamSingle2
+ DefMsg Frs, GibReady , 3, ParamSingle1+ParamSingle2+ParamSingle3
+
+ DefMsg MemRob,LoadRob,0, NoParamSingle
+ DefMsg MemRob,SaveRob,0, NoParamSingle
+ DefMsg MemRob,StartRobRun,0, NoParamSingle
+ DefMsg MemRob,StoreRobPos,0, NoParamSingle
+ DefMsg MemRob,StoreRobSync,0, NoParamSingle
+ DefMsg MemRob,StoreRobReady,0, NoParamSingle
+ DefMsg MemRob,InitRobTeach,0, NoParamSingle
+ DefMsg MemRob,DeinitRobTeach,0, NoParamSingle
+ DefMsg MemRob,ClearRobTeach,0, NoParamSingle
+ DefMsg MemRob,ResetRobTeach,0, NoParamSingle
+ DefMsg MemRob,GetRobSync,1,ParamSingle1
+ DefMsg MemRob,GetRobReady,0, NoParamSingle
+ DefMsg MemRob,RobPos1,3, NoParamSingle
+ DefMsg MemRob,RobPos2,3, NoParamSingle
+ DefMsg MemRob,DebugRob,0, NoParamSingle
+
+ DefMsg MemFrs,LoadFrs,0, NoParamSingle
+ DefMsg MemFrs,SaveFrs,0, NoParamSingle
+ DefMsg MemFrs,StartFrsRun,0, NoParamSingle
+ DefMsg MemFrs,StoreFrsPos,0, NoParamSingle
+ DefMsg MemFrs,StoreFrsSync,0, NoParamSingle
+ DefMsg MemFrs,StoreFrsReady,0, NoParamSingle
+ DefMsg MemFrs,StoreFrsPieceRef,0, NoParamSingle
+ DefMsg MemFrs,StoreFrsTiefe,0, NoParamSingle
+ DefMsg MemFrs,StoreFrsDrill,0, NoParamSingle
+ DefMsg MemFrs,InitFrsTeach,0, NoParamSingle
+ DefMsg MemFrs,DeinitFrsTeach,0, NoParamSingle
+ DefMsg MemFrs,ClearFrsTeach,0, NoParamSingle
+ DefMsg MemFrs,ResetFrsTeach,0, NoParamSingle
+ DefMsg MemFrs,GetFrsSync,1,ParamSingle1
+ DefMsg MemFrs,GetFrsReady,0, NoParamSingle
+ DefMsg MemFrs,FrsPos1,3, NoParamSingle
+ DefMsg MemFrs,FrsPos2,3, NoParamSingle
+ DefMsg MemFrs,FrsPieceRef,3, NoParamSingle
+ DefMsg MemFrs,FrsTiefe,3, NoParamSingle
+ DefMsg MemFrs,GetFrsError,1, ParamSingle1
+ DefMsg MemFrs,GetFrsWarning,1, ParamSingle1
+ DefMsg MemFrs,DebugFrs,0, NoParamSingle
+
+ DefMsg TeachFrs,Bug,0,NoParamSingle
+
+;
+; ****************************************************************************
diff --git a/tests/t_mic51/defParam.inc b/tests/t_mic51/defParam.inc
new file mode 100644
index 0000000..8d7e9d5
--- /dev/null
+++ b/tests/t_mic51/defParam.inc
@@ -0,0 +1,46 @@
+; *****************************************************************************
+; Definition der Parameter
+; Format:
+; DefParam <Parametername>, <Wert>, <String>
+; soll der String gleichlautend wie der Parametername sein dann reicht ""
+;
+
+ DefParam On, 001H, ""
+ DefParam Off, 000H, ""
+ DefParam Plus, 001H, "+"
+ DefParam Minus, 000H, "-"
+ DefParam Fast, 001H, ""
+ DefParam Slow, 000H, ""
+ DefParam Superslow, 002H, ""
+
+; Hier kommen die Warning-Codes fr die Fr„se
+
+ DefParam Queue_Warning, 081H, "Queue Warning"
+
+; Hier kommen die Error-Codes fr die Fr„se
+
+ DefParam Queue_Full, 061H, "Queue Full"
+ DefParam Undef_Par, 062H, "Undefined Parameter"
+ DefParam Undef_Piece_Ref, 063H, "Undefined Piece Reference"
+ DefParam Undef_Drill_Ref, 064H, "Undefined Drill Reference"
+ DefParam Undef_Koord_Ref, 065H, "Undefined Koord Reference"
+ DefParam Internal_Error, 066H, "Internal Error"
+
+ DefParam End_X_Plus, 067H, "Software End X+"
+ DefParam End_Y_Plus, 068H, "Software End Y+"
+ DefParam End_Z_Plus, 069H, "Software End Z+"
+ DefParam End_V_Plus, 06AH, "Software End V+"
+ DefParam End_X_Minus, 070H, "Software End X-"
+ DefParam End_Y_Minus, 071H, "Software End Y-"
+ DefParam End_Z_Minus, 072H, "Software End Z-"
+ DefParam End_V_Minus, 073H, "Software End V-"
+
+ DefParam Hard_End_X_Plus, 074H, "Hardware End X+"
+ DefParam Hard_End_Y_Plus, 075H, "Hardware End Y+"
+ DefParam Hard_End_Z_Plus, 076H, "Hardware End Z+"
+ DefParam Hard_End_V_Plus, 077H, "Hardware End V+"
+ DefParam Hard_End_X_Minus, 078H, "Hardware End X-"
+ DefParam Hard_End_Y_Minus, 079H, "Hardware End Y-"
+ DefParam Hard_End_Z_Minus, 07AH, "Hardware End Z-"
+ DefParam Hard_End_V_Minus, 07BH, "Hardware End V-"
+; *****************************************************************************
diff --git a/tests/t_mic51/defgequ.inc b/tests/t_mic51/defgequ.inc
new file mode 100644
index 0000000..c77f9b1
--- /dev/null
+++ b/tests/t_mic51/defgequ.inc
@@ -0,0 +1,48 @@
+; ****************************************************************************
+; EQU - Anweisungen fuer alle Module
+; ****************************************************************************
+
+ ifndef defgequ_inc
+defgequ_inc equ 000H
+
+; ----------------------------------------------------------------------------
+StringEnde equ 000H
+TableEnd equ 0FFH
+TableAnf equ 0FEH
+Rob_NextMsg set 001H
+Frs_NextMsg set 001H
+TeachRob_NextMsg set 001H
+TeachFrs_NextMsg set 001H
+MemRob_NextMsg set 001H
+MemFrs_NextMsg set 001H
+NextModul set 010H ; Modul < 10H : = Message from PC!!
+ ; Doku beachten.
+; ----------------------------------------------------------------------------
+; Definition der Netzwerkadressen
+;
+uC_Rob equ 001H ; Microcontroller des Roboters
+uC_Frs equ 002H ; Microcontroller der Fraese
+uC_Teach_Rob equ 003H ; Microcontroller Teach-In Roboter
+uC_Teach_Frs equ 004H ; Microcontroller Teach-In Fraese
+uC_Teach_Key equ 005H ; Microcontroller Teach-In Tastatur
+
+uC_PC_SIO equ 00EH ; Microcontroller PC
+
+; ----------------------------------------------------------------------------
+
+ elseif
+ fatal "Die Datei DEFGEQU.INC ist mehrmals eingebunden"
+ endif
+
+; ----------------------------------------------------------------------------
+
+NoParamSingle equ 000H
+ParamSingle1 equ 001H
+ParamSingle2 equ 002H
+ParamSingle3 equ 004H
+ParamSingle4 equ 008H
+ParamSingle5 equ 010H
+ParamSingle6 equ 020H
+
+;
+; ****************************************************************************
diff --git a/tests/t_mic51/defint.inc b/tests/t_mic51/defint.inc
new file mode 100644
index 0000000..2ea07c5
--- /dev/null
+++ b/tests/t_mic51/defint.inc
@@ -0,0 +1,234 @@
+;****************************************************************************
+; Definition der Interrupts und des Timers 2
+;
+
+Falling_Edge EQU True
+Low_Level EQU False
+Negative_Trans EQU False
+Positive_Trans EQU True
+
+Param_On EQU True
+Param_Off EQU False
+
+Nope EQU False
+
+Tm2_Off EQU 0 ;
+Tm2_Timer EQU 1 ; Input selection
+Tm2_Counter EQU 2 ;
+Tm2_Gated EQU 3 ;
+
+Tm2_Reload_Off EQU 0 ;
+Tm2_Reload_Ov EQU 2 ; Reload mode
+Tm2_Reload_Ext EQU 3 ;
+
+Tm2_Comp_Mode0 EQU False ; Compare mode
+Tm2_Comp_Mode1 EQU True ;
+
+Tm2_Slow EQU True ; Prescaler selection
+Tm2_Normal EQU False ;
+
+Tm2_CC_Off EQU 0
+Tm2_CC_Capt_Ext EQU 1
+Tm2_CC_Comp_On EQU 2
+Tm2_CC_Capt_CRCL EQU 3
+
+;-----------------------------------------------------------------------------
+
+Init_Interrupt MACRO PInterrupt, PTrig, PState
+ IFNDEF PInterrupt
+ FATAL "unbekannter Interrupt"
+ ELSEIF
+
+ SWITCH PInterrupt
+ CASE INT0_VEKTOR ; INT0
+ IF PTrig
+ SETB IT0
+ ELSEIF
+ CLR IT0
+ ENDIF
+
+ CASE INT1_VEKTOR ; INT1
+ IF PTrig
+ SETB IT1
+ ELSEIF
+ CLR IT1
+ ENDIF
+
+ CASE INT2_VEKTOR ; INT2
+ IF PTrig
+ SETB I2FR
+ ELSEIF
+ CLR I2FR
+ ENDIF
+
+ CASE INT3_VEKTOR ; INT3
+ IF PTrig
+ SETB I3FR
+ ELSEIF
+ CLR I3FR
+ ENDIF
+
+ ELSECASE
+ ENDCASE
+
+ IF PState
+ Int_On PInterrupt
+ ELSEIF
+ Int_Off PInterrupt
+ ENDIF
+
+ ENDIF
+ ENDM
+
+
+;-----------------------------------------------------------------------------
+
+Int_On MACRO PInterrupt
+ IFNDEF PInterrupt
+ FATAL "unbekannter Interrupt"
+ ELSEIF
+ SWITCH PInterrupt
+ CASE INT0_VEKTOR
+ CLR IE0
+ SETB EX0
+ CASE ICT0_VEKTOR
+ CLR TF0
+ SETB ET0
+ CASE INT1_VEKTOR
+ CLR IE1
+ SETB EX1
+ CASE ICT1_VEKTOR
+ CLR TF1
+ SETB ET1
+ CASE ICT2_VEKTOR
+ CLR TF2
+ CLR EXF2
+ SETB ET2
+ CASE AD_I_VEKTOR
+ CLR IADC
+ SETB EADC
+ CASE INT2_VEKTOR
+ CLR IEX2
+ SETB EX2
+ CASE INT3_VEKTOR
+ CLR IEX3
+ SETB EX3
+ CASE INT4_VEKTOR
+ CLR IEX4
+ SETB EX4
+ CASE INT5_VEKTOR
+ CLR IEX5
+ SETB EX5
+ CASE INT6_VEKTOR
+ CLR IEX6
+ SETB EX6
+ ENDCASE
+ ENDIF
+ ENDM
+
+;-----------------------------------------------------------------------------
+
+Int_Off MACRO PInterrupt
+ IFNDEF PInterrupt
+ FATAL "unbekannter Interrupt"
+ ELSEIF
+ SWITCH PInterrupt
+ CASE INT0_VEKTOR
+ CLR EX0
+ CLR IE0
+ CASE ICT0_VEKTOR
+ CLR ET0
+ CLR TF0
+ CASE INT1_VEKTOR
+ CLR EX1
+ CLR IE1
+ CASE ICT1_VEKTOR
+ CLR ET1
+ CLR TF1
+ CASE ICT2_VEKTOR
+ CLR ET2
+ CLR TF2
+ CLR EXF2
+ CASE AD_I_VEKTOR
+ CLR EADC
+ CLR IADC
+ CASE INT2_VEKTOR
+ CLR EX2
+ CLR IEX2
+ CASE INT3_VEKTOR
+ CLR EX3
+ CLR IEX3
+ CASE INT4_VEKTOR
+ CLR EX4
+ CLR IEX4
+ CASE INT5_VEKTOR
+ CLR EX5
+ CLR IEX5
+ CASE INT6_VEKTOR
+ CLR EX6
+ CLR IEX6
+ ENDCASE
+ ENDIF
+ ENDM
+
+;-----------------------------------------------------------------------------
+
+Init_Timer2 MACRO PInput, PReloadMode, PCompareMode, PPrescaler, PReloadValue
+
+ SWITCH PInput
+ CASE Tm2_Off
+ CLR T2I1
+ CLR T2I0
+ CASE Tm2_Timer
+ CLR T2I1
+ SETB T2I0
+ CASE Tm2_Counter
+ SETB T2I1
+ CLR T2I0
+ CASE Tm2_Gated
+ SETB T2I1
+ SETB T2I0
+ ENDCASE
+
+ SWITCH PReloadMode
+ CASE Tm2_Reload_Off
+ CLR T2R1
+ CLR T2R0
+ CASE Tm2_Reload_Ov
+ SETB T2R1
+ CLR T2R0
+ CASE Tm2_Reload_Ext
+ SETB T2R1
+ SETB T2R0
+ ENDCASE
+
+ IF PCompareMode
+ SETB T2CM
+ ELSEIF
+ CLR T2CM
+ ENDIF
+
+ IF PPrescaler
+ SETB T2PS
+ ELSEIF
+ CLR T2PS
+ ENDIF
+
+ MOV CRCL, #(PReloadValue # 256)
+ MOV CRCH, #(PReloadValue / 256)
+
+ ENDM
+
+
+
+Init_Comp_Timer2 MACRO PMode1, PMode2, PMode3, PValue1, PValue2, PValue3
+
+ MOV CCEN, #(PMode1*4+PMode2*16+PMode3*64)
+ MOV CCL1, #(PValue1 # 256)
+ MOV CCH1, #(PValue1 / 256)
+ MOV CCL2, #(PValue1 # 256)
+ MOV CCH2, #(PValue1 / 256)
+ MOV CCL3, #(PValue1 # 256)
+ MOV CCH3, #(PValue1 / 256)
+
+ ENDM
diff --git a/tests/t_mic51/defmacro.inc b/tests/t_mic51/defmacro.inc
new file mode 100644
index 0000000..f5b710d
--- /dev/null
+++ b/tests/t_mic51/defmacro.inc
@@ -0,0 +1,175 @@
+
+; ***************************************************************************
+; Definition einer Tabelle aus den MSG - Includedateien
+
+Create_IncOffsTab macro TabName, IncDatei
+TabName_Tab: label $
+FStr: db TableAnf
+ db FStrEnd - FStr, StringEnde, FStrEnd - FStr
+FStrEnd:
+ include IncDatei
+TabName_Tend: label $
+ db TableEnd
+ endm
+
+
+Create_IncTab macro TabName, IncDatei
+TabName_Tab: label $
+ include IncDatei
+TabName_Tend: label $
+ endm
+
+
+Create_IncKeyTab macro State, Port, Modul, IncDatei
+Key_Counter set 0
+State_Port_Modul_Tab: label $
+ include IncDatei
+State_Port_Modul_Tend: label $
+ if Key_Counter <> 8
+ fatal "Inkorrekte Anzahl von Elementen in Key-Tabelle"
+ endif
+ endm
+
+
+Create_MsgJmpTab macro Modul, IncDatei
+Modul_MsgCall_Tab: label $
+ include IncDatei
+Modul_MsgCall_Tend: label $
+ db TableEnd
+ endm
+
+
+
+; ***************************************************************************
+;
+
+DefModul macro Modul, NetAdr
+
+ ifndef Modul
+Modul equ NextModul
+Net_Modul equ NetAdr
+NextModul set NextModul + 1
+
+ SHARED Modul,NetAdr
+
+ endif
+
+ ifdef ModulNetAdr_Tab
+ ifndef ModulNetAdr_TEND
+ if (ModulNetAdr_Tab + Modul - $) < 0
+ Fatal "NetAdr Tabelle inkonsistent"
+ elseif
+ org ModulNetAdr_Tab + Modul
+ endif
+
+ db NetAdr
+ endif
+ endif
+
+; -------------------------
+
+ ifdef ModulStr_Tab
+ ifndef ModulStr_TEnd
+
+strdef: db Modul, strdefnext - strdef, "MODUL", StringEnde, strdefnext - strdef
+strdefnext:
+
+ endif
+ endif
+
+ endm
+
+;
+; ***************************************************************************
+;
+
+DefParam macro Param, Wert, String
+
+ ifndef Param
+Param equ Wert
+
+ SHARED Param
+
+ endif
+
+ ifdef ParamStr_Tab
+ ifndef ParamStr_TEnd
+strdef: db Wert
+ db strdefnext - strdef
+ if String = ""
+ db "PARAM", StringEnde
+ elseif
+ db String, StringEnde
+ endif
+strdefnext:
+ endif
+ endif
+
+ endm
+
+;
+; ***************************************************************************
+;
+
+DefKey macro Status, Port, Modul, String
+
+ ifdef Status_Port_Modul_Tab
+ ifndef Status_Port_Modul_TEnd
+strdef: db strdefnext - strdef
+ db String,StringEnde
+strdefnext:
+Key_Counter set Key_Counter + 1
+ endif
+ endif
+
+ endm
+
+;
+; ***************************************************************************
+;
+
+DefMsg macro Modul, MsgName, ParamCount, ParamPattern
+
+; ---------------------------------------------------------------------------
+; Definition der Message-Nummern
+
+ ifndef MsgName
+MsgName equ Modul_NextMsg
+Modul_NextMsg set Modul_NextMsg + 1
+
+ SHARED MsgName
+
+ endif
+; ---------------------------------------------------------------------------
+; Aufbau der Tabelle fuer den Message-Handler
+
+ ifdef Modul_MsgCall_Tab
+ ifndef Modul_MsgCall_Tend
+ if (Modul_MsgCall_Tab + (2 * MsgName) - $) < 0
+ Fatal "Msg-Call Tabelle inkonsistent"
+ elseif
+ org Modul_MsgCall_Tab + (2 * MsgName)
+ endif
+
+ db Adr_MsgName # 256
+ db Adr_MsgName / 256
+ endif
+ endif
+
+; ---------------------------------------------------------------------------
+; Aufbau der Stringtabelle
+
+ ifdef MsgStr_Tab
+ ifndef MsgStr_TEnd
+
+strdef: db Modul, strdefnext - strdef, MsgName, "MSGNAME", StringEnde, ParamCount, ParamPattern
+ db strdefnext - strdef
+strdefnext:
+ endif
+ endif
+
+ endm
+;
+; ***************************************************************************
+
+
diff --git a/tests/t_mic51/net_lcd.inc b/tests/t_mic51/net_lcd.inc
new file mode 100644
index 0000000..6a0cabc
--- /dev/null
+++ b/tests/t_mic51/net_lcd.inc
@@ -0,0 +1,33 @@
+; D:\USER\MEM\NET_LCD.ASM-Includefile fr Assembler-Programm
+LCD_HOME equ 0108H
+LCD_CR equ 0126H
+LCD_LF equ 0172H
+LCD_CLEAR equ 01C0H
+LCD_WRITE_CHAR equ 01DEH
+LCD_WRITE_STRING equ 01FAH
+LCD_SET_DD_RAM_ADDRESS equ 022AH
+LCD_STATUS equ 0248H
+LCD_CURSER_ONOFF equ 025BH
+SET_MY_ADRESS equ 061DH
+SET_CALLBACK_ADRESS equ 0622H
+READ_STATUS equ 0629H
+READ_MESSAGE equ 063AH
+READ_SPECIAL_MESSAGE equ 0662H
+SEND_MESSAGE equ 0693H
+INT0_VEKTOR equ 0FF00H
+ICT0_VEKTOR equ 0FF03H
+INT1_VEKTOR equ 0FF06H
+ICT1_VEKTOR equ 0FF09H
+ICT2_VEKTOR equ 0FF0CH
+AD_I_VEKTOR equ 0FF0FH
+INT2_VEKTOR equ 0FF12H
+INT3_VEKTOR equ 0FF15H
+INT4_VEKTOR equ 0FF18H
+INT5_VEKTOR equ 0FF1BH
+INT6_VEKTOR equ 0FF1EH
+DATA_START equ 03CH
+X_DATA_START equ 010H
+I_DATA_START equ 080H
+BIT_DATA_START equ 0BH
+CODE_START equ 01000H
+; Ende Includefile fr Assembler-Programm
diff --git a/tests/t_mic51/t_mic51.asm b/tests/t_mic51/t_mic51.asm
new file mode 100644
index 0000000..ce29ab1
--- /dev/null
+++ b/tests/t_mic51/t_mic51.asm
@@ -0,0 +1,2197 @@
+;Program: TEACH-IN EINHEIT
+;
+;Autor: Laurent Savary
+;
+;Datum: 9.5.94
+;
+;letze Aenderung: 23.6.94
+;
+;
+;Dateiname: TEACHIN.ASM
+;
+;------------------------------------------------------------------------------
+
+Init_Vektor macro Vektor,Routine
+
+; mov Vektor+0,#(Routine/256) ;der Interruptvektor wird
+; mov Vektor+1,#(Routine#256) ;ins interne RAM geladen
+
+ push acc
+ push dph
+ push dpl
+ mov dptr,#Vektor
+ mov a,#00000010b ; LJMP
+ movx @dptr,a
+ inc dptr
+ mov a,#(Routine/256)
+ movx @dptr,a
+ inc dptr
+ mov a,#(Routine#256)
+ movx @dptr,a
+ pop dpl
+ pop dph
+ pop acc
+
+ endm
+
+DEC_DPTR MACRO
+ INC DPL
+ DJNZ DPL,DEC_DPTR1
+ DEC DPH
+DEC_DPTR1: DEC DPL
+ ENDM
+
+
+INC_R0R1 MACRO
+ INC R0
+ INC R0
+ DJNZ R0,INC_R0R1_End
+ INC R1
+INC_R0R1_End:
+ ENDM
+
+
+DEC_R0R1: MACRO
+ INC R0
+ DJNZ R0,DEC_R0R1_End
+ DEC R1
+DEC_R0R1_End: DEC R0
+ ENDM
+
+;---------------------------------------------------------------------
+
+post_Message macro
+ push acc
+SEND_NET1: LCALL READ_STATUS
+ JB ACC.1,SEND_NET1
+ pop acc
+ LCALL SEND_MESSAGE
+ endm
+
+Take_Message macro
+ push acc
+RECEIVE_NET1: LCALL READ_STATUS
+ JNB ACC.0,RECEIVE_NET1
+ pop acc
+ LCALL READ_MESSAGE
+ endm
+
+;------------------------------------------------------------------------------
+
+ cpu 80515
+ include stddef51.inc
+ include net_lcd.inc
+ include defint.inc
+ include defgequ.inc
+ include defmacro.inc
+
+ USING 0
+
+;------------------------ Konstanten ------------------------------------------
+
+Ass_Keyboard_Only EQU False ; Wenn True, TI-Einheit lauft nur mit
+ ; der Tastatur (kein Tastenfeld)
+
+Last_Code EQU 0FFFFh ; Endeadressen
+Last_Bit_Data EQU 07Fh ; der Speicher-
+Last_Data EQU 07Fh ; bereiche
+Last_IData EQU 0FFh ; bestimmen
+Last_XData EQU 0FFFFh
+
+Kb_Max_Length EQU 40 ; Hoechstlaenge der anzuzeigenden Strings
+TI_Sample_Valid_Time EQU 30 ; Gueltige Druckdauer in ms
+
+ASCII_Space EQU 32 ;
+ASCII_Left EQU 19 ;
+ASCII_Right EQU 4 ;
+ASCII_Up EQU 5 ;
+ASCII_Down EQU 24 ; ASCII-Code fuer die
+ASCII_CR EQU 13 ; Tastatur
+ASCII_Esc EQU 27 ;
+ASCII_DEL EQU 127 ;
+ASCII_BkSpc EQU 8 ;
+ASCII_LWord EQU 1 ;
+ASCII_RWord EQU 6 ;
+ASCII_Search EQU 12 ;
+
+KSS_Off EQU 0
+KSS_Mod EQU 1
+KSS_Mod_Top EQU 2
+KSS_Mod_Bot EQU 3
+KSS_Msg EQU 4
+KSS_Msg_Top EQU 5
+KSS_Msg_Bot EQU 6
+KSS_Inc_Mod EQU 7
+KSS_No_Choice EQU 8
+
+R0_Bk1 EQU 08h
+R1_Bk1 EQU 09h
+R2_Bk1 EQU 0Ah
+R3_Bk1 EQU 0Bh
+R4_Bk1 EQU 0Ch
+R5_Bk1 EQU 0Dh
+R6_Bk1 EQU 0Eh
+R7_Bk1 EQU 0Fh
+
+;------------------------------------------------------------------------------
+
+ segment data
+ org Data_Start
+
+Save_P4 DB ? ;
+Save_P5 DB ? ;
+Old_P4 DB ? ;
+Old_P5 DB ? ;
+Temp_P4 DB ? ; benoetigte Variablen fuer
+Temp_P5 DB ? ; Teach_In_Sampler
+TI_On_P4 DB ? ;
+TI_Off_P4 DB ? ;
+TI_On_P5 DB ? ;
+TI_Off_P5 DB ? ;
+TI_Sample_Counter DB ? ;
+
+Text_Dec_Status DB ?
+Kb_Char_Buffer DB ?
+Kb_Str_Pointer DB ?
+Kb_Cursor DB ?
+ASCII_Low_Byte DB ?
+ASCII_High_Byte DB ?
+Rcv_Msg_Length DB ?
+My_Slave_Adr DB ? ; Physikalische Adresse dieses Moduls
+
+Kb_Search_Status DB ? ;
+Kb_Search_DPL DB ? ;
+Kb_Search_DPH DB ? ; Benoetigte Variablen fuer
+KS_Actual_Word DB ? ; Keyboard Search
+KS_Actual_Module DB ? ;
+KS_Cursor DB ? ;
+
+Stat_Code DB ? ;
+Stat_Address DB ? ;
+Stat_Num_Param DB ? ; Benoetigte Variablen fuer
+Stat_Picture DB ? ; Text_Decoder
+Stat_Module DB ? ;
+Stat_Length DB ? ;
+
+ if $ > Last_Data
+ then fatal "Data-Bereichgrenze ueberschritten"
+ endif
+
+
+;------------------------------------------------------------------------------
+
+ segment xdata
+ org X_Data_Start
+
+Kb_Str_Buffer DB Kb_Max_Length dup (?) ; Text Buffer (fuer die Tastatur)
+Token_Str DB Kb_Max_Length dup (?) ; Ergebnis von Get_Token
+Net_Rcv_Str DB Kb_Max_Length dup (?) ; Empfangene Message vom Teach-In Modul
+
+ if $ > Last_XData
+ then fatal "XData-Bereichgrenze ueberschritten"
+ endif
+
+;------------------------------------------------------------------------------
+
+ segment idata
+ org I_Data_Start
+
+Msg_Registers DB 8 dup (?) ; Register-Buffer fur die zu sendenden Messages
+
+ if $ > Last_IData
+ then fatal "IData-Bereichgrenze ueberschritten"
+ endif
+
+
+;------------------------------------------------------------------------------
+
+ segment bitdata
+ org Bit_Data_Start
+
+Kb_Str_Ready DB ? ; -> Text_Decoder
+Kb_Char_Ready DB ? ; -> Keyb_Controller
+TI_Sample_Chg_Flg DB ? ; -> TeachIn_Decoder
+TD_Status_Ready DB ? ; -> LCD_Controller
+TD_Send_Ready DB ? ; -> Send_Manager
+Receive_Ready DB ? ; -> Receive_Manager
+TD_Next_Flg DB ? ; -> Kb_Controller
+KS_Status_Ready DB ? ; -> LCD_Controller
+KS_Active_Flg DB ? ; -> KB_Search_Up / _Down
+Kb_Dsp_Ready DB ? ; -> LCD_Controller
+Ext_Dsp_Ready DB ? ; -> LCD_Controller
+System_Error DB ?
+Sys_Robot_Mode DB ?
+Sys_Keyboard_Mode DB ?
+TID_Done_Flg DB ? ; -> TeachIn_Sampler
+
+ if $ > Last_Bit_Data
+ then fatal "Bit_Data-Bereichgrenze ueberschritten"
+ endif
+
+
+;------------------------------------------------------------------------------
+
+ segment code
+ org Code_Start
+
+;====================== H A U P T P R O G R A M M =============================
+
+ segment code
+
+Main_Prog: CLR EAL ;alle Interrupts sperren
+ MOV SP,#Stack-1 ;Stackpointer setzen
+
+ LCALL Init_Data
+ LCALL Init_IData
+ LCALL Init_BitData
+ LCALL Init_XData
+ LCALL Init_Timer
+ LCALL Init_Mode
+Main_Error: JB System_Error,Main_Error
+
+ LCALL Init_Net
+ LCALL LCD_Clear
+ MOV A,#1
+ LCALL LCD_Curser_OnOff
+ LCALL Init_Int
+ SETB EAL
+
+ CLR TESTBIT
+ CLR MSG
+ MOV Sp_MSG_Buffer,#0
+ CLR Sp_MSG
+ LCALL INIT_TEACH
+ LCALL INIT_RUN
+ LCALL RESET_TEACH
+ LCALL INIT_FRS
+
+Main_Loop: LCALL Main_Manager
+ LCALL Main_Event_Loop
+ SJMP Main_Loop
+
+
+;------------------------------------------------------------------------------
+
+Adr_Table: Create_IncTab ModulNetAdr, "defModul.inc"
+Module_Table: Create_IncOffsTab ModulStr, "defModul.inc"
+Symbol_Table: Create_IncOffsTab ParamStr, "defParam.inc"
+Stat_Table: Create_IncOffsTab MsgStr, "defMsg.inc"
+
+KOn_P4_Rob: Create_IncKeyTab On, P4, TeachRob, "defKey.inc"
+KOff_P4_Rob: Create_IncKeyTab Off, P4, TeachRob, "defKey.inc"
+KOn_P5_Rob: Create_IncKeyTab On, P5, TeachRob, "defKey.inc"
+KOff_P5_Rob: Create_IncKeyTab Off, P5, TeachRob, "defKey.inc"
+KOn_P4_Frs: Create_IncKeyTab On, P4, TeachFrs, "defKey.inc"
+KOff_P4_Frs: Create_IncKeyTab Off, P4, TeachFrs, "defKey.inc"
+KOn_P5_Frs: Create_IncKeyTab On, P5, TeachFrs, "defKey.inc"
+KOff_P5_Frs: Create_IncKeyTab Off, P5, TeachFrs, "defKey.inc"
+
+;--------------------------------------------------------------------------
+ include t_mod1.asm ;
+;------------------------------------------------------------------------------
+
+Main_Manager: JNB Kb_Char_Ready,MM_Txt_Dec
+ LCALL Keyb_Controller
+
+MM_Txt_Dec: JNB Kb_Str_Ready,MM_TI_Dec
+ LCALL Text_Decoder
+
+MM_TI_Dec: JNB TI_Sample_Chg_Flg,MM_Send_Mng
+ LCALL TeachIn_Decoder
+
+MM_Send_Mng: JNB TD_Send_Ready,MM_Receive_Mng
+ LCALL Send_Manager
+
+MM_Receive_Mng: JNB Receive_Ready,MM_LCD_Ctrl
+ LCALL Receive_Manager
+
+MM_LCD_Ctrl: JB Ext_Dsp_Ready,MM_LCD_Ctrl2
+ JB Kb_Dsp_Ready,MM_LCD_Ctrl2
+ JB TD_Status_Ready,MM_LCD_Ctrl2
+ JB KS_Status_Ready,MM_LCD_Ctrl2
+ SJMP MM_End
+MM_LCD_Ctrl2: LCALL LCD_Controller
+
+MM_End: RET
+
+;--------------------------------------------------------------------------
+
+Init_Data:
+ MOV Save_P4,#0FFh
+ MOV Save_P5,#0FFh
+ MOV Old_P4,#0FFh
+ MOV Old_P5,#0FFh
+ MOV Temp_P4,#0FFh
+ MOV Temp_P5,#0FFh
+ MOV TI_On_P4,#00
+ MOV TI_Off_P4,#00
+ MOV TI_On_P5,#00
+ MOV TI_Off_P5,#00
+ MOV TI_Sample_Counter,#00
+ MOV Rcv_Msg_Length,#00
+ MOV My_Slave_Adr,#00
+
+ MOV Text_Dec_Status,#00
+ MOV Kb_Char_Buffer,#00
+ MOV Kb_Str_Pointer,#00
+ MOV Kb_Cursor,#00
+ MOV ASCII_Low_Byte,#00
+ MOV ASCII_High_Byte,#00
+
+ MOV Kb_Search_DPL,#00
+ MOV Kb_Search_DPH,#00
+ MOV KS_Actual_Word,#00
+ MOV KS_Actual_Module,#00
+ MOV KS_Cursor,#00
+ MOV Kb_Search_Status,#00
+
+ MOV Stat_Code,#00
+ MOV Stat_Address,#00
+ MOV Stat_Num_Param,#00
+ MOV Stat_Picture,#00
+ MOV Stat_Module,#00
+ MOV Stat_Length,#00
+ RET
+
+
+Init_IData: LCALL Clr_Msg_Buffer
+ RET
+
+
+Init_XData: PUSH DPL
+ PUSH DPH
+ PUSH Acc
+
+ MOV DPTR,#Kb_Str_Buffer
+ MOV A,#ASCII_Space
+ LCALL Clear_Str
+ MOV DPTR,#Token_Str
+ MOV A,#StringEnde
+ LCALL Clear_Str
+
+ POP Acc
+ POP DPH
+ POP DPL
+ RET
+
+
+Init_BitData: CLR Kb_Str_Ready
+ CLR Kb_Char_Ready
+ CLR TI_Sample_Chg_Flg
+ CLR TD_Status_Ready
+ CLR TD_Send_Ready
+ CLR Receive_Ready
+ SETB TD_Next_Flg
+ CLR KS_Active_Flg
+ CLR KS_Status_Ready
+ CLR Kb_Dsp_Ready
+ CLR Ext_Dsp_Ready
+ CLR System_Error
+ CLR Sys_Robot_Mode
+ CLR Sys_Keyboard_Mode
+ CLR TID_Done_Flg
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Init_Mode
+; Parameter : -
+; Rueckgabeparameter : Sys_Robot_Mode, Sys_Keyboard_Mode,System_Error
+;
+; entscheidet, ob das Programm im TI-Roboter, TI-Fraese oder TI-Tastatur
+; laufen muss. (SRM /SKM) (/SRM /SKM) (SKM)
+
+
+Init_Mode: PUSH PSW
+ PUSH DPL
+ PUSH DPH
+
+ CLR System_Error
+
+ if Ass_Keyboard_Only
+ SJMP IM_Keyboard
+ elseif
+ CLR Sys_Robot_Mode
+ CLR Sys_Keyboard_Mode
+ LCALL LCD_Clear
+ MOV DPTR,#Screen_Title
+ LCALL LCD_Write_String
+ JNB P3.5,IM_Robot
+ JB P3.4,IM_Error
+ MOV DPTR,#Screen_Drill
+ SJMP IM_End
+ endif
+
+IM_Robot: JNB P3.4,IM_Keyboard
+ SETB Sys_Robot_Mode
+ MOV DPTR,#Screen_Robot
+ SJMP IM_End
+
+IM_Keyboard: SETB Sys_Keyboard_Mode
+ MOV DPTR,#Screen_Key
+ SJMP IM_End
+
+IM_Error: SETB System_Error
+ MOV DPTR,#Screen_Error
+
+IM_End: LCALL LCD_Write_String
+ LCALL Wait_2s
+
+ POP DPH
+ POP DPL
+ POP PSW
+ RET
+
+Screen_Title: DB "**** TEACH-IN UNIT v1.0 ****",00
+Screen_Drill: DB " Drill mode",00
+Screen_Robot: DB " Robot mode",00
+Screen_Key: DB " Keyboard mode",00
+Screen_Error: DB " ERROR : Incorrect micro-controller",00
+
+;--------------------------------------------------------------------------
+
+Init_Int: Init_Vektor INT0_VEKTOR,Keyb_Sampler
+ Init_Interrupt INT0_VEKTOR,Falling_Edge,Param_On
+ Init_Vektor ICT0_VEKTOR,TeachIn_Sampler
+ Init_Interrupt ICT0_VEKTOR,Nope,Param_On
+ RET
+
+;--------------------------------------------------------------------------
+
+
+Init_Net: PUSH Acc
+ PUSH DPL
+ PUSH DPH
+
+ MOV DPTR,#MESSAGE_INTERRUPT ;Receive_Sampler
+ LCALL Set_CallBack_Adress
+ MOV DPTR,#Adr_Table
+ JB Sys_Keyboard_Mode,Init_Net_Key
+ JNB Sys_Robot_Mode,Init_Net_Frs
+
+Init_Net_Rob: MOV A,#TeachRob
+ SJMP Init_Net_End
+
+Init_Net_Frs: MOV A,#TeachFrs
+ SJMP Init_Net_End
+
+Init_Net_Key: MOV A,#TeachKey
+
+Init_Net_End: MOVC A,@A+DPTR
+ MOV My_Slave_Adr,A
+ LCALL Set_My_Adress
+
+ POP DPH
+ POP DPL
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+
+Init_Timer: MOV TH0,#00
+ MOV TL0,#00
+ MOV TMOD,#00110001b ; T1 : Off, T0 : 16 Bit Timer
+ SETB TR0 ; T0 einschalten
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : LCD_Controller
+; Parameter : Ext_Dsp_Ready -> DPTR
+; TD_Status_Ready -> Text_Dec_Status
+; KS_Status_Ready -> Kb_Search_Status
+; Rueckgabeparameter : -
+; wenn Ext_Dsp_Ready gesetzt wird, zeigt den mit DPTR gezeigten String
+; auf den Bildschirm an.
+; wenn TD_Status_Ready (bzw KS_Status_Ready) gesetzt wird, zeigt die
+; entsprechende Meldung von Text_Dec_Status (bzw Kb_Search_Status)
+;
+
+LCD_Controller: PUSH PSW
+ PUSH Acc
+ PUSH AR0
+ PUSH AR1
+ PUSH DPL
+ PUSH DPH
+ LCALL LCD_Home
+
+ JNB Ext_Dsp_Ready,LCD_Str_Buffer
+ CLR Ext_Dsp_Ready
+ MOV A,#40h
+ LCALL LCD_Set_DD_RAM_Address
+ MOV R1,#Kb_Max_Length
+
+LCD_Ext_Loop: MOVX A,@DPTR
+ LCALL LCD_Write_Char
+ INC DPTR
+ DJNZ R1,LCD_Ext_Loop
+ LCALL LCD_Home
+
+LCD_Str_Buffer: JNB Kb_Dsp_Ready,LCD_TD_Status
+ CLR Kb_Dsp_Ready
+ MOV DPTR,#Kb_Str_Buffer
+ MOV R1,#Kb_Max_Length
+
+LCD_Str_Loop: MOVX A,@DPTR
+ LCALL LCD_Write_Char
+ INC DPTR
+ DJNZ R1,LCD_Str_Loop
+
+LCD_TD_Status: JNB TD_Status_Ready,LCD_KS_Status
+ CLR TD_Status_Ready
+
+ MOV A,#40
+ LCALL LCD_Set_DD_RAM_Address
+ MOV DPTR,#LCD_TD_Table
+ MOV R0,Text_Dec_Status
+ CJNE R0,#00,LCD_TD_Loop
+ SJMP LCD_TD_Cont
+
+LCD_TD_Loop: MOV A,#41
+ ADD A,DPL
+ MOV DPL,A
+ MOV A,DPH
+ ADDC A,#00
+ MOV DPH,A
+ DJNZ R0,LCD_TD_Loop
+
+LCD_TD_Cont: LCALL LCD_Write_String
+
+LCD_KS_Status: JNB KS_Status_Ready,LCD_End
+ CLR KS_Status_Ready
+
+ MOV A,#40
+ LCALL LCD_Set_DD_RAM_Address
+ MOV DPTR,#LCD_KS_Table
+ MOV R0,Kb_Search_Status
+ CJNE R0,#00,LCD_KS_Loop
+ SJMP LCD_KS_Cont
+
+LCD_KS_Loop: MOV A,#41
+ ADD A,DPL
+ MOV DPL,A
+ MOV A,DPH
+ ADDC A,#00
+ MOV DPH,A
+ DJNZ R0,LCD_KS_Loop
+
+LCD_KS_Cont: LCALL LCD_Write_String
+
+LCD_End: MOV A,Kb_Cursor
+ LCALL LCD_Set_DD_RAM_Address
+
+ POP DPH
+ POP DPL
+ POP AR1
+ POP AR0
+ POP Acc
+ POP PSW
+ RET
+
+LCD_TD_Table: DB "Edit OK : Sending ",00
+ DB "Edit ERROR : message waited ",00
+ DB "Edit ERROR : incorrect message ",00
+ DB "Edit ERROR : more parameters waited ",00
+ DB "Edit ERROR : parameter range ",00
+ DB "Edit ERROR : module name waited ",00
+ DB "Edit ERROR : incorrect module name ",00
+ DB "Edit WARNING : too many parameters ",00
+
+LCD_KS_Table: DB "Text editing ",00
+ DB "Search : Choose a module ",00
+ DB "Search : Choose a module, reached TOP ",00
+ DB "Search : Choose a module, reached BOTT. ",00
+ DB "Search : Choose a message ",00
+ DB "Search : Choose a message, reached TOP ",00
+ DB "Search : Choose a message, reached BOTT.",00
+ DB "Search : Incorrect module ",00
+ DB "Search : No choice available ",00
+
+;--------------------------------------------------------------------------
+
+Keyb_Sampler:
+ MOV Kb_Char_Buffer,P1
+ SETB Kb_Char_Ready
+ RETI
+
+;--------------------------------------------------------------------------
+; Routine : Keyb_Controller
+; Parameter : Kb_Char_Ready ; (Buchstabe im Buffer)
+; Kb_Char_Buffer ; (zu verarbeitender Buchstabe)
+; Kb_Cursor ; (Cursorposition auf LCD)
+; KS_Active_Flg ; (Keyb. Search Modus)
+; Kb_Str_Buffer ; (Text Buffer f. Tastatur)
+; TD_Next_Flg ; Text_Decoder ist fertig
+; Rueckgabeparameter : Kb_Cursor
+; KS_Active_Flg
+; Kb_Str_Buffer
+; Kb_Str_Ready ; (->Text_Decoder : String verarbeiten)
+; Kb_Search_Status ; (Keyb. Search Zustand)
+; KS_Status_Ready ; (-> LCD : Zustand anzeigen)
+;
+; Verwaltet Kb_Str_Buffer nach der Tastatur-Eingaben
+
+
+Keyb_Controller:
+ PUSH Acc
+ PUSH PSW
+ PUSH DPL
+ PUSH DPH
+
+ CLR Kb_Char_Ready
+ MOV A,Kb_Char_Buffer
+
+ JNB TD_Next_Flg,Kb_Ctrl_UP
+ CLR TD_Next_Flg
+Kb_Ctrl_Test1: CJNE A,#ASCII_Left,Kb_Ctrl_Test2
+ SJMP Kb_Ctrl_Old
+Kb_Ctrl_Test2: CJNE A,#ASCII_Right,Kb_Ctrl_Test3
+ SJMP Kb_Ctrl_Old
+Kb_Ctrl_Test3: CJNE A,#ASCII_BkSpc,Kb_Ctrl_Test4
+ SJMP Kb_Ctrl_Old
+Kb_Ctrl_Test4: CJNE A,#ASCII_CR,Kb_Ctrl_New
+
+
+Kb_Ctrl_Old: MOV Kb_Search_Status,#KSS_Off
+ SETB KS_Status_Ready
+ LJMP Kb_Ctrl_Up
+
+Kb_Ctrl_New: PUSH Acc
+ MOV A,#ASCII_Space
+ MOV DPTR,#Kb_Str_Buffer
+ LCALL Clear_Str
+ MOV Kb_Cursor,#00
+ MOV Kb_Search_Status,#KSS_Off
+ SETB KS_Status_Ready
+ POP Acc
+
+Kb_Ctrl_UP: CJNE A,#ASCII_Up,Kb_Ctrl_DOWN
+ LCALL Kb_Search_Up
+ LJMP Kb_Ctrl_End
+
+Kb_Ctrl_DOWN: CJNE A,#ASCII_Down,Kb_Ctrl_RET
+ LCALL Kb_Search_Down
+ LJMP Kb_Ctrl_End
+
+Kb_Ctrl_RET: CLR KS_Active_Flg
+ CJNE A,#ASCII_CR,Kb_Ctrl_LEFT
+ SETB Kb_Str_Ready
+ LJMP Kb_Ctrl_End
+
+Kb_Ctrl_LEFT: CJNE A,#ASCII_Left,Kb_Ctrl_RIGHT
+ LCALL Exe_LEFT
+ LJMP Kb_Ctrl_End
+
+Kb_Ctrl_RIGHT: CJNE A,#ASCII_Right,Kb_Ctrl_DEL
+ LCALL Exe_RIGHT
+ LJMP Kb_Ctrl_End
+
+Kb_Ctrl_DEL: CJNE A,#ASCII_Del,Kb_Ctrl_BKSPC
+ LCALL Exe_DEL
+ LJMP Kb_Ctrl_End
+
+Kb_Ctrl_BKSPC: CJNE A,#ASCII_BkSpc,Kb_Ctrl_ESC
+ LCALL Exe_LEFT
+ LCALL Exe_DEL
+ LJMP Kb_Ctrl_End
+
+Kb_Ctrl_ESC: CJNE A,#ASCII_Esc,Kb_Ctrl_Alpha
+ MOV DPTR,#Kb_Str_Buffer
+ MOV A,#ASCII_Space
+ LCALL Clear_Str
+ MOV Kb_Cursor,#00
+ LJMP Kb_Ctrl_End
+
+Kb_Ctrl_Alpha: LCALL Exe_Set_Actual_Letter
+ MOV A,Kb_Char_Buffer
+ MOVX @DPTR,A
+ LCALL Exe_RIGHT
+
+Kb_Ctrl_End: SETB Kb_Dsp_Ready
+ POP DPH
+ POP DPL
+ POP PSW
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+
+Exe_Set_Actual_Letter: ; laedt in DPTR die externale Adresse
+ PUSH Acc ; des vom Kb_Cursor gezeigten Zeichens
+ PUSH PSW
+ MOV A,Kb_Cursor
+ MOV DPTR,#Kb_Str_Buffer
+ ADD A,DPL
+ MOV DPL,A
+ JNC ESAL_End
+ INC DPH
+ESAL_End: POP PSW
+ POP Acc
+ RET
+
+Exe_LEFT: PUSH AR1 ; dekr. Kb_Cursor
+ DEC Kb_Cursor
+ MOV R1,Kb_Cursor
+ CJNE R1,#0FFh,Exe_LEFT_End
+ MOV Kb_Cursor,#00
+Exe_LEFT_End: POP AR1
+ RET
+
+Exe_RIGHT: PUSH Acc ; inkr. Kb_Cursor
+ PUSH PSW
+ INC Kb_Cursor
+ CLR C
+ MOV A,#Kb_Max_Length-1
+ SUBB A,Kb_Cursor
+ JNC Exe_RIGHT_End
+ MOV Kb_Cursor,#Kb_Max_Length-1
+Exe_RIGHT_End: POP PSW
+ POP Acc
+ RET
+
+Exe_DEL: PUSH Acc ; loescht aktuelles Zeichen
+ LCALL Exe_Set_Actual_Letter
+ MOV A,#ASCII_Space
+ MOVX @DPTR,A
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Kb_Init_Search
+; Parameter : Kb_Str_Buffer
+; Kb_Cursor
+; Rueckgabeparameter : KS_Status_Ready
+; Kb_Search_Status
+; KS_Active_Flg
+; KS_Actual_Module
+; Kb_Search_DPL
+; Kb_Search_DPH
+; KS_Cursor
+;
+; Sucht, auf welchem Wort der Cursor sich befindet und zeigt das erste ent-
+; sprechende Element aus der Search-Menu-Tabelle (zB : wenn Cursor auf Message,
+; sucht die erste Message fuer das schon eingetragene Modul).
+
+
+Kb_Init_Search: PUSH Acc
+ PUSH B
+ PUSH PSW
+ PUSH DPL
+ PUSH DPH
+
+ LCALL Kb_Valid_Word
+ MOV A,KS_Actual_Word
+ CJNE A,#1,KIS_Msg ; Cursor auf 1. Wort -> Modul
+
+ MOV Kb_Search_DPL,#(Module_Table # 256)
+ MOV Kb_Search_DPH,#(Module_Table / 256)
+ LCALL Search_Next_Module
+ JC KIS_No_Choice ; springt wenn noch kein Modul in der Tabelle
+ MOV DPTR,#Kb_Str_Buffer ;
+ MOV A,#ASCII_Space ; loescht Kb_Str_Buffer
+ LCALL Clear_Str ;
+ MOV Kb_Cursor,#00 ;
+ MOV DPL,Kb_Search_DPL
+ MOV DPH,Kb_Search_DPH
+ INC DPTR
+ INC DPTR
+ MOV Kb_Search_Status,#KSS_Mod
+ SJMP KIS_Found
+
+KIS_Msg: CJNE A,#2,KIS_No_Choice
+ MOV Kb_Str_Pointer,#00 ; Cursor auf 2. Wort -> Message
+ LCALL Get_Token
+ LCALL Is_Token_Module
+ JNC KIS_Mod_Corr
+ MOV Kb_Search_Status,#KSS_Inc_Mod ; erstes Wort kein Korrektes Modul
+ SJMP KIS_End
+
+KIS_Mod_Corr: MOV Kb_Cursor,Kb_Str_Pointer
+ LCALL Exe_Right ; ein Leerzeichen nach dem 1. Wort lassen
+ MOV KS_Actual_Module,A ; Modulnummer abspeichern
+ MOV Kb_Search_DPL,#(Stat_Table # 256)
+ MOV Kb_Search_DPH,#(Stat_Table / 256)
+ LCALL Search_Next_Msg
+ JC KIS_No_Choice ; existiert Message fuer dieses Modul ?
+ MOV DPTR,#Kb_Str_Buffer ; Ja -> Mess. in Textbuffer kopieren
+ MOV A,#ASCII_Space
+ MOV B,Kb_Cursor
+ LCALL Clear_Pos_Str ; Kb_Str_Buffer ab der Cursorposition loeschen
+ MOV DPL,Kb_Search_DPL
+ MOV DPH,Kb_Search_DPH
+ INC DPTR
+ INC DPTR
+ INC DPTR
+ MOV Kb_Search_Status,#KSS_Msg
+ SJMP KIS_Found
+
+KIS_No_Choice: MOV Kb_Search_Status,#KSS_No_Choice ; Nein -> Fehlermeldung
+ SJMP KIS_End
+
+KIS_Found: MOV KS_Cursor,Kb_Cursor ; kopiert das gefundene Element
+ LCALL Copy_Pos_Buffer ; in Kb_Str_Buffer ab KS_Cursor
+ SETB KS_Active_Flg ;
+
+KIS_End: SETB KS_Status_Ready
+ POP DPH
+ POP DPL
+ POP PSW
+ POP B
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Kb_Valid_Word
+; Parameter : Kb_Str_Buffer
+; Kb_Cursor
+; Rueckgabeparameter : KS_Actual_Word
+;
+; Sucht auf welchem Wort der Cursor sich befindet
+
+
+Kb_Valid_Word: PUSH Acc
+ PUSH PSW
+ PUSH DPL
+ PUSH DPH
+
+ MOV DPTR,#Kb_Str_Buffer
+ MOV Kb_Str_Pointer,#00
+ MOV KS_Actual_Word,#00
+
+KVW_Loop: LCALL Get_Token
+ INC KS_Actual_Word
+ CLR C
+ MOV A,Kb_Str_Pointer
+ SUBB A,Kb_Cursor ; wenn Kb_Str_Pointer > Kb_Cursor
+ JC KVW_Loop ; hat man das richtige Wort gefunden
+
+ POP DPH
+ POP DPL
+ POP PSW
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Kb_Search_Up
+; Parameter : KS_Active_Flg
+; Kb_Search_DPL
+; Kb_Search_DPH
+; KS_Cursor
+; Rueckgabeparameter : KS_Active_Flg
+; Kb_Search_DPL
+; Kb_Search_DPH
+;
+; Legt fest, ob die Search-Routinen initialisiert werden muessen, ob das vorhergehende
+; Modul, oder Message, abgeholt werden muss.
+
+
+Kb_Search_Up: PUSH Acc
+ PUSH PSW
+ PUSH DPL
+ PUSH DPH
+
+ JB KS_Active_Flg,KSU_Choose ; Schon im Search-Modus ?
+ LCALL Kb_Init_Search ; Nein -> Initialisierung
+ SJMP KSU_End
+
+KSU_Choose: MOV A,KS_Actual_Word ; Ja -> auf welchem Wort liegt der Cursor ?
+ CJNE A,#1,KSU_Msg
+ LCALL Search_Prev_Module ; 1. Wort -> sucht Modul
+ JC KSU_Mod_Top ; gefunden ?
+ MOV Kb_Search_Status,#KSS_Mod ; Ja -> DPTR retten
+ MOV DPL,Kb_Search_DPL
+ MOV DPH,Kb_Search_DPH
+ INC DPTR
+ INC DPTR
+ SJMP KSU_Show
+
+KSU_Mod_Top: MOV Kb_Search_Status,#KSS_Mod_Top ; Nein -> Top of list
+ SJMP KSU_End
+
+KSU_Msg: LCALL Search_Prev_Msg ; 2. Wort -> sucht Message
+ JC KSU_Msg_Top ; gefunden ?
+ MOV Kb_Search_Status,#KSS_Msg ; Ja -> DPTR retten
+ MOV DPL,Kb_Search_DPL
+ MOV DPH,Kb_Search_DPH
+ INC DPTR
+ INC DPTR
+ INC DPTR
+ SJMP KSU_Show
+
+KSU_Msg_Top: MOV Kb_Search_Status,#KSS_Msg_Top ; Nein -> Top of list
+ SJMP KSU_End
+
+KSU_Show: MOV Kb_Cursor,KS_Cursor ; gefundenes Wort in Textbuffer
+ PUSH DPL ; kopieren
+ PUSH DPH
+ MOV DPTR,#Kb_Str_Buffer
+ MOV A,#ASCII_Space
+ MOV B,Kb_Cursor
+ LCALL Clear_Pos_Str
+ POP DPH
+ POP DPL
+ LCALL Copy_Pos_Buffer
+
+KSU_End: SETB KS_Status_Ready
+ POP DPH
+ POP DPL
+ POP PSW
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Kb_Search_Down
+; Parameter : KS_Active_Flg
+; Kb_Search_DPL
+; Kb_Search_DPH
+; KS_Cursor
+; Rueckgabeparameter : KS_Active_Flg
+; Kb_Search_DPL
+; Kb_Search_DPH
+;
+; Legt fest, ob die Search-Routinen initialisiert werden muessen, ob das naechste
+; Modul, oder Message, abgeholt werden muss.
+
+
+Kb_Search_Down: PUSH Acc
+ PUSH PSW
+ PUSH DPL
+ PUSH DPH
+
+ JB KS_Active_Flg,KSD_Choose ; schon im Search Modus ?
+ LCALL Kb_Init_Search ; Nein -> Initialisierung
+ SJMP KSD_End
+
+KSD_Choose: MOV A,KS_Actual_Word ; Ja -> welches Wort ?
+ CJNE A,#1,KSD_Msg
+ LCALL Search_Next_Module ; 1. Wort -> sucht naechstes Modul
+ JC KSD_Mod_Bot ; gefunden ?
+ MOV Kb_Search_Status,#KSS_Mod ; Ja -> DPTR retten
+ MOV DPL,Kb_Search_DPL
+ MOV DPH,Kb_Search_DPH
+ INC DPTR
+ INC DPTR
+ SJMP KSD_Show
+
+KSD_Mod_Bot: MOV Kb_Search_Status,#KSS_Mod_Bot ; Nein -> bottom of list
+ SJMP KSD_End
+
+KSD_Msg: LCALL Search_Next_Msg ; 2. Wort -> sucht naechste Message
+ JC KSD_Msg_Bot ; gefunden ?
+ MOV Kb_Search_Status,#KSS_Msg ; Ja -> DPTR retten
+ MOV DPL,Kb_Search_DPL
+ MOV DPH,Kb_Search_DPH
+ INC DPTR
+ INC DPTR
+ INC DPTR
+ SJMP KSD_Show
+
+KSD_Msg_Bot: MOV Kb_Search_Status,#KSS_Msg_Bot ; Nein -> bottom of list
+ SJMP KSD_End
+
+KSD_Show: MOV Kb_Cursor,KS_Cursor ; gefundenes Wort in Textbuffer
+ PUSH DPL ; kopieren
+ PUSH DPH
+ MOV DPTR,#Kb_Str_Buffer
+ MOV A,#ASCII_Space
+ MOV B,Kb_Cursor
+ LCALL Clear_Pos_Str
+ POP DPH
+ POP DPL
+ LCALL Copy_Pos_Buffer
+
+KSD_End: SETB KS_Status_Ready
+ POP DPH
+ POP DPL
+ POP PSW
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Search_Next_Module
+; Parameter : Kb_Search_DPL
+; Kb_Search_DPH
+; Rueckgabeparameter : C (gesetzt -> nicht gefunden)
+; Kb_Search_DPL
+; Kb_Search_DPH
+;
+; Sucht naechstes Modul ab aktueller Position in der Tabelle (durch KB_Search_DPL
+; (DPH) gespeichert)
+
+
+Search_Next_Module:
+ PUSH Acc
+ PUSH DPL
+ PUSH DPH
+
+ MOV DPL,Kb_Search_DPL ; aktuelle Pos. in DPTR laden
+ MOV DPH,Kb_Search_DPH
+ MOV A,#1
+ MOVC A,@A+DPTR
+ ADD A,DPL ; DPTR mit Offset addieren
+ MOV DPL,A
+ JNC SNMod_Cont
+ INC DPH
+SNMod_Cont: CLR C
+ CLR A
+ MOVC A,@A+DPTR
+ XRL A,#TableEnd
+ JZ SNMod_End ; Ende der Tabelle ?
+ MOV Kb_Search_DPL,DPL ; Nein -> DPTR retten
+ MOV Kb_Search_DPH,DPH
+ CPL C
+
+SNMod_End: CPL C ; Ja -> nicht gefunden
+ POP DPH
+ POP DPL
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Search_Prev_Module
+; Parameter : Kb_Search_DPL
+; Kb_Search_DPH
+; Rueckgabeparameter : C (gesetzt -> nicht gefunden)
+; Kb_Search_DPL
+; Kb_Search_DPH
+;
+; Sucht vorhergehendes Modul ab aktueller Position in der Tabelle (durch KB_Search_DPL
+; (DPH) gespeichert). Analog zu Search_Next_Module
+
+
+Search_Prev_Module:
+ PUSH Acc
+ PUSH AR1
+ PUSH DPL
+ PUSH DPH
+
+ MOV DPL,Kb_Search_DPL
+ MOV DPH,Kb_Search_DPH
+ DEC_DPTR
+ CLR A
+ MOVC A,@A+DPTR
+ INC DPTR
+ CLR C
+ MOV R1,A
+ MOV A,DPL
+ SUBB A,R1
+ MOV DPL,A
+ JNC SPMod_Cont
+ DEC DPH
+SPMod_Cont: CLR C
+ CLR A
+ MOVC A,@A+DPTR
+ XRL A,#TableAnf
+ JZ SPMod_End
+ MOV Kb_Search_DPL,DPL
+ MOV Kb_Search_DPH,DPH
+ CPL C
+
+SPMod_End: CPL C
+ POP DPH
+ POP DPL
+ POP AR1
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Search_Next_Msg
+; Parameter : Kb_Search_DPL
+; Kb_Search_DPH
+; KS_Actual_Module
+; Rueckgabeparameter : C (gesetzt -> nicht gefunden)
+; Kb_Search_DPL
+; Kb_Search_DPH
+;
+; Sucht naechste Message ab aktueller Position in der Tabelle (durch KB_Search_DPL
+; (DPH) gespeichert), die KS_Actual_Module entspricht
+
+
+Search_Next_Msg:
+ PUSH Acc
+ PUSH DPL
+ PUSH DPH
+
+ MOV DPL,Kb_Search_DPL ; aktuelle Pos. in DPTR laden
+ MOV DPH,Kb_Search_DPH
+
+SNMsg_Loop: MOV A,#1
+ MOVC A,@A+DPTR
+ ADD A,DPL ; DPTR und Offset addieren
+ MOV DPL,A
+ JNC SNMsg_Cont
+ INC DPH
+SNMsg_Cont: CLR C
+ CLR A
+ MOVC A,@A+DPTR
+ CJNE A,#TableEnd,SNMsg_Mod ; Ende der Tabelle ?
+ SETB C ; Ja -> nicht gefunden
+ SJMP SNMsg_End
+SNMsg_Mod: CJNE A,KS_Actual_Module,SNMsg_Loop ; Nein -> Modulnummer korrekt ?
+ ; Nein -> sucht weiter
+ MOV Kb_Search_DPL,DPL ; Ja -> DPTR retten
+ MOV Kb_Search_DPH,DPH
+ CLR C
+
+SNMsg_End: POP DPH
+ POP DPL
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Search_Prev_Msg
+; Parameter : Kb_Search_DPL
+; Kb_Search_DPH
+; KS_Actual_Module
+; Rueckgabeparameter : C (gesetzt -> nicht gefunden)
+; Kb_Search_DPL
+; Kb_Search_DPH
+;
+; Sucht vorhergehende Message ab aktueller Position in der Tabelle (durch KB_Search_DPL
+; (DPH) gespeichert), die KS_Actual_Module entspricht. Analog zu Search_Next_Msg
+
+
+Search_Prev_Msg:
+ PUSH Acc
+ PUSH DPL
+ PUSH DPH
+ PUSH AR1
+
+ MOV DPL,Kb_Search_DPL
+ MOV DPH,Kb_Search_DPH
+
+SPMsg_Loop: DEC_DPTR
+ CLR A
+ MOVC A,@A+DPTR
+ INC DPTR
+ CLR C
+ MOV R1,A
+ MOV A,DPL
+ SUBB A,R1
+ MOV DPL,A
+ JNC SPMsg_Cont
+ DEC DPH
+SPMsg_Cont: CLR C
+ CLR A
+ MOVC A,@A+DPTR
+ CJNE A,#TableAnf,SPMsg_Mod
+ SETB C
+ SJMP SPMsg_End
+SPMsg_Mod: CJNE A,KS_Actual_Module,SPMsg_Loop
+ MOV Kb_Search_DPL,DPL
+ MOV Kb_Search_DPH,DPH
+ CLR C
+
+SPMsg_End: POP AR1
+ POP DPH
+ POP DPL
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Text_Decoder
+; Parameter : Kb_Str_Buffer
+; Rueckgabeparameter : Msg_Registers
+; Text_Dec_Status
+; TD_Status_Ready
+; TD_Send_Ready
+; Stat_Module
+; Stat_Num_Param
+; Stat_Picture
+; Stat_Length
+; Stat_Code
+;
+; Interpretiert den im Kb_Str_Buffer liegenden Text und legt die entsprechenden
+; Werte in Msg_Registers und Stat_ Variablen ab. Wenn korrekter Text, setzt das
+; TD_Send_Ready-Flag (ready to send).
+
+
+Text_Decoder: PUSH AR0
+ PUSH AR1
+ PUSH AR2
+ PUSH Acc
+ PUSH PSW
+ PUSH DPL
+ PUSH DPH
+
+ LCALL Clr_Msg_Buffer
+ MOV Stat_Length,#02
+
+ CLR Kb_Str_Ready
+ MOV Kb_Str_Pointer,#00
+ LCALL Get_Token ; sucht 1. Wort
+ JNC TD_Module ; gefunden ?
+ MOV Text_Dec_Status,#5 ; Nein -> Fehler (fehlendes Modul)
+ LJMP TD_End
+
+TD_Module: LCALL Is_Token_Module ; Ja -> ist das Modul korrekt ?
+ JNC TD_Statement
+ MOV Text_Dec_Status,#6 ; Nein -> Fehler (inkorrektes Modul)
+ LJMP TD_End
+
+TD_Statement: MOV Stat_Module,A ; Ja -> Modulnummer abspeichern
+ LCALL Get_Token ; sucht 2. Wort
+ JNC TD_Stat_Cont ; gefunden ?
+ MOV Text_Dec_Status,#1 ; Nein -> Fehler (fehlende Message)
+ LJMP TD_End
+
+TD_Stat_Cont: MOV R0,#(Token_Str # 256) ; Ja -> sucht Message in der Tabelle
+ MOV R1,#(Token_Str / 256)
+ MOV DPTR,#Stat_Table
+
+TD_Stat_Loop: CLR A ;
+ MOVC A,@A+DPTR ;
+ CJNE A,#TableEnd,TD_Stat_Cont2
+ MOV Text_Dec_Status,#2 ; nur die Messages der Tabelle, die
+ LJMP TD_End ; das aktuelle Modul entsprechen, muessen
+ ; betrachtet werden
+TD_Stat_Cont2: XRL A,Stat_Module ;
+ JZ TD_Stat_Check ;
+
+TD_Stat_Next: MOV A,#01 ;
+ MOVC A,@A+DPTR ;
+ ADD A,DPL ; sucht naechste Message in der
+ MOV DPL,A ; Tabelle
+ JNC TD_Stat_Loop ;
+ INC DPH ;
+ SJMP TD_Stat_Loop ;
+
+TD_Stat_Check: INC DPTR
+ INC DPTR
+ CLR A
+ MOVC A,@A+DPTR
+ MOV Stat_Code,A
+ INC DPTR
+
+ LCALL Compare_Str ; Text und Message in der Tabelle
+ JNC TD_Parameters ; vergleichen
+ DEC_DPTR
+ DEC_DPTR
+ DEC_DPTR
+ SJMP TD_Stat_Next ; nicht gleich -> next one !
+
+TD_Parameters: LCALL Jump_Blank_Str ; gleich -> Parameter dekodieren
+ MOV R0,#Msg_Registers
+ MOV @R0,Stat_Module
+
+ INC R0
+ MOV @R0,Stat_Code
+
+ INC DPTR
+ CLR A
+ MOVC A,@A+DPTR
+ MOV Stat_Num_Param,A
+ MOV R1,A
+ JZ TD_Send
+
+ INC DPTR
+ CLR A
+ MOVC A,@A+DPTR
+ MOV Stat_Picture,A
+ INC R0
+
+TD_Par_Loop: LCALL Get_Token
+ JNC TD_Par_Symbol
+ MOV Text_Dec_Status,#3
+ LJMP TD_End
+
+TD_Par_Symbol: CLR C
+ LCALL Is_Token_Symbol
+ JC TD_Par_Digit
+ MOV ASCII_Low_Byte,A
+ MOV ASCII_High_Byte,#00
+ SJMP TD_Par_Load
+
+TD_Par_Digit: CLR C
+ LCALL ASCII_To_Bin
+ JNC TD_Par_Load
+ MOV Text_Dec_Status,#4
+ SJMP TD_End
+
+TD_Par_Load: MOV A,Stat_Picture
+ JB Acc.0,TD_Par_Single
+ MOV @R0,ASCII_High_Byte
+ MOV ASCII_High_Byte,#00
+ INC R0
+ INC Stat_Length
+
+TD_Par_Single: MOV R2,ASCII_High_Byte
+ CJNE R2,#00,TD_Par_Error
+ MOV @R0,ASCII_Low_Byte
+ INC R0
+ INC Stat_Length
+ RR A
+ MOV Stat_Picture,A
+ DJNZ R1,TD_Par_Loop
+
+TD_Send: MOV Text_Dec_Status,#0
+ SETB TD_Send_Ready
+ LCALL Get_Token
+ JC TD_End
+ MOV Text_Dec_Status,#7
+ SJMP TD_End
+
+TD_Par_Error: MOV Text_Dec_Status,#4
+
+TD_End: SETB TD_Status_Ready
+ SETB TD_Next_Flg
+ POP DPH
+ POP DPL
+ POP PSW
+ POP Acc
+ POP AR2
+ POP AR1
+ POP AR0
+ RET
+
+;--------------------------------------------------------------------------
+
+Get_Token: PUSH Acc
+ PUSH P2
+ PUSH DPL
+ PUSH DPH
+ PUSH AR0
+ PUSH AR1
+ PUSH AR2
+
+ MOV DPTR,#Token_Str
+ CLR A
+ LCALL Clear_Str
+ MOV DPTR,#Kb_Str_Buffer
+ MOV A,#Kb_Max_Length ;
+ CLR C ;
+ SUBB A,Kb_Str_Pointer ;
+ JNZ GT_Cont ; R2 = Anzahl der noch
+ SETB C ; zuverarbeitenden
+ SJMP GT_End ; Buchstaben
+ ;
+GT_Cont: MOV R2,A ;
+ MOV A,DPL
+ ADD A,Kb_Str_Pointer
+ MOV DPL,A
+ JNC GT_Blank_Loop
+ INC DPH
+
+GT_Blank_Loop: MOVX A,@DPTR
+ CJNE A,#ASCII_Space,GT_Text
+ INC DPTR
+ INC Kb_Str_Pointer
+ DJNZ R2,GT_Blank_Loop
+ SETB C
+ SJMP GT_End
+
+GT_Text: MOV R0,#(Token_Str # 256)
+ MOV R1,#(Token_Str / 256)
+
+GT_Text_Loop: MOVX A,@DPTR
+ CJNE A,#ASCII_Space,GT_Text_Add
+ CLR C
+ SJMP GT_End
+
+GT_Text_Add: LCALL UpCase
+ MOV P2,R1
+ MOVX @R0,A
+ INC Kb_Str_Pointer
+ INC_R0R1
+ INC DPTR
+ DJNZ R2,GT_Text_Loop
+ CLR C
+
+GT_End: POP AR2
+ POP AR1
+ POP AR0
+ POP DPH
+ POP DPL
+ POP P2
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+
+Compare_Str: IRP Source,Acc,P2,DPL,DPH,AR0,AR1,AR2,AR3
+ PUSH Source
+ ENDM
+
+ CLR C
+ MOV R2,#Kb_Max_Length
+
+ CLR A
+ MOVC A,@A+DPTR
+ CJNE A,#StringEnde,Comp_Loop
+ SJMP Comp_False
+
+Comp_Loop: MOV R3,A
+ MOV P2,R1
+ MOVX A,@R0
+ XRL A,R3
+ JNZ Comp_False
+ MOV A,R3
+ JZ Comp_End
+ INC DPTR
+ INC_R0R1
+ CLR A
+ MOVC A,@A+DPTR
+ DJNZ R2,Comp_Loop
+ CPL C
+
+Comp_False: CPL C
+
+Comp_End: IRP Target,AR3,AR2,AR1,AR0,DPH,DPL,P2,Acc
+ POP Target
+ ENDM
+ RET
+
+;--------------------------------------------------------------------------
+TeachIn_Sampler:
+ PUSH Acc
+ PUSH PSW
+ PUSH AR1
+ MOV TH0,#0FCh
+
+ MOV Temp_P4,P4
+ MOV Temp_P5,P5
+ MOV A,Temp_P4
+ XRL A,Save_P4
+ JNZ TI_Smp_Edge
+ MOV A,Temp_P5
+ XRL A,Save_P5
+ JZ TI_Smp_Inc
+
+TI_Smp_Edge: MOV TI_Sample_Counter,#00
+ MOV Save_P4,Temp_P4
+ MOV Save_P5,Temp_P5
+ SJMP TI_Smp_End
+
+TI_Smp_Inc: INC TI_Sample_Counter
+ MOV A,TI_Sample_Counter
+ CJNE A,#TI_Sample_Valid_Time,TI_Smp_End
+ MOV TI_Sample_Counter,#00
+ MOV A,Old_P4
+ XRL A,Save_P4
+ JNZ TI_Smp_Change
+ MOV A,Old_P5
+ XRL A,Save_P5
+ JZ TI_Smp_End
+
+TI_Smp_Change: SETB TI_Sample_Chg_Flg
+ JNB TID_Done_Flg,TISC_No_Init
+ CLR TID_Done_Flg
+ MOV TI_On_P4,#00
+ MOV TI_Off_P4,#00
+ MOV TI_On_P5,#00
+ MOV TI_Off_P5,#00
+
+TISC_No_Init: MOV A,Old_P4
+ XRL A,Save_P4
+ MOV R1,A ; R1 = Save_P4
+ MOV A,Save_P4
+ CPL A
+ ANL A,R1
+ ORL A,TI_On_P4
+ MOV TI_On_P4,A
+
+ MOV A,Save_P4
+ ANL A,R1
+ MOV TI_Off_P4,A
+ MOV A,Old_P5
+ XRL A,Save_P5
+ MOV R1,A
+ MOV A,Save_P5
+ CPL A
+ ANL A,R1
+ MOV TI_On_P5,A
+ MOV A,Save_P5
+ ANL A,R1
+ MOV TI_Off_P5,A
+
+ MOV Old_P4,Save_P4
+ MOV Old_P5,Save_P5
+
+TI_Smp_End: POP AR1
+ POP PSW
+ POP Acc
+ RETI
+
+;--------------------------------------------------------------------------
+
+TeachIn_Decoder:
+ PUSH Acc
+ PUSH DPL
+ PUSH DPH
+
+ CLR TI_Sample_Chg_Flg
+ MOV A,TI_On_P4
+ JZ TID_Table2
+ JB Sys_Robot_Mode,TID_T1_Rob
+ MOV DPTR,#KOn_P4_Frs
+ LCALL TID_Main
+ SJMP TID_Table2
+
+TID_T1_Rob: MOV DPTR,#KOn_P4_Rob
+ LCALL TID_Main
+
+TID_Table2: MOV A,TI_Off_P4
+ JZ TID_Table3
+ JB Sys_Robot_Mode,TID_T2_Rob
+ MOV DPTR,#KOff_P4_Frs
+ LCALL TID_Main
+ SJMP TID_Table3
+
+TID_T2_Rob: MOV DPTR,#KOff_P4_Rob
+ LCALL TID_Main
+
+TID_Table3: MOV A,TI_On_P5
+ JZ TID_Table4
+ JB Sys_Robot_Mode,TID_T3_Rob
+ MOV DPTR,#KOn_P5_Frs
+ LCALL TID_Main
+ SJMP TID_Table4
+
+TID_T3_Rob: MOV DPTR,#KOn_P5_Rob
+ LCALL TID_Main
+
+TID_Table4: MOV A,TI_Off_P5
+ JZ TID_End
+ JB Sys_Robot_Mode,TID_T4_Rob
+ MOV DPTR,#KOff_P5_Frs
+ LCALL TID_Main
+ SJMP TID_End
+
+TID_T4_Rob: MOV DPTR,#KOff_P5_Rob
+ LCALL TID_Main
+
+TID_End: SETB TID_Done_Flg
+
+ POP DPH
+ POP DPL
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+
+TID_Main: PUSH Acc
+ PUSH PSW
+ PUSH DPL
+ PUSH DPH
+ PUSH AR0
+ PUSH AR1
+
+ MOV R1,#8
+TID_Main_Loop: CLR C
+ RRC A
+ JNC TID_Main_Next
+
+ PUSH Acc
+ MOV A,#1
+ MOVC A,@A+DPTR
+ MOV R0,A
+ POP Acc
+ CJNE R0,#StringEnde,TID_Main_Msg
+ SJMP TID_Main_Next
+
+TID_Main_Msg: PUSH DPL
+ PUSH DPH
+ PUSH Acc
+ MOV DPTR,#Kb_Str_Buffer
+ MOV A,#ASCII_Space
+ LCALL Clear_Str
+ POP Acc
+ POP DPH
+ POP DPL
+
+ INC DPTR
+ MOV Kb_Cursor,#00
+ LCALL Copy_Pos_Buffer
+ SETB Kb_Str_Ready
+ SETB Kb_Dsp_Ready
+ CLR KS_Active_Flg
+ DEC_DPTR
+ LCALL Main_Manager
+
+TID_Main_Next: PUSH Acc
+ CLR A
+ MOVC A,@A+DPTR
+ ADD A,DPL
+ MOV DPL,A
+ JNC TIDM_Next_Cont
+ INC DPH
+
+TIDM_Next_Cont: POP Acc
+ DJNZ R1,TID_Main_Loop
+
+ POP AR1
+ POP AR0
+ POP DPH
+ POP DPL
+ POP PSW
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+
+Send_Manager: PUSH Acc
+ PUSH B
+ PUSH DPL
+ PUSH DPH
+ PUSH AR0
+ PUSH PSW
+
+ CLR TD_Send_Ready
+
+Send_Mng_Load: MOV R0,#Msg_Registers
+ MOV R0_Bk1,@R0
+ MOV A,@R0 ; logische Adresse
+ INC R0
+ MOV R1_Bk1,@R0
+ INC R0
+ MOV R2_Bk1,@R0
+ INC R0
+ MOV R3_Bk1,@R0
+ INC R0
+ MOV R4_Bk1,@R0
+ INC R0
+ MOV R5_Bk1,@R0
+ INC R0
+ MOV R6_Bk1,@R0
+ INC R0
+ MOV R7_Bk1,@R0
+
+ MOV DPTR,#Adr_Table
+ MOVC A,@A+DPTR
+ MOV B,Stat_Length
+ SETB RS0
+ CLR RS1
+
+ Post_Message
+
+ POP PSW
+ POP AR0
+ POP DPH
+ POP DPL
+ POP B
+ POP Acc
+ RET
+;--------------------------------------------------------------------------
+
+Receive_Sampler:
+ lcall MESSAGE_INTERRUPT
+; SETB Receive_Ready
+ RET
+
+
+Receive_Manager:
+ PUSH Acc
+ PUSH B
+ PUSH PSW
+
+ CLR Receive_Ready
+ SETB RS0
+ CLR RS1
+
+ Take_Message
+ CLR RS0
+ MOV Rcv_Msg_Length,A
+ MOV DPTR,#Net_Rcv_Str
+ MOV A,#ASCII_Space
+ LCALL Clear_Str
+
+ MOV A,R1_Bk1
+ LCALL Bin_To_ASCII
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,B
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,#ASCII_Space
+ MOVX @DPTR,A
+ INC DPTR
+
+ MOV A,R2_Bk1
+ LCALL Bin_To_ASCII
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,B
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,#ASCII_Space
+ MOVX @DPTR,A
+ INC DPTR
+
+ MOV A,R3_Bk1
+ LCALL Bin_To_ASCII
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,B
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,#ASCII_Space
+ MOVX @DPTR,A
+ INC DPTR
+
+ MOV A,R4_Bk1
+ LCALL Bin_To_ASCII
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,B
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,#ASCII_Space
+ MOVX @DPTR,A
+ INC DPTR
+
+ MOV A,R5_Bk1
+ LCALL Bin_To_ASCII
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,B
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,#ASCII_Space
+ MOVX @DPTR,A
+ INC DPTR
+
+ MOV A,R6_Bk1
+ LCALL Bin_To_ASCII
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,B
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,#ASCII_Space
+ MOVX @DPTR,A
+ INC DPTR
+
+ MOV A,R7_Bk1
+ LCALL Bin_To_ASCII
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,B
+ MOVX @DPTR,A
+ INC DPTR
+ MOV A,#ASCII_Space
+ MOVX @DPTR,A
+
+ MOV DPTR,#Net_Rcv_Str
+ SETB Ext_Dsp_Ready
+
+ POP PSW
+ POP B
+ POP Acc
+ RET
+
+;=============================== Tools ====================================
+
+Is_Token_Symbol:
+ PUSH AR0
+ PUSH AR1
+ PUSH AR2
+ PUSH AR3
+ PUSH DPL
+ PUSH DPH
+
+ CLR C
+ MOV DPTR,#Symbol_Table
+ MOV R0,#(Token_Str # 256)
+ MOV R1,#(Token_Str / 256)
+
+Is_Symb_Loop: CLR A
+ MOVC A,@A+DPTR
+ MOV R3,A ; Symbolwert
+ XRL A,#TableEnd
+ JZ Is_Symb_Not_Found
+
+ INC DPTR
+ CLR A
+ MOVC A,@A+DPTR
+ MOV R2,A ; Offset
+
+ INC DPTR
+ LCALL Compare_Str
+ JNC Is_Symb_Found
+
+ DEC_DPTR
+ DEC_DPTR
+ MOV A,DPL
+ ADD A,R2
+ MOV DPL,A
+ JNC Is_Symb_Loop
+ INC DPH
+ SJMP Is_Symb_Loop
+
+Is_Symb_Found: MOV A,R3
+ CLR C
+ SJMP Is_Symb_End
+
+Is_Symb_Not_Found:
+ SETB C
+
+Is_Symb_End: POP DPH
+ POP DPL
+ POP AR3
+ POP AR2
+ POP AR1
+ POP AR0
+ RET
+
+;--------------------------------------------------------------------------
+
+Is_Token_Module:
+ PUSH AR0
+ PUSH AR1
+ PUSH AR2
+ PUSH AR3
+ PUSH DPL
+ PUSH DPH
+
+ CLR C
+ MOV DPTR,#Module_Table
+ MOV R0,#(Token_Str # 256)
+ MOV R1,#(Token_Str / 256)
+
+Is_Mod_Loop: CLR A
+ MOVC A,@A+DPTR
+ MOV R3,A ; Modulname
+ XRL A,#TableEnd
+ JZ Is_Mod_Not_Found
+
+ INC DPTR
+ CLR A
+ MOVC A,@A+DPTR
+ MOV R2,A ; Offset
+
+ INC DPTR
+ LCALL Compare_Str
+ JNC Is_Mod_Found
+
+ DEC_DPTR
+ DEC_DPTR
+ MOV A,DPL
+ ADD A,R2
+ MOV DPL,A
+ JNC Is_Mod_Loop
+ INC DPH
+ SJMP Is_Mod_Loop
+
+Is_Mod_Found: MOV A,R3
+ CLR C
+ SJMP Is_Mod_End
+
+Is_Mod_Not_Found:
+ SETB C
+
+Is_Mod_End: POP DPH
+ POP DPL
+ POP AR3
+ POP AR2
+ POP AR1
+ POP AR0
+ RET
+
+;--------------------------------------------------------------------------
+
+Bin_To_ASCII: PUSH AR0
+ PUSH DPL
+ PUSH DPH
+
+ MOV DPTR,#BTA_Table
+ MOV B,#16
+ DIV AB
+ MOVC A,@A+DPTR
+ MOV R0,A
+ MOV A,B
+ MOVC A,@A+DPTR
+ MOV B,A
+ MOV A,R0
+
+ POP DPH
+ POP DPL
+ POP AR0
+ RET
+
+BTA_Table: DB "0123456789ABCDEF"
+
+;--------------------------------------------------------------------------
+
+ASCII_To_Bin: IRP Source,Acc,P2,DPL,DPH,AR0,AR1,AR2,AR3
+ PUSH Source
+ ENDM
+
+ MOV R0,#(Token_Str # 256)
+ MOV R1,#(Token_Str / 256)
+ MOV DPTR,#ATB_Table
+ MOV ASCII_Low_Byte,#00
+ MOV ASCII_High_Byte,#00
+ MOV R2,#00
+
+ATB_Search: INC_R0R1
+ INC R2
+ MOV P2,R1
+ MOVX A,@R0
+ JNZ ATB_Search
+
+ DEC_R0R1
+
+ATB_Loop: CLR C
+ MOV P2,R1
+ MOVX A,@R0
+ LCALL Is_Digit
+ JC ATB_Not_Digit
+ MOV R3,A
+ JZ ATB_Next
+
+ATB_Add_Loop: CLR A
+ MOVC A,@A+DPTR
+ CJNE A,#0FFh,ATB_Add_Cont
+ SJMP ATB_False
+ATB_Add_Cont: ADD A,ASCII_Low_Byte
+ MOV ASCII_Low_Byte,A
+ MOV A,#01
+ MOVC A,@A+DPTR
+ ADDC A,ASCII_High_Byte
+ JC ATB_End
+ MOV ASCII_High_Byte,A
+ DJNZ R3,ATB_Add_Loop
+
+ATB_Next: INC DPTR
+ INC DPTR
+ DEC_R0R1
+ DJNZ R2,ATB_Loop
+
+ CLR C ;
+ MOV A,ASCII_High_Byte ; Overflow (+) ?
+ MOV C,Acc.7 ;
+ SJMP ATB_End ;
+
+ATB_Not_Digit: CJNE A,#45,ATB_False
+ CJNE R2,#1,ATB_False
+ CLR C
+ CLR A
+ SUBB A,ASCII_Low_Byte
+ MOV ASCII_Low_Byte,A
+ CLR A
+ SUBB A,ASCII_High_Byte
+ MOV ASCII_High_Byte,A
+
+ CLR C ;
+ MOV A,ASCII_High_Byte ;
+ MOV C,Acc.7 ; Overflow (-) ?
+ CPL C ;
+ SJMP ATB_End ;
+
+ATB_False: SETB C
+
+ATB_End: IRP Target,AR3,AR2,AR1,AR0,DPH,DPL,P2,Acc
+ POP Target
+ ENDM
+ RET
+
+ATB_Table: DB 001h,000h
+ DB 00Ah,000h
+ DB 064h,000h
+ DB 0E8h,003h
+ DB 010h,027h
+ DB 0FFh
+
+;--------------------------------------------------------------------------
+
+Jump_Blank_Str:
+ PUSH Acc
+
+JB_Loop: MOV A,#00
+ MOVC A,@A+DPTR
+ JZ JB_End
+ INC DPTR
+ SJMP JB_Loop
+
+JB_End: POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+;Routine : Clear_Str
+;Parameter: A (Loeschzeichen)
+; DPTR (zu loeschender String)
+
+Clear_Str: PUSH DPL
+ PUSH DPH
+ PUSH AR1
+ MOV R1,#Kb_Max_Length
+Clear_Str_Loop: MOVX @DPTR,A
+ INC DPTR
+ DJNZ R1,Clear_Str_Loop
+ POP AR1
+ POP DPH
+ POP DPL
+ RET
+
+;--------------------------------------------------------------------------
+;Routine : Clear_Pos_Str (loescht einen String von Startposition bis Ende)
+;Parameter: DPTR (zu loeschender String)
+; A (Loeschzeichen)
+; B (Startposition)
+
+
+Clear_Pos_Str: PUSH Acc
+ PUSH PSW
+ PUSH DPL
+ PUSH DPH
+ PUSH AR1
+
+ MOV R1,B
+ CJNE R1,#Kb_Max_Length,CPS_Cont
+ SJMP CPS_End
+CPS_Cont: PUSH Acc
+ MOV A,B
+ ADD A,DPL
+ MOV DPL,A
+ JNC CPS_Cont2
+ INC DPH
+
+CPS_Cont2: CLR C
+ MOV A,#Kb_Max_Length
+ SUBB A,B
+ MOV R1,A
+ POP Acc
+ JC CPS_End
+CPS_Loop: MOVX @DPTR,A
+ INC DPTR
+ DJNZ R1,CPS_Loop
+
+CPS_End: POP AR1
+ POP DPH
+ POP DPL
+ POP PSW
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+; Routine : Copy_Pos_Buffer (kopiert einen String in Kb_Str_Buffer
+; ab Kb_Cursor; dieser zeigt dann nach
+; dem letzten Zeichen des Strings)
+; Parameter: DPTR (zu kopierender String)
+
+
+Copy_Pos_Buffer:
+ PUSH Acc
+ PUSH PSW
+ PUSH P2
+ PUSH DPL
+ PUSH DPH
+ PUSH AR0
+ PUSH AR1
+
+ MOV R0,#(Kb_Str_Buffer # 256)
+ MOV R1,#(Kb_Str_Buffer / 256)
+ MOV A,R0
+ ADD A,Kb_Cursor
+ MOV R0,A
+ JNC CPB_Loop
+ INC R1
+
+CPB_Loop: MOV A,Kb_Cursor
+ CJNE A,#Kb_Max_Length,CPB_Loop_Cont
+ DEC Kb_Cursor
+ SJMP CPB_End
+
+CPB_Loop_Cont: CLR A
+ MOVC A,@A+DPTR
+ JZ CPB_End
+ MOV P2,R1
+ MOVX @R0,A
+ INC DPTR
+ INC Kb_Cursor
+ INC_R0R1
+ SJMP CPB_Loop
+
+CPB_End: POP AR1
+ POP AR0
+ POP DPH
+ POP DPL
+ POP P2
+ POP PSW
+ POP Acc
+ RET
+
+;--------------------------------------------------------------------------
+
+UpCase: PUSH PSW
+ PUSH AR0
+
+ MOV R0,A
+ CLR C
+ SUBB A,#97
+ JC UpCase_Rest
+ MOV A,#122
+ SUBB A,R0
+ JC UpCase_Rest
+ MOV A,R0
+ SUBB A,#32
+ SJMP UpCase_End
+UpCase_Rest: MOV A,R0
+
+UpCase_End: POP AR0
+ POP PSW
+ RET
+
+;--------------------------------------------------------------------------
+
+Is_Digit: PUSH AR0
+
+ CLR C
+ MOV R0,A
+ SUBB A,#48
+ JC Is_Digit_Rest
+ MOV A,#57
+ SUBB A,R0
+ JC Is_Digit_Rest
+ MOV A,R0
+ SUBB A,#48
+ SJMP Is_Digit_End
+
+Is_Digit_Rest: MOV A,R0
+
+Is_Digit_End: POP AR0
+ RET
+
+;--------------------------------------------------------------------------
+
+Wait_2s: PUSH AR0
+ PUSH AR1
+ PUSH AR2
+
+ MOV R2,#12
+Wait_Loop2: MOV R1,#250
+Wait_Loop1: MOV R0,#250
+Wait_Loop0: DJNZ R0,Wait_Loop0
+ DJNZ R1,Wait_Loop1
+ DJNZ R2,Wait_Loop2
+
+ POP AR2
+ POP AR1
+ POP AR0
+ RET
+
+;--------------------------------------------------------------------------
+
+Clr_Msg_Buffer: PUSH AR0
+ PUSH AR1
+
+ MOV R1,#8
+ MOV R0,#Msg_Registers
+Clr_Msg_Loop: MOV @R0,#00
+ INC R0
+ DJNZ R1,Clr_Msg_Loop
+
+ POP AR1
+ POP AR0
+ RET
+
+;------------------------------------------------------------------------------
+
+;Stackarea in idata nach oben nur durch Prozessorram begrenzt!!
+;Dieses Segment muá IMMER als letztes stehen!!!
+
+ segment idata
+
+Stack: db ? ;ab hier liegt der Stack
+
+;------------------------------------------------------------------------------
+
+ end
diff --git a/tests/t_mic51/t_mic51.doc b/tests/t_mic51/t_mic51.doc
new file mode 100644
index 0000000..94ba34e
--- /dev/null
+++ b/tests/t_mic51/t_mic51.doc
@@ -0,0 +1,6 @@
++---------------------- Test Application MIC51 ----------------------------+
+| |
+| This is a student's program from RWTH Aachen's microprocessor course. It |
+| tests the MCS51 (not 251!) codegenerator and makes heavy use of macros. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_mic51/t_mic51.inc b/tests/t_mic51/t_mic51.inc
new file mode 100644
index 0000000..27d4051
--- /dev/null
+++ b/tests/t_mic51/t_mic51.inc
@@ -0,0 +1,165 @@
+; t_mic51.asm-Includefile für Assembler-Programm
+ROB equ 10H
+UC_ROB equ 1H
+FRS equ 11H
+UC_FRS equ 2H
+TEACHROB equ 12H
+UC_TEACH_ROB equ 3H
+TEACHFRS equ 13H
+UC_TEACH_FRS equ 4H
+TEACHKEY equ 14H
+UC_TEACH_KEY equ 5H
+MEMROB equ 15H
+UC_TEACH_ROB equ 3H
+MEMFRS equ 16H
+UC_TEACH_FRS equ 4H
+PC_SIO equ 17H
+UC_PC_SIO equ 0EH
+ON equ 1H
+OFF equ 0H
+PLUS equ 1H
+MINUS equ 0H
+FAST equ 1H
+SLOW equ 0H
+SUPERSLOW equ 2H
+QUEUE_WARNING equ 81H
+QUEUE_FULL equ 61H
+UNDEF_PAR equ 62H
+UNDEF_PIECE_REF equ 63H
+UNDEF_DRILL_REF equ 64H
+UNDEF_KOORD_REF equ 65H
+INTERNAL_ERROR equ 66H
+END_X_PLUS equ 67H
+END_Y_PLUS equ 68H
+END_Z_PLUS equ 69H
+END_V_PLUS equ 6AH
+END_X_MINUS equ 70H
+END_Y_MINUS equ 71H
+END_Z_MINUS equ 72H
+END_V_MINUS equ 73H
+HARD_END_X_PLUS equ 74H
+HARD_END_Y_PLUS equ 75H
+HARD_END_Z_PLUS equ 76H
+HARD_END_V_PLUS equ 77H
+HARD_END_X_MINUS equ 78H
+HARD_END_Y_MINUS equ 79H
+HARD_END_Z_MINUS equ 7AH
+HARD_END_V_MINUS equ 7BH
+MOVEAB equ 1H
+MOVEAS equ 2H
+MOVEAE equ 3H
+MOVEARW equ 4H
+MOVEALW equ 5H
+MOVEAH equ 6H
+MOVEAPOS1 equ 7H
+MOVEAPOS2 equ 8H
+MOVERB equ 9H
+MOVERS equ 0AH
+MOVERE equ 0BH
+MOVERRW equ 0CH
+MOVERLW equ 0DH
+MOVERH equ 0EH
+MOVERPOS1 equ 0FH
+MOVERPOS2 equ 10H
+MOVECBL equ 11H
+MOVECBR equ 12H
+STOPCB equ 13H
+MOVECSU equ 14H
+MOVECSD equ 15H
+STOPCS equ 16H
+MOVECEU equ 17H
+MOVECED equ 18H
+STOPCE equ 19H
+MOVECHU equ 1AH
+MOVECHD equ 1BH
+STOPCHP equ 1CH
+MOVECHL equ 1DH
+MOVECHR equ 1EH
+STOPCHT equ 1FH
+MOVECHO equ 20H
+MOVECHC equ 21H
+STOPCH equ 22H
+ROBVELOCITY equ 23H
+ROBGOHOME equ 24H
+SETHOME equ 25H
+GIBPOS1 equ 26H
+GIBPOS2 equ 27H
+ROBGIBREADY equ 28H
+ROBINIT equ 29H
+ROBDEINIT equ 2AH
+INIT equ 1H
+DEINIT equ 2H
+MOVECX equ 3H
+MOVECY equ 4H
+MOVECZ equ 5H
+MOVECV equ 6H
+STOPCX equ 7H
+STOPCY equ 8H
+STOPCZ equ 9H
+STOPCV equ 0AH
+FRSVELOCITY equ 0BH
+FRSVELOCITYDRAW equ 0CH
+FRSGOHOME equ 0DH
+REFFAHRT equ 0EH
+SETDRILLREF equ 0FH
+SETPIECEREF equ 10H
+MOVEX equ 11H
+MOVEY equ 12H
+MOVEZ equ 13H
+MOVEAPOS equ 14H
+MOVERX equ 15H
+MOVERY equ 16H
+MOVERZ equ 17H
+MOVERV equ 18H
+MOVERPOS equ 19H
+MOVEVOPEN equ 1AH
+MOVEVCLOSE equ 1BH
+MOVEV equ 1CH
+GOPIECEREFPOS equ 1DH
+MOVEPR equ 1EH
+DRILL equ 1FH
+SETMASTERADRESS equ 20H
+GIBFRSPOS1 equ 21H
+GIBFRSPOS2 equ 22H
+GIBPOSP equ 23H
+GIBSTATUS equ 24H
+GIBREADY equ 25H
+LOADROB equ 1H
+SAVEROB equ 2H
+STARTROBRUN equ 3H
+STOREROBPOS equ 4H
+STOREROBSYNC equ 5H
+STOREROBREADY equ 6H
+INITROBTEACH equ 7H
+DEINITROBTEACH equ 8H
+CLEARROBTEACH equ 9H
+RESETROBTEACH equ 0AH
+GETROBSYNC equ 0BH
+GETROBREADY equ 0CH
+ROBPOS1 equ 0DH
+ROBPOS2 equ 0EH
+DEBUGROB equ 0FH
+LOADFRS equ 1H
+SAVEFRS equ 2H
+STARTFRSRUN equ 3H
+STOREFRSPOS equ 4H
+STOREFRSSYNC equ 5H
+STOREFRSREADY equ 6H
+STOREFRSPIECEREF equ 7H
+STOREFRSTIEFE equ 8H
+STOREFRSDRILL equ 9H
+INITFRSTEACH equ 0AH
+DEINITFRSTEACH equ 0BH
+CLEARFRSTEACH equ 0CH
+RESETFRSTEACH equ 0DH
+GETFRSSYNC equ 0EH
+GETFRSREADY equ 0FH
+FRSPOS1 equ 10H
+FRSPOS2 equ 11H
+FRSPIECEREF equ 12H
+FRSTIEFE equ 13H
+GETFRSERROR equ 14H
+GETFRSWARNING equ 15H
+DEBUGFRS equ 16H
+BUG equ 1H
+; Ende Includefile für Assembler-Programm
diff --git a/tests/t_mic51/t_mic51.ori b/tests/t_mic51/t_mic51.ori
new file mode 100755
index 0000000..e9ce88f
--- /dev/null
+++ b/tests/t_mic51/t_mic51.ori
Binary files differ
diff --git a/tests/t_mic51/t_mod1.asm b/tests/t_mic51/t_mod1.asm
new file mode 100644
index 0000000..fb91ac8
--- /dev/null
+++ b/tests/t_mic51/t_mod1.asm
@@ -0,0 +1,487 @@
+
+; Aufgabe Nr.: Teach- In Einheit fuer uP- Praktikum II
+; --- Link- Modul ---
+; Autor: Joerg Vollandt
+; erstellt am : 13.06.1994
+; letzte Aenderung am : 02.08.1994
+; Bemerkung :
+;
+; Dateiname : t_mod1.asm
+;
+;=====================================================================
+ SEGMENT CODE
+ USING 0
+
+ INCLUDE MAKRO1.ASM
+ INCLUDE TAST1.ASM
+ INCLUDE MEM1.ASM
+ INCLUDE TEACH1.ASM
+ INCLUDE RUN1.ASM
+ INCLUDE DEBUG.ASM
+;=====================================================================
+; Definitionen der Funktionen der Teach- In Einheit
+
+Adr_InitRobTeach EQU INIT_TEACH ; Initialisieren der Teach- In Einheit
+Adr_InitFrsTeach EQU INIT_TEACH ; Initialisieren der Teach- In Einheit
+Adr_DeinitRobTeach EQU DEINIT_TEACH ; Deinitialisieren der Teach- In Einheit
+Adr_DeinitFrsTeach EQU DEINIT_TEACH ; Deinitialisieren der Teach- In Einheit
+Adr_ClearRobTeach EQU CLEAR_TEACH ; Speicher loeschen
+Adr_ClearFrsTeach EQU CLEAR_TEACH ; Speicher loeschen
+Adr_ResetRobTeach EQU RESET_TEACH ; Speicher zum lesen zuruecksetzen
+Adr_ResetFrsTeach EQU RESET_TEACH ; Speicher zum lesen zuruecksetzen
+Adr_StoreRobPos EQU STORE_ROB ; Position Roboter speichern
+Adr_StoreFrsPos EQU STORE_FRAES ; Position Fraese speichern
+Adr_StoreRobSync EQU STORE_SYNC ; Synchronisation speichern
+Adr_StoreFrsSync EQU STORE_SYNC ; Synchronisation speichern
+Adr_StoreRobReady EQU STORE_READY ; Warten auf Geraet speichern
+Adr_StoreFrsReady EQU STORE_READY ; Warten auf Geraet speichern
+Adr_StoreFrsPieceRef EQU STORE_PIECE_REF ; Werkstueck Nullpkt. festlegen
+Adr_StoreFrsTiefe EQU STORE_TIEFE ; Fraestiefe festlegen
+Adr_StoreFrsDrill EQU STORE_DRILL ; Fraesdatei bearbeiten
+Adr_GetRobSync EQU GET_SYNC_MSG ; Synchronisation empfangen
+Adr_GetFrsSync EQU GET_SYNC_MSG ; Synchronisation empfangen
+Adr_GetRobReady EQU GET_READY_MSG ; Ready empfangen
+Adr_GetFrsReady EQU GET_READY_MSG ; Ready empfangen
+Adr_LoadRob EQU LOAD_ROB ; Roboter Teach- In Datei von PC laden
+Adr_LoadFrs EQU LOAD_FRAES ; Fraese- Teach- In Datei von PC laden
+Adr_SaveRob EQU SAVE_ROB ; Roboter Teach- In Datei auf PC speichern
+Adr_SaveFrs EQU SAVE_FRAES ; Fraese- Teach- In Datei auf PC speichern
+
+Adr_RobPos1 EQU FIRST_FROM_ROB ; Position von Roboter 1. Teil
+Adr_RobPos2 EQU SECOND_FROM_ROB ; Position von Roboter 2. Teil
+Adr_FrsPos1 EQU FIRST_FROM_FRS ; Position von Fraese 1. Teil
+Adr_FrsPos2 EQU SECOND_FROM_FRS ; Position von Fraese 2. Teil
+Adr_FrsPieceRef EQU PIECE_REF_FROM_FRS ; Position von Fraese
+Adr_FrsTiefe EQU TIEFE_FROM_FRS ; Position von Fraese
+
+Adr_DebugRob EQU DEBUG_MEM ; Position von Roboter 2. Teil
+Adr_DebugFrs EQU DEBUG_MEM ; Position von Roboter 2. Teil
+Adr_StartRobRun EQU START_RUNNING ; Runmanager starten
+Adr_StartFrsRun EQU START_RUNNING ; Runmanager starten
+
+Adr_GetFrsError EQU Get_Error_from_frs ;
+Adr_GetFrsWarning EQU Get_Warning_from_frs ;
+
+
+MemRob_MsgCall_Tab:
+ include defMsg.inc
+MemRob_MsgCall_Tend:
+
+MemFrs_MsgCall_Tab:
+ include defMsg.inc
+MemFrs_MsgCall_Tend:
+
+;------------------------------------------------------------------------------
+; Speicherdefinitionen
+
+
+ SEGMENT BITDATA
+
+MSG DB ?
+Sp_MSG DB ?
+READY DB ?
+CRC DB ?
+
+TESTBIT DB ?
+RUNNINGBIT DB ?
+Sync_Waiting DB ?
+Ready_Waiting DB ?
+Drilling DB ?
+Drill_down DB ?
+PAUSE DB ?
+FrsWarning DB ?
+SingleStep DB ?
+Break DB ?
+
+Ref_Flag DB ?
+Tiefe_Flag DB ?
+
+ SEGMENT DATA
+
+Sp_MSG_Buffer DB ?
+T_Sync_Counter DB ?
+R_Sync_Counter DB ?
+Queue_Counter DB ?
+
+Frs_Ref_x DW ?
+Frs_Ref_y DW ?
+Frs_Ref_z DW ?
+Frs_Ref_Tiefe DW ?
+
+;---------------------------------------------------------------------
+ SEGMENT CODE
+;---------------------------------------------------------------------
+; Funktion : CALL_BACK- Fkt. wird nach Empfang einer Message
+; aufgerufen.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+MESSAGE_BIT BIT ACC.0 ; Message Bits
+SPECIAL_MESSAGE_BIT BIT ACC.2
+START_BIT BIT ACC.0 ; Special- Message Bits
+STOP_BIT BIT ACC.1
+RESET_BIT BIT ACC.3
+PAUSE_BIT BIT ACC.2
+AUX1_BIT BIT ACC.4
+AUX2_BIT BIT ACC.5
+
+MESSAGE_INTERRUPT:
+ PUSH ACC
+ LCALL READ_STATUS
+ JNB SPECIAL_MESSAGE_BIT,MESSAGE_INTERRUPT1
+ LCALL READ_SPECIAL_MESSAGE ; Special_Message lesen
+ MOV Sp_MSG_Buffer,A ; und retten
+ SETB Sp_MSG
+ POP ACC
+ RET
+
+MESSAGE_INTERRUPT1:
+ JNB MESSAGE_BIT,MESSAGE_INTERRUPT2
+ SETB MSG ; Normale Msg.empfangen
+MESSAGE_INTERRUPT2:
+ POP ACC
+ RET
+
+
+;---------------------------------------------------------------------
+; Funktion : Message- Scheduler fuer Speichermodul.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+; ****************************************************************************
+; R0 Empf„nger (logische Adresse)
+; R1 Message
+; R2 - R7 Parameter
+; ****************************************************************************
+
+Message_Handler MACRO Modul
+
+ push PSW
+ push ACC
+ push DPH
+ push DPL
+
+ mov DPTR,#Msg_Hndl_Ret ; Ruecksprungadresse vom indirekten
+ push DPL ; Jump ergibt indirekten Call
+ push DPH
+ mov DPTR,#Modul_MsgCall_Tab
+ mov A,AR1
+ clr C
+ rlc A
+ mov AR1,A
+ jnc No_inc
+ inc DPH
+No_inc: movc A,@A+DPTR
+ push ACC
+ inc DPTR
+ mov A,AR1
+ movc A,@A+DPTR
+ push ACC
+ ret ; indireckter Sprung
+
+Msg_Hndl_Ret:
+ pop DPL
+ pop DPH
+Msg_Ha_Exit:
+ pop ACC
+ pop PSW
+
+ ENDM
+
+;---------------------------------------------------------------------
+; Funktion : Message- Scheduler fuer PC- Messages.
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+MEM_SCHEDULER:
+ PUSH PSW
+ PUSH ACC
+ CLR MSG
+ MOV A,R0
+ IFCALL 02h,GET_FROM_PC ; TI-Datei von PC an Roboter
+ IFCALL 03h,GET_FROM_PC ; TI-Datei von PC an Fraese
+ IFCALL 01h,GET_WORKFR_FROM_PC ; Fraesdatei von PC
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Message auf die Module verteilen
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register : -
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+Dispatch_Msg:
+ PUSH PSW
+ PUSH ACC
+ MOV A,R0
+ CJNE A,#10h,Dis_Msg0 ; Msg.-Nr. <=10h sind von PC
+Dis_Msg0: JC Dis_Msg01 ; und werden von MEM_SCHEDULER
+ LJMP Dis_Msg02 ; bearbeitet
+Dis_Msg01:
+ LCALL MEM_SCHEDULER
+ LJMP Dis_Msg_Ret
+
+Dis_Msg02:
+ cjne A,#TeachRob,Dis_Msg10
+ LJMP Dis_Msg11
+Dis_Msg10: LJMP Dis_Msg2
+Dis_Msg11:
+ ifdef TeachRob_MsgCall_Tab
+ Message_Handler TeachRob
+ endif
+ ljmp Dis_Msg_Ret
+
+Dis_Msg2: cjne A,#TeachFrs,Dis_Msg20
+ LJMP Dis_Msg21
+Dis_Msg20: LJMP Dis_Msg3
+Dis_Msg21:
+ ifdef TeachFrs_MsgCall_Tab
+ Message_Handler TeachFrs
+ endif
+ ljmp Dis_Msg_Ret
+
+Dis_Msg3: cjne A,#Rob,Dis_Msg30
+ LJMP Dis_Msg31
+Dis_Msg30: LJMP Dis_Msg4
+Dis_Msg31:
+ ifdef Rob_MsgCall_Tab
+ Message_Handler Rob
+ endif
+ ljmp Dis_Msg_Ret
+
+Dis_Msg4: cjne A,#Frs,Dis_Msg40
+ LJMP Dis_Msg41
+Dis_Msg40: LJMP Dis_Msg5
+Dis_Msg41:
+ ifdef Frs_MsgCall_Tab
+ Message_Handler Frs
+ endif
+ ljmp Dis_Msg_Ret
+
+Dis_Msg5: cjne A,#MemFrs,Dis_Msg50
+ LJMP Dis_Msg51
+Dis_Msg50: LJMP Dis_Msg6
+Dis_Msg51:
+ ifdef MemFrs_MsgCall_Tab
+ Message_Handler MemFrs
+ endif
+ ljmp Dis_Msg_Ret
+
+Dis_Msg6: cjne A,#MemRob,Dis_Msg60
+ LJMP Dis_Msg61
+Dis_Msg60: LJMP Dis_Msg7
+Dis_Msg61:
+ ifdef MemRob_MsgCall_Tab
+ Message_Handler MemRob
+ endif
+ ljmp Dis_Msg_Ret
+
+Dis_Msg7:
+
+Dis_Msg_Ret:
+ POP ACC
+ POP PSW
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : START-Routine
+; Aufrufparameter : Wird durch die globale Message "START" ausgeloesst
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+GLOBAL_START:
+ ;LCD 40H,"START-Routine "
+ LCALL START_RUNNING
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : NOTAUS-Routine
+; Aufrufparameter : Wird durch die globale Message "STOP" ausgeloesst
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+GLOBAL_NOTAUS:
+ LCD 40H,"NOTAUS!!! Abbruch. "
+ CLR RUNNINGBIT
+ LCALL INIT_TEACH
+ LCALL RESET_TEACH
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : RESET-Routine
+; Aufrufparameter : Wird durch die globale Message "RESET" ausgeloesst
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+GLOBAL_RESET:
+ LCD 40H,"Teachin- u. Runmanager initialisiert. "
+ LCALL INIT_TEACH
+ LCALL INIT_RUN
+ LCALL RESET_TEACH
+ LCALL INIT_FRS
+ CLR TESTBIT
+
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : PAUSE-Routine
+; Aufrufparameter : Wird durch die globale Message "PAUSE" ausgeloesst
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+GLOBAL_PAUSE:
+ JB RUNNINGBIT,GLOBAL_PAUSE_1
+ LJMP GLOBAL_PAUSE_ENDE
+GLOBAL_PAUSE_1:
+ CPL PAUSE
+ JNB PAUSE,GLOBAL_PAUSE_AUS
+ LCD 40H,"Pausemodus. Weiter mit <PAUSE>. "
+ RET
+GLOBAL_PAUSE_AUS:
+ LCD 40H,"Pausemodus aufgehoben. "
+ RET
+GLOBAL_PAUSE_ENDE:
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : AUX1-Routine
+; Aufrufparameter : Wird durch die globale Message "AUX1" ausgeloesst
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+GLOBAL_AUX1:
+ LCD 40H,"AUX1-Routine "
+ SETB SingleStep
+ JNB Ready_Waiting,GLOBAL_AUX1_ENDE
+ SETB Break
+GLOBAL_AUX1_ENDE
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : AUX2-Routine
+; Aufrufparameter : Wird durch die globale Message "AUX2" ausgeloesst
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+GLOBAL_AUX2:
+ ;LCD 40H,"AUX2-Routine "
+ LCD 40H,"Teachin- Datei wird gelaeden. "
+ LCALL LOAD_ROB
+ LCALL LOAD_FRAES
+ RET
+
+;---------------------------------------------------------------------
+; Funktion : Hauptprogramm fuer das Speichermodul
+; Aufrufparameter : -
+; Ruechgabeparameter : -
+; Veraenderte Register :
+; Stackbedarf :
+; Zeitbedarf :
+;
+
+Main_Event_Loop:
+ JNB Sp_MSG,No_Sp_Msg
+ LCALL Do_Sp_Msg
+ JB Sp_MSG,Main_Event_Loop
+No_Sp_Msg:
+ JNB MSG,No_Msg
+ LCALL Do_Msg
+ JB MSG,Main_Event_Loop
+No_Msg:
+ JNB RUNNINGBIT,No_Runnig
+ LCALL Do_Runnig
+No_Runnig:
+ JB Sp_MSG,Main_Event_Loop
+ JB MSG,Main_Event_Loop
+
+ RET
+
+
+Do_Msg: CLR MSG
+ PUSH_ALL
+ LCALL READ_MESSAGE
+ LCALL Dispatch_Msg
+ POP_ALL
+ RET
+
+Do_Sp_Msg:
+ CLR Sp_MSG
+ PUSH ACC
+ MOV A,Sp_MSG_Buffer
+SM_START: JNB START_BIT,SM_NOTAUS ; Special- Message Fkt.
+ LCALL GLOBAL_START ; aufrufen
+ POP ACC
+ RET
+SM_NOTAUS: JNB STOP_BIT,SM_RESET
+ LCALL GLOBAL_NOTAUS
+ POP ACC
+ RET
+SM_RESET: JNB RESET_BIT,SM_PAUSE
+ LCALL GLOBAL_RESET
+ POP ACC
+ RET
+SM_PAUSE: JNB PAUSE_BIT,SM_AUX1
+ LCALL GLOBAL_PAUSE
+ POP ACC
+ RET
+SM_AUX1: JNB AUX1_BIT,SM_AUX2
+ LCALL GLOBAL_AUX1
+ POP ACC
+ RET
+SM_AUX2: JNB AUX2_BIT,SM_ENDE
+ LCALL GLOBAL_AUX2
+ POP ACC
+ RET
+SM_ENDE: POP ACC
+ RET
+
+Do_Runnig:
+ JB Drilling,Do_Drilling
+ JB PAUSE,Do_Waiting
+ JB Sync_Waiting,Do_Waiting
+ JB Ready_Waiting,Do_Waiting
+ LCALL RUN_MODUL
+Do_Waiting:
+ RET
+
+Do_Drilling:
+ JNB FrsWarning,No_FrsWarning ; Queue- Warnung von Frs
+ PUSH_ALL
+ post_message2 #Frs,#GibReady,#MemFrs,#GetFrsReady,#0
+ POP_ALL
+ CLR FrsWarning
+ SETB READY_WAITING
+No_FrsWarning:
+ RET
+
+;=====================================================================
+; END
+;---------------------------------------------------------------------
+
diff --git a/tests/t_msp/asflags b/tests/t_msp/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_msp/asflags
diff --git a/tests/t_msp/t_msp.asm b/tests/t_msp/t_msp.asm
new file mode 100644
index 0000000..c0bb12c
--- /dev/null
+++ b/tests/t_msp/t_msp.asm
@@ -0,0 +1,116 @@
+ cpu msp430
+
+ include regmsp.inc
+
+ede equ 0f016h
+toni equ 01114h
+
+ mov r12,r7
+ mov pc,r7
+ mov sp,r7
+ mov sr,r7
+
+ mov 2(r5),6(r6)
+
+ mov ede,toni
+
+ mov &ede,&toni
+
+ mov @r10,0(r11)
+
+ mov @r10+,0(r11)
+
+ mov #45,toni
+ mov #0,toni
+ mov #1,toni
+ mov #2,toni
+ mov #4,toni
+ mov #8,toni
+ mov #-1,toni
+
+ dadd #45,r4
+
+ rrc r5
+ rra.b toni
+ push pc
+ swpb &ede
+ call 1234h
+ sxt @r5+
+
+ reti
+
+ jmp 234h
+ jne $
+ jn $+2
+
+;----------------------------------
+; emulierte Befehle
+
+ adc r6
+ adc.w r6
+ adc.b r6
+ dadc @r4
+ dadc.w @r4
+ dadc.b @r4
+ dec toni
+ dec.w toni
+ dec.b toni
+ decd &toni
+ decd.w &toni
+ decd.b &toni
+ inc ede
+ inc.w ede
+ inc.b ede
+ incd &ede
+ incd.w &ede
+ incd.b &ede
+ sbc 55h(r9)
+ sbc.w 55h(r9)
+ sbc.b 55h(r9)
+
+ inv @r6
+ inv.w @r6
+ inv.b @r6
+ rla r5
+ rla.w r5
+ rla.b r5
+ rlc @r14
+ rlc.w @r14
+ rlc.b @r14
+
+ clr 0(r10)
+ clr.w 0(r10)
+ clr.b 0(r10)
+ clrc
+ clrn
+ clrz
+ pop sr
+ setc
+ setn
+ setz
+ tst toni
+ tst.w toni
+ tst.b toni
+
+ br r5
+ dint
+ eint
+ nop
+ ret
+
+ padding on
+ .byte 1,2,3,4
+ .byte "Hello world"
+ .byte "Hello world!"
+ .word 1,2,3,4
+ .bss 20
+ .bss 21
+
+ padding off
+ .byte 1,2,3,4
+ .byte "Hello world"
+ .byte "Hello world!"
+ .word 1,2,3,4
+ .bss 20
+ .bss 21
+
diff --git a/tests/t_msp/t_msp.doc b/tests/t_msp/t_msp.doc
new file mode 100644
index 0000000..da3085d
--- /dev/null
+++ b/tests/t_msp/t_msp.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application MSP ----------------------------+
+| |
+| This is a (synthetic) test of the MSP430 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_msp/t_msp.ori b/tests/t_msp/t_msp.ori
new file mode 100644
index 0000000..4278619
--- /dev/null
+++ b/tests/t_msp/t_msp.ori
Binary files differ
diff --git a/tests/t_parsys/asflags b/tests/t_parsys/asflags
new file mode 100644
index 0000000..01f6552
--- /dev/null
+++ b/tests/t_parsys/asflags
@@ -0,0 +1 @@
+-c \ No newline at end of file
diff --git a/tests/t_parsys/float.i68 b/tests/t_parsys/float.i68
new file mode 100644
index 0000000..fbfc1e9
--- /dev/null
+++ b/tests/t_parsys/float.i68
@@ -0,0 +1,1226 @@
+; FLOAT.I68
+;-----------------------------------------------------------------------------
+; Fliesskommaroutinen fuer den PC-PAR 68000, Version ohne 68881
+; entnommen mc 11/88, c't...
+
+;-----------------------------------------------------------------------------
+; Definitionen
+
+vorz equ 0
+subflag equ 1
+maxexpo equ 255
+bias equ 127
+extend equ $10
+e equ $402df854 ; exp(1)
+ln2 equ $3f317218 ; ln(2)
+ln10 equ $40135d8e ; ln(10)
+eins equ $3f800000 ; 1.0
+zwei equ $40000000 ; 2.0
+pi2 equ $40c90fdb ; Pi*2
+pi equ $40490fdb ; Pi
+pihalf equ $3fc90fdb ; Pi/2
+
+;-----------------------------------------------------------------------------
+; Librarykopf:
+
+
+S_FloatLib: dc.l S_floatlibend-S_floatlibstart ; Laenge
+S_floatlibstart:
+ dc.l -1 ; Speicher fuer Zeiger
+ dc.b "FLOAT",0 ; Name
+ ds 0
+
+
+
+;-----------------------------------------------------------------------------
+; Sprungtabelle:
+
+ bra.l S_fadd
+ bra.l S_fsub
+ bra.l S_fmul
+ bra.l S_fdiv
+ bra.l S_fmul2
+ bra.l S_fsqrt
+ bra.l S_fabs
+ bra.l S_floatlibnop
+ bra.l S_fcmp
+ bra.l S_fitof
+ bra.l S_fftoi
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_fexp
+ bra.l S_fsinh
+ bra.l S_fcosh
+ bra.l S_ftanh
+ bra.l S_fcoth
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_fln
+ bra.l S_flog
+ bra.l S_fasinh
+ bra.l S_facosh
+ bra.l S_fatanh
+ bra.l S_facoth
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_fsin
+ bra.l S_fcos
+ bra.l S_ftan
+ bra.l S_fcot
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_floatlibnop
+ bra.l S_fasin
+ bra.l S_facos
+ bra.l S_fatan
+ bra.l S_facot
+
+
+;-----------------------------------------------------------------------------
+; Konstanten :
+
+S_Const1 dc.s 1.0
+
+;-----------------------------------------------------------------------------
+; Nullprozedur :
+
+S_floatlibnop: rts
+
+;-----------------------------------------------------------------------------
+; Addition : D0.S = D0.S + D1.S
+
+ ds 0
+S_fadd:
+ addq.l #1,_fadd_cnt.w
+ movem.l d1-d5,-(a7) ; benoetigte Register retten
+ rol.l #1,d0 ; Operanden rotieren und in Form
+ rol.l #1,d1 ; eeee eeee ffff ... fffs bringen
+ move.l d0,d2
+ sub.l d1,d2 ; Differenz beider Zahlen bilden
+ bcc.s fadd_1
+ exg d0,d1 ; ggf. vertauschen, so dass der
+fadd_1: move.b d0,d3 ; kleinere in Register D1 steht
+ and.b #1,d3 ; maskiere das Vorzeichenbit
+ btst #vorz,d2 ; haben beide gleiches Vorzeichen ?
+ beq.s fadd_2 ; bei verschiedenen Vorzeichen
+ bset #subflag,d3 ; Flag fuer Subtraktion setzen
+fadd_2: rol.l #8,d0 ; Form: ffff ... fffs eeee eeee
+ clr.w d4 ; Exponent der ersten Zahl
+ move.b d0,d4 ; wird im Register D4 aufgebaut
+ sne d0 ; falls ungleich Null, dann
+ ror.l #1,d0 ; implizite Eins, sonst implizite
+ clr.b d0 ; Null erzeugen, neu positionieren
+
+ rol.l #8,d1 ; jetzt das gleiche fuer den
+ clr.w d5 ; zweiten Operanden, der Exponent
+ move.b d1,d5 ; kommt ins Register D5
+ sne d1
+ ror.l #1,d1
+ clr.b d1
+
+; In den Registern D0 und D1 stehen jetzt nur noch die Mantissen
+; im Format ffff ... ffff 0000 0000, also linksbuendig, wobei die
+; ehemals implizite Null bzw. Eins nun explizit an erster Stelle steht.
+; In den Registern D4 und D5 stehen die Exponenten der beiden Zahlen.
+; Das Vorzeichen des Ergebnisses sowie die Subtraktionsflags sind im
+; Register D3 zwischengespeichert.
+
+ move.w d4,d2 ; Jetzt Differenz der Exponenten
+ sub.w d5,d2 ; berechnen
+ cmp.w #24,d2 ; groesser als 24 ?
+ bgt.s fadd_rnd ; ja, --> Ergebnis ist groessere Zahl
+ lsr.l d2,d1 ; Mantisse um (D2)-Bits verschieben
+ btst #subflag,d3 ; Subtraktion oder Addition ?
+ bne.s fadd_subtr ; ggf. zur Subtraktion springen
+ add.l d1,d0 ; die beiden Mantissen addieren
+ bcc.s fadd_rnd ; kein Ueberlauf --> zum Runden
+ roxr.l #1,d0 ; Ueberlauf einschieben
+ addq.w #1,d4 ; Exponent korrigieren
+ bra.s fadd_rnd ; und zum Runden
+
+fadd_subtr: sub.l d1,d0 ; die beiden Mantissen subtrahieren
+ beq.s fadd_zero ; bei Null ist das Gesamtergebnis Null
+ bmi.s fadd_rnd ; bei fuehrender Eins zum Runden
+fadd_nrm: tst.w d4 ; Exponent ist schon Null ?
+ beq.s fadd_rnd ; dann ist Ergebnis denormalisiert
+ subq.w #1,d4 ; Exponent erniedrigen
+ lsl.l #1,d0 ; Mantisse normalisieren bis
+ bpl.s fadd_nrm ; fuehrende Eins auftaucht
+
+fadd_rnd: add.l #$80,d0 ; jetzt Runden auf Bit hinter
+ bcc.s fadd_nov ; Mantisse
+ roxr.l #1,d0 ; bei Ueberlauf Mantisse normalisieren
+ addq.w #1,d4 ; und Exponent korrigieren
+fadd_nov: clr.b d0 ; Rest-Mantisse loeschen
+ tst.l d0 ; Ist die Mantisse komplett Null ?
+ beq.s fadd_zero ; ja, dann ist Ergebnis auch Null
+ cmp.w #maxexpo,d4 ; Exponent-Ueberlauf ?
+ blt.s fadd_nue
+ move.w #maxexpo,d4 ; Unendlich Exponent = maxexpo
+ clr.l d0 ; Mantisse = Null
+ bra.s fadd_den
+
+fadd_nue: tst.w d4 ; Exponent Null ( Zahl denormalisiert? )
+ beq.s fadd_den ; ja -->
+ lsl.l #1,d0 ; fuehrendes Bit wird nicht gespeichert
+fadd_den: move.b d4,d0 ; Exponent einsetzen
+ ror.l #8,d0 ; Form: eeee eeee ffff ... fffx
+ roxr.b #1,d3 ; Vorzeichen in Carry schieben
+ roxr.l #1,d0 ; Form: seee eeee efff ... ffff
+
+fadd_zero:
+ movem.l (a7)+,d1-d5 ; Register restaurieren
+ rts ; Ende, Ergebnis steht in D0.L
+
+;-----------------------------------------------------------------------------
+; Subtraktion : D0.S = D0.S - D1.S
+
+ ds 0
+S_fsub:
+ bchg #31,d1 ; Vorzeichen des zweiten Operanden
+ bra S_fadd ; invertieren und zur Addition springen
+
+
+;-----------------------------------------------------------------------------
+; Multiplikation : D0.S = D0.S * D1.S
+
+ ds 0
+S_fmul:
+ addq.l #1,_fmul_cnt.w
+ movem.l d1-d5,-(a7) ; benoetigte Register retten
+ move.l d0,d2 ; Operand 1 kopieren
+ eor.l d1,d2 ; EXOR um Vorzeichen zu bestimmen
+
+ swap d0 ; Registerhaelften Operand 1 vertauschen
+ move.l d0,d3 ; Operand 1 ab jetzt in Register D3
+ and.w #$7f,d3 ; Exponent und Vorzeichen loeschen
+ and.w #$7f80,d0 ; Exponent maskieren
+ beq.s fmul_dn1 ; gleich Null: Zahl ist denormalisiert
+ bset #7,d3 ; implizite Eins einsetzen
+ sub.w #$0080,d0 ; Bias kompensieren
+
+fmul_dn1: swap d1 ; jetzt Operand 2 behandeln
+ move.w d1,d4
+ and.w #$7f,d1
+ and.w #$7f80,d4
+ beq.s fmul_dn2
+ bset #7,d1
+ sub.w #$0080,d4 ; Bias kompensieren
+
+fmul_dn2: add.w d0,d4 ; Exponenten addieren
+ lsr.w #7,d4 ; richtig positionieren
+ sub.w #bias-3,d4 ; Bias-3 subtrahieren
+ cmp.w #-24,d4 ; totaler Unterlauf ?
+ blt.s fmul_zero ; ja, dann ist Ergebnis Null
+
+ move.w d3,d0 ; oberes Mantissenwort von Operand 1
+ mulu d1,d0 ; mal oberem Mantissenwort von Op2
+ swap d0 ; entspricht Verschiebung um 16 Bit
+
+; Das obere Wort von D0 ist nach der Multiplikation auf jeden Fall Null,
+; da die oberen Mantissenworte nur im Bereich 0 ... 255 liegen.
+; Das groete moegliche Ergebnis ist also 255 x 255 = 65025 = 0000FE01.
+; Nach der Vertauschung erhalten wir also eine Zahl der xxxx 0000.
+; Die untere Registerhaelfte von D0 koennen wir kurzzeitig als Zwischen-
+; speicher verwenden.
+
+ move.w d3,d0 ; oberes Wort von Operand 1 merken
+ swap d3 ; jetzt unteres Wort Op1 mal oberes Op2
+ move.w d1,d5
+ mulu d3,d5 ; Ergebnis steht im D5
+ swap d1 ; jetzt unteres Wort Op1 mal unteres Op2
+ mulu d1,d3 ; Ergebnis steht im D3
+ swap d3 ; entspricht Verschiebung um 16 Bit
+ mulu d0,d1 ; jetzt oberes Wort Op1 mal unteres Op2
+
+ move.w d3,d0 ; zum ersten Zwischenergebnis dazu
+ add.l d5,d0 ; jetzt alles aufaddieren
+ add.l d1,d0
+ beq.s fmul_res ; falls Mantisse Null auch Ergebnis Null
+ bmi.s fmul_rnd ; fuehrende Eins? dann zum Runden
+
+; Im Register D0.L befinden sich die oberen 32 Bit des Produktes,
+; im oberen Wort von D3 die restlichen 16 Bit.
+
+ tst.w d4 ; Exponent ist negativ ?
+ bmi.s fmul_unt ; ggf. Unterlauf behandeln
+
+fmul_nor: tst.w d4 ; Exponent = Null ?
+ beq.s fmul_rnd ; falls Null, dann zum Runden
+ roxl.l #1,d3 ; Im oberen Wort von D3 sind die
+ roxl.l #1,d0 ; niedrigsten Bits des Produktes
+ subq.w #1,d4 ; Exponent korrigieren
+ tst.l d0 ; Mantisse testen
+ bpl.s fmul_nor ; bis fuehrende Eins auftaucht
+
+fmul_rnd: add.l #$80,d0 ; Rundung
+ bcc.s fmul_nov
+ roxr.l #1,d0 ; Ueberlauf einschieben
+ addq.w #1,d4 ; Exponent korrigieren
+fmul_nov: cmp.w #maxexpo,d4 ; Exponent-Ueberlauf ?
+ blt.s fmul_nue
+fdiv_err: move.w #maxexpo,d4 ; Ueberlauf: Exponent = Maxexpo
+ clr.l d0 ; Mantisse = Null
+ bra.s fmul_den
+
+fmul_nue: tst.w d4 ; Exponent = Null ?
+ beq.s fmul_den ; falls Null, dann denormalisiert
+ lsl.l #1,d0 ; fuehrende Eins wird nicht abgespeichert
+
+fmul_den: move.b d4,d0 ; Exponent einsetzen
+ ror.l #8,d0 ; Form: eeee eeee ffff ... fffx
+ roxl.l #1,d2 ; Vorzeichen in Carry schieben
+ roxr.l #1,d0 ; und ins Ergebnis einsetzen
+
+fmul_res: movem.l (a7)+,d1-d5 ; Register restaurieren
+ rts
+
+fmul_zero: clr.l d0 ; Null erzeugen
+ bra.s fmul_res ; Ende, Ergebnis steht in D0.L
+
+fmul_unt: cmp.w #-24,d4 ; totaler Unterlauf ?
+ ble.s fmul_zero ; Dann ist das Ergebnis auf jeden Fall Null
+ neg.w d4 ; sonst Shift-Zaehler erzeugen
+ lsr.l d4,d0 ; und Zahl denormalisieren
+ clr.w d4 ; Exponent ist Null als Kennzeichen
+ bra.s fmul_rnd ; fuer eine denormalisierte Zahl
+
+;-----------------------------------------------------------------------------
+; Division : D0.S = D0.S / D1.S
+
+ ds 0
+S_fdiv:
+ addq.l #1,_fdiv_cnt.w
+ movem.l d1-d5,-(a7) ; benoetigte Register retten
+ move.l d0,d2 ; Operand 1 kopieren
+ eor.l d1,d2 ; EXOR um Vorzeichen zu bestimmen
+
+ swap d0 ; Registerhaelften Operand 1 vertauschen
+ move.l d0,d3 ; Operand 1 ab jetzt in Register D3
+ and.w #$7f,d3 ; Exponent und Vorzeichen loeschen
+ and.w #$7f80,d0 ; Exponent maskieren
+ beq.s fdiv_dn1 ; gleich Null: Zahl ist denormalisiert
+ bset #7,d3 ; implizite Eins einsetzen
+ sub.w #$0080,d0 ; Bias kompensieren
+
+fdiv_dn1: swap d1 ; jetzt Operand 2 behandeln
+ move.w d1,d4
+ and.w #$7f,d1
+ and.w #$7f80,d4
+ beq.s fdiv_dn2
+ bset #7,d1
+ sub.w #$0080,d4
+
+fdiv_dn2: sub.w d4,d0 ; Exponenten subtrahieren
+ move.w d0,d4 ; Exponent nach D4 kopieren
+ asr.w #7,d4 ; richtig positionieren
+ add.w #bias,d4 ; Bias addieren
+ cmp.w #-24,d4 ; totaler Ueberlauf ?
+ blt.s fmul_zero ; ja, dann ist Ergebnis Null
+
+ swap d1 ; Form: 0fff ... ffff 0000 0000
+ beq.s fdiv_err ; falls Divisor Null, dann wird
+ lsl.l #7,d1 ; als Ergebnis unendlich ausgegeben
+ swap d3
+ beq.s fmul_zero ; falls Divident Null --> Ergebnis Null
+ lsl.l #7,d3
+
+fdiv_nlp: btst #30,d1 ; ist der Divisor normalisiert ?
+ bne.s fdiv_nor ; ja, -->
+ addq.w #1,d4 ; nein, Exponent erhoehen
+ lsl.l #1,d1 ; Divisor verschieben bis Form 01ff ..
+ bra.s fdiv_nlp
+
+fdiv_nor: clr.l d0 ; Ergebnis vorbesetzen
+ add.w #25,d4 ; Exponent ist nicht groesser als Null
+
+fdiv_lop: move.l d3,d5 ; Divident zwischenspeichern
+ sub.l d1,d3 ; Divisor abziehen
+ eori #extend,ccr ; X-Bit invertieren
+ bcc.s fdiv_one ; kein Carry: Divisor passt
+ move.l d5,d3 ; zurueckkopieren (X-Bit unveraendert!)
+fdiv_one: roxl.l #1,d0 ; Ergebnis aufbauen
+ lsl.l #1,d3 ; Divident verschieben
+ subq.w #1,d4 ; Exponent erniedrigen
+ beq.s fdiv_den ; falls Null, dann denormalisiert
+ btst #24,d0 ; fuehrende Eins in Ergebnis-Mantisse?
+ beq.s fdiv_lop ; nein, weiter rechnen
+
+fdiv_den: lsl.l #7,d0 ; Mantisse positionieren
+ beq fmul_res ; Null ?
+ bra fmul_rnd ; zum Runden
+;-----------------------------------------------------------------------------
+; Multiplikation mit einer Zweierpotenz: D0.S=D0.S * 2^(D1.W)
+
+ ds 0
+S_fmul2:
+ addq.l #1,_fmul_cnt.w
+ movem.l d1-d2,-(a7) ; Register retten
+ move.l d0,d2 ; Vorzeichen in D2 Bit 31 merken
+ lsl.l #1,d0 ; Vorzeichen rausschieben
+ beq.s fmul2_zero ; falls Null, dann ist Ergebnis Null
+ rol.l #8,d0 ; Form: ffff ... fff0 eeee eeee
+ clr.w d2 ; auf Wort vorbereiten
+ move.b d0,d2 ; Exponent in D2
+ beq.s fmul2_den
+ tst.w d1 ; Multiplikation oder Division?
+ bmi.s fmul2_div ; (neg. Exponent entspr. Div.)
+
+ add.w d1,d2 ; Summe der Exponenten bilden
+ cmp.w #maxexpo,d2 ; Ueberlauf?
+ bge.s fmul2_over ; ja, Ergebnis ist unendlich
+fmul2_res: move.b d2,d0 ; Ergebnisexponent einsetzen
+ ror.l #8,d0 ; Form: eeee eeee ffff ... fffx
+ roxl.l #1,d2 ; Vorzeichen ins X-Bit
+ roxr.l #1,d0 ; und ins Ergebnis einschieben
+fmul2_zero: movem.l (a7)+,d1-d2 ; Register restaurieren
+ rts
+
+fmul2_over: move.w #maxexpo,d2 ; Unendlich: Exponent = maxexpo
+ clr.l d0 ; Mantisse = Null
+ bra.s fmul2_res
+
+fmul2_div: add.w d1,d2 ; Summe der Exponenten bilden
+ bgt.s fmul2_res ; Unterlauf? nein --> Ergebnis
+ ori #Extend,ccr ; implizite Eins real machen
+ roxr.l #1,d0 ; Form: 1fff ... ffff xxxx xxxx
+fmul2_dnr: tst.w d2 ; Exponent = Null ?
+ beq.s fmul2_res ; ja, Ergebnis ist denormalisiert
+ lsr.l #1,d0 ; Mantisse denormalisieren
+ beq.s fmul2_zero ; totaler Unterlauf: Ergebnis ist Null
+ addq.w #1,d2 ; Exponent korrigieren
+ bra.s fmul2_dnr
+fmul2_ddd: add.w d1,d2 ; Summe der Exponenten bilden
+ bra.s fmul2_dnr ; mit denormalisiereter Eingabe bearbeiten
+
+fmul2_den: tst.w d1 ; Multiplikation oder Division
+ bmi.s fmul2_ddd
+ clr.b d0 ; Form: ffff ... fff0 0000 0000
+fmul2_nor: lsl.l #1,d0 ; Mantisse nach links schieben
+ bcs.s fmul2_stp ; bis fuehrende Eins auftaucht
+ subq.w #1,d1 ; oder zweiter Exponent Null wird
+ bne.s fmul2_nor
+ bra.s fmul2_res ; Ergebnis abliefern
+fmul2_stp: add.w d1,d2 ; Rest zum Exponenten addieren
+ bra.s fmul2_res ; Bias stimmt auch ( jetzt 127 statt 126)
+
+;-----------------------------------------------------------------------------
+; Vergleich zweier Zahlen: cmp d0,d1
+
+S_fcmp:
+ bclr #31,d0 ; Zahl 1 >=0 ?
+ bne.s fcmp_2
+fcmp_1:
+ bclr #31,d1 ; Zahl 2 >=0 ?
+ bne.s fcmp_12
+fcmp_11:
+ cmp.l d1,d0 ; beide Zahlen >=0
+ rts ; dann Betraege vergleichen
+fcmp_12:
+ moveq.l #1,d0 ; Zahl 1 >=0 und Zahl 2 <0
+ cmp.l #-1,d0
+ rts
+fcmp_2:
+ bclr #31,d1 ; Zahl 2 >=0 ?
+ bne.s fcmp_22
+fcmp_21:
+ moveq.l #-1,d0 ; Zahl 1 <0 und Zahl 2 >=0
+ cmp.w #1,d0 ; dann kleiner
+ rts
+fcmp_22:
+ neg.l d0
+ neg.l d1
+ cmp.l d1,d0 ; beide Zahlen <0, dann ver-
+ rts ; kehrtherum vergleichen
+
+
+;-----------------------------------------------------------------------------
+; Longint-->Gleitkomma
+; D0.L --> D0.S
+
+S_fitof:
+ movem.l d1-d2,-(a7) ; Register retten
+ tst.l d0 ; Integer ist Null ?
+ beq.s fitof_res; Ergebnis ist auch Null
+ smi d1 ; Vorzeichen in D1 merken
+ bpl.s fitof_pos
+ neg.l d0 ; ggf. Integer negieren
+fitof_pos: move.w #bias+32,d2 ; Exponent vorbesetzen
+fitof_shift: subq.w #1,d2 ; Mantisse verschieben
+ lsl.l #1,d0 ; bis fuehrende Eins rausfliegt
+ bcc.s fitof_shift
+ move.b d2,d0 ; Exponent einsetzen
+ ror.l #8,d0 ; Zahl positionieren
+ roxr.b #1,d1 ; Vorzeichen in X-Bit
+ roxr.l #1,d0 ; und ins Ergebnis
+fitof_res: movem.l (a7)+,d1-d2 ; fertig
+ rts
+
+;-----------------------------------------------------------------------------
+; Gleitkomma --> Longint:
+; D0.S --> D0.L
+
+S_fftoi:
+ movem.l d1-d2,-(a7) ; Register retten
+ roxl.l #1,d0 ; Vorzeichen in Carry
+ scs d1 ; in D1 merken
+ rol.l #8,d0 ; Form: ffff ... fffx eeee eeee
+ move.b d0,d2 ; Exponent extrahieren
+ sub.b #bias,d2 ; Bias subtrahieren
+ bmi.s fftoi_zero ; kleiner Null -> Ergebnis = Null
+ cmp.b #31,d2 ; Ueberlauf?
+ bge.s fftoi_over
+ ori #extend,ccr ; Implizite Eins explizit machen
+ roxr.l #1,d0
+ clr.b d0 ; Form: 1fff ... ffff 0000 0000
+fftoi_shft:
+ lsr.l #1,d0 ; jetzt Verschiebung bis
+ addq.b #1,d2 ; Exponent stimmt
+ cmp.b #31,d2
+ bne.s fftoi_shft
+ tst.b d1 ; Zahl negativ ?
+ bpl.s fftoi_pos
+ neg.l d0 ; ggf. Ergebnis negieren
+fftoi_pos:
+ movem.l (a7)+,d1-d2 ; Register wieder holen
+ rts
+fftoi_zero:
+ clr.l d0 ; Unterlauf; Ergebnis ist Null
+ bra.s fftoi_pos
+fftoi_over:
+ move.l #$7fffffff,d0 ; Ueberlauf: Maxint zurueckgeben
+ tst.b d1 ; positiv oder negativ ?
+ bpl.s fftoi_pos
+ not.l d0 ; Einser-Komplement erzeugt Minint
+ bra.s fftoi_pos
+
+;-----------------------------------------------------------------------------
+; Quadratwurzel : D0.S-->D0.S
+
+ ds 0
+fsqrt_domainerror:
+ move.l #$ffc00000,d0 ; -NAN zurueckgeben
+ movem.l (a7)+,d1-d4
+ rts
+fsqrt_sq0:
+ clr.l d0
+ movem.l (a7)+,d1-d4
+ rts
+S_fsqrt:
+ addq.l #1,_fsqrt_cnt.w
+ movem.l d1-d4,-(a7) ; D1-D4 werden sonst zerstoert
+ move.l d0,d4
+ bmi.s fsqrt_domainerror ; Fehler bei negativem Argument
+ swap d4 ; MSW des Arguments
+ and.l #$7f80,d4 ; Exponent isolieren
+ beq.s fsqrt_sq0 ; Zahl ist 0, wenn Exponent 0
+ and.l #$007fffff,d0 ; Mantisse isolieren
+ sub.w #$7f*$80,d4 ; Exponent im Zweierkomplement
+ bclr #7,d4 ; Exponent ungerade? (und LSB auf 0)
+ beq.s fsqrt_evenexp
+ add.l d0,d0 ; ja: Mantisse * 2
+ add.l #$01000000-$00800000,d0 ; Hidden Bit setzen, 1.Iteration
+
+fsqrt_evenexp:
+ ; 1. Iteration fuer geraden Exponenten: Hidden Bit nicht setzen
+ asr.w #1,d4 ; Exponent/2 mit Vorzeichen
+ add.w #$7f*$80,d4 ; Exponent wieder in Offset-Darst.
+ swap d4 ; neuen Exponenten im MSW aufheben
+ lsl.l #7,d0 ; x ausrichten
+ move.l #$40000000,d2 ; xroot nach erster Iteration
+ move.l #$10000000,d3 ; m2=2 << (MaxBit-1);
+fsqrt_loop10:
+ move.l d0,d1 ; xx2 = x
+fsqrt_loop11:
+ sub.l d2,d1 ; xx2 -= root
+ lsr.l #1,d2 ; xroot >>= 1
+ sub.l d3,d1 ; x2 -= m2
+ bmi.s fsqrt_dontset1
+ move.l d1,d0 ; x = xx2
+ or.l d3,d2 ; xroot += m2
+ lsr.l #2,d3 ; m2 >>= 2
+ bne.s fsqrt_loop11
+ bra.s fsqrt_d0d1same
+fsqrt_dontset1:
+ lsr.l #2,d3 ; m2 >>= 2
+ bne.s fsqrt_loop10 ; Schleife 15* abarbeiten
+ ; Bit 22..8
+ ; 17. Iteration (Bit 7) mit separatem Code durchfuehren:
+ move.l d0,d1 ; xx2 = x
+fsqrt_d0d1same:
+ sub.l d2,d1 ; xx2 -= root
+ ror.l #1,d2 ; xroot >>= 1 mitsamt Carry...
+ swap d2 ; auf neues Alignment umstellen
+ subq.l #1,d1 ; Carry von 0-0x4000: x2 -= m2
+ ; Teil 1
+ bmi.s fsqrt_dontset7
+ or.l #-$40000000,d1 ; 0 - 0x4000: x2 -= m2, Teil 2
+ move.l d1,d0 ; x = xx2
+ or.w #$4000,d2 ; xroot += m2
+fsqrt_dontset7:
+ swap d0 ; x auf neues Alignment umstellen
+
+ move.w #$1000,d3 ; m2 - Bit 16..31 bereits 0
+fsqrt_loop20:
+ move.l d0,d1 ; xx2 = x
+fsqrt_loop21:
+ sub.l d2,d1 ; xx2 -= xroot
+ lsr.l #1,d2 ; xroot >>= 1
+ sub.l d3,d1 ; x2 -= m2
+ bmi.s fsqrt_dontset2
+ move.l d1,d0 ; x = xx2
+ or.w d3,d2 ; xroot += m2
+ lsr.w #2,d3 ; m2 >>= 2
+ bne.s fsqrt_loop21
+ bra.s fsqrt_finish
+fsqrt_dontset2:
+ lsr.w #2,d3 ; m2 >>= 2
+ bne.s fsqrt_loop20 ; Schleife 7 * abarbeiten (n=6..0)
+fsqrt_finish:
+ sub.l d2,d0 ; Aufrunden notwendig ?
+ bls.s fsqrt_noinc
+ addq.l #1,d2 ; wenn ja, durchfuehren
+fsqrt_noinc:
+ bclr #23,d2 ; Hidden Bit loeschen
+ or.l d4,d2 ; Exponent und Mantisse kombinieren
+ move.l d2,d0 ; Ergebnis
+ movem.l (a7)+,d1-d4
+ rts ; Z-,S-, und V-Flag o.k.
+
+;-----------------------------------------------------------------------------
+; Absolutbetrag: D0.S--> D0.S
+
+ ds 0
+
+S_fabs: bclr #31,d0 ; ganz einfach...
+ rts
+
+;-----------------------------------------------------------------------------
+; Exponentialfunktion: D0.S--> D0.S
+
+; Die "krummen" Konstanten legen wir als hex ab, damit es keine Vergleichs-
+; fehler durch Rundungsvarianzen gibt.
+
+S_fexp_Const0: dc.l $3FB8AA3B ; ld(exp(1.0)) = ld(e) = 1/ln(2)
+S_fexp_ConstA: dc.l $3D0DF4E0 ; 0.034657359038 Polynomkonstanten
+S_fexp_ConstB: dc.l $411F4606 ; 9.9545957821
+S_fexp_ConstC: dc.l $441A7E3A ; 617.97226953
+S_fexp_ConstD: dc.l $42AED5C2 ; 87.417498202
+
+ ds 0
+S_fexp: movem.l d1-d5,-(sp)
+
+ bclr #31,d0 ; Vorzeichen loeschen und nach D2 retten
+ sne d2
+
+ move.l S_fexp_Const0(pc),d1 ; auf 2erpotenz umrechnen
+ bsr S_fmul
+
+ move.l d0,d3 ; in Ganzzahlanteil und Nach-
+ bsr S_fftoi ; kommastellen (z) zerlegen
+ move.l d0,d4 ; Ganzzahlanteil nach D4
+ bsr S_fitof
+ move.l d0,d1
+ move.l d3,d0
+ bsr S_fsub
+ move.l d0,d3
+
+ move.l d0,d1 ; z^2 berechnen
+ bsr S_fmul
+ move.l d0,d5 ; noch zu gebrauchen
+
+ move.l S_fexp_ConstD(pc),d1 ; --> D+z^2
+ bsr S_fadd
+ move.l d0,d1 ; --> C/(..)
+ move.l S_fexp_ConstC(pc),d0
+ bsr S_fdiv
+ move.l d0,d1 ; --> B-(..)
+ move.l S_fexp_ConstB(pc),d0
+ bsr S_fsub
+ move.l d3,d1 ; --> (..)-z
+ bsr S_fsub
+ exg d0,d5 ; Ergebnis retten
+ move.l S_fexp_ConstA(pc),d1 ; A*z^2 berechnen
+ bsr S_fmul
+ move.l d5,d1 ; ergibt Nenner
+ bsr S_fadd
+ move.l d0,d1 ; Quotient bilden
+ move.l d3,d0
+ bsr S_fdiv
+ moveq #1,d1 ; verdoppeln
+ bsr S_fmul2
+ move.l S_Const1(pc),d1 ; 1 addieren
+ bsr S_fadd
+ move.l d4,d1 ; Potenzieren
+ bsr S_fmul2
+
+ tst.b d2 ; war Argument negativ ?
+ beq.s S_fexp_ArgPos
+ move.l d0,d1 ; dann Kehrwert bilden
+ move.l S_Const1(pc),d0
+ bsr S_fdiv
+
+Terminate:
+S_fexp_ArgPos: movem.l (sp)+,d1-d5
+
+ rts
+
+;------------------------------------------------------------------------------
+; Sinus hyperbolicus: D0.S-->D0.S
+
+S_fsinh:
+ movem.l d1-d2,-(a7) ; Register retten
+ bsr S_fexp ; exp(x) berechnen
+ move.l d0,d2 ; in D2 merken
+ move.l d0,d1 ; exp(-x)=1/exp(x) berechnen
+ move.l #eins,d0
+ bsr S_fdiv
+ move.l d0,d1 ; Teilergebnisse subtrahieren
+ move.l d2,d0
+ bsr S_fsub
+ move.w #-1,d1 ; halbieren
+ bsr S_fmul2
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+
+;------------------------------------------------------------------------------
+; Cosinus hyperbolicus: D0.S-->D0.S
+
+S_fcosh:
+ movem.l d1-d2,-(a7) ; Register retten
+ bsr S_fexp ; exp(x) berechnen
+ move.l d0,d2 ; in D2 merken
+ move.l d0,d1 ; exp(-x)=1/exp(x) berechnen
+ move.l #eins,d0
+ bsr S_fdiv
+ move.l d2,d1 ; Teilergebnisse addieren
+ bsr S_fadd
+ move.w #-1,d1 ; halbieren
+ bsr S_fmul2
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Tangens hyperbolicus: D0.S-->D0.S
+
+S_ftanh:
+ movem.l d1-d3,-(a7) ; Register sichern
+ bsr S_fexp ; exp(x) berechnen
+ move.l d0,d2 ; in D2 merken
+ move.l d0,d1 ; exp(-x)=1/exp(x) berechnen
+ move.l #eins,d0
+ bsr S_fdiv
+ move.l d0,d3 ; in D3 merken
+ move.l d2,d1 ; Summe=Nenner berechnen
+ bsr S_fadd
+ exg d0,d2 ; jetzt exp(x) in D0, Nenner
+ move.l d3,d1 ; in D2
+ bsr S_fsub ; Zaehler berechnen
+ move.l d2,d1 ; Quotient berechnen
+ bsr S_fdiv
+ movem.l (a7)+,d1-d3 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Cotangens hyperbolicus: D0.S-->D0.S
+
+S_fcoth:
+ tst.l d0 ; Argument Null ?
+ beq.s S_fcoth_valerr ; dann zur Fehlerroutine
+ movem.l d1-d3,-(a7) ; Register sichern
+ bsr S_fexp ; exp(x) berechnen
+ move.l d0,d2 ; in D2 merken
+ move.l d0,d1 ; exp(-x)=1/exp(x) berechnen
+ move.l #eins,d0
+ bsr S_fdiv
+ move.l d0,d3 ; in D3 merken
+ move.l d0,d1 ; Differenz=Nenner berechnen
+ move.l d2,d0
+ bsr S_fsub
+ exg d0,d2 ; jetzt exp(x) in D0, Nenner
+ move.l d3,d1 ; in D2
+ bsr S_fadd ; Zaehler berechnen
+ move.l d2,d1 ; Quotient berechnen
+ bsr S_fdiv
+ movem.l (a7)+,d1-d3 ; Register zurueck
+ rts
+S_fcoth_valerr:
+ move.l #$7f800000,d0 ; +INF zurueckgeben
+ rts
+
+;-----------------------------------------------------------------------------
+; nat. Logarithmus: D0.S-->D0.S
+
+ ds 0
+S_fln:
+ tst.l d0 ; Argument <=0 ?
+ ble S_fln_errval
+ movem.l d1-d7,-(a7) ; Register retten
+ move.l d0,d3 ; Argument sichern
+
+ move.l #eins,d1 ; Zahl>1?
+ bsr S_fsub ; ( dies ist sinnvoll bei
+ tst.l d0 ; Zahlen <<1 );
+ smi d7 ; und die Vorzeichenumkehr merken
+ bpl.s S_fln_gr1 ; ja-->o.k.
+ move.l d3,d1 ; ansonsten Kehrwert bilden
+ move.l #eins,d0
+ bsr S_fdiv
+ move.l d0,d3
+
+S_fln_gr1:
+ clr.l d2 ; Merker = Null
+S_fln_nrm:
+ move.l d3,d0 ; Zahl > 1 ?
+ move.l #eins,d1
+ bsr S_fsub
+ bmi.s S_fln_isok
+ beq.s S_fln_isok
+ sub.l #$00800000,d3 ; ja-->Zahl durch 2 teilen...
+ addq.w #1,d2 ; ...und Merker erhoehen
+ bra.s S_fln_nrm ; nochmal probieren
+S_fln_isok:
+ move.l d0,d3 ; Zahl um Eins erniedrigt abspeichern
+ move.l d0,d4 ; yz:=y
+ moveq.l #1,d6 ; zaehler:=1
+ clr.l d5 ; Summe:=0
+ bchg #31,d3 ; Multiplikator negativ
+S_fln_loop:
+ move.l d6,d0 ; Zaehler in Gleitkomma wandeln
+ bsr S_fitof
+ move.l d0,d1 ; s:=s+yz/zaehler*vz
+ move.l d4,d0
+ bsr S_fdiv
+ move.l d5,d1
+ bsr S_fadd
+ cmp.l d5,d0 ; noch signifikant ?
+ beq.s S_fln_loopend
+ move.l d0,d5
+ addq.w #1,d6 ; zaehler:=zaehler+1
+ cmp.w #10,d6 ; Schleife fertig ?
+ beq.s S_fln_loopend
+ move.l d4,d0 ; yz:=yz*y
+ move.l d3,d1
+ bsr S_fmul
+ move.l d0,d4
+ bra.s S_fln_loop
+S_fln_loopend:
+ move.l d2,d0 ; Merker in Gleitkomma
+ bsr S_fitof
+ move.l #ln2,d1 ; * ln(2)
+ bsr S_fmul
+ move.l d5,d1 ; s:=s+merker
+ bsr S_fadd
+
+ tst.b d7 ; noch Vorzeichen tauschen ?
+ beq.s S_fln_end
+ bchg #31,d0
+S_fln_end:
+ movem.l (a7)+,d1-d7 ; Register zurueck
+ rts
+S_fln_errval:
+ move.l #$ffc00000,d0 ; -NAN zurueckgeben
+ rts
+
+;-----------------------------------------------------------------------------
+; 10er-Logarithmus : D0.S --> D0.S
+
+S_flog:
+ tst.l d0 ; Argument <=0 ?
+ ble.s S_flog_errval
+ bsr S_fln ; nat. Logarithmus bilden
+ move.l #ln10,d1 ; umrechnen
+ bsr S_fdiv
+ rts
+S_flog_errval:
+ move.l #$ffc00000,d0 ; -NAN zurueckgeben
+ rts
+
+;-----------------------------------------------------------------------------
+; Areasinus hyperbolicus: D0.S-->D0.S == ln[x+sqrt(x*x+1)]
+
+S_fasinh:
+ movem.l d1-d2,-(a7)
+ move.l d0,d2 ; Argument sichern
+ move.l d0,d1 ; quadrieren
+ bsr S_fmul
+ move.l #eins,d1 ; 1 addieren
+ bsr S_fadd
+ bsr S_fsqrt ; Wurzel ziehen
+ move.l d2,d1 ; Argument addieren
+ bsr S_fadd
+ bsr S_fln ; Logarithmus des ganzen
+ movem.l (a7)+,d1-d2
+ rts
+
+;-----------------------------------------------------------------------------
+; Areacosinus hyperbolicus: D0.S-->D0.S == ln[x+sqrt(x*x-1)]
+
+S_facosh:
+ movem.l d1-d2,-(a7) ; Register sichern
+ move.l d0,d2 ; Argument sichern
+ move.l #eins,d1 ; Argument <1 ?
+ bsr S_fcmp
+ bmi.s S_facosh_errval
+ move.l d2,d0 ; Argument zurueck
+ move.l d0,d1 ; quadrieren
+ bsr S_fmul
+ move.l #eins,d1 ; 1 abziehen
+ bsr S_fsub
+ bsr S_fsqrt ; Wurzel ziehen
+ move.l d2,d1 ; Argument addieren
+ bsr S_fadd
+ bsr S_fln ; Logarithmus des ganzen
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+S_facosh_errval:
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ move.l #$ffc00000,d0 ; NAN zurueckgeben
+ rts
+
+;-----------------------------------------------------------------------------
+; Areatangens hyperbolicus: D0.S-->D0.S == 0.5*ln((1+x)/(1-x))
+
+S_fatanh:
+ movem.l d1-d2,-(a7) ; Register sichern
+ move.l d0,d2 ; Argument sichern
+ bclr #31,d0 ; Vorzeichen weg
+ cmp.l #eins,d0
+ beq.s S_fatanh_inf ; =1-->INF
+ bhi.s S_fatanh_errval ; >1-->NAN
+ move.l d2,d1 ; Nenner berechnen
+ move.l #eins,d0
+ bsr S_fsub
+ exg d0,d2 ; Zaehler berechnen
+ move.l #eins,d1
+ bsr S_fadd
+ move.l d2,d1 ; Quotient daraus
+ bsr S_fdiv
+ bsr S_fln ; logarithmieren
+ move.w #-1,d1 ; halbieren
+ bsr S_fmul2
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+S_fatanh_inf:
+ move.l #$ff000000,d0 ; vorzeichenbehaftete Unend-
+ roxr.l #1,d0 ; lichkeit
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+S_fatanh_errval:
+ move.l #$7fc00000,d0 ; NAN geben
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Areakotangens hyperbolicus: D0.S--> D0.S == 0.5*ln((1+x)/(x-1))
+
+S_facoth:
+ movem.l d1-d2,-(a7) ; Register sichern
+ move.l d0,d2 ; Argument sichern
+ roxl.l #1,d0 ; Vorzeichen in X-Flag
+ cmp.l #eins*2,d0
+ beq.s S_facoth_inf ; =1-->INF
+ bmi.s S_facoth_errval ; <1-->NAN
+ move.l d2,d0 ; Nenner berechnen
+ move.l #eins,d1
+ bsr S_fsub
+ exg d0,d2 ; Zaehler berechnen
+ move.l #eins,d1
+ bsr S_fadd
+ move.l d2,d1 ; Quotient daraus
+ bsr S_fdiv
+ bsr S_fln ; logarithmieren
+ move.w #-1,d1 ; halbieren
+ bsr S_fmul2
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+S_facoth_inf:
+ move.l #$ff000000,d0 ; vorzeichenbehaftete Unend-
+ roxr.l #1,d0 ; lichkeit
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+S_facoth_errval:
+ move.l #$7fc00000,d0 ; NAN geben
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Kosinusfunktion: D0.S--> D0.S
+
+ ds 0
+S_fcos:
+ movem.l d1-d6,-(a7) ; Register retten
+ bclr #31,d0 ; cos(-x)=cos(x)
+
+ move.l #pi2,d1 ; auf Bereich 0..2*Pi reduzieren
+S_fcos_subtr:
+ cmp.l d1,d0 ; x>=2*Pi ?
+ blo.s S_fcos_subend ; ja-->Ende
+ bchg #31,d1 ; fuer Subtraktion
+ bsr S_fadd ; reduzieren
+ bchg #31,d1 ; Subtrahend wieder richtig
+ bra.s S_fcos_subtr
+S_fcos_subend:
+ cmp.l #pi,d0 ; x>Pi ?
+ blo.s S_fcos_nosub
+ exg d0,d1 ; ja-->cos(x)=cos(2*Pi-x)
+ bsr S_fsub
+S_fcos_nosub:
+ move.l d0,d1 ; wir brauchen nur x^2
+ bsr S_fmul
+ bset #31,d0
+ move.l d0,d3 ; -x^2 in D3
+ move.l d0,d4 ; D4 enthaelt laufende Potenz von x^2
+ ; inkl. Vorzeichen
+ move.l #zwei,d5 ; D5 enthaelt laufende Fakultaet
+ move.l #eins,d2 ; D2 enthaelt Summe
+ moveq.l #2,d6 ; D6 enthaelt Zaehler
+S_fcos_loop:
+ move.l d5,d1 ; s:=s+yz/zaehler
+ move.l d4,d0
+ bsr S_fdiv
+ move.l d2,d1
+ bsr S_fadd
+ cmp.l d2,d0 ; Veraendert sich Summe noch ?
+ beq.s S_fcos_end
+ move.l d0,d2
+ addq.b #2,d6 ; i:=i+1
+ cmp.b #22,d6 ; i=11 ?
+ beq.s S_fcos_end
+ move.w d6,d0 ; Fakultaet erhhen: *(2n-1)*(2n)
+ mulu.w d6,d0 ; =4*n^2-2*n
+ sub.w d6,d0
+ bsr S_fitof ; dazumultiplizieren
+ move.l d5,d1
+ bsr S_fmul
+ move.l d0,d5
+ move.l d4,d0 ; yz:=yz*y
+ move.l d3,d1
+ bsr S_fmul
+ move.l d0,d4
+ bra.s S_fcos_loop
+S_fcos_end:
+ ; Ergebnis bereits in D0
+ movem.l (a7)+,d1-d6 ; Register zurueck
+ rts
+
+;----------------------------------------------------------------------------
+; Sinus : D0.S-->D0.S
+
+S_fsin:
+ move.l d1,-(a7) ; Register retten
+ move.l #pihalf,d1 ; sin(x)=cos(x-pi/2)
+ bsr S_fsub
+ bsr S_fcos
+ move.l (a7)+,d1 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Tangens: D0.S-->D0.S
+
+S_ftan:
+ movem.l d1-d4,-(a7) ; Register retten
+ tst.l d0 ; Vorzeichen merken
+ smi d4
+ bclr #31,d0
+ move.l #pi,d1 ; auf Bereich 0..Pi reduzieren
+S_ftan_subtr:
+ cmp.l d1,d0 ; x>=Pi ?
+ blo.s S_ftan_subend ; ja-->Ende
+ bchg #31,d1 ; fuer Subtraktion
+ bsr S_fadd ; reduzieren
+ bchg #31,d1 ; Subtrahend wieder richtig
+ bra.s S_ftan_subtr
+S_ftan_subend:
+ move.l d0,d2 ; Argument merken
+ bsr S_fcos ; Nenner rechnen
+ move.l d0,d3 ; Nenner merken
+ move.l d0,d1 ; sqr(1-x^2) rechnen
+ bsr S_fmul
+ move.l d0,d1
+ move.l #eins,d0
+ bsr S_fsub
+ bsr S_fsqrt
+ move.l d3,d1
+ bsr S_fdiv ; Quotient
+ tst.b d4 ; Vorzeichen dazu
+ beq.s S_ftan_noneg
+ bchg #31,d0
+S_ftan_noneg:
+ movem.l (a7)+,d1-d4 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Kotangens: D0.S-->D0.S
+
+S_fcot:
+ movem.l d1-d4,-(a7) ; Register retten
+ tst.l d0 ; Vorzeichen merken
+ smi d4
+ bclr #31,d0
+ move.l #pi,d1 ; auf Bereich 0..Pi reduzieren
+S_fcot_subtr:
+ cmp.l d1,d0 ; x>=Pi ?
+ blo.s S_fcot_subend ; ja-->Ende
+ bchg #31,d1 ; fuer Subtraktion
+ bsr S_fadd ; reduzieren
+ bchg #31,d1 ; Subtrahend wieder richtig
+ bra.s S_fcot_subtr
+S_fcot_subend:
+ move.l d0,d2 ; Argument merken
+ bsr S_fcos ; Zaehler rechnen
+ move.l d0,d3 ; Zaehler merken
+ move.l d0,d1 ; sqr(1-x^2) rechnen
+ bsr S_fmul
+ move.l d0,d1
+ move.l #eins,d0
+ bsr S_fsub
+ bsr S_fsqrt
+ move.l d0,d1
+ move.l d3,d0
+ bsr S_fdiv ; Quotient
+ tst.b d4 ; Vorzeichen dazu
+ beq.s S_fcot_noneg
+ bchg #31,d0
+S_fcot_noneg:
+ movem.l (a7)+,d1-d4 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Arcustangens: D0.S-->D0.S
+
+S_fatan:
+ movem.l d1-d6,-(a7) ; Register sichern
+ subq.l #2,a7 ; Platz fuer Hilfsvariablen
+ tst.l d0 ; Vorzeichen merken...
+ smi (a7)
+ bclr #31,d0 ; ...und loeschen
+ cmp.l #eins,d0 ; Argument>1 ?
+ shi 1(a7) ; ja :
+ bls.s S_fatan_no1 ; nein :
+ move.l d0,d1 ; ja : Kehrwert bilden
+ move.l #eins,d0
+ bsr S_fdiv
+S_fatan_no1:
+ move.l #3,d2 ; Zaehler initialisieren
+ move.l d0,d5 ; Summe initialisieren
+ move.l d0,d4 ; laufende Potenz = x^1
+ move.l d0,d1 ; x^2 berechnen
+ bsr S_fmul
+ move.l d0,d3
+ bset #31,d3 ; immer mit -x^2 multiplizieren
+S_fatan_loop:
+ move.l d4,d0 ; naechste Potenz ausrechnen
+ move.l d3,d1
+ bsr S_fmul
+ move.l d0,d4
+ move.l d2,d0 ; Nenner in Gleitkomma
+ bsr S_fitof
+ move.l d0,d1 ; Division ausfuehren
+ move.l d4,d0
+ bsr S_fdiv
+ move.l d5,d1 ; zur Summe addieren
+ bsr S_fadd
+ cmp.l d0,d5 ; noch signifikant ?
+ beq.s S_fatan_endloop ; nein-->Ende
+ move.l d0,d5
+ addq.l #2,d2 ; Zaehler erhoehen
+ cmp.l #61,d2 ; fertig ?
+ bne.s S_fatan_loop
+S_fatan_endloop:
+ move.l d5,d0 ; Ergebnis in D0 bringen
+ tst.b 1(a7) ; war Argument < 1 ?
+ beq.s S_fatan_not2
+ bchg #31,d0 ; ja : Erg.=Pi/2-Erg
+ move.l #pihalf,d1
+ bsr S_fadd
+S_fatan_not2:
+ tst.b (a7) ; Vorzeichen dazu
+ beq.s S_fatan_not1
+ bset #31,d0
+S_fatan_not1:
+ addq.l #2,a7 ; Hilfsvar. abraeumen
+ movem.l (a7)+,d1-d6 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Arcuskotangens: D0.S-->D0.S
+
+S_facot:
+ move.l d1,-(a7) ; Register sichern
+ bsr S_fatan ; acot(x)=pi/2-atan(x)
+ bchg #31,d0
+ move.l #pihalf,d1
+ bsr S_fadd
+ move.l (a7)+,d1 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Arcussinus: D0.S --> D0.S
+
+S_fasin:
+ movem.l d1-d2,-(a7) ; Register retten
+ move.l d0,d2 ; Argument merken
+ move.l d0,d1 ; Quadrat berechnen
+ bsr S_fmul
+ bset #31,d0 ; 1-x^2 bilden
+ move.l #eins,d1
+ bsr S_fadd
+ tst.l d0 ; Sonderfaelle abfangen
+ bmi.s S_fasin_errval ; <0 geht nicht
+ beq.s S_fasin_inf ; Endwerte
+ bsr S_fsqrt ; Wurzel ...
+ move.l d0,d1 ; ... und Quotient
+ move.l d2,d0
+ bsr S_fdiv
+ bsr S_fatan ; zuletzt das wichtigste
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+S_fasin_errval:
+ move.l #$7fc00000,d0 ; NAN zurueckgeben
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+S_fasin_inf:
+ move.l #pihalf,d0 ; +- pi/2 zurueckgeben
+ and.l #$80000000,d2 ; Vorzeichen dazu
+ or.l d2,d0
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+
+;-----------------------------------------------------------------------------
+; Arcuskosinus: D0.S --> D0.S
+
+S_facos:
+ tst.l d0 ; Argument=0 ?
+ beq.s S_facos_inf
+ move.l d0,d2 ; Argument merken
+ move.l d0,d1 ; Quadrat berechnen
+ bsr S_fmul
+ bset #31,d0 ; 1-x^2 bilden
+ move.l #eins,d1
+ bsr S_fadd
+ tst.l d0 ; Sonderfaelle abfangen
+ bmi.s S_facos_errval ; <0 geht nicht
+ bsr S_fsqrt ; Wurzel ...
+ move.l d2,d1 ; ... und Quotient
+ bsr S_fdiv
+ bsr S_fatan ; zuletzt das wichtigste
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+S_facos_errval:
+ move.l #$7fc00000,d0 ; NAN zurueckgeben
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+S_facos_inf:
+ move.l #pihalf,d0 ; +- pi/2 zurueckgeben
+ and.l #$80000000,d2 ; Vorzeichen dazu
+ or.l d2,d0
+ movem.l (a7)+,d1-d2 ; Register zurueck
+ rts
+
+S_floatlibend:
diff --git a/tests/t_parsys/float81.i68 b/tests/t_parsys/float81.i68
new file mode 100644
index 0000000..ed5a3dc
--- /dev/null
+++ b/tests/t_parsys/float81.i68
@@ -0,0 +1,293 @@
+;----------------------------------------------------------------------------
+; Fliesskommaroutinen fuer den PcPar68000 - Version mit 68881
+
+;-----------------------------------------------------------------------------
+; Definitionen:
+
+CoConst1 equ $32 ; Offsets im Konstantenrom
+CoConstPi equ 0 ; des 6888x
+
+;-----------------------------------------------------------------------------
+; Librarykopf:
+
+
+S_Float81Lib: dc.l S_float81libend-S_float81libstart ; Laenge
+S_float81libstart:
+ dc.l -1 ; Speicher fuer Zeiger
+ dc.b "FLOAT",0 ; Name
+ ds 0
+
+
+;-----------------------------------------------------------------------------
+; Sprungtabelle:
+
+ bra.l S_fadd_co68
+ bra.l S_fsub_co68
+ bra.l S_fmul_co68
+ bra.l S_fdiv_co68
+ bra.l S_fsqrt_co68
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_fcmp_co68
+ bra.l S_fitof_co68
+ bra.l S_fftoi_co68
+ bra.l S_fabs_co68
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_fexp_co68
+ bra.l S_fsinh_co68
+ bra.l S_fcosh_co68
+ bra.l S_ftanh_co68
+ bra.l S_fcoth_co68
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_fln_co68
+ bra.l S_flog_co68
+ bra.l S_fasinh_co68
+ bra.l S_facosh_co68
+ bra.l S_fatanh_co68
+ bra.l S_facoth_co68
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_fsin_co68
+ bra.l S_fcos_co68
+ bra.l S_ftan_co68
+ bra.l S_fcot_co68
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_float81libnop
+ bra.l S_fasin_co68
+ bra.l S_facos_co68
+ bra.l S_fatan_co68
+ bra.l S_facot_co68
+
+S_float81libnop: rts
+
+;----------------------------------------------------------------------------
+
+ fpu on
+S_fadd_co68:
+ addq.l #1,_fadd_cnt.w
+ fmove.s d0,fp0
+ fadd.s d1,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fsub_co68:
+ addq.l #1,_fadd_cnt.w
+ fmove.s d0,fp0
+ fsub.s d1,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fmul_co68:
+ addq.l #1,_fmul_cnt.w
+ fmove.s d0,fp0
+ fsglmul.s d1,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fdiv_co68:
+ addq.l #1,_fdiv_cnt.w
+ fmove.s d0,fp0
+ fsgldiv.s d1,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fmul2_co68:
+ addq.l #1,_fmul_cnt.w
+ fmove.s d0,fp0
+ fscale.w d1,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fitof_co68:
+ fmove.l d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fftoi_co68:
+ fmove.s d0,fp0
+ fmove.l fp0,d0
+ rts
+
+
+S_fsqrt_co68:
+ addq.l #1,_fsqrt_cnt.w
+ fsqrt.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fabs_co68: bclr #31,d0 ; ganz einfach...
+ rts
+
+
+S_fcmp_co68:
+ fmove.s d0,fp0
+ fcmp.s d1,fp0
+ fbeq.l S_fcmp_coeq ; Variante 1:gleich
+ fbgt.l S_fcmp_cogt ; Variante 2:groeer
+
+ moveq #1,d0 ; Bedingung "kleiner"
+ cmp.w #2,d0 ; erzeugen
+ rts
+S_fcmp_cogt:
+ moveq #2,d0 ; Bedingung "groesser"
+ cmp.w #1,d0 ; erzeugen
+ rts
+S_fcmp_coeq:
+ cmp.w d0,d0 ; Bedingung "gleich"
+ rts ; erzeugen
+
+
+S_fexp_co68:
+ fetox.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fsinh_co68:
+ fsinh.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fcosh_co68:
+ fcosh.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_ftanh_co68:
+ ftanh.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fcoth_co68:
+ fmove.s d0,fp0
+ fsinh.x fp0,fp1
+ fcosh.x fp0
+ fsgldiv.x fp1,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fln_co68:
+ flogn.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_flog_co68:
+ flog10.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fasinh_co68:
+ fmove.s d0,fp0
+ fmove.x fp0,fp1
+ fmul.x fp1,fp0
+ fmovecr.x #CoConst1,fp2
+ fadd.x fp2,fp0
+ fsqrt.x fp0
+ fadd.x fp1,fp0
+ flogn.x fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_facosh_co68:
+ fmove.s d0,fp0
+ fmove.x fp0,fp1
+ fmul.x fp1,fp0
+ fmovecr.x #CoConst1,fp2
+ fsub.x fp2,fp0
+ fsqrt.x fp0
+ fadd.x fp1,fp0
+ flogn.x fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fatanh_co68:
+ fatanh.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_facoth_co68:
+ fmovecr.x #CoConst1,fp0
+ fdiv.s d0,fp0
+ fatanh.x fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fcos_co68:
+ fcos.s d0,fp0
+ fmove.x fp0,d0
+ rts
+
+
+S_fsin_co68:
+ fsin.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_ftan_co68:
+ ftan.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fcot_co68:
+ fsincos.s d0,fp0:fp1
+ fsgldiv.x fp1,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fatan_co68:
+ fatan.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_facot_co68:
+ fatan.s d0,fp1
+ fmovecr.x #CoConstPi,fp0
+ fscale.w #-1,fp0
+ fsub.x fp1,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_fasin_co68:
+ fasin.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+
+S_facos_co68:
+ facos.s d0,fp0
+ fmove.s fp0,d0
+ rts
+
+S_float81libend:
+
+ fpu off
+
diff --git a/tests/t_parsys/parsys.i68 b/tests/t_parsys/parsys.i68
new file mode 100644
index 0000000..e5a2569
--- /dev/null
+++ b/tests/t_parsys/parsys.i68
@@ -0,0 +1,115 @@
+; Includedatei PcPar-System
+; vor dem Programm mit include einbinden
+
+;----------------------------------------------------------------------------
+; offizieller Datenbereich:
+
+ shared S_RegSave,S_MemEnd,S_ParNo,S_CPUNo
+ shared _fadd_cnt,_fmul_cnt,_fdiv_cnt,_fsqrt_cnt
+
+ org $400
+S_MemEnd:
+ ds.l 1 ; Speicherende ( Default 64K )
+S_SysStart:
+ ds.l 1 ; Anfang des Systemcodes
+S_ParNo: ; vom PC geschiebene Werte
+ ds.w 1 ; Parallelrechneradresse
+S_LibAdr: ; Adresse der Library-
+ ds.l 1 ; sprungtabelle
+_fadd_cnt: ; Anzahl ausgefuehrter Gleit-
+ ds.l 1 ; kommaadditionen/subtraktion
+_fmul_cnt: ; dito Multiplikation
+ ds.l 1
+_fdiv_cnt: ; dito Division
+ ds.l 1
+_fsqrt_cnt: ; dito Quadratwurzel
+ ds.l 1
+S_FreeMemEnd:
+ ds.l 1 ; Ende freien Speichers
+S_CPUNo:
+ ds.w 1 ; CPU-Typ: 0 = 68008
+ ; 1 = 68000
+ ; 2 = 68010
+ ; 3 = 68020
+ ; 4 = 68030
+ ; Byte 1 : $01 = 68881
+ ; $02 = 68882
+ ; $10 = 68851
+ org $600
+
+S_SSPEnd:
+ ds.l 1 ; Anfang des Systemstacks
+S_ResVecSave: ; Sicherung Resetvektor
+ ds.l 1
+S_RegSave: ; Registersicherung
+ ds.l 17 ; wird vom PC veraendert
+S_ExVec: ; Exceptionvektor
+ ds.w 1
+S_LibStart:
+ ds.l 1 ; Anfang Librarykette
+ org $800
+
+;-----------------------------------------------------------------------------
+; Libraryoffsets :
+
+fadd equ $0000
+fsub equ $0004
+fmul equ $0008
+fdiv equ $000c
+fmul2 equ $0010
+fsqrt equ $0014
+fabs equ $0018
+
+fcmp equ $0020
+fitof equ $0024
+fftoi equ $0028
+
+fexp equ $0040
+fsinh equ $0044
+fcosh equ $0048
+ftanh equ $004c
+fcoth equ $0050
+
+fln equ $0060
+flog equ $0064
+fasinh equ $0068
+facosh equ $006c
+fatanh equ $0070
+facoth equ $0074
+
+fsin equ $0080
+fcos equ $0084
+ftan equ $0088
+fcot equ $008c
+
+fasin equ $00a0
+facos equ $00a4
+fatan equ $00a8
+facot equ $00ac
+
+;----------------------------------------------------------------------------
+; Konstanten fuer Betriebssystemaufrufe:
+
+TrapProgEnd equ 15 ; Trap fuer Programmende
+
+TrapTglSStep equ 14 ; Trap Einzelschritt an/aus
+
+TrapLibCtrl equ 13 ; Trap Libraryverwaltung
+LibCtrlInstall equ 0
+LibCtrlGetAdr equ 1
+
+;----------------------------------------------------------------------------
+; andere Konstanten:
+
+S_Latch equ $fffffffe ; Adresse der I/O-Latches
+
+is68008 equ $00 ; Prozessorcode 68008
+is68000 equ $01 ; " 68000
+is68010 equ $02 ; " 68010
+is68020 equ $03 ; " 68020
+is68030 equ $04 ; " 68030
+has68881 equ $01 ; " 68881
+has68882 equ $02 ; " 68882
+hasMMU equ $10 ; " 68851
+intMMU equ $20 ; " interne MMU
+
diff --git a/tests/t_parsys/t_parsys.asm b/tests/t_parsys/t_parsys.asm
new file mode 100644
index 0000000..8afe6f3
--- /dev/null
+++ b/tests/t_parsys/t_parsys.asm
@@ -0,0 +1,994 @@
+ include parsys.i68
+
+ page 60
+ cpu 68000
+
+;-----------------------------------------------------------------------------
+; Die Exceptionvektoren:
+
+ supmode on
+
+ org $00000000 ; Die Vektoren
+ dc.l 0 ; Adresse vom Stack (Dummy)
+ dc.l Start ; erster Start
+ dc.l ex_vec2 ; Busfehler
+ dc.l ex_vec3 ; Adressfehler
+ dc.l ex_vec4 ; Illegaler Befehl
+ dc.l ex_vec5 ; Division durch Null
+ dc.l ex_vec6 ; Befehl CHK
+ dc.l ex_vec7 ; Befehl TRAPV
+ dc.l ex_vec8 ; Privilegverletzung
+ dc.l StepProc ; Ablaufverfolgung
+ dc.l ex_vec10 ; Line-A --> Gleitkomma
+ dc.l S_LineF ; Line-F --> 68881-Emulator
+ dc.l ex_vec12 ; Reserviert
+ dc.l ex_vec13 ; Koprozessor-Protokollfehler
+ dc.l ex_vec14 ; illegaler FRESTORE-Frame
+ dc.l ex_vec15 ; nicht initialisierter Unterbrechungsvektor
+ dc.l ex_vec16 ; Reserviert
+ dc.l ex_vec17 ; Reserviert
+ dc.l ex_vec18 ; Reserviert
+ dc.l ex_vec19 ; Reserviert
+ dc.l ex_vec20 ; Reserviert
+ dc.l ex_vec21 ; Reserviert
+ dc.l ex_vec22 ; Reserviert
+ dc.l ex_vec23 ; Reserviert
+ dc.l ex_vec24 ; Unechte Unterbrechung
+ dc.l ex_vec25 ; autovektoriell 1
+ dc.l ex_vec26 ; autovektoriell 2
+ dc.l ex_vec27 ; autovektoriell 3
+ dc.l ex_vec28 ; autovektoriell 4
+ dc.l ex_vec29 ; autovektoriell 5
+ dc.l ex_vec30 ; autovektoriell 6
+ dc.l ex_vec31 ; autovektoriell 7
+ dc.l PcSysCall ; Trap #0 --> PC-Kommunikation
+ dc.l ex_vec33 ; Trap #1
+ dc.l ex_vec34 ; Trap #2
+ dc.l ex_vec35 ; Trap #3
+ dc.l ex_vec36 ; Trap #4
+ dc.l ex_vec37 ; Trap #5
+ dc.l ex_vec38 ; Trap #6
+ dc.l ex_vec39 ; Trap #7
+ dc.l ex_vec40 ; Trap #8
+ dc.l ex_vec41 ; Trap #9
+ dc.l ex_vec42 ; Trap #10
+ dc.l ex_vec43 ; Trap #11
+ dc.l ex_vec44 ; Trap #12
+ dc.l S_LibFun ; Trap #13 --> Libraryverwaltung
+ dc.l S_StepTgl ; Trap #14 --> Trace an/aus
+ dc.l S_ProgEnd ; Trap #15 --> Programmende
+ dc.l ex_vec48 ; BSUN in FPU gesetzt
+ dc.l ex_vec49 ; FPU inexaktes Ergebnis
+ dc.l ex_vec50 ; FPU Division durch 0
+ dc.l ex_vec51 ; FPU Unterlauf
+ dc.l ex_vec52 ; FPU Operandenfehler
+ dc.l ex_vec53 ; FPU Ueberlauf
+ dc.l ex_vec54 ; FPU signaling NAN
+ dc.l ex_vec55 ; reserviert
+ dc.l ex_vec56 ; MMU Konfigurationsfehler
+ dc.l ex_vec57 ; MMU Illegale Operation
+ dc.l ex_vec58 ; MMU Zugriffsfehler
+ ; Vektoren 59..255 frei
+
+;----------------------------------------------------------------------------
+; Installationssequenz:
+
+ org $800
+start:
+ clr.w S_Latch.w ; Port nullen
+
+ and.b #$fc,S_MemEnd+3.w ; Speichergroesse auf Lang-
+ ; wortadresse ausrichten
+ move.l S_MemEnd.w,a7 ; SSP setzen
+
+ lea -256(a7),a0 ; SSP-Anfang in A0
+ move.l a0,S_SSPEnd.w ; sichern
+
+ lea S_End.w,a1 ; Codelaenge berechnen
+ lea S_Start.w,a2
+ sub.l a2,a1 ; A1=Laenge Systemcode
+ moveq #4,d0 ; auf mehrfaches von 4 aus-
+ sub.w a1,d0 ; richten
+ and.l #3,d0
+ add.l d0,a1
+
+ sub.l a1,a0 ; Start des Systemcodes rechnen
+ move.l a0,S_SysStart.w ; sichern
+ move.l a0,$4.w ; =Programmstart
+
+ move.l a1,d0 ; Systemcode umkopieren
+ lsr.l #2,d0 ; =Zahl Langworttransfers
+ subq.w #1,d0 ; wg. DBRA
+S_SysCopy: move.l (a2)+,(a0)+
+ dbra d0,S_SysCopy
+
+ sub.l a2,a0 ; Verschiebedifferenz rechnen
+ move.l a0,d1
+
+ lea 8.w,a1 ; alle Vektoren relozieren
+ moveq #45,d0
+S_RelVec: add.l d1,(a1)+
+ dbra d0,S_RelVec
+
+ move.l S_SysStart.w,a1 ; obere Speichergrenze in USP...
+ move a1,usp
+ move.l a1,S_FreeMemEnd.w ; und Variable
+
+ move.l #-1,S_LibStart.w; Librarykette leer
+
+ lea S_floatlib.w,a0 ; passende FloatLib installieren
+ btst #0,S_Latch+1.w ; 68881 vorhanden ?
+ bne.s S_NoCo81
+ lea S_float81lib.w,a0 ; ja-->andere Library
+S_NoCo81: moveq #LibCtrlInstall,d0 ; einschreiben
+ trap #TrapLibCtrl
+
+ moveq #LibCtrlGetAdr,d0 ; Adresse holen
+ lea S_LibName.w,a0
+ trap #TrapLibCtrl
+ move.l d0,S_LibAdr.w
+
+ move.l 4*4.w,a4 ; Exceptionvektoren 4 und 11 retten
+ move.l 11*4.w,a5
+ move.l sp,a6 ; SP retten
+ move.l #S_NoCPU,4*4.w ; neue Exceptionhandler einschreiben
+ move.l #S_NoMMU,11*4.w
+ moveq #is68008,d1 ; Prozessorcode loeschen
+
+ cpu 68030 ; fuer zus. Befehle
+
+ ori #1,ccr ; 68008 ausfiltern
+ moveq #is68000,d1
+
+ movec vbr,d0 ; geht erst ab 68010
+ moveq #is68010,d1
+
+ extb d0 ; geht erst ab 68020
+ moveq #is68020,d1
+
+ cpu 68000 ; nicht mehr gebraucht
+ fpu on ; dafuer dies
+
+S_NoCPU: btst #0,S_Latch+1.w ; FPU vorhanden ?
+ bne.s S_NoFPU ; nein-->
+ or.w #has68881,d1 ; ja : 68881 annehmen
+ fnop ; FPU idle machen, damit im folgenden
+ fsave -(sp) ; ein idle frame gespeichert wird
+ cmp.b #$18,1(sp) ; Framelaenge=$18 fuer 68881, $38 fuer 882
+ beq.s S_NoFPU
+ add.w #(has68882-has68881),d1 ; 68882 eintragen
+
+ fpu off ; FPU nicht mehr gebraucht
+ pmmu on ; dafuer die MMU
+
+S_NoFPU: move.l a4,4*4.w ; Exception 4 zuruecksetzen
+ pflusha ; dies versteht auch die 68030-MMU
+ add.w #hasMMU,d1 ; gefunden: Flag dazu
+ move.l #S_SmallMMU,11*4.w ; testen ob Schmalspur-MMU
+ psave -(sp)
+ bra.s S_NoMMU ; Ergebnis 68020/68851
+
+S_SmallMMU: move.b #is68030,d1 ; 68030 eintragen (nicht MOVEQ!!)
+ add.w #(intMMU-hasMMU),d1 ; Code interne MMU
+
+S_NoMMU: move.l a5,11*4.w ; Line-F-Vektor zuruecksetzen
+ move.l a6,sp ; SP restaurieren
+ move.w d1,S_CPUNo.w ; Ergebnis einschreiben
+
+ trap #TrapProgEnd
+
+S_LibName: dc.b "FLOAT",0
+
+;----------------------------------------------------------------------------
+; Gleitkommalibrary, ohne 68881:
+
+ supmode off
+
+ include float.i68
+
+;----------------------------------------------------------------------------
+; Gleitkommalibrary, mit 68881:
+
+ supmode off
+
+ include float81.i68
+
+;----------------------------------------------------------------------------
+; Die Startsequenz:
+
+ supmode on
+
+S_Start: clr.w S_Latch.w ; Ports loeschen
+ clr.l _fadd_cnt.w ; Zielvariablen loeschen
+ clr.l _fmul_cnt.w
+ clr.l _fdiv_cnt.w
+ clr.l _fsqrt_cnt.w
+
+ move.l S_MemEnd.w,d0 ; SSP an Speicherende legen
+ move.l d0,$0.w ; Neben Resetvekor vermerken
+ move.l d0,a7 ; SSP setzen
+ move.l S_FreeMemEnd.w,a0 ; USP liegt am Speicherende
+ move a0,usp
+
+ andi #$dfff,sr ; In Usermodus schalten
+ jmp Start.w ; zum Programmstart
+
+;----------------------------------------------------------------------------
+; Die Ausnahmebehandlungsprozeduren:
+
+ex_vec2:
+ move.w #2,S_ExVec.w
+ bra.l ex_handle
+ex_vec3:
+ move.w #3,S_ExVec.w
+ bra.l ex_handle
+ex_vec4:
+ move.w #4,S_ExVec.w
+ bra.l ex_handle
+ex_vec5:
+ move.w #5,S_ExVec.w
+ bra.l ex_handle
+ex_vec6:
+ move.w #6,S_ExVec.w
+ bra.l ex_handle
+ex_vec7:
+ move.w #7,S_ExVec.w
+ bra.l ex_handle
+ex_vec8:
+ move.w #8,S_ExVec.w
+ bra.l ex_handle
+ex_vec10:
+ move.w #10,S_ExVec.w
+ bra.l ex_handle
+ex_vec11:
+ move.w #0,S_Control+S_Response.w ; FPU resetten
+ move.w #11,S_ExVec.w
+ bra.l ex_handle
+ex_vec12:
+ move.w #12,S_ExVec.w
+ bra.l ex_handle
+ex_vec13:
+ move.w #13,S_ExVec.w
+ bra.l ex_handle
+ex_vec14:
+ move.w #14,S_ExVec.w
+ bra.l ex_handle
+ex_vec15:
+ move.w #15,S_ExVec.w
+ bra.l ex_handle
+ex_vec16:
+ move.w #16,S_ExVec.w
+ bra.l ex_handle
+ex_vec17:
+ move.w #17,S_ExVec.w
+ bra.l ex_handle
+ex_vec18:
+ move.w #18,S_ExVec.w
+ bra.l ex_handle
+ex_vec19:
+ move.w #19,S_ExVec.w
+ bra.l ex_handle
+ex_vec20:
+ move.w #20,S_ExVec.w
+ bra.l ex_handle
+ex_vec21:
+ move.w #21,S_ExVec.w
+ bra.l ex_handle
+ex_vec22:
+ move.w #22,S_ExVec.w
+ bra.l ex_handle
+ex_vec23:
+ move.w #23,S_ExVec.w
+ bra.l ex_handle
+ex_vec24:
+ move.w #24,S_ExVec.w
+ bra.l ex_handle
+ex_vec25:
+ move.w #25,S_ExVec.w
+ bra.l ex_handle
+ex_vec26:
+ move.w #26,S_ExVec.w
+ bra.l ex_handle
+ex_vec27:
+ move.w #27,S_ExVec.w
+ bra.l ex_handle
+ex_vec28:
+ move.w #28,S_ExVec.w
+ bra.l ex_handle
+ex_vec29:
+ move.w #29,S_ExVec.w
+ bra.l ex_handle
+ex_vec30:
+ move.w #30,S_ExVec.w
+ bra.l ex_handle
+ex_vec31:
+ move.w #31,S_ExVec.w
+ bra.l ex_handle
+ex_vec33:
+ move.w #33,S_ExVec.w
+ bra.l ex_handle
+ex_vec34:
+ move.w #34,S_ExVec.w
+ bra.l ex_handle
+ex_vec35:
+ move.w #35,S_ExVec.w
+ bra.l ex_handle
+ex_vec36:
+ move.w #36,S_ExVec.w
+ bra.l ex_handle
+ex_vec37:
+ move.w #37,S_ExVec.w
+ bra.l ex_handle
+ex_vec38:
+ move.w #38,S_ExVec.w
+ bra.l ex_handle
+ex_vec39:
+ move.w #39,S_ExVec.w
+ bra.l ex_handle
+ex_vec40:
+ move.w #40,S_ExVec.w
+ bra.l ex_handle
+ex_vec41:
+ move.w #41,S_ExVec.w
+ bra.l ex_handle
+ex_vec42:
+ move.w #42,S_ExVec.w
+ bra.l ex_handle
+ex_vec43:
+ move.w #43,S_ExVec.w
+ bra.l ex_handle
+ex_vec44:
+ move.w #44,S_ExVec.w
+ bra.l ex_handle
+ex_vec48:
+ move.w #48,S_ExVec.w
+ bra.l ex_handle
+ex_vec49:
+ move.w #49,S_ExVec.w
+ bra.l ex_handle
+ex_vec50:
+ move.w #50,S_ExVec.w
+ bra.l ex_handle
+ex_vec51:
+ move.w #51,S_ExVec.w
+ bra.l ex_handle
+ex_vec52:
+ move.w #52,S_ExVec.w
+ bra.l ex_handle
+ex_vec53:
+ move.w #53,S_ExVec.w
+ bra.l ex_handle
+ex_vec54:
+ move.w #54,S_ExVec.w
+ bra.l ex_handle
+ex_vec55:
+ move.w #55,S_ExVec.w
+ bra.l ex_handle
+ex_vec56:
+ move.w #56,S_ExVec.w
+ bra.l ex_handle
+ex_vec57:
+ move.w #57,S_ExVec.w
+ bra.l ex_handle
+ex_vec58:
+ move.w #58,S_ExVec.w
+
+ex_handle:
+ movem.l d0-d7/a0-a7,S_RegSave.w ; Wert der Register abspeichern
+ move usp,a0
+ move.l a0,S_RegSave+64.w
+ lea S_Latch.w,a0
+ move.w S_ExVec.w,d0 ; Vektornr. holen
+ move.b d0,1(a0) ; Fehlernr. ausgeben
+ex_infinite:
+ move.b d0,d1 ; Die LED n-mal blinken lassen ; Die LED n-mal blinken lassen
+ex_blink:
+ bset #0,(a0) ; LED an
+ bsr.s ex_wait
+ bclr #0,(a0) ; LED aus
+ bsr.s ex_wait
+ subq.b #1,d1
+ bne.s ex_blink
+ move.b #$05,d1 ; eine Pause einlegen
+ex_pause:
+ bsr.s ex_wait
+ subq.b #1,d1
+ bne.s ex_pause
+ bra.s ex_handle ; und alles von vorne
+
+ex_wait:
+ move.l d0,-(a7) ; Register retten
+ move.l #$50000,d0 ; ungefaehr 1/2 Sekunde
+ex_wloop: ; Register herunterzaehlen
+ subq.l #1,d0
+ bne.s ex_wloop
+ move.l (a7)+,d0 ; D0 wieder zurueck
+ rts
+
+;----------------------------------------------------------------------------
+; Einzelschrittverfolgung:
+
+StepProc:
+ clr.b S_Latch+1.w
+ movem.l d0-d7/a0-a7,S_RegSave.w ; Register retten
+ move usp,a0
+ move.l a0,S_RegSave+64.w
+ move.l $4.w,S_ResVecSave.w ; Resetvektor sichern
+ lea S_Restart(pc),a0 ; am Punkt S_StepBack wacht
+ move.l a0,$4.w ; der PcPar wieder auf
+ move.b #9,S_Latch+1.w ; ParMon-Aufruf ausgeben
+ stop #$2000 ; hier geht es nur mit einem
+ ; Reset weiter
+
+;----------------------------------------------------------------------------
+; Routinen zur Kommunikation mit dem PC (Trap 0)
+
+PcSysCall:
+ clr.b S_Latch+1.w
+ movem.l d0-d7/a0-a7,S_RegSave.w ; Register retten
+ move usp,a0
+ move.l a0,S_RegSave+64.w
+ move.l $4.w,S_ResVecSave.w ; Resetvektor sichern
+ lea S_Restart(pc),a0 ; am Punkt S_Restart wacht
+ move.l a0,$4.w ; der PcPar wieder auf
+ move.b #$40,S_Latch+1.w ; PC-Aufruf ausgeben
+ stop #$2000 ; hier geht es nur mit einem
+
+S_Restart:
+ clr.b S_Latch+1.w ; Systemanfrage loeschen
+ move.l S_ResVecSave.w,$4.w ; Resetvektor zurueck
+ move.l S_RegSave+64.w,a0
+ move a0,usp
+ movem.l S_RegSave.w,d0-d7/a0-a7 ; Register zurueckholen
+ rte ; das war's
+
+;----------------------------------------------------------------------------
+; Libraryverwaltung : Trap #13
+;
+; Struktur einer Library :
+;
+; Adresse 0: Laenge in Bytes (1 <= Laenge <= 256k)
+; Adresse 4: Dummyzeiger =-1 (vom System verwendet) \
+; Adresse 8: Libraryname als ASCIIZ-String | kopierter Block
+; Adresse n: Sprungtabelle |
+; Adresse m: Librarycode, private Daten /
+;
+; der gesamte Librarycode muss lageunabhaengig geschrieben sein !
+;
+; definierte Unterfunktionen:
+;
+; D0.L=0 : Library installieren
+; D0.L=1 : Libraryzeiger holen
+;
+;----------------------------------------------------------------------------
+
+; Subfunktion 0: Library von Adresse 0 installieren:
+; Eingabe: A0=Startadresse der Library
+; Ausgabe: keine
+
+S_LibFun: movem.l d1-d2/a1-a2,-(a7) ; Register sichern
+ tst.l d0 ; ist es Funktion 0 ?
+ bne.s S_LibFun1 ; nein-->bei Funktion 1 weitertesten
+
+ move.l (a0),d0 ; Laenge Library holen
+ addq.l #3,d0 ; auf Doppelworte aufrunden
+ and.b #$fc,d0
+ moveq #1,d1
+ cmp.l #$40000,d0 ; Maximalgroesse ueberschritten ?
+ bge.l S_LibErr ; ja-->Ende mit Fehler Nr.1
+
+ move usp,a1 ; Userstack holen
+ move.l S_FreeMemEnd.w,d2 ; mom. belegte Stackmenge berechnen
+ sub.l a1,d2
+ move.l a1,a2 ; neue Untergrenze in A2 rechnen
+ sub.l d0,a2
+ moveq #2,d1
+ cmp.l #$800,a2 ; unter abs. Untergrenze gesunken ?
+ ble.l S_LibErr ; ja-->Ende mit Fehler Nr.2
+
+ move a2,usp ; neuen Userstack einschreiben
+ lsr.l #1,d2 ; Stackgroesse in Worten
+ bra.s S_LibStckEnd ; damit Ende, falls kein Stack belegt
+
+S_LibStckCpy: move.w (a1)+,(a2)+ ; Userstack umkopieren
+S_LibStckEnd: dbra d2,S_LibStckCpy
+
+ move.l S_FreeMemEnd.w,a1 ; Startadresse der Library rechnen
+ sub.l d0,a1 ; =altes Speicherende-Laenge
+ addq.l #4,a0 ; Quellzeiger weitersetzen
+ move.l S_LibStart.w,d1 ; bisheriges Ende der Kette holen
+ move.l d1,(a0) ; in neue Library eintragen
+ move.l a1,S_FreeMemEnd.w ; Speichergrenze heruntersetzen
+ move.l a1,S_LibStart.w ; neuen Kettenanfang eintragen
+
+ lsr.l #2,d0 ; Laenge in Doppelworte umrechnen
+ subq.w #1,d0 ; wg. DBRA
+
+S_LibInstLoop: move.l (a0)+,(a1)+ ; Library umkopieren
+ dbra d0,S_LibInstLoop
+
+ bra.l S_LibOK ; Ende ohne Fehler
+
+; Subfunktion 1: Library finden, deren Name ab (A0) als ASCIIZ steht:
+; Eingabe: A0=Startadresse des ASCIIZ-Strings
+; Ausgabe: D0=Startadresse der Sprungtabelle
+
+S_LibFun1: subq.l #1,d0 ; ist es Funktion 1 ?
+ bne.s S_LibFun2 ; nein-->bei Funktion 2 weitertesten
+
+ move.l S_LibStart.w,a2 ; Wurzelzeiger der Kette holen
+
+S_LibGetLoop: moveq #3,d1 ; Kettenende erreicht ?
+ move.l a2,d0
+ addq.l #1,d0 ; wird durch -1 angezeigt
+ beq.l S_LibErr ; ja-->Ende mit Fehler
+
+ move.l a0,d0 ; Startadresse Vergleichsstring retten
+ lea 4(a2),a1 ; A1 zeigt auf zu testenden Namen
+S_LibGetComp: cmpm.b (a0)+,(a1)+ ; ein Zeichen vergleichen
+ bne.s S_LibGetNext ; ungleich-->weiter in Kette
+ tst.b -1(a0) ; War das das Ende ?
+ beq.s S_LibGetFnd ; ja-->Heureka!
+ bra.s S_LibGetComp ; ansonsten naechstes Zeichen vergleichen
+
+S_LibGetNext: move.l (a2),a2 ; weiter auf Nachfolger in Kette
+ move.l d0,a0 ; A0 auf Referenzstringanfang
+ bra.s S_LibGetLoop
+
+S_LibGetFnd: move.l a1,d0 ; Libraryadresse gerade machen
+ addq.l #1,d0
+ bclr #0,d0
+
+ bra.l S_LibOK ; Ende ohne Fehler
+
+S_LibFun2: moveq #127,d1 ; unbekannte Funktion:
+ bra.l S_LibErr
+
+S_LibErr: move.l d1,d0 ; Fehlercode in D0 holen
+ movem.l (a7)+,d1-d2/a1-a2 ; Register zurueck
+ or.b #1,1(a7) ; Carry setzen
+ rte
+
+S_LibOK: movem.l (a7)+,d1-d2/a1-a2 ; Register zurueck
+ and.b #$fe,1(a7) ; Carry loeschen
+ rte
+
+;----------------------------------------------------------------------------
+; Tracemode ein/aus:
+
+S_StepTgl:
+ andi #$7fff,sr ; bitte hier kein Trace!
+ bclr #7,(a7) ; altes T-Flag loeschen
+ btst #0,1(a7)
+ bne.s S_StepOn ; C=1-->Tracemodus an
+ rte ; C=0-->fertig
+S_StepOn:
+ bset #7,(a7) ; T-Flag setzen
+ rte
+
+;----------------------------------------------------------------------------
+; Programmende (Trap 15)
+
+S_ProgEnd: lea S_Start(pc),a0 ; Startvektor zurueck
+ move.l a0,4.w
+ move.b #$ff,S_Latch+1.w ; "Ich bin fertig"
+ stop #$2000 ; und Ende
+
+;----------------------------------------------------------------------------
+; Line-F-Exception
+
+S_Response equ $fffffe00 ; In a6 (Coprozessor-Register)
+S_Control equ $02 ; Alle weiteren Register relativ
+S_Save equ $04 ; zu "Response"
+S_Restore equ $06
+S_Command equ $0a ; in a5
+S_Condition equ $0e
+S_Operand equ $10 ; in a4
+S_Reg_Selec equ $14
+S_Ins_Add equ $18
+
+ supmode on
+
+S_LineF: btst #0,S_Latch+1.w ; Ist ein Koprozessor vorhanden ?
+ bne ex_vec11 ; nein-->normaler Line-F
+
+ movem.l d0-d7/a0-a6,S_RegSave.w ; Register retten
+ move.l usp,a0 ; USP retten
+ move.l a0,S_RegSave+60.w ; (geht nur ueber Umweg)
+ lea S_Response.w,a6 ; #response nach A6
+ lea S_Command(a6),a5 ; #command nach A5
+ lea S_Operand(a6),a6 ; #operand nach A4
+ lea S_RegSave.w,a3 ; #dregs nach A3
+ move.l 2(a7),a0 ; PC nach A0
+ move.w (a0),d1 ; Kommando nach D1
+S_again: ; Einsprung fuer weitere FPU-Befehle
+ and.w #%0000000111000000,d1 ; Spezialteil ausmaskieren
+ bne S_spezial ; Ein Bit gesetzt-->Spezialbefehl
+ move.w 2(a0),d1 ; zweiten Befehlsteil in D1 merken
+ move.w d1,(a5) ; Befehl in FPU schr. (A5==#command)
+S_do_ca: ; Einsprung fuer weitere Nachfragen an FPU
+ move.w (a6),d0 ; Response lesen
+ btst #12,d0 ; Erstes Modusbit testen
+ bne S_rw_1x ; ==1 --> springen
+ btst #11,d0 ; Zweites Modusbit testen
+ beq.s S_rw_00 ; ==0 --> springen
+; ----- %xxx01, Null-Primitive/Transfer Single CPU Register
+ btst #10,d0 ; Register uebertragen ?
+ bne.s S_rw_sngl ; Ja--> Transfer Single CPU-Register
+ btst #15,d0 ; CA (Come Again) gesetzt ?
+ bne.s S_do_ca ; Ja--> weiter fragen, sonst fertig
+ addq.l #4,a0 ; A0 um reine Befehlslaenge weiter
+ ; ( alles andere wurde in calc_add erledigt )
+ move.w (a0),d1 ; erstes Befehlswort holen
+ move.w d1,d0 ; und nach D0
+ and.w #$f000,d0 ; Wieder COP-Befehl ?
+ eor.w #$f000,d0
+ beq.s S_again ; Ja-->direkt weitermachen
+ move.l a0,2(a7) ; Neuen PC eintragen
+ move.l S_RegSave+60.w,a0 ; USP wiederherstellen
+ move.l a0,usp ; (geht nur ueber Umweg)
+ movem.l (a3),d0-a6 ; Register wiederherstellen
+ rte ; Trap beenden
+S_rw_sngl:
+ and.w #%1110000,d1 ; Registernummer ausmaskieren ( nur Dn )
+ lsr.w #2,d1 ; D1=Nummer*4
+ move.l 0(a3,d1.w),(a4) ; Register uebertragen (a4==#operand, a3==#dregs)
+ bra.s S_do_ca ; danach kommt immer noch etwas
+;-----%xxx00, Transfer multiple coprocessor Reg.
+S_rw_00:
+ bsr S_calc_add ; Operandenadresse nach A1 holen
+ move.w S_Reg_Selec(a6),d4 ; Registerliste nach D4 holen
+ btst #13,d0 ; Dr-Bit testen
+ beq.s S_w_00 ; ==0--> Daten in FPU schreiben
+ btst #12,d0 ; Predekrementmodus ?
+ beq.s S_r_pred ; ==0--> Ja,springen
+ moveq #7,d0 ; Schleifenzaehler fuer 8 Bits
+S_11:
+ lsl.w #1,d4 ; Ein Bit ins Carry
+ bcc.s S_21 ; nur bei Bit==1 etwas machen
+ move.l (a4),(a1)+ ; 1 (A4==#operand)
+ move.l (a4),(a1)+ ; 2
+ move.l (a4),(a1)+ ; 3 Langworte fuer jedes Register
+S_21:
+ dbra d0,S_11 ; Fuer alle 8 Bits
+ bra.s S_do_ca ; Nochmal FPU befragen
+S_r_Pred:
+ moveq #7,d0 ; Schleifenzaehler fuer 8 Bits
+S_12:
+ lsl.w #1,d4 ; Ein Bit ins Carry
+ bcc.s S_22 ; nur bei Bit=1 etwas machen
+ move.l (a4),(a1)+ ; 1 (A4==#operand)
+ move.l (a4),(a1)+ ; 2
+ move.l (a4),(a1)+ ; 3 Langworte fuer jedes Register
+ suba.w #24,a1 ; Dekrement durchfuehren
+S_22:
+ dbra d0,S_12 ; Fuer alle 8 Bits
+ adda.w #12,a1 ; A1 wieder auf letztes Register
+ move.l a1,(a2) ; A1 als Registerinhalt abspeichern
+ bra S_do_ca ; Nochmal FPU befragen
+S_w_00:
+ move.w (a0),d0 ; erstes Befehlswort holen
+ and.b #%111000,d0 ; Adressierungsart maskieren
+ cmp.b #%011000,d0 ; Gleich (An)+ ?
+ beq.s S_w_Post ; Ja-->Postinkrementiermodus
+ moveq #7,d0 ; Schleifenzaehler fuer 8 Bits
+S_13:
+ lsl.w #1,d4 ; Ein Bit ins Carry
+ bcc.s S_23 ; Nur bei Bit==1 etwas machen
+ move.l (a1)+,(a4) ; 1 (A4==#operand)
+ move.l (a1)+,(a4) ; 2
+ move.l (a1)+,(a4) ; 3 Langworte fuer jedes Register
+S_23:
+ dbra d0,S_13 ; Fuer alle 8 Bits
+ bra S_do_ca ; Nochmal FPU befragen
+S_w_Post:
+ suba.w #12,a1 ; Inkrement von calc_add aufheben
+ moveq #7,d0 ; Schleifenzaehler fuer 8 Bits
+S_14:
+ lsl.w #1,d4 ; Ein Bit ins Carry
+ bcc.s S_24 ; nur bei Bit==1 etwas machen
+ move.l (a1)+,(a4) ; 1 (A4==#operand)
+ move.l (a1)+,(a4) ; 2
+ move.l (a1)+,(a4) ; 3 Langworte fuer jedes Register
+S_24:
+ dbra d0,S_14 ; Fuer alle 8 Bits
+ move.l a1,(a2) ; A1 als Registerinhalt abspeichern
+ bra S_do_ca ; Nochmal FPU befragen
+
+S_rw_1x:
+ btst #11,d0 ; zweites Modusbit testen
+ bne.s S_rw_11 ; ==1 --> springen (Trap,Error)
+ btst #13,d0 ; DR-Bit testen
+ beq.s S_w_10 ; ==0 --> Daten an FPU schreiben
+;----- %xx110, evaluate effective adress and transfer data
+ bsr S_calc_add ; Operandenadresse berechnen
+ ; A1=Operandenadresse, d1.l=Operandenl„nge
+ cmp.w #2,d1 ; Laenge-2
+ ble.s S_r_bw ; <=2 --> Wort-oder-Byteoperand
+S_r_11:
+ move.l (a4),(a1)+ ; ein Langwort lesen (A4==#operand)
+ subq.l #4,d1 ; und runterzaehlen
+ bgt.s S_r_11 ; >0 --> weiter uebertragen
+ bra S_do_ca ; Nochmal FPU befragen
+S_r_bw:
+ btst #0,d1 ; Byte ?
+ bne.s S_r_byte ; Ja!
+ move.w (a4),(a1) ; Wort-Operand lesen (A4==#operand)
+ bra S_do_ca ; Nochmal FPU befragen
+S_r_byte:
+ move.b (a4),(a1) ; Byte-Operand lesen (A4==#operand)
+ bra.l S_do_ca ; Nochmal FPU befragen
+
+;----- %xx101, evaluate effective adress and transfer data
+S_w_10:
+ bsr S_calc_add ; Operandenadresse berechnen
+ ; A1=Operandenadresse, d1.l=Operandenl„nge
+ cmp.w #2,d1 ; Laenge-2
+ ble.s S_w_bw ; <=2 --> Wort-oder-Byteoperand
+S_w_11:
+ move.l (a1)+,(a4) ; ein Langwort lesen (A4==#operand)
+ subq.l #4,d1 ; und runterzaehlen
+ bgt.s S_w_11 ; >0 --> weiter uebertragen
+ bra S_do_ca ; Nochmal FPU befragen
+S_w_bw:
+ btst #0,d1 ; Byte ?
+ bne.s S_w_byte ; Ja!
+ move.w (a1),(a4) ; Wort-Operand lesen (A4==#operand)
+ bra S_do_ca ; Nochmal FPU befragen
+S_w_byte:
+ move.b (a1),(a4) ; Byte-Operand lesen (A4==#operand)
+ bra.l S_do_ca ; Nochmal FPU befragen
+
+;----- %xxx11, take pre-instruction exception
+S_rw_11:
+ bra ex_vec11 ; Error-Handler anspringen
+; ( hier koennte man eine genauere Fehleranalyse machen )
+
+S_spezial: ; Sprungbefehle etc.
+ cmp.w #%001000000,d1 ; FScc,FDBcc oder FTRAPcc
+ beq.s S_s_trap
+ cmp.w #%010000000,d1 ; Branch mit 16-Bit-Offset
+ beq.l S_s_br16
+ cmp.w #%011000000,d1 ; Branch mit 32-Bit-Offset
+ beq.l S_s_br32
+ bra ex_vec11 ; FSAVE/FRESTORE nicht unterstuetzt
+S_s_trap:
+ move.w (a0),d0 ; Erstes Befehlswort nach D0
+ move.w d0,d1 ; und nach D1 retten
+ and.w #%111000,d0 ; Wichtige Bits ausmaskieren
+ cmp.w #%001000,d0 ; FDBcc ?
+ beq.s S_s_fdbcc ; Ja-->springen
+ cmp.w #%111000,d0 ; FTRAP ?
+ beq ex_vec11 ; Ja-->Fehler (nicht unterstuetzt)
+ ; sonst FScc
+ move.w 2(a0),S_condition(a6) ; Bedingung an FPU schicken
+ moveq #1,d0 ; Operandenlaenge=1 (fuer calc_add)
+ bsr S_calc_add ; Operandenadresse berechnen
+S_15:
+ move.w (a6),d0 ; Response lesen
+ btst #8,d0 ; IA-Bit testen
+ beq.s S_25 ; ==0 --> fertig
+ and.w #%1100000000000,d0 ; Bits 11 und 12 ausmaskieren
+ eor.w #%1100000000000,d0 ; Beide gesetzt ?
+ bne.s S_15 ; Nicht beide==1 --> warten
+ bra ex_vec11 ; Sonst ist Exception aufgetreten
+S_25:
+ btst #0,d0 ; Antwortbit testen
+ sne (a1) ; Je nach Bit setzen/loeschen
+ bra S_do_ca ; Nochmal FPU befragen
+S_s_fdbcc:
+ move.w 2(a0),S_condition(a6) ; Bedingung an FPU schicken
+ and.w #%111,d1 ; Registernummer maskieren (D1=(A0))
+ lsl.w #2,d1 ; D1=Nummer*4
+ lea 0(a3,d1.w),a1 ; A1 enthaelt Adresse des Datenreg.
+ move.l (a1),d1 ; Dn holen
+ subq.w #1,d1 ; Dn=Dn-1
+ move.l d1,(a1) ; Dn zurueckschreiben
+ move.l a0,a2 ; alten PC nach A2 holen
+ addq.l #2,a0 ; PC 2 weiter ( fuer "nicht springen")
+S_16:
+ move.w (a6),d0 ; Response lesen
+ btst #8,d0 ; IA-Bit testen
+ beq.s S_26 ; ==0 --> fertig
+ and.w #%1100000000000,d0 ; Bits 11 und 12 ausmaskieren
+ eor.w #%1100000000000,d0 ; Beide gesetzt ?
+ bne.s S_16 ; Nicht beide==1 --> warten
+ bra ex_vec11 ; Sonst ist Exception aufgetreten
+S_26:
+ btst #0,d0 ; Antwortbit testen
+ bne S_do_ca ; True-->das war's schon
+ adda.w 2(a2),a2 ; 16-Bit-Sprungdist. add. (A2=PC)
+ addq.w #1,d1 ; Dn=-1 ?
+ beq S_do_ca ; Ja-->kein Sprung (Schleifenende)
+ move.l a2,a0 ; Sonst "Sprung" (neuen PC laden)
+ bra S_do_ca ; nochmal FPU befragen
+S_s_br16:
+ move.w (a0),S_Condition(a6) ; Bedingung an FPU schicken
+S_17:
+ move.w (a6),d0 ; Response lesen
+ btst #8,d0 ; IA-Bit testen
+ beq.s S_27 ; ==0 --> fertig
+ and.w #%1100000000000,d0 ; Bits 11 und 12 ausmaskieren
+ eor.w #%1100000000000,d0 ; Beide gesetzt ?
+ bne.s S_17 ; Nicht beide==1 --> warten
+ bra ex_vec11 ; Sonst ist Exception aufgetreten
+S_27:
+ btst #0,d0 ; Antwortbit testen
+ beq S_do_ca ; False--> das war's schon
+ adda.w 2(a0),a0 ; 16-Bit-Sprungdistanz addieren
+ subq.l #2,a0 ; Ein Wort zurueck ( weil spaeter
+ ; noch 4 addiert wird und und nur 2 addiert werden muesste )
+ bra S_do_ca ; Nochmal FPU befragen
+S_s_br32:
+ move.w (a0),S_Condition(a6) ; Bedingung an FPU schicken
+S_18:
+ move.w (a6),d0 ; Response lesen
+ btst #8,d0 ; IA-Bit testen
+ beq.s S_28 ; ==0 --> fertig
+ and.w #%1100000000000,d0 ; Bits 11 und 12 ausmaskieren
+ eor.w #%1100000000000,d0 ; Beide gesetzt ?
+ bne.s S_18 ; Nicht beide==1 --> warten
+ bra ex_vec11 ; Sonst ist Exception aufgetreten
+S_28:
+ addq.l #2,a0 ; Befehl ist 3 Worte lang
+ ; (jetzt : (A0)=Distanz)
+ btst #0,d0 ; Antwortbit testen
+ beq S_do_ca ; False--> das war's schon
+ adda.l (a0),a0 ; 32-Bit-Sprungdistanz addieren
+ subq.l #4,a0 ; Zwei Worte zurueck ( weil spaeter
+ ; noch 4 addiert wird, 2 wurden schon addiert )
+ bra S_do_ca ; Nochmal FPU befragen
+S_calc_add:
+ ; Operandenadresse berechnen. A0 muss die Adresse des Line-F-
+ ; Befehls enthalten, D0 im unteren Byte die Operandenlaenge.
+ ; die zu berechnende Adresse wird in A1 abgelegt. A0 wird
+ ; um die Laenge der zusaetzlichen Daten erhaelt.
+ ; Zusaetzlich wird in D1 die Laenge des Operanden zurueckge-
+ ; geben (in Bytes, als Langwort). D2,D3,A3 werden zerstoert.
+ ; Bei den Adressierungsarten -(An),(An)+ steht in A2 ein
+ ; Zeiger auf die Stelle, in der der Inhalt des Adressregisters
+ ; gisters An steht (wird fuer FMOVEM gebraucht).
+
+ clr.l d1 ; Laenge als Langwort loeschen
+ move.b d0,d1 ; und Byte umkopieren
+ move.w (a0),d2 ; erstes Befehlswort nach D2
+ move.w d2,d3 ; und D3 retten
+ and.w #%111000,d3 ; Adressierungsart ausmaskieren
+ lsr.w #1,d3 ; D3=Adressierungsart*4 (Langworte)
+ lea S_cs_tab(pc),a1 ; Sprungtabellenadresse nach A1
+ move.l 0(a1,d3.w),a1 ; Adresse der Routine nach A1
+ jmp (a1) ; und Routine anspringen
+S_c_drd: ; %000 Data Register Direct: Dn
+S_c_ard: ; %001 Address Register Direct: An
+ lea (a3),a1 ; A1 auf Registerfeld
+ and.w #%1111,d2 ; Registernummer ausmaskieren
+; ( und ein Bit vom Modus, 0 fuer Daten-,1 fuer Adressregister )
+ lsl.w #2,d2 ; D2="Registernummer"*4 (+Modusbit)
+ addq.w #4,d2 ; +4 (fuer Operandenlaenge)
+ sub.w d1,d2 ; Wahre Laenge abziehen
+ adda.w d2,a1 ; Offset auf Registerfeldanfang add.
+ rts
+S_c_ari: ; %010 Address Register indirect: (An)
+ and.w #%111,d2 ; Registernummer ausmaskieren
+ lsl.w #2,d2 ; D2=Registernummer*4
+ move.l 32(a3,d2.w),a1 ; Adresse nach A1
+ rts
+S_c_arpo: ; %011 Adressregister indirect with Postincrement: (An)+
+ and.w #%111,d2 ; Registernummer ausmaskieren
+ lsl.w #2,d2 ; D2=Registernummer*4
+ lea 32(a3,d2.w),a2 ; Adresse Adressregister nach A2
+ move.l (a2),a1 ; Adresse (Inhalt A.-Reg.) nach A1
+ btst #0,d1 ; D1 ungerade ? (Byteoperand)
+ bne.s S_29 ; Ja-->Spezialbehandlung
+S_19:
+ add.l d1,(a2) ; Inkrement durchfuehren
+ rts
+S_29:
+ cmp.w #4*7,d2 ; Ist A7 gemeint ?
+ bne.s S_19 ; nein-->normal vorgehen
+ addq.l #2,(a2) ; Sonst (bei Byte) 2 addieren,
+ rts ; damit Stack gerade bleibt!
+S_c_arpr: ; %100 Adressregister Indirect with Predekrement: -(An)
+ and.w #%111,d2 ; Registernummer ausmaskieren
+ lsl.w #2,d2 ; D2=Registernummer*4
+ lea 32(a3,d2.w),a2 ; Adresse des Adressreg. nach A2
+ btst #0,d1 ; D1 ungerade? (Byteoperand)
+ bne.s S_210 ; Ja-->Spezialbehandlung
+S_110:
+ sub.l d1,(a2) ; Dekrement durchfuehren
+ move.l (a2),a1 ; Adresse (Inhalt des A.-Reg) nach A1
+ rts
+S_210:
+ cmp.w #4*7,d2 ; Ist A7 gemeint?
+ bne.s S_110 ; nein-->normal vorgehen
+ subq.l #2,(a2) ; Sonst (bei Byte) 2 addieren,
+ ; damit Stack gerade bleibt !
+ move.l (a2),a1 ; Adresse (Inhalt des A.-Reg) nach A1
+ rts
+S_c_ar16: ; %101 Addressregister Indirect with Displacement: d16(An)
+ and.w #%111,d2 ; Registernummer ausmaskieren
+ lsl.w #2,d2 ; D2=Registernummer*4
+ move.l 32(a3,d2.w),a1 ; Adresse nach A1
+ move.w 4(a0),d2 ; 3.Befehlswort nach D2 (Offset)
+ adda.w d2,a1 ; Offset auf Adresse addieren
+ addq.l #2,a0 ; A0 ein Wort (d16) weiter
+ rts
+S_c_ar08: ; %110 Addressregister Indirect with Index : d8(An,Xn)
+ and.w #%111,d2 ; Registernummer ausmaskieren
+ lsl.w #2,d2 ; D2=Registernummer*4
+ move.l 32(a3,d2.w),a1 ; Adresse nach A1
+ move.w 4(a0),d2 ; 3.Befehlswort nach D2 (Byte-Offset)
+ move.w d2,d3 ; und nach D3
+ and.w #$ff,d3 ; Byte ausmaskieren (Byte-Offset)
+ adda.w d3,a1 ; Offset auf Adresse addieren
+ btst #11,d2 ; 1=long; 0=word
+ bne.s S_c_ar81
+ and.w #%1111000000000000,d2 ; Nummer von Dn und Modusbit
+ lsr.w #5,d2 ; maskieren
+ lsr.w #5,d2 ; D2=Registernummer*4 (und modusbit)
+ adda.w 2(a3,d2.w),a1 ; 16-Bit-Index auf A1 addieren
+ addq.l #2,a0 ; A0 ein Wort (Kram & d8) weiter
+ rts
+S_c_ar81:
+ and.w #%1111000000000000,d2 ; Nummer von Dn und Modusbit
+ lsr.w #5,d2 ; maskieren
+ lsr.w #5,d2 ; D2=Registernummer*4 (und modusbit)
+ adda.w 0(a3,d2.w),a1 ; 32-Bit-Index auf A1 addieren
+ addq.l #2,a0 ; A0 ein Wort (Kram & d8) weiter
+ rts
+S_c_pc: ; %111 absolut short/long, PC-relativ (ohne/mit Index) \ oder direkt
+ btst #2,d2 ; Immidiate ?
+ bne.s S_immi ; <>0 --> Ja!
+ btst #1,d2 ; PC-relativ ?
+ bne.s S_pc_rel ; <>0 --> Ja!
+ btst #0,d2 ; Long ?
+ bne.s S_c_long ; <>0 --> Ja!
+ ; sonst short
+ move.w 4(a0),d2 ; Wortadresse holen
+ ext.l d2 ; Auf Langwort erweitern
+ move.l d2,a1 ; und als Operandenadresse merken
+ addq.l #2,a0 ; A0 ein Wort (Short-A.) weiter
+ rts
+S_c_long:
+ move.l 4(a0),a1 ; Langwortadresse holen
+ addq.l #4,a0 ; A0 zwei Worte (Long-A.) weiter
+ rts
+S_immi:
+ move.l a0,a1 ; Befehlsadresse nach A1
+ add.l d1,a0 ; A0 ueber Operand hinwegsetzen
+ rts
+S_pc_rel:
+ btst #0,d2 ; mit Index ?
+ bne.s S_pc_idx ; <>0 --> Ja!
+ move.l a0,a1 ; PC nach A1
+ adda.w 4(a0),a1 ; Offset addieren
+ addq.l #4,a1 ; +4 fuer Laenge des FPU-Befehls
+ addq.l #2,a0 ; A0 zwei (16-Bit-Offset) weiter
+ rts
+S_pc_idx:
+ move.l a0,a1 ; PC nach A1
+ clr.w d2 ; Oberes Byte loeschen
+ move.b 5(a0),d2 ; Offset nach D2
+ adda.w d2,a1 ; und addieren
+ addq.l #4,a1 ; +4 fuer Laenge des FPU-Befehls
+ move.b 4(a0),d2 ; D2=Registernummer*16 und Modusbit
+ ; ( high-Byte ist noch 0 )
+ btst #3,d2 ; Long-Bit testen
+ bne.s S_pc_i_l ; <>0 -->Long-Index
+ and.b #%11110000,d2 ; Registerinformation ausblenden
+ lsr.w #2,d2 ; D2=Registernummer*4 (und Modusbit)
+ adda.w 2(a3,d2.w),a1 ; Word-Index addieren
+ addq.l #2,a0 ; A0 zwei (8-Bit-Offset & Kram) weiter
+ rts
+S_pc_i_l:
+ and.b #%11110000,d2 ; Restinformation ausblenden
+ lsr.w #2,d2 ; D2=Registernummer*4 (und Modusbit)
+ adda.l 0(a3,d2.w),a1 ; Long-Index addieren
+ addq.l #2,a0 ; A0 zwei (8-Bit-Offset & Kram) weiter
+ rts ; Ende von S_calc_add
+
+S_cs_tab:
+ dc.l S_c_drd,S_c_ard,S_c_ari,S_c_arpo ; Sprungtabelle fuer
+ dc.l S_c_arpr,S_c_ar16,S_c_ar08,S_c_pc ; Adressierungsarten
+S_End:
+
diff --git a/tests/t_parsys/t_parsys.doc b/tests/t_parsys/t_parsys.doc
new file mode 100644
index 0000000..10d31c7
--- /dev/null
+++ b/tests/t_parsys/t_parsys.doc
@@ -0,0 +1,8 @@
++---------------------- Test Application PARSYS ----------------------------+
+| |
+| Back to the roots! This is the "operating system" of my 68000-based par- |
+| allel computer I built several years ago and which was the main reason to |
+| write my own assembler because the original one from RDK was too buggy to |
+| work reliably with it. Contains also a lot of FPU orders. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_parsys/t_parsys.inc b/tests/t_parsys/t_parsys.inc
new file mode 100644
index 0000000..7ffd805
--- /dev/null
+++ b/tests/t_parsys/t_parsys.inc
@@ -0,0 +1,10 @@
+(* tests/t_parsys/t_parsys.asm-Includefile für CONST-Sektion *)
+S_RegSave = $608;
+S_MemEnd = $400;
+S_ParNo = $408;
+S_CPUNo = $422;
+_fadd_cnt = $40E;
+_fmul_cnt = $412;
+_fdiv_cnt = $416;
+_fsqrt_cnt = $41A;
+(* Ende Includefile für CONST-Sektion *)
diff --git a/tests/t_parsys/t_parsys.ori b/tests/t_parsys/t_parsys.ori
new file mode 100644
index 0000000..d26be99
--- /dev/null
+++ b/tests/t_parsys/t_parsys.ori
Binary files differ
diff --git a/tests/t_scmp/asflags b/tests/t_scmp/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_scmp/asflags
diff --git a/tests/t_scmp/t_scmp.asm b/tests/t_scmp/t_scmp.asm
new file mode 100644
index 0000000..0fdc8ca
--- /dev/null
+++ b/tests/t_scmp/t_scmp.asm
@@ -0,0 +1,59 @@
+ cpu sc/mp
+
+ lde
+ xae
+ ane
+ ore
+ xre
+ dae
+ ade
+ cae
+
+ sio
+ sr
+ srl
+ rr
+ rrl
+
+ halt
+ ccl
+ scl
+ dint
+ ien
+ csa
+ cas
+ nop
+
+ ldi 0x12
+ ani 0x23
+ ori 0x34
+ xri 0x45
+ dai 0x56
+ adi 0x67
+ cai 0x78
+ dly 0x89
+
+ xpal pc
+ xpah p2
+ xppc p1
+
+ ld e(pc)
+ st @e(p2)
+ and 10(p1)
+ or @-20(p3)
+ xor vari
+vari: dad -30(p2)
+ add @40(p1)
+ cad vari
+
+ jmp vari
+ jp 10(p2)
+ jz vari
+ jnz vari
+
+ ild vari
+ dld -5(p2)
+
+; org 0xfff
+; ldi 0x20
+
diff --git a/tests/t_scmp/t_scmp.doc b/tests/t_scmp/t_scmp.doc
new file mode 100644
index 0000000..8c863b8
--- /dev/null
+++ b/tests/t_scmp/t_scmp.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application SCMP ----------------------------+
+| |
+| This is a (synthetic) test of the SC/MP code generator |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_scmp/t_scmp.ori b/tests/t_scmp/t_scmp.ori
new file mode 100755
index 0000000..75684f1
--- /dev/null
+++ b/tests/t_scmp/t_scmp.ori
Binary files differ
diff --git a/tests/t_secdrive/asflags b/tests/t_secdrive/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_secdrive/asflags
diff --git a/tests/t_secdrive/lowlevel.inc b/tests/t_secdrive/lowlevel.inc
new file mode 120000
index 0000000..968acf7
--- /dev/null
+++ b/tests/t_secdrive/lowlevel.inc
@@ -0,0 +1 @@
+wd1003at.inc \ No newline at end of file
diff --git a/tests/t_secdrive/secparam.inc b/tests/t_secdrive/secparam.inc
new file mode 100644
index 0000000..8bf8381
--- /dev/null
+++ b/tests/t_secdrive/secparam.inc
@@ -0,0 +1,1619 @@
+;*****************************************************************************
+;* Sekund„rlaufwerkstreiber, Modul SecParam *
+;* liefert Laufwerksparameter, falls fehlend im Bootsektor *
+;* stellt das ganze Formatiermen zur Verfgung *
+;*****************************************************************************
+
+ section SecParam
+
+;*****************************************************************************
+;* gemeinsam benutzte Meldungen *
+;*****************************************************************************
+
+TrackMsg db "Spur (0..Spurzahl-1) : $"
+HeadMsg db "Kopf (0..Kopfzahl-1) : $"
+ConfirmMsg db "Sind Sie sicher ?$"
+InterleaveMsg db "Interleave (1..Sektorzahl-1) : $"
+
+;*****************************************************************************
+;* Routine BreakOnESC *
+;* schaut nach, ob ESC gedrckt wurde *
+;* Ausgabe: C=1, falls ja *
+;*****************************************************************************
+
+ GlobProc BreakOnESC
+
+ push ax ; Register retten
+ mov ah,1 ; Tastaturpuffer antesten
+ int INT_Keyboard
+ clc ; Annahme nicht gedrckt
+ jz Ende
+ mov ah,0 ; Zeichen da: dies abholen
+ int INT_Keyboard
+ cmp al,ESC ; ist es ESC ?
+ clc ; Annahme nein
+ jne Ende
+ stc ; jawoll!
+Ende: pop ax ; Register zurck
+ ret
+
+ endp
+
+;*****************************************************************************
+;* Routine YesNo *
+;* fragt nach Ja oder Nein *
+;* Ausgabe: C=0, falls ja *
+;*****************************************************************************
+
+ proc YesNo
+
+ push ax ; Register retten
+
+QueryLoop: mov ah,DOS_RdChar ; ein Zeichen lesen
+ int INT_DOS
+
+ cmp al,'a' ; Kleinbuchstaben ?
+ jb Upper
+ cmp al,'z'
+ ja Upper
+ add al,'A'
+ sub al,'a'
+Upper:
+ cmp al,'J' ; akzeptierte Zeichen fr Ja
+ clc
+ je YNDone
+ cmp al,'Y'
+ clc
+ je YNDone
+ cmp al,'N' ; akzeptierte Zeichen fr Nein
+ stc
+ je YNDone
+
+ PrChar BEL ; alles andere anmeckern
+ jmp QueryLoop
+
+YNDone: PrChar al ; Zeichen als Echo ausgeben
+ PrChar CR ; Zeilenvorschub
+ PrChar LF
+ pop ax ; Register zurck
+
+ ret
+
+ endp
+
+;*****************************************************************************
+;* Routine ReadNumber *
+;* liest einen Wert von 0..n in AX ein *
+;* Eingabe: AX = Maximalwert *
+;* DI = Zeiger auf Meldung *
+;* Ausgabe: AX = eingelesene Zahl *
+;*****************************************************************************
+
+ proc ReadNumber
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push si
+
+ mov si,ax ; Maximalwert retten
+InLoop: mov dx,di ; Meldung ausgeben
+ mov ah,DOS_WrString
+ int INT_DOS
+ lea dx,[KeyBuffer] ; Zahl als String einlesen
+ mov ah,DOS_RdString
+ int INT_DOS
+ PrChar CR
+ PrChar LF
+ mov ax,0 ; jetzt Zeichen verarbeiten
+ mov cl,[KeyBuffer+1]
+ mov ch,0
+ lea bx,[KeyBuffer+2]
+ jcxz InvFormat ; Nullschleife abfangen
+ConvLoop: mov dx,10 ; bisheriges Ergebnis hochmultiplizieren
+ mul dx
+ mov dl,[bx] ; ein Zeichen holen
+ inc bx
+ sub dl,'0' ; ASCII-Offset abziehen
+ jc InvFormat ; bei Formatfehler abbrechen
+ cmp dl,9 ; nur 0..9 erlaubt
+ ja InvFormat
+ add al,dl ; dazuaddieren
+ adc ah,0
+ loop ConvLoop
+ jmp ChkRange ; fertig: weiter zur Bereichsprfung
+InvFormat: PrMsg InvMsg ; wenn fehlerhaft, meckern
+ jmp InLoop ; und nochmal versuchen
+ChkRange: cmp ax,si ; auáerhalb Bereich ?
+ jbe OK
+ PrMsg OverMsg ; ja: meckern...
+ jmp InLoop ; ...und auf ein neues
+
+OK: pop si ; Register zurck
+ pop dx
+ pop cx
+ pop bx
+
+ ret
+
+KeyBufferLen equ 30 ; 30 Zeichen sollten fr Zahlen reichen...
+KeyBuffer db KeyBufferLen ; Maimall„nge fr DOS
+ db 0 ; effektive L„nge Eingabe
+ db KeyBufferLen dup (0) ; Platz fr Eingabe
+InvMsg db "Ungltiges Zahlenformat",CR,LF,'$'
+OverMsg db "Bereichsberschreitung",CR,LF,'$'
+
+ endp
+
+;******************************************************************************
+;* eine Anzahl Leerzeichen ausgeben *
+;* In : CX = Anzahl *
+;******************************************************************************
+
+ globproc WriteSpc
+
+ push dx ; Register retten
+
+ jcxz NULL ; Nullschleife abfangen
+Loop: mov ah,DOS_WrChar
+ mov dl,' '
+ int INT_DOS
+ loop Loop
+
+NULL: pop dx ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* vorzeichenlose Zahl dezimal ausgeben *
+;* In : AX = Zahl *
+;* CL = min. Stellenzahl *
+;******************************************************************************
+
+ globproc WriteDec
+
+ push di ; Register retten
+ push cx
+ push dx
+
+ mov ch,0 ; CH z„hlt effektive Zeichenzahl
+InLoop: sub dx,dx ; Stellendivision
+ mov di,10 ; gewnschtes Zahlensystem
+ div di
+ mov di,ax ; war es vorher 0 ?
+ or di,dx ; (wenn Quotient & Rest 0)
+ jnz NZero ; nein-->normal ausgeben
+ or ch,ch ; noch erste Stelle ?
+ jz NZero ; dann auf jeden Fall 0 ausgeben
+ mov dl,0f0h ; ansonsten Leerzeichen fr leading 0
+NZero: push dx ; Zeichen speichern...
+ inc ch ; ...und mitz„hlen
+ cmp ch,cl ; Mindestzahl ausgegeben ?
+ jb InLoop ; nein-->weiter
+ or ax,ax ; ansonsten: 0 ?
+ jnz InLoop ; nein, weitermachen
+
+ shr cx,8 ; effektive Zahl nach CX
+OLoop: pop dx ; ein Zeichen runterholen
+ add dl,'0' ; in ASCII konvertieren
+ mov ah,DOS_WrChar ; ber DOS ausgeben
+ int INT_DOS
+ loop OLoop
+
+ pop dx
+ pop cx
+ pop di ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* vorzeichenlose Zahl hexadezimal ausgeben *
+;* In : AX = Zahl *
+;* CL = min. Stellenzahl *
+;******************************************************************************
+
+ globproc WriteHex
+
+ push di ; Register retten
+ push cx
+ push dx
+
+ mov ch,0 ; CH z„hlt effektive Zeichenzahl
+InLoop: sub dx,dx ; Stellendivision
+ mov di,16 ; gewnschtes Zahlensystem
+ div di
+ mov di,ax ; war es vorher 0 ?
+ or di,dx ; (wenn Quotient & Rest 0)
+ jnz NZero ; nein-->normal ausgeben
+ or ch,ch ; noch erste Stelle ?
+ jz NZero ; dann auf jeden Fall 0 ausgeben
+ mov dl,0f0h ; ansonsten Leerzeichen fr leading 0
+NZero: push dx ; Zeichen speichern...
+ inc ch ; ...und mitz„hlen
+ cmp ch,cl ; Mindestzahl ausgegeben ?
+ jb InLoop ; nein-->weiter
+ or ax,ax ; ansonsten: 0 ?
+ jnz InLoop ; nein, weitermachen
+
+ shr cx,8 ; effektive Zahl nach CX
+OLoop: pop dx ; ein Zeichen runterholen
+ add dl,'0' ; in ASCII konvertieren
+ cmp dl,'9'
+ jbe NoHex
+ add dl,7
+NoHex: mov ah,DOS_WrChar ; ber DOS ausgeben
+ int INT_DOS
+ loop OLoop
+
+ pop dx
+ pop cx
+ pop di ; Register zurck
+ ret
+
+ endp
+
+;*****************************************************************************
+;* Routine GeometryDefined - stellt fest, ob Geometrie fr ei Laufwerk defi- *
+;* niert ist *
+;* Eingabe: AL = Laufwerksnummer *
+;* Ausgabe: C = 0, falls OK *
+;*****************************************************************************
+
+ proc GeometryDefined
+
+ push di ; Register retten
+ call GetPTabAdr ; Tabellenadresse bilden
+ cmp word ptr[di+DrPar_Cyls],0 ; Zylinderzahl 0 ?
+ stc
+ je Fin
+ cmp byte ptr[di+DrPar_Heads],0 ; Kopfzahl 0 ?
+ stc
+ je Fin
+ cmp byte ptr[di+DrPar_NSecs],0 ; Sektorzahl 0 ?
+ stc
+ je Fin
+ clc ; alles OK
+Fin: pop di ; Register zurck
+ ret
+
+ endp
+
+;*****************************************************************************
+;* Routine QueryRedefine - fragt nach, ob Geometrie neu definert werden soll *
+;* Eingabe: AL = Laufwerk *
+;* Ausgabe: C = 0, falls ja *
+;*****************************************************************************
+
+ proc QueryRedefine
+
+ add al,'1' ; Laufwerksnummer in ASCII umrechnen
+ mov [UndefMsg2],al ; in Meldung einschreiben
+ PrMsg UndefMsg
+ PrMsg DoQueryMsg ; nachfragen, ob Definition erwnscht
+ call YesNo
+ ret
+
+UndefMsg db "Geometrie fr Laufwerk "
+UndefMsg2 db " undefiniert.",CR,LF,"$"
+DoQueryMsg db "Geometrie neu definieren ? $"
+
+ endp
+
+;*****************************************************************************
+;* Routine ReadGeomety - liest Laufwerksgeometrie vom Benutzer ein *
+;* Eingabe: AL = phys. Laufwerksnummer *
+;*****************************************************************************
+
+ proc ReadGeometry
+
+ push ax ; Register retten
+ push si
+ push di
+
+ call GetPTabAdr ; Zeiger auf Parametertabelle holen
+ mov si,di
+
+ lea di,[CylInpMsg] ; Zylinderzahl erfragen
+ mov ax,1024
+ call ReadNumber
+ mov [si+DrPar_Cyls],ax
+
+ lea di,[HeadInpMsg] ; Kopfzahl erfragen
+ mov ax,16
+ call ReadNumber
+ mov [si+DrPar_Heads],al
+
+ lea di,[RWCInpMsg] ; RWC-Zylinder erfragen
+ mov ax,65535
+ call ReadNumber
+ mov [si+DrPar_RedWr],ax
+
+ lea di,[PreInpMsg] ; Pr„kompensations-Zylinder erfragen
+ mov ax,65535
+ call ReadNumber
+ mov [si+DrPar_PrComp],ax
+
+ lea di,[ECCInpMsg] ; ECC-L„nge erfragen
+ mov ax,11
+ call ReadNumber
+ mov [si+DrPar_ECCLen],ax
+
+ mov al,[si+DrPar_Heads] ; Steuerbyte Bit 3=1, falls Platte
+ dec al
+ and al,8 ; mehr als 8 K”pfe hat
+ mov [si+DrPar_CByte],al
+
+ mov al,0 ; Timeouts unbenutzt
+ mov [si+DrPar_TOut],al
+ mov [si+DrPar_FTOut],al
+ mov [si+DrPar_CTOut],al
+
+ mov ax,[si+DrPar_Cyls] ; Parkzylinder=Zylinderzahl+1
+ inc ax
+ mov [si+DrPar_LZone],ax
+
+ lea di,[SecInpMsg] ; Sektorzahl erfragen
+ mov ax,255
+ call ReadNumber
+ mov [si+DrPar_NSecs],al
+
+ pop di ; Register zurck
+ pop si
+ pop ax
+ ret
+
+CylInpMsg db "Anzahl Zylinder (max. 1024) : $"
+HeadInpMsg db "Anzahl K”pfe (max. 16) : $"
+RWCInpMsg db "Startzylinder fr reduzierten Schreibstrom (max. 65535) : $"
+PreInpMsg db "Startzylinder fr Pr„kompensation (max. 65535) : $"
+ECCInpMsg db "max. ECC-Fehlerburstl„nge (5 oder 11) : $"
+SecInpMsg db "Sektorzahl (max. 255) : $"
+
+ endp
+
+;*****************************************************************************
+;* Routine WriteGeoToDisk - schreibt Laufwerksgeometrie auf Platte *
+;* Eingabe: AL = phys. Laufwerksnummer *
+;* Ausgabe: C+AX = Fehlerstatus *
+;*****************************************************************************
+
+ proc WriteGeoToDisk
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov dx,ds ; alles im folgenden im Datensegment
+ mov es,dx
+
+ mov dl,al ; Laufwerksnummer retten
+ mov ah,0 ; Kopf 0,
+ sub bx,bx ; Spur 0,
+ mov cx,0101h ; Sektor 1 lesen
+ lea di,[SectorBuffer]
+ call ReadSectors
+ jc GeoError ; Abbruch bei Fehler
+
+ mov al,dl ; Geometrietabelle adressieren
+ call GetPTabAdr
+ mov si,di ; selbige in MBR einschreiben
+ lea di,[SectorBuffer+DrPar_Offset]
+ mov cx,DrPar_Len/2
+ cld
+ rep movsw
+
+ mov al,dl ; jetzt den ganzen Kram zurckschreiben
+ mov ah,0
+ sub bx,bx
+ mov cx,0101h
+ lea si,[SectorBuffer]
+ call WriteSectors
+ jc GeoError
+
+Fin: pop es ; Register zurck
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ ret
+
+GeoError: mov ah,bl ; Fehlerausgabe
+ call WrErrorCode
+ jmp Fin
+
+ endp
+
+;*****************************************************************************
+;* Routine QueryParams *
+;* Eingabe: AL = Laufwerksnummer *
+;* AH = 1, falls Rckschreiben erlaubt *
+;* Ausgabe: AL = 0: Laufwerk vergessen *
+;* AL = 1: Mastersektor neu lesen *
+;* AL = 2: Tabelle nur transient eingetragen, kein Neulesen *
+;*****************************************************************************
+
+ globproc QueryParams
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov bx,ax ; Laufwerksnummer retten
+ call QueryRedefine ; nachfragen, ob Neudefinition erwnscht
+ mov al,0 ; Abbruch bei Nein
+ ljc Terminate
+
+ mov al,bl ; Geometrie einlesen
+ call ReadGeometry
+
+ shr bh,1 ; Rckschreiben erlaubt ?
+ cmc ; C=1-->verboten
+ jc NoWriteBack
+
+ PrMsg WriteBackMsg ; nachfragen, ob Rckschreiben erwnscht
+ call YesNo
+NoWriteBack: mov al,2 ; Neulesen bei Nein verhindern
+ jc Terminate
+
+ mov al,bl
+ call WriteGeoToDisk
+ jc WrError
+
+ mov al,1 ; Ergebnis: MBR-Lesen wiederholen
+ jmp Terminate
+WrError: mov al,0 ; Schreibfehler: Laufwerk ignorieren
+
+Terminate: pop es ; Register zurck
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ret
+
+WriteBackMsg db "Parametersatz zurckschreiben ? $"
+
+ endp
+
+;****************************************************************************
+;* Laufwerksnummer einlesen *
+;* Ausgabe: AL = Laufwerksnummer *
+;****************************************************************************
+
+ proc InputDrive
+
+ push dx ; Register retten
+
+RdLoop: PrMsg PromptMsg ; Anfrage ausgeben
+ mov ah,DOS_RdChar ; ein Zeichen holen
+ int INT_DOS
+ mov dl,al ; Zeichen retten
+ PrChar dl ; Laufwerk als Echo zurckgeben
+ PrChar CR
+ PrChar LF
+ sub dl,'1' ; nur 1 oder 2 erlaubt
+ jc RdLoop
+ cmp dl,MaxPDrives
+ jae RdLoop
+ mov al,dl ; Laufwerk in AL zurckgeben
+
+ pop dx ; Register zurck
+ ret
+
+PromptMsg db "Laufwerksnummer (1 oder 2) : $"
+
+ endp
+
+;****************************************************************************
+;* Men fr Plattenfunktionen *
+;****************************************************************************
+
+ proc SelectDisk
+
+ push ax ; Register sichern
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov dh,ah ; Rckschreibeflag sichern
+ call InputDrive
+ mov dl,al ; Laufwerksnummer sichern
+
+ mov al,dl ; Geometrie noch undefiniert ?
+ call GeometryDefined
+ jnc IsOK ; Nein, alles in Butter
+
+ mov al,dl ; nicht definiert: versuchen,
+ mov ah,0 ; Geometrie vom MBR zu lesen
+ mov bx,ds
+ mov es,bx
+ sub bx,bx
+ mov cx,0101h
+ lea di,[SectorBuffer]
+ call ReadSectors
+ jnc CopyTable ; kein Fehler->Tabelle auslesen
+ mov dh,0 ; wenn Fehler, nie zurckschreiben
+ jmp ReadManual ; und manuell probieren
+CopyTable: lea si,[SectorBuffer+DrPar_Offset]
+ mov al,dl
+ call GetPTabAdr
+ mov cx,DrPar_Len/2
+ cld
+ rep movsw
+ mov al,dl ; Geometrie jetzt da ?
+ call GeometryDefined
+ jnc IsOK ; falls ja, Ende
+
+ReadManual: mov al,dl ; fragen, ob Redefinition erwnscht
+ call QueryRedefine
+ jc NotOK ; falls nein, Abbruch
+ mov al,dl ; ansonsten einlesen
+ call ReadGeometry
+ shr dh,1 ; zurckschreiben ?
+ jnc IsOK
+ mov al,dl ; ja...
+ call WriteGeoToDisk ; Fehler ignorieren
+
+IsOK: mov [MomDrive],dl ; Laufwerk akzeptiert
+
+NotOK: pop es ; Register zurck
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ ret
+
+ endp
+
+;----------------------------------------------------------------------------
+
+ proc ChangeGeometry
+
+ cmp [MomDrive],-1 ; Laufwerk berhaupt schon definiert ?
+ jne DriveDefined
+ call InputDrive ; nein: lesen & einschreiben
+ mov [MomDrive],al
+DriveDefined: mov al,[MomDrive] ; neue Geometrie einlesen
+ call ReadGeometry
+ mov al,[MomDrive]
+ call WriteGeoToDisk ; die auch gleich zu schreiben versuchen
+
+ ret
+
+ endp
+
+;----------------------------------------------------------------------------
+
+ proc VerifyDisk
+
+ pusha ; restlos alles...
+
+ mov al,[MomDrive] ; erstmal sicherstellen, daá der
+ call SetDriveParams ; Kontroller die Geometrie kennt
+
+ mov al,[MomDrive] ; die Geometrie brauchen wir auch
+ call GetPTabAdr
+
+ PrMsg ESCMsg
+ sub bp,bp ; Fehlerz„hler
+ mov si,bp ; Zylinderz„hler
+ mov dx,bp ; Folgefehlerz„hler
+CylLoop: mov dl,0 ; Kopfz„hler
+HeadLoop: PrMsg CylMsg ; zu testende Spur ausgeben
+ mov ax,si
+ mov cl,4
+ call WriteDec
+ PrMsg HeadMsg
+ mov al,dl
+ mov ah,0
+ mov cl,2
+ call WriteDec
+ PrChar CR
+
+ mov al,[MomDrive] ; eine Spur testen
+ mov ah,dl
+ mov bx,si
+ mov cl,[di+DrPar_NSecs]
+ mov ch,1
+ call VeriSectors
+
+ jnc NoError ; evtl. Fehlerbehandlung
+ push ax
+ PrChar LF
+ pop ax
+ mov ah,[MomDrive]
+ call WrErrorCode
+ inc bp ; Fehlerz„hler rauf
+ inc dh
+ test dh,7 ; alle 8 Fehler in Reihe nachfragen
+ jnz NextTrack
+ PrMsg GoOnMsg
+ call YesNo
+ jc Terminate
+ jmp NextTrack
+NoError: mov dh,0 ; eine Spur gut->Folgenz„hler l”schen
+NextTrack: call BreakONESC ; Abbruch ?
+ jc Terminate
+ inc dl ; n„chster Kopf
+ cmp dl,[di+DrPar_Heads]
+ jb HeadLoop
+ inc si ; n„chster Zylinder
+ cmp si,[di+DrPar_Cyls]
+ ljb CylLoop
+
+Terminate: mov ax,bp ; Fehlerzahl ausgeben
+ mov cl,5
+ call WriteDec
+ PrMsg ErrorMsg
+
+ popa ; Register zurck
+
+ ret
+
+EscMsg db "Verifizieren..",CR,LF,"Abbruch mit <ESC>",CR,LF,'$'
+CylMsg db "Zylinder $"
+HeadMsg db ", Kopf $"
+GoOnMsg db "Test fortsetzen? $"
+ErrorMsg: db " Fehler gefunden ",CR,LF,'$'
+
+ endp
+
+;----------------------------------------------------------------------------
+
+ proc FormatDisk
+
+ push ax ; Register retten
+ push bx
+ push cx
+ push di
+ push es
+
+ mov al,[MomDrive] ; erstmal sicherstellen, daá der
+ call SetDriveParams ; Kontroller die Geometrie kennt
+
+ mov al,[MomDrive]
+ call GetPTabAdr
+InterLoop: mov al,[di+DrPar_NSecs] ; Maximum=Sektorzahl-1
+ dec al
+ mov ah,0
+ lea di,[InterleaveMsg] ; Interleave erfragen
+ call ReadNumber
+ or ax,ax ; Null wollen wir nicht
+ jz InterLoop
+ mov bl,al ; Interleave retten
+ PrMsg ConfirmMsg ; sicherheitshalber nachfragen
+ call YesNo
+ jc Fin
+ PrMsg NewLine
+ PrMsg FormatMsg
+ mov ah,bl ; Interleave zurck
+ mov al,[MomDrive]
+ call FormatUnit
+ jc FormatError ; Fehler beim Formatieren ?
+
+NoFormatError: PrMsg WriteMsg
+ lea di,[SectorBuffer] ; MBR erzeugen
+ cld
+ mov cx,SecSize/2-1 ; letztes Wort anders!
+ mov ax,ds
+ mov es,ax
+ sub ax,ax ; prinzipiell erstmal alles Nullen
+ rep stosw
+ mov word ptr[di],0aa55h ; Gltigkeitsflag am Ende
+ mov al,[MomDrive] ; Geometrietabelle eintragen
+ call GetPTabAdr
+ mov si,di
+ lea di,[SectorBuffer+DrPar_Offset]
+ mov cx,DrPar_Len/2
+ rep movsw
+ mov al,[MomDrive] ; Sektor schreiben
+ mov ah,0 ; MBR auf Kopf 0,
+ mov bx,0 ; Spur 0,
+ mov cx,0101h ; Sektor 1
+ lea si,[SectorBuffer]
+ call WriteSectors
+ jc FormatError ; Fehler beim Schreiben ?
+
+Fin: pop es ; Register zurck
+ pop di
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+FormatError: cmp al,DErr_UserTerm ; Abbruch durch Benutzer ?
+ je Fin ; dann nicht meckern
+ push ax ; Fehlercode retten
+ pushf
+ PrMsg NewLine
+ popf
+ pop ax
+ mov ah,[MomDrive] ; Fehlermeldung ausgeben
+ call WrErrorCode
+ jmp Fin
+
+FormatMsg db "Formatieren...",CR,LF,'$'
+WriteMsg db "MBR schreiben...",CR,LF,'$'
+
+ endp
+
+;----------------------------------------------------------------------------
+
+ proc BadTrack
+
+ push bx
+ push si
+ push di
+
+ mov al,[MomDrive] ; Zeiger auf Geometrietabelle
+ call GetPTabAdr ; holen
+ mov si,di
+
+ lea di,[TrackMsg] ; Spurnummer abfragen
+ mov ax,[si+DrPar_Cyls]
+ dec ax
+ call ReadNumber
+ mov bx,ax
+ lea di,[HeadMsg] ; Kopfnummer abfragen
+ mov ax,[si+DrPar_Heads]
+ dec ax
+ call ReadNumber
+ mov ah,al
+ push ax ; sicherheitshalber noch best„tigen
+ PrMsg ConfirmMsg
+ call YesNo
+ pop ax
+ jc NoError
+ mov al,[MomDrive] ; Spur markieren
+ call MarkBad
+ jnc NoError
+ push ax ; Fehlercode retten
+ pushf
+ PrMsg NewLine
+ popf
+ pop ax
+ mov ah,[MomDrive]
+ call WrErrorCode
+NoError:
+ pop di
+ pop si
+ pop bx
+
+ ret
+
+ endp
+
+;----------------------------------------------------------------------------
+
+ proc FormTrack
+
+ push bx
+ push si
+ push di
+
+ mov al,[MomDrive] ; Zeiger auf Geometrietabelle
+ call GetPTabAdr ; holen
+ mov si,di
+
+ lea di,[TrackMsg] ; Spurnummer abfragen
+ mov ax,[si+DrPar_Cyls]
+ dec ax
+ call ReadNumber
+ mov bx,ax
+ lea di,[HeadMsg] ; Kopfnummer abfragen
+ mov ax,[si+DrPar_Heads]
+ dec ax
+ call ReadNumber
+ mov ah,al
+ push ax ; Kopf retten
+InterLoop: mov al,[si+DrPar_NSecs] ; Interleave-Maximum=Sektorzahl-1
+ dec al
+ mov ah,0
+ lea di,[InterleaveMsg] ; Interleave erfragen
+ call ReadNumber
+ or ax,ax ; Null wollen wir nicht
+ jz InterLoop
+ mov cl,al ; Interleave passend ablegen
+ PrMsg ConfirmMsg ; nochmal nachfragen
+ call YesNo
+ pop ax
+ jc NoError
+ mov al,[MomDrive] ; Kopf zurck
+ call FormatTrack
+ jnc NoError
+ push ax ; Fehlercode retten
+ pushf
+ PrMsg NewLine
+ popf
+ pop ax
+ mov ah,[MomDrive]
+ call WrErrorCode
+NoError:
+ pop di
+ pop si
+ pop bx
+
+ ret
+
+ endp
+
+;----------------------------------------------------------------------------
+
+; packt eine Sektorkoordinate ins BIOS-Format
+; -->Zylinder=BX, Kopf=AH, Sektor=AL
+; <--Zylinder/Sektor=BX, Kopf=AH
+
+ proc PackCoordinate
+
+ shl bh,6
+ or bh,al
+ xchg bl,bh
+ ret
+
+ endp
+
+ proc UnpackCoordinate
+
+ xchg bh,bl ; Zylinderbytes in richtige Reihenfolge
+ mov al,bh ; Sektor ausmaskieren
+ and al,00111111b
+ shr bh,6 ; Zylinder korrigieren
+
+ ret
+
+ endp
+
+; berechnet aus einer Sektorkoordinate die lineare Sektornummer
+; -->Zylinder/Sektor=BX, Kopf=AH, Geometriezeiger=SI
+; <--Sektornummer=DX/AX
+
+ proc LinearizeCoordinate
+
+ push bx
+ push cx
+
+ mov cx,ax ; Kopf retten
+ mov al,bh ; Zylinder rekonstruieren
+ mov ah,bl
+ shr ah,6
+ mov dl,[si+DrPar_Heads]
+ mov dh,0
+ mul dx ; = Anzahl Spuren bis Zylinderbeginn
+ add al,ch ; Startkopf dazuaddieren
+ adc ah,0 ; bisher hoffentlich nur 16 Bit...
+ mov dl,[si+DrPar_NSecs]
+ mov dh,0
+ mul dx ; = Anzahl Spuren bis Spurbeginn
+ and bl,3fh ; letztendlich Sektor-1 dazu
+ dec bl
+ add al,bl
+ adc ah,0
+ adc dx,0
+
+ pop cx
+ pop bx
+
+ ret
+
+ endp
+
+ proc MakePart
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ PrMsg ConfirmMsg ; sind wir sicher ?
+ call YesNo
+ ljc End
+
+ mov al,[MomDrive] ; Laufwerk rekalibrieren
+ call Recalibrate
+ ljc PartError
+
+ mov al,[MomDrive] ; alten MBR auslesen
+ mov ah,0
+ mov bx,0
+ mov cx,0101h
+ mov si,ds
+ mov es,si
+ lea di,[SectorBuffer]
+ call ReadSectors
+ ljc PartError
+
+ mov al,[MomDrive] ; Plattengeometrie holen
+ call GetPTabAdr
+ mov si,di
+
+ lea di,[SectorBuffer+ParTab_Offset] ; an erste Tabelle schreiben
+ mov byte ptr [di+ParTab_BFlag],80h ; Partition aktiv
+ cmp byte ptr[si+DrPar_Heads],1 ; nur ein Kopf ?
+ ja MoreHeads
+ mov bx,1 ; ja: Start auf Zyl. 1, Kopf 0
+ mov ah,0
+ jmp WriteStart
+MoreHeads: sub bx,bx ; nein: Start auf Zyl. 0, Kopf 1
+ mov ah,1
+WriteStart: mov al,01h ; Startsektor immer 1
+ call PackCoordinate
+ mov [di+ParTab_FHead],ah
+ mov [di+ParTab_FSecCyl],bx
+ call LinearizeCoordinate ; linearen Start schreiben
+ mov [di+ParTab_LinSec],ax
+ mov [di+ParTab_LinSec+2],dx
+ push dx
+ push ax
+ mov bx,[si+DrPar_Cyls] ; Ende: Zylinder n-2, Kopf n-1, Sektor n
+ sub bx,2
+ mov ah,[si+DrPar_Heads]
+ dec ah
+ mov al,[si+DrPar_NSecs]
+ call PackCoordinate
+ mov [di+ParTab_LHead],ah
+ mov [di+ParTab_LSecCyl],bx
+ call LinearizeCoordinate ; Sektorzahl berechnen
+ pop bx ; dazu Start abziehen
+ sub ax,bx
+ pop bx
+ sbb dx,bx
+ add ax,1 ; !!! L„nge=Stop-Start+1
+ adc dx,0
+ mov [di+ParTab_NSecs],ax
+ mov [di+ParTab_NSecs+2],dx
+ or dx,dx ; falls >64K Sektoren,
+ jz NoBigDOS ; eine BigDOS-Partition
+ mov bl,6
+ jmp TypeFound
+NoBigDOS: cmp ax,32679 ; ab 32680 Sektoren 16-Bit-FAT
+ jb NoFAT16
+ mov bl,04
+ jmp TypeFound
+NoFAT16: mov bl,1 ; kleine 12-Bit-Partition
+TypeFound: mov [di+ParTab_Type],bl
+ add di,ParTab_Len ; die anderen 3 Partitionen l”schen
+ mov cx,3*(ParTab_Len/2)
+ sub ax,ax
+ cld
+ rep stosw
+
+ mov al,[MomDrive] ; neuen MBR schreiben
+ mov ah,0
+ mov bx,0
+ mov cx,0101h
+ lea si,[SectorBuffer]
+ call WriteSectors
+ ljc PartError
+
+End: pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ret
+
+PartError: push ax ; Fehlercode retten
+ pushf
+ PrMsg NewLine
+ popf
+ pop ax
+ mov ah,[MomDrive] ; Fehlermeldung ausgeben
+ call WrErrorCode
+ jmp End
+
+ConfirmMsg: db "ACHTUNG! Alle bisherigen Partitionen auf der",CR,LF
+ db "Festplatte werden gel”scht! Fortfahren? $"
+
+ endp
+
+;----------------------------------------------------------------------------
+
+ proc FormatPart
+
+ pusha
+
+ mov ax,ds ; wir arbeiten nur im Datensegment
+ mov es,ax
+
+ PrMsg ConfirmMsg ; vorher nachfragen
+ call YesNo
+ ljc Ende
+
+ mov al,[MomDrive] ; Laufwerk rekalibrieren
+ call Recalibrate
+ ljc LFormError
+
+; Schritt 1: MBR lesen
+
+ mov al,[MomDrive] ; MBR auslesen, um Partitions-
+ mov ah,0 ; daten zu bekommen
+ mov bx,0
+ mov cx,0101h
+ lea di,[SectorBuffer]
+ call ReadSectors
+ ljc LFormError
+
+; Schritt 2: Partitionsdaten in BPB kopieren
+
+ lea di,[SectorBuffer+ParTab_Offset] ; auf Partitionsdaten
+ mov al,[di+ParTab_Type] ; muá prim„re Partition sein
+ cmp al,1 ; DOS 2.x FAT12?
+ je ParTypeOK
+ cmp al,4 ; DOS 3.x FAT16?
+ je ParTypeOK
+ cmp al,6 ; DOS 4.x BIGDOS?
+ je ParTypeOK
+ PrMsg InvParTypeMsg ; nichts dergleichen: Abbruch
+ jmp Ende
+ParTypeOK: mov word ptr[BPB_SysID],'AF' ; FAT-Kennung in BPB eintragen
+ mov word ptr[BPB_SysID+2],'1T' ; FAT12/FAT16
+ mov word ptr[BPB_SysID+5],' '
+ mov ah,'2' ; Annahme FAT12
+ cmp al,1
+ je ParIsFAT12 ; wenn Typ=1, OK
+ mov ah,'6' ; ansonsten FAT16
+ParIsFAT12: mov byte ptr[BPB_SysID+4],ah
+ mov ax,[di+ParTab_NSecs] ; Sektorzahl in BPB schreiben
+ mov dx,[di+ParTab_NSecs+2]
+ mov word ptr[BPB_NumSecs32],ax
+ mov word ptr[BPB_NumSecs32+2],dx
+ or dx,dx ; falls < 64K Sektoren,
+ jz ParIsNotBig ; GrӇe auch unten eintragen,
+ sub ax,ax ; ansonsten 0
+ParIsNotBig: mov [BPB_NumSecs16],ax
+ mov ax,word ptr[di+ParTab_LinSec] ; Startsektor umkopieren
+ mov dx,word ptr[di+ParTab_LinSec+2]
+ mov word ptr[BPB_LinStart],ax
+ mov word ptr[BPB_LinStart+2],dx
+
+; Schritt 3: Partitionsdaten in Partitionstabelle kopieren, damit wir die
+; linearen Schreib/Lesefunktionen nutzen k”nnen
+
+ mov [DrCnt],1 ; nur ein Laufwerk belegt
+ mov ah,[di+ParTab_FHead] ; Startkoordinate ablegen
+ mov bx,[di+ParTab_FSecCyl]
+ call UnpackCoordinate
+ mov [DrTab+DrTab_StartHead],ah
+ mov word ptr [DrTab+DrTab_StartCyl],bx
+ mov [DrTab+DrTab_StartSec],al
+ mov ax,[di+ParTab_LinSec]
+ mov word ptr [DrTab+DrTab_LinStart],ax
+ mov ax,[di+ParTab_LinSec+2]
+ mov word ptr [DrTab+DrTab_LinStart+2],ax
+ mov ax,[di+ParTab_NSecs]
+ mov word ptr [DrTab+DrTab_SecCnt],ax
+ mov ax,[di+ParTab_NSecs+2]
+ mov word ptr [DrTab+DrTab_SecCnt+2],ax
+ mov al,[MomDrive] ; Laufwerk einschreiben
+ mov [DrTab+DrTab_Drive],al
+ mov byte ptr[DrTab+DrTab_BPB],0 ; kein BPB
+
+; Schritt 4: konstante Felder in BPB eintragen
+
+ mov [BPB_SecSize],SecSize ; SektorgrӇe konstant 512 Byte
+ mov [BPB_ResvdSecs],1 ; nur Bootsektor reserviert
+ mov [BPB_NumFATs],2 ; 2 FATs ist DOS-Standard
+ mov [BPB_MediaID],0f8h ; Media-Byte fr Platten konstant
+ mov al,[MomDrive]
+ call GetPTabAdr
+ mov ah,0
+ mov al,[di+DrPar_NSecs]; Plattenzylinder und -k”pfe
+ mov [BPB_SecsPerTrk],ax
+ mov al,[di+DrPar_Heads]
+ mov [BPB_Heads],ax
+ mov al,[MomDrive] ; Plattennummer+80h
+ add al,80h
+ mov [BPB_PhysNo],ax
+ mov [BPB_ExtID],29h ; Erkennung, daá erw. BPB gltig
+ mov ah,0 ; Seriennummer=Uhrzeit
+ int INT_Clock
+ mov word ptr[BPB_SerialNo],cx
+ mov word ptr[BPB_SerialNo+2],dx
+ lea di,[BPB_Name] ; Name ist leer
+ mov cx,11
+ mov al,' '
+ cld
+ rep stosb
+
+; Schritt 5: einige Sachen vom Anwender erfragen
+
+DirEntLoop: mov ax,1024 ; mehr ist wohl kaum sinnvoll
+ lea di,[DirEntriesMsg]
+ call ReadNumber
+ cmp ax,SecSize/32 ; weniger als ein Sektor ergibt
+ jb DirEntLoop ; keinen Sinn
+ mov [BPB_DirLen],ax ; Anzahl in BPB eintragen
+ mov dx,0 ; Directory-Sektorzahl berechnen
+ mov bx,SecSize/32
+ div bx
+ or dx,dx ; ggfs. aufrunden
+ jz DirLenEven
+ inc ax
+DirLenEven: mov [DirLen],ax
+
+; Schritt 6: Clusterl„nge berechnen
+
+ mov ax,word ptr[BPB_NumSecs32] ; # Sektoren in Datenfeld
+ mov dx,word ptr[BPB_NumSecs32+2] ; und FATs berechnen
+ sub ax,[BPB_ResvdSecs]
+ sbb dx,0
+ sub ax,[DirLen]
+ sbb dx,0
+ mov bl,1 ; Annahme: m”glichst wenig Sektoren pro Cluster
+ClusterLoop: or dx,dx ; wenn noch mehr als 64K Cluster,
+ jnz ClusterNxtLoop ; auf jeden Fall zu groá
+ cmp ax,4080 ; bei weniger als 4K Clustern
+ jb ClusterEndLoop ; auf jeden Fall OK
+ cmp [BPB_SysID+4],'2' ; sonst bei FAT12
+ je ClusterNxtLoop ; auf jeden Fall zu viel
+ cmp ax,65510 ; bei FAT16 Vergleich auf 64K
+ jb ClusterEndLoop
+ClusterNxtLoop: shl bl,1 ; zu viel: Cluster verdoppeln
+ js ClusterEndLoop ; bei 128 Sektoren/Cluster abbrechen
+ shr dx,1 ; Clusterzahl halbiert sich
+ rcr ax,1
+ jmp ClusterLoop
+ClusterEndLoop: mov [BPB_SecsPerClust],bl ; Ergebnis einschreiben
+ add ax,2 ; Dummy-Eintr„ge in FAT
+ adc dx,0
+ mov bx,341 ; Anzahl FAT-Sektoren berechnen
+ cmp [BPB_SysID+4],'2'
+ jz Cluster12
+ mov bx,256
+Cluster12: div bx
+ or dx,dx ; Sektorzahl aufrunden
+ jz FATLenEven
+ inc ax
+FATLenEven: mov [BPB_SecsPerFAT],ax ; Anzahl FAT-Sektoren einschreiben
+
+; Schritt 7: Bootsektor aufbauen
+
+ PrMsg WrBootSectMsg
+ lea di,[SectorBuffer]
+ cld
+ mov al,0ebh ; Dummy-Sprung einschreiben
+ stosb
+ mov al,0feh
+ stosb
+ mov al,90h
+ stosb
+ mov ax,'ES' ; OEM-ID einschreiben
+ stosw
+ mov ax,'DC'
+ stosw
+ mov ax,'IR'
+ stosw
+ mov ax,'EV'
+ stosw
+ lea si,[BPBBuffer] ; BPB einschreiben
+ mov cx,BPB_Length
+ rep movsb
+ mov cx,SectorBuffer+SecSize ; Rest vom Bootsektor nullen
+ sub cx,di
+ mov al,0
+ rep stosb
+ mov ax,0 ; Bootsektor ist log. Sektor 0
+ mov dx,ax
+ mov bl,0 ; Partition 0
+ call TranslateParams
+ mov cl,1 ; nur ein Sektor
+ lea si,[SectorBuffer]
+ call WriteSectors
+ ljc LFormError
+
+; Schritt 8: Directory & FATs ausnullen
+
+ lea di,[SectorBuffer] ; Sektorpuffer wird benutzt
+ mov cx,SecSize/2
+ cld
+ sub ax,ax
+ rep stosw
+ PrMsg WrFATMsg
+ mov ax,[BPB_ResvdSecs] ; Startsektor FATs holen
+ sub dx,dx
+ lea si,[SectorBuffer]
+ mov cx,[BPB_SecsPerFAT]
+ add cx,cx ; beide FATs nullen
+FATZeroLoop: push ax ; Sektornummer und -zahl retten
+ push cx
+ push dx
+ mov bl,0
+ call TranslateParams
+ mov cl,1
+ call WriteSectors
+ pop dx
+ pop cx
+ pop ax
+ ljc LFormError
+ add ax,1 ; n„chster Sektor
+ adc dx,0
+ loop FATZeroLoop
+ push ax ; !!! PrMsg zerst”rt AX-Register
+ PrMsg WrDirMsg
+ pop ax
+ mov cx,[DirLen] ; dito fr Directory
+DirZeroLoop: push ax
+ push cx
+ push dx
+ mov bl,0
+ call TranslateParams
+ mov cl,1
+ call WriteSectors
+ pop dx
+ pop cx
+ pop ax
+ ljc LFormError
+ add ax,1 ; n„chster Sektor
+ adc dx,0
+ loop DirZeroLoop
+
+; Schritt 9: Sektoren testen und FAT initialisieren
+
+ mov ax,[BPB_ResvdSecs] ; Datensektorbeginn berechnen
+ sub dx,dx
+ mov [FAT1Pos],ax ; Beginn 1. FAT hinter Bootsektor
+ mov [FAT1Pos+2],dx
+ add ax,[BPB_SecsPerFAT] ; Beginn 2. FAT hinter 1. FAT
+ adc dx,0
+ mov [FAT2Pos],ax
+ mov [FAT2Pos+2],dx
+ add ax,[BPB_SecsPerFAT]
+ adc dx,0
+ add ax,[DirLen] ; Datenbeginn hinter Directory
+ adc dx,0
+ mov [DataPos],ax ; diesen Startsektor retten
+ mov [DataPos+2],dx
+
+ mov ax,word ptr[BPB_NumSecs32] ; Anzahl Cluster berechnen
+ mov dx,word ptr[BPB_NumSecs32+2]
+ sub ax,[DataPos]
+ sbb dx,[DataPos+2]
+ mov bl,[BPB_SecsPerClust] ; / SecsPerCluster
+ mov bh,0
+ div bx
+ mov [ClusterCnt],ax
+
+ call ClearFATBuffer ; erste Elemente in FAT schreiben
+ mov ah,0ffh
+ mov al,[BPB_MediaID]
+ call WriteFAT
+ mov al,0ffh
+ call WriteFAT
+ PrMsg ESCMsg
+ mov ax,[DataPos] ; Schleifenvorbereitung
+ mov dx,[DataPos+2]
+ mov cx,[ClusterCnt]
+VerifyLoop: push ax ; Z„hler retten
+ mov bp,cx
+ push dx
+ mov bl,0 ; immer Laufwerk 0
+ call TranslateParams ; Cluster testlesen
+ mov cl,[BPB_SecsPerClust]
+ test bp,15 ; nur alle 16 Cluster schreiben
+ jnz NoWriteVeri
+ push ax ; Clusternummer ausgeben
+ push cx
+ PrMsg ClusterMsg
+ mov ax,[ClusterCnt]
+ sub ax,bp
+ add ax,2 ; erster Datencluster hat Nummer 2
+ mov cl,5
+ call WriteDec
+ PrChar CR
+ pop cx
+ pop ax
+NoWriteVeri: call VeriSectors
+ mov ax,0 ; Annahme OK (SUB wrde C l”schen...)
+ jnc Verify_OK
+ mov ax,0fff7h
+Verify_OK: call WriteFAT
+ pop dx ; Z„hler zurck
+ mov cx,bp
+ pop ax
+ add al,[BPB_SecsPerClust]
+ adc ah,0
+ adc dx,0
+ call BreakOnESC ; Abbruch durch Benutzer ?
+ jc Ende
+ loop VerifyLoop
+ cmp [FATBufferFill],0 ; Puffer rausschreiben
+ je NoFATFlush
+ call FlushFATBuffer
+NoFATFlush:
+
+Ende: PrMsg NewLine
+ mov [DrCnt],0 ; sonst kommt jemand ins Schleudern...
+ popa
+ ret
+
+LFormError: push ax ; Fehlercode retten
+ pushf
+ PrMsg NewLine
+ popf
+ pop ax
+ mov ah,[MomDrive] ; Fehlermeldung ausgeben
+ call WrErrorCode
+ jmp Ende
+
+WriteFAT: push bx ; einen FAT-Eintrag schreiben
+ mov bx,ax
+ call WriteFATNibble ; Bit 0..3 schreiben
+ mov al,bl ; Bit 4..7 schreiben
+ shr al,4
+ call WriteFATNIbble
+ mov al,bh ; Bit 8..11 schreiben
+ call WriteFATNibble
+ cmp [BPB_SysID+4],'2' ; evtl. Bit 12..15 schreiben
+ je WriteFAT12
+ mov al,bh
+ shr al,4
+ call WriteFATNibble
+WriteFAT12: pop bx
+ ret
+
+WriteFATNibble: push bx
+ and al,15 ; Bit 0..3 ausmaskieren
+ jz SkipWriteNibble ; Nullen brauchen wir nicht schreiben
+ mov [MustFlushFAT],1 ; vermerken, daá Puffer nicht genullt ist
+ mov bx,[FATBufferFill] ; Bit 1.. enthalten Adresse
+ shr bx,1
+ jnc WriteFATLower ; oben oder unten schreiben
+ shl al,4
+WriteFATLower: or FATBuffer[bx],al
+SkipWriteNibble:inc [FATBufferFill]
+ cmp [FATBufferFill],SecSize*2 ; Sektor voll ?
+ jne WriteFAT_NFlush
+ call FlushFATBuffer
+WriteFAT_NFlush:pop bx
+ ret
+
+FlushFATBuffer: push bx
+ push cx
+ push dx
+ push si
+ cmp [MustFlushFAT],0 ; nix zu tun ?
+ je SkipFlushDisk
+ mov ax,[FAT1Pos] ; erste FAT schreiben
+ mov dx,[FAT1Pos+2]
+ mov bl,0
+ call TranslateParams
+ mov cl,1
+ lea si,[FATBuffer]
+ call WriteSectors
+ mov ax,[FAT2Pos] ; zweite FAT schreiben
+ mov dx,[FAT2Pos+2]
+ mov bl,0
+ call TranslateParams
+ mov cl,1
+ lea si,[FATBuffer]
+ call WriteSectors
+SkipFlushDisk: call ClearFATBuffer ; Zeiger wieder auf 0
+ add [FAT1Pos],1 ; FAT-Sektornummern weiterz„hlen
+ adc [FAT1Pos+2],0
+ add [FAT2Pos],1
+ adc [FAT2Pos+2],0
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ ret
+
+
+ClearFATBuffer: push cx
+ push di
+ cld
+ lea di,[FATBuffer]
+ mov cx,SecSize/2
+ sub ax,ax
+ rep stosw
+ pop di
+ pop cx
+ mov [FATBufferFill],ax
+ mov [MustFlushFAT],al
+ ret
+
+ConfirmMsg db "ACHTUNG! Alle Daten gehen verloren! Fortfahren? $"
+InvParTypeMsg db CR,LF,"Partition 1 hat ungltigen Typ oder ist undefiniert!",CR,LF,'$'
+DirEntriesMsg db "Anzahl Eintr„ge im Wurzelverzeichnis (16..1024) : $"
+WrBootSectMsg db "Schreibe Boot-Sektor...",CR,LF,'$'
+WrFATMsg db "Initialisiere FATs...",CR,LF,'$'
+WrDirMsg db "Initialisiere Wurzelverzeichnis...",CR,LF,'$'
+ESCMsg db "Abbruch mit <ESC>",CR,LF,'$'
+ClusterMsg db "Teste Cluster $"
+
+DirLen dw ? ; # Directory-Sektoren
+ClusterCnt dw ?
+FAT1Pos dw 2 dup (?) ; speichern Sektorz„hler w„hrend Test
+FAT2Pos dw 2 dup (?)
+DataPos dw 2 dup (?)
+
+BPBBuffer: ; Zwischenspeicher fr BPB
+BPB_SecSize dw ? ; SektorgrӇe in Bytes
+BPB_SecsPerClust db ? ; Sektoren pro Cluster
+BPB_ResvdSecs dw ? ; reservierte Sektoren (Bootsektor)
+BPB_NumFATs db ? ; Anzahl FATs
+BPB_DirLen dw ? ; Anzahl Eintr„ge im Directory
+BPB_NumSecs16 dw ? ; Anzahl Sektoren, falls <32 MByte
+BPB_MediaID db ? ; Media-Erkennungsbyte
+BPB_SecsPerFAT dw ? ; Sektoren pro FAT
+BPB_SecsPerTrk dw ? ; Sektoren pro Spur
+BPB_Heads dw ? ; Anzahl K”pfe
+BPB_LinStart dd ? ; linearer Startsektor auf Laufwerk
+BPB_NumSecs32 dd ? ; Anzahl Sektoren, falls >=32 MByte
+BPB_PhysNo dw ? ; physikalische Laufwerks-Nummer
+BPB_ExtID db ? ; Erkennung, daá es ein erweiterter Boot-Record ist
+BPB_SerialNo dd ? ; Seriennummer
+BPB_Name db 11 dup (?) ; Name
+BPB_SysID db 7 dup (?) ; Systemerkennung
+BPB_Length equ $-BPBBuffer ; L„nge BPB
+
+FATBuffer db SecSize dup (?) ; Puffer, um FATs aufzubauen
+MustFlushFAT db ? ; Flag, ob FAT-Puffer geschrieben werden muá
+FATBufferFill dw ? ; Anzahl Nibbles in FAT-Puffer
+
+ endp
+
+;----------------------------------------------------------------------------
+
+ globproc DiskMenu
+
+ push ax ; Register retten
+ push cx
+ push di
+
+ mov [spsave],sp ; Stack umschalten
+ mov [sssave],ss
+ mov ax,cs
+ mov ss,ax
+ lea sp,[Stack]
+
+MenuLoop: mov al,[MomDrive] ; Festplatten-Nr. in Kopfmeldung einschreiben
+ add al,'1'
+ cmp al,'0'
+ jnz DrivePresent ; falls Laufwerk noch undefiniert, - ausgeben
+ mov al,'-'
+DrivePresent: mov [MenuMsg_Drv],al
+ PrMsg MenuMsg
+ mov al,[MomDrive]
+ cmp al,-1 ; falls <>-1, Geometrie ausgeben
+ je NoDrivePresent
+ call GetPTabAdr ; dazu Tabelle holen
+ mov ax,[di+DrPar_Cyls]
+ mov cl,5
+ call WriteDec
+ PrMsg CylMsg
+ mov al,[di+DrPar_Heads]
+ mov ah,0
+ mov cl,3
+ call WriteDec
+ PrMsg HeadMsg
+ mov al,[di+DrPar_NSecs]
+ mov ah,0
+ mov cl,3
+ call WriteDec
+ PrMsg SecMsg
+NoDrivePresent:
+ PrMsg MenuList
+ mov ah,DOS_RdChar
+ int INT_DOS
+ push ax
+ PrChar al
+ PrMsg TwoLines
+ pop ax
+
+ cmp al,'0' ; 0 = Men verlassen
+ lje MenuEnd
+
+ cmp al,'1' ; 1 = Platte wechseln
+ jne NoSelectDisk
+ mov ah,1 ; Rckschreiben erlaubt
+ call SelectDisk
+ jmp MenuLoop
+NoSelectDisk:
+ cmp al,'2' ; 2 = Geometrie wechseln
+ jne NoChangeGeometry
+ call ChangeGeometry
+ jmp MenuLoop
+NoChangeGeometry:
+ cmp [MomDrive],-1 ; fr alles weitere muá Platte gesetzt sein
+ jne DiskIsSelected
+ push ax
+ shl ax,8 ; Annahme: Geometrie nicht zurckschreiben
+ cmp ah,'3'
+ je NoWriteBack
+ inc al ; fr alles auáer low-level schon
+NoWriteBack: call SelectDisk ; implizit Laufwerk erfragen
+ PrMsg NewLine
+ pop ax
+ cmp [MomDrive],-1
+ lje MenuLoop ; wenn immer noch nicht gesetzt, Abbruch
+DiskIsSelected:
+ cmp al,'3' ; 3 = Platte low-leveln
+ jne NoFormatDisk
+ call FormatDisk
+ jmp MenuLoop
+NoFormatDisk:
+ cmp al,'4' ; 4 = Spur formatieren
+ jne NoFormTrack
+ call FormTrack
+ jmp MenuLoop
+NoFormTrack:
+ cmp al,'5' ; 5 = Platte prflesen
+ jne NoBadTrack
+ call BadTrack
+ jmp MenuLoop
+NoBadTrack:
+ cmp al,'6' ; 6 = Platte verifizieren
+ jne NoVerifyDisk
+ call VerifyDisk
+ jmp MenuLoop
+NoVerifyDisk:
+ cmp al,'7' ; 7 = Partition anlegen
+ jne NoMakePart
+ call MakePart
+ jmp MenuLoop
+NoMakePart:
+ cmp al,'8' ; 8 = Partition formatieren
+ jne NoFormatPart
+ call FormatPart
+ jmp MenuLoop
+NoFormatPart: PrChar BEL ; alle anderen Angaben anmeckern
+ jmp MenuLoop
+MenuEnd: mov ss,[sssave] ; Stack zurck
+ mov sp,[spsave]
+
+ pop di
+ pop cx
+ pop ax ; Register zurck
+
+ ret
+
+MenuMsg db CR,LF,"SECDRIVE Men Platte:"
+MenuMsg_Drv db '-',CR,LF,'$'
+CylMsg db " Zylinder,$"
+HeadMsg db " K”pfe,$"
+SecMsg db " Sektoren",CR,LF,'$'
+MenuList db CR,LF
+ db "1 = Platte wechseln",CR,LF
+ db "2 = Geometrie neu definieren",CR,LF
+ db "3 = Platte formatieren",CR,LF
+ db "4 = Spur formatieren",CR,LF
+ db "5 = Defekte Spuren markieren",CR,LF
+ db "6 = Platte verifizieren",CR,LF
+ db "7 = Partition erstellen",CR,LF
+ db "8 = Partition log. formatieren",CR,LF
+ db "------------------------",CR,LF
+ db "0 = Men verlassen",CR,LF,'$'
+spsave dw ?
+sssave dw ?
+
+ db 1024 dup (?) ; Programmstack
+Stack:
+
+ endp
+
+MomDrive db -1
+TwoLines: db CR,LF
+NewLine: db CR,LF,'$'
+
+ endsection
diff --git a/tests/t_secdrive/t_secdrive.asm b/tests/t_secdrive/t_secdrive.asm
new file mode 100644
index 0000000..4fc82c9
--- /dev/null
+++ b/tests/t_secdrive/t_secdrive.asm
@@ -0,0 +1,1476 @@
+;******************************************************************************
+;* *
+;* SECDRIVE - Treiber fr einen 2. HD-Kontroller im PC *
+;* *
+;* Historie: 12. 8.1993 Grundsteinlegung, Definitionen *
+;* 16. 8.1993 Dispatcher *
+;* Basislesefunktionen *
+;* 17. 8.1993 Partitionsinformationen zusammenkratzen *
+;* 18. 8.1993 Laufwerksparameter initialisieren *
+;* 19. 8.1993 Zylinder/Sektorregister setzen *
+;* Partitiossektorbaum durchgehen *
+;* 24. 8.1993 BPB aufbauen *
+;* 25. 8.1993 Parameterbersetzung *
+;* Einlesen *
+;* Sektoren schreiben *
+;* 26. 8.1993 Fehlerbehandlung *
+;* Verify *
+;* 1. Restore-Versuch mit Seek *
+;* 7. 9.1993 Versuch Version 1.39 mit Proc's *
+;* 28. 9.1993 etwas gekrzt *
+;* 27.12.1994 leichte Korrekturen im Restore *
+;* 28.12.1994 Trennung Low-Level-Routinen begonnen *
+;* 19. 1.1995 Fehlermeldungen im Klartext *
+;* *
+;******************************************************************************
+
+;******************************************************************************
+;* globale Definitionen *
+;******************************************************************************
+
+; A C H T U N G : Mono.SYS muá fr Debugging geladen sein !!!!
+
+debug equ 0
+debug2 equ 0
+
+ include bitfuncs.inc
+
+ cpu 80186 ; WD 1003 fordert min. 80286
+
+Diag_NoError equ 01h ; Selbstdiagnosecodes: kein Fehler
+Diag_ContError equ 02h ; Controller-Fehler
+Diag_SBufError equ 03h ; Sektorpuffer defekt
+Diag_ECCError equ 04h ; Fehlerkorrektor defekt
+Diag_ProcError equ 05h ; Steuerprozessor defekt
+Diag_Timeout equ 06h ; Controller antwortet nicht
+
+ParTab struct
+BFlag db ? ; Partitionseintrag: Partition aktiv ?
+FHead db ? ; Startkopf
+FSecCyl dw ? ; Startzylinder/sektor
+Type db ? ; Partitionstyp
+LHead db ? ; Endkopf
+LSecCyl dw ? ; Endzylinder/sektor
+LinSec dd ? ; Anzahl Sektoren
+NSecs dd ? ; linearer Startsektor
+ endstruct
+
+DErr_WrProtect equ 00h ; Treiberfehlercodes: Schreibschutz
+DErr_InvUnit equ 01h ; unbekannte Ger„tenummer
+DErr_NotReady equ 02h ; Laufwerk nicht bereit
+DErr_Unknown equ 03h ; Unbekannes Treiberkommando
+DErr_CRCError equ 04h ; Prfsummenfehler
+DErr_InvBlock equ 05h ; ungltiger Request-Header
+DErr_TrkNotFnd equ 06h ; Spur nicht gefunden
+DErr_InvMedia equ 07h ; Unbekanntes Tr„gerformat
+DErr_SecNotFnd equ 08h ; Sektor nicht gefunden
+DErr_PaperEnd equ 09h ; Papierende im Drucker
+DErr_WrError equ 0ah ; allg. Schreibfehler
+DErr_RdError equ 0bh ; allg. Schreibfehler
+DErr_GenFail equ 0ch ; allg. Fehler
+DErr_InvChange equ 0fh ; unerlaubter Diskettenwechsel
+
+DErr_UserTerm equ 0ffh ; Fehlercode Abbruch durch Benutzer
+
+SecSize equ 512 ; SektorgrӇe in Bytes
+MaxPDrives equ 2 ; Maximalzahl physikalischer Laufwerke
+MaxDrives equ 10 ; Maximalzahl verwaltbarer Laufwerke
+MaxParts equ 4 ; Maximalzahl Partitionen in einem Sektor
+MaxRetry equ 2 ; max. 2 Lese/Schreibversuche
+StackSize equ 512 ; etwas mehr wg. Rekursion
+
+DrPar_Offset equ 1aeh ; Offset Parametertabelle im Part.-Sektor
+ParTab_Offset equ 1beh ; Offset Partitionstabelle " " "
+ParSecID_Offset equ 1feh ; Offset Partitionssektorflag (55aa)
+BPBOfs equ 11 ; Offset BPB im Bootsektor
+
+INT_DOS equ 21h ; DOS-Funktionsaufruf
+INT_Mono equ 60h ; Haken zum VT100-Treiber
+INT_Clock equ 1ah ; BIOS-Uhreneinstieg
+INT_Keyboard equ 16h ; BIOS-Tastatureinstieg
+
+DOS_WrString equ 9 ; DOS-Funktionen
+DOS_WrChar equ 6
+DOS_RdString equ 10
+DOS_RdChar equ 8
+
+HD_ID equ 0f8h ; Media-ID fr Festplatten
+
+CR equ 13
+LF equ 10
+BEL equ 7
+ESC equ 27
+
+;******************************************************************************
+; Makros *
+;******************************************************************************
+
+;jmp macro adr
+; !jmp long adr
+; endm
+
+beep macro
+ push ax
+ mov ax,0e07h
+ int 10h
+ pop ax
+ endm
+
+PrMsg macro Adr ; Meldung ausgeben
+ push dx ; Register retten
+ lea dx,[Adr]
+ mov ah,DOS_WrString
+ int INT_DOS
+ pop dx ; Register zurck
+ endm
+
+PrChar macro Zeichen ; Zeichen ausgeben
+ push dx ; Register retten
+ push ax
+ mov dl,Zeichen
+ mov ah,DOS_WrChar
+ int INT_DOS
+ pop ax
+ pop dx ; Register zurck
+ endm
+
+;------------------------------------------------------------------------------
+
+btst macro op,bit ; ein einzelnes Bit testen
+ test op,(1<<bit)
+ endm
+
+;------------------------------------------------------------------------------
+
+ljnz macro adr ; lange Sprnge
+ jz Next
+ jmp adr
+Next:
+ endm
+
+ljne macro adr
+ je Next
+ jmp adr
+Next:
+ endm
+
+ljc macro adr
+ jnc Next
+ jmp adr
+Next:
+ endm
+
+lje macro adr
+ jne Next
+ jmp adr
+Next:
+ endm
+
+ljz macro adr
+ jnz Next
+ jmp adr
+Next:
+ endm
+
+ljb macro adr
+ jnb Next
+ jmp adr
+Next:
+ endm
+
+;------------------------------------------------------------------------------
+
+proc macro name
+ section name
+ public name:parent
+name label $
+ endm
+
+globproc macro name
+ section name
+ public name
+name label $
+ endm
+
+endp macro
+ endsection
+ endm
+
+;------------------------------------------------------------------------------
+; Fehlermakro
+
+JmpOnError macro Drv,Adr
+ jnc GoOn ; kein Fehler, weitermachen
+ mov ah,Drv
+ call WrErrorCode ; Fehler-->ausgeben...
+ jmp Adr ; ...Abbruch
+GoOn:
+ endm
+
+;******************************************************************************
+;* Treiberkopf *
+;******************************************************************************
+
+
+ assume cs:code,ds:nothing,ss:nothing,es:nothing
+
+ org 0
+
+DriverHead: dd -1 ; Zeiger auf Nachfolger
+ dw 0000100000000010b ; Attribut
+; ^ ^ ^
+; ³ ³ ÀÄ kann 32-Bit-Setornummern verarbeiten
+; ³ ÀÄÄÄÄÄÄÄÄÄÄÄ kennt Close/Open/Removeable
+; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Blocktreiber
+ dw StrategyProc ; Zeiger auf Strategieroutine
+ dw InterruptProc ; Zeiger auf eigentlichen Treibercode
+NrOfVols: db 0 ; Zahl log. Laufwerke
+ db "SECDRIV" ; bei Blocktreibern unbenutzt
+
+;******************************************************************************
+;* residente Daten *
+;******************************************************************************
+
+Rh_Ptr dd ? ; Speicher fr Request-Header
+
+JmpTable dw Init ; Sprungtabelle: Initialisierung
+ dw MediaCheck ; Medium gewechselt ?
+ dw BuildBPB ; Parameterblock laden
+ dw IOCTLRead ; Steuerdaten vom Treiber
+ dw Read ; Daten lesen
+ dw ND_Read ; Lesen, ohne Pufferstatus zu „ndern
+ dw InputStatus ; Daten im Eingabepuffer ?
+ dw InputFlush ; Eingabepuffer l”schen
+ dw Write ; Daten schreiben
+ dw Write_Verify ; Daten mit Prflesen schreiben
+ dw OutputStat ; Ausgabepuffer leer ?
+ dw OutputFlush ; Ausgabepuffer l”schen
+ dw IOCTLWrite ; Steuerdaten zum Treiber
+ dw DeviceOpen ; DOS hat eine Datei darauf ge”ffnet
+ dw DeviceClose ; DOS hat eine Datei darauf geschlossen
+ dw Removeable ; Ist Datentr„ger wechselbar ?
+ dw OutputTillBusy ; Ausgabe, bis Puffer voll
+ dw GenIOCTL ; genormtes IOCTL
+ dw GetLogical ; Laufwerkszuordnung lesen
+ dw SetLogical ; Laufwerkszuordnung setzen
+ dw IOCTLQuery ; Abfrage, ob GenIOCTL untersttzt
+
+SectorBuffer: db SecSize dup (?) ; Sektorpuffer fr Treiber selber
+
+ db StackSize dup (?) ; Treiberstack
+DriverStack:
+
+BPBSize equ 36
+DrTab struct ; Laufwerkstabelle:
+StartHead db ? ; Startkopf
+StartCyl dw ? ; Startzylinder
+StartSec db ? ; Startsektor
+LinStart dd ? ; lin. Startsektor
+SecCnt dd ? ; Gesamtsektorzahl
+Drive db ? ; Laufwerk
+BPB db BPBSize dup (?) ; BPB
+ endstruct
+
+DrTab db DrTab_Len*MaxDrives dup (?)
+DrTab_BPBs dd 2*MaxDrives dup (?)
+DrCnt db 0 ; Anzahl gefundener Laufwerke
+DrOfs db 0 ; erster freier Laufwerksbuchstabe
+
+DrPar struct ; Plattenparametersatz:
+Cyls dw ? ; Zylinderzahl
+Heads db ? ; Kopfzahl
+RedWr dw ? ; Startzylinder reduzierter Schreibstrom
+PrComp dw ? ; Startzylinder Pr„kompensation
+ECCLen db ? ; max. korrigierbarer Fehlerburst (Bits)
+CByte db ? ; Wert frs Plattensteuerregister
+TOut db ? ; genereller Timeout
+FTOut db ? ; Timeout Formatierung
+CTOut db ? ; Timeout fr Prfung
+LZone dw ? ; Landezylinder
+NSecs db ? ; Sektorzahl
+Dummy db ? ; unbenutzt
+ endstruct
+
+DrPars db DrPar_Len*MaxPDrives dup (0)
+
+;******************************************************************************
+;* Strategieroutine *
+;******************************************************************************
+
+StrategyProc: mov word ptr [Rh_Ptr],bx ; Zeiger speichern
+ mov word ptr [Rh_Ptr+2],es
+ retf
+
+;******************************************************************************
+;* Treiberdispatcher *
+;******************************************************************************
+
+Rh struct
+Size db ? ; gemeinsame Headerteile: L„nge Block
+Unit db ? ; angesprochenes Laufwerk
+Func db ? ; Treibersubfunktion
+Status dw ? ; Ergebnis
+Resvd db 8 dup (?) ; unbenutzt
+ endstruct
+
+InterruptProc: pusha ; alle Register retten
+
+ cli ; Stack umschalten
+ mov si,ss ; alten zwischenspeichern
+ mov di,sp
+ mov ax,cs ; neuen setzen
+ mov ss,ax
+ lea sp,[DriverStack]
+ push di ; alten auf neuem (!) speichern
+ push si
+ sti
+
+ mov ax,cs ; DS auf Treibersegment
+ mov ds,ax
+ assume ds:code
+
+ les bx,[Rh_Ptr] ; Zeiger laden
+ mov word ptr es:[bx+Rh_Status],0 ; Status l”schen
+
+ mov al,es:[bx+Rh_Func] ; Subfunktion ausrechnen
+ if debug
+ call PrByte
+ endif
+ mov ah,0
+ add ax,ax
+ mov si,ax
+ jmp JmpTable[si]
+
+ jmp Init
+
+;******************************************************************************
+;* gemeinsames Ende *
+;******************************************************************************
+
+StateError: btst al,1 ; Bit 1: Spur 0 nicht gefunden
+ jz StateError_N1
+ mov al,DErr_TrkNotFnd
+ jmp StateError_End
+StateError_N1: btst al,2 ; Bit 2: abgebrochenes Kommando
+ jz StateError_N2
+ btst ah,5 ; Bit S5: Schreibfehler
+ jz StateError_N21
+ mov al,DErr_WrError
+ jmp StateError_End
+StateError_N21: btst ah,4 ; Bit S4: Positionierung nicht vollst„ndig
+ jnz StateError_N22
+ mov al,DErr_TrkNotFnd
+ jmp StateError_End
+StateError_N22: btst ah,6 ; Bit S6: Laufwerk nicht bereit
+ jnz StateError_N23
+ mov al,DErr_NotReady
+ jmp StateError_End
+StateError_N23: mov al,DErr_GenFail ; Notnagel 1
+ jmp StateError_End
+StateError_N2: test al,11h ; Bit 0/4: Sektor nicht gefunden
+ jz StateError_N3
+ mov al,DErr_SecNotFnd
+ jmp StateError_End
+StateError_N3: btst al,6 ; Bit 6: Prfsummenfehler
+ jz StateError_N4
+ mov al,DErr_CRCError
+ jmp StateError_End
+StateError_N4: mov al,DErr_GenFail ; Notnagel 2
+StateError_End: les bx,[Rh_Ptr] ; Code einspeichern
+ mov es:[bx+Rh_Status],al
+ jmp Error
+
+Unknown: les bx,[Rh_Ptr]
+ mov byte ptr es:[bx+Rh_Status],DErr_Unknown ; unbek. Funktion
+
+Error: or byte ptr es:[bx+Rh_Status+1],80h ; Fehler-Flag setzen
+ jmp Done
+
+Busy: les bx,[Rh_Ptr]
+ or byte ptr es:[bx+Rh_Status+1],2 ; Busy-Flag setzen
+
+Done: les bx,[Rh_Ptr]
+ or byte ptr es:[bx+Rh_Status+1],1 ; Done-Flag setzen
+
+ if debug
+ call NxtLine
+ endif
+
+ cli ; Stack zurckschalten
+ pop si
+ pop di ; alten in SI:DI laden
+ mov sp,di ; einschreiben
+ mov ss,si
+ sti
+
+ popa ; Register zurck
+ retf
+
+;******************************************************************************
+;* Debugginghilfe *
+;******************************************************************************
+
+ if debug||debug2
+
+HexTab db "0123456789ABCDEF"
+
+PrByte: push es ; Register retten
+ push di
+ push bx
+ push ax
+
+ lea bx,[HexTab]
+
+
+ db 0d4h,10h ; AAM 16
+ push ax
+ mov al,ah
+ xlat
+ mov ah,0eh
+ int 10h
+ pop ax
+ xlat
+ mov ah,0eh
+ int 10h
+
+ pop ax ; Register zurck
+ pop bx
+ pop di
+ pop es
+ ret
+
+PrWord: xchg ah,al ; Hi-Byte
+ call PrByte
+ xchg ah,al
+ call PrByte
+ ret
+
+PrChar: push ax
+ mov ah,0eh
+ int 10h
+ pop ax
+ ret
+
+NxtLine: push ax ; Register retten
+ push bx
+ push dx
+
+ mov ax,0e0dh
+ int 10h
+ mov ax,0e0ah
+ int 10h
+
+ pop dx ; Register zurck
+ pop bx
+ pop ax
+
+ endif
+
+;******************************************************************************
+;* residente Subfunktionen *
+;******************************************************************************
+
+;******************************************************************************
+;* eine logische Laufwerksnummer berprfen *
+;* In : AL = Laufwerk *
+;* Out : C = 1, falls Fehler *
+;******************************************************************************
+
+ proc ChkDrive
+
+ cmp al,[DrCnt] ; C=1, falls < (d.h. OK)
+ cmc ; Deshalb noch einmal drehen
+ jnc OK ; C=0, alles in Butter
+ les bx,[Rh_Ptr] ; ansonsten Fehlerstatus setzen
+ mov byte ptr es:[bx+Rh_Status],DErr_InvUnit
+OK: ret
+
+ endp
+
+;******************************************************************************
+;* Adresse der phys. Laufwerkstabelle errechnen *
+;* In : AL = Laufwerk *
+;* Out : DI = Adresse *
+;******************************************************************************
+
+ proc GetPTabAdr
+
+ mov ah,DrPar_Len ; relative Adresse berechnen
+ mul ah
+ lea di,[DrPars] ; Offset dazu
+ add di,ax
+ ret
+
+ endp
+
+;******************************************************************************
+;* Adresse eines Partitionsdeskriptors errechnen *
+;* In : AL = log. Laufwerk *
+;* Out : DI = Adresse *
+;******************************************************************************
+
+ proc GetTabAdr
+
+ mov ah,DrTab_Len ; relative Adresse berechnen
+ mul ah
+ lea di,[DrTab] ; Offset dazu
+ add di,ax
+ ret
+
+ endp
+
+;******************************************************************************
+;* logische Parameter in physikalische bersetzen *
+;* In : BL = log. Laufwerk *
+;* DX:AX = relative Sektornummer *
+;* Out : AL = phys. Laufwerk *
+;* AH = Kopf *
+;* BX = Zylinder *
+;* CH = Sektor *
+;******************************************************************************
+
+ proc TranslateParams
+
+ push di ; Register retten
+
+ xchg bx,ax ; Adresse Parametertabelle holen
+ call GetTabAdr
+
+ add bx,[di+DrTab_LinStart] ; in absolute Sektornummer
+ adc dx,[di+DrTab_LinStart+2] ; umrechnen
+ mov al,[di+DrTab_Drive] ; phys. Laufwerksnummer holen
+ push ax ; bis zum Ende retten
+
+ call GetPTabAdr ; von dieser phys. Platte die Tabelle holen
+ mov ax,bx ; Sektor# wieder nach DX:AX
+ mov bl,[di+DrPar_NSecs] ; Sektorzahl auf 16 Bit
+ mov bh,0 ; aufblasen
+ div bx
+ mov ch,dl ; Modulo-Rest ist Sektornummer auf
+ inc ch ; Spur: Vorsicht, Numerierung ab 1 !!!
+ sub dx,dx ; wieder auf 32 Bit erweitern
+ mov bl,[di+DrPar_Heads] ; Kopfnummer herausfummeln
+ div bx
+ mov bx,ax ; Quotient ist Zylinder
+ pop ax ; Laufwerk zurck
+ mov ah,dl ; Rest ist Kopf
+
+ pop di ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* Einbindung Low-Level-Routinen *
+;******************************************************************************
+
+; definiert werden mssen:
+
+; LowLevelIdent: Meldung ber untersttzte Hardware ausgeben
+; ContDiag: Kontroller-Selbsttest durchfhren
+; Ergebniskode in AL
+; Recalibrate: Laufwerk [AL] auf Zylinder 0 fahren
+; Fehlerflag in C, Fehlerkode in AX
+; SetDriveParams: dem Kontroller die Geometrie fr Laufwerk [AL] einbleuen
+; Fehlerflag in C
+; ReadSectors: von Laufwerk [AL] ab Zylinder [BX], Kopf [AH], Sektor [CH]
+; [CL] Sektoren in Puffer ab ES:DI lesen
+; Fehlerflag in C, Fehlerkode in AX
+; WriteSectors: auf Laufwerk [AL] ab Zylinder [BX], Kopf [AH], Sektor [CH]
+; [CL] Sektoren von Puffer ab ES:SI schreiben
+; Fehlerflag in C, Fehlerkode in AX
+; VeriSectors: auf Laufwerk [AL] ab Zylinder [BX], Kopf [AH], Sektor [CH]
+; [CL] Sektoren verifizieren
+; Fehlerflag in C, Fehlerkode in AX
+; FormatUnit: Laufwerk [AL] mit Interleave [AH] formatieren, Fehlerkode
+; in AX
+; FormatTrack: Zylinder [BX], Kopf [AH] auf Laufwerk [AL] mit Interleave
+; [CL] formatieren, Fehlerkode in AX
+; MarkBad: Zylinder [BX], Kopf [AH] auf Laufwerk [AL] als defekt
+; markieren, Fehlerkode in AX
+
+ include "lowlevel.inc"
+
+;******************************************************************************
+;* Bootsektor eines log. Laufwerkes lesen *
+;* In : AL = Laufwerksnummer *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ proc ReadBootSec
+
+ push es ; Register retten
+ push bx
+ push cx
+ push di
+
+ call GetTabAdr ; Eintrag in Laufwerkstabelle ermitteln
+ mov al,[di+DrTab_Drive] ; davon ersten Sektor lesen
+ mov ah,[di+DrTab_StartHead]
+ mov bx,[di+DrTab_StartCyl]
+ mov cl,1
+ mov ch,[di+DrTab_StartSec]
+ mov di,cs
+ mov es,di
+ lea di,[SectorBuffer]
+ call ReadSectors
+
+ pop di ; Register zurck
+ pop cx
+ pop bx
+ pop es
+ ret
+
+ endp
+
+;******************************************************************************
+;* Funktion 1: Test, ob Medium gewechselt *
+;******************************************************************************
+
+ proc MediaCheck
+
+Rh_MediaID equ Rh_Resvd+8 ; erwartetes Media-ID
+Rh_Return equ Rh_MediaID+1 ; Ergebnis-Flag
+Rh_VolName equ Rh_Return+1 ; Adresse alter Laufwerksname
+
+ cmp byte ptr es:[bx+Rh_MediaID],HD_ID ; gltige ID ?
+ je OK
+ mov byte ptr es:[bx+Rh_Status],DErr_InvMedia ; nein...
+ jmp Error
+OK: mov byte ptr es:[bx+Rh_Return],1 ; nie gewechselt
+ jmp Done
+
+ endp
+
+;******************************************************************************
+;* Funktion 2: BPB aufbauen *
+;******************************************************************************
+
+ proc BuildBPB
+
+Rh2 struct
+ db Rh_Len dup (?)
+MediaID db ? ; erwartetes Media-ID
+FATSector dd ? ; Pufferadresse 1. FAT-Sektor
+BPBAddress dd ? ; Adresse neuer BPB
+ endstruct
+
+ mov al,es:[bx+Rh_Unit]
+ call ChkDrive ; Laufwerksnummer gltig ?
+ ljc Error ; nein-->Fehler & Ende
+
+ call ReadBootSec ; Bootsektor lesen
+ ljc StateError ; bei Fehlern Ende
+
+ les bx,[Rh_Ptr] ; Zeiger neu laden
+ mov al,es:[bx+Rh_Unit] ; Tabellenadresse aufbauen
+ call GetTabAdr
+ lea di,[di+DrTab_BPB] ; DI auf BPB-Speicher
+ mov es:[bx+Rh2_BPBAddress],di ; BPB-Zeiger abspeichern
+ mov es:[bx+Rh2_BPBAddress+2],cs
+
+ mov si,cs ; BPB umkopieren
+ mov es,si
+ lea si,[SectorBuffer+BPBOfs]
+ cld
+ mov cx,BPBSize
+ rep movsb
+
+ jmp Done
+
+ endp
+
+;******************************************************************************
+
+IOCTLRead: jmp Unknown
+
+;******************************************************************************
+;* Funktion 4: Sektoren lesen *
+;******************************************************************************
+
+Rh4 struct
+ db Rh_len dup (?)
+MediaID db ? ; Media-ID Laufwerk
+BufOfs dw ? ; Adresse Datenpuffer
+BufSeg dw ?
+NSecs dw ? ; Anzahl zu lesender Bl”cke
+FirstSec dw ? ; Startsektor bzw. $FFFF fr 32-Bit-Nummern
+VolID dd ? ; Adresse Laufwerksname
+LFirstSec dw ? ; lange Startsektornummer
+HFirstSec dw ?
+ endstruct
+
+Read: mov al,es:[bx+Rh_Unit] ; Laufwerksnummer prfen
+ call ChkDrive
+ ljc Error
+
+ mov ch,al ; Laufwerksnummer retten
+ mov ax,es:[bx+Rh4_FirstSec] ; Sektor holen (BIGDOS beachten)
+ sub dx,dx
+ cmp ax,-1
+ jne Read_SmallSec
+ mov ax,es:[bx+Rh4_LFirstSec]
+ mov dx,es:[bx+Rh4_HFirstSec]
+Read_SmallSec: mov cl,es:[bx+Rh4_NSecs] ; Sektorzahl laden (muá <=128 sein)
+ les di,es:[bx+Rh4_BufOfs] ; Zieladresse laden
+ mov bl,ch ; Laufwerksnummer nach BL
+
+ if debug
+ push ax
+ push cx
+ mov cx,ax
+ mov al,' '
+ call PrChar
+ mov al,bl ; Laufwerksnummer
+ call PrByte
+ mov al,' '
+ call PrChar
+ mov ax,dx ; Startsektor
+ call PrWord
+ mov ax,cx
+ call PrWord
+ mov al,' '
+ call PrChar
+ pop cx
+ mov al,cl ; Sektorzahl
+ call PrByte
+ mov al,' '
+ call PrChar
+ mov ax,es ; Startadresse
+ call PrWord
+ mov al,':'
+ call PrChar
+ mov ax,di
+ call PrWord
+ pop ax
+ endif
+
+ call TranslateParams ; umrechnen lassen
+ call ReadSectors ; der eigentliche Lesevorgang
+
+ ljc StateError ; bei Fehlern...
+ jmp Done ; ansonsten o.k.
+
+;******************************************************************************
+
+ND_Read: jmp Unknown
+
+InputStatus: jmp Unknown
+
+InputFlush: jmp Unknown
+
+;******************************************************************************
+;* Funktion 8: Sektoren schreiben *
+;******************************************************************************
+
+Rh8 struct
+ db Rh_len dup (?)
+MediaID db ? ; Media-ID Laufwerk
+BufOfs dw ? ; Adresse Datenpuffer
+BufSeg dw ?
+NSecs dw ? ; Anzahl zu lesender Bl”cke
+FirstSec dw ? ; Startsektor bzw. $FFFF fr 32-Bit-Nummern
+VolID dd ? ; Adresse Laufwerksname
+LFirstSec dw ? ; lange Startsektornummer
+HFirstSec dw ?
+ endstruct
+
+DoWrite: if debug2
+ mov al,es:[bx+Rh_Unit]
+ call PrByte
+ mov al,' '
+ call PrChar
+ mov ax,es:[bx+Rh8_FirstSec]
+ call PrWord
+ mov al,' '
+ mov ax,es:[bx+Rh8_HFirstSec]
+ call PrWord
+ mov ax,es:[bx+Rh8_LFirstSec]
+ call PrWord
+ call NxtLine
+ endif
+
+ mov al,es:[bx+Rh_Unit]
+ mov ch,al ; Laufwerksnummer retten
+ mov ax,es:[bx+Rh8_FirstSec] ; Sektor holen (BIGDOS beachten)
+ sub dx,dx
+ cmp ax,-1
+ jne DWrite_SmallSec
+ mov ax,es:[bx+Rh8_LFirstSec]
+ mov dx,es:[bx+Rh8_HFirstSec]
+DWrite_SmallSec:mov cl,es:[bx+Rh8_NSecs] ; Sektorzahl laden (muá <=128 sein)
+ les si,es:[bx+Rh8_BufOfs] ; Zieladresse laden
+ mov bl,ch ; Laufwerksnummer nach BL
+
+ if debug
+ push ax
+ push cx
+ mov cx,ax
+ mov al,' '
+ call PrChar
+ mov al,bl ; Laufwerksnummer
+ call PrByte
+ mov al,' '
+ call PrChar
+ mov ax,dx ; Startsektor
+ call PrWord
+ mov ax,cx
+ call PrWord
+ mov al,' '
+ call PrChar
+ pop cx
+ mov al,cl ; Sektorzahl
+ call PrByte
+ mov al,' '
+ call PrChar
+ mov ax,es ; Startadresse
+ call PrWord
+ mov al,':'
+ call PrChar
+ mov ax,si
+ call PrWord
+ pop ax
+ endif
+
+ call TranslateParams ; umrechnen lassen
+ call WriteSectors ; der eigentliche Lesevorgang
+
+ ret
+
+Write: mov al,es:[bx+Rh_Unit] ; Laufwerksnummer prfen
+ call ChkDrive
+ ljc Error
+
+ call DoWrite
+
+ ljc StateError ; bei Fehlern...
+ jmp Done ; ansonsten o.k.
+
+
+;******************************************************************************
+;* Funktion 9: Sektoren schreiben mit šberprfung *
+;******************************************************************************
+
+Rh9 struct
+ db Rh_len dup (?)
+MediaID db ? ; Media-ID Laufwerk
+BufOfs dw ? ; Adresse Datenpuffer
+BufSeg dw ?
+NSecs dw ? ; Anzahl zu lesender Bl”cke
+FirstSec dw ? ; Startsektor bzw. $FFFF fr 32-Bit-Nummern
+VolID dd ? ; Adresse Laufwerksname
+LFirstSec dw ? ; lange Startsektornummer
+HFirstSec dw ?
+ endstruct
+
+Write_Verify: mov al,es:[bx+Rh_Unit] ; Laufwerksnummer prfen
+ call ChkDrive
+ ljc Error
+
+ call DoWrite ; schreiben
+
+ ljc StateError ; bei Fehlern vorher abbrechen
+
+ les bx,[Rh_Ptr] ; Parameter nochmal fr Verify laden
+ mov al,es:[bx+Rh_Unit]
+ mov ch,al
+ mov ax,es:[bx+Rh9_FirstSec]
+ sub dx,dx
+ cmp ax,-1
+ jne VWrite_SmallSec
+ mov ax,es:[bx+Rh9_LFirstSec]
+ mov dx,es:[bx+Rh9_HFirstSec]
+VWrite_SmallSec:mov cl,es:[bx+Rh9_NSecs]
+ mov bl,ch
+
+ call TranslateParams ; nochmal umrechen...
+ call VeriSectors ; und prflesen
+
+ jmp Done ; alles gut gegangen
+
+;******************************************************************************
+
+OutputStat: jmp Unknown
+
+OutputFlush: jmp Unknown
+
+IOCTLWrite: jmp Unknown
+
+;******************************************************************************
+;* kein Device wechselbar, ™ffnen/Schleáen interessiert nicht *
+;******************************************************************************
+
+DeviceOpen: jmp Done
+
+DeviceClose: jmp Done
+
+Removeable: jmp Done
+
+;******************************************************************************
+
+OutputTillBusy: jmp Unknown
+
+GenIOCTL: jmp Unknown
+
+GetLogical: jmp Unknown
+
+SetLogical: jmp Unknown
+
+IOCTLQuery: jmp Unknown
+
+;******************************************************************************
+;* Funktion 0: Initialisierung *
+;******************************************************************************
+
+ include "secparam.inc"
+
+Rh0 struct
+ db Rh_len dup (?)
+Units db ? ; Zahl bedienter Laufwerke
+EndOfs dw ? ; Endadresse Offset
+EndSeg dw ? ; Endadresse Segment
+ParamOfs dw ? ; Parameter Offsetadresse
+ParamSeg dw ? ; Parameter Segmentadresse
+FirstDrive db ? ; erstes freies Laufwerk
+MsgFlag db ? ; Flag, ob DOS Fehler ausgeben darf
+ endstruct
+
+Init: PrMsg HelloMsg ; Meldung ausgeben
+ call LowLevelIdent ; Startmeldung des Low-Level-Treibers
+
+ mov byte ptr es:[bx+Rh0_Units],0 ; noch keine Laufwerke
+
+ mov al,es:[bx+Rh0_FirstDrive] ; Startlaufwerk retten
+ mov [DrOfs],al
+
+ mov ax,cs ; ES auf gem. Segment
+ mov es,ax
+
+; Schritt 1: Controller prfen
+
+ PrMsg DiagMsg0
+ call ContDiag ; Diagnose ausfhren
+ sub al,Diag_NoError
+ cmp al,6 ; auáerhalb ?
+ jae Diag_Over
+ add al,al ; Meldung ausrechnen
+ mov ah,0
+ mov si,ax
+ mov dx,DiagMsgTable[si]
+ mov ah,9
+ int INT_DOS
+ or si,si ; fehlerfrei ?
+ ljnz Init_Err ; Nein, Fehler
+ jmp Init_ChkDrives ; Ja, weiter zum Laufwerkstest
+
+Diag_Over: push ax
+ PrMsg UndefDiagMsg ; undefinierter Fehlercode
+ pop ax
+ add al,Diag_NoError ; Meldung rckkorrigieren
+ db 0d4h,10h ; AAM 16
+ add ax,'00'
+ push ax
+ mov al,ah
+ mov ah,14
+ int 10h
+ pop ax
+ mov ah,14
+ int 10h
+ PrChar CR
+ PrChar LF
+ jmp Init_Err
+
+
+; Schritt 2: Laufwerke testen
+
+; Menaufruf?
+
+Init_ChkDrives: mov ax,40h ; CTRL gedrckt ?
+ mov es,ax
+ btst byte ptr es:[17h],2
+ jz Init_Menu
+ call DiskMenu
+
+; Schritt 2a: Laufwerk rekalibrieren
+
+Init_Menu: mov al,[MomDrive]
+ call Recalibrate
+ ljc Init_NextDrive ; Fehler: Laufwerk berspringen
+
+; Schritt 2b: Masterpartitionssektor lesen
+
+ReadMaster: mov al,[MomDrive]
+ mov ah,0 ; Kopf...
+ sub bx,bx ; ...Zylinder...
+ mov cx,0101h ; ...ein Sektor ab Sektor 1
+ mov di,ds
+ mov es,di
+ lea di,[SectorBuffer] ; in den Sektorpuffer
+ call ReadSectors
+ JmpOnError [MomDrive],Init_NextDrive ; Fehler ?
+
+; Schritt 2c: Laufwerksparameter initialisieren
+
+ lea si,[SectorBuffer+DrPar_Offset] ; Quelladresse im Sektor
+ mov al,[MomDrive] ; Zieladresse ausrechnen
+ call GetPTabAdr
+ mov cx,DrPar_Len
+ cld
+ rep movsb
+
+ sub di,DrPar_Len ; Laufwerk nicht initialisiert ?
+ cmp word ptr[di+DrPar_Cyls],0
+ je DoQuery
+ cmp byte ptr[di+DrPar_Heads],0
+ je DoQuery
+ cmp byte ptr[di+DrPar_NSecs],0
+ jne NoQuery
+DoQuery: mov al,[MomDrive] ; wenn ja, dann nachfragen
+ mov ah,1 ; Rckschreiben hier erlaubt
+ call QueryParams
+ or al,al ; =0-->Laufwerk ignorieren
+ jz Init_NextDrive
+ dec al ; =1-->nochmal lesen
+ jz ReadMaster ; ansonsten weitermachen
+
+NoQuery: mov al,[MomDrive] ; Laufwerksparameter ausgeben...
+ call PrintPDrive
+ mov al,[MomDrive] ; ...und dem Controller einbleuen
+ call SetDriveParams
+ JmpOnError [MomDrive],Init_NextDrive
+ mov al,[MomDrive]
+ call Recalibrate
+ JmpOnError [MomDrive],Init_NextDrive
+
+; Schritt 2d: durch die Partitionssektoren hangeln
+
+ mov al,[MomDrive] ; Laufwerk : momentanes
+ cbw ; Kopf : 0
+ push ax
+ sub ax,ax
+ push ax ; Zylinder : 0
+ inc ax ; Sektor : 1
+ push ax
+ dec ax
+ push ax ; lin. Sektornummer 0
+ push ax
+ call ScanParts
+
+Init_NextDrive: inc [MomDrive] ; Z„hler weitersetzen
+ cmp [MomDrive],MaxPDrives
+ ljb Init_ChkDrives
+
+ cmp [DrCnt],0 ; keine Partitionen gefunden ?
+ jne Init_PDrives
+ PrMsg ErrMsgNoDrives ; ja: meckern
+ jmp Init_Err
+
+Init_PDrives: PrMsg LDriveMsg
+ mov [MomDrive],0 ; Parameter der Partitionen ausgeben
+ lea bp,[DrTab_BPBs] ; und BPB-Tabelle aufbauen
+ cld
+
+Init_PLDrives: mov al,[MomDrive]
+ call PrintLDrive
+
+ mov al,[MomDrive] ; Bootsdektor lesen
+ call ReadBootSec
+ lea si,[SectorBuffer+BPBOfs] ; BPB rauskopieren
+ mov al,[MomDrive]
+ call GetTabAdr
+ lea di,[di+DrTab_BPB]
+ mov ax,cs
+ mov es,ax
+ mov ds:[bp],di ; Adresse nebenbei ablegen
+ add bp,2
+ mov cx,BPBSize
+ rep movsb
+
+ inc [MomDrive]
+ mov al,[MomDrive]
+ cmp al,[DrCnt]
+ jb Init_PLDrives
+
+ PrChar LF ; sieht besser aus...
+
+ les bx,[Rh_Ptr] ; Zeiger auf BPB-Zeiger einschreiben
+ lea ax,[DrTab_BPBs]
+ mov es:[bx+Rh0_ParamOfs],ax
+ mov es:[bx+Rh0_ParamSeg],cs
+ jmp Init_OK ; Initialisierung erfolgeich zu Ende
+
+Init_Err: PrMsg WKeyMsg
+ xor ah,ah ; damit Meldung lesbar bleibt
+ int 16h
+ sub ax,ax ; Treiber aus Speicher entfernen
+ jmp Init_End
+
+Init_OK: mov al,[DrCnt] ; Laufwerkszahl holen
+ les bx,[Rh_Ptr]
+ mov es:[bx+Rh0_Units],al ; im Request Header eintragen
+ mov [NrOfVols],al ; im Treiberkopf eintragen
+ lea ax,[Init] ; residenten Teil installieren
+
+Init_End: les bx,[Rh_Ptr]
+ mov es:[bx+Rh0_EndOfs],ax ; Endadresse setzen
+ mov es:[bx+Rh0_EndSeg],cs
+
+ jmp Done
+
+;******************************************************************************
+;* transiente Unterroutinen *
+;******************************************************************************
+
+;******************************************************************************
+;* Partitionsbaum durchgehen *
+;* In : dw Kopf/Laufwerk *
+;* dw Zylinder *
+;* dw Sektor *
+;* dd lineare Nummer des Sektors *
+;******************************************************************************
+
+ScParts_DrHd equ 12 ; Parameteradressen auf Stack
+ScParts_Cyl equ 10
+ScParts_Sec equ 8
+ScParts_LinSec equ 4
+ScParts_ParTab equ 0-(MaxParts*ParTab_Len) ; Kopie Partitionstabelle
+ScParts_LocSize equ 0-ScParts_ParTab ; belegter Stack
+
+ScanParts: enter ScParts_LocSize,0
+
+; Partitionssektor lesen
+
+ mov ax,[bp+ScParts_DrHd]
+ mov bx,[bp+ScParts_Cyl]
+ mov ch,[bp+ScParts_Sec]
+ mov cl,1
+ mov di,cs
+ mov es,di
+ lea di,[SectorBuffer]
+ call ReadSectors
+ JmpOnError [MomDrive],ScanParts_End
+
+; Partitionssektorkennung o.k. ?
+
+ cmp word ptr SectorBuffer[ParSecID_Offset],0aa55h
+ ljne ScanParts_End
+
+; Partitionstabelle auslesen
+
+ lea si,[SectorBuffer+ParTab_Offset] ; Quelladresse
+ mov di,ss ; Zieladresse auf Stack
+ mov es,di
+ lea di,[bp+ScParts_ParTab]
+ mov cx,MaxParts*ParTab_Len ; L„nge
+ cld
+ rep movsb
+
+; Partitionstabelle durchgehen
+
+ mov si,ScParts_ParTab ; vorne anfangen
+ mov cx,MaxParts ; alle durchgehen
+ScanParts_Scan: push cx
+
+ mov al,[bp+si+ParTab_Type] ; Typ der Partition lesen
+ lea bx,[AccPartTypes-1] ; auf Suchtabelle
+ScanParts_LAcc: inc bx ; einen Eintrag weiter
+ cmp byte ptr [bx],0 ; Tabellenende ?
+ je ScanParts_Next ; ja-->war nix
+ cmp al,[bx] ; gefunden ?
+ jne ScanParts_LAcc ;
+
+ mov bx,[bp+si+ParTab_LinSec] ; linearen Startsektor ausrechnen
+ mov cx,[bp+si+ParTab_LinSec+2]
+ add bx,[bp+ScParts_LinSec] ; in CX:BX
+ adc cx,[bp+ScParts_LinSec+2]
+
+ cmp al,5 ; extended partition ?
+ jne ScanParts_Enter
+
+ push si ; ja: Zeiger fr Rekursion retten
+ mov al,[bp+ScParts_DrHd] ; Laufwerk & Kopf zusammenbauen
+ mov ah,[bp+si+ParTab_FHead]
+ push ax
+ mov ax,[bp+si+ParTab_FSecCyl] ; Zylinder ausfiltern
+ xchg ah,al
+ shr ah,6
+ push ax
+ mov al,[bp+si+ParTab_FSecCyl] ; Sektor ausfiltern
+ and ax,63
+ push ax
+ push cx
+ push bx
+ call ScanParts
+ pop si ; Zeiger zurck
+ jmp ScanParts_Next
+
+ScanParts_Enter:mov al,[DrCnt] ; Partition in Tabelle eintragen
+ call GetTabAdr ; dazu Adresse neuen Eintrags holen
+ cld
+ mov ax,cs ; Ziel im Segment
+ mov es,ax
+ mov al,[bp+si+ParTab_FHead] ; Kopf kopieren
+ stosb
+ mov ax,[bp+si+ParTab_FSecCyl] ; Zylinder kopieren
+ xchg ah,al
+ shr ah,6
+ stosw
+ mov al,[bp+si+ParTab_FSecCyl] ; Sektor kopieren
+ and al,63
+ stosb
+ mov ax,bx ; linearen Startsektor kopieren
+ stosw
+ mov ax,cx
+ stosw
+ mov ax,[bp+si+ParTab_NSecs] ; Sektorzahl kopieren
+ stosw
+ mov ax,[bp+si+ParTab_NSecs+2]
+ stosw
+ mov al,[bp+ScParts_DrHd] ; Laufwerksnummer kopieren
+ stosb
+ inc [DrCnt] ; ein log. Laufwerk mehr
+
+ScanParts_Next: add si,ParTab_Len ; auf n„chste Partition
+ pop cx
+ dec cx
+ ljnz ScanParts_Scan
+
+ScanParts_End: leave
+ ret 10
+
+;******************************************************************************
+;* Daten eines physikalischen Laufwerks ausgeben *
+;* In : AL = Laufwerk *
+;******************************************************************************
+
+ proc PrintPDrive
+
+ push cx ; Register retten
+ push dx
+ push di
+
+ cbw ; AH l”schen
+ push ax ; Laufwerk ausgeben
+ PrMsg PDriveMsg1
+ pop ax
+ push ax
+ inc ax
+ mov cl,1
+ call WriteDec
+ PrMsg PDriveMsg2
+
+ pop ax ; Adresse Laufwerkstabelle berechnen
+ call GetPTabAdr
+
+ mov ax,[di+DrPar_Cyls] ; Zylinder ausgeben
+ mov cl,5
+ call WriteDec
+ PrMsg PDriveMsg3
+
+ mov al,[di+DrPar_Heads] ; K”pfe ausgeben
+ mov ah,0
+ mov cl,3
+ call WriteDec
+ PrMsg PDriveMsg4
+
+ mov al,[di+DrPar_NSecs] ; Sektoren ausgeben
+ mov ah,0
+ mov cl,4
+ call WriteDec
+ PrMsg PDriveMsg5
+
+ mov al,[di+DrPar_Heads] ; Gesamtsektorzahl berechnen
+ mul byte ptr [di+DrPar_NSecs]
+ mul word ptr [di+DrPar_Cyls]
+ call WriteMBytes
+ PrMsg PDriveMsg6
+
+ pop di ; Register zurck
+ pop dx
+ pop cx
+ ret
+
+ endp
+
+;******************************************************************************
+;* Daten eines logischen Laufwerks ausgeben *
+;* In : AL = Laufwerk *
+;******************************************************************************
+
+ proc PrintLDrive
+
+ push cx ; Register retten
+ push dx
+ push di
+
+ mov dx,ax ; Laufwerk retten
+ push dx
+ mov cx,3 ; ausgeben
+ call WriteSpc
+ add dl,[DrOfs]
+ add dl,'A'
+ mov ah,DOS_WrChar
+ int INT_DOS
+ PrChar ':'
+
+ pop ax ; Tabelle holen
+ call GetTabAdr
+
+ mov al,[di+DrTab_Drive] ; Laufwerk ausgeben...
+ inc al
+ cbw
+ mov cl,9
+ call WriteDec
+
+ mov ax,[di+DrTab_StartCyl] ; ...Zylinder...
+ mov cl,10
+ call WriteDec
+
+ mov al,[di+DrTab_StartHead] ; ...Kopf...
+ cbw
+ mov cl,7
+ call WriteDec
+
+ mov al,[di+DrTab_StartSec] ; ...Sektor...
+ cbw
+ mov cl,8
+ call WriteDec
+
+ mov cx,2
+ call WriteSpc
+ mov ax,[di+DrTab_SecCnt] ; ...GrӇe
+ mov dx,[di+DrTab_SecCnt+2]
+ call WriteMBytes
+
+ PrMsg PDriveMsg6 ; Meldung wiederverwertet...
+
+ pop di ; Register zurck
+ pop dx
+ pop cx
+ ret
+
+ endp
+
+;******************************************************************************
+;* Fehlercode eines Laufwerks ausgeben *
+;* In : AL = Fehlercode *
+;* AH = Laufwerksnummer (0,1...) *
+;******************************************************************************
+
+ proc WrErrorCode
+
+ push bx ; Register retten
+ push cx
+ push dx
+
+ add ah,'1' ; LW-Nummer in ASCII umrechnen...
+ mov [DrvErrorMsg2],ah ; ...und einschreiben
+ mov ch,al ; Kode sichern
+ PrMsg DrvErrorMsg
+ mov cl,7 ; bei Bit 0 anfangen
+ErrLoop: rol ch,1 ; fagl. Bit in Carry
+ jnc NoErrBit
+ mov bl,cl ; Bit gefunden: Index ausrechnen
+ mov bh,0
+ add bx,bx
+ mov dx,[bx+Pointers]
+ mov ah,DOS_WrString
+ int INT_DOS
+NoErrBit: dec cl ; n„chstes Bit
+ jnz ErrLoop
+
+ pop dx ; Register zurck
+ pop cx
+ pop bx
+
+ ret
+
+DrvErrorMsg: db "Fehler auf Festplatte "
+DrvErrorMsg2: db "0:",CR,LF,'$'
+
+Pointers dw Msg0,Msg1,Msg2,Msg3,Msg4,Msg5,Msg6,Msg7
+Msg0 db " Adreámarke nicht gefunden",CR,LF,'$'
+Msg1 db " Spur 0 nicht gefunden",CR,LF,'$'
+Msg2 db " Kommandoabbruch",CR,LF,'$'
+Msg3 db "$"
+Msg4 db " Sektor nicht gefunden",CR,LF,'$'
+Msg5 db "$"
+Msg6 db " Datenfehler",CR,LF,'$'
+Msg7 db " Sektor als defekt markiert",CR,LF,'$'
+
+ endp
+
+;******************************************************************************
+;* Sektorenzahl als MBytes ausgeben *
+;* In: DX:AX = Sektorzahl *
+;******************************************************************************
+
+ proc WriteMBytes
+
+SecsPerMByte equ (2^20)/SecSize
+
+ push cx ; Register retten
+ push dx
+
+ add ax,SecsPerMByte/20 ; wg. Rundung
+ adc dx,0
+
+ mov cx,SecsPerMByte ; durch 2048 teilen = MByte
+ div cx
+ push dx ; Nachkommastellen retten
+ mov cl,6
+ call WriteDec
+
+ PrChar '.' ; Nachkommastelle
+ pop ax ; holen
+ cwd
+ mov cx,SecsPerMByte/10 ; Sektoren pro 100 KByte
+ div cx
+ mov cl,1 ; ausgeben
+ call WriteDec
+
+ pop dx ; Register zurck
+ pop cx
+ ret
+
+ endp
+
+;******************************************************************************
+;* transiente Daten *
+;******************************************************************************
+
+HelloMsg: db CR,LF,"Sekund„rlaufwerkstreiber V0.4",CR,LF,'$'
+
+ErrMsgNoDrives: db CR,LF,"Fehler: keine Partitionen gefunden",CR,LF,'$'
+
+DiagMsg0: db CR,LF,"Controller-Selbsttest: ",'$'
+DiagMsg1: db "OK",CR,LF,'$'
+DiagMsg2: db "Controller fehlerhaft",CR,LF,'$'
+DiagMsg3: db "Sektorpuffer defekt",CR,LF,'$'
+DiagMsg4: db "Fehlerkorrektur defekt",CR,LF,'$'
+DiagMsg5: db "Steuerprozessor defekt",CR,LF,'$'
+DiagMsg6: db "Timeout",CR,LF,'$'
+DiagMsgTable dw DiagMsg1,DiagMsg2,DiagMsg3,DiagMsg4,DiagMsg5,DiagMsg6
+UndefDiagMsg db "Unbekannter Fehlercode #$"
+WKeyMsg: db "Weiter mit beliebiger Taste...",CR,LF,'$'
+
+PDriveMsg1: db "Festplatte $"
+PDriveMsg2: db " :$"
+PDriveMsg3: db " Zylinder,$"
+PDriveMsg4: db " K”pfe,$"
+PDriveMsg5: db " Sektoren,$"
+PDriveMsg6: db " MByte",CR,LF,'$'
+
+LDriveMsg: db CR,LF,"vorhandene Partitionen:",CR,LF
+ db "Laufwerk Platte Zylinder Kopf"
+ db " Sektor Kapazit„t",CR,LF,'$'
+
+AccPartTypes db 1 ; akzeptierte Partitionstypen: DOS 2.x FAT12
+ db 4 ; DOS 3.x FAT16
+ db 5 ; DOS 3.3 extended
+ db 6 ; DOS 3.31 >32 MByte
+ db 0 ; Tabellenende
+
+MomDrive db 0 ; momentan gescanntes Laufwerk
+
+ end
diff --git a/tests/t_secdrive/t_secdrive.doc b/tests/t_secdrive/t_secdrive.doc
new file mode 100644
index 0000000..0aece08
--- /dev/null
+++ b/tests/t_secdrive/t_secdrive.doc
@@ -0,0 +1,9 @@
++----------------------- Test Application SECDRIVE --------------------------+
+| |
+| YUCK! 8086/MSDOS-Code ;-) |
+| This is a MSDOS driver for a secondary MFM/RLL/ESDI/IDE controller I |
+| wrote a few years ago - just to get another 40MB of storage (which was |
+| a lot at that time...) |
+| This app also demonstrates the usage of the newly introduced structures. |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_secdrive/t_secdrive.ori b/tests/t_secdrive/t_secdrive.ori
new file mode 100755
index 0000000..0538002
--- /dev/null
+++ b/tests/t_secdrive/t_secdrive.ori
Binary files differ
diff --git a/tests/t_secdrive/wd1002xt.inc b/tests/t_secdrive/wd1002xt.inc
new file mode 100644
index 0000000..7dd1268
--- /dev/null
+++ b/tests/t_secdrive/wd1002xt.inc
@@ -0,0 +1,773 @@
+;******************************************************************************
+;* *
+;* Includedatei fr SECMAIN.ASM *
+;* liefert low-level-Routinen fr SecMain *
+;* Version hier fr WD1002XT-kompatible Kontroller: *
+;* MFM, RLL (?) *
+;* *
+;* Historie: 28.12.1994 *
+;* 26. 3.1994 Formatierroutinen *
+;* 8. 4.1994 defekte Spuren markieren *
+;* *
+;******************************************************************************
+
+ section wd1002xt
+
+;------------------------------------------------------------------------------
+; Portadressen
+
+Port_Base equ 320h ; prim„re Basisadresse
+Port_Data equ Port_Base+0 ; Datenregister (R+W)
+Port_Status equ Port_Base+1 ; Statusregister (R)
+Port_Reset equ Port_Base+1 ; Reset ausl”sen (W)
+Port_Config equ Port_Base+2 ; Jumper auslesen (R)
+Port_Select equ Port_Base+2 ; Kontroller selektieren (W)
+Port_IRQDRQ equ Port_Base+3 ; IRQ/DRQ-Leitungen freigeben (W)
+
+;------------------------------------------------------------------------------
+; Kommandocodes
+
+Cmd_Diagnose equ 0e4h ; Kommando: Kontroller-Selbsttest
+Cmd_GetStatus equ 003h ; Status letzter Operation lesen
+Cmd_TestReady equ 000h ; Test, ob Laufwerk bereit
+Cmd_Restore equ 001h ; Laufwerk rekalibrieren
+Cmd_SetParams equ 00ch ; Laufwerksparameter setzen
+Cmd_Seek equ 00bh ; Spur anfahren
+Cmd_Read equ 008h ; Sektoren lesen
+Cmd_Write equ 00ah ; Sektoren schreiben
+Cmd_Verify equ 005h ; Sektoren auf Lesbarkeit prfen
+Cmd_WriteBuffer equ 00fh ; Sektorpuffer beschreiben
+Cmd_FormatDisk equ 004h ; Laufwerk formatieren
+Cmd_FormatTrack equ 006h ; Spur formatieren
+Cmd_FormatBad equ 007h ; Spur als defekt markieren
+
+;------------------------------------------------------------------------------
+; I/O-Bremse
+
+IODelay macro
+ jmp $+2
+ endm
+
+;------------------------------------------------------------------------------
+; Puffer
+
+CmdBufSize equ 6 ; enth„lt Kommandoblock fr WD1002
+CmdBuf db CmdBufSize dup (0)
+
+StatBufSize equ 4 ; enth„lt Statusinfo vom WD1002
+StatBuf db StatBufSize dup (0)
+
+GeomBufSize equ 8 ; enth„lt Parametertabelle fr Laufwerk
+GeomBuf db GeomBufSize dup (0)
+
+;******************************************************************************
+;* Kommandopuffer initialisieren *
+;******************************************************************************
+
+ proc InitCmdBuf
+
+ push ax ; Register retten
+
+ sub ax,ax ; mit Nullen initialisieren
+ mov word ptr[CmdBuf],ax
+ mov word ptr[CmdBuf+2],ax
+ mov ah,45h ; Retry on, 70us Steprate
+ mov word ptr[CmdBuf+4],ax
+
+ pop ax ; Register zurck
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* einen Datenblock an den Kontroller schicken *
+;* In : ES:SI = Datenblock *
+;* CX = Anzahl Bytes *
+;* Out : C=1 bei Protokollfehler *
+;******************************************************************************
+
+ proc SendBlock
+
+ push ax ; Register retten
+ push cx
+ push dx
+ push si
+
+ mov dx,Port_Status
+ jcxz ZeroLoop ; Nullschleife abfangen
+ cld ; !!!
+OutLoop: in al,dx ; Status lesen
+ btst al,0 ; warten, bis REQ-Bit auf 1
+ jz OutLoop
+ btst al,1 ; IO-Bit muá 0 sein
+ stc
+ jnz ErrEnd
+ mov dl,Lo(Port_Data); ein Byte auf Datenport ausgeben
+ seges
+ outsb
+ mov dl,Lo(Port_Status) ; zurck fr n„chsten Durchlauf
+ loop OutLoop
+ZeroLoop: clc ; Ende ohne Fehler
+ErrEnd:
+ pop si ; Register zurck
+ pop dx
+ pop cx
+ pop ax
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* einen Datenblock vom Kontroller lesen *
+;* In : ES:DI = Datenblock *
+;* CX = Anzahl Bytes *
+;* Out : C=1 bei Protokollfehler *
+;******************************************************************************
+
+ proc RecvBlock
+
+ push ax ; Register retten
+ push cx
+ push dx
+ push di
+
+ mov dx,Port_Status
+ jcxz ZeroLoop ; Nullschleife abfangen
+ cld ; !!!
+InLoop: in al,dx ; Status lesen
+ btst al,0 ; warten, bis REQ-Bit auf 1
+ jz InLoop
+ btst al,1 ; IO-Bit muá 1 sein
+ stc
+ jz ErrEnd
+ mov dl,Lo(Port_Data); ein Byte von Datenport einlesen
+ insb
+ mov dl,Lo(Port_Status) ; zurck fr n„chsten Durchlauf
+ loop InLoop
+ZeroLoop: clc ; Ende ohne Fehler
+ErrEnd:
+ pop di ; Register zurck
+ pop dx
+ pop cx
+ pop ax
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Status bilden *
+;* Out : C+AX = Status *
+;******************************************************************************
+
+ proc BuildStatus
+
+ push dx ; Register retten
+
+ mov dx,Port_Status ; auf Datum warten
+Loop: in al,dx
+ btst al,0 ; bis REQ=1
+ jz Loop
+ btst al,1 ; und IO=1
+ jz Loop
+ mov dl,Lo(Port_Data); CCB auslesen
+ in al,dx
+ mov ah,al ; retten fr Fehlerabfrage
+ and al,2 ; Bit 1 ausmaskieren
+ clc
+ ljz End ; wenn = 0, kein Fehler und AL=0
+
+ push cx ; zus„tzliche Register retten
+ push si
+ push di
+ push es
+
+ call InitCmdBuf ; ansonsten Kommando absetzen, um
+ mov [CmdBuf],Cmd_GetStatus ; Status zu lesen
+ and ah,20h ; Status fr korr. Laufwerk abfragen
+ mov [CmdBuf+1],ah
+ mov dx,Port_Status
+WaitNBusy: in al,dx
+ btst al,3
+ jnz WaitNBusy
+ mov ax,ds ; NICHT ExecCmd benutzen, da sonst
+ mov es,ax ; Rekursion !
+ lea si,[CmdBuf]
+ mov cx,CmdBufSize
+ mov dl,Lo(Port_Select)
+ out dx,al
+ call SendBlock
+ lea di,[StatBuf] ; 4 Statusbytes auslesen
+ mov cx,StatBufSize
+ call RecvBlock
+ mov dl,Lo(Port_Status); CCB nicht vergessen!!
+Loop2: in al,dx
+ btst al,0 ; bis REQ=1
+ jz Loop2
+ btst al,1 ; und IO=1
+ jz Loop2
+ mov dl,Lo(Port_Data)
+ in al,dx
+ mov al,[StatBuf] ; Fehlercode = 1.Byte,
+ and al,7fh ; Bit 0..6
+ stc ; Carry signalisiert Fehler
+ pop es ; zus„tzliche Register zurck
+ pop di
+ pop si
+ pop cx
+
+End: mov ah,0 ; MSB ohne Bedeutung
+ pop dx ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* XT- in AT-Fehlerkode umsetzen *
+;* Eingabe: AL = XT-Fehlerkode *
+;* Ausgabe: C+AX = AT-Fehlerstatus *
+;******************************************************************************
+
+ proc TranslateStatus
+
+ push bx
+ push si
+
+ mov bl,al ; alten Status sichern
+ mov bh,-1
+ lea si,[TransTable]
+ cld
+TransLoop: lodsw ; einen Eintrag laden
+ cmp al,bh ; Tabellenende?
+ je TransEnd
+ cmp al,bl ; Treffer?
+ jne TransLoop ; nein, weitersuchen
+ mov al,ah ; bersetzten Code laden
+ cmp al,0 ; Code fr kein Fehler?
+ clc
+ je Ende ; ja, C=0
+ jmp TransErr ; ansonsten C=1
+TransEnd: mov al,04h ; Aborted Command annehmen
+TransErr: stc ; Fehlerflag setzen
+
+Ende: pop si ; Register zurck
+ pop bx
+
+ ret
+
+TransTable: db 00h,00h ; kein Fehler
+ db 02h,02h ; kein Seek Complete-Signal
+ db 03h,04h ; Write Fault
+ db 04h,04h ; Laufwerk nicht bereit
+ db 06h,02h ; Spur 0 nicht gefunden
+ db 08h,02h ; Laufwerk positioniert noch
+ db 11h,40h ; unkorrigierbarer Datenfehler
+ db 12h,01h ; Adreámarke nicht gefunden
+ db 15h,10h ; Positionierfehler
+ db 18h,00h ; korrigierbarer Fehler (ignoriert)
+ db 19h,80h ; Spur als defekt markiert
+ db -1,-1 ; Tabellenende
+
+ endp
+
+;******************************************************************************
+;* ein Kommando ausfhren *
+;* In : AL = Kommando *
+;******************************************************************************
+
+ proc ExecCmd
+
+ push cx ; Register retten
+ push ax
+ push dx
+ push si
+ push es
+
+ mov [CmdBuf],al ; Kommandokode in Datenblock einschreiben
+ mov dx,Port_Status ; warten, bis Kontroller frei
+WaitNBusy: in al,dx
+ btst al,3
+ jnz WaitNBusy
+ mov dx,Port_Select ; Kontroller selektieren
+ out dx,al
+ mov ax,ds ; Adresse Kommandoblock
+ mov es,ax
+ lea si,[CmdBuf]
+ mov cx,CmdBufSize ; L„nge Kommandoblock
+ call SendBlock ; Kommandoblock abschicken
+
+ pop es ; Register zurck
+ pop si
+ pop dx
+ pop ax
+ pop cx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Laufwerk und Sonderwerte in Kommandoblock einprogrammieren *
+;* In : AL = Laufwerk *
+;* AH = Kopf *
+;******************************************************************************
+
+ proc SetDriveEnv
+
+ push ax ; Register retten
+
+
+ shl al,5 ; Laufwerksbit an Stelle 5
+ or al,ah
+ mov [CmdBuf+1],al ; als 2. Byte im Kommandopuffer schreiben
+
+ pop ax ; Register zurck
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Zylinder- und Sektorparameter an Kontroller ausgeben *
+;* In : BX = Startzylinder *
+;* CL = Sektorzahl/Interleave *
+;* CH = Startsektor *
+;******************************************************************************
+
+ proc SetTransParams
+
+ push ax ; Register retten
+
+ mov [CmdBuf+3],bl ; LSB Startzylinder
+ mov al,bh ; MSB Startzylinder
+ shl al,6 ; in Bit 6..7 schieben
+ add al,ch ; Sektor dazu
+ dec al ; !!! Sektoren ab 0
+ mov [CmdBuf+2],al
+ mov [CmdBuf+4],cl ; Sektorzahl
+
+ pop ax ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* Begráungsmeldung ausgeben: *
+;******************************************************************************
+
+ globproc LowLevelIdent
+
+ push ax ; Register retten
+
+ PrMsg IdentMsg
+
+ pop ax
+
+ ret
+
+IdentMsg db "Low-Level-Routinen fr WD1002S-WX2 und kompatible Controller",CR,LF,'$'
+
+ endp
+
+;******************************************************************************
+;* Controller-Diagnose: *
+;* Out : AL = Diagnosecode *
+;******************************************************************************
+
+ globproc ContDiag
+
+ push cx ; Register retten
+ push bx
+ push dx
+
+ sub cx,cx
+ mov dx,Port_Status ; auf Status
+BWait: in al,dx
+ btst al,3 ; auf NOT BUSY warten
+ loopnz BWait ; oder bis 64K Durchl„ufe durch
+ or cx,cx ; Timeout ?
+ jne NTOut
+ mov al,Diag_Timeout ; ja: Fehlercode setzen...
+ jmp End ; ...und Feierabend
+
+NTOut: call InitCmdBuf ; Kommando Selbsttest ausfhren
+ mov al,Cmd_Diagnose
+ call ExecCmd
+ call BuildStatus ; Status holen
+
+ cmp al,5 ; WD1002 definiert nur Code 0..5
+ jb DoTrans
+ mov al,7 ; "undefinierter Code"
+ jmp End
+DoTrans: lea bx,[TransTbl] ; ansonsten umsetzen
+ xlat
+
+End: pop dx ; Register zurck
+ pop bx
+ pop cx
+ ret
+
+TransTbl: db Diag_NoError ; Code 0: kein Fehler
+ db Diag_ContError ; Code 1: WD1010 fehlerhaft
+ db Diag_ECCError ; Code 2: WD11C00 fehlerhaft
+ db Diag_SBufError ; Code 3: Sektorpuffer defekt
+ db Diag_ProcError ; Code 4: WD1015 RAM defekt
+ db Diag_ProcError ; Code 5: WD1015 ROM defekt
+
+
+ endp
+
+;******************************************************************************
+;* Laufwerk rekalibrieren, gleichzeitig Test, ob vorhanden *
+;* In : AL = Laufwerk *
+;* Out : C + AX = Status *
+;******************************************************************************
+
+
+ globproc Recalibrate
+
+ push ax ; Register retten
+ push cx
+
+ call InitCmdBuf ; testen, ob Laufwerk bereit
+ mov ah,0 ; Kopf dafr unwichtig
+ call SetDriveEnv
+ mov dl,al ; Laufwerksnummer retten, gleichzeitig
+ mov dh,0 ; Kopf auf 0 setzen
+ mov al,Cmd_TestReady
+ call ExecCmd
+ call BuildStatus
+ jc TotEnde ; C=1 --> Ende mit Fehler
+
+ call InitCmdBuf ; sanfte Tour: Spur 0 mit Seek anfahren
+ mov ax,dx
+ call SetDriveEnv
+ mov al,0 ; Zylinder lo=0
+ mov [CmdBuf+3],al
+ inc al ; Zylinder Hi=0, Startsektor=1
+ mov [CmdBuf+2],al
+ mov al,Cmd_Seek
+ call ExecCmd
+ call BuildStatus
+ jnc TotEnde ; kein Fehler, alles in Butter
+
+ call InitCmdBuf ; ansonsten echtes Restore versuchen
+ mov ax,dx
+ call SetDriveEnv
+ mov al,Cmd_Restore
+ call ExecCmd
+ call BuildStatus
+ call TranslateStatus
+
+TotEnde: pop dx ; Register zurck
+ pop ax
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Dem Kontroller die Laufwerksgeometrie mitteilen *
+;* In : AL = Laufwerk *
+;* Out : C = 1-->Fehler *
+;******************************************************************************
+
+ globproc SetDriveParams
+
+ push cx ; Register retten
+ push si
+ push es
+
+ call GetPTabAdr ; Adresse Parametertabelle holen
+ call InitCmdBuf ; Kommando anstoáen
+ call SetDriveEnv
+ mov al,Cmd_SetParams
+ call ExecCmd
+
+
+ mov ax,[di+DrPar_Cyls] ; Parametertabelle aufbauen
+ xchg ah,al
+ mov word ptr [GeomBuf],ax
+ mov al,[di+DrPar_Heads]
+ mov byte ptr[GeomBuf+2],al
+ mov ax,[di+DrPar_RedWr]
+ xchg ah,al
+ mov word ptr[GeomBuf+3],ax
+ mov ax,[di+DrPar_PrComp]
+ xchg ah,al
+ mov word ptr[GeomBuf+5],ax
+ mov al,[di+DrPar_ECCLen]
+ mov byte ptr[GeomBuf+7],al
+ lea si,[GeomBuf] ; Block abschicken
+ mov cx,GeomBufSize
+ mov ax,ds
+ mov es,ax
+ call SendBlock
+ call BuildStatus
+ call TranslateStatus
+
+ pop es ; Register zurck
+ pop si
+ pop cx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Sektor(en) lesen *
+;* In : AL = Laufwerk *
+;* AH = Startkopf *
+;* BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;* ES:DI = Zeiger auf Datenpuffer *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc ReadSectors
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push di
+ push es
+
+ call InitCmdBuf ; Puffer initialisieren
+ call SetDriveEnv
+ call SetTransParams
+ mov al,Cmd_Read ; Lesen triggern
+ PrChar '1'
+ call ExecCmd
+ PrChar '2'
+
+SecLoop: mov dx,Port_Status ; warten, bis Request-Bit gesetzt
+RLoop: in al,dx
+ btst al,0
+ jz RLoop
+ btst al,2 ; Daten oder Status ?
+ jnz ErrEnd ; wenn jetzt Status, ist etwas schief gelaufen
+ push cx ; ansonsten Sektor auslesen
+ mov cx,SecSize
+ PrChar '3'
+ call RecvBlock
+ PrChar '4'
+ pop cx
+ dec cl
+ add di,SecSize
+ jnz RLoop ; und n„chsten Sektor verarbeiten
+
+ErrEnd: PrChar '5'
+ call BuildStatus
+ PrChar '6'
+ call TranslateStatus
+
+ pop es ; Register zurck
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Sektor(en) verifizieren *
+;* In : AL = Laufwerk *
+;* AH = Startkopf *
+;* BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc VeriSectors
+
+ push bx ; Register retten
+ push cx
+ push dx
+
+ call InitCmdBuf ; Puffer initialisieren
+ call SetDriveEnv
+ call SetTransParams
+ mov al,Cmd_Verify ; Verifikation triggern
+ call ExecCmd
+
+ call BuildStatus
+ call TranslateStatus
+
+ pop dx ; Register zurck
+ pop cx
+ pop bx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Sektor(en) schreiben *
+;* In : AL = Laufwerk *
+;* AH = Startkopf *
+;* BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;* ES:SI = Zeiger auf Datenpuffer *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc WriteSectors
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push si
+ push es
+
+
+ call InitCmdBuf ; Puffer initialisieren
+ call SetDriveEnv
+ call SetTransParams
+ mov al,Cmd_Write ; Lesen triggern
+ call ExecCmd
+
+SecLoop: mov dx,Port_Status ; warten, bis Request-Bit gesetzt
+WLoop: in al,dx
+ btst al,0
+ jz WLoop
+ btst al,2 ; Daten oder Status ?
+ jnz ErrEnd ; wenn jetzt Status, ist etwas schief gelaufen
+ push cx ; ansonsten Sektor auslesen
+ mov cx,SecSize
+ call SendBlock
+ pop cx
+ dec cl
+ add si,SecSize
+ jnz WLoop ; und n„chsten Sektor verarbeiten
+
+ErrEnd: call BuildStatus
+ call TranslateStatus
+
+ pop es ; Register zurck
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Laufwerk formatieren *
+;* In : AL = Laufwerk *
+;* AH = Interleave *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc FormatUnit
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov bx,ax ; Interleave & Laufwerk retten
+
+ mov ax,ds ; vorher noch den Sektorpuffer im
+ mov es,ax ; Controller ausnullen
+ lea di,[SectorBuffer]
+ mov cx,SecSize/2
+ sub ax,ax
+ rep stosw
+ call InitCmdBuf
+ mov al,Cmd_WriteBuffer
+ call ExecCmd
+ lea si,[SectorBuffer]
+ mov cx,SecSize
+ call SendBlock
+ call BuildStatus
+ jc End ; unwahrscheinlich, aber...
+
+ call InitCmdBuf ; Puffer initialisieren
+ mov al,bl ; Laufwerk wieder zurck
+ mov ah,0 ; Startkopf ist 0
+ call SetDriveEnv
+ mov [CmdBuf+4],bh ; Interleave einschreiben
+ mov al,Cmd_FormatDisk ; Formatieren triggern
+ call ExecCmd
+
+ErrEnd: call BuildStatus
+End: call TranslateStatus
+
+ pop es ; Register zurck
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Spur formatieren *
+;* In : AL = Laufwerk *
+;* AH = Kopf *
+;* BX = Zylinder *
+;* CL = Interleave *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc FormatTrack
+
+ push bx
+ push cx
+
+ call InitCmdBuf ; Parameter einschreiben
+ call SetDriveEnv
+ mov ch,1 ; Sektorinformation muá nur gltig sein
+ call SetTransParams
+ mov al,Cmd_FormatTrack
+ call ExecCmd
+ call BuildStatus
+
+ pop cx
+ pop bx
+ ret
+
+ endp
+
+;******************************************************************************
+;* Spur als defekt markieren *
+;* In : AL = Laufwerk *
+;* AH = Kopf *
+;* BX = Zylinder *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc MarkBad
+
+ push bx
+ push cx
+
+ call InitCmdBuf ; Parameter einschreiben
+ call SetDriveEnv
+ mov cx,0103h ; Sektorinformation muá nur gltig sein
+ call SetTransParams
+ mov al,Cmd_FormatBad
+ call ExecCmd
+ call BuildStatus
+
+ pop cx
+ pop bx
+ ret
+
+ endp
+
+ endsection
diff --git a/tests/t_secdrive/wd1003at.inc b/tests/t_secdrive/wd1003at.inc
new file mode 100644
index 0000000..7714eec
--- /dev/null
+++ b/tests/t_secdrive/wd1003at.inc
@@ -0,0 +1,952 @@
+;******************************************************************************
+;* *
+;* Includedatei fr SECMAIN.ASM *
+;* liefert low-level-Routinen fr SecMain *
+;* Version hier fr WD1003-kompatible Kontroller: *
+;* MFM, RLL, ESDI, AT-Bus *
+;* *
+;* Historie: 28.12.1994 herberkopiert aus Hauptmodul *
+;* 30.12.1994 LowLevelIdent *
+;* 19. 1.1995 Workaround fr LCS6220 *
+;******************************************************************************
+
+ section wd1003at
+
+Base1 equ 170h ; Basisadresse Task-File
+Base2 equ 370h ; Basisadresse Floppy-Teil
+Task_Data equ Base1+0 ; Datentransferregister (R/W)
+Task_Error equ Base1+1 ; genauerer Fehlercode (R)
+Task_PreComp equ Base1+1 ; erster Zylinder Pr„komp. (/4, nur W)
+Task_SecCnt equ Base1+2 ; Zahl zu transferierender Sektoren (R/W)
+Task_SecNum equ Base1+3 ; Startsektor (R/W)
+Task_CylLo equ Base1+4 ; Startzylinder Bit 0..7 (R/W)
+Task_CylHi equ Base1+5 ; Startzylinder Bit 8..n (R/W)
+Task_DrHead equ Base1+6 ; Laufwerk/Startkopf (R/W)
+Task_Status equ Base1+7 ; Status Laufwerk & Controller (R)
+Task_Command equ Base1+7 ; Kommando Controller (W)
+Task_FDiskReg equ Base2+6 ; Bit 3=1: >8 K”pfe
+
+Cmd_Restore equ 10h ; Kommando: Rekalibrieren
+Cmd_Seek equ 70h ; Kommando: Zylinder anfahren
+Cmd_Read equ 20h ; Kommando: Sektoren lesen
+Cmd_Write equ 30h ; Kommando: Sektoren schreiben
+Cmd_Format equ 50h ; Kommando: Spur formatieren
+Cmd_Verify equ 40h ; Kommando: Sektoren auf Lesbarkeit prfen
+Cmd_Diagnose equ 90h ; Kommando: Selbsttest
+Cmd_SetParams equ 91h ; Kommando: Laufwerksparameter setzen
+
+ proc WriteParams
+
+ mov [axsave],ax
+ mov [cxsave],cx
+ PrChar ' '
+ mov ax,bx
+ mov cl,5
+ call WriteDec
+ PrChar ' '
+ mov al,byte ptr[axsave+1]
+ mov ah,0
+ mov cl,2
+ call WriteDec
+ PrChar ' '
+ mov al,byte ptr[cxsave+1]
+ mov ah,0
+ mov cl,2
+ call WriteDec
+ PrChar ' '
+ mov al,byte ptr[cxsave]
+ mov ah,0
+ mov cl,2
+ call WriteDec
+ PrChar ' '
+ mov ax,es
+ mov cl,4
+ call WriteHex
+ PrChar ':'
+ mov ax,bp
+ mov cl,4
+ call WriteHex
+ mov ax,[axsave]
+ mov cx,[cxsave]
+ ret
+
+cxsave dw ?
+axsave dw ?
+
+ endp
+
+;******************************************************************************
+;* Workaround fr LCS6220: Wird direkt nach dem Einschalten ein Seek ausge- *
+;* fhrt, gibt der Kontroller f„lschlicherweise Daten aus und blockiert alle *
+;* weiteren Kommandos. Diese Routine r„umt einfach den Puffer leer... *
+;******************************************************************************
+
+ proc ClearBuffer
+
+ push dx ; Register retten
+ push ax
+
+RdLoop: mov dx,Task_Status ; Bit 3 noch gesetzt ?
+ in al,dx
+ btst al,3
+ jz RdLoopEnd ; nein --> fertig
+ mov dx,Task_Data
+ in ax,dx
+ jmp RdLoop
+RdLoopEnd:
+ pop ax ; Register zurck
+ pop dx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Interleave-Tabelle berechnen *
+;* In : AL = Sektorzahl *
+;* AH = Interleave *
+;* DH = Bad-Flag *
+;******************************************************************************
+
+ proc SetInterleaveBuffer
+
+ pusha ; Register retten
+ push es
+
+ push ax ; Sektorpuffer initialisieren
+ mov ax,ds
+ mov es,ax
+ sub ax,ax
+ lea di,[SectorBuffer]
+ mov cx,SecSize/2
+ cld
+ rep stosw
+ pop ax
+
+ sub di,di ; DI=Adresse in Puffer=(phys. Sektor-1)*2
+ mov dl,dh ; DL = Bad-Flag
+ mov dh,1 ; DH=log. Sektornummer
+ mov cl,al ; CX=Schleifenz„hler
+ mov ch,0
+ mov bl,al ; Sektorzahl*2 nach BX
+ mov bh,0
+ add bx,bx
+ mov si,ax ; Interleave*2 nach SI
+ shr si,8
+ add si,si
+InterLoop: cmp byte ptr SectorBuffer[di],0 ; Eintrag frei ?
+ je Inter_FreeFound ; ja, beenden
+ add di,2 ; nein, linear weitersuchen
+ cmp di,bx
+ jb InterLoop
+ mov di,0 ; Wrap-Around bercksichtigen
+ jmp InterLoop
+Inter_FreeFound:mov word ptr SectorBuffer[di],dx ; Sektor einschreiben
+ add di,si ; Interleave-Sprung dazu
+ cmp di,bx ; Modulo Sektorzahl
+ jb Inter_NoWrap
+ sub di,bx
+Inter_NoWrap: inc dh ; n„chster log. Sektor
+ loop InterLoop
+
+ pop es ; Register zurck
+ popa
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Laufwerk und Sonderwerte einprogrammieren *
+;* In : AL = Laufwerk *
+;* AH = Kopf *
+;******************************************************************************
+
+ proc SetDriveEnv
+
+ push di ; Register retten
+ push dx
+ mov dx,ax ; Laufwerk/Kopf retten
+
+ call GetPTabAdr ; Tabellenadresse holen
+
+ mov al,dl ; Laufwerk und Kopf zusammenbauen
+ shl al,4
+ or al,dh
+ or al,0a0h
+ mov dx,Task_DrHead
+ out dx,al
+ mov ax,[di+DrPar_PrComp] ; Startzylinder Pr„kompensation
+ shr ax,2
+ mov dl,Lo(Task_PreComp)
+ out dx,al
+ mov al,[di+DrPar_CByte] ; Wert fr Fixed Disk Register
+ mov dx,Task_FDiskReg
+ out dx,al
+ call WaitBusy
+
+ clc ; Ende ohne Fehler
+ pop dx
+ pop di
+ ret
+
+ endp
+
+;******************************************************************************
+;* Zylinder- und Sektorparameter an Kontroller ausgeben *
+;* In : BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;******************************************************************************
+
+ proc SetTransParams
+
+ push dx ; Register retten
+
+ mov dx,Task_CylLo ; Startzylinder programmieren
+ mov al,bl
+ out dx,al
+ mov dx,Task_CylHi ;***
+ mov al,bh
+ out dx,al
+ mov dx,Task_SecNum ; Startsektor... ;***
+ mov al,ch
+ out dx,al
+ mov dx,Task_SecCnt ; ...und Sektorzahl ;***
+ mov al,cl
+ out dx,al
+
+ pop dx ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* warten, bis Controller bereit oder Fehler *
+;* Out : AL = letzter Status *
+;******************************************************************************
+
+ proc WaitBusy
+
+ push dx ; Register retten
+ mov dx,Task_Status ; auf Statusregister
+Loop: in al,dx ; Status lesen
+ btst al,7 ; Bit 7 noch gesetzt ?
+ jnz Loop ; ja--> weiter pollen
+ pop dx ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* warten, bis Laufwerk bereit *
+;* Out : AL = letzter Status *
+;******************************************************************************
+
+ proc WaitDrive
+
+ push dx ; Register retten
+ mov dx,Task_Status ; auf Statusregister
+Loop: in al,dx ; Status lesen
+ btst al,7 ; Bit 7 = 0 ? ( Controller Busy )
+ jnz Loop
+ btst al,6 ; Bit 6 = 1 ? ( Drive not Ready )
+ jz Loop
+ btst al,4 ; Bit 4 = 1 ? ( Seek not complete )
+ jz Loop
+ pop dx
+ ret
+
+ endp
+
+;******************************************************************************
+;* warten, bis Datentransfer erforderlich *
+;* Out : AL = letzter Status *
+;* C = 1, falls Fehler *
+;******************************************************************************
+
+ proc WaitData
+
+ push dx ; Register retten
+ mov dx,Task_Status ; auf Statusregister
+Loop: in al,dx ; Status lesen
+ btst al,7 ; Bit 7 = 0 ?
+ jnz Loop
+ btst al,3 ; Bit 3 = 1 ?
+ jz Loop
+ pop dx ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* Status bilden *
+;* Out : C+AX = Status *
+;******************************************************************************
+
+ proc BuildError
+
+ push dx ; Register retten
+
+ mov dx,Task_Status ; Statusregister lesen
+ in al,dx
+ mov ah,al
+ btst ah,0 ; Fehlerflag gesetzt ?
+ clc
+ jz End ; kein Fehler
+
+ mov dx,Task_Error ; ja: Error-Register lesen ;***
+ in al,dx
+ stc
+
+End: pop dx ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* Begráungsmeldung ausgeben: *
+;******************************************************************************
+
+ globproc LowLevelIdent
+
+ push ax ; Register retten
+
+ PrMsg IdentMsg
+
+ pop ax
+
+ ret
+
+IdentMsg db "Low-Level-Routinen fr WD1003-WAH und kompatible Controller",CR,LF,'$'
+
+ endp
+
+;******************************************************************************
+;* Controller-Diagnose: *
+;* Out : AL = Diagnosecode *
+;******************************************************************************
+
+ globproc ContDiag
+
+ push cx ; Register retten
+ push dx
+
+ mov dx,Task_Status ; das erste Mal mit Timeout warten
+ sub cx,cx
+BWait: in al,dx
+ btst al,7 ; auf NOT BUSY warten
+ loopnz BWait ; oder bis 64K Durchl„ufe durch
+ or cx,cx ; Timeout ?
+ jne NTOut
+ mov al,Diag_Timeout ; ja: Fehlercode setzen...
+ jmp End ; ...und Feierabend
+
+NTOut: mov al,CMD_Diagnose ; Selbsttest starten
+ mov dl,Lo(Task_Command)
+ out dx,al
+ call WaitBusy ; auf Fertigstellung warten
+ mov dl,Lo(Task_Error) ; Ergebnis laden
+ in al,dx
+
+End: pop dx ; Register zurck
+ pop cx
+ ret
+
+ endp
+
+;******************************************************************************
+;* Dem Kontroller die Laufwerksgeometrie mitteilen *
+;* In : AL = Laufwerk *
+;* Out : C = 1-->Fehler *
+;******************************************************************************
+
+ globproc SetDriveParams
+
+ push di ; Register retten
+ push dx
+ mov dl,al ; Laufwerk retten
+
+ call GetPTabAdr ; Adresse Parametertabelle holen
+
+ call WaitBusy ; Kontroller muá frei sein
+
+ mov al,dl ; Kopfzahl/Laufwerk vorbesetzen
+ shl al,4
+ mov ah,[di+DrPar_Heads]
+ dec ah ; Maximalnummer anstelle Gesamtzahl
+ or al,ah
+ or al,0a0h
+ mov dx,Task_DrHead
+ out dx,al
+ mov dl,Lo(Task_SecCnt) ; Sektorzahl setzen
+ mov al,[di+DrPar_NSecs]
+ out dx,al
+
+ mov dl,Lo(Task_Command) ; Parameter bertragen
+ mov al,Cmd_SetParams
+ out dx,al
+
+ call WaitBusy ; auf Fertigstellung warten
+
+ clc ; Ende ohne Fehler
+ pop dx
+ pop di
+ ret
+
+ endp
+
+;******************************************************************************
+;* Laufwerk rekalibrieren, gleichzeitig Test, ob vorhanden *
+;* In : AL = Laufwerk *
+;* Out : C + AX = Status *
+;******************************************************************************
+
+ globproc Recalibrate
+
+ push cx ; Register retten
+ push dx
+
+ mov cx,ax ; Laufwerk retten
+ call WaitBusy ; warten, bis Controller frei
+
+ mov dx,Task_DrHead ; Laufwerk eintragen
+ mov al,cl
+ shl al,4
+ add al,0a0h
+ out dx,al
+
+ mov dl,Lo(Task_Status) ; Laufwerk muss jetzt bereit sein,
+ in al,dx ; da sich einige Kontroller sonst im
+ and al,50h ; folgenden aufh„ngen, falls
+ cmp al,50h ; keine Platte angeschlossen ist.
+ stc ; falls nicht bereit, Fehler simulieren
+ mov al,4 ; "Aborted Command"
+ jne TotEnde
+ mov al,0
+ mov dl,Lo(Task_CylLo) ; erstmal auf die sanfte Tour:
+ out dx,al ; Spur 0 anfahren
+ mov dl,Lo(Task_CylHi)
+ out dx,al
+ mov dl,Lo(Task_Command)
+ mov al,Cmd_Seek
+ out dx,al
+ call WaitBusy
+ call BuildError
+ jnc Ende ; wenn OK: fertig
+
+ call ClearBuffer ; falls sich der Longshine verheddert...
+ mov dl,Lo(Task_Command) ; 2. Anlauf: echtes Restore
+ mov al,Cmd_Restore
+ out dx,al
+
+ call WaitBusy ; auf Controller warten
+
+Ende: call BuildError ; Status einlesen
+TotEnde:
+ pop dx ; Register zurck
+ pop cx
+ ret
+
+ endp
+
+;******************************************************************************
+;* Sektor(en) lesen *
+;* In : AL = Laufwerk *
+;* AH = Startkopf *
+;* BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;* ES:DI = Zeiger auf Datenpuffer *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc ReadSectors
+
+ push si ; Register sichern
+ push dx
+ push bp
+
+ if debug
+ PrChar 'R'
+ mov bp,di
+ call WriteParams
+ endif
+
+ sub bp,bp ; Fehlerz„hler auf 0
+
+Retry: push ax ; Parameter sichern
+ push bx
+ push cx
+ push di
+
+ mov si,ax ; Laufwerk/Kopf retten
+ call WaitBusy ; warten, bis Ruhe im Wald
+
+ mov ax,si
+ call SetDriveEnv ; Laufwerk jetzt schon setzen, damit
+ ; korr. Ready-Signal abgefragt wird
+ call WaitDrive ; bis Laufwerk bereit
+
+ call SetTransParams ; restliche Parameter ausgeben
+
+ mov ch,0 ; Sektorzahl nach SI
+ mov si,cx
+ mov dx,Task_Command ; Kommando triggern
+ mov al,Cmd_Read
+ out dx,al
+
+ mov dx,Task_Data ; Vorbereitung fr INSW
+ cld
+Loop: call WaitBusy ; auf gelesenen Sektor warten
+ btst al,0 ; Fehler ?
+ jnz Again ; -->neu aufsetzen
+ call WaitData
+ btst al,0
+ jnz Again
+ call WaitDrive
+ btst al,0
+ jnz Again
+ mov cx,SecSize/2 ; Daten transferieren
+ rep insw ; bagger, schaufel
+ dec si ; n„chster Sektor
+ jnz Loop
+
+End: pop di ; Parameter nicht mehr gebraucht
+ pop cx
+ pop bx
+ pop ax
+Term: if debug
+ PrChar CR
+ PrChar LF
+ endif
+ call BuildError
+ pop bp
+ pop dx
+ pop si
+
+ ret
+
+Again: inc bp ; Fehlerz„hler rauf
+ cmp bp,MaxRetry ; zu oft aufgetreten ?
+ jae End
+
+ pop di ; nein: Parameter vom Stack
+ pop cx
+ pop bx
+ pop ax
+ mov si,ax ; Laufwerk retten
+ call Recalibrate ; auf Spur 0 zurck
+ jc Term ; bei erneutem Fehler Abbruch
+ mov ax,si
+ call SetDriveParams ; Parameter neu initialisieren
+ mov ax,si
+ jmp Retry ; neuer Versuch
+
+
+ endp
+
+;******************************************************************************
+;* Sektor(en) verifizieren *
+;* In : AL = Laufwerk *
+;* AH = Startkopf *
+;* BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc VeriSectors
+
+ push si ; Register sichern
+ push dx
+ push bp
+
+ if debug
+ PrChar 'V'
+ mov bp,0
+ call WriteParams
+ endif
+
+ sub bp,bp ; Fehlerz„hler auf 0
+
+Retry: push ax ; Parameter sichern
+ push bx
+ push cx
+
+ mov si,ax ; Laufwerk/Kopf retten
+ call WaitBusy ; warten, bis Ruhe im Wald
+
+ mov ax,si
+ call SetDriveEnv ; Laufwerk jetzt schon setzen, damit
+ ; korr. Ready-Signal abgefragt wird
+ call WaitDrive ; bis Laufwerk bereit
+
+ call SetTransParams ; restliche Parameter ausgeben
+
+ mov dx,Task_Command ; Kommando triggern
+ mov al,Cmd_Verify
+ out dx,al
+
+ call WaitBusy ; auf Fertigstellung warten
+ mov cx,16 ; einige Kontroller brauchen
+DelStat: loop DelStat ; etwas fr das Fehlerflag
+ mov dx,Task_Status
+ in al,dx
+ btst al,0 ; Fehler ?
+ jnz Again ; -->neu aufsetzen
+ call WaitDrive
+ btst al,0
+ jnz Again
+
+Ende: pop cx ; Parameter nicht mehr gebraucht
+ pop bx
+ pop ax
+Term: if debug
+ PrChar CR
+ PrChar LF
+ endif
+ call BuildError
+ pop bp
+ pop dx
+ pop si
+
+ ret
+
+Again: inc bp ; Fehlerz„hler rauf
+ cmp bp,MaxRetry ; zu oft aufgetreten ?
+ jae Ende
+
+ pop cx ; nein: Parameter vom Stack
+ pop bx
+ pop ax
+ mov si,ax ; Laufwerk retten
+ call Recalibrate ; auf Spur 0 zurck
+ jc Term ; bei erneutem Fehler Abbruch
+ mov ax,si
+ call SetDriveParams ; Parameter neu initialisieren
+ mov ax,si
+ jmp Retry ; neuer Versuch
+ mov ax,si
+ endp
+
+;******************************************************************************
+;* Sektor(en) schreiben *
+;* In : AL = Laufwerk *
+;* AH = Startkopf *
+;* BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;* ES:SI = Zeiger auf Datenpuffer *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc WriteSectors
+
+ push di ; Register sichern
+ push dx
+ push bp
+
+ if debug
+ PrChar 'W'
+ mov bp,si
+ call WriteParams
+ endif
+
+ xor bp,bp ; Fehlerz„hler auf 0
+
+Retry: push ax ; Parameter sichern
+ push bx
+ push cx
+ push si
+
+ mov di,ax ; Laufwerk/Kopf retten
+ call WaitBusy ; warten, bis Ruhe im Wald
+
+ mov ax,di
+ call SetDriveEnv ; Laufwerk jetzt schon setzen, damit
+ ; korr. Ready-Signal abgefragt wird
+ call WaitDrive ; bis Laufwerk bereit
+
+ call SetTransParams ; restliche Parameter ausgeben
+
+ mov ch,0 ; Sektorzahl nach DI
+ mov di,cx
+ mov dx,Task_Command ; Kommando triggern
+ mov al,Cmd_Write
+ out dx,al
+
+ mov dx,Task_Data ; Vorbereitung fr OUTSW
+ cld
+Loop: call WaitBusy ; auf Datenbereitschaft warten
+ btst al,0 ; Fehler ?
+ jnz Again ; ja-->neu aufsetzen
+ call WaitData
+ btst al,0
+ jnz Again
+ call WaitDrive
+ btst al,0
+ jnz Again
+ mov cx,SecSize/2 ; Daten transferieren
+ seges
+ rep outsw ; bagger, schaufel
+ call WaitBusy ; warten, bis Transfer fertig
+ btst al,0
+ jnz Again
+ dec di ; n„chster Sektor
+ jnz Loop
+
+End: pop si ; Parameter nicht mehr gebraucht
+ pop cx
+ pop bx
+ pop ax
+Term: if debug
+ PrChar CR
+ PrChar LF
+ endif
+ call BuildError
+ pop bp
+ pop dx
+ pop di
+
+ ret
+
+Again: inc bp ; Fehlerz„hler rauf
+ cmp bp,MaxRetry ; zu oft aufgetreten ?
+ jae End
+
+ pop si ; nein: Parameter vom Stack
+ pop cx
+ pop bx
+ pop ax
+ mov di,ax ; Laufwerk retten
+ call Recalibrate ; auf Spur 0 zurck
+ jc Term ; bei erneutem Fehler Abbruch
+ mov ax,di
+ call SetDriveParams ; Parameter neu initialisieren
+ mov ax,di
+ jmp Retry ; neuer Versuch
+
+ endp
+
+;******************************************************************************
+;* Laufwerk formatieren *
+;* In : AL = Laufwerk *
+;* AH = Interleave *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc FormatUnit
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push bp
+
+ mov bx,ax ; Interleave retten
+ PrMsg ESCMsg
+ mov ax,bx
+ call GetPTabAdr ; Parametertabelle->DI
+ mov ax,bx
+ mov dh,0 ; gute Spuren schreiben
+ mov al,[di+DrPar_NSecs]
+ call SetInterleaveBuffer ; Tabelle berechnen
+ mov ax,bx
+ call Recalibrate ; Kontroller reinitialisieren
+ jc Fin
+ mov ax,bx
+ mov bp,[di+DrPar_Cyls] ; Zylinderz„hler in BP (abw„rts)
+ dec bp
+ mov dl,al ; Laufwerk in DL
+ cld
+CylLoop: mov dh,0 ; Kopf in dh
+HeadLoop: call WaitBusy ; warten, bis WD1003 frei
+ call WriteCoords ; Bildschirmausgabe
+ mov ax,dx ; Laufwerk+Kopf progr.
+ call SetDriveEnv
+ mov bx,bp ; Zylinder+Sektor progr.
+ mov cl,[di+DrPar_NSecs]
+ mov ch,1
+ call SetTransParams
+ mov bx,dx
+ mov dx,Task_Command
+ mov al,Cmd_Format
+ out dx,al
+ call WaitData ; Sektortabelle schicken
+ mov cx,SecSize/2
+ mov dx,Task_Data
+ lea si,[SectorBuffer]
+ rep outsw
+ call WaitBusy ; warten, bis Kontroller fertig
+ shr al,1 ; Fehlerbit in Carry laden
+ jnc GoOn
+ PrMsg ErrorMsg ; falls Fehler, Meldung ausgeben
+ mov dx,bx
+ call WriteCoords
+ PrChar LF
+GoOn: mov dx,bx ; Laufwerk und Kopf zurck
+ call BreakOnESC ; will der Benutzer abbrechen ?
+ jc UserTerm ; ja, Abbruch
+ inc dh ; n„chster Kopf
+ cmp dh,[di+DrPar_Heads]
+ jb HeadLoop
+ dec bp ; n„chster Zylinder
+ jns CylLoop
+TermLoop: mov al,dl ; damit die Seek-Rate wieder stimmt
+ call Recalibrate
+
+Fin: push ax ; Fehlerstatus halten
+ pushf
+ PrChar LF
+ popf ; Fehlerstatus zurck
+ pop ax
+ pop bp
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ ret
+
+UserTerm: mov al,dl ; Abbruch durch Benutzer: noch schnell
+ call Recalibrate ; rekalibrieren
+ jc Fin ; Fehler dabei ?
+ stc ; Ansonsten Sonderfehlercode
+ mov al,DErr_UserTerm
+ jmp Fin
+
+WriteCoords: push ax ; Kopf/Zylinder ausgeben
+ push cx
+
+ PrMsg CylMsg
+ mov ax,bp
+ mov cl,6
+ call WriteDec
+ PrMsg HeadMsg
+ mov al,dh
+ mov ah,0
+ mov cl,3
+ call WriteDec
+ PrChar CR
+
+ pop cx
+ pop ax
+ ret
+
+ESCMsg: db "Abbruch mit <ESC>",CR,LF,'$'
+CylMsg: db "Zylinder $"
+HeadMsg: db ", Kopf $"
+ErrorMsg: db "Formatierfehler auf $"
+
+ endp
+
+;******************************************************************************
+;* Spur formatieren *
+;* In : AL = Laufwerk *
+;* AH = Kopf *
+;* BX = Zylinder *
+;* CL = Interleave *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc FormatTrack
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push si
+ push di
+ push bp
+
+ mov bp,ax ; Laufwerk & Kopf retten
+ call Recalibrate ; Laufwerk sicherheitshalber rekalibrieren
+ mov ax,bp
+ call GetPTabAdr ; Sektortabelle aufbauen
+ mov dh,0 ; fehlerhafte Sektoren schreiben
+ mov ah,cl ; Interleave vorgeben
+ mov al,[di+DrPar_NSecs]
+ call SetInterleaveBuffer
+ mov ax,bp ; Laufwerk und Kopf zurck
+ call SetDriveEnv ; in Kontroller einprogrammieren
+ mov cl,[di+DrPar_NSecs] ; Sektor& Zylinder einschreiben
+ mov ch,1
+ call SetTransParams
+ mov dx,Task_Command ; Kommando schicken
+ mov al,Cmd_Format
+ out dx,al
+ call WaitData ; Sektortabelle schicken
+ mov cx,SecSize/2
+ mov dx,Task_Data
+ lea si,[SectorBuffer]
+ rep outsw
+ call WaitBusy ; warten, bis Kontroller fertig
+ jc Fin ; Abbruch bei Fehler
+ mov ax,bp ; Laufwerk nochmal rekalibrieren
+ call Recalibrate ; damit Steprate stimmt
+
+Fin: pop bp
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ ret
+
+ endp
+
+;******************************************************************************
+;* Spur als defekt markieren *
+;* In : AL = Laufwerk *
+;* AH = Kopf *
+;* BX = Zylinder *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc MarkBad
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push si
+ push di
+ push bp
+
+ mov bp,ax ; Laufwerk & Kopf retten
+ call Recalibrate ; Laufwerk sicherheitshalber rekalibrieren
+ mov ax,bp
+ call GetPTabAdr ;Sektortabelle aufbauen
+ mov dh,80h ; fehlerhafte Sektoren schreiben
+ mov ah,3 ; Interleave ist ziemlich egal...
+ mov al,[di+DrPar_NSecs]
+ call SetInterleaveBuffer
+ mov ax,bp ; Laufwerk und Kopf zurck
+ call SetDriveEnv ; in Kontroller einprogrammieren
+ mov cl,[di+DrPar_NSecs] ; Sektor& Zylinder einschreiben
+ mov ch,1
+ call SetTransParams
+ mov dx,Task_Command ; Kommando schicken
+ mov al,Cmd_Format
+ out dx,al
+ call WaitData ; Sektortabelle schicken
+ mov cx,SecSize/2
+ mov dx,Task_Data
+ lea si,[SectorBuffer]
+ rep outsw
+ call WaitBusy ; warten, bis Kontroller fertig
+ jc Fin ; Abbruch bei Fehler
+ mov ax,bp ; Laufwerk nochmal rekalibrieren
+ call Recalibrate ; damit Steprate stimmt
+
+Fin: pop bp
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ ret
+
+ endp
+
+ endsection
diff --git a/tests/t_st6/asflags b/tests/t_st6/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_st6/asflags
diff --git a/tests/t_st6/t_st6.asm b/tests/t_st6/t_st6.asm
new file mode 100755
index 0000000..7cbdc2b
--- /dev/null
+++ b/tests/t_st6/t_st6.asm
@@ -0,0 +1,82 @@
+ cpu st6225
+
+ nop
+ ret
+ reti
+ stop
+ wait
+
+ jrz pc
+ jrnz pc+1
+ jrc pc+2
+ jrnc pc+3
+
+ ld a,v
+ ld a,w
+ ld a,x
+ ld a,y
+ ld a,12h
+ ld a,(x)
+ ld a,(y)
+ ld v,a
+ ld 12h,a
+ ld (x),a
+ ld (y),a
+
+ ldi a,12h
+ ldi v,12h
+ ldi 12h,12h
+
+ jp 123h
+ call 123h
+
+ add a,v
+ add a,12h
+ add a,(x)
+ add a,(y)
+
+ and a,v
+ and a,12h
+ and a,(x)
+ and a,(y)
+
+ cp a,v
+ cp a,12h
+ cp a,(x)
+ cp a,(y)
+
+ sub a,v
+ sub a,12h
+ sub a,(x)
+ sub a,(y)
+
+ addi a,12h
+ andi a,12h
+ cpi a,12h
+ subi a,12h
+
+ clr a
+ clr v
+ clr 12h
+
+ com a
+ rlc a
+ sla a
+
+ inc a
+ inc v
+ inc 12h
+ inc (x)
+ inc (y)
+
+ dec a
+ dec v
+ dec 12h
+ dec (x)
+ dec (y)
+
+ set 3,v
+ res 5,12h
+
+ jrs 3,v,pc
+ jrr 5,12h,pc+1
diff --git a/tests/t_st6/t_st6.doc b/tests/t_st6/t_st6.doc
new file mode 100644
index 0000000..311bc51
--- /dev/null
+++ b/tests/t_st6/t_st6.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application ST6 -----------------------------+
+| |
+| This is a (synthetic) test of the ST6's instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_st6/t_st6.ori b/tests/t_st6/t_st6.ori
new file mode 100755
index 0000000..c7e305a
--- /dev/null
+++ b/tests/t_st6/t_st6.ori
Binary files differ
diff --git a/tests/t_st7/asflags b/tests/t_st7/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_st7/asflags
diff --git a/tests/t_st7/t_st7.asm b/tests/t_st7/t_st7.asm
new file mode 100644
index 0000000..c371c84
--- /dev/null
+++ b/tests/t_st7/t_st7.asm
@@ -0,0 +1,561 @@
+ cpu st7
+ page 0
+
+ halt
+ iret
+ nop
+ rcf
+ ret
+ rim
+ rsp
+ scf
+ sim
+ trap
+ wfi
+
+ adc a,#$15
+ adc a,$12
+ adc a,$12.w
+ adc a,$1234
+ adc a,(x)
+ adc a,($12,x)
+ adc a,($12.w,x)
+ adc a,($1234,x)
+ adc a,(y)
+ adc a,($12,y)
+ adc a,($12.w,y)
+ adc a,($1234,y)
+ adc a,[$12]
+ adc a,[$12.w]
+ adc a,([$12],x)
+ adc a,([$12.w],x)
+ adc a,([$12],y)
+ adc a,([$12.w],y)
+
+ add a,#$15
+ add a,$12
+ add a,$12.w
+ add a,$1234
+ add a,(x)
+ add a,($12,x)
+ add a,($12.w,x)
+ add a,($1234,x)
+ add a,(y)
+ add a,($12,y)
+ add a,($12.w,y)
+ add a,($1234,y)
+ add a,[$12]
+ add a,[$12.w]
+ add a,([$12],x)
+ add a,([$12.w],x)
+ add a,([$12],y)
+ add a,([$12.w],y)
+
+ and a,#$15
+ and a,$12
+ and a,$12.w
+ and a,$1234
+ and a,(x)
+ and a,($12,x)
+ and a,($12.w,x)
+ and a,($1234,x)
+ and a,(y)
+ and a,($12,y)
+ and a,($12.w,y)
+ and a,($1234,y)
+ and a,[$12]
+ and a,[$12.w]
+ and a,([$12],x)
+ and a,([$12.w],x)
+ and a,([$12],y)
+ and a,([$12.w],y)
+
+ bcp a,#$15
+ bcp a,$12
+ bcp a,$12.w
+ bcp a,$1234
+ bcp a,(x)
+ bcp a,($12,x)
+ bcp a,($12.w,x)
+ bcp a,($1234,x)
+ bcp a,(y)
+ bcp a,($12,y)
+ bcp a,($12.w,y)
+ bcp a,($1234,y)
+ bcp a,[$12]
+ bcp a,[$12.w]
+ bcp a,([$12],x)
+ bcp a,([$12.w],x)
+ bcp a,([$12],y)
+ bcp a,([$12.w],y)
+
+ or a,#$15
+ or a,$12
+ or a,$12.w
+ or a,$1234
+ or a,(x)
+ or a,($12,x)
+ or a,($12.w,x)
+ or a,($1234,x)
+ or a,(y)
+ or a,($12,y)
+ or a,($12.w,y)
+ or a,($1234,y)
+ or a,[$12]
+ or a,[$12.w]
+ or a,([$12],x)
+ or a,([$12.w],x)
+ or a,([$12],y)
+ or a,([$12.w],y)
+
+ sbc a,#$15
+ sbc a,$12
+ sbc a,$12.w
+ sbc a,$1234
+ sbc a,(x)
+ sbc a,($12,x)
+ sbc a,($12.w,x)
+ sbc a,($1234,x)
+ sbc a,(y)
+ sbc a,($12,y)
+ sbc a,($12.w,y)
+ sbc a,($1234,y)
+ sbc a,[$12]
+ sbc a,[$12.w]
+ sbc a,([$12],x)
+ sbc a,([$12.w],x)
+ sbc a,([$12],y)
+ sbc a,([$12.w],y)
+
+ sub a,#$15
+ sub a,$12
+ sub a,$12.w
+ sub a,$1234
+ sub a,(x)
+ sub a,($12,x)
+ sub a,($12.w,x)
+ sub a,($1234,x)
+ sub a,(y)
+ sub a,($12,y)
+ sub a,($12.w,y)
+ sub a,($1234,y)
+ sub a,[$12]
+ sub a,[$12.w]
+ sub a,([$12],x)
+ sub a,([$12.w],x)
+ sub a,([$12],y)
+ sub a,([$12.w],y)
+
+ xor a,#$15
+ xor a,$12
+ xor a,$12.w
+ xor a,$1234
+ xor a,(x)
+ xor a,($12,x)
+ xor a,($12.w,x)
+ xor a,($1234,x)
+ xor a,(y)
+ xor a,($12,y)
+ xor a,($12.w,y)
+ xor a,($1234,y)
+ xor a,[$12]
+ xor a,[$12.w]
+ xor a,([$12],x)
+ xor a,([$12.w],x)
+ xor a,([$12],y)
+ xor a,([$12.w],y)
+
+ call $12
+ call $12.w
+ call $1234
+ call (x)
+ call ($12,x)
+ call ($12.w,x)
+ call ($1234,x)
+ call (y)
+ call ($12,y)
+ call ($12.w,y)
+ call ($1234,y)
+ call [$12]
+ call [$12.w]
+ call ([$12],x)
+ call ([$12.w],x)
+ call ([$12],y)
+ call ([$12.w],y)
+
+ jp $12
+ jp $12.w
+ jp $1234
+ jp (x)
+ jp ($12,x)
+ jp ($12.w,x)
+ jp ($1234,x)
+ jp (y)
+ jp ($12,y)
+ jp ($12.w,y)
+ jp ($1234,y)
+ jp [$12]
+ jp [$12.w]
+ jp ([$12],x)
+ jp ([$12.w],x)
+ jp ([$12],y)
+ jp ([$12.w],y)
+
+ clr a
+ clr x
+ clr y
+ clr $12
+ clr (x)
+ clr ($12,x)
+ clr (y)
+ clr ($12,y)
+ clr [$12]
+ clr ([$12],x)
+ clr ([$12],y)
+
+ cpl a
+ cpl x
+ cpl y
+ cpl $12
+ cpl (x)
+ cpl ($12,x)
+ cpl (y)
+ cpl ($12,y)
+ cpl [$12]
+ cpl ([$12],x)
+ cpl ([$12],y)
+
+ dec a
+ dec x
+ dec y
+ dec $12
+ dec (x)
+ dec ($12,x)
+ dec (y)
+ dec ($12,y)
+ dec [$12]
+ dec ([$12],x)
+ dec ([$12],y)
+
+ inc a
+ inc x
+ inc y
+ inc $12
+ inc (x)
+ inc ($12,x)
+ inc (y)
+ inc ($12,y)
+ inc [$12]
+ inc ([$12],x)
+ inc ([$12],y)
+
+ neg a
+ neg x
+ neg y
+ neg $12
+ neg (x)
+ neg ($12,x)
+ neg (y)
+ neg ($12,y)
+ neg [$12]
+ neg ([$12],x)
+ neg ([$12],y)
+
+ rlc a
+ rlc x
+ rlc y
+ rlc $12
+ rlc (x)
+ rlc ($12,x)
+ rlc (y)
+ rlc ($12,y)
+ rlc [$12]
+ rlc ([$12],x)
+ rlc ([$12],y)
+
+ rrc a
+ rrc x
+ rrc y
+ rrc $12
+ rrc (x)
+ rrc ($12,x)
+ rrc (y)
+ rrc ($12,y)
+ rrc [$12]
+ rrc ([$12],x)
+ rrc ([$12],y)
+
+ sla a
+ sla x
+ sla y
+ sla $12
+ sla (x)
+ sla ($12,x)
+ sla (y)
+ sla ($12,y)
+ sla [$12]
+ sla ([$12],x)
+ sla ([$12],y)
+
+ sll a
+ sll x
+ sll y
+ sll $12
+ sll (x)
+ sll ($12,x)
+ sll (y)
+ sll ($12,y)
+ sll [$12]
+ sll ([$12],x)
+ sll ([$12],y)
+
+ sra a
+ sra x
+ sra y
+ sra $12
+ sra (x)
+ sra ($12,x)
+ sra (y)
+ sra ($12,y)
+ sra [$12]
+ sra ([$12],x)
+ sra ([$12],y)
+
+ srl a
+ srl x
+ srl y
+ srl $12
+ srl (x)
+ srl ($12,x)
+ srl (y)
+ srl ($12,y)
+ srl [$12]
+ srl ([$12],x)
+ srl ([$12],y)
+
+ swap a
+ swap x
+ swap y
+ swap $12
+ swap (x)
+ swap ($12,x)
+ swap (y)
+ swap ($12,y)
+ swap [$12]
+ swap ([$12],x)
+ swap ([$12],y)
+
+ tnz a
+ tnz x
+ tnz y
+ tnz $12
+ tnz (x)
+ tnz ($12,x)
+ tnz (y)
+ tnz ($12,y)
+ tnz [$12]
+ tnz ([$12],x)
+ tnz ([$12],y)
+
+ cp a,#$12
+ cp a,$12
+ cp a,$12.w
+ cp a,$1234
+ cp a,(x)
+ cp a,($12,x)
+ cp a,($12.w,x)
+ cp a,($1234,x)
+ cp a,(y)
+ cp a,($12,y)
+ cp a,($12.w,y)
+ cp a,($1234,y)
+ cp a,[$12]
+ cp a,[$12.w]
+ cp a,([$12],x)
+ cp a,([$12.w],x)
+ cp a,([$12],y)
+ cp a,([$12.w],y)
+ cp x,#$12
+ cp x,$12
+ cp x,$12.w
+ cp x,$1234
+ cp x,(x)
+ cp x,($12,x)
+ cp x,($12.w,x)
+ cp x,($1234,x)
+ cp x,[$12]
+ cp x,[$12.w]
+ cp x,([$12],x)
+ cp x,([$12.w],x)
+ cp y,#$12
+ cp y,$12
+ cp y,$12.w
+ cp y,$1234
+ cp y,(y)
+ cp y,($12,y)
+ cp y,($12.w,y)
+ cp y,($1234,y)
+ cp y,[$12]
+ cp y,[$12.w]
+ cp y,([$12],y)
+ cp y,([$12.w],y)
+
+ ld a,#$12
+ ld a,$12
+ ld a,$12.w
+ ld a,$1234
+ ld a,(x)
+ ld a,($12,x)
+ ld a,($12.w,x)
+ ld a,($1234,x)
+ ld a,(y)
+ ld a,($12,y)
+ ld a,($12.w,y)
+ ld a,($1234,y)
+ ld a,[$12]
+ ld a,[$12.w]
+ ld a,([$12],x)
+ ld a,([$12.w],x)
+ ld a,([$12],y)
+ ld a,([$12.w],y)
+ ld a,x
+ ld a,y
+ ld a,s
+ ld x,#$12
+ ld x,$12
+ ld x,$12.w
+ ld x,$1234
+ ld x,(x)
+ ld x,($12,x)
+ ld x,($12.w,x)
+ ld x,($1234,x)
+ ld x,[$12]
+ ld x,[$12.w]
+ ld x,([$12],x)
+ ld x,([$12.w],x)
+ ld x,a
+ ld x,y
+ ld x,s
+ ld y,#$12
+ ld y,$12
+ ld y,$12.w
+ ld y,$1234
+ ld y,(y)
+ ld y,($12,y)
+ ld y,($12.w,y)
+ ld y,($1234,y)
+ ld y,[$12]
+ ld y,[$12.w]
+ ld y,([$12],y)
+ ld y,([$12.w],y)
+ ld y,a
+ ld y,x
+ ld y,s
+ ld s,a
+ ld s,x
+ ld s,y
+ ld $12,a
+ ld $12.w,a
+ ld $1234,a
+ ld (x),a
+ ld ($12,x),a
+ ld ($12.w,x),a
+ ld ($1234,x),a
+ ld (y),a
+ ld ($12,y),a
+ ld ($12.w,y),a
+ ld ($1234,y),a
+ ld [$12],a
+ ld [$12.w],a
+ ld ([$12],x),a
+ ld ([$12.w],x),a
+ ld ([$12],y),a
+ ld ([$12.w],y),a
+ ld $12,x
+ ld $12.w,x
+ ld $1234,x
+ ld (x),x
+ ld ($12,x),x
+ ld ($12.w,x),x
+ ld ($1234,x),x
+ ld [$12],x
+ ld [$12.w],x
+ ld ([$12],x),x
+ ld ([$12.w],x),x
+ ld $12,y
+ ld $12.w,y
+ ld $1234,y
+ ld (y),y
+ ld ($12,y),y
+ ld ($12.w,y),y
+ ld ($1234,y),y
+ ld [$12],y
+ ld [$12.w],y
+ ld ([$12],y),y
+ ld ([$12.w],y),y
+
+ bres $12,#5
+ bres [$12],#2
+ bset $12,#5
+ bset [$12],#2
+
+ btjf $12,#5,pc
+ btjf [$12],#2,pc
+ btjt $12,#5,pc
+ btjt [$12],#2,pc
+
+ callr pc
+ jra pc
+ jrc pc
+ jreq pc
+ jrf pc
+ jrh pc
+ jrih pc
+ jril pc
+ jrm pc
+ jrmi pc
+ jrnc pc
+ jrne pc
+ jrnh pc
+ jrnm pc
+ jrpl pc
+ jrt pc
+ jruge pc
+ jrugt pc
+ jrule pc
+ jrult pc
+
+ callr [$12]
+ jra [$12]
+ jrc [$12]
+ jreq [$12]
+ jrf [$12]
+ jrh [$12]
+ jrih [$12]
+ jril [$12]
+ jrm [$12]
+ jrmi [$12]
+ jrnc [$12]
+ jrne [$12]
+ jrnh [$12]
+ jrnm [$12]
+ jrpl [$12]
+ jrt [$12]
+ jruge [$12]
+ jrugt [$12]
+ jrule [$12]
+ jrult [$12]
+
+ mul x,a
+ mul y,a
+
+ push a
+ push x
+ push y
+ push cc
+ pop a
+ pop x
+ pop y
+ pop cc
+
+
diff --git a/tests/t_st7/t_st7.doc b/tests/t_st7/t_st7.doc
new file mode 100644
index 0000000..d318126
--- /dev/null
+++ b/tests/t_st7/t_st7.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application ST7 -----------------------------+
+| |
+| This is a (synthetic) test of the ST7's instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_st7/t_st7.ori b/tests/t_st7/t_st7.ori
new file mode 100644
index 0000000..8813d35
--- /dev/null
+++ b/tests/t_st7/t_st7.ori
Binary files differ
diff --git a/tests/t_st9/asflags b/tests/t_st9/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_st9/asflags
diff --git a/tests/t_st9/t_st9.asm b/tests/t_st9/t_st9.asm
new file mode 100644
index 0000000..f2a3714
--- /dev/null
+++ b/tests/t_st9/t_st9.asm
@@ -0,0 +1,1243 @@
+ cpu st9040
+ page 0
+
+ include regst9
+
+ ccf
+ di
+ ei
+ halt
+ iret
+ nop
+ rcf
+ ret
+ scf
+ sdm
+ spm
+ wfi
+
+;----------------------------------------
+
+ adc r5,r13
+ adc r7,(r12)
+ adc R100,R130
+ adc r7,R22
+ adc R70,r11
+ adc (r7),R32
+ adc (r7),r11
+
+ adc R32,(r5)
+ adc R13,(rr4)
+ adc r13,(rr4)
+ adc R13,(rr4)+
+ adc r13,(rr4)+
+ adc R13,-(rr4)
+ adc r13,-(rr4)
+ adc r10,rr12(rr6)
+ adc R11,123(rr8)
+ adc r11,123(rr8)
+ adc r3,1234h
+ adc R11,1234(rr8)
+ adc r11,1234(rr8)
+
+ adc (rr4),R13
+ adc (rr4),r13
+ adc (rr4)+,R13
+ adc (rr4)+,r13
+ adc -(rr4),R13
+ adc -(rr4),r13
+ adc rr12(rr6),r10
+ adc 123(rr8),R11
+ adc 123(rr8),r11
+ adc 1234h,r3
+ adc 1234(rr8),R11
+ adc 1234(rr8),r11
+
+ adc (RR4),(rr8)
+ adc (rr4),(rr8)
+
+ adc R14,#12h
+ adc r14,#12h
+ adc (rr6),#12h
+ adc 1234h,#12h
+
+
+ adcw rr4,rr12
+ adcw RR100,RR130
+ adcw rr6,RR22
+ adcw RR70,rr10
+ adcw (r7),RR32
+ adcw (r7),rr10
+ adcw RR32,(r5)
+ adcw rr6,(r12)
+
+ adcw rr12,(rr4)
+ adcw RR12,(rr4)
+ adcw RR12,(rr4)+
+ adcw rr12,(rr4)+
+ adcw RR12,-(rr4)
+ adcw rr12,-(rr4)
+ adcw rr10,rr12(rr6)
+ adcw RR10,123(rr8)
+ adcw rr10,123(rr8)
+ adcw rr2,1234h
+ adcw RR10,1234(rr8)
+ adcw rr10,1234(rr8)
+
+ adcw (rr4),rr12
+ adcw (rr4),RR12
+ adcw (rr4)+,RR12
+ adcw (rr4)+,rr12
+ adcw -(rr4),RR12
+ adcw -(rr4),rr12
+ adcw rr12(rr6),rr10
+ adcw 123(rr8),RR10
+ adcw 123(rr8),rr10
+ adcw 1234h,rr2
+ adcw 1234(rr8),RR10
+ adcw 1234(rr8),rr10
+
+ adcw (rr4),(rr8)
+
+ adcw RR14,#1234h
+ adcw rr14,#1234h
+ adcw (rr6),#1234h
+ adcw 123(rr6),#1234h
+ adcw 1234(rr6),#1234h
+ adcw 1234h,#1234h
+
+;---------------------------------------------
+
+ add r5,r13
+ add r7,(r12)
+ add R100,R130
+ add r7,R22
+ add R70,r11
+ add (r7),R32
+ add (r7),r11
+ add R32,(r5)
+
+ add R13,(rr4)
+ add r13,(rr4)
+ add R13,(rr4)+
+ add r13,(rr4)+
+ add R13,-(rr4)
+ add r13,-(rr4)
+ add r10,rr12(rr6)
+ add R11,123(rr8)
+ add r11,123(rr8)
+ add r3,1234h
+ add R11,1234(rr8)
+ add r11,1234(rr8)
+
+ add (rr4),R13
+ add (rr4),r13
+ add (rr4)+,R13
+ add (rr4)+,r13
+ add -(rr4),R13
+ add -(rr4),r13
+ add rr12(rr6),r10
+ add 123(rr8),R11
+ add 123(rr8),r11
+ add 1234h,r3
+ add 1234(rr8),R11
+ add 1234(rr8),r11
+
+ add (RR4),(rr8)
+ add (rr4),(rr8)
+
+ add R14,#12h
+ add r14,#12h
+ add (rr6),#12h
+ add 1234h,#12h
+
+
+ addw rr4,rr12
+ addw RR100,RR130
+ addw rr6,RR22
+ addw RR70,rr10
+ addw (r7),RR32
+ addw (r7),rr10
+ addw RR32,(r5)
+ addw rr6,(r12)
+
+ addw rr12,(rr4)
+ addw RR12,(rr4)
+ addw RR12,(rr4)+
+ addw rr12,(rr4)+
+ addw RR12,-(rr4)
+ addw rr12,-(rr4)
+ addw rr10,rr12(rr6)
+ addw RR10,123(rr8)
+ addw rr10,123(rr8)
+ addw rr2,1234h
+ addw RR10,1234(rr8)
+ addw rr10,1234(rr8)
+
+ addw (rr4),rr12
+ addw (rr4),RR12
+ addw (rr4)+,RR12
+ addw (rr4)+,rr12
+ addw -(rr4),RR12
+ addw -(rr4),rr12
+ addw rr12(rr6),rr10
+ addw 123(rr8),RR10
+ addw 123(rr8),rr10
+ addw 1234h,rr2
+ addw 1234(rr8),RR10
+ addw 1234(rr8),rr10
+
+ addw (rr4),(rr8)
+
+ addw RR14,#1234h
+ addw rr14,#1234h
+ addw (rr6),#1234h
+ addw 123(rr6),#1234h
+ addw 1234(rr6),#1234h
+ addw 1234h,#1234h
+
+;---------------------------------------------
+
+ and r5,r13
+ and r7,(r12)
+ and R100,R130
+ and r7,R22
+ and R70,r11
+ and (r7),R32
+ and (r7),r11
+ and R32,(r5)
+
+ and R13,(rr4)
+ and r13,(rr4)
+ and R13,(rr4)+
+ and r13,(rr4)+
+ and R13,-(rr4)
+ and r13,-(rr4)
+ and r10,rr12(rr6)
+ and R11,123(rr8)
+ and r11,123(rr8)
+ and r3,1234h
+ and R11,1234(rr8)
+ and r11,1234(rr8)
+
+ and (rr4),R13
+ and (rr4),r13
+ and (rr4)+,R13
+ and (rr4)+,r13
+ and -(rr4),R13
+ and -(rr4),r13
+ and rr12(rr6),r10
+ and 123(rr8),R11
+ and 123(rr8),r11
+ and 1234h,r3
+ and 1234(rr8),R11
+ and 1234(rr8),r11
+
+ and (RR4),(rr8)
+ and (rr4),(rr8)
+
+ and R14,#12h
+ and r14,#12h
+ and (rr6),#12h
+ and 1234h,#12h
+
+
+ andw rr4,rr12
+ andw RR100,RR130
+ andw rr6,RR22
+ andw RR70,rr10
+ andw (r7),RR32
+ andw (r7),rr10
+ andw RR32,(r5)
+ andw rr6,(r12)
+
+ andw rr12,(rr4)
+ andw RR12,(rr4)
+ andw RR12,(rr4)+
+ andw rr12,(rr4)+
+ andw RR12,-(rr4)
+ andw rr12,-(rr4)
+ andw rr10,rr12(rr6)
+ andw RR10,123(rr8)
+ andw rr10,123(rr8)
+ andw rr2,1234h
+ andw RR10,1234(rr8)
+ andw rr10,1234(rr8)
+
+ andw (rr4),rr12
+ andw (rr4),RR12
+ andw (rr4)+,RR12
+ andw (rr4)+,rr12
+ andw -(rr4),RR12
+ andw -(rr4),rr12
+ andw rr12(rr6),rr10
+ andw 123(rr8),RR10
+ andw 123(rr8),rr10
+ andw 1234h,rr2
+ andw 1234(rr8),RR10
+ andw 1234(rr8),rr10
+
+ andw (rr4),(rr8)
+
+ andw RR14,#1234h
+ andw rr14,#1234h
+ andw (rr6),#1234h
+ andw 123(rr6),#1234h
+ andw 1234(rr6),#1234h
+ andw 1234h,#1234h
+
+;---------------------------------------------
+
+ cp r5,r13
+ cp r7,(r12)
+ cp R100,R130
+ cp r7,R22
+ cp R70,r11
+ cp (r7),R32
+ cp (r7),r11
+ cp R32,(r5)
+
+ cp R13,(rr4)
+ cp r13,(rr4)
+ cp R13,(rr4)+
+ cp r13,(rr4)+
+ cp R13,-(rr4)
+ cp r13,-(rr4)
+ cp r10,rr12(rr6)
+ cp R11,123(rr8)
+ cp r11,123(rr8)
+ cp r3,1234h
+ cp R11,1234(rr8)
+ cp r11,1234(rr8)
+
+ cp (rr4),R13
+ cp (rr4),r13
+ cp (rr4)+,R13
+ cp (rr4)+,r13
+ cp -(rr4),R13
+ cp -(rr4),r13
+ cp rr12(rr6),r10
+ cp 123(rr8),R11
+ cp 123(rr8),r11
+ cp 1234h,r3
+ cp 1234(rr8),R11
+ cp 1234(rr8),r11
+
+ cp (RR4),(rr8)
+ cp (rr4),(rr8)
+
+ cp R14,#12h
+ cp r14,#12h
+ cp (rr6),#12h
+ cp 1234h,#12h
+
+
+ cpw rr4,rr12
+ cpw RR100,RR130
+ cpw rr6,RR22
+ cpw RR70,rr10
+ cpw (r7),RR32
+ cpw (r7),rr10
+ cpw RR32,(r5)
+ cpw rr6,(r12)
+
+ cpw rr12,(rr4)
+ cpw RR12,(rr4)
+ cpw RR12,(rr4)+
+ cpw rr12,(rr4)+
+ cpw RR12,-(rr4)
+ cpw rr12,-(rr4)
+ cpw rr10,rr12(rr6)
+ cpw RR10,123(rr8)
+ cpw rr10,123(rr8)
+ cpw rr2,1234h
+ cpw RR10,1234(rr8)
+ cpw rr10,1234(rr8)
+
+ cpw (rr4),rr12
+ cpw (rr4),RR12
+ cpw (rr4)+,RR12
+ cpw (rr4)+,rr12
+ cpw -(rr4),RR12
+ cpw -(rr4),rr12
+ cpw rr12(rr6),rr10
+ cpw 123(rr8),RR10
+ cpw 123(rr8),rr10
+ cpw 1234h,rr2
+ cpw 1234(rr8),RR10
+ cpw 1234(rr8),rr10
+
+ cpw (rr4),(rr8)
+
+ cpw RR14,#1234h
+ cpw rr14,#1234h
+ cpw (rr6),#1234h
+ cpw 123(rr6),#1234h
+ cpw 1234(rr6),#1234h
+ cpw 1234h,#1234h
+
+;---------------------------------------------
+
+ or r5,r13
+ or r7,(r12)
+ or R100,R130
+ or r7,R22
+ or R70,r11
+ or (r7),R32
+ or (r7),r11
+ or R32,(r5)
+
+ or R13,(rr4)
+ or r13,(rr4)
+ or R13,(rr4)+
+ or r13,(rr4)+
+ or R13,-(rr4)
+ or r13,-(rr4)
+ or r10,rr12(rr6)
+ or R11,123(rr8)
+ or r11,123(rr8)
+ or r3,1234h
+ or R11,1234(rr8)
+ or r11,1234(rr8)
+
+ or (rr4),R13
+ or (rr4),r13
+ or (rr4)+,R13
+ or (rr4)+,r13
+ or -(rr4),R13
+ or -(rr4),r13
+ or rr12(rr6),r10
+ or 123(rr8),R11
+ or 123(rr8),r11
+ or 1234h,r3
+ or 1234(rr8),R11
+ or 1234(rr8),r11
+
+ or (RR4),(rr8)
+ or (rr4),(rr8)
+
+ or R14,#12h
+ or r14,#12h
+ or (rr6),#12h
+ or 1234h,#12h
+
+
+ orw rr4,rr12
+ orw RR100,RR130
+ orw rr6,RR22
+ orw RR70,rr10
+ orw (r7),RR32
+ orw (r7),rr10
+ orw RR32,(r5)
+ orw rr6,(r12)
+
+ orw rr12,(rr4)
+ orw RR12,(rr4)
+ orw RR12,(rr4)+
+ orw rr12,(rr4)+
+ orw RR12,-(rr4)
+ orw rr12,-(rr4)
+ orw rr10,rr12(rr6)
+ orw RR10,123(rr8)
+ orw rr10,123(rr8)
+ orw rr2,1234h
+ orw RR10,1234(rr8)
+ orw rr10,1234(rr8)
+
+ orw (rr4),rr12
+ orw (rr4),RR12
+ orw (rr4)+,RR12
+ orw (rr4)+,rr12
+ orw -(rr4),RR12
+ orw -(rr4),rr12
+ orw rr12(rr6),rr10
+ orw 123(rr8),RR10
+ orw 123(rr8),rr10
+ orw 1234h,rr2
+ orw 1234(rr8),RR10
+ orw 1234(rr8),rr10
+
+ orw (rr4),(rr8)
+
+ orw RR14,#1234h
+ orw rr14,#1234h
+ orw (rr6),#1234h
+ orw 123(rr6),#1234h
+ orw 1234(rr6),#1234h
+ orw 1234h,#1234h
+
+;---------------------------------------------
+
+ sbc r5,r13
+ sbc r7,(r12)
+ sbc R100,R130
+ sbc r7,R22
+ sbc R70,r11
+ sbc (r7),R32
+ sbc (r7),r11
+ sbc R32,(r5)
+
+ sbc R13,(rr4)
+ sbc r13,(rr4)
+ sbc R13,(rr4)+
+ sbc r13,(rr4)+
+ sbc R13,-(rr4)
+ sbc r13,-(rr4)
+ sbc r10,rr12(rr6)
+ sbc R11,123(rr8)
+ sbc r11,123(rr8)
+ sbc r3,1234h
+ sbc R11,1234(rr8)
+ sbc r11,1234(rr8)
+
+ sbc (rr4),R13
+ sbc (rr4),r13
+ sbc (rr4)+,R13
+ sbc (rr4)+,r13
+ sbc -(rr4),R13
+ sbc -(rr4),r13
+ sbc rr12(rr6),r10
+ sbc 123(rr8),R11
+ sbc 123(rr8),r11
+ sbc 1234h,r3
+ sbc 1234(rr8),R11
+ sbc 1234(rr8),r11
+
+ sbc (RR4),(rr8)
+ sbc (rr4),(rr8)
+
+ sbc R14,#12h
+ sbc r14,#12h
+ sbc (rr6),#12h
+ sbc 1234h,#12h
+
+
+ sbcw rr4,rr12
+ sbcw RR100,RR130
+ sbcw rr6,RR22
+ sbcw RR70,rr10
+ sbcw (r7),RR32
+ sbcw (r7),rr10
+ sbcw RR32,(r5)
+ sbcw rr6,(r12)
+
+ sbcw rr12,(rr4)
+ sbcw RR12,(rr4)
+ sbcw RR12,(rr4)+
+ sbcw rr12,(rr4)+
+ sbcw RR12,-(rr4)
+ sbcw rr12,-(rr4)
+ sbcw rr10,rr12(rr6)
+ sbcw RR10,123(rr8)
+ sbcw rr10,123(rr8)
+ sbcw rr2,1234h
+ sbcw RR10,1234(rr8)
+ sbcw rr10,1234(rr8)
+
+ sbcw (rr4),rr12
+ sbcw (rr4),RR12
+ sbcw (rr4)+,RR12
+ sbcw (rr4)+,rr12
+ sbcw -(rr4),RR12
+ sbcw -(rr4),rr12
+ sbcw rr12(rr6),rr10
+ sbcw 123(rr8),RR10
+ sbcw 123(rr8),rr10
+ sbcw 1234h,rr2
+ sbcw 1234(rr8),RR10
+ sbcw 1234(rr8),rr10
+
+ sbcw (rr4),(rr8)
+
+ sbcw RR14,#1234h
+ sbcw rr14,#1234h
+ sbcw (rr6),#1234h
+ sbcw 123(rr6),#1234h
+ sbcw 1234(rr6),#1234h
+ sbcw 1234h,#1234h
+
+;---------------------------------------------
+
+ sub r5,r13
+ sub r7,(r12)
+ sub R100,R130
+ sub r7,R22
+ sub R70,r11
+ sub (r7),R32
+ sub (r7),r11
+ sub R32,(r5)
+
+ sub R13,(rr4)
+ sub r13,(rr4)
+ sub R13,(rr4)+
+ sub r13,(rr4)+
+ sub R13,-(rr4)
+ sub r13,-(rr4)
+ sub r10,rr12(rr6)
+ sub R11,123(rr8)
+ sub r11,123(rr8)
+ sub r3,1234h
+ sub R11,1234(rr8)
+ sub r11,1234(rr8)
+
+ sub (rr4),R13
+ sub (rr4),r13
+ sub (rr4)+,R13
+ sub (rr4)+,r13
+ sub -(rr4),R13
+ sub -(rr4),r13
+ sub rr12(rr6),r10
+ sub 123(rr8),R11
+ sub 123(rr8),r11
+ sub 1234h,r3
+ sub 1234(rr8),R11
+ sub 1234(rr8),r11
+
+ sub (RR4),(rr8)
+ sub (rr4),(rr8)
+
+ sub R14,#12h
+ sub r14,#12h
+ sub (rr6),#12h
+ sub 1234h,#12h
+
+
+ subw rr4,rr12
+ subw RR100,RR130
+ subw rr6,RR22
+ subw RR70,rr10
+ subw (r7),RR32
+ subw (r7),rr10
+ subw RR32,(r5)
+ subw rr6,(r12)
+
+ subw rr12,(rr4)
+ subw RR12,(rr4)
+ subw RR12,(rr4)+
+ subw rr12,(rr4)+
+ subw RR12,-(rr4)
+ subw rr12,-(rr4)
+ subw rr10,rr12(rr6)
+ subw RR10,123(rr8)
+ subw rr10,123(rr8)
+ subw rr2,1234h
+ subw RR10,1234(rr8)
+ subw rr10,1234(rr8)
+
+ subw (rr4),rr12
+ subw (rr4),RR12
+ subw (rr4)+,RR12
+ subw (rr4)+,rr12
+ subw -(rr4),RR12
+ subw -(rr4),rr12
+ subw rr12(rr6),rr10
+ subw 123(rr8),RR10
+ subw 123(rr8),rr10
+ subw 1234h,rr2
+ subw 1234(rr8),RR10
+ subw 1234(rr8),rr10
+
+ subw (rr4),(rr8)
+
+ subw RR14,#1234h
+ subw rr14,#1234h
+ subw (rr6),#1234h
+ subw 123(rr6),#1234h
+ subw 1234(rr6),#1234h
+ subw 1234h,#1234h
+
+;---------------------------------------------
+
+ tcm r5,r13
+ tcm r7,(r12)
+ tcm R100,R130
+ tcm r7,R22
+ tcm R70,r11
+ tcm (r7),R32
+ tcm (r7),r11
+ tcm R32,(r5)
+
+ tcm R13,(rr4)
+ tcm r13,(rr4)
+ tcm R13,(rr4)+
+ tcm r13,(rr4)+
+ tcm R13,-(rr4)
+ tcm r13,-(rr4)
+ tcm r10,rr12(rr6)
+ tcm R11,123(rr8)
+ tcm r11,123(rr8)
+ tcm r3,1234h
+ tcm R11,1234(rr8)
+ tcm r11,1234(rr8)
+
+ tcm (rr4),R13
+ tcm (rr4),r13
+ tcm (rr4)+,R13
+ tcm (rr4)+,r13
+ tcm -(rr4),R13
+ tcm -(rr4),r13
+ tcm rr12(rr6),r10
+ tcm 123(rr8),R11
+ tcm 123(rr8),r11
+ tcm 1234h,r3
+ tcm 1234(rr8),R11
+ tcm 1234(rr8),r11
+
+ tcm (RR4),(rr8)
+ tcm (rr4),(rr8)
+
+ tcm R14,#12h
+ tcm r14,#12h
+ tcm (rr6),#12h
+ tcm 1234h,#12h
+
+
+ tcmw rr4,rr12
+ tcmw RR100,RR130
+ tcmw rr6,RR22
+ tcmw RR70,rr10
+ tcmw (r7),RR32
+ tcmw (r7),rr10
+ tcmw RR32,(r5)
+ tcmw rr6,(r12)
+
+ tcmw rr12,(rr4)
+ tcmw RR12,(rr4)
+ tcmw RR12,(rr4)+
+ tcmw rr12,(rr4)+
+ tcmw RR12,-(rr4)
+ tcmw rr12,-(rr4)
+ tcmw rr10,rr12(rr6)
+ tcmw RR10,123(rr8)
+ tcmw rr10,123(rr8)
+ tcmw rr2,1234h
+ tcmw RR10,1234(rr8)
+ tcmw rr10,1234(rr8)
+
+ tcmw (rr4),rr12
+ tcmw (rr4),RR12
+ tcmw (rr4)+,RR12
+ tcmw (rr4)+,rr12
+ tcmw -(rr4),RR12
+ tcmw -(rr4),rr12
+ tcmw rr12(rr6),rr10
+ tcmw 123(rr8),RR10
+ tcmw 123(rr8),rr10
+ tcmw 1234h,rr2
+ tcmw 1234(rr8),RR10
+ tcmw 1234(rr8),rr10
+
+ tcmw (rr4),(rr8)
+
+ tcmw RR14,#1234h
+ tcmw rr14,#1234h
+ tcmw (rr6),#1234h
+ tcmw 123(rr6),#1234h
+ tcmw 1234(rr6),#1234h
+ tcmw 1234h,#1234h
+
+;---------------------------------------------
+
+ tm r5,r13
+ tm r7,(r12)
+ tm R100,R130
+ tm r7,R22
+ tm R70,r11
+ tm (r7),R32
+ tm (r7),r11
+ tm R32,(r5)
+
+ tm R13,(rr4)
+ tm r13,(rr4)
+ tm R13,(rr4)+
+ tm r13,(rr4)+
+ tm R13,-(rr4)
+ tm r13,-(rr4)
+ tm r10,rr12(rr6)
+ tm R11,123(rr8)
+ tm r11,123(rr8)
+ tm r3,1234h
+ tm R11,1234(rr8)
+ tm r11,1234(rr8)
+
+ tm (rr4),R13
+ tm (rr4),r13
+ tm (rr4)+,R13
+ tm (rr4)+,r13
+ tm -(rr4),R13
+ tm -(rr4),r13
+ tm rr12(rr6),r10
+ tm 123(rr8),R11
+ tm 123(rr8),r11
+ tm 1234h,r3
+ tm 1234(rr8),R11
+ tm 1234(rr8),r11
+
+ tm (RR4),(rr8)
+ tm (rr4),(rr8)
+
+ tm R14,#12h
+ tm r14,#12h
+ tm (rr6),#12h
+ tm 1234h,#12h
+
+
+ tmw rr4,rr12
+ tmw RR100,RR130
+ tmw rr6,RR22
+ tmw RR70,rr10
+ tmw (r7),RR32
+ tmw (r7),rr10
+ tmw RR32,(r5)
+ tmw rr6,(r12)
+
+ tmw rr12,(rr4)
+ tmw RR12,(rr4)
+ tmw RR12,(rr4)+
+ tmw rr12,(rr4)+
+ tmw RR12,-(rr4)
+ tmw rr12,-(rr4)
+ tmw rr10,rr12(rr6)
+ tmw RR10,123(rr8)
+ tmw rr10,123(rr8)
+ tmw rr2,1234h
+ tmw RR10,1234(rr8)
+ tmw rr10,1234(rr8)
+
+ tmw (rr4),rr12
+ tmw (rr4),RR12
+ tmw (rr4)+,RR12
+ tmw (rr4)+,rr12
+ tmw -(rr4),RR12
+ tmw -(rr4),rr12
+ tmw rr12(rr6),rr10
+ tmw 123(rr8),RR10
+ tmw 123(rr8),rr10
+ tmw 1234h,rr2
+ tmw 1234(rr8),RR10
+ tmw 1234(rr8),rr10
+
+ tmw (rr4),(rr8)
+
+ tmw RR14,#1234h
+ tmw rr14,#1234h
+ tmw (rr6),#1234h
+ tmw 123(rr6),#1234h
+ tmw 1234(rr6),#1234h
+ tmw 1234h,#1234h
+
+;---------------------------------------------
+
+ xor r5,r13
+ xor r7,(r12)
+ xor R100,R130
+ xor r7,R22
+ xor R70,r11
+ xor (r7),R32
+ xor (r7),r11
+ xor R32,(r5)
+
+ xor R13,(rr4)
+ xor r13,(rr4)
+ xor R13,(rr4)+
+ xor r13,(rr4)+
+ xor R13,-(rr4)
+ xor r13,-(rr4)
+ xor r10,rr12(rr6)
+ xor R11,123(rr8)
+ xor r11,123(rr8)
+ xor r3,1234h
+ xor R11,1234(rr8)
+ xor r11,1234(rr8)
+
+ xor (rr4),R13
+ xor (rr4),r13
+ xor (rr4)+,R13
+ xor (rr4)+,r13
+ xor -(rr4),R13
+ xor -(rr4),r13
+ xor rr12(rr6),r10
+ xor 123(rr8),R11
+ xor 123(rr8),r11
+ xor 1234h,r3
+ xor 1234(rr8),R11
+ xor 1234(rr8),r11
+
+ xor (RR4),(rr8)
+ xor (rr4),(rr8)
+
+ xor R14,#12h
+ xor r14,#12h
+ xor (rr6),#12h
+ xor 1234h,#12h
+
+
+ xorw rr4,rr12
+ xorw RR100,RR130
+ xorw rr6,RR22
+ xorw RR70,rr10
+ xorw (r7),RR32
+ xorw (r7),rr10
+ xorw RR32,(r5)
+ xorw rr6,(r12)
+
+ xorw rr12,(rr4)
+ xorw RR12,(rr4)
+ xorw RR12,(rr4)+
+ xorw rr12,(rr4)+
+ xorw RR12,-(rr4)
+ xorw rr12,-(rr4)
+ xorw rr10,rr12(rr6)
+ xorw RR10,123(rr8)
+ xorw rr10,123(rr8)
+ xorw rr2,1234h
+ xorw RR10,1234(rr8)
+ xorw rr10,1234(rr8)
+
+ xorw (rr4),rr12
+ xorw (rr4),RR12
+ xorw (rr4)+,RR12
+ xorw (rr4)+,rr12
+ xorw -(rr4),RR12
+ xorw -(rr4),rr12
+ xorw rr12(rr6),rr10
+ xorw 123(rr8),RR10
+ xorw 123(rr8),rr10
+ xorw 1234h,rr2
+ xorw 1234(rr8),RR10
+ xorw 1234(rr8),rr10
+
+ xorw (rr4),(rr8)
+
+ xorw RR14,#1234h
+ xorw rr14,#1234h
+ xorw (rr6),#1234h
+ xorw 123(rr6),#1234h
+ xorw 1234(rr6),#1234h
+ xorw 1234h,#1234h
+
+;---------------------------------------------
+
+ ld r13,R230
+ ld r4,r12
+ ld R123,r5
+ ld (r6),r12
+ ld r12,(r6)
+ ld (r9),R56
+ ld (r10),r11
+ ld R100,(r7)
+ ld 72(r5),r8
+ ld r8,72(r5)
+ ld R120,R130
+
+ ld r10,(rr12)
+ ld (r4)+,(rr6)+
+ ld R240,(rr2)+
+ ld r10,(rr2)+
+ ld R4,-(rr6)
+ ld r4,-(rr6)
+ ld R230,(rr8)
+ ld r2,rr6(rr4)
+ ld R14,123(rr6)
+ ld r14,123(rr6)
+ ld r12,1234h
+ ld R12,1234(rr8)
+ ld r12,1234(rr8)
+
+ ld (rr4)+,(r6)+
+ ld (rr12),(r10)
+ ld (rr2)+,R240
+ ld (rr2)+,r10
+ ld -(rr6),R4
+ ld -(rr6),r4
+ ld (rr8),R230
+ ld rr6(rr4),r2
+ ld 123(rr6),R14
+ ld 123(rr6),r14
+ ld 1234h,r12
+ ld 1234(rr8),R12
+ ld 1234(rr8),r12
+
+ ld (RR4),(rr6)
+ ld (rr4),(rr6)
+
+ ld r8,#242
+ ld R8,#123
+ ld (rr6),#23h
+ ld 1234h,#56h
+
+
+ ldw rr10,rr14
+ ldw (r7),RR128
+ ldw (r9),rr4
+ ldw RR40,(r5)
+ ldw rr6,(r5)
+ ldw 123(r7),rr8
+ ldw rr10,123(r5)
+ ldw RR40,RR120
+ ldw rr12,RR136
+ ldw RR136,rr12
+
+ ldw rr8,(rr6)
+ ldw RR20,(rr10)+
+ ldw rr12,(rr10)+
+ ldw RR124,-(rr2)
+ ldw rr4,-(rr2)
+ ldw RR8,(rr6)
+ ldw rr10,rr2(rr6)
+ ldw RR20,123(rr8)
+ ldw rr8,123(rr8)
+ ldw rr4,1234h
+ ldw RR20,1234(rr8)
+ ldw rr8,1234(rr8)
+
+ ldw (rr6),rr8
+ ldw (rr10)+,RR20
+ ldw (rr10)+,rr12
+ ldw -(rr2),RR124
+ ldw -(rr2),rr4
+ ldw (rr6),RR8
+ ldw rr2(rr6),rr10
+ ldw 123(rr8),RR20
+ ldw 123(rr8),rr8
+ ldw 1234h,rr4
+ ldw 1234(rr8),RR20
+ ldw 1234(rr8),rr8
+
+ ldw (rr6),(rr10)
+
+ ldw rr8,#2345h
+ ldw RR100,#4268
+ ldw (rr6),#1234h
+ ldw 123(rr6),#1234h
+ ldw 1234(rr6),#1234h
+ ldw 1234h,#1234h
+
+;-----------------------------------
+
+ clr R32
+ clr r2
+ clr (R32)
+ clr (r2)
+
+ cpl R32
+ cpl r2
+ cpl (R32)
+ cpl (r2)
+
+ da R32
+ da r2
+ da (R32)
+ da (r2)
+
+ dec R32
+ dec r2
+ dec (R32)
+ dec (r2)
+
+ inc R32
+ inc r2
+ inc (R32)
+ inc (r2)
+
+ pop R32
+ pop r2
+ pop (R32)
+ pop (r2)
+
+ popu R32
+ popu r2
+ popu (R32)
+ popu (r2)
+
+ rlc R32
+ rlc r2
+ rlc (R32)
+ rlc (r2)
+
+ rol R32
+ rol r2
+ rol (R32)
+ rol (r2)
+
+ ror R32
+ ror r2
+ ror (R32)
+ ror (r2)
+
+ rrc R32
+ rrc r2
+ rrc (R32)
+ rrc (r2)
+
+ sra R32
+ sra r2
+ sra (R32)
+ sra (r2)
+
+ swap R32
+ swap r2
+ swap (R32)
+ swap (r2)
+
+ decw RR32
+ decw rr2
+
+ ext RR10
+ ext rr10
+
+ incw RR32
+ incw rr2
+
+ popuw RR32
+ popuw rr2
+
+ popw RR32
+ popw rr2
+
+ rlcw RR32
+ rlcw rr2
+
+ rrcw RR32
+ rrcw rr2
+
+ sraw RR32
+ sraw rr2
+
+;------------------------------
+
+ band r4.5,r8.2
+ band r4.5,r8.!2
+
+ bld r4.5,r8.!2
+ bld r4.5,r8.2
+
+ bor r4.5,r8.2
+ bor r4.5,r8.!2
+
+ bxor r4.5,r8.2
+ bxor r4.5,r8.!2
+
+;------------------------------
+
+ bcpl r4.5
+
+ bres r4.5
+
+ bset r4.5
+
+ btset r4.5
+ btset (rr4).5
+
+ btjf r10.2,pc
+ btjt r10.2,pc
+
+;------------------------------
+
+ call (RR30)
+ call (rr6)
+ call 3521h
+
+ jp (RR30)
+ jp (rr6)
+ jp 1024
+
+ jpeq 1024
+
+ jreq pc
+
+;------------------------------
+
+ cpjfi r2,(rr14),pc
+ cpjti r2,(rr14),pc
+
+ djnz r6,pc
+ dwjnz RR6,pc
+ dwjnz rr6,pc
+
+;------------------------------
+
+ div rr8,r6
+ mul rr6,r8
+ divws rr6,rr8,RR10
+
+;------------------------------
+
+ ldpp (rr8)+,(rr12)+
+ lddp (rr8)+,(rr12)+
+ ldpd (rr8)+,(rr12)+
+ lddd (rr8)+,(rr12)+
+
+;------------------------------
+
+ pea 16(RR32)
+ pea 16(rr2)
+ pea 1600(RR32)
+ pea 1600(rr2)
+
+ peau 16(RR32)
+ peau 16(rr2)
+ peau 1600(RR32)
+ peau 1600(rr2)
+
+;------------------------------
+
+ push R32
+ push r2
+ push (R32)
+ push (r2)
+ push #23h
+
+ pushu R32
+ pushu r2
+ pushu (R32)
+ pushu (r2)
+ pushu #23h
+
+ pushuw RR32
+ pushuw rr2
+ pushuw #1234h
+
+ pushw RR32
+ pushw rr2
+ pushw #1234h
+
+;------------------------------
+
+ sla r6
+ sla R6
+ sla (rr6)
+
+ slaw rr4
+ slaw RR4
+ slaw (rr4)
+
+;------------------------------
+
+ spp #5
+ srp #3
+ srp0 #3
+ srp1 #3
+
+;------------------------------
+
+ xch r2,r4
+
+dvar equ 1234h,data
+cvar label 2345h
+
+ assume dp:0
+; ld r0,dvar
+ ld r0,cvar
+ assume dp:1
+ ld r0,dvar
+; ld r0,cvar
+
+bit1 bit r5.1
+bit2 bit r6.!7
+bit3 bit bit1
+bit4 bit bit1+1
+
+ bld r0.0,bit3
+ bld r0.1,!bit3
+
diff --git a/tests/t_st9/t_st9.doc b/tests/t_st9/t_st9.doc
new file mode 100644
index 0000000..8068250
--- /dev/null
+++ b/tests/t_st9/t_st9.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application ST9 -----------------------------+
+| |
+| This is a (synthetic) test of the ST9's instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_st9/t_st9.ori b/tests/t_st9/t_st9.ori
new file mode 100755
index 0000000..b2bc395
--- /dev/null
+++ b/tests/t_st9/t_st9.ori
Binary files differ
diff --git a/tests/t_tms7/asflags b/tests/t_tms7/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_tms7/asflags
diff --git a/tests/t_tms7/t_tms7.asm b/tests/t_tms7/t_tms7.asm
new file mode 100755
index 0000000..efd4e0a
--- /dev/null
+++ b/tests/t_tms7/t_tms7.asm
@@ -0,0 +1,364 @@
+ cpu tms70c08
+
+ page 0
+
+ include reg7000
+
+; additional syntax options marked with ***
+
+ adc b,a
+ adc r10,a
+ adc r20,b
+ adc r30,r40
+ adc %20,a
+ adc #20,a ; ***
+ adc %30,b
+ adc #30,b ; ***
+ adc %40,r50
+ adc #40,r50 ; ***
+
+ add b,a
+ add r10,a
+ add r20,b
+ add r30,r40
+ add %20,a
+ add #20,a ; ***
+ add %30,b
+ add #30,b ; ***
+ add %40,r50
+ add #40,r50 ; ***
+
+ and b,a
+ and r10,a
+ and r20,b
+ and r30,r40
+ and %20,a
+ and #20,a ; ***
+ and %30,b
+ and #30,b ; ***
+ and %40,r50
+ and #40,r50 ; ***
+ andp a,p20
+ and a,p20 ; ***
+ andp b,p30
+ and b,p30 ; ***
+ andp #50,p40
+ and #50,p40 ; ***
+
+ btjo b,a,$
+ btjo r10,a,$
+ btjo r20,b,$
+ btjo r30,r40,$
+ btjo %20,a,$
+ btjo #20,a,$ ; ***
+ btjo %30,b,$
+ btjo #30,b,$ ; ***
+ btjo %40,r50,$
+ btjo #40,r50,$ ; ***
+ btjop a,p20,$
+ btjo a,p20,$ ; ***
+ btjop b,p30,$
+ btjo b,p30,$ ; ***
+ btjop #50,p40,$
+ btjo #50,p40,$ ; ***
+
+ btjz b,a,$
+ btjz r10,a,$
+ btjz r20,b,$
+ btjz r30,r40,$
+ btjz %20,a,$
+ btjz #20,a,$ ; ***
+ btjz %30,b,$
+ btjz #30,b,$ ; ***
+ btjz %40,r50,$
+ btjz #40,r50,$ ; ***
+ btjzp a,p20,$
+ btjz a,p20,$ ; ***
+ btjzp b,p30,$
+ btjz b,p30,$ ; ***
+ btjzp #50,p40,$
+ btjz #50,p40,$ ; ***
+
+ br @1234h
+ br 1234h ; ***
+ br @1234h(b)
+ br 1234h(b) ; ***
+ br *r30
+
+ call @1234h
+ call 1234h ; ***
+ call @1234h(b)
+ call 1234h(b) ; ***
+ call *r30
+
+ clr a
+ clr b
+ clr r10
+
+ clrc
+
+ cmp b,a
+ cmp r10,a
+ cmp r20,b
+ cmp r30,r40
+ cmp %20,a
+ cmp #20,a ; ***
+ cmp %30,b
+ cmp #30,b ; ***
+ cmp %40,r50
+ cmp #40,r50 ; ***
+ cmpa @1234h
+ cmpa 1234h ; ***
+ cmp @1234h,a ; ***
+ cmp 1234h,a ; ***
+ cmpa @1234h(b)
+ cmpa 1234h(b) ; ***
+ cmp @1234h(b),a ; ***
+ cmp 1234h(b),a ; ***
+ cmpa *r60
+ cmp *r60,a ; ***
+
+ dac b,a
+ dac r10,a
+ dac r20,b
+ dac r30,r40
+ dac %20,a
+ dac #20,a ; ***
+ dac %30,b
+ dac #30,b ; ***
+ dac %40,r50
+ dac #40,r50 ; ***
+
+ dec a
+ dec b
+ dec r10
+
+ decd a
+ decd b
+ decd r10
+
+ dint
+
+ djnz a,$
+ djnz b,$
+ djnz r10,$
+
+ dsb b,a
+ dsb r10,a
+ dsb r20,b
+ dsb r30,r40
+ dsb %20,a
+ dsb #20,a ; ***
+ dsb %30,b
+ dsb #30,b ; ***
+ dsb %40,r50
+ dsb #40,r50 ; ***
+
+ eint
+
+ idle
+
+ inc a
+ inc b
+ inc r10
+
+ inv a
+ inv b
+ inv r10
+
+ jmp $
+ jc $
+ jeq $
+ jhs $
+ jl $
+ jn $
+ jnc $
+ jne $
+ jnz $
+ jp $
+ jpz $
+ jz $
+
+ lda @1234h
+ lda 1234h ; ***
+ mov @1234h,a ; ***
+ mov 1234h,a ; ***
+ lda @1234h(b)
+ lda 1234h(b) ; ***
+ mov @1234h(b),a ; ***
+ mov 1234h(b),a ; ***
+ lda *r10
+ mov *r10,a ; ***
+
+ ldsp
+
+ mov a,b
+ mov a,r10
+ mov b,a
+ mov b,r20
+ mov r30,a
+ mov r40,b
+ mov r50,r60
+ mov %10,a
+ mov #10,a ; ***
+ mov %20,b
+ mov #20,b ; ***
+ mov %30,r70
+ mov #30,r70 ; ***
+
+ movd %1234h,r10
+ movd #1234h,r10 ; ***
+ movd %1234h(b),r20
+ movd #1234h(b),r20 ; ***
+ movd r30,r40
+
+ movw %1234h,r10 ; ***
+ movw #1234h,r10 ; ***
+ movw %1234h(b),r20 ; ***
+ movw #1234h(b),r20 ; ***
+ movw r30,r40 ; ***
+
+ movp a,p10
+ mov a,p10 ; ***
+ movp b,p20
+ mov b,p20 ; ***
+ movp %10,p30
+ movp #10,p30 ; ***
+ mov %10,p30 ; ***
+ mov #10,p30 ; ***
+ movp p40,a
+ mov p40,a ; ***
+ movp p50,b
+ mov p50,b ; ***
+
+ mpy b,a
+ mpy r10,a
+ mpy r20,b
+ mpy r30,r40
+ mpy %20,a
+ mpy #20,a ; ***
+ mpy %30,b
+ mpy #30,b ; ***
+ mpy %40,r50
+ mpy #40,r50 ; ***
+
+ nop
+
+ or b,a
+ or r10,a
+ or r20,b
+ or r30,r40
+ or %20,a
+ or #20,a ; ***
+ or %30,b
+ or #30,b ; ***
+ or %40,r50
+ or #40,r50 ; ***
+ orp a,p20
+ or a,p20 ; ***
+ orp b,p30
+ or b,p30 ; ***
+ orp #50,p40
+ or #50,p40 ; ***
+
+ pop a
+ pop b
+ pop r10
+ pop st
+
+ push a
+ push b
+ push r10
+ push st
+
+ reti
+ rti ; ***
+
+ rets
+ rts ; ***
+
+ rl a
+ rl b
+ rl r10
+
+ rlc a
+ rlc b
+ rlc r10
+
+ rr a
+ rr b
+ rr r10
+
+ rrc a
+ rrc b
+ rrc r10
+
+ sbb b,a
+ sbb r10,a
+ sbb r20,b
+ sbb r30,r40
+ sbb %20,a
+ sbb #20,a ; ***
+ sbb %30,b
+ sbb #30,b ; ***
+ sbb %40,r50
+ sbb #40,r50 ; ***
+
+ setc
+
+ sta @1234h
+ sta 1234h ; ***
+ mov a,@1234h ; ***
+ mov a,1234h ; ***
+ sta @1234h(b)
+ sta 1234h(b) ; ***
+ mov a,@1234h(b) ; ***
+ mov a,1234h(b) ; ***
+ sta *r10
+ mov a,*r10 ; ***
+
+ stsp
+
+ sub b,a
+ sub r10,a
+ sub r20,b
+ sub r30,r40
+ sub %20,a
+ sub #20,a ; ***
+ sub %30,b
+ sub #30,b ; ***
+ sub %40,r50
+ sub #40,r50 ; ***
+
+ swap a
+ swap b
+ swap r10
+
+ trap 0
+ trap 23
+
+ tsta
+ tst a ; ***
+ tstb
+ tst b ; ***
+
+ xchb a
+ xchb b ; ***
+ xchb r10
+
+ xor b,a
+ xor r10,a
+ xor r20,b
+ xor r30,r40
+ xor %20,a
+ xor #20,a ; ***
+ xor %30,b
+ xor #30,b ; ***
+ xor %40,r50
+ xor #40,r50 ; ***
+ xorp a,p20
+ xor a,p20 ; ***
+ xorp b,p30
+ xor b,p30 ; ***
+ xorp #50,p40
+ xor #50,p40 ; ***
diff --git a/tests/t_tms7/t_tms7.doc b/tests/t_tms7/t_tms7.doc
new file mode 100644
index 0000000..8729cc7
--- /dev/null
+++ b/tests/t_tms7/t_tms7.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application TMS7 ---------------------------+
+| |
+| This is a (synthetic) test of the TMS7000 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_tms7/t_tms7.ori b/tests/t_tms7/t_tms7.ori
new file mode 100755
index 0000000..c8d60c7
--- /dev/null
+++ b/tests/t_tms7/t_tms7.ori
Binary files differ
diff --git a/tests/t_xa/asflags b/tests/t_xa/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_xa/asflags
diff --git a/tests/t_xa/t_xa.asm b/tests/t_xa/t_xa.asm
new file mode 100644
index 0000000..68800d2
--- /dev/null
+++ b/tests/t_xa/t_xa.asm
@@ -0,0 +1,603 @@
+ cpu xag3
+
+ page 0
+
+ include stddefxa
+
+ segment io
+
+port1 ds.b 1
+port2 ds.b 1
+
+ segment code
+
+ supmode on
+
+regbit1 bit r3l.4
+regbit2 bit sp.5
+regbit3 bit r5h.5
+regbit4 bit sp.14
+membit1 bit 22h.5
+membit2 bit 50023h.5
+iobit1 bit port1.2
+regbit5 bit regbit4+1
+
+ add.b r4h,r1l
+ add.w r5,r3
+ add.b r5l,[r6]
+ add.w r4,[sp]
+ add.b [r6],r5l
+ add.w [sp],r4
+ add.b r3h,[r6+2]
+ add.w r4,[r3+100]
+ add.b [r6+2],r3h
+ add.w [r3+100],r4
+ add.b r3h,[r6+200]
+ add.w r4,[r3+1000]
+ add.b [r6+200],r3h
+ add.w [r3+1000],r4
+ add.b r4h,[r1+]
+ add.w r5,[r6+]
+ add.b [r1+],r4h
+ add.w [r6+],r5
+ add.b 200h,r2l
+ add.w 123h,r6
+ add.b r2l,200h
+ add.w r6,123h
+ add.b r5h,#34h
+ add.w r3,#1234h
+ add.b [r5],#34h
+ add.w [r3],#1234h
+ add.b [r5+],#34h
+ add.w [r3+],#1234h
+ add.b [r5+2],#34h
+ add.w [r3+100],#1234h
+ add.b [r5+200],#34h
+ add.w [r3+1000],#1234h
+ add.b 200h,#34h
+ add.w 123h,#1234h
+
+ addc.b r4h,r1l
+ addc.w r5,r3
+ addc.b r5l,[r6]
+ addc.w r4,[sp]
+ addc.b [r6],r5l
+ addc.w [sp],r4
+ addc.b r3h,[r6+2]
+ addc.w r4,[r3+100]
+ addc.b [r6+2],r3h
+ addc.w [r3+100],r4
+ addc.b r3h,[r6+200]
+ addc.w r4,[r3+1000]
+ addc.b [r6+200],r3h
+ addc.w [r3+1000],r4
+ addc.b r4h,[r1+]
+ addc.w r5,[r6+]
+ addc.b [r1+],r4h
+ addc.w [r6+],r5
+ addc.b 200h,r2l
+ addc.w 123h,r6
+ addc.b r2l,200h
+ addc.w r6,123h
+ addc.b r5h,#34h
+ addc.w r3,#1234h
+ addc.b [r5],#34h
+ addc.w [r3],#1234h
+ addc.b [r5+],#34h
+ addc.w [r3+],#1234h
+ addc.b [r5+2],#34h
+ addc.w [r3+100],#1234h
+ addc.b [r5+200],#34h
+ addc.w [r3+1000],#1234h
+ addc.b 200h,#34h
+ addc.w 123h,#1234h
+
+ adds.b r5h,#3
+ adds.w r6,#5
+ adds.b [r4],#3
+ adds.w [sp],#5
+ adds.b [r4+],#3
+ adds.w [sp+],#5
+ adds.b [r4+20],#3
+ adds.w [sp+20],#5
+ adds.b [r4-200],#3
+ adds.w [sp-200],#5
+ adds.b 200h,#3
+ adds.w 123h,#5
+
+ and.b r4h,r1l
+ and.w r5,r3
+ and.b r5l,[r6]
+ and.w r4,[sp]
+ and.b [r6],r5l
+ and.w [sp],r4
+ and.b r3h,[r6+2]
+ and.w r4,[r3+100]
+ and.b [r6+2],r3h
+ and.w [r3+100],r4
+ and.b r3h,[r6+200]
+ and.w r4,[r3+1000]
+ and.b [r6+200],r3h
+ and.w [r3+1000],r4
+ and.b r4h,[r1+]
+ and.w r5,[r6+]
+ and.b [r1+],r4h
+ and.w [r6+],r5
+ and.b 200h,r2l
+ and.w 123h,r6
+ and.b r2l,200h
+ and.w r6,123h
+ and.b r5h,#34h
+ and.w r3,#1234h
+ and.b [r5],#34h
+ and.w [r3],#1234h
+ and.b [r5+],#34h
+ and.w [r3+],#1234h
+ and.b [r5+2],#34h
+ and.w [r3+100],#1234h
+ and.b [r5+200],#34h
+ and.w [r3+1000],#1234h
+ and.b 200h,#34h
+ and.w 123h,#1234h
+
+ anl c,regbit1
+ anl c,/iobit1
+ anl c,r5.12
+ anl c,/r4h.1
+
+ asl.b r4h,r1l
+ asl.w r6,r3h
+ asl.d r2,r4l
+ asl.b r4h,#6
+ asl.w r6,#12
+ asl.d r2,#24
+
+ asr.b r4h,r1l
+ asr.w r6,r3h
+ asr.d r2,r4l
+ asr.b r4h,#6
+ asr.w r6,#12
+ asr.d r2,#24
+
+ bcc label1
+ nop
+ bcc label2
+ nop
+ bcs label1
+ beq label1
+ bg label1
+ bge label1
+ bgt label1
+ ble label1
+ blt label1
+ bmi label1
+ bne label1
+ bnv label1
+ bov label1
+ bpl label1
+ br label1
+
+ call label1
+ call label1
+ call [r4]
+
+ cjne r5l,123h,label1
+ cjne r6,456h,label1
+ cjne r5l,#34h,label1
+ cjne r6,#1234h,label1
+ cjne.b [r6],#34h,label1
+ cjne.w [r6],#1234h,label1
+
+label1: nop
+label2: nop
+
+ clr regbit1
+
+ cmp.b r4h,r1l
+ cmp.w r5,r3
+ cmp.b r5l,[r6]
+ cmp.w r4,[sp]
+ cmp.b [r6],r5l
+ cmp.w [sp],r4
+ cmp.b r3h,[r6+2]
+ cmp.w r4,[r3+100]
+ cmp.b [r6+2],r3h
+ cmp.w [r3+100],r4
+ cmp.b r3h,[r6+200]
+ cmp.w r4,[r3+1000]
+ cmp.b [r6+200],r3h
+ cmp.w [r3+1000],r4
+ cmp.b r4h,[r1+]
+ cmp.w r5,[r6+]
+ cmp.b [r1+],r4h
+ cmp.w [r6+],r5
+ cmp.b 200h,r2l
+ cmp.w 123h,r6
+ cmp.b r2l,200h
+ cmp.w r6,123h
+ cmp.b r5h,#34h
+ cmp.w r3,#1234h
+ cmp.b [r5],#34h
+ cmp.w [r3],#1234h
+ cmp.b [r5+],#34h
+ cmp.w [r3+],#1234h
+ cmp.b [r5+2],#34h
+ cmp.w [r3+100],#1234h
+ cmp.b [r5+200],#34h
+ cmp.w [r3+1000],#1234h
+ cmp.b 200h,#34h
+ cmp.w 123h,#1234h
+
+ cpl r4l
+ cpl sp
+
+ da r4l
+
+ div.w r4,r1h
+ div.w r5,#23
+ div.d r2,r5
+ div.d r6,#1234h
+
+ divu.b r4l,r5l
+ divu.b r4l,#23
+ divu.w r4,r1h
+ divu.w r5,#23
+ divu.d r2,r5
+ divu.d r6,#1234h
+
+d1: djnz r5l,d1
+d2: djnz.b 123h,d2
+d3: djnz r5,d3
+d4: djnz.w 123h,d4
+
+ fcall 123456h
+
+ fjmp 123456h
+
+ jb regbit1,d1
+ jbc regbit1,d2
+
+ jmp 1234h
+ jmp [r3]
+ jmp [a+dptr]
+ jmp [[r5+]]
+
+ jnb regbit1,d3
+
+ jnz d3
+
+ jz d3
+
+ lea r5,r4+4
+ lea r6,r1+1000
+
+ lsr.b r4h,r1l
+ lsr.w r6,r3h
+ lsr.d r2,r4l
+ lsr.b r4h,#6
+ lsr.w r6,#12
+ lsr.d r2,#24
+
+ mov c,regbit1
+ mov regbit1,c
+ mov usp,r4
+ mov sp,usp
+ mov.b r4h,r1l
+ mov.w r5,r3
+ mov.b r5l,[r6]
+ mov.w r4,[sp]
+ mov.b [r6],r5l
+ mov.w [sp],r4
+ mov.b r3h,[r6+2]
+ mov.w r4,[r3+100]
+ mov.b [r6+2],r3h
+ mov.w [r3+100],r4
+ mov.b r3h,[r6+200]
+ mov.w r4,[r3+1000]
+ mov.b [r6+200],r3h
+ mov.w [r3+1000],r4
+ mov.b r4h,[r1+]
+ mov.w r5,[r6+]
+ mov.b [r1+],r4h
+ mov.w [r6+],r5
+ mov.b [r3+],[r4+]
+ mov.w [r3+],[r4+]
+ mov.b 200h,r2l
+ mov.w 123h,r6
+ mov.b r2l,200h
+ mov.w r6,123h
+ mov.b 123h,[r5]
+ mov.w 456h,[sp]
+ mov.b [r5],123h
+ mov.w [sp],456h
+ mov.b r5h,#34h
+ mov.w r3,#1234h
+ mov.b [r5],#34h
+ mov.w [r3],#1234h
+ mov.b [r5+],#34h
+ mov.w [r3+],#1234h
+ mov.b [r5+2],#34h
+ mov.w [r3+100],#1234h
+ mov.b [r5+200],#34h
+ mov.w [r3+1000],#1234h
+ mov.b 200h,#34h
+ mov.w 123h,#1234h
+ mov.b 123h,200h
+ mov.w 123h,200h
+
+ movc r4l,[r5+]
+ movc r4,[r5+]
+ movc a,[a+dptr]
+ movc a,[a+pc]
+
+ movs.b r5h,#3
+ movs.w r6,#5
+ movs.b [r4],#3
+ movs.w [sp],#5
+ movs.b [r4+],#3
+ movs.w [sp+],#5
+ movs.b [r4+20],#3
+ movs.w [sp+20],#5
+ movs.b [r4-200],#3
+ movs.w [sp-200],#5
+ movs.b 200h,#3
+ movs.w 123h,#5
+
+ movx r3l,[r6]
+ movx r3,[sp]
+ movx [r6],r3l
+ movx [sp],r3
+
+ mul r0,r5
+ mul r6,#1234h
+
+ mulu r3l,r4h
+ mulu r5l,#100
+ mulu r0,r5
+ mulu r6,#1234h
+
+ neg r4l
+ neg sp
+
+ nop
+
+ norm.b r4h,r1l
+ norm.w r6,r3h
+ norm.d r2,r4l
+
+ or.b r4h,r1l
+ or.w r5,r3
+ or.b r5l,[r6]
+ or.w r4,[sp]
+ or.b [r6],r5l
+ or.w [sp],r4
+ or.b r3h,[r6+2]
+ or.w r4,[r3+100]
+ or.b [r6+2],r3h
+ or.w [r3+100],r4
+ or.b r3h,[r6+200]
+ or.w r4,[r3+1000]
+ or.b [r6+200],r3h
+ or.w [r3+1000],r4
+ or.b r4h,[r1+]
+ or.w r5,[r6+]
+ or.b [r1+],r4h
+ or.w [r6+],r5
+ or.b 200h,r2l
+ or.w 123h,r6
+ or.b r2l,200h
+ or.w r6,123h
+ or.b r5h,#34h
+ or.w r3,#1234h
+ or.b [r5],#34h
+ or.w [r3],#1234h
+ or.b [r5+],#34h
+ or.w [r3+],#1234h
+ or.b [r5+2],#34h
+ or.w [r3+100],#1234h
+ or.b [r5+200],#34h
+ or.w [r3+1000],#1234h
+ or.b 200h,#34h
+ or.w 123h,#1234h
+
+ orl c,regbit1
+ orl c,/iobit1
+ orl c,r5.12
+ orl c,/r4h.1
+
+ pop.b 123h
+ pop.w 200h
+ pop r2l
+ pop r2l,r3l
+ pop r4h
+ pop r4h,r5h
+ pop r2l,r3l,r4h,r5h
+ pop r1
+ pop r2,r5;,sp
+
+ popu.b 123h
+ popu.w 200h
+ popu r2l
+ popu r2l,r3l
+ popu r4h
+ popu r4h,r5h
+ popu r2l,r3l,r4h,r5h
+ popu r1
+ popu r2,r5,sp
+
+ push.b 123h
+ push.w 200h
+ push r2l
+ push r2l,r3l
+ push r4h
+ push r4h,r5h
+ push r2l,r3l,r4h,r5h
+ push r1
+ push r2,r5,sp
+
+ pushu.b 123h
+ pushu.w 200h
+ pushu r2l
+ pushu r2l,r3l
+ pushu r4h
+ pushu r4h,r5h
+ pushu r2l,r3l,r4h,r5h
+ pushu r1
+ pushu r2,r5,sp
+
+ reset
+
+ ret
+
+ reti
+
+ rl r3h,#3
+ rl r5,#12
+
+ rlc r3h,#3
+ rlc r5,#12
+
+ rr r3h,#3
+ rr r5,#12
+
+ rrc r3h,#3
+ rrc r5,#12
+
+ setb regbit1
+
+ sext r1l
+ sext r2
+
+ sub.b r4h,r1l
+ sub.w r5,r3
+ sub.b r5l,[r6]
+ sub.w r4,[sp]
+ sub.b [r6],r5l
+ sub.w [sp],r4
+ sub.b r3h,[r6+2]
+ sub.w r4,[r3+100]
+ sub.b [r6+2],r3h
+ sub.w [r3+100],r4
+ sub.b r3h,[r6+200]
+ sub.w r4,[r3+1000]
+ sub.b [r6+200],r3h
+ sub.w [r3+1000],r4
+ sub.b r4h,[r1+]
+ sub.w r5,[r6+]
+ sub.b [r1+],r4h
+ sub.w [r6+],r5
+ sub.b 200h,r2l
+ sub.w 123h,r6
+ sub.b r2l,200h
+ sub.w r6,123h
+ sub.b r5h,#34h
+ sub.w r3,#1234h
+ sub.b [r5],#34h
+ sub.w [r3],#1234h
+ sub.b [r5+],#34h
+ sub.w [r3+],#1234h
+ sub.b [r5+2],#34h
+ sub.w [r3+100],#1234h
+ sub.b [r5+200],#34h
+ sub.w [r3+1000],#1234h
+ sub.b 200h,#34h
+ sub.w 123h,#1234h
+
+ subb.b r4h,r1l
+ subb.w r5,r3
+ subb.b r5l,[r6]
+ subb.w r4,[sp]
+ subb.b [r6],r5l
+ subb.w [sp],r4
+ subb.b r3h,[r6+2]
+ subb.w r4,[r3+100]
+ subb.b [r6+2],r3h
+ subb.w [r3+100],r4
+ subb.b r3h,[r6+200]
+ subb.w r4,[r3+1000]
+ subb.b [r6+200],r3h
+ subb.w [r3+1000],r4
+ subb.b r4h,[r1+]
+ subb.w r5,[r6+]
+ subb.b [r1+],r4h
+ subb.w [r6+],r5
+ subb.b 200h,r2l
+ subb.w 123h,r6
+ subb.b r2l,200h
+ subb.w r6,123h
+ subb.b r5h,#34h
+ subb.w r3,#1234h
+ subb.b [r5],#34h
+ subb.w [r3],#1234h
+ subb.b [r5+],#34h
+ subb.w [r3+],#1234h
+ subb.b [r5+2],#34h
+ subb.w [r3+100],#1234h
+ subb.b [r5+200],#34h
+ subb.w [r3+1000],#1234h
+ subb.b 200h,#34h
+ subb.w 123h,#1234h
+
+ trap #5
+
+ xch r3h,r5l
+ xch r5l,r3h
+ xch r3,r5
+ xch r5,r3
+ xch r3h,[r5]
+ xch [r5],r3h
+ xch r3,[r5]
+ xch [r5],r3
+ xch r3h,123h
+ xch 123h,r3h
+ xch r3,200h
+ xch 200h,r3
+
+ xor.b r4h,r1l
+ xor.w r5,r3
+ xor.b r5l,[r6]
+ xor.w r4,[sp]
+ xor.b [r6],r5l
+ xor.w [sp],r4
+ xor.b r3h,[r6+2]
+ xor.w r4,[r3+100]
+ xor.b [r6+2],r3h
+ xor.w [r3+100],r4
+ xor.b r3h,[r6+200]
+ xor.w r4,[r3+1000]
+ xor.b [r6+200],r3h
+ xor.w [r3+1000],r4
+ xor.b r4h,[r1+]
+ xor.w r5,[r6+]
+ xor.b [r1+],r4h
+ xor.w [r6+],r5
+ xor.b 200h,r2l
+ xor.w 123h,r6
+ xor.b r2l,200h
+ xor.w r6,123h
+ xor.b r5h,#34h
+ xor.w r3,#1234h
+ xor.b [r5],#34h
+ xor.w [r3],#1234h
+ xor.b [r5+],#34h
+ xor.w [r3+],#1234h
+ xor.b [r5+2],#34h
+ xor.w [r3+100],#1234h
+ xor.b [r5+200],#34h
+ xor.w [r3+1000],#1234h
+ xor.b 200h,#34h
+ xor.w 123h,#1234h
+
+ mov.b [r5+],[r5+]
+ xch r4l,r4l
+ pop r7
+ norm.b r4l,r4l
+ norm.w r4,r4h
+ norm.d r4,r5l
+ mov [r4+],r4l
+ mov r4h,[r4+]
+ movc r4h,[r4+]
+ add [r4+],r4l
+ add r4h,[r4+]
+ mov r5,[r5+]
+
diff --git a/tests/t_xa/t_xa.doc b/tests/t_xa/t_xa.doc
new file mode 100644
index 0000000..3a7edf8
--- /dev/null
+++ b/tests/t_xa/t_xa.doc
@@ -0,0 +1,5 @@
++--------------------------- Test Application XA ----------------------------+
+| |
+| This is a (synthetic) test of the Philips XA instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_xa/t_xa.ori b/tests/t_xa/t_xa.ori
new file mode 100644
index 0000000..edfa696
--- /dev/null
+++ b/tests/t_xa/t_xa.ori
Binary files differ
diff --git a/tests/t_z380/asflags b/tests/t_z380/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_z380/asflags
diff --git a/tests/t_z380/t_z380.asm b/tests/t_z380/t_z380.asm
new file mode 100644
index 0000000..a681044
--- /dev/null
+++ b/tests/t_z380/t_z380.asm
@@ -0,0 +1,677 @@
+ cpu z380
+ include regz380
+
+ extmode on
+
+ page 0
+ relaxed on
+
+ ddir w
+ ddir ib,w
+ ddir iw,w
+ ddir ib
+ ddir lw
+ ddir ib,lw
+ ddir iw,lw
+ ddir iw
+
+ cpl
+ cpl a
+ neg
+ neg a
+
+ ei
+ ei $40
+ di
+ di $bf
+
+ btest
+ exall
+ exxx
+ exxy
+ indw
+ indrw
+ iniw
+ inirw
+ lddw
+ lddrw
+ ldiw
+ ldirw
+ mtest
+ otdrw
+ otirw
+ outdw
+ outiw
+ retb
+
+ cplw
+ cplw hl
+ negw
+ negw hl
+
+ ret
+ ret nz
+ ret z
+ ret nc
+ ret c
+ ret po
+ ret nv
+ ret pe
+ ret v
+ ret p
+ ret ns
+ ret m
+ ret s
+
+ jp 1234h
+ jp 123456h
+ ddir ib
+ jp 123456h
+ ddir iw
+ jp 123456h
+ ddir w
+ jp 123456h
+ ddir lw
+ jp 123456h
+ ddir w,iw
+ jp 123456h
+ jp 12345678h
+ ddir lw
+ jp 12345678h
+ jp z,4321h
+ jp nc,654321h
+ jp pe,87654321h
+ jp (hl)
+ jp (ix)
+ jp (iy)
+
+ call $1234
+ call $123456
+ call $12345678
+ call nz,$4321
+ call m,$654321
+ call po,$87654321
+
+ jr $+20
+ jr c,$-20
+ jr $-200
+ jr z,$+200
+ jr $+$200000
+ jr nc,$-$200000
+
+ calr $+20
+ calr c,$-20
+ calr $-200
+ calr z,$+200
+ calr $+$200000
+ calr nc,$-$200000
+
+ djnz $+20
+ djnz $-200
+ djnz $+$200000
+
+ exts a
+ exts
+ extsw hl
+ extsw
+
+ and a
+ and a,b
+ and a,c
+ and a,d
+ and a,e
+ and a,h
+ and a,l
+ and a,ixl
+ and a,ixu
+ and a,iyl
+ and a,iyu
+ and a,$55
+ and a,(hl)
+ and a,(ix+20)
+ and a,(iy-300)
+ and a,(ix+100000)
+
+ andw ix
+ andw hl,ix
+ andw hl,iy
+ andw hl,bc
+ andw hl,de
+ andw hl,hl
+ andw hl,(ix+5)
+ andw hl,(iy-200)
+ andw hl,55aah
+
+ cp a
+ cp a,b
+ cp a,c
+ cp a,d
+ cp a,e
+ cp a,h
+ cp a,l
+ cp a,ixl
+ cp a,ixu
+ cp a,iyl
+ cp a,iyu
+ cp a,$34
+ cp a,(hl)
+ cp a,(ix-20)
+ cp a,(iy+$300)
+ cp a,(ix+100000h)
+
+ cpw ix
+ cpw hl,ix
+ cpw hl,iy
+ cpw hl,bc
+ cpw hl,de
+ cpw hl,hl
+ cpw hl,(ix+17)
+ cpw hl,(iy-200)
+ cpw hl,$aa55
+
+ or a
+ or a,b
+ or a,c
+ or a,d
+ or a,e
+ or a,h
+ or a,l
+ or a,ixl
+ or a,ixu
+ or a,iyl
+ or a,iyu
+ or a,$34
+ or a,(hl)
+ or a,(ix-20)
+ or a,(iy+$300)
+ or a,(ix+100000h)
+
+ orw ix
+ orw hl,ix
+ orw hl,iy
+ orw hl,bc
+ orw hl,de
+ orw hl,hl
+ orw hl,(ix+17)
+ orw hl,(iy-200)
+ orw hl,$aa55
+
+ xor a
+ xor a,b
+ xor a,c
+ xor a,d
+ xor a,e
+ xor a,h
+ xor a,l
+ xor a,ixl
+ xor a,ixu
+ xor a,iyl
+ xor a,iyu
+ xor a,$34
+ xor a,(hl)
+ xor a,(ix-20)
+ xor a,(iy+$300)
+ xor a,(ix+100000h)
+
+ xorw ix
+ xorw hl,ix
+ xorw hl,iy
+ xorw hl,bc
+ xorw hl,de
+ xorw hl,hl
+ xorw hl,(ix+17)
+ xorw hl,(iy-200)
+ xorw hl,$aa55
+
+ sub a
+ sub a,b
+ sub a,c
+ sub a,d
+ sub a,e
+ sub a,h
+ sub a,l
+ sub a,ixl
+ sub a,ixu
+ sub a,iyl
+ sub a,iyu
+ sub a,$34
+ sub a,(hl)
+ sub a,(ix-20)
+ sub a,(iy+$300)
+ sub a,(ix+100000h)
+
+ sub hl,(1234h)
+ sub hl,(123456h)
+ sub hl,(12345678h)
+ sub sp,3412o
+
+ subw ix
+ subw hl,ix
+ subw hl,iy
+ subw hl,bc
+ subw hl,de
+ subw hl,hl
+ subw hl,(ix+17)
+ subw hl,(iy-200)
+ subw hl,$aa55
+
+ add a,b
+ add a,iyu
+ add a,' '
+ add a,(hl)
+ add a,(ix+10)
+ add a,(ix+1000)
+ add hl,bc
+ add ix,de
+ add iy,iy
+ add ix,sp
+ add hl,(12345678h)
+ add sp,3412o
+
+ addw bc
+ addw hl,hl
+ addw hl,iy
+ addw hl,2314h
+ addw hl,(ix+128)
+
+ adc a,h
+ adc a,ixu
+ adc a,20
+ adc a,(hl)
+ adc a,(ix-500)
+ adc hl,sp
+
+ adcw hl,bc
+ adcw hl,iy
+ adcw hl,$abcd
+ adcw hl,(iy-30)
+
+ sbc a,d
+ sbc a,iyl
+ sbc a,20h
+ sbc a,(hl)
+ sbc a,(ix+500)
+ sbc hl,sp
+
+ sbcw hl,bc
+ sbcw hl,iy
+ sbcw hl,$abcd
+ sbcw hl,(iy-30)
+
+ dec a
+ dec (hl)
+ dec ixu
+ dec (ix+35)
+
+ decw de
+ dec iy
+
+ inc a
+ inc (hl)
+ inc ixu
+ inc (ix+35)
+
+ incw de
+ inc iy
+
+ rl d
+ rl (hl)
+ rl (ix+200)
+ rlw ix
+ rlw iy
+ rlw de
+ rlw hl
+ rlw (hl)
+ rlw (iy+$100000)
+
+ rlc d
+ rlc (hl)
+ rlc (ix+200)
+ rlcw ix
+ rlcw iy
+ rlcw de
+ rlcw hl
+ rlcw (hl)
+ rlcw (iy+$100000)
+
+ rr d
+ rr (hl)
+ rr (ix+200)
+ rrw ix
+ rrw iy
+ rrw de
+ rrw hl
+ rrw (hl)
+ rrw (iy+$100000)
+
+ rrc d
+ rrc (hl)
+ rrc (ix+200)
+ rrcw ix
+ rrcw iy
+ rrcw de
+ rrcw hl
+ rrcw (hl)
+ rrcw (iy+$100000)
+
+ sla d
+ sla (hl)
+ sla (ix+200)
+ slaw ix
+ slaw iy
+ slaw de
+ slaw hl
+ slaw (hl)
+ slaw (iy+$100000)
+
+ sra d
+ sra (hl)
+ sra (ix+200)
+ sraw ix
+ sraw iy
+ sraw de
+ sraw hl
+ sraw (hl)
+ sraw (iy+$100000)
+
+ srl d
+ srl (hl)
+ srl (ix+200)
+ srlw ix
+ srlw iy
+ srlw de
+ srlw hl
+ srlw (hl)
+ srlw (iy+$100000)
+
+ bit 5,a
+ bit 6,(hl)
+ bit 3,(ix+67)
+
+ res 5,a
+ res 6,(hl)
+ res 3,(ix+67)
+
+ set 5,a
+ set 6,(hl)
+ set 3,(ix+67)
+
+ mlt bc
+ mlt hl
+ mlt sp
+
+ ld a,c
+ ld a,h
+ ld a,iyu
+ ld a,ixl
+ ld a,(hl)
+ ld a,(ix+20)
+ ld a,(iy-300)
+ ld a,(bc)
+ ld a,(de)
+ ld a,'A'
+ ld a,(2000h)
+ ld a,(10000h)
+ ld a,r
+ ld a,i
+ ld d,a
+ ld d,e
+ ld d,ixl
+ ld d,(hl)
+ ld d,(iy+15)
+ ld d,'D'
+ ld ixl,a
+ ld iyu,'I'
+ ld iyl,iyu
+ ld ixu,ixl
+ ld ixl,e
+ ld (hl),a
+ ld (hl),c
+ ld (ix+100),a
+ ld (iy-200),d
+ ld (hl),'H'
+ ld (ix),'X'
+ ld (hl),hl
+ ld (hl),de
+ ld (hl),bc
+ ld (hl),ix
+ ld (hl),iy
+ ld (ix),hl
+ ld (ix),de
+ ld (ix),bc
+ ld (iy),hl
+ ld (iy),de
+ ld (iy),bc
+ ld (iy),ix
+ ld (ix+123456h),iy
+ ld sp,hl
+ ld sp,iy
+ ddir lw
+ ld sp,123456h
+ ld sp,(6)
+ ld bc,(hl)
+ ld de,(hl)
+ ld hl,(hl)
+ ld bc,(ix)
+ ld de,(ix)
+ ld hl,(ix)
+ ld bc,(iy)
+ ld de,(iy)
+ ld hl,(iy)
+ ld bc,hl
+ ld de,bc
+ ld de,ix
+ ld hl,iy
+ ld de,(bc)
+ ld hl,(de)
+ ld hl,2000h
+ ddir lw
+ ld hl,12345687h
+ ld hl,(2000h)
+ ld de,(20000h)
+ ld hl,(sp+5)
+ ld de,(sp-200)
+ ld ix,(hl)
+ ld iy,(hl)
+ ld ix,(iy)
+ ld iy,(ix)
+ ld iy,hl
+ ld ix,bc
+ ld ix,iy
+ ld iy,ix
+ ld ix,(bc)
+ ld iy,(de)
+ ddir lw
+ ld ix,123456h
+ ld iy,0
+ ld ix,(2000h)
+ ld iy,(87654321h)
+ ld ix,(sp)
+ ld (bc),a
+ ld (de),a
+ ld (bc),de
+ ld (de),hl
+ ld (de),iy
+ ld ($20001),a
+ ld (123456h),hl
+ ld (123456h),ix
+ ld (123456h),de
+ ld (123456h),sp
+ ld i,a
+ ld i,hl
+ ld r,a
+ ld hl,i
+ ld (sp),de
+ ld (sp),ix
+ ld (hl),10
+ ldw (hl),1000
+ ddir lw
+ ldw (hl),100000
+ ldw (bc),30
+ ldw (de),40
+
+ pop af
+ pop sr
+ pop bc
+ pop de
+ pop hl
+ pop ix
+ pop iy
+ push af
+ push sr
+ push 300
+ push bc
+ push de
+ push hl
+ push ix
+ push iy
+
+ ex af,af'
+ ex (sp),hl
+ ex hl,(sp)
+ ex (sp),ix
+ ex ix,(sp)
+ ex (sp),iy
+ ex iy,(sp)
+ ex de,hl
+ ex hl,de
+ ex a,a'
+ ex c,c'
+ ex a,h
+ ex d,a
+ ex a,(hl)
+ ex (hl),a
+ ex bc,de
+ ex bc,hl
+ ex bc,ix
+ ex bc,iy
+ ex de,bc
+ ex de,hl
+ ex de,ix
+ ex de,iy
+ ex hl,bc
+ ex hl,de
+ ex hl,ix
+ ex hl,iy
+ ex ix,bc
+ ex ix,de
+ ex ix,hl
+ ex ix,iy
+ ex iy,bc
+ ex iy,de
+ ex iy,hl
+ ex iy,ix
+ ex bc,bc'
+ ex de,de'
+ ex hl,hl'
+ ex ix,ix'
+ ex iy,iy'
+
+ im 0
+ im 1
+ im 2
+ im 3
+
+ in a,(12h)
+ out (12h),a
+ in c,(c)
+ out (c),c
+ out (c),12h
+
+ inw bc,(c)
+ outw (c),bc
+ inw de,(c)
+ outw (c),de
+ inw hl,(c)
+ outw (c),hl
+ outw (c),$2002
+
+ in0 d,(20h)
+ in0 (20h)
+ out0 (20h),e
+
+ ina a,(12h)
+ inaw hl,(1234h)
+ outa (123456h),a
+ outaw (12345678h),hl
+
+ tstio 1<<7
+
+ tst a
+ tst (hl)
+ tst 33h
+
+ divuw (ix+5)
+ multw hl,(iy-3)
+ multuw hl,(iy+100)
+ divuw hl,bc
+ multw hl,de
+ multuw hl,hl
+ divuw hl,ix
+ multw hl,iy
+ multuw hl,ix
+ divuw hl,10
+ multw hl,100
+ multuw hl,1000
+
+ ldctl sr,a
+ ldctl xsr,a
+ ldctl a,xsr
+ ldctl dsr,a
+ ldctl a,dsr
+ ldctl ysr,a
+ ldctl a,ysr
+ ldctl sr,20h
+ ldctl xsr,31h
+ ldctl dsr,42h
+ ldctl ysr,53h
+ ldctl sr,hl
+ ldctl hl,sr
+
+ resc lw
+ setc lw
+ resc lck
+ setc lck
+ setc xm
+
+ swap bc
+ swap de
+ swap hl
+ swap ix
+ swap iy
+
+ out (c),0
+
+ cpu z80undoc
+
+ slia d
+ slia (ix+5)
+ slia (hl)
+ slia a
+ inc ixl
+ inc iyu
+ dec ixu
+ dec iyl
+ ld iyl,'a'
+ ld b,ixl
+ ld ixu,c
+ ld iyl,iyu
+ add a,ixl
+ adc a,ixu
+ sub a,iyl
+ sbc a,iyu
+ and a,ixl
+ xor a,ixu
+ or a,iyl
+ cp a,iyu
+ rlc (ix+3)
+ rrc b,(iy-3)
+ slia a,(ix-100)
+ res 5,h
+ set 6,(ix+6)
+ bit 3,(hl)
+ res c,4,(ix-1)
+ set l,6,(iy+17)
+ out (c),0
+ in (c)
+ tsti
diff --git a/tests/t_z380/t_z380.doc b/tests/t_z380/t_z380.doc
new file mode 100644
index 0000000..b9b1af3
--- /dev/null
+++ b/tests/t_z380/t_z380.doc
@@ -0,0 +1,5 @@
++------------------------- Test Application Z380 ----------------------------+
+| |
+| This is a (synthetic) test of the Z80/Z380/Z80UNDOC instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_z380/t_z380.ori b/tests/t_z380/t_z380.ori
new file mode 100644
index 0000000..83a5d92
--- /dev/null
+++ b/tests/t_z380/t_z380.ori
Binary files differ
diff --git a/tests/t_z8/asflags b/tests/t_z8/asflags
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/t_z8/asflags
diff --git a/tests/t_z8/t_z8.asm b/tests/t_z8/t_z8.asm
new file mode 100644
index 0000000..a2f46c7
--- /dev/null
+++ b/tests/t_z8/t_z8.asm
@@ -0,0 +1,116 @@
+ cpu z8601
+
+ ccf
+ rcf
+ scf
+
+ di
+ ei
+
+ halt
+ stop
+
+ wdh
+ wdt
+
+ iret
+ ret
+
+ nop
+
+ and r7,r13
+ and r5,vari
+ and vari,r4
+
+ and r3,@r14
+ and r2,@vari
+ and vari,@r6
+
+ and r3,#5
+ and vari,#77
+ and @r9,#35h
+ and @vari,#10011b
+
+ add 2,5
+ adc r5,#4
+ sub @r0,#20
+ sbc r7,vari
+ or vari,@r5
+ tcm r0,@r8
+ tm @vari,#00001000b
+ cp vari,#20
+ xor r5,#255
+
+ inc r5
+ inc @r12
+ inc vari
+
+ dec r6
+ dec vari
+ dec @r5
+ dec @vari
+ decw rr6
+ decw vari
+ decw @r5
+ decw @vari
+ decw @r5
+
+test1: jr test1
+ jr f,test1
+ jr uge,test1
+
+ djnz r5,test1
+
+ call test1
+ call @vari
+ call @rr10
+
+ jp test1
+ jp c,test1
+ jp @vari
+ jp @rr6
+
+
+ ld r3,r4
+ ld r5,vari
+ ld r6,@r7
+ ld r8,@vari
+ ld r9,vari(r10)
+ ld r11,#45
+
+ ld vari,r12
+ ld vari,vari
+ ld vari,@r13
+ ld vari,@vari
+ ld vari,#67
+
+ ld @r14,r15
+ ld @r0,vari
+ ld @r1,#89
+
+ ld @vari,r2
+ ld @vari,vari
+ ld @vari,#01
+
+ ld vari(r3),r4
+
+
+ ldc r5,@rr6
+ ldc @rr8,r7
+ lde r9,@rr10
+ lde @rr12,r11
+
+ ldci @r13,@rr14
+ ldci @rr0,@r15
+ ldei @r1,@rr2
+ ldei @rr4,@r3
+
+
+ srp #0
+
+
+ segment data
+
+ org 0aah
+vari:
+
diff --git a/tests/t_z8/t_z8.doc b/tests/t_z8/t_z8.doc
new file mode 100644
index 0000000..c6cc2b5
--- /dev/null
+++ b/tests/t_z8/t_z8.doc
@@ -0,0 +1,5 @@
++-------------------------- Test Application Z8 -----------------------------+
+| |
+| This is a (synthetic) test of the Z8 instruction set |
+| |
++----------------------------------------------------------------------------+
diff --git a/tests/t_z8/t_z8.ori b/tests/t_z8/t_z8.ori
new file mode 100644
index 0000000..ffe9e81
--- /dev/null
+++ b/tests/t_z8/t_z8.ori
Binary files differ
diff --git a/tests/testall b/tests/testall
new file mode 100755
index 0000000..15bb2d1
--- /dev/null
+++ b/tests/testall
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+echo executing self tests...
+echo "=================================================================" > ../testlog
+echo "Summaric results:" >> ../testlog
+SUMPASS="0"
+SUMFAIL="0"
+if [ "$1" = "" ]; then
+ SUBDIRS=t_*
+else
+ SUBDIRS="$1"
+fi
+for t in $SUBDIRS; do
+ cd $t
+ cat $t.doc
+ ../../asl `cat asflags` -i ../../include $t.asm | tee $t.log
+ ../../p2bin -k -l 0 -r 0x-0x $t
+ echo +---------------------------------------------------------------+
+ if cmp $t.ori $t.bin; then
+ echo "Test $t succeeded!"
+ SUMPASS=`expr $SUMPASS + 1`
+ echo "$t : OK" >> ../../testlog
+ else
+ echo "Test $t failed!"
+ SUMFAIL=`expr $SUMFAIL + 1`
+ echo "$t : failed" >> ../../testlog
+ fi
+ grep assembly $t.log >> ../../testlog
+ grep Assemblierzeit $t.log >> ../../testlog
+ echo +---------------------------------------------------------------+
+ rm -f $t.bin
+ rm -f $t.log
+ rm -f $t.h
+ cd ..
+done
+echo "successes: $SUMPASS" >> ../testlog
+echo "failures : $SUMFAIL" >> ../testlog
+cat ../testlog
diff --git a/tests/testall.bat b/tests/testall.bat
new file mode 100644
index 0000000..8d81cc8
--- /dev/null
+++ b/tests/testall.bat
@@ -0,0 +1,117 @@
+@echo off
+if "%1"=="" goto main
+
+cd %1
+type %1.doc | ..\..\addcr
+set ASCMD=@asflags
+..\..\asl -i ..\..\include -L +t 31 %1.asm
+set ASCMD=
+..\..\p2bin -k -l 0 -r $-$ %1
+..\..\bincmp %1.bin %1.ori
+if errorlevel 1 goto errcond
+echo Test %1 succeeded!
+set SUMPASS=%SUMPASS%!
+echo %1 : OK >> ..\..\testlog
+:goon
+echo +---------------------------------------------------------------+
+type %1.lst | find "assembly" >> ..\..\testlog
+type %1.lst | find "Assemblierzeit" >> ..\..\testlog
+if exist %1.lst del %1.lst >nul
+if exist %1.inc del %1.inc >nul
+if exist %1.bin del %1.bin >nul
+cd ..
+goto end
+
+:errcond
+echo Test %1 failed!
+set SUMFAIL=%SUMFAIL%-
+echo %1 : failed >> ..\..\testlog
+goto goon
+
+:main
+if exist ..\addcr.exe goto nocomp
+bcc -e..\addcr.exe -ml ..\addcr.c
+del addcr.obj
+:nocomp
+if exist ..\bincmp.exe goto nocomp2
+bcc -e..\bincmp.exe -ml ..\bincmp.c
+del bincmp.obj
+:nocomp2
+echo executing self tests...
+echo ================================================================= >..\testlog
+echo Summaric results: >> ..\testlog
+set SUMPASS=
+set SUMFAIL=
+call testall t_166
+call testall t_16c5x
+call testall t_16c84
+call testall t_17c42
+call testall t_251
+call testall t_296
+call testall t_29k
+call testall t_32
+call testall t_3201x
+call testall t_3203x
+call testall t_3205x
+call testall t_3206x
+call testall t_370
+call testall t_4004
+call testall t_403
+call testall t_4500
+call testall t_47c00
+call testall t_48
+call testall t_56000
+call testall t_56300
+call testall t_65
+call testall t_6502u
+call testall t_6804
+call testall t_68040
+call testall t_6805
+call testall t_6808
+call testall t_6812
+call testall t_6816
+call testall t_7000
+call testall t_75k0
+call testall t_7700
+call testall t_7720
+call testall t_77230
+call testall t_7725
+call testall t_78c1x
+call testall t_78k0
+call testall t_85
+call testall t_87c800
+call testall t_8X30x
+call testall t_96
+call testall t_960
+call testall t_97c241
+call testall t_9900
+call testall t_ace
+call testall t_avr
+call testall t_bas52
+call testall t_buf32
+call testall t_cop8
+call testall t_f2mc8l
+call testall t_fl90
+call testall t_fl900
+call testall t_full09
+call testall t_h8_3
+call testall t_h8_5
+call testall t_m16c
+call testall t_mcore
+call testall t_mic51
+call testall t_msp
+call testall t_parsys
+call testall t_scmp
+call testall t_secdri
+call testall t_st6
+call testall t_st7
+call testall t_st9
+call testall t_tms7
+call testall t_xa
+call testall t_z380
+call testall t_z8
+echo successes: %SUMPASS% >> ..\testlog
+echo failures: %SUMFAIL% >> ..\testlog
+type ..\testlog
+
+:end
diff --git a/tests/testall.cmd b/tests/testall.cmd
new file mode 100644
index 0000000..667dc39
--- /dev/null
+++ b/tests/testall.cmd
@@ -0,0 +1,117 @@
+@echo off
+if "%1"=="" goto main
+
+cd %1
+type %1.doc | ..\..\addcr
+set ASCMD=@asflags
+..\..\asl -i ..\..\include -L +t 31 %1.asm
+set ASCMD=
+..\..\p2bin -k -l 0 -r $-$ %1
+..\..\bincmp %1.bin %1.ori
+if errorlevel 1 goto errcond
+echo Test %1 succeeded!
+set SUMPASS=%SUMPASS%+
+echo %1 : OK >> ..\..\testlog
+:goon
+echo +---------------------------------------------------------------+
+type %1.lst | find "assembly" >> ..\..\testlog
+type %1.lst | find "Assemblierzeit" >> ..\..\testlog
+if exist %1.lst del %1.lst >nul
+if exist %1.inc del %1.inc >nul
+if exist %1.bin del %1.bin >nul
+cd ..
+goto end
+
+:errcond
+echo Test %1 failed!
+set SUMFAIL=%SUMFAIL%-
+echo %1 : failed >> ..\..\testlog
+goto goon
+
+:main
+if exist ..\addcr.exe goto nocomp
+echo Compiling 'addcr'...
+gcc -o ..\addcr.exe ..\addcr.c
+:nocomp
+if exist ..\bincmp.exe goto nocomp2
+echo Compiling 'bincmp'...
+gcc -o ..\bincmp.exe ..\bincmp.c
+:nocomp2
+echo executing self tests...
+echo "=================================================================" >..\testlog
+echo Summaric results: >> ..\testlog
+set SUMPASS=
+set SUMFAIL=
+call testall t_166
+call testall t_16c5x
+call testall t_16c84
+call testall t_17c42
+call testall t_251
+call testall t_296
+call testall t_29k
+call testall t_32
+call testall t_3201x
+call testall t_3203x
+call testall t_3205x
+call testall t_3206x
+call testall t_370
+call testall t_4004
+call testall t_403
+call testall t_4500
+call testall t_47c00
+call testall t_48
+call testall t_56000
+call testall t_56300
+call testall t_65
+call testall t_6502u
+call testall t_6804
+call testall t_68040
+call testall t_6805
+call testall t_6808
+call testall t_6812
+call testall t_6816
+call testall t_7000
+call testall t_75k0
+call testall t_7700
+call testall t_7720
+call testall t_77230
+call testall t_7725
+call testall t_78c1x
+call testall t_78k0
+call testall t_85
+call testall t_87c800
+call testall t_8X30x
+call testall t_96
+call testall t_960
+call testall t_97c241
+call testall t_9900
+call testall t_ace
+call testall t_avr
+call testall t_bas52
+call testall t_buf32
+call testall t_cop8
+call testall t_f2mc8l
+call testall t_fl90
+call testall t_fl900
+call testall t_full09
+call testall t_h8_3
+call testall t_h8_5
+call testall t_m16c
+call testall t_mcore
+call testall t_mic51
+call testall t_msp
+call testall t_parsys
+call testall t_scmp
+call testall t_secdrive
+call testall t_st6
+call testall t_st7
+call testall t_st9
+call testall t_tms7
+call testall t_xa
+call testall t_z380
+call testall t_z8
+echo successes: %SUMPASS% >> ..\testlog
+echo failures: %SUMFAIL% >> ..\testlog
+type ..\testlog
+
+:end
diff --git a/tests/warnlog.DE b/tests/warnlog.DE
new file mode 100644
index 0000000..f75bc00
--- /dev/null
+++ b/tests/warnlog.DE
@@ -0,0 +1,35 @@
+t_166.asm(175) : Warnung : moegliche Pipelining-Effekte
+t_166.asm(181) : Warnung : moegliche Pipelining-Effekte
+t_166.asm(181) : Warnung : moegliche Pipelining-Effekte
+t_166.asm(185) : Warnung : moegliche Pipelining-Effekte
+t_166.asm(226) : Warnung : Seite moeglicherweise nicht adressierbar
+t_166.asm(231) : Warnung : Seite moeglicherweise nicht adressierbar
+t_16c84.asm(9) : Warnung : veralteter Befehl
+t_16c84.asm(50) : Warnung : veralteter Befehl
+t_3203x.asm(259) : Warnung : mehrfache Adressregisterbenutzung in einer Anweisung
+t_3203x.asm(259) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_3203x.asm(261) : Warnung : mehrfache Adressregisterbenutzung in einer Anweisung
+t_7000.asm(95) : Warnung : moegliche Pipelining-Effekte
+t_7000.asm(96) : Warnung : moegliche Pipelining-Effekte
+t_7000.asm(97) : Warnung : moegliche Pipelining-Effekte
+t_7000.asm(98) : Warnung : moegliche Pipelining-Effekte
+t_7000.asm(99) : Warnung : moegliche Pipelining-Effekte
+t_75k0.asm(186) : Warnung : Seite moeglicherweise nicht adressierbar
+t_87c800.asm(134) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_87c800.asm(135) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_87c800.asm(167) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_96.asm(155) : Warnung : kurzer Sprung moeglich
+t_96.asm(159) : Warnung : kurzer Sprung moeglich
+t_cop8.asm(112) : Warnung : Distanz 0 nicht bei Kurzsprung erlaubt (NOP erzeugt)
+t_xa.asm(591) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(592) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(593) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(594) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(595) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(596) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(597) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(598) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(599) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(600) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(601) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
+t_xa.asm(602) : Warnung : nicht vorhersagbare Ausfuehrung dieser Anweisung
diff --git a/tests/warnlog.EN b/tests/warnlog.EN
new file mode 100644
index 0000000..5e7afe3
--- /dev/null
+++ b/tests/warnlog.EN
@@ -0,0 +1,35 @@
+t_166.asm(175) : warning : possible pipelining effects
+t_166.asm(181) : warning : possible pipelining effects
+t_166.asm(181) : warning : possible pipelining effects
+t_166.asm(185) : warning : possible pipelining effects
+t_166.asm(226) : warning : page might not be addressable
+t_166.asm(231) : warning : page might not be addressable
+t_16c84.asm(9) : warning : obsolete instruction, usage discouraged
+t_16c84.asm(50) : warning : obsolete instruction, usage discouraged
+t_3203x.asm(259) : warning : multiple use of address register in one instruction
+t_3203x.asm(259) : warning : unpredictable execution of this instruction
+t_3203x.asm(261) : warning : multiple use of address register in one instruction
+t_7000.asm(95) : warning : possible pipelining effects
+t_7000.asm(96) : warning : possible pipelining effects
+t_7000.asm(97) : warning : possible pipelining effects
+t_7000.asm(98) : warning : possible pipelining effects
+t_7000.asm(99) : warning : possible pipelining effects
+t_75k0.asm(186) : warning : page might not be addressable
+t_87c800.asm(134) : warning : unpredictable execution of this instruction
+t_87c800.asm(135) : warning : unpredictable execution of this instruction
+t_87c800.asm(167) : warning : unpredictable execution of this instruction
+t_96.asm(155) : warning : short jump possible
+t_96.asm(159) : warning : short jump possible
+t_cop8.asm(112) : warning : distance of 0 not allowed for short jump (NOP created instead)
+t_xa.asm(591) : warning : unpredictable execution of this instruction
+t_xa.asm(592) : warning : unpredictable execution of this instruction
+t_xa.asm(593) : warning : unpredictable execution of this instruction
+t_xa.asm(594) : warning : unpredictable execution of this instruction
+t_xa.asm(595) : warning : unpredictable execution of this instruction
+t_xa.asm(596) : warning : unpredictable execution of this instruction
+t_xa.asm(597) : warning : unpredictable execution of this instruction
+t_xa.asm(598) : warning : unpredictable execution of this instruction
+t_xa.asm(599) : warning : unpredictable execution of this instruction
+t_xa.asm(600) : warning : unpredictable execution of this instruction
+t_xa.asm(601) : warning : unpredictable execution of this instruction
+t_xa.asm(602) : warning : unpredictable execution of this instruction
diff --git a/tex2doc.c b/tex2doc.c
new file mode 100644
index 0000000..163cbc0
--- /dev/null
+++ b/tex2doc.c
@@ -0,0 +1,2247 @@
+/* tex2doc.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Konverter TeX-->ASCII-DOC */
+/* */
+/* Historie: 9. 2.1998 Grundsteinlegung */
+/* 20. 6.1998 Zentrierung */
+/* 11. 7.1998 weitere Landessonderzeichen */
+/* 13. 7.1998 Cedilla */
+/* 12. 9.1998 input-Statement */
+/* 12. 1.1999 andere Kapitelherarchie fuer article */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include "asmitree.h"
+#include "chardefs.h"
+#include <ctype.h>
+#include <string.h>
+#include "strutil.h"
+
+#include "findhyphen.h"
+#ifndef __MSDOS__
+#include "ushyph.h"
+#include "grhyph.h"
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#define TOKLEN 250
+
+static char *TableName,
+ *BiblioName,
+ *ContentsName,
+#define ErrorEntryCnt 3
+ *ErrorEntryNames[ErrorEntryCnt];
+
+typedef enum{EnvNone,EnvDocument,EnvItemize,EnvEnumerate,EnvDescription,EnvTable,
+ EnvTabular,EnvRaggedLeft,EnvRaggedRight,EnvCenter,EnvVerbatim,
+ EnvQuote,EnvTabbing,EnvBiblio,EnvMarginPar,EnvCaption,EnvHeading,EnvCount} EnvType;
+
+typedef enum{FontStandard,FontEmphasized,FontBold,FontTeletype,FontItalic} TFontType;
+typedef enum{FontTiny,FontSmall,FontNormalSize,FontLarge,FontHuge} TFontSize;
+
+typedef enum{AlignNone,AlignCenter,AlignLeft,AlignRight} TAlignment;
+
+typedef struct _TEnvSave
+ {
+ struct _TEnvSave *Next;
+ EnvType SaveEnv;
+ int ListDepth,ActLeftMargin,LeftMargin,RightMargin;
+ int EnumCounter,FontNest;
+ TAlignment Alignment;
+ } TEnvSave,*PEnvSave;
+
+typedef struct _TFontSave
+ {
+ struct _TFontSave *Next;
+ TFontType FontType;
+ TFontSize FontSize;
+ } TFontSave,*PFontSave;
+
+typedef enum{ColLeft,ColRight,ColCenter,ColBar} TColumn;
+#define MAXCOLS 30
+#define MAXROWS 200
+typedef char *TableLine[MAXCOLS];
+typedef struct
+ {
+ int ColumnCount,TColumnCount;
+ TColumn ColTypes[MAXCOLS];
+ int ColLens[MAXCOLS];
+ int LineCnt;
+ TableLine Lines[MAXROWS];
+ Boolean LineFlags[MAXROWS];
+ Boolean MultiFlags[MAXROWS];
+ } TTable;
+
+typedef struct _TRefSave
+ {
+ struct _TRefSave *Next;
+ char *RefName,*Value;
+ } TRefSave,*PRefSave;
+
+typedef struct _TTocSave
+ {
+ struct _TTocSave *Next;
+ char *TocName;
+ } TTocSave,*PTocSave;
+
+static char *EnvNames[EnvCount]=
+ {"___NONE___","document","itemize","enumerate","description","table","tabular",
+ "raggedleft","raggedright","center","verbatim","quote","tabbing",
+ "thebibliography","___MARGINPAR___","___CAPTION___","___HEADING___"};
+
+static int IncludeNest;
+static FILE *infiles[50],*outfile;
+static char *infilename;
+static char TocName[200];
+static int CurrLine=0,CurrColumn;
+
+#define CHAPMAX 6
+static int Chapters[CHAPMAX];
+static int TableNum,FontNest,ErrState,FracState,BibIndent,BibCounter;
+#define TABMAX 100
+static int TabStops[TABMAX],TabStopCnt,CurrTabStop;
+static Boolean InAppendix,InMathMode,DoRepass;
+static TTable ThisTable;
+static int CurrRow,CurrCol;
+static Boolean GermanMode;
+
+static EnvType CurrEnv;
+static TFontType CurrFontType;
+static TFontSize CurrFontSize;
+static int CurrListDepth;
+static int EnumCounter;
+static int ActLeftMargin,LeftMargin,RightMargin;
+static TAlignment Alignment;
+static PEnvSave EnvStack;
+static PFontSave FontStack;
+static PRefSave FirstRefSave,FirstCiteSave;
+static PTocSave FirstTocSave;
+
+static PInstTable TeXTable;
+
+/*--------------------------------------------------------------------------*/
+
+ void ChkStack(void)
+BEGIN
+END
+
+ static void error(char *Msg)
+BEGIN
+ int z;
+
+ fprintf(stderr,"%s:%d.%d: %s\n",infilename,CurrLine,CurrColumn,Msg);
+ for (z=0; z<IncludeNest; fclose(infiles[z++]));
+ fclose(outfile);
+ exit(2);
+END
+
+ static void warning(char *Msg)
+BEGIN
+ fprintf(stderr,"%s:%d.%d: %s\n",infilename,CurrLine,CurrColumn,Msg);
+END
+
+ static void SetLang(Boolean IsGerman)
+BEGIN
+ char **pp;
+
+ if (GermanMode==IsGerman) return;
+
+ DestroyTree();
+ if ((GermanMode=IsGerman))
+ BEGIN
+ TableName="Tabelle";
+ BiblioName="Literaturverzeichnis";
+ ContentsName="Inhalt";
+ ErrorEntryNames[0]="Typ";
+ ErrorEntryNames[1]="Ursache";
+ ErrorEntryNames[2]="Argument";
+#ifndef __MSDOS__
+ BuildTree(GRHyphens);
+#endif
+ END
+ else
+ BEGIN
+ TableName="Table";
+ BiblioName="Bibliography";
+ ContentsName="Contents";
+ ErrorEntryNames[0]="Type";
+ ErrorEntryNames[1]="Reason";
+ ErrorEntryNames[2]="Argument";
+#ifndef __MSDOS__
+ BuildTree(USHyphens);
+ for (pp=USExceptions; *pp!=NULL; pp++) AddException(*pp);
+#endif
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddLabel(char *Name, char *Value)
+BEGIN
+ PRefSave Run,Prev,Neu;
+ int cmp=(-1);
+ char err[200];
+
+ for (Run=FirstRefSave,Prev=Nil; Run!=Nil; Prev=Run,Run=Run->Next)
+ if ((cmp=strcmp(Run->RefName,Name))>=0) break;
+
+ if ((Run!=Nil) AND (cmp==0))
+ BEGIN
+ if (strcmp(Run->Value,Value)!=0)
+ BEGIN
+ sprintf(err,"value of label '%s' has changed",Name);
+ warning(err); DoRepass=True;
+ free(Run->Value); Run->Value=strdup(Value);
+ END
+ END
+ else
+ BEGIN
+ Neu=(PRefSave) malloc(sizeof(TRefSave));
+ Neu->RefName=strdup(Name);
+ Neu->Value=strdup(Value);
+ Neu->Next=Run;
+ if (Prev==Nil) FirstRefSave=Neu; else Prev->Next=Neu;
+ END
+END
+
+ static void AddCite(char *Name, char *Value)
+BEGIN
+ PRefSave Run,Prev,Neu;
+ int cmp=(-1);
+ char err[200];
+
+ for (Run=FirstCiteSave,Prev=Nil; Run!=Nil; Prev=Run,Run=Run->Next)
+ if ((cmp=strcmp(Run->RefName,Name))>=0) break;
+
+ if ((Run!=Nil) AND (cmp==0))
+ BEGIN
+ if (strcmp(Run->Value,Value)!=0)
+ BEGIN
+ sprintf(err,"value of citation '%s' has changed",Name);
+ warning(err); DoRepass=True;
+ free(Run->Value); Run->Value=strdup(Value);
+ END
+ END
+ else
+ BEGIN
+ Neu=(PRefSave) malloc(sizeof(TRefSave));
+ Neu->RefName=strdup(Name);
+ Neu->Value=strdup(Value);
+ Neu->Next=Run;
+ if (Prev==Nil) FirstCiteSave=Neu; else Prev->Next=Neu;
+ END
+END
+
+ static void GetLabel(char *Name, char *Dest)
+BEGIN
+ PRefSave Run;
+ char err[200];
+
+ for (Run=FirstRefSave; Run!=Nil; Run=Run->Next)
+ if (strcmp(Name,Run->RefName)==0) break;
+
+ if (Run==Nil)
+ BEGIN
+ sprintf(err,"undefined label '%s'",Name);
+ warning(err); DoRepass=True;
+ END
+ strcpy(Dest,(Run==Nil) ? "???" : Run->Value);
+END
+
+ static void GetCite(char *Name, char *Dest)
+BEGIN
+ PRefSave Run;
+ char err[200];
+
+ for (Run=FirstCiteSave; Run!=Nil; Run=Run->Next)
+ if (strcmp(Name,Run->RefName)==0) break;
+
+ if (Run==Nil)
+ BEGIN
+ sprintf(err,"undefined citation '%s'",Name);
+ warning(err); DoRepass=True;
+ END
+ strcpy(Dest,(Run==Nil) ? "???" : Run->Value);
+END
+
+ static void PrintLabels(char *Name)
+BEGIN
+ PRefSave Run;
+ FILE *file=fopen(Name,"a");
+
+ if (file==Nil) perror(Name);
+
+ for (Run=FirstRefSave; Run!=Nil; Run=Run->Next)
+ fprintf(file,"Label %s %s\n",Run->RefName,Run->Value);
+ fclose(file);
+END
+
+ static void PrintCites(char *Name)
+BEGIN
+ PRefSave Run;
+ FILE *file=fopen(Name,"a");
+
+ if (file==Nil) perror(Name);
+
+ for (Run=FirstCiteSave; Run!=Nil; Run=Run->Next)
+ fprintf(file,"Citation %s %s\n",Run->RefName,Run->Value);
+ fclose(file);
+END
+
+ static void PrintToc(char *Name)
+BEGIN
+ PTocSave Run;
+ FILE *file=fopen(Name,"w");
+
+ if (file==Nil) perror(Name);
+
+ for (Run=FirstTocSave; Run!=Nil; Run=Run->Next)
+ fprintf(file,"%s\n\n",Run->TocName);
+ fclose(file);
+END
+
+/*------------------------------------------------------------------------------*/
+
+
+ static void GetNext(char *Src, char *Dest)
+BEGIN
+ char *c=strchr(Src,' ');
+
+ if (c==Nil)
+ BEGIN
+ strcpy(Dest,Src); *Src='\0';
+ END
+ else
+ BEGIN
+ *c='\0'; strcpy(Dest,Src);
+ for (c++; *c==' '; c++);
+ strcpy(Src,c);
+ END
+END
+
+ static void ReadAuxFile(char *Name)
+BEGIN
+ FILE *file=fopen(Name,"r");
+ char Line[300],Cmd[300],Nam[300],Val[300];
+
+ if (file==Nil) return;
+
+ while (NOT feof(file))
+ BEGIN
+ if (fgets(Line,299,file)==Nil) break;
+ if (Line[strlen(Line)-1]=='\n') Line[strlen(Line)-1]='\0';
+ GetNext(Line,Cmd);
+ if (strcmp(Cmd,"Label")==0)
+ BEGIN
+ GetNext(Line,Nam); GetNext(Line,Val);
+ AddLabel(Nam,Val);
+ END
+ else if (strcmp(Cmd,"Citation")==0)
+ BEGIN
+ GetNext(Line,Nam); GetNext(Line,Val);
+ AddCite(Nam,Val);
+ END
+ END
+
+ fclose(file);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean issep(char inp)
+BEGIN
+ return ((inp==' ') OR (inp=='\t') OR (inp=='\n'));
+END
+
+ static Boolean isalphanum(char inp)
+BEGIN
+ return ((inp>='A') AND (inp<='Z'))
+ OR ((inp>='a') AND (inp<='z'))
+ OR ((inp>='0') AND (inp<='9'))
+ OR (inp=='.');
+END
+
+static char LastChar='\0';
+static char SaveSep='\0',SepString[TOKLEN]="";
+static Boolean DidEOF=False;
+static char BufferLine[TOKLEN]="",*BufferPtr=BufferLine;
+typedef struct
+ {
+ char Token[TOKLEN],Sep[TOKLEN];
+ } PushedToken;
+static int PushedTokenCnt=0;
+static PushedToken PushedTokens[16];
+
+ static int GetChar(void)
+BEGIN
+ Boolean Comment;
+ static Boolean DidPar=False;
+ char *Result;
+
+ if (*BufferPtr=='\0')
+ BEGIN
+ do
+ BEGIN
+ if (IncludeNest<=0) return EOF;
+ do
+ BEGIN
+ Result=fgets(BufferLine,TOKLEN,infiles[IncludeNest-1]);
+ if (Result!=Nil) break;
+ fclose(infiles[--IncludeNest]);
+ if (IncludeNest<=0) return EOF;
+ END
+ while (True);
+ CurrLine++;
+ BufferPtr=BufferLine;
+ Comment=(strlen(BufferLine)>=2) AND (strncmp(BufferLine,"%%",2)==0);
+ if ((*BufferLine=='\0') OR (*BufferLine=='\n'))
+ BEGIN
+ if ((CurrEnv==EnvDocument) AND (NOT DidPar))
+ BEGIN
+ strcpy(BufferLine,"\\par\n"); DidPar=True; Comment=False;
+ END
+ END
+ else if (NOT Comment) DidPar=False;
+ END
+ while (Comment);
+ END
+ return *(BufferPtr++);
+END
+
+ static Boolean ReadToken(char *Dest)
+BEGIN
+ int ch,z;
+ Boolean Good;
+ char *run;
+
+ if (PushedTokenCnt>0)
+ BEGIN
+ strcpy(Dest,PushedTokens[0].Token); strcpy(SepString,PushedTokens[0].Sep);
+ for (z=0; z<PushedTokenCnt-1; z++) PushedTokens[z]=PushedTokens[z+1];
+ PushedTokenCnt--;
+ return True;
+ END
+
+ if (DidEOF) return FALSE;
+
+ CurrColumn=BufferPtr-BufferLine+1;
+
+ /* falls kein Zeichen gespeichert, fuehrende Blanks ueberspringen */
+
+ *Dest='\0'; *SepString=SaveSep; run=SepString+((SaveSep=='\0')?0:1);
+ if (LastChar=='\0')
+ BEGIN
+ do
+ BEGIN
+ ch=GetChar(); if (ch=='\r') ch=GetChar();
+ if (issep(ch)) *(run++)=' ';
+ END
+ while ((issep(ch)) AND (ch!=EOF));
+ *run='\0';
+ if (ch==EOF)
+ BEGIN
+ DidEOF=TRUE; return FALSE;
+ END
+ END
+ else
+ BEGIN
+ ch=LastChar; LastChar='\0';
+ END
+
+ /* jetzt Zeichen kopieren, bis Leerzeichen */
+
+ run=Dest;
+ SaveSep='\0';
+ if (isalphanum(*(run++)=ch))
+ BEGIN
+ do
+ BEGIN
+ ch=GetChar();
+ Good=(NOT issep(ch)) AND (isalphanum(ch)) AND (ch!=EOF);
+ if (Good) *(run++)=ch;
+ END
+ while (Good);
+
+ /* Dateiende ? */
+
+ if (ch==EOF) DidEOF=TRUE;
+
+ /* Zeichen speichern ? */
+
+ else if ((NOT issep(ch)) AND (NOT isalphanum(ch))) LastChar=ch;
+
+ /* Separator speichern ? */
+
+ else if (issep(ch)) SaveSep=' ';
+ END
+
+ /* Ende */
+
+ *run='\0'; return True;
+END
+
+ static void BackToken(char *Token)
+BEGIN
+ if (PushedTokenCnt>=16) return;
+ strcpy(PushedTokens[PushedTokenCnt].Token,Token);
+ strcpy(PushedTokens[PushedTokenCnt].Sep,SepString);
+ PushedTokenCnt++;
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void assert_token(char *ref)
+BEGIN
+ char token[TOKLEN];
+
+ ReadToken(token);
+ if (strcmp(ref,token)!=0)
+ BEGIN
+ sprintf(token,"\"%s\" expected",ref); error(token);
+ END
+END
+
+ static void collect_token(char *dest, char *term)
+BEGIN
+ char Comp[TOKLEN];
+ Boolean first=TRUE,done;
+
+ *dest='\0';
+ do
+ BEGIN
+ ReadToken(Comp);
+ done=(strcmp(Comp,term)==0);
+ if (NOT done)
+ BEGIN
+ if (NOT first) strcat(dest,SepString);
+ strcat(dest,Comp);
+ END
+ first=False;
+ END
+ while (NOT done);
+END
+
+/*--------------------------------------------------------------------------*/
+
+static char OutLineBuffer[TOKLEN]="",SideMargin[TOKLEN];
+
+ static void PutLine(Boolean DoBlock)
+BEGIN
+ int ll=RightMargin-LeftMargin+1;
+ int l,n,ptrcnt,diff,div,mod,divmod;
+ char *chz,*ptrs[50];
+ Boolean SkipFirst,IsFirst;
+
+ fputs(Blanks(LeftMargin-1),outfile);
+ if ((Alignment!=AlignNone) OR (NOT DoBlock))
+ BEGIN
+ l=strlen(OutLineBuffer);
+ diff=ll-l;
+ switch (Alignment)
+ BEGIN
+ case AlignRight: fputs(Blanks(diff),outfile); l=ll; break;
+ case AlignCenter: fputs(Blanks(diff>>1),outfile); l+=diff>>1; break;
+ default: break;
+ END
+ fputs(OutLineBuffer,outfile);
+ END
+ else
+ BEGIN
+ SkipFirst=((CurrEnv==EnvItemize) OR (CurrEnv==EnvEnumerate) OR (CurrEnv==EnvDescription) OR (CurrEnv==EnvBiblio));
+ if (LeftMargin==ActLeftMargin) SkipFirst=False;
+ l=ptrcnt=0; IsFirst=SkipFirst;
+ for (chz=OutLineBuffer; *chz!='\0'; chz++)
+ BEGIN
+ if ((chz>OutLineBuffer) AND (*(chz-1)!=' ') AND (*chz==' '))
+ BEGIN
+ if (NOT IsFirst) ptrs[ptrcnt++]=chz;
+ IsFirst=False;
+ END
+ l++;
+ END
+ diff=ll+1-l;
+ div=(ptrcnt>0) ? diff/ptrcnt : 0; mod=diff-(ptrcnt*div);
+ divmod=(mod>0) ? ptrcnt/mod : ptrcnt+1;
+ IsFirst=SkipFirst;
+ ptrcnt=0;
+ for (chz=OutLineBuffer; *chz!='\0'; chz++)
+ BEGIN
+ fputc(*chz,outfile);
+ if ((chz>OutLineBuffer) AND (*(chz-1)!=' ') AND (*chz==' '))
+ BEGIN
+ if (NOT IsFirst)
+ BEGIN
+ n=div;
+ if ((mod>0) AND ((ptrcnt%divmod)==0))
+ BEGIN
+ mod--; n++;
+ END
+ if (n>0) fputs(Blanks(n),outfile);
+ ptrcnt++;
+ END
+ IsFirst=False;
+ END
+ END
+ l=RightMargin-LeftMargin+1;
+ END
+ if (*SideMargin!='\0')
+ BEGIN
+ fputs(Blanks(ll+3-l),outfile);
+ fprintf(outfile,"%s",SideMargin);
+ *SideMargin='\0';
+ END
+ fputc('\n',outfile);
+ LeftMargin=ActLeftMargin;
+END
+
+ static void AddLine(char *Part, char *Sep)
+BEGIN
+ int mlen=RightMargin-LeftMargin+1,*hyppos,hypcnt,z,hlen;
+ char *search,save,*lastalpha;
+
+ if (strlen(Sep)>1) Sep[1]='\0';
+ if (*OutLineBuffer!='\0') strcat(OutLineBuffer,Sep);
+ strcat(OutLineBuffer,Part);
+ if (strlen(OutLineBuffer)>=mlen)
+ BEGIN
+ search=OutLineBuffer+mlen;
+ while (search>=OutLineBuffer)
+ BEGIN
+ if (*search==' ') break;
+ if (search>OutLineBuffer)
+ if (*(search-1)=='-') break;
+ else if (*(search-1)=='/') break;
+ else if (*(search-1)==';') break;
+ else if (*(search-1)==';') break;
+ search--;
+ END
+ if (search<=OutLineBuffer)
+ BEGIN
+ PutLine(True); *OutLineBuffer='\0';
+ END
+ else
+ BEGIN
+ if (*search==' ')
+ BEGIN
+ for (lastalpha=search+1; *lastalpha!='\0'; lastalpha++)
+ if ((mytolower(*lastalpha)<'a') OR (mytolower(*lastalpha)>'z')) break;
+ if (lastalpha-search>3)
+ BEGIN
+ save=(*lastalpha); *lastalpha='\0';
+ DoHyphens(search+1,&hyppos,&hypcnt);
+ *lastalpha=save;
+ hlen=(-1);
+ for (z=0; z<hypcnt; z++)
+ if ((search-OutLineBuffer)+hyppos[z]+1<mlen) hlen=hyppos[z];
+ if (hlen>0)
+ BEGIN
+ memmove(search+hlen+2,search+hlen+1,strlen(search+hlen+1)+1);
+ search[hlen+1]='-';
+ search+=hlen+2;
+ END
+ if (hypcnt>0) free(hyppos);
+ END
+ END
+ save=(*search); *search='\0';
+ PutLine(True); *search=save;
+ for (; *search==' '; search++);
+ strcpy(OutLineBuffer,search);
+ END
+ END
+END
+
+ static void AddSideMargin(char *Part, char *Sep)
+BEGIN
+ if (strlen(Sep)>1) Sep[1]='\0';
+ if (*Sep!='\0')
+ if ((*SideMargin!='\0') OR (NOT issep(*Sep))) strcat(SideMargin,Sep);
+ strcat(SideMargin,Part);
+END
+
+ static void FlushLine(void)
+BEGIN
+ if (*OutLineBuffer!='\0')
+ BEGIN
+ PutLine(False);
+ *OutLineBuffer='\0';
+ END
+END
+
+ static void ResetLine(void)
+BEGIN
+ *OutLineBuffer='\0';
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void SaveFont(void)
+BEGIN
+ PFontSave NewSave;
+
+ NewSave=(PFontSave) malloc(sizeof(TFontSave));
+ NewSave->Next=FontStack;
+ NewSave->FontSize=CurrFontSize;
+ NewSave->FontType=CurrFontType;
+ FontStack=NewSave; FontNest++;
+END
+
+ static void RestoreFont(void)
+BEGIN
+ PFontSave OldSave;
+
+ if (FontStack==Nil) return;
+
+ OldSave=FontStack; FontStack=FontStack->Next;
+ CurrFontSize=OldSave->FontSize;
+ CurrFontType=OldSave->FontType;
+ free(OldSave);
+ FontNest--;
+END
+
+ static void SaveEnv(EnvType NewEnv)
+BEGIN
+ PEnvSave NewSave;
+
+ NewSave=(PEnvSave) malloc(sizeof(TEnvSave));
+ NewSave->Next=EnvStack;
+ NewSave->ListDepth=CurrListDepth;
+ NewSave->LeftMargin=LeftMargin;
+ NewSave->Alignment=Alignment;
+ NewSave->ActLeftMargin=ActLeftMargin;
+ NewSave->RightMargin=RightMargin;
+ NewSave->EnumCounter=EnumCounter;
+ NewSave->SaveEnv=CurrEnv;
+ NewSave->FontNest=FontNest;
+ EnvStack=NewSave;
+ CurrEnv=NewEnv;
+ FontNest=0;
+END
+
+ static void RestoreEnv(void)
+BEGIN
+ PEnvSave OldSave;
+
+ OldSave=EnvStack; EnvStack=OldSave->Next;
+ CurrListDepth=OldSave->ListDepth;
+ LeftMargin=OldSave->LeftMargin;
+ ActLeftMargin=OldSave->ActLeftMargin;
+ RightMargin=OldSave->RightMargin;
+ Alignment=OldSave->Alignment;
+ EnumCounter=OldSave->EnumCounter;
+ FontNest=OldSave->FontNest;
+ CurrEnv=OldSave->SaveEnv;
+ free(OldSave);
+END
+
+ static void InitTableRow(int Index)
+BEGIN
+ int z;
+
+ for (z=0; z<ThisTable.TColumnCount; ThisTable.Lines[Index][z++]=Nil);
+ ThisTable.MultiFlags[Index]=False;
+ ThisTable.LineFlags[Index]=False;
+END
+
+ static void NextTableColumn(void)
+BEGIN
+ if (CurrEnv!=EnvTabular) error("table separation char not within tabular environment");
+
+ if ((ThisTable.MultiFlags[CurrRow])
+ OR (CurrCol>=ThisTable.TColumnCount))
+ error("too many columns within row");
+
+ CurrCol++;
+END
+
+ static void AddTableEntry(char *Part, char *Sep)
+BEGIN
+ char *Ptr=ThisTable.Lines[CurrRow][CurrCol];
+ int nlen=(Ptr==Nil) ? 0 : strlen(Ptr);
+ Boolean UseSep=(nlen>0);
+
+ if (strlen(Sep)>1) Sep[1]='\0';
+ if (UseSep) nlen+=strlen(Sep); nlen+=strlen(Part);
+ if (Ptr==Nil)
+ BEGIN
+ Ptr=(char *) malloc(nlen+1); *Ptr='\0';
+ END
+ else Ptr=(char *) realloc(Ptr,nlen+1);
+ if (UseSep) strcat(Ptr,Sep); strcat(Ptr,Part);
+ ThisTable.Lines[CurrRow][CurrCol]=Ptr;
+END
+
+ static void DoPrnt(char *Ptr, TColumn Align, int len)
+BEGIN
+ int l=(Ptr==Nil) ? 0 : strlen(Ptr),diff;
+
+ len-=2;
+ diff=len-l;
+ fputc(' ',outfile);
+ switch (Align)
+ BEGIN
+ case ColRight: fputs(Blanks(diff),outfile); break;
+ case ColCenter: fputs(Blanks((diff+1)/2),outfile); break;
+ default: break;
+ END
+ if (Ptr!=Nil)
+ BEGIN
+ fputs(Ptr,outfile); free(Ptr);
+ END
+ switch (Align)
+ BEGIN
+ case ColLeft: fputs(Blanks(diff),outfile); break;
+ case ColCenter: fputs(Blanks(diff/2),outfile); break;
+ default: break;
+ END
+ fputc(' ',outfile);
+END
+
+ static void DumpTable(void)
+BEGIN
+ int RowCnt,rowz,colz,colptr,ml,l,diff,sumlen,firsttext,indent;
+
+ /* compute widths of individual rows */
+ /* get index of first text column */
+
+ RowCnt=(ThisTable.Lines[CurrRow][0]!=Nil) ? CurrRow+1 : CurrRow;
+ firsttext=(-1);
+ for (colz=colptr=0; colz<ThisTable.ColumnCount; colz++)
+ if (ThisTable.ColTypes[colz]==ColBar) ThisTable.ColLens[colz]=1;
+ else
+ BEGIN
+ ml=0;
+ for (rowz=0; rowz<RowCnt; rowz++)
+ if ((NOT ThisTable.LineFlags[rowz]) AND (NOT ThisTable.MultiFlags[rowz]))
+ BEGIN
+ l=(ThisTable.Lines[rowz][colptr]==Nil) ? 0 : strlen(ThisTable.Lines[rowz][colptr]);
+ if (ml<l) ml=l;
+ END
+ ThisTable.ColLens[colz]=ml+2;
+ colptr++;
+ if (firsttext<0) firsttext=colz;
+ END
+
+ /* get total width */
+
+ for (colz=sumlen=0; colz<ThisTable.ColumnCount; sumlen+=ThisTable.ColLens[colz++]);
+ indent=(RightMargin-LeftMargin+1-sumlen)/2; if (indent<0) indent=0;
+
+ /* search for multicolumns and extend first field if table is too lean */
+
+ ml=0;
+ for (rowz=0; rowz<RowCnt; rowz++)
+ if ((NOT ThisTable.LineFlags[rowz]) AND (ThisTable.MultiFlags[rowz]))
+ BEGIN
+ l=(ThisTable.Lines[rowz][0]==Nil) ? 0 : strlen(ThisTable.Lines[rowz][0]);
+ if (ml<l) ml=l;
+ END
+ if (ml+4>sumlen)
+ BEGIN
+ diff=ml+4-sumlen;
+ ThisTable.ColLens[firsttext]+=diff;
+ END
+
+ /* print rows */
+
+ for (rowz=0; rowz<RowCnt; rowz++)
+ BEGIN
+ fputs(Blanks(LeftMargin-1+indent),outfile);
+ if (ThisTable.MultiFlags[rowz])
+ BEGIN
+ l=sumlen;
+ if (ThisTable.ColTypes[0]==ColBar)
+ BEGIN
+ l--; fputc('|',outfile);
+ END
+ if (ThisTable.ColTypes[ThisTable.ColumnCount-1]==ColBar) l--;
+ DoPrnt(ThisTable.Lines[rowz][0],ThisTable.ColTypes[firsttext],l);
+ if (ThisTable.ColTypes[ThisTable.ColumnCount-1]==ColBar) fputc('|',outfile);
+ END
+ else
+ BEGIN
+ for (colz=colptr=0; colz<ThisTable.ColumnCount; colz++)
+ if (ThisTable.LineFlags[rowz])
+ if (ThisTable.ColTypes[colz]==ColBar) fputc('+',outfile);
+ else for (l=0; l<ThisTable.ColLens[colz]; l++) fputc('-',outfile);
+ else
+ if (ThisTable.ColTypes[colz]==ColBar) fputc('|',outfile);
+ else
+ BEGIN
+ DoPrnt(ThisTable.Lines[rowz][colptr],ThisTable.ColTypes[colz],ThisTable.ColLens[colz]);
+ colptr++;
+ END
+ END
+ fputc('\n',outfile);
+ END
+END
+
+ static void DoAddNormal(char *Part, char *Sep)
+BEGIN
+ switch (CurrEnv)
+ BEGIN
+ case EnvMarginPar: AddSideMargin(Part,Sep); break;
+ case EnvTabular: AddTableEntry(Part,Sep); break;
+ default: AddLine(Part,Sep);
+ END
+END
+
+ static void GetTableName(char *Dest)
+BEGIN
+ if (InAppendix) sprintf(Dest,"%c.%d",Chapters[0]+'A',TableNum);
+ else sprintf(Dest,"%d.%d",Chapters[0],TableNum);
+END
+
+ static char *GetSectionName(char *Dest)
+BEGIN
+ char *run=Dest;
+ int z;
+
+ for (z=0; z<=2; z++)
+ BEGIN
+ if ((z>0) AND (Chapters[z]==0)) break;
+ if ((InAppendix) AND (z==0))
+ run+=sprintf(run,"%c.",Chapters[z]+'A');
+ else run+=sprintf(run,"%d.",Chapters[z]);
+ END
+ return run;
+END
+
+/*--------------------------------------------------------------------------*/
+
+static char BackSepString[TOKLEN];
+
+ static void TeXFlushLine(Word Index)
+BEGIN
+ if (CurrEnv==EnvTabular)
+ BEGIN
+ for (CurrCol++; CurrCol<ThisTable.TColumnCount; ThisTable.Lines[CurrRow][CurrCol++]=strdup(""));
+ CurrRow++;
+ if (CurrRow==MAXROWS) error("too many rows in table");
+ InitTableRow(CurrRow); CurrCol=0;
+ END
+ else
+ BEGIN
+ if (*OutLineBuffer=='\0') strcpy(OutLineBuffer," ");
+ FlushLine();
+ END
+ if (CurrEnv==EnvTabbing) CurrTabStop=0;
+END
+
+ static void TeXKillLine(Word Index)
+BEGIN
+ ResetLine();
+END
+
+ static void TeXDummy(Word Index)
+BEGIN
+END
+
+ static void TeXDummyNoBrack(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ ReadToken(Token);
+END
+
+ static void TeXDummyInCurl(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("{");
+ ReadToken(Token);
+ assert_token("}");
+END
+
+ static void TeXNewCommand(Word Index)
+BEGIN
+ char Token[TOKLEN];
+ int level;
+
+ assert_token("{");
+ assert_token("\\");
+ ReadToken(Token);
+ assert_token("}");
+ ReadToken(Token);
+ if (strcmp(Token,"[")==0)
+ BEGIN
+ ReadToken(Token);
+ assert_token("]");
+ END
+ assert_token("{"); level=1;
+ do
+ BEGIN
+ ReadToken(Token);
+ if (strcmp(Token,"{")==0) level++;
+ else if (strcmp(Token,"}")==0) level--;
+ END
+ while (level!=0);
+END
+
+ static void TeXDef(Word Index)
+BEGIN
+ char Token[TOKLEN];
+ int level;
+
+ assert_token("\\");
+ ReadToken(Token);
+ assert_token("{"); level=1;
+ do
+ BEGIN
+ ReadToken(Token);
+ if (strcmp(Token,"{")==0) level++;
+ else if (strcmp(Token,"}")==0) level--;
+ END
+ while (level!=0);
+END
+
+ static void TeXFont(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("\\");
+ ReadToken(Token); assert_token("="); ReadToken(Token); ReadToken(Token);
+ assert_token("\\"); ReadToken(Token);
+END
+
+ static void TeXAppendix(Word Index)
+BEGIN
+ int z;
+
+ InAppendix=True;
+ *Chapters=(-1);
+ for (z=1; z<CHAPMAX; Chapters[z++]=0);
+END
+
+static int LastLevel;
+
+ static void TeXNewSection(Word Level)
+BEGIN
+ int z;
+
+ if (Level>=CHAPMAX) return;
+
+ FlushLine(); fputc('\n',outfile);
+
+ assert_token("{"); LastLevel=Level;
+ SaveEnv(EnvHeading); RightMargin=200;
+
+ Chapters[Level]++;
+ for (z=Level+1; z<CHAPMAX; Chapters[z++]=0);
+ if (Level==0) TableNum=0;
+END
+
+ static void EndSectionHeading(void)
+BEGIN
+ int Level=LastLevel,z;
+ char Line[TOKLEN],Title[TOKLEN],*run;
+ PTocSave NewTocSave,RunToc;
+
+ strcpy(Title,OutLineBuffer); *OutLineBuffer='\0';
+
+ run=Line;
+ if (Level<3)
+ BEGIN
+ run=GetSectionName(run);
+ run+=sprintf(run," ");
+ if ((Level==2) AND (((strlen(Line)+strlen(Title))&1)==0)) run+=sprintf(run," ");
+ END
+ sprintf(run,"%s",Title);
+
+ fprintf(outfile," %s\n ",Line);
+ for (z=0; z<strlen(Line); z++)
+ switch(Level)
+ BEGIN
+ case 0: fputc('=',outfile); break;
+ case 1: fputc('-',outfile); break;
+ case 2: fputc(((z&1)==0) ? '-' : ' ',outfile); break;
+ case 3: fputc('.',outfile); break;
+ END
+ fprintf(outfile,"\n");
+
+ if (Level<3)
+ BEGIN
+ NewTocSave=(PTocSave) malloc(sizeof(TTocSave));
+ NewTocSave->Next=Nil;
+ run=Line; run=GetSectionName(run); run+=sprintf(run," "); sprintf(run,"%s",Title);
+ NewTocSave->TocName=(char *) malloc(6+Level+strlen(Line));
+ strcpy(NewTocSave->TocName,Blanks(5+Level));
+ strcat(NewTocSave->TocName,Line);
+ if (FirstTocSave==Nil) FirstTocSave=NewTocSave;
+ else
+ BEGIN
+ for (RunToc=FirstTocSave; RunToc->Next!=Nil; RunToc=RunToc->Next);
+ RunToc->Next=NewTocSave;
+ END
+ END
+END
+
+ static EnvType GetEnvType(char *Name)
+BEGIN
+ EnvType z;
+
+ for (z=EnvNone+1; z<EnvCount; z++)
+ if (strcmp(Name,EnvNames[z])==0) return z;
+
+ error("unknown environment");
+ return EnvNone;
+END
+
+ static void TeXBeginEnv(Word Index)
+BEGIN
+ char EnvName[TOKLEN],Add[TOKLEN];
+ EnvType NEnv;
+ Boolean done;
+ TColumn NCol;
+ int z;
+
+ assert_token("{");
+ ReadToken(EnvName);
+ if ((NEnv=GetEnvType(EnvName))==EnvTable)
+ BEGIN
+ ReadToken(Add);
+ if (strcmp(Add,"*")==0) assert_token("}");
+ else if (strcmp(Add,"}")!=0) error("unknown table environment");
+ END
+ else assert_token("}");
+
+ if (NEnv!=EnvVerbatim) SaveEnv(NEnv);
+
+ switch (NEnv)
+ BEGIN
+ case EnvItemize:
+ case EnvEnumerate:
+ case EnvDescription:
+ FlushLine(); if (CurrListDepth==0) fputc('\n',outfile);
+ ++CurrListDepth;
+ ActLeftMargin=LeftMargin=(CurrListDepth*4)+1;
+ RightMargin=70;
+ EnumCounter=0;
+ break;
+ case EnvBiblio:
+ FlushLine(); fputc('\n',outfile);
+ fprintf(outfile," %s\n ",BiblioName);
+ for (z=0; z<strlen(BiblioName); z++) fputc('=',outfile);
+ fputc('\n',outfile);
+ assert_token("{"); ReadToken(Add); assert_token("}");
+ ActLeftMargin=LeftMargin=4+(BibIndent=strlen(Add));
+ break;
+ case EnvVerbatim:
+ FlushLine();
+ if ((*BufferLine!='\0') AND (*BufferPtr!='\0'))
+ BEGIN
+ fprintf(outfile,"%s",BufferPtr);
+ *BufferLine='\0'; BufferPtr=BufferLine;
+ END
+ do
+ BEGIN
+ fgets(Add,TOKLEN-1,infiles[IncludeNest-1]); CurrLine++;
+ done=strstr(Add,"\\end{verbatim}")!=Nil;
+ if (NOT done) fprintf(outfile,"%s",Add);
+ END
+ while (NOT done);
+ fputc('\n',outfile);
+ break;
+ case EnvQuote:
+ FlushLine(); fputc('\n',outfile);
+ ActLeftMargin=LeftMargin=5;
+ RightMargin=70;
+ break;
+ case EnvTabbing:
+ FlushLine(); fputc('\n',outfile);
+ TabStopCnt=0; CurrTabStop=0;
+ break;
+ case EnvTable:
+ ReadToken(Add);
+ if (strcmp(Add,"[")!=0) BackToken(Add);
+ else
+ do
+ BEGIN
+ ReadToken(Add);
+ END
+ while (strcmp(Add,"]")!=0);
+ FlushLine(); fputc('\n',outfile);
+ ++TableNum;
+ break;
+ case EnvCenter:
+ FlushLine(); Alignment=AlignCenter; break;
+ case EnvRaggedRight:
+ FlushLine(); Alignment=AlignLeft; break;
+ case EnvRaggedLeft:
+ FlushLine(); Alignment=AlignRight; break;
+ case EnvTabular:
+ FlushLine(); assert_token("{");
+ ThisTable.ColumnCount=ThisTable.TColumnCount=0;
+ do
+ BEGIN
+ ReadToken(Add);
+ done=strcmp(Add,"}")==0;
+ if (NOT done)
+ BEGIN
+ if (ThisTable.ColumnCount>=MAXCOLS) error("too many columns in table");
+ if (strcmp(Add,"|")==0) NCol=ColBar;
+ else if (strcmp(Add,"l")==0) NCol=ColLeft;
+ else if (strcmp(Add,"r")==0) NCol=ColRight;
+ else if (strcmp(Add,"c")==0) NCol=ColCenter;
+ else
+ BEGIN
+ NCol=ColBar;
+ error("unknown table column descriptor");
+ END
+ if ((ThisTable.ColTypes[ThisTable.ColumnCount++]=NCol)!=ColBar)
+ ThisTable.TColumnCount++;
+ END
+ END
+ while (NOT done);
+ InitTableRow(CurrRow=0); CurrCol=0;
+ break;
+ default:
+ break;
+ END
+END
+
+ static void TeXEndEnv(Word Index)
+BEGIN
+ char EnvName[TOKLEN],Add[TOKLEN];
+ EnvType NEnv;
+
+ assert_token("{");
+ ReadToken(EnvName);
+ if ((NEnv=GetEnvType(EnvName))==EnvTable)
+ BEGIN
+ ReadToken(Add);
+ if (strcmp(Add,"*")==0) assert_token("}");
+ else if (strcmp(Add,"}")!=0) error("unknown table environment");
+ END
+ else assert_token("}");
+
+ if (EnvStack==Nil) error("end without begin");
+ if (CurrEnv!=NEnv) error("begin and end of environment do not match");
+
+ switch (CurrEnv)
+ BEGIN
+ case EnvItemize:
+ case EnvEnumerate:
+ case EnvDescription:
+ FlushLine(); if (CurrListDepth==1) fputc('\n',outfile);
+ break;
+ case EnvBiblio:
+ case EnvQuote:
+ case EnvTabbing:
+ FlushLine(); fputc('\n',outfile);
+ break;
+ case EnvCenter:
+ case EnvRaggedRight:
+ case EnvRaggedLeft:
+ FlushLine(); break;
+ case EnvTabular:
+ DumpTable();
+ break;
+ case EnvTable:
+ FlushLine(); fputc('\n',outfile);
+ break;
+ default:
+ break;
+ END
+
+ RestoreEnv();
+END
+
+ static void TeXItem(Word Index)
+BEGIN
+ char NumString[20],Token[TOKLEN],Acc[TOKLEN];
+
+ FlushLine();
+ switch(CurrEnv)
+ BEGIN
+ case EnvItemize:
+ LeftMargin=ActLeftMargin-3;
+ AddLine(" - ","");
+ break;
+ case EnvEnumerate:
+ LeftMargin=ActLeftMargin-4;
+ sprintf(NumString,"%3d ",++EnumCounter);
+ AddLine(NumString,"");
+ break;
+ case EnvDescription:
+ ReadToken(Token);
+ if (strcmp(Token,"[")!=0) BackToken(Token);
+ else
+ BEGIN
+ collect_token(Acc,"]");
+ LeftMargin=ActLeftMargin-4;
+ sprintf(NumString,"%3s ",Acc);
+ AddLine(NumString,"");
+ END
+ break;
+ default:
+ error("\\item not in a list environment");
+ END
+END
+
+ static void TeXBibItem(Word Index)
+BEGIN
+ char NumString[20],Token[TOKLEN],Name[TOKLEN],Format[10];
+
+ if (CurrEnv!=EnvBiblio) error("\\bibitem not in bibliography environment");
+
+ assert_token("{"); collect_token(Name,"}");
+
+ FlushLine(); fputc('\n',outfile); ++BibCounter;
+
+ LeftMargin=ActLeftMargin-BibIndent-3;
+ sprintf(Format,"[%%%dd] ",BibIndent);
+ sprintf(NumString,Format,BibCounter);
+ AddLine(NumString,"");
+ sprintf(NumString,"%d",BibCounter);
+ AddCite(Name,NumString);
+ ReadToken(Token); *SepString='\0'; BackToken(Token);
+END
+
+ static void TeXAddDollar(Word Index)
+BEGIN
+ DoAddNormal("$",BackSepString);
+END
+
+ static void TeXAddUnderbar(Word Index)
+BEGIN
+ DoAddNormal("_",BackSepString);
+END
+
+ static void TeXAddPot(Word Index)
+BEGIN
+ DoAddNormal("^",BackSepString);
+END
+
+ static void TeXAddAmpersand(Word Index)
+BEGIN
+ DoAddNormal("&",BackSepString);
+END
+
+ static void TeXAddAt(Word Index)
+BEGIN
+ DoAddNormal("@",BackSepString);
+END
+
+ static void TeXAddImm(Word Index)
+BEGIN
+ DoAddNormal("#",BackSepString);
+END
+
+ static void TeXAddPercent(Word Index)
+BEGIN
+ DoAddNormal("%",BackSepString);
+END
+
+ static void TeXAddSSharp(Word Index)
+BEGIN
+ DoAddNormal(CH_sz,BackSepString);
+END
+
+ static void TeXAddIn(Word Index)
+BEGIN
+ DoAddNormal("in",BackSepString);
+END
+
+ static void TeXAddReal(Word Index)
+BEGIN
+ DoAddNormal("R",BackSepString);
+END
+
+ static void TeXAddGreekMu(Word Index)
+BEGIN
+ DoAddNormal(CH_mu,BackSepString);
+END
+
+ static void TeXAddGreekPi(Word Index)
+BEGIN
+ DoAddNormal("Pi",BackSepString);
+END
+
+ static void TeXAddLessEq(Word Index)
+BEGIN
+ DoAddNormal("<=",BackSepString);
+END
+
+ static void TeXAddGreaterEq(Word Index)
+BEGIN
+ DoAddNormal(">=",BackSepString);
+END
+
+ static void TeXAddNotEq(Word Index)
+BEGIN
+ DoAddNormal("<>",BackSepString);
+END
+
+ static void TeXAddMid(Word Index)
+BEGIN
+ DoAddNormal("|",BackSepString);
+END
+
+ static void TeXAddRightArrow(Word Index)
+BEGIN
+ DoAddNormal("->",BackSepString);
+END
+
+ static void TeXAddLongRightArrow(Word Index)
+BEGIN
+ DoAddNormal("-->",BackSepString);
+END
+
+ static void TeXAddLeftArrow(Word Index)
+BEGIN
+ DoAddNormal("<-",BackSepString);
+END
+
+ static void TeXAddLeftRightArrow(Word Index)
+BEGIN
+ DoAddNormal("<->",BackSepString);
+END
+
+ static void TeXDoFrac(Word Index)
+BEGIN
+ assert_token("{"); *SepString='\0'; BackToken("("); FracState=0;
+END
+
+ static void NextFracState(void)
+BEGIN
+ if (FracState==0)
+ BEGIN
+ assert_token("{");
+ *SepString='\0';
+ BackToken(")"); BackToken("/"); BackToken("(");
+ END
+ else if (FracState==1)
+ BEGIN
+ *SepString='\0'; BackToken(")");
+ END
+ if ((++FracState)==2) FracState=(-1);
+END
+
+ static void TeXNewFontType(Word Index)
+BEGIN
+ CurrFontType=(TFontType) Index;
+END
+
+ static void TeXEnvNewFontType(Word Index)
+BEGIN
+ char NToken[TOKLEN];
+
+ SaveFont();
+ CurrFontType=(TFontType) Index;
+ assert_token("{");
+ ReadToken(NToken);
+ strcpy(SepString,BackSepString);
+ BackToken(NToken);
+END
+
+ static void TeXNewFontSize(Word Index)
+BEGIN
+ CurrFontSize=(TFontSize) Index;
+END
+
+ static void TeXEnvNewFontSize(Word Index)
+BEGIN
+ char NToken[TOKLEN];
+
+ SaveFont();
+ CurrFontSize=(TFontSize) Index;
+ assert_token("{");
+ ReadToken(NToken);
+ strcpy(SepString,BackSepString);
+ BackToken(NToken);
+END
+
+ static void TeXAddMarginPar(Word Index)
+BEGIN
+ assert_token("{");
+ SaveEnv(EnvMarginPar);
+END
+
+ static void TeXAddCaption(Word Index)
+BEGIN
+ char tmp[100];
+ int cnt;
+
+ assert_token("{");
+ if (CurrEnv!=EnvTable) error("caption outside of a table");
+ FlushLine(); fputc('\n',outfile);
+ SaveEnv(EnvCaption);
+ AddLine(TableName,""); cnt=strlen(TableName);
+ GetTableName(tmp); strcat(tmp,": ");
+ AddLine(tmp," "); cnt+=1+strlen(tmp);
+ LeftMargin=1; ActLeftMargin=cnt+1; RightMargin=70;
+END
+
+ static void TeXHorLine(Word Index)
+BEGIN
+ if (CurrEnv!=EnvTabular) error("\\hline outside of a table");
+
+ if (ThisTable.Lines[CurrRow][0]!=Nil) InitTableRow(++CurrRow);
+ ThisTable.LineFlags[CurrRow]=True;
+ InitTableRow(++CurrRow);
+END
+
+ static void TeXMultiColumn(Word Index)
+BEGIN
+ char Token[TOKLEN],*endptr;
+ int cnt;
+
+ if (CurrEnv!=EnvTabular) error("\\hline outside of a table");
+ if (CurrCol!=0) error("\\multicolumn must be in first column");
+
+ assert_token("{"); ReadToken(Token); assert_token("}");
+ cnt=strtol(Token,&endptr,10);
+ if (*endptr!='\0') error("invalid numeric format to \\multicolumn");
+ if (cnt!=ThisTable.TColumnCount) error("\\multicolumn must span entire table");
+ assert_token("{");
+ do
+ BEGIN
+ ReadToken(Token);
+ END
+ while (strcmp(Token,"}")!=0);
+ ThisTable.MultiFlags[CurrRow]=True;
+END
+
+ static void TeXIndex(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("{");
+ do
+ BEGIN
+ ReadToken(Token);
+ END
+ while (strcmp(Token,"}")!=0);
+END
+
+ static int GetDim(Double *Factors)
+BEGIN
+ char Acc[TOKLEN];
+ static char *UnitNames[]={"cm","mm",""},**run,*endptr;
+ Double Value;
+
+ assert_token("{"); collect_token(Acc,"}");
+ for (run=UnitNames; **run!='\0'; run++)
+ if (strcmp(*run,Acc+strlen(Acc)-strlen(*run))==0) break;
+ if (**run=='\0') error("unknown unit for dimension");
+ Acc[strlen(Acc)-strlen(*run)]='\0';
+ Value=strtod(Acc,&endptr);
+ if (*endptr!='\0') error("invalid numeric format for dimension");
+ return (int)(Value*Factors[run-UnitNames]);
+END
+
+static Double HFactors[]={4.666666,0.4666666,0};
+static Double VFactors[]={3.111111,0.3111111,0};
+
+ static void TeXHSpace(Word Index)
+BEGIN
+
+ DoAddNormal(Blanks(GetDim(HFactors)),"");
+END
+
+ static void TeXVSpace(Word Index)
+BEGIN
+ int z,erg;
+
+ erg=GetDim(VFactors);
+ FlushLine();
+ for (z=0; z<erg; z++) fputc('\n',outfile);
+END
+
+ static void TeXRule(Word Index)
+BEGIN
+ int h=GetDim(HFactors),v=GetDim(VFactors);
+ char Rule[200];
+
+ for (v=0; v<h; Rule[v++]='-'); Rule[v]='\0';
+ DoAddNormal(Rule,BackSepString);
+END
+
+ static void TeXAddTabStop(Word Index)
+BEGIN
+ int z,n,p;
+
+ if (CurrEnv!=EnvTabbing) error("tab marker outside of tabbing environment");
+ if (TabStopCnt>=TABMAX) error("too many tab stops");
+
+ n=strlen(OutLineBuffer);
+ for (p=0; p<TabStopCnt; p++)
+ if (TabStops[p]>n) break;
+ for (z=TabStopCnt-1; z>=p; z--) TabStops[z+1]=TabStops[z];
+ TabStops[p]=n; TabStopCnt++;
+END
+
+ static void TeXJmpTabStop(Word Index)
+BEGIN
+ int diff;
+
+ if (CurrEnv!=EnvTabbing) error("tab trigger outside of tabbing environment");
+ if (CurrTabStop>=TabStopCnt) error("not enough tab stops");
+
+ diff=TabStops[CurrTabStop]-strlen(OutLineBuffer);
+ if (diff>0) DoAddNormal(Blanks(diff),"");
+ CurrTabStop++;
+END
+
+ static void TeXDoVerb(Word Index)
+BEGIN
+ char Token[TOKLEN],*pos,Marker;
+
+ ReadToken(Token);
+ if (*SepString!='\0') error("invalid control character for \\verb");
+ Marker=(*Token); strcpy(Token,Token+1); strcpy(SepString,BackSepString);
+ do
+ BEGIN
+ DoAddNormal(SepString,"");
+ pos=strchr(Token,Marker);
+ if (pos!=Nil)
+ BEGIN
+ *pos='\0'; DoAddNormal(Token,"");
+ *SepString='\0'; BackToken(pos+1);
+ break;
+ END
+ else
+ BEGIN
+ DoAddNormal(Token,""); ReadToken(Token);
+ END
+ END
+ while (True);
+END
+
+ static void TeXErrEntry(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("{"); ReadToken(Token); assert_token("}"); assert_token("{");
+ *SepString='\0';
+ BackToken("\\"); BackToken("item"); BackToken("["); BackToken(Token); BackToken("]");
+ ErrState=0;
+END
+
+ static void NextErrState(void)
+BEGIN
+ if (ErrState<3) assert_token("{");
+ if (ErrState==0)
+ BEGIN
+ *SepString='\0';
+ BackToken("\\"); BackToken("begin"); BackToken("{"); BackToken("description"); BackToken("}");
+ END
+ if ((ErrState>=0) AND (ErrState<=2))
+ BEGIN
+ *SepString='\0';
+ BackToken("\\"); BackToken("item"); BackToken("["); BackToken(ErrorEntryNames[ErrState]);
+ BackToken(":"); BackToken("]"); BackToken("\\"); BackToken("\\");
+ END
+ if (ErrState==3)
+ BEGIN
+ *SepString='\0';
+ BackToken("\\"); BackToken("\\"); BackToken(" ");
+ BackToken("\\"); BackToken("end"); BackToken("{"); BackToken("description"); BackToken("}");
+ ErrState=(-1);
+ END
+ else ErrState++;
+END
+
+ static void TeXWriteLabel(Word Index)
+BEGIN
+ char Name[TOKLEN],Value[TOKLEN];
+
+ assert_token("{"); collect_token(Name,"}");
+
+ if (CurrEnv==EnvCaption) GetTableName(Value);
+ else
+ BEGIN
+ GetSectionName(Value);
+ if (Value[strlen(Value)-1]=='.') Value[strlen(Value)-1]='\0';
+ END
+
+ AddLabel(Name,Value);
+END
+
+ static void TeXWriteRef(Word Index)
+BEGIN
+ char Name[TOKLEN],Value[TOKLEN];
+
+ assert_token("{"); collect_token(Name,"}");
+ GetLabel(Name,Value);
+ DoAddNormal(Value,BackSepString);
+END
+
+ static void TeXWriteCitation(Word Index)
+BEGIN
+ char Name[TOKLEN],Value[TOKLEN];
+
+ assert_token("{"); collect_token(Name,"}");
+ GetCite(Name,Value);
+ sprintf(Name,"[%s]",Value);
+ DoAddNormal(Name,BackSepString);
+END
+
+ static void TeXNewParagraph(Word Index)
+BEGIN
+ FlushLine();
+ fputc('\n',outfile);
+END
+
+ static void TeXContents(Word Index)
+BEGIN
+ FILE *file=fopen(TocName,"r");
+ char Line[200];
+
+ if (file==Nil)
+ BEGIN
+ warning("contents file not found.");
+ DoRepass=True; return;
+ END
+
+ FlushLine();
+ fprintf(outfile," %s\n\n",ContentsName);
+ while (NOT feof(file))
+ BEGIN
+ fgets(Line,199,file); fputs(Line,outfile);
+ END
+
+ fclose(file);
+END
+
+ static void TeXParSkip(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ ReadToken(Token);
+ do
+ BEGIN
+ ReadToken(Token);
+ if ((strncmp(Token,"plus",4)==0) OR (strncmp(Token,"minus",5)==0))
+ BEGIN
+ END
+ else
+ BEGIN
+ BackToken(Token); return;
+ END
+ END
+ while (1);
+END
+
+ static void TeXNLS(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'a': Repl=CH_ae; break;
+ case 'e': Repl=CH_ee; break;
+ case 'i': Repl=CH_ie; break;
+ case 'o': Repl=CH_oe; break;
+ case 'u': Repl=CH_ue; break;
+ case 'A': Repl=CH_Ae; break;
+ case 'E': Repl=CH_Ee; break;
+ case 'I': Repl=CH_Ie; break;
+ case 'O': Repl=CH_Oe; break;
+ case 'U': Repl=CH_Ue; break;
+ case 's': Repl=CH_sz; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXNLSGrave(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'a': Repl=CH_agrave; break;
+ case 'A': Repl=CH_Agrave; break;
+ case 'e': Repl=CH_egrave; break;
+ case 'E': Repl=CH_Egrave; break;
+ case 'i': Repl=CH_igrave; break;
+ case 'I': Repl=CH_Igrave; break;
+ case 'o': Repl=CH_ograve; break;
+ case 'O': Repl=CH_Ograve; break;
+ case 'u': Repl=CH_ugrave; break;
+ case 'U': Repl=CH_Ugrave; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXNLSAcute(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'a': Repl=CH_aacute; break;
+ case 'A': Repl=CH_Aacute; break;
+ case 'e': Repl=CH_eacute; break;
+ case 'E': Repl=CH_Eacute; break;
+ case 'i': Repl=CH_iacute; break;
+ case 'I': Repl=CH_Iacute; break;
+ case 'o': Repl=CH_oacute; break;
+ case 'O': Repl=CH_Oacute; break;
+ case 'u': Repl=CH_uacute; break;
+ case 'U': Repl=CH_Uacute; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXNLSCirc(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'a': Repl=CH_acirc; break;
+ case 'A': Repl=CH_Acirc; break;
+ case 'e': Repl=CH_ecirc; break;
+ case 'E': Repl=CH_Ecirc; break;
+ case 'i': Repl=CH_icirc; break;
+ case 'I': Repl=CH_Icirc; break;
+ case 'o': Repl=CH_ocirc; break;
+ case 'O': Repl=CH_Ocirc; break;
+ case 'u': Repl=CH_ucirc; break;
+ case 'U': Repl=CH_Ucirc; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXNLSTilde(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'n': Repl=CH_ntilde; break;
+ case 'N': Repl=CH_Ntilde; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXCedilla(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("{"); collect_token(Token,"}");
+ if (strcmp(Token,"c")==0) strcpy(Token,CH_ccedil);
+ if (strcmp(Token,"C")==0) strcpy(Token,CH_Ccedil);
+
+ DoAddNormal(Token,BackSepString);
+END
+
+ static Boolean TeXNLSSpec(char *Line)
+BEGIN
+ Boolean Found=True;
+ char *Repl=Nil;
+ int cnt=0;
+
+ if (*SepString=='\0')
+ switch (*Line)
+ BEGIN
+ case 'o': cnt=1; Repl=CH_oslash; break;
+ case 'O': cnt=1; Repl=CH_Oslash; break;
+ case 'a':
+ switch (Line[1])
+ BEGIN
+ case 'a': cnt=2; Repl=CH_aring; break;
+ case 'e': cnt=2; Repl=CH_aelig; break;
+ default: Found=False;
+ END
+ break;
+ case 'A':
+ switch (Line[1])
+ BEGIN
+ case 'A': cnt=2; Repl=CH_Aring; break;
+ case 'E': cnt=2; Repl=CH_Aelig; break;
+ default: Found=False;
+ END
+ break;
+ default: Found=False;
+ END
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)!=cnt) memmove(Line+strlen(Repl),Line+cnt,strlen(Line)-cnt+1);
+ memcpy(Line,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Line);
+ return Found;
+END
+
+ static void TeXHyphenation(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("{"); collect_token(Token,"}");
+ AddException(Token);
+END
+
+ static void TeXDoPot(void)
+BEGIN
+ char Token[TOKLEN];
+
+ ReadToken(Token);
+ if (*Token=='2')
+ BEGIN
+ if (strlen(CH_e2)>1) memmove(Token+strlen(CH_e2),Token+1,strlen(Token));
+ memcpy(Token,CH_e2,strlen(CH_e2));
+ END
+ else DoAddNormal("^",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXDoSpec(void)
+BEGIN
+ strcpy(BackSepString,SepString);
+ TeXNLS(0);
+END
+
+ static void TeXInclude(Word Index)
+BEGIN
+ char Token[TOKLEN],Msg[TOKLEN];
+
+ assert_token("{"); collect_token(Token,"}");
+ if ((infiles[IncludeNest]=fopen(Token,"r"))==Nil)
+ BEGIN
+ sprintf(Msg,"file %s not found",Token);
+ error(Msg);
+ END
+ else IncludeNest++;
+END
+
+ static void TeXDocumentStyle(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ ReadToken(Token);
+ if (strcmp(Token,"[")==0)
+ BEGIN
+ do
+ BEGIN
+ ReadToken(Token);
+ if (strcmp(Token,"german")==0) SetLang(True);
+ END
+ while (strcmp(Token,"]")!=0);
+ assert_token("{");
+ ReadToken(Token);
+ if (strcasecmp(Token, "article") == 0)
+ BEGIN
+ AddInstTable(TeXTable,"section",0,TeXNewSection);
+ AddInstTable(TeXTable,"subsection",1,TeXNewSection);
+ AddInstTable(TeXTable,"subsubsection",3,TeXNewSection);
+ END
+ else
+ BEGIN
+ AddInstTable(TeXTable,"chapter",0,TeXNewSection);
+ AddInstTable(TeXTable,"section",1,TeXNewSection);
+ AddInstTable(TeXTable,"subsection",2,TeXNewSection);
+ AddInstTable(TeXTable,"subsubsection",3,TeXNewSection);
+ END
+ assert_token("}");
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+
+ int main(int argc, char **argv)
+BEGIN
+ char Line[TOKLEN],Comp[TOKLEN],*p,AuxFile[200];
+ int z;
+
+ if (argc<3)
+ BEGIN
+ fprintf(stderr,"calling convention: %s <input file> <output file>\n",*argv);
+ exit(1);
+ END
+
+ TeXTable=CreateInstTable(301);
+
+ IncludeNest=0;
+ if ((*infiles=fopen(argv[1],"r"))==Nil)
+ BEGIN
+ perror(argv[1]); exit(3);
+ END
+ else IncludeNest++;
+ infilename=argv[1];
+ if (strcmp(argv[2],"-")==0) outfile=stdout;
+ else if ((outfile=fopen(argv[2],"w"))==Nil)
+ BEGIN
+ perror(argv[2]); exit(3);
+ END
+
+ AddInstTable(TeXTable,"\\",0,TeXFlushLine);
+ AddInstTable(TeXTable,"par",0,TeXNewParagraph);
+ AddInstTable(TeXTable,"-",0,TeXDummy);
+ AddInstTable(TeXTable,"hyphenation",0,TeXHyphenation);
+ AddInstTable(TeXTable,"kill",0,TeXKillLine);
+ AddInstTable(TeXTable,"/",0,TeXDummy);
+ AddInstTable(TeXTable,"pagestyle",0,TeXDummyInCurl);
+ AddInstTable(TeXTable,"thispagestyle",0,TeXDummyInCurl);
+ AddInstTable(TeXTable,"sloppy",0,TeXDummy);
+ AddInstTable(TeXTable,"clearpage",0,TeXDummy);
+ AddInstTable(TeXTable,"cleardoublepage",0,TeXDummy);
+ AddInstTable(TeXTable,"topsep",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"parskip",0,TeXParSkip);
+ AddInstTable(TeXTable,"parindent",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"textwidth",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"evensidemargin",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"oddsidemargin",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"newcommand",0,TeXNewCommand);
+ AddInstTable(TeXTable,"def",0,TeXDef);
+ AddInstTable(TeXTable,"font",0,TeXFont);
+ AddInstTable(TeXTable,"documentstyle",0,TeXDocumentStyle);
+ AddInstTable(TeXTable,"appendix",0,TeXAppendix);
+ AddInstTable(TeXTable,"makeindex",0,TeXDummy);
+ AddInstTable(TeXTable,"begin",0,TeXBeginEnv);
+ AddInstTable(TeXTable,"end",0,TeXEndEnv);
+ AddInstTable(TeXTable,"item",0,TeXItem);
+ AddInstTable(TeXTable,"bibitem",0,TeXBibItem);
+ AddInstTable(TeXTable,"errentry",0,TeXErrEntry);
+ AddInstTable(TeXTable,"$",0,TeXAddDollar);
+ AddInstTable(TeXTable,"_",0,TeXAddUnderbar);
+ AddInstTable(TeXTable,"&",0,TeXAddAmpersand);
+ AddInstTable(TeXTable,"@",0,TeXAddAt);
+ AddInstTable(TeXTable,"#",0,TeXAddImm);
+ AddInstTable(TeXTable,"%",0,TeXAddPercent);
+ AddInstTable(TeXTable,"ss",0,TeXAddSSharp);
+ AddInstTable(TeXTable,"in",0,TeXAddIn);
+ AddInstTable(TeXTable,"rz",0,TeXAddReal);
+ AddInstTable(TeXTable,"mu",0,TeXAddGreekMu);
+ AddInstTable(TeXTable,"pi",0,TeXAddGreekPi);
+ AddInstTable(TeXTable,"leq",0,TeXAddLessEq);
+ AddInstTable(TeXTable,"geq",0,TeXAddGreaterEq);
+ AddInstTable(TeXTable,"neq",0,TeXAddNotEq);
+ AddInstTable(TeXTable,"mid",0,TeXAddMid);
+ AddInstTable(TeXTable,"frac",0,TeXDoFrac);
+ AddInstTable(TeXTable,"rm",FontStandard,TeXNewFontType);
+ AddInstTable(TeXTable,"em",FontEmphasized,TeXNewFontType);
+ AddInstTable(TeXTable,"bf",FontBold,TeXNewFontType);
+ AddInstTable(TeXTable,"tt",FontTeletype,TeXNewFontType);
+ AddInstTable(TeXTable,"it",FontItalic,TeXNewFontType);
+ AddInstTable(TeXTable,"bb",FontBold,TeXEnvNewFontType);
+ AddInstTable(TeXTable,"tty",FontTeletype,TeXEnvNewFontType);
+ AddInstTable(TeXTable,"ii",FontItalic,TeXEnvNewFontType);
+ AddInstTable(TeXTable,"tiny",FontTiny,TeXNewFontSize);
+ AddInstTable(TeXTable,"small",FontSmall,TeXNewFontSize);
+ AddInstTable(TeXTable,"normalsize",FontNormalSize,TeXNewFontSize);
+ AddInstTable(TeXTable,"large",FontLarge,TeXNewFontSize);
+ AddInstTable(TeXTable,"huge",FontHuge,TeXNewFontSize);
+ AddInstTable(TeXTable,"tin",FontTiny,TeXEnvNewFontSize);
+ AddInstTable(TeXTable,"rightarrow",0,TeXAddRightArrow);
+ AddInstTable(TeXTable,"longrightarrow",0,TeXAddLongRightArrow);
+ AddInstTable(TeXTable,"leftarrow",0,TeXAddLeftArrow);
+ AddInstTable(TeXTable,"leftrightarrow",0,TeXAddLeftRightArrow);
+ AddInstTable(TeXTable,"marginpar",0,TeXAddMarginPar);
+ AddInstTable(TeXTable,"caption",0,TeXAddCaption);
+ AddInstTable(TeXTable,"label",0,TeXWriteLabel);
+ AddInstTable(TeXTable,"ref",0,TeXWriteRef);
+ AddInstTable(TeXTable,"cite",0,TeXWriteCitation);
+ AddInstTable(TeXTable,"hline",0,TeXHorLine);
+ AddInstTable(TeXTable,"multicolumn",0,TeXMultiColumn);
+ AddInstTable(TeXTable,"ttindex",0,TeXIndex);
+ AddInstTable(TeXTable,"hspace",0,TeXHSpace);
+ AddInstTable(TeXTable,"vspace",0,TeXVSpace);
+ AddInstTable(TeXTable,"=",0,TeXAddTabStop);
+ AddInstTable(TeXTable,">",0,TeXJmpTabStop);
+ AddInstTable(TeXTable,"verb",0,TeXDoVerb);
+ AddInstTable(TeXTable,"printindex",0,TeXDummy);
+ AddInstTable(TeXTable,"tableofcontents",0,TeXContents);
+ AddInstTable(TeXTable,"rule",0,TeXRule);
+ AddInstTable(TeXTable,"\"",0,TeXNLS);
+ AddInstTable(TeXTable,"`",0,TeXNLSGrave);
+ AddInstTable(TeXTable,"'",0,TeXNLSAcute);
+ AddInstTable(TeXTable,"^",0,TeXNLSCirc);
+ AddInstTable(TeXTable,"~",0,TeXNLSTilde);
+ AddInstTable(TeXTable,"c",0,TeXCedilla);
+ AddInstTable(TeXTable,"newif",0,TeXDummy);
+ AddInstTable(TeXTable,"fi",0,TeXDummy);
+ AddInstTable(TeXTable,"ifelektor",0,TeXDummy);
+ AddInstTable(TeXTable,"elektortrue",0,TeXDummy);
+ AddInstTable(TeXTable,"elektorfalse",0,TeXDummy);
+ AddInstTable(TeXTable,"input",0,TeXInclude);
+
+ for (z=0; z<CHAPMAX; Chapters[z++]=0);
+ TableNum=0; FontNest=0;
+ TabStopCnt=0; CurrTabStop=0;
+ ErrState=FracState=(-1);
+ InAppendix=False;
+ EnvStack=Nil;
+ CurrEnv=EnvNone; CurrListDepth=0;
+ ActLeftMargin=LeftMargin=1; RightMargin=70;
+ Alignment=AlignNone;
+ EnumCounter=0;
+ CurrFontType=FontStandard; CurrFontSize=FontNormalSize;
+ FontStack=Nil; FirstRefSave=Nil; FirstCiteSave=Nil; FirstTocSave=Nil;
+ *SideMargin='\0';
+ DoRepass=False;
+ BibIndent=BibCounter=0;
+ GermanMode=True; SetLang(False);
+
+ strcpy(TocName,argv[1]);
+ if ((p=strrchr(TocName,'.'))!=Nil) *p='\0';
+ strcat(TocName,".dtoc");
+
+ strcpy(AuxFile,argv[1]);
+ if ((p=strrchr(AuxFile,'.'))!=Nil) *p='\0';
+ strcat(AuxFile,".daux");
+ ReadAuxFile(AuxFile);
+
+ while (1)
+ BEGIN
+ if (NOT ReadToken(Line)) break;
+ if (strcmp(Line,"\\")==0)
+ BEGIN
+ strcpy(BackSepString,SepString);
+ if (NOT ReadToken(Line)) error("unexpected end of file");
+ if (*SepString!='\0') BackToken(Line);
+ else if (NOT LookupInstTable(TeXTable,Line))
+ if (NOT TeXNLSSpec(Line))
+ BEGIN
+ sprintf(Comp,"unknown TeX command %s",Line);
+ warning(Comp);
+ END
+ END
+ else if (strcmp(Line,"$")==0)
+ BEGIN
+ if ((InMathMode=(NOT InMathMode)))
+ BEGIN
+ strcpy(BackSepString,SepString);
+ ReadToken(Line); strcpy(SepString,BackSepString);
+ BackToken(Line);
+ END
+ END
+ else if (strcmp(Line,"&")==0) NextTableColumn();
+ else if ((strcmp(Line,"^")==0) AND (InMathMode)) TeXDoPot();
+ else if ((strcmp(Line,"\"")==0) AND (GermanMode)) TeXDoSpec();
+ else if (strcmp(Line,"{")==0)
+ SaveFont();
+ else if (strcmp(Line,"}")==0)
+ if (FontNest>0) RestoreFont();
+ else if (ErrState>=0) NextErrState();
+ else if (FracState>=0) NextFracState();
+ else switch (CurrEnv)
+ BEGIN
+ case EnvMarginPar: RestoreEnv(); break;
+ case EnvCaption: FlushLine(); RestoreEnv(); break;
+ case EnvHeading: EndSectionHeading(); RestoreEnv(); break;
+ default: RestoreFont();
+ END
+ else DoAddNormal(Line,SepString);
+ END
+ FlushLine();
+ DestroyInstTable(TeXTable);
+
+ for (z=0; z<IncludeNest; fclose(infiles[z++]));
+ fclose(outfile);
+
+ unlink(AuxFile);
+ PrintLabels(AuxFile); PrintCites(AuxFile);
+ PrintToc(TocName);
+
+ if (DoRepass) fprintf(stderr,"additional pass recommended\n");
+
+ return 0;
+END
+
+#ifdef CKMALLOC
+#undef malloc
+#undef realloc
+
+ void *ckmalloc(size_t s)
+BEGIN
+ void *tmp=malloc(s);
+ if (tmp==NULL)
+ BEGIN
+ fprintf(stderr,"allocation error(malloc): out of memory");
+ exit(255);
+ END
+ return tmp;
+END
+
+ void *ckrealloc(void *p, size_t s)
+BEGIN
+ void *tmp=realloc(p,s);
+ if (tmp==NULL)
+ BEGIN
+ fprintf(stderr,"allocation error(realloc): out of memory");
+ exit(255);
+ END
+ return tmp;
+END
+#endif
+
diff --git a/tex2html.c b/tex2html.c
new file mode 100644
index 0000000..dc1dcbb
--- /dev/null
+++ b/tex2html.c
@@ -0,0 +1,2570 @@
+/* tex2html.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Konverter TeX-->HTML */
+/* */
+/* Historie: 2. 4.1998 Grundsteinlegung (Transfer von tex2doc.c) */
+/* 5. 4.1998 Sonderzeichen, Fonts, <> */
+/* 6. 4.1998 geordnete Listen */
+/* 20. 6.1998 Ausrichtung links/rechts/zentriert */
+/* überlagerte Textattribute */
+/* mehrspaltiger Index */
+/* 5. 7.1998 Korrekturen in der Index-Ausgabe */
+/* 11. 7.1998 weitere Landessonderzeichen */
+/* 13. 7.1998 Cedilla */
+/* 12. 9.1998 input-Statement */
+/* 12. 1.1999 andere Kapitelhierarchie fuer article */
+/* 28. 3.1999 TeX-Kommando Huge ergaenzt */
+/* 14. 6.1999 mit optionaler Aufspaltung in Subdateien begonnen */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include "asmitree.h"
+#include "chardefs.h"
+#include <ctype.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <string.h>
+#include "strutil.h"
+
+/*--------------------------------------------------------------------------*/
+
+#define TOKLEN 350
+
+static char *TableName,
+ *BiblioName,
+ *ContentsName,
+ *IndexName,
+#define ErrorEntryCnt 3
+ *ErrorEntryNames[ErrorEntryCnt];
+
+typedef enum{EnvNone,EnvDocument,EnvItemize,EnvEnumerate,EnvDescription,EnvTable,
+ EnvTabular,EnvRaggedLeft,EnvRaggedRight,EnvCenter,EnvVerbatim,
+ EnvQuote,EnvTabbing,EnvBiblio,EnvMarginPar,EnvCaption,EnvHeading,EnvCount} EnvType;
+
+typedef enum{FontStandard,FontEmphasized,FontBold,FontTeletype,FontItalic,FontSuper,FontCnt} TFontType;
+static char *FontNames[FontCnt]={"","EM","B","TT","I","SUP"};
+#define MFontEmphasized (1<<FontEmphasized)
+#define MFontBold (1<<FontBold)
+#define MFontTeletype (1<<FontTeletype)
+#define MFontItalic (1<<FontItalic)
+typedef enum{FontTiny,FontSmall,FontNormalSize,FontLarge,FontHuge} TFontSize;
+
+typedef struct _TEnvSave
+ {
+ struct _TEnvSave *Next;
+ EnvType SaveEnv;
+ int ListDepth,ActLeftMargin,LeftMargin,RightMargin;
+ int EnumCounter,FontNest;
+ Boolean InListItem;
+ } TEnvSave,*PEnvSave;
+
+typedef struct _TFontSave
+ {
+ struct _TFontSave *Next;
+ int FontFlags;
+ TFontSize FontSize;
+ } TFontSave,*PFontSave;
+
+typedef enum{ColLeft,ColRight,ColCenter,ColBar} TColumn;
+#define MAXCOLS 30
+#define MAXROWS 200
+typedef char *TableLine[MAXCOLS];
+typedef struct
+ {
+ int ColumnCount,TColumnCount;
+ TColumn ColTypes[MAXCOLS];
+ int ColLens[MAXCOLS];
+ int LineCnt;
+ TableLine Lines[MAXROWS];
+ Boolean LineFlags[MAXROWS];
+ Boolean MultiFlags[MAXROWS];
+ } TTable;
+
+typedef struct _TRefSave
+ {
+ struct _TRefSave *Next;
+ char *RefName,*Value;
+ } TRefSave,*PRefSave;
+
+typedef struct _TTocSave
+ {
+ struct _TTocSave *Next;
+ char *TocName;
+ } TTocSave,*PTocSave;
+
+typedef struct _TIndexSave
+ {
+ struct _TIndexSave *Next;
+ char *Name;
+ int RefCnt;
+ } TIndexSave,*PIndexSave;
+
+static char *EnvNames[EnvCount]=
+ {"___NONE___","document","itemize","enumerate","description","table","tabular",
+ "raggedleft","raggedright","center","verbatim","quote","tabbing",
+ "thebibliography","___MARGINPAR___","___CAPTION___","___HEADING___"};
+
+static int IncludeNest;
+static FILE *infiles[50],*outfile;
+static char *infilename, *outfilename;
+static char TocName[200];
+static int CurrLine=0,CurrColumn;
+
+#define CHAPMAX 6
+static int Chapters[CHAPMAX];
+static int TableNum,FontNest,ErrState,FracState,BibIndent,BibCounter;
+#define TABMAX 100
+static int TabStops[TABMAX],TabStopCnt,CurrTabStop;
+static Boolean InAppendix,InMathMode,DoRepass,InListItem;
+static TTable ThisTable;
+static int CurrRow,CurrCol;
+static Boolean GermanMode;
+
+static int Structured;
+
+static EnvType CurrEnv;
+static int CurrFontFlags;
+static TFontSize CurrFontSize;
+static int CurrListDepth;
+static int EnumCounter;
+static int ActLeftMargin,LeftMargin,RightMargin;
+static PEnvSave EnvStack;
+static PFontSave FontStack;
+static PRefSave FirstRefSave,FirstCiteSave;
+static PTocSave FirstTocSave;
+static PIndexSave FirstIndex;
+
+static PInstTable TeXTable;
+
+/*--------------------------------------------------------------------------*/
+
+ void ChkStack(void)
+BEGIN
+END
+
+ static void error(char *Msg)
+BEGIN
+ int z;
+
+ fprintf(stderr,"%s:%d.%d: %s\n",infilename,CurrLine,CurrColumn,Msg);
+ for (z=0; z<IncludeNest; fclose(infiles[z++])); fclose(outfile);
+ exit(2);
+END
+
+ static void warning(char *Msg)
+BEGIN
+ fprintf(stderr,"%s:%d.%d: %s\n",infilename,CurrLine,CurrColumn,Msg);
+END
+
+ static void SetLang(Boolean IsGerman)
+BEGIN
+ if (GermanMode==IsGerman) return;
+
+ if ((GermanMode=IsGerman))
+ BEGIN
+ TableName="Tabelle";
+ BiblioName="Literaturverzeichnis";
+ ContentsName="Inhalt";
+ IndexName="Index";
+ ErrorEntryNames[0]="Typ";
+ ErrorEntryNames[1]="Ursache";
+ ErrorEntryNames[2]="Argument";
+ END
+ else
+ BEGIN
+ TableName="Table";
+ BiblioName="Bibliography";
+ ContentsName="Contents";
+ IndexName="Index";
+ ErrorEntryNames[0]="Type";
+ ErrorEntryNames[1]="Reason";
+ ErrorEntryNames[2]="Argument";
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void AddLabel(char *Name, char *Value)
+BEGIN
+ PRefSave Run,Prev,Neu;
+ int cmp;
+ char err[200];
+
+ for (Run=FirstRefSave,Prev=Nil; Run!=Nil; Prev=Run,Run=Run->Next)
+ if ((cmp=strcmp(Run->RefName,Name))>=0) break;
+
+ if ((Run!=Nil) AND (cmp==0))
+ BEGIN
+ if (strcmp(Run->Value,Value)!=0)
+ BEGIN
+ sprintf(err,"value of label '%s' has changed",Name);
+ warning(err); DoRepass=True;
+ free(Run->Value); Run->Value=strdup(Value);
+ END
+ END
+ else
+ BEGIN
+ Neu=(PRefSave) malloc(sizeof(TRefSave));
+ Neu->RefName=strdup(Name);
+ Neu->Value=strdup(Value);
+ Neu->Next=Run;
+ if (Prev==Nil) FirstRefSave=Neu; else Prev->Next=Neu;
+ END
+END
+
+ static void AddCite(char *Name, char *Value)
+BEGIN
+ PRefSave Run,Prev,Neu;
+ int cmp;
+ char err[200];
+
+ for (Run=FirstCiteSave,Prev=Nil; Run!=Nil; Prev=Run,Run=Run->Next)
+ if ((cmp=strcmp(Run->RefName,Name))>=0) break;
+
+ if ((Run!=Nil) AND (cmp==0))
+ BEGIN
+ if (strcmp(Run->Value,Value)!=0)
+ BEGIN
+ sprintf(err,"value of citation '%s' has changed",Name);
+ warning(err); DoRepass=True;
+ free(Run->Value); Run->Value=strdup(Value);
+ END
+ END
+ else
+ BEGIN
+ Neu=(PRefSave) malloc(sizeof(TRefSave));
+ Neu->RefName=strdup(Name);
+ Neu->Value=strdup(Value);
+ Neu->Next=Run;
+ if (Prev==Nil) FirstCiteSave=Neu; else Prev->Next=Neu;
+ END
+END
+
+ static void GetLabel(char *Name, char *Dest)
+BEGIN
+ PRefSave Run;
+ char err[200];
+
+ for (Run=FirstRefSave; Run!=Nil; Run=Run->Next)
+ if (strcmp(Name,Run->RefName)==0) break;
+
+ if (Run==Nil)
+ BEGIN
+ sprintf(err,"undefined label '%s'",Name);
+ warning(err); DoRepass=True;
+ END
+ strcpy(Dest,(Run==Nil) ? "???" : Run->Value);
+END
+
+ static void GetCite(char *Name, char *Dest)
+BEGIN
+ PRefSave Run;
+ char err[200];
+
+ for (Run=FirstCiteSave; Run!=Nil; Run=Run->Next)
+ if (strcmp(Name,Run->RefName)==0) break;
+
+ if (Run==Nil)
+ BEGIN
+ sprintf(err,"undefined citation '%s'",Name);
+ warning(err); DoRepass=True;
+ END
+ strcpy(Dest,(Run==Nil) ? "???" : Run->Value);
+END
+
+ static void PrintLabels(char *Name)
+BEGIN
+ PRefSave Run;
+ FILE *file=fopen(Name,"a");
+
+ if (file==Nil) perror(Name);
+
+ for (Run=FirstRefSave; Run!=Nil; Run=Run->Next)
+ fprintf(file,"Label %s %s\n",Run->RefName,Run->Value);
+ fclose(file);
+END
+
+ static void PrintCites(char *Name)
+BEGIN
+ PRefSave Run;
+ FILE *file=fopen(Name,"a");
+
+ if (file==Nil) perror(Name);
+
+ for (Run=FirstCiteSave; Run!=Nil; Run=Run->Next)
+ fprintf(file,"Citation %s %s\n",Run->RefName,Run->Value);
+ fclose(file);
+END
+
+ static void PrintToc(char *Name)
+BEGIN
+ PTocSave Run;
+ FILE *file=fopen(Name,"w");
+
+ if (file==Nil) perror(Name);
+
+ for (Run=FirstTocSave; Run!=Nil; Run=Run->Next)
+ fprintf(file,"%s\n\n",Run->TocName);
+ fclose(file);
+END
+
+/*------------------------------------------------------------------------------*/
+
+
+ static void GetNext(char *Src, char *Dest)
+BEGIN
+ char *c=strchr(Src,' ');
+
+ if (c==Nil)
+ BEGIN
+ strcpy(Dest,Src); *Src='\0';
+ END
+ else
+ BEGIN
+ *c='\0'; strcpy(Dest,Src);
+ for (c++; *c==' '; c++);
+ strcpy(Src,c);
+ END
+END
+
+ static void ReadAuxFile(char *Name)
+BEGIN
+ FILE *file=fopen(Name,"r");
+ char Line[300],Cmd[300],Nam[300],Val[300];
+
+ if (file==Nil) return;
+
+ while (NOT feof(file))
+ BEGIN
+ if (fgets(Line,299,file)==Nil) break;
+ if (Line[strlen(Line)-1]=='\n') Line[strlen(Line)-1]='\0';
+ GetNext(Line,Cmd);
+ if (strcmp(Cmd,"Label")==0)
+ BEGIN
+ GetNext(Line,Nam); GetNext(Line,Val);
+ AddLabel(Nam,Val);
+ END
+ else if (strcmp(Cmd,"Citation")==0)
+ BEGIN
+ GetNext(Line,Nam); GetNext(Line,Val);
+ AddCite(Nam,Val);
+ END
+ END
+
+ fclose(file);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static Boolean issep(char inp)
+BEGIN
+ return ((inp==' ') OR (inp=='\t') OR (inp=='\n'));
+END
+
+ static Boolean isalphanum(char inp)
+BEGIN
+ return ((inp>='A') AND (inp<='Z'))
+ OR ((inp>='a') AND (inp<='z'))
+ OR ((inp>='0') AND (inp<='9'))
+ OR (inp=='.');
+END
+
+static char LastChar='\0';
+static char SaveSep='\0',SepString[TOKLEN]="";
+static Boolean DidEOF=False;
+static char BufferLine[TOKLEN]="",*BufferPtr=BufferLine;
+typedef struct
+ {
+ char Token[TOKLEN],Sep[TOKLEN];
+ } PushedToken;
+static int PushedTokenCnt=0;
+static PushedToken PushedTokens[16];
+
+ static int GetChar(void)
+BEGIN
+ Boolean Comment;
+ static Boolean DidPar=False;
+ char *Result;
+
+ if (*BufferPtr=='\0')
+ BEGIN
+ do
+ BEGIN
+ if (IncludeNest<=0) return EOF;
+ do
+ BEGIN
+ Result=fgets(BufferLine,TOKLEN,infiles[IncludeNest-1]);
+ if (Result!=Nil) break;
+ fclose(infiles[--IncludeNest]);
+ if (IncludeNest<=0) return EOF;
+ END
+ while (True);
+ CurrLine++;
+ BufferPtr=BufferLine;
+ Comment=(strlen(BufferLine)>=2) AND (strncmp(BufferLine,"%%",2)==0);
+ if ((*BufferLine=='\0') OR (*BufferLine=='\n'))
+ BEGIN
+ if ((CurrEnv==EnvDocument) AND (NOT DidPar))
+ BEGIN
+ strcpy(BufferLine,"\\par\n"); DidPar=True; Comment=False;
+ END
+ END
+ else if (Comment)
+ BEGIN
+ if (BufferLine[strlen(BufferLine)-1]=='\n')
+ BufferLine[strlen(BufferLine)-1]='\0';
+ if (strncmp(BufferLine+2,"TITLE ",6)==0)
+ fprintf(outfile,"<TITLE>%s</TITLE>\n",BufferLine+8);
+ END
+ else DidPar=False;
+ END
+ while (Comment);
+ END
+ return *(BufferPtr++);
+END
+
+ static Boolean ReadToken(char *Dest)
+BEGIN
+ int ch,z;
+ Boolean Good;
+ char *run;
+
+ if (PushedTokenCnt>0)
+ BEGIN
+ strcpy(Dest,PushedTokens[0].Token); strcpy(SepString,PushedTokens[0].Sep);
+ for (z=0; z<PushedTokenCnt-1; z++) PushedTokens[z]=PushedTokens[z+1];
+ PushedTokenCnt--;
+ return True;
+ END
+
+ if (DidEOF) return FALSE;
+
+ CurrColumn=BufferPtr-BufferLine+1;
+
+ /* falls kein Zeichen gespeichert, fuehrende Blanks ueberspringen */
+
+ *Dest='\0'; *SepString=SaveSep; run=SepString+((SaveSep=='\0')?0:1);
+ if (LastChar=='\0')
+ BEGIN
+ do
+ BEGIN
+ ch=GetChar(); if (ch=='\r') ch=GetChar();
+ if (issep(ch)) *(run++)=' ';
+ END
+ while ((issep(ch)) AND (ch!=EOF));
+ *run='\0';
+ if (ch==EOF)
+ BEGIN
+ DidEOF=TRUE; return FALSE;
+ END
+ END
+ else
+ BEGIN
+ ch=LastChar; LastChar='\0';
+ END
+
+ /* jetzt Zeichen kopieren, bis Leerzeichen */
+
+ run=Dest;
+ SaveSep='\0';
+ if (isalphanum(*(run++)=ch))
+ BEGIN
+ do
+ BEGIN
+ ch=GetChar();
+ Good=(NOT issep(ch)) AND (isalphanum(ch)) AND (ch!=EOF);
+ if (Good) *(run++)=ch;
+ END
+ while (Good);
+
+ /* Dateiende ? */
+
+ if (ch==EOF) DidEOF=TRUE;
+
+ /* Zeichen speichern ? */
+
+ else if ((NOT issep(ch)) AND (NOT isalphanum(ch))) LastChar=ch;
+
+ /* Separator speichern ? */
+
+ else if (issep(ch)) SaveSep=' ';
+ END
+
+ /* Ende */
+
+ *run='\0'; return True;
+END
+
+ static void BackToken(char *Token)
+BEGIN
+ if (PushedTokenCnt>=16) return;
+ strcpy(PushedTokens[PushedTokenCnt].Token,Token);
+ strcpy(PushedTokens[PushedTokenCnt].Sep,SepString);
+ PushedTokenCnt++;
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void assert_token(char *ref)
+BEGIN
+ char token[TOKLEN];
+
+ ReadToken(token);
+ if (strcmp(ref,token)!=0)
+ BEGIN
+ sprintf(token,"\"%s\" expected",ref); error(token);
+ END
+END
+
+ static void collect_token(char *dest, char *term)
+BEGIN
+ char Comp[TOKLEN];
+ Boolean first=TRUE,done;
+
+ *dest='\0';
+ do
+ BEGIN
+ ReadToken(Comp);
+ done=(strcmp(Comp,term)==0);
+ if (NOT done)
+ BEGIN
+ if (NOT first) strcat(dest,SepString);
+ strcat(dest,Comp);
+ END
+ first=False;
+ END
+ while (NOT done);
+END
+
+/*--------------------------------------------------------------------------*/
+
+static char OutLineBuffer[TOKLEN]="",SideMargin[TOKLEN];
+
+ static void PutLine(Boolean DoBlock)
+BEGIN
+ int l,n,ptrcnt,diff,div,mod,divmod;
+ char *chz,*ptrs[50];
+ Boolean SkipFirst,IsFirst;
+
+ fputs(Blanks(LeftMargin-1),outfile);
+ if ((CurrEnv==EnvRaggedRight) OR (NOT DoBlock))
+ BEGIN
+ fprintf(outfile,"%s",OutLineBuffer);
+ l=strlen(OutLineBuffer);
+ END
+ else
+ BEGIN
+ SkipFirst=((CurrEnv==EnvItemize) OR (CurrEnv==EnvEnumerate) OR (CurrEnv==EnvDescription) OR (CurrEnv==EnvBiblio));
+ if (LeftMargin==ActLeftMargin) SkipFirst=False;
+ l=ptrcnt=0; IsFirst=SkipFirst;
+ for (chz=OutLineBuffer; *chz!='\0'; chz++)
+ BEGIN
+ if ((chz>OutLineBuffer) AND (*(chz-1)!=' ') AND (*chz==' '))
+ BEGIN
+ if (NOT IsFirst) ptrs[ptrcnt++]=chz;
+ IsFirst=False;
+ END
+ l++;
+ END
+ diff=RightMargin-LeftMargin+1-l;
+ div=(ptrcnt>0) ? diff/ptrcnt : 0; mod=diff-(ptrcnt*div);
+ divmod=(mod>0) ? ptrcnt/mod : ptrcnt+1;
+ IsFirst=SkipFirst;
+ ptrcnt=0;
+ for (chz=OutLineBuffer; *chz!='\0'; chz++)
+ BEGIN
+ fputc(*chz,outfile);
+ if ((chz>OutLineBuffer) AND (*(chz-1)!=' ') AND (*chz==' '))
+ BEGIN
+ if (NOT IsFirst)
+ BEGIN
+ n=div;
+ if ((mod>0) AND ((ptrcnt%divmod)==0))
+ BEGIN
+ mod--; n++;
+ END
+ if (n>0) fputs(Blanks(n),outfile);
+ ptrcnt++;
+ END
+ IsFirst=False;
+ END
+ END
+ l=RightMargin-LeftMargin+1;
+ END
+ if (*SideMargin!='\0')
+ BEGIN
+ fputs(Blanks(RightMargin-LeftMargin+4-l),outfile);
+#if 0
+ fprintf(outfile,"%s",SideMargin);
+#endif
+ *SideMargin='\0';
+ END
+ fputc('\n',outfile);
+ LeftMargin=ActLeftMargin;
+END
+
+ static void AddLine(char *Part, char *Sep)
+BEGIN
+ int mlen=RightMargin-LeftMargin+1;
+ char *search,save;
+
+ if (strlen(Sep)>1) Sep[1]='\0';
+ if (*OutLineBuffer!='\0') strcat(OutLineBuffer,Sep);
+ strcat(OutLineBuffer,Part);
+ if (strlen(OutLineBuffer)>=mlen)
+ BEGIN
+ search=OutLineBuffer+mlen;
+ while (search>=OutLineBuffer)
+ BEGIN
+ if (*search==' ') break;
+ search--;
+ END
+ if (search<=OutLineBuffer)
+ BEGIN
+ PutLine(False); *OutLineBuffer='\0';
+ END
+ else
+ BEGIN
+ save=(*search); *search='\0';
+ PutLine(False); *search=save;
+ for (; *search==' '; search++);
+ strcpy(OutLineBuffer,search);
+ END
+ END
+END
+
+ static void AddSideMargin(char *Part, char *Sep)
+BEGIN
+ if (strlen(Sep)>1) Sep[1]='\0';
+ if (*Sep!='\0')
+ if ((*SideMargin!='\0') OR (NOT issep(*Sep))) strcat(SideMargin,Sep);
+ strcat(SideMargin,Part);
+END
+
+ static void FlushLine(void)
+BEGIN
+ if (*OutLineBuffer!='\0')
+ BEGIN
+ PutLine(False);
+ *OutLineBuffer='\0';
+ END
+END
+
+ static void ResetLine(void)
+BEGIN
+ *OutLineBuffer='\0';
+END
+
+ static void AddTableEntry(char *Part, char *Sep)
+BEGIN
+ char *Ptr=ThisTable.Lines[CurrRow][CurrCol];
+ int nlen=(Ptr==Nil) ? 0 : strlen(Ptr);
+ Boolean UseSep=(nlen>0);
+
+ if (strlen(Sep)>1) Sep[1]='\0';
+ if (UseSep) nlen+=strlen(Sep); nlen+=strlen(Part);
+ if (Ptr==Nil)
+ BEGIN
+ Ptr=(char *) malloc(nlen+1); *Ptr='\0';
+ END
+ else Ptr=(char *) realloc(Ptr,nlen+1);
+ if (UseSep) strcat(Ptr,Sep); strcat(Ptr,Part);
+ ThisTable.Lines[CurrRow][CurrCol]=Ptr;
+END
+
+ static void DoAddNormal(char *Part, char *Sep)
+BEGIN
+ if (strcmp(Part,"<")==0) Part="&lt;";
+ else if (strcmp(Part,">")==0) Part="&gt;";
+ else if (strcmp(Part,"&")==0) Part="&amp;";
+
+ switch (CurrEnv)
+ BEGIN
+ case EnvMarginPar: AddSideMargin(Part,Sep); break;
+ case EnvTabular: AddTableEntry(Part,Sep); break;
+ default: AddLine(Part,Sep);
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+
+ static void SaveFont(void)
+BEGIN
+ PFontSave NewSave;
+
+ NewSave=(PFontSave) malloc(sizeof(TFontSave));
+ NewSave->Next=FontStack;
+ NewSave->FontSize=CurrFontSize;
+ NewSave->FontFlags=CurrFontFlags;
+ FontStack=NewSave; FontNest++;
+END
+
+ static void PrFontDiff(int OldFlags, int NewFlags)
+BEGIN
+ TFontType z;
+ int Mask;
+ char erg[10];
+
+ for (z=FontStandard+1,Mask=2; z<FontCnt; z++,Mask=Mask<<1)
+ if ((OldFlags^NewFlags)&Mask)
+ BEGIN
+ sprintf(erg,"<%s%s>",(NewFlags&Mask)?"":"/",FontNames[z]);
+ DoAddNormal(erg,"");
+ END
+END
+
+ static void PrFontSize(TFontSize Type, Boolean On)
+BEGIN
+ char erg[10];
+
+ strcpy(erg,"<");
+ if (FontNormalSize==Type) return;
+
+ if (NOT On) strcat(erg,"/");
+ switch (Type)
+ BEGIN
+ case FontTiny:
+ case FontSmall: strcat(erg,"SMALL"); break;
+ case FontLarge:
+ case FontHuge: strcat(erg,"BIG"); break;
+ default: break;
+ END
+ strcat (erg,">");
+ DoAddNormal(erg,"");
+ if ((FontTiny==Type) OR (FontHuge==Type)) DoAddNormal(erg,"");
+END
+
+ static void RestoreFont(void)
+BEGIN
+ PFontSave OldSave;
+
+ if (FontStack==Nil) return;
+
+ PrFontDiff(CurrFontFlags,FontStack->FontFlags);
+ PrFontSize(CurrFontSize,False);
+
+ OldSave=FontStack; FontStack=FontStack->Next;
+ CurrFontSize=OldSave->FontSize;
+ CurrFontFlags=OldSave->FontFlags;
+ free(OldSave);
+ FontNest--;
+END
+
+ static void SaveEnv(EnvType NewEnv)
+BEGIN
+ PEnvSave NewSave;
+
+ NewSave=(PEnvSave) malloc(sizeof(TEnvSave));
+ NewSave->Next=EnvStack;
+ NewSave->ListDepth=CurrListDepth;
+ NewSave->LeftMargin=LeftMargin;
+ NewSave->ActLeftMargin=ActLeftMargin;
+ NewSave->RightMargin=RightMargin;
+ NewSave->EnumCounter=EnumCounter;
+ NewSave->SaveEnv=CurrEnv;
+ NewSave->FontNest=FontNest;
+ NewSave->InListItem=InListItem;
+ EnvStack=NewSave;
+ CurrEnv=NewEnv;
+ FontNest=0;
+END
+
+ static void RestoreEnv(void)
+BEGIN
+ PEnvSave OldSave;
+
+ OldSave=EnvStack; EnvStack=OldSave->Next;
+ CurrListDepth=OldSave->ListDepth;
+ LeftMargin=OldSave->LeftMargin;
+ ActLeftMargin=OldSave->ActLeftMargin;
+ RightMargin=OldSave->RightMargin;
+ EnumCounter=OldSave->EnumCounter;
+ FontNest=OldSave->FontNest;
+ InListItem=OldSave->InListItem;
+ CurrEnv=OldSave->SaveEnv;
+ free(OldSave);
+END
+
+ static void InitTableRow(int Index)
+BEGIN
+ int z;
+
+ for (z=0; z<ThisTable.TColumnCount; ThisTable.Lines[Index][z++]=Nil);
+ ThisTable.MultiFlags[Index]=False;
+ ThisTable.LineFlags[Index]=False;
+END
+
+ static void NextTableColumn(void)
+BEGIN
+ if (CurrEnv!=EnvTabular) error("table separation char not within tabular environment");
+
+ if ((ThisTable.MultiFlags[CurrRow])
+ OR (CurrCol>=ThisTable.TColumnCount))
+ error("too many columns within row");
+
+ CurrCol++;
+END
+
+ static void DumpTable(void)
+BEGIN
+ int TextCnt,RowCnt,rowz,rowz2,rowz3,colz,colptr,ml,l,diff,sumlen,firsttext,indent;
+ char *ColTag;
+
+ /* compute widths of individual rows */
+ /* get index of first text column */
+
+ RowCnt=(ThisTable.Lines[CurrRow][0]!=Nil) ? CurrRow+1 : CurrRow;
+ firsttext=(-1);
+ for (colz=colptr=0; colz<ThisTable.ColumnCount; colz++)
+ if (ThisTable.ColTypes[colz]==ColBar) ThisTable.ColLens[colz]=1;
+ else
+ BEGIN
+ ml=0;
+ for (rowz=0; rowz<RowCnt; rowz++)
+ if ((NOT ThisTable.LineFlags[rowz]) AND (NOT ThisTable.MultiFlags[rowz]))
+ BEGIN
+ l=(ThisTable.Lines[rowz][colptr]==Nil) ? 0 : strlen(ThisTable.Lines[rowz][colptr]);
+ if (ml<l) ml=l;
+ END
+ ThisTable.ColLens[colz]=ml+2;
+ colptr++;
+ if (firsttext<0) firsttext=colz;
+ END
+
+ /* count number of text columns */
+
+ for (colz=TextCnt=0; colz<ThisTable.ColumnCount; colz++)
+ if (ThisTable.ColTypes[colz]!=ColBar) TextCnt++;
+
+ /* get total width */
+
+ for (colz=sumlen=0; colz<ThisTable.ColumnCount; sumlen+=ThisTable.ColLens[colz++]);
+ indent=(RightMargin-LeftMargin+1-sumlen)/2; if (indent<0) indent=0;
+
+ /* search for multicolumns and extend first field if table is too lean */
+
+ ml=0;
+ for (rowz=0; rowz<RowCnt; rowz++)
+ if ((NOT ThisTable.LineFlags[rowz]) AND (ThisTable.MultiFlags[rowz]))
+ BEGIN
+ l=(ThisTable.Lines[rowz][0]==Nil) ? 0 : strlen(ThisTable.Lines[rowz][0]);
+ if (ml<l) ml=l;
+ END
+ if (ml+4>sumlen)
+ BEGIN
+ diff=ml+4-sumlen;
+ ThisTable.ColLens[firsttext]+=diff;
+ END
+
+ /* tell browser to switch to table mode */
+
+ fprintf(outfile,"<P><CENTER><TABLE SUMMARY=\"No Summary\" BORDER=1 CELLPADDING=5>\n");
+
+ /* print rows */
+
+ rowz=0;
+ while (rowz<RowCnt)
+ BEGIN
+ /* find first text line */
+
+ for (; rowz<RowCnt; rowz++)
+ if (NOT ThisTable.LineFlags[rowz]) break;
+
+ /* find last text line */
+
+ for (rowz2=rowz; rowz2<RowCnt; rowz2++)
+ if (ThisTable.LineFlags[rowz2]) break;
+ rowz2--;
+
+ if (rowz<RowCnt)
+ BEGIN
+ /* if more than one line follows, take this as header line(s) */
+
+ if ((rowz2<=RowCnt-3) AND (ThisTable.LineFlags[rowz2+1]) AND (ThisTable.LineFlags[rowz2+2]))
+ ColTag="TH";
+ else
+ ColTag="TD";
+
+ /* start a row */
+
+ fprintf(outfile,"<TR ALIGN=LEFT>\n");
+
+ /* over all columns... */
+
+ colptr=0;
+ for (colz=0; colz<((ThisTable.MultiFlags[rowz])?firsttext+1:ThisTable.ColumnCount); colz++)
+ if (ThisTable.ColTypes[colz]!=ColBar)
+ BEGIN
+ /* start a column */
+
+ fprintf(outfile,"<%s VALIGN=TOP NOWRAP",ColTag);
+ if (ThisTable.MultiFlags[rowz]) fprintf(outfile," COLSPAN=%d",TextCnt);
+ switch(ThisTable.ColTypes[colz])
+ BEGIN
+ case ColLeft: fputs(" ALIGN=LEFT>",outfile); break;
+ case ColCenter: fputs(" ALIGN=CENTER>",outfile); break;
+ case ColRight: fputs(" ALIGN=RIGHT>",outfile); break;
+ default: break;
+ END
+
+ /* write items */
+
+ for (rowz3=rowz; rowz3<=rowz2; rowz3++)
+ BEGIN
+ if (ThisTable.Lines[rowz3][colptr]!=Nil)
+ BEGIN
+ fputs(ThisTable.Lines[rowz3][colptr],outfile);
+ free(ThisTable.Lines[rowz3][colptr]);
+ END
+ if (rowz3!=rowz2) fputs("<BR>\n",outfile);
+ END
+
+ /* end column */
+
+ fprintf(outfile,"</%s>\n",ColTag);
+
+ colptr++;
+ END
+
+ /* end row */
+
+ fprintf(outfile,"</TR>\n");
+
+ rowz=rowz2+1;
+ END
+ END
+
+ /* end table mode */
+
+ fprintf(outfile,"</TABLE></CENTER>\n");
+END
+
+ static void GetTableName(char *Dest)
+BEGIN
+ if (InAppendix) sprintf(Dest,"%c.%d",Chapters[0]+'A',TableNum);
+ else sprintf(Dest,"%d.%d",Chapters[0],TableNum);
+END
+
+ static char *GetSectionName(char *Dest)
+BEGIN
+ char *run=Dest;
+ int z;
+
+ for (z=0; z<=2; z++)
+ BEGIN
+ if ((z>0) AND (Chapters[z]==0)) break;
+ if ((InAppendix) AND (z==0))
+ run+=sprintf(run,"%c.",Chapters[z]+'A');
+ else run+=sprintf(run,"%d.",Chapters[z]);
+ END
+ return run;
+END
+
+ static void AddToc(char *Line)
+BEGIN
+ PTocSave NewTocSave,RunToc;
+
+ NewTocSave=(PTocSave) malloc(sizeof(TTocSave));
+ NewTocSave->Next=Nil;
+ NewTocSave->TocName=strdup(Line);
+ if (FirstTocSave==Nil) FirstTocSave=NewTocSave;
+ else
+ BEGIN
+ for (RunToc=FirstTocSave; RunToc->Next!=Nil; RunToc=RunToc->Next);
+ RunToc->Next=NewTocSave;
+ END
+END
+
+/*--------------------------------------------------------------------------*/
+
+static char BackSepString[TOKLEN];
+
+ static void TeXFlushLine(Word Index)
+BEGIN
+ if (CurrEnv==EnvTabular)
+ BEGIN
+ for (CurrCol++; CurrCol<ThisTable.TColumnCount; ThisTable.Lines[CurrRow][CurrCol++]=strdup(""));
+ CurrRow++;
+ if (CurrRow==MAXROWS) error("too many rows in table");
+ InitTableRow(CurrRow); CurrCol=0;
+ END
+ else if (CurrEnv==EnvTabbing)
+ BEGIN
+ CurrTabStop=0;
+ PrFontDiff(CurrFontFlags,0);
+ AddLine("</TD></TR>",""); FlushLine();
+ AddLine("<TR><TD NOWRAP>","");
+ PrFontDiff(0,CurrFontFlags);
+ END
+ else
+ BEGIN
+ if (*OutLineBuffer=='\0') strcpy(OutLineBuffer," ");
+ AddLine("<BR>",""); FlushLine();
+ END
+END
+
+ static void TeXKillLine(Word Index)
+BEGIN
+ ResetLine();
+ if (CurrEnv==EnvTabbing)
+ BEGIN
+ AddLine("<TR><TD NOWRAP>","");
+ PrFontDiff(0,CurrFontFlags);
+ END
+END
+
+ static void TeXDummy(Word Index)
+BEGIN
+END
+
+ static void TeXDummyNoBrack(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ ReadToken(Token);
+END
+
+ static void TeXDummyInCurl(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("{");
+ ReadToken(Token);
+ assert_token("}");
+END
+
+ static void TeXNewCommand(Word Index)
+BEGIN
+ char Token[TOKLEN];
+ int level;
+
+ assert_token("{");
+ assert_token("\\");
+ ReadToken(Token);
+ assert_token("}");
+ ReadToken(Token);
+ if (strcmp(Token,"[")==0)
+ BEGIN
+ ReadToken(Token);
+ assert_token("]");
+ END
+ assert_token("{"); level=1;
+ do
+ BEGIN
+ ReadToken(Token);
+ if (strcmp(Token,"{")==0) level++;
+ else if (strcmp(Token,"}")==0) level--;
+ END
+ while (level!=0);
+END
+
+ static void TeXDef(Word Index)
+BEGIN
+ char Token[TOKLEN];
+ int level;
+
+ assert_token("\\");
+ ReadToken(Token);
+ assert_token("{"); level=1;
+ do
+ BEGIN
+ ReadToken(Token);
+ if (strcmp(Token,"{")==0) level++;
+ else if (strcmp(Token,"}")==0) level--;
+ END
+ while (level!=0);
+END
+
+ static void TeXFont(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("\\");
+ ReadToken(Token); assert_token("="); ReadToken(Token); ReadToken(Token);
+ assert_token("\\"); ReadToken(Token);
+END
+
+ static void TeXAppendix(Word Index)
+BEGIN
+ int z;
+
+ InAppendix=True;
+ *Chapters=(-1);
+ for (z=1; z<CHAPMAX; Chapters[z++]=0);
+END
+
+static int LastLevel;
+
+ static void TeXNewSection(Word Level)
+BEGIN
+ int z;
+
+ if (Level>=CHAPMAX) return;
+
+ FlushLine(); fputc('\n',outfile);
+
+ assert_token("{"); LastLevel=Level;
+ SaveEnv(EnvHeading); RightMargin=200;
+
+ Chapters[Level]++;
+ for (z=Level+1; z<CHAPMAX; Chapters[z++]=0);
+ if (Level==0) TableNum=0;
+END
+
+ static void EndSectionHeading(void)
+BEGIN
+ int Level=LastLevel;
+ char Line[TOKLEN],Title[TOKLEN],Ref[TOKLEN],*run,*rep;
+
+ strcpy(Title,OutLineBuffer); *OutLineBuffer='\0';
+
+ fprintf(outfile, "<H%d>", Level + 1);
+
+ run = Line;
+ if (Level < 3)
+ BEGIN
+ GetSectionName(Ref);
+ for (rep = Ref; *rep != '\0'; rep++)
+ if (*rep == '.') *rep = '_';
+ fprintf(outfile, "<A NAME=\"sect_%s\">", Ref);
+ run = GetSectionName(run);
+ run += sprintf(run, " ");
+ END
+ sprintf(run, "%s", Title);
+
+ fprintf(outfile, "%s", Line);
+
+ if (Level < 3)
+ BEGIN
+ fputs("</A>", outfile);
+ run = Line; run = GetSectionName(run);
+ run += sprintf(run," "); sprintf(run, "%s", Title);
+ AddToc(Line);
+ END
+
+ fprintf(outfile, "</H%d>\n", Level + 1);
+END
+
+ static EnvType GetEnvType(char *Name)
+BEGIN
+ EnvType z;
+
+ for (z=EnvNone+1; z<EnvCount; z++)
+ if (strcmp(Name,EnvNames[z])==0) return z;
+
+ error("unknown environment");
+ return EnvNone;
+END
+
+ static void TeXBeginEnv(Word Index)
+BEGIN
+ char EnvName[TOKLEN],Add[TOKLEN],*p;
+ EnvType NEnv;
+ Boolean done;
+ TColumn NCol;
+
+ assert_token("{");
+ ReadToken(EnvName);
+ if ((NEnv=GetEnvType(EnvName))==EnvTable)
+ BEGIN
+ ReadToken(Add);
+ if (strcmp(Add,"*")==0) assert_token("}");
+ else if (strcmp(Add,"}")!=0) error("unknown table environment");
+ END
+ else assert_token("}");
+
+ if (NEnv!=EnvVerbatim) SaveEnv(NEnv);
+
+ switch (NEnv)
+ BEGIN
+ case EnvDocument:
+ fputs("</HEAD>\n",outfile);
+ fputs("<BODY>\n",outfile);
+ break;
+ case EnvItemize:
+ FlushLine(); fprintf(outfile,"<UL>\n");
+ ++CurrListDepth;
+ ActLeftMargin=LeftMargin=(CurrListDepth*4)+1;
+ RightMargin=70;
+ EnumCounter=0;
+ InListItem=False;
+ break;
+ case EnvDescription:
+ FlushLine(); fprintf(outfile,"<DL COMPACT>\n");
+ ++CurrListDepth;
+ ActLeftMargin=LeftMargin=(CurrListDepth*4)+1;
+ RightMargin=70;
+ EnumCounter=0;
+ InListItem=False;
+ break;
+ case EnvEnumerate:
+ FlushLine(); fprintf(outfile,"<OL>\n");
+ ++CurrListDepth;
+ ActLeftMargin=LeftMargin=(CurrListDepth*4)+1;
+ RightMargin=70;
+ EnumCounter=0;
+ InListItem=False;
+ break;
+ case EnvBiblio:
+ FlushLine(); fprintf(outfile,"<P>\n");
+ fprintf(outfile,"<H1><A NAME=\"sect_bib\">%s</A></H1>\n<DL COMPACT>\n",BiblioName);
+ assert_token("{"); ReadToken(Add); assert_token("}");
+ ActLeftMargin=LeftMargin=4+(BibIndent=strlen(Add));
+ AddToc(BiblioName);
+ break;
+ case EnvVerbatim:
+ FlushLine(); fprintf(outfile,"<PRE>\n");
+ if ((*BufferLine!='\0') AND (*BufferPtr!='\0'))
+ BEGIN
+ fprintf(outfile,"%s",BufferPtr);
+ *BufferLine='\0'; BufferPtr=BufferLine;
+ END
+ do
+ BEGIN
+ fgets(Add,TOKLEN-1,infiles[IncludeNest-1]); CurrLine++;
+ done=strstr(Add,"\\end{verbatim}")!=Nil;
+ if (NOT done)
+ BEGIN
+ for (p=Add; *p!='\0';)
+ if (*p=='<')
+ BEGIN
+ memmove(p+3,p,strlen(p)+1);
+ memcpy(p,"&lt;",4);
+ p+=4;
+ END
+ else if (*p=='>')
+ BEGIN
+ memmove(p+3,p,strlen(p)+1);
+ memcpy(p,"&gt;",4);
+ p+=4;
+ END
+ else p++;
+ fprintf(outfile,"%s",Add);
+ END
+ END
+ while (NOT done);
+ fprintf(outfile,"\n</PRE>\n");
+ break;
+ case EnvQuote:
+ FlushLine(); fprintf(outfile,"<BLOCKQUOTE>\n");
+ ActLeftMargin=LeftMargin=5;
+ RightMargin=70;
+ break;
+ case EnvTabbing:
+ FlushLine(); fputs("<TABLE SUMMARY=\"No Summary\" CELLPADDING=2>\n",outfile);
+ TabStopCnt=0; CurrTabStop=0; RightMargin=TOKLEN-1;
+ AddLine("<TR><TD NOWRAP>","");
+ PrFontDiff(0,CurrFontFlags);
+ break;
+ case EnvTable:
+ ReadToken(Add);
+ if (strcmp(Add,"[")!=0) BackToken(Add);
+ else
+ do
+ BEGIN
+ ReadToken(Add);
+ END
+ while (strcmp(Add,"]")!=0);
+ FlushLine(); fputc('\n',outfile);
+ ++TableNum;
+ break;
+ case EnvCenter:
+ FlushLine();
+ fputs("<CENTER>\n",outfile);
+ break;
+ case EnvRaggedRight:
+ FlushLine();
+ fputs("<DIV ALIGN=LEFT>\n",outfile);
+ break;
+ case EnvRaggedLeft:
+ FlushLine();
+ fputs("<DIV ALIGN=RIGHT>\n",outfile);
+ break;
+ case EnvTabular:
+ FlushLine(); assert_token("{");
+ ThisTable.ColumnCount=ThisTable.TColumnCount=0;
+ do
+ BEGIN
+ ReadToken(Add);
+ done=strcmp(Add,"}")==0;
+ if (NOT done)
+ BEGIN
+ if (ThisTable.ColumnCount>=MAXCOLS) error("too many columns in table");
+ NCol=ColLeft;
+ if (strcmp(Add,"|")==0) NCol=ColBar;
+ else if (strcmp(Add,"l")==0) NCol=ColLeft;
+ else if (strcmp(Add,"r")==0) NCol=ColRight;
+ else if (strcmp(Add,"c")==0) NCol=ColCenter;
+ else error("unknown table column descriptor");
+ if ((ThisTable.ColTypes[ThisTable.ColumnCount++]=NCol)!=ColBar)
+ ThisTable.TColumnCount++;
+ END
+ END
+ while (NOT done);
+ InitTableRow(CurrRow=0); CurrCol=0;
+ break;
+ default:
+ break;
+ END
+END
+
+ static void TeXEndEnv(Word Index)
+BEGIN
+ char EnvName[TOKLEN],Add[TOKLEN];
+ EnvType NEnv;
+
+ assert_token("{");
+ ReadToken(EnvName);
+ if ((NEnv=GetEnvType(EnvName))==EnvTable)
+ BEGIN
+ ReadToken(Add);
+ if (strcmp(Add,"*")==0) assert_token("}");
+ else if (strcmp(Add,"}")!=0) error("unknown table environment");
+ END
+ else assert_token("}");
+
+ if (EnvStack==Nil) error("end without begin");
+ if (CurrEnv!=NEnv) error("begin and end of environment do not match");
+
+ switch (CurrEnv)
+ BEGIN
+ case EnvDocument:
+ FlushLine();
+ fputs("</BODY>\n",outfile);
+ break;
+ case EnvItemize:
+ if (InListItem) AddLine("</LI>","");
+ FlushLine(); fprintf(outfile,"</UL>\n");
+ break;
+ case EnvDescription:
+ if (InListItem) AddLine("</DD>","");
+ FlushLine(); fprintf(outfile,"</DL>\n");
+ break;
+ case EnvEnumerate:
+ if (InListItem) AddLine("</LI>","");
+ FlushLine(); fprintf(outfile,"</OL>\n");
+ break;
+ case EnvQuote:
+ FlushLine(); fprintf(outfile,"</BLOCKQUOTE>\n");
+ break;
+ case EnvBiblio:
+ FlushLine(); fprintf(outfile,"</DL>\n");
+ break;
+ case EnvTabbing:
+ PrFontDiff(CurrFontFlags,0);
+ AddLine("</TD></TR>",""); FlushLine();
+ fputs("</TABLE>",outfile);
+ break;
+ case EnvCenter:
+ FlushLine();
+ fputs("</CENTER>\n",outfile);
+ break;
+ case EnvRaggedRight:
+ case EnvRaggedLeft:
+ FlushLine();
+ fputs("</DIV>\n",outfile);
+ break;
+ case EnvTabular:
+ DumpTable();
+ break;
+ case EnvTable:
+ FlushLine(); fputc('\n',outfile);
+ break;
+ default:
+ break;
+ END
+
+ RestoreEnv();
+END
+
+ static void TeXItem(Word Index)
+BEGIN
+ char Token[TOKLEN],Acc[TOKLEN];
+
+ if (InListItem)
+ AddLine((CurrEnv==EnvDescription) ? "</DD>" : "</LI>","");
+ FlushLine();
+ InListItem=True;
+ switch(CurrEnv)
+ BEGIN
+ case EnvItemize:
+ fprintf(outfile,"<LI>");
+ LeftMargin=ActLeftMargin-3;
+ break;
+ case EnvEnumerate:
+ fprintf(outfile,"<LI>");
+ LeftMargin=ActLeftMargin-4;
+ break;
+ case EnvDescription:
+ ReadToken(Token);
+ if (strcmp(Token,"[")!=0) BackToken(Token);
+ else
+ BEGIN
+ collect_token(Acc,"]");
+ LeftMargin=ActLeftMargin-4;
+ fprintf(outfile,"<DT>%s",Acc);
+ END
+ fprintf(outfile,"<DD>");
+ break;
+ default:
+ error("\\item not in a list environment");
+ END
+END
+
+ static void TeXBibItem(Word Index)
+BEGIN
+ char NumString[20],Token[TOKLEN],Name[TOKLEN],Value[TOKLEN];
+
+ if (CurrEnv!=EnvBiblio) error("\\bibitem not in bibliography environment");
+
+ assert_token("{"); collect_token(Name,"}");
+
+ FlushLine(); AddLine("<DT>",""); ++BibCounter;
+
+ LeftMargin=ActLeftMargin-BibIndent-3;
+ sprintf(Value,"<A NAME=\"cite_%s\">",Name);
+ DoAddNormal(Value,"");
+ sprintf(NumString,"[%*d] </A><DD>",BibIndent,BibCounter);
+ AddLine(NumString,"");
+ sprintf(NumString,"%d",BibCounter);
+ AddCite(Name,NumString);
+ ReadToken(Token); *SepString='\0'; BackToken(Token);
+END
+
+ static void TeXAddDollar(Word Index)
+BEGIN
+ DoAddNormal("$",BackSepString);
+END
+
+ static void TeXAddUnderbar(Word Index)
+BEGIN
+ DoAddNormal("_",BackSepString);
+END
+
+ static void TeXAddPot(Word Index)
+BEGIN
+ DoAddNormal("^",BackSepString);
+END
+
+ static void TeXAddAmpersand(Word Index)
+BEGIN
+ DoAddNormal("&",BackSepString);
+END
+
+ static void TeXAddAt(Word Index)
+BEGIN
+ DoAddNormal("@",BackSepString);
+END
+
+ static void TeXAddImm(Word Index)
+BEGIN
+ DoAddNormal("#",BackSepString);
+END
+
+ static void TeXAddPercent(Word Index)
+BEGIN
+ DoAddNormal("%",BackSepString);
+END
+
+ static void TeXAddSSharp(Word Index)
+BEGIN
+ DoAddNormal("&szlig;",BackSepString);
+END
+
+ static void TeXAddIn(Word Index)
+BEGIN
+ DoAddNormal("in",BackSepString);
+END
+
+ static void TeXAddReal(Word Index)
+BEGIN
+ DoAddNormal("R",BackSepString);
+END
+
+ static void TeXAddGreekMu(Word Index)
+BEGIN
+ DoAddNormal("&micro;",BackSepString);
+END
+
+ static void TeXAddGreekPi(Word Index)
+BEGIN
+ DoAddNormal("Pi",BackSepString);
+END
+
+ static void TeXAddLessEq(Word Index)
+BEGIN
+ DoAddNormal("<=",BackSepString);
+END
+
+ static void TeXAddGreaterEq(Word Index)
+BEGIN
+ DoAddNormal(">=",BackSepString);
+END
+
+ static void TeXAddNotEq(Word Index)
+BEGIN
+ DoAddNormal("<>",BackSepString);
+END
+
+ static void TeXAddMid(Word Index)
+BEGIN
+ DoAddNormal("|",BackSepString);
+END
+
+ static void TeXAddRightArrow(Word Index)
+BEGIN
+ DoAddNormal("->",BackSepString);
+END
+
+ static void TeXAddLongRightArrow(Word Index)
+BEGIN
+ DoAddNormal("-->",BackSepString);
+END
+
+ static void TeXAddLeftArrow(Word Index)
+BEGIN
+ DoAddNormal("<-",BackSepString);
+END
+
+ static void TeXAddLeftRightArrow(Word Index)
+BEGIN
+ DoAddNormal("<->",BackSepString);
+END
+
+ static void TeXDoFrac(Word Index)
+BEGIN
+ assert_token("{"); *SepString='\0'; BackToken("("); FracState=0;
+END
+
+ static void NextFracState(void)
+BEGIN
+ if (FracState==0)
+ BEGIN
+ assert_token("{");
+ *SepString='\0';
+ BackToken(")"); BackToken("/"); BackToken("(");
+ END
+ else if (FracState==1)
+ BEGIN
+ *SepString='\0'; BackToken(")");
+ END
+ if ((++FracState)==2) FracState=(-1);
+END
+
+ static void TeXNewFontType(Word Index)
+BEGIN
+ int NewFontFlags;
+
+ if (Index==FontStandard) NewFontFlags=0; else NewFontFlags=CurrFontFlags|(1<<Index);
+ PrFontDiff(CurrFontFlags,NewFontFlags);
+ CurrFontFlags=NewFontFlags;
+END
+
+ static void TeXEnvNewFontType(Word Index)
+BEGIN
+ char NToken[TOKLEN];
+
+ SaveFont();
+ TeXNewFontType(Index);
+ assert_token("{");
+ ReadToken(NToken);
+ strcpy(SepString,BackSepString);
+ BackToken(NToken);
+END
+
+ static void TeXNewFontSize(Word Index)
+BEGIN
+ PrFontSize(CurrFontSize=(TFontSize) Index,True);
+END
+
+ static void TeXEnvNewFontSize(Word Index)
+BEGIN
+ char NToken[TOKLEN];
+
+ SaveFont();
+ TeXNewFontSize(Index);
+ assert_token("{");
+ ReadToken(NToken);
+ strcpy(SepString,BackSepString);
+ BackToken(NToken);
+END
+
+ static void TeXAddMarginPar(Word Index)
+BEGIN
+ assert_token("{");
+ SaveEnv(EnvMarginPar);
+END
+
+ static void TeXAddCaption(Word Index)
+BEGIN
+ char tmp[100];
+ int cnt;
+
+ assert_token("{");
+ if (CurrEnv!=EnvTable) error("caption outside of a table");
+ FlushLine(); fputs("<P><CENTER>",outfile);
+ SaveEnv(EnvCaption);
+ AddLine(TableName,""); cnt=strlen(TableName);
+ GetTableName(tmp); strcat(tmp,": ");
+ AddLine(tmp," "); cnt+=1+strlen(tmp);
+ LeftMargin=1; ActLeftMargin=cnt+1; RightMargin=70;
+END
+
+ static void TeXHorLine(Word Index)
+BEGIN
+ if (CurrEnv!=EnvTabular) error("\\hline outside of a table");
+
+ if (ThisTable.Lines[CurrRow][0]!=Nil) InitTableRow(++CurrRow);
+ ThisTable.LineFlags[CurrRow]=True;
+ InitTableRow(++CurrRow);
+END
+
+ static void TeXMultiColumn(Word Index)
+BEGIN
+ char Token[TOKLEN],*endptr;
+ int cnt;
+
+ if (CurrEnv!=EnvTabular) error("\\hline outside of a table");
+ if (CurrCol!=0) error("\\multicolumn must be in first column");
+
+ assert_token("{"); ReadToken(Token); assert_token("}");
+ cnt=strtol(Token,&endptr,10);
+ if (*endptr!='\0') error("invalid numeric format to \\multicolumn");
+ if (cnt!=ThisTable.TColumnCount) error("\\multicolumn must span entire table");
+ assert_token("{");
+ do
+ BEGIN
+ ReadToken(Token);
+ END
+ while (strcmp(Token,"}")!=0);
+ ThisTable.MultiFlags[CurrRow]=True;
+END
+
+ static void TeXIndex(Word Index)
+BEGIN
+ char Token[TOKLEN],Erg[TOKLEN];
+ PIndexSave run,prev,neu;
+
+ assert_token("{");
+ collect_token(Token,"}");
+ run=FirstIndex; prev=Nil;
+ while ((run!=Nil) AND (strcmp(Token,run->Name)>0))
+ BEGIN
+ prev=run; run=run->Next;
+ END
+ if ((run==Nil) OR (strcmp(Token,run->Name)<0))
+ BEGIN
+ neu=(PIndexSave) malloc(sizeof(TIndexSave));
+ neu->Next=run;
+ neu->RefCnt=1;
+ neu->Name=strdup(Token);
+ if (prev==Nil) FirstIndex=neu; else prev->Next=neu;
+ run=neu;
+ END
+ else run->RefCnt++;
+ sprintf(Erg,"<A NAME=\"index_%s_%d\"></A>",Token,run->RefCnt);
+ DoAddNormal(Erg,"");
+END
+
+ static int GetDim(Double *Factors)
+BEGIN
+ char Acc[TOKLEN];
+ static char *UnitNames[]={"cm","mm",""},**run,*endptr;
+ Double Value;
+
+ assert_token("{"); collect_token(Acc,"}");
+ for (run=UnitNames; **run!='\0'; run++)
+ if (strcmp(*run,Acc+strlen(Acc)-strlen(*run))==0) break;
+ if (**run=='\0') error("unknown unit for dimension");
+ Acc[strlen(Acc)-strlen(*run)]='\0';
+ Value=strtod(Acc,&endptr);
+ if (*endptr!='\0') error("invalid numeric format for dimension");
+ return (int)(Value*Factors[run-UnitNames]);
+END
+
+static Double HFactors[]={4.666666,0.4666666,0};
+static Double VFactors[]={3.111111,0.3111111,0};
+
+ static void TeXHSpace(Word Index)
+BEGIN
+
+ DoAddNormal(Blanks(GetDim(HFactors)),"");
+END
+
+ static void TeXVSpace(Word Index)
+BEGIN
+ int z,erg;
+
+ erg=GetDim(VFactors);
+ FlushLine();
+ for (z=0; z<erg; z++) fputc('\n',outfile);
+END
+
+ static void TeXRule(Word Index)
+BEGIN
+ int h=GetDim(HFactors);
+ char Rule[200];
+
+ GetDim(VFactors);
+ sprintf(Rule,"<HR WIDTH=\"%d%%\" ALIGN=LEFT>",(h*100)/70);
+ DoAddNormal(Rule,BackSepString);
+END
+
+ static void TeXAddTabStop(Word Index)
+BEGIN
+ int z,n,p;
+
+ if (CurrEnv!=EnvTabbing) error("tab marker outside of tabbing environment");
+ if (TabStopCnt>=TABMAX) error("too many tab stops");
+
+ n=strlen(OutLineBuffer);
+ for (p=0; p<TabStopCnt; p++)
+ if (TabStops[p]>n) break;
+ for (z=TabStopCnt-1; z>=p; z--) TabStops[z+1]=TabStops[z];
+ TabStops[p]=n; TabStopCnt++;
+
+ PrFontDiff(CurrFontFlags,0);
+ DoAddNormal("</TD><TD NOWRAP>","");
+ PrFontDiff(0,CurrFontFlags);
+END
+
+ static void TeXJmpTabStop(Word Index)
+BEGIN
+ if (CurrEnv!=EnvTabbing) error("tab trigger outside of tabbing environment");
+ if (CurrTabStop>=TabStopCnt) error("not enough tab stops");
+
+ PrFontDiff(CurrFontFlags,0);
+ DoAddNormal("</TD><TD NOWRAP>","");
+ PrFontDiff(0,CurrFontFlags);
+ CurrTabStop++;
+END
+
+ static void TeXDoVerb(Word Index)
+BEGIN
+ char Token[TOKLEN],*pos,Marker;
+
+ ReadToken(Token);
+ if (*SepString!='\0') error("invalid control character for \\verb");
+ Marker=(*Token); strcpy(Token,Token+1); strcpy(SepString,BackSepString);
+ do
+ BEGIN
+ DoAddNormal(SepString,"");
+ pos=strchr(Token,Marker);
+ if (pos!=Nil)
+ BEGIN
+ *pos='\0'; DoAddNormal(Token,"");
+ *SepString='\0'; BackToken(pos+1);
+ break;
+ END
+ else
+ BEGIN
+ DoAddNormal(Token,""); ReadToken(Token);
+ END
+ END
+ while (True);
+END
+
+ static void TeXErrEntry(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("{"); ReadToken(Token); assert_token("}"); assert_token("{");
+ *SepString='\0';
+ BackToken("\\"); BackToken("item"); BackToken("["); BackToken(Token); BackToken("]");
+ ErrState=0;
+END
+
+ static void NextErrState(void)
+BEGIN
+ if (ErrState<3) assert_token("{");
+ if (ErrState==0)
+ BEGIN
+ *SepString='\0';
+ BackToken("\\"); BackToken("begin"); BackToken("{"); BackToken("description"); BackToken("}");
+ END
+ if ((ErrState>=0) AND (ErrState<=2))
+ BEGIN
+ *SepString='\0';
+ BackToken("\\"); BackToken("item"); BackToken("["); BackToken(ErrorEntryNames[ErrState]);
+ BackToken(":"); BackToken("]"); BackToken("\\"); BackToken("\\");
+ END
+ if (ErrState==3)
+ BEGIN
+ *SepString='\0';
+ BackToken("\\"); BackToken("\\"); BackToken(" ");
+ BackToken("\\"); BackToken("end"); BackToken("{"); BackToken("description"); BackToken("}");
+ ErrState=(-1);
+ END
+ else ErrState++;
+END
+
+ static void TeXWriteLabel(Word Index)
+BEGIN
+ char Name[TOKLEN],Value[TOKLEN];
+
+ assert_token("{"); collect_token(Name,"}");
+
+ if (CurrEnv==EnvCaption) GetTableName(Value);
+ else
+ BEGIN
+ GetSectionName(Value);
+ if (Value[strlen(Value)-1]=='.') Value[strlen(Value)-1]='\0';
+ END
+
+ AddLabel(Name,Value);
+ sprintf(Value,"<A NAME=\"ref_%s\"></A>",Name);
+ DoAddNormal(Value,"");
+END
+
+ static void TeXWriteRef(Word Index)
+BEGIN
+ char Name[TOKLEN],Value[TOKLEN],HRef[TOKLEN];
+
+ assert_token("{"); collect_token(Name,"}");
+ GetLabel(Name,Value);
+ sprintf(HRef,"<A HREF=\"#ref_%s\">",Name);
+ DoAddNormal(HRef,BackSepString);
+ DoAddNormal(Value,"");
+ DoAddNormal("</A>","");
+END
+
+ static void TeXWriteCitation(Word Index)
+BEGIN
+ char Name[TOKLEN],Value[TOKLEN],HRef[TOKLEN];
+
+ assert_token("{"); collect_token(Name,"}");
+ GetCite(Name,Value);
+ sprintf(HRef,"<A HREF=\"#cite_%s\">",Name);
+ DoAddNormal(HRef,BackSepString);
+ sprintf(Name,"[%s]",Value);
+ DoAddNormal(Name,"");
+ DoAddNormal("</A>","");
+END
+
+ static void TeXNewParagraph(Word Index)
+BEGIN
+ FlushLine();
+ fprintf(outfile,"<P>\n");
+END
+
+ static void TeXContents(Word Index)
+BEGIN
+ FILE *file=fopen(TocName,"r");
+ char Line[200],Ref[50],*ptr,*run;
+ int Level;
+
+ if (file==Nil)
+ BEGIN
+ warning("contents file not found.");
+ DoRepass=True; return;
+ END
+
+ FlushLine();
+ fprintf(outfile,"<P>\n<H1>%s</H1><P>\n",ContentsName);
+ while (NOT feof(file))
+ BEGIN
+ fgets(Line,199,file);
+ if ((*Line!='\0') AND (*Line!='\n'))
+ BEGIN
+ if (strncmp(Line,BiblioName,strlen(BiblioName))==0)
+ BEGIN
+ strcpy(Ref,"bib"); Level=1;
+ END
+ else if (strncmp(Line,IndexName,strlen(IndexName))==0)
+ BEGIN
+ strcpy(Ref,"index"); Level=1;
+ END
+ else
+ BEGIN
+ ptr=Ref; Level=1;
+ if (Line[strlen(Line)-1]=='\n') Line[strlen(Line)-1]='\0';
+ for (run=Line; *run!='\0'; run++) if (*run!=' ') break;
+ for (; *run!='\0'; run++)
+ if (*run==' ') break;
+ else if (*run=='.')
+ BEGIN
+ *(ptr++)='_';
+ Level++;
+ END
+ else if ((*run>='0') AND (*run<='9')) *(ptr++)=(*run);
+ else if ((*run>='A') AND (*run<='Z')) *(ptr++)=(*run);
+ *ptr='\0';
+ END
+ fprintf(outfile,"<P><H%d>",Level);
+ if (*Ref!='\0') fprintf(outfile,"<A HREF=\"#sect_%s\">",Ref);
+ fputs(Line,outfile);
+ if (*Ref!='\0') fprintf(outfile,"</A></H%d>",Level);
+ fputc('\n',outfile);
+ END
+ END
+
+ fclose(file);
+END
+
+ static void TeXPrintIndex(Word Index)
+BEGIN
+ PIndexSave run;
+ int i,rz;
+
+ FlushLine();
+ fprintf(outfile,"<H1><A NAME=\"sect_index\">%s</A></H1>\n",IndexName);
+ AddToc(IndexName);
+
+ fputs("<TABLE SUMMARY=\"Index\" BORDER=0 CELLPADDING=5>\n",outfile); rz=0;
+ for (run=FirstIndex; run!=Nil; run=run->Next)
+ BEGIN
+ if ((rz%5)==0) fputs("<TR ALIGN=LEFT>\n",outfile);
+ fputs("<TD VALIGN=TOP NOWRAP>",outfile);
+ fputs(run->Name,outfile);
+ for (i=0; i<run->RefCnt; i++)
+ fprintf(outfile," <A HREF=\"#index_%s_%d\">%d</A>",run->Name,i+1,i+1);
+ fputs("</TD>\n",outfile);
+ if ((rz%5)==4) fputs("</TR>\n",outfile);
+ rz++;
+ END
+ if ((rz%5)!=0) fputs("</TR>\n",outfile);
+ fputs("</TABLE>\n",outfile);
+END
+
+ static void TeXParSkip(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ ReadToken(Token);
+ do
+ BEGIN
+ ReadToken(Token);
+ if ((strncmp(Token,"plus",4)==0) OR (strncmp(Token,"minus",5)==0))
+ BEGIN
+ END
+ else
+ BEGIN
+ BackToken(Token); return;
+ END
+ END
+ while (1);
+END
+
+ static void TeXNLS(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'a': Repl="&auml;"; break;
+ case 'e': Repl="&euml;"; break;
+ case 'i': Repl="&iuml;"; break;
+ case 'o': Repl="&ouml;"; break;
+ case 'u': Repl="&uuml;"; break;
+ case 'A': Repl="&Auml;"; break;
+ case 'E': Repl="&Euml;"; break;
+ case 'I': Repl="&Iuml;"; break;
+ case 'O': Repl="&Ouml;"; break;
+ case 'U': Repl="&Uuml;"; break;
+ case 's': Repl="&szlig;"; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXNLSGrave(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'a': Repl="&agrave;"; break;
+ case 'e': Repl="&egrave;"; break;
+ case 'i': Repl="&igrave;"; break;
+ case 'o': Repl="&ograve;"; break;
+ case 'u': Repl="&ugrave;"; break;
+ case 'A': Repl="&Agrave;"; break;
+ case 'E': Repl="&Egrave;"; break;
+ case 'I': Repl="&Igrave;"; break;
+ case 'O': Repl="&Ograve;"; break;
+ case 'U': Repl="&Ugrave;"; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXNLSAcute(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'a': Repl="&aacute;"; break;
+ case 'e': Repl="&eacute;"; break;
+ case 'i': Repl="&iacute;"; break;
+ case 'o': Repl="&oacute;"; break;
+ case 'u': Repl="&uacute;"; break;
+ case 'A': Repl="&Aacute;"; break;
+ case 'E': Repl="&Eacute;"; break;
+ case 'I': Repl="&Iacute;"; break;
+ case 'O': Repl="&Oacute;"; break;
+ case 'U': Repl="&Uacute;"; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXNLSCirc(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'a': Repl="&acirc;"; break;
+ case 'e': Repl="&ecirc;"; break;
+ case 'i': Repl="&icirc;"; break;
+ case 'o': Repl="&ocirc;"; break;
+ case 'u': Repl="&ucirc;"; break;
+ case 'A': Repl="&Acirc;"; break;
+ case 'E': Repl="&Ecirc;"; break;
+ case 'I': Repl="&Icirc;"; break;
+ case 'O': Repl="&Ocirc;"; break;
+ case 'U': Repl="&Ucirc;"; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXNLSTilde(Word Index)
+BEGIN
+ char Token[TOKLEN],*Repl="";
+ Boolean Found=True;
+
+ *Token='\0';
+ ReadToken(Token);
+ if (*SepString=='\0')
+ switch (*Token)
+ BEGIN
+ case 'n': Repl="&ntilde;"; break;
+ case 'N': Repl="&Ntilde;"; break;
+ default : Found=False;
+ END
+ else Found=False;
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)>1) memmove(Token+strlen(Repl),Token+1,strlen(Token));
+ memcpy(Token,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Token);
+END
+
+ static void TeXCedilla(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("{"); collect_token(Token,"}");
+ if (strcmp(Token,"c")==0) strcpy(Token,"&ccedil;");
+ if (strcmp(Token,"C")==0) strcpy(Token,"&Ccedil;");
+
+ DoAddNormal(Token,BackSepString);
+END
+
+ static Boolean TeXNLSSpec(char *Line)
+BEGIN
+ Boolean Found=True;
+ char *Repl=Nil;
+ int cnt=0;
+
+ if (*SepString=='\0')
+ switch (*Line)
+ BEGIN
+ case 'o': cnt=1; Repl="&oslash;"; break;
+ case 'O': cnt=1; Repl="&Oslash;"; break;
+ case 'a':
+ switch (Line[1])
+ BEGIN
+ case 'a': cnt=2; Repl="&aring;"; break;
+ case 'e': cnt=2; Repl="&aelig;"; break;
+ default: Found=False;
+ END
+ break;
+ case 'A':
+ switch (Line[1])
+ BEGIN
+ case 'A': cnt=2; Repl="&Aring;"; break;
+ case 'E': cnt=2; Repl="&AElig;"; break;
+ default: Found=False;
+ END
+ break;
+ default: Found=False;
+ END
+
+ if (Found)
+ BEGIN
+ if (strlen(Repl)!=cnt) memmove(Line+strlen(Repl),Line+cnt,strlen(Line)-cnt+1);
+ memcpy(Line,Repl,strlen(Repl)); strcpy(SepString,BackSepString);
+ END
+ else DoAddNormal("\"",BackSepString);
+
+ BackToken(Line);
+ return Found;
+END
+
+ static void TeXHyphenation(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ assert_token("{"); collect_token(Token,"}");
+END
+
+ static void TeXDoPot(void)
+BEGIN
+ char Token[TOKLEN];
+
+ ReadToken(Token);
+ if (strcmp(Token,"1")==0)
+ DoAddNormal("&sup1;",BackSepString);
+ else if (strcmp(Token,"2")==0)
+ DoAddNormal("&sup2;",BackSepString);
+ else if (strcmp(Token,"3")==0)
+ DoAddNormal("&sup3;",BackSepString);
+ else if (strcmp(Token,"{")==0)
+ BEGIN
+ SaveFont();
+ TeXNewFontType(FontSuper);
+ ReadToken(Token);
+ strcpy(SepString,BackSepString);
+ BackToken(Token);
+ END
+ else
+ BEGIN
+ DoAddNormal("^",BackSepString);
+ AddLine(Token,"");
+ END
+END
+
+ static void TeXDoSpec(void)
+BEGIN
+ strcpy(BackSepString,SepString);
+ TeXNLS(0);
+END
+
+ static void TeXInclude(Word Index)
+BEGIN
+ char Token[TOKLEN],Msg[TOKLEN];
+
+ assert_token("{"); collect_token(Token,"}");
+ if ((infiles[IncludeNest]=fopen(Token,"r"))==Nil)
+ BEGIN
+ sprintf(Msg,"file %s not found",Token);
+ error(Msg);
+ END
+ else IncludeNest++;
+END
+
+ static void TeXDocumentStyle(Word Index)
+BEGIN
+ char Token[TOKLEN];
+
+ ReadToken(Token);
+ if (strcmp(Token,"[")==0)
+ BEGIN
+ do
+ BEGIN
+ ReadToken(Token);
+ if (strcmp(Token,"german")==0) SetLang(True);
+ END
+ while (strcmp(Token,"]")!=0);
+ assert_token("{");
+ ReadToken(Token);
+ if (strcasecmp(Token, "article") == 0)
+ BEGIN
+ AddInstTable(TeXTable,"section",0,TeXNewSection);
+ AddInstTable(TeXTable,"subsection",1,TeXNewSection);
+ AddInstTable(TeXTable,"subsubsection",3,TeXNewSection);
+ END
+ else
+ BEGIN
+ AddInstTable(TeXTable,"chapter",0,TeXNewSection);
+ AddInstTable(TeXTable,"section",1,TeXNewSection);
+ AddInstTable(TeXTable,"subsection",2,TeXNewSection);
+ AddInstTable(TeXTable,"subsubsection",3,TeXNewSection);
+ END
+ assert_token("}");
+ END
+END
+
+ static void StartFile(char *Name)
+BEGIN
+ char comp[TOKLEN];
+ struct stat st;
+
+ /* create name ? */
+
+ if (Structured)
+ BEGIN
+ sprintf(comp, "%s.dir/%s", outfilename, Name);
+ Name = comp;
+ END
+
+ /* open file */
+
+ if ((outfile = fopen(Name, "w")) == NULL)
+ BEGIN
+ perror(Name); exit(3);
+ END
+
+ /* write head */
+
+ fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",outfile);
+ fputs("<HTML>\n",outfile);
+ fputs("<HEAD>\n",outfile);
+ fprintf(outfile,"<META NAME=\"Author\" CONTENT=\"automatically generated by tex2html from %s\">\n",infilename);
+ stat(Name, &st);
+ strncpy(comp, ctime(&st.st_mtime), TOKLEN - 1);
+ if (comp[strlen(comp) - 1] == '\n') comp[strlen(comp) - 1] = '\0';
+ fprintf(outfile, "<META NAME=\"Last-modified\" CONTENT=\"%s\">\n", comp);
+END
+
+/*--------------------------------------------------------------------------*/
+
+ int main(int argc, char **argv)
+BEGIN
+ char Line[TOKLEN],Comp[TOKLEN],*p,AuxFile[200];
+ int z, ergc;
+
+ /* assume defaults for flags */
+
+ Structured = False;
+
+ /* extract switches */
+
+ ergc = 1;
+ for (z = 1; z < argc; z++)
+ BEGIN
+ if (strcmp(argv[z], "-w") == 0)
+ Structured = True;
+ else
+ argv[ergc++] = argv[z];
+ END
+ argc = ergc;
+
+ /* do we want that ? */
+
+ if (argc<3)
+ BEGIN
+ fprintf(stderr, "calling convention: %s [switches] <input file> <output file>\n"
+ "switches: -w --> create structured document\n", *argv);
+ exit(1);
+ END
+
+ /* set up inclusion stack */
+
+ IncludeNest=0;
+ if ((*infiles=fopen(argv[1],"r"))==Nil)
+ BEGIN
+ perror(argv[1]); exit(3);
+ END
+ else IncludeNest++;
+ /* set up hash table */
+
+ TeXTable=CreateInstTable(301);
+
+ AddInstTable(TeXTable,"\\",0,TeXFlushLine);
+ AddInstTable(TeXTable,"par",0,TeXNewParagraph);
+ AddInstTable(TeXTable,"-",0,TeXDummy);
+ AddInstTable(TeXTable,"hyphenation",0,TeXHyphenation);
+ AddInstTable(TeXTable,"kill",0,TeXKillLine);
+ AddInstTable(TeXTable,"/",0,TeXDummy);
+ AddInstTable(TeXTable,"pagestyle",0,TeXDummyInCurl);
+ AddInstTable(TeXTable,"thispagestyle",0,TeXDummyInCurl);
+ AddInstTable(TeXTable,"sloppy",0,TeXDummy);
+ AddInstTable(TeXTable,"clearpage",0,TeXDummy);
+ AddInstTable(TeXTable,"cleardoublepage",0,TeXDummy);
+ AddInstTable(TeXTable,"topsep",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"parskip",0,TeXParSkip);
+ AddInstTable(TeXTable,"parindent",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"textwidth",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"evensidemargin",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"oddsidemargin",0,TeXDummyNoBrack);
+ AddInstTable(TeXTable,"newcommand",0,TeXNewCommand);
+ AddInstTable(TeXTable,"def",0,TeXDef);
+ AddInstTable(TeXTable,"font",0,TeXFont);
+ AddInstTable(TeXTable,"documentstyle",0,TeXDocumentStyle);
+ AddInstTable(TeXTable,"appendix",0,TeXAppendix);
+ AddInstTable(TeXTable,"makeindex",0,TeXDummy);
+ AddInstTable(TeXTable,"begin",0,TeXBeginEnv);
+ AddInstTable(TeXTable,"end",0,TeXEndEnv);
+ AddInstTable(TeXTable,"item",0,TeXItem);
+ AddInstTable(TeXTable,"bibitem",0,TeXBibItem);
+ AddInstTable(TeXTable,"errentry",0,TeXErrEntry);
+ AddInstTable(TeXTable,"$",0,TeXAddDollar);
+ AddInstTable(TeXTable,"_",0,TeXAddUnderbar);
+ AddInstTable(TeXTable,"&",0,TeXAddAmpersand);
+ AddInstTable(TeXTable,"@",0,TeXAddAt);
+ AddInstTable(TeXTable,"#",0,TeXAddImm);
+ AddInstTable(TeXTable,"%",0,TeXAddPercent);
+ AddInstTable(TeXTable,"ss",0,TeXAddSSharp);
+ AddInstTable(TeXTable,"in",0,TeXAddIn);
+ AddInstTable(TeXTable,"rz",0,TeXAddReal);
+ AddInstTable(TeXTable,"mu",0,TeXAddGreekMu);
+ AddInstTable(TeXTable,"pi",0,TeXAddGreekPi);
+ AddInstTable(TeXTable,"leq",0,TeXAddLessEq);
+ AddInstTable(TeXTable,"geq",0,TeXAddGreaterEq);
+ AddInstTable(TeXTable,"neq",0,TeXAddNotEq);
+ AddInstTable(TeXTable,"mid",0,TeXAddMid);
+ AddInstTable(TeXTable,"frac",0,TeXDoFrac);
+ AddInstTable(TeXTable,"rm",FontStandard,TeXNewFontType);
+ AddInstTable(TeXTable,"em",FontEmphasized,TeXNewFontType);
+ AddInstTable(TeXTable,"bf",FontBold,TeXNewFontType);
+ AddInstTable(TeXTable,"tt",FontTeletype,TeXNewFontType);
+ AddInstTable(TeXTable,"it",FontItalic,TeXNewFontType);
+ AddInstTable(TeXTable,"bb",FontBold,TeXEnvNewFontType);
+ AddInstTable(TeXTable,"tty",FontTeletype,TeXEnvNewFontType);
+ AddInstTable(TeXTable,"ii",FontItalic,TeXEnvNewFontType);
+ AddInstTable(TeXTable,"tiny",FontTiny,TeXNewFontSize);
+ AddInstTable(TeXTable,"small",FontSmall,TeXNewFontSize);
+ AddInstTable(TeXTable,"normalsize",FontNormalSize,TeXNewFontSize);
+ AddInstTable(TeXTable,"large",FontLarge,TeXNewFontSize);
+ AddInstTable(TeXTable,"huge",FontHuge,TeXNewFontSize);
+ AddInstTable(TeXTable,"Huge",FontHuge,TeXNewFontSize);
+ AddInstTable(TeXTable,"tin",FontTiny,TeXEnvNewFontSize);
+ AddInstTable(TeXTable,"rightarrow",0,TeXAddRightArrow);
+ AddInstTable(TeXTable,"longrightarrow",0,TeXAddLongRightArrow);
+ AddInstTable(TeXTable,"leftarrow",0,TeXAddLeftArrow);
+ AddInstTable(TeXTable,"leftrightarrow",0,TeXAddLeftRightArrow);
+ AddInstTable(TeXTable,"marginpar",0,TeXAddMarginPar);
+ AddInstTable(TeXTable,"caption",0,TeXAddCaption);
+ AddInstTable(TeXTable,"label",0,TeXWriteLabel);
+ AddInstTable(TeXTable,"ref",0,TeXWriteRef);
+ AddInstTable(TeXTable,"cite",0,TeXWriteCitation);
+ AddInstTable(TeXTable,"hline",0,TeXHorLine);
+ AddInstTable(TeXTable,"multicolumn",0,TeXMultiColumn);
+ AddInstTable(TeXTable,"ttindex",0,TeXIndex);
+ AddInstTable(TeXTable,"hspace",0,TeXHSpace);
+ AddInstTable(TeXTable,"vspace",0,TeXVSpace);
+ AddInstTable(TeXTable,"=",0,TeXAddTabStop);
+ AddInstTable(TeXTable,">",0,TeXJmpTabStop);
+ AddInstTable(TeXTable,"verb",0,TeXDoVerb);
+ AddInstTable(TeXTable,"printindex",0,TeXPrintIndex);
+ AddInstTable(TeXTable,"tableofcontents",0,TeXContents);
+ AddInstTable(TeXTable,"rule",0,TeXRule);
+ AddInstTable(TeXTable,"\"",0,TeXNLS);
+ AddInstTable(TeXTable,"`",0,TeXNLSGrave);
+ AddInstTable(TeXTable,"'",0,TeXNLSAcute);
+ AddInstTable(TeXTable,"^",0,TeXNLSCirc);
+ AddInstTable(TeXTable,"~",0,TeXNLSTilde);
+ AddInstTable(TeXTable,"c",0,TeXCedilla);
+ AddInstTable(TeXTable,"newif",0,TeXDummy);
+ AddInstTable(TeXTable,"fi",0,TeXDummy);
+ AddInstTable(TeXTable,"ifelektor",0,TeXDummy);
+ AddInstTable(TeXTable,"elektortrue",0,TeXDummy);
+ AddInstTable(TeXTable,"elektorfalse",0,TeXDummy);
+ AddInstTable(TeXTable,"input",0,TeXInclude);
+
+ /* preset state variables */
+
+ for (z=0; z<CHAPMAX; Chapters[z++]=0);
+ TableNum=0; FontNest=0;
+ TabStopCnt=0; CurrTabStop=0;
+ ErrState=FracState=(-1);
+ InAppendix=False;
+ EnvStack=Nil;
+ CurrEnv=EnvNone; CurrListDepth=0;
+ ActLeftMargin=LeftMargin=1; RightMargin=70;
+ EnumCounter=0; InListItem=False;
+ CurrFontFlags=0; CurrFontSize=FontNormalSize;
+ FontStack=Nil;
+ FirstRefSave=Nil; FirstCiteSave=Nil; FirstTocSave=Nil; FirstIndex=Nil;
+ *SideMargin='\0';
+ DoRepass=False;
+ BibIndent=BibCounter=0;
+ GermanMode=True; SetLang(False);
+
+ /* open help files */
+
+ strcpy(TocName,argv[1]);
+ if ((p=strrchr(TocName,'.'))!=Nil) *p='\0';
+ strcat(TocName,".htoc");
+
+ strcpy(AuxFile,argv[1]);
+ if ((p=strrchr(AuxFile,'.'))!=Nil) *p='\0';
+ strcat(AuxFile,".haux");
+ ReadAuxFile(AuxFile);
+
+ /* save file names */
+
+ infilename = argv[1];
+ outfilename = argv[2];
+ if (strcmp(outfilename, "-")==0)
+ BEGIN
+ if (Structured)
+ BEGIN
+ printf("%s: structured write must be to a directory\n", *argv);
+ exit(1);
+ END
+ else outfile = stdout;
+ END
+
+ /* do we need to make a directory ? */
+
+ else if (Structured)
+ BEGIN
+ sprintf(Line, "%s.dir", outfilename);
+#ifdef __MSDOS__
+ mkdir(Line, 055);
+#else
+ mkdir(Line, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+#endif
+ StartFile("intro.html");
+ END
+
+ /* otherwise open the single file */
+
+ else
+ StartFile(argv[2]);
+
+ /* start to parse */
+
+ while (1)
+ BEGIN
+ if (NOT ReadToken(Line)) break;
+ if (strcmp(Line,"\\")==0)
+ BEGIN
+ strcpy(BackSepString,SepString);
+ if (NOT ReadToken(Line)) error("unexpected end of file");
+ if (*SepString!='\0') BackToken(Line);
+ else if (NOT LookupInstTable(TeXTable,Line))
+ if (NOT TeXNLSSpec(Line))
+ BEGIN
+ sprintf(Comp,"unknown TeX command %s",Line);
+ warning(Comp);
+ END
+ END
+ else if (strcmp(Line,"$")==0)
+ BEGIN
+ if ((InMathMode=(NOT InMathMode)))
+ BEGIN
+ strcpy(BackSepString,SepString);
+ ReadToken(Line); strcpy(SepString,BackSepString);
+ BackToken(Line);
+ END
+ END
+ else if (strcmp(Line,"&")==0) NextTableColumn();
+ else if ((strcmp(Line,"^")==0) AND (InMathMode)) TeXDoPot();
+ else if ((strcmp(Line,"\"")==0) AND (GermanMode)) TeXDoSpec();
+ else if (strcmp(Line,"{")==0)
+ SaveFont();
+ else if (strcmp(Line,"}")==0)
+ if (FontNest>0) RestoreFont();
+ else if (ErrState>=0) NextErrState();
+ else if (FracState>=0) NextFracState();
+ else switch (CurrEnv)
+ BEGIN
+ case EnvMarginPar:
+ RestoreEnv(); break;
+ case EnvCaption:
+ FlushLine(); fputs("</CENTER><P>\n",outfile); RestoreEnv(); break;
+ case EnvHeading:
+ EndSectionHeading(); RestoreEnv(); break;
+ default: RestoreFont();
+ END
+ else DoAddNormal(Line,SepString);
+ END
+ FlushLine();
+ DestroyInstTable(TeXTable);
+
+ fputs("</HTML>\n",outfile);
+
+ for (z=0; z<IncludeNest; fclose(infiles[z++]));
+ fclose(outfile);
+
+ unlink(AuxFile);
+ PrintLabels(AuxFile); PrintCites(AuxFile);
+ PrintToc(TocName);
+
+ if (DoRepass) fprintf(stderr,"additional pass recommended\n");
+
+ return 0;
+END
+
+#ifdef CKMALLOC
+#undef malloc
+#undef realloc
+
+ void *ckmalloc(size_t s)
+BEGIN
+ void *tmp=malloc(s);
+ if (tmp==NULL)
+ BEGIN
+ fprintf(stderr,"allocation error(malloc): out of memory");
+ exit(255);
+ END
+ return tmp;
+END
+
+ void *ckrealloc(void *p, size_t s)
+BEGIN
+ void *tmp=realloc(p,s);
+ if (tmp==NULL)
+ BEGIN
+ fprintf(stderr,"allocation error(realloc): out of memory");
+ exit(255);
+ END
+ return tmp;
+END
+#endif
+
diff --git a/tools.res b/tools.res
new file mode 100644
index 0000000..4d632d3
--- /dev/null
+++ b/tools.res
@@ -0,0 +1,35 @@
+;* tools.res
+;*****************************************************************************
+;* AS-Portierung *
+;* *
+;* Stringdefinitionen, die alle AS-Tools brauchen *
+;* *
+;* Historie: 31. 5.1996 Grundsteinlegung *
+;* *
+;*****************************************************************************
+
+Include header.res
+
+Message FormatErr1aMsg
+ "Das Format der Datei ""
+ "the format of file ""
+
+Message FormatErr1bMsg
+ "" ist fehlerhaft!"
+ "" is invalid!"
+
+Message FormatErr2Msg
+ "Bitte "CH_ue"bersetzen Sie die Quelldatei neu!"
+ "please reassemble the source file!"
+
+Message IOErrAHeaderMsg
+ "Bei Bearbeitung der Datei ""
+ "the following error occured while processing ""
+
+Message IOErrBHeaderMsg
+ "" ist folgender Fehler aufgetreten:"
+ "" :"
+
+Message ErrMsgTerminating
+ "Das Programm wird beendet!"
+ "program terminated!"
diff --git a/tools2.res b/tools2.res
new file mode 100644
index 0000000..b233c09
--- /dev/null
+++ b/tools2.res
@@ -0,0 +1,70 @@
+;* tools.res
+;*****************************************************************************
+;* AS-Portierung *
+;* *
+;* Stringdefinitionen, die alle AS-Tools brauchen *
+;* *
+;* Historie: 31. 5.1996 Grundsteinlegung *
+;* *
+;*****************************************************************************
+
+;-----------------------------------------------------------------------------
+; Durchsagen
+
+Message InfoMessHead1
+ "Aufruf: "
+ "calling convention: "
+
+;-----------------------------------------------------------------------------
+; Fehlermeldungen
+
+Message FormatInvHeaderMsg
+ "ung&uuml;ltiger Dateikopf"
+ "invalid file header"
+
+Message FormatInvRecordHeaderMsg
+ "ung&uuml;ltiger Datensatzkopf"
+ "invalid record header"
+
+Message FormatInvRecordLenMsg
+ "fehlerhafte Datensatzl&auml;nge"
+ "invalid record length"
+
+Message ErrMsgNullMaskA
+ "Warnung : Dateimaske "
+ "warning : file mask "
+
+Message ErrMsgNullMaskB
+ " pa&szlig;t auf keine Datei!"
+ " does not fit to any file!"
+
+Message ErrMsgInvEnvParam
+ "Fehlerhafter Environment-Parameter : "
+ "invalid environment parameter: "
+
+Message ErrMsgInvParam
+ "Fehlerhafter Parameter : "
+ "invalid parameter : "
+
+Message ErrMsgTargMissing
+ "Zieldateiangabe fehlt!"
+ "destination file specification missing!"
+
+Message ErrMsgAutoFailed
+ "automatische Bereichserkennung fehlgeschlagen!"
+ "automatic range setting failed!"
+
+Message ErrMsgOverlap
+ "Warnung: &uuml;berlappende Belegung!"
+ "warning: overlapping memory allocation!"
+
+Message ErrMsgProgTerm
+ "Programmabbruch"
+ "program terminated"
+
+;---------------------------------------------------------------------------
+
+Message Suffix
+ ".p"
+ ".p"
+
diff --git a/toolutils.c b/toolutils.c
new file mode 100644
index 0000000..b7f2680
--- /dev/null
+++ b/toolutils.c
@@ -0,0 +1,293 @@
+/* toolutils.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Unterroutinen fuer die AS-Tools */
+/* */
+/* Historie: 31. 5.1996 Grundsteinlegung */
+/* 27.10.1997 Routinen aus P2... heruebergenommen */
+/* 27. 3.1999 Granularitaet SC144xx */
+/* 30. 5.1999 Adresswildcard-Funktion */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+#include <string.h>
+
+#include "strutil.h"
+#include "cmdarg.h"
+#include "stdhandl.h"
+#include "ioerrs.h"
+
+#include "nls.h"
+#include "nlmessages.h"
+#include "tools.rsc"
+
+#include "toolutils.h"
+
+LongWord Magic=0x1b34244d;
+
+/****************************************************************************/
+
+static Boolean DoFilter;
+static int FilterCnt;
+static Byte FilterBytes[100];
+
+static char *InfoMessCopyright="(C) 1992,1998 Alfred Arnold";
+
+Word FileID=0x1489; /* Dateiheader Eingabedateien */
+char *OutName="STDOUT"; /* Pseudoname Output */
+
+static TMsgCat MsgCat;
+
+/****************************************************************************/
+
+ void WrCopyRight(char *Msg)
+BEGIN
+ printf("%s\n%s\n",Msg,InfoMessCopyright);
+END
+
+ void DelSuffix(char *Name)
+BEGIN
+ char *p,*z,*Part;
+
+ p=Nil;
+ for (z=Name; *z!='\0'; z++) if (*z=='\\') p=z;
+ Part=(p!=Nil)?(p):(Name); Part=strchr(Part,'.');
+ if (Part!=Nil) *Part='\0';
+END
+
+ void AddSuffix(char *s, char *Suff)
+BEGIN
+ char *p,*z,*Part;
+
+ p=Nil;
+ for (z=s; *z!='\0'; z++) if (*z=='\\') p=z;
+ Part=(p!=Nil)?(p):(s);
+ if (strchr(Part,'.')==Nil) strmaxcat(s,Suff,255);
+END
+
+
+ void FormatError(char *Name, char *Detail)
+BEGIN
+ fprintf(stderr,"%s%s%s (%s)\n",catgetmessage(&MsgCat,Num_FormatErr1aMsg),
+ Name,catgetmessage(&MsgCat,Num_FormatErr1bMsg),Detail);
+ fprintf(stderr,"%s\n",catgetmessage(&MsgCat,Num_FormatErr2Msg));
+ exit(3);
+END
+
+ void ChkIO(char *Name)
+BEGIN
+ int io;
+
+ io=errno;
+
+ if (io==0) return;
+
+ fprintf(stderr,"%s%s%s\n",catgetmessage(&MsgCat,Num_IOErrAHeaderMsg),Name,catgetmessage(&MsgCat,Num_IOErrBHeaderMsg));
+
+ fprintf(stderr,"%s.\n",GetErrorMsg(io));
+
+ fprintf(stderr,"%s\n",catgetmessage(&MsgCat,Num_ErrMsgTerminating));
+
+ exit(2);
+END
+
+ Word Granularity(Byte Header)
+BEGIN
+ switch (Header)
+ BEGIN
+ case 0x09:
+ case 0x76:
+ case 0x7d:
+ return 4;
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x74:
+ case 0x75:
+ case 0x77:
+ case 0x12:
+ case 0x3b:
+ case 0x6d:
+ return 2;
+ default:
+ return 1;
+ END
+END
+
+ void ReadRecordHeader(Byte *Header, Byte* Segment, Byte *Gran,
+ char *Name, FILE *f)
+BEGIN
+ if (fread(Header,1,1,f)!=1) ChkIO(Name);
+ if ((*Header!=FileHeaderEnd) AND (*Header!=FileHeaderStartAdr))
+ if (*Header==FileHeaderDataRec)
+ BEGIN
+ if (fread(Header,1,1,f)!=1) ChkIO(Name);
+ if (fread(Segment,1,1,f)!=1) ChkIO(Name);
+ if (fread(Gran,1,1,f)!=1) ChkIO(Name);
+ END
+ else
+ BEGIN
+ *Segment=SegCode;
+ *Gran=Granularity(*Header);
+ END
+END
+
+ void WriteRecordHeader(Byte *Header, Byte *Segment, Byte *Gran,
+ char *Name, FILE *f)
+BEGIN
+ Byte h;
+
+ if ((*Header==FileHeaderEnd) OR (*Header==FileHeaderStartAdr))
+ BEGIN
+ if (fwrite(Header,1,1,f)!=1) ChkIO(Name);
+ END
+ else if ((*Segment!=SegCode) OR (*Gran!=Granularity(*Header)))
+ BEGIN
+ h=FileHeaderDataRec;
+ if (fwrite(&h,1,1,f)) ChkIO(Name);
+ if (fwrite(Header,1,1,f)) ChkIO(Name);
+ if (fwrite(Segment,1,1,f)) ChkIO(Name);
+ if (fwrite(Gran,1,1,f)) ChkIO(Name);
+ END
+ else
+ BEGIN
+ if (fwrite(Header,1,1,f)) ChkIO(Name);
+ END
+END
+
+ CMDResult CMD_FilterList(Boolean Negate, char *Arg)
+BEGIN
+ Byte FTemp;
+ Boolean err;
+ char *p;
+ int Search;
+ String Copy;
+
+ if (*Arg=='\0') return CMDErr;
+ strmaxcpy(Copy,Arg,255);
+
+ do
+ BEGIN
+ p=strchr(Copy,','); if (p!=Nil) *p='\0';
+ FTemp=ConstLongInt(Copy,&err);
+ if (NOT err) return CMDErr;
+
+ for (Search=0; Search<FilterCnt; Search++)
+ if (FilterBytes[Search]==FTemp) break;
+
+ if ((Negate) AND (Search<FilterCnt))
+ FilterBytes[Search]=FilterBytes[--FilterCnt];
+
+ else if ((NOT Negate) AND (Search>=FilterCnt))
+ FilterBytes[FilterCnt++]=FTemp;
+
+ if (p!=Nil) strcpy(Copy,p+1);
+ END
+ while (p!=Nil);
+
+ DoFilter=(FilterCnt!=0);
+
+ return CMDArg;
+END
+
+ Boolean FilterOK(Byte Header)
+BEGIN
+ int z;
+
+ if (DoFilter)
+ BEGIN
+ for (z=0; z<FilterCnt; z++)
+ if (Header==FilterBytes[z]) return True;
+ return False;
+ END
+ else return True;
+END
+
+ Boolean RemoveOffset(char *Name, LongWord *Offset)
+BEGIN
+ int z,Nest;
+ Boolean err;
+
+ *Offset=0;
+ if (Name[strlen(Name)-1]==')')
+ BEGIN
+ z=strlen(Name)-2; Nest=0;
+ while ((z>=0) AND (Nest>=0))
+ BEGIN
+ switch (Name[z])
+ BEGIN
+ case '(':Nest--; break;
+ case ')':Nest++; break;
+ END
+ if (Nest!=-1) z--;
+ END
+ if (Nest!=-1) return False;
+ else
+ BEGIN
+ Name[strlen(Name)-1]='\0';
+ *Offset=ConstLongInt(Name+z+1,&err);
+ Name[z]='\0';
+ return err;
+ END
+ END
+ else return True;
+END
+
+ void EraseFile(char *FileName, LongWord Offset)
+BEGIN
+ if (Offset==0); /* satisfy some compilers */
+
+ if (unlink(FileName)==-1) ChkIO(FileName);
+END
+
+ void toolutils_init(char *ProgPath)
+BEGIN
+ Word z;
+ LongWord XORVal;
+
+ opencatalog(&MsgCat,"tools.msg",ProgPath,MsgId1,MsgId2);
+
+ FilterCnt=0; DoFilter=False;
+ for (z=0; z<strlen(InfoMessCopyright); z++)
+ BEGIN
+ XORVal=InfoMessCopyright[z];
+ XORVal=XORVal << (((z+1)%4)*8);
+ Magic=Magic^XORVal;
+ END
+END
+
+ Boolean AddressWildcard(char *addr)
+BEGIN
+ return ((strcmp(addr, "$") == 0) OR (strcasecmp(addr, "0x") == 0));
+END
+
+#ifdef CKMALLOC
+#undef malloc
+#undef realloc
+
+ void *ckmalloc(size_t s)
+BEGIN
+ void *tmp=malloc(s);
+ if (tmp==NULL)
+ BEGIN
+ fprintf(stderr,"allocation error(malloc): out of memory");
+ exit(255);
+ END
+ return tmp;
+END
+
+ void *ckrealloc(void *p, size_t s)
+BEGIN
+ void *tmp=realloc(p,s);
+ if (tmp==NULL)
+ BEGIN
+ fprintf(stderr,"allocation error(realloc): out of memory");
+ exit(255);
+ END
+ return tmp;
+END
+#endif
+
+
diff --git a/toolutils.h b/toolutils.h
new file mode 100644
index 0000000..2e96454
--- /dev/null
+++ b/toolutils.h
@@ -0,0 +1,52 @@
+/* toolutils.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Unterroutinen fuer die AS-Tools */
+/* */
+/* Historie: 31. 5.1996 Grundsteinlegung */
+/* 30. 5.1999 Adresswildcard-Funktion */
+/* */
+/*****************************************************************************/
+
+#include "fileformat.h"
+
+extern LongWord Magic;
+
+extern Word FileID;
+
+extern char *OutName;
+
+
+extern void WrCopyRight(char *Msg);
+
+extern void DelSuffix(char *Name);
+
+extern void AddSuffix(char *Name, char *Suff);
+
+extern void FormatError(char *Name, char *Detail);
+
+extern void ChkIO(char *Name);
+
+extern Word Granularity(Byte Header);
+
+extern void ReadRecordHeader(Byte *Header, Byte* Segment, Byte *Gran,
+ char *Name, FILE *f);
+
+extern void WriteRecordHeader(Byte *Header, Byte* Segment, Byte *Gran,
+ char *Name, FILE *f);
+
+extern CMDResult CMD_FilterList(Boolean Negate, char *Arg);
+
+extern Boolean FilterOK(Byte Header);
+
+extern Boolean RemoveOffset(char *Name, LongWord *Offset);
+
+
+extern void EraseFile(char *FileName, LongWord Offset);
+
+
+extern Boolean AddressWildcard(char *addr);
+
+
+extern void toolutils_init(char *ProgPath);
diff --git a/tsc.h b/tsc.h
new file mode 100644
index 0000000..b3a9928
--- /dev/null
+++ b/tsc.h
@@ -0,0 +1,3 @@
+/* tsc.asm-Includefile für C-Programm */
+#define test 0x24
+/* Ende Includefile für C-Programm */
diff --git a/umlaut.c b/umlaut.c
new file mode 100644
index 0000000..77bfa84
--- /dev/null
+++ b/umlaut.c
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "sysdefs.h"
+#include "specchars.h"
+
+#define TMPNAME "tempfile"
+
+ int main(int argc, char **argv)
+{
+ FILE *src,*dest;
+ int ch;
+ int z,z2,res;
+ unsigned char cmdline[1024];
+ long charcnt,metacnt,crcnt;
+
+ if (argc<2)
+ {
+ fprintf(stderr,"usage: %s <file> [more files]\n",argv[0]);
+ exit(1);
+ }
+
+ for (z=1; z<argc; z++)
+ {
+ src=fopen(argv[z],OPENRDMODE);
+ if (src==NULL)
+ {
+ fprintf(stderr,"error opening %s for reading\n",argv[z]); exit(2);
+ }
+ dest=fopen(TMPNAME,OPENWRMODE);
+ if (dest==NULL)
+ {
+ fprintf(stderr,"error opening %s for writing\n",TMPNAME); exit(2);
+ }
+ charcnt=metacnt=crcnt=0;
+ while (!feof(src))
+ {
+ ch=fgetc(src); charcnt++;
+ switch (ch)
+ {
+ case EOF:
+ break;
+ case 13:
+ crcnt++; break;
+ default:
+ for (z2=0; *specchars[z2]!=0000; z2++)
+ if (ch==specchars[z2][0])
+ { fputc(specchars[z2][1],dest); metacnt++; break; }
+ if (*specchars[z2]==0000) fputc(ch,dest);
+ }
+ }
+ fclose(src); fclose(dest);
+ sprintf(cmdline,"mv %s %s",TMPNAME,argv[z]); res=system(cmdline);
+ if (res!=0)
+ {
+ fprintf(stderr,"command \"%s\" failed\n",cmdline); exit(2);
+ }
+ printf("%s: %ld char(s), %ld cr(s) stripped, %ld meta char(s) converted\n",
+ argv[z],charcnt,crcnt,metacnt);
+ }
+
+ exit(0);
+}
diff --git a/unumlaut.c b/unumlaut.c
new file mode 100644
index 0000000..73caab7
--- /dev/null
+++ b/unumlaut.c
@@ -0,0 +1,91 @@
+#include "stdinc.h"
+
+#include "chardefs.h"
+
+typedef struct
+ {
+ int isochar;
+ char *syschar;
+ } chartrans;
+
+static chartrans specchars[]=
+ {{0344,CH_ae},
+ {0366,CH_oe},
+ {0374,CH_ue},
+ {0304,CH_Ae},
+ {0326,CH_Oe},
+ {0334,CH_Ue},
+ {0337,CH_sz},
+ {0262,CH_e2},
+ {0265,CH_mu},
+ {0340,CH_agrave},
+ {0000,""}};
+
+#define TMPNAME "tempfile"
+
+ void doexec(char *cmdline)
+{
+ int res=system(cmdline);
+ if (res!=0)
+ {
+ fprintf(stderr,"command \"%s\" failed\n",cmdline); exit(2);
+ }
+}
+
+ int main(int argc, char **argv)
+{
+ FILE *src,*dest;
+ int ch;
+ unsigned char cmdline[1024];
+ long charcnt,metacnt,crcnt;
+ chartrans *z2;
+
+ if (argc<2)
+ {
+ fprintf(stderr,"usage: %s <file> [destfile]\n",argv[0]);
+ exit(1);
+ }
+
+ src=fopen(argv[1],OPENRDMODE);
+ if (src==NULL)
+ {
+ fprintf(stderr,"error opening %s for reading\n",argv[1]); exit(2);
+ }
+ dest=fopen((argc==2)?TMPNAME:argv[2],OPENWRMODE);
+ if (dest==NULL)
+ {
+ fprintf(stderr,"error opening %s for writing\n",TMPNAME); exit(2);
+ }
+ charcnt=metacnt=crcnt=0;
+ while (!feof(src))
+ {
+ ch=fgetc(src); charcnt++;
+ switch (ch)
+ {
+ case EOF:
+ break;
+ case 10:
+ fputc(13,dest); fputc(10,dest); crcnt++; break;
+ default:
+ for (z2=specchars; z2->isochar!=0000; z2++)
+ if (ch==z2->isochar)
+ { fputs(z2->syschar,dest); metacnt++; break; }
+ if (z2->isochar==0000) fputc(ch,dest);
+ }
+ }
+ fclose(src); fclose(dest);
+ if (argc==2)
+ BEGIN
+#if defined (__MSDOS__) || defined(__EMX__)
+ sprintf(cmdline,"copy %s %s",TMPNAME,argv[1]);
+#else
+ sprintf(cmdline,"cp %s %s",TMPNAME,argv[1]);
+#endif
+ doexec(cmdline);
+ unlink(TMPNAME);
+ END
+ printf("%s: %ld char(s), %ld cr(s) added, %ld meta char(s) reconverted\n",
+ argv[1],charcnt,crcnt,metacnt);
+
+ return 0;
+}
diff --git a/ushyph.c b/ushyph.c
new file mode 100644
index 0000000..fd85d10
--- /dev/null
+++ b/ushyph.c
@@ -0,0 +1,696 @@
+/* ushyph.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Trennungsmuster (US-)englisch */
+/* abgeleitet von 'ushyphen.tex' aus TeX */
+/* */
+/* Historie: 16. 2.1998 Konvertierung */
+/* 2. 7.1998 für MSDOS auskommentiert */
+/* */
+/*****************************************************************************/
+
+#include <stdio.h>
+
+#ifndef __MSDOS__
+char *USHyphens[]=
+
+/* The Plain TeX hyphenation tables [NOT TO BE CHANGED IN ANY WAY!] */
+
+{".ach4 .ad4der .af1t .al3t .am5at .an5c .ang4 .ani5m",
+ ".ant4 .an3te .anti5s .ar5s .ar4tie .ar4ty .as3c",
+ ".as1p .as1s .aster5 .atom5 .au1d .av4i .awn4",
+ ".ba4g .ba5na .bas4e .ber4 .be5ra .be3sm .be5sto",
+ ".bri2 .but4ti .cam4pe .can5c .capa5b .car5ol .ca4t",
+ ".ce4la .ch4 .chill5i .ci2 .cit5r .co3e .co4r",
+ ".cor5ner .de4moi .de3o .de3ra .de3ri .des4c .dictio5",
+ ".do4t .du4c .dumb5 .earth5 .eas3i .eb4 .eer4",
+ ".eg2 .el5d .el3em .enam3 .en3g .en3s .eq5ui5t",
+ ".er4ri .es3 .eu3 .eye5 .fes3 .for5mer .ga2 .ge2",
+ ".gen3t4 .ge5og .gi5a .gi4b .go4r .hand5i .han5k",
+ ".he2 .hero5i .hes3 .het3 .hi3b .hi3er .hon5ey",
+ ".hon3o .hov5 .id4l .idol3 .im3m .im5pin .in1",
+ ".in3ci .ine2 .in2k .in3s .ir5r .is4i .ju3r .la4cy",
+ ".la4m .lat5er .lath5 .le2 .leg5e .len4 .lep5",
+ ".lev1 .li4g .lig5a .li2n .li3o .li4t .mag5a5",
+ ".mal5o .man5a .mar5ti .me2 .mer3c .me5ter .mis1",
+ ".mist5i .mon3e .mo3ro .mu5ta .muta5b .ni4c .od2",
+ ".odd5 .of5te .or5ato .or3c .or1d .or3t .os3 .os4tl",
+ ".oth3 .out3 .ped5al .pe5te .pe5tit .pi4e .pio5n",
+ ".pi2t .pre3m .ra4c .ran4t .ratio5na .ree2 .re5mit",
+ ".res2 .re5stat .ri4g .rit5u .ro4q .ros5t .row5d",
+ ".ru4d .sci3e .self5 .sell5 .se2n .se5rie .sh2",
+ ".si2 .sing4 .st4 .sta5bl .sy2 .ta4 .te4 .ten5an",
+ ".th2 .ti2 .til4 .tim5o5 .ting4 .tin5k .ton4a",
+ ".to4p .top5i .tou5s .trib5ut .un1a .un3ce .under5",
+ ".un1e .un5k .un5o .un3u .up3 .ure3 .us5a .ven4de",
+ ".ve5ra .wil5i .ye4 4ab. a5bal a5ban abe2 ab5erd",
+ "abi5a ab5it5ab ab5lat ab5o5liz 4abr ab5rog ab3ul",
+ "a4car ac5ard ac5aro a5ceou ac1er a5chet 4a2ci",
+ "a3cie ac1in a3cio ac5rob act5if ac3ul ac4um a2d",
+ "ad4din ad5er. 2adi a3dia ad3ica adi4er a3dio",
+ "a3dit a5diu ad4le ad3ow ad5ran ad4su 4adu a3duc",
+ "ad5um ae4r aeri4e a2f aff4 a4gab aga4n ag5ell",
+ "age4o 4ageu ag1i 4ag4l ag1n a2go 3agog ag3oni",
+ "a5guer ag5ul a4gy a3ha a3he ah4l a3ho ai2 a5ia",
+ "a3ic. ai5ly a4i4n ain5in ain5o ait5en a1j ak1en",
+ "al5ab al3ad a4lar 4aldi 2ale al3end a4lenti a5le5o",
+ "al1i al4ia. ali4e al5lev 4allic 4alm a5log. a4ly.",
+ "4alys 5a5lyst 5alyt 3alyz 4ama am5ab am3ag ama5ra",
+ "am5asc a4matis a4m5ato am5era am3ic am5if am5ily",
+ "am1in ami4no a2mo a5mon amor5i amp5en a2n an3age",
+ "3analy a3nar an3arc anar4i a3nati 4and ande4s",
+ "an3dis an1dl an4dow a5nee a3nen an5est. a3neu",
+ "2ang ang5ie an1gl a4n1ic a3nies an3i3f an4ime",
+ "a5nimi a5nine an3io a3nip an3ish an3it a3niu",
+ "an4kli 5anniz ano4 an5ot anoth5 an2sa an4sco",
+ "an4sn an2sp ans3po an4st an4sur antal4 an4tie",
+ "4anto an2tr an4tw an3ua an3ul a5nur 4ao apar4",
+ "ap5at ap5ero a3pher 4aphi a4pilla ap5illar ap3in",
+ "ap3ita a3pitu a2pl apoc5 ap5ola apor5i apos3t",
+ "aps5es a3pu aque5 2a2r ar3act a5rade ar5adis",
+ "ar3al a5ramete aran4g ara3p ar4at a5ratio ar5ativ",
+ "a5rau ar5av4 araw4 arbal4 ar4chan ar5dine ar4dr",
+ "ar5eas a3ree ar3ent a5ress ar4fi ar4fl ar1i ar5ial",
+ "ar3ian a3riet ar4im ar5inat ar3io ar2iz ar2mi",
+ "ar5o5d a5roni a3roo ar2p ar3q arre4 ar4sa ar2sh",
+ "4as. as4ab as3ant ashi4 a5sia. a3sib a3sic 5a5si4t",
+ "ask3i as4l a4soc as5ph as4sh as3ten as1tr asur5a",
+ "a2ta at3abl at5ac at3alo at5ap ate5c at5ech at3ego",
+ "at3en. at3era ater5n a5terna at3est at5ev 4ath",
+ "ath5em a5then at4ho ath5om 4ati. a5tia at5i5b",
+ "at1ic at3if ation5ar at3itu a4tog a2tom at5omiz",
+ "a4top a4tos a1tr at5rop at4sk at4tag at5te at4th",
+ "a2tu at5ua at5ue at3ul at3ura a2ty au4b augh3",
+ "au3gu au4l2 aun5d au3r au5sib aut5en au1th a2va",
+ "av3ag a5van ave4no av3era av5ern av5ery av1i",
+ "avi4er av3ig av5oc a1vor 3away aw3i aw4ly aws4",
+ "ax4ic ax4id ay5al aye4 ays4 azi4er azz5i 5ba.",
+ "bad5ger ba4ge bal1a ban5dag ban4e ban3i barbi5",
+ "bari4a bas4si 1bat ba4z 2b1b b2be b3ber bbi4na",
+ "4b1d 4be. beak4 beat3 4be2d be3da be3de be3di",
+ "be3gi be5gu 1bel be1li be3lo 4be5m be5nig be5nu",
+ "4bes4 be3sp be5str 3bet bet5iz be5tr be3tw be3w",
+ "be5yo 2bf 4b3h bi2b bi4d 3bie bi5en bi4er 2b3if",
+ "1bil bi3liz bina5r4 bin4d bi5net bi3ogr bi5ou",
+ "bi2t 3bi3tio bi3tr 3bit5ua b5itz b1j bk4 b2l2",
+ "blath5 b4le. blen4 5blesp b3lis b4lo blun4t 4b1m",
+ "4b3n bne5g 3bod bod3i bo4e bol3ic bom4bi bon4a",
+ "bon5at 3boo 5bor. 4b1ora bor5d 5bore 5bori 5bos4",
+ "b5ota both5 bo4to bound3 4bp 4brit broth3 2b5s2",
+ "bsor4 2bt bt4l b4to b3tr buf4fer bu4ga bu3li",
+ "bumi4 bu4n bunt4i bu3re bus5ie buss4e 5bust 4buta",
+ "3butio b5uto b1v 4b5w 5by. bys4 1ca cab3in",
+ "ca1bl cach4 ca5den 4cag4 2c5ah ca3lat cal4la",
+ "call5in 4calo can5d can4e can4ic can5is can3iz",
+ "can4ty cany4 ca5per car5om cast5er cas5tig 4casy",
+ "ca4th 4cativ cav5al c3c ccha5 cci4a ccompa5 ccon4",
+ "ccou3t 2ce. 4ced. 4ceden 3cei 5cel. 3cell 1cen",
+ "3cenc 2cen4e 4ceni 3cent 3cep ce5ram 4cesa 3cessi",
+ "ces5si5b ces5t cet4 c5e4ta cew4 2ch 4ch. 4ch3ab",
+ "5chanic ch5a5nis che2 cheap3 4ched che5lo 3chemi",
+ "ch5ene ch3er. ch3ers 4ch1in 5chine. ch5iness 5chini",
+ "5chio 3chit chi2z 3cho2 ch4ti 1ci 3cia ci2a5b",
+ "cia5r ci5c 4cier 5cific. 4cii ci4la 3cili 2cim",
+ "2cin c4ina 3cinat cin3em c1ing c5ing. 5cino cion4",
+ "4cipe ci3ph 4cipic 4cista 4cisti 2c1it cit3iz",
+ "5ciz ck1 ck3i 1c4l4 4clar c5laratio 5clare cle4m",
+ "4clic clim4 cly4 c5n 1co co5ag coe2 2cog co4gr",
+ "coi4 co3inc col5i 5colo col3or com5er con4a c4one",
+ "con3g con5t co3pa cop3ic co4pl 4corb coro3n cos4e",
+ "cov1 cove4 cow5a coz5e co5zi c1q cras5t 5crat.",
+ "5cratic cre3at 5cred 4c3reta cre4v cri2 cri5f",
+ "c4rin cris4 5criti cro4pl crop5o cros4e cru4d",
+ "4c3s2 2c1t cta4b ct5ang c5tant c2te c3ter c4ticu",
+ "ctim3i ctu4r c4tw cud5 c4uf c4ui cu5ity 5culi",
+ "cul4tis 3cultu cu2ma c3ume cu4mi 3cun cu3pi cu5py",
+ "cur5a4b cu5ria 1cus cuss4i 3c4ut cu4tie 4c5utiv",
+ "4cutr 1cy cze4 1d2a 5da. 2d3a4b dach4 4daf",
+ "2dag da2m2 dan3g dard5 dark5 4dary 3dat 4dativ",
+ "4dato 5dav4 dav5e 5day d1b d5c d1d4 2de. deaf5",
+ "deb5it de4bon decan4 de4cil de5com 2d1ed 4dee.",
+ "de5if deli4e del5i5q de5lo d4em 5dem. 3demic",
+ "dem5ic. de5mil de4mons demor5 1den de4nar de3no",
+ "denti5f de3nu de1p de3pa depi4 de2pu d3eq d4erh",
+ "5derm dern5iz der5s des2 d2es. de1sc de2s5o des3ti",
+ "de3str de4su de1t de2to de1v dev3il 4dey 4d1f",
+ "d4ga d3ge4t dg1i d2gy d1h2 5di. 1d4i3a dia5b",
+ "di4cam d4ice 3dict 3did 5di3en d1if di3ge di4lato",
+ "d1in 1dina 3dine. 5dini di5niz 1dio dio5g di4pl",
+ "dir2 di1re dirt5i dis1 5disi d4is3t d2iti 1di1v",
+ "d1j d5k2 4d5la 3dle. 3dled 3dles. 4dless 2d3lo",
+ "4d5lu 2dly d1m 4d1n4 1do 3do. do5de 5doe 2d5of",
+ "d4og do4la doli4 do5lor dom5iz do3nat doni4 doo3d",
+ "dop4p d4or 3dos 4d5out do4v 3dox d1p 1dr drag5on",
+ "4drai dre4 drea5r 5dren dri4b dril4 dro4p 4drow",
+ "5drupli 4dry 2d1s2 ds4p d4sw d4sy d2th 1du",
+ "d1u1a du2c d1uca duc5er 4duct. 4ducts du5el du4g",
+ "d3ule dum4be du4n 4dup du4pe d1v d1w d2y 5dyn",
+ "dy4se dys5p e1a4b e3act ead1 ead5ie ea4ge ea5ger",
+ "ea4l eal5er eal3ou eam3er e5and ear3a ear4c ear5es",
+ "ear4ic ear4il ear5k ear2t eart3e ea5sp e3ass",
+ "east3 ea2t eat5en eath3i e5atif e4a3tu ea2v eav3en",
+ "eav5i eav5o 2e1b e4bel. e4bels e4ben e4bit e3br",
+ "e4cad ecan5c ecca5 e1ce ec5essa ec2i e4cib ec5ificat",
+ "ec5ifie ec5ify ec3im eci4t e5cite e4clam e4clus",
+ "e2col e4comm e4compe e4conc e2cor ec3ora eco5ro",
+ "e1cr e4crem ec4tan ec4te e1cu e4cul ec3ula 2e2da",
+ "4ed3d e4d1er ede4s 4edi e3dia ed3ib ed3ica ed3im",
+ "ed1it edi5z 4edo e4dol edon2 e4dri e4dul ed5ulo",
+ "ee2c eed3i ee2f eel3i ee4ly ee2m ee4na ee4p1",
+ "ee2s4 eest4 ee4ty e5ex e1f e4f3ere 1eff e4fic",
+ "5efici efil4 e3fine ef5i5nite 3efit efor5es e4fuse.",
+ "4egal eger4 eg5ib eg4ic eg5ing e5git5 eg5n e4go.",
+ "e4gos eg1ul e5gur 5egy e1h4 eher4 ei2 e5ic",
+ "ei5d eig2 ei5gl e3imb e3inf e1ing e5inst eir4d",
+ "eit3e ei3th e5ity e1j e4jud ej5udi eki4n ek4la",
+ "e1la e4la. e4lac elan4d el5ativ e4law elaxa4",
+ "e3lea el5ebra 5elec e4led el3ega e5len e4l1er",
+ "e1les el2f el2i e3libe e4l5ic. el3ica e3lier",
+ "el5igib e5lim e4l3ing e3lio e2lis el5ish e3liv3",
+ "4ella el4lab ello4 e5loc el5og el3op. el2sh el4ta",
+ "e5lud el5ug e4mac e4mag e5man em5ana em5b e1me",
+ "e2mel e4met em3ica emi4e em5igra em1in2 em5ine",
+ "em3i3ni e4mis em5ish e5miss em3iz 5emniz emo4g",
+ "emoni5o em3pi e4mul em5ula emu3n e3my en5amo",
+ "e4nant ench4er en3dic e5nea e5nee en3em en5ero",
+ "en5esi en5est en3etr e3new en5ics e5nie e5nil",
+ "e3nio en3ish en3it e5niu 5eniz 4enn 4eno eno4g",
+ "e4nos en3ov en4sw ent5age 4enthes en3ua en5uf",
+ "e3ny. 4en3z e5of eo2g e4oi4 e3ol eop3ar e1or",
+ "eo3re eo5rol eos4 e4ot eo4to e5out e5ow e2pa",
+ "e3pai ep5anc e5pel e3pent ep5etitio ephe4 e4pli",
+ "e1po e4prec ep5reca e4pred ep3reh e3pro e4prob",
+ "ep4sh ep5ti5b e4put ep5uta e1q equi3l e4q3ui3s",
+ "er1a era4b 4erand er3ar 4erati. 2erb er4bl er3ch",
+ "er4che 2ere. e3real ere5co ere3in er5el. er3emo",
+ "er5ena er5ence 4erene er3ent ere4q er5ess er3est",
+ "eret4 er1h er1i e1ria4 5erick e3rien eri4er er3ine",
+ "e1rio 4erit er4iu eri4v e4riva er3m4 er4nis 4ernit",
+ "5erniz er3no 2ero er5ob e5roc ero4r er1ou er1s",
+ "er3set ert3er 4ertl er3tw 4eru eru4t 5erwau e1s4a",
+ "e4sage. e4sages es2c e2sca es5can e3scr es5cu",
+ "e1s2e e2sec es5ecr es5enc e4sert. e4serts e4serva",
+ "4esh e3sha esh5en e1si e2sic e2sid es5iden es5igna",
+ "e2s5im es4i4n esis4te esi4u e5skin es4mi e2sol",
+ "es3olu e2son es5ona e1sp es3per es5pira es4pre",
+ "2ess es4si4b estan4 es3tig es5tim 4es2to e3ston",
+ "2estr e5stro estruc5 e2sur es5urr es4w eta4b",
+ "eten4d e3teo ethod3 et1ic e5tide etin4 eti4no",
+ "e5tir e5titio et5itiv 4etn et5ona e3tra e3tre",
+ "et3ric et5rif et3rog et5ros et3ua et5ym et5z",
+ "4eu e5un e3up eu3ro eus4 eute4 euti5l eu5tr",
+ "eva2p5 e2vas ev5ast e5vea ev3ell evel3o e5veng",
+ "even4i ev1er e5verb e1vi ev3id evi4l e4vin evi4v",
+ "e5voc e5vu e1wa e4wag e5wee e3wh ewil5 ew3ing",
+ "e3wit 1exp 5eyc 5eye. eys4 1fa fa3bl fab3r",
+ "fa4ce 4fag fain4 fall5e 4fa4ma fam5is 5far far5th",
+ "fa3ta fa3the 4fato fault5 4f5b 4fd 4fe. feas4",
+ "feath3 fe4b 4feca 5fect 2fed fe3li fe4mo fen2d",
+ "fend5e fer1 5ferr fev4 4f1f f4fes f4fie f5fin.",
+ "f2f5is f4fly f2fy 4fh 1fi fi3a 2f3ic. 4f3ical",
+ "f3ican 4ficate f3icen fi3cer fic4i 5ficia 5ficie",
+ "4fics fi3cu fi5del fight5 fil5i fill5in 4fily",
+ "2fin 5fina fin2d5 fi2ne f1in3g fin4n fis4ti f4l2",
+ "f5less flin4 flo3re f2ly5 4fm 4fn 1fo 5fon",
+ "fon4de fon4t fo2r fo5rat for5ay fore5t for4i",
+ "fort5a fos5 4f5p fra4t f5rea fres5c fri2 fril4",
+ "frol5 2f3s 2ft f4to f2ty 3fu fu5el 4fug fu4min",
+ "fu5ne fu3ri fusi4 fus4s 4futa 1fy 1ga gaf4",
+ "5gal. 3gali ga3lo 2gam ga5met g5amo gan5is ga3niz",
+ "gani5za 4gano gar5n4 gass4 gath3 4gativ 4gaz",
+ "g3b gd4 2ge. 2ged geez4 gel4in ge5lis ge5liz",
+ "4gely 1gen ge4nat ge5niz 4geno 4geny 1geo ge3om",
+ "g4ery 5gesi geth5 4geto ge4ty ge4v 4g1g2 g2ge",
+ "g3ger gglu5 ggo4 gh3in gh5out gh4to 5gi. 1gi4a",
+ "gia5r g1ic 5gicia g4ico gien5 5gies. gil4 g3imen",
+ "3g4in. gin5ge 5g4ins 5gio 3gir gir4l g3isl gi4u",
+ "5giv 3giz gl2 gla4 glad5i 5glas 1gle gli4b",
+ "g3lig 3glo glo3r g1m g4my gn4a g4na. gnet4t",
+ "g1ni g2nin g4nio g1no g4non 1go 3go. gob5 5goe",
+ "3g4o4g go3is gon2 4g3o3na gondo5 go3ni 5goo go5riz",
+ "gor5ou 5gos. gov1 g3p 1gr 4grada g4rai gran2",
+ "5graph. g5rapher 5graphic 4graphy 4gray gre4n 4gress.",
+ "4grit g4ro gruf4 gs2 g5ste gth3 gu4a 3guard",
+ "2gue 5gui5t 3gun 3gus 4gu4t g3w 1gy 2g5y3n",
+ "gy5ra h3ab4l hach4 hae4m hae4t h5agu ha3la hala3m",
+ "ha4m han4ci han4cy 5hand. han4g hang5er hang5o",
+ "h5a5niz han4k han4te hap3l hap5t ha3ran ha5ras",
+ "har2d hard3e har4le harp5en har5ter has5s haun4",
+ "5haz haz3a h1b 1head 3hear he4can h5ecat h4ed",
+ "he5do5 he3l4i hel4lis hel4ly h5elo hem4p he2n",
+ "hena4 hen5at heo5r hep5 h4era hera3p her4ba here5a",
+ "h3ern h5erou h3ery h1es he2s5p he4t het4ed heu4",
+ "h1f h1h hi5an hi4co high5 h4il2 himer4 h4ina",
+ "hion4e hi4p hir4l hi3ro hir4p hir4r his3el his4s",
+ "hith5er hi2v 4hk 4h1l4 hlan4 h2lo hlo3ri 4h1m",
+ "hmet4 2h1n h5odiz h5ods ho4g hoge4 hol5ar 3hol4e",
+ "ho4ma home3 hon4a ho5ny 3hood hoon4 hor5at ho5ris",
+ "hort3e ho5ru hos4e ho5sen hos1p 1hous house3",
+ "hov5el 4h5p 4hr4 hree5 hro5niz hro3po 4h1s2 h4sh",
+ "h4tar ht1en ht5es h4ty hu4g hu4min hun5ke hun4t",
+ "hus3t4 hu4t h1w h4wart hy3pe hy3ph hy2s 2i1a",
+ "i2al iam4 iam5ete i2an 4ianc ian3i 4ian4t ia5pe",
+ "iass4 i4ativ ia4tric i4atu ibe4 ib3era ib5ert",
+ "ib5ia ib3in ib5it. ib5ite i1bl ib3li i5bo i1br",
+ "i2b5ri i5bun 4icam 5icap 4icar i4car. i4cara",
+ "icas5 i4cay iccu4 4iceo 4ich 2ici i5cid ic5ina",
+ "i2cip ic3ipa i4cly i2c5oc 4i1cr 5icra i4cry ic4te",
+ "ictu2 ic4t3ua ic3ula ic4um ic5uo i3cur 2id i4dai",
+ "id5anc id5d ide3al ide4s i2di id5ian idi4ar i5die",
+ "id3io idi5ou id1it id5iu i3dle i4dom id3ow i4dr",
+ "i2du id5uo 2ie4 ied4e 5ie5ga ield3 ien5a4 ien4e",
+ "i5enn i3enti i1er. i3esc i1est i3et 4if. if5ero",
+ "iff5en if4fr 4ific. i3fie i3fl 4ift 2ig iga5b",
+ "ig3era ight3i 4igi i3gib ig3il ig3in ig3it i4g4l",
+ "i2go ig3or ig5ot i5gre igu5i ig1ur i3h 4i5i4",
+ "i3j 4ik i1la il3a4b i4lade i2l5am ila5ra i3leg",
+ "il1er ilev4 il5f il1i il3ia il2ib il3io il4ist",
+ "2ilit il2iz ill5ab 4iln il3oq il4ty il5ur il3v",
+ "i4mag im3age ima5ry imenta5r 4imet im1i im5ida",
+ "imi5le i5mini 4imit im4ni i3mon i2mu im3ula 2in.",
+ "i4n3au 4inav incel4 in3cer 4ind in5dling 2ine",
+ "i3nee iner4ar i5ness 4inga 4inge in5gen 4ingi",
+ "in5gling 4ingo 4ingu 2ini i5ni. i4nia in3io in1is",
+ "i5nite. 5initio in3ity 4ink 4inl 2inn 2i1no i4no4c",
+ "ino4s i4not 2ins in3se insur5a 2int. 2in4th in1u",
+ "i5nus 4iny 2io 4io. ioge4 io2gr i1ol io4m ion3at",
+ "ion4ery ion3i io5ph ior3i i4os io5th i5oti io4to",
+ "i4our 2ip ipe4 iphras4 ip3i ip4ic ip4re4 ip3ul",
+ "i3qua iq5uef iq3uid iq3ui3t 4ir i1ra ira4b i4rac",
+ "ird5e ire4de i4ref i4rel4 i4res ir5gi ir1i iri5de",
+ "ir4is iri3tu 5i5r2iz ir4min iro4g 5iron. ir5ul",
+ "2is. is5ag is3ar isas5 2is1c is3ch 4ise is3er",
+ "3isf is5han is3hon ish5op is3ib isi4d i5sis is5itiv",
+ "4is4k islan4 4isms i2so iso5mer is1p is2pi is4py",
+ "4is1s is4sal issen4 is4ses is4ta. is1te is1ti",
+ "ist4ly 4istral i2su is5us 4ita. ita4bi i4tag",
+ "4ita5m i3tan i3tat 2ite it3era i5teri it4es 2ith",
+ "i1ti 4itia 4i2tic it3ica 5i5tick it3ig it5ill",
+ "i2tim 2itio 4itis i4tism i2t5o5m 4iton i4tram",
+ "it5ry 4itt it3uat i5tud it3ul 4itz. i1u 2iv",
+ "iv3ell iv3en. i4v3er. i4vers. iv5il. iv5io iv1it",
+ "i5vore iv3o3ro i4v3ot 4i5w ix4o 4iy 4izar izi4",
+ "5izont 5ja jac4q ja4p 1je jer5s 4jestie 4jesty",
+ "jew3 jo4p 5judg 3ka. k3ab k5ag kais4 kal4 k1b",
+ "k2ed 1kee ke4g ke5li k3en4d k1er kes4 k3est.",
+ "ke4ty k3f kh4 k1i 5ki. 5k2ic k4ill kilo5 k4im",
+ "k4in. kin4de k5iness kin4g ki4p kis4 k5ish kk4",
+ "k1l 4kley 4kly k1m k5nes 1k2no ko5r kosh4 k3ou",
+ "kro5n 4k1s2 k4sc ks4l k4sy k5t k1w lab3ic l4abo",
+ "laci4 l4ade la3dy lag4n lam3o 3land lan4dl lan5et",
+ "lan4te lar4g lar3i las4e la5tan 4lateli 4lativ",
+ "4lav la4v4a 2l1b lbin4 4l1c2 lce4 l3ci 2ld",
+ "l2de ld4ere ld4eri ldi4 ld5is l3dr l4dri le2a",
+ "le4bi left5 5leg. 5legg le4mat lem5atic 4len.",
+ "3lenc 5lene. 1lent le3ph le4pr lera5b ler4e 3lerg",
+ "3l4eri l4ero les2 le5sco 5lesq 3less 5less. l3eva",
+ "lev4er. lev4era lev4ers 3ley 4leye 2lf l5fr 4l1g4",
+ "l5ga lgar3 l4ges lgo3 2l3h li4ag li2am liar5iz",
+ "li4as li4ato li5bi 5licio li4cor 4lics 4lict.",
+ "l4icu l3icy l3ida lid5er 3lidi lif3er l4iff li4fl",
+ "5ligate 3ligh li4gra 3lik 4l4i4l lim4bl lim3i",
+ "li4mo l4im4p l4ina 1l4ine lin3ea lin3i link5er",
+ "li5og 4l4iq lis4p l1it l2it. 5litica l5i5tics",
+ "liv3er l1iz 4lj lka3 l3kal lka4t l1l l4law",
+ "l2le l5lea l3lec l3leg l3lel l3le4n l3le4t ll2i",
+ "l2lin4 l5lina ll4o lloqui5 ll5out l5low 2lm l5met",
+ "lm3ing l4mod lmon4 2l1n2 3lo. lob5al lo4ci 4lof",
+ "3logic l5ogo 3logu lom3er 5long lon4i l3o3niz",
+ "lood5 5lope. lop3i l3opm lora4 lo4rato lo5rie",
+ "lor5ou 5los. los5et 5losophiz 5losophy los4t lo4ta",
+ "loun5d 2lout 4lov 2lp lpa5b l3pha l5phi lp5ing",
+ "l3pit l4pl l5pr 4l1r 2l1s2 l4sc l2se l4sie",
+ "4lt lt5ag ltane5 l1te lten4 ltera4 lth3i l5ties.",
+ "ltis4 l1tr ltu2 ltur3a lu5a lu3br luch4 lu3ci",
+ "lu3en luf4 lu5id lu4ma 5lumi l5umn. 5lumnia lu3o",
+ "luo3r 4lup luss4 lus3te 1lut l5ven l5vet4 2l1w",
+ "1ly 4lya 4lyb ly5me ly3no 2lys4 l5yse 1ma 2mab",
+ "ma2ca ma5chine ma4cl mag5in 5magn 2mah maid5",
+ "4mald ma3lig ma5lin mal4li mal4ty 5mania man5is",
+ "man3iz 4map ma5rine. ma5riz mar4ly mar3v ma5sce",
+ "mas4e mas1t 5mate math3 ma3tis 4matiza 4m1b mba4t5",
+ "m5bil m4b3ing mbi4v 4m5c 4me. 2med 4med. 5media",
+ "me3die m5e5dy me2g mel5on mel4t me2m mem1o3 1men",
+ "men4a men5ac men4de 4mene men4i mens4 mensu5",
+ "3ment men4te me5on m5ersa 2mes 3mesti me4ta met3al",
+ "me1te me5thi m4etr 5metric me5trie me3try me4v",
+ "4m1f 2mh 5mi. mi3a mid4a mid4g mig4 3milia",
+ "m5i5lie m4ill min4a 3mind m5inee m4ingl min5gli",
+ "m5ingly min4t m4inu miot4 m2is mis4er. mis5l",
+ "mis4ti m5istry 4mith m2iz 4mk 4m1l m1m mma5ry",
+ "4m1n mn4a m4nin mn4o 1mo 4mocr 5mocratiz mo2d1",
+ "mo4go mois2 moi5se 4mok mo5lest mo3me mon5et",
+ "mon5ge moni3a mon4ism mon4ist mo3niz monol4 mo3ny.",
+ "mo2r 4mora. mos2 mo5sey mo3sp moth3 m5ouf 3mous",
+ "mo2v 4m1p mpara5 mpa5rab mpar5i m3pet mphas4",
+ "m2pi mpi4a mp5ies m4p1in m5pir mp5is mpo3ri mpos5ite",
+ "m4pous mpov5 mp4tr m2py 4m3r 4m1s2 m4sh m5si",
+ "4mt 1mu mula5r4 5mult multi3 3mum mun2 4mup",
+ "mu4u 4mw 1na 2n1a2b n4abu 4nac. na4ca n5act",
+ "nag5er. nak4 na4li na5lia 4nalt na5mit n2an nanci4",
+ "nan4it nank4 nar3c 4nare nar3i nar4l n5arm n4as",
+ "nas4c nas5ti n2at na3tal nato5miz n2au nau3se",
+ "3naut nav4e 4n1b4 ncar5 n4ces. n3cha n5cheo n5chil",
+ "n3chis nc1in nc4it ncour5a n1cr n1cu n4dai n5dan",
+ "n1de nd5est. ndi4b n5d2if n1dit n3diz n5duc ndu4r",
+ "nd2we 2ne. n3ear ne2b neb3u ne2c 5neck 2ned",
+ "ne4gat neg5ativ 5nege ne4la nel5iz ne5mi ne4mo",
+ "1nen 4nene 3neo ne4po ne2q n1er nera5b n4erar",
+ "n2ere n4er5i ner4r 1nes 2nes. 4nesp 2nest 4nesw",
+ "3netic ne4v n5eve ne4w n3f n4gab n3gel nge4n4e",
+ "n5gere n3geri ng5ha n3gib ng1in n5git n4gla ngov4",
+ "ng5sh n1gu n4gum n2gy 4n1h4 nha4 nhab3 nhe4",
+ "3n4ia ni3an ni4ap ni3ba ni4bl ni4d ni5di ni4er",
+ "ni2fi ni5ficat n5igr nik4 n1im ni3miz n1in 5nine.",
+ "nin4g ni4o 5nis. nis4ta n2it n4ith 3nitio n3itor",
+ "ni3tr n1j 4nk2 n5kero n3ket nk3in n1kl 4n1l",
+ "n5m nme4 nmet4 4n1n2 nne4 nni3al nni4v nob4l",
+ "no3ble n5ocl 4n3o2d 3noe 4nog noge4 nois5i no5l4i",
+ "5nologis 3nomic n5o5miz no4mo no3my no4n non4ag",
+ "non5i n5oniz 4nop 5nop5o5li nor5ab no4rary 4nosc",
+ "nos4e nos5t no5ta 1nou 3noun nov3el3 nowl3 n1p4",
+ "npi4 npre4c n1q n1r nru4 2n1s2 ns5ab nsati4",
+ "ns4c n2se n4s3es nsid1 nsig4 n2sl ns3m n4soc",
+ "ns4pe n5spi nsta5bl n1t nta4b nter3s nt2i n5tib",
+ "nti4er nti2f n3tine n4t3ing nti4p ntrol5li nt4s",
+ "ntu3me nu1a nu4d nu5en nuf4fe n3uin 3nu3it n4um",
+ "nu1me n5umi 3nu4n n3uo nu3tr n1v2 n1w4 nym4",
+ "nyp4 4nz n3za 4oa oad3 o5a5les oard3 oas4e",
+ "oast5e oat5i ob3a3b o5bar obe4l o1bi o2bin ob5ing",
+ "o3br ob3ul o1ce och4 o3chet ocif3 o4cil o4clam",
+ "o4cod oc3rac oc5ratiz ocre3 5ocrit octor5a oc3ula",
+ "o5cure od5ded od3ic odi3o o2do4 odor3 od5uct.",
+ "od5ucts o4el o5eng o3er oe4ta o3ev o2fi of5ite",
+ "ofit4t o2g5a5r og5ativ o4gato o1ge o5gene o5geo",
+ "o4ger o3gie 1o1gis og3it o4gl o5g2ly 3ogniz o4gro",
+ "ogu5i 1ogy 2ogyn o1h2 ohab5 oi2 oic3es oi3der",
+ "oiff4 oig4 oi5let o3ing oint5er o5ism oi5son",
+ "oist5en oi3ter o5j 2ok o3ken ok5ie o1la o4lan",
+ "olass4 ol2d old1e ol3er o3lesc o3let ol4fi ol2i",
+ "o3lia o3lice ol5id. o3li4f o5lil ol3ing o5lio",
+ "o5lis. ol3ish o5lite o5litio o5liv olli4e ol5ogiz",
+ "olo4r ol5pl ol2t ol3ub ol3ume ol3un o5lus ol2v",
+ "o2ly om5ah oma5l om5atiz om2be om4bl o2me om3ena",
+ "om5erse o4met om5etry o3mia om3ic. om3ica o5mid",
+ "om1in o5mini 5ommend omo4ge o4mon om3pi ompro5",
+ "o2n on1a on4ac o3nan on1c 3oncil 2ond on5do",
+ "o3nen on5est on4gu on1ic o3nio on1is o5niu on3key",
+ "on4odi on3omy on3s onspi4 onspir5a onsu4 onten4",
+ "on3t4i ontif5 on5um onva5 oo2 ood5e ood5i oo4k",
+ "oop3i o3ord oost5 o2pa ope5d op1er 3opera 4operag",
+ "2oph o5phan o5pher op3ing o3pit o5pon o4posi",
+ "o1pr op1u opy5 o1q o1ra o5ra. o4r3ag or5aliz",
+ "or5ange ore5a o5real or3ei ore5sh or5est. orew4",
+ "or4gu 4o5ria or3ica o5ril or1in o1rio or3ity",
+ "o3riu or2mi orn2e o5rof or3oug or5pe 3orrh or4se",
+ "ors5en orst4 or3thi or3thy or4ty o5rum o1ry os3al",
+ "os2c os4ce o3scop 4oscopi o5scr os4i4e os5itiv",
+ "os3ito os3ity osi4u os4l o2so os4pa os4po os2ta",
+ "o5stati os5til os5tit o4tan otele4g ot3er. ot5ers",
+ "o4tes 4oth oth5esi oth3i4 ot3ic. ot5ica o3tice",
+ "o3tif o3tis oto5s ou2 ou3bl ouch5i ou5et ou4l",
+ "ounc5er oun2d ou5v ov4en over4ne over3s ov4ert",
+ "o3vis oviti4 o5v4ol ow3der ow3el ow5est ow1i",
+ "own5i o4wo oy1a 1pa pa4ca pa4ce pac4t p4ad",
+ "5pagan p3agat p4ai pain4 p4al pan4a pan3el pan4ty",
+ "pa3ny pa1p pa4pu para5bl par5age par5di 3pare",
+ "par5el p4a4ri par4is pa2te pa5ter 5pathic pa5thy",
+ "pa4tric pav4 3pay 4p1b pd4 4pe. 3pe4a pear4l",
+ "pe2c 2p2ed 3pede 3pedi pedia4 ped4ic p4ee pee4d",
+ "pek4 pe4la peli4e pe4nan p4enc pen4th pe5on p4era.",
+ "pera5bl p4erag p4eri peri5st per4mal perme5 p4ern",
+ "per3o per3ti pe5ru per1v pe2t pe5ten pe5tiz 4pf",
+ "4pg 4ph. phar5i phe3no ph4er ph4es. ph1ic 5phie",
+ "ph5ing 5phisti 3phiz ph2l 3phob 3phone 5phoni",
+ "pho4r 4phs ph3t 5phu 1phy pi3a pian4 pi4cie",
+ "pi4cy p4id p5ida pi3de 5pidi 3piec pi3en pi4grap",
+ "pi3lo pi2n p4in. pind4 p4ino 3pi1o pion4 p3ith",
+ "pi5tha pi2tu 2p3k2 1p2l2 3plan plas5t pli3a pli5er",
+ "4plig pli4n ploi4 plu4m plum4b 4p1m 2p3n po4c",
+ "5pod. po5em po3et5 5po4g poin2 5point poly5t",
+ "po4ni po4p 1p4or po4ry 1pos pos1s p4ot po4ta",
+ "5poun 4p1p ppa5ra p2pe p4ped p5pel p3pen p3per",
+ "p3pet ppo5site pr2 pray4e 5preci pre5co pre3em",
+ "pref5ac pre4la pre3r p3rese 3press pre5ten pre3v",
+ "5pri4e prin4t3 pri4s pris3o p3roca prof5it pro3l",
+ "pros3e pro1t 2p1s2 p2se ps4h p4sib 2p1t pt5a4b",
+ "p2te p2th pti3m ptu4r p4tw pub3 pue4 puf4 pul3c",
+ "pu4m pu2n pur4r 5pus pu2t 5pute put3er pu3tr",
+ "put4ted put4tin p3w qu2 qua5v 2que. 3quer 3quet",
+ "2rab ra3bi rach4e r5acl raf5fi raf4t r2ai ra4lo",
+ "ram3et r2ami rane5o ran4ge r4ani ra5no rap3er",
+ "3raphy rar5c rare4 rar5ef 4raril r2as ration4",
+ "rau4t ra5vai rav3el ra5zie r1b r4bab r4bag rbi2",
+ "rbi4f r2bin r5bine rb5ing. rb4o r1c r2ce rcen4",
+ "r3cha rch4er r4ci4b rc4it rcum3 r4dal rd2i rdi4a",
+ "rdi4er rdin4 rd3ing 2re. re1al re3an re5arr 5reav",
+ "re4aw r5ebrat rec5oll rec5ompe re4cre 2r2ed re1de",
+ "re3dis red5it re4fac re2fe re5fer. re3fi re4fy",
+ "reg3is re5it re1li re5lu r4en4ta ren4te re1o",
+ "re5pin re4posi re1pu r1er4 r4eri rero4 re5ru",
+ "r4es. re4spi ress5ib res2t re5stal re3str re4ter",
+ "re4ti4z re3tri reu2 re5uti rev2 re4val rev3el",
+ "r5ev5er. re5vers re5vert re5vil rev5olu re4wh r1f",
+ "rfu4 r4fy rg2 rg3er r3get r3gic rgi4n rg3ing",
+ "r5gis r5git r1gl rgo4n r3gu rh4 4rh. 4rhal",
+ "ri3a ria4b ri4ag r4ib rib3a ric5as r4ice 4rici",
+ "5ricid ri4cie r4ico rid5er ri3enc ri3ent ri1er",
+ "ri5et rig5an 5rigi ril3iz 5riman rim5i 3rimo",
+ "rim4pe r2ina 5rina. rin4d rin4e rin4g ri1o 5riph",
+ "riph5e ri2pl rip5lic r4iq r2is r4is. ris4c r3ish",
+ "ris4p ri3ta3b r5ited. rit5er. rit5ers rit3ic ri2tu",
+ "rit5ur riv5el riv3et riv3i r3j r3ket rk4le rk4lin",
+ "r1l rle4 r2led r4lig r4lis rl5ish r3lo4 r1m",
+ "rma5c r2me r3men rm5ers rm3ing r4ming. r4mio",
+ "r3mit r4my r4nar r3nel r4ner r5net r3ney r5nic",
+ "r1nis4 r3nit r3niv rno4 r4nou r3nu rob3l r2oc",
+ "ro3cr ro4e ro1fe ro5fil rok2 ro5ker 5role. rom5ete",
+ "rom4i rom4p ron4al ron4e ro5n4is ron4ta 1room",
+ "5root ro3pel rop3ic ror3i ro5ro ros5per ros4s",
+ "ro4the ro4ty ro4va rov5el rox5 r1p r4pea r5pent",
+ "rp5er. r3pet rp4h4 rp3ing r3po r1r4 rre4c rre4f",
+ "r4reo rre4st rri4o rri4v rron4 rros4 rrys4 4rs2",
+ "r1sa rsa5ti rs4c r2se r3sec rse4cr rs5er. rs3es",
+ "rse5v2 r1sh r5sha r1si r4si4b rson3 r1sp r5sw",
+ "rtach4 r4tag r3teb rten4d rte5o r1ti rt5ib rti4d",
+ "r4tier r3tig rtil3i rtil4l r4tily r4tist r4tiv",
+ "r3tri rtroph4 rt4sh ru3a ru3e4l ru3en ru4gl ru3in",
+ "rum3pl ru2n runk5 run4ty r5usc ruti5n rv4e rvel4i",
+ "r3ven rv5er. r5vest r3vey r3vic rvi4v r3vo r1w",
+ "ry4c 5rynge ry3t sa2 2s1ab 5sack sac3ri s3act",
+ "5sai salar4 sal4m sa5lo sal4t 3sanc san4de s1ap",
+ "sa5ta 5sa3tio sat3u sau4 sa5vor 5saw 4s5b scan4t5",
+ "sca4p scav5 s4ced 4scei s4ces sch2 s4cho 3s4cie",
+ "5scin4d scle5 s4cli scof4 4scopy scour5a s1cu",
+ "4s5d 4se. se4a seas4 sea5w se2c3o 3sect 4s4ed",
+ "se4d4e s5edl se2g seg3r 5sei se1le 5self 5selv",
+ "4seme se4mol sen5at 4senc sen4d s5ened sen5g",
+ "s5enin 4sentd 4sentl sep3a3 4s1er. s4erl ser4o",
+ "4servo s1e4s se5sh ses5t 5se5um 5sev sev3en sew4i",
+ "5sex 4s3f 2s3g s2h 2sh. sh1er 5shev sh1in sh3io",
+ "3ship shiv5 sho4 sh5old shon3 shor4 short5 4shw",
+ "si1b s5icc 3side. 5sides 5sidi si5diz 4signa",
+ "sil4e 4sily 2s1in s2ina 5sine. s3ing 1sio 5sion",
+ "sion5a si2r sir5a 1sis 3sitio 5siu 1siv 5siz",
+ "sk2 4ske s3ket sk5ine sk5ing s1l2 s3lat s2le",
+ "slith5 2s1m s3ma small3 sman3 smel4 s5men 5smith",
+ "smol5d4 s1n4 1so so4ce soft3 so4lab sol3d2 so3lic",
+ "5solv 3som 3s4on. sona4 son4g s4op 5sophic s5ophiz",
+ "s5ophy sor5c sor5d 4sov so5vi 2spa 5spai spa4n",
+ "spen4d 2s5peo 2sper s2phe 3spher spho5 spil4",
+ "sp5ing 4spio s4ply s4pon spor4 4spot squal4l",
+ "s1r 2ss s1sa ssas3 s2s5c s3sel s5seng s4ses.",
+ "s5set s1si s4sie ssi4er ss5ily s4sl ss4li s4sn",
+ "sspend4 ss2t ssur5a ss5w 2st. s2tag s2tal stam4i",
+ "5stand s4ta4p 5stat. s4ted stern5i s5tero ste2w",
+ "stew5a s3the st2i s4ti. s5tia s1tic 5stick s4tie",
+ "s3tif st3ing 5stir s1tle 5stock stom3a 5stone",
+ "s4top 3store st4r s4trad 5stratu s4tray s4trid",
+ "4stry 4st3w s2ty 1su su1al su4b3 su2g3 su5is",
+ "suit3 s4ul su2m sum3i su2n su2r 4sv sw2 4swo",
+ "s4y 4syc 3syl syn5o sy5rin 1ta 3ta. 2tab ta5bles",
+ "5taboliz 4taci ta5do 4taf4 tai5lo ta2l ta5la",
+ "tal5en tal3i 4talk tal4lis ta5log ta5mo tan4de",
+ "tanta3 ta5per ta5pl tar4a 4tarc 4tare ta3riz",
+ "tas4e ta5sy 4tatic ta4tur taun4 tav4 2taw tax4is",
+ "2t1b 4tc t4ch tch5et 4t1d 4te. tead4i 4teat",
+ "tece4 5tect 2t1ed te5di 1tee teg4 te5ger te5gi",
+ "3tel. teli4 5tels te2ma2 tem3at 3tenan 3tenc",
+ "3tend 4tenes 1tent ten4tag 1teo te4p te5pe ter3c",
+ "5ter3d 1teri ter5ies ter3is teri5za 5ternit ter5v",
+ "4tes. 4tess t3ess. teth5e 3teu 3tex 4tey 2t1f",
+ "4t1g 2th. than4 th2e 4thea th3eas the5at the3is",
+ "3thet th5ic. th5ica 4thil 5think 4thl th5ode",
+ "5thodic 4thoo thor5it tho5riz 2ths 1tia ti4ab",
+ "ti4ato 2ti2b 4tick t4ico t4ic1u 5tidi 3tien tif2",
+ "ti5fy 2tig 5tigu till5in 1tim 4timp tim5ul 2t1in",
+ "t2ina 3tine. 3tini 1tio ti5oc tion5ee 5tiq ti3sa",
+ "3tise tis4m ti5so tis4p 5tistica ti3tl ti4u 1tiv",
+ "tiv4a 1tiz ti3za ti3zen 2tl t5la tlan4 3tle.",
+ "3tled 3tles. t5let. t5lo 4t1m tme4 2t1n2 1to",
+ "to3b to5crat 4todo 2tof to2gr to5ic to2ma tom4b",
+ "to3my ton4ali to3nat 4tono 4tony to2ra to3rie",
+ "tor5iz tos2 5tour 4tout to3war 4t1p 1tra tra3b",
+ "tra5ch traci4 trac4it trac4te tras4 tra5ven trav5es5",
+ "tre5f tre4m trem5i 5tria tri5ces 5tricia 4trics",
+ "2trim tri4v tro5mi tron5i 4trony tro5phe tro3sp",
+ "tro3v tru5i trus4 4t1s2 t4sc tsh4 t4sw 4t3t2",
+ "t4tes t5to ttu4 1tu tu1a tu3ar tu4bi tud2 4tue",
+ "4tuf4 5tu3i 3tum tu4nis 2t3up. 3ture 5turi tur3is",
+ "tur5o tu5ry 3tus 4tv tw4 4t1wa twis4 4two 1ty",
+ "4tya 2tyl type3 ty5ph 4tz tz4e 4uab uac4 ua5na",
+ "uan4i uar5ant uar2d uar3i uar3t u1at uav4 ub4e",
+ "u4bel u3ber u4bero u1b4i u4b5ing u3ble. u3ca",
+ "uci4b uc4it ucle3 u3cr u3cu u4cy ud5d ud3er",
+ "ud5est udev4 u1dic ud3ied ud3ies ud5is u5dit",
+ "u4don ud4si u4du u4ene uens4 uen4te uer4il 3ufa",
+ "u3fl ugh3en ug5in 2ui2 uil5iz ui4n u1ing uir4m",
+ "uita4 uiv3 uiv4er. u5j 4uk u1la ula5b u5lati",
+ "ulch4 5ulche ul3der ul4e u1len ul4gi ul2i u5lia",
+ "ul3ing ul5ish ul4lar ul4li4b ul4lis 4ul3m u1l4o",
+ "4uls uls5es ul1ti ultra3 4ultu u3lu ul5ul ul5v",
+ "um5ab um4bi um4bly u1mi u4m3ing umor5o um2p unat4",
+ "u2ne un4er u1ni un4im u2nin un5ish uni3v un3s4",
+ "un4sw unt3ab un4ter. un4tes unu4 un5y un5z u4ors",
+ "u5os u1ou u1pe uper5s u5pia up3ing u3pl up3p",
+ "upport5 upt5ib uptu4 u1ra 4ura. u4rag u4ras ur4be",
+ "urc4 ur1d ure5at ur4fer ur4fr u3rif uri4fic ur1in",
+ "u3rio u1rit ur3iz ur2l url5ing. ur4no uros4 ur4pe",
+ "ur4pi urs5er ur5tes ur3the urti4 ur4tie u3ru",
+ "2us u5sad u5san us4ap usc2 us3ci use5a u5sia",
+ "u3sic us4lin us1p us5sl us5tere us1tr u2su usur4",
+ "uta4b u3tat 4ute. 4utel 4uten uten4i 4u1t2i uti5liz",
+ "u3tine ut3ing ution5a u4tis 5u5tiz u4t1l ut5of",
+ "uto5g uto5matic u5ton u4tou uts4 u3u uu4m u1v2",
+ "uxu3 uz4e 1va 5va. 2v1a4b vac5il vac3u vag4",
+ "va4ge va5lie val5o val1u va5mo va5niz va5pi var5ied",
+ "3vat 4ve. 4ved veg3 v3el. vel3li ve4lo v4ely",
+ "ven3om v5enue v4erd 5vere. v4erel v3eren ver5enc",
+ "v4eres ver3ie vermi4n 3verse ver3th v4e2s 4ves.",
+ "ves4te ve4te vet3er ve4ty vi5ali 5vian 5vide.",
+ "5vided 4v3iden 5vides 5vidi v3if vi5gn vik4 2vil",
+ "5vilit v3i3liz v1in 4vi4na v2inc vin5d 4ving",
+ "vio3l v3io4r vi1ou vi4p vi5ro vis3it vi3so vi3su",
+ "4viti vit3r 4vity 3viv 5vo. voi4 3vok vo4la",
+ "v5ole 5volt 3volv vom5i vor5ab vori4 vo4ry vo4ta",
+ "4votee 4vv4 v4y w5abl 2wac wa5ger wag5o wait5",
+ "w5al. wam4 war4t was4t wa1te wa5ver w1b wea5rie",
+ "weath3 wed4n weet3 wee5v wel4l w1er west3 w3ev",
+ "whi4 wi2 wil2 will5in win4de win4g wir4 3wise",
+ "with3 wiz5 w4k wl4es wl3in w4no 1wo2 wom1 wo5ven",
+ "w5p wra4 wri4 writa4 w3sh ws4l ws4pe w5s4t",
+ "4wt wy4 x1a xac5e x4ago xam3 x4ap xas5 x3c2",
+ "x1e xe4cuto x2ed xer4i xe5ro x1h xhi2 xhil5",
+ "xhu4 x3i xi5a xi5c xi5di x4ime xi5miz x3o x4ob",
+ "x3p xpan4d xpecto5 xpe3d x1t2 x3ti x1u xu3a",
+ "xx4 y5ac 3yar4 y5at y1b y1c y2ce yc5er y3ch",
+ "ych4e ycom4 ycot4 y1d y5ee y1er y4erf yes4",
+ "ye4t y5gi 4y3h y1i y3la ylla5bl y3lo y5lu ymbol5",
+ "yme4 ympa3 yn3chr yn5d yn5g yn5ic 5ynx y1o4",
+ "yo5d y4o5g yom4 yo5net y4ons y4os y4ped yper5",
+ "yp3i y3po y4poc yp2ta y5pu yra5m yr5ia y3ro",
+ "yr4r ys4c y3s2e ys3ica ys3io 3ysis y4so yss4",
+ "ys1t ys3ta ysur4 y3thin yt3ic y1w za1 z5a2b",
+ "zar2 4zb 2ze ze4n ze4p z1er ze3ro zet4 2z1i",
+ "z4il z4is 5zl 4zm 1zo zo4m zo5ol zte4 4z1z2",
+ "z4zy",
+
+#if 1
+
+/* Patterns for standard Hyphenation Pattern Memory of 8000.
+ Can be used with all standard TeX versions.
+ Hyphenation trie becomes 6661 with 229 ops.
+ These patterns are based on the Hyphenation Exception Log
+ published in TUGboat, Volume 10 (1989), No. 3, pp. 337-341,
+ and a large number of bad hyphened words not yet published.
+ If added to Liang's before the closing bracket } of \patterns,
+ the patterns run errorfree as far as known at this moment.
+ Patterns do not find all admissible hyphens of the words in
+ the Exception Log. The file ushyphen.max do.
+ Can be used freely for non-commercial purposes.
+ Copyright 1990 G.D.C. Kuiken. e-mail: wbahkui@hdetud1.tudelft.nl
+ Postal address: P.O. Box 65791, NL 2506 EB Den Haag, Holland.
+ Patterns of March 1, 1990. */
+
+ ".driv4 .eth1y6l1 .eu4ler .ev2 .ga4som .ge4ome",
+ ".he3p6a .in5u2t .kil2ni .ko6rte .le6ice .me4gal",
+ ".met4ala .mimi4cr .mis4ers .ne6o3f .non1e2m .semi5",
+ ".sem4ic .semid6 .semip4 .semir4 .sem6is4 .semiv4",
+ ".sph6in1 .to6pog .to2q .vi4car .we2b1l .ree4c a4cabl",
+ "af6fish anal6ys anoa4c anti3de anti3n2 anti3re",
+ "a4peable ar4range as5ymptot at6tes. augh4tl av3iou",
+ "ba6r1onie bbi4t be4vie bid4if bil4lab bio5m bi3orb",
+ "bio3rh blan4d blin4d blon4d bo4tul brus4q bus6i2er",
+ "bus6i2es buss4in but4ed. but4ted cad5em catas4",
+ "4chs. chs3hu ciga3r cin4q cle4ar co6ph1o3n cous4ti",
+ "cri5tie cro5e4co c2tro3me6c cu4ranc 4d3alone data3b",
+ "d2dib de4als. de2clin de5fin5iti de4mos des3ic",
+ "de4tic dic5aid dif5fra di4ren di4rer 4dlead 4dli4e",
+ "do5word drif4ta d3tab ea4nies e3chas edg3l eli4tis",
+ "e3loa en3dix e6pineph e4rian. espac6i ethy6lene",
+ "eu4clid1 feb3ru fermi3o 3fich flag6el g6endre.",
+ "geo3d ght3we g3lead 4g1lish g4nac g4nor. g4nores",
+ "4go4niza griev3 ha4parr hatch3 hex2a hipela4 ho6r1ic.",
+ "h4teou id4ios ign4it i4jk im5peda infras4 i5nitely.",
+ "irre6v3oc i5tesima ithi4l janu3a ke6ling ki5netic",
+ "k3sha la4cie lai6ness l3chai l3chil6d lea4sa lecta6b",
+ "litho5g ll1fl l4lish lo4ges. l3tea lthi4ly lue1p",
+ "man3u1sc mar3gin medi4c medi5cin medio6c me5gran",
+ "mi3dab mil4lag milli5li mi6n3is. min4ute m3mab",
+ "5maphro 5mocrat moe4las mole5c mon4ey1l mono5ch",
+ "mo4no1en moro6n5is monos6 moth4et2 mou5sin mshack4",
+ "mu4dro mul4ti5u nar4chs. nch4est ne5back 4neski",
+ "nd3thr nfin5ites 4nian. nge5nes ng3ho ng3spr nk3rup",
+ "n5less nom1a6l nom5eno no5mist non5eq noni4so no5vemb",
+ "ns5ceiv ns4moo ntre3p obli2g1 o3chas oerst4 oke3st",
+ "olon4om o3mecha6 o5norma ono4ton o3nou op3ism.",
+ "or4tho3ni4t orth5ri o4spher o6v3ian. oxi6d2ic pal6mat",
+ "parag6ra4 par4ale param4 para5me pee4v1 phi2l3an",
+ "phi5latel pi4cad pli4cab pli5nar 1pole. poly1e",
+ "prema5c pre5neu pres4pli pro4cess proc5ity. pro4ge",
+ "3pseu4d pseud6od2 pseud6of2 ptomat4 p5trol pubes5c",
+ "quain4te qu6a3si3 quasir6 quasis6 quiv4ar r5abolic",
+ "ra3chu r3a3dig radi1o6g r4amen ra4me3triz ra3mou",
+ "ran4has ra3or r3binge re4cipr rec4ogn rec5t6ang",
+ "re2f1orma re4tribu r3ial. riv3ol rk3ho 6rks. ro3bot3",
+ "roe4las r3thou r3treu r3veil rz3sc sales5c sales5w",
+ "sca6p1er sca4tol s4chitz sci4utt scy4th se1mi6t1ic",
+ "sep5temb shoe5st side5st side5sw sky3sc s4ogamy",
+ "so4lute s4pace s4pacin spe5cio spher5o spi4cil",
+ "spokes5w sports5c sports5w s5quito s4sa3chu ss3hat",
+ "s4sian. s4tamp s4tants star5tli sta3ti st5b stor5ab",
+ "strat5ag strib5ut st5scr stupi4d styl5is su2per1e6",
+ "3sync sythi4 swimm6 ta3gon. talka5 ta3min t6ap6ath",
+ "tar4rh tch3c tch5ed tch5ier t1cr tele4g tele1r6o",
+ "tess4es tha4lam tho5don tho5geni thok4er thy4lan",
+ "thy3sc 4tian. ti4nom tli4er tot3ic trai5tor tra5vers",
+ "treach5e tr4ial. 5tro1leum tro5fit trop4is tropo5les",
+ "tropo5lis tropol5it tsch5ie ttribut5 turn5ar t1wh",
+ "ty4pal u2ral. v3ativ va6guer v5ereig voice5p waste3w6",
+ "waveg4 w3c week3n wide5sp wo4ken wrap5aro x1q",
+ "xquis3 y5ched ym5etry y3stro z2z3w z2z3w",
+#endif
+ NULL
+};
+#endif
+
+/* Do NOT make any alterations to this list! --- DEK */
+
+char *USExceptions[]=
+{"as-so-ciate",
+ "as-so-ciates",
+ "dec-li-na-tion",
+ "oblig-a-tory",
+ "phil-an-thropic",
+ "present",
+ "presents",
+ "project",
+ "projects",
+ "reci-procity",
+ "re-cog-ni-zance",
+ "ref-or-ma-tion",
+ "ret-ri-bu-tion",
+ "ta-ble",
+ NULL
+};
diff --git a/ushyph.h b/ushyph.h
new file mode 100644
index 0000000..f23e21d
--- /dev/null
+++ b/ushyph.h
@@ -0,0 +1,14 @@
+/* ushyph.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Trennungsmuster (US-)englisch */
+/* abgeleitet von 'ushyphen.tex' aus TeX */
+/* */
+/* Historie: 16.2.1998 Konvertierung */
+/* */
+/*****************************************************************************/
+
+extern char *USHyphens[];
+
+extern char *USExceptions[];
diff --git a/version.c b/version.c
new file mode 100644
index 0000000..b2bdccb
--- /dev/null
+++ b/version.c
@@ -0,0 +1,28 @@
+/* version.c */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Lagert die Versionsnummer */
+/* */
+/* Historie: 14.10.1997 Grundsteinlegung */
+/* 25. 7.1998 Version 1.41r8beta */
+/* 18.10.1998 Build 4 */
+/* 25.10.1998 Build 5 */
+/* 10. 1.1999 Build 6 */
+/* 17. 1.1999 Build 7 */
+/* 27. 1.1999 Build 8 */
+/* 27. 1.1999 Build 9 */
+/* 7. 2.1999 Build 10 */
+/* 19. 4.1999 Build 11 */
+/* 20. 4.1999 Build 12 */
+/* 2. 5.1999 Build 13 */
+/* 6. 7.1999 Build 14 */
+/* 15. 9.1999 Build 15 */
+/* 7.11.1999 Final Build */
+/* */
+/*****************************************************************************/
+
+#include "stdinc.h"
+
+char *Version="1.41r8";
+LongInt VerNo=0x1418;
diff --git a/version.h b/version.h
new file mode 100644
index 0000000..7026630
--- /dev/null
+++ b/version.h
@@ -0,0 +1,12 @@
+/* version.h */
+/*****************************************************************************/
+/* AS-Portierung */
+/* */
+/* Lagert die Versionsnummer */
+/* */
+/* Historie: 14.10.1997 Grundsteinlegung */
+/* */
+/*****************************************************************************/
+
+extern char *Version;
+extern LongInt VerNo;